CDStretchCommands.mesa (part of ChipNDale)
Copyright © 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi, July 11, 1983 3:42 pm
last edited Christian Jacobi, November 12, 1985 11:00:42 am PST
DIRECTORY
CD,
CDInstances,
CDBasics,
CDCallSpecific,
CDSequencer,
CDOps,
CDOrient,
CDProperties,
CDValue,
IO,
TerminalIO;
CDStretchCommands:
CEDAR
PROGRAM
IMPORTS CDInstances, CDBasics, CDOps, CDOrient, CDProperties, CDSequencer, CDValue, IO, TerminalIO =
BEGIN
StretchApplication:
PROC [design:
CD.Design, inst:
CD.Instance, orientInPlane:
CD.Orientation, amount:
CD.Number]
RETURNS [include:
CD.InstanceList←
NIL, removeMe:
BOOL←
FALSE] =
-- orientInPlane:
-- at position "original" the bottom edge [(0, 0), (1, 0)] is streched
-- mirroring is ignored
-- amount>0 ==> grow in direction orientInPlane
-- amount<0 ==> shrink on edge orientInPlane
BEGIN
CallSpecific:
PROC [design:
CD.Design, inst:
CD.Instance, x:
REF, objectSpecific:
REF]
RETURNS [done:
BOOL←
FALSE, removeMe:
BOOL←
FALSE, include:
CD.InstanceList←
NIL,
repaintMe: BOOL←FALSE, repaintInclude: BOOL←FALSE] =
BEGIN
IF objectSpecific#
NIL
THEN
BEGIN
class: REF = CDProperties.GetProp[inst.ob.class.properties, objectSpecific];
IF class#
NIL
AND
ISTYPE[class,
REF CDCallSpecific.CallProc]
THEN
BEGIN
[done: done,
removeMe: removeMe,
include: include,
repaintMe: repaintMe,
repaintInclude: repaintInclude] ← NARROW[class, REF CDCallSpecific.CallProc]^[design, inst, x]
END;
END;
END;
appOrient, orientInObject: CD.Orientation;
done, repaintMe, repaintInclude: BOOL;
offset: REF CD.Position ← NEW[CD.Position←[0, 0]];
--ignore mirroring and 45 degrees
orientInPlane ← CDOrient.ConcentrateOnRotate90[orientInPlane];
appOrient ← CDOrient.ConcentrateOnRotate90[inst.orientation];
orientInObject ← CDOrient.DecomposeOrient[
itemOrientInWorld: orientInPlane,
cellOrientInWorld: appOrient
];
IF CDOrient.IncludesOddRot90[orientInObject] THEN offset.x𡤊mount ELSE offset.y𡤊mount;
CDOps.DelayedRedraw[design, CDInstances.InstRectO[inst]];
[done, removeMe, include, repaintMe, repaintInclude] ← CallSpecific[design, inst, offset , $Lengthen];
IF done
THEN {
SELECT CDOrient.ConcentrateOnRotate90[orientInPlane]
FROM
CDOrient.original => {
inst.location.y ← inst.location.y-amount;
IF include#NIL THEN CDInstances.TranslateList[include, [0, -amount]]
};
CDOrient.rotate90 => NULL;
CDOrient.rotate180 => NULL;
CDOrient.rotate270 => {
inst.location.x ← inst.location.x-amount;
IF include#NIL THEN CDInstances.TranslateList[include, [-amount, 0]]
};
ENDCASE => ERROR;
CDOps.DelayedRedraw[design, CDInstances.InstRectO[inst]];
};
END;
SelectBorder:
PROC [r:
CD.Rect, pos:
CD.Position]
RETURNS [orient:
CD.Orientation] =
BEGIN
dx1, dx2, dy1, dy2: CD.Number;
r ← CDBasics.Extend[r, 200];
dx1 ← ABS[r.x1-pos.x];
dx2 ← ABS[r.x2-pos.x];
dy1 ← ABS[r.y1-pos.y];
dy2 ← ABS[r.y2-pos.y];
IF (pos.x
IN [r.x1..r.x2])
OR pos.y
IN [r.y1..r.y2]
THEN {
IF dx1<=dx2
THEN
--left
IF dy1<=dy2
THEN
--down
IF dx1<=dy1 THEN orient ← CDOrient.rotate270
ELSE orient ← CDOrient.original
ELSE
--top
IF dx1<=dy2 THEN orient ← CDOrient.rotate270
ELSE orient ← CDOrient.rotate180
ELSE
--right
IF dy1<=dy2
THEN
--down
IF dx2<=dy1 THEN orient ← CDOrient.rotate90
ELSE orient ← CDOrient.original
ELSE
--top
IF dx2<=dy2 THEN orient ← CDOrient.rotate90
ELSE orient ← CDOrient.rotate180
}
ELSE
--outside enough-- {
orient ← CDOrient.original
}
END;
DetermineDirection:
PROC [sampleApp:
CD.Instance, from, to:
CD.Position]
RETURNS [amount:
CD.Number, orientInPlane:
CD.Orientation] =
--given a sample application and a vector, determine in what absolute direction and how much
--a stretch should be
--must: sampleApp#NIL
BEGIN
r: CD.Rect = CDInstances.InstRectI[sampleApp];
IF
ABS[to.x-from.x]>
ABS[to.y-from.y]
THEN {
--horizontal stretch vector
IF
ABS[r.x1-from.x] <
ABS[r.x2-from.x]
THEN {
--left edge--
amount ← from.x-to.x;
orientInPlane ← CDOrient.rotate270
}
ELSE {
--right edge--
amount ← to.x-from.x;
orientInPlane ← CDOrient.rotate90
}
}
ELSE {
--vertical stretch vector
IF
ABS[r.y1-from.y] <
ABS[r.y2-from.y]
THEN {
--near to origin (bottom) edge--
amount ← from.y-to.y;
orientInPlane ← CDOrient.original
}
ELSE {
--far from origin (top) edge--
amount ← to.y-from.y;
orientInPlane ← CDOrient.rotate180
}
};
END;
FixDirection:
PROC [r:
CD.Rect, pos:
CD.Position, dir:
CD.Orientation, dirAmount:
CD.Number]
RETURNS [amount:
CD.Number, orientInPlane:
CD.Orientation] =
--must: sampleApp#NIL
BEGIN
Fiddle:
PROC [] = {
amount ← -amount;
orientInPlane ← CDOrient.ComposeOrient[orientInPlane, CDOrient.rotate180];
};
mouseRight: BOOL = ABS[r.x1-pos.x] > ABS[r.x2-pos.x];
mouseUp: BOOL = ABS[r.y1-pos.y] > ABS[r.y2-pos.y];
amount ← dirAmount;
orientInPlane ← dir;
SELECT dir
FROM
CDOrient.rotate270 --left-- => IF mouseRight THEN Fiddle[];
CDOrient.rotate90 --right-- => IF ~mouseRight THEN Fiddle[];
CDOrient.original --down-- =>IF mouseUp THEN Fiddle[];
CDOrient.rotate180 --up-- => IF ~mouseUp THEN Fiddle[];
ENDCASE => ERROR;
END;
DoAStretch:
PROC [design:
CD.Design, from, to:
CD.Position, growAsToX:
BOOL←
FALSE, edgeInOrient:
BOOL←
FALSE, orient:
CD.Orientation←
CD.original] =
BEGIN
pointedAp: CD.Instance;
orientInPlane: CD.Orientation;
amount: CD.Number;
include: CD.InstanceList;
removeMe: BOOL;
removeList, includeList: CD.InstanceList←NIL;
count: NAT ← 0;
IF growAsToX AND edgeInOrient THEN ERROR;
IF ~growAsToX
AND ~edgeInOrient AND from=to
THEN {
TerminalIO.WriteRope[" null stretch\n"];
RETURN
};
pointedAp ← CDInstances.InstanceAt[il: CDOps.InstList[design], pos: from, selectedOnly: TRUE];
IF pointedAp=
NIL
THEN {
TerminalIO.WriteRope[" no selected object pointed\n"];
RETURN
};
IF growAsToX
THEN {
amount←to.x;
orientInPlane ← SelectBorder[CDInstances.InstRectI[pointedAp], from]
}
ELSE IF edgeInOrient THEN [amount, orientInPlane] ← FixDirection[CDInstances.InstRectI[pointedAp], from, orient, to.x]
ELSE [amount, orientInPlane] ← DetermineDirection[pointedAp, from, to];
FOR list:
CD.InstanceList ← CDOps.InstList[design], list.rest
WHILE list#
NIL
DO
IF list.first.selected
THEN {
count ← count+1;
[include, removeMe] ← StretchApplication[design, list.first, orientInPlane, amount];
IF removeMe THEN removeList ← CONS[list.first, removeList];
IF include#NIL THEN includeList ← CDInstances.AppendToList[include, includeList];
}
ENDLOOP;
RemoveAppList[design, removeList];
CDOps.IncludeInstanceList[design, includeList];
TerminalIO.WriteF1["%g objects tried to stretch\n", IO.int[count]];
END;
RemoveAppList:
PROC [design:
CD.Design, appList:
CD.InstanceList, draw:
BOOL←
TRUE] =
BEGIN
FOR list:
CD.InstanceList ← appList, list.rest
WHILE list#
NIL
DO
CDOps.RemoveInstance[design, list.first, draw];
ENDLOOP;
END;
StretchCommandS:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch selected"];
DoAStretch[design: comm.design, from: comm.sPos, to: comm.pos]
END;
StepValue:
PROC [comm: CDSequencer.Command]
RETURNS [n:
CD.Number] =
BEGIN
n ← CDValue.FetchInt[boundTo: comm.design, key: $CDxStepValue, propagation: global];
IF n<=0 THEN n ← comm.design.technology.lambda
END;
GrowStepSCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["grow selected"];
DoAStretch[design: comm.design, from: comm.pos, to: [StepValue[comm], 0], growAsToX: TRUE ]
END;
ShrinkStepSCommand:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["shrink selected"];
DoAStretch[design: comm.design, from: comm.pos, to: [-StepValue[comm], 0], growAsToX: TRUE ]
END;
StretchStepLeftCommandS:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step selected left"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm], 0], edgeInOrient: TRUE, orient: CDOrient.rotate270]
END;
StretchStepRightCommandS:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step selected right"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm], 0], edgeInOrient: TRUE, orient: CDOrient.rotate90]
END;
StretchStepUpCommandS:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step selected up"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm], 0], edgeInOrient: TRUE, orient: CDOrient.rotate180]
END;
StretchStepDownCommandS:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step selected down"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm], 0], edgeInOrient: TRUE, orient: CDOrient.original]
END;
CDSequencer.ImplementCommand[$StretchS, StretchCommandS];
CDSequencer.ImplementCommand[$GrowStepS, GrowStepSCommand];
CDSequencer.ImplementCommand[$ShrinkStepS, ShrinkStepSCommand];
CDSequencer.ImplementCommand[$StretchStepLeftS, StretchStepLeftCommandS];
CDSequencer.ImplementCommand[$StretchStepRightS, StretchStepRightCommandS];
CDSequencer.ImplementCommand[$StretchStepUpS, StretchStepUpCommandS];
CDSequencer.ImplementCommand[$StretchStepDownS, StretchStepDownCommandS];
END.