Riena/Navigation

From Eclipsepedia

Jump to: navigation, search

Contents

Navigation Concepts

The goal of the Riena navigation concept is to make navigation as easy and comfortable as possible for the enterprise user.

Subapplications

The Riena application ist made up from possibly multiple subapplications identifyable by the handles in the top area of the application window.

Riena Cient SubApplications.PNG

This example shows a Riena client application with 2 subapplications called 'Navigation' and 'Playground'. The 'Navigation' subapplication is currently selected.

Module Groups, Modules and Submodules

Each subapplication may contain multiple module groups, each module group may contain multiple modules and each module may contain multiple submodules. Submodules may be organized in a hierarchical way, ie a submodul may have zero (probably the most common case), one or more submodules as children.

Riena Client Navigation.PNG The picture to the left shows 3 module groups, the first one containing two modules (named 'Module 1' and 'M2 (not closable)'). The second and third module group each contain one module only (named 'Module 1.2.1' and 'Navigate', resp). The modules named 'M2 (not closable)' Module 1.2.1' cannot be closed by the user indicated by the absence of the 'X' button in the right corner of the module widget.

Note that only the first module within the first module group is expanded, ie its submodules are visible within the navigation tree. This is because that module is currently selected. We can also see that the first submodule (named 'SubModule 1.1') is the parent of another submodule (named 'SubModule 1.1.1') and has a sibling (named 'SubModule 1.2') within the same module. Selecting a subapplication, module group or module automatically activates the first submodule within that context. This implies the there is no work area associated with modules, module groups or subapplications - only submodules can have an associated work area (ie view and optionally a controller)

The Riena navigation therefore can be thought of as a tree where the root is the application node and the leafs are the submodule nodes.

Navigation Node Common Properties

There are some properties that can be defined for all navigation nodes:

  • id - The id is made up from two parts, a type and an instance part. This is explained later on this page.
  • children - The type of children depends on the parent, a module node eg can only have submodule nodes as children.

Navigation nodes except module group nodes may also have a label and/or an icon.

Programmatic Creation

All navigation structures may easily be created programmatically. If the application class configured in extension org.eclipse.core.runtime.applications extends org.eclipse.riena.navigation.ui.application.AbstractApplication the method createModel() would be sent within the start(IApplicationContext context) method. The default implementation just returns an application node without any children:

public static final String DEFAULT_APPLICATION_TYPEID = "application";
 
protected IApplicationNode createModel() {
	NavigationNodeId applicationNodeId = new NavigationNodeId(DEFAULT_APPLICATION_TYPEID);
	IApplicationNode applicationModel = new ApplicationNode(applicationNodeId);
	return applicationModel;
}

All navigation node interfaces extend a common super interface, org.eclipse.riena.navigation.INavigationNode. The implementation classes form a corresponding hierarchy where all non abstract navigation node classes inherit from org.eclipse.riena.navigation.model.NavigationNode:

  Riena INavigationNode Hierarchy.PNG   Riena NavigationNode Hierarchy.PNG


Using Custom createModel() method

Let's now try to create the 'Navigation' subapplication and the first module group from the screenshot above. We start our implementation of the createModel() method with a call to the super implemetantion to receive an IApplicationNode and configure label and application icon:

@Override
protected IApplicationNode createModel() {
	IApplicationNode applicationNode = super.createModel();
	applicationNode.setLabel("Riena Navigation Example");
	applicationNode.setIcon(createIconPath(ExampleIcons.ICON_APPLICATION));
 
// ... everthing described below goes here ...
 
	return applicationModel;

Creating a Subapplication

To be able to create a subapplication we need one more thing: As subapplications in Riena correspond to RCP perspectives we need to contribute the corresponding extension. The view class representing the subapplication perspective in Riena is org.eclipse.riena.navigation.ui.swt.views.SubApplicationView, so we will configure our subapplication as follows (of course the id is not required to be 'subapplication.1'):

<extension point="org.eclipse.ui.perspectives">
   <perspective
         class="org.eclipse.riena.navigation.ui.swt.views.SubApplicationView"
         id="subapplication.1"
         name="subapplication.1">
   </perspective>
</extension>

We can now

  • create a subapplication node with a certain node id
  • register it with the WorkareaManager to assign the perspective we configured
  • finally add it to the application node
// Navigation SubApplication
NavigationNodeId nodeId = new NavigationNodeId("org.eclipse.riena.example.navigation.subapplication");
ISubApplicationNode subApplication = new SubApplicationNode(nodeId, "Navigation");
WorkareaManager.getInstance().registerDefinition(subApplication, "subapplication.1");
applicationNode.addChild(subApplication);

This would bring up the Riena application with one subapplication called 'Navigation' that does not contain any content (please ignore menu and toolbar for now - those are there because I lazily abused the Riena example client and did not remove them): Riena EmptyNavigationSubApp.PNG

Creating a Module Group

Creating a module group is rather easy in as there is no label, icon or work area that could require configuration. As we also do not need a node id here we can simply write:

// create a module group and add it to subapplication
IModuleGroupNode moduleGroup = new ModuleGroupNode(null);
subApplication.addChild(moduleGroup);

This does not change anything in the visualization of our example client as we do not yet have any modules within or module group and empty groups are not displayed. Therefore let's proceed creating our first module...

Creating a Module

// create a module and add it module group
IModuleNode module = new ModuleNode(null, "Module 1");
module.setIcon(createIconPath(ExampleIcons.ICON_APPLICATION));
moduleGroup.addChild(module);

...and add a submodule right away.

Creating Submodules

As the submodule has a presentation in the work area the associated view needs to be configured using the eclipse 'org.eclipse.ui.views' extension point:

<extension point="org.eclipse.ui.views">
   <view allowMultiple="true"
         class="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView"
         id="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView"
         name="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
   </view>
</extension>

The association from node to view is done, just like for the subapplication, via the WorkareaManager.

// create "SubModule 1.1" and add it to "Module 1"
nodeId = new NavigationNodeId("org.eclipse.riena.example.customerDetail");
ISubModuleNode subModule = new SubModuleNode(nodeId, "SubModule 1.1");
subModule.setIcon(createIconPath(ExampleIcons.ICON_FILE));
WorkareaManager.getInstance().registerDefinition(subModule, 
     CustomerDetailSubModuleController.class, CustomerDetailSubModuleView.ID);
module.addChild(subModule);

Starting the application would bring up the example appliation like this:

Riena NavigationOneModule.PNG

Note that

  • the first submodule found within the whole application (ie. first submodule within first module within first module group within first subapplication) is automatically selected by default
  • the module cannot be expanded as it has only one submodule (expanding would not make too much sense as with one submodule you do not have too many options to select another submodule)

Final Steps

It should now be easy to add some more submodules

// create "SubModule 1.1.1" and add it to "SubModule 1.1"
nodeId = new NavigationNodeId("org.eclipse.riena.example.customerDetail");
ISubModuleNode subModule2 = new SubModuleNode(nodeId, "SubModule 1.1.1");
WorkareaManager.getInstance().registerDefinition(subModule2, 
     CustomerDetailSubModuleController.class, CustomerDetailSubModuleView.ID);
subModule.addChild(subModule2);
 
// create "SubModule 1.2" and add it to "Module 1"
nodeId = new NavigationNodeId("org.eclipse.riena.example.customerDetail");
subModule = new SubModuleNode(nodeId, "SubModule 1.2");
WorkareaManager.getInstance().registerDefinition(subModule, 
     CustomerDetailSubModuleController.class, CustomerDetailSubModuleView.ID);
module.addChild(subModule);

or create a second module within the same module group. For variation we make the second module non closable.

// create "M2 (not closable)" and add it to the module group
module = new ModuleNode(null, "M2 (not closable)");
module.setIcon(createIconPath(ExampleIcons.ICON_HOMEFOLDER));
module.setClosable(false);
moduleGroup.addChild(module);
 
// create "SubModule 2.1" and add it to "M2 (not closable)"
nodeId = new NavigationNodeId("org.eclipse.riena.example.customerDetail");
subModule = new SubModuleNode(nodeId, "SubModule 2.1");
WorkareaManager.getInstance().registerDefinition(subModule, 
     CustomerDetailSubModuleController.class, CustomerDetailSubModuleView.ID);
module.addChild(subModule);

resulting in our final example application:

Riena NavigationTwoModules.PNG

That's all for the programmatic creation of the navigation tree basics. Now let's have a look how this could be achieved using the declarative way.

Using Extension Points

All navigation structures may also be created in a declarative way using extension points. Just like if using the programmatic approach the application class configured in extension org.eclipse.core.runtime.applications is required to extend org.eclipse.riena.navigation.ui.application.AbstractApplication so the method createModel() will be sent within the start(IApplicationContext context) method. The application class is (except for your view and controller implementations, of course) the only java code that is required to create exactly the same navigation structure as we did before the programmatic way.

Using Custom createModel() method

The implementation of the createModel() method is really only required to set label and icon of the application, we will not add any more code to this method:

@Override
protected IApplicationNode createModel() {
	IApplicationNode applicationNode = super.createModel();
	applicationNode.setLabel("Riena Navigation Example");
	applicationNode.setIcon(createIconPath(ExampleIcons.ICON_APPLICATION));
	return applicationModel;

Creating a Subapplication

To create a subapplication we need to contribute the corresponding perspective extension. This is exactly the same as before:

<extension point="org.eclipse.ui.perspectives">
   <perspective
         class="org.eclipse.riena.navigation.ui.swt.views.SubApplicationView"
         id="subapplication.1"
         name="subapplication.1">
   </perspective>
</extension>

The following xml code shows how to

  • define a subapplication node with a certain node id
  • assign the perspective we configured
  • assign the label for the subapplication handle

Please ignore the assembly element for now, I will explain it later:

<extension point="org.eclipse.riena.navigation.assemblies">
   <assembly
         id="org.eclipse.riena.example.navigation.assembly"
         autostartsequence="100"
         parentTypeId="application">
      <!-- create subapplication -->
      <subapplication 
            label="Navigation"
            typeId="org.eclipse.riena.example.navigation.subapplication"
            view="subapplication.1">
      </subapplication>
   </assembly>
</extension>

This would bring up the same Riena application with one subapplication called 'Navigation' not containing any content like in the first step of the programmatic example: Riena EmptyNavigationSubApp.PNG

Creating a Module Group

Creating a module group just requires adding the modulegroup element to our subapplication element. There are no attributes required but we will assign a name so we can easily identify it within the PDE:

<subapplication 
      label="Navigation"
      typeId="org.eclipse.riena.example.navigation.subapplication"
      view="subapplication.1">
   <!-- create module group and add it subapplication -->
   <modulegroup name="group">
   </modulegroup>
</subapplication>

This does not change anything in the visualization of our example client as we do not yet have any modules within or module group and empty groups are not displayed. Therefore let's again proceed creating our module...

Creating a Module

As you may have already guessed there is also a module element that can be added as a child to the modulegroup element:

<modulegroup name="group">
   <module
         label="Module 1"
         icon="org.eclipse.riena.example.client:/icons/0457_a_a00.png">
   </module>
</modulegroup>

The icon path is prefixed with the bundle name so the generic Riena navigation assembler would be able to find it.

Creating Submodules

As the submodule has a presentation in the work area the associated view needs to be configured using the eclipse 'org.eclipse.ui.views' extension point:

<extension point="org.eclipse.ui.views">
   <view allowMultiple="true"
         class="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView"
         id="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView"
         name="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
   </view>
</extension>

The association from node to view and controller is donevia the view and controller attributes where the controller atribute takes the fully qualified name of the controller class.

<module
      label="Module 1"
      icon="org.eclipse.riena.example.client:/icons/0457_a_a00.png">
   <!-- create "SubModule 1.1" and add it to "Module 1" -->
   <submodule
         label="SubModule 1.1"
         icon="org.eclipse.riena.example.client:/icons/file.gif"
         typeId="org.eclipse.riena.example.customerDetail"
         controller="org.eclipse.riena.example.client.controllers.CustomerDetailSubModuleController"
         view="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
   </submodule>
</module>

Starting the application would bring up the example appliation lokking just like in the programmatic case:

Riena NavigationOneModule.PNG

Final Steps

It should now be easy to add some more submodules

<module
      label="Module 1"
      icon="org.eclipse.riena.example.client:/icons/0457_a_a00.png">
   <!-- create "SubModule 1.1" and add it to "Module 1" -->
   <submodule
         label="SubModule 1.1"
         icon="org.eclipse.riena.example.client:/icons/file.gif"
         typeId="org.eclipse.riena.example.customerDetail"
         controller="org.eclipse.riena.example.client.controllers.CustomerDetailSubModuleController"
         view="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
      <!-- create "SubModule 1.1.1" and add it to "SubModule 1.1" -->
      <submodule
            label="SubModule 1.1.1"
            icon="org.eclipse.riena.example.client:/icons/file.gif"
            typeId="org.eclipse.riena.example.customerDetail"
            controller="org.eclipse.riena.example.client.controllers.CustomerDetailSubModuleController"
            view="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
      </submodule>
   </submodule>
   <!-- create "SubModule 1.2" and add it to "Module 1" -->
   <submodule
         label="SubModule 1.2"
         icon="org.eclipse.riena.example.client:/icons/file.gif"
         typeId="org.eclipse.riena.example.customerDetail"
         controller="org.eclipse.riena.example.client.controllers.CustomerDetailSubModuleController"
         view="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
   </submodule>
</module>

or create a second module within the same module group. Again the second module will not be closable.

// create "M2 (not closable)" and add it to the module group
// create "SubModule 2.1" and add it to "M2 (not closable)"
<modulegroup name="group">
   <module
         label="Module 1"
         icon="org.eclipse.riena.example.client:/icons/0457_a_a00.png">
   <!-- ... code from above... -->
   </module>
   <module
         label="M2 (not closable)"
         icon="org.eclipse.riena.example.client:/icons/HomeFolder.gif"
         unclosable="true">
      <!-- create "SubModule 2.1" and add it to "M2 (not closable)" -->
      <submodule
            label="SubModule 2.1"
            icon="org.eclipse.riena.example.client:/icons/file.gif"
            typeId="org.eclipse.riena.example.customerDetail"
            controller="org.eclipse.riena.example.client.controllers.CustomerDetailSubModuleController"
            view="org.eclipse.riena.example.client.views.CustomerDetailSubModuleView">
      </submodule>
   </module>
</modulegroup>

resulting in the same example application as the programmatic way:

Riena NavigationTwoModules.PNG

Tis concludes the extension point section of the navigation tree basics.

Navigation Node Assemblers

Assembler Basics

As you have seen in the previous section the extension point contains assembly elements. These elements decribe how a certain part of the Riena navigation tree is going to be 'assembled'. Basically there are two options

  • Custom Assemblers provide the user with the option to create parts of the navigation tree structure in a programmatic way without using any additional xml. A custom assembler would create navigation nodes just the way we did within the createModel() method of the programmatic example. A custom assembler MUST implement the interface org.eclipse.riena.navigation.INavigationAssembler
  • Generic Assemblers are prepared to use the element structure provided within the assembly element. Generic Assemblers MUST implement the org.eclipse.riena.navigation.IGenericNavigationAssembler interface. There is a default implementation of a generic assembler, org.eclipse.riena.navigation.model.GenericNavigationAssembler, that will be used if no assembler is specified.

Navigation Assembler Variables

  • riena.navigation.nodeid
  • riena.navigation.nodecontext
  • riena.navigation.parameter

Generic Assembler Reference

assembly

use

attributes

  • name - Used to display a friendly string within the PDE
  • id - Unique id of the assembly.
  • assembler - The assembler class to be used to create this assembly. The class must implement org.eclipse.riena.navigation.INavigationAssembler. If this attribute is missing class org.eclipse.riena.navigation.model.GenericNavigationAssembler will be used.
  • parentTypeId - The type part of the default parents node id. If the user tries to create a navigation node this assembly is responsible for and no parent is provided, tha application is searched for a node with this type id and adds the node created by this assembly to that parent.
  • autostartsequence - Automatically calls the associated assembler upon application startup thus creating the navigation nodes for this assembly. The attribute should be an integer indicating the index of this assembly within the startup sequence and therefore defines the position(s) of the associated node(s).
  • ref - Reference to another assembly defined elsewhere with that id. If the assembly element is a child element of on of the oother elements except foreach this is the only legal attribute. This attribute has no meaning(and should therefore not be used) within a top level assembly definition.

subelements

Exactly one of subapplication or modulegroup or module or submodule is required if using a generic assembler. If a custom assembler is used none is required.

subapplication

use

attributes

  • name - Used to display a friendly string within the PDE
  • typeId
  • instanceId
  • label - Text to be displayed in the subapplications handle.
  • view - Id of the perspective associated with this subapplication.

subelements

any combination of an arbitrary number of modulegroup and/or assembly elements

modulegroup

use

attributes

  • name - Used to display a friendly string within the PDE
  • typeId
  • instanceId

subelements

any combination of an arbitrary number of module and/or assembly elements

module

use

attributes

  • name - Used to display a friendly string within the PDE
  • typeId
  • instanceId
  • label
  • icon
  • unclosable

subelements

any combination of an arbitrary number of submodule and/or assembly elements

submodule

use

attributes

  • name - Used to display a friendly string within the PDE
  • typeId
  • instanceId
  • label
  • icon
  • view
  • controller
  • shared

subelements

any combination of an arbitrary number of submodule, foreach and/or assembly elements

foreach

use

attributes

  • element
  • in

subelements

exactly one submodule element