CDDirectoryExtrasImpl.mesa (a Chipndale module)
Copyright © 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi November 16, 1984 11:40:08 am PST
last edited Christian Jacobi November 20, 1984 12:06:09 pm PST
DIRECTORY
CD,
CDApplications,
CDBasics,
CDDirectoryExtras,
CDDirectory,
CDEvents,
CDInterestRects,
CDObjectProcs,
CDOps,
CDOrient,
CDProperties,
CDValue,
CDX,
TerminalIO;
CDDirectoryExtrasImpl:
CEDAR
PROGRAM
IMPORTS CDApplications, CDBasics, CDDirectory, CDEvents, CDInterestRects, CDObjectProcs, CDOps, CDOrient, CDProperties, CDValue, CDX, TerminalIO
EXPORTS CDDirectoryExtras =
BEGIN
furtherKey: ATOM = $ReplaceDirectChild;
ReplaceRec: TYPE = CDDirectoryExtras.ReplaceRec;
ReplaceDChildsProc: TYPE = CDDirectoryExtras.ReplaceDChildsProc;
ReplaceList:
TYPE = CDDirectoryExtras
.ReplaceList
;
ReplaceList: TYPE = LIST OF REF ReplaceRec;
DangerousGetChangeEvent:
PROC []
RETURNS [CDEvents.EventRegistration] =
--remove this silly procedure as fast as possible
BEGIN
x: REF = CDValue.Fetch[key: $CDxPrivateAfterChange];
IF x#NIL THEN TRUSTED {RETURN [LOOPHOLE[x]]}
ELSE {
changeEvent: CDEvents.EventRegistration ~ CDEvents.RegisterEventType[$AfterChange];
CDValue.Store[key: $CDxPrivateAfterChange, value: changeEvent];
RETURN [changeEvent]
}
END;
changeEvent: CDEvents.EventRegistration ~ DangerousGetChangeEvent[];
InstallReplaceDChildProc:
PUBLIC
PROC [type:
REF
CD.ObjectProcs, rdcp: ReplaceDChildsProc] =
BEGIN
CDObjectProcs.StoreFurther[type, furtherKey, NEW[ReplaceDChildsProc←rdcp]];
END;
DoReplaceDirectChild:
PUBLIC ReplaceDChildsProc =
BEGIN
refP: REF = CDObjectProcs.FetchFurther[me.p, furtherKey];
IF refP#
NIL
THEN
WITH refP
SELECT
FROM
rdc: REF ReplaceDChildsProc => changed ← rdc^[me, design, replace];
ENDCASE => NULL;
IF changed
THEN {
[] ← CDEvents.ProcessEvent[changeEvent, design, me];
}
END;
ReplaceObject:
PUBLIC
PROC [design:
CD.Design,
old: CD.ObPtr,
new: CD.ObPtr,
off: CD.DesignPosition←[0, 0]
] =
--all over in the design replace old by new
--may be delayed
BEGIN
repRef:
REF ReplaceRec ←
NEW[ReplaceRec←[
old: old,
oldSize: old.size,
newSize: new.size,
new: new,
off: off
]];
IF design=NIL THEN ERROR;
FOR plist:
LIST
OF
CD.PushRec ← design.actual, plist.rest
WHILE plist#
NIL
DO
IF plist.first.mightReplace#
NIL
AND plist.first.mightReplace.ob=old
THEN
TerminalIO.WriteRope["** Tries to replace pushed in cell; does not work\n"];
ENDLOOP;
ReplaceAllChilds[design, repRef]
END;
RepositionObject:
PUBLIC
PROC [design:
CD.Design,
ob: CD.ObPtr,
oldSize: CD.DesignPosition,
baseOff: CD.DesignPosition←[0, 0]
] =
--all over in the design tries to reposition ob;
--may be delayed
BEGIN
repRef:
REF ReplaceRec ←
NEW[ReplaceRec←[
old: ob,
oldSize: oldSize,
newSize: ob.size,
new: ob,
off: baseOff
]];
oldOrigin: CD.DesignPosition = CDX.ClientOrigin[ob];
CDX.SetClientOrigin[design, ob, CDBasics.SubPoints[oldOrigin, baseOff]];
IF design=NIL THEN ERROR;
ReplaceAllChilds[design, repRef]
END;
ReplaceAllChilds:
PROC [design:
CD.Design, repRef:
REF ReplaceRec] =
--design#NIL
BEGIN
ref:
REF ReplaceList ←
NARROW[
CDValue.Fetch[boundTo: design, key: repositioningListKey, propagation: design]
];
IF ref#
NIL
THEN {
-- we are inside replace process, remember object
IF ref^=NIL THEN ref^ ← LIST[repRef]
ELSE {
FOR l: ReplaceList ← ref^, l.rest
DO
IF l.first.old=repRef.old
THEN
--impossible; call me to debug this
ERROR;
IF l.rest=NIL THEN {l.rest ← LIST[repRef]; EXIT}
ENDLOOP;
};
RETURN
};
-- we are not inside reposition process, start one
ref ← NEW[ReplaceList←LIST[repRef]];
CDValue.Store[boundTo: design, key: repositioningListKey, value: ref];
WHILE ref^#
NIL
DO
repList: ReplaceList ← ref^;
ref^ ← NIL;
DoReplaceAllChilds[design, repList];
ENDLOOP;
CDValue.Store[boundTo: design, key: repositioningListKey, value: NIL];
CDOps.DelayedRedraw[design];
END;
DoReplaceAllChilds:
PUBLIC
PROC [design:
CD.Design, repList: ReplaceList] =
BEGIN
ReplaceForOne: CDDirectory.EachEntryAction =
-- PROC [name: Rope.ROPE, ob: CD.ObPtr] RETURNS [quit: BOOLLSE] --
BEGIN
[] ← DoReplaceDirectChild[me: ob, design: design, replace: repList];
END;
FOR list: ReplaceList ← repList, list.rest
WHILE list#
NIL
DO
list.first.newSize ← list.first.new.size;
ENDLOOP;
[] ← CDDirectory.Enumerate[design, ReplaceForOne];
FOR plist:
LIST
OF
CD.PushRec ← design.actual, plist.rest
WHILE plist#
NIL
DO
app: CD.ApplicationPtr ← plist.first.mightReplace;
CDProperties.PutPropOnObject[plist.first.dummyCell.ob, $Owner, design]; --HACK XXX XXX
FOR rlist: ReplaceList ← repList, rlist.rest
WHILE rlist#
NIL
DO
rep: REF ReplaceRec = rlist.first;
IF app#
NIL
AND app.ob=rep.old
THEN {
realPos:
CD.DesignPosition = CDOrient.MapPosition[
itemInCell: PointRect[rep.off],
cellSize: rep.oldSize,
cellInstOrient: app.orientation,
cellInstPos: app.location
].posInWorld;
fakePos:
CD.DesignPosition = CDOrient.MapPosition[
itemInCell: [0, 0, 0, 0],
cellSize: rep.newSize,
cellInstOrient: app.orientation,
cellInstPos: [0, 0]
].posInWorld;
app.location ← CDBasics.SubPoints[realPos, fakePos];
}
ENDLOOP;
[] ← ReplaceDirectChildForDummyCells[plist.first.dummyCell.ob, repList];
ENDLOOP;
END;
PointRect:
PROC [p:
CD.Position]
RETURNS [
CD.Rect] =
INLINE {
RETURN [[x1: p.x, y1: p.y, x2: p.x, y2: p.y]]
};
ReplaceDirectChildForDummyCells:
PUBLIC
PROC [cellOb:
CD.ObPtr, replace: ReplaceList]
RETURNS [needReposition:
BOOL] =
BEGIN
cp: CD.CellPtr = NARROW[cellOb.specificRef];
needReposition ← FALSE;
FOR replaceList: ReplaceList ← replace, replaceList.rest
WHILE replaceList#
NIL
DO
rep: REF ReplaceRec = replaceList.first;
IF rep.old=cellOb THEN LOOP;
FOR appList:
CD.ApplicationList ← cp.contents, appList.rest
WHILE appList#
NIL
DO
IF appList.first.ob=rep.old
THEN {
IF rep.newSize#rep.oldSize
OR rep.off#[0, 0]
THEN {
realPos:
CD.DesignPosition = CDOrient.MapPosition[
itemInCell: PointRect[rep.off],
cellSize: rep.oldSize,
cellInstOrient: appList.first.orientation,
cellInstPos: appList.first.location
].posInWorld;
fakePos:
CD.DesignPosition = CDOrient.MapPosition[
itemInCell: [0, 0, 0, 0],
cellSize: rep.newSize,
cellInstOrient: appList.first.orientation,
cellInstPos: [0, 0]
].posInWorld;
appList.first.location ← CDBasics.SubPoints[realPos, fakePos];
needReposition ← TRUE;
};
appList.first.ob ← rep.new
};
ENDLOOP;
ENDLOOP;
END;
RepositionCell:
PUBLIC PROC [cellOb:
CD.ObPtr, design:
CD.Design]
RETURNS [didReposition:
BOOLEAN] =
BEGIN
ComputeBounds:
PROC [ob:
CD.ObPtr]
RETURNS [
CD.DesignRect] =
--returns bounds in coordinate system of ob itself
BEGIN
WITH ob.specificRef
SELECT
FROM
cptr: CD.CellPtr => RETURN [CDApplications.BoundingRect[cptr.contents]];
ENDCASE => ERROR;
END;
oldR: CD.DesignRect ← cellOb.p.insideRect[cellOb];
oldSize: CD.DesignPosition ← cellOb.size;
newR: CD.DesignRect = ComputeBounds[cellOb];
newSize: CD.DesignPosition ← CDBasics.SizeOfRect[newR];
newBase: CD.DesignPosition = CDBasics.BaseOfRect[newR];
IF (didReposition ← oldR#newR
OR oldSize#newSize)
THEN {
cp: CD.CellPtr = NARROW[cellOb.specificRef];
IF newBase#[0, 0]
THEN
CDApplications.TranslateList[cp.contents, CDBasics.NegOffset[newBase]];
cellOb.size ← newSize;
IF design#
NIL
THEN
RepositionObject[
design: design,
ob: cellOb,
oldSize: oldSize,
baseOff: newBase
]
}
END;
repositioningListKey: REF ATOM ~ NEW[ATOM←$RepositioningList];
CDValue.EnregisterKey[repositioningListKey];
CDObjectProcs.RegisterFurther[furtherKey];
END.