package au.gov.ga.earthsci.application.parts.progress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.jobs.ProgressProvider;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
/**
* A simple progress part inspired by the legacy Eclipse 3.x
* <code>DetailedProgressView</code>
* <p/>
* Used to show the progress of currently running jobs.
* <p/>
* This part also injects an {@link ProgressProvider} onto the current
* {@link IJobManager} to capture progress information. Other plugins should not
* override this provider.
* <hr/>
* <b>Important:</b> This part should be replaced with the inbuilt one when it
* becomes available in the Eclipse 4.x release train.
* <hr/>
*
* @author James Navin (james.navin@ga.gov.au)
*/
public class ProgressPart
{
private static final Map<Integer, String> JOB_STATE_LABEL = new HashMap<Integer, String>();
static
{
JOB_STATE_LABEL.put(Job.WAITING, Messages.ProgressPart_WaitingStatusLabel);
JOB_STATE_LABEL.put(Job.SLEEPING, Messages.ProgressPart_SleepingStatusLabel);
JOB_STATE_LABEL.put(Job.RUNNING, Messages.ProgressPart_RunningStatusLabel);
}
@Inject
private IJobManager jobManager;
private TableViewer viewer;
private List<JobInfo> jobList = new ArrayList<JobInfo>();
@Inject
public void init(Composite parent, MPart part)
{
viewer = new TableViewer(parent, SWT.V_SCROLL);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setInput(jobList);
viewer.getTable().setLinesVisible(true);
viewer.getTable().setHeaderVisible(true);
viewer.setSorter(new ViewerSorter()
{
@Override
public int category(Object element)
{
return ((JobInfo) element).job.getState();
}
@Override
public int compare(Viewer viewer, Object e1, Object e2)
{
return ((JobInfo) e1).job.getPriority() - ((JobInfo) e2).job.getPriority();
}
});
viewer.addFilter(new ViewerFilter()
{
@Override
public boolean select(Viewer viewer, Object parentElement, Object element)
{
return ((JobInfo) element).job.getState() != Job.SLEEPING;
}
});
createColumns();
jobManager.addJobChangeListener(new JobChangeAdapter()
{
@Override
public void scheduled(IJobChangeEvent event)
{
JobInfo jobInfo = new JobInfo(event.getJob(), ProgressPart.this);
synchronized (jobList)
{
jobList.add(jobInfo);
}
asyncRefresh();
super.scheduled(event);
}
@Override
public void done(final IJobChangeEvent event)
{
JobInfo jobInfo = findInfoForJob(event.getJob());
synchronized (jobList)
{
jobList.remove(jobInfo);
}
asyncRefresh();
}
});
jobManager.setProgressProvider(new ProgressProvider()
{
@Override
public IProgressMonitor createMonitor(final Job job)
{
JobInfo jobInfo = findInfoForJob(job);
if (jobInfo == null)
{
jobInfo = new JobInfo(job, ProgressPart.this);
synchronized (jobList)
{
jobList.add(jobInfo);
}
asyncRefresh();
}
return jobInfo;
}
});
}
private JobInfo findInfoForJob(Job job)
{
synchronized (jobList)
{
for (JobInfo info : jobList)
{
if (info.job == job)
{
return info;
}
}
}
return null;
}
private void createColumns()
{
TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
column.getColumn().setText(Messages.ProgressPart_JobNameColumnLabel);
column.getColumn().setWidth(500);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
return ((JobInfo) element).job.getName();
}
});
column = new TableViewerColumn(viewer, SWT.NONE);
column.getColumn().setText(Messages.ProgressPart_JobStateColumnLabel);
column.getColumn().setWidth(100);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
return JOB_STATE_LABEL.get(((JobInfo) element).job.getState());
}
});
column = new TableViewerColumn(viewer, SWT.NONE);
column.getColumn().setText(Messages.ProgressPart_JobProgressColumnLabel);
column.getColumn().setWidth(100);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
return ((JobInfo) element).getProgress();
}
});
column = new TableViewerColumn(viewer, SWT.NONE);
column.getColumn().setText(Messages.ProgressPart_JobTaskColumnLabel);
column.getColumn().setWidth(500);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
return ((JobInfo) element).currentTask;
}
});
}
private void asyncRefresh()
{
if (!viewer.getTable().isDisposed())
{
Display.getDefault().asyncExec(new Runnable()
{
@Override
public void run()
{
if (!viewer.getTable().isDisposed())
{
viewer.refresh();
}
}
});
}
}
private void asyncUpdate(final JobInfo job)
{
if (!viewer.getTable().isDisposed())
{
Display.getDefault().asyncExec(new Runnable()
{
@Override
public void run()
{
if (!viewer.getTable().isDisposed())
{
viewer.update(job, null);
}
}
});
}
}
private static class JobInfo extends NullProgressMonitor
{
ProgressPart view;
String currentTask;
int totalWork;
int work;
Job job;
public JobInfo(Job job, final ProgressPart view)
{
this.view = view;
this.job = job;
this.job.addJobChangeListener(new JobChangeAdapter()
{
@Override
public void aboutToRun(IJobChangeEvent event)
{
view.asyncUpdate(JobInfo.this);
}
@Override
public void running(IJobChangeEvent event)
{
view.asyncUpdate(JobInfo.this);
}
});
}
String getProgress()
{
if (totalWork == IProgressMonitor.UNKNOWN)
{
return Messages.ProgressPart_UnknownProgress;
}
return (int) (work * 100d / totalWork) + "%"; //$NON-NLS-1$
}
@Override
public void worked(int work)
{
this.work += work;
view.asyncUpdate(this);
}
@Override
public void beginTask(String name, int totalWork)
{
this.currentTask = name;
this.totalWork = totalWork;
view.asyncUpdate(this);
}
@Override
public void subTask(String name)
{
this.currentTask = name;
view.asyncUpdate(this);
}
}
}