Friday, March 30, 2007

Where to start?

A developer that starts his adventure with eclipse contributions, always hit one obstacle - Eclipse is big. Huge. Enormous.

A dozens of plugins in newly downloaded distribution. Thousands of classes, and uncountable amount of code lines.

So, how to get from user interface the underlying code?

I will show you the easy way:

1. Check out all plugins from repository that are connected with your area of interests.


2. Lets say we are trying to modify 'Apply Patch...' action. So press Ctrl-H and perform search.


3. There is no much results:



4. When you check them, you will see another terms to search:


5. Search for them again:


6. Voila - we have the action (and the code):



Best Regards,
Chris

Wednesday, March 21, 2007

How to report operation progress?

Recently I had to learn a little bit about how to report the progress of an operation. I mean this component which is shown below and which you possibly very often see while using Eclipse:



Never before I had to take care about this, so I knew only that, there were some progress monitors, which I had to pass to some methods. I started digging into the web and found two very good articles: How to Correctly and Uniformly Use Progress Monitors and FAQ How do I use progress monitors? . Both documents contain very useful information and give nice examples. However, these two papers describe the approach in which class SubProgressMonitor is used. This solution is good, but why use good solution, when better one can be used? Since Eclipse 3.3 class SubMonitor is available (in the project org.eclipse.equinox.common in package org.eclipse.core.runtime) and this is a very good news. Why?
Basically because:
  • we don't have to call methods beginTask() and done() on the instance of SubMonitor class
  • it is easier now to create submonitors (there is a method newChild(int totalWork))
  • in SubMonitor we can find method setWorkRemining() which allows us to redistribute the remaining space on the progress monitor
  • SubMonitor protects the caller from common progress reporting bugs in a called method
I was trying to find some information in the Web concerning SubMonitor, but I failed. Fortunately I found useful info in the javadoc, so I decided to make it more public to make this solution more popular.
First of all we have to convert any other kind of progress monitor into SubMonitor. This is very easy, because we can use one of two static methods:
public
static SubMonitor convert(IProgressMonitor monitor, int work)

and
public
static SubMonitor convert(IProgressMonitor monitor, String taskName, int work)

So after invoking:
SubMonitor progress = SubMonitor.convert(monitor, 100);

we can benefit from all the advances of SubMonitor class.
The basic example of using SubMonitor could look like this:

void someOperation(IProgressMonitor monitor) {

// Convertion of the given monitor
SubMonitor progressSubMonitor = SubMonitor.convert(monitor, 100);

// 70% of work is consumed
doSomeWork(progressSubMonitor.newChild(70));

// 30% of work is consumed
progressSubMonitor.worked(30);

}

My main concern about reporting the progress was how to manipulate the number of work items, when some operation will or will not be executed (so when we have a condition). Fortunately with SubMonitor it is pretty easy. The example below shows how to do this:

void
someOperation(IProgressMonitor monitor) {

SubMonitor progressSubMonitor = SubMonitor.convert(monitor, 100);

if (condition) {
// 50% of work is consumed

doSomeWork(progressSubMonitor.newChild(40));
}

//if there is any work item resumed from the first 40% then use it

progress.setWorkRemaining(40);

// the rest of work items is consumed

doSomeWork(progress.newChild(60));

}


It is also easy to handle the loop case:

void someOperation(IProgressMonitor monitor, Collection someCollection) {

SubMonitor progressSubMonitor = SubMonitor.convert(monitor, 100);

// Create a new progress monitor that uses 70% of the total progress
SubMonitor loopProgress = progressSubMonitor.newChild(70);

// Allocate one tick for each element of the given collection.
loopProgress.setWorkRemaining(someCollection.size());

for (Iterator iter = someCollection.iterator(); iter.hasNext();) {
Object next = iter.next();
//Do something with the element from collection and
//consume one work item
doSomeWorkOnElement(next, loopProgress.newChild(1));
}

// Use the remaining 30% of the progress monitor to do some work outside
// the loop
doSomeWork(progressSubMonitor .newChild(30));

}

Have fun with using SubMonitor ;-)