CDRepetitionsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, October 27, 1983 3:36 pm
Last Edited by: Christian Jacobi, December 17, 1986 3:08:11 pm PST
DIRECTORY
CD,
CDBasics,
CDDirectory,
CDIO,
CDProperties,
CDRepetitions,
IO,
Rope,
TokenIO;
CDRepetitionsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDDirectory, CDIO, CDProperties, IO, TokenIO, Rope
EXPORTS CDRepetitions
SHARES CDDirectory =
BEGIN
RepSpecific: TYPE = CDRepetitions.RepSpecific;
RepRec: TYPE = CDRepetitions.RepRec;
pForRepetitions: CD.ObjectClass = CD.RegisterObjectClass[$Repetitions, [
drawMe: DrawMeForRepetitions,
quickDrawMe: QuickDrawMeForRepetitions,
internalRead: ReadRepetition,
internalWrite: WriteRepetition,
describe: Describe
]];
Describe: PROC [me: CD.Object] RETURNS [Rope.ROPE] = {
rp: RepSpecific = NARROW[me.specific];
RETURN [IO.PutFR[
"repetition [%g] ""%g""",
[integer[rp.count]],
[rope[CDDirectory.Name[me]]]
]]
};
Adjust: PROC [repOb: CD.Object, rp: RepSpecific] = {
or: CD.Rect ← CDBasics.MapRect[rp.ob.bbox, [[0,0], rp.orientation]];
ir: CD.Rect ← CDBasics.MapRect[CD.InterestRect[rp.ob], [[0,0], rp.orientation]];
totalOffset: CD.Position ← [(rp.count-1)*rp.offset.x, (rp.count-1)*rp.offset.y];
repOb.bbox ← CDBasics.Surround[or, CDBasics.MoveRect[or, totalOffset]];
rp.ir ← CDBasics.Surround[ir, CDBasics.MoveRect[ir, totalOffset]];
};
InternalCreateRepetition: PROC [ob: CD.Object, count: NAT, offset: CD.Position, orientation: CD.Orientation] RETURNS [CD.Object] = {
rp: RepSpecific = NEW[RepRec←[
ob: ob,
ir: [0, 0, 0, 0],
orientation: orientation,
offset: offset,
count: MAX[1, MIN[count, 512]]
]];
repOb: CD.Object = NEW[CD.ObjectRep←[
class: pForRepetitions,
specific: rp
]];
Adjust[repOb, rp];
RETURN [repOb];
};
CreateRepetition: PUBLIC PROC [design: CD.Design, ob: CD.Object, count: NAT, offset: CD.Position, orientation: CD.Orientation] RETURNS [CD.Object] = {
repOb: CD.Object = InternalCreateRepetition[ob, count, offset, orientation];
[] ← CDDirectory.Include[design, repOb, Rope.Cat["=rep-", CDDirectory.Name[ob]]];
RETURN [repOb];
};
DrawMeForRepetitions: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = {
rptr: RepSpecific ← NARROW[inst.ob.specific];
dummyInstance: CD.Instance ← NEW[CD.InstanceRep←[ob: rptr.ob]];
t1: CD.Transformation ← CDBasics.ComposeTransform[[[0,0], rptr.orientation], trans];
off: CD.Position ← CDBasics.MapPoint[rptr.offset, [[0,0], trans.orient]];
FOR i: INT IN [0..rptr.count) DO
IF pr.stopFlag^ THEN EXIT;
pr.drawChild[dummyInstance, t1, pr];
t1.off ← CDBasics.AddPoints[t1.off, off]
ENDLOOP;
};
QuickDrawMeForRepetitions: PROC [inst: CD.Instance, trans: CD.Transformation, pr: CD.DrawRef] = {
rptr: RepSpecific ← NARROW[inst.ob.specific];
t1: CD.Transformation ← CDBasics.ComposeTransform[[[0,0], rptr.orientation], trans];
off: CD.Position ← CDBasics.MapPoint[rptr.offset, [[0,0], trans.orient]];
IF pr.dummyInst=NIL THEN pr.dummyInst ← NEW[CD.InstanceRep←[ob: rptr.ob]];
FOR i: INT IN [0..rptr.count) DO
IF pr.stopFlag^ THEN EXIT;
pr.dummyInst.ob ← rptr.ob;
rptr.ob.class.quickDrawMe[pr.dummyInst, t1, pr];
t1.off ← CDBasics.AddPoints[t1.off, off]
ENDLOOP;
};
Another: PROC [me: CD.Object, fromOrNil: CD.Design, into: CD.Design, friendly: BOOL] RETURNS [new: CD.Object, topMode: CDDirectory.InclOrReady←ready, childMode: CDDirectory.ImmOrIncl←immutable] = {
rp: RepSpecific = NARROW[me.specific];
new ← InternalCreateRepetition[rp.ob, rp.count, rp.offset, rp.orientation];
CDProperties.AppendProps[winner: new.properties, looser: me.properties, putOnto: new];
IF ~rp.ob.class.inDirectory OR (fromOrNil#NIL AND fromOrNil=into) THEN
childMode ← included
};
EnumerateRepeatedObjects: PROC [me: CD.Object, p: CDDirectory.EnumerateObjectsProc, x: REF] = {
rptr: RepSpecific = NARROW[me.specific];
p[rptr.ob, x];
};
ReadRepetition: CD.InternalReadProc = {
ob: CD.Object = CDIO.ReadObject[h];
count: NAT = TokenIO.ReadInt[h];
offset: CD.Position = CDIO.ReadPos[h];
orientation: CD.Orientation = CDIO.ReadOrientation[h];
rep: CD.Object ← InternalCreateRepetition[ob: ob, count: count, offset: offset, orientation: orientation];
?? IF CDIO.VersionKey[h]<=15 THEN not necessary; I can't believe it but I tested it
RETURN [rep];
};
WriteRepetition: CD.InternalWriteProc = {
specific: RepSpecific = NARROW[ob.specific];
CDIO.WriteObject[h, specific.ob];
TokenIO.WriteInt[h, specific.count];
CDIO.WritePos[h, specific.offset];
CDIO.WriteOrientation[h, specific.orientation];
};
ReplaceDirectChildForReps: CDDirectory.ReplaceDChildsProc = {
rp: CDRepetitions.RepSpecific = NARROW[me.specific];
bbox: CD.Rect ← me.bbox;
ir: CD.Rect ← rp.ir;
FOR replaceList: CDDirectory.ReplaceList ← replace, replaceList.rest WHILE replaceList#NIL DO
rep: REF CDDirectory.ReplaceRec ← replaceList.first;
IF rep.old=rp.ob THEN {
trans: CD.Transformation ← CDBasics.ComposeTransform[
itemInCell: rep.trans,
cellInWorld: [[0, 0], rp.orientation]
].itemInWorld;
rp.ob ← rep.new;
rp.orientation ← trans.orient;
Adjust[me, rp];
IF trans.off#[0, 0] THEN
CDDirectory.ReplaceObject[design: design, old: me, new: me, trans: [trans.off, original]]
ELSE IF me.bbox#bbox OR rp.ir#ir THEN
CDDirectory.PropagateResize[design, me];
changed ← TRUE;EXIT;
};
ENDLOOP;
};
InitRepetitions: PROC [] = {
rp: REF CDDirectory.DirectoryProcs = CDDirectory.InstallDirectoryProcs[pForRepetitions, [
enumerateChildObjects: EnumerateRepeatedObjects,
replaceDirectChilds: ReplaceDirectChildForReps,
another: Another
]];
};
InitRepetitions[];
END.