TiogaItemClass.mesa; Written by Scott McGregor. May 1983
Edited by McGregor. September 1, 1983 4:12 pm
DIRECTORY
Atom USING [PropList],
Graphics USING [Context],
TIPUser USING [TIPTable],
TiogaLooks USING [Looks, noLooks],
TiogaNode;
TiogaItemClass: CEDAR DEFINITIONS = BEGIN OPEN TiogaNode;
Item Classes
ItemClass: TYPE = REF ItemClassRec;
ItemClassRec: TYPE = RECORD [
length: ItemLengthProc ← NIL,
Returns the maximum node offset plus one for an item.
notify: ItemNotifyProc ← NIL,
All mouse and keyboard input is passed to the item implementor in the form of a list of REF ANY generated either by the item class' TIPTable or by the Tioga selection TIPTable.
edit: ItemEditProc ← NIL,
The ItemNotifyProc accepts user interface operations, whereas the ItemEditProc accepts direct edit operations, where all of the parameters are tightly bound.
compose: ItemComposeProc ← NIL,
Format the node contents into boxes and separators.
display: ItemDisplayProc ← NIL,
Display composed contents.
incrDisplay: ItemIncrementalDisplayProc ← NIL,
Attempt an efficient display updatefor minor edits (classes should not implement this interface without providing the more general ItemDisplayProc interface as well).
cachedDisplayTable: ItemCachedDisplayTableProc ← DefaultItemCachedDisplayTableProc,
For children to notify parent that displayed data may have become invalid.
setSelection: ItemSetSelectionProc ← NIL,
Called in order to force selection to a particular item. This will typically be called by a child item when expanding the selection in the Tioga document tree.
get: ItemGetProc ← NIL,
Fetch the contents of an item.
set: ItemSetProc ← NIL,
Set new contents for an item.
copy: ItemCopyProc ← NIL,
Copy the relevent data from one item to another.
init: ItemInitProc ← NIL,
Called first thing on node creation.
destroy: ItemDestroyProc ← NIL,
Notification to the implementor that the item is being removed from the document tree.
tipTable: TIPUser.TIPTable ← NIL,
Item specific user input.
flavor: ItemFlavor ← NIL,
Each item class has a unique name to distinguish it from other implementations.
props: Atom.PropList ← NIL
Implementor private class operations, data, etc.
];
ItemFlavor: TYPE = ATOM ;
Item: TYPE = RefItemNode ;
defaultTextClassID: ItemClassID = TiogaNode.defaultTextClassID;
invalidItemID: ItemClassID = TiogaNode.invalidItemClassID;
----------
ItemLengthProc: TYPE = PROC [self: Item] RETURNS [length: Offset] ;
Returns number of distinguishable positions within a node (length = 0 implies empty node).
----------
----------
ItemNotifyProc: TYPE = PROC [self: Item, events: LIST OF REF ANY] ;
Passed a list of event notifications from either the item class' TIPTable or the Tioga system TIPTable.
----------
----------
ItemEditProc: TYPE = PROC [self: Item, edit: EditRecord] ;
Direct access to the editing routines for a node class. The EditProc is not responsible for repainting, but must invalidate displayed nodes such that subsequent repaint would correctly display the changes.
EditRecord: TYPE = RECORD [
op: ATOM,
primary: SubNode ← nullSubNode,
secondary: Span ← nullSpan,
data: REFNIL,
count: INTEGER ← 0,
looks: TiogaLooks.Looks ← TiogaLooks.noLooks
] ;
The edit record can be thought of as a virtual machine instruction for the node editor, where the op is the operation to be performed and the remaining fields are optional parameters. While it is up to each node implementation to determine which operations it will support and what their semantics are, the following are suggested:
$Delete   - primary bounds the portion to delete.
$Insert   - primary is the insertion point, secondary is the material to be copied.
$Append   - primary is the append point, secondary is the material to be copied.
$InsertRope  - primary is the insertion point, data is the rope to be inserted.
$AppendRope - primary is the append point, data is the rope to be appended.
$SetLooks   - primary bounds the affected portion, looks contains the new looks bits.
The count field is included for operations such as BackSpace where it may be more efficient for the edit implementation to implement the operation multiple times rather than making multiple calls on the edit virtual machine.
----------
----------
ItemInitProc: TYPE = PROC [self: Item] ;
Called immediately after creation of a node.
----------
----------
ItemDestroyProc: TYPE = PROC [self: Item] ;
Called to free any resources held by a node when it has been destroyed (only resources that the GC is unable to return need be freed).
----------
----------
ItemCopyProc: TYPE = PROC [self, new: Item] ;
Copy private node data.
----------
----------
ItemSetSelectionProc: TYPE = PROC [self: Item, selection: REF ANY] ;
Force selection into a node. By convention, if selection is NIL then the entire node is selected.
----------
----------
ItemSetProc: TYPE = PROC [self: Item, op: ATOMNIL, data: REF ANY, finalise: BOOLTRUE] ;
Called to set the contents or other attributes of a node. By convention, if op=$Restore then data is a Rope.ROPE obtained from a previous call on self.get and stored out on disk.
----------
----------
ItemGetProc: TYPE = PROC [self: Item, op: ATOMNIL] RETURNS [data: REF ANY] ;
Called to query the contents or other attributes of a node. By convention, if op=$Save then data returned should be a Rope.ROPE representation of the item's private data in a form suitable for saving on disk and passing to a item.set with op=$Restore.
----------
----------
ItemComposeProc: TYPE = PROC [
self: Item,
startLoc: TiogaNode.Location, -- note that startLoc.path.node could be a child of self
composingStick: ComposingStick,
startIndex: NAT ← 0, -- first index to use on the composing stick
direction: LayoutDirection ← horizontal
]
RETURNS [
end: TiogaNode.Location, -- should be either within self or in a child of self
why: Break ← eon,
endIndex: NAT-- last index used on the composing stick
] ;
----------
----------
ItemDisplayProc: TYPE = PROC [
self: Item, dc: Graphics.Context,
composingStick: ComposingStick,
startIndex: NAT ← 0,
endIndex: NAT,
clear: BOOLTRUE
] ;
----------
----------
Data structures relevent to composition and display
LayoutDirection: TYPE = { horizontal, vertical } ← horizontal;
Break: TYPE = { eon, cr, wrap, hyphen } ← eon;
Distance: TYPE = INTEGER ← 0;
unbounded: Distance = LAST[Distance] ;
Metrics: TYPE = RECORD [
leftExtent, rightExtent: Distance ← 0, -- size before and after the x=0 baseline
topExtent, bottomExtent: Distance ← 0 -- size above and below the y=0 baseline
] ;
FlexOrder: TYPE = [0..3];
KerfIndex: TYPE = [0..LAST[CARDINAL]/SIZE[Kerf]-7];
Penalty: TYPE = INTEGER;
Glue: TYPE = RECORD [
size: Distance,
stretch: Distance, stretchOrder: FlexOrder,
shrink: Distance, shrinkOrder: FlexOrder
];
ComposingStick: TYPE = REF ComposingStickRec;
ComposingStickRec: TYPE = RECORD [
elements: ElementSeq,
kerfs: KerfSeq,
results: LineBreakSeq
];
ElementSeq: TYPE = REF ElementSeqRec;
ElementSeqRec: TYPE = RECORD [
length: NAT,
seq: SEQUENCE maxLength: NAT OF Element
];
OfElement: TYPE = {box, glue, tab, kerf};
Element: TYPE = RECORD [
SELECT kind: OfElement FROM
box => [metrics: Metrics],
A box is somthing that occupies a fixed amount of space in the line.
glue => [
stretchOrder, shrinkOrder: FlexOrder,
size, stretch, shrink: Distance
],
Glue is something that occupies a variable amount of space in the line. It has three components: its normal size, the amount by which it should be allowed to grow without a large penalty, and the amount by which it is allowed to shrink. The stretch and shrink have an order of infinity associated with them.
tab => [distanceFromStartOfLine: Distance],
kerf => [kerfIndex: KerfIndex, offset: Offset],
A kerf is a place in the line where a break is possible. It has three major parts, the join, the prebreak, and the postbreak. The join describes the size and flexibility of what is to go into the line if no break occurs at the kerf. If a break does occur at the kerf, the prebreak describes what goes before the break (i.e., at the end of the line), and the postbreak describes what goes at the beginning of the next line. A kerf also has an associated penalty to be charged if the break is taken, and some extra information to allow the positions of the chosen breaks to be communicated back to the client.
ENDCASE
];
KerfSeq: TYPE = REF KerfSeqRec;
KerfSeqRec: TYPE = RECORD [
length: KerfIndex,
seq: SEQUENCE maxLength: KerfIndex OF Kerf
];
Kerf: TYPE = RECORD [
join, prebreak, postbreak: Glue,
penalty: Penalty,
node: Ref
];
LineBreakSeq: TYPE = REF LineBreakRec;
LineBreakRec: TYPE = RECORD [
length: NAT,
seq: SEQUENCE maxLength: NAT OF LineBreak
];
LineBreak: TYPE = RECORD [
node: Ref,
offset: Offset,
glueSet: Distance
];
----------
----------
ItemIncrementalDisplayProc: TYPE = PROC [
self: Item,
dc: Graphics.Context,
whatChanged: REF,
growProc: GrowProc,
clear: BOOLTRUE
]
RETURNS [
metrics: Metrics,
okToBLTX, okToBLTY: BOOLTRUE
] ;
ItemGrowProc: TYPE = PROC [
self: Item,
metrics: Metrics,
okToBLTToNewLoc: BOOLTRUE
]
RETURNS [
metrics: Metrics,
clear: BOOLTRUE
] ;
----------
----------
ItemCachedDisplayTableProc: TYPE = PROC [parent, child: Item] RETURNS [dt: REF --TiogaDisplayTable.DisplayTable--];
When a node has become invalidated because of an edit, it must make sure that it invalidates any DisplayTable entries that might include it. A child node is expected to call this procedure in its parent and if the table returned is non-nil, it must set the invalid bit for any display table entries that include the edited region. The parent node must likewise call its parent.
DefaultItemCachedDisplayTableProc: ItemCachedDisplayTableProc;
For simple item classes that do not keep a private DisplayTable
----------
See TiogaNodeOps for registration of Item Classes
END.