CDRepetitionsImpl.mesa (part of Chipndale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi October 27, 1983 3:36 pm
last edited Christian Jacobi November 19, 1984 7:53:55 pm PST
DIRECTORY
CD,
CDApplications USING [--NewApplicationI,-- BoundingRect],
CDBasics,
CDCallSpecific,
CDCells,
CDDirectory,
CDDirectoryExtras,
CDInterestRects,
CDIO,
CDOrient,
CDProperties,
CDRepetitions,
TokenIO;
CDRepetitionsImpl: CEDAR PROGRAM
IMPORTS CD, CDApplications, CDBasics, CDCallSpecific, CDCells, CDDirectory, CDDirectoryExtras, CDInterestRects, CDIO, CDOrient, CDProperties, TokenIO
EXPORTS CDRepetitions
SHARES CDDirectory =
BEGIN
RepPtr: TYPE = CDRepetitions.RepPtr;
RepRec: TYPE = CDRepetitions.RepRec;
pForRepetitions: REF CD.ObjectProcs ~ CD.RegisterObjectType[$Repetitions];
RepositionElementsR: CDDirectory.RepositionElementsProc
-- PROC [me: CD.ObPtr, objToReposition: CD.ObPtr, oldSize: CD.DesignPosition, newBound: CD.DesignRect, design: CD.Design] -- =
BEGIN
rp: RepPtr ~ NARROW[me.specificRef];
IF rp.ob=objToReposition THEN {
rp.offsetOfFirst ← CDOrient.MapPosition[
itemInCell: newBound,
cellSize: oldSize,
cellInstOrient: rp.orientation,
cellInstPos: rp.offsetOfFirst];
CDDirectory.RepositionAnObject[design, me];
}
END;
ComputeBoundsR: CDDirectory.ComputeBoundsProc
-- PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] -- =
BEGIN
rp: RepPtr = NARROW[ob.specificRef];
sz: CD.DesignPosition = CDOrient.OrientedSize[rp.ob.size, rp.orientation];
toffset: CD.DesignPosition = [(rp.count-1)*rp.offset.x, (rp.count-1)*rp.offset.y];
r1: CD.DesignRect = CDBasics.RectAt[rp.offsetOfFirst, sz];
r2: CD.DesignRect = CDBasics.RectAt[CDBasics.AddPoints[rp.offsetOfFirst, toffset], sz];
RETURN CDBasics.Surround[r1, r2];
END;
AdjustItselfR: CDDirectory.AdjustItselfProc
-- PROC [objToReposition: CD.ObPtr, newBound: CD.DesignRect] -- =
BEGIN
AdjustItself[objToReposition];
END;
AdjustItself: PROC [me: CD.ObPtr] =
BEGIN
rp: RepPtr = NARROW[me.specificRef];
rp.offsetOfFirst ← [0, 0];
IF rp.offset.x<0 THEN rp.offsetOfFirst.x← -(rp.count-1)*rp.offset.x;
IF rp.offset.y<0 THEN rp.offsetOfFirst.y← -(rp.count-1)*rp.offset.y;
END;
NonDefaultIR: PROC[ob: CD.ObPtr, iR: CD.DesignRect] RETURNS [BOOL] = INLINE {
RETURN [iR.x1#0 OR iR.y1#0 OR iR.x2#ob.size.x OR iR.y2#ob.size.y]
};
InternalCreateRepetition: PROC [ob: CD.ObPtr, count: NAT, offset: CD.DesignPosition, orientation: CD.Orientation] RETURNS [CD.ObPtr] =
BEGIN
repOb: CD.ObPtr = NEW[CD.ObjectDefinition];
rp: RepPtr = NEW[RepRec];
sz: CD.DesignPosition = CDOrient.OrientedSize[ob.size, orientation];
--do not use all the interestrect feature
useIR: BOOL;
iR: CD.DesignRect;
[iR, useIR] ← CDInterestRects.GetInterestRect[ob];
repOb.p ← pForRepetitions;
count ← MAX[1, MIN[count, 512]];
repOb.size.x ← sz.x+(count-1)*ABS[offset.x];
repOb.size.y ← sz.y+(count-1)*ABS[offset.y];
repOb.level ← ob.level;
rp.ob ← ob;
rp.offsetOfFirst ← [0, 0];
IF offset.x<0 THEN rp.offsetOfFirst.x← -(count-1)*offset.x;
IF offset.y<0 THEN rp.offsetOfFirst.y← -(count-1)*offset.y;
rp.orientation ← orientation;
rp.offset ← offset;
rp.count ← count;
repOb.specificRef ← rp;
IF useIR OR NonDefaultIR[ob, iR] THEN {
iR ← CDOrient.DeMapRect[
itemInWorld: iR,
cellSize: ob.size,
cellInstOrient: orientation
];
iR.x2 ← iR.x2+(count-1)*ABS[offset.x];
iR.y2 ← iR.y2+(count-1)*ABS[offset.y];
CDInterestRects.SetInterestRect[repOb, iR]
};
RETURN [repOb];
END;
CreateRepetition: PUBLIC PROC [design: CD.Design, ob: CD.ObPtr, count: NAT, offset: CD.DesignPosition, orientation: CD.Orientation𡤀] RETURNS [CD.ObPtr] =
BEGIN
repOb: CD.ObPtr = InternalCreateRepetition[ob, count, offset, orientation];
[] ← CDDirectory.Include[design, repOb];
RETURN [repOb];
END;
DrawMeForRepetitions: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
ENABLE UNWIND => IF pr.nesting.first=aptr THEN pr.nesting ← pr.nesting.rest;
rptr: RepPtr ← NARROW[aptr.ob.specificRef];
rel, sz: CD.DesignPosition;
o: CD.Orientation ← CDOrient.ComposeOrient[rptr.orientation, orient];
dummyApp: CD.ApplicationPtr ← NEW[CD.Application];
xi: REF INT;
dummyApp.ob ← rptr.ob;
rel ← rptr.offsetOfFirst;
sz ← CDOrient.OrientedSize[rptr.ob.size, rptr.orientation];
pr.nesting ← CONS[aptr, pr.nesting];
--hang two properties on the application; both pointing to the same int containing the
--repetition number;
--the first property has the name $CDxIndex
--the second property name is the value of the property $CDxIndexProperty
WITH CDProperties.GetPropFromApplication[aptr, $CDxIndex] SELECT FROM
intP: REF INT => xi ← intP;
ENDCASE => {
xi ← NEW[INT];
CDProperties.PutPropOnApplication[aptr, $CDxIndex, xi];
WITH CDProperties.GetPropFromApplication[aptr, $CDxIndexProperty] SELECT FROM
ixP: ATOM => {
CDProperties.PutPropOnApplication[aptr, ixP, xi];
};
ENDCASE => NULL
};
--do drawing
FOR i: INT IN [0..rptr.count) DO
p: CD.DesignPosition ← CDOrient.MapPosition[
itemInCell: CDBasics.RectAt[rel, sz],
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos
];
IF pr.stopFlag^ THEN EXIT;
xi^ ← i;
pr.drawChild[dummyApp, p, o, pr];
rel ← CDBasics.AddPoints[rel, rptr.offset];
ENDLOOP;
IF pr.nesting.first=aptr THEN pr.nesting ← pr.nesting.rest
END;
QuickDrawMeForRepetitions: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
ENABLE UNWIND => IF pr.nesting.first=aptr THEN pr.nesting ← pr.nesting.rest;
rptr: RepPtr ← NARROW[aptr.ob.specificRef];
rel, sz: CD.DesignPosition;
o: CD.Orientation ← CDOrient.ComposeOrient[rptr.orientation, orient];
dummyApp: CD.ApplicationPtr ← NEW[CD.Application];
xi: REF INT;
dummyApp.ob ← rptr.ob;
rel ← rptr.offsetOfFirst;
sz ← CDOrient.OrientedSize[rptr.ob.size, rptr.orientation];
pr.nesting ← CONS[aptr, pr.nesting];
--hang two properties on the application; both pointing to the same int containing the
--repetition number;
--the first property has the name $CDxIndex
--the second property name is the value of the property $CDxIndexProperty
WITH CDProperties.GetPropFromApplication[aptr, $CDxIndex] SELECT FROM
intP: REF INT => xi ← intP;
ENDCASE => {
xi ← NEW[INT];
CDProperties.PutPropOnApplication[aptr, $CDxIndex, xi];
WITH CDProperties.GetPropFromApplication[aptr, $CDxIndexProperty] SELECT FROM
ixP: ATOM => {
CDProperties.PutPropOnApplication[aptr, ixP, xi];
};
ENDCASE => NULL
};
--do drawing
FOR i: INT IN [0..rptr.count) DO
p: CD.DesignPosition ← CDOrient.MapPosition[
itemInCell: CDBasics.RectAt[rel, sz],
cellSize: aptr.ob.size,
cellInstOrient: orient,
cellInstPos: pos
];
IF pr.stopFlag^ THEN EXIT;
xi^ ← i;
rptr.ob.p.quickDrawMe[dummyApp, p, o, pr];
rel ← CDBasics.AddPoints[rel, rptr.offset];
ENDLOOP;
IF pr.nesting.first=aptr THEN pr.nesting ← pr.nesting.rest
END;
Another: PROC [me: CD.ObPtr, from, to: CD.Design] RETURNS [CD.ObPtr] =
BEGIN
rp: RepPtr = NARROW[me.specificRef];
RETURN [CreateRepetition[to, rp.ob, rp.count, rp.offset, rp.orientation]]
END;
IncCount: CDCallSpecific.CallProc
-- PROC [design: CD.Design, aptr: CD.ApplicationPtr, x: REF] RETURNS [done: BOOL←TRUE, removeMe: BOOL�LSE, include: CD.ApplicationList←NIL, repaintMe: BOOL�LSE, repaintInclude: BOOL�LSE] -- =
BEGIN
sz: CD.DesignPosition ← aptr.ob.size;
ap: CD.ApplicationPtr ← NEW[CD.Application𡤊ptr^];
rptr: RepPtr ← NARROW[aptr.ob.specificRef];
newOb: CD.ObPtr = CreateRepetition[design, rptr.ob, rptr.count+1, rptr.offset, rptr.orientation];
IF ap.ob.size#newOb.size THEN {
relativeNewBound: CD.DesignRect ← [x1: 0, y1: 0, x2: aptr.ob.size.x, y2: aptr.ob.size.y];
IF rptr.offset.x>=0 THEN relativeNewBound.x2 ← aptr.ob.size.x+rptr.offset.x
ELSE relativeNewBound.x1 ← rptr.offset.x;
IF rptr.offset.y>=0 THEN relativeNewBound.y2 ← aptr.ob.size.y+rptr.offset.y
ELSE relativeNewBound.y1 ← rptr.offset.y;
ap.location ← CDOrient.MapPosition[
itemInCell: relativeNewBound,
cellSize: aptr.ob.size,
cellInstOrient: aptr.orientation,
cellInstPos: aptr.location];
};
ap.ob ← newOb;
include ← LIST[ap];
repaintMe ← TRUE;
removeMe ← TRUE;
repaintInclude ← TRUE;
END;
DecCount: CDCallSpecific.CallProc
-- PROC [design: CD.Design, aptr: CD.ApplicationPtr, x: REF] RETURNS [done: BOOL←TRUE, removeMe: BOOL�LSE, include: CD.ApplicationList←NIL, repaintMe: BOOL�LSE, repaintInclude: BOOL�LSE] -- =
BEGIN
sz: CD.DesignPosition ← aptr.ob.size;
ap: CD.ApplicationPtr ← NEW[CD.Application𡤊ptr^];
rptr: RepPtr ← NARROW[aptr.ob.specificRef];
newOb: CD.ObPtr = CreateRepetition[design, rptr.ob, rptr.count-1, rptr.offset, rptr.orientation];
IF ap.ob.size#newOb.size THEN {
relativeNewBound: CD.DesignRect ← [x1: 0, y1: 0, x2: aptr.ob.size.x, y2: aptr.ob.size.y];
IF rptr.offset.x>=0 THEN relativeNewBound.x2 ← aptr.ob.size.x-rptr.offset.x
ELSE relativeNewBound.x1 ← -rptr.offset.x;
IF rptr.offset.y>=0 THEN relativeNewBound.y2 ← aptr.ob.size.y-rptr.offset.y
ELSE relativeNewBound.y1 ← -rptr.offset.y;
ap.location ← CDOrient.MapPosition[
itemInCell: relativeNewBound,
cellSize: aptr.ob.size,
cellInstOrient: aptr.orientation,
cellInstPos: aptr.location];
};
ap.ob ← newOb;
include ← LIST[ap];
repaintMe ← TRUE;
removeMe ← TRUE;
repaintInclude ← TRUE;
END;
TransformToCell: CDCallSpecific.CallProc
-- PROC [design: CD.Design, aptr: CD.ApplicationPtr, x: REF] RETURNS [done: BOOL←TRUE, removeMe: BOOL�LSE, include: CD.ApplicationList←NIL, repaintMe: BOOL�LSE, repaintInclude: BOOL�LSE] -- =
BEGIN
rptr: RepPtr = NARROW[aptr.ob.specificRef];
cob: CD.ObPtr = CreateRepetitionCell[design: design,
ob: rptr.ob,
count: rptr.count,
offset: rptr.offset,
orientation: rptr.orientation
];
removeMe ← TRUE;
repaintMe ← TRUE;
include ← LIST[NEW[CD.Application ← [
ob: cob,
location: aptr.location,
orientation: aptr.orientation,
selected: aptr.selected,
properties: CDProperties.CopyProps[aptr.properties]
]]];
repaintInclude ← TRUE;
END;
EnumerateRepeatedObjects: PROC [me: CD.ObPtr, p: CDDirectory.EnumerateObjectsProc, x: REF] =
BEGIN
rptr: RepPtr = NARROW[me.specificRef];
p[rptr.ob, x];
END;
ReadRepetition: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- =
BEGIN
ob: CD.ObPtr = CDIO.ReadObject[];
count: NAT = TokenIO.ReadInt[];
offsetx: INT = TokenIO.ReadInt[];
offsety: INT = TokenIO.ReadInt[];
orientation: CD.Orientation = CDIO.ReadOrientation[];
RETURN [ InternalCreateRepetition[
ob: ob,
count: count,
offset: [offsetx, offsety],
orientation: orientation
]];
END;
WriteRepetition: CD.InternalWriteProc -- PROC [me: ObPtr] -- =
BEGIN
specific: RepPtr = NARROW[me.specificRef];
CDIO.WriteObject[specific.ob];
TokenIO.WriteInt[specific.count];
TokenIO.WriteInt[specific.offset.x];
TokenIO.WriteInt[specific.offset.y];
CDIO.WriteOrientation[specific.orientation];
END;
NewApplicationX: --IMPORTED-- PROC [ob: CD.ObPtr, location: CD.DesignPosition←[0,0], orientation: CD.Orientation𡤀,
selected: BOOLEANFALSE, properties: CD.Properties←NIL] RETURNS [CD.ApplicationPtr] =
--creates a new application, does neither draw nor include it into any world
--modifies location such that ob...insideRect is at original location
BEGIN
inr: CD.DesignRect = CDInterestRects.GetInterestRect[ob].r;
off: CD.DesignPosition = CDOrient.MapPosition[
itemInCell: inr,
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: [0, 0]
];
a: CD.ApplicationPtr = NEW[CD.Application ← CD.Application[
ob: ob,
location: CDBasics.SubPoints[location, off],
orientation: orientation,
selected: selected,
properties: properties
]];
RETURN [a]
END;
CreateRepetitionCell: PUBLIC PROC [design: CD.Design, ob: CD.ObPtr, count: NAT, offset: CD.DesignPosition, orientation: CD.Orientation𡤀] RETURNS [CD.ObPtr] =
BEGIN
ap: CD.ApplicationPtr;
pos: CD.DesignPosition ← [0, 0];
co: CD.ObPtr = CDCells.CreateEmptyCell[];
cp: CD.CellPtr = NARROW[co.specificRef];
useIR: BOOL;
iR: CD.DesignRect;
[iR, useIR] ← CDInterestRects.GetInterestRect[ob];
count ← MAX[count, 1];
IF offset.x<0 THEN {pos.x ← -offset.x*(count-1)};
IF offset.y<0 THEN {pos.y ← -offset.y*(count-1)};
FOR i: NAT IN [1..count] DO
ap ← NEW[CD.Application←[ob: ob, location: pos, orientation: orientation, selected: FALSE]];
ap ← NewApplicationX[ob: ob, location: pos, orientation: orientation];
pos ← CDBasics.AddPoints[pos, offset];
cp.contents ← CONS[ap, cp.contents]
ENDLOOP;
co.size ← CDBasics.SizeOfRect[CDApplications.BoundingRect[cp.contents]];
[] ← CDDirectory.Include[design, co, "-repetition-"];
IF useIR OR NonDefaultIR[ob, iR] THEN {
iR ← CDOrient.MapRect[
itemInCell: iR,
cellSize: ob.size,
cellInstOrient: orientation
];
iR.x2 ← iR.x2+(count-1)*ABS[offset.x];
iR.y2 ← iR.y2+(count-1)*ABS[offset.y];
CDInterestRects.SetInterestRect[co, iR]
};
RETURN [co];
END;
ReplaceDirectChildForReps: CDDirectory.ReplaceDirectChildProc =
BEGIN
rp: CDRepetitions.RepPtr = NARROW[me.specificRef];
found ← rp.ob=old;
IF found THEN {
rp.offsetOfFirst ← CDOrient.MapPosition[
itemInCell: CDBasics.MoveRect[[x1: 0, y1: 0, x2: new.size.x, y2: new.size.y], off],
cellSize: old.size,
cellInstOrient: rp.orientation,
cellInstPos: rp.offsetOfFirst
];
rp.ob ← new
};
END;
NewReplaceDirectChildForReps: CDDirectoryExtras.ReplaceDChildsProc =
BEGIN
found: BOOLFALSE;
rp: CDRepetitions.RepPtr = NARROW[me.specificRef];
FOR replaceList: CDDirectoryExtras.ReplaceList ← replace, replaceList.rest WHILE replaceList#NIL DO
rep: REF CDDirectoryExtras.ReplaceRec = replaceList.first;
IF rep.old=rp.ob THEN {
IF rep.newSize#rep.oldSize OR rep.off#[0, 0] THEN {
rp.offsetOfFirst ← CDOrient.MapPosition[
itemInCell: CDBasics.MoveRect[
[x1: 0, y1: 0, x2: rep.newSize.x, y2: rep.newSize.y], rep.off],
cellSize: rep.oldSize,
cellInstOrient: rp.orientation,
cellInstPos: rp.offsetOfFirst
];
rp.ob ← rep.new;
found ← TRUE;
EXIT
}
};
ENDLOOP;
IF found THEN {
newR: CD.DesignRect ← ComputeBoundsR[me];
IF newR#CDBasics.RectAt[[0, 0], me.size] THEN {
newSize: CD.DesignPosition ← CDBasics.SizeOfRect[newR];
oldSize: CD.DesignPosition ← me.size;
newBase: CD.DesignPosition = CDBasics.BaseOfRect[newR];
AdjustItself[me];
me.size ← newSize;
IF design#NIL THEN
CDDirectoryExtras.RepositionObject[
design: design,
ob: me,
oldSize: oldSize,
baseOff: newBase
]
}
}
END;
InitRepetitions: PROC [] =
BEGIN
rp: REF CDDirectory.DirectoryProcs ~ CDDirectory.InstallDirectoryProcs[pForRepetitions];
rp.enumerateChildObjects ← EnumerateRepeatedObjects;
rp.adjustItself ← AdjustItselfR;
rp.repositionElements ← RepositionElementsR;
rp.computeBounds ← ComputeBoundsR;
rp.replaceDirectChilds ← ReplaceDirectChildForReps;
rp.another ← Another;
pForRepetitions.drawMe ← DrawMeForRepetitions;
pForRepetitions.quickDrawMe ← QuickDrawMeForRepetitions;
pForRepetitions.internalRead ← ReadRepetition;
pForRepetitions.internalWrite ← WriteRepetition;
CDDirectoryExtras.InstallReplaceDChildProc[pForRepetitions, NewReplaceDirectChildForReps];
CDCallSpecific.Register[$TransformToCell, pForRepetitions, TransformToCell];
CDCallSpecific.Register[$IncCount, pForRepetitions, IncCount];
CDCallSpecific.Register[$DecCount, pForRepetitions, DecCount];
END;
InitRepetitions[];
END.