"Show me your flowchart and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowchart; it'll be obvious." — Fred Brooks, The Mythical Man Month
Looking at the diagram below, the class Multivalent,
at top center, is the central point for shared state.
It holds Browsers, which correspond to top-level windows.
Each Browser holds a document tree,
with exactly one Root.
The document tree includes in one unified tree
both graphical user interface (GUI) elements
such as the menubar and toolbar (shown in the bottom half of the diagram
in the leftmost of the three rough columns),
and tree nodes that correspond to document content (middle column).
Regardless of whether the concrete document being displayed
is PDF, HTML, DVI, manual pages, scanned paper, or something else,
the document tree looks the same at this level.
All of the functionality in the system is implemented by
groups or Layers of
Behaviors (rightmost column),
which can apply to the entire
Browser if they hook on to the Root,
or document "genres" such as "HTML" and "PDF",
or specific documents by hooking onto Documents.
The diagram depicts the high level data structures;
in dynamic operation, control flow passes through the tree and
through behaviors in protocols:
restore, format, paint,
events, semantic events, and so on;
all activity pertaining to a particular function should be done
in the corresponding protocol, which is carefully sequenced
under system control so as to avoid conflicts among competing classes.
We now examine the diagram in more detail.
The class Multivalent starts up the system when invoked
by the Java Virtual Machine. It holds shared state such as
preferences (including arbitrary persisten variables, and
mappings from MIME type or file suffix to
behavior that reads that document format),
hooks to the network file cacheing,
and methods that can create a new Browser
or fetch a previously created one by name.
Any class anywhere can obtain the singleton instance of this class
with the static call Multivalent.getMultivalent().
A Browser corresponds to an independent window
that can be moved about the screen, iconified, and so on.
It holds state shared within a Browser
such as the selection and the focus subwindow.
It interfaces between the operating system and the Multivalent world:
paint requests and mouse and keyboard events initiated by the user
come through the OS to this class, which then
routes them to the appropriate protocol for passing through the
tree or behaviors.
All visual content is drawn via the document tree
with a single Root.
Tree nodes have the tree navigation facilities common to all tree packages,
such as getting a child (getChild()),
getting one's parent (getParentNode()),
getting one's name (getName()),
and so on.
The Root is special in that it is a gateway between
the document tree and the containing Browser.
As a convenience, the method getRoot() on any Node
climbs up the tree and returns the Root
(Diagram also
available in .pdf
for printing.)
The document tree contains both GUI nodes and nodes corresponding to concrete document formats. In both cases, the "structure" is represented in internal nodes, and "words" (text, image, button) in nodes at or near the leaves. In most other GUI toolkits, GUI elements are typically organized in a tree with layout widgets containing more specialized widgets as leaves. In Multivalent, which focuses on human readable documents, GUI widgets and text/image nodes are the same: a button is simply a word with a specialized function when you click on it, and widget layout is done with the same layout functions used for, say, laying out an HTML table. This has benefits in both directions: when documents are faced with, say, a HTML form, the tree is uniform, and there is no need to bridge two different systems, tree nodes and system GUI widgets. In the other direction, GUI widgets benefit from sophisticated display (buttons can display a HTML table and be controlled by stylesheets).
In the GUI subtree specifically (left column),
VMenuButton, which displays a label like "File"
or "Edit" in the menubar and when clicked
displays its associated menu, is an internal node whose
appearance is given by its subtree, which can be of arbitrary complexity,
anything from a simple ASCII text to a full HTML table to a page of PDF.
VMenuButtons can have explicit menus in the tree, but often
they generate them on demand by creating an empty menu with
a label and passing it to all the Behavior in the system
to add entries.
The subtree corresponding to the content of the concrete document
format (middle column) represents the structure of the document in
internal nodes and the words and images and shapes in leaves. For
SGML and XML the structure is identical to the parse tree, for HTML it
is the corrected parse tree with appearance tags like I, B, TT, and
EMPH separated out as Spans (see below), and for PDF and
scanned paper the only available structure is often just text regions.
The Document at the head of the subtree
represents an independent document in that it has a URI,
a stylesheet,
and, as available, attributes for author, title, and so on.
Document has a link to the Behaviors
associated with it, and in fact Root is a subclass of
Document with a link to the Behaviors
operational on all Documents.
Behavior implement all the user-level functionality
of the system. They are grouped in Layers,
and the list of Behavior in a hub is read from
a XML hub document.
System.hub, most important hub, is associated with the
Root and establishes all those Behaviors
that are always active no matter if the document displayed is HTML, PDF,
or something else.
Associated with a particular Document is a genre hub,
such as for one for HTML or scanned paper. Often genre hubs share
via inclusion other hubs; for instance, DVI and scanned paper share the
"fixed format" hub.
To read new documents, format them, paint them on the screen, and
respond to events,
the system initiates a protocol.
Depending on the protocol, the system passes control through tree
Nodes (a tree-based protocol)
or through the Behaviors in the
Root and the current Document
(a round-robin protocol).
Behaviors can also be invoked during tree-based protocols
by observing the tree at any node; when control passes
through this node in the tree walk, the observing Behavior
is notified before and after the node itself
is traversed.
An example of such a Behavior is
one that implements key bindings;
it listens for key events (java.awt.event.KeyEvent)
that matches a binding and takes action on a match,
and then has the option of short-circuiting further propagation
of the event.
A widely use Behavior type,
the Span
is often used for hyperlinks and highlight regions.
It hooks into the tree at two points
and can affect appearance and receive events
at any point inbetween, cutting across structural boundaries.
In the diagram, the generic base class Span
is used to associate a label, such as "i", "tt", or "emph" in HTML,
over some text for the stylesheet to determine its appearance.