File: WalnutMsgSetButtonsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Contents: co-ordinates MsgSet button handling for WalnutControlWindow
Willie-Sue, March 20, 1985 9:08:04 am PST
created October, 1982 by Willie-Sue
Last edit by:
Willie-Sue on: September 19, 1984 2:49:40 pm PDT
DIRECTORY
Buttons USING [ButtonProc, SetDisplayStyle],
Rope,
VFonts USING [StringWidth],
ViewerOps
USING [AddProp, DestroyViewer, FetchProp, GrowViewer, MoveViewer,
OpenIcon, PaintViewer],
ViewerClasses USING [Viewer],
ViewerSpecs USING[openLeftWidth, openRightWidth],
WalnutDB
USING [Entity, Msg, MsgSet, activeMsgSet, deletedMsgSet, MsgSetDomain,
DeclareMsgSet, EqEntities, GetEntitiesInDomain, GetName],
WalnutMsgOps USING [BuildMsgSetDisplayer, MsgSetInViewer],
WalnutViewer USING [AnotherButton],
WalnutWindow
USING [MsgSetButton, MsgSetButtonObject,
msgSetBorders, walnut, walnutQueue, walnutRulerBefore, walnutRulerAfter,
walnutTS];
WalnutMsgSetButtonsImpl:
CEDAR
PROGRAM
IMPORTS
Buttons,
VFonts, ViewerOps, ViewerSpecs,
WalnutDB, WalnutMsgOps, WalnutViewer, WalnutWindow
EXPORTS WalnutWindow =
BEGIN OPEN WalnutDB, WalnutWindow;
--------------------------
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
MsgSetButtonNotFound: SIGNAL = CODE; -- something is wrong
selectedMsgSetButtons: PUBLIC MsgSetButton← NIL; -- List of selected MsgSets (may be empty)
lastMsgSetButton: PUBLIC MsgSetButton← NIL; -- tail of List of MsgSets (never empty)
firstMsgSetButton: PUBLIC MsgSetButton← NIL; -- head of List of MsgSets (never empty
SelectMsgSetProc: Buttons.ButtonProc =
IF red THEN deselect all & select this one; IF yellow then display;
IF blue THEN toggle whether selected or not
BEGIN
viewer: Viewer← NARROW[parent];
msbH: MsgSetButton← NARROW[ViewerOps.FetchProp[viewer, $msbH]];
msb, msb2: MsgSetButton;
IF mouseButton = yellow THEN {MSDisplay[msbH, shift]; RETURN};
IF mouseButton = red
THEN
-- deselect any selected
{
IF (msb← selectedMsgSetButtons) #
NIL
THEN
{ selectedMsgSetButtons←
NIL;
DO
Buttons.SetDisplayStyle[msb.selector, $BlackOnWhite];
IF (msb2← msb.selected) = NIL THEN EXIT;
msb.selected← NIL;
msb← msb2;
ENDLOOP;
}
}
ELSE -- blue button
{
FOR msb← selectedMsgSetButtons, msb.selected
UNTIL msb=
NIL
DO
IF msb = msbH THEN {DeselectMsgSet[msbH]; RETURN};
ENDLOOP;
msbH.selected ← selectedMsgSetButtons;
};
selectedMsgSetButtons← msbH;
Buttons.SetDisplayStyle[viewer, $WhiteOnBlack];
END;
--------------------------
ShowMsgSetButtons:
PUBLIC
PROC =
BEGIN
eL: LIST OF Entity← GetEntitiesInDomain[d: MsgSetDomain, alphaOrder: TRUE];
ms: Entity;
v: Viewer;
IF firstMsgSetButton # NIL THEN { UpdateMSBs[eL]; RETURN};
v← WalnutViewer.AnotherButton[q: walnutQueue, name: "Active", proc: SelectMsgSetProc,
sib: walnutRulerBefore, border: msgSetBorders, newLine: TRUE, paint: FALSE];
firstMsgSetButton← lastMsgSetButton←
NEW[MsgSetButtonObject← [msgSet: activeMsgSet, selector: v]];
ViewerOps.AddProp[v, $msbH, lastMsgSetButton];
AddMSButton[deletedMsgSet, "Deleted", FALSE];
FOR elT:
LIST
OF Entity← eL, elT.rest
UNTIL elT=
NIL
DO
ms← elT.first;
IF ~EqEntities[ms, deletedMsgSet]
AND ~EqEntities[ms, activeMsgSet]
THEN
AddMSButton[ms, GetName[ms], FALSE]; -- changes lastMsgSetButton
ENDLOOP;
END;
GetSelectedMsgSets:
PUBLIC
PROC
RETURNS[msL:
LIST
OF MsgSetButton] =
BEGIN
FOR msB: MsgSetButton← selectedMsgSetButtons, msB.selected
UNTIL msB=
NIL
DO
msL← CONS[msB, msL];
ENDLOOP;
END;
AddMsgSetButton:
PUBLIC
PROC[msgSet: MsgSet, msName:
ROPE, select:
BOOL] =
BEGIN
AddMSButton[msgSet, msName];
IF select THEN SelectMsgSetProc[lastMsgSetButton.selector]; -- red-select new MsgSet
END;
DeleteMsgSetButton: PUBLIC PROC[msgSet: MsgSet] =
if msgSet is Active, just destroy viewer, but not button
BEGIN
prevMsb: MsgSetButton← firstMsgSetButton;
FOR msb: MsgSetButton← firstMsgSetButton, msb.next UNTIL msb = NIL DO
IF EqEntities[msb.msgSet, msgSet]
THEN
{ msV: Viewer← msb.msViewer;
IF msV # NIL AND ~msV.destroyed THEN ViewerOps.DestroyViewer[msV];
IF EqEntities[msgSet, activeMsgSet] THEN { msb.msViewer← NIL; RETURN};
DeselectMsgSet[msb];
IF msb = lastMsgSetButton THEN lastMsgSetButton← prevMsb;
prevMsb.next← msb.next;
ViewerOps.DestroyViewer[msb.selector];
RETURN
};
prevMsb← msb;
ENDLOOP;
END;
FindMSViewer:
PUBLIC
PROC[msgSet: MsgSet]
RETURNS[Viewer] =
BEGIN
FOR msb: MsgSetButton← firstMsgSetButton, msb.next
UNTIL msb =
NIL
DO
IF EqEntities[msb.msgSet, msgSet]
THEN
{
IF msb.msViewer =
NIL
THEN
RETURN[
NIL]
ELSE
IF ~msb.msViewer.destroyed
THEN
RETURN[msb.msViewer]
ELSE
{ msb.msViewer← NIL; RETURN[NIL]}};
ENDLOOP;
SIGNAL MsgSetButtonNotFound;
RETURN[NIL];
END;
DisplayMsgSet:
PUBLIC
PROC[msgSet: MsgSet]
RETURNS[Viewer] =
{ msb: MsgSetButton;
MSDisplay[msb← FindMSBForMsgSet[msgSet], FALSE];
RETURN[msb.msViewer];
};
DestroyAllMsgSetButtons:
PUBLIC
PROC =
BEGIN
selectedMsgSetButtons← NIL;
FOR msb: MsgSetButton← firstMsgSetButton, msb.next
UNTIL msb=
NIL
DO
ViewerOps.DestroyViewer[msb.selector, FALSE];
ENDLOOP;
firstMsgSetButton← lastMsgSetButton← NIL;
ViewerOps.MoveViewer[walnutRulerAfter, walnutRulerAfter.wx,
walnutRulerBefore.wy+walnutRulerBefore.wh+14+2, walnutRulerAfter.ww,
walnutRulerAfter.wh, FALSE];
ViewerOps.MoveViewer[walnutTS, walnutTS.wx,
walnutRulerAfter.wy+walnutRulerAfter.wh+1, walnutTS.ww,
walnutTS.wh, FALSE];
ViewerOps.PaintViewer[walnut, client];
END;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
AddMSButton:
PROC[msgSet: MsgSet, msName:
ROPE, paint:
BOOL←
TRUE] =
assumes msgSet does not already have a button; there is always a lastMsgSetButton
BEGIN
msbH: MsgSetButton;
newV: Viewer;
v: Viewer← lastMsgSetButton.selector;
x: INTEGER← v.wx + v.ww + 2; -- x for new button
width: INT← VFonts.StringWidth[msName];
parentWidth:
INTEGER←
IF ~walnut.iconic
THEN walnut.cw
ELSE
IF walnut.column = left
THEN ViewerSpecs.openLeftWidth
ELSE ViewerSpecs.openRightWidth;
newLine: BOOL← (x + width + 3) >= parentWidth; -- will button fit on this line??
IF newLine
AND (walnutTS#
NIL)
THEN
-- move Rule & typescript viewers
{ nH:
INTEGER← v.wh + (
IF msgSetBorders
THEN 1
ELSE 0);
ViewerOps.MoveViewer[walnutTS, walnutTS.wx, walnutTS.wy+nH, walnutTS.ww,
walnutTS.wh, FALSE];
ViewerOps.MoveViewer[walnutRulerAfter, walnutRulerAfter.wx,
walnutRulerAfter.wy + nH,
walnutRulerAfter.ww,
walnutRulerAfter.wh, FALSE];
IF paint THEN ViewerOps.PaintViewer[walnut, client];
};
newV← WalnutViewer.AnotherButton[q: walnutQueue, name: msName,
proc: SelectMsgSetProc,
sib: v, border: msgSetBorders, newLine: newLine, paint: paint];
msbH← NEW[MsgSetButtonObject← [msgSet: msgSet, selector: newV]];
ViewerOps.AddProp[newV, $msbH, msbH];
lastMsgSetButton.next← msbH;
lastMsgSetButton← msbH;
END;
UpdateMSBs:
PROC[eL:
LIST
OF Entity] =
BEGIN
ms, ms2: Entity;
newMS, lastNewMS: LIST OF MsgSet;
elT: LIST OF Entity← eL;
prevMsb: MsgSetButton;
msb: MsgSetButton← firstMsgSetButton;
DeleteMSB:
PROC[msButton: MsgSetButton] =
BEGIN
DeselectMsgSet[msButton];
ViewerOps.DestroyViewer[msb.selector];
END;
msb.msgSet← DeclareMsgSet[msb.selector.name].msgSet; -- Active
msb← msb.next;
msb.msgSet← DeclareMsgSet[msb.selector.name].msgSet; -- Deleted
prevMsb← msb;
msb← msb.next;
DO
IF elT=NIL OR msb=NIL THEN EXIT;
ms← elT.first;
IF EqEntities[ms, deletedMsgSet]
OR EqEntities[ms, activeMsgSet]
THEN
{ elT← elT.rest; LOOP};
ms2← DeclareMsgSet[msb.selector.name, OldOnly].msgSet;
IF ms2=
NIL
THEN
-- msgSet was destroyed
{ prevMsb.next← msb.next; DeleteMSB[msb]; msb← prevMsb.next; LOOP};
IF EqEntities[ms, ms2]
THEN
{ msb.msgSet← ms; prevMsb← msb; msb← msb.next; elT← elT.rest; LOOP};
there was a new msgset created
IF newMS =
NIL
THEN newMS← lastNewMS←
CONS[ms,
NIL]
ELSE lastNewMS← lastNewMS.rest← CONS[ms, NIL];
elT← elT.rest;
ENDLOOP;
IF msb#
NIL
THEN
-- delete these guys (ran out of msgSets)
DO
prevMsb.next← msb.next;
IF msb = lastMsgSetButton THEN lastMsgSetButton← prevMsb;
DeleteMSB[msb];
IF (msb← prevMsb.next)=NIL THEN EXIT;
ENDLOOP;
IF newMS#
NIL
THEN
-- add these at end
FOR nms:
LIST
OF MsgSet← newMS, nms.rest
UNTIL nms=
NIL
DO
AddMSButton[nms.first, GetName[nms.first]];
ENDLOOP;
IF elT #
NIL
THEN
-- more to add
FOR elT← elT, elT.rest
UNTIL elT=
NIL
DO
AddMSButton[elT.first, GetName[elT.first]];
ENDLOOP;
END;
DeselectMsgSet:
PROC[msbH: MsgSetButton] =
BEGIN
msb: MsgSetButton← selectedMsgSetButtons;
FOR msb2: MsgSetButton← msb, msb2.selected
UNTIL msb2=
NIL
DO
IF msb2 = msbH
THEN
-- found on list so take off
{ msb.selected← msb2.selected;
IF msbH = selectedMsgSetButtons THEN selectedMsgSetButtons← msbH.selected;
msbH.selected← NIL;
Buttons.SetDisplayStyle[msbH.selector, $BlackOnWhite];
RETURN
};
msb← msb2;
ENDLOOP;
END;
MSDisplay:
PROC[msb: MsgSetButton, shift:
BOOL] =
BEGIN
OPEN ViewerOps;
msV: Viewer← msb.msViewer;
IF (msV #
NIL)
AND ~msV.destroyed
THEN
{
IF msV.iconic
THEN OpenIcon[msV, shift]
ELSE IF shift THEN GrowViewer[msV] ELSE PaintViewer[msV, all]
}
ELSE
{ msb.msViewer←
WalnutMsgOps.BuildMsgSetDisplayer[msb.msgSet, msb.selector.name, shift];
WalnutMsgOps.MsgSetInViewer[NIL, msb.msgSet, msb.msViewer]
};
END;
FindMSBForMsgSet:
PUBLIC
PROC[msgSet: MsgSet]
RETURNS[MsgSetButton] =
BEGIN
FOR msb: MsgSetButton← firstMsgSetButton, msb.next
UNTIL msb =
NIL
DO
IF EqEntities[msb.msgSet, msgSet]
THEN
{
IF msb.msViewer #
NIL
AND msb.msViewer.destroyed
THEN msb.msViewer←
NIL;
RETURN[msb];
}
ENDLOOP;
RETURN[NIL];
END;
END.