| /******************************************************************************* |
| * Copyright (c) 2009, 2017 xored software, Inc. and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * xored software, Inc. - initial API and Implementation (Andrei Sobolev) |
| *******************************************************************************/ |
| package org.eclipse.dltk.core; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| |
| /** |
| * This class is designed to show progress messages using Eclipse Jobs subsystem |
| * |
| * @author asobolev |
| * @since 2.0 |
| */ |
| public class ProgressMonitoringJob extends Job implements IProgressMonitor { |
| private static class WorkNode { |
| int type; |
| String message; |
| double worked; |
| |
| public WorkNode(int type, String message, double worked) { |
| super(); |
| this.type = type; |
| this.message = message; |
| this.worked = worked; |
| } |
| } |
| |
| private static final int BEGIN_TASK = 0; |
| |
| private static final int DONE = 1; |
| |
| private static final int INTERNAL_WORKED = 2; |
| |
| private static final int SET_CANCELED = 3; |
| |
| private static final int SET_TASK_NAME = 4; |
| |
| private static final int SUB_TASK = 5; |
| |
| private static final int WORKED = 6; |
| |
| private List<WorkNode> queue = new LinkedList<>(); |
| |
| private final Object lock = new Object(); |
| private boolean canceled = false; |
| |
| public ProgressMonitoringJob(String message, int totalWork) { |
| super(message); |
| setPriority(Job.LONG); |
| schedule(); |
| beginTask(message, totalWork); |
| } |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| for (;;) { |
| if (monitor.isCanceled()) { |
| synchronized (lock) { |
| canceled = true; |
| return Status.CANCEL_STATUS; |
| } |
| } |
| synchronized (lock) { |
| if (queue.isEmpty()) { |
| try { |
| lock.wait(100); |
| } catch (InterruptedException e) { |
| DLTKCore.error(e); |
| } |
| continue; |
| } |
| |
| WorkNode node = queue.remove(0); |
| if (node != null) { |
| switch (node.type) { |
| case BEGIN_TASK: |
| monitor.beginTask(node.message, (int) node.worked); |
| break; |
| case DONE: |
| monitor.done(); |
| return Status.OK_STATUS; |
| case INTERNAL_WORKED: |
| monitor.internalWorked(node.worked); |
| break; |
| case SET_CANCELED: |
| monitor.setCanceled(node.worked == 1 ? true : false); |
| break; |
| case SET_TASK_NAME: |
| monitor.setTaskName(node.message); |
| break; |
| case SUB_TASK: |
| monitor.subTask(node.message); |
| break; |
| case WORKED: |
| monitor.worked((int) node.worked); |
| break; |
| } |
| |
| } |
| } |
| } |
| } |
| |
| @Override |
| public void beginTask(String name, int totalWork) { |
| synchronized (lock) { |
| WorkNode node = new WorkNode(BEGIN_TASK, name, totalWork); |
| addToQueue(node); |
| } |
| } |
| |
| private void addToQueue(WorkNode node) { |
| synchronized (lock) { |
| queue.add(node); |
| lock.notifyAll(); |
| } |
| } |
| |
| @Override |
| public void done() { |
| addToQueue(new WorkNode(DONE, null, 0)); |
| } |
| |
| @Override |
| public void internalWorked(double work) { |
| addToQueue(new WorkNode(INTERNAL_WORKED, null, work)); |
| |
| } |
| |
| @Override |
| public boolean isCanceled() { |
| synchronized (lock) { |
| return canceled; |
| } |
| } |
| |
| @Override |
| public void setCanceled(boolean value) { |
| synchronized (lock) { |
| this.canceled = value; |
| } |
| addToQueue(new WorkNode(SET_CANCELED, null, value ? 1 : 0)); |
| } |
| |
| @Override |
| public void setTaskName(String name) { |
| addToQueue(new WorkNode(SET_TASK_NAME, name, 0)); |
| |
| } |
| |
| @Override |
| public void subTask(String name) { |
| addToQueue(new WorkNode(SUB_TASK, name, 0)); |
| } |
| |
| @Override |
| public void worked(int work) { |
| addToQueue(new WorkNode(WORKED, null, work)); |
| } |
| } |