This document is work in progress. Comments, improvements and additional content are welcomed.
Swing applications beyond a basic level of complexity benefit greatly from the functionality provided by a command framework. These frameworks tend to extend the basic Swing Action functionality and provide the user with support for the creation, management and configuration of menubar, toolbar and popup menus and a host of other useful features you will commonly require when dealing with rich clients. Spring Rich Client possesses such a command framework, currently located in the package:
org.springframework.richclient.command
Some of the features provided by the framework include:
Delving straight in to the code is the best way to learn about the framework and we will start by showing how to work with shared or global commands. These commands typically populate top level application menus and toolbars and are responded to differently depending on the currently displayed view. Our example will show us how to define and interact with an application menubar and toolbar that looks like the following:
Central to the command framework, allowing declaration of global commands as well as the definitions for the application toolbar and menubar is the commands-context.xml file. This is a standard Spring XML Beanfactory definition file in which we declare our menubar and toolbar structure by wiring together different beans. The location of this file is injected in to the ApplicationLifeCycleAdvisor on startup of the application. If we take a snippet from our richclient-application-context.xml file we can see the location of the command context file injected as a property of the lifecycleadvisor bean:
<bean id="lifecycleAdvisor" class="com.mcauley.client.SimpleLifecycleAdvisor"> <property name="windowCommandBarDefinitions" value="ui/commands-context.xml"/> <property name="startingPageId" value="initialView"/> <property name="eventExceptionHandler" value="com.mcauley.client.SimpleApp$AWTExceptionHandler"/> </bean>
In our example, the property windowCommandBarDefinitions locates the application window commands definition file at ui/commands-context.xml . At a more detailed level, the commands context defined by this file is installed as a child of the application context, which in turn is defined in richclient-application.xml. The application framework will propagate application events from the main context down to the commands context, so that beans defined in the commands context can process these events if required.
The accompanying project source structure was created using the default Maven archetype, and under that structure you can see that the two files commands-context.xml and richclient-application-context.xml are located at:
myclient\src\main\resources\ui\commands-context.xml myclient\src\main\resources\ctx\richclient-application-context.xml
Now we have introduced the commands-context file we can take a further look inside to see how we define our application toolbars and menubars. The file defines some magic beans, that is, beans the Application Framework expects to exist in the file with specific names. In the commands-context file, the magic bean names are menuBar , toolBar and windowCommandBarManager . As you would expect, the menusBar and toolbar beans declare the structure and content of the application menubar and toolbars. The windowCommandBarManager defines the bean that will manage the commands associated with an application Window. Specifically, we use this bean to declare Global commands that are visible throughout the Application. These global commands are also referred to as shared commands.
Our windowCommandBarManager declaration looks as follows:
<bean id="windowCommandManager" class="org.springframework.richclient.application.support.ApplicationWindowCommandManager"> <property name="sharedCommandIds"> <list> <value>propertiesCommand</value> <value>exportCommand</value> </list> </property> </bean>
This tells the framework that an instance of ApplicationCommandManager (we will cover CommandManagers in more detail later) will be managing the window commands and to add two shared, or global commands to that manager. In our example we have declared that there are two shared commands identified as propertiesCommand and exportCommand . For now, this is all we need to declare these commands as global. Now we can see how to add commands to the menubar and toolbar by looking at the following code sample from the context file.
<bean id="menuBar" class="org.springframework.richclient.command.CommandGroupFactoryBean"> <property name="members"> <list> <ref bean="fileMenu"/> <ref bean="windowMenu"/> <value>glue</value> <ref bean="helpMenu"/> </list> </property> </bean>
<bean id="toolBar" class="org.springframework.richclient.command.CommandGroupFactoryBean"> <property name="members"> <list> <value>exportCommand</value> <value>propertiesCommand</value> </list> </property> </bean>
Looking at the menuBar bean, we are defining an application menuBar with three command elements, fileMenu, windowMenu and helpMenu. Each of these menus forms a member of a Command Group and the CommandGroupFactoryBean class is used to create the actual command group, made up of the elements of the list in the members property. Similarly for the toolbar bean, we have a command factory bean that creates a toolbar group that has two members � exportCommand and propertiesCommand. Note that the members of the toolbar group are global commands as defined above and we will cover how to interact with these commands later. But first a few observations.
In our menubar, the commands appear as File , Window and Help . Also note that the Help member appears to the right of the menubar. Where does the text and icon image come from for the commands and how did we layout the Help menu member to the right. Clicking on each main menu command displays drop down menus which may contain submenus � how do we define these elements? Note also the presence of command mnemonics and keyboard accelerators.
Here is how the menu members look when you click on them:
File menu:
Window menu:
Help menu:
We shall look at the text, icon mnemonic and accelerator elements of a command before we cover the generation of submenus and the location of the Help menu. Firstly, the command framework provides some predefined command configurations, some global command identities and some useful ActionCommands that are all configured for use straight out of the box. For shared commands, the process works as follows: when you add a shared command identity to the windowCommandManager in the commands-context file then the framework will automatically configure that command based on information derived from the command Id. The Id is simply the name of the command and is used to reference that command throughout your application. The command will be configured with such things as a display text, a tooltip, an icon, a mnemonic and a keyboard accelerator if defined in your application resource files. The resource files in question are messages.properties and images.properties. These are the standard location for messages and icon resources in the application framework and it will be assumed you are familiar with their use.
As a reminder, in the archetype application project, the two files are located at:
/myclient/src/main/resources/ui/messages.properties /myclient/src/main/resources/ui/images.properties
So, for our exportCommand, identified as a shared command, the command identity exportCommand is used to look up configuration information about this command. Note that the id has to be unique.
In the messages.properties file we find they following entries:
exportCommand.label=&Export@alt X exportCommand.caption=Exports the view data
We have a key for the entries made up of the command Id (exportCommand ) and two subkeys, label and caption. The command caption is used as a tooltip in the application for that command. The command label is more involved. The & symbol identifies the mnemonic to use for the command. The following text is the label itself, in our case Export . The remaining part of the string identifies the keyboard accelerator used to trigger this command. In this instance, the accelerator is identified as Alt X . Both the label mnemonic and the accelerator are optional additions for the command. We will look at configuration in more detail later on. We now have the textual configuration of the command in place and by a similar mechanism we can provide an icon for the command by placing an entry in the images.properties file that locates the icon to use for the command.
By looking at our images.properties file we can see the entry:
exportCommand.icon=misc/skip_status.gif
Again, the unique command Id is used to locate an icon entry for the command which is used in toolbars and menus as shown in the preceding images. Note that if the icon resource cannot be found then a broken image placeholder will be shown instead.
We have seen how to add and configure a global command but where do the entries for the other commands get defined? In our example that includes menu entries for File , Window and Help along with command entries for Properties , Exit , New Window , Show View and About .
We can see in the commands-context file that our menubar has four entries in its list of members. fileMenu , windowMenu , glue and helpMenu . Three of these come with predefined messages in the application framework, so we don�t need to add any text (in English that is, you would if you wanted to loclaise the text to a language not already included). The remaining member glue is a configuration layout hint that behaves the same as the Glue component of the standard Box layout. By adding this member, it fills out all available space between the Window and Help menu members and causes the Help menu element to be displayed to the right of the menubar. We can also see that each of these menu bar entries has its own bean definition. These definitions declare the content of each menu.
The definition for the file menu is as follows:
<bean id="fileMenu" class="org.springframework.richclient.command.CommandGroupFactoryBean"> <property name="members"> <list> <value>propertiesCommand</value> <value>separator</value> <value>exportCommand</value> <value>separator</value> <bean class="org.springframework.richclient.command.support.ExitCommand"/> </list> </property> </bean>
So we have five entries in the member list, telling us that this drop down menu has that many constituent elements. Three of the members represent commands and the other two indicate the use of visual separators in the displayed menu. Note that in this case, two of the members are shared commands and the last, ExitCommand, is a predefined ActionCommand. The behaviour of the latter command does not change depending on the view displayed.
The method of configuration for these group command members is the same. The unique Id of the command is used as a lookup key to find display information, such as label, tooltip and icon etc. Before going on to look further at interacting with global commands or understanding ActionCommands, we can summarise how we add elements to the application menubar or toolbar.