After reading this section, you should understand what a LaunchTask
is and how it is used in the context of an ApplicationFrame.
Basically speaking, LaunchTask implementations are used to decouple
application-specific initialization code from the ApplicationFrame
class, instances of which are needed for any standalone application based on the
Skeleton framework.
Even though the ApplicationFrame class acts like a controller, it
should not be extended with specialized initialization code, which is only required once
during application startup.
The ApplicationFrame-derived class
SwingApplicationFrame decouples this specialized code by reading a
list of “launch tasks” when starting up and executing them sequentially. You
may override the getLauncherTask() method of the parent
SwingApplicationFrame class and return a new list. Otherwise, you may
use the default list without any modification.
The Skeleton provides a basic framework for all currently required
LaunchTask types. There are LaunchTasks to load files
(LoadFileLaunchTask), LaunchTasks to create and initialize
ToolBars (AbstractToolBarLaunchTask), Menus (AbstractMenuLaunchTask),
as well as LaunchTasks to create Commands (CommandLaunchTask).
Either use these superclasses as the basis for your own implementations or extend the
default LaunchTask implementations of the Skeleton framework.
The following sections show the LaunchTask implementations used
in this chapter's sample application.
Application preferences may differ for every Skeleton-based
application you create. These preferences are configured in an xml file and the
preference dialog of you running application will reflect the structure of this file.
You will return the file's path in the method
getDefaultPreferences() of class
CustomPreferencesLaunchTask. You can always count on a
similar look and navigation structure when setting preferences.
In order to store the settings of a user, a file needs to be written to a directory
on the host system. This file is located in the directory {user.home} and the file
name is returned in the method getFilename(). The following
code snippet shows how these customizations are made in the sample application.
Example 9.4. Overridden Methods for Files
/**
* This LauchTask specifies the preferences to use.
*/
public class CustomPreferencesLaunchTask
extends LoadPreferencesLaunchTask
{
/**
* Constructor specifying the ApplicationFrame.
* @param applicationFrame the ApplicationFrame
*/
public CustomPreferencesLaunchTask(ApplicationFrame applicationFrame)
{
super(applicationFrame);
}
/**
* Returns the path to the initial preference file relative
* to the load class specified in method getLoadClass().
*/
protected String getDefaultPreferences()
{
return "../resource/xml/defaultprefs.xml";
}
/**
* All changes to the initial application settings get written
* out to this file. It will be located in folder {user.home}.
*/
protected String getFilename()
{
return "skeleton_example.prefs";
}
/**
* The class to use to load the initial preference file.
*/
protected Class getLoadClass()
{
return Main.class;
}
}
You may wish to refer to the Framework Manual for more information on this special topic.
In order to create custom commands for a Skeleton-based application
you can provide your own CommandLaunchTask implementation and
override the perform() or postCreate()
method. In our sample application we used the latter approach:
Example 9.5. Overridden postCreate() Method
// this method is called after the common commands were set up
public void postCreate(Object object)
{
// register circular...
new LayoutCommand(getApplicationFrame(), LAYOUT_CIRCULAR_IDS,
GraphLayoutController.Circular);
// ..., energy layout...
new LayoutCommand(getApplicationFrame(), LAYOUT_ENERGY_IDS,
GraphLayoutController.Energy);
// ...and hierarchical top-bottom
new LayoutCommand(getApplicationFrame(), LAYOUT_HIERARCHICAL_IDS,
GraphLayoutController.HierarchicalToBottom);
// toggle the edge types used in edge creation mode
new ToggleAssignEdgeModeCommand(
getApplicationFrame(),
ToggleAssignEdgeModeCommand.MENU_EDIT_TOGGLE_EDGE_MODE);
}
The Skeleton creates a set of default menus called “File”, “Edit”,
“View”, “Tools”, “Window” and “Help”.
Each of these menus has a corresponding default command. To add a custom command
to the menubar or toolbar of the application, you have to create it first. In the next
step, you can add the command to the UI. For the sample application this is done in class
CustomToolbarLaunchTask.
Example 9.6. Adding Commands to the Toolbar
// Add edge creation mode toggle button to toolbar.
public void postCreate(Object object)
{
SwingToolBar toolbar=
(SwingToolBar) getApplicationFrame().getToolBars()[0];
// Edge creation mode
final String ecIconURL ="icons/menu/edgeCreation.png";
addToToolBarToggleButton(
toolbar,
GUIItem.MENU_EDIT_TOGGLE_EDGE_CREATION,
ecIconURL, ecIconURL, ecIconURL, ecIconURL,
GUIResource.class);
final String conModeIconURL = "../resource/images/con_mode.png";
final String conModePressedIconURL = "../resource/images/ass_mode.png";
addToToolBarToggleButton(
toolbar,
ToggleAssignEdgeModeCommand.MENU_EDIT_TOGGLE_EDGE_MODE,
conModeIconURL,
conModePressedIconURL,
conModeIconURL,
conModePressedIconURL,
Main.class);
}
The element definitions describing geometries, styles and rules are
specified in a file which is loaded in the method
perform() of class
LoadElementDefinitionsLaunchTask.
Example 9.7. Loading Element Definitions
/**
* Loads the graph element definitions from the resource file
* "geometry.xml", "styles.xml", "rules.xml" and "elements.xml".
* Afterwards the corresponding pools are filled with this definitions.
*/
public class LoadElementDefinitionsLaunchTask extends LaunchTask
{
private final static String RES_PATH = "../resource/xml/";
private ApplicationFrame appFrame;
/**
* Constructor specifying the ApplicationFrame to use.
* @param applicationFrame Application context for this LaunchTask.
*/
public LoadElementDefinitionsLaunchTask(
ApplicationFrame applicationFrame)
{
this.appFrame= applicationFrame;
}
public String getName()
{
return "Loading Element Definitions";
}
public int run() throws Exception
{
GraphGeometryService.loadGeometriesFromResource(
RES_PATH + "geometry.xml", ExampleApplicationFrame.class);
StyleService.loadStylesFromResource(
RES_PATH + "styles.xml", ExampleApplicationFrame.class);
RuleRegistry rr =RuleRegistry.loadRulesFromResource(
RES_PATH + "rules.xml", ExampleApplicationFrame.class);
((SwingApplicationFrame)appFrame).setRuleRegistry(rr);
ElementService.loadElementsFromResource(
RES_PATH + "elements.xml", ExampleApplicationFrame.class);
return LAUNCHTASKSTATUS_SUCCESS;
}
}
After the element definitions have been loaded, they can be placed inside
a so-called RepositoryItemPanel. The following
code snippet shows you how to do this. Please have a look at class
CustomRepositoryLaunchTask in the sample
application as well.
Example 9.8.
// Create Custom Node Repository
RepositoryItemPanel nodeRepIP= new RepositoryItemPanel(2, 2);
nodeRepIP.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
final UIManager uiMan = getApplicationFrame().getUIManager();
VisualGraphObjectRepositoryItem tmpRepItem =
new VisualGraphObjectRepositoryItem(
getApplicationFrame().getDragContext(),
ElementPool.get("AppNodeElement"),
uiMan.getText("node.appl"));
tmpRepItem.setIcon(SwingUtil.getResourceIcon(
"../resource/images/app_node.png",
Main.class,
tmpRepItem, false));
nodeRepIP.addJComponent(tmpRepItem);
© 2004, 2005 Tensegrity Software GmbH