Jump to: navigation, search

Riena/Detached Views

{{#eclipseproject:rt.riena}}
Riena ProjectGetting Started ▶ Detached Views

This document explains how to easily open auxiliary 'detached' views when a certain navigation node is selected in the main window, as shown in the following screenshot:

Riena detached views.png

Riena has a mechanism that allows developers to show a ViewPart in a separate 'detached' shell/window. This can be used to show one or more views in separate shells. These shells are draggable, moveable, but not closeable. Only one view can be shown in each 'detached' shell. This view can be a regular ViewPart or an implementation of Riena's SubModuleView.

Hooking into the Navigation Tree

To show / hide / dispose the 'detached' shells, we want to react to events in the navigation tree on the left of the main window. Typically when a node is selected, the corresponding SubModuleView is shown in the workarea (i.e. main area on the right). When this happens we would like to show additional 'detached' views. When the navigation node becomes unselected, we would like to hide these views.

To accomplish that we need to attach a custom listener to the view's navigation node. This is typically done in the basicCreatePartControl(...) method of our sub module:

protected void basicCreatePartControl(Composite parent) {
  // ...
  getNavigationNode().addSimpleListener(new NodeListener());
}

The class NodeListener extends SimpleNavigationNodeAdapter. This adapter has several methods, that are invoked at different points during the lifecycle of a navigation node. When the node becomes selected (=activated) the method activated((INavigationNode source) is invoked – in that case we show the detached view. When the node becomes de-selected (=deactivated) the method deactivated(INavigationNode source) is invoked – in that case we hide the detached view. When the node is destroyed (=disposed) the method disposed(INavigationNode source) is invoked – in that case perform any necessary clean-up.

private final class NodeListener extends SimpleNavigationNodeAdapter {
  public void activated(INavigationNode<?> source) {
    // show detached views
  }
  public void deactivated(INavigationNode<?> source) {
    // hide detached views
  } 		
  public void disposed(INavigationNode<?> source) {
    // clean-up
}

Showing / Hiding detached views

To show / hide / dispose the detached views we need to manage a Shell for each view. Riena provides the class DetachedViewsManager, which makes this easy.

  1. We need to create a new instance of DetachedViewsManager in our listener as a class variable. The manager needs to know the main window, so we pass it a reference to Shell or to IWorkbenchSite via the constructor.
  2. To show a view, we invoke dvManager.showView(String id, Class<? extends ViewPart> viewClazz, int position). The first time this method is invoked for a given id, it will create a new shell and show a new view of the type viewClazz in it. It will then open the shell at the given position. The second time this method is invoked, the shell with the specified id will already exist, so it will just make it visible. More information on the parameters:
    id
    is an arbitrary String, used to identify the shell hosting this view
    viewClazz
    a class specifying a ViewPart which we want to show in the shell. This class must have a parameterless constructor.
    position
    one of SWT.{TOP,BOTTOM,LEFT,RIGHT}. Will open the shell on the appropriate side of the main window. There is also an alternative method #showView(..., Rectangle bounds) which will open the shell with a position and size we specify. The location preference is only considered when the shell is created (i.e. the first time we invoked this method)</tt>
  3. To hide a view, we invoke dvManager.hideView(String id), where id is the name of the shell we wish to hide.
  4. To clean-up, we invoke dvManager.dispose(). This will dispose all shells that have been created but are currently hidden. Typically this is done in the disposed(...) method of the node listener. Afterwards it is also a good idea to remove the node listener itself from the navigation node.

Here is the full code for the NodeListener class:

private final class NodeListener extends SimpleNavigationNodeAdapter {
  private final DetachedViewsManager dvManager = new DetachedViewsManager(getSite());
 
  public void activated(INavigationNode<?> source) {
    dvManager.showView("viewRight", TreeSubModuleView.class, SWT.RIGHT);
  }
 
  public void deactivated(INavigationNode<?> source) {
    dvManager.hideView("viewRight"); //$NON-NLS-1$
  }
 
  public void disposed(INavigationNode<?> source) {
    dvManager.dispose();
    getNavigationNode().removeSimpleListener(this);
  }
}

Special Requirements

When opening a Riena SubModuleView, such as the TreeSubModuleView, as a detached view you must be aware of the following:

Riena strictly separates view and controller. The view is responsible for creating the UI. The controller is responsible for the business logic / ridgets. The SubModuleViews shown in the main window have a controller attached to them. This pairing is normally kept in the navigation node. The views opened in 'detached' mode do not have a navigation node. As such, they do not have any way of knowing which controller to create :-(. To work around this limitation it is important to implement the createController(...) method.

If a SubModuleView subclass does not have this method, two things will happen:

  1. no controller will be created. You will notice that the widgets are there, but their labels / behavior / anything done in the controller is missing.
  2. a warning is written out to the application's log.

Fortunately, implementing the createController method is easy, as shown below:

public class TreeSubModuleView extends SubModuleView<TreeSubModuleController> {
 
  protected TreeSubModuleController createController(ISubModuleNode node) {
    return new TreeSubModuleController(node);
  } 
  // ...
}

References

See:

  • class DetachedSubModuleView in the org.eclipse.riena.example.client bundle
  • class DetachedViewsManager in the org.eclipse.riena.ui.swt bundle
  • class SnippetDetachedView001 in the org.eclipse.riena.sample.snippets bundle