-- File: WalnutMsgSetButtonsImpl.mesa -- Contents: co-ordinates MsgSet button handling for WalnutControlWindow -- created October, 1982 by Willie-Sue -- Last edit by: -- Willie-Sue on: June 6, 1983 10:12 am DIRECTORY Buttons USING [ButtonProc, SetDisplayStyle], Rope, VFonts USING [StringWidth], ViewerOps USING [AddProp, DestroyViewer, FetchProp, GrowViewer, MoveViewer, OpenIcon, PaintViewer], ViewerClasses, ViewerSpecs USING[openLeftWidth, openRightWidth], WalnutDB, WalnutDisplayerOps, WalnutViewer, WalnutWindow; WalnutMsgSetButtonsImpl: CEDAR PROGRAM IMPORTS Buttons, VFonts, ViewerOps, ViewerSpecs, WalnutDB, WalnutDisplayerOps, WalnutViewer, WalnutWindow EXPORTS WalnutWindow = BEGIN OPEN WalnutDB, WalnutWindow; ---------------------------- 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 NoSelectMsgSetProc: Buttons.ButtonProc = -- display or exclusive select BEGIN viewer: Viewer_ NARROW[parent]; msbH: MsgSetButton_ NARROW[ViewerOps.FetchProp[viewer, $msbH]]; IF mouseButton=yellow THEN MSDisplay[msbH, control] ELSE Report["Can't select the ", viewer.name, " MsgSet"]; END; 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 selectedMsgSetButtons # NIL THEN IF EqEntities[selectedMsgSetButtons.msgSet, deletedMsgSet] THEN mouseButton_ red; 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", TRUE, FALSE]; -- can't Select this MsgSet 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[msgSet: ms, msName: GetName[ms], paint: FALSE]; -- changes lastMsgSetButton ENDLOOP; END; GetSelectedMsgSets: PUBLIC PROC RETURNS[msL: LIST OF MsgSet] = BEGIN FOR msB: MsgSetButton_ selectedMsgSetButtons, msB.selected UNTIL msB=NIL DO msL_ CONS[msB.msgSet, 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] = 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]; 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]; }; -- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * AddMSButton: PROC[msgSet: MsgSet, msName: ROPE, noSelectProc: BOOL_ FALSE, 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.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 { ViewerOps.MoveViewer[walnutTS, walnutTS.wx, walnutTS.wy+v.wh, walnutTS.ww, walnutTS.wh, FALSE]; ViewerOps.MoveViewer[walnutRulerAfter, walnutRulerAfter.wx, walnutRulerAfter.wy+v.wh + (IF msgSetBorders THEN 1 ELSE 0), walnutRulerAfter.ww, walnutRulerAfter.wh, FALSE]; IF paint THEN ViewerOps.PaintViewer[walnut, client]; }; newV_ WalnutViewer.AnotherButton[q: walnutQueue, name: msName, proc: IF noSelectProc THEN NoSelectMsgSetProc ELSE 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; 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_ WalnutDisplayerOps.BuildMsgSetDisplayer[msb.msgSet, msb.selector.name, shift]; WalnutDisplayerOps.DisplayMsgSetInViewer[msb.msgSet, msb.msViewer] }; END; FindMSBForMsgSet: PROC[msgSet: MsgSet] RETURNS[MsgSetButton] = BEGIN FOR msb: MsgSetButton_ firstMsgSetButton, msb.next UNTIL msb = NIL DO IF EqEntities[msb.msgSet, msgSet] THEN RETURN[msb]; ENDLOOP; SIGNAL MsgSetButtonNotFound; RETURN[NIL]; END; END.