DIRECTORY Buttons, CD, CDEvents, CDExtras, CDLayers, CDPanel, CDPanelExtras, CDPrivate, CDSequencer, CDTipEtc, CDValue, Containers, Labels, Menus, MBQueue, Rope USING [Cat, Concat, ROPE], TerminalIO, UserProfile, ViewerEvents, ViewerClasses, ViewerOps; CDPanelImpl: CEDAR MONITOR IMPORTS Buttons, CD, CDEvents, CDExtras, CDLayers, CDSequencer, CDTipEtc, CDValue, Containers, Labels, MBQueue, Rope, TerminalIO, UserProfile, ViewerEvents, ViewerOps EXPORTS CDPanel, CDPanelExtras SHARES CDLayers = BEGIN Error: ERROR = CODE; panelKey: REF INT = NEW[INT]; -- used instead of atoms, to be really unique panelClassKey: REF INT = NEW[INT]; globalClass: PanelClass = NEW[PanelEntryList_NIL]; Panel: TYPE = REF PanelRecord; -- one per design PanelRecord: TYPE = RECORD [ container: ViewerClasses.Viewer_NIL, design: CD.Design, class: PanelClass_NIL, nextLayerX: CARDINAL, nextLayerY: CARDINAL, nextX: CARDINAL, nextY: CARDINAL, nextSpecialX: CARDINAL, layerLabel: Labels.Label, layerWidths: LIST OF WidthValueRef _ NIL, firstLayer: REF LayerDefine _ NIL, labels: LIST OF REF Tripple _ NIL ]; panelList: LIST OF Panel _ NIL; GetPanel: PROC [design: CD.Design] RETURNS [Panel] = BEGIN x: REF _ CDValue.Fetch[boundTo: design, key: panelKey, propagation: global]; IF x=NIL THEN { panel: Panel = NEW[PanelRecord]; panel.class _ GetPanelClass[design.technology]; panel.design _ design; [] _ CDValue.StoreConditional[design, panelKey, panel]; RETURN [GetPanel[design]] }; RETURN [NARROW[x, Panel]]; END; GetPanelClass: PROC [tech: CD.Technology] RETURNS [PanelClass] = BEGIN IF tech=NIL THEN RETURN [globalClass] ELSE { x: REF _ CDValue.Fetch[boundTo: tech, key: panelClassKey, propagation: technology]; IF x=NIL THEN { panelClass: PanelClass = NEW[PanelEntryList_NIL]; [] _ CDValue.StoreConditional[boundTo: tech, key: panelClassKey, value: panelClass]; RETURN [GetPanelClass[tech]]; }; RETURN [NARROW[x, PanelClass]]; } END; CreatePanel: PUBLIC ENTRY PROC [design: CD.Design] RETURNS [ViewerClasses.Viewer] = BEGIN ENABLE UNWIND => NULL; panel: Panel _ GetPanel[design]; panelClass: PanelClass _ GetPanelClass[design.technology]; IF panel.container#NIL AND NOT panel.container.destroyed THEN RETURN [panel.container]; panel.container _ NIL; panel.labels _ NIL; IF panelClass#NIL AND panelClass^#NIL THEN CreatePanelViewer[panel]; CheckPanelList[panel]; RETURN [panel.container] END; AppendEntryInClass: INTERNAL PROC [class: PanelClass, entry: REF ANY] = BEGIN IF class^=NIL THEN class^ _ LIST[entry] ELSE FOR list: PanelEntryList _ class^, list.rest DO IF list.rest = NIL THEN {list.rest _ LIST[entry]; EXIT} ENDLOOP; END; AppendEntryInViewers: INTERNAL PROC [class: PanelClass, entry: REF ANY] = BEGIN FOR list: LIST OF Panel _ panelList, list.rest WHILE list#NIL DO IF list.first.container#NIL AND ~list.first.container.destroyed THEN { IF list.first.class=class OR class=globalClass THEN NewEntry[list.first, entry]; } ENDLOOP END; CheckPanelList: INTERNAL PROC [p: Panel] = BEGIN copiedList: LIST OF Panel _ NIL; FOR list: LIST OF Panel _ panelList, list.rest WHILE list#NIL DO IF list.first.container#NIL AND ~list.first.container.destroyed AND list.first#p THEN copiedList _ CONS[list.first, copiedList] ENDLOOP; IF p#NIL THEN copiedList _ CONS[p, copiedList]; panelList _ copiedList END; AppendEntry: INTERNAL PROC [class: PanelClass, entry: REF ANY] = BEGIN AppendEntryInClass[class, entry]; AppendEntryInViewers[class, entry]; END; DefineNewLine: PUBLIC ENTRY PROC [tech: CD.Technology] = BEGIN ENABLE UNWIND => NULL; class: PanelClass = GetPanelClass[tech]; AppendEntry[class, $NewLine]; END; DefineButton: PUBLIC ENTRY PROC [tech: CD.Technology_NIL, name: Rope.ROPE, proc: CDSequencer.CommandProc _ NIL, command: ATOM _ NIL, queue: CDSequencer.QueueMethod _ useDefault, topLine: BOOL _ FALSE, border: BOOL _ FALSE,data: REF _ NIL, cdValueKey: REF _ NIL] = BEGIN ENABLE UNWIND => NULL; class: PanelClass = GetPanelClass[tech]; bd: REF ButtonDefine; IF command=NIL AND queue=useDefault THEN queue _ doQueue; bd _ NEW[ButtonDefine _ [ name: name, proc: proc, command: command, queue: queue, data: data, border: border, topLine: topLine, cdValueKey: cdValueKey ]]; AppendEntry[class, bd]; END; DefineLabel: PUBLIC ENTRY PROC [tech: CD.Technology_NIL, name: Rope.ROPE, border: BOOL _ FALSE, cdValueKey: REF _ NIL] = BEGIN ENABLE UNWIND => NULL; class: PanelClass = GetPanelClass[tech]; lab: REF LabelDefine; lab _ NEW[LabelDefine _ [name: name, border: border, cdValueKey: cdValueKey]]; AppendEntry[class, lab]; END; layerDefinitions: REF ARRAY [0..CD.layerNum) OF REF LayerDefine = NEW[ARRAY [0..CD.layerNum) OF REF LayerDefine _ ALL[NIL]]; LayerText: PROC [lev: CD.Layer] RETURNS [Rope.ROPE] = BEGIN RETURN [IF layerDefinitions[lev]#NIL THEN layerDefinitions[lev].text ELSE "not defined" ] END; LayerDefine: TYPE = RECORD [ layer: CD.Layer _ CD.combined, text: Rope.ROPE _ NIL, min, default: CD.Number _ 0 ]; IntDefine: TYPE = RECORD [ cdValueKey: REF, text: Rope.ROPE, min, max, default: INT, lambda: INT _ 1 ]; ButtonDefine: TYPE = RECORD [ name: Rope.ROPE, proc: CDSequencer.CommandProc _ NIL, command: ATOM _ NIL, queue: CDSequencer.QueueMethod, topLine: BOOL _ FALSE, border: BOOL _ FALSE, data: REF _ NIL, cdValueKey: REF _ NIL ]; LabelDefine: TYPE = RECORD [ name: Rope.ROPE, cdValueKey: REF, border: BOOL _ FALSE ]; PanelEntryList: TYPE = LIST OF REF ANY; -- one per CD.Technology PanelClass: TYPE = REF PanelEntryList; DefineLayerEntry: PUBLIC ENTRY PROC [tech: CD.Technology, lev: CD.Layer, text: Rope.ROPE, min, default: CD.Number_1] = BEGIN ENABLE UNWIND => NULL; panelClass: PanelClass = GetPanelClass[tech]; IF lev=CD.combined THEN ERROR; IF layerDefinitions[lev]#NIL THEN RETURN WITH ERROR CD.Error[doubleRegistration, "re-registers layer"]; layerDefinitions[lev] _ NEW[LayerDefine _ [ layer: lev, text: text, min: min, default: default ]]; AppendEntry[panelClass, layerDefinitions[lev]]; CDLayers.SetLayerWidth[design: NIL --!!! it sets default--, layer: lev, width: default]; END; NotifyCurrentLayer: CDLayers.DesignNotifyProc = BEGIN panel: Panel = GetPanel[design]; IF panel.layerLabel#NIL THEN { l: CD.Layer _ CDLayers.CurrentLayer[design]; Labels.Set[panel.layerLabel, LayerText[l]]; } END; NotifyLayerWidth: CDLayers.LayerNotifyProc = BEGIN panel: Panel = GetPanel[design]; IF panel.layerLabel#NIL THEN { FOR list: LIST OF WidthValueRef _ panel.layerWidths, list.rest WHILE list#NIL DO IF list.first.layerDefine.layer=layer THEN { Labels.Set[list.first.numbLab, CDExtras.ToLambda[ n: CDLayers.LayerWidth[design, layer], lambda: design.technology.lambda ] ]; EXIT; }; ENDLOOP; } END; topY: CARDINAL = 1; entryHSpace: CARDINAL = 3; entryHeight: CARDINAL = 12; shorterEntryVSpace: CARDINAL = 1; Caption: PROC [panel: Panel] RETURNS [Rope.ROPE] = BEGIN RETURN [Rope.Cat[ IF panel.design.name#NIL THEN panel.design.name ELSE "no name", " ", panel.design.technology.name, " ", CDExtras.PushedCellName[panel.design] ]]; END; CreatePanelViewer: INTERNAL PROC [panel: Panel] = BEGIN MakeClassEntries: INTERNAL PROC [class: PanelClass] = BEGIN FOR l: PanelEntryList _ class^, l.rest WHILE l#NIL DO NewEntry[panel, l.first]; ENDLOOP; END; TerminalIO.WriteRope["Create a control panel\n"]; IF panel=NIL OR panel.design=NIL OR panel.design.technology=NIL THEN { TerminalIO.WriteRope["not registered properly\n"]; ERROR }; panel.labels _ NIL; panel.layerWidths _ NIL; panel.nextLayerX _ panel.nextX _ 0; panel.nextY _ topY; panel.nextLayerY _ topY+entryHeight+entryHSpace; panel.container _ Containers.Create[[ name: Caption[panel], openHeight: CDValue.FetchInt[ boundTo: panel.design, key: $PanelHeight, propagation: global, ifNotFound: 120], scrollable: TRUE, iconic: UserProfile.Boolean["ChipNDale.ControlViewerOpenIconic", FALSE], icon: CDTipEtc.GetPanelIcon[panel.design], column: right ]]; ViewerOps.AddProp[panel.container, $CDPanelPrivate, panel]; [] _ NextLabel[panel, "current layer:"]; panel.layerLabel _ NextLabel[panel: panel, extraSpaces: 2, name: LayerText[CDLayers.CurrentLayer[panel.design]], extraWidth: 2 ]; [] _ NextLabel[panel, "| "]; panel.nextSpecialX _ panel.nextX; panel.nextY _ 3*(entryHeight+entryHSpace); panel.nextX _ 0; MakeClassEntries[panel.class]; MakeClassEntries[globalClass]; IF panel.firstLayer#NIL THEN CDLayers.SetCurrentLayer[panel.design, panel.firstLayer.layer]; END; NewEntry: INTERNAL PROC[panel: Panel, entry: REF] = BEGIN IF panel.container.destroyed THEN RETURN; WITH entry SELECT FROM layerDefine: REF LayerDefine => { IF panel.firstLayer=NIL THEN panel.firstLayer _ layerDefine; CreateLayerEntry[panel, layerDefine]; }; intDef: REF IntDefine => CreateIntEntry[panel, intDef]; butDef: REF ButtonDefine => CreateButtEntry[panel, butDef]; labDef: REF LabelDefine => [] _ CreateLabEntry[panel, labDef]; a: ATOM => { SELECT a FROM $NewLine => CreateLnEntry[panel]; ENDCASE => ERROR; }; ENDCASE => ERROR; END; RepaintCaptions: ENTRY CDEvents.EventProc = BEGIN panel: Panel _ GetPanel[design]; IF panel.container#NIL THEN { panel.container.name _ Caption[panel]; ViewerOps.PaintViewer[panel.container, caption]; }; END; WidthValueRec: TYPE = RECORD [ layerDefine: REF LayerDefine, panel: Panel, numbLab: Labels.Label _ NIL ]; WidthValueRef: TYPE = REF WidthValueRec; NextMBQButton: INTERNAL PROC [panel: Panel, label: Rope.ROPE, proc: Buttons.ButtonProc, border: BOOL _ FALSE, clientData: REF ANY _ NIL] = BEGIN yoff: INT = Containers.ScrollOffset[panel.container]; button: Buttons.Button = MBQueue.CreateButton[q: panel.design.queue, info: [ name: label, wx: panel.nextX, wy: panel.nextY+yoff, wh: entryHeight, parent: panel.container, border: border ], clientData: clientData, proc: proc ]; panel.nextX _ button.wx+button.ww+entryHSpace; END; NextButton: INTERNAL PROC [panel: Panel, label: Rope.ROPE, proc: Buttons.ButtonProc, clientData: REF ANY _ NIL, topLine: BOOL _ FALSE, border: BOOL _ FALSE] RETURNS [button: Buttons.Button] = BEGIN yoff: INT = Containers.ScrollOffset[panel.container]; x: INT _ panel.nextX; y: INT _ panel.nextY; IF topLine THEN {x _ panel.nextSpecialX; y _ 0}; button _ Buttons.Create[ info: [ name: label, wx: x, wy: y+yoff, wh: entryHeight, parent: panel.container, border: border ], clientData: clientData, proc: proc ]; IF topLine THEN panel.nextSpecialX _ button.wx+button.ww+entryHSpace ELSE panel.nextX _ button.wx+button.ww+entryHSpace END; NextLabel: INTERNAL PROC [panel: Panel, name: Rope.ROPE, border: BOOL _ FALSE, extraSpaces: CARDINAL _ 0, extraWidth: CARDINAL _ 0] RETURNS [Labels.Label] = BEGIN yoff: INT = Containers.ScrollOffset[panel.container]; label: Labels.Label; IF name=NIL THEN name _ " "; WHILE extraWidth>0 DO name _ Rope.Concat[base: name, rest: " "]; extraWidth _ extraWidth-1; ENDLOOP; label _ Labels.Create[ info: [ name: name, wx: panel.nextX+extraSpaces*entryHSpace, wy: panel.nextY+yoff, wh: entryHeight, parent: panel.container, border: border ] ]; panel.nextX _ label.wx+label.ww+entryHSpace; RETURN [label] END; CreateIntEntry: INTERNAL PROC [panel: Panel, intDef: REF IntDefine] = BEGIN initialValue: Rope.ROPE; intRef: REF Tripple _ NEW[Tripple _ [panel: panel, define: intDef]]; lambda: INT _ intDef.lambda; IF lambda<=0 THEN lambda _ panel.design.technology.lambda; [] _ NextMBQButton[panel: panel, label: intDef.text, proc: IntCalled, clientData: intRef]; initialValue _ CDExtras.ToLambda[ n: CDValue.FetchInt[ boundTo: panel.design, key: intDef.cdValueKey, propagation: technology, ifNotFound: intDef.default ], lambda: lambda ]; intRef.feedback _ NextLabel[panel: panel, name: initialValue, extraWidth: 9]; END; Tripple: TYPE = RECORD [panel: Panel, define: REF _ NIL, feedback: REF _ NIL]; CreateLabEntry: INTERNAL PROC [panel: Panel, labDef: REF LabelDefine] RETURNS [tripple: REF Tripple_NIL] = BEGIN lab: Labels.Label _ NextLabel[ panel: panel, name: labDef.name, border: labDef.border ]; IF labDef.cdValueKey#NIL THEN { tripple _ NEW[Tripple _ [panel: panel, define: labDef, feedback: lab]]; panel.labels _ CONS[tripple, panel.labels]; RedisplayLabel[tripple]; } END; RedisplayLabel: PROC [tripple: REF Tripple] = BEGIN IF tripple=NIL THEN RETURN; WITH tripple.define SELECT FROM labDef: REF LabelDefine => { x: REF = CDValue.Fetch[ boundTo: tripple.panel.design, key: labDef.cdValueKey, propagation: global ]; Labels.Set[NARROW[tripple.feedback], CDExtras.ToRope[x, "-?-"]]; }; butDef: REF ButtonDefine => { x: REF = CDValue.Fetch[ boundTo: tripple.panel.design, key: butDef.cdValueKey, propagation: global ]; Buttons.ReLabel[NARROW[tripple.feedback], CDExtras.ToRope[x, "-?-"]]; }; ENDCASE => WITH tripple.feedback SELECT FROM t: REF Tripple => RedisplayLabel[t] ENDCASE => NULL; END; RedisplayLabels: PUBLIC PROC [design: CD.Design] = BEGIN panel: Panel = GetPanel[design]; IF panel.container=NIL OR panel.container.destroyed THEN RETURN; FOR list: LIST OF REF Tripple _ panel.labels, list.rest WHILE list#NIL DO RedisplayLabel[list.first]; ENDLOOP; END; CreateButtEntry: INTERNAL PROC [panel: Panel, butDef: REF ButtonDefine] = BEGIN but: Buttons.Button = NextButton[ panel: panel, label: butDef.name, proc: ButtonCalled, border: butDef.border, topLine: butDef.topLine, clientData: NEW[Tripple _ [panel: panel, define: butDef]] ]; IF butDef.cdValueKey#NIL THEN { tripple: REF Tripple _ NEW[Tripple _ [panel: panel, define: butDef, feedback: but]]; panel.labels _ CONS[tripple, panel.labels]; RedisplayLabel[tripple]; } END; ButtonCalled: Buttons.ButtonProc = BEGIN tripple: REF Tripple = NARROW[clientData]; butDef: REF ButtonDefine = NARROW[tripple.define]; comm: CDSequencer.Command = NEW[CDSequencer.CommandRec_[ data: butDef.data, design: tripple.panel.design ]]; IF butDef.proc#NIL THEN CDSequencer.ExecuteProc[comm: comm, proc: butDef.proc, queue: butDef.queue] ELSE IF butDef.command#NIL THEN CDSequencer.ExecuteCommand[comm: comm, command: butDef.command, queue: butDef.queue]; END; Double: PROC[i: INT] RETURNS [INT] = INLINE { IF i(FIRST[INT]/2) THEN i _ i+i; RETURN [i] }; Inc: PROC[i: INT, x: INT_1] RETURNS [INT] = INLINE { IF i<=LAST[INT]-x THEN i _ i+x; RETURN [i] }; Dec: PROC[i: INT, x: INT_1] RETURNS [INT] = INLINE { IF i>=FIRST[INT]+x THEN i _ i-x; RETURN [i] }; GetAnInt: PROC [old, default: INT, label: Rope.ROPE, lambda: INT_1] RETURNS [new: INT] = BEGIN ENABLE TerminalIO.UserAbort => GOTO aborted; choice: LIST OF Rope.ROPE; new _ old; IF lambda=1 THEN choice _ LIST["+1", "-1", "*2", "/2", "default", "type"] ELSE choice _ LIST["+1", "-1", "*2", "/2", "default", "type", "type int", "trunc"]; SELECT TerminalIO.RequestSelection[label: label, choice: choice] FROM 1 => new _ Inc[old, lambda]; 2 => new _ Dec[old, lambda]; 3 => {new _ Double[old]}; 4 => {new _ old/2}; 5 => {new _ default}; 6 => {new _ TerminalIO.RequestInt["type value > "]*lambda}; 7 => {new _ TerminalIO.RequestInt["type value (int) > "]}; 8 => {new _ old/lambda*lambda}; ENDCASE => TerminalIO.WriteRope["Skipped\n"]; EXITS aborted => NULL; END; IntCalled: ENTRY Buttons.ButtonProc = BEGIN ENABLE UNWIND => NULL; i: INT; tripple: REF Tripple = NARROW[clientData]; intDef: REF IntDefine = NARROW[tripple.define]; lambda: INT _ intDef.lambda; IF lambda<=0 THEN lambda _ tripple.panel.design.technology.lambda; i _ CDValue.FetchInt[ boundTo: tripple.panel.design, key: intDef.cdValueKey, propagation: global, ifNotFound: intDef.default ]; IF shift THEN { IF control THEN i _ i/lambda*lambda ELSE i _ GetAnInt[i, intDef.default, intDef.text, lambda] } ELSE IF mouseButton=Menus.MouseButton[blue] THEN { IF control THEN i_i/2 ELSE i _ Dec[i, lambda] } ELSE IF mouseButton=Menus.MouseButton[red] THEN { IF control THEN i _ Double[i] ELSE i _ Inc[i, lambda] }; i _ MAX[MIN[i, intDef.max], intDef.min]; CDValue.StoreInt[ boundTo: tripple.panel.design, key: intDef.cdValueKey, value: i ]; Labels.Set[NARROW[tripple.feedback], CDExtras.ToLambda[n: i, lambda: lambda]]; END; CreateLnEntry: INTERNAL PROC [panel: Panel] = BEGIN panel.nextY _ panel.nextY+entryHSpace+entryHeight; panel.nextX _ 0; END; CreateLayerEntry: INTERNAL PROC [panel: Panel, layerDefine: REF LayerDefine] = BEGIN yoff: INT = Containers.ScrollOffset[panel.container]; p: WidthValueRef _ NEW[WidthValueRec _ WidthValueRec[layerDefine: layerDefine, panel: panel] ]; button: Buttons.Button = MBQueue.CreateButton[q: panel.design.queue, info: [ name: layerDefine.text, wx: panel.nextLayerX, wy: panel.nextLayerY+yoff, wh: entryHeight, parent: panel.container, border: FALSE ], clientData: p, proc: WireWidthCalled ]; p.numbLab _ Labels.Create[ info: [ wx: panel.nextLayerX, wy: panel.nextLayerY+shorterEntryVSpace+entryHeight+yoff, wh: entryHeight, ww: button.ww+4*entryHSpace, --2 spaces for real; 2 covering leading blank of next # parent: panel.container, border: FALSE, name: CDExtras.ToLambda[ n: CDLayers.LayerWidth[panel.design, layerDefine.layer], lambda: panel.design.technology.lambda ] ] ]; panel.nextLayerX _ button.wx+button.ww+2*entryHSpace; panel.layerWidths _ CONS[p, panel.layerWidths]; END; WireWidthCalled: Buttons.ButtonProc = BEGIN ENABLE UNWIND => NULL; wireRef: WidthValueRef = NARROW[clientData]; lev: CD.Layer = wireRef.layerDefine.layer; design: CD.Design _ wireRef.panel.design; width: CD.Number _ CDLayers.LayerWidth[design, lev]; lambda: INT _ design.technology.lambda; IF shift THEN { IF control THEN width _ width/lambda*lambda ELSE width _ GetAnInt[width, wireRef.layerDefine.default, wireRef.layerDefine.text, lambda] } ELSE IF mouseButton=Menus.MouseButton[blue] THEN { IF control THEN width _ width/2 ELSE width _ Dec[width, lambda] } ELSE IF mouseButton=Menus.MouseButton[red] THEN { IF control THEN width _ Double[width] ELSE width _ Inc[width, lambda] } ELSE IF mouseButton=Menus.MouseButton[yellow] THEN { CDLayers.SetCurrentLayer[design, lev]; RETURN }; width _ MAX[width, 0]; CDLayers.SetLayerWidth[design, lev, width]; END; DefineIntEntry: PUBLIC PROC [tech: CD.Technology, cdValueKey: REF, text: Rope.ROPE, min: INT, max: INT, default: INT] = BEGIN DefineIntEntryX[tech, cdValueKey, text, min, max, default, 1]; END; DefineIntEntryX: PUBLIC ENTRY PROC [tech: CD.Technology, cdValueKey: REF, text: Rope.ROPE, min: INT, max: INT, default: INT, lambda: INT] = BEGIN ENABLE UNWIND => NULL; class: PanelClass = GetPanelClass[tech]; def: REF IntDefine = NEW[IntDefine _ [cdValueKey: cdValueKey, text: text, min: min, max: max, default: default, lambda: lambda]]; AppendEntry[class, def]; CDValue.StoreInt[boundTo: tech, key: cdValueKey, value: default]; END; ContainerDeleted: ViewerEvents.EventProc = { WITH ViewerOps.FetchProp[viewer, $CDPanelPrivate] SELECT FROM panel: Panel => { ViewerOps.AddProp[viewer, $CDPanelPrivate, NIL]; IF panel.container=viewer AND panel.design#NIL THEN { CDValue.Store[panel.design, panelKey, NIL]; panel.container _ NIL; panel.design _ NIL; panel.class _ NIL; panel.layerLabel _ NIL; panel.layerWidths _ NIL; panel.firstLayer _ NIL; panel.labels _ NIL; }; }; ENDCASE => NULL; }; [] _ CDValue.EnregisterKey[panelKey, NIL]; [] _ CDValue.EnregisterKey[panelClassKey, NIL]; CDValue.EnregisterKey[key: $PanelHeight]; CDEvents.RegisterEventProc[$RenameDesign, RepaintCaptions]; CDEvents.RegisterEventProc[$AfterPush, RepaintCaptions]; CDEvents.RegisterEventProc[$AfterPop, RepaintCaptions]; CDLayers.RegisterNotifiers[layer: NotifyCurrentLayer, width: NotifyLayerWidth]; [] _ ViewerEvents.RegisterEventProc[ContainerDeleted, destroy, $Container]; END. €CDPanelImpl.mesa (part of ChipNDale) Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, August 8, 1983 5:20 pm last edited by Christian Jacobi, January 16, 1986 12:19:22 pm PST --only one panel-viewer per design is created --panel may or may not be updated if definitions occur after first creation --supress creation of viewer if empty -- Viewer Stuff -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --uses intermediate layer variables! --clientData: REF ANY, mouseButton: { red, yellow, blue } --clientData: REF ANY, mouseButton: { red, yellow, blue } --break circularities (for garbage collection) --module initialization Κ˜codešœ'™'Kšœ Οmœ7™BKšœ,™,KšœA™AK™—šΟk ˜ K˜ Kšžœ˜K˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜K˜ K˜ K˜ K˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœžœžœ˜K˜ K˜ Kšœ ˜ Kšœ˜K˜ —K˜šΠbl œžœžœ˜KšžœŸ˜¦Kšžœ˜Kšžœ ˜—Kšž˜K˜Kšœžœžœ˜K˜Kš œ žœžœžœžœΟc-˜LKš œžœžœžœžœ˜"K˜Kšœžœžœ˜2K˜Kšœžœžœ ˜0šœ žœžœ˜Kšœ žœ˜$Kšœ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ žœžœžœ˜)Kšœ žœž˜"Kšœžœžœžœ ž˜!Kšœ˜—K˜Kšœ žœžœ žœ˜K˜šΟnœžœžœ ˜4Kšžœ˜KšœžœF˜Lšžœžœž˜Kšœžœ˜ Kšœ/˜/Kšœ˜Kšœ7˜7Kšžœ˜Kšœ˜—Kšžœžœ ˜Kšžœ˜K˜—š‘ œžœžœ žœ˜@Kšž˜Kšžœžœžœžœ˜&šžœ˜KšœžœM˜Sšžœžœžœ˜Kšœžœžœ˜1KšœT˜TKšžœ˜Kšœ˜—Kšžœžœ˜K˜—Kšžœ˜K˜—š ‘ œžœžœžœ žœ žœ˜SKšœ-™-KšœK™Kšžœ˜Kšžœžœžœ˜—K˜ K˜:Kš žœžœžœžœžœžœ˜WKšœžœ˜Kšœžœ˜Kšœ%™%Kš žœ žœžœ žœžœ˜DKšœ˜Kšžœ˜Kšžœ˜K˜—š ‘œžœžœžœžœ˜GKšž˜Kšžœžœžœ žœ˜'šž˜šžœ*ž˜/Kš žœ žœžœžœ žœ˜8Kšžœ˜——Kšžœ˜K˜—š ‘œžœžœžœžœ˜IKšž˜š žœžœžœžœžœž˜@šžœžœžœ!žœ˜FKšžœžœžœ˜PK˜—Kšž˜—Kšžœ˜K˜—š‘œžœžœ ˜*Kšž˜Kšœ žœžœ žœ˜ š žœžœžœžœžœž˜@š žœžœžœ!žœžœ˜VKšœ žœ˜)—Kšžœ˜—Kšžœžœžœžœ˜/Kšœ˜Kšžœ˜—K˜š ‘ œžœžœžœžœ˜@Kšž˜Kšœ!˜!Kšœ#˜#Kšžœ˜K˜—š‘ œžœžœžœ˜8šžœ˜Kšžœžœžœ˜—K˜(K˜Kšžœ˜—K˜š$‘ œžœžœžœžœ žœ žœ"žœ žœžœ8žœžœ žœžœžœžœ žœžœ˜‡šžœ˜Kšžœžœžœ˜—K˜(Kšœžœ˜Kšžœ žœžœžœ˜9šœžœ˜Kšœ ˜ Kšœ8˜8Kšœ8˜8Kšœ˜—K˜Kšžœ˜K˜—š‘ œžœžœžœžœ žœ žœ žœžœžœžœ˜xšžœ˜Kšžœžœžœ˜—K˜(Kšœžœ ˜KšœžœE˜NKšœ˜Kšžœ˜K˜—š œžœžœžœ žœžœ˜BKšžœžœžœ žœžœžœžœ˜:—K˜š ‘ œžœžœžœžœ˜5Kšž˜šžœžœžœ˜%Kšžœ˜ Kšžœ˜Kšœ˜—Kšžœ˜—K˜šœ žœžœ˜Kšœžœ ˜Kšœ žœžœ˜Kšœ˜K˜K˜—šœ žœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜K˜K˜—šœžœžœ˜Kšœ žœ˜Kšœ žœ˜%Kšœ žœžœ˜Kšœ˜Kšœ žœžœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœ žœž˜Kšœ˜—K˜šœ žœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœž˜Kšœ˜—K˜Kš œžœžœžœžœžœ ˜AKšœ žœžœ˜&K˜K˜š ‘œžœžœžœ1žœ˜všžœ˜Kšžœžœžœ˜—K˜-Kšžœžœ žœžœ˜šžœžœžœ˜"Kšžœžœžœžœ1˜E—šœžœ˜+Kšœ2˜2K˜—K˜/Kšœ# œ˜XKšžœ˜K˜—šΟbœ˜/Kšž˜K˜ šžœžœžœ˜Kšœžœ'˜,Kšœ+˜+K˜—Kšžœ˜—K˜š’œ˜,Kšž˜K˜ šžœžœžœ˜š žœžœžœ.žœžœž˜Pšžœ$žœ˜,šœ˜šœ˜Kšœ'˜'Kšœ ˜ Kšœ˜—Kšœ˜—Kšžœ˜K˜—Kšžœ˜—K˜—Kšžœ˜—K˜K™Kšœ?™?K˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜!K˜K˜š‘œžœžœžœ˜2Kšž˜šžœ ˜Kšžœžœžœžœ ˜?K˜Kšœ˜K˜K˜%K˜—Kšžœ˜K˜—š‘œžœžœ˜1Kšž˜K˜š‘œžœžœ˜5Kšœ$™$Kšž˜šžœ$žœžœž˜5Kšœ˜Kšžœ˜—Kšžœ˜—K˜K˜1š žœžœžœžœžœžœž˜FKšœ3˜3Kšž˜Kšœ˜—Kšœžœ˜Kšœžœ˜Kšœ#˜#Kšœ˜Kšœ0˜0šœ%˜%K˜šœ˜KšœQ˜Q—Kšœ žœ˜KšœAžœ˜HKšœ*˜*K˜ K˜—Kšœ;˜;K˜(šœ*˜*Kšœ˜Kšœ5˜5Kšœ ˜ Kšœ˜—K˜Kšœ!˜!Kšœ*˜*K˜Kšœ˜Kšœ˜šžœžœžœ˜Kšœ?˜?—Kšžœ˜K˜—š‘œžœžœžœ˜3Kšž˜Kšžœžœžœ˜)šžœžœž˜šœ žœ˜!Kšžœžœžœ ˜šœžœ˜ šžœž˜ Kšœ#˜#Kšžœžœ˜—K˜—Kšžœžœ˜—Kšžœ˜—K˜š‘œžœ˜+Kšž˜K˜ šžœžœžœ˜K˜&K˜0K˜—šžœ˜K˜——šœžœžœ˜Kšœ žœ˜K˜Kšœž˜K˜—Kšœžœžœ˜(K˜š‘ œžœžœ˜,Kš œ žœ$žœžœžœžœžœ˜^Kšž˜Kšœžœ,˜5šœD˜D˜K˜Kšœ˜Kšœ˜K˜K˜K˜—K˜K˜ K˜—K˜.Kšžœ˜K˜—š‘ œžœžœžœ(žœžœžœ žœžœ žœžœžœ˜ΏKšž˜Kšœžœ,˜5Kšœžœ˜Kšœžœ˜Kšžœ žœ!˜0šœ˜˜K˜Kšœ ˜ K˜K˜Kšœ˜K˜—K˜K˜ K˜—Kšžœ žœ5˜DKšžœ.˜2Kšžœ˜K˜—š‘ œžœžœžœ žœžœžœžœžœ˜œKšž˜Kšœžœ,˜5K˜Kšžœžœžœ˜"šžœž˜Kšœ+˜+Kšœ˜Kšžœ˜—˜˜K˜(Kšœ˜K˜K˜K˜K˜—K˜—K˜,Kšžœ˜Kšžœ˜K˜—š‘œžœžœžœ ˜EKšž˜Kšœžœ˜Kšœžœ žœ+˜DKšœžœ˜Kšžœ žœ)˜:KšœZ˜Zšœ!˜!šœ˜K˜Kšœ˜Kšœ˜K˜K˜—Kšœ˜Kšœ˜—KšœM˜MKšžœ˜—K˜Kš œ žœžœžœžœ žœžœ˜NK˜š ‘œžœžœžœ žœ˜jKšž˜šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šžœžœžœ˜Kšœ žœ:˜GKšœžœ˜+Kšœ˜K˜—Kšžœ˜—K˜š‘œžœ žœ ˜-Kšž˜Kšžœ žœžœžœ˜šžœžœžœ˜ šœžœ˜šœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ žœ/˜@Kšœ˜—šœžœ˜šœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœžœ/˜EKšœ˜—šžœ˜ šžœžœž˜!Kšœžœ˜#Kšžœžœ˜———Kšžœ˜—K˜š‘œžœžœ žœ ˜2Kšž˜K˜ Kš žœžœžœžœžœ˜@š žœžœžœžœ#žœžœž˜IKšœ˜Kšž˜—Kšžœ˜—K˜š‘œžœžœžœ˜IKšž˜šœ!˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ žœ*˜9Kšœ˜—šžœžœžœ˜Kšœ žœ žœ:˜TKšœžœ˜+Kšœ˜K˜—Kšžœ˜—K˜š’ œ˜"Kšž˜Kšœ žœ žœ ˜*Kšœžœžœ˜2šœžœ˜8Kšœ˜Kšœ˜Kšœ˜—šžœ žœž˜KšœK˜K—šžœžœž˜KšœU˜U—Kšžœ˜—K˜š ‘œžœžœžœžœžœ˜-Kšžœžœžœžœžœžœžœ ˜3Kšžœ˜ K˜K˜—š‘œžœžœžœžœžœžœ˜4Kšžœžœžœžœ ˜Kšžœ˜ K˜K˜—š‘œžœžœžœžœžœžœ˜4Kšžœžœžœžœ ˜ Kšžœ˜ K˜K˜—š‘œžœžœžœ žœžœžœ˜Xšž˜Kšžœžœ ˜,—Kšœžœžœžœ˜Kšœ ˜ šžœ žœ˜Kšœ žœ,˜9—šžœ˜Kšœ žœA˜N—šžœ;ž˜EKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ;˜;Kšœ:˜:Kšœ˜Kšžœ&˜-—Kšžœ žœ˜Kšžœ˜—š’ œžœ˜%Kšœ9™9šžœ˜Kšžœžœžœ˜—Kšœžœ˜Kšœ žœ žœ ˜*Kšœžœ žœ˜/Kšœžœ˜Kšžœ žœ1˜B˜Kšœ˜Kšœ˜Kšœ˜K˜K˜—šžœžœ˜Kšžœ žœ˜$Kšžœ5˜9K˜—šžœžœ%žœ˜3Kšžœ žœžœ˜-Kšœ˜—šžœžœ$žœ˜2Kšžœ žœžœ˜5Kšœ˜—Kšœžœžœ˜(˜Kšœ˜Kšœ˜K˜K˜—Kšœ žœ=˜NKšžœ˜K˜—š‘ œžœžœ˜-Kšž˜K˜2K˜Kšžœ˜K˜—š‘œžœžœžœ˜NKšž˜Kšœžœ,˜5šœžœ˜'Kšœ5˜5Kšœ˜—šœD˜D˜K˜Kšœ˜K˜K˜Kšœž˜ K˜—K˜Kšœ˜K˜—šœ˜˜K˜Kšœ9˜9K˜Kšœ 8˜TK˜Kšœž˜šœ˜Kšœ8˜8Kšœ&˜&Kšœ˜—Kšœ˜—K˜—Kšœ6˜6Kšœžœ˜/Kšžœ˜K˜—š’œ˜%Kšœ9™9šž˜Kšžœžœžœ˜—Kšœžœ ˜,Kšœžœ#˜*Kšœ)˜)Kšœžœ+˜4Kšœžœ˜'šžœžœ˜Kšžœ žœ˜,KšžœW˜[K˜—šžœžœ%žœ˜2Kšžœ žœžœ˜?Kšœ˜—šžœžœ$žœ˜2Kšžœ žœžœ˜EKšœ˜—šžœžœ'žœ˜4Kšœ&˜&Kšž˜Kšœ˜—Kšœžœ ˜Kšœ+˜+Kšžœ˜—K˜š‘œžœžœžœžœ žœžœžœ žœ˜wKšž˜Kšœ>˜>šžœ˜K˜——š‘œžœžœžœžœžœ žœžœžœ žœ žœ˜‹šžœ˜Kšžœžœžœ˜—K˜(Kšœžœ žœi˜K˜KšœA˜AKšžœ˜—K˜š’œ˜,Kšœ.™.šžœ.žœž˜=šœ˜Kšœ+žœ˜0šžœžœžœžœ˜5Kšœ&žœ˜+Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜—K˜—Kšžœžœ˜—K˜—K™Kšœ™Kšœ%žœ˜*Kšœ*žœ˜/Kšœ)˜)K˜;K˜8K˜7KšœO˜OKšœK˜KKšžœ˜K˜K˜—…—LiΎ