Using the Model View Controller pattern when creating viewers

I realized after using the dashboard application I created for my team how nice it would be if it used a breadcrumb type of navigation to go between its pages. The cool thing about breadcrumb navigation is it only takes up one horizontal line on the screen – not a lot of real estate. Here is a screen shot of the widget:

The way a breadcrumb navigation works is each entry in the list is hot and if you click on one of the entries you will get a menu for all of its children and down. Here is a screen shot where the root page is selected – you basically get the navigation for the entire application in a single menu:

If you click on a middle entry you will only see from itself down in the hierarchy:

This is a pretty straightforward sample where I created a Widget, a View, and then a content provider and a label provider. The cool thing is, since I abstracted everything you could replace any piece to get a different behavior. Making a widget allows others to embed my widget into their views and then even use their own label and content providers but still relying on what the base widget provides. I decided to make my viewer extend from “org.eclipse.jface.viewers.ContentViewer” and enforce a content provider derived from “ITreeContentProvider” and a label provider derived from “ILabelProvider“.

The widget is where all of the UI is drawn. In the attached source the widget is the BreadCrumbNavViewer class. I used basic Labels for the UI, however I did use the SWidgets that are shipped with Notes and Expeditor so my navigator can have the look and feel of the client. I also probed the Theme, Color and Font registry to figure out what ones to use, you can see that in the source. The beauty of the Model-View-Controller pattern is the view part does not know anything about the objects it is presenting. You will notice the entire widget only works with Object's, nothing else.

The view is very basic, pretty much all of the code is below however, you can go and see all of the code for BreadCrumbNavigatorView. I made the view implement a SelectionListener interface where it gets called back with the original Object it passed in for the menus. This makes the abstraction complete – while the widget provides the menu, the view acts on the selection.

The content and label providers are where all of the implementation specific code is for handling the Topology Handler model. This means this breadcrumb widget can be used with any model – not just Topology. In composite applications the model is a hierarchy of pages and labels. The code you see in the providers is specific to it.

Lastly, if you want to have a custom navigator you need to set some application and page properties in order to get the behavior of the original navigator. First, you need to specify the “com.ibm.rcp.navigationModel=custom” and and the “com.ibm.rcp.useNavigator=true” in the Application advanced properties in CAE. This will make each perspective show in the same tab and not have a new tab open. These application page settings will by default display each page of your CA in the same tab. For any page (not the Application page) that you would like to have displayed in a separate tab, add “com.ibm.rcp.useNavigator=false” to that page's properties.

Full plugin and source can be downloaded here.

Code for BreadCrumbNavigatorView

	BreadCrumbNavViewer nav = null;

@Override
public void createPartControl(Composite arg0) {
nav = new BreadCrumbNavViewer(arg0, SWT.NONE, this);

nav.setContentProvider(new TopologyNavContentProvider());
nav.setLabelProvider(new TopologyNavLabelProvider());

TopologyHandler handler = TopologyHandlerFactory.getHandler( );
Navigation n = handler.getNavigation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getPerspective().getId());
nav.setInput(n);
}

@Override
public void setFocus() {
// TODO Auto-generated method stub

}

public void selectionChanged(Object obj) {
if (obj instanceof Page){
Page page = (Page )obj;
try {
PlatformUI.getWorkbench().showPerspective(
page.getPerspective(),
PlatformUI.getWorkbench().getActiveWorkbenchWindow());
} catch (WorkbenchException e) {
e.printStackTrace();
}
}
}

Tags: : : :

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.