7 |
:Revision: $Revision$ |
:Revision: $Revision$ |
8 |
:Status: Incomplete |
:Status: Incomplete |
9 |
|
|
10 |
Goals: get the xupdf and pp functionality under one model. |
This PEG attempts to define a flexible framework for FenPDF |
11 |
|
and related designs. |
12 |
|
|
13 |
|
|
14 |
Issues |
Issues |
15 |
====== |
====== |
16 |
|
|
|
- How do we do non-regeneration of vobscenes on mouse events? |
|
|
|
|
|
RESOLVED: Pass the old VobScene to the mouse event handler method |
|
|
and use the boolean return value to determine whether |
|
|
regeneration is needed. |
|
|
|
|
|
This also fixes the idea that the *BuoyViewMainNode* is really a single |
|
|
view in a single VobScene. |
|
|
|
|
|
- Should we let keystrokes also not-regenerate the vobscene? |
|
|
|
|
17 |
- Who creates the nodes? What about when a node contains a link |
- Who creates the nodes? What about when a node contains a link |
18 |
to itself? Are all nodes really the same? |
to itself? Are all nodes really the same? |
19 |
|
|
133 |
Link.c = TransclusionLink.c + o; |
Link.c = TransclusionLink.c + o; |
134 |
|
|
135 |
|
|
136 |
Interfaces |
The Main Interfaces |
137 |
---------- |
------------------- |
138 |
|
|
139 |
Now, the picture gets clearer: the whole structure of the current buoy view |
Now, the picture gets clearer: the whole structure of the current buoy view |
140 |
should be *defined* by a single facade: |
should be *defined* by a single facade: |
158 |
methods |
methods |
159 |
void link(int dir, int anchorCS, BuoyViewNodeType otherNode, Object linkId, Object otherAnchor) |
void link(int dir, int anchorCS, BuoyViewNodeType otherNode, Object linkId, Object otherAnchor) |
160 |
|
|
161 |
|
class BuoyViewConnector "interface" |
162 |
|
jlink |
163 |
|
methods |
164 |
|
void addBuoys(VobScene, BuoyViewMainNode, BuoyLinkListener) |
165 |
|
|
166 |
class BuoyViewMainNode "interface" |
class BuoyViewMainNode "interface" |
167 |
jlink |
jlink |
168 |
fields |
fields |
179 |
BuoyViewNodeType createMainNode(Object linkId, Object anchor, BuoyLinkListener l) |
BuoyViewNodeType createMainNode(Object linkId, Object anchor, BuoyLinkListener l) |
180 |
|
|
181 |
|
|
182 |
dep "calls" BuoyViewMainNode BuoyLinkListener |
dep "calls" BuoyViewConnector BuoyLinkListener |
183 |
dep "use" RealBuoyViewManager BuoyViewNodeType |
dep "use" RealBuoyViewManager BuoyViewNodeType |
184 |
dep "use" RealBuoyViewManager BuoyViewMainNode |
dep "use" RealBuoyViewManager BuoyViewMainNode |
185 |
|
dep "use" RealBuoyViewManager BuoyViewConnector |
186 |
dep "create" BuoyViewNodeType BuoyViewMainNode |
dep "create" BuoyViewNodeType BuoyViewMainNode |
187 |
|
|
188 |
--- |
--- |
189 |
|
|
190 |
vertically(60, zap, BuoyViewMainNode, BuoyViewNodeType); |
vertically(60, zap, BuoyViewConnector, BuoyViewMainNode, BuoyViewNodeType); |
191 |
horizontally(100, foo, RealBuoyViewManager, zap); |
horizontally(100, foo, RealBuoyViewManager, zap); |
192 |
vertically(140, bar, BuoyLinkListener, RealBuoyViewManager); |
vertically(160, bar, BuoyLinkListener, RealBuoyViewManager); |
193 |
|
|
194 |
The linkId passed to BuoyLinkListener must be unique for each node |
The linkId passed to BuoyLinkListener must be unique for each node |
195 |
and the identifies the link -- it must be the same in both directions. |
and the identifies the link -- it must be the same in both directions. |
199 |
// mainnode1's BuoyLinkListener set to l. |
// mainnode1's BuoyLinkListener set to l. |
200 |
|
|
201 |
mainnode1.renderMain(...); |
mainnode1.renderMain(...); |
202 |
|
connector.addBuoys(...); |
203 |
// l.link(d, *, nodetype2, L, A) got called as callback |
// l.link(d, *, nodetype2, L, A) got called as callback |
204 |
|
|
205 |
mainnode2 = nodetype2.createMainNode(L, A, l) |
mainnode2 = nodetype2.createMainNode(L, A, l) |
206 |
mainnode2.renderMain(...); |
mainnode2.renderMain(...); |
207 |
|
connector.addBuoys(...); |
208 |
// l.link(-d, *, nodetype1, L, B) MUST GET CALLED |
// l.link(-d, *, nodetype1, L, B) MUST GET CALLED |
209 |
|
|
210 |
Of course, if the underlying |
Of course, if the underlying |
225 |
sequence CallBuoyManager |
sequence CallBuoyManager |
226 |
call RealBuoyViewManager "render" |
call RealBuoyViewManager "render" |
227 |
call BuoyViewMainNodeA "renderMain" |
call BuoyViewMainNodeA "renderMain" |
228 |
|
call BuoyViewConnector "addBuoys" |
229 |
call RealBuoyViewManager "link(NodeTypeB)" |
call RealBuoyViewManager "link(NodeTypeB)" |
230 |
call BuoyViewNodeTypeB "renderBuoy" |
call BuoyViewNodeTypeB "renderBuoy" |
231 |
call RealBuoyViewManager "mouse" |
call RealBuoyViewManager "mouse" |
232 |
call BuoyViewNodeTypeB "createMainNode" |
call BuoyViewNodeTypeB "createMainNode" |
233 |
create BuoyViewMainNodeB |
create BuoyViewMainNodeB |
234 |
call RealBuoyViewManager "render" |
call RealBuoyViewManager "render" |
235 |
call BuoyViewMainNodeB "renderMain" |
call BuoyViewMainNodeB "renderMain" |
236 |
|
call BuoyViewConnector "addBuoys" |
237 |
call RealBuoyViewManager "link(NodeTypeA)" |
call RealBuoyViewManager "link(NodeTypeA)" |
238 |
call BuoyViewNodeTypeA "renderBuoy" |
call BuoyViewNodeTypeA "renderBuoy" |
239 |
|
|
240 |
seqobject RealBuoyViewManager |
seqobject RealBuoyViewManager |
241 |
|
seqobject BuoyViewConnector |
242 |
seqobject BuoyViewNodeTypeA |
seqobject BuoyViewNodeTypeA |
243 |
seqobject BuoyViewNodeTypeB |
seqobject BuoyViewNodeTypeB |
244 |
seqobject BuoyViewMainNodeA |
seqobject BuoyViewMainNodeA |
247 |
|
|
248 |
--- |
--- |
249 |
RealBuoyViewManager.c = (0,0); |
RealBuoyViewManager.c = (0,0); |
250 |
horizontally(100, foo, RealBuoyViewManager, BuoyViewNodeTypeA, |
horizontally(20, foo, RealBuoyViewManager, BuoyViewConnector, BuoyViewNodeTypeA, |
251 |
BuoyViewMainNodeA, BuoyViewNodeTypeB, |
BuoyViewMainNodeA, BuoyViewNodeTypeB, |
252 |
BuoyViewMainNodeB.ghost); |
BuoyViewMainNodeB.ghost); |
253 |
|
|
260 |
Its node type object is called to create the new focus object. Then, the |
Its node type object is called to create the new focus object. Then, the |
261 |
render pattern is repeated, but now with BuoyViewMainNodeB in the focus. |
render pattern is repeated, but now with BuoyViewMainNodeB in the focus. |
262 |
|
|
263 |
The semi-pluggable implementation |
Varying geometries |
264 |
--------------------------------- |
------------------ |
|
|
|
|
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. |
|
|
|
|
|
.. UML:: SemiPluggableBuoys |
|
|
|
|
|
jlinkpackage org.nongnu.libvob.buoy |
|
|
|
|
|
class BuoyViewNodeType "interface" |
|
|
jlink |
|
|
|
|
|
class BuoyViewMainNode "interface" |
|
|
jlink |
|
|
|
|
|
class BuoyLinkListener "interface" |
|
|
jlink |
|
|
|
|
|
class BuoyAdaptor |
|
|
jlink |
|
|
inherit BuoyViewNodeType |
|
|
assoc multi(*) - multi(*) CellBuoyViewNodeType |
|
|
|
|
|
class BuoyAdaptor.LinkAdaptor |
|
|
jlink |
|
|
inherit gzz.view.CellPlacementHook |
|
|
assoc multi(*) - multi(1) BuoyAdaptor |
|
|
assoc multi(*) - multi(1) BuoyLinkListener |
|
|
|
|
|
class gzz.view.CellPlacementHook "interface" |
|
|
jlink |
|
|
|
|
|
class CellBuoyViewNodeType "interface" |
|
|
jlink |
|
|
methods |
|
|
boolean ownsCell(Cell c) |
|
|
void renderBuoy(VobScene vs, int into, Cell c) |
|
|
BuoyViewMainNode createMainNode(Cell c, CellPlacementHook hook) |
|
|
|
|
|
class CellBuoyViewLinker "interface" |
|
|
jlink |
|
|
methods |
|
|
void doLinks(Cell c, VobScene vs, int cs, |
|
|
BuoyViewNodeType cellNodeType, |
|
|
BuoyLinkListener l); |
|
265 |
|
|
266 |
|
It is possible (e.g., FenPDF has this) that different main nodees require |
267 |
|
different geometries for the buoys. |
268 |
|
|
269 |
|
Let's list the design pressures: |
270 |
|
|
271 |
class ConcreteNodeType "pseudo" |
- The size of the area reserved for the buoy view has to be changeable easily |
272 |
inherit CellBuoyViewNodeType |
(e.g., in FenPDF, scrolling the separator) |
|
class ConcreteMainNode "pseudo" |
|
|
inherit BuoyViewMainNode |
|
273 |
|
|
274 |
|
- The sizes and geometries should be set centrally, pluggably, not hardcoded |
275 |
|
to the different view |
276 |
|
|
277 |
dep "call" ConcreteMainNode gzz.view.CellPlacementHook |
- The geometries depend on the main node type, but not on the content (at least |
278 |
dep "call" BuoyAdaptor.LinkAdaptor CellBuoyViewLinker |
yet). |
|
dep "call" CellBuoyViewLinker BuoyLinkListener |
|
279 |
|
|
280 |
dep "create" ConcreteNodeType ConcreteMainNode |
- Different connectors should be able to have different buoy geometries (think, e.g., |
281 |
|
about normal structlink buoys in fenpdf vs. the treetime buoys) |
282 |
|
|
283 |
--- |
So, the solution is to provide the buoymanager different geometry managers, |
284 |
vertically(150, gazz, BuoyViewNodeType, BuoyViewMainNode, BuoyLinkListener); |
multiplexed between main node types and buoy types. |
285 |
vertically(60, foo, BuoyAdaptor, BuoyAdaptor.LinkAdaptor, gzz.view.CellPlacementHook); |
There are two different geometry managers, one for the main view and another |
286 |
vertically(300, cbv, CellBuoyViewNodeType, CellBuoyViewLinker); |
for the buoys. |
|
vertically(60, conc, ConcreteNodeType, ConcreteMainNode); |
|
287 |
|
|
288 |
horizontally(20, groo, gazz, foo, cbv, conc); |
Both may be called two ways: to create the coordinate systems, or just to set |
289 |
|
the changed coordinates. |
290 |
|
|
291 |
BuoyAdaptor.c = (0,0); |
Here's the geometer for the main views:: |
292 |
|
|
293 |
|
public interface BuoyMainViewGeometer { |
294 |
|
/** Create or set the main coordinate system size. |
295 |
|
* @param into The matching parent and parent, giving the rectangle into |
296 |
|
* which to place the cs. |
297 |
|
* @param key The key to use for the returned coordinate system |
298 |
|
* in into. There may be others in between. |
299 |
|
* @param create Whether to create the coordinate systems or just set parameters |
300 |
|
* in existing ones. |
301 |
|
* @return The coordinate system into which to place the main view. |
302 |
|
*/ |
303 |
|
int mainCS(int into, Object key, boolean create); |
304 |
|
} |
305 |
|
|
306 |
There are two different types of links that this part of the systme |
And here's the geometer for the buoys:: |
|
needs to know: Cell to Cell and Cell to PermaScroll. |
|
|
... |
|
307 |
|
|
308 |
In the next diagram, the classes that implement the pagespan nodes |
public interface BuoyGeometer { |
|
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. |
|
309 |
|
|
310 |
.. UML:: PageSpanSemiPluggableBuoyNodes |
/** Create any parameter coordinate systems depending on the surrounding |
311 |
|
* rectangle. |
312 |
|
* This method **may** set state inside the BuoyGeometer. |
313 |
|
* @param into The matching parent and parent, giving the rectangle in |
314 |
|
* which the whole buoyview and mainview are placed. |
315 |
|
* @param create Whether to create the coordinate systems or just set parameters |
316 |
|
* in existing ones. |
317 |
|
*/ |
318 |
|
void prepare(int into, boolean create); |
319 |
|
|
320 |
jlinkpackage org.nongnu.libvob.buoy |
/** Create or set the main coordinate system size. |
321 |
|
* @param into The matching parent and parent, giving the rectangle in |
322 |
|
* which the whole buoyview and mainview are placed. |
323 |
|
* @param anchor The coordinate system of the anchor, or -1 if not applicable. |
324 |
|
* @param key The key to use for the returned coordinate system |
325 |
|
* in into. There may be others in between. |
326 |
|
* @param w,h The size requested for the buoy. |
327 |
|
*/ |
328 |
|
int buoyCS(int into, int anchor, Object key, float w, float h); |
329 |
|
|
330 |
class CellBuoyViewLinker "interface" |
} |
|
jlink |
|
|
class BuoyViewNodeType "interface" |
|
|
jlink |
|
|
class BuoyViewMainNode "interface" |
|
|
jlink |
|
|
|
|
|
class ScrollblockCellLinker |
|
|
jlink |
|
|
inherit CellBuoyViewLinker |
|
|
assoc - multi(1) role(cellNodeType) BuoyViewNodeType |
|
|
|
|
|
awhole = assoc ScrollblockCellLinker - multi(1) role(transclusionNodeType) WholePageSpanNodeType |
|
|
aanchor = assoc ScrollblockCellLinker - multi(1) role(xulinkNodeType) AnchorPageSpanNodeType |
|
|
|
|
|
class AbstractPageSpanNodeType "pyClass" |
|
|
inherit BuoyViewNodeType |
|
|
methods |
|
|
createMainNode(linkId, anchorSpan, listener) |
|
331 |
|
|
|
class WholePageSpanNodeType "pyClass" |
|
|
inherit AbstractPageSpanNodeType |
|
|
class AnchorPageSpanNodeType "pyClass" |
|
|
inherit AbstractPageSpanNodeType |
|
|
class PageSpanMainNode "pyClass" |
|
|
inherit BuoyViewMainNode |
|
332 |
|
|
|
dep "create" AbstractPageSpanNodeType PageSpanMainNode |
|
333 |
|
|
|
--- |
|
|
|
|
|
CellBuoyViewLinker.c = (0,0); |
|
|
|
|
|
horizontally(80, inters, CellBuoyViewLinker, |
|
|
BuoyViewNodeType, BuoyViewMainNode); |
|
|
|
|
|
horizontally(220, pspnt, WholePageSpanNodeType, AnchorPageSpanNodeType); |
|
|
|
|
|
vertically(30, pspstuff, AbstractPageSpanNodeType, pspnt, PageSpanMainNode); |
|
|
|
|
|
vertically(100, topi, CellBuoyViewLinker, ScrollblockCellLinker); |
|
|
|
|
|
AbstractPageSpanNodeType.c = ScrollblockCellLinker.c + (100, -100); |
|
|
|
|
|
awhole.p = ScrollblockCellLinker.c{left} .. WholePageSpanNodeType.c; |
|
|
aanchor.p = ScrollblockCellLinker.c{right} .. AnchorPageSpanNodeType.c; |
|
|
|
|
|
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 |
|
334 |
|
|
|
dep "create" PPCanvasNode PPCanvasCursor |
|
335 |
|
|
336 |
|
.. :vim set syntax=text: |