CDSimpleOpsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 12, 1983 10:56 am
Last edited by: Christian Jacobi, October 30, 1986 10:30:04 am PST
DIRECTORY
CD,
CDBasics,
CDEvents,
CDInstances,
CDOps,
CDProperties,
CDSimpleOps,
Rope USING [IsEmpty, ROPE],
TerminalIO;
CDSimpleOpsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDEvents, CDInstances, CDOps, CDProperties, Rope, TerminalIO
EXPORTS CDSimpleOps
SHARES CD =
BEGIN
renameEvent: CDEvents.EventRegistration ← CDEvents.RegisterEventType[$RenameDesign];
RenameDesign: PUBLIC PROC [design: CD.Design, name: Rope.ROPE] RETURNS [done: BOOL] = {
--is only local name
dont: BOOL;
oldName: Rope.ROPE ← design.name;
IF Rope.IsEmpty[name] THEN RETURN [FALSE];
design.name ← name;
dont ← CDEvents.ProcessEvent[renameEvent, design, oldName, TRUE];
IF dont THEN {
design.name ← oldName;
[] ← CDEvents.ProcessEvent[renameEvent, design, oldName, FALSE];
};
done ← ~dont
};
Select: PUBLIC PROC [design: CD.Design, pos: CD.Position, verbose: BOOL] = {
sel: CD.Instance ← NIL;
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF ~w.first.selected THEN {
IF CDInstances.PointToI[pos, w.first] THEN {sel ← w.first; EXIT}
};
ENDLOOP;
IF sel#NIL THEN {
sel.selected ← TRUE;
--reorder list, future select selects next lower application
CDOps.ReOrderInstance[design, sel];
CDOps.RedrawInstance[design, sel];
IF verbose THEN TerminalIO.PutRope[CDOps.InstRope[sel]];
}
ELSE IF verbose THEN {
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF w.first.selected THEN {
IF CDInstances.PointToI[pos, w.first] THEN {
TerminalIO.PutRopes[CDOps.InstRope[w.first], " again"];
RETURN
}
};
ENDLOOP;
TerminalIO.PutRope[" no pointed object"];
}
};
DeSelect: PUBLIC PROC [design: CD.Design, pos: CD.Position, verbose: BOOL] = {
inst: CD.Instance ← CDInstances.InstanceAt[CDOps.InstList[design], pos, TRUE];
IF inst#NIL THEN {
IF ~inst.selected THEN ERROR;
inst.selected ← FALSE;
CDOps.RedrawInstance[design, inst];
--reorder list, future select op finds next lower application
CDOps.ReOrderInstance[design, inst];
};
IF verbose THEN TerminalIO.PutRope[CDOps.InstRope[inst]];
};
BoundingRectAndCount: PROC [list: CD.InstanceList, selectedOnly: BOOLEANFALSE] RETURNS [bound: CD.Rect�sics.empty, cnt: INT𡤀] = {
FOR tem: LIST OF CD.Instance ← list, tem.rest WHILE tem#NIL DO
IF selectedOnly AND NOT tem.first.selected THEN LOOP;
cnt ← cnt+1;
bound ← CDBasics.Surround[bound, CDInstances.InstRectO[tem.first]]
ENDLOOP;
};
DeselectAll: PUBLIC PROC [design: CD.Design] = {
doItSingleWise: NAT = 4;
sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]];
b: CD.Rect;
cnt: INT;
[b, cnt] ← BoundingRectAndCount[list: sel];
CDInstances.DeSelectList[sel];
IF cnt<=doItSingleWise THEN
FOR l: CD.InstanceList ← sel, l.rest WHILE l#NIL DO
CDOps.RedrawInstance[design, l.first]
ENDLOOP
ELSE CDOps.Redraw[design, b];
};
SelectAll: PUBLIC PROC [design: CD.Design] = {
--dont care about redrawing too much
b: CD.Rect ← CDInstances.BoundingRectO[list: CDOps.InstList[design], selectedOnly: FALSE];
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
w.first.selected ← TRUE
ENDLOOP;
CDOps.Redraw[design, b, FALSE];
};
AreaSelectTouched: PROC [design: CD.Design, area: CD.Rect] = {
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF NOT w.first.selected
AND CDBasics.Intersect[area, CDInstances.InstRectI[w.first]] THEN {
w.first.selected ← TRUE;
CDOps.RedrawInstance[design, w.first, FALSE];
};
ENDLOOP;
};
AreaDeSelectTouched: PROC [design: CD.Design, area: CD.Rect] = {
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF w.first.selected
AND CDBasics.Intersect[area, CDInstances.InstRectI[w.first]] THEN {
w.first.selected ← FALSE;
CDOps.RedrawInstance[design, w.first];
};
ENDLOOP;
};
AreaSelectContained: PROC [design: CD.Design, area: CD.Rect] = {
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF CDBasics.Inside[CDInstances.InstRectI[w.first], area] THEN w.first.selected ← TRUE
ENDLOOP;
CDOps.Redraw[design, area, FALSE];
};
AreaDeSelectContained: PROC [design: CD.Design, area: CD.Rect] = {
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF CDBasics.Inside[CDInstances.InstRectI[w.first], area] THEN w.first.selected ← FALSE
ENDLOOP;
CDOps.Redraw[design, area];
};
AreaSelect: PUBLIC PROC [design: CD.Design, area: CD.Rect, includePartial: BOOL] = {
IF includePartial THEN AreaSelectTouched[design, area]
ELSE AreaSelectContained[design, area];
};
AreaDeSelect: PUBLIC PROC [design: CD.Design, area: CD.Rect, includePartial: BOOL] = {
IF includePartial THEN AreaDeSelectTouched[design, area]
ELSE AreaDeSelectContained[design, area];
};
DeleteSelected: PUBLIC PROC [design: CD.Design, verbose: BOOL] = {
count: INT ← 0;
toDelete, newContents: CD.InstanceList;
[selected: toDelete, others: newContents] ← CDInstances.SplitSelected[CDOps.InstList[design]];
CDOps.SetInstList[design, newContents];
FOR w: CD.InstanceList ← toDelete, w.rest WHILE w#NIL DO
count ← count+1;
CDOps.RedrawInstance[design, w.first, TRUE];
ENDLOOP;
IF verbose THEN {
IF count#1 THEN TerminalIO.PutF1["%g objects", [integer[count]]]
ELSE TerminalIO.PutRope[CDOps.InstRope[toDelete.first]]
};
RememberShortTime[design, toDelete];
};
RedrawMoved: PROC [design: CD.Design, r: CD.Rect, offset: CD.Position] = {
moved: CD.Rect ← CDBasics.MoveRect[r, offset];
IF CDBasics.Intersect[r, moved] THEN
CDOps.Redraw[design, CDBasics.Surround[r, moved], TRUE]
ELSE {
CDOps.Redraw[design, r];
CDOps.Redraw[design, moved]; -- use eraseFirst because also used by copy
}
};
MoveSelected: PUBLIC PROC [design: CD.Design, offset: CD.Position] = {
sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]];
bounding: CD.Rect ← CDBasics.empty;
FOR w: CD.InstanceList ← sel, w.rest WHILE w#NIL DO
inst: CD.Instance ← w.first;
bounding ← CDBasics.Surround[bounding, CDInstances.InstRectO[inst]];
inst.trans.off ← CDBasics.AddPoints[inst.trans.off, offset];
ENDLOOP;
RedrawMoved[design, bounding, offset]
};
CopySelected: PUBLIC PROC [design: CD.Design, offset: CD.Position] = {
new: CD.InstanceList←NIL;
sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]];
bounding: CD.Rect ← CDInstances.BoundingRectO[sel];
FOR w: CD.InstanceList ← sel, w.rest WHILE w#NIL DO
inst: CD.Instance ← CDInstances.Copy[w.first];
inst.trans.off ← CDBasics.AddPoints[inst.trans.off, offset];
inst.selected ← TRUE;
new ← CONS[inst, new];
w.first.selected ← FALSE;
ENDLOOP;
CDOps.IncludeInstanceList[design, new, FALSE];
RedrawMoved[design, bounding, offset];
};
TransformSelected: PUBLIC PROC [design: CD.Design, transform: CD.Orientation, base: CD.Rect] = {
ib, is, orientOff: CD.Position; r, oldbb: CD.Rect; oldPseudoCellT, newPseudoCellT: CD.Transformation;
sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]];
IF sel=NIL THEN RETURN;
oldbb ← CDInstances.BoundingRectO[sel];
IF ~CDBasics.NonEmpty[base] THEN base ← CDInstances.BoundingRectI[sel];
ib ← CDBasics.BaseOfRect[base];
is ← CDBasics.SizeOfRect[base];
oldPseudoCellT ← [ib, original];
r ← CDBasics.MapRect[CDBasics.RectAt[[0,0], is], [[0,0], transform]];
orientOff ← CDBasics.BaseOfRect[r];
newPseudoCellT ← [CDBasics.SubPoints[ib, orientOff], transform];
FOR w: CD.InstanceList ← sel, w.rest WHILE w#NIL DO
pseudoCellRel: CD.Transformation ← CDBasics.DecomposeTransform[w.first.trans, oldPseudoCellT];
w.first.trans ← CDBasics.ComposeTransform[pseudoCellRel, newPseudoCellT]
ENDLOOP;
CDOps.Redraw[design, oldbb];
CDOps.Redraw[design, CDBasics.MapRect[CDBasics.DeMapRect[oldbb, oldPseudoCellT], newPseudoCellT]]
};
-- -- -- -- -- -- -- -- -- -- -- --
remSize: CARDINAL = 20;
RememberBuffer: TYPE = RECORD[
a: ARRAY [0..remSize) OF REFALL[NIL],
next: CARDINAL𡤀];
Forgett: PROC[class: REF] = {
--helps the garbage collector,
--special may prevent circularities through properties
WITH class SELECT FROM
il: CD.InstanceList =>
FOR l: CD.InstanceList ← il, l.rest WHILE l#NIL DO
Forgett[l.first]
ENDLOOP;
inst: CD.Instance => {inst.properties ← NIL; inst.ob ← NIL};
ENDCASE => NULL;
};
GetDeletedList: PROC [d: CD.Design] RETURNS [REF RememberBuffer] = {
WITH CDProperties.GetListProp[d.unDoBuffers^, $delete] SELECT FROM
dl: REF RememberBuffer => RETURN [dl];
ENDCASE => {
dl: REF RememberBuffer ← NEW[RememberBuffer];
CDProperties.PutProp[d.unDoBuffers, $delete, dl];
RETURN [dl]
};
};
RememberShortTime: PROC [d: CD.Design, what: REF] = {
dl: REF RememberBuffer ← GetDeletedList[d];
Forgett[dl.a[dl.next]];
dl.a[dl.next] ← what;
dl.next ← (dl.next+1) MOD remSize;
};
GiveRemembered: PROC [d: CD.Design] RETURNS [REF] = {
x: REF;
dl: REF RememberBuffer ← GetDeletedList[d];
IF dl=NIL THEN RETURN [NIL];
dl.next ← (dl.next+remSize-1) MOD remSize;
x ← dl.a[dl.next];
dl.a[dl.next] ← NIL;
RETURN [x];
};
Undelete: PUBLIC PROC [design: CD.Design, n: INT𡤀] = {
del: REF ← GiveRemembered[design];
IF del=NIL THEN RETURN;
WITH del SELECT FROM
il: CD.InstanceList => CDOps.IncludeInstanceList[design, il];
inst: CD.Instance => CDOps.IncludeInstance[design, inst]
ENDCASE => NULL;
};
FlushDeletedCache: PUBLIC PROC [design: CD.Design] = {
dl: REF RememberBuffer ← GetDeletedList[design];
IF dl#NIL THEN{
dl.next ← (dl.next+remSize-1) MOD remSize;
DO
dl.next ← (dl.next+remSize-1) MOD remSize;
IF dl.a[dl.next]=NIL THEN EXIT;
Forgett[dl.a[dl.next]];
dl.a[dl.next] ← NIL;
ENDLOOP;
};
design.unDoBuffers ← CD.InitPropRef[];
};
END.