SourceForge.net Logo

Site menu:

Version 1.3 released

2005-10-28

The AppTools library and workbench version 1.3 has been released. The workbench now uses internal frames for the application plug-ins by default. The platform will look for a 'lib' subdirectory at startup, and make any classes found in jar/zip files available for all plug-ins.

Related projects:

- ProbeMaker
- MolTools library

AppTools plug-in development guide

  1. The AppTools plugin system
  2. A few simple examples

The AppTools plugin system

AppTools provides an extensible application platform that is based on the plug-in concept. In the context of AppTools, a plug-in is a software component (small or large) that is accessible through a single class (although its functionality may be provided by any number of classes). Plug-ins may be dynamically loaded into an AppTools platform instance.

Plug-ins may range from small components that define various different ways to complete a particular type of task, to full-grown applications that use other plug-ins to perform some or many of its operations. One example is the ProbeMaker software, which is a plugin in itself, and uses the apptools plug-in mechanism to achieve extensibility for much of the functionality of the program.

By default, the extensible applications platform supports one type of plugin, ActivePlugIn, which is the plugin type used for plugin applications in general. The AppTools Workbench, which is a graphical user interface for the platform, supports a specialized version of this plugin, the UIActivePlugIn, which is used for providing a graphical user interface for an application, or for another plug-in. Plugins that are in themselves extensible may register new types of plug-ins (generally so-called ‘service’ plugins, that are invoked when needed, only) with the platform, and the platform will load available plugins of the type. These three types of plug-ins are represented by three Java interfaces, PlugIn, ActivePlugIn, and UIActivePlugIn.

PlugIn

First out, the PlugIn interface is the interface to be implemented by all extensions. This is a marker interface that doesn't define any methods. However, for a plugin to work correctly, a few methods are required. Firstly, all plugins are created using their no-argument constructors, so the plugin class must have a public parameter-less constructor. Otherwise, it will not be discovered by the platform. Furthermore, each plug-in class should define two static methods return descriptive strings:

public static String getBriefDescription() should return a short name of the plugin, suitable for display in lists or other selection widgets.

public static String getLongDescription() should return a longer description, which may be in HTML, of the plugin. The platform may use this to display info about the plugin as a tooltip, or in some other way to give the user more info when selecting plugins for a particular task.

ActivePlugIn

The ActivePlugIn interface defines a number of methods that control the life-cycle of an active plugin. An active plug-in is instantiated with its no-argument constructor, as for all plug-ins. The platform then queries the plugin to check which other plugins are required by it, and their versions. After activating any non-active required plugins, the plugin is set up for use with the platform. When the user deactivates the plug-in or exits the platform, the plugin is called in order to shut itself down and release any resources, etc.

public Map getPlugInRequirements()

public void setup(Platform platform) throws PlugInException

public boolean teardown()

public String getVersion()

The getPlugInRequirements should return a Map of [name, version] pairs, with one pair for each other plug-in that this plug-in requires. The name value should be the fully qualified class name of the other plug-in, and the version shoul be a string on the form x.y.z representing the least allowed version of the other plug-in.

If the activation of all required plug-ins was succesful, the setup method will be called, providing the plug-in with a handle to the Platform it is running in. This should be used to register action sets, preferences entries, etc. with the platform

When the user deactivates the plug-in, or exits the platform, the teardown method is called. The plugin should then de-register anything that was registered, perhaps save date and release any other resources. The return value is currently not used by the platform, but the intended use is that a plug-in that for some reason does not want to be torn down should return false.

The getVersion method should return a string on the form x.y.z that is the current version of the plug-in.

UIActivePlugIn

The Workbench will recognize a specialization of the ActivePlugIn, the UIActivePlugIn, that also defines the methods getIcon(), and createFunctionalityUI(). The former may return an Icon to display with the UI of this plugin, and the latter a Component that will be displayed in the platform GUI as an interface for the plugin. Both are called after calling the setup method

public Icon getIcon()

public Component createFunctionalityUI()

Setting up active plug-ins

The setup method gets called once during the life cycle of a plug-in, and gives the opportunity for the plug-in to adapt the platform to some extent. This is done by registering actions and preferences with the platform. When the teardown method is called, this should be deregistered.

The platform interface defines a number of methods for this purpose:

public void addActionSet(ActionSet set)

public void removeActionSet(ActivePlugIn set)

public void addQuickActionSet(ActionSet set)

public void removeQuickActionSet(ActivePlugIn set)

public void addPreferenceEntries(EntryDescriptor[] entries, String nodePath, PreferenceChangeListener listener)

public void removePreferenceEntries(EntryDescriptor[] entries, String nodePath, PreferenceChangeListener listener)

The add/remove ActionSet methods are used to register a group of related actions with the platform. These will appear as menu options in the workbench, under a menu named according to the ActionSet.

The add/remove QuickActionSet methods are used to associate one or more groups of actions with a particular plugin. These actions will be available as buttons in the workbench toolbar when the corresponding plug-in is shown. This is thus intended mainly for UI plugins.

The add/remove PreferencesEntries methods are used to register a number of EntryDescriptor objects for this plugin. These descriptors are used to read/store user preferences for the plugin, and to edit the preferences through the workbench. If a listener is provided, this will be registered with the corresponding preferences node, and be called if non-default values are found in the preferences store, and whenever the preferences are changed during runtime.

User interaction

The platform also supplies a few methods to allow plug-ins to interact with the user in a user interface-independent manner. These are provided by a PlatformUI object that is accessed by the platform’s getUI() method. This object supplies the following methods for user input/output:

public byte sendMessage(String message, String messageTitle, byte responseType)

public byte sendMessages(List message, String messageTitle, byte responseType)

public File selectFile(javax.swing.filechooser.FileFilter filter, File defaultFile, String caption)

public File[] selectFiles(javax.swing.filechooser.FileFilter filter, String caption)

public File selectSaveFile(javax.swing.filechooser.FileFilter filter, File defaultFile, String caption, String autoSuffix)

public void inputData(DataHolder dh, String title)

See the documentation for more details on these methods

Registering and selecting plug-ins

Under construction…

A few simple examples

This section will give a few examples on how to create plugins.

Example 1, Hello world menu:

This example shows how to register actions with the platform, and how to send a simple message to the user. HelloWorldMenuPlugIn.java

Example 2, more Hello world!

This example demonstrates how to read user through the platform. It may seem a bit cumbersome to do it this way. Of course the JOptionPane class may be used instead for getting user input, but this requires that a graphical user interface is available, while the platform system allows other types of user interfaces. HelloWorldMenuPlugIn2.java