CDSelectCommands.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
Christian Jacobi, June 29, 1983 4:44 pm
last edited Christian Jacobi, June 11, 1985 10:16:46 am PDT
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.x<r.x1 THEN (r.x1-pos.x) ELSE IF pos.x>r.x2 THEN (pos.x-r.x2) ELSE 0),
(IF pos.y<r.y1 THEN (r.y1-pos.y) ELSE IF pos.y>r.y2 THEN (pos.y-r.y2) ELSE 0)
]]
END;
CloseReSelectExclusive:
PROC [design:
CD.Design, pos:
CD.Position, verbose:
BOOL←
TRUE, dist:
CD.Number] =
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<dist THEN {ap ← w.first; dist ← d}
ENDLOOP;
IF ap#
NIL
THEN {
ap.selected ← TRUE;
CDCommandOps.RedrawInstance[design, ap, FALSE];
IF verbose
THEN {
TerminalIO.WriteRope[" found close object"];
CDCommandOps.WriteInfo[ap]
}
}
}
END;
ReSelectExclusiveComm:
PROC [comm: CDSequencer.Command] =
--select pointed application exclusive;
--(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
ReallyClose:
PROC [p1, p2:
CD.Position]
RETURNS [
BOOL] =
INLINE {
RETURN [ABS[p1.x-p2.x]<=CD.lambda AND ABS[p1.y-p2.y]<=CD.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]<=CD.lambda OR ABS[p1.y-p2.y]<=CD.lambda]
END;
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]<=CD.lambda OR ABS[p1.y-p2.y]<=CD.lambda]
END;
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.