<> <> DIRECTORY Basics, IO, OrderedSymbolTableRef, Rope, SchemeRep, SchemeEditing, ViewerClasses, ViewerOps, ViewerTools, ViewRec; SchemePictures: CEDAR PROGRAM IMPORTS IO, OrderedSymbolTableRef, Rope, SchemeEditing, ViewerOps, ViewerTools, ViewRec EXPORTS SchemeEditing = BEGIN OPEN SchemeRep, SchemeEditing; CompareNames: PUBLIC OrderedSymbolTableRef.CompareProc --PROC [r1, r2: Item] RETURNS [Comparison]-- = BEGIN ToRope: PROC [any: REF ANY] RETURNS [k: ROPE] = {k _ WITH any SELECT FROM r: ROPE => r, ct: CellType => ct.name, p: Port => p.name, n: Net => n.name, c: Component => c.name, cp: ComponentPort => cp.port.name, pic: PictureDef => pic.name, c: Coord => c.name, pt: Point => pt.name, l: Line => l.name, t: Text => t.name, pi: PictureInstance => pi.name, ENDCASE => ERROR}; k1: ROPE _ ToRope[r1]; k2: ROPE _ ToRope[r2]; RETURN [k1.Compare[k2]]; END; CompareCoords: OrderedSymbolTableRef.CompareProc --PROC [r1, r2: Item] RETURNS [Comparison]-- = BEGIN k1: REAL _ WITH r1 SELECT FROM c: Coord => c.z, l: LORA => NARROW[l.first, Coord].z, r: REF REAL => r^, ENDCASE => ERROR; k2: REAL _ WITH r2 SELECT FROM c: Coord => c.z, l: LORA => NARROW[l.first, Coord].z, r: REF REAL => r^, ENDCASE => ERROR; RETURN [IF k1 < k2 THEN less ELSE IF k1 > k2 THEN greater ELSE equal]; END; NotifyLabels: PUBLIC PROC [labels: LORA, editor: Editor] = BEGIN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: CONS[$Labels, labels]]; END; NewPicture: PUBLIC PROC [session: Session, name: ROPE] RETURNS [pic: PictureDef] = BEGIN pic _ NEW [PictureDefRep _ [ name: name, coordsByValue: [ OrderedSymbolTableRef.CreateTable[CompareCoords], OrderedSymbolTableRef.CreateTable[CompareCoords]], coordsByName: OrderedSymbolTableRef.CreateTable[CompareNames], points: OrderedSymbolTableRef.CreateTable[CompareNames], objects: OrderedSymbolTableRef.CreateTable[CompareNames] ]]; session.picsTable.Insert[pic]; END; Export: PROC [session: Session, export: BOOLEAN] = BEGIN editor: Editor _ session.mostRecentEditor; session.ctlRV.DisplayMessage[ViewRec.clearMessagePlace]; IF editor.primary.point = NIL THEN {Complain[editor, "No point selected"]; RETURN}; IF NOT export THEN { uses: LIST OF ROPE _ FindExportedPointUses[editor.primary.point]; IF uses # NIL THEN {Complain[editor, IO.PutFR["Can't unexport; it's used by %g", IO.refAny[uses]]]; RETURN}; editor.primary.point.exported _ export; RecomputeExported[editor.primary.point.c[X]]; RecomputeExported[editor.primary.point.c[Y]]} ELSE { editor.primary.point.exported _ export; editor.primary.point.c[X].exported _ TRUE; editor.primary.point.c[Y].exported _ TRUE}; END; RecomputeExported: PROC [c: Coord] = {e: BOOL _ FALSE; FOR l: LORA _ c.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM c2: Coord => NULL; p: Point => IF p.exported THEN e _ TRUE; ENDCASE => ERROR; ENDLOOP; c.exported _ e}; FindExportedPointUses: PROC [point: Point] RETURNS [uses: LIST OF ROPE] = BEGIN uses _ NIL; FOR l: LORA _ point.pic.instances, l.rest WHILE l # NIL DO pi: PictureInstance _ NARROW[l.first]; pip: Point _ NARROW[pi.points.Lookup[PIPointName[pi.name, point.name]]]; IF pip.dependents # NIL THEN uses _ CONS[IO.PutFR["%g.%g", IO.rope[pi.in.name], IO.rope[pi.name]], uses]; ENDLOOP; END; PIPointName: PUBLIC PROC [piName, pointName: ROPE] RETURNS [piPointName: ROPE] = {piPointName _ piName.Cat[".", pointName]}; MakePoint: PUBLIC PROC [pic: PictureDef, vertex: Vertex, name: ROPE _ NIL] RETURNS [point: Point] = BEGIN Try: PROC [x: Coord] RETURNS [found: BOOLEAN _ FALSE] = BEGIN FOR l: LORA _ x.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM c: Coord => NULL; p: Point => IF p.c[Y] = vertex[Y] THEN {point _ p; RETURN [TRUE]}; ENDCASE => ERROR; ENDLOOP; END; atX: REF ANY _ pic.coordsByValue[X].Lookup[vertex[X]]; WITH atX SELECT FROM c: Coord => IF Try[c] THEN RETURN; la: LORA => FOR l: LORA _ la, l.rest WHILE l # NIL DO IF Try[NARROW[l.first]] THEN RETURN; ENDLOOP; ENDCASE => ERROR; IF name = NIL THEN name _ NewName[pic.points]; point _ NewPoint[pic, name, vertex]; END; NewPoint: PUBLIC PROC [pic: PictureDef, name: ROPE, vertex: Vertex] RETURNS [point: Point] = BEGIN point _ NEW [PointRep _ [c: vertex, name: name, pic: pic, dependents: NIL]]; pic.points.Insert[point]; vertex[X].dependents _ CONS[point, vertex[X].dependents]; vertex[Y].dependents _ CONS[point, vertex[Y].dependents]; END; nameCount: INT _ 0; NewName: PUBLIC PROC [for: Table] RETURNS [name: ROPE] = {found: REF ANY _ $Found; WHILE found # NIL DO found _ for.Lookup[name _ IO.PutFR["^%g|", IO.int[nameCount _ nameCount + 1]]]; ENDLOOP}; NewCoord: PUBLIC PROC [axis: Axis, at: REAL, pic: PictureDef, parent: REF ANY _ NIL, name: ROPE _ NIL] RETURNS [new: Coord] = BEGIN org: REAL _ IF parent # NIL THEN WITH parent SELECT FROM coord: Coord => coord.z, pi: PictureInstance => pi.org.c[axis].z, ENDCASE => ERROR ELSE 0; IF name = NIL THEN name _ NewName[pic.coordsByName]; new _ EnsureCoord[pic, name]; new^ _ [name: new.name, pic: pic, axis: axis, z: at, sz: at, dependents: NIL, parent: parent, dz: at - org]; EntableCoord[pic.coordsByValue[axis], new]; IF parent # NIL THEN WITH parent SELECT FROM coord: Coord => coord.dependents _ CONS[new, coord.dependents]; pi: PictureInstance => pi.coords.Insert[new]; ENDCASE => ERROR; END; NewLine: PUBLIC PROC [pic: PictureDef, a, b: Point] RETURNS [line: Line] = BEGIN editor: Editor _ NARROW[pic.editor]; IF a = NIL OR b = NIL THEN RETURN [NIL]; IF a.deleted OR b.deleted THEN ERROR; line _ NEW [LineRep _ [name: NewName[pic.objects], a: a, b: b, sa: [0, 0], sb: [0, 0]]]; pic.objects.Insert[line]; a.dependents _ CONS[line, a.dependents]; b.dependents _ CONS[line, b.dependents]; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: line]; END; DeleteLine: PUBLIC PROC [pic: PictureDef, a, b: Point, line: Line _ NIL] = BEGIN editor: Editor _ NARROW[pic.editor]; IF line = NIL THEN line _ FindLine[a, b]; IF line = NIL THEN RETURN; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: line]; line.a.dependents _ Filter[line.a.dependents, line]; line.b.dependents _ Filter[line.b.dependents, line]; [] _ pic.objects.Delete[line]; END; FindLine: PUBLIC PROC [a, b: Point] RETURNS [line: Line] = {IF a = NIL OR b = NIL THEN RETURN [NIL]; FOR l: LORA _ a.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM t: Text => NULL; l2: Line => IF (l2.a = a AND l2.b = b) OR (l2.a = b AND l2.b = a) THEN RETURN [l2]; pi: PictureInstance => NULL; ENDCASE => ERROR; ENDLOOP; line _ NIL}; NewText: PUBLIC PROC [pic: PictureDef, p: Point, rope: ROPE] = BEGIN editor: Editor _ NARROW[pic.editor]; text: Text; text _ NEW [TextRep _ [name: NewName[pic.objects], org: p, sxy: [0, 0], rope: rope]]; pic.objects.Insert[text]; p.dependents _ CONS[text, p.dependents]; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: text]; END; DeleteText: PUBLIC PROC [pic: PictureDef, at: Point, text: Text _ NIL] = BEGIN editor: Editor _ NARROW[pic.editor]; IF text = NIL THEN text _ FindText[at]; IF text = NIL THEN RETURN; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: text]; text.org.dependents _ Filter[text.org.dependents, text]; [] _ pic.objects.Delete[text]; END; FindText: PROC [at: Point] RETURNS [text: Text] = {FOR l: LORA _ at.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM t: Text => IF t.org = at THEN RETURN [t]; l2: Line => NULL; pi: PictureInstance => NULL; ENDCASE => ERROR; ENDLOOP; text _ NIL}; NewInstance: PUBLIC PROC [pic: PictureDef, p: Point, className, iconName: ROPE] = BEGIN editor: Editor _ NARROW[pic.editor]; ct: CellType _ NARROW[editor.session.typesTable.Lookup[className]]; def: PictureDef; IF ct = NIL THEN {Complain[editor, "No such cellType"]; RETURN}; def _ NARROW[IF ct.icons.Size[] = 1 THEN ct.icons.LookupSmallest[] ELSE ct.icons.Lookup[iconName]]; IF def = NIL THEN {Complain[editor, "No such icon"]; RETURN}; [] _ CreateInstance[in: pic, of: def, org: p]; END; FindPI: PUBLIC PROC [at: Point] RETURNS [pi: PictureInstance] = {FOR l: LORA _ at.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM t: Text => NULL; l2: Line => NULL; pi: PictureInstance => IF pi.org = at THEN RETURN [pi]; ENDCASE => ERROR; ENDLOOP; pi _ NIL}; DeleteInstance: PUBLIC PROC [pic: PictureDef, at: Point, pi: PictureInstance _ NIL] = BEGIN check, ok: BOOLEAN _ TRUE; Per: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] = {stop _ FALSE; WITH any SELECT FROM c: Coord => IF check THEN {bad: BOOLEAN _ FALSE; FOR l: LORA _ c.dependents, l.rest WHILE l # NIL DO WITH l.first SELECT FROM c2: Coord => bad _ TRUE; p: Point => bad _ bad OR (p.fromPI # pi); ENDCASE => ERROR; ENDLOOP; IF bad THEN {ok _ FALSE; Complain[editor, IO.PutFR[" exported coord %g has dependents", IO.rope[c.name]]]}} ELSE DeleteCoord[c]; p: Point => IF check THEN {IF p.dependents # NIL THEN {ok _ FALSE; Complain[editor, IO.PutFR[" exported point %g has dependents", IO.rope[p.name]]]}} ELSE DeletePoint[pic, p]; ENDCASE => ERROR}; editor: Editor _ NARROW[pic.editor]; IF pi = NIL THEN pi _ FindPI[at]; IF pi = NIL THEN RETURN; pi.coords.EnumerateIncreasing[Per]; IF NOT ok THEN RETURN; pi.points.EnumerateIncreasing[Per]; IF NOT ok THEN RETURN; check _ FALSE; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: pi]; pi.points.EnumerateIncreasing[Per]; pi.coords.EnumerateIncreasing[Per]; pi.org.dependents _ Filter[pi.org.dependents, pi]; [] _ pic.objects.Delete[pi]; pi.of.instances _ Filter[pi.of.instances, pi]; END; CreateInstance: PUBLIC PROC [in, of: PictureDef, org: Point] RETURNS [pi: PictureInstance] = BEGIN AddCoord: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] = BEGIN inDef: Coord _ NARROW[any]; stop _ FALSE; IF NOT inDef.exported THEN RETURN; IF (inDef.exportedTo # NIL) AND (inDef.exportedTo.parent = pi) THEN RETURN; inDef.exportedTo _ NewCoord[inDef.axis, inDef.z + pi.org.c[inDef.axis].z, in, pi]; END; AddPoint: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] = BEGIN inDef: Point _ NARROW[any]; inCaller: Point; stop _ FALSE; IF NOT inDef.exported THEN RETURN; inCaller _ MakePoint[in, [inDef.c[X].exportedTo, inDef.c[Y].exportedTo], PIPointName[pi.name, inDef.name]]; inCaller.fromPort _ inDef.name; inCaller.fromPI _ pi; pi.points.Insert[inCaller]; END; editor: Editor _ NARROW[in.editor]; pi _ EnsurePictureInstance[in, NewName[in.objects]]; pi^ _ [name: pi.name, in: in, of: of, org: org, s: [0, 0], coords: OrderedSymbolTableRef.CreateTable[CompareNames], points: OrderedSymbolTableRef.CreateTable[CompareNames]]; pi.of.instances _ CONS[pi, pi.of.instances]; org.dependents _ CONS[pi, org.dependents]; of.coordsByName.EnumerateIncreasing[AddCoord]; of.points.EnumerateIncreasing[AddPoint]; IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: pi]; END; CheckInstances: PROC [pic: PictureDef] = BEGIN Check: PROC [any: REF ANY] RETURNS [stop: BOOL] = {stop _ FALSE; WITH any SELECT FROM l: Line => NULL; t: Text => NULL; pi: PictureInstance => IF pi.in # pic THEN ERROR; ENDCASE => ERROR}; pic.objects.EnumerateIncreasing[Check]; END; Complain: PUBLIC PROC [editor: Editor, complaint: ROPE] = {editor.session.ctlRV.DisplayMessage[complaint]}; CreateSession: PROC [name: ROPE] RETURNS [session: Session] = BEGIN ctl: CtlPanel _ NEW [CtlPanelRep _ [ Clear: Clear, ReadFile: ReadFile, WriteFile: WriteFile, CreateCellType: CreateCellType, CreateIcon: CreateIcon, EditType: EditType, Export: Export, cellType: "foo", icon: "bar", name: "baz"]]; session _ NEW [SessionRep _ [ name: name, typesMenu: ViewerTools.MakeNewTextViewer[info: [name: name.Cat[" Types"], iconic: FALSE], paint: FALSE], ctlRV: NIL, ctlPanel: ctl, editors: NIL, typesTable: OrderedSymbolTableRef.CreateTable[CompareNames], picsTable: OrderedSymbolTableRef.CreateTable[CompareNames]]]; ViewerOps.SetOpenHeight[session.typesMenu, 100]; session.ctlRV _ ViewRec.ViewRef[ agg: ctl, specs: ViewRec.BindAllOfATypeFromRefs[rec: ctl, handle: NEW [Session _ session]], viewerInit: [name: name.Cat[" Ctl"], iconic: FALSE]]; END; END.