CDViewerImpl.mesa (part of ChipNDale)
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
by Christian Jacobi, October 13, 1983 3:07 pm
last edited by Christian Jacobi, March 29, 1986 6:51:59 pm PST
DIRECTORY
CD,
CDBasics,
CDDrawQueue,
CDPrivate,
CDSequencer,
CDViewer,
CDViewerBase,
CDVPrivate,
CDVScale,
Rope USING [ROPE, Equal],
ViewerClasses;
CDViewerImpl:
CEDAR
PROGRAM
IMPORTS CDBasics, CDDrawQueue, CDPrivate, CDSequencer, CDViewerBase, CDVPrivate, CDVScale, Rope
EXPORTS CDViewer
SHARES CDVPrivate, CDPrivate =
BEGIN
ViewerList: TYPE = LIST OF ViewerClasses.Viewer;
ViewersOf:
PUBLIC
PROC[design:
REF]
RETURNS [vl: ViewerList←
NIL] =
BEGIN
WITH design
SELECT
FROM
me: CDVPrivate.VRef => IF me.viewer#NIL THEN RETURN [LIST[me.viewer]];
comm: CDSequencer.Command => RETURN [ViewersOf[comm.ref]];
ENDCASE => NULL;
FOR l:
LIST
OF CDVPrivate.VRef ← CDVPrivate.allVRefs, l.rest
WHILE l#
NIL
DO
IF (design=l.first.actualDesign
OR design=l.first.actualDesign.technology OR design=NIL)
AND l.first.viewer#
NIL
THEN
vl ← CONS[l.first.viewer, vl];
ENDLOOP
END;
VisibleRect:
PUBLIC PROC [viewer: ViewerClasses.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
me: CDVPrivate.VRef => r ← me.dClip;
ENDCASE => NULL;
END;
DesignOf:
PUBLIC PROC [viewer: ViewerClasses.Viewer]
RETURNS [design:
CD.Design ←
NIL] =
--NIL if not a ChipNDale design
BEGIN
IF viewer#
NIL
THEN
WITH viewer.data
SELECT
FROM
me: CDVPrivate.VRef => design ← me.actualDesign
ENDCASE => NULL;
END;
ShowPosition:
PUBLIC
PROC[viewer: ViewerClasses.Viewer, pos:
CD.Position] =
--moves viewer such that pos is in visible area (does not open closed viewer)
--approximative only
BEGIN
IF viewer#
NIL
AND viewer.data#
NIL
AND ISTYPE[viewer.data, CDVPrivate.VRef] THEN {
viewerCenterOffset: CD.Position ← [viewer.cw/2, viewer.ch/2];
designCenterOffset: CD.Position;
me: CDVPrivate.VRef = NARROW[viewer.data];
dscale: CDVScale.ScaleRec ← CDVScale.MakeScale[nscale: me.scale.nscale, grid: me.scale.grid];
IF CDBasics.InsidePos[pos, me.deviceDrawRef.interestClip] THEN RETURN;
CDDrawQueue.Flush[me.ct]; --we change the scaleing info! somebody might be drawing
designCenterOffset ← CDVScale.ViewerToDesignPosition[dscale, viewerCenterOffset];
dscale ← CDVScale.MakeScale[nscale: me.scale.nscale, grid: me.scale.grid, off: CDBasics.SubPoints[pos, designCenterOffset]];
me.intendedScale ← dscale;
RepaintViewer[me];
};
END;
ShowAndScale:
PUBLIC
PROC[viewer: ViewerClasses.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
AND viewer.data#
NIL
AND ISTYPE[viewer.data, CDVPrivate.VRef] THEN {
me: CDVPrivate.VRef = NARROW[viewer.data];
dscale: CDVScale.ScaleRec;
off: CD.Position ← CDBasics.Center[rect];
s: CARDINAL ← 0;
CDDrawQueue.Flush[me.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: me.scale.grid, off: off];
me.intendedScale ← dscale;
RepaintViewer[me];
};
END;
CreateViewer:
PUBLIC
PROC [design:
CD.Design, openDialogue:
BOOL]
RETURNS [ViewerClasses.Viewer] =
BEGIN
IF openDialogue THEN CDSequencer.OpenDialogue[design];
RETURN [CDVPrivate.CreateViewer[design]]
END;
FindDesign:
PUBLIC PROC[name: Rope.
ROPE, case:
BOOL ←
FALSE]
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 CDVPrivate.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:
BOOL←
FALSE] =
BEGIN
FOR l:
LIST
OF CDVPrivate.VRef ← CDVPrivate.allVRefs, l.rest
WHILE l#
NIL
AND ~quit
DO
quit ← p[l.first.actualDesign];
ENDLOOP;
END;
GetViewer:
PUBLIC PROC [comm: CDSequencer.Command]
RETURNS [v: ViewerClasses.Viewer ←
NIL] =
BEGIN
IF comm#
NIL
THEN
WITH comm.ref
SELECT
FROM
my: CDVPrivate.VRef => RETURN [my.viewer]
ENDCASE => NULL
END;
LastViewer:
PUBLIC
PROC[]
RETURNS [ViewerClasses.Viewer]=
BEGIN
RETURN [CDVPrivate.LastViewer[]]
END;
--########################################
--extensions
RepaintViewer:
PROC[vRef: CDVPrivate.VRef] =
INLINE BEGIN
CDDrawQueue.Flush[vRef.ct];
CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$changeScale, CDBasics.universe]];
END;
ToInt:
PROC [ref:
REF]
RETURNS [i:
INT𡤀] =
INLINE {
WITH ref
SELECT
FROM
ri: REF INT => i ← ri^
ENDCASE => NULL
};
GetGrid: ViewerClasses.GetProc = {
me: CDVPrivate.VRef = NARROW[self.data];
RETURN [NEW[INT←me.scale.grid]]
};
SetGrid: ViewerClasses.SetProc = {
maxGrid: INT = 2600; --compute carefully such that no overflow can occur
vRef: CDVPrivate.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]]]
];
RepaintViewer[vRef];
};
--########################################
CDViewerBase.ImplementGetProc[$Grid, GetGrid];
CDViewerBase.ImplementSetProc[$Grid, SetGrid];
CDPrivate.InstallDesignEnumerator[EnumDesigns];
END.