Replacing the Perspective-Switcher in RCP apps

For simple RCP Applications the Perspective-Switcher widget that ships with Eclipse is overloaded and cumbersome to use.

persp switcher Replacing the Perspective Switcher in RCP apps

We are going to get rid of it and replace it with an equivalent menu and/or toolbar for switching perspectives. Both should have an indicator to show which perspective is currently active.

persp menu and toolbar Replacing the Perspective Switcher in RCP apps

Hiding the Perspective-Switcher

To hide the Perspective-Switcher we go to our ApplicationWorkbenchWindowAdvisor and instruct the IWorkbenchWindowConfigurer to not show the perspective bar.

public void preWindowOpen() {
  IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
   configurer.setShowPerspectiveBar(false);
  // ...
}

 

Using simple commands – not enough

Let’s see how we could contribute a menu / toolbar for switching perspectives. 

The workbench has the command ‘org.eclipse.ui.perspectives.showPerspective’ that can switch to a given perspective. It accepts a parameter ‘org.eclipse.ui.perspectives.showPerspective.perspectiveId’ with the ID of the perspective to show. Optionally a second parameter ‘org.eclipse.ui.perspectives.showPerspective.newWindow’ will open the perspective in a new window if set to ‘true’.

Using  the ‘org.eclipse.ui.menus’ extension point we could contribute a menu with an appropriate <command> for each perspective:

   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu">
         <menu
               id="menu.perspectivesStatic"
               label="Perspectives">
            <command
                  commandId="org.eclipse.ui.perspectives.showPerspective"
                  icon="/icons/perspA.png"
                  label="Perspective A"
                  style="radio">
               <parameter
                     name="org.eclipse.ui.perspectives.showPerspective.perspectiveId"
                     value="example.perspectiveswitch.simple.PerspectiveA">
               </parameter>
            </command>
            <!-- repeat --!> 

 

Unfortunately this approach has some drawbacks:

  • long xml files
  • the list of available perspectives is static – brittle and requires manual maintenance
  • it is difficult to indicate which perspective is currently selected

Using dynamic contributions – success

Fortunately the <dynamic> element of  ’org.eclipse.ui.menus’ comes to our rescue. It allows us to contribute a Java class that populates the menu/toolbar on the fly (note: use a separate class for each).

Here’s the <dynamic> element that populates the ‘Perspectives’ menu:

   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu">
         <menu
               id="menu.perspectivesDynamic"
               label="Perspectives">
            <dynamic
                  class="example.perspectiveswitch.PerspectiveSwitcherMenu"
                  id="perspectiveSwitcherMenu">
            </dynamic>
      </menuContribution>
   </extension> 

 

The class PerspectiveSwitcherMenu fills the menu on the fly.

We obtain the array of  IPerspectiveDescriptors from the workbench. For each we create a MenuItem with the perspective’s icon and description. Since we created images, we have to dispose them when the menu item is disposed, using a dispose listener. A selection listener is in charge of switching perspective when a menu item is clicked. To provide indication about the active perspective we use the SWT.RADIO style and select one of the menu items. Since the menu is created on the fly each time it is used, we do not need to track the active perspective :-).

public class PerspectiveSwitcherMenu extends ContributionItem {

public void fill(Menu menu, int index) {
  String activePerspective = getPerspectiveId();
  IPerspectiveDescriptor[] perspectives = PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives();
  for(int i = 0; i < perspectives.length; i++) {
    IPerspectiveDescriptor descriptor = perspectives[i];
    // i is used as an item index; 0-n will add items to the top of the menu
    MenuItem item = new MenuItem(menu, SWT.RADIO, i);
    item.setData(KEY_PERSPECTIVE_DESCR, descriptor);
    item.setText(descriptor.getLabel());
    final Image image = descriptor.getImageDescriptor().createImage();
    item.setImage(image);
    item.addDisposeListener(new DisposeListener(){
      public void widgetDisposed(DisposeEvent e) {
        image.dispose();
      }
    });
    item.addSelectionListener(menuListener);
    if(descriptor.getId().equals(activePerspective)) {
      item.setSelection(true);
    }
  }
}

public final boolean isDynamic() {
  return true;
}

 

The toolbar contribution is very similar to the above. Using the ‘org.eclipse.ui.menus’ extension point, we add a <dynamic> element to a <toolbar>. We then implement PerspectiveSwitcherToolbar which extends ContributionItem and overrides the fill(Toolbar, int) to create a toolbar on the fly.

Since the toolbar is visible all the time, we have to track the active perspective, so we can update the ‘selected’ (=depressed) state of the toolbar buttons as necessary. This turned out to be quite tricky. Here’s the solution I went for: a listener tracking the active perspective is installed in each window. If the perspective changes, we look-up the toolbar and update the ‘selected’ state. Since windows may come and go, a second listener keeps track of window creation / disposal and installs / removes the perspective listener as necessary. I wish this was a bit easier – but I’m sharing the below code so you can save a bit of time on this.

Source Download

Download the full code here: example perspective switch.zip

Happy hacking,
Elias.  

PS: If you want to trade off more screen real-estate for a fancier switcher you can use a ‘standalone’ view or a composite that is placed around the page contents. Tom Seidel has the details on his blog.

7 Responses to “Replacing the Perspective-Switcher in RCP apps”

  1. Manuel Woelker says:

    Very nice, found myself doing something similar for a customer project a while back (although the requirements were slightly different).

    I really like the conciseness of the XML, plus the fact that new perspectives automatically show up without having to muck with a new menu contribution duplicating most of the data (e.g. name, id, image).

  2. Wayne Beaton says:

    Would you consider converting this into an article for Eclipse Corner? I don’t think you need to add very much (short articles are good).

  3. @Manuel: thanks

    @Wayne: Let’s discuss this in bugzilla.

    Kind regards,
    Elias.

  4. CTG says:

    Very cool. I also wanted to put the toolbar on the left hand side, and it took me a while to figure it out. What you do is change the toolbar contribution locationURI to toolbar:org.eclipse.ui.trim.vertical1 (vertical2 would put it on the right hand side).

    Thanks for the article.

  5. Pierre GAUTIER says:

    Hello,

    Does this article imply that it’s impossible to get rid of the perspective bar menu ?

    If the response is no I’m gonna use your article right now.

    Thanks by advance.

  6. Honza Herold says:

    Thanks for this post. It inspired me to do something similar.
    http://blog.trixi.cz/2011/05/rcp-custom-perspective-switcher

  7. SlowStrider says:

    Wow, great stuff. I really like your perspective switcher toolbar, this way it’s trivial to place a perspective switcher at the top left side in the coolbar which is not possible by default.

    It does not show the perspective labels, but this can be done by simply adding the line

    item.setText(descriptor.getLabel());

    after the line

    item.setImage(image0;

7 responses so far

Written by . Published in Categories: EclipseSource News, Planet Eclipse