Patterns for JHotDraw
Douglas Kirk
Department of Computer Science
University of Strathclyde
Livingstone Tower
Glasgow G1 1XH, Scotland
Tel: +44 (0)141 548 3622
Email: doug@cs.strath.ac.uk
 
This work is based heavily on the work of R. Johnson in his seminal 1992 paper "Documenting Frameworks using Patterns". This work merely attempts to adapt the concepts presented there into a format suitable for the Eggenschwiler & Gamma implementation of HotDraw.


JHotDraw Patterns
Semantic Graphic Editors
Defining Drawing Elements
Changing drawing element attributes
Making new kinds of Tools
Making new kinds of handles
Making new Menus
Constraints
Creating Animation

 


Semantic Graphic Editors

HotDraw is a framework for structured drawing editors. It can be used to build editors for specialised two-dimensional drawings such as schematic diagrams, blueprints, music, or program designs. The elements of these drawings can have constraints between them, they can react to commands by the user, and they can be animated.

Figure 1: Pert chart editor

Figure 1 shows a PERT chart editor created using HotDraw. This example shows the fundamental aspects of a HotDraw application. The top of the figure holds the menu bar. The default bar is created with File, Edit, Align, Attributes and a Debug menu. Each menu contains familiar functionality i.e. the File menu allows the user to load and save diagrams etc. The menu bar is fully customisable, existing menus can be removed or edited and additional ones created to suit the needs of specific applications.

On the left hand side of the application is the Tool Palette. This defines the set of actions a user can perform with the application. In this example the palette contains a selection tool, a text editing tool, a PERT event creation tool, a PERT connection tool and a straight-line tool. By default this palette is configured with only a selection tool, but the framework does contain a collection of predefined tools to choose from and application specific tools can be created if required.

At the bottom of the application lies the status bar. This displays the current state that the system is in. In the above example the bar informs us that the selection tool is currently active. The status bar can be altered to return information specific to your application.

The largest part of the application is taken up by the Drawing View. This view provides a representation of the underlying application model. In the case of HotDraw the model is an object called Drawing (which is similar in function to its real world equivalent)

The shapes on the Drawing View are Figures in this case rectangles, text and lines. Figures are used to represent the discrete components in a diagram. Again the framework is pre-supplied with many commonly required figures and the developer has the opportunity to define new ones for their application.

The figure on the right hand side of the application is the currently selected shape and the little squares and the circle that are visible on it are called Handles. Handles show that a shape is selected and also provide editing functionality. The set of handles that are defined for each figure is customisable, the number of them, position and shape of them can all be changed and most importantly the behaviour defined for each one can be altered. Handles can be used to change a figure’s size, colour, and shape … any attribute of the figure can be edited this way.

The final elements shown on this diagram are constraints between figures. In this example the lines that connect the PERT events together represent constraints (although constraints do not have to be visible) and in this case they ensure that the duration of every event takes into account the duration of every preceding event in the graph.

HotDraw is designed around a direct manipulation paradigm. This places certain obligations on the developer. Where possible the application should adopt the direct manipulation approach. A user will manipulate an element of a drawing by using the mouse to select it then operate upon it. i.e. clicking on a PERT event in the above application will select it, causing its handles to display. The user may then drag the circular handle with the mouse and a new connecting line will appear. If the user positions the end of this line over another PERT event before releasing the mouse button then a connection between the two events will be made (and the constraints between then enforced).

Drawing editors created with HotDraw can assume several forms. Most commonly they are created as stand alone classes by sub classing DrawApplication, alternatively the application can be created as an applet (a simple application designed to run in a web browser) by sub classing DrawApplet.

A stand-alone application can be created via the following code:

Main(){
        DrawApplication drawApp = new DrawApplication();
        DrawApp.open();
}
This creates a default application that is initialised with a single tool and the standard menu configuration.

To design a drawing editor using HotDraw, first list the atomic elements of the diagram. Each one will be a subclass of Figure. Decide whether the drawing needs to be animated. List the tools that will be in the palette and make a subclass of DrawApplication with a createTools(Palette) method that creates and adds all the applications tools to the supplied Palette.


Defining Drawing Elements

There are an infinite variety of primitive figures that can be included in a drawing. Thus, there needs to be a way to make new figures for each application.

Each kind of drawing element is a subclass of Figure. In HotDraw there are four strategies to figure creation. The relative strengths and weaknesses of each are explained below.

  1. Use existing classes: HotDraw is supplied with default implementations for many common figures, such as EllipseFigure, RectangleFigure, and LineFigure. These may be reused ‘as is’ in new applications, this saves developers the time and effort required to create such elements themselves but reduces the knowledge the developer has about how that figure is implemented (important in efficiency and robustness arguments).
  2. Subclass existing classes: Often the default implementations of Figure are ‘almost but not quite’ what is required by an application. In such circumstances it makes sense to customise the existing figure to fit the applications needs. This saves time compared with starting from scratch and provides insight into the organisation of that figure but sub classing will increase the number of classes in the system and carries the responsibility of ensuring that the original intent of that inheritance hierarchy is maintained.
  3. Composition: An alternative to sub classing, composition can be used in situations where the new functionality required can be created by arranging several pre existing figures together. e.g. A text label could be defined as a rectangle with a text object inside. To facilitate this kind of creation HotDraw provides a subclass of Figure called CompositeFigure that essentially acts as a collection of figures. Composition frees the developer from class details, can reuse existing tools and allows dynamic configuration (new arrangements of figures can be constructed while the program runs). Against it, composition doesn’t provide as much freedom as sub classing (it can only compose what is available) and it can be difficult to debug due to its dynamic nature.
  4. Custom figure: The ultimate amount of creative freedom comes from sub classing Figure or AbstractFigure. The choice of which class to choose depends on which is closest to the needs of the application. If the required Figure is very unusual then it may be required to subclass from Figure, but this should be avoided were possible due to the large number of abstract methods that require a definition. Instead it’s much more usual to subclass AbstractFigure which only requires four methods to be defined, basicMoveBy, basicDisplayBox, displayBox, and handles. This approach provides almost total control over how a figure is implemented however it comes at the cost of requiring an understanding of how the interface of Figure is used by the HotDraw framework.
Each drawing element in a HotDraw application is a subclass of Figure. Figures can be used directly or customised by sub classing or composition. In extreme cases a custom figure may be created by sub classing from the Figure class directly.

Changing drawing element attributes

There are at least three ways to edit a figure’s attributes: with a handle, via the menu bar, or with a special tool. Each technique is appropriate in different cases.

Editing a figure implies that it has been selected or is selected as a side effect of the editing process. This is important because the developer must ensure that all the edit methods below are only activated when the capability to perform that function exists. (There is no point trying to edit text on a figure with no text).

  1. Handles: All figures have a handles method that returns a vector of handles for that figure. Handles support the direct manipulation paradigm in HotDraw therefore they are best suited to coarse-grained tasks such as editing a Figure’s size, shape or position. By default Abstract Figure returns a handle (for resizing) on each corner of the shapes display box. It is common for subclasses to maintain this behaviour and to add to it appropriately.
  2. Tools: Although more frequently used to create figures, tools can be used to add new attributes to existing figures. They are well suited to more precise tasks i.e. editing text, where handles would be difficult to use.
  3. Menus: These can be very similar to tools, often the menu structure will mirror the tool palette. They are preferable for selection oriented events such as choosing the active fill colour or changing fonts.
Although many edit tasks may favour use of one of the above strategies over the others it is equally true that most edit operations can be achieved by any or all three of these techniques. i.e editing a figures colour can be done via a handle, a tool or a menu. The developer should select the approach that is correct for their application.

List the attributes of a drawing element that you want to edit. For each attribute, decide whether to edit it with a handle, an operation from the menu, or a tool, and either update the handles method in a subclass of Figure or override the createMenu or createTool methods of DrawApplication.


Making new kinds of Tools

Tools represent the modes of interaction between a user interface and a drawing. Selecting a tool from the palette lets the user manipulate figures, create new figures, or perform operations upon a figure or the entire drawing. An important part of designing an editor using HotDraw is to design the set of tools that will exist on the palette.

The createTools method in DrawApplication is passed an AWT panel as a parameter and instantiates the panel with icons for all the tools in use by the application. By default createTools only creates a SelectionTool but it is easily overridden to return all the tools required by an application. HotDraw provides support for many different types of tools there are at least three distinct categories each of which are explained below:

  1. Creation Tools: The most common of these are Creation Tools. Initially creation would appear to require a great number of tools, one for every type of figure but in actual fact there is only one called CreationTool. This is a very valuable tool because it can be parameterised to create any predefined type of figure. In other words CreationTool can be customised via its constructor to become a tool that creates ellipse figures or a tool that creates rectangle figures, etc. Any predefined Figure can be created this way. CreationTool saves the developer the effort of having to write independent but very similar tools for each type of figure that an application wishes to create.
  2. Connection Tools: Defined in an identical manner to CreationTool except that it specifically creates connections between figures. Instead of having separate tools for each type of connector this single class provides a mechanism that can create any kind of connection.
  3. ActionTools: Aside from creation and connection, tools can also be used to perform application specific actions. The Action Tool subclass provides a starting point for tools that wish to operate in this manner. This tool provides an action method that is invoked upon a mouse down event. Subclasses can override the action method to provide custom behaviour for the tool.
The createTools method of DrawApplication defines the tools that will be on the palette by returning an AWT panel that contains all the tools. Tools are typically defined as either creation, connection or action tools and there are appropriate subclasses to customise for each.


Making new kinds of handles

Handles vary in behaviour. Sometimes handles change the size of a figure, sometimes they change its colour, and sometimes they create new lines. In general, one could imagine pressing on a handle performing any kind of operation. Moreover, handles can be attached to any part of a figure, and they move when the figure moves.

Figure 2: Handles on three figures

Figure 2 shows some of the different kinds of handles in HotDraw. It has three figures in it and they have all been selected to display their handles. The first thing to notice is that handles can have different appearances, in the above diagram there are four distinct styles of handle, an empty rectangle, a white rectangle, a green rectangle and a yellow circle. The different appearances can be used to denote different behaviours i.e. in this example the empty rectangles are null handles and perform no action other than to show selection. The white rectangles are the default handles in HotDraw and provide resize functionality. The green rectangle in the top middle of the TextFigure allows the connector to be disconnected from the figure. Finally the yellow dots provide custom behaviour specific to a figure i.e. on the ElbowConnector they allow each segment of the connector to be repositioned independently while on the TextFigure the single yellow dot changes the font size of the text.

The Handle interface in HotDraw defines the important behaviours a handle must implement. Commonly developers will subclass AbstractHandle (which implements the handle interface) to provide the required functionality. To change a handle’s appearance the draw method has to be overridden. The handle can have any appearance the application requires but it should be remembered that it is good practice to keep the functionality of handles consistent with their behaviour through out an application. Positioning of a handle on a figure can be altered by sub classing the locate method. This method returns a point around which the handle will be centred. Often handles are required to be positioned at precise locations on a figure. In such circumstances the RelativeLocator class can be used inside the locate method to provide a simple way to discover the position of the centre or corner of the figure that is required.

The main behaviour of a handle is defined in three methods. They are invokeStart, invokeStep and invokeEnd. Each of these methods are called by a user initiated event, invokeStart is called whenever the user clicks the mouse down on a handle, invokeStep when ever a user drags a handle and invokeEnd when ever the user releases the mouse button. Every interaction with a handle will therefore invoke a sequence of method calls where invokeStart is called at the beginning of the interaction invokeStep optionally may be called in the middle and invokeEnd will be called when the interaction is over. This granularity across the interaction allows the developer greater control over the behaviour. i.e. if the handle has to respond to a mouse click then the behaviour has to go in either the start or end methods (step will not be called on a mouse click). Further the developer can decide whether they want the behaviour to occur as soon as the button goes down or wait until the button is released.

Several different types of handle are already predefined in HotDraw, they include ChangeConnectionHandle, ElbowHandle, LocatorHandle, and PolygonHandle. It should be noted however that because handles tend to be very specific to their intended application opportunities for reuse are quite rare. Therefore developers should expected to have to write their own handles either by implementing the Handle interface or by sub classing AbstractHandle.

Handles are used to implement the direct manipulation paradigm in HotDraw. They are iconic representations that exist on the Figure and define some form of edit behaviour. There are three methods that define the behaviour of a Handle invokeStart, invokeStep and invokeEnd.


Making new Menus

Menus contain specific categories of functionality. Menus may be used to support file operations, edit operations etc. Sometimes the default menus created by HotDraw are too general and they either allow functionality that the application shouldn’t have or overlook functionality that is required. It is therefore important to be able to customise the menus in an application.

Menus are defined in the DrawApplication class. By default HotDraw predefines a menu structure with the following menus: files, edit, debug, alignment, arrow, colour and font size. These menus can be removed or added to as appropriate in the application. More over DrawApplication defines separate create methods for each of the above menus. This does two things, first it defines this set of menus as the standard set for this domain i.e. you don’t have to use them but you probably will. Second it also allows these menus to be very easily altered because all the relevant information is localised into a single method. When adding menus developers should be aware of this structure and seek to mimic it in their extensions.

Creating the menu bar occurs in the createMenu method. This method is very simple thanks to the above design. First it creates a menu bar and then it calls each create method in turn to add that menu to the menu bar, customisation is easily achieved by omitting unrequired menus and adding in method calls to your own create methods.

The framework also defines the CommandMenu class. This class is used inside new create methods to add menu items to the menu. It allows subclasses to define what action is taken when the user selects it and also provides methods for the DrawApplication to set its enabled state depending on the state of the drawing (not all menu items are available all the time). Finally menus can be recursive so its quite possible to have a menu item that leads to a further menu.

Menus are defined in their own create method, this allows them to be easily changed and simplifies the createMenu method which only has to select which create methods to call.


Constraints

Often an attribute of one figure is a function of the attributes of other figures. For example, in the PERT chart editor of Figure 1, the duration for an event is the maximum of the ending dates of all the events that precede it, i.e. that have a connection to it. As another example, the endpoints of the lines connecting PERTevents depend on the locations of the events. Handles also depend on the figure to which they are attached.

HotDraw has a standard way of keeping track of dependencies between Figures. Objects (even other figures) that are interested in the state of a Figure implement the FigureChangeListener interface. Each Figure has a collection of such listeners (usually empty), and the addFigureChangeListener and removeFigureChangeListener methods in Figure update this collection. Whenever a figure changes state it will iterate through the collection of listening objects and inform each of them about the state change. The listener can then perform its own action to ensure that a constraint is upheld.

The FigureChangeListener describes several different methods that may be invoked upon a state change. The figureChanged method is the most general informing the listener that some part of the figure has changed state. Typically the listener requires more information than this in order to act. To provide this information a FigureChangedEvent object is passed to the listener as a parameter to the method. The Event contains a reference to the figure that the listener can use to determine if the part of the figure that it is interested in has changed. In a similar manner the FigureChangeListener can also send figureInvalidated, figureRemoved, figureRequestRemove, and figureRequestUpdate messages to the listener allowing it some granularity in choosing which change events to react to.

The framework provides a set of classes that implement the FigureChangeListener interface. The root of these classes is the interface ConnectionFigure. This and its subclasses are used to enforce binary constraints between Figures in a Drawing. For example the class LineConnection is used to connect two figures with a line. This class first registers itself with both figures. It interrogates them via the connectAt method to get connection points for the start and the end of the line and draws itself. Now if either of the figures move the line is notified and it can request that the figure send a new connection point. Further if a figure is deleted then the line will be notified and can delete itself (a connection is not allowed to be open).

Constraints are always binary i.e. one thing always depends upon another.


Creating Animation

Constraints, handles and tools let a drawing react to a user. Animation gives a drawing a life of its own. Animation requires a controlling object to direct all the figures in a drawing.

Animation is provided in HotDraw by making a subclass of Drawing that implements the Animatable interface. This interface defines one method animationStep that is called to render a single frame of animation. When Drawing is sub classed appropriately the framework will repeatedly call its animationStep method. This allows animationStep to perform incremental updates to the state of the drawing which, because of their frequency appear to the user as animation.

This type of animation requires that each figure in the drawing has some rules to govern how it is updated on each new frame. At the crudest level this can be performed directly inside Drawing where animationStep directly specifies how each figure should move. This is acceptable when we want all figures to be animated in the same way but when different subclasses of figure require individual behaviour this approach does not work very well.

An alternative is for each animating figure in a drawing to implement their own animationStep method. These methods are not called directly by the framework, instead they rely on animationStep in drawing to call them. The advantage of this approach is that it allows animation behaviour to be easily specialised in different classes. This can allow a drawing to feature some shapes that animate and some that don’t and have those that are animating act differently according to their type.

Independent figure animation can be invoked from the following code:

public void animationStep() {
    Enumeration k = figures();

    while (k.hasMoreElements()){
        Figure fig = (Figure)k.nextElement();
        if(fig instanceof Animatable){
            Animatable anim = (Animatable)fig;
            anim.animationStep();
        }
    }
}
 
Often it is desirable to have control over animation behaviour so that the user can start or stop it as appropriate. Unfortunately HotDraw does not provide explicit support for such an operation, developers wishing to create such an effect must create it for themselves.

Animate a drawing by making a subclass for it that defines the animationStep method to perform the next step in the animation. Animate a figure by defining a further animationStep method for it. Use this method to create specific animation behaviour for that figure, then call it from the drawing’s animationStep method.