<> <> <> <> <> <<>> DIRECTORY CD, CDCells, CDDirectory, CDEvents, CDCommandOps, CDMenus, CDOps, CDPanelFonts, CDProperties, CDSatellites, CDSequencer, CDTexts, IO, PW, TerminalIO; CDSatellitesImpl: CEDAR PROGRAM IMPORTS CDCells, CDDirectory, CDEvents, CDCommandOps, CDMenus, CDOps, CDPanelFonts, CDProperties, CDTexts, IO, PW, TerminalIO EXPORTS CDSatellites = BEGIN OPEN CDSatellites; satellitesProp: ATOM _ PW.RegisterProp[$CDSatellites, TRUE]; <> <<>> <> SetSatellites: PUBLIC PROC [master: CD.Instance, satellites: ObList _ NIL] = { CDProperties.PutPropOnInstance[master, satellitesProp, satellites]; }; <<>> AddSatellites: PUBLIC PROC [master: CD.Instance, satellites: ObList _ NIL] = { s: ObList _ NARROW[CDProperties.GetPropFromInstance[master, satellitesProp]]; FOR l: ObList _ satellites, l.rest WHILE l#NIL DO s _ CONS[l.first, s] ENDLOOP; CDProperties.PutPropOnInstance[master, satellitesProp, s]; }; GetSatellites: PUBLIC PROC [master: CD.Instance] RETURNS [satellites: ObList _ NIL] = { satellites _ NARROW [CDProperties.GetPropFromInstance[master, satellitesProp]]; }; GetSatelliteRopes: PUBLIC PROC [masterProps: CD.PropList] RETURNS [ropes: LIST OF ROPE _ NIL] = { FOR list: ObList _ NARROW [CDProperties.GetPropFromList[masterProps, satellitesProp]], list.rest WHILE list#NIL DO rope: ROPE _ NARROW [list.first.specificRef, CDTexts.TextPtr].text; ropes _ CONS [rope, ropes]; ENDLOOP; }; EnforceConstraint: PUBLIC PROC [world: LIST OF CD.Instance] RETURNS [allOk: BOOL] = { allOk _ TRUE; FOR iList: LIST OF CD.Instance _ world, iList.rest WHILE iList#NIL DO oldObList: ObList _ NARROW [CDProperties.GetProp[iList.first, satellitesProp]]; newObList: ObList _ NIL; thisOk: BOOL _ TRUE; FOR oList: ObList _ oldObList, oList.rest WHILE oList#NIL DO IF ExistsInstance[oList.first, world] THEN newObList _ CONS[oList.first, newObList] ELSE thisOk _ FALSE ENDLOOP; IF ~thisOk THEN { CDProperties.PutProp[iList.first, satellitesProp, newObList]; allOk _ FALSE}; ENDLOOP; }; <> satelliteUniqueIDProp: ATOM _ PW.RegisterProp[$CDSatelliteUniqueID, TRUE]; <> BeforeOutput: CDEvents.EventProc = { id: INT _ 0; AddIDOnWorld: PROC [world: CD.InstanceList] = { FOR list: CD.InstanceList _ world, list.rest WHILE list#NIL DO satellites: ObList _ GetSatellites[list.first]; ref: REF INT; IF satellites=NIL THEN LOOP; ref _ NEW [INT _ id]; id _ id + 1; CDProperties.PutPropOnInstance[list.first, satelliteUniqueIDProp, ref]; FOR sats: ObList _ satellites, sats.rest WHILE sats#NIL DO CDProperties.PutPropOnObject[sats.first, satelliteUniqueIDProp, ref]; ENDLOOP; ENDLOOP; }; AddID: CDDirectory.EachEntryAction = { IF ~CDCells.IsCell[ob] THEN RETURN; AddIDOnWorld[NARROW [ob.specificRef, CD.CellPtr].contents]; }; [] _ CDDirectory.Enumerate[design, AddID]; AddIDOnWorld[CDOps.InstList[design]]; }; AfterInput: CDEvents.EventProc = { UseIDOnWorld: PROC [world: CD.InstanceList] = { FOR list: CD.InstanceList _ world, list.rest WHILE list#NIL DO master: CD.Instance _ list.first; satellites: ObList _ NIL; refInt: REF INT _ NARROW [CDProperties.GetPropFromInstance[master, satelliteUniqueIDProp]]; IF refInt=NIL THEN LOOP; FOR sats: CD.InstanceList _ world, sats.rest WHILE sats#NIL DO sat: CD.Object _ sats.first.ob; satRefInt: REF INT _ NARROW [CDProperties.GetPropFromObject[sat, satelliteUniqueIDProp]]; IF satRefInt=NIL OR satRefInt^#refInt^ THEN LOOP; IF ~Member[satellites, sat] THEN satellites _ CONS [sat, satellites]; ENDLOOP; SetSatellites[master, satellites]; ENDLOOP; }; UseID: CDDirectory.EachEntryAction = { IF ~CDCells.IsCell[ob] THEN RETURN; UseIDOnWorld[NARROW [ob.specificRef, CD.CellPtr].contents]; }; [] _ CDDirectory.Enumerate[design, UseID]; UseIDOnWorld[CDOps.InstList[design]]; }; <<>> <> AfterCellReplacement: CDEvents.EventProc = { ob: CD.Object _ NARROW [x]; [] _ EnforceConstraint[NARROW[ob.specificRef, CD.CellPtr].contents]; }; <> <> SelectGroupCommand: PROC [comm: CDSequencer.Command] = { world: CD.InstanceList _ CDOps.InstList[comm.design]; multiple: BOOL; selected: CD.Instance; numSats: INT; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~SingleSelected[selected, multiple] THEN RETURN; IF CDTexts.IsText[selected.ob] THEN numSats _ SelectGroup[comm.design, world, FindMaster[world, selected.ob]] ELSE numSats _ SelectGroup[comm.design, world, selected]; TerminalIO.WriteF["Group selected: %g satellites(s) in group\n", IO.int[numSats]]; }; <> AddSatelliteCommand: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; name: ROPE; font: CDTexts.CDFont _ CDPanelFonts.CurrentFont[comm.design]; text: CD.Object; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~SingleSelected[selected, multiple] THEN RETURN; IF CDTexts.IsText[selected.ob] THEN { TerminalIO.WriteRope["\n** Selected instance is text--can't put a satellite on it.\n"]; RETURN; }; name _ TerminalIO.RequestRope["Type Satellite: "]; IF name=NIL THEN {TerminalIO.WriteRope["\n** Empty name--can't do it.\n"]; RETURN}; IF font=NIL THEN {TerminalIO.WriteRope["\n** No current font--can't do it.\n"]; RETURN}; text _ CDTexts.CreateText[name, font]; CDOps.AddAnObject[design: comm.design, ob: text, location: comm.pos, orientation: 0]; AddSatellites[selected, LIST[text]]; TerminalIO.WriteRope["Satellite added\n"]; }; <<>> <> SetSatellitesCommand: PROC [comm: CDSequencer.Command] = { world: CD.InstanceList _ CDOps.InstList[comm.design]; satellites: ObList _ NIL; master: CD.Instance _ NIL; FOR list: CD.InstanceList _ world, list.rest WHILE list#NIL DO instance: CD.Instance _ list.first; IF ~instance.selected THEN LOOP; IF CDTexts.IsText[instance.ob] THEN { IF Member[satellites, instance.ob] THEN LOOP; <> IF FindMaster[world, instance.ob]#NIL THEN { [] _ SelectGroup[comm.design, world, FindMaster[world, instance.ob]]; TerminalIO.WriteRope["\n** Some satellite is already in another group, which is now shown selected--not done.\n"]; RETURN; }; satellites _ CONS [instance.ob, satellites]; } ELSE { IF master#NIL THEN { TerminalIO.WriteRope["\n** More than one master selected--can't do it.\n"]; RETURN; }; master _ instance; }; ENDLOOP; IF master=NIL THEN { TerminalIO.WriteRope["\n** No master selected--can't do it.\n"]; RETURN; }; SetSatellites[master, satellites]; TerminalIO.WriteRope["Satellites set\n"]; }; <> EnforceSatelliteConstraintCommand: PROC [comm: CDSequencer.Command] = { ok: BOOL _ EnforceConstraint[CDOps.InstList[comm.design]]; IF ok THEN TerminalIO.WriteRope["Satellite constraint ok.\n"] ELSE TerminalIO.WriteRope["Satellite constraint NOT ok--enforcing it.\n"]; }; <<>> <> ExistsInstance: PROC [ob: CD.Object, world: LIST OF CD.Instance] RETURNS [BOOL] = { FOR iList: LIST OF CD.Instance _ world, iList.rest WHILE iList#NIL DO IF iList.first.ob=ob THEN RETURN [TRUE] ENDLOOP; RETURN [FALSE] }; Member: PROC [objects: ObList, object: CD.Object] RETURNS [BOOL _ FALSE] = { WHILE objects#NIL DO IF objects.first=object THEN RETURN [TRUE]; objects _ objects.rest; ENDLOOP; }; FindMaster: PROC [world: LIST OF CD.Instance, satellite: CD.Object] RETURNS [master: CD.Instance _ NIL] = { FOR list: CD.InstanceList _ world, list.rest WHILE list#NIL DO IF Member[GetSatellites[list.first], satellite] THEN RETURN [list.first]; ENDLOOP; }; SingleSelected: PROC [selected: CD.Instance, multiple: BOOL] RETURNS [BOOL] = { IF selected=NIL THEN { TerminalIO.WriteRope["\n** No current selection--can't do it.\n"]; RETURN[FALSE]; }; IF multiple THEN { TerminalIO.WriteRope["\n** Multiple instances selected--can't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; <<>> <