| /******************************************************************************* |
| * Copyright (c) 2003, 2007 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| * Brock Janiczak <brockj@tpg.com.au> - Fix for Bug 123169 [Progress] NPE from JobInfo |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.progress; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.graphics.Image; |
| |
| /** |
| * JobInfo is the class that keeps track of the tree structure for objects that |
| * display job status in a tree. |
| */ |
| class JobInfo extends JobTreeElement { |
| |
| private IStatus blockedStatus; |
| |
| private volatile boolean canceled = false; |
| private List children = Collections.synchronizedList(new ArrayList()); |
| |
| private Job job; |
| |
| private GroupInfo parent; |
| |
| private TaskInfo taskInfo; |
| |
| //Default to no progress |
| private int ticks = -1; |
| |
| /** |
| * Create a top level JobInfo. |
| * |
| * @param enclosingJob |
| */ |
| JobInfo(Job enclosingJob) { |
| this.job = enclosingJob; |
| } |
| |
| /** |
| * Add the subtask to the receiver. |
| * |
| * @param subTaskName |
| */ |
| void addSubTask(String subTaskName) { |
| children.add(new SubTaskInfo(this, subTaskName)); |
| } |
| |
| /** |
| * Add the amount of work to the job info. |
| * |
| * @param workIncrement |
| */ |
| void addWork(double workIncrement) { |
| if (taskInfo == null) { |
| return; |
| } |
| if (parent == null || ticks < 1) { |
| taskInfo.addWork(workIncrement); |
| } else { |
| taskInfo.addWork(workIncrement, parent, ticks); |
| } |
| } |
| |
| /** |
| * Begin the task called taskName with the supplied work. |
| * |
| * @param taskName |
| * @param work |
| */ |
| void beginTask(String taskName, int work) { |
| taskInfo = new TaskInfo(this, taskName, work); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#cancel() |
| */ |
| public void cancel() { |
| this.canceled = true; |
| this.job.cancel(); |
| //Call the refresh so that this is updated immediately |
| ProgressManager.getInstance().refreshJobInfo(this); |
| } |
| |
| /** |
| * Clear the collection of subtasks an the task info. |
| */ |
| void clearChildren() { |
| children.clear(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo() |
| */ |
| void clearTaskInfo() { |
| taskInfo = null; |
| } |
| |
| /** |
| * Compare the the job of the receiver to job2. |
| * |
| * @param jobInfo |
| * The info we are comparing to |
| * @return @see Comparable#compareTo(java.lang.Object) |
| */ |
| private int compareJobs(JobInfo jobInfo) { |
| |
| Job job2 = jobInfo.getJob(); |
| |
| //User jobs have top priority |
| if (job.isUser()) { |
| if (!job2.isUser()) { |
| return -1; |
| } |
| } else { |
| if (job2.isUser()) { |
| return 1; |
| } |
| } |
| |
| //Show the blocked ones last |
| if (isBlocked()) { |
| if (!jobInfo.isBlocked()) { |
| return 1; |
| } |
| } else { |
| if (jobInfo.isBlocked()) { |
| return -1; |
| } |
| } |
| |
| if (job.getPriority() == job2.getPriority()) { |
| return job.getName().compareTo(job2.getName()); |
| } |
| |
| if (job.getPriority() > job2.getPriority()) { |
| return -1; |
| } |
| return 1; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Comparable#compareTo(java.lang.Object) |
| */ |
| public int compareTo(Object arg0) { |
| |
| if (!(arg0 instanceof JobInfo)) { |
| return super.compareTo(arg0); |
| } |
| JobInfo element = (JobInfo) arg0; |
| |
| //If the receiver is cancelled then it is lowest priority |
| if (isCanceled() && !element.isCanceled()) { |
| return 1; |
| } |
| |
| if (element.getJob().getState() == getJob().getState()) { |
| return compareJobs(element); |
| } |
| |
| if (getJob().getState() == Job.RUNNING) { |
| return -1; |
| } |
| return 1; |
| |
| } |
| |
| /** |
| * Dispose of the receiver. |
| */ |
| void dispose() { |
| if (parent != null) { |
| parent.removeJobInfo(this); |
| } |
| } |
| |
| /** |
| * Return the blocked status or <code>null</code> if there isn't one. |
| * |
| * @return Returns the blockedStatus. |
| */ |
| public IStatus getBlockedStatus() { |
| return blockedStatus; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren() |
| */ |
| Object[] getChildren() { |
| return children.toArray(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getCondensedDisplayString() |
| */ |
| String getCondensedDisplayString() { |
| TaskInfo info = getTaskInfo(); |
| if (info != null) { |
| return info.getDisplayStringWithoutTask(true); |
| } |
| return getJob().getName(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayImage() |
| */ |
| public Image getDisplayImage() { |
| int done = getPercentDone(); |
| if (done > 0) { |
| return super.getDisplayImage(); |
| } |
| if (isBlocked()) { |
| return JFaceResources.getImage(ProgressManager.BLOCKED_JOB_KEY); |
| } |
| int state = getJob().getState(); |
| if (state == Job.SLEEPING) { |
| return JFaceResources.getImage(ProgressManager.SLEEPING_JOB_KEY); |
| } |
| if (state == Job.WAITING) { |
| return JFaceResources.getImage(ProgressManager.WAITING_JOB_KEY); |
| } |
| //By default return the first progress image |
| return super.getDisplayImage(); |
| |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString() |
| */ |
| String getDisplayString() { |
| return getDisplayString(true); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString(boolean) |
| */ |
| String getDisplayString(boolean showProgress) { |
| String name = getDisplayStringWithStatus(showProgress); |
| if (job.isSystem()) { |
| return NLS.bind(ProgressMessages.JobInfo_System, (new Object[] { name })); |
| } |
| return name; |
| } |
| |
| /** |
| * Get the display string based on the current status and the name of the |
| * job. |
| * @param showProgress a boolean to indicate if we should |
| * show progress or not. |
| * |
| * @return String |
| */ |
| private String getDisplayStringWithStatus(boolean showProgress) { |
| if (isCanceled()) { |
| return NLS.bind(ProgressMessages.JobInfo_Cancelled, (new Object[] { getJob().getName() })); |
| } |
| if (isBlocked()) { |
| return NLS.bind(ProgressMessages.JobInfo_Blocked, (new Object[] { getJob().getName(), |
| blockedStatus.getMessage() })); |
| } |
| if (getJob().getState() == Job.RUNNING) { |
| TaskInfo info = getTaskInfo(); |
| if (info == null) { |
| return getJob().getName(); |
| } |
| return info.getDisplayString(showProgress); |
| } |
| if (getJob().getState() == Job.SLEEPING) { |
| return NLS.bind(ProgressMessages.JobInfo_Sleeping, (new Object[] { getJob().getName() })); |
| } |
| |
| return NLS.bind(ProgressMessages.JobInfo_Waiting, (new Object[] { getJob().getName() })); |
| |
| } |
| |
| /** |
| * Return the GroupInfo for the receiver if it' is active. |
| * |
| * @return GroupInfo or <code>null</code>. |
| */ |
| GroupInfo getGroupInfo() { |
| if (parent != null) { |
| return parent; |
| } |
| return null; |
| } |
| |
| /** |
| * Return the job that the receiver is collecting data on. |
| * |
| * @return Job |
| */ |
| Job getJob() { |
| return job; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#getParent() |
| */ |
| Object getParent() { |
| return parent; |
| } |
| |
| /** |
| * Return the amount of progress we have had as a percentage. If there is no |
| * progress or it is indeterminate return IProgressMonitor.UNKNOWN. |
| * |
| * @return int |
| */ |
| int getPercentDone() { |
| TaskInfo info = getTaskInfo(); |
| if (info != null){ |
| if(info.totalWork == IProgressMonitor.UNKNOWN) { |
| return IProgressMonitor.UNKNOWN; |
| } |
| if(info.totalWork == 0) { |
| return 0; |
| } |
| return (int) info.preWork * 100 / info.totalWork; |
| } |
| return IProgressMonitor.UNKNOWN; |
| } |
| |
| /** |
| * @return Returns the taskInfo. |
| */ |
| TaskInfo getTaskInfo() { |
| return taskInfo; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren() |
| */ |
| boolean hasChildren() { |
| return children.size() > 0; |
| } |
| |
| /** |
| * Return whether or not there is a task. |
| * |
| * @return boolean |
| */ |
| boolean hasTaskInfo() { |
| return taskInfo != null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive() |
| */ |
| boolean isActive() { |
| return getJob().getState() != Job.NONE; |
| } |
| |
| /** |
| * Return whether or not the receiver is blocked. |
| * |
| * @return boolean <code>true</code> if this is a currently |
| * blocked job. |
| */ |
| public boolean isBlocked() { |
| return getBlockedStatus() != null; |
| } |
| |
| /** |
| * Return whether or not the job was cancelled in the UI. |
| * |
| * @return boolean |
| */ |
| public boolean isCanceled() { |
| return canceled; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#isCancellable() |
| */ |
| public boolean isCancellable() { |
| return super.isCancellable(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo() |
| */ |
| boolean isJobInfo() { |
| return true; |
| } |
| |
| /** |
| * Set the description of the blocking status. |
| * |
| * @param blockedStatus |
| * The IStatus that describes the blockage or <code>null</code> |
| */ |
| public void setBlockedStatus(IStatus blockedStatus) { |
| this.blockedStatus = blockedStatus; |
| } |
| |
| /** |
| * Set the GroupInfo to be the group. |
| * |
| * @param group |
| */ |
| void setGroupInfo(GroupInfo group) { |
| parent = group; |
| } |
| |
| /** |
| * Set the name of the taskInfo. |
| * |
| * @param name |
| */ |
| void setTaskName(String name) { |
| taskInfo.setTaskName(name); |
| } |
| |
| /** |
| * Set the number of ticks this job represents. Default is indeterminate |
| * (-1). |
| * |
| * @param ticks |
| * The ticks to set. |
| */ |
| public void setTicks(int ticks) { |
| this.ticks = ticks; |
| } |
| |
| } |