DIRECTORY
CD, CDBasics, CDDirectory, CDFeedback, CDOps, CDProperties, CDRects, CDViewer, CDCells, ImagerTransformation, Real, Rope;
CDFeedbackImpl:
CEDAR
PROGRAM
IMPORTS CDBasics, CDDirectory, CDOps, CDProperties, CDRects, CDViewer, CDCells, ImagerTransformation, Real
EXPORTS CDFeedback =
{OPEN CDFeedback;
Showing: TYPE = REF ShowingRep;
ShowingRep:
PUBLIC
TYPE =
RECORD [
design: CD.Design,
insts: InstanceList ← NIL];
InstanceList: TYPE = LIST OF Instance;
Instance:
TYPE =
RECORD [
in: CD.Object,
appl: CD.Instance];
feedbackKey: PUBLIC ATOM ← $Feedback;
EmptyShow: PUBLIC SIGNAL = CODE;
NoneVisible: PUBLIC SIGNAL = CODE;
Show:
PUBLIC PROC [
design: CD.Design,
rect:
CD.Rect,
Will be clipped to bounding box of containing cells.
message: Rope.
ROPE ←
NIL,
Goes on the application as value of $SignalName property.
flag:
ATOM ← $feedback,
Goes on the application as value of feedbackKey property.
in: CellType,
EnumerateSomeInstances:
PROC [
cellType: CellType,
to: PROC [transform: Transform, parent: CellType] RETURNS [stop: BOOL]
]
EnumerateSomeInstances may enumerate as many or as few (even none, if you're willing to live with the consequences) of the instances of cellType as it wishes.
]
RETURNS [showing: Showing] =
{
AddRect:
PROC [r:
CD.Rect, obj:
CD.Object] = {
ir: CD.Rect ← IF obj # NIL THEN CDBasics.Intersection[r, CDBasics.RectAt[pos: [0,0], size: obj.size]] ELSE r;
ro: CD.Object ← CDRects.CreateRect[size: CDBasics.SizeOfRect[ir], l: CD.errorLayer];
appl:
CD.Instance ← CDCells.IncludeOb[design: design, cell: obj, ob: ro,
position: CDBasics.BaseOfRect[ir],
cellCSystem: cdCoords,
obCSystem: interrestCoords].newInst;
CDProperties.PutInstanceProp[appl, $SignalName, message];
CDProperties.PutInstanceProp[appl, feedbackKey, flag];
showing.insts ← CONS[[obj, appl], showing.insts];
madeMarks ← TRUE;
};
someVisibleBounds: CD.Rect;
madeMarks, foundVisible: BOOL ← FALSE;
FindTop:
PROC [r:
CD.Rect, ct: CellType] = {
IF ct = top
THEN {
IF foundVisible THEN ERROR ELSE someVisibleBounds ← r;
foundVisible ← TRUE}
ELSE {
TryInstance:
PROC [transform: Transform, parent: CellType]
RETURNS [stop:
BOOL] = {
FindTop[TransformRect[r, transform], parent];
stop ← foundVisible
};
EnumerateSomeInstances[ct, TryInstance];
};
};
Mark:
PROC [r:
CD.Rect, ct: CellType] = {
IF ct = top
THEN {
AddRect[r, NIL];
IF NOT foundVisible THEN FindTop[r, top];
}
ELSE {
MarkInInstance:
PROC [transform: Transform, parent: CellType]
RETURNS [stop:
BOOL] = {
Mark[TransformRect[r, transform], parent];
stop ← FALSE;
};
shownHere: BOOL -- in names a ChipNDale object that is a cell in design--;
found: BOOL;
obj: CD.Object;
[found, obj] ← CDDirectory.Fetch[design, ct];
shownHere ← found AND ISTYPE[obj.specificRef, CD.CellPtr];
IF shownHere
THEN {
AddRect[r, obj];
IF NOT foundVisible THEN FindTop[r, ct]
}
ELSE {
EnumerateSomeInstances[ct, MarkInInstance];
}
};
};
showing ← NEW [ShowingRep ← [design]];
Mark[rect, in];
IF foundVisible
THEN {
--scroll to show someVisibleBounds
vl: CDViewer.ViewerList ← CDViewer.ViewersOf[design];
FOR vl ← vl, vl.rest
WHILE vl #
NIL
DO
IF CDViewer.DesignOf[vl.first].design = design THEN CDViewer.ShowAndScale[viewer: vl.first, rect: someVisibleBounds];
ENDLOOP;
}
ELSE IF madeMarks THEN NoneVisible[]
ELSE EmptyShow[];
};
UnShow:
PUBLIC
PROC [showing: Showing] = {
FOR il: InstanceList ← showing.insts, il.rest
WHILE il #
NIL
DO
[] ← CDCells.RemoveInstance[design: showing.design, cell: il.first.in, inst: il.first.appl]
ENDLOOP;
CDOps.Redraw[showing.design];
};
TransformRect:
PROC [r:
CD.Rect, t: Transform]
RETURNS [s:
CD.Rect] = {
tr: ImagerTransformation.Rectangle ← ImagerTransformation.TransformRectangle[
t, [x: r.x1, y: r.y1, w: r.x2 - r.x1, h: r.y2 - r.y1]];
s ←
CD.Rect[
x1: Real.Round[tr.x],
y1: Real.Round[tr.y],
x2: Real.Round[tr.x + tr.w],
y2: Real.Round[tr.y + tr.h]
];
};
Start:
PROC = {
[] ← CDProperties.RegisterProperty[feedbackKey];
};
Start[];
}.