CDRepetitionsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, October 27, 1983 3:36 pm
Last Edited by: Christian Jacobi, February 23, 1987 3:22:15 pm PST
DIRECTORY
CD,
CDBasics,
CDDirectory,
CDIO,
CDProperties,
CDRepetitions,
IO,
Rope,
TokenIO;
CDRepetitionsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDDirectory, CDIO, CDProperties, IO, TokenIO
EXPORTS CDRepetitions
SHARES CDDirectory =
BEGIN
RepSpecific: TYPE = CDRepetitions.RepSpecific;
pForRepetitions: CD.ObjectClass = CD.RegisterObjectClass[$Repetitions, [
drawMe: DrawMeForRepetitions,
quickDrawMe: QuickDrawMeForRepetitions,
internalRead: ReadRepetition,
internalWrite: WriteRepetition,
describe: Describe
]];
Describe: CD.DescribeProc = {
rp: RepSpecific = NARROW[ob.specific];
r: Rope.ROPEIO.PutFR["repetition [%g]", [integer[rp.count]]];
RETURN [r]
};
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]];
};
CreateRepetition: PUBLIC PROC [design: CD.Design, ob: CD.Object, count: NAT, offset: CD.Position, orientation: CD.Orientation] RETURNS [CD.Object] = {
rp: RepSpecific = NEW[CDRepetitions.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];
IF design#NIL THEN CDDirectory.SetOwner[design, repOb];
RETURN [repOb];
};
DrawMeForRepetitions: CD.DrawProc = {
rptr: RepSpecific ← NARROW[ob.specific];
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[pr, rptr.ob, t1];
t1.off ← CDBasics.AddPoints[t1.off, off]
ENDLOOP;
};
QuickDrawMeForRepetitions: CD.DrawProc = {
rptr: RepSpecific ← NARROW[ob.specific];
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;
rptr.ob.class.quickDrawMe[pr, rptr.ob, t1];
t1.off ← CDBasics.AddPoints[t1.off, off]
ENDLOOP;
};
Another: PROC [me: CD.Object, fromOrNil: CD.Design←NIL, into: CD.Design←NIL, friendly: BOOLFALSE] RETURNS [new: CD.Object←NIL, childAccessible: BOOLFALSE] = {
rp: RepSpecific = NARROW[me.specific];
new ← CreateRepetition[into, rp.ob, rp.count, rp.offset, rp.orientation];
CDProperties.AppendProps[winner: new.properties, looser: me.properties, putOnto: new];
childAccessible ← ~rp.ob.class.composed OR (fromOrNil#NIL AND fromOrNil=into)
};
EnumerateChildren: PROC [me: CD.Object, proc: CDDirectory.EachObjectProc, data: REF] RETURNS [quit: BOOL] = {
rptr: RepSpecific = NARROW[me.specific];
quit ← proc[rptr.ob, data];
};
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 ← CreateRepetition[design: CDIO.DesignInReadOperation[h], 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];
};
ReplaceDirectChildren: 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;
IF me.immutable THEN ERROR;
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: EnumerateChildren,
replaceDirectChilds: ReplaceDirectChildren,
another: Another
]];
};
InitRepetitions[];
END.