public final class SubMonitor extends Object implements IProgressMonitor
A progress monitor that uses a given amount of work ticks from a parent monitor. This is intended as a safer, easier-to-use alternative to SubProgressMonitor. The main benefits of SubMonitor over SubProgressMonitor are:
USAGE:
When implementing a method that accepts an IProgressMonitor:
SubMonitor.convert(...).
to convert the IProgressMonitor
into a SubMonitor. SubMonitor.newChild(...)
whenever you need to call another method that
accepts an IProgressMonitor.DEFAULT BEHAVIOR:
When writing JavaDoc for a method that accepts an IProgressMonitor, you should assume the following default behavior unless the method's JavaDoc says otherwise:
BEST PRACTISES:
We recommend that newly-written methods follow the given contract:
If you wish to follow these conventions, you may copy and paste the following text into your method's JavaDoc:
@param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
to call done() on the given monitor. Accepts null
, indicating that no progress should be
reported and that the operation cannot be cancelled.
Example: Recommended usage
This example demonstrates how the recommended usage of SubMonitor
makes it unnecessary to call
IProgressMonitor.done() in most situations.
It is never necessary to call done() on a monitor obtained from convert
or progress.newChild()
.
In this example, there is no guarantee that monitor
is an instance of SubMonitor
, making it
necessary to call monitor.done()
. The JavaDoc contract makes this the responsibility of the caller.
// param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
// to call done() on the given monitor. Accepts null
, indicating that no progress should be
// reported and that the operation cannot be cancelled.
//
void doSomething(IProgressMonitor monitor) {
// Convert the given monitor into a progress instance
SubMonitor progress = SubMonitor.convert(monitor, 100);
// Use 30% of the progress to do some work
doSomeWork(progress.newChild(30));
// Advance the monitor by another 30%
progress.worked(30);
// Use the remaining 40% of the progress to do some more work
doSomeWork(progress.newChild(40));
}
Example: Default usage
You will often need to implement a method that does not explicitly stipulate that calling done() is the responsibility of the caller. In this case, you should use the following pattern:
// param monitor the progress monitor to use for reporting progress to the user, or null
indicating
// that no progress should be reported and the operation cannot be cancelled.
//
void doSomething(IProgressMonitor monitor) {
// Convert the given monitor into a progress instance
SubMonitor progress = SubMonitor.convert(monitor, 100);
try {
// Use 30% of the progress to do some work
doSomeWork(progress.newChild(30));
// Advance the monitor by another 30%
progress.worked(30);
// Use the remaining 40% of the progress to do some more work
doSomeWork(progress.newChild(40));
} finally {
if (monitor != null) {
monitor.done();
}
}
}
Example: Branches
This example demonstrates how to smoothly report progress in situations where some of the work is optional.
void doSomething(IProgressMonitor monitor) { SubMonitor progress = SubMonitor.convert(monitor, 100); if (condition) { // Use 50% of the progress to do some work doSomeWork(progress.newChild(50)); } // Don't report any work, but ensure that we have 50 ticks remaining on the progress monitor. // If we already consumed 50 ticks in the above branch, this is a no-op. Otherwise, the remaining // space in the monitor is redistributed into 50 ticks. progress.setWorkRemaining(50); // Use the remainder of the progress monitor to do the rest of the work doSomeWork(progress.newChild(50)); }
Please beware of the following anti-pattern:
if (condition) { // Use 50% of the progress to do some work doSomeWork(progress.newChild(50)); } else { // Bad: Causes the progress monitor to appear to start at 50%, wasting half of the // space in the monitor. progress.worked(50); }
Example: Loops
This example demonstrates how to report progress in a loop.
void doSomething(IProgressMonitor monitor, Collection someCollection) { SubMonitor progress = SubMonitor.convert(monitor, 100); // Create a new progress monitor that uses 70% of the total progress and will allocate one tick // for each element of the given collection. SubMonitor loopProgress = progress.newChild(70).setWorkRemaining(someCollection.size()); for (Iterator iter = someCollection.iterator(); iter.hasNext();) { Object next = iter.next(); doWorkOnElement(next, loopProgress.newChild(1)); } // Use the remaining 30% of the progress monitor to do some work outside the loop doSomeWork(progress.newChild(30)); }
Example: Infinite progress
This example demonstrates how to report logarithmic progress in situations where the number of ticks cannot be easily computed in advance.
void doSomething(IProgressMonitor monitor, LinkedListNode node) { SubMonitor progress = SubMonitor.convert(monitor); while (node != null) { // Regardless of the amount of progress reported so far, // use 0.01% of the space remaining in the monitor to process the next node. progress.setWorkRemaining(10000); doWorkOnElement(node, progress.newChild(1)); node = node.next; } }
This class can be used without OSGi running.
Modifier and Type | Field and Description |
---|---|
static int |
SUPPRESS_ALL_LABELS
May be passed as a flag to newChild.
|
static int |
SUPPRESS_BEGINTASK
May be passed as a flag to newChild.
|
static int |
SUPPRESS_NONE
May be passed as a flag to newChild.
|
static int |
SUPPRESS_SETTASKNAME
May be passed as a flag to newChild.
|
static int |
SUPPRESS_SUBTASK
May be passed as a flag to newChild.
|
UNKNOWN
Modifier and Type | Method and Description |
---|---|
void |
beginTask(String name,
int totalWork)
Starts a new main task.
|
static SubMonitor |
convert(IProgressMonitor monitor)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor.
|
static SubMonitor |
convert(IProgressMonitor monitor,
int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks.
|
static SubMonitor |
convert(IProgressMonitor monitor,
String taskName,
int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks.
|
void |
done()
Notifies that the work is done; that is, either the main task is completed
or the user canceled it.
|
protected static boolean |
eq(Object o1,
Object o2) |
void |
internalWorked(double work)
Internal method to handle scaling correctly.
|
boolean |
isCanceled()
Returns whether cancelation of current operation has been requested.
|
SubMonitor |
newChild(int totalWork)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver.
|
SubMonitor |
newChild(int totalWork,
int suppressFlags)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver.
|
void |
setCanceled(boolean b)
Sets the cancel state to the given value.
|
void |
setTaskName(String name)
Sets the task name to the given value.
|
SubMonitor |
setWorkRemaining(int workRemaining)
Sets the work remaining for this SubMonitor instance.
|
void |
subTask(String name)
Notifies that a subtask of the main task is beginning.
|
void |
worked(int work)
Notifies that a given number of work unit of the main task
has been completed.
|
public static final int SUPPRESS_ALL_LABELS
public static final int SUPPRESS_BEGINTASK
public static final int SUPPRESS_NONE
public static final int SUPPRESS_SETTASKNAME
public static final int SUPPRESS_SUBTASK
public void beginTask(String name, int totalWork)
This method is equivalent calling setWorkRemaining(...) on the receiver. Unless the SUPPRESS_BEGINTASK flag is set, this will also be equivalent to calling setTaskName(...) on the parent.
beginTask
in interface IProgressMonitor
name
- new main task nametotalWork
- number of ticks to allocateIProgressMonitor.beginTask(java.lang.String, int)
public static SubMonitor convert(IProgressMonitor monitor)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is not necessary to call done() on the result, but the caller is responsible for calling done() on the argument. Calls beginTask on the argument.
This method should generally be called at the beginning of a method that accepts an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
monitor
- monitor to convert to a SubMonitor instance or null. Treats null
as a new instance of NullProgressMonitor
.public static SubMonitor convert(IProgressMonitor monitor, int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated with the given number of ticks. It is not necessary to call done() on the result, but the caller is responsible for calling done() on the argument. Calls beginTask on the argument.
This method should generally be called at the beginning of a method that accepts an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
monitor
- monitor to convert to a SubMonitor instance or null. Treats null
as a new instance of NullProgressMonitor
.work
- number of ticks that will be available in the resulting monitorpublic static SubMonitor convert(IProgressMonitor monitor, String taskName, int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated with the given number of ticks. It is not necessary to call done() on the result, but the caller is responsible for calling done() on the argument. Calls beginTask on the argument.
This method should generally be called at the beginning of a method that accepts an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
monitor
- to convert into a SubMonitor instance or null. If given a null argument,
the resulting SubMonitor will not report its progress anywhere.taskName
- user readable name to pass to monitor.beginTask. Never null.work
- initial number of ticks to allocate for children of the SubMonitorpublic void done()
IProgressMonitor
done
in interface IProgressMonitor
public void internalWorked(double work)
IProgressMonitor
internalWorked
in interface IProgressMonitor
work
- the amount of work donepublic boolean isCanceled()
IProgressMonitor
isCanceled
in interface IProgressMonitor
true
if cancellation has been requested,
and false
otherwiseIProgressMonitor.setCanceled(boolean)
public SubMonitor newChild(int totalWork)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. It is not necessary to call beginTask
or done
on the
result. However, the resulting progress monitor will not report any work after the first
call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
or setWorkRemaining.
Each SubMonitor only has one active child at a time. Each time newChild() is called, the result becomes the new active child and any unused progress from the previously-active child is consumed.
This is property makes it unnecessary to call done() on a SubMonitor instance, since child monitors are automatically cleaned up the next time the parent is touched.
////////////////////////////////////////////////////////////////////////////
// Example 1: Typical usage of newChild
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
doSomething(progress.newChild(50));
doSomethingElse(progress.newChild(50));
}
////////////////////////////////////////////////////////////////////////////
// Example 2: Demonstrates the function of active children. Creating children
// is sufficient to smoothly report progress, even if worked(...) and done()
// are never called.
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
for (int i = 0; i < 100; i++) {
// Creating the next child monitor will clean up the previous one,
// causing progress to be reported smoothly even if we don't do anything
// with the monitors we create
progress.newChild(1);
}
}
////////////////////////////////////////////////////////////////////////////
// Example 3: Demonstrates a common anti-pattern
void wrongMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// WRONG WAY: Won't have the intended effect, as only one of these progress
// monitors may be active at a time and the other will report no progress.
callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
}
void rightMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
Object someValue = computeValue(progress.newChild(50));
callMethod(progress.newChild(50), someValue);
}
totalWork
- number of ticks to consume from the receiverpublic SubMonitor newChild(int totalWork, int suppressFlags)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. It is not necessary to call beginTask
or done
on the
result. However, the resulting progress monitor will not report any work after the first
call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
or setWorkRemaining.
Each SubMonitor only has one active child at a time. Each time newChild() is called, the result becomes the new active child and any unused progress from the previously-active child is consumed.
This is property makes it unnecessary to call done() on a SubMonitor instance, since child monitors are automatically cleaned up the next time the parent is touched.
////////////////////////////////////////////////////////////////////////////
// Example 1: Typical usage of newChild
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
doSomething(progress.newChild(50));
doSomethingElse(progress.newChild(50));
}
////////////////////////////////////////////////////////////////////////////
// Example 2: Demonstrates the function of active children. Creating children
// is sufficient to smoothly report progress, even if worked(...) and done()
// are never called.
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
for (int i = 0; i < 100; i++) {
// Creating the next child monitor will clean up the previous one,
// causing progress to be reported smoothly even if we don't do anything
// with the monitors we create
progress.newChild(1);
}
}
////////////////////////////////////////////////////////////////////////////
// Example 3: Demonstrates a common anti-pattern
void wrongMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// WRONG WAY: Won't have the intended effect, as only one of these progress
// monitors may be active at a time and the other will report no progress.
callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
}
void rightMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
Object someValue = computeValue(progress.newChild(50));
callMethod(progress.newChild(50), someValue);
}
totalWork
- number of ticks to consume from the receiverpublic void setCanceled(boolean b)
IProgressMonitor
setCanceled
in interface IProgressMonitor
b
- true
indicates that cancelation has
been requested (but not necessarily acknowledged);
false
clears this flagIProgressMonitor.isCanceled()
public void setTaskName(String name)
IProgressMonitor
setTaskName
in interface IProgressMonitor
name
- the name (or description) of the main taskIProgressMonitor.beginTask(java.lang.String, int)
public SubMonitor setWorkRemaining(int workRemaining)
Sets the work remaining for this SubMonitor instance. This is the total number of ticks that may be reported by all subsequent calls to worked(int), newChild(int), etc. This may be called many times for the same SubMonitor instance. When this method is called, the remaining space on the progress monitor is redistributed into the given number of ticks.
It doesn't matter how much progress has already been reported with this SubMonitor instance. If you call setWorkRemaining(100), you will be able to report 100 more ticks of work before the progress meter reaches 100%.
workRemaining
- total number of remaining tickspublic void subTask(String name)
IProgressMonitor
subTask
in interface IProgressMonitor
name
- the name (or description) of the subtaskpublic void worked(int work)
IProgressMonitor
worked
in interface IProgressMonitor
work
- a non-negative number of work units just completed