<> <> <> <> DIRECTORY BasicTime, CD, CDInstances, CDBasics, CDSimpleOps, CDCommandOps, CDOps, CDOrient, CDSequencer, TerminalIO; CDSelectCommands: CEDAR PROGRAM IMPORTS BasicTime, CDInstances, CDBasics, CDCommandOps, CDSimpleOps, CDOps, CDSequencer, TerminalIO = BEGIN SelectExclusive: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Select pointed"]; CDSimpleOps.DeselectAll[comm.design]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.WriteLn[]; END; ReSelectExclusive: PROC [design: CD.Design, pos: CD.Position, verbose: BOOL_TRUE] RETURNS [done: BOOL_TRUE] = BEGIN Deselect: PROC[a: CD.Instance] = INLINE BEGIN IF a.selected THEN { a.selected _ FALSE; CDCommandOps.RedrawInstance[design, a] } END; DeselectList: PROC[list: CD.InstanceList] = BEGIN FOR w: CD.InstanceList _ list, w.rest WHILE w#NIL DO Deselect[w.first] ENDLOOP END; ap: CD.Instance _ NIL; --any application where pos points to FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF CDInstances.PointToI[pos, w.first] THEN { <<--hit>> IF w.first.selected THEN { DeselectList[w.rest]; CDOps.ReOrderInstance[design, w.first]; IF verbose THEN CDCommandOps.WriteInfo[w.first]; RETURN } ELSE IF ap=NIL THEN ap _ w.first } ELSE Deselect[w.first] ENDLOOP; <<--if a selected ap is pointed we already did return>> IF ap#NIL THEN { ap.selected _ TRUE; CDOps.ReOrderInstance[design, ap]; CDCommandOps.RedrawInstance[design, ap, FALSE]; IF verbose THEN CDCommandOps.WriteInfo[ap] } ELSE { done _ FALSE; IF verbose THEN TerminalIO.WriteRope[" (no object)"]; } END; RectDist: PROC[pos: CD.Position, r: CD.Rect] RETURNS [CD.Number] = <<--Distance between a point and a rectangle>> BEGIN RETURN [MAX[ (IF pos.xr.x2 THEN (pos.x-r.x2) ELSE 0), (IF pos.yr.y2 THEN (pos.y-r.y2) ELSE 0) ]] END; CloseReSelectExclusive: PROC [design: CD.Design, pos: CD.Position, verbose: BOOL_TRUE, dist: CD.Number_100] = BEGIN IF ~ReSelectExclusive[design, pos, verbose] THEN { ap: CD.Instance _ NIL; FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO d: CD.Number = RectDist[pos, CDInstances.InstRectI[w.first]]; IF d> <<--(but dont select an other application if the pointed one is already the right one)>> BEGIN TerminalIO.WriteRope["Select"]; [] _ ReSelectExclusive[comm.design, comm.pos]; TerminalIO.WriteLn[]; END; --crazy heuristics to determine which kind of selection is wanted lastPos: CD.Position; lastA: REF _ NIL; lastTime: BasicTime.GMT _ BasicTime.earliestGMT; SameAsLast: PROC[comm: CDSequencer.Command] RETURNS [yes: BOOL] = BEGIN lambda: CD.Number = comm.design.technology.lambda; ReallyClose: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE { RETURN [ABS[p1.x-p2.x]<=lambda AND ABS[p1.y-p2.y]<=lambda] }; now: BasicTime.GMT _ BasicTime.Now[]; yes _ ReallyClose[lastPos, comm.pos] AND lastA=comm.a AND BasicTime.Period[lastTime, now]<=2; lastPos _ comm.pos; lastA _ comm.a; lastTime _ now; END; CloseReSelectComm: PROC [comm: CDSequencer.Command] = <<--select pointed application exclusive;>> <<--(but dont select an other application if the pointed one is already the right one)>> <<--if there is none, select closest>> <<--cycle through if exactly sme position>> BEGIN TerminalIO.WriteRope["select "]; IF SameAsLast[comm] THEN CDSimpleOps.DeselectAll[comm.design]; [] _ CloseReSelectExclusive[comm.design, comm.pos, TRUE, 50]; TerminalIO.WriteLn[]; END; MultiOnlySelectComm: PROC [comm: CDSequencer.Command] = BEGIN NotRect: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE BEGIN RETURN [ABS[p1.x-p2.x]<=lambda OR ABS[p1.y-p2.y]<=lambda] END; lambda: CD.Number = comm.design.technology.lambda; IF NotRect[comm.pos, comm.sPos] THEN CloseReSelectComm[comm] ELSE AreaOnlySelect[comm]; END; DoubleAddSelectComm: PROC [comm: CDSequencer.Command] = BEGIN IF SameAsLast[comm] THEN { TerminalIO.WriteRope["Change selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; } ELSE TerminalIO.WriteRope["Add selection "]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.WriteLn[]; END; DeselectPointed: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Remove selection "]; CDSimpleOps.DeSelect[comm.design, comm.pos]; TerminalIO.WriteLn[]; END; DeSelectLast: PROC [design: CD.Design, pos: CD.Position, usePos: BOOL_TRUE] RETURNS [done: BOOL_FALSE] = BEGIN sel: CD.Instance _ NIL; FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF w.first.selected THEN { IF ~usePos OR CDInstances.PointToI[pos, w.first] THEN sel _ w.first; }; ENDLOOP; IF sel#NIL THEN { sel.selected _ FALSE; done _ TRUE; CDCommandOps.RedrawInstance[design, sel] } END; DeselectLastSelected: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Remove selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; TerminalIO.WriteLn[]; END; AddSelection: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Add selection "]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.WriteLn[]; END; DeselectAll: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Deselect all\n"]; CDSimpleOps.DeselectAll[comm.design] END; DeleteSelected: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Delete selected\n"]; CDSimpleOps.DeleteSelected[comm.design] END; SelectAll: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Select all\n"]; CDSimpleOps.SelectAll[comm.design] END; AreaAddSelect: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Inclusive select area\n"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] END; MultiAddSelect: PROC [comm: CDSequencer.Command] = <<--Auto select area or pointed or changed>> BEGIN NotRect: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE BEGIN RETURN [ABS[p1.x-p2.x]<=lambda OR ABS[p1.y-p2.y]<=lambda] END; lambda: CD.Number = comm.design.technology.lambda; IF NotRect[comm.pos, comm.sPos] THEN DoubleAddSelectComm[comm] ELSE { TerminalIO.WriteRope["select inclusive area\n"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] } END; AreaAddSelectTouching: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["select inclusive touching\n"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] END; AreaOnlySelect: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Select area\n"]; CDSimpleOps.DeselectAll[comm.design]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] END; ADeSelect: PROC [comm: CDSequencer.Command] = <<--Auto deselect area or pointed>> BEGIN TerminalIO.WriteRope["Deselect "]; IF comm.pos=comm.sPos THEN CDSimpleOps.DeSelect[comm.design, comm.pos] ELSE CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]]; TerminalIO.WriteLn[]; END; AreaDeSelect: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Deselect area\n"]; CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] END; AreaDeSelectTouching: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Deselect touching\n"]; CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] END; CDSequencer.ImplementCommand[$OnlySelectP, SelectExclusive,, doQueue]; CDSequencer.ImplementCommand[$ReSelectOnlyP, ReSelectExclusiveComm,, doQueue]; CDSequencer.ImplementCommand[$CloseReSelectOnlyP, CloseReSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AddSelectP, AddSelection,, doQueue]; CDSequencer.ImplementCommand[$DeSelectLP, DeselectLastSelected,, doQueue]; CDSequencer.ImplementCommand[$DeSelectFP, DeselectPointed,, doQueue]; CDSequencer.ImplementCommand[$DeSelectS, DeselectAll,, doQueue]; CDSequencer.ImplementCommand[$SelectAll, SelectAll,, doQueue]; CDSequencer.ImplementCommand[$AreaOnlySelect, AreaOnlySelect,, doQueue]; CDSequencer.ImplementCommand[$MultiOnlySelect, MultiOnlySelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelect, AreaAddSelect,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelectTouching, AreaAddSelectTouching,, doQueue]; CDSequencer.ImplementCommand[$MultiAddSelect, MultiAddSelect,, doQueue]; CDSequencer.ImplementCommand[$DoubleAddSelect, DoubleAddSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelect, AreaDeSelect,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelectTouching, AreaDeSelectTouching,, doQueue]; CDSequencer.ImplementCommand[$ADeSelect, ADeSelect,, doQueue]; END.