CDUtilImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, June 10, 1985 12:06:12 pm PDT
Last edited by: Christian Jacobi, November 17, 1986 12:55:38 pm PST
DIRECTORY
CD,
CDBasics,
CDCells,
CDDirectory,
CDInstances,
CDOps,
CDProperties,
CDRects,
Rope,
CDUtil;
CDUtilImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOps, CDProperties, CDRects, Rope
EXPORTS CDUtil =
BEGIN
InstRec: TYPE = CDUtil.InstRec;
Direction: TYPE = CDUtil.Direction;
CreateSimpleCell:
PUBLIC
PROC [design:
CD.Design, contents:
LIST
OF InstRec, cellName: Rope.
ROPE ←
NIL, direction: Direction ← right, alignHigh:
BOOL ←
FALSE]
RETURNS [
CD.Object] = {
r, ir: CD.Rect ← [0, 0, 0, 0];
c: CD.Object = CDCells.CreateEmptyCell[];
inst: CD.Instance;
pos: CD.Position ← [0, 0];
IF Rope.IsEmpty[cellName] THEN cellName ← "-SimpleCell";
NARROW[c.specific, CD.CellSpecific].name ← cellName;
FOR list:
LIST
OF InstRec ← contents, list.rest
WHILE list#
NIL
DO
IF list.first.ob=NIL THEN LOOP;
ir ← CDBasics.MapRect[list.first.ob.bbox, [[0,0], list.first.orient]];
SELECT direction
FROM
right => {
pos.x ← r.x2-ir.x1;
IF alignHigh THEN pos.y ← -ir.y2 ELSE pos.y ← -ir.y1
};
left => {
pos.x ← r.x1-ir.x2;
IF alignHigh THEN pos.y ← -ir.y2 ELSE pos.y ← -ir.y1
};
up => {
pos.y ← r.y2-ir.y1;
IF alignHigh THEN pos.x ← -ir.x2 ELSE pos.x ← -ir.x1
};
down => {
pos.y ← r.y1-ir.y2;
IF alignHigh THEN pos.x ← -ir.x2 ELSE pos.x ← -ir.x1
};
none => pos ← [0, 0];
ENDCASE => ERROR;
inst ← CDCells.IncludeOb[cell: c, ob: list.first.ob,
trans: [[pos.x+list.first.dX, pos.y+list.first.dY], list.first.orient],
mode: dontResize
].newInst;
r ← CDInstances.InstRectI[inst];
IF list.first.properties#
NIL
THEN
CDProperties.AppendProps[inst.properties, list.first.properties, inst];
IF ~Rope.IsEmpty[list.first.name]
THEN
CDProperties.PutInstanceProp[inst, $InstanceName, list.first.name];
ENDLOOP;
[] ← CDCells.ResizeCell[NIL, c];
IF design#NIL THEN [] ← CDDirectory.Include[design, c];
RETURN[c]
};
PartialCopy:
PUBLIC
PROC [ob:
CD.Object, design:
CD.Design, instances:
LIST
OF Rope.
ROPE←
NIL, remove:
BOOL←
TRUE, prop:
ATOM ← $InstanceName, name: Rope.
ROPE←
NIL]
RETURNS [copy:
CD.Object←
NIL] = {
--copy the object; creates a cell
--remove TRUE:
--all the instances with property prop are and a value in instances are removed
--remove FALSE:
--only the instances with property prop are and a value in instances are copied
ExpandToCell:
PROC [ob:
CD.Object, from:
CD.Design]
RETURNS [cell:
CD.Object] = {
--returns cell; however we dont care if cell is in design or not...
tm, cm: CDDirectory.DMode;
cell ← ob;
IF ~CDCells.IsCell[cell]
THEN {
[cell, tm, cm] ← CDDirectory.Expand[ob, from, from];
IF cell=NIL OR ~CDCells.IsCell[cell] THEN RETURN [NIL];
IF cm#included
THEN
IF ~CDDirectory.FixChildren[cell, from] THEN RETURN [NIL]
}
};
ShouldCopy:
PROC[i:
CD.Instance]
RETURNS [copy:
BOOL←
TRUE] = {
--accesses parameters of CopyInst
ref: REF = CDProperties.GetInstanceProp[i, prop];
IF ref#
NIL
THEN {
val: Rope.ROPE = CDOps.ToRope[ref];
FOR rl:
LIST
OF Rope.
ROPE ← instances, rl.rest
WHILE rl#
NIL
DO
IF Rope.Equal[val, rl.first] THEN RETURN [copy ← ~remove];
ENDLOOP
};
copy ← remove
};
cell:
CD.Object ← ExpandToCell[ob, design];
don't care if top level in design; we copy anyway
IF cell#
NIL
THEN {
newList: CD.InstanceList ← NIL;
cp, newCp: CD.CellSpecific;
EachInst: CDCells.InstEnumerator = {
IF ShouldCopy[inst]
THEN
newList ← CONS[CDInstances.Copy[inst], newList];
};
copy ← CDCells.CreateEmptyCell[];
cp ← NARROW[cell.specific];
newCp ← NARROW[copy.specific];
copy.bbox ← cell.bbox;
CDProperties.CopyProps[cell.properties, copy];
newCp^ ← cp^; newCp.sequence ← NIL;
[] ← CDCells.EnumerateInstances[cell, EachInst];
newCp.contents ← newList;
--interest rect: by luck, the right thing happens even without coding
[] ← CDCells.ResizeCell[NIL, copy];
IF design#NIL THEN [] ← CDDirectory.Include[design, copy, name];
}
ELSE ERROR;
};
FlattenChild:
PROC [inst:
CD.Instance, trans:
CD.Transformation, pr:
REF
CD.DrawInformation] = {
fRef: REF FlattenRec = NARROW[pr.devicePrivate];
newInst: CD.Instance ← NEW[CD.InstanceRep←[ob: inst.ob, trans: trans, properties: CDProperties.DCopyProps[inst.properties]]];
IF fRef.flattenInst[newInst] THEN inst.ob.class.drawMe[newInst, trans, pr]
ELSE fRef.cellPtr.contents ← CONS[newInst, fRef.cellPtr.contents];
};
FlattenBareRect:
PROC [r:
CD.Rect, l:
CD.Layer, pr:
CD.DrawRef] = {
fRef: REF FlattenRec = NARROW[pr.devicePrivate];
inst:
CD.Instance ←
NEW[
CD.InstanceRep←[
ob: CDRects.CreateBareRect[size: CDBasics.SizeOfRect[r], l: l],
trans: [CDBasics.BaseOfRect[r], original]
]];
fRef.cellPtr.contents ← CONS[inst, fRef.cellPtr.contents];
};
FlattenRec:
TYPE =
RECORD [
cell: CD.Object,
cellPtr: CD.CellSpecific,
flattenInst: CDUtil.InstPredicate
];
DefaultFlattenInst: CDUtil.InstPredicate = {
IF ~inst.ob.class.inDirectory THEN RETURN [FALSE];
IF CDProperties.GetObjectProp[inst.ob, $DontFlatten]#NIL THEN RETURN [FALSE];
RETURN [TRUE]
};
Flatten:
PUBLIC PROC [ob:
CD.Object, design:
CD.Design, flattenInst: CDUtil.InstPredicate←
NIL]
RETURNS [new:
CD.Object←
NIL] = {
fRef:
REF FlattenRec =
NEW[FlattenRec←[
cell: CDCells.CreateEmptyCell[],
cellPtr: NIL,
flattenInst: IF flattenInst#NIL THEN flattenInst ELSE DefaultFlattenInst
]];
fPr:
CD.DrawRef =
CD.CreateDrawRef[[
design: design,
drawRect: FlattenBareRect,
drawChild: FlattenChild,
selections: FALSE,
devicePrivate: fRef,
contextFilter: NEW[CD.ContextFilter←ALL[TRUE]]
]];
fRef.cellPtr ← NARROW[fRef.cell.specific];
ob.class.drawMe[inst: NEW[CD.InstanceRep←[ob: ob]], trans: [], pr: fPr];
IF ~CDCells.IsEmpty[fRef.cell]
THEN {
name: Rope.ROPE ← CDDirectory.Name[ob];
IF Rope.IsEmpty[name] THEN name ← CDOps.ObjectRope[ob];
fRef.cellPtr.name ← Rope.Concat["!", name];
new ← fRef.cell;
CDCells.SetInterestRect[NIL, new, CD.InterestRect[ob], doit];
IF design#
NIL
THEN {
[] ← CDDirectory.Include[design, new];
[] ← CDDirectory.FixChildren[new, design];
--actually, fixing children would also work for NIL design
--but PW sometimes use NIL design and we don't want to remove
--all children in this case
}
};
};
END.