Jan 14

If you:

  • are a fast and willing learner
  • are passionate about developing quality software
  • are self-disciplined and self-motivating
  • tired of the typical city and office life
  • need more flexibility in your working day
  • have experience in Object-oriented development
  • have experience in Java (acronyms optional)
  • are willing to either move to Worcester or work remotely with regular visits to Worcester

Then we:

  • want to talk to you about contracting or permanent employee options
  • want to provide training and mentoring
  • want to make you part of a newly founded team that has the goal of becoming the leading Southern Africa Eclipse RCP/RAP and OSGi development team
  • want to expose you not only to exciting new software projects, prototyping, and technology research, but also to interesting consultation opportunities, and unfortunately a bit of less interesting maintenance work

Email us at: jobs@richclientgui.com

Tagged with:
Jun 03

This is the third part of my blog series on the Eclipse Commands framework. Please see Part One for an outline of topics covered in the various blogs.

Limiting visibility of Commands

A powerful feature of the Commands framework is that you can declare in the plugin.xml when a Command should be visible (or rather when specific menu contributions should be visible) and when it should be enabled. This is done by using what is called core expressions.


Simple visibleWhen definition

Let us take a simple example first: we want to limit the Annotate eBook command (from the example in Part Two: Quick Review) to only show in the context menu if one item is selected in the view. If no item is selected, or more than one, it must not appear in the menu.

  • First select the popup:org.eclipse.ui.popup.any?after=additions menu contribution extension element
  • Now select the Annotate command element, right-click and choose New -> visibleWhen
  • Set the checkEnabled value to false (setting to true will use the enabled state of the command to determine the visibility)
  • Right-click on the visibleWhen element, and choose New -> with
  • Set the variable attribute to “activeMenuSelection“. “activeMenuSelection” is a known expressions variable that will get resolved when the platform must populate the context menu. Se the list of other known expression variables.
  • Right-click on the activeMenuSelection(with) element and choose New -> count
  • Set the value attribute for count to “1“.

    We have now set up the context-menu contribution to only show the Annotate command when one and only one item in the view is selected. That was not so difficult, was it? I remember spending hours on creating nice selection behaviour helper classes for IActionDelegate-based frameworks, and still not getting the initial visibility or enabling of the actions in the menus right, due to constraints with that approach.

    The menu contributions extension in the plugin.xml now looks like:



       <extension
             point="org.eclipse.ui.menus">
          <menuContribution
                locationURI="menu:file?before=quit">
             <command
                   commandId="com.richclientgui.myreader.commands.OpenEBook"
                   mnemonic="O"
                   style="push">
             </command>
             <command
                   commandId="com.richclientgui.myreader.commands.AnnotateEBook"
                   mnemonic="A"
                   style="push">
             </command>
          </menuContribution>
          <menuContribution
                locationURI="popup:org.eclipse.ui.popup.any?after=additions">
             <command
                   commandId="com.richclientgui.myreader.commands.AnnotateEBook"
                   label="Annotate"
                   mnemonic="A"
                   style="push">
                <visibleWhen
                      checkEnabled="false">
                   <with
                         variable="activeMenuSelection">
                      <count
                            value="1">
                      </count>
                   </with>
                </visibleWhen>
             </command>
          </menuContribution>
       </extension>



    Expression Definitions

    Before I delve more deeply into even more interesting visibleWhen capabilities, first a very nifty tip on core expressions: it is possible to declare a specific expression definition, and then just refer to that definition from your visibleWhen, activeWhen, etc elements.

    We do this with the org.eclipse.core.expressions.definitions extension. To define an expression that checks that only one item is selected:

  • Add the org.eclipse.core.expressions.definitions extension (click Add… on Extensions tab of plugin manifest editor, you might need to uncheck the “Show only extension points from the required plug-ins” checkbox)
  • Give a proper id to your definition, e.g. expression.onlyOneItemSelected
  • Right-click on the expression.onlyOneItemSelected element and choose New -> with
  • Set the variable attribute to “activeMenuSelection“.
  • Right-click on the activeMenuSelection(with) element and choose New -> count
  • Set the value attribute for count to “1“.

    You might have noticed it is the same steps as those followed for a simple visibleWhen definition above.
    For those who rather do it directly in the plugin.xml, here is the org.eclipse.core.expressions.definitions extension declaration:





       <extension
             point="org.eclipse.core.expressions.definitions">
          <definition
                id="expression.onlyOneItemSelected">
             <with
                   variable="activeMenuSelection">
                <count
                      value="1">
                </count>
             </with>
          </definition>
       </extension>


    How do I use the expression definition?

    What do you gain with first defining an expression? Well, you can reuse this definition in multiple places in your plugin.xml if you need the same expression, whether it is for a visibleWhen, activeWhen or enabledWhen declaration.

    To replace our expression for our context menu contribution with the definition, you simply do the following:

  • Select the activeMenuSelection(when) element under the popup:org.eclipse.ui.popup.any?after=additions menu contribution’s visibleWhen element, right-click and select Delete
  • Right-click again on the visibleWhen element and choose New -> reference
  • Set the definitionId attribute to expression.onlyOneItemSelected (i.e. the id of the expression definition you want to use to evaluate whether the menu contribution must be visible or not)

    If you run the application now, it should still behave the same as before we used our own definition, but now we are ready for a much more complex playing field. Underneath is a screenshot of how the extension declarations should look in the Plugin Editor.

    Extensions Commands 4


    To infinity and beyond: the power of expressions

    We have seen a very basic expression up to now. You should have seen a number of other possible items to choose from when you selected New -> with in the steps above. I list them below. These can all be used to build up complex expressions that gets evaluated at runtime to determine whether a specific menu contribution should be visible or not, if used in conjunction with a visibleWhen element.
    Possible Expression Elements

    Element Description
    adapt Use to adapt the object in focus (i.e. the object passed to the expression) to the specified type. See Using adapt for more information.
    and AND the results from evaluating the sub-elements
    count Use to count the number of elements in a collection. The value attribute be an integer or a supported wildcard. See Using count for more information.
    equals Use to check equality of the focussed object with the specified value attribute
    instanceof Use to perform an instanceof check on the object in focus. See Using instanceof for more information.
    iterate Use to iterate over a collection, if the focussed object is of type java.util.Collection. See Using iterate for more information.
    not NOT the results from evaluating the sub-elements
    or OR the results from evaluating the sub-elements
    reference This is the element we use to refer to an expression defined under org.eclipse.core.expressions.definitions. The definitionId is the unique id of the expression definition to use for the evaluation.
    systemTest Use to test a system property, where property is the name of the property to get via System.getProperty, and value is the expected value to test against (as String value).
    test Use this element to test the value of a specific property on the focussed object. See Using test for more information.
    with Use to change the object to inspect or focus on to the object referenced by the variable attribute. See the list of available expression variables.
    resolve Resolve does almost the same as with, but it allows the use of a custom IVariableResolver, and passing the specified args as arguments to the variable resolver. More detail might be topic of a future blog post. I must admit, I have never used this one.

    Note on String values

    The value attribute for the above elements gets specified as some string. Here follows the extract from the Eclipse online help on how that String value might get converted:

    When specifying a value to be tested against any of these expressions, the value is assumed to be a string except for when the following conversions are successful:

  • the string “true” is converted into Boolean.TRUE
  • the string “false” is converted into Boolean.FALSE
  • if the string contains a dot, the interpreter tries to convert the value into a Float object
  • if the string only consists of numbers, the interpreter converts the value into an Integer object
    the conversion into a Boolean, Float, or Integer can be suppressed by surrounding the string with single quotes.


    Using adapt

    Adapt is used to adapt the object in focus (you can see this as the object provided or specified by the parent element) to the type specified its the type attribute. Any sub-elements of the adapt element will be evaluated against the adapted object. Read up about IAdapterFactory and IAdaptable interfaces for more information about adaption.
    If the object can be adapted, the adapt evaluate to true. E.g. we can define an expression for evaluating if something adapts to the ICountable interface.





       <extension
             point="org.eclipse.core.expressions.definitions">
          <definition
                id="isCountable">
             <adapt
                   type="org.eclipse.core.expressions.ICountable">
             </adapt>
          </definition>
       </extension>



    Using instanceof

    This is used to perform an instanceof check on the object in focus. We can for example enhance our Annotate eBook menu contribution in the File menu to only display if at least on of the selected items is an instance of java.lang.String (iterate gets discussed here):





       <extension
             point="org.eclipse.ui.menus">
          <menuContribution
                locationURI="menu:file?before=quit">
             <command
                   commandId="com.richclientgui.myreader.commands.OpenEBook"
                   mnemonic="O"
                   style="push">
             </command>
             <command
                   commandId="com.richclientgui.myreader.commands.AnnotateEBook"
                   mnemonic="A"
                   style="push">
                <visibleWhen
                      checkEnabled="false">
                   <with
                         variable="selection">
                      <iterate
                            ifEmpty="false"
                            operator="or">
                         <instanceof
                               value="java.lang.String">
                         </instanceof>
                      </iterate>
                   </with>
                </visibleWhen>
             </command>
          </menuContribution>



    Using iterate

    Iterate can be used if the object in focus is a java.util.Collection (e.g. when with is used in the parent element and the variable attribute is set to “selection“). It iterates through the collection, and evaluate the sub-elements against each item in the collection.

    The operator attribute can be set to and or or. For and, every item must cause the sub-elements of the expression to evaluate to true, and for or, at least one must evaluate to true.

    The ifEmpty attribute can be set to true or false. If true, then the iterate expression will evaluate to true for empty collections, else to false.

    See the example under the instanceof section.


    Using count

    The count element’s value attribute can take an integer value as parameter if the collection needs to contain the exact number of items. However, the following wildcards are also allowed:

    * Any number of items
    ? Zero or one item
    + One ore more items
    ! No items

    See our first simple visibleWhen example for usage.


    Using test

    Test can be used to evaluate the state (i.e. value) of a specific property of the focussed object. The test expression can evaluate to true, false or not-loaded if the property tester (implemented by a Java class) is not loaded.

    property specifies the name of the property of the object to test
    args specifies additional arguments to pass to the property tester
    value the value we expect the property to be
    forcePluginActivation if this is set to true, the plugin that contributes the property tester class will be loaded to enable the evaluation, if it is not loaded yet. However, this loading will only happen if the evaluation context used allows plugin activation. What does this mean: do not depend that when you set this flag to true, the plugin containing the property tester code will actually be loaded.

    In a future blog I will discuss how to implement your own property testers; quite a powerful feature. For now, let me just point you to some property testers available for your enjoyment. You can follow the links for the detailed code level information, or else have a look at the Propery Testers section in the Command Core Expressions wiki page for a summary.

  • PlatformPropertyTester
  • ResourcePropertyTester
  • FilePropertyTester
  • ProjectPropertyTester
  • ResourceMappingPropertyTester
  • ActivityPropertyTester
  • OpenPerspectivePropertyTester


    Core Expression Variables

    I was planning to list the most common variables available for core expressions here and discuss some of them, but time caught up with me. For now I will point you to:

  • The Variables and the Command Framework section in the Command Core Expressions wiki page.
  • The ISources.java file that list these variables.

    Note: if you use the selection variable, you need to make sure the View that you are expecting a selection from is a SelectionProvider for the platform by registering it as a selection provider, e.g. by calling getSite().setSelectionProvider(viewer).

    Coming soon…

  • What about enabling and disabling Commands? (enabledWhen, activeWhen)
  • More on using object properties to determine visibility and enablement of Commands (propertyTesters)
  • If you don’t like XML: how to tune your Commands from the Java side of things (the programmatic approach)

    References

  • Eclipse.org Commands Framework Article in bugzilla
  • Article on Eclipse Commands Framework, by Marc R. Hoffmann
  • Eclipse.org Wiki on Command Framework
  • Eclipse Commands Tutorial, by Lars Vogel
  • Eclipse.org Wiki on Core Expressions
  • Eclipse.org Wiki on Menu Contributions
  • Eclipse.org Wiki on mapping from old to new menu contribution extension points

    Enough said.

  • Tagged with:
    Jun 01

    When faced with a bulky problem…
    When faced with a bulky problem...

    you have to start digging.
    you have to start digging

    Thanks to Aslam Khan for planting the term “archeology of Java” in a discussion.

    Tagged with:
    Jun 01

    Quick Review: Defining a Command

    In this blog I just want review the basic definition of a command by adding an additional Command to the example application using the steps defined in Part Two of the series on Eclipse RCP Commands.

    We already have an Open eBook command that we made visible in the File menu of the MyReader application. Now we want to another item to the File menu, as well as to a context menu, to allow the user to annotate an eBook. Let us call this the Annotate eBook command. So let us follow the same eight steps we did for the Open eBook command.

    Step 1: Create RCP application

    Done already (I assume you are working from the example in Part Two.)

    Step 2: Add org.eclipse.ui.commands extension to plugin.xml.

    Done already. (see step 2 of previous blog)

    Step 3: Declare Annotate eBook command.

  • right-click the org.eclipse.ui.commands extension, and select New -> Command from the context menu.
  • change the id to something like “com.richclientgui.myreader.commands.AnnotateEBook
  • change the name to “Annotate eBook
  • change description to “Annotates the current eBook

    Our plugin.xml now contains the following entry for the org.eclipse.ui.commands extension:





    <extension
    point=“org.eclipse.ui.commands”>
    <command
    defaultHandler=“com.richclientgui.myreader.handlers.DefaultOpenEBookHandler”
    description=“Open an eBook file for reading”
    id=“com.richclientgui.myreader.commands.OpenEBook”
    name=“Open eBook”>
    </command>
    <command
    description=“Annotates the current eBook”
    id=“com.richclientgui.myreader.commands.AnnotateEBook”
    name=“Annotate eBook”>
    </command>
    </extension>


    Step 4: Add the org.eclipse.ui.menus extension to plugin.xml.

    Done. (see step 4 of previous blog)

    Step 5: Add the menuContribution element

    We want to make our Annotate eBook command accessible both in the File menu, and in the context menu of the view. We already declared a menuContribution for the File menu (see step 5 of previous blog).
    In order to make the command accessible in any context menu, we add a new menuContribution:

  • Right-click the org.eclipse.ui.menus extension, and select New -> menuContribution from the context menu
  • Change the locationURI to popup:org.eclipse.ui.popup.any?after=additions

    Step 6: Add the Annotate eBook command to the menuContributions.

  • Right-click on the menuContribution created in step 5, and select New -> command from the context menu.
  • Change commandId to the id you provided to your Command definition in step 3.
  • Change mnemonic to “A” to underline the first letter of “Annotate” as your shortcut mnemonic for your command in the menu.
  • Repeat the above for the menu:file?before=quit menuContribution element.But now we have an interesting problem: the client wants the menu item in the File menu to read “Annotate eBook“, but the context menu’s item must read only “Annotate“. If we change the name attribute of the command definition, then it will change in both places. Luckily, the Commands API can help us out here. It is possible to change the presentation of commands for specific menu contributions by “overriding” the text to be used for labels and tooltips. To do this we:
  • Select the command contribution element under the popup:org.eclipse.ui.popup.any?after=additions menu contribution elment,
  • and change the value of the label attribute to “Annotate”.
    Our org.eclipse.ui.menus extension definition in the plugin.xml now looks like:





    <extension
    point=“org.eclipse.ui.menus”>
    <menuContribution
    locationURI=“menu:file?before=quit”>
    <command
    commandId=“com.richclientgui.myreader.commands.OpenEBook”
    mnemonic=“O”
    style=“push”>
    </command>
    <command
    commandId=“com.richclientgui.myreader.commands.AnnotateEBook”
    mnemonic=“A”
    style=“push”>
    </command>
    </menuContribution>
    <menuContribution
    locationURI=“popup:org.eclipse.ui.popup.any?after=additions”>
    <command
    commandId=“com.richclientgui.myreader.commands.AnnotateEBook”
    label=“Annotate”
    mnemonic=“A”
    style=“push”>
    </command>
    </menuContribution>
    </extension>


    Step 7: Change command menu-item placement.

    Let’s assume we are happy with the current placement.

    Step 8: Implement a default Handler

    Let us be lazy again and implement a very basic handler that just opens a message dialog. I will go into more detail about org.eclipse.core.commands.Handler and a future blog.

  • Implement a class called DefaultAnnotateEBookHandler that extends AbstractHandler, and only override the execute(…) method to call the JFace MessageDialog class to show some information.
  • Select the AnnotateEBookCommand definition from step 3 and select the DefaultAnnotateEBookHandler class as the defaultHandler’s value.
    The code for DefaultAnnotateEBookHandler looks something like this:





    import org.eclipse.core.commands.AbstractHandler;
    import org.eclipse.core.commands.ExecutionEvent;
    import org.eclipse.core.commands.ExecutionException;
    import org.eclipse.jface.dialogs.MessageDialog;
    import org.eclipse.swt.widgets.Display;

    public class DefaultAnnotateEBookHandler extends AbstractHandler {

    public Object execute(ExecutionEvent event) throws ExecutionException {
    MessageDialog.openInformation(Display.getDefault().getActiveShell(),
    “Annotate”, “For now: write in the margins of the real book.”);
    return null;
    }

    }


    Where’s that context menu?

    Those of you who have actually been entering the example code, would have found out by now that there is no context showing when running the example. Why not? Well, we have not created a context menu yet for our View. Do that, open the View class created by the New Plug-in Project Wizard in step 1 of my previous blog.
    Change the code to look like this (basically adding the createContextMenu() method):





    public class View extends ViewPart {
    public static final String ID = “MyReader.view”;
    private TableViewer viewer;

    //other code not shown…

    public void createPartControl(Composite parent) {
    viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
    | SWT.V_SCROLL);
    viewer.setContentProvider(new ViewContentProvider());
    viewer.setLabelProvider(new ViewLabelProvider());
    viewer.setInput(getViewSite());
    createContextMenu();
    }

    private void createContextMenu(){
    final MenuManager mm = new MenuManager(“view.popupmenu”);
    mm.setRemoveAllWhenShown(true);
    mm.addMenuListener(new IMenuListener(){
    public void menuAboutToShow(IMenuManager manager) {
    mm.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }
    });
    final Menu menu = mm.createContextMenu(viewer.getTable());
    viewer.getTable().setMenu(menu);
    getSite().registerContextMenu(mm, viewer);
    }


    If you run the MyReader application now, you should get the context menu when right-clicking in the view, proudly showing your “Annotate” item.

    Feel free to download the source code for this blog’s example.

    Next up

  • Showing commands only when you want to…

    References

  • Eclipse.org Commands Framework Article in bugzilla
  • Article on Eclipse Commands Framework, by Marc R. Hoffmann
  • Eclipse.org Wiki on Command Framework
  • Eclipse Commands Tutorial, by Lars Vogel

    Enough said.

  • Tagged with:
    May 29

    Some XCode shortcut keys I found very useful:

    Editor keys

    Key Description
    Tab Accept the current completion and jump to after it
    Escape, Control-comma, F5 Shows a pop-up list from which you can select from all the available code sense completions
    Control-period to insert the most likely completion
    Control-Slash / Shift-Control-Slash move between place holder tokens
    Cmd-/ insert comment line
    Ctrl+Left/Right Arrow Jump to previous/next word
    Command-[ and Command-] indent and unindent selected text
    Control-Command Left/Right fold and unfold the function
    Command-Shift-E expand the editor view to full height of the window

    Navigation keys

    Key Description
    Alt-Command-Up Switch between .m and .h file
    Alt-Command-Left / Alt-Command-Right Navigate among open files back and forth.
    Command-Shift-D Show the “Open Quickly” dialog for navigating to defined type or function in your project
    Control-Option-1 Show list of all project files
    Control-Option-2 Show list of members of current file
    Control-Option-3 Show list of include files
    Control-Option-4 Show list of bookmarks
    Control-Option-5 Show list of breakpoints
    Control-Shift-R Show the Console
    Control-Alt-Command-R clear the log
    Shift-Command-C Show the Class browser
    Command-= Jump to the next error in the list of build errors
    Command-Shift-F Display the multiple Find panel
    Command-O Jump to the Project tab
    Command-Shift-B Jump to the Build tab
    Command-Shift-Y Jump to the Debug tab

    Mouse tips

  • Double-click on the square brackets or parentheses to select everything between opening and closing brackets
  • Command-double click on a symbol to see the definition of a symbol
  • Option-double click on a symbol to see the documentation for that symbol

    Thanks to Adeem Basraa for his shortcuts list that helped me find my way around XCode and was a reference for this quick blog.

  • Tagged with:
    May 27

    This is my second blog about the Eclipse Commands framework, but actually the first one containing useful (I hope) information. I’m going to focus on the topic from a practical “using it in development” point of view, trying to keep the examples as simple as possible and the theory limited. For an updated outline please refer to the first blog in the series: Eclipse RCP Commands Part One.

    Short history: the Commands framework has been around partially since Eclipse 3.0, maturing over the versions until it became quite useful in Eclipse 3.3. Some refinements in Eclipse 3.4 makes it even more appealing. I must admit, before Eclipse 3.3 I saw no reason for using Commands, and I stuck to using IActions and IActionDelegates, trying to work around their issues as much as possible (and falling into the rythm of the copy-and-paste anti-pattern in order to contribute an IActionDelegate to multiple places in a UI). No I’m trying to convince all my clients to “renew” their code to use Commands…

    What are Commands

    A command is neither the presentation nor a particular behavior implementation; it is an abstract representation of some semantical behavior.” - Marc R. Hoffmann (see Article on Eclipse Commands Framework)

    That’s the best quote I could find as to what a Command is. What does it boil down to? I assume (hope?) you are all familiar with the Model-View-Controller pattern, used especially when developing UI applications. By abstracting a particular piece of functionality into separate Model, View and Controller objects, the code is must less coupled, allowing more (and easier) reuse, flexibility and extensibility.

    Well, the Command design is not exactly MVC, but it has the same goals in mind. It abstracts the actual business or application semantics (i.e. what is actually meant to happen from business or application functionality perspective) into this thing called a Command. Worries about how it should appear in the UI (menu contributions), or what exactly must happen on a code implementation level to execute the command (handlers) is left for later. In this way we get the same decoupling of presentation and implementation as with MVC, and thus the gain in reusability of Commands and their handlers, and increase in the flexibility and extensibility of the code, thus leading overall to code that is much easier to maintain.

    Add to the above paragraph that code that is easier to maintain leads to huge development cost savings, and you’ll have a convincing argument to offer to your boss for allowing you to refactor away all the old IActionDelegates.

    Ok, but what to we do with Commands?

    Plain and simple: we use it to implement functions that our application can perform and make it available as menu or toolbar items so the user can invoke it.

    On a more practical level

    That is about enough theory for one day. Let’s get down to the bits and the bytes.

    The Example

    Firstly, I want to introduce my patent-pending idea for an application. Image this: you have this cross-platform application (obviously implemented using Eclipse RCP) that can actually read electronic versions of books, that we can call “e-books”. “Wow!” you say. “Amazing”. “What a novel idea”.

    Let us call our bleeding edge application MyReader. You can download the source code for this blog’s version of the example.

    Step 1: Create a RCP application using Eclipse 3.4 (I’m using 3.4.1) and the New Plug-in Project wizard.

  • Name the project MyReader
  • On the next wizard page fill in the details you want, but make sure “Would you like to create a rich client application” is set to “Yes“.
  • On the third wizard page, select the “RCP application with a view” as the template to use.
  • Run the resulting RCP application to make sure it runs, so you don’t blame my examples later for messing up your pristine code.

    Now we have the example application that we are going to enable with Commands. Exciting, isn’t it?

    How to define a Command

    To have a command that is actually accessible in the UI, and able to do something, we need 3 “components”:

  • The Intent: the Command declaration
  • The Presentation: the menu contribution declaration(s)
  • The Behaviour: the Handler that implements the behaviour of the Command

    Declaring the Command (Intent)

    We declare the Command using the org.eclipse.ui.commands extension point. I’m sure you remember this command we declare indicates the meaning or intent of the functionality we want to add to our application or plugin.

    Let us explore this Command declaration in our example, and then I’ll discuss what is going on.
    We need to open an ebook file with our application, so we will define a command to do this.

    Step 2: Add the org.eclipse.ui.commands extension to our plugin.xml

  • Open the PDE-Editor (Plugin Editor), if it is not open already, and select the Extensions tab. (You double-click the plugin.xml or MANIFEST.MF files in the project. However, if you did not know that, you must maybe first implement a “Hello RCP World” application before jumping to Commands…)
  • If, due to random bit-changes caused by unexplained solar activity, you already have the org.eclipse.ui.commands extension in your list of extensions, then do not follow the rest of this step.
  • Click on the “Add…” button.
  • Start typing in “org.eclipse.ui.commands“, and select it from the filtered list when you see it. If it is not available uncheck the “Show only extension points from required plug-ins” option.
  • Select the Finish button. This will add the org.eclipse.ui.commands entry to your plugin.xml file.

    Step 3: Declare the Open File command

  • right-click the org.eclipse.ui.commands extension, and select New -> Command from the context menu.
  • change the id to something like “mydomain.myreader.commands.OpenEBook
  • change the name to “Open eBook
  • change description to “Opens an eBook file for reading
  • for now, ignore the rest

    Steps 2 and 3 updates the plugin.xml file of the plugin project by adding the necessary extension point and declaring a basic command. The plugin.xml file now contains:






       <extension
             point="org.eclipse.ui.commands">
          <command
                description="Open an eBook file for reading"
                id="com.richclientgui.myreader.commands.OpenEBook"
                name="Open eBook">
          </command>
       </extension>


    Congratulations! Your first command.

    “But if I run my app, I don’t see this command. What’s wrong?” Nothing. We still need to define how this command will be visible in the UI, and what the behavior should be when this command is invoked. As mentioned earlier, these are decoupled from the Command declaration.

    However, let us first examine the declaration in the plugin.xml. The org.eclipse.ui.commands extension allows us to declare, among other things, a Command. The Command definition needs the following attributes:

    id a unique id that will be used for referring to this command when declaring the UI contributions and Handlers
    name a user-readable name that will be used for the label in the menu contribution(s), if the menu contribution does not define its own label
    description a user-readable name that will be used for the tooltip in the menu contribution(s), if the contribution does not define its own description

    We are still going to have a look at some of the other attributes available. If you can’t wait, go and see org.eclipse.ui.commands for more detailed information about the extension point definition. Go on, don’t mind me.

    Note: here we had a look at how to declare commands using the extension point in the plugin.xml file. In a later blog I plan to discuss how to do it programmatically. I will update this section with a link to that blog as soon as it is available.

    Basic menu contribution (Presentation)

    It is time to get his command to be presented in the UI of the application. I assume you have already done some nice UI design work sessions with your potential end-users and you are ready to build the ultimate user friendly intuitive graphical user interface for your application. For our example we are just going to use the UI-design-by-coincidence approach and just add our stuff and see how it looks.

    In order to contribute an item that will invoke a Command to the UI, we need to add the org.eclipse.ui.menus extension to our plugin.xml, and declare a MenuContribution element followed by a Command element.

    We first declare where (i.e. the main menubar or toolbar, or a view or editor specific menu and/or toolbar, or a context menu) the command should be added via the MenuContribution. Then we declare the visual representation of our Command using the MenuContribution’s Command element.

    Step 4:Add the org.eclipse.ui.menus extension to plugin.xml

  • Click on the Add… button in the Plugin Editor.
  • Select the org.eclipse.ui.menus extension from the list of available extensions. If it is not available uncheck the “Show only extension points from required plug-ins” option.
  • Select the Finish button. This will add the org.eclipse.ui.menus extension to the plugin.xml file.

    Step 5: Add the MenuContribution element

  • Right-click the org.eclipse.ui.menus extension, and select New -> menuContribution from the context menu
  • Change the locationURI to menu:file?after=additions (don’t worry, we’ll discuss it just now)

    Step 6: Add the Command to the MenuContribution

  • Right-click on the menuContribution created in step 5, and select New -> command from the context menu.
  • Change commandId to the id you provided to your Command definition in step 3.
  • Change mnemonic to “O” to underline the first letter of the “Open” as your shortcut mnemonic for your command in the menu.

    I’m sure you are eager to run your MyReader app now. Go ahead, please. Do you see it? A grayed-out Open eBook menu-item just underneath Exit in the File menu.
    First Menu Contribution with grayed-out Open eBook Command

    That is not quite what we intended. We’ll get there, though. First a discussion on what we actually did.

    We first needed to add the org.eclipse.ui.menus extension to our plugin, and then we declared that we want to contribute an item to a menu via the MenuContribution element. We only had to specify one attribute: the locationURI. More on that in the next section.

    We then declared that we are actually contributing a Command item as part of our MenuContribution. This is not the actual definition of a Command, but just an element indicating that we wish to represent the command with the identifier specified in commandId as an item in the menu or toolbar that we are declaring this MenuContribution for. Thus by specifying the locationURI “menu:file?after=additions” and the commandId “com.richclientgui.myreader.commands.OpenEBook” we are saying that we want the OpenEBook command to display in the standard File menu after the additions placeholder.

    The mnemonic attribute indicates what character should be underlined and act as a shortcut key for selecting the menu item, if that menu is currently open. Other additional attributes can be specified to manage the presentation of the Command in the menu, e.g. the icon, label (overriding the value set in the Command’s name attribute), tooltip (overriding the value set in the Command’s description attribute), etc. This gives us the flexibility to present the same Command slightly different depending on where it gets contributed, something that is not possible with IActions and IActionDelegates.

    LocationURI

    The locationURI is an interesting attribute: it allows the developer to use a URI string to specify where a specific contribution (whether it is a command item, a submenu or some other widget that can be contributed) must be added. It is of the form:
    [scheme]:[id]?[placement arguments]

    scheme The scheme indicates the type of the target component of the contribution, and can be one of:

  • menu : either main menu or view menu
  • toolbar : either main toolbar or view toolbar
  • popup : context menu
  • id The unique identifier of the menu, toolbar or context (popup) menu where the contribution must be added. See the list below for standard platform identifiers that can be used.
    placement The arguments helps to define the placement of the contribution items in relation to another item or placeholder (i.e. GroupMarker) in the target menu. It consists of either the word “before” or “after” followed by an equal sign (=) and then the identifier of a menu contribution item. The word “additions” can also be used in place of an identifier. Contributions added to “additions” will typically be placed last in a menu.

    Talking in detail about the locationURI and menu contribution placement can be a long blog entry on its own, so I want to come to this subject in more detail later in the series.

    Note: I usually declare my view’s identifier as the same as the fully qualified Java class name of the ViewPart implementation class, and then use the convention viewID.menu, viewID.toolbar and viewID.popup as identifiers for its various menus. E.g. a View implemented in the class com.richclientgui.myreader.BookView will have the Id com.richclientgui.myreader.BookView and the menu IDs com.richclientgui.myreader.BookView.menu, com.richclientgui.myreader.BookView.toolbar and com.richclientgui.myreader.BookView.popup.

    Platform Menu IDs

    Some standard identifiers are available for commonly used menus and toolbars:

    ID Description
    org.eclipse.ui.main.menu the main Eclipse application menubar
    org.eclipse.ui.main.toolbar the main Eclipse application toolbar
    org.eclipse.ui.popup.any contributions using this identifier will be visible in all context menus of the application (well, that’s not the full truth, but that is a topic for another blog)
    menu:file three guesses what menu this one point to…
    menu:help I’m not even going to say its a menu, and you only get one guess
    menu:window Ok, you start to get the picture
    helpEnd name of group-marker at end of Help menu
    quit id of Exit action

    See IIDEActionConstants and IWorkbenchActionConstants for more useful identifiers.

    I can’t wait to move that Open eBook item to the top of the menu…

    Step 7: Change Command menu-item placement

  • Select the menuContribution element we specified in step 6.
  • Change the locationURI to be menu:file?before=quit

    Running our latest version gives us a still grayed-out item, but at least where we want it.

    Open eBook Command in right place

    And our plugin.xml has grown a bit:






       <extension
             point="org.eclipse.ui.commands">
          <command
                description="Open an eBook file for reading"
                id="com.richclientgui.myreader.commands.OpenEBook"
                name="Open eBook">
          </command>
       </extension>
       <extension
             point="org.eclipse.ui.menus">
          <menuContribution
                locationURI="menu:file?before=quit">
             <command
                   commandId="com.richclientgui.myreader.commands.OpenEBook"
                   mnemonic="O"
                   style="push">
             </command>
          </menuContribution>
       </extension>


    Now to implement the behaviour.

    Simple Handler (Behaviour)

    After all this build-up, it is quite simple to actually add behaviour to a Command. You need to

  • implement a class that extends org.eclipse.core.commands.AbstractHandler,
  • and update your Command’s defaultHandler attribute that you left empty in step 3.

    Step 8: Implement a default Handler

  • Implement a class called DefaultOpenEBookHandler that extends AbstractHandler, and only override the execute(…) method. I just added a call to the JFace MessageDialog class to show some information. I will discuss these Handler classes more in a future blog in the series.
  • Select the OpenEBookCommand definition from step 3 and select the DefaultOpenEBookHandler class as the defaultHandler’s value.

    Here is my DefaultOpenEBookHandler class:






    package com.richclientgui.myreader.handlers;

    import org.eclipse.core.commands.AbstractHandler;
    import org.eclipse.core.commands.ExecutionEvent;
    import org.eclipse.core.commands.ExecutionException;
    import org.eclipse.jface.dialogs.MessageDialog;
    import org.eclipse.swt.widgets.Display;

    public class DefaultOpenEBookHandler extends AbstractHandler {

      public Object execute(ExecutionEvent eventthrows ExecutionException {
        MessageDialog.openInformation(Display.getDefault().getActiveShell(),
            "O no!""I’m not ready yet. Go read the hardcopy book.");
        return null;
      }

    }


    If you run the application now, you will actually see that the command item in the menu is enabled, and you should see a dialog with a message if you select the item.
    Open eBook Command shows dialog

    The Sum of the Parts

    We saw a basic introduction of how to:

  • declare a Command
  • contribute that command to the main menu-bar
  • define a class that encapsulated the behaviour of the Command

    Each of these components on their own does not add value to an application, but together it forms a powerful yet flexible and very maintainable Commands framework, far superior to using IActions and IActionDelegates because of the separation between the intent, presentation and behaviour.

    Summary of Steps

    Step 1 Create sample RCP application
    Step 2 Add the org.eclipse.ui.commands extension to our plugin.xml
    Step 3 Declare the Open File command
    Step 4 Add the org.eclipse.ui.menus extension to plugin.xml
    Step 5 Add the MenuContribution element
    Step 6 Add the Command to the MenuContribution
    Step 7 Change Command menu-item placement
    Step 8 Implement a default Handler

    You can download the source code for this blog’s version of the example.

    Next Episode

    Do not miss out on the next exciting episode on Eclipse RCP Commands. There I’ll be tackling mind-blowing topics, like

  • how to show commands only when you want to
  • how to disable commands
  • dynamic menu contributions
  • handling the Handlers
    (Time and weather permitting.)

    References

  • Eclipse.org Commands Framework Article in bugzilla
  • Article on Eclipse Commands Framework, by Marc R. Hoffmann
  • Eclipse.org Wiki on Command Framework
  • Eclipse Commands Tutorial, by Lars Vogel

    Enough said for now.

  • Tagged with:
    preload preload preload