Developer Notes

6. Annotation/Reference area classes

An annotation or reference area is characteristic of Pliny's user interface. This section provides a brief overview of the relevant classes that make the annotation/reference area work.

The first thing to realise about the annotation/reference area is that it is implemented in Eclipse's GEF framework which is a set of classes specifically designed to support the kinds of manipulation of schematic objects in a 2D space that Pliny exhibits. If you have not yet read about GEF this is a good time to go and do so! Some pointers are provided in the section a Little Reading.

GEF promotes the MVC (Model-View-Controller) paradigm for design of application classes:

  • Model: The application manipulates data that is stored in the data model. In Pliny the data model are the classes in the package uk.ac.kcl.cch.jb.pliny.model. There is more about the Pliny data model in the section the Pliny Data Model.
  • View: The application shows relevant data from the Model on the screen using instance of "View" classes. In GEF these classes must be instances of GEF's draw2d objects. Pliny View objects are packaged in uk.ac.kcl.cch.jb.pliny.figures.
  • Controller: The Controller object connects model objects to view objects and manages user interaction. In GEF, controllers are called EditParts, and Pliny standard EditParts are in package uk.ac.kcl.cch.jb.pliny.parts. There will be, in general, one controller object for each model item the editor is supposed to display, and there is one draw2d figure that corresponds to that object. The model object doesn't know about its view object or its controller, but it is a PropertyChangeObject, and uses this mechanism to announces any changes that happen to it. The controller has links to both the model object it operates for, and the view object it manages, and therefore acts as a kind of middleman for all operations the user requests. Since the controller needs to know about changes in the model so that it can keep its figures uptodate to reflect these changes, it sets itself up to listen to the changes its model item announces, so that it can make whatever changes are needed as they occur.

    GEF code manages much of the mouse-based interaction on screen objects (such as dragging out items, or moving them around on the screen). In a GEF application, if the user requests something of this kind to be done to a view object on the screen, GEF askes the corresponding controller for permission to do it, and if it can be, will invoke code to make it happen. The code to check to see if a particular user interact can result in changes in the data is done by means of what GEF calls a policy. Policies in GEF are attached to GEF EditParts. Pliny's policies are in uk.ac.kcl.cch.jb.pliny.policies. Policies are attached to a particular EditPart instance when GEF invokes the EditPart's createEditPolicies() method, and both control what kinds of interactions its object supports, and what happens when the user does that operation.

    .

    EditPolicy classes, then, define what is to happen when a user does some sort of operation on the corresponding draw2d figuure. If a user action to an object on the screen is meant to result in changes in the data, then that change is carried out in GEF through the execution of some Pliny code which is an extension of the GEF command class. The job of the policy code, then, is to specify which command is to be done when then user does something on the screen. As is mentioned elsewhere, GEF's command model supports undo and redo, and hence is used in non-GEF parts of Pliny as well where support for undoing is desirable. Pliny's commands are in uk.ac.kcl.cch.jb.pliny.commands

    It is important to understand that the code in a comment only works at the model level. For example, all a command does to delete an object that appears on the screen is delete the corresponding model object. Changes to the screen that result when the user does something on the screen are triggered, then, by changes (via a command) to the underlying model: because GEF Editparts listen to their model elements and, when model data changes, respond by invoking code that will change the display to keep things synchronised with the changing model data.

When you are new to GEF it is sometimes hard to see how the links between model, view, controller, policies and commands causes data and display to change when the user does something on the screen. What happens is:

  • When the user does something on the screen (say, select a graphical object, and push the delete key) this request to delete is passed to the GEF EditPart that is managing interactions for the object that the user has asked to have deleted.
  • The part's code will check its policies to find out if deleting is permitted, and if so, what command should be executed to do the deletion.
  • If the policy permits, GEF will execute the part of the chosen command that deletes the material from the data model. The command causes the data model to be updated by deleting data it stores about the deleted object. Now the screen needs to be updated to show the deletion.
  • EditParts, as they are set up, listen for changes in the data model that interest them. If the user has deleted, say, a reference object, then the edit part that corresponds to the area where the reference object is displayed will be listening to the model for news about when its children reference objects are deleted or added. Thus, when the deletion happens, the area EditPart will be notified that one of its children has been deleted from the model. The code provided in the EditPart will, as a result, cause its children items from the data model to be redrawn -- resulting in the object disappearing from the screen, since the command to delete will have deleted the object from t he model, and hence the deleted model object is no longer there.

Note the reference to children of an EditPart in the previous paragraph. As well as the MVC paradigm, GEF promotes an hierarchical view of the screen that it contains. From both the Model and Controller perspective they are viewed as having children:

  • for the model perspective within Pliny a resource has a reference/annotation area, and its children are reference objects (LinkableObjects), and its children is either a text for a note content or another reference/annotation area -- which provides a recursive nature to the display.
  • there is a parallel hierarchy in the controllers -- the controller for the master reference/annotation area has controller children that manager the reference objects, and the children's children manage the content displayed in the reference objects.

Building the GEF-managed frame, and the PlinyGEFEditFactory

As you can see by now, there is a more-or-less one-to-one relationship between model elements to be displayed on the screen, draw2d figures and controllers to co-ordinate actions between them. How then does, GEF know what kind of controller and figure belongs to each model item it needs to show?

  • As GEF is given each model element to display it first needs to create a corresponding controller element. Since different classes of model elements need different controllers it has to be told what kind of controller to create for each model element it is given. In GEF, this is the role of an object called a EditPartFactory. In Pliny a base version of this factory is called uk.ac.kcl.cch.jb.pliny.factories.PlinyGEFEditFactory, and it can, if necessary be subclassed by other plugins to provide refinements in its operation. In it is the method createEditPart which GEF calls each time it needs a new EditPart to correspond to a model part it has been given, and this method must return a corresponding instantiated EditPart/controller.
  • Once GEF has the EditPart that will act as the controller for the particular model object it relies on the EditPart to create the apprpriate draw2d figure, which the EditPart will create when its createFigure() method is called.

Here are a few more words about the PlinyGEFEditFactory's createEditPart method.

  • The signature for this method is
    public EditPart createEditPart(EditPart context, Object model)

    As we must said above, this method -- which does the real work of the class -- is called by GEF each time it has a new model element it needs to display. The method is passed two pieces of data by GEF. The second parameter (model) is the model object for which the controller EditPart is to be created. GEF will call this method for each model part it finds. The first parameter (context) is the parent EditPart in which the model object is to be displayed. By providing this context element the code is able to generate different EditParts depending upon the context in which it is invoked.

  • When the context doesn't matter the process is really very simple, and most of the codein PlinyGEFEditFactory simply determine the class of the model and generates a new corresponding EditPart. Here is a fragement of code:
    		if(model instanceof LinkableObject)
    			part = new LinkableObjectPart((LinkableObject)model);
    

    (part is subsequently returned to the calling part of GEF as the result) As you can see, the code fragment shown here checks to see if the model class it is given is a uk.ac.kcl.cch.jb.pliny.model.LinkableObject. If it is it creates a new corresponding EditPart uk.ac.kcl.cch.jb.pliny.parts.LinkableObjectPart and this newly created EditPart is given its corresponding model element as a parameter in its constructor.

In the following sections we look at the MVC classes associated with the reference/annotation area. The approach is somewhat hierarchical (reflecting the hierarchical nature of the display itself), starting with the entire Annotation Area and going down into its components.

Classes for the Reference or Annotation Area

Pliny's annotation area is a 2D space managed by GEF. Each Resource has some sort of reference/annotation area associated with it.

  • The Annotation/reference Area's model class is, then the Pliny data model's uk.ac.kcl.cch.jb.pliny.model.Resource class.
  • The Annotation/Reference area's view class is a draw2d figure upon which GEF can layout its data. For Pliny this is one of several different classes:

    Although these different figure classes have slightly different jobs to do they are all extensions of draw2d's ScrollPane figure which means that they provide an scollable area -- the reference/annotation area upon which their data can be shown.

  • The Controller class for the annotation area has to manage the display of the reference objects and links that it contains as children. Again, the class to use differs depending upon the type of resource:

Classes for the Reference Object

A Pliny reference/annotation area can hold reference objects. The MVC classes for these objects are:

  • The Model class for a reference object is the Pliny data model class uk.ac.kcl.cch.jb.pliny.model.LinkableObject. Position and size information for the object is stored in here (and page on which it appears for PDF resources). The particular reference area it belongs to is stored in LinkableObject's displayIn item as a link to the owning Resource. The particular Resource the reference object refers to is stored in the LinkableObject's surrogateFor item.

    Recall that the user can edit the "name" associated with a reference object by double-clicking on it. What really happens is that the editing is pushed through to the name of the resource which is the surrogateFor for this LinkableObject.

  • The View class is an instance of the class uk.ac.kcl.cch.jb.pliny.figures.LinkableObjectFigure. This draw2d figure displays the top title area by placing a component figuure uk.ac.kcl.cch.jb.pliny.figures.TopPanel which takes care of displaying the surrogate's title and providing the various buttons and icons that decorate this title area.
  • The Controller class for each reference object is an instance of the GEF edit-part class uk.ac.kcl.cch.jb.pliny.parts.LinkableObjectPart for reference objects to reference areas in Notes and web pages (which are not scaleable), or uk.ac.kcl.cch.jb.pliny.parts.ScalableLinkableObjectPart for reference objects in Image and PDF annotation areas (which are).

Classes for Anchors

Anchors appear in Image and PDF annotation areas as boxes which identify areas of the underlying image/page. The classes for anchors are:

  • The Model class for an anchor is uk.ac.kcl.cch.jb.pliny.model.LinkableObject (the same as for a reference object), but one without a surrogateFor item. It must, of course, have a displayedIn to show who owns it, and information to place it properly (with page on which it appears for PDF resources).
  • The View class for an anchor is simply a generic draw2d Label class with a border displayed. There is no Pliny-specific class for it.
  • The Controller class for an anchor is uk.ac.kcl.cch.jb.pliny.parts.ScalableAnchorPart

Content area of a Reference Object

We have described above the figure involved in defining the area for the reference object, and defining its top title area, but we haven't yet talked about its content area. What happens in the content area depends is one of three possibilities:

  • For some resources acting as surrogates for a reference object, the resource itself provides a figure to use as content (a draw2d figure, and for an Image and PDF Resource it is a thumbnail image). In this case there are no GEF view objects or controllers, the reference object's figure includes the content figure for display in its content area.
  • For Note resources acting as surrogates for the a reference object the textual content of the Note can (and usually is) the thing being displayed. The MVC structure in this instance is described in the section "Content area: Note textual content".
  • Alternatively, the content area may be displaying the reference area for the reference object's resource.

Content area: Note textual content

When the content area displays the textual content of a note there are two levels of MVC classes involved -- a holder for the content and the content itself.

At the holder level the MVC classes are:

The only child of the holder level is the Note itself whose text is to be displayed, thus at the content level the MVC classes are:

Content area: reference area display

When the content area is displaying the reference area for its reference object's Resource the structure takes on a recursive character.

  • the Model class is uk.ac.kcl.cch.jb.pliny.model.MapContentHolder. Like the model class TextContentHolder, this class is not a member of the Pliny persisted data model classes and is defined to facilitate the interactions with GEF.
  • the View class is uk.ac.kcl.cch.jb.pliny.figures.MapContentFigure which provides a scrollable content area and configures it for display of a 2D-oriented reference area, similar to the the parent reference area itself.
  • the Controller class is uk.ac.kcl.cch.jb.pliny.parts.MapContentHolderPart. The children of this class are reference objects, so the recursion mentioned above happens here -- with children parts being modelled using those classes defined in the section Classes for the Reference Object (above).

Connectors

A Pliny diagram can also contain connector lines between reference areas. GEF supports line drawing between objects, and requires that the objects that can act as sources or targets for the line must be defined as GEF Nodes. The MVC classes for the links themselves are:


John Bradley
Center for Computing in the Humanities
King's College London