All plugins for the Spyglass visualization framework reside under this package.
Contents
Types of plug-ins and class hierarchy
From the functional point of view there are three types of plug-ins for the Spyglass framework:
- plug-ins that draw onto the canvas, called drawing plug-ins (example:
{@link de.uniluebeck.itm.spyglass.plugin.simplenodepainter.SimpleNodePainterPlugin})
- plug-ins that aggregate data, do statistics and so on and write them onto the so called
global information section (the bar on the right hand side of the window), called global
information plug-ins (example:
{@link de.uniluebeck.itm.spyglass.plugin.simpleglobalinformation.SimpleGlobalInformationPlugin})
- plug-ins that do both, called drawing global information plug-ins
As plug-ins are furthermore distinguished by semantic properties there's a convention that specifies
that plug-ins with similar semantics should be of the same parent type.
The {@link de.uniluebeck.itm.spyglass.plugin.imagepainter.ImagePainterPlugin} for example is derived from
the abstract base class {@link de.uniluebeck.itm.spyglass.plugin.backgroundpainter.BackgroundPainterPlugin},
which itself is derived from {@link de.uniluebeck.itm.spyglass.plugin.Plugin}, the base class of all
plug-ins.
In this way plug-ins are grouped semantically, which also may, depending on the semantics, result in
common behaviour implemented in the respective base class. Furthermore, the plug-ins are presented to
the user in exactly the same hierarchy defined by the inheritance hierarchy (take a look in the properties
dialog of the running application).
Implementing plug-ins
Resulting from the introduction
(Types of plug-ins and class hierarchy) you have
to follow some rules if you want to implement your own plug-ins:
-
Every plugin must implement the abstract base class {@link de.uniluebeck.itm.spyglass.plugin.Plugin},
either by extending another abstract class such as
{@link de.uniluebeck.itm.spyglass.plugin.backgroundpainter.BackgroundPainterPlugin} or directly.
In both cases, the implementor should carefully read the documentation of
{@link de.uniluebeck.itm.spyglass.plugin.Plugin}. Some properties, for example the human-readable
name of your plug-in, are determined at runtime by calling static methods of your class. Therefore
it's crucial that these methods are implemented in every plug-in. As there's no way to force you
overwriting static methods in the Java programming language, it's up to the programmer to read the
documentation, since your IDE won't tell you.
-
To create a drawing plug-in you must implement
{@link de.uniluebeck.itm.spyglass.plugin.Drawable}. Objects are painted onto the canvas by using
so called drawing objects (see Drawing Objects).
-
To create a global information plug-in you must implement
{@link de.uniluebeck.itm.spyglass.plugin.GlobalInformation}.
-
In case the plug-in needs metrics for the node's position in order to work correctly,
it must implement {@link de.uniluebeck.itm.spyglass.plugin.NeedsMetric}. If your plug-in
implements this interface the framework automatically deactivates your plug-in if there's a
node positioner active which doesn't provide metrics.
Drawing Objects
Plug-ins draw onto the canvas by adding drawing objects (see
{@link de.uniluebeck.itm.spyglass.drawing.DrawingObject}) onto their layer. Every
plug-in has it's own layer "to draw on" (see {@link de.uniluebeck.itm.spyglass.layer.Layer}).
The order in which is drawn results from the order in which the plug-in instances are sorted in the
preferences dialog of the running Spyglass application. The topmost plug-in will be the last in queue
to draw, therefore drawing over drawings of the lower plug-ins.
Writing your own plug-in you can either
- use primitive drawing objects, which are located in the package
{@link de.uniluebeck.itm.sypglass.drawing.primitive}
- or use plug-in specific drawing objects which should then be located into your plug-in specific
package.
If you need to write a new drawing object that might be used as a primitive since it's so marvellous that
it can be reused by other plug-ins, it might be a good idea to place it into the primitive-package.
The drawing of Spyglass is event-driven. Because of that your plug-in instance needs to inform the framework
about drawing objects added or removed. Please check the following methods for further information:
- {@link de.uniluebeck.itm.spyglass.plugin.Plugin#fireDrawingObjectAdded(de.uniluebeck.itm.spyglass.drawing.DrawingObject)}
- {@link de.uniluebeck.itm.spyglass.plugin.Plugin#fireDrawingObjectRemoved(de.uniluebeck.itm.spyglass.drawing.DrawingObject)}
Global Information Plug-Ins
In order to implement plug-ins that draw onto the global information area your plug-in class must
implement {@link de.uniluebeck.itm.spyglass.plugin.GlobalInformation}. It must furthermore provide
a GUI widget of class {@link de.uniluebeck.itm.spyglass.gui.view.GlobalInformationWidget} which is
later on displayed to the user inside a swt {@link org.eclipse.swt.widgets.ExpandBar} during
runtime. The content of the widget is of arbitrary type. You could, e.g. display an overview map of
the drawing area exactly as you could display any type of table displaying structured information.
Plug-in Preferences and Instance Properties
Spyglass implements a system for storing plugin preferences in a unified manner over all plug-ins.
Spyglass makes sure that plug-in preferences as well as plug-in instance preferences are loaded and
stored on program startup respectively program shutdown, as well when users edit the preferences.
In order to achieve this behavior plug-in implementors must implement
{@link de.uniluebeck.itm.spyglass.plugin.Plugin#createPreferencePage(PluginPreferenceDialog, Spyglass)}
as well as {@link de.uniluebeck.itm.spyglass.plugin.Plugin#getXMLConfig()} and the corresponding
classes {@link de.uniluebeck.itm.spyglass.gui.configuration.PluginPreferencePage} and
{@link de.uniluebeck.itm.spyglass.xmlconfig.PluginXMLConfig}.
This document was written by Daniel Bimschas
(daniel@bimschas.com).
Feel free to contact me regarding questions or errors in this document.