-- File: WalnutMsgSetButtonsImpl.mesa -- Contents: co-ordinates MsgSet button handling for WalnutControlWindow -- 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.