CDStretchCommands.mesa (part of Chipndale)
by Christian Jacobi July 11, 1983 3:42 pm
last edited Christian Jacobi February 14, 1984 4:05 pm
DIRECTORY
CD,
CDApplications,
CDSequencer,
CDCallSpecific,
CDInline,
CDObjectProcs,
CDOps,
CDOrient,
CDValue,
TerminalIO;
CDStretchCommands: CEDAR PROGRAM
IMPORTS CDApplications, CDInline, CDObjectProcs, CDOps, CDOrient, CDSequencer, CDValue, TerminalIO =
BEGIN
StretchApplication: PROC [design: CD.Design, aptr: CD.ApplicationPtr, orientInPlane: CD.Orientation, amount: CD.DesignNumber] RETURNS [include: CD.ApplicationList←NIL, removeMe: BOOLFALSE] =
-- 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, aptr: CD.ApplicationPtr, x: REF, objectSpecific: REF]
RETURNS [done: BOOLFALSE, removeMe: BOOLFALSE, include: CD.ApplicationList←NIL,
repaintMe: BOOLFALSE, repaintInclude: BOOLFALSE] =
BEGIN
IF objectSpecific#NIL THEN
BEGIN
p: REF = CDObjectProcs.FetchFurther [aptr.ob.p, objectSpecific];
IF p#NIL AND ISTYPE[p, REF CDCallSpecific.CallProc] THEN
BEGIN
[done: done,
removeMe: removeMe,
include: include,
repaintMe: repaintMe,
repaintInclude: repaintInclude] ← NARROW[p, REF CDCallSpecific.CallProc]^[design, aptr, x]
END;
END;
END;
appOrient, orientInObject: CD.Orientation;
done, repaintMe, repaintInclude: BOOL;
offset: REF CD.DesignPosition ← NEW[CD.DesignPosition←[0, 0]];
--ignore mirroring and 45 degrees
orientInPlane ← CDOrient.ConcentrateOnRotate90[orientInPlane];
appOrient ← CDOrient.ConcentrateOnRotate90[aptr.orientation];
orientInObject ← CDOrient.DecomposeOrient[
itemOrientInWorld: orientInPlane,
cellOrientInWorld: appOrient
];
IF CDOrient.IncludesOddRot90[orientInObject] THEN offset.x𡤊mount ELSE offset.y𡤊mount;
CDOps.DelayedRedraw[design, CDApplications.ARectO[aptr]];
[done, removeMe, include, repaintMe, repaintInclude] ← CallSpecific[design, aptr, offset , $Lengthen];
IF done THEN {
SELECT CDOrient.ConcentrateOnRotate90[orientInPlane] FROM
CDOrient.original => {
aptr.location.y ← aptr.location.y-amount;
IF include#NIL THEN CDApplications.TranslateList[include, [0, -amount]]
};
CDOrient.rotate90 => NULL;
CDOrient.rotate180 => NULL;
CDOrient.rotate270 => {
aptr.location.x ← aptr.location.x-amount;
IF include#NIL THEN CDApplications.TranslateList[include, [-amount, 0]]
};
ENDCASE => ERROR;
CDOps.DelayedRedraw[design, CDApplications.ARectO[aptr]];
};
END;
SelectBorder: PROC [r: CD.DesignRect, pos: CD.DesignPosition] RETURNS [orient: CD.Orientation] =
BEGIN
dx1, dx2, dy1, dy2: CD.DesignNumber;
r ← CDInline.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.ApplicationPtr, from, to: CD.DesignPosition] RETURNS [amount: CD.DesignNumber, 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.DesignRect = CDApplications.ARectI[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.DesignRect, pos: CD.DesignPosition, dir: CD.Orientation, dirAmount: CD.DesignNumber] RETURNS [amount: CD.DesignNumber, 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.DesignPosition, pointed: BOOLFALSE, growAsToX: BOOLFALSE, edgeInOrient: BOOLFALSE, orient: CD.Orientation←CD.original] =
-- ~pointed: stretch selected
-- pointed: stretch pointed
BEGIN
pointedAp: CD.ApplicationPtr;
orientInPlane: CD.Orientation;
amount: CD.DesignNumber;
include: CD.ApplicationList;
removeMe: BOOL;
removeList, includeList: CD.ApplicationList←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 ← CDApplications.AplicationAt[al: CDOps.AppList[design], pos: from, selectedOnly: ~pointed];
IF pointedAp=NIL THEN {
IF pointed THEN TerminalIO.WriteRope[" no object pointed\n"]
ELSE TerminalIO.WriteRope[" no selected object pointed\n"];
RETURN
};
IF growAsToX THEN {
amount←to.x;
orientInPlane ← SelectBorder[CDApplications.ARectI[pointedAp], from]
}
ELSE IF edgeInOrient THEN [amount, orientInPlane] ← FixDirection[CDApplications.ARectI[pointedAp], from, orient, to.x]
ELSE [amount, orientInPlane] ← DetermineDirection[pointedAp, from, to];
IF pointed THEN { -- use pointed
count ← 1;
[includeList, removeMe] ← StretchApplication[design, pointedAp, orientInPlane, amount];
IF removeMe THEN removeList ← LIST[pointedAp];
}
ELSE { -- use selected
FOR list: CD.ApplicationList ← CDOps.AppList[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 ← CDApplications.AppendToList[include, includeList];
}
ENDLOOP;
};
RemoveAppList[design, removeList];
CDOps.IncludeApplicationList[design, includeList];
TerminalIO.WriteInt[count];
TerminalIO.WriteRope[" objects tried to stretch\n"];
END;
RemoveAppList: PROC [design: CD.Design, appList: CD.ApplicationList, draw: BOOLTRUE] =
BEGIN
FOR list: CD.ApplicationList ← appList, list.rest WHILE list#NIL DO
CDOps.RemoveApplication[design, list.first, draw];
ENDLOOP;
END;
StretchCommandP: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch pointed"];
DoAStretch[design: comm.design, from: comm.sPos, to: comm.pos, pointed: TRUE]
END;
StretchCommandS: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch selected"];
DoAStretch[design: comm.design, from: comm.sPos, to: comm.pos, pointed: FALSE]
END;
StepValue: PROC[design: CD.Design] RETURNS [CD.DesignNumber] =
BEGIN
RETURN [CD.lambda*MAX[CDValue.FetchInt[boundTo: design, key: $CDxStepValue, propagation: global], 1]]
END;
GrowStepSCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["grow selected"];
DoAStretch[design: comm.design, from: comm.pos, to: [StepValue[comm.design], 0], pointed: FALSE, growAsToX: TRUE ]
END;
GrowStepPCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["grow pointed"];
DoAStretch[design: comm.design, from: comm.pos, to: [StepValue[comm.design], 0], pointed: TRUE, growAsToX: TRUE ]
END;
ShrinkStepSCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["shrink selected"];
DoAStretch[design: comm.design, from: comm.pos, to: [-StepValue[comm.design], 0], pointed: FALSE, growAsToX: TRUE ]
END;
ShrinkStepPCommand: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["shrink pointed"];
DoAStretch[design: comm.design, from: comm.pos, to: [-StepValue[comm.design], 0], pointed: TRUE, 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.design], 0], pointed: FALSE, 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.design], 0], pointed: FALSE, 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.design], 0], pointed: FALSE, 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.design], 0], pointed: FALSE, edgeInOrient: TRUE, orient: CDOrient.original]
END;
StretchStepLeftCommandP: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step pointed left"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm.design], 0], pointed: TRUE, edgeInOrient: TRUE, orient: CDOrient.rotate270]
END;
StretchStepRightCommandP: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step pointed right"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm.design], 0], pointed: TRUE, edgeInOrient: TRUE, orient: CDOrient.rotate90]
END;
StretchStepUpCommandP: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step pointed up"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm.design], 0], pointed: TRUE, edgeInOrient: TRUE, orient: CDOrient.rotate180]
END;
StretchStepDownCommandP: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Stretch step pointed down"];
DoAStretch[design: comm.design, from: comm.sPos, to: [StepValue[comm.design], 0], pointed: TRUE, edgeInOrient: TRUE, orient: CDOrient.original]
END;
CDSequencer.ImplementCommand[$StretchP, StretchCommandP];
CDSequencer.ImplementCommand[$StretchS, StretchCommandS];
CDSequencer.ImplementCommand[$GrowStepS, GrowStepSCommand];
CDSequencer.ImplementCommand[$GrowStepP, GrowStepPCommand];
CDSequencer.ImplementCommand[$ShrinkStepS, ShrinkStepSCommand];
CDSequencer.ImplementCommand[$ShrinkStepP, ShrinkStepPCommand];
CDSequencer.ImplementCommand[$StretchStepLeftS, StretchStepLeftCommandS];
CDSequencer.ImplementCommand[$StretchStepRightS, StretchStepRightCommandS];
CDSequencer.ImplementCommand[$StretchStepUpS, StretchStepUpCommandS];
CDSequencer.ImplementCommand[$StretchStepDownS, StretchStepDownCommandS];
CDSequencer.ImplementCommand[$StretchStepLeftP, StretchStepLeftCommandP];
CDSequencer.ImplementCommand[$StretchStepRightP, StretchStepRightCommandP];
CDSequencer.ImplementCommand[$StretchStepUpP, StretchStepUpCommandP];
CDSequencer.ImplementCommand[$StretchStepDownP, StretchStepDownCommandP];
END.