By the way...

This content is now pretty old: check the homepage for the latest.

In this session we will look at the ownerManagerView and its associated descriptor. This is the bit which displays the tree view on the "Owner Manager" screen of the Petclinic sample application. Looks like the author got the bean name right :) (What's the hardest problem in computer science? It's naming a class well, so that the next coder can understand what the class does. Believe it).

Ok, let's have a look at the view descriptor and see how one of those is defined.

<bean id="ownerManagerView"
class="org.springframework.richclient.application.support.DefaultViewDescriptor">
<property name="viewClass">
<value>org.springframework.richclient.samples.petclinic.ui.OwnerManagerView</value>
</property>
<property name="viewProperties">
<map>
<entry key="clinic">
<ref bean="clinic"/>
</entry>
</map>
</property>
</bean>

This is fairly straightforward - a descriptor has a class name to instantiate, and what looks like a list of properties to apply to that class on creation.

The view is created by the descriptor, using the createView() method. This, amongst other things, adds the view to the 'ApplicationEventMulticaster' (defined in richclient-application-context.xml) if the view of type ApplicationListener. I guess this is so the view can get messages from the outside world if necessary. So far, so good.

So what does this view look like: The main window looks like this, with the ownerManagerView defined in the centre:

Let's see how we define each segment of this view.

View Caption

AbstractView contains a bunch of accessor methods (that's a fancy word for a 'get' method, in case you weren't aware) to define things like caption, description, display name etc. These are mostly got from the descriptor class. In this case, our descriptor doesn't appear to define them - perhaps it uses defaults. Let's skip a few steps and cheat: We'll search for the caption text and see what we come up with.

messages.properties: ownerManagerView.label=&Owner Manager

Aha. Our old friend messages.properties. Let's see what happens if we change this.

messages.properties: ownerManagerView.label=&Chris' Owner Manager

Sure enough:

Looks like to define a caption name, it looks like you define the "<viewName>.label" message. And even better, you can define the name in one place and it's changed across the whole application, including in the menus. Neat.

I'm guessing the icon and other text options are defined in the same way.

Laying out the view

The OwnerManagerView derives from AbstractView. Poking through AbstractView, we find the following:

protected abstract JComponent createControl();

Ok, so that looks like the method that's called when the view needs to be created. How does OwnerManagerView define this?

protected JComponent createControl() {
JPanel view = new JPanel(new BorderLayout());
createOwnerManagerTree();
JScrollPane sp = new JScrollPane(ownersTree);
view.add(sp, BorderLayout.CENTER);
return view;
}

Ok, we're in standard Java Swing territory here. First we create a shiny new panel, with a simple layout. We create the owner manager tree, a new scroll pane to hold it, and then add the scroll pane to the panel.

The Tree

The createOwnerManagerTree() method is fairly straightforward Java Swing component construction also, except that there are a number of utility classes and interfaces built into Spring Rich Client which help you out. The FocusableTreeCellRenderer class, for example, makes the tree cells work a little more like windows trees (therefore, how people expect them to work, for better or worse). Choosing what to display in each tree cell is standard Swing API legwork, except that Spring Rich Client makes it easy to pick an icon - see this snippet from the custom treeCellRenderer:

this.setIcon(getIconSource().getIcon("owner.bullet"));

That refers to our plumbed in icon source bean, which we looked at in Session Four. Let's be mischievous and change this icon to the spring logo, and see what happens:

owner.bullet=spring-logo.gif

This is what we get:

Hmm - that doesn't look like the spring logo... But hang on, what's that on standard output?

WARNING: Unable to load image resource at 'class path resource [images/spring-logo.gif]'; returning the broken image indicator.

Oops. Looks like I typed the name incorrectly. Let's try:

owner.bullet=spring-logo.png

That's better. It's looks awful, but that's what you get for sticking so large an image on a tree cell. I'm surprised it worked at all, actually :)

Tree Events

How do we handle events generated by this tree? Check out this cool Spring Rich Client utility class, TreeStatusBarUpdater:

  ownersTree.addTreeSelectionListener(new TreeStatusBarUpdater(getStatusBar()) {
public String getSelectedObjectName() {
Owner selectedOwner = getSelectedOwner();
if (selectedOwner != null) {
return selectedOwner.getFirstName() + " " + selectedOwner.getLastName();
}
else {
return "Owners";
}
}
});

When we select a new node, this inline class allows us to easily supply a String to update the status bar with. That's really neat.

Similar utilities exist for the mouse listeners:

  ownersTree.addMouseListener(new PopupMenuMouseListener() {
protected boolean onAboutToShow(MouseEvent e) {
return !isRootOrNothingSelected();
}</p>
<p> protected JPopupMenu getPopupMenu() {
return getSelectedOwner() != null ? createOwnerPopupContextMenu() : createPetPopupContextMenu();
}
});

All you do is define whether or not to show the popup, and which menu to show if you do. Creating Java's Swing components in Spring Rich Client seems to be a breeze...

Summary

This session, we learned how to create and lay out views in Spring Rich Client. We looked at the view descriptor and how it uses default labels to display captions and icons. We saw how easy it is to create tree components that feel 'right', and we oohed at the really useful utility classes Spring Rich Client provides to lay out controls and handle events.

Next time, let's have a look at all those commands and executors we've seen inside the OwnerManagerView.java, and try to work all that out.