CDViewerImpl.mesa (part of ChipNDale)
Copyright © 1983, 1986, 1987 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi, October 13, 1983 3:07 pm
Last Edited by: Christian Jacobi, April 17, 1987 12:21:40 pm PDT
DIRECTORY
CD,
CDBasics,
CDDrawQueue,
CDPanel,
CDPrivate,
CDSequencer,
CDViewer,
CDViewerBackdoor,
CDVPrivate,
CDVScale,
Rope USING [ROPE, Equal],
ViewerOps,
ViewerClasses;
CDViewerImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDDrawQueue, CDPanel, CDPrivate, CDViewerBackdoor, CDVPrivate, CDVScale, Rope, ViewerOps
EXPORTS CDViewer
SHARES CDVPrivate, CDPrivate =
BEGIN
Viewer: TYPE = ViewerClasses.Viewer;
ViewerList: TYPE = LIST OF Viewer;
VRef: TYPE = CDVPrivate.VRef;
ViewersOf: PUBLIC PROC [design: REF] RETURNS [vl: ViewerList←NIL] =
BEGIN
WITH design SELECT FROM
vRef: VRef => IF vRef.viewer#NIL THEN RETURN [LIST[vRef.viewer]];
comm: CDSequencer.Command => RETURN [ViewersOf[comm.ref]];
v: Viewer => RETURN [LIST[v]];
vL: ViewerList => RETURN [vL];
ENDCASE => NULL;
FOR l: LIST OF VRef ← CDVPrivate.allVRefs, l.rest WHILE l#NIL DO
IF design=l.first.actualDesign OR design=l.first.actualDesign.technology OR design=NIL THEN
IF l.first.viewer#NIL THEN vl ← CONS[l.first.viewer, vl];
ENDLOOP;
END;
VisibleRect: PUBLIC PROC [viewer: Viewer] RETURNS [r: CD.Rect ← CDBasics.empty] =
--undefined if viewer not open or not ChipNDale design
BEGIN
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => r ← vRef.dClip;
ENDCASE => NULL;
END;
DesignOf: PUBLIC PROC [viewer: Viewer] RETURNS [design: CD.Design ← NIL] =
--NIL if not a ChipNDale design
BEGIN
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => RETURN [vRef.actualDesign];
ENDCASE => NULL;
FOR v: Viewer ← viewer, v.parent WHILE v#NIL DO
WITH ViewerOps.FetchProp[v, $ChipNDaleDesign] SELECT FROM
d: CD.Design => RETURN [d];
ENDCASE => NULL;
ENDLOOP;
END;
ShowPosition: PUBLIC PROC[viewer: Viewer, pos: CD.Position] =
--moves viewer such that pos is in visible area (does not open closed viewer)
--approximative only
BEGIN
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => {
viewerCenterOffset: CD.Position ← [viewer.cw/2, viewer.ch/2];
designCenterOffset: CD.Position;
dscale: CDVScale.ScaleRec ← CDVScale.MakeScale[nscale: vRef.scale.nscale, grid: vRef.scale.grid];
IF CDBasics.InsidePos[pos, vRef.deviceDrawRef.interestClip] THEN RETURN;
CDDrawQueue.Flush[vRef.ct]; --we change the scaleing info! somebody might be drawing
designCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
dscale ← CDVScale.MakeScale[nscale: vRef.scale.nscale, grid: vRef.scale.grid, off: CDBasics.SubPoints[pos, designCenterOffset]];
vRef.intendedScale ← dscale;
RepaintVRef[vRef];
};
ENDCASE => NULL;
END;
ShowAndScale: PUBLIC PROC[viewer: Viewer, rect: CD.Rect] =
--moves and scales viewer such that rect is in visible area (does not open closed viewer)
--approximative only
BEGIN
IF viewer#NIL THEN
WITH viewer.data SELECT FROM
vRef: VRef => {
dscale: CDVScale.ScaleRec;
off: CD.Position ← CDBasics.Center[rect];
s: CARDINAL ← 0;
CDDrawQueue.Flush[vRef.ct]; --we change the scaleing info! somebody might be drawing
FOR j: CARDINAL IN [0..CDVScale.scaleNum) DO
s ← j;
dscale ← CDVScale.MakeScale[nscale: s, grid: 1];
IF CDVScale.ViewerToDesignScalar[dscale, viewer.cw]>(rect.x2-rect.x1)
AND CDVScale.ViewerToDesignScalar[dscale, viewer.ch]>(rect.y2-rect.y1) THEN EXIT;
ENDLOOP;
dscale ← CDVScale.MakeScale[nscale: s, grid: 1];
off.x ← off.x - CDVScale.ViewerToDesignScalar[dscale, viewer.cw]/2;
off.y ← off.y - CDVScale.ViewerToDesignScalar[dscale, viewer.ch]/2;
dscale ← CDVScale.MakeScale[nscale: s, grid: vRef.scale.grid, off: off];
vRef.intendedScale ← dscale;
RepaintVRef[vRef];
};
ENDCASE => NULL;
END;
CreateViewer: PUBLIC PROC [design: CD.Design, openPanel: BOOL] RETURNS [v: Viewer] = {
v ← CDVPrivate.CreateViewer[design];
IF openPanel THEN [] ← CDPanel.Create[design];
};
FindDesign: PUBLIC PROC[name: Rope.ROPE, case: BOOLFALSE] RETURNS [CD.Design] =
--only designs with viewers can be found;
--if multiple designs have the same name, find arbitrary one
BEGIN
FOR l: LIST OF VRef ← CDVPrivate.allVRefs, l.rest WHILE l#NIL DO
IF Rope.Equal[l.first.actualDesign.name, name, case] THEN RETURN[l.first.actualDesign];
ENDLOOP;
RETURN [NIL]
END;
EnumDesigns: PROC[p: CDPrivate.DesignEnumerator] RETURNS [quit: BOOLFALSE] = {
FOR l: LIST OF VRef ← CDVPrivate.allVRefs, l.rest WHILE l#NIL AND ~quit DO
quit ← p[l.first.actualDesign];
ENDLOOP;
};
GetViewer: PUBLIC PROC [comm: CDSequencer.Command] RETURNS [v: Viewer ← NIL] =
BEGIN
IF comm#NIL THEN
WITH comm.ref SELECT FROM
viewer: Viewer => RETURN [viewer];
vRef: VRef => RETURN [vRef.viewer];
ENDCASE => IF comm.design#NIL THEN {
vL: ViewerList ← ViewersOf[comm.design];
IF vL#NIL AND vL.rest=NIL THEN RETURN [vL.first];
};
END;
LastViewer: PUBLIC PROC[] RETURNS [Viewer] = {
RETURN [CDVPrivate.LastViewer[]]
};
--########################################
--extensions
RepaintVRef: PROC[vRef: VRef] = INLINE {
CDDrawQueue.Flush[vRef.ct];
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]];
};
ToInt: PROC [ref: REF] RETURNS [i: INT𡤀] = {
WITH ref SELECT FROM
ri: REF INT => i ← ri^
ENDCASE => NULL
};
GetGrid: ViewerClasses.GetProc = {
vRef: VRef = NARROW[self.data];
RETURN [NEW[INT←vRef.scale.grid]]
};
SetGrid: ViewerClasses.SetProc = {
maxGrid: INT = 2600; --compute carefully such that no overflow can occur
vRef: VRef = NARROW[self.data];
CDDrawQueue.Flush[vRef.ct];
vRef.intendedScale ← CDVScale.MakeScale[
off: vRef.scale.off,
nscale: vRef.scale.nscale,
grid: MIN[maxGrid, MAX[1, ToInt[data]]]
];
RepaintVRef[vRef];
};
GetViewerHard: PROC [design: CD.Design, hint: REFNIL] RETURNS [ViewerClasses.Viewer←NIL] = {
--figures out "the" viewer issued for a design
v: ViewerClasses.Viewer←NIL;
vL: CDViewer.ViewerList←NIL;
WITH hint SELECT FROM
v2: ViewerClasses.Viewer => v ← v2;
comm: CDSequencer.Command =>
IF comm.design=design OR comm.design=NIL THEN v ← GetViewer[comm];
ENDCASE => NULL;
IF v#NIL AND DesignOf[v]=design THEN RETURN [v];
vL ← ViewersOf[design];
IF vL#NIL AND DesignOf[vL.first]=design THEN RETURN [vL.first];
};
GetGridForCDPrivate: PROC [design: CD.Design, hint: REFNIL] RETURNS [g: CD.Number𡤀] = {
v: ViewerClasses.Viewer ← GetViewerHard[design, hint];
IF v#NIL THEN {
WITH ViewerOps.GetViewer[v, $Grid] SELECT FROM
ri: REF INT => g ← ri^;
ENDCASE => NULL;
};
IF g<=0 THEN g ← design.technology.lambda;
};
CDViewerBackdoor.InstallGetProc[$Grid, GetGrid];
CDViewerBackdoor.InstallSetProc[$Grid, SetGrid];
CDPrivate.InstallDesignEnumerator[EnumDesigns];
CDPrivate.InstallGetGrid[GetGridForCDPrivate];
END.