|
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.
Classes for the Reference Object
A Pliny reference/annotation area can hold reference objects. The
MVC classes for these objects 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
|