CDVCommands.mesa (part of ChipNDale)
Copyright © 1983, 1986, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, June 29, 1983 4:44 pm
Last Edited by: Christian Jacobi, April 1, 1987 8:05:54 pm PST
Some procedures by: Jean-Marc Frailong, June 3, 1987 12:30:59 pm PDT
DIRECTORY
Atom,
CD,
CDBasics,
CDDefaultProcs,
CDDrawQueue,
CDCells,
CDEnvironment,
CDEvents,
CDInstances,
CDOps,
CDPanel,
CDProperties,
CDSequencer,
CDValue,
CDViewer,
CDViewerBackdoor,
CDViewerInternals,
CDVPrivate,
CDVScale,
Imager,
ImagerSample USING [MapFromFrameBuffer, Move, nullFunction],
InterminalBackdoor USING [terminal],
IO,
PopUpSelection,
Process,
Rope,
SF USING [Vec],
Terminal,
TerminalIO,
UserProfile,
VFonts,
ViewerClasses USING [Viewer],
ViewerOps USING [PaintViewer, GetViewer, SetViewer, OpenIcon, BlinkIcon];
CDVCommands:
CEDAR
PROGRAM
IMPORTS Atom, CD, CDBasics, CDDefaultProcs, CDDrawQueue, CDCells, CDEnvironment, CDEvents, CDInstances, CDOps, CDPanel, CDProperties, CDSequencer, CDValue, CDViewer, CDViewerBackdoor, CDVPrivate, CDVScale, Imager, ImagerSample, InterminalBackdoor, IO, PopUpSelection, Process, Rope, Terminal, TerminalIO, UserProfile, ViewerOps, VFonts
EXPORTS CDViewerInternals
SHARES CDVPrivate =
BEGIN
VRef: TYPE = CDVPrivate.VRef;
--Utilities and public
DoWithVRef:
PROC [comm: CDSequencer.Command, proc:
PROC[vRef: VRef]] = {
v: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF v=NIL THEN TerminalIO.PutRope["failed: no viewer\n"]
ELSE
WITH v.data
SELECT
FROM
vRef: VRef => IF ~vRef.viewer.destroyed THEN proc[vRef];
ENDCASE => NULL;
};
AddCR:
PROC [r: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
--if r does not already has a CR
ml: INT ← Rope.Length[r];
IF Rope.Fetch[r, ml-1]#'\n THEN RETURN[Rope.Concat[r, "\n"]];
RETURN [r];
};
MsgAndVRef:
PROC [comm: CDSequencer.Command, msg: Rope.
ROPE]
RETURNS [vRef: VRef←
NIL] = {
v: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
TerminalIO.PutRope[AddCR[msg]];
IF v=NIL THEN TerminalIO.PutRope[" failed: no viewer\n"]
ELSE
WITH v.data
SELECT
FROM
vr: VRef =>
IF ~vr.viewer.destroyed THEN vRef ← vr
ELSE TerminalIO.PutRope[" failed: viewer destroyed\n"];
ENDCASE => TerminalIO.PutRope[" failed: no ChipNDale viewer\n"];
};
Repaint:
PROC [v:
REF] = {
WITH v
SELECT
FROM
vRef: VRef => {
CDDrawQueue.Flush[vRef.ct];
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]];
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]];
};
viewer: ViewerClasses.Viewer => Repaint[viewer.data];
comm: CDSequencer.Command => Repaint[comm.ref];
ENDCASE => NULL;
};
SaveScale:
PUBLIC
PROC [viewer: ViewerClasses.Viewer] = {
IF viewer#
NIL
THEN
WITH viewer.data
SELECT
FROM
vRef: VRef => CDProperties.PutProp[vRef.properties, $CDxSavedScale, NEW[CDVScale.ScaleRec ← vRef.scale]];
ENDCASE => NULL;
};
RestoreScale:
PUBLIC
PROC [viewer: ViewerClasses.Viewer] = {
IF viewer#
NIL
THEN
WITH viewer.data
SELECT
FROM
vRef: VRef => {
GetScale:
PROC [key:
ATOM]
RETURNS [CDVScale.ScaleRec] = {
WITH CDProperties.GetProp[vRef.properties, key]
SELECT
FROM
sr: REF CDVScale.ScaleRec => RETURN [sr^];
ENDCASE => RETURN [CDVScale.MakeScale[]];
};
scale: CDVScale.ScaleRec ← GetScale[$CDxSavedScale];
CDDrawQueue.Flush[vRef.ct];
--NO SaveScale[viewer]; it is better to have one fixed point
IF vRef.scale.off=scale.off
AND vRef.scale.nscale=scale.nscale
THEN
scale ← GetScale[$CDxSecondaryScale];
CDProperties.PutProp[vRef.properties, $CDxSecondaryScale, NEW[CDVScale.ScaleRec ← vRef.scale]];
vRef.intendedScale ← CDVScale.MakeScale[off: scale.off, nscale: scale.nscale, grid: vRef.scale.grid];
Repaint[vRef];
};
ENDCASE => NULL;
};
WriteLnScale:
PROC [v:
REF] = {
TerminalIO.PutRope["\n"];
We don't really write the scale number because the scale is changed asynchrounously
and we don't really know when its done.
WITH v SELECT FROM
vRef: VRef => TerminalIO.PutF1[" (scale: %g)\n", IO.int[vRef.scale.nscale]];
viewer: ViewerClasses.Viewer => WriteLnScale[viewer.data];
comm: CDSequencer.Command => WriteLnScale[comm.ref];
ENDCASE => TerminalIO.PutRope["\n"];
};
ChangeScale:
PROC [vRef: VRef, newScale:
INT] = {
newScale ← MIN[MAX[0, newScale], CDVScale.scaleNum-1];
IF vRef.scale.nscale = newScale
THEN
TerminalIO.PutRope["no scale change"]
ELSE {
oldDesignCenterOffset, newDesignCenterOffset: CD.Position;
viewerCenterOffset: CD.Position ← [vRef.viewer.cw/2, vRef.viewer.ch/2];
off: CD.Position ← vRef.scale.off;
dscale: CDVScale.ScaleRec;
CDDrawQueue.Flush[vRef.ct];
TerminalIO.PutRope["change scale"];
dscale ← CDVScale.MakeScale[nscale: vRef.scale.nscale, grid: vRef.scale.grid];
oldDesignCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
dscale ← CDVScale.MakeScale[nscale: newScale, grid: vRef.scale.grid];
newDesignCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
off ← CDBasics.SubPoints[
CDBasics.AddPoints[off, oldDesignCenterOffset],
newDesignCenterOffset
];
dscale ← CDVScale.MakeScale[off: off, nscale: newScale, grid: vRef.scale.grid];
vRef.intendedScale ← dscale;
Repaint[vRef];
};
WriteLnScale[vRef.viewer];
};
ScaleUp:
PROC [comm: CDSequencer.Command] = {
Do:
PROC[vRef: VRef] = {
i: INT ← vRef.scale.nscale;
i ← IF i>0 THEN i-1 ELSE 0;
ChangeScale[vRef, i];
};
DoWithVRef[comm, Do]
};
ScaleDown:
PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {ChangeScale[vRef, vRef.scale.nscale+1]};
DoWithVRef[comm, Do]
};
SimpleMoveScreen: PROC [comm: CDSequencer.Command] = {
Do: PROC[vRef: VRef] = {
off: CD.Position;
CDDrawQueue.Flush[vRef.ct];
off.x ← vRef.scale.off.x-(comm.pos.x-comm.sPos.x);
off.y ← vRef.scale.off.y-(comm.pos.y-comm.sPos.y);
vRef.intendedScale ← CDVScale.MakeScale[off: off,nscale: vRef.scale.nscale,grid: vRef.scale.grid];
Repaint[vRef];
};
TerminalIO.PutRope["move window\n"];
DoWithVRef[comm, Do]
};
MoveScreenCmd:
PROC [comm: CDSequencer.Command] ~ {
Queue a special paint request as result of the move command. Do NOT flush the queue since display might be uncomplete if repaint is interrupted now.
Do:
PROC[vRef: VRef] = {
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$fastMoveScreen, [x1: comm.pos.x-comm.sPos.x, y1: comm.pos.y-comm.sPos.y, x2: 0, y2: 0]]];
};
TerminalIO.PutRope["move window\n"];
DoWithVRef[comm, Do]
};
GCD:
PROC [ m, n:
INT ]
RETURNS [
INT ] = {
r: INT;
SELECT m
FROM
<0 => m ← -m;
ENDCASE => NULL;
SELECT n
FROM
<0 => n ← -n;
>0 => NULL;
ENDCASE => RETURN[m];
r ← m MOD n;
WHILE r>0 DO m ← n; n ← r; r ← m MOD n; ENDLOOP;
RETURN[n];
};
DoMoveScreen: CDViewerBackdoor.FurtherPaintProc ~ {
Does the repainting associated to MoveScreenCmd. The algorithm is as follows:
- Flush the queue (required because of ordering problems....)
- Under VRef monitor, do:
- check that the scale did not change and the offset is non-null. Quit if so.
- compute offset in viewer coordinates
- compute area of viewer that is part of the old and new view as the intersection between the viewer's client area and the same offsetted (dstBltRect), translate result back by the offset to get srcBltRect
- Blit the right area (under Terminal lock to suppress cursor if color display)
- Enumerate the rectangles of the viewer client space that need repaint, convert them back conservatively to CD coordinates
- If the move could not be done fast, re-queue a regular redraw (a null move results in a full repaint to undo any wedging that might occur) and return
- Set the new scale in effect
- For each rectangle that needs repaint, erase it and queue a redraw command. The erasing is done first to make the display look cleaner to the user... The rectangles are erased twice, but this is necessary to avoid some wedging (pop out of cell and move fast immediately)
ProtectedAction:
PROC [vRef: VRef] ~ {
Contains all the actions that need the VRef to be invariant. This is a conceptually part of the CDVDraw module.
FrameBaseOfViewerRect:
PROC [r:
CD.Rect]
RETURNS [
SF.Vec] ~
INLINE {
Convert a rectangle in viewer coordinates to its base in frame coordinates (origin at top...)
RETURN [[
s: vRef.frame.height-vRef.viewer.wy-r.y2,
f: vRef.viewer.wx+r.x1
]];
};
Blit:
PROC [] ~ {
-- Move bits around
ImagerSample.Move[
map: ImagerSample.MapFromFrameBuffer[vRef.frame],
dstMin: FrameBaseOfViewerRect[dstBltRect],
srcMin: FrameBaseOfViewerRect[srcBltRect],
size: [s: srcBltRect.y2-srcBltRect.y1, f: srcBltRect.x2-srcBltRect.x1],
function: ImagerSample.nullFunction];
};
WillRepaint:
PROC [vr:
CD.Rect
--viewer coordinates--] ~ {
Convert a viewer coordinates rectangle into a design coordinates rectangle guaranteed to be larger when mapped back, and insert it in the repaint list.
toRepaint ←
CONS [
CD.Rect[
x1: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.x1]+vRef.intendedScale.off.x-1,
y1: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.y1]+vRef.intendedScale.off.y-1,
x2: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.x2]+vRef.intendedScale.off.x+1,
y2: CDVScale.UngriddedViewerToDesignScalar[vRef.intendedScale, vr.y2]+vRef.intendedScale.off.y+1
], toRepaint];
};
clientRect, srcBltRect, dstBltRect: CD.Rect;
offset: CD.Position;
Check that fast redraw is possible and consistent
IF vRef.scale.nscale#vRef.intendedScale.nscale OR vRef.scale.off=vRef.intendedScale.off THEN RETURN; -- do a regular redraw
Compute the correct rectangles for the bit blit
clientRect ← [x1: vRef.viewer.cx, y1: vRef.viewer.cy, x2: vRef.viewer.cx+vRef.viewer.cw, y2: vRef.viewer.cy+vRef.viewer.ch]; -- viewer client rect in viewer coords
offset ← CDVScale.DesignToViewerPosition[vRef.intendedScale, vRef.scale.off];
dstBltRect ← CDBasics.Intersection[clientRect, CDBasics.MoveRect[clientRect, offset]];
srcBltRect ← CDBasics.MoveRect[dstBltRect, CDBasics.NegOffset[offset]];
Do the bit-blit, while removing cursor if on color display
IF vRef.display=bw
THEN Blit[]
ELSE Terminal.ModifyColorFrame[vt: InterminalBackdoor.terminal, action: Blit];
Compute the screen rectangles that need repaint, convert them back to CD coordinates and queue them for execution
CDBasics.DecomposeRect[r: clientRect, test: dstBltRect, outside: WillRepaint];
}; -- End of ProtectedAction
toRepaint: LIST OF CD.Rect ← NIL; -- when NIL, means repaint all, erase and paint each rect
req: REF CDDrawQueue.Request ← NARROW[key];
scale: CDVScale.ScaleRec ← me.scale;
off: CD.Position; mod: CD.Number;
Fix offset to keep stipples matching
mod ← MAX[CDVScale.ViewerToDesignScalar[scale, 4], 1];
IF scale.grid>1 THEN mod ← mod/GCD[mod, scale.grid]*scale.grid;
off ← [scale.off.x-req.rect.x1/mod*mod, scale.off.y-req.rect.y1/mod*mod];
me.intendedScale ← CDVScale.MakeScale[off: off, nscale: scale.nscale, grid: scale.grid];
CDDrawQueue.Flush[me.ct];
CDVPrivate.DoInsideMonitor[ProtectedAction, me];
IF toRepaint=
NIL
THEN {
-- cannot do a fast move, do a repaint and quit.
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]];
RETURN;
};
Update scale information in all concerned parties...
CDVPrivate.ResetDrawScale[me];
Repaint the missing parts
WHILE toRepaint#
NIL
DO
CDVPrivate.RepaintBackground[me, toRepaint.first, TRUE]; --immediate
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, toRepaint.first]];--delayed
toRepaint ← toRepaint.rest;
ENDLOOP;
};
GetViewerInt:
PROC [viewer: ViewerClasses.Viewer, at:
ATOM]
RETURNS [i:
INT ← -1] = {
WITH ViewerOps.GetViewer[viewer, at]
SELECT
FROM
ri: REF INT => i ← ri^;
ENDCASE => NULL;
};
GridComm:
PROC [comm: CDSequencer.Command] = {
GridRope:
PROC [v: ViewerClasses.Viewer]
RETURNS [r: Rope.
ROPE] = {
r ← CDOps.LambdaRope[GetViewerInt[viewer, $Grid], lambda]
};
g: INT ← -1;
lambda: INT ← comm.design.technology.lambda;
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer=NIL THEN TerminalIO.PutRope["no viewer\n"]
ELSE {
IF comm.key=$GridDouble THEN g ← GetViewerInt[viewer, $Grid]*2
ELSE IF comm.key=$GridHalf THEN g ← GetViewerInt[viewer, $Grid]/2
ELSE {
TerminalIO.PutF1["grid command (current grid = %g)\n", [rope[GridRope[viewer]]]];
SELECT PopUpSelection.Request[
choice: LIST[" 1", " 2", " 4", " 8", "16", "1/2", "default", "type lambda", "type int", "move selected to grid", "TICKS"],
header: "grid",
headerDoc: "grid = distance used for snapping the cursor"] FROM
1 => g ← lambda;
2 => g ← 2*lambda;
3 => g ← 4*lambda;
4 => g ← 8*lambda;
5 => g ← 16*lambda;
6 => g ← lambda/2;
7 => g ← CDValue.FetchInt[boundTo: CDViewer.DesignOf[viewer], key: $CDxInitGrid, propagation: global];
8 => g ← MIN[INT[2600/lambda], TerminalIO.RequestInt["grid: "]]*lambda;
9 => g ← MIN[INT[2600], TerminalIO.RequestInt["grid: "]];
10 => {MoveToGridComm[comm]; RETURN};
11 => {CDSequencer.ExecuteCommand[key: $TicksInfo, comm: comm]; RETURN};
ENDCASE => g ← -1;
};
IF g>0
AND g<=2600
THEN {
ViewerOps.SetViewer[viewer: viewer, data: NEW[INT←g], op: $Grid];
TerminalIO.PutF1[" grid set to %g \n", IO.rope[CDOps.LambdaRope[g, lambda]]];
}
ELSE TerminalIO.PutRope[" failed \n"];
};
};
ChangeGridComm:
PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
};
SetSimplificationComm:
PROC[comm: CDSequencer.Command] = {
Do:
PROC[vRef: VRef] = {
n: INT;
CDDrawQueue.Flush[vRef.ct];
n ← PopUpSelection.Request[
choice: LIST["very simplified", "simplified", "standard", "detailed", "very detailed", "show all"],
header: "viewer simplification treshold",
headerDoc: "the viewer simplification treshold is multiplied with the cell simplification treshold"
];
SELECT n
FROM
1 => vRef.suppressFactorForCells ← 0.4;
2 => vRef.suppressFactorForCells ← 0.7;
3 => vRef.suppressFactorForCells ← 1;
4 => vRef.suppressFactorForCells ← 1.6;
5 => vRef.suppressFactorForCells ← 2.6;
6 => vRef.suppressFactorForCells ← 0;
ENDCASE => RETURN;
Repaint[vRef]
};
TerminalIO.PutRope["set viewer simplification threshold\n"];
DoWithVRef[comm, Do]
};
InstanceNames:
PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm];
TerminalIO.PutRope["display instance names\n"];
IF v#
NIL
THEN
ViewerOps.PaintViewer[v, client, FALSE, $DrawInstanceNames]
};
SignalNames:
PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
TerminalIO.PutRope["display signal names\n"];
IF v#
NIL
THEN
ViewerOps.PaintViewer[v, client, FALSE, $DrawSignalNames]
};
GetOppositViewer:
PROC [comm: CDSequencer.Command]
RETURNS [ViewerClasses.Viewer] = {
--gets viewer on different screen if possible,
--else different viewer, if possible...
vl: CDViewer.ViewerList = CDViewer.ViewersOf[comm.design];
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
onColor: BOOL = (viewer=NIL OR viewer.column=color);
FOR l: CDViewer.ViewerList ← vl, l.rest
WHILE l#
NIL
DO
IF ~l.first.iconic
THEN
IF (l.first.column=color)#onColor THEN RETURN [l.first];
ENDLOOP;
FOR l: CDViewer.ViewerList ← vl, l.rest
WHILE l#
NIL
DO
IF ~l.first.iconic
THEN
IF l.first.column#viewer.column THEN RETURN [l.first];
ENDLOOP;
FOR l: CDViewer.ViewerList ← vl, l.rest
WHILE l#
NIL
DO
IF ~l.first.iconic
THEN
IF l.first#viewer THEN RETURN [l.first];
ENDLOOP;
RETURN [viewer];
};
ShowRectX:
PROC [comm: CDSequencer.Command] = {
SmallScale:
PROC [comm: CDSequencer.Command]
RETURNS [
BOOL] = {
min: CD.Number = 30;
RETURN [min>ABS[comm.pos.x-comm.sPos.x] AND min>ABS[comm.pos.y-comm.sPos.y]]
};
viewer: ViewerClasses.Viewer ~ GetOppositViewer[comm];
TerminalIO.PutRope["position a viewer\n"];
IF viewer#
NIL
THEN
IF SmallScale[comm] THEN CDViewer.ShowPosition[viewer: viewer, pos: comm.sPos]
ELSE CDViewer.ShowAndScale[viewer: viewer, rect: CDBasics.ToRect[comm.pos, comm.sPos]];
};
RestoreViewComm:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["restore previous scale\n"];
RestoreScale[CDViewer.GetViewer[comm]];
};
ShowRect:
PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer ~ CDViewer.GetViewer[comm];
TerminalIO.PutRope["scale viewer"];
SaveScale[viewer];
IF comm.pos=comm.sPos THEN CDViewer.ShowPosition[viewer, comm.pos]
ELSE CDViewer.ShowAndScale[viewer, CDBasics.ToRect[comm.pos, comm.sPos]];
WriteLnScale[viewer];
};
ResetScaleComm:
PROC [comm: CDSequencer.Command] = {
ResetScaleAll:
PROC [viewer: ViewerClasses.Viewer] = {
b: CD.Rect;
TerminalIO.PutRope["reset scale (view all)"];
b ← CDOps.BoundingBox[CDViewer.DesignOf[viewer]];
IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b];
WriteLnScale[viewer];
};
viewer: ViewerClasses.Viewer ← CDViewer.GetViewer[comm];
IF viewer#
NIL
THEN {
SaveScale[viewer];
ResetScaleAll[viewer];
};
};
ResetScaleToSelectedComm:
PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
TerminalIO.PutRope["reset scale to selection"];
IF viewer#
NIL
THEN {
b: CD.Rect ← CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: TRUE];
IF CDBasics.NonEmpty[b]
THEN {
SaveScale[viewer];
CDViewer.ShowAndScale[viewer: viewer, rect: b];
WriteLnScale[viewer];
RETURN;
};
};
TerminalIO.PutRope[" no selection\n"];
};
ResetScaleToPushedComm:
PROC [comm: CDSequencer.Command] = {
viewer: ViewerClasses.Viewer = CDViewer.GetViewer[comm];
IF viewer#
NIL
THEN {
b: CD.Rect;
SaveScale[viewer];
TerminalIO.PutRope["reset scale (to view all of pushed cell)"];
b ← CDInstances.BoundingRectO[list: CDOps.InstList[comm.design], selectedOnly: FALSE];
IF CDBasics.NonEmpty[b] THEN CDViewer.ShowAndScale[viewer, b];
WriteLnScale[viewer];
};
};
ShowViewersComm:
PROC [comm: CDSequencer.Command] = {
Do:
PROC[vRef: VRef] = {
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$ShowViewers, CDBasics.universe]];
};
TerminalIO.PutRope["show viewers\n"];
DoWithVRef[comm, Do]
};
SplitViewer:
PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["split viewer\n"];
[] ← CDViewer.CreateViewer[comm.design, FALSE]
};
SetCellSimplification:
PROC [comm: CDSequencer.Command] = {
Do:
PROC[vRef: VRef] = {
scale: CDVScale.ScaleRec ← vRef.scale;
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.selected
AND CDCells.IsCell[l.first.ob]
THEN {
simplifyOn: CD.Number ← CDVScale.DesignToViewerScalar[scale, l.first.ob.bbox.y2-l.first.ob.bbox.y1];
CDCells.SetSimplificationTreshhold[l.first.ob, simplifyOn, TRUE];
CDOps.RedrawInstance[comm.design, l.first];
};
ENDLOOP;
};
TerminalIO.PutRope["put visibility threshold to current scale\n"];
DoWithVRef[comm, Do]
};
EnforcePanel:
PROC [comm: CDSequencer.Command] = {
v: ViewerClasses.Viewer;
TerminalIO.PutRope["enforce a control panel\n"];
v ← CDPanel.Create[comm.design];
IF v#
NIL
THEN {
IF v.iconic THEN ViewerOps.OpenIcon[v]
ELSE ViewerOps.BlinkIcon[v, 1, 1, 200]
};
};
FontSubstOnComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: substitute tioga fonts"];
IF vRef#
NIL
THEN {
vRef.fontSubstitution ← TRUE;
CDProperties.PutProp[comm.design, $CDxSubstituteFonts, $TRUE];
Repaint[vRef];
};
};
FontSubstOffComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't substitute tioga fonts"];
IF vRef#
NIL
THEN {
vRef.fontSubstitution ← FALSE;
CDProperties.PutProp[comm.design, $CDxSubstituteFonts, NIL];
Repaint[vRef];
};
};
DrawEnvComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw environment of pushed cells"];
IF vRef#
NIL
THEN {
vRef.environment ← TRUE;
CDProperties.PutProp[comm.design, $CDxDrawEnvironment, NIL];
Repaint[vRef];
};
};
DontDrawEnvComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw environment of pushed cells"];
IF vRef#
NIL
THEN {
vRef.environment ← FALSE;
CDProperties.PutProp[comm.design, $CDxDrawEnvironment, $FALSE];
Repaint[vRef];
};
};
DrawSymbolicsComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw symbolic objects"];
IF vRef#
NIL
THEN {
vRef.symbolics ← TRUE;
CDProperties.PutProp[comm.design, $CDxDrawSymbolics, NIL];
Repaint[vRef];
};
};
DontDrawSymbolicsComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw symbolic objects"];
IF vRef#
NIL
THEN {
vRef.symbolics ← FALSE;
CDProperties.PutProp[comm.design, $CDxDrawSymbolics, $FALSE];
Repaint[vRef];
};
};
DrawBordersComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: draw with borders"];
IF vRef#
NIL
THEN {
vRef.borders ← TRUE;
CDProperties.PutProp[comm.design, $CDxSkipBorder, $FALSE];
Repaint[vRef];
};
};
DontDrawBordersComm:
PROC [comm: CDSequencer.Command] = {
vRef: VRef ← MsgAndVRef[comm, "viewer drawmode: don't draw borders"];
IF vRef#
NIL
THEN {
vRef.borders ← FALSE;
CDProperties.PutProp[comm.design, $CDxSkipBorder, NIL];
Repaint[vRef];
};
};
CheckEdited:
PROC [design:
CD.Design] = {
IF design#
NIL
THEN {
edited: BOOL ← design.edited;
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf[design], vl.rest
WHILE vl#
NIL
DO
IF vl.first.newVersion#edited
THEN {
vl.first.newVersion ← edited;
ViewerOps.PaintViewer[vl.first, caption]
};
ENDLOOP
}
};
CheckEditedEvent: CDEvents.EventProc = {
TRUSTED {Process.Detach[FORK CheckEdited[design]]};
};
NoteProfileChange: UserProfile.ProfileChangedProc = {
IF reason=edit
THEN {
FOR vl: CDViewer.ViewerList ← CDViewer.ViewersOf[
NIL], vl.rest
WHILE vl#
NIL
DO
d: CD.Design ← CDViewer.DesignOf[vl.first];
IF d#NIL THEN vl.first.tipTable ← CDEnvironment.GetTipTable[d];
ENDLOOP
};
};
MoveToGridComm:
PROC [comm: CDSequencer.Command] = {
selCnt, movCnt: INT ← 0;
grid: CD.Number ← CDOps.GetGrid[comm.design, comm];
TerminalIO.PutRope["move (interest rect) to grid positions;"];
IF grid<1 THEN {TerminalIO.PutRope["failed: bad grid value"]; RETURN};
FOR l:
CD.InstanceList ← CDOps.InstList[comm.design], l.rest
WHILE l#
NIL
DO
IF l.first.selected
THEN {
pos: CD.Position ← CDBasics.BaseOfRect[CDInstances.InstRectI[l.first]];
gridded: CD.Position ← [(pos.x)/grid*grid, (pos.y)/grid*grid];
selCnt ← selCnt+1;
IF gridded#pos
THEN {
CDSequencer.MarkChanged[comm.design];
CDOps.RedrawInstance[comm.design, l.first];
l.first.trans.off ← CDBasics.AddPoints[l.first.trans.off, CDBasics.SubPoints[gridded, pos]];
CDOps.RedrawInstance[comm.design, l.first, FALSE];
movCnt ← movCnt+1;
};
};
ENDLOOP;
TerminalIO.PutF[" %g selected, %g moved objects\n", [integer[selCnt]], [integer[movCnt]]];
};
ShowViewers: CDViewerBackdoor.FurtherPaintProc = {
--monitored by ProtectedRepaint
OutlineViewer:
PROC [me: CDVPrivate.VRef, other: ViewerClasses.Viewer] = {
otherMe: CDVPrivate.VRef = NARROW[other.data];
r: CD.Rect = otherMe.dClip;
p1: CD.Position = CDVScale.DesignToViewerPosition[me.scale, [r.x1, r.y1]];
p2: CD.Position = CDVScale.DesignToViewerPosition[me.scale, [r.x2, r.y2]];
CDVPrivate.InvertArea[me, p1.x, p1.y, p1.x+1, p2.y];
CDVPrivate.InvertArea[me, p1.x, p2.y, p2.x, p2.y+1];
CDVPrivate.InvertArea[me, p2.x, p2.y, p2.x+1, p1.y];
CDVPrivate.InvertArea[me, p2.x, p1.y, p1.x, p1.y+1];
};
FOR l: CDViewer.ViewerList ← CDViewer.ViewersOf[me.actualDesign], l.rest
WHILE l#
NIL
DO
IF ~l.first.iconic AND l.first#me.viewer THEN OutlineViewer[me: me, other: l.first];
ENDLOOP
};
PaintSignalNames: CDViewerBackdoor.FurtherPaintProc = {
--monitored by ProtectedRepaint
PaintProperties[me, $SignalName]
};
PaintInstanceNames: CDViewerBackdoor.FurtherPaintProc = {
--monitored by ProtectedRepaint
PaintProperties[me, $InstanceName]
};
IgnoreContext: CD.DrawContextProc = {};
PaintProperties:
PROC [me: CDVPrivate.VRef, key:
ATOM] = {
nameDevice: REF NameDevice ← NEW[NameDevice←[propKey: key, vPriv: me]];
internalPr:
CD.DrawRef =
CD.CreateDrawRef[[
design: me.actualDesign,
interestClip: me.dClip,
devicePrivate: nameDevice,
drawChild: NamedDrawChild,
drawRect: CDDefaultProcs.IgnoreRect,
drawContext: IgnoreContext,
stopFlag: me.stoprequest
]];
Imager.SetColor[me.viewContext, Imager.black];
Imager.SetFont[me.viewContext, defaultFont];
CDOps.DrawDesign[me.actualDesign, internalPr];
};
NameDevice: TYPE = RECORD [propKey: ATOM, vPriv: CDVPrivate.VRef];
defaultFont: Imager.Font = VFonts.DefaultFont[];
NamedDrawChild: CD.DrawProc = {
dev: REF NameDevice = NARROW[pr.devicePrivate];
text: Rope.ROPE ← NIL;
ob.class.drawMe[pr, ob, trans, readOnlyInstProps];
WITH CDProperties.GetListProp[readOnlyInstProps, dev.propKey]
SELECT
FROM
r: Rope.ROPE => text ← r;
a: ATOM => text ← Atom.GetPName[a];
ENDCASE => NULL;
IF text#
NIL
THEN {
r: CD.Rect ← CDBasics.MapRect[CD.InterestRect[ob], trans];
p: CD.Position ← CDVScale.DesignToViewerPosition[dev.vPriv.scale, CDBasics.BaseOfRect[r]];
Imager.SetXY[dev.vPriv.viewContext, [p.x+1, p.y+1]];
Imager.SetColor[dev.vPriv.viewContext, Imager.black];
Imager.SetFont[dev.vPriv.viewContext, defaultFont];
Imager.ShowRope[dev.vPriv.viewContext, text];
};
};
DrawSignalNames: CDViewerBackdoor.FurtherPaintProc = {
-- called from anywhere, not monitored
CDDrawQueue.QueueInsertDrawCommand[me.ct, [$SignalNames, CDBasics.universe]];
};
DrawInstanceNames: CDViewerBackdoor.FurtherPaintProc = {
-- called from anywhere, not monitored
CDDrawQueue.QueueInsertDrawCommand[me.ct, [$InstanceNames, CDBasics.universe]];
};
UserProfile.CallWhenProfileChanges[NoteProfileChange];
CDPanel.Button[tech: NIL, button: [text: "stop"], command: $AbortCommand, queue: dontQueue, topLine: TRUE];
CDPanel.Button[tech: NIL, button: [text: "split"], proc: SplitViewer, queue: dontQueue, topLine: TRUE];
CDSequencer.ImplementCommand[$ScaleLessDetail, ScaleDown,, dontQueue];
CDSequencer.ImplementCommand[$ScaleMoreDetail, ScaleUp,, dontQueue];
CDSequencer.ImplementCommand[$MoveScreen, MoveScreenCmd,, dontQueue];
CDSequencer.ImplementCommand[$DisplayNames, SignalNames,, doQueue];
CDSequencer.ImplementCommand[$DisplayInstanceNames, InstanceNames,, doQueue];
CDSequencer.ImplementCommand[$ShowRectX, ShowRectX,, dontQueue];
CDSequencer.ImplementCommand[$ShowRect, ShowRect,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleAll, ResetScaleComm,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleTop, ResetScaleToPushedComm,, dontQueue];
CDSequencer.ImplementCommand[$ResetScaleSel, ResetScaleToSelectedComm,, dontQueue];
CDSequencer.ImplementCommand[$DisplayViewers, ShowViewersComm,, doQueue];
CDSequencer.ImplementCommand[$SplitViewer, SplitViewer,, dontQueue];
CDSequencer.ImplementCommand[$GridInfo, GridComm,, doQueue];
CDSequencer.ImplementCommand[$GridDouble, GridComm,, doQueue];
CDSequencer.ImplementCommand[$GridHalf, GridComm,, doQueue];
CDSequencer.ImplementCommand[$SetSimplification, SetSimplificationComm,, dontQueue];
CDSequencer.ImplementCommand[$RestoreScale, RestoreViewComm,, dontQueue];
CDSequencer.ImplementCommand[$SetCellSimplification, SetCellSimplification];
CDSequencer.ImplementCommand[$EnforcePanel, EnforcePanel,, doQueue];
CDSequencer.ImplementCommand[$ViewFSub, FontSubstOnComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNFSub, FontSubstOffComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewEnv, DrawEnvComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNEnv, DontDrawEnvComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewSym, DrawSymbolicsComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNSym, DontDrawSymbolicsComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewBord, DrawBordersComm,, dontQueue];
CDSequencer.ImplementCommand[$ViewNBord, DontDrawBordersComm,, dontQueue];
CDSequencer.ImplementCommand[$MoveToGrid, MoveToGridComm, NIL, doQueue];
CDEvents.RegisterEventProc[event: $AfterOutput, proc: CheckEditedEvent];
CDEvents.RegisterEventProc[event: $CheckEdited, proc: CheckEditedEvent];
--protected procedures
CDViewerBackdoor.InstallFurtherPaint[keyValue: $ShowViewers, proc: ShowViewers];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $SignalNames, proc: PaintSignalNames];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $InstanceNames, proc: PaintInstanceNames];
--unprotected procedures
CDViewerBackdoor.InstallFurtherPaint[keyValue: $DrawSignalNames, proc: DrawSignalNames];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $DrawInstanceNames, proc: DrawInstanceNames];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $fastMoveScreen, proc: DoMoveScreen];
END.