CirioButtons.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Sturgis, January 19, 1990 2:43:23 pm PST
Last tweaked by Mike Spreitzer on August 29, 1990 10:30:46 am PDT
DIRECTORY
IO USING[STREAM],
MBQueue USING[Queue],
Rope USING[ROPE],
StackCirio USING[Stack],
ViewerClasses USING[Viewer];
CirioButtons: CEDAR DEFINITIONS =
BEGIN
Viewer: TYPE ~ ViewerClasses.Viewer;
Cirio uses a rather baroque button mechanism. Because many buttons appear in more than one tool, we provide an interface to a collection of these buttons. Each of these buttons is accessed from a ButtonProc. This button proc expects a REF ANY data item. We include a specification for that data item.
each button requires access to general control information
ViewerControl: TYPE = REF ViewerControlBody;
ViewerControlBody: TYPE = MONITORED RECORD[
destroyStarted: BOOLEAN,
okToDestroy: BOOLEAN,
self: Viewer,
script: Viewer,
in: IO.STREAM, -- viewer typescript
out: IO.STREAM, -- writes onto the viewer typescript
mbQueue: MBQueue.Queue,
nextButtonAction: LIST OF ButtonAction,
lastButtonAction: LIST OF ButtonAction,
formatPrompt: PROC [counter: INT, clientData: REF ANY] RETURNS [Rope.ROPE],
interpretTextLine: PROC[line: Rope.ROPE, reports: IO.STREAM, clientData: REF ANY] RETURNS[Rope.ROPE],
shutDown: PROC[clientData: REF ANY, reports: IO.STREAM],
clientData: REF ANY
];
ButtonAction: TYPE = REF ButtonActionBody;
ButtonActionBody: TYPE = RECORD[
action: PROC[ButtonAction],
data: REF ANY,
ignoreDestroyStarted: BOOLEANFALSE];
CreateViewer: PROC
[
name: Rope.ROPE,
scriptY: CARD,
formatPrompt: PROC [counter: INT, clientData: REF ANY] RETURNS [Rope.ROPE],
interpretTextLine: PROC[line: Rope.ROPE, reports: IO.STREAM, clientData: REF ANY] RETURNS[Rope.ROPE],
shutDown: PROC[clientData: REF ANY, reports: IO.STREAM],
clientData: REF ANY]
RETURNS[ViewerControl];
MainActionProc: PROC[control: ViewerControl];
This routine is to be forked. It is to run outside the mbQueue. There is to be exactly one of these per tool instance. (i.e., one per Viewer).
Stack debug buttons
InstallWalkStackButton: PROC[bs: ButtonSet, stack: StackCirio.Stack, threadIndexText: Rope.ROPE, frameIndexLabel: Viewer];
(threadIndexText will be NIL for a pop up debugger.)
InstallShowFrameButton: PROC[bs: ButtonSet, stack: StackCirio.Stack];
InstallSourcePositionButton: PROC[bs: ButtonSet, stack: StackCirio.Stack];
InstallSourceLanguageButton: PROC[bs: ButtonSet, stack: StackCirio.Stack];
Button installation procedures
ButtonSet: TYPE = REF ButtonSetBody;
ButtonSetBody: TYPE = RECORD[
container: Viewer,
new buttons will be created with container as their parent
vc: ViewerControl,
validFlag: BOOLEAN,
Starts True. Set to False during subsequent destruction of the buttons. When false, most buttons should act as no-ops.
x, y: CARD,
colX: CARD,
lineH: CARD,
fixedWidth: CARD ← 0];
x and y will change as buttons are added
ButtonSize: TYPE = RECORD[w, h: CARD];
CreateButtonSet: PROC[container: Viewer, vc: ViewerControl, x, y: CARD, colX: CARD, lineH: CARD, fixedWidth: CARD ← 0] RETURNS[ButtonSet];
KillButtonSet: PROC[bs: ButtonSet, paint: BOOLEANTRUE] RETURNS[ButtonSet];
this will destroy the containing viewer.
Hence, the containing viewer should be a subviewer of the main viewer.
always returns NIL, for clearing a variable
NewLine: PROC[bs: ButtonSet];
MoveToY: PROC[bs: ButtonSet, y: CARD]; -- resets x to colX
SkipY: PROC[bs: ButtonSet, h: CARD];
MoveToX: PROC[bs: ButtonSet, x: CARD];
SkipX: PROC[bs: ButtonSet, w: CARD];
GetButtonSize: PROC[name: Rope.ROPE] RETURNS[ButtonSize];
InstallCommandButton: PROC [
bs: ButtonSet,
name: Rope.ROPE, border: BOOLFALSE, guarded: BOOLFALSE,
clientData1: REF ANY,
choices: ChoiceList ← NIL,
proc1: PROC[button: Viewer, vc: ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] ← NIL,
proc2: PROC[button: Viewer, vc: ViewerControl, key, clientData1, clientData2: REF ANY]]
RETURNS[Viewer];
If proc1 is non-nil, then it gets called at (approx) button click time. proc2 will be called later, after all previously queued actions have been completed. If proc1 was nil, then clientData2 in proc2 will be nil, otherwise it will be the result of proc1.
It is expected that proc1 will perform no significant action. The purpose of proc1 is to record any significant visible information that may change before proc2 runs. For example, proc1 might record the contents of a current selection.
Few command buttons will require a proc1.
ChoiceList: TYPE = LIST OF Choice;
Choice: TYPE = RECORD [key: REF ANY, doc: Rope.ROPE];
InstallLabelButton: PROC[bs: ButtonSet, name: Rope.ROPE] RETURNS[Viewer];
InstallRule: PROC[bs: ButtonSet];
END..