<> <> <> <> 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: 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 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] = { 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]]; CDDrawQueue.QueueInsertDrawCommand[vRef.ct, CDDrawQueue.Request[$redraw, CDBasics.universe]]; }; ToInt: PROC [ref: REF] RETURNS [i: INT_0] = { 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: REF_NIL] 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: REF_NIL] RETURNS [g: CD.Number_0] = { 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.