Rob Kremer, kremer@cpsc.ucalgary.ca

CHAPTER 4

IMPLEMENTATION


This chapter briefly describes the current implementation of Accord and HyperC, primarily with respect to HyperC's class structure. The description includes references back to the design requirements in the pervious chapter. This chapter also describes Accord's user interface.

The application is named "Accord". The supporting class libraries are designed to be more general than needed for this one application and are collectively referred to by the name "HyperC". HyperC contains a database library, a node window implementation library, and a graphics library.

Accord and HyperC were implemented on the IBM PC and compatible machines in the Microsoft Windows 3.1 environment. It was implemented using Borland C++ 3.1 with Application Frameworks, a class library supporting windows and related objects.

While not all requirement levels are implemented at this point, all level 1 requirements have been implemented. HyperC implements the hypermedia database by utilizing the file system and streamable objects. The distributed nature of the database is achieved by utilizing network file servers since communication between remote processes has not yet been implemented.

Accord and HyperC were developed over a ten month period, including design, implementation, testing, debugging, and learning the Microsoft Windows system. The Accord application is about 600 lines of code, while the HyperC library is about 12,000 lines of code. The largest part of the time was taken by iterative design and testing of the practicality of ideas in the context of development environment.

The development method was iterative prototyping. That is, the system was original conceived in a "sketch" form which only outlined the major subsystems, such as the database, nodes, persistent references and node windows. Relationships between these subsystems (which all mapped onto classes) where defined. Next, "dummy" implementations where written to create a runnable (but not functional) system. As each of the subsystems were gradually refined, their function and relationships could be confirmed or re-worked. Much of the design and code was liberally thrown out when strategies did not pan out. In this way, working models were created very early in the development period, which allowed for very early informal useability testing.

Class Libraries

HyperC consists primarily of a set of class libraries which are accessed by an outer interface, or application window. In the case of the present implementation, the application window is an MDI (Multiple Document Interface) window, which is a standard window type under Microsoft Windows. It consists of a window frame containing an arbitrary number of overlapping child windows and an application-wide menu bar.

Figure 1 outlines a simplified application structure with the application window shown at the top. The application window calls on the HyperC database class library and the HyperC node window implementation class library for the actual functionality of the application in response to menu commands from its menu bar. The HyperC database class library implements all hypermedia database functions, but does not contain any visual representations for the objects. The HyperC node windows implementation class library is responsible for providing a visual window interface for the node objects as well as for various objects that might be contained within the nodes such as "glyph" (iconic) representations for other nodes and links. The HyperC graphics class library provides some basic object oriented graphics building blocks beyond what is available in Microsoft Windows, such as object-anchored arcs and labeled shapes. The OWL (Object Windows Library) class library is commercially available from Borland and provides a C++ class interface to Microsoft Windows objects.


Figure 1: A simplified view of the Accord and HyperC application structure

Hypermedia Database Class Library

To minimize development effort, the hyperbase is based on object persistence. The Borland OWL library provided the basis for this implementation of object persistence, but some debugging, type extensions, and an exception handling implementation were required. The persistent method used is streamable objects, or object I/O. Streamable objects are implemented by requiring each streamable class to define a read and a write function which is responsible for reading and writing its data from and to a stream respectively. A persistence stream is a specialization of ordinary stream classes that handles some additional housekeeping details such as keeping a database of pointers so that two pointers will reference the same object instead of two identical copies of the object. The streamable object implementation has the additional advantage of allowing simple, consistent object communication between processes and over a network or data line.

In order to fulfill the "readable old data" requirement, persistent objects' normal persistent read() and write() functions were extended to allow class versioning. That is, write() functions write out a class static version number to the stream before writing any of the data. The read() functions can use this version number to recognize older versions and convert the data accordingly -- for example, by filling in default values to data members that had been added since the old version.

The class library for the hypermedia database consists of the classes shown in figure 2. Note that only the important relationships are drawn. The following sections describe the various classes.


Figure 2: The classes in the HyperC database class library

Class Node

Class Node is the interface to a hypermedia node. It has some subtype of the generic window class, TWindow, associated with it as its physical interface element. It is responsible for maintaining data about its persistent reference, its name, and the content type. The name and content type are user editable via a dialog box. The Node class fulfills the "node content type extension" requirement and level 1 of the "node content type" requirement.

The Link Classes

The link classes are Link, DoubleLink, and ListOfLinks. Link is the basic link implementation and maintains information about the link type, the direction of the link, and its reference and referent nodes. Link has no interface element (aside from an editing dialog box). DoubleLink is a specialization of Link that is aware of its counterpart DoubleLink associated with its referent node. ListOfLinks is a container in which all of a node's links are placed for storage or retrieval in the persistent system. The Link class fulfills level 1 of the "one-way/two-way links" requirement, while the DoubleLink class fulfills level 2. The Link class also fulfills the "link type extension" requirement, the "link anchoring" requirement, and level 1 of the "link type" requirement.

The Reference Classes

The reference classes are solely responsible for storage and retrieval of nodes and their links. This allows the actual implementation of the database (an important efficiency consideration) to change without affecting the rest of the implementation -- one need only replace the two classes with alternate implementations that have the same interface. In this implementation, nodes are stored one per file; each node also has a separate file containing its links (if it has any). Detailed lock information is also stored in a separate file.

The reference classes are NodeRef and DB. Although the class DB is visible in the library, most applications need not use it since its functionality is accessed via the NodeRef class. The DB class implements a hypermedia database, which, in this implementation, is a directory containing node files, link files, and some dictionary files.

A NodeRef object is the exclusive reference to a node and all its links, and fulfills the "persistent reference" requirement. The NodeRef class is responsible for translating a reference to a Node object, a Link object, or a ListOfLinks object, as well as handling storage and retrieval of these objects. NodeRef is by far the most complex class in the library: It is essentially a dynamic type, changing state automatically between indirect reference, direct reference, local reference, and invalid reference. This complexity is necessary to fulfill the "no central server" requirement as well as the "hyperbase division" requirement.


Figure 3: Reference translation

The scheme to translate from an indirect node reference to an object is given in figure 3. The translation proceeds as follows. An indirect reference is translated to a direct reference using the database it is contained in as a context -- the database contains a dictionary of "virtual" to "physical" database names, where physical database names contain both a network node name (a computer) and a database name that is local to that network node. A direct reference can only be translated to a local reference if the host computer is the one specified in the physical database name, otherwise a request is forwarded to the specified computer, which should return the target object. A local reference uses the database dictionary to produce the local filename, and finally, the object can be instantiated from the file using the persistent system.

Lock management is also a responsibility of the NodeRef class. Although full remote messaging over the network has not yet been implemented, lock management is required since HyperC databases are spread throughout the network on file servers. Thus, multiple users normally share the hyperspace. Currently, node locking is done on a one writer, many reader basis. Locks are automatically downgraded from writer to reader if a write lock cannot be achieved. External locking is not allowed on links: Clients must do all link operations on an atomic basis. The reason for the different locking schemes is that nodes are large, complex objects which users spend comparatively long times studying and privately modifying, while links are very small, simple objects that are edited in only very short time intervals (link editing being confined to creation, type changes, and deletion). It is possible for users to overwrite one another's link edits, but these collisions are perceived to be extremely rare, and of very low cost to the user.

Given this locking scheme, level 1 of the "node sharing" requirement is fulfilled, but levels 2 and 3 are not yet implemented. Level 1 of the "easy sharing" requirement is also fulfilled.

The Parameter Classes

The parameter classes are HyperC and ID. Parameter class objects merely contain parametric information used by other classes within the database library. ID objects contain user information such as the user ID, the application name, and the computer's network name. HyperC objects contain an ID object, fonts, user preferences, and information about the location of initialization and data files.

Graphics Class Library

The graphics class library is shown in figure 4. The graphics library is a general purpose library of graphics objects that includes objects of slightly higher order than is available in the Windows graphics routines. All the graphics objects have a parent window that must be a subtype of the GraphicsWindow class (included in the library). GraphicsWindow keeps track of all the contained graphics objects in two lists: one each for static graphics and sensitive graphics.


Figure 4: The graphics class library

Class Graphic is the base class of all graphics. Under graphics are two groups of classes. VisualGraphic classes (Line and Shape) have visual representations, while BehaviouralGraphic classes (GRelation, RelationableGraphic and SensitiveGraphic) do not have a visual representation but do implement important behaviour such as pointer sensitivity or "relationability". Behavioural graphics objects all contain pointers to visual graphics objects, which act as their interface element. For example, the objects of class GNode (behavioural) have a pointer to an object of class Shape (visual). A GNode (being a SensitiveGraphic) can receive notification that the mouse has been clicked at a certain point, but it must ask the Shape object if this point is within its bounds; if the Shape object replies that it is, the GNode (being a SensitiveGraphic) must decide what to do. The behavioural/visual split also simplifies operations like changing an object's shape from a ellipse to a rectangle, since the behavioural object's pointer need only be reassigned.


Figure 5: An "ideal" form for the graphics class hierarchy

The class hierarchy may seem a little complex, and it is more complex than necessary. The problem lies in the fact that the C++ compiler used does not properly handle virtual base classes. Thus, it is not possible (in this implementation) to have GNode multiply inherit from both RelationableGraphic and SensitiveGraphic (which should both directly inherit from BehaviouralGraphic) -- see figure 5. Furthermore, one should think of a graphics object as inheriting from one VisualGraphic class and zero or more BehaviouralGraphic classes. However, if the library were implemented this way it would have to contain many more classes (one for each combination) instead of a limited number of BehaviouralClass combinations with pointers to objects from a limited number of VisualGraphic classes. The ideal hierarchy would also make the users' need to change the visual look (surround type) of GNode more difficult to program.

An important concept encapsulated by the graphics library is binary relations. The RelationableGraphic class captures the concept of an object that can participate in a binary relationship (by maintaining a list of pointers to objects of class Relation). The Relation class captures the concept of a binary relationship between two RelationableGraphic objects (by maintaining pointers to these two objects). Class Relation is a behavioural class and maintains a Line class object as its visual interface. In this way, lines or arrows can be easily anchored to other graphics objects so that they will move whenever the anchor objects move.

The printing utility classes, TPrintout, TPrinter, and TPrinterSetupDlg merely assist in printing from the windows environment.

Node Window Class Library

The node window class library is responsible for the interface elements of a node -- its window. There are three window types, all in a single inheritance line: ViewNode, PosterBoard, and WhiteBoard (see Figure 5). Only WhiteBoard is normally used by applications. The other two classes merely represent incremental development toward the WhiteBoard and are maintained as separate classes primarily for program maintenance considerations. As is obvious from the diagram, the node window class library makes heavy use of the graphic class library as the basis for its interface elements.


Figure 5: The node window class library

The ViewNode class is responsible for concept maps and their manipulation. It uses NodeGNode and LinkGNode to represent nodes and link labels respectively. Class NodeGNode is a specialization of the graphics library's GNode class and so fulfills both level 1 and 2 of the "node sensitivity in concept maps" requirement. LinkGNode is also a specialization of class GNode and represents link labels while the link arcs are objects of the graphics library's GRelation class (not shown in the diagram). These together represent links in the concept maps and fulfill levels 1 and 2 of the "link sensitivity in concept maps" requirement. Both NodeGNode and LinkGNode maintain references to their represented hypermedia objects (nodes and links, respectively). They also add their own popup menus to the interface element to allow the user to select appropriate operations. The various menu commands allow editing (creating, modifying, and deleting) elements of both the concept map display and the underlying hypermedia database. Shortcut keys to the menu commands are also provided. The ViewNode class fulfills the "contents of a generic view" requirement. While database views have not yet been implemented, class ViewNode will form a base class of the database view class to fulfill the "contents of a database view" requirement.

The PosterBoard class is a specialization of ViewNode that adds annotation box objects, fulfilling the "annotations" requirement. Annotation box objects are confined to the scope of the node, and are not visible from outside the node. Annotation classes include class TextBox and class OLEBox. A TextBox is a simple box containing editable text. An OLEBox is an implementation using Microsoft's OLE (Object Linking and Embedding) to embed data from other applications in the box with the ability to evoke the other application for editing or "playing". This allows arbitrary annotation using pictures, graphics, sound, and video, depending on the locally available software and hardware. Embedded objects are quite arbitrary and may include word processor documents, spreadsheets, or any other application that complies to the OLE server standard. The OLE system is capable of displaying the visual representation of objects, even though the requisite hardware or software is not available; this fulfills the "minimum hardware/maximum function" requirement at both level 1 and 2.

The WhiteBoard class has not been implemented yet, but will add to the PosterBoard class standard drawing tools to enable sketching on the background of a node (another form of annotation).

Accord Shell

The class libraries have been used to implement a general interface for Accord. The interface is a Microsoft Windows standard MDI (Multiple Document Interface) application, which provides for a single application window enclosing several child windows (node windows) that can be iconified, maximized, moved, sized, tiled or cascaded. This fulfills the "multiple concurrent visible nodes" requirement and the "easy node arrangement" requirement. Commands are entered via a bar menu as well as "hot keys" (object-local popup menus and direct manipulation are available within nodes).


Figure 6: The Accord MDI interface

Figure 6 shows a screen dump of an Accord session. There are three overlapped nodes displayed showing three different concept maps. The user has clicked on the menu bar to show the pulldown menu for the Node menu item. The first node was displayed by using the Node|Open menu command to produce a node selection dialog box. The other two nodes where displayed by following the hyperlinks (double clicking) from glyphs in the concept map of the first node.

Module Structure

The current implementation of Accord has two separate run time modules: one executable file and a DLL (Dynamic Link Library). The DLL contains only the classes from the hypermedia database class library, and acts as a server to the hypermedia database by virtue of being the shared code used by all applications that need to use the database. The DLL maintains its own data space, but no stack or execution thread. The current executable consists of the basic Accord shell, as well as its own copy of the code from all the other libraries linked together. These all exist in a single module to permit sharing of a executable-global HyperC object, which is used for identification and parameter customization when communicating with the hypermedia database DLL. The graphics class library could easily be removed into a separate DLL since it does not make use of the global HyperC object.

Human/Computer Interface Considerations

This section addresses the human/computer interface issues of Accord and HyperC and the solutions and philosophy used in this implementation. It describes the actual user interface and serves to fill out the rather abstract information in the preceding sections.

The general philosophy is that Accord and HyperC should follow as closely as possible the interface "flavour" of the host operating system. This is chosen on the grounds that most users will have had experience with the host operating system (Microsoft Windows) and therefore will understand and expect its "normal" behaviour. For this reason, even if the HCI solutions chosen by the host operating system are not optimal, the host's solutions will likely be a better choice for Accord and HyperC than the optimal. This philosophy will cause some problems if Accord and HyperC are ported to other environments (since each platform must have a different "feel" to match the host operating system), but this is minor compared to the problems that will be encountered with differences in the programming interface in the various windowing environments.

As seen in figure 6, Accord adopts the MDI (Multiple Document Interface) structure as do most of the major Microsoft Windows applications (Microsoft Word, Microsoft Excel, Borland C++ API, etc.). The MDI is a single window frame containing a single menu bar and an arbitrary number of child (document) windows. From the outside, the MDI frame is an ordinary Windows overlapped window. Internally, the MDI frame is a Mac-like environment with many "applications" sharing a single message bar. The MDI is a good match for Accord as each hypermedia node display corresponds to a child document.

Consistent with the MDI model, Accord's interface makes use of menus and direct manipulation, but these are optionally supplemented with "hot keys" and button bars.

Menus

The Accord MDI bar menu is kept as standard as possible.

File Window DataBase Node Options Help

The File, Window, Options, and Help commands are standard to most applications, while the DataBase and Node commands are unique to Accord. The DataBase command shows a pulldown menu of the subcommands New (create a new, empty database), Show DataBases (bring up a dialog box showing reachable databases with subcommands to make one the current database and to delete a database), and Copy DataBases (copy, import, export, and register databases).

File Window DataBase Node Options Help
New...

Show DataBases...

Copy DataBases...

The Node command shows a pulldown menu containing all the node subcommands.

File Window DataBase Node Options Help
Open...

New...

Delete...

Attributes Ctl+A

Save Ctl+S

Delete

Verify Ctl+V

Colors Ctl+C

Zoom Clt+Z

Arrange Glyphs

The three commands above the separator line, Open..., New..., and Delete..., all manipulate nodes independently of the current context. The seven commands below the separator line all act on the current (uppermost displayed) node window. They are all grayed if there is no displayed node.

Note that these last seven commands act on the current node, not within the current node. Commands that manipulate the contents of the a node are affected by context-sensitive popup menus within the node itself. All these popup menus are accessed via the right mouse button while the pointer is over the relevant display object. The background popup (the one shown when the user right clicks on the background of a node display) allows for creating new node glyphs (either by showing an existing node or creating a new one) at the position where the mouse was clicked. The popup menus of concept map node glyphs and link labels are more elaborate, allowing for both manipulation of the concept map and manipulation of the underlying hyperbase. For example, the popup menu for concept node glyphs is as follows:

Expand Links

Collapse Links

Link To Shift+Left

Type Only

1 Level Dbl+Left

n Levels

Show Node Shift+Dbl+Left

Attributes... Ctl+Dbl+Left

Hide Node Glyph

Delete Node

Verify

The popup menu for concept map link labels is as follows:

Expand Links 1 Level Dbl+Left

n Levels

Hide Links

Delete Links

Rename Links Ctl-Left

Link To Shift-Left

Most of the popup menu command functions are obvious, however there is possible confusion over the commands that manipulate the view and those that manipulate the hyperspace. The only operations that cause such confusion are the creation and deletion operations since the view is constrained to always reflect a subset of the hyperspace. View manipulations are distinguished from hyperspace manipulations by using Open (as opposed to New) commands for creation and Hide (as opposed to Delete) for deletion. Whether this is sufficiently clear to the typical user is open to study.

All menus also list "hot key" equivalents where they are available.

Direct Manipulation

While menus are used extensively to access nodes and databases, when an object is visible (in a node display, for instance) the interface is based on direct manipulation principles wherever possible. That is, the user is expected to use the mouse to select, drag, and draw objects. See table 1 for a listing of the direct manipulation mouse commands used in concept maps. All of these commands are based on mouse keys which may be qualified by the shift and control keys. All of them (except the Move and Show Menu commands) are also available via the object menus, which is especially helpful for novice users (who will be reminded of the direct manipulation commands by the menu text).

selectleft click
multiple selectshift-left click OR drag select box around objects
movedrag with the left mouse key down
multiple movedrag a (multiply) selected object with the left mouse key
expand linksdouble-right click
open the referenced nodeshift-double-right click (nodes only)
edit the node/link attributescontrol-double-right click
create linkdraw from source to destination with shift-left mouse key
show menuleft click

Table 1: Direct manipulation commands for concept maps

The direct manipulation commands have non-textual parameters which are implicit in the interface operation. For example, Move has the parameters object and coordinate, and these are implicitly defined by the top object at the coordinate at the start (key down) position and the coordinate of the end (key up) position. The exception to this rule is the Create Link command, which requires a link name parameter (aside from the implicit source and destination parameters). The problem is solved in three ways:

1. naming the link "Undefined" and showing the label as a small box

2. naming the link with the last name used

3. popping up a small dialog box to query the user for a name

The user may choose the appropriate behaviour via a control panel available under the "Options" selection of the bar menu. To date, most users seem to be most satisfied with the second option, although the others are used on occasion, depending on the task.

Summary

This chapter has briefly described the Accord and HyperC implementation with respect to the design requirements of chapter 3. The three class libraries are the hypermedia database library, the node window library and the graphic library. These libraries are all used to produce the Accord application that runs as a Microsoft Windows MDI (Multiple Document Interface) standard application. Accord's interface makes use of both menu and direct manipulation paradigms.

Rob Kremer, kremer@cpsc.ucalgary.ca