PEG buoydesign--tjl: Buoy view (xupdf) redesign

Author: Tuomas J. Lukka
Last-Modified:2003-02-09
Revision: 1.16
Status: Incomplete

Goals: get the xupdf and pp functionality under one model.

Issues

Architecture

The abstract buoy data model

First of all, define the abstract buoyview model as follows:

peg.gen.html#BuoyviewModel BuoyviewModel

In PP, a node is a 2D canvas on which there are cells, and Anchors are zz cells and links are connections between clones of anchor cells on a particular dimension.

In xupdf, a node is a cell containing a PDF document, and the anchors and links are defined implicitly by the xanalogical transclusions and xulinks.

A PDF scrollblock, on the other hand, is very different: no cell, no cellview! The architecture needs to support all these.

peg.gen.html#BuoyviewModels BuoyviewModels

Interfaces

Now, the picture gets clearer: the whole structure of the current buoy view should be defined by a single facade:

Important Invariant (a la ZZstructure dimension): if node A, anchor A.1 shows a link X to node B anchor B.4, hen after B.setFocus(B.4), node B will show the link X as well.

gzz.view.buoy.BuoyLinkListener gzz.view.buoy.BuoyViewMainNode gzz.view.buoy.BuoyViewNodeType peg.gen.html#BuoyManagerBasic BuoyManagerBasic

The linkId passed to BuoyLinkListener must be unique for each node and the identifies the link -- it must be the same in both directions. The previous invariant in code is an invariant which these interfaces must obey:

// mainnode1's BuoyLinkListener set to l.

mainnode1.renderMain(...);
// l.link(d, *, nodetype2, L, A) got called as callback

mainnode2 = nodetype2.createMainNode(L, A, l)
mainnode2.renderMain(...);
// l.link(-d, *, nodetype1, L, B) MUST GET CALLED

Of course, if the underlying data structure is modified between the calls to renderMain, the invariant need no longer hold.

The coordsys the main view is being rendered into defines the extent by its (modified) unit square; this extent is not binding but more like a hint.

Matcher structure can separate left&right links and know which way

Now, to make things clear, the call sequence for RealBuoyViewManager is

peg.gen.html#BuoyManagerCall BuoyManagerCall

In the diagram, we first see RealBuoyViewManager render the view, calling BuoyViewMainNodeA to render the main node and getting a callback through the BuoyLinkListener interface about a link. This causes it to call BuoyViewNodeTypeB to render the buoy.

Then, the mouse click comes which takes the focus to the buoy of type B. Its node type object is called to create the new focus object. Then, the render pattern is repeated, but now with BuoyViewMainNodeB in the focus.

The semi-pluggable implementation

In this implementation of the BuoyViewMainNode and BuoyViewNodeType interfaces, the node and link types are almost pluggable. There are naturally some problems with full pluggability, due to the bidirectionality of the links: some node types will only match some other node types, etc.

As the main example, consider the above case with ZZ cell nodes, PP canvases and scrollblocks. The ZZ cell nodes and PP canvases are both in ZZstructure and use cellviews so they can be handled by the same linking managers, but the scrollblocks cannot.

The following diagram shows the current arrangement, where the pluggability is handled through the interfaces CellBuoyViewNodeType (where the concrete cbvnodetypes create their respective mainnodes) and CellBuoyViewLinker.

gzz.view.buoy.BuoyViewNodeType gzz.view.buoy.BuoyViewMainNode gzz.view.buoy.BuoyLinkListener gzz.view.buoy.BuoyAdaptor BuoyAdaptor.LinkAdaptor gzz.view.CellPlacementHook gzz.view.buoy.CellBuoyViewNodeType gzz.view.buoy.CellBuoyViewLinker peg.gen.html#SemiPluggableBuoys SemiPluggableBuoys

There are two different types of links that this part of the systme needs to know: Cell to Cell and Cell to PermaScroll. ...

In the next diagram, the classes that implement the pagespan nodes and their associations to the rest of the system are shown. The cellNodeType BuoyViewNodeType is the node type that is to be used for xanalogical links to cells.

gzz.view.buoy.CellBuoyViewLinker gzz.view.buoy.BuoyViewNodeType gzz.view.buoy.BuoyViewMainNode gzz.view.buoy.ScrollblockCellLinker peg.gen.html#PageSpanSemiPluggableBuoyNodes PageSpanSemiPluggableBuoyNodes

As seen, ScrollblockCellLinker is the class implementing CellBuoyViewLinker, and when asked to make links for a given cell, it looks for both enfiladeoverlaps (transclusions) and xu links. Different types of pagespannodetypes are used for these: for transclusions seeing the whole original pagespan scrollblock is good, and for xu links, seeing only the anchor part of the target is good.

Foo:

class PPCanvasNode
    inherit CellBuoyViewNodeType

class PPCanvasCursor
    fields
        float x, y
        float zoom
    inherit BuoyViewMainNode

dep "create" PPCanvasNode PPCanvasCursor