DIRECTORY Containers USING [Create], Convert USING [RealFromRope], Imager USING [black, Color, MaskVector, SetColor, SetStrokeWidth, white], ImagerBackdoor USING [GetReal], IO USING [GetCedarTokenRope, GetReal, PutF, PutRope, TokenKind], Real USING [CompareREAL], RedBlackTree, --using lots... Rope USING [Equal, ROPE], TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords], Trc, TrcViewers USING [VecFromTIPCoords], Vector2 USING [InlineAdd, Length, Sub, VEC], ViewerClasses USING [Viewer, ViewerRec], ViewerOps USING [PaintViewer]; TrcEditImpl: CEDAR PROGRAM IMPORTS Containers, Convert, Imager, ImagerBackdoor, IO, Real, RedBlackTree, Rope, TIPUser, Trc, TrcViewers, Vector2, ViewerOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector2.VEC; EditInstance: TYPE ~ REF EditInstanceRep; EditInstanceRep: TYPE ~ RECORD [ pins: RedBlackTree.Table _ RedBlackTree.Create[getKey: TrcEditGet, compare: TrcEditCompare], toAdjust: VEC, action: EditAction _ none ]; EditAction: TYPE ~ {none, abort, insert, delete}; Pin: TYPE ~ REF PinRep; PinRep: TYPE ~ RECORD [ vec: Vector2.VEC ]; RealToRef: PROC [real: REAL] RETURNS [ref: REF] ~ INLINE { RETURN [NEW[REAL _ real]]; }; RefToReal: PROC [ref: REF] RETURNS [real: REAL] ~ INLINE { WITH ref SELECT FROM refReal: REF REAL => RETURN [refReal^]; pin: Pin => RETURN [pin.x] ENDCASE => ERROR; }; TrcEditGet: RedBlackTree.GetKey = { RETURN [RealToRef[NARROW[data, Pin].x]]; }; TrcEditCompare: RedBlackTree.Compare = { RETURN [Real.CompareREAL[NARROW[data, Pin].x, RefToReal[k]]]; }; FindNearestPin: PROC [pins: RedBlackTree.Table, loc: VEC] RETURNS [pin: Pin] ~ { left, equal, right: REF; [left, equal, right] _ RedBlackTree.Lookup3[self: pins, lookupKey: RealToRef[loc.x]]; IF equal=NIL THEN { pin1: Pin ~ NARROW[left]; pin2: Pin ~ NARROW[right]; IF pin1=NIL THEN RETURN [pin2]; --Even if it's NIL IF pin2=NIL THEN RETURN [pin1]; RETURN [IF pin1^.Sub[loc].Length[] < pin2^.Sub[loc].Length[] THEN pin1 ELSE pin2]; } ELSE { RETURN [NARROW[equal]] }; }; EditFcn: Trc.Fcn = { instance: EditInstance ~ NARROW[trc.instance]; left, equal, right: REF; [left, equal, right] _ RedBlackTree.Lookup3[self: instance.pins, lookupKey: RealToRef[a]]; IF equal=NIL THEN { pin1: Pin ~ NARROW[left]; pin2: Pin ~ NARROW[right]; IF pin1=NIL THEN { IF pin2=NIL THEN RETURN [a]; --I.e. deleting all the pins produces an identity RETURN [pin2.y]; } ELSE { alpha: REAL; IF pin2=NIL THEN RETURN [pin1.y]; alpha _ (a-pin1.x)/(pin2.x-pin1.x); RETURN [alpha*(pin2.y) + (1.0-alpha)*(pin1.y)] }; } ELSE { RETURN [NARROW[equal, Pin].y] }; }; EditNotify: Trc.NotifyProc = { instance: EditInstance ~ NARROW[trc.instance]; vec: Vector2.VEC; markRequests: LIST OF MarkRequest _ NIL; FOR each: LIST OF REF ANY _ input, each.rest UNTIL each=NIL DO WITH each.first SELECT FROM coords: TIPUser.TIPScreenCoords => { vec _ TrcViewers.VecFromTIPCoords[viewer: viewer, coords: coords]; }; token: ATOM => SELECT token FROM $Commit => { SELECT instance.action FROM delete => [] _ RedBlackTree.Delete[self: instance.pins, deleteKey: RealToRef[instance.toAdjust.x]]; insert => RedBlackTree.Insert[self: instance.pins, dataToInsert: NEW[PinRep _ [instance.toAdjust]], insertKey: RealToRef[instance.toAdjust.x]]; ENDCASE; instance.action _ none; Trc.NotifyListeners[trc: trc, fork: TRUE]; }; $Abort => instance.action _ abort; $Insert => { UNTIL RedBlackTree.Lookup[self: instance.pins, lookupKey: RealToRef[vec.x]]=NIL DO vec.x _ LOOPHOLE[SUCC[LOOPHOLE[vec.x, INT]], REAL]; ENDLOOP; instance.toAdjust _ vec; markRequests _ LIST[[vec]]; instance.action _ insert; }; $Delete => { pin: Pin ~ FindNearestPin[pins: instance.pins, loc: vec]; IF pin#NIL THEN { instance.action _ delete; instance.toAdjust _ pin^; markRequests _ LIST[[pin^, Imager.white]]; }; }; $Adjust => SELECT instance.action FROM delete => { pin: Pin ~ FindNearestPin[pins: instance.pins, loc: vec]; IF pin=NIL THEN ERROR; IF pin^#instance.toAdjust THEN { markRequests _ LIST[[instance.toAdjust], [pin^, Imager.white]]; instance.toAdjust _ pin^; }; }; insert => { IF RedBlackTree.Lookup[self: instance.pins, lookupKey: RealToRef[vec.x]]=NIL THEN { --Otherwise ignore markRequests _ LIST[[instance.toAdjust, Imager.white], [vec]]; instance.toAdjust _ vec; }; }; ENDCASE; ENDCASE; ENDCASE; ENDLOOP; IF markRequests#NIL THEN ViewerOps.PaintViewer[viewer: viewer, hint: client, clearClient: FALSE, whatChanged: markRequests]; }; MarkRequest: TYPE ~ RECORD [vec: VEC, color: Imager.Color _ Imager.black]; EditBackground: Trc.BackgroundProc = { Mark: PROC [vec: VEC] ~ INLINE { Imager.MaskVector[context: context, p1: vec.InlineAdd[[-d,-d]], p2: vec.InlineAdd[[d,d]]]; Imager.MaskVector[context: context, p1: vec.InlineAdd[[d,-d]], p2: vec.InlineAdd[[-d,d]]]; }; instance: EditInstance ~ NARROW[trc.instance]; w: REAL ~ ImagerBackdoor.GetReal[context: context, key: strokeWidth]; d: REAL ~ 3*w; Imager.SetStrokeWidth[context: context, strokeWidth: w/2]; IF whatChanged=NIL THEN { XMarksTheSpot: RedBlackTree.EachNode = { pin: Pin ~ NARROW[data]; Mark[pin^]; }; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: XMarksTheSpot]; } ELSE { WITH whatChanged SELECT FROM atom: ATOM => NULL; --Somebody has us layered markRequest: LIST OF MarkRequest => { FOR each: LIST OF MarkRequest _ markRequest, each.rest UNTIL each=NIL DO Imager.SetColor[context: context, color: each.first.color]; Mark[each.first.vec]; ENDLOOP; }; ENDCASE => ERROR; }; }; EditPickle: Trc.PickleProc = { instance: EditInstance ~ NARROW[trc.instance]; WriteEachPin: RedBlackTree.EachNode = { pin: Pin ~ NARROW[data]; IO.PutF[stream: stream, format: "\n%g\t%g\t%g", v1: [rope[indentation]], v2: [real[pin.x]], v3: [real[pin.y]]]; }; IO.PutRope[self: stream, r: " {"]; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: WriteEachPin]; IO.PutF[stream: stream, format: "\n%g}", v1: [rope[indentation]]]; }; EditDepickle: Trc.DepickleProc = { instance: EditInstance ~ NEW[EditInstanceRep]; token: ROPE; tokenKind: IO.TokenKind; IF ~IO.GetCedarTokenRope[stream: stream].token.Equal["{"] THEN ERROR; [tokenKind: tokenKind, token: token] _ IO.GetCedarTokenRope[stream: stream]; WHILE tokenKind=tokenREAL DO vec: VEC ~ [x: Convert.RealFromRope[token], y: IO.GetReal[stream]]; RedBlackTree.Insert[self: instance.pins, dataToInsert: NEW[PinRep _ [vec]], insertKey: RealToRef[vec.x]]; ENDLOOP; IF ~Rope.Equal[token, "}"] THEN ERROR; }; EditControl: Trc.BuildControlViewerProc = { viewer _ Containers.Create[info: info]; IF trc.instance=NIL THEN { trc.instance _ NEW[EditInstanceRep]; }; }; EditCopy: Trc.CopyProc = { CopyEachPin: RedBlackTree.EachNode = { pin: Pin ~ NARROW[data]; RedBlackTree.Insert[self: newInstance.pins, dataToInsert: NEW[PinRep _ pin^], insertKey: RealToRef[pin.x]]; }; instance: EditInstance ~ NARROW[trc.instance]; newInstance: EditInstance ~ NEW[EditInstanceRep]; new _ NEW[Trc.TRCRep _ [class: trc.class, instance: newInstance, listener: NIL]]; RedBlackTree.EnumerateIncreasing[self: instance.pins, procToApply: CopyEachPin]; }; editClass: Trc.Class ~ NEW[Trc.ClassRep _ [ flavor: $Edit, fcn: EditFcn, blockFcn: Trc.DefaultBlockFcn, copy: EditCopy, pickle: EditPickle, depickle: EditDepickle, notify: EditNotify, tipTable: TIPUser.InstantiateNewTIPTable[file: "TrcEdit.tip"], background: EditBackground, control: EditControl, classData: NIL ]]; Trc.RegisterClass[editClass]; END. TrcEditImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Eric Nickell, April 10, 1986 9:39:00 am PST TrcEdit, EXPORTS TrcEdit OPEN TrcEdit; [data: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] [trc: TRC, a: REAL] RETURNS [b: REAL] [viewer: ViewerClasses.Viewer, trc: TRC, input: LIST OF REF ANY] This is an extreme kludge to get slightly off the pin, but to be as close as can be to it. [trc: TRC, context: Imager.Context, rectangle: ImagerTransformation.Rectangle, whatChanged: REF _ NIL] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] [trc: TRC, stream: STREAM, indentation: ROPE _ NIL] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] [class: Trc.Class, stream: STREAM] RETURNS [trc: TRC] [trc: TRC, info: ViewerClasses.ViewerRec, propList: Properties.PropList _ NIL] RETURNS [viewer: ViewerClasses.Viewer] [trc: TRC] RETURNS [new: TRC] [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] Κ˜™Icodešœ Οmœ1™šžœ žœž˜šœ$˜$K˜BKšœ˜—šœžœžœž˜ –"[trc: TRC, fork: BOOL _ FALSE]šœ ˜ šžœž˜K–;[self: RedBlackTree.Table, deleteKey: RedBlackTree.Key]˜cK–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœAžœK˜Kšžœ˜—K˜Kšœ$žœ˜*Kšœ˜—K˜"šœ ˜ –;[self: RedBlackTree.Table, lookupKey: RedBlackTree.Key]šžœGžœž˜RK™ZKš œžœžœžœžœžœ˜3Kšžœ˜—Kšœ˜Kšœžœ˜K˜Kšœ˜—šœ ˜ K˜9šžœžœžœ˜Kšœ˜Kšœ˜Kšœžœ˜*Kšœ˜—Kšœ˜—šœ žœž˜&šœ ˜ K˜9Kšžœžœžœžœ˜šžœžœ˜ Kšœžœ,˜?K˜Kšœ˜—Kšœ˜—šœ ˜ šžœGžœžœŸ˜fKšœžœ+˜>Kšœ˜Kšœ˜—Kšœ˜—Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ˜—K–w[viewer: ViewerClasses.Viewer, hint: ViewerOps.PaintHint, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL]šžœžœžœBžœ˜|K˜—K–R -- [trc: TRC, context: Imager.Context, rectangle: ImagerTransformation.Rectangle]šœ žœžœžœ&˜Jšœ&˜&Kš£f™fš’œžœžœžœ˜ K–1[context: Imager.Context, p1: VEC, p2: VEC]˜ZK–1[context: Imager.Context, p1: VEC, p2: VEC]˜ZK˜—Kšœžœ˜.K–:[context: Imager.Context, key: ImagerBackdoor.RealKey]šœžœ>˜EKšœžœ˜K–0[context: Imager.Context, strokeWidth: REAL]˜:šžœ žœžœ˜–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜(Kš£:™:Kšœ žœ˜K˜ K˜—K–B[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]˜RKšœ˜—šžœ˜šžœ žœž˜KšœžœžœŸ˜.šœ žœžœ˜%š žœžœžœ&žœžœž˜HK–;[context: Imager.Context, color: ImagerColorDefs.Color]˜;K˜Kšžœ˜—Kšœ˜—Kšžœžœ˜—Kšœ˜—K˜—–7 -- [trc: TRC, stream: STREAM, indentation: ROPE _ NIL]šœ˜Kš£3™3Kšœžœ˜.–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜'Kš£:™:Kšœ žœ˜K–―[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šžœm˜oK˜—Kšžœ ˜"K–B[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]˜QK–―[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šžœ@˜BK˜—–9 -- [class: Trc.Class, stream: STREAM] RETURNS [trc: TRC]šœ"˜"Kš£5™5Kšœžœ˜.Kšœžœ˜ Kšœ žœ ˜K–0[stream: STREAM, flushComments: BOOL _ TRUE]šžœžœ4žœžœ˜EKšœ'žœ#˜Lšžœž˜K–[stream: STREAM]šœžœ'žœ˜CK–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœ7žœ/˜iKšžœ˜—K–-[s1: ROPE, s2: ROPE, case: BOOL _ TRUE]šžœžœžœ˜&K˜—–y -- [trc: TRC, info: ViewerClasses.ViewerRec, propList: Properties.PropList _ NIL] RETURNS [viewer: ViewerClasses.Viewer]˜+Kš£u™uK–™[info: ViewerClasses.ViewerRec _ [class: NIL, wx: 0, wy: 0, ww: 0, wh: 0, cx: 0, cy: 0, cw: 0, ch: 0, lock: [process: PROCESS#0B, count: 0B (0)], tipTable: NIL, name: NIL, file: NIL, label: NIL, menu: NIL, icon: 177777B?, column: left, caption: FALSE, scrollable: TRUE, hscrollable: FALSE, iconic: TRUE, border: TRUE, newVersion: FALSE, newFile: FALSE, visible: TRUE, offDeskTop: FALSE, destroyed: FALSE, init: FALSE, saveInProgress: FALSE, inhibitDestroy: FALSE, guardDestroy: FALSE, paintingWedged: FALSE, ...], paint: BOOL _ TRUE]˜'šžœžœžœ˜Kšœžœ˜$Kšœ˜—K˜—–! -- [trc: TRC] RETURNS [new: TRC]˜Kš£™–> -- [data: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE]˜&Kš£:™:Kšœ žœ˜K–b[self: RedBlackTree.Table, dataToInsert: RedBlackTree.UserData, insertKey: RedBlackTree.Key]šœ:žœ.˜kK˜—Kšœžœ˜.Kšœžœ˜1KšœžœBžœ˜QK–B[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]˜PK˜—šœžœ˜+Kšœ œ˜K˜ Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜K–[file: ROPE _ NIL]šœ  3œ˜>Kšœ˜Kšœ˜Kšœ ž˜K˜—K˜Kšœ˜K˜—K˜Kšžœ˜—…—Έ6Ρ