Home > Eclipse development, Software Development > Writing an Eclipse Plug-in (Part 18): Common Navigator: Adding Submenus (Presentation)

Writing an Eclipse Plug-in (Part 18): Common Navigator: Adding Submenus (Presentation)


[Before you get too engaged in this post: you might want to skip it. Yes, I realize that the writing is engaging, witty, poetic, philosophical, daring, edgy, and technically astute, but what is all that to being wrong? Just jump forward to Part 18 – Take 2 for a refactoring of this post with many of the wrong parts taken out. However, the writing is still what it is and for that I offer my apologies.]

And now, the moment you’ve all been waiting for: adding commands to the popup menu.

I know, you are just aquiver in anticipation.

What menus do we need to put in? Just a few. The Custom Navigator popup menu should contain:

  • New – Sub-menu with choices (Custom Project, Schema, and Deployment. Eventually we will change Schema to Tables, Views, Filters)
  • Copy – Ctrl+C (an item in a category or an entire category)
  • Paste – Ctrl+V (an item in a category or an entire category)
  • Remove – Del or Ctrl+X (an item in a category or an entire category)

We will not worry about Import/Export behavior as that will be added to the Import/Export Wizard with the associated additions to the main menu, toolbar, etc. done as appropriate (meaning later, when I care).

The thing to remember is: presentation first, behavior second.

For now, we are going to set up the menus with bogus behavior. Since I don’t usually test the presentation this works out well for me. We’ll get around to behavior in the next post. Let’s get the menus in place and then we will snap the commands (next time).

Where should the popup menu configuration/code go: into the customplugin or customnavigator project? Because we are directly affecting the navigator popup menu the configuration will go into the customnavigator plug-in. I promise not to regret it later when someone points out why it would really be in the customplugin project.

How (are we doing it?)

First: let’s add one menu item to the New menu.

  1. customnavigator –> plugin.xml –> Extensions –> All Extensions –> Add –> org.eclipse.ui.menus
  2. org.eclipse.ui.menus –> New –> menuContribution
    • locationURI: popup:common.new.menu?after=additions
  3. popup:common.new.menu?after=additions (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.newWizard
    • label: Custom Project
    • icon: icons/project-folder.png
  4. As a sanity check start the runtime workbench.

    Back to the grindstone.

  5. popup:common.new.menu?after=additions (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.newWizard
    • label: Schema File
    • icon: icons/schema-file_16x16.png (copy this from the customplugin icon folder)
  6. popup:common.new.menu?after=additions (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.newWizard
    • label: Deployment File
    • icon: icons/deployment-file_16x16.png (copy this from the customplugin icon folder)

Next: let’s add three standard menus: Copy/Paste/Delete. Again, for now we will assign default commands that we will change later.

Let’s use the following icons for the copy/paste/delete menu items (yes, I copied them from Eclipse):

  1. org.eclipse.ui.menus –> New –> menuContribution
    • locationURI: popup:customnavigator.navigator?before=import
  2. popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.copy
    • label: Copy
    • icon: icons/copy_16x16.png
  3. popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.paste
    • label: Paste
    • icon: icons/paste_16x16.png
  4. popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.delete
    • label: Delete
    • icon: icons/delete_16x16.png
  5. popup:customnavigator.navigator?before=import (menuContribution) –> New –> separator
    • name: customnavigator.separator
    • visible: true

The above is a lot to do all at once so feel free to add one section at a time and check the runtime workbench. Once you add the org.eclipse.ui.menus extension along with the menuContribution and one of the commands you should be able to open the Custom Perspective, right click in the Custom Navigator and see a lovely popup menu.

The final result is beautifully displayed in the screen capture (don’t sweat the fact that Delete is not disabled. That is under the control of Eclipse and the clipboard. You will probably have a different item enabled or none).

Don’t let the gratuitous use of Ctrl+N upset you. We will take care of messing those up later.

But first: time to reveal the magic.

Why (did we do it that way?)

If you want to add a menu item to the popup menu the easiest way is to use the org.eclipse.ui.menus extension and add a menuContribution to it (hmm. That would imply there is another way to do this. Yes, using actionSets…which have been deprecated, so don’t). The menuContribution‘s locationURI is the path to the location within the popup where your new menu item should go. If we were adding our menu item at the top level popup we would simply have used a locationURI of popup:customplugin.customnavigator?after=additions; that’s right: simply using the id of the navigator places the menu item into its popup. Using the after=additions piece puts the menu items directly in the popup right after the last item…which is not where we want it.

So the $54,000 question is: what locationURI do we use to put our menu items in the correct spot?

Before I can answer that we have to fix something. Well, some of us have to fix something.

For those of you doing this on Windows: shield your eyes and move on to the section titled CONTINUE HERE (while goto may be considered harmful, continue here isn’t).

Now that we have all of those miscreants out of the way: those of you who need to see the answer with your own eyes, but are using Kubuntu, need to change the Eclipse key binding for the runtime workbench from Shift+Alt+F2 to Shift+Alt+F3. Why? Because in order to discover the correct path to the New menu in the popup we need the Plug-in Spy to work. The Plug-in Spy, at least on Kubuntu, does not work properly because Shift+Alt+F2 doesn’t work properly; changing the key binding from Shift+Alt+F2 to Shift+Alt+F3 works.

How do we change the key binding? Start and do the following from the runtime workbench:

  1. Window –> Preferences –> General –> Keys
  2. In the text field below the Scheme drop down type: shift+alt+f
  3. Press Delete in the Binding field to remove the current key binding
  4. With the cursor in the Binding field press the shift key, the alt key and the F3 key all at the same time.
  5. Click OK to close the Preferences window

Now the bad news: you will have to do this every time you start the runtime workbench if you want to use the Plug-in Spy unless you unset the Launch configuration to clear the workspace; by not clearing the workspace you may find weird behavior that isn’t weird but appears to be weird because the runtime workbench is not cleaning up after itself. I recommend leaving the Launch configuration alone…meaning with the Clear selection checked.

The good news: you don’t need to use the Plug-in spy that often so this manual step is something you will not do too often. Grow up or start taking stronger meds.

CONTINUE HERE

Those of you on Windows: every time I say press Shift+Alt+F3 you must press Shift+Alt+F2. Got it? Shift+Alt+F3 really mean Shift+Alt+F2 (just in Windows). Think you can handle that?

  1. Start the runtime workbench and open the Custom Perspective
  2. Press Shift+Alt+F3. Notice the cursor changes appearance
  3. Right click in the Custom Navigator and select New –> Project
  4. Oh look! A window with wonderful information!

And there it is: the path used by the active contribution location URI: common.new.menu. Change the current path from popup:customplugin.customnavigator?after=additions to popup:common.new.menu?after=additions and start the runtime workbench again. The menus are exactly where we want them.

The configuration of the remaining menus now make sense. Add a new menuContribution to the org.eclipse.ui.menus extension and, using the high-level custom navigator path location URI (popup:customnavigator.navigator?before=import), we tell Eclipse to put the menus before the import section. Again, just to supply the required information we assign the internal copy, paste, and delete commandIds to the various menus.

Here are the instructions again:

  • org.eclipse.ui.menus –> New –> menuContribution
    • locationURI: popup:customnavigator.navigator?before=import
  • popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.copy
    • label: Copy
    • icon: icons/copy_16x16.png
  • popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.paste
    • label: Paste
    • icon: icons/paste_16x16.png
  • popup:customnavigator.navigator?before=import (menuContribution) –> New –> command
    • commandId: org.eclipse.ui.edit.delete
    • label: Delete
    • icon: icons/delete_16x16.png
  • popup:customnavigator.navigator?before=import (menuContribution) –> New –> separator
    • name: customnavigator.separator
    • visible: true

Doesn’t it look great? It just makes you proud to be a plug-in developer.

The next big question: why did we do that? Or more accurately: where is the documentation for this magic?

My answer is going to be very unsatisfying: I don’t know. I went through a number of plug-ins, web sites and help files and found nothing. When I remembered the Plug-in Spy, and fixed the Shift+Alt+F2 problem (Kubuntu, remember?), I was able to discover the path I was looking for.

However, that is not the reason why this post has taken so long to appear; I have had a lot on my mind and this wasn’t it. In the next post we will add command objects to the New menu items and ignore the Copy/Paste/Delete stuff (those commands need to be configured to recognize our custom types so they copy things properly. They might work our of the box, but since I haven’t thought through all of the implication I will assume that they will have to be changed).

Time to wash up:

  • Go to the Overview tab, click on Externalize Strings Wizard and externalize the strings
  • In plugin.xml click on the MANIFEST.MF tab, click on the light bulb in the left hand margin and select Add Missing Packages

Who’s better than you?

What Just Happened?

The popup menu items have been added! Without behavior!

In addition it was the Plug-in Spy that made it possible for me to create the proper locationURI I needed to insert the new menus in the correct spot.

Don’t underestimate the power of Plug-in Spy.

The cat is not only alive, but curious, which leads one to worry about the cat’s future.

(I hope this answered your question, Augusto.)

Code

No code…again.

bundle.properties

#Properties file for customnavigator
Bundle-Name = Custom Navigator Plug-in
view.name = Custom Plug-in Navigator
category.name = Custom Projects
navigatorContent.name = Custom Navigator Content
customProject.command.label = Custom Project
schemaFile.command.label = Schema File
deploymentFile.command.label = Deployment File
copy.command.label = Copy
paste.command.label = Paste
delete.command.label = Delete

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.ui.views">
      <category
            id="customnavigator.category"
            name="%category.name">
      </category>
      <view
            allowMultiple="false"
            category="customnavigator.category"
            class="org.eclipse.ui.navigator.CommonNavigator"
            icon="icons/navigator.png"
            id="customnavigator.navigator"
            name="%view.name">
      </view>
   </extension>
   <extension
         point="org.eclipse.ui.navigator.viewer">
      <viewerActionBinding
            viewerId="customnavigator.navigator">
         <includes>
            <actionExtension
                  pattern="org.eclipse.ui.navigator.resources.*">
            </actionExtension>
         </includes>
      </viewerActionBinding>
      <viewerContentBinding
            viewerId="customnavigator.navigator">
         <includes>
            <contentExtension
                  pattern="customnavigator.navigatorContent">
            </contentExtension>
         </includes>
      </viewerContentBinding>
   </extension>
   <extension
         point="org.eclipse.ui.navigator.navigatorContent">
      <navigatorContent
            activeByDefault="true"
            contentProvider="customnavigator.navigator.ContentProvider"
            id="customnavigator.navigatorContent"
            labelProvider="customnavigator.navigator.LabelProvider"
            name="%navigatorContent.name">
         <triggerPoints>
            <instanceof
                  value="org.eclipse.core.resources.IWorkspaceRoot">
            </instanceof>
         </triggerPoints>
         <commonSorter
               class="customnavigator.sorter.SchemaCategorySorter"
               id="customnavigator.sorter.schemacategorysorter">
            <parentExpression>
               <or>
                  <instanceof
                        value="customnavigator.navigator.CustomProjectSchema">
                  </instanceof>
               </or>
            </parentExpression>
         </commonSorter>
      </navigatorContent>
   </extension>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="popup:common.new.menu?after=additions">
         <command
               commandId="org.eclipse.ui.newWizard"
               icon="icons/project-folder.png"
               label="%customProject.command.label"
               style="push">
         </command>
         <command
               commandId="org.eclipse.ui.newWizard"
               icon="icons/schema-file_16x16.png"
               label="%schemaFile.command.label"
               style="push">
         </command>
         <command
               commandId="org.eclipse.ui.newWizard"
               icon="icons/deployment-file_16x16.png"
               label="%deploymentFile.command.label"
               style="push">
         </command>
      </menuContribution>
      <menuContribution
            locationURI="popup:customnavigator.navigator?before=import">
         <command
               commandId="org.eclipse.ui.edit.copy"
               icon="icons/copy_16x16.png"
               label="%copy.command.label"
               style="push">
         </command>
         <command
               commandId="org.eclipse.ui.edit.paste"
               icon="icons/paste_16x16.png"
               label="%paste.command.label"
               style="push">
         </command>
         <command
               commandId="org.eclipse.ui.edit.delete"
               icon="icons/delete_16x16.png"
               label="%delete.command.label"
               style="push">
         </command>
         <separator
               name="customnavigator.separator"
               visible="true">
         </separator>
      </menuContribution>
   </extension>

</plugin>
Advertisements
  1. Augusto
    February 11, 2010 at 11:38 am

    Thank you for the post 😉

  2. Peter
    November 17, 2011 at 10:01 pm

    I wonder why i didn’t stumble on your blog earlier… this is awesome!!! I’ve been searching for common.new.menu for almost a week.. and my co-worker pointed out your blog!!

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: