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:
BOOLEAN←
FALSE]
RETURNS [bound:
CD.Rectsics.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 REF ← ALL[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.