DIRECTORY Controls, ControlsPrivate, Draw2d, Imager, ViewerClasses, ViewerOps; ControlsSketchImpl: CEDAR PROGRAM IMPORTS ControlsPrivate, Draw2d, Imager, ViewerOps EXPORTS Controls, ControlsPrivate ~ BEGIN OPEN Controls; Chain: TYPE ~ REF ChainRep; ChainRep: TYPE ~ RECORD [ p0, p1: INTEGER _ 0, -- current vector to draw firstRun: Run _ NIL, lastRun: Run _ NIL, pairs: PosSequence _ NIL -- chain points ]; Run: TYPE ~ REF RunRep; RunRep: TYPE ~ RECORD [ start, stop: INTEGER _ 0, -- inclusive indices into pairs next: Run _ NIL ]; NewSketch: PUBLIC PROC [control: Control] ~ { chain: Chain _ NEW[ChainRep]; control.sketchRef _ chain; chain.pairs _ NEW[PosSequenceRep[10000]]; -- should be large enough chain.firstRun _ NEW[RunRep]; chain.lastRun _ chain.firstRun; }; EnlargePosSequence: PROC [chain: Chain] ~ { IF chain # NIL AND chain.pairs # NIL THEN { old: PosSequence _ chain.pairs; new: PosSequence _ NEW[PosSequenceRep[2*old.maxLength]]; FOR n: NAT IN [0..old.length) DO new[n] _ old[n]; ENDLOOP; new.length _ old.length; chain.pairs _ new; }; }; ClearSketch: PUBLIC PROC [control: Control, repaint: BOOL _ TRUE] ~ { IF control.type = sketch THEN { chain: Chain _ NARROW[control.sketchRef]; newChain: Chain _ NEW[ChainRep _ [pairs: chain.pairs]]; chain.pairs.length _ 0; control.sketchRef _ newChain; newChain.firstRun _ NEW[RunRep]; newChain.lastRun _ newChain.firstRun; IF repaint THEN ViewerOps.PaintViewer[control.viewer, client, FALSE, NIL]; }; }; AddPos: PROC [chain: Chain, pair: Pos] ~ { pairs: PosSequence _ chain.pairs; IF pairs.length = pairs.maxLength THEN EnlargePosSequence[chain]; pairs[pairs.length] _ pair; pairs.length _ pairs.length+1; }; NotifySketch: PUBLIC PROC [control: Control] ~ { chain: Chain _ NARROW[control.sketchRef]; mouse: Mouse _ control.mouse; SELECT mouse.state FROM down => { chain.p0 _ chain.p1 _ chain.pairs.length; IF chain.firstRun = NIL THEN { chain.firstRun _ NEW[RunRep_ [start: chain.p0]]; chain.lastRun _ chain.firstRun; } ELSE { chain.lastRun.next _ NEW[RunRep]; chain.lastRun _ chain.lastRun.next; chain.lastRun.start _ chain.p0; }; AddPos[chain, [mouse.x, mouse.y]]; }; held => { chain.p1 _ chain.pairs.length; chain.p0 _ chain.p1-1; AddPos[chain, [mouse.x, mouse.y]]; }; up => chain.lastRun.stop _ chain.p1; ENDCASE => RETURN; ViewerOps.PaintViewer[control.viewer, client, FALSE, control]; IF mouse.state = up THEN ControlsPrivate.MaybeForkControlProc[control]; }; LinePos: PROC [context: Context, p0, p1: Pos] ~ { Draw2d.Line[context, [p0.x, p0.y], [p1.x, p1.y]]; }; PaintSketch: PUBLIC ViewerClasses.PaintProc ~ { control: Control _ NARROW[self.data]; chain: Chain _ NARROW[control.sketchRef]; IF chain = NIL THEN RETURN; IF whatChanged = NIL THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, 0, 0, self.ww, self.wh]; Imager.SetColor[context, Imager.black]; SketchReDraw[context, chain]; } ELSE { pairs: PosSequence _ chain.pairs; LinePos[context, pairs[chain.p0], pairs[chain.p1]]; }; }; SketchReDraw: PROC [context: Context, chain: Chain] ~ { pairs: PosSequence _ chain.pairs; start: Run _ chain.firstRun; FOR run: Run _ start, run.next WHILE run # NIL DO FOR n: NAT IN [run.start..run.stop) DO LinePos[context, pairs[n], pairs[n+1]]; ENDLOOP; ENDLOOP; }; GetSketch: PUBLIC PROC [control: Control] RETURNS [PosSequences] ~ { chain: Chain _ NARROW[control.sketchRef]; chainPoss: PosSequence _ chain.pairs; start: Run _ chain.firstRun; sketch: PosSequences _ NEW[PosSequencesRep]; FOR run: Run _ start, run.next WHILE run # NIL DO n: INTEGER _ 0; sketchPoss: PosSequence _ NEW[PosSequenceRep[run.stop-run.start+1]]; sketch[sketch.length] _ sketchPoss; sketch.length _ sketch.length+1; FOR r: NAT IN [run.start..run.stop] DO sketchPoss[n] _ chainPoss[r]; n _ n+1; ENDLOOP; ENDLOOP; RETURN[sketch]; }; SetSketch: PUBLIC PROC [control: Control, sketch: PosSequences, repaint: BOOL _ TRUE] ~ { run: Run _ NIL; iPos, nPoss: INT _ 0; chain: Chain _ NARROW[control.sketchRef]; FOR n: INT IN [0..sketch.length) DO nPoss _ nPoss+sketch[n].length; ENDLOOP; IF nPoss > chain.pairs.maxLength THEN chain.pairs _ NEW[PosSequenceRep[nPoss]]; FOR n: INT IN [0..sketch.length) DO pairs: PosSequence _ sketch[n]; FOR i: INT IN [0..pairs.length) DO chain.pairs[i+iPos] _ pairs[i]; ENDLOOP; IF run # NIL THEN {run.next _ NEW[RunRep]; run _ run.next} ELSE chain.firstRun _ run _ NEW[RunRep]; run.start _ iPos; iPos _ iPos+pairs.length; run.stop _ iPos-1; ENDLOOP; IF repaint THEN ViewerOps.PaintViewer[control.viewer, client, FALSE, NIL]; }; NLinesInSketch: PUBLIC PROC [control: Control] RETURNS [INTEGER] ~ { IF control.sketchRef = NIL THEN RETURN[0] ELSE { chain: Chain _ NARROW[control.sketchRef]; nLines: INTEGER _ 0; FOR r: Run _ chain.firstRun, r.next WHILE r # NIL DO nLines _ nLines+1; ENDLOOP; RETURN[nLines]; }; }; NPossInSketch: PUBLIC PROC [control: Control] RETURNS [INTEGER] ~ { IF control.sketchRef = NIL THEN RETURN[0] ELSE { chain: Chain _ NARROW[control.sketchRef]; nPoss: INTEGER _ 0; FOR run: Run _ chain.firstRun, run.next WHILE run # NIL DO nPoss _ nPoss+run.stop-run.start+1; ENDLOOP; RETURN[nPoss]; }; }; END. τControlsSketchmpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, October 8, 1986 9:55:22 pm PDT Sketch Type Definitions Sketch Initialization/Clearing Sketch Notification Sketch Painting Sketch Processing ΚP˜šœ™Jšœ Οmœ1™Jšžœžœ/˜GJšœ˜——š ™š£œžœ$˜1Jšœ1˜1Jšœ˜—J˜š£Οbœžœ˜/Jšœžœ ˜%Jšœžœ˜)J˜Jšžœ žœžœžœ˜šžœž˜šžœ˜Jšœ'˜'Jšœ7˜7Jšœ'˜'Jšœ˜J˜—šžœ˜Lšœ!˜!Lšœ3˜3L˜——J˜J˜—š’ œžœ%˜7Jšœ!˜!Jšœ˜J˜šžœžœžœž˜1šžœžœžœž˜&Lšœ'˜'Jšžœ˜—Jšžœ˜—J˜——š ™š£ œžœžœžœ˜DJšœžœ˜)Jšœ%˜%Jšœ˜Jšœžœ˜,J˜šžœžœžœž˜1Jšœžœ˜Jšœžœ'˜DJšœ#˜#J˜ J˜šžœžœžœž˜&Lšœ˜L˜Jšžœ˜—Jšžœ˜—J˜Jšžœ ˜J˜J˜—š £ œžœžœ3žœžœ˜YJšœ žœ˜Jšœ žœ˜Jšœžœ˜)J˜Jš žœžœžœžœ!žœ˜LJšžœžœžœ˜OJ˜šžœžœžœž˜#L˜Lš žœžœžœžœ!žœ˜Kšžœž˜ Lšžœ žœ˜-Lšžœžœ ˜(—L˜L˜L˜Jšžœ˜—J˜Jšžœ žœ/žœžœ˜JJ˜J˜—š£œž œžœžœ˜Dšžœž˜Jšžœžœ˜šžœ˜Jšœžœ˜)Jšœžœ˜J˜Jš žœ!žœžœžœžœ˜PJšžœ ˜L˜——J˜J˜—š£ œž œžœžœ˜Cšžœž˜Jšžœžœ˜šžœ˜Jšœžœ˜)Lšœžœ˜L˜šžœ%žœžœž˜:J˜#Jšžœ˜—L˜Lšžœ˜L˜——J˜J˜——Jšžœ˜J˜J˜—…—B†