Replacing the Perspective-Switcher in RCP apps

March 31, 2009 | 4 min Read

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

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.

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 for each perspective:

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 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 element that populates the ‘Perspectives’ menu:

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 element to a . 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.