Eclipse Search

Loading

Aug 22, 2008

Adding an IAction to a Job

How do you show the partial results of a background job that is not yet completed? Quick answer is by adding an Action to that Job. The long answer is this tip.

The Progress view shows all the jobs that are scheduled. It also shows the progress bar which is updated with the amount of work done. Consider this snippet:

Job job = new Job("My Job") {
    @Override
    protected IStatus run(IProgressMonitor monitor) {
        monitor.beginTask("My job is working...", 100);
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {} // ignore
            monitor.worked(1);
        }
        monitor.done();
        return new Status(IStatus.OK, Activator.PLUGIN_ID, "Job finished");
    }

};
job.schedule();

The Progress view shows this job like this:


 
Jobs allow user defined key-value pair properties to be set on them. The key would be QualifiedName and the value will be any Object. The Progress view identifies certain properties set on the job and acts accordingly. One of the properties is IProgressConstants.ACTION_PROPERTY. The value should be an IAction.

job.setProperty(IProgressConstants.ACTION_PROPERTY, new Action() {
    @Override
    public void run() {
        MessageDialog.openInformation(new Shell(), "Job Status", "Some partial results processed can be displayed here");    
        }
    });
}


When you set an action on a job as above, the Progress view finds it and gives you the visual hint:




The progress text becomes a hyperlink. When you click on it, the associated action will be executed. You can probably open up a dialog with the results of the job which is completed so far.

As soon as the job is over, the Progress view removes it from the view. Is there a way to reuse this same action to show the complete set of results even after the job is finished? Yes. The Progress view understands another property called IProgressConstants.KEEP_PROPERTY. Its a boolean property, and when its set, the Job stays in the Progress view even after its finished.

job.setProperty(IProgressConstants.KEEP_PROPERTY, true);




Since the ProgressMonitor is done, the text for the hyperlink is now taken from the IStatus that is returned from the Job.

All is fine when the job finishes normally. But what if the return status is an error? Progress view opens up a Dialog and shows you the status. It might be intrusive sometimes. Is there a way to suppress the dialog so that the user can go back to the Progress view and check the status? Again Yes. Just set the boolean property IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, there won't be any dialogs. The Progress view icon in the status bar will indicate the user that some job did not complete normally. When the user clicks on the job, can reuse the same action to display what went wrong.

job.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, true);




 
Did you see the other job in the above pictures? It has a nice looking icon. So how do we associate an icon with our job? Yes, what you think is right. The Progress view also understands an another property IProgressConstants.ICON_PROPERTY thru which you can set your icon:

job.setProperty(IProgressConstants.ICON_PROPERTY, getJobImageDescriptor());

There you go:



Next time you create a long running background job, consider setting these properties.

Update [28-Oct-09]: Starting from 3.6 M3, you can now associate a Command also

Aug 20, 2008

Adding Color and Font preferences

You had that nice looking editors and views. You loved the button color and the geeky font. But your boss didn't. Solution? Put a preference so that the user can choose which ever he likes ;-)

Ok. That may not be the real rationale, but for a valid reason, you wanted to have Color and Font preferences in the PreferencePage. The obvious answer for us (the plugin develoepers) would be to add ColorFieldEditor & FontFieldEditor in our existing PreferencePage. But its not obvious for the user to look into your plugins Preference Page for changing them. Eclipse already provides a PreferencePage for these customizations: Colors and Fonts page ( General->Appearance->Colors and Fonts ) Users might be looking into this place to change the colors & fonts.


As you can see in the above image it categorizes the available preferences; gives a filter to search; provides space for description and preview; and a tool tip for the current value of the preference. This is much more than the *FieldEditor right? In this tip let us see how to add our preferences into that and access them.

You need to extend the org.eclipse.ui.themes extension point for adding your content into this page. I would like to provide one category with one color preference and one font preference. The extension is:

<extension point="org.eclipse.ui.themes">
    <themeElementCategory
        id="com.eclipse-tips.blog.preferences.themeElementCategory"
        label="Eclipse Tips">
        <description>
            An example theme category
        </description>
    </themeElementCategory>
    <colorDefinition
        categoryId="com.eclipse-tips.blog.preferences.themeElementCategory"
        id="com.eclipse-tips.blog.preferences.colorDefinition"
        label="Some Color"
        value="COLOR_DARK_BLUE">
        <description>
            Your description goes here
        </description>
    </colorDefinition>
    <fontDefinition
        categoryId="com.eclipse-tips.blog.preferences.themeElementCategory"
        id="com.eclipse-tips.blog.preferences.fontDefinition"
        label="Some Font"
        value="Lucida Sans-italic-18">
        <description>
            Description for this font
        </description>
    </fontDefinition>
</extension>


Guess all the elements are self explanatory - except for the value element. For colorDefinition the value element will be the COLOR_* constants defined in the SWT class. You can specify your custom colors thru comma separated RGB values like 125,245,96. For fontDefinition it would be fontname-style-height. Now our UI will look like:



To get the values stored in the preferences, you need to use the IThemeManager:

IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
ITheme currentTheme = themeManager.getCurrentTheme();
 
ColorRegistry colorRegistry = currentTheme.getColorRegistry();
Color color = colorRegistry.get("com.eclipse-tips.blog.preferences.colorDefinition");

FontRegistry fontRegistry = currentTheme.getFontRegistry();
Font font = fontRegistry.get("com.eclipse-tips.blog.preferences.fontDefinition");

Once you get the current theme, you can get the preferences stored by giving the appropriate ids defined in the plugin.xml

What you have seen is just the tip of the iceberg. The themes extension point has much more functionalities (The Preview is one such example). I'll explain them later, but you can see the Extension Point description here.

Aug 13, 2008

ArrayContentProvider - A default implementation for IStructuredContentProvider

Today I discovered that JFace provides a nice default implementation for the IStructuredContentProvider - the org.eclipse.jface.viewers.ArrayContentProvider class. Most of the time, the input to a ListViewer will be either an array of objects or List of objects. This content provider handles both cases. In fact it handles Collection - so you can even pass a Set or Queue to the viewer.setInput() method.

This might be the shortest tip I've ever written. Couldn't resist myself from blogging this. Hope its useful :-)

Update [6-Oct-2008]:
    ArrayContentProvider is now a singleton! Which means, less memory consumed even if you use this for multiple viewers

Aug 6, 2008

Using Dynamic Templates in EMF

In the previous tips, we saw how to use the ECore to generate new methods & comments. Now lets see how to customize the generation process itself.



EMF uses JET to generate the Java code. EMF ships a default set of JET templates which are used for the code generation. However, you can create your own templates and ask EMF to use that. Creating those templates from scratch is an enormous task, the best approach is to edit the default templates.



The default templates are available inside the org.eclipse.emf.codegen.ecore plugin. To get those into your project:



  • Open the Plug-ins view and Right click the org.eclipse.emf.codegen.ecore plugin

  • Select Import As -> Binary Project





  • Now your workspace should contain this plug-in project. Copy the templates directory and Paste it in your EMF Project. After this step, you can delete the org.eclipse.emf.codegen.ecore project and remove it from your workspace. 



  • Set the Dynamic Templates to true and specify the directory where your templates are stored.




Now that you have the templates in your project, let tell EMF to use these. Open your .genmodel and go to the Properties View.



You can customize these templates to suit your requirements. Say for example, you want edit the Copyright statement that is generated in every Java file. Open the templates/Header.javajetinc file and add the required content. You would have to know JET to do that, but its fairly simple. You can refer to the articles here and here for more help on JET.