CDSymbolicObjectsImpl.mesa (part of ChipNDale)
Copyright © 1984, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, August 8, 1984 12:41:50 pm PDT
Last Edited by: Christian Jacobi, August 16, 1986 6:32:13 pm PDT
DIRECTORY
CD,
CDInstances,
CDBasics,
CDLayers USING [MakeAbstract, AbstractToPaint],
CDImports,
CDIO,
CDOps,
CDOrient,
CDSymbolicObjects,
CDPrivate,
CDProperties,
CDRects,
Imager,
ImagerPath,
LRUCache,
Rope;
CDSymbolicObjectsImpl: CEDAR MONITOR
IMPORTS CD, CDInstances, CDBasics, CDLayers, CDIO, CDOps, CDOrient, CDPrivate, CDProperties, CDRects, Imager, ImagerPath, LRUCache, Rope
EXPORTS CDSymbolicObjects
SHARES CDLayers =
BEGIN
symNameProp: ATOM = $SignalName;
symLayerProp: ATOM = $layerOfPin;
symOwnerProp: ATOM = $ownerOfPin;
markObject: CD.Object;
markObjectPath: ImagerPath.Trajectory = CreateMarkObjectPath[];
dummySpecific: REF SymRec = NEW[SymRec];
SymRec: TYPE = RECORD [dummy: INT ← 17];
pinLayer: PUBLIC CD.Layer ← CD.NewLayer[NIL, $pinRepresentation];
segmentLayer: PUBLIC CD.Layer ← CD.NewLayer[NIL, $segmentRepresentation];
markLayer: CD.Layer ← CD.undefLayer;
lruQueue: LRUCache.Handle ← LRUCache.Create[87, CDPrivate.Hash, Equal];
freePin: CD.Object ← NIL; --reduces the allocators work
freeSegment: CD.Object ← NIL;
GivePin: ENTRY PROC [] RETURNS [ob: CD.Object] = INLINE {
ob ← freePin; freePin ← NIL;
IF ob=NIL THEN
ob ← NEW[CD.ObjectRep←[class: pinClass, specificRef: dummySpecific, layer: pinLayer]];
};
GiveSegment: ENTRY PROC [] RETURNS [ob: CD.Object] = INLINE {
ob ← freeSegment; freeSegment ← NIL;
IF ob=NIL THEN
ob ← NEW[CD.ObjectRep←[class: segmentClass, specificRef: dummySpecific, layer: segmentLayer]];
};
Equal: PROC[x, y: REF] RETURNS [BOOL] = {
ob1: CD.Object = NARROW[x];
ob2: CD.Object = NARROW[y];
RETURN [ob1.class=ob2.class AND ob1.size=ob2.size AND ob1.layer=ob2.layer]
};
pinClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$PinOb0, [
drawMe: DrawPin,
quickDrawMe: DrawPin,
showMeSelected: ShowSelectedSymRL,
internalRead: ReadPin,
internalWrite: WritePinOrSegment,
wireTyped: TRUE,
symbolic: TRUE,
description: "pin",
describeInst: DescribeInstance
]];
segmentClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$SymbolicSegment, [
drawMe: DrawSegment,
quickDrawMe: DrawSegment,
showMeSelected: ShowSelectedSymRL,
internalRead: ReadSegment,
internalWrite: WritePinOrSegment,
wireTyped: TRUE,
symbolic: TRUE,
description: "segment",
describeInst: DescribeInstance
]];
markClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$AlignmentMarkOb, [
drawMe: DrawMark,
quickDrawMe: DrawMark,
internalRead: ReadMark,
internalWrite: WriteMark,
symbolic: TRUE,
description: "mark"
]];
CreateMarkObjectPath: PROC [] RETURNS [markObjectPath: ImagerPath.Trajectory] = {
markObjectPath ← ImagerPath.MoveTo[[0, 0]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [0, 3]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [1, 2]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [3, 4]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [4, 3]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [2, 1]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [3, 0]];
markObjectPath ← ImagerPath.LineTo[markObjectPath, [0, 0]];
};
Init: PROC [] = {
--rects
CDLayers.MakeAbstract[pinLayer];
CDRects.UseAsCreateRect[pinLayer, RCreatePin, pinClass];
--lines
CDLayers.MakeAbstract[segmentLayer];
CDRects.UseAsCreateRect[segmentLayer, RCreateSegment, segmentClass];
--points
markObject ← NEW[CD.ObjectRep ← [
class: markClass,
size: [4, 4],
layer: markLayer,
specificRef: $AlignmentMarkOb
]];
--common
[] ← CDProperties.RegisterProperty[symLayerProp, $layer];
[] ← CDProperties.RegisterProperty[symOwnerProp, $atom];
CDProperties.InstallProcs[prop: symOwnerProp, new: [makeCopy: CDProperties.CopyVal]];
CDProperties.InstallProcs[prop: symLayerProp, new: [makeCopy: CDProperties.CopyVal]];
};
CreateMark: PUBLIC PROC [dummySize: CD.Number𡤀] RETURNS [CD.Object] = {
RETURN [markObject]
};
CreateSegment: PUBLIC PROC [length: CD.Number, dummyWidth: CD.Number𡤀] RETURNS [ob: CD.Object] = {
used: REF; insert: BOOL;
ob ← GiveSegment[];
IF dummyWidth<=0 THEN dummyWidth ← 8;
ob.size ← CDBasics.MaxPoint[[dummyWidth, length], [1, 1]];
[insert: insert, used: used] ← LRUCache.Include[lruQueue, ob];
IF ~insert THEN {
freeSegment ← ob;
ob ← NARROW[used];
};
};
RCreateSegment: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] = {
RETURN [CreateSegment[size.y, size.x]]
};
CreatePin: PUBLIC PROC [size: CD.Position] RETURNS [ob: CD.Object] = {
used: REF; insert: BOOL;
ob ← GivePin[];
ob.size ← CDBasics.MaxPoint[size, [1, 1]];
[insert: insert, used: used] ← LRUCache.Include[lruQueue, ob];
IF ~insert THEN {
freePin ← ob;
ob ← NARROW[used];
};
};
RCreatePin: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] = {
--has the right form for CDRects type
RETURN [CreatePin[size]]
};
IsSymbolicOb: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN [ob.class=markClass OR ob.class=segmentClass OR ob.class=pinClass]
};
IsMark: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN [ob.class=markClass]
};
IsSegment: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN [ob.class=segmentClass]
};
IsPin: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN [ob.class=pinClass]
};
SymbolicKind: PUBLIC PROC [ob: CD.Object] RETURNS [k: CDSymbolicObjects.Kind] = {
SELECT TRUE FROM
ob.class=pinClass => k ← pin;
ob.class=segmentClass => k ← segment;
ob.class=markClass => k ← mark;
ENDCASE => k ← notSymbolic
};
SetOwner: PUBLIC PROC [symInst: CD.Instance, owner: ATOMNIL] = {
IF IsSymbolicOb[symInst.ob] THEN
CDProperties.PutInstanceProp[symInst, symOwnerProp, owner]
};
GetOwner: PUBLIC PROC [symInst: CD.Instance] RETURNS [at: ATOM] = {
WITH CDProperties.GetInstanceProp[symInst, symOwnerProp] SELECT FROM
a: ATOM => at ← a
ENDCASE => at ← NIL
};
SetName: PUBLIC PROC [symInst: CD.Instance, name: Rope.ROPE] = {
IF IsSymbolicOb[symInst.ob] THEN
CDProperties.PutInstanceProp[symInst, symNameProp, name]
};
GetName: PUBLIC PROC [symInst: CD.Instance] RETURNS [r: Rope.ROPENIL] = {
IF IsSymbolicOb[symInst.ob] THEN {
WITH CDProperties.GetInstanceProp[symInst, symNameProp] SELECT FROM
n: Rope.ROPE => r ← n;
rt: REF READONLY TEXT => r ← Rope.FromRefText[rt];
ENDCASE => NULL;
}
};
SetLayer: PUBLIC PROC [symInst: CD.Instance, layer: CD.Layer] = {
IF IsSymbolicOb[symInst.ob] THEN
CDProperties.PutInstanceProp[symInst, symLayerProp, CDPrivate.layers[layer]]
};
GetLayer: PUBLIC PROC [symInst: CD.Instance] RETURNS [layer: CD.Layer] = {
WITH CDProperties.GetInstanceProp[symInst, symLayerProp] SELECT FROM
lp: CDPrivate.LayerRef => layer ← lp^.number
ENDCASE => layer ← CD.undefLayer
};
DirectionFromOrient: PUBLIC PROC [o: CD.Orientation] RETURNS [dir: CDSymbolicObjects.Direction] = {
SELECT o FROM
CDOrient.original, CDOrient.rotate180X => dir ← west;
CDOrient.rotate90, CDOrient.rotate90X => dir ← south;
CDOrient.rotate180, CDOrient.mirrorX => dir ← east;
CDOrient.rotate270, CDOrient.rotate270X => dir ← north;
ENDCASE => ERROR;
};
OrientFromDirection: PUBLIC PROC [dir: CDSymbolicObjects.Direction] RETURNS [o: CD.Orientation] = {
SELECT dir FROM
west => o ← CDOrient.original;
south => o ← CDOrient.rotate90;
east => o ← CDOrient.rotate180;
north => o ← CDOrient.rotate270;
ENDCASE => ERROR;
};
CreateSymInst: PUBLIC PROC [name: Rope.ROPE, denotes: CD.Rect, dummySize: CD.Number, layer: CD.Layer, owner: ATOM, approachFrom: CDSymbolicObjects.Direction] RETURNS [symInst: CD.Instance] = {
symOb: CD.Object;
orient: CD.Orientation ← OrientFromDirection[approachFrom];
loc: CD.Position;
denotes ← CDBasics.NormalizeRect[denotes];
IF denotes.x1#denotes.x2 AND denotes.y1#denotes.y2 THEN {
--pin
loc ← CDBasics.BaseOfRect[denotes];
symOb ← CreatePin[CDOrient.OrientedSize[CDBasics.SizeOfRect[denotes], orient]];
}
ELSE IF denotes.x1=denotes.x2 AND denotes.y1=denotes.y2 THEN {
--mark
p: CD.Position;
symOb ← CreateMark[dummySize];
p ← CDOrient.MapPoint[
pointInCell: [0, 0],
cellSize: symOb.size,
cellInstOrient: orient,
cellInstPos: [0, 0]
];
loc ← [x: denotes.x1-p.x, y: denotes.y1-p.y];
}
ELSE {
--segment
l: CD.Number;
IF denotes.x1=denotes.x2 THEN {
l ← denotes.y2-denotes.y1;
IF approachFrom=south OR approachFrom=north THEN {
-- erroneous parameters..
approachFrom ← west;
orient ← OrientFromDirection[approachFrom];
}
}
ELSE {
l ← denotes.x2-denotes.x1;
IF approachFrom=west OR approachFrom=east THEN {
-- erroneous parameters..
approachFrom ← south;
orient ← OrientFromDirection[approachFrom];
}
};
symOb ← CreateSegment[length: l, dummyWidth: dummySize];
loc ← CDBasics.BaseOfRect[denotes];
SELECT approachFrom FROM
west, south => NULL;
east => loc.x ← loc.x-symOb.size.x;
north => loc.y ← loc.y-symOb.size.x;
ENDCASE => ERROR;
};
layer ← CDLayers.AbstractToPaint[layer];
symInst ← CDInstances.NewInst[ob: symOb, location: loc, orientation: orient];
IF name#NIL THEN SetName[symInst, name];
IF layer#CD.undefLayer THEN SetLayer[symInst, layer];
IF owner#NIL THEN SetOwner[symInst, owner];
};
Denotes: PUBLIC PROC [symInst: CD.Instance] RETURNS [CD.Rect] = {
itemInCell: CD.Rect;
SELECT TRUE FROM
symInst.ob.class=pinClass => itemInCell ← [x1: 0, y1: 0, x2: symInst.ob.size.x, y2: symInst.ob.size.y];
symInst.ob.class=segmentClass => itemInCell ← [x1: 0, y1: 0, x2: 0, y2: symInst.ob.size.y];
symInst.ob.class=markClass => itemInCell ← [0, 0, 0, 0];
ENDCASE => ERROR;
RETURN [CDOrient.MapRect[
itemInCell: itemInCell,
cellInstPos: symInst.location,
cellSize: symInst.ob.size,
cellInstOrient: symInst.orientation
]]
};
EnumerateSymbolicObs: PUBLIC PROC [cellOb: CD.Object←NIL, eachInst: CDSymbolicObjects.InstEnumerator] RETURNS [quit: BOOLFALSE] = {
cp: CD.CellPtr;
WITH cellOb.specificRef SELECT FROM
c: CD.CellPtr => cp ← c;
ip: CDImports.ImportPtr => { -- HACK? until imports handle symbolic objects more reasonably
IF ip.boundInstance=NIL THEN RETURN [TRUE];
quit ← EnumerateSymbolicObs[ip.boundInstance.ob, eachInst];
RETURN
};
ENDCASE => RETURN [TRUE];
FOR list: CD.InstanceList ← cp.contents, list.rest WHILE (list#NIL AND ~quit) DO
IF IsSymbolicOb[list.first.ob] THEN {
quit ← eachInst[list.first]; -- do NOT catch errors
};
ENDLOOP;
};
FindSymbolicObs: PUBLIC PROC [cellOb: CD.Object←NIL, name: Rope.ROPE] RETURNS [il: CD.InstanceList←NIL] = {
Enumerate: CDSymbolicObjects.InstEnumerator = {
IF Rope.Equal[GetName[inst], name] THEN il ← CONS[inst, il];
};
[] ← EnumerateSymbolicObs[cellOb, Enumerate];
};
WritePinOrSegment: CD.InternalWriteProc -- PROC [me: Object] -- = {
CDIO.WritePos[me.size];
};
WriteMark: CD.InternalWriteProc --PROC [me: Object]-- = {
};
ReadPin: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {
RETURN [CreatePin[CDIO.ReadPos[]]]
};
ReadSegment: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {
p: CD.Position ← CDIO.ReadPos[];
RETURN [CreateSegment[p.y, p.x]]
};
ReadMark: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {
RETURN [markObject]
};
DescribeInstance: PROC[i: CD.Instance] RETURNS [Rope.ROPE] = {
RETURN [Rope.Cat[CDOps.LayerName[GetLayer[i]], " ", i.ob.class.description]];
};
ShowSelectedSymRL: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = {
pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], CD.shadeLayer, pr]
};
DrawPin: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] = {
DrawPinInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
Imager.MaskVector[context, [0, 0], [ob.size.x, ob.size.y]];
Imager.MaskVector[context, [0, ob.size.y], [ob.size.x, 0]];
};
IF pr.symbolics AND (pr.scaleHint*MIN[inst.ob.size.y, inst.ob.size.x]>3 OR pr.scaleHint<=0) THEN {
pr.drawContext[pr, DrawPinInContext, inst.ob, pos, orient, pinLayer];
pr.drawComment[r: CDOrient.RectAt[pos, inst.ob.size, orient], comment: GetName[inst], pr: pr]
};
};
DrawSegment: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] = {
DrawSegmentInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
Imager.MaskVector[context, [0, 0], [0, ob.size.y]];
Imager.MaskVector[context, [0, 0], [ob.size.x, ob.size.y/2]];
Imager.MaskVector[context, [0, ob.size.y], [ob.size.x, ob.size.y/2]];
};
IF pr.symbolics AND (pr.scaleHint*inst.ob.size.y>3 OR pr.scaleHint<=0) THEN {
pr.drawContext[pr, DrawSegmentInContext, inst.ob, pos, orient, segmentLayer];
pr.drawComment[r: CDOrient.RectAt[pos, inst.ob.size, orient], comment: GetName[inst], pr: pr]
}
};
DrawMark: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] = {
DrawPath: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
Imager.MaskFillTrajectory[context, markObjectPath];
};
IF pr.symbolics AND (pr.scaleHint*inst.ob.size.y>2 OR pr.scaleHint<=0) THEN {
pr.drawContext[pr, DrawPath, markObject, pos, orient, markLayer]
}
};
Init[];
END.