DIRECTORY Buttons, Commander, Controls, Convert, FileNames, Imager, ImagerFont, ImagerOps, ImagerPath, IO, List, Process, ProcessProps, Real, RealFns, Rope, TIPUser, TypeScript, VFonts, ViewerClasses, ViewerIO, ViewerOps, ViewerTools; ControlsImpl: CEDAR MONITOR IMPORTS Buttons, Convert, FileNames, Imager, ImagerOps, ImagerPath, IO, Process, ProcessProps, Real, RealFns, Rope, TIPUser, TypeScript, VFonts, ViewerIO, ViewerOps, ViewerTools EXPORTS Controls ~ BEGIN OPEN Controls; ROPE: TYPE ~ Rope.ROPE; maxNRows: INTEGER ~ 10; tsHeight: INTEGER ~ 18; capHeight: INTEGER ~ 14; PaintOuter: ViewerClasses.PaintProc ~ { IF whatChanged = NIL THEN { o: OuterData _ NARROW[self.data]; Imager.MaskRectangleI[context, 0, o.outerH-capHeight, self.ww, 1]; IF o.entries # NIL THEN Imager.MaskRectangleI[context, 0, o.entryY, self.ww, 1]; IF o.typeScript # NIL THEN Imager.MaskRectangleI[context, 0, o.tsY, self.ww, 1]; IF o.graphics # NIL THEN Imager.MaskRectangleI[context, 0, o.graphicsY-1, self.ww, 1]; }; }; AdjustOuter: ViewerClasses.AdjustProc ~ { o: OuterData _ NARROW[self.data]; o.outerH _ self.wh; IF o.graphics # NIL THEN { o.graphicsH _ o.outerH-capHeight-o.controlH-o.entryH-o.tsH; SetYs[o]; ViewerOps.EstablishViewerPosition[o.graphics, 0, o.graphicsY, self.ww, o.graphicsH]; }; IF o.typeScript # NIL THEN ViewerOps.EstablishViewerPosition[o.typeScript, 0, o.tsY+1, self.ww, o.tsH-2]; IF o.entries # NIL THEN FOR e: LIST OF Entry _ o.entries, e.rest WHILE e # NIL DO ee: Entry _ e.first; ViewerOps.EstablishViewerPosition[ee.viewer, ee.x, o.entryY+ee.y, ee.w, ee.h]; ENDLOOP; }; PaintGraphics: ViewerClasses.PaintProc ~ { d: GraphicsData _ NARROW[self.data]; d.show[context, d.viewer.ww, d.viewer.wh, d.data, whatChanged]; }; PaintControl: ViewerClasses.PaintProc ~ { c: ControlData _ NARROW[self.data]; Action: PROC ~ { IF whatChanged = NIL AND c.type = circ THEN Circle[context, c.cx, c.cy, c.rad, FALSE]; FOR detents: LIST OF Detents _ c.detents, detents.rest WHILE detents # NIL DO Tick[context, c, detents.first.val, FALSE, 1]; ENDLOOP; UnTick[context, c]; Tick[context, c, c.val, c.detented, 2]; c.predetented _ c.detented; IF c.status # NIL THEN { ViewerTools.SetContents[c.status, Convert.FtoRope[c.val, IF c.truncate THEN 0 ELSE 3]]; ViewerOps.PaintViewer[c.status, client]; }; }; ImagerOps.DoWithBuffer[context, Action, 0, 0, self.ww, self.wh]; }; gControlData: REF ANY; gControlInput: LIST OF REF ANY; newControlInputBoolean: BOOL; newControlInputCondition: CONDITION; NotifyControl: ViewerClasses.NotifyProc ~ {NewControlInput[self.data, input]}; NewControlInput: ENTRY PROC [data: REF ANY, input: LIST OF REF ANY] ~ { gControlData _ data; gControlInput _ input; NOTIFY newControlInputCondition; newControlInputBoolean _ TRUE; }; GetControlInput: ENTRY PROC RETURNS [control: ControlData] ~ { IF NOT newControlInputBoolean THEN WAIT newControlInputCondition; newControlInputBoolean _ FALSE; control _ NARROW[gControlData]; IF gControlInput = NIL THEN RETURN; control.mouse _ SetMouse[NARROW[gControlInput.rest.first], NARROW[gControlInput.first]]; }; WatchControl: PROC ~ { DO c: ControlData _ GetControlInput[]; ComputeControlVal[c, c.mouse.x, c.mouse.y]; IF c.outerData # NIL THEN c.outerData.val _ c.val; ViewerOps.PaintViewer[c.viewer, client, FALSE, c]; IF c.proc # NIL THEN c.proc[c]; ENDLOOP; }; gGraphicsData: REF ANY; gGraphicsInput: LIST OF REF ANY; newGraphicsInputBoolean: BOOL; newGraphicsInputCondition: CONDITION; NotifyGraphics: ViewerClasses.NotifyProc ~ {NewGraphicsInput[self.data, input]}; NewGraphicsInput: ENTRY PROC [data: REF ANY, input: LIST OF REF ANY] ~ { gGraphicsData _ data; gGraphicsInput _ input; newGraphicsInputBoolean _ TRUE; NOTIFY newGraphicsInputCondition; }; GetGraphicsInput: ENTRY PROC RETURNS [graphics: GraphicsData] ~ { IF NOT newGraphicsInputBoolean THEN WAIT newGraphicsInputCondition; newGraphicsInputBoolean _ FALSE; graphics _ NARROW[gGraphicsData]; IF gGraphicsInput = NIL THEN RETURN; graphics.mouse _SetMouse[NARROW[gGraphicsInput.rest.first],NARROW[gGraphicsInput.first]]; }; WatchGraphics: PROC ~ { DO g: GraphicsData _ GetGraphicsInput[]; IF g.proc # NIL THEN g.proc[g]; ViewerOps.PaintViewer[g.viewer, client, FALSE, g]; ENDLOOP; }; OuterViewer: PUBLIC PROC [ name: ROPE _ NIL, column: ViewerClasses.Column _ right, entries: LIST OF Entry _ NIL, controls: ControlList _ NIL, controlSizes: ControlSizes _ [200, 25, 60], graphicsHeight: INT _ 0, graphicsProc: GraphicsProc _ NIL, graphicsShow: GraphicsShow _ NIL, destroyProc: DestroyProc _ NIL, typeScript: BOOL _ FALSE, data: REF ANY _ NIL, noOpen: BOOL _ FALSE] RETURNS [viewer: Viewer] ~ { outerData: OuterData _ NEW[OuterDataRec _ [controls: controls, entries: entries, data: data]]; outerData.directory _ FileNames.CurrentWorkingDirectory[]; outerData.cmdOut _ WITH ProcessProps.GetProp[$CommanderHandle] SELECT FROM cmd: Commander.Handle => cmd.err, ENDCASE => NIL; outerData.controlH _ ControlPositions[controls, controlSizes]; outerData.graphicsH _ graphicsHeight; outerData.tsH _ IF typeScript THEN tsHeight ELSE 0; outerData.entryH _ EntryPositions[entries]; outerData.outerH _ outerData.controlH+outerData.graphicsH+outerData.tsH+outerData.entryH+capHeight; SetYs[outerData]; viewer _ ViewerOps.CreateViewer[ flavor: $Outer, paint: FALSE, info: [ name: name, data: outerData, openHeight: outerData.outerH, scrollable: FALSE, column: column, iconic: TRUE] ]; IF typeScript THEN { outerData.typeScript _ TypeScript.Create[[parent: viewer, border: FALSE]]; [outerData.tSin,outerData.tSout] _ ViewerIO.CreateViewerStreams[NIL, outerData.typeScript]; }; IF graphicsHeight # 0 THEN { outerData.graphics _ GraphicsViewer[viewer, outerData.controlH, graphicsHeight-100, graphicsProc, graphicsShow, data]; outerData.graphicsData _ NARROW[outerData.graphics.data]; }; EntryViewerList[viewer, entries, outerData]; ControlViewerList[viewer, outerData.graphics, controls, outerData]; outerData.destroyProc _ destroyProc; outerData.parent _ viewer; IF NOT noOpen THEN ViewerOps.OpenIcon[viewer]; }; SetYs: PROC [outer: OuterData] ~ { outer.controlY _ 0; outer.graphicsY _ outer.controlY+outer.controlH; outer.tsY _ outer.graphicsY+outer.graphicsH; outer.entryY _ outer.tsY+outer.tsH; }; GraphicsViewer: PUBLIC PROC [parent: Viewer, y, h: INT _ 0, proc: GraphicsProc, show: GraphicsShow, data: REF ANY] RETURNS [viewer: Viewer] ~ { graphicsData: GraphicsData _ NEW[GraphicsDataRec _ [ proc: proc, show: show, data: data, parent: parent]]; viewer _ ViewerOps.CreateViewer[ flavor: $Graphics, paint: FALSE, info: [ data: graphicsData, scrollable: FALSE, ww: parent.ww, wy: y, wh: h, border: FALSE, parent: parent]]; graphicsData.viewer _ viewer; }; NewControl: PUBLIC PROC [ name: ROPE _ NIL, type: ControlType _ horiz, taper: ControlTaper _ lin, min, max, init: REAL _ 0.0, report: BOOL _ TRUE, truncate: BOOL _ FALSE, detents: LIST OF Detents _ NIL, proc: ControlProc _ NIL, data: REF ANY _ NIL, row: INTEGER _ 0, x, y, w, h: INTEGER _ 0, dummy: BOOL _ FALSE] RETURNS [ControlData] ~ { c: ControlData _ NEW[ControlDataRec]; IF type = circ THEN w _ h _ MIN[w, h]; c^ _ [ name: name, type: type, taper: taper, min: min, max: max, init: init, val: init, truncate: truncate, report: report, detents: detents, proc: proc, data: data, x: x, y: y, w: w, h: h, dummy: dummy]; IF row # 0 THEN ControlRow[c, row]; RETURN[c]; }; EntryReLabel: PUBLIC PROC [outerData: OuterData, oldName, newName: ROPE] ~ { FOR e: LIST OF Entry _ outerData.entries, e.rest WHILE e # NIL DO IF Rope.Equal[e.first.viewer.name, oldName] THEN Buttons.ReLabel[e.first.viewer, newName]; ENDLOOP; }; EntryToggle: PUBLIC PROC [outerData: OuterData, state: BOOL, trueName, falseName: ROPE] ~ { IF state THEN EntryReLabel[outerData, falseName, trueName] ELSE EntryReLabel[outerData, trueName, falseName]; }; EntryStyle: PUBLIC PROC [outerData: OuterData, name: ROPE, style: ATOM] ~ { FOR e: LIST OF Entry _ outerData.entries, e.rest WHILE e # NIL DO IF Rope.Equal[e.first.viewer.name, name] THEN Buttons.SetDisplayStyle[e.first.viewer, style]; ENDLOOP; }; EntryPositions: PUBLIC PROC [entries: LIST OF Entry] RETURNS [entryHeight: INTEGER] ~ { margin: INTEGER ~ 4; entryRows: ARRAY [0..maxNRows) OF RECORD [x: INTEGER _ margin, y, h: INTEGER _ 0]; FOR e: LIST OF Entry _ entries, e.rest WHILE e # NIL DO font: Imager.Font _ VFonts.DefaultFont[e.first.font]; IF e.first.w = 0 THEN e.first.w _ VFonts.StringWidth[e.first.name, font]+8; IF e.first.h = 0 THEN e.first.h _ VFonts.FontHeight[font]+3; ENDLOOP; FOR e: LIST OF Entry _ entries, e.rest WHILE e # NIL DO e.first.row _ MAX[0, MIN[maxNRows-1, e.first.row]]; DO IF MAX[e.first.x, entryRows[e.first.row].x]+e.first.w < 600 THEN EXIT; IF e.first.row >= maxNRows-2 THEN EXIT; e.first.row _ e.first.row+1; ENDLOOP; IF e.first.x = 0 THEN e.first.x _ entryRows[e.first.row].x ELSE entryRows[e.first.row].x _ e.first.x; entryRows[e.first.row].x _ e.first.x+e.first.w+margin-1; entryRows[e.first.row].h _ MAX[entryRows[e.first.row].h, e.first.h]; ENDLOOP; entryRows[0].y _ margin+1; entryHeight _ entryRows[0].y+entryRows[0].h+margin; FOR n: NAT IN [1..maxNRows) DO IF entryRows[n].h # 0 THEN entryHeight _ entryHeight+entryRows[n].h+margin; entryRows[n].y _ entryRows[n-1].y+entryRows[n].h+margin; ENDLOOP; FOR e: LIST OF Entry _ entries, e.rest WHILE e # NIL DO e.first.y _ entryRows[e.first.row].y; ENDLOOP; }; EntryViewerList: PUBLIC PROC [parent: Viewer, entries: LIST OF Entry, data: OuterData] ~ { FOR e: LIST OF Entry _ entries, e.rest WHILE e # NIL DO e.first.viewer _ EntryViewer[parent, e.first, data]; ENDLOOP; }; EntryViewer: PUBLIC PROC [parent: Viewer, e: Entry, data: OuterData] RETURNS [Viewer] ~ { RETURN[Buttons.Create[ info: [ parent: parent, name: e.name, wx: e.x, wy: e.y], proc: e.proc, clientData: data, fork: e.fork, font: e.font, documentation: e.documentation, guarded: e.guarded, paint: e.paint ]]; }; TypeScriptClear: PUBLIC PROC [outerData: OuterData] ~ { IF outerData.tSout = NIL OR outerData.tSclear THEN RETURN; IO.PutRope[outerData.tSout, "\n"]; outerData.tSclear _ TRUE; }; TypeScriptWrite: PUBLIC PROC [outerData: OuterData, rope: ROPE] ~ { IF outerData.tSout = NIL THEN RETURN; IO.PutRope[outerData.tSout, rope]; outerData.tSclear _ FALSE; }; TypeScriptRead: PUBLIC PROC [outerData: OuterData] RETURNS [ROPE] ~ { IF outerData.tSin = NIL THEN RETURN[NIL]; ViewerTools.SetSelection[outerData.typeScript]; RETURN[IO.GetLineRope[outerData.tSin]]; }; TypeScriptReadFileName: PUBLIC PROC [outer: Controls.OuterData] RETURNS [ROPE] ~ { reply: ROPE; TypeScriptWrite[outer, "\nFilename: "]; reply _ TypeScriptRead[outer]; IF reply = NIL THEN { TypeScriptWrite[outer, ". . . aborted.\n"]; RETURN[NIL]; }; RETURN[IF Rope.Find[reply, "/"] # -1 THEN reply ELSE Rope.Concat[outer.directory, reply]]; }; ControlRow: PUBLIC PROC [c: ControlData, row: INTEGER] ~ { c.x _ 15; c.y _ 15+(row-1)*(60+30); c.row _ row; }; ControlPositions: PUBLIC PROC [controls: ControlList, sizes: ControlSizes] RETURNS [height: INTEGER] ~ { x, y: INTEGER _ 15; row, maxH: INTEGER _ 0; hw: INTEGER _ sizes.horizWid; vw: INTEGER _ sizes.vertWid; dia: INTEGER _ sizes.circDia; FOR c: ControlList _ controls, c.rest WHILE c # NIL AND c.first # NIL DO cc: ControlData _ c.first; IF cc.w = 0 THEN cc.w _ SELECT cc.type FROM horiz => hw, vert => vw, ENDCASE => dia; IF cc.h = 0 THEN cc.h _ SELECT cc.type FROM horiz => vw, vert => dia, ENDCASE => dia; IF cc.h > maxH THEN maxH _ cc.h; IF cc.x # 0 THEN x _ cc.x; IF cc.y # 0 THEN y _ cc.y; IF x+cc.w+15 > 600 THEN {x _ 15; y _ y+maxH+30; row _ row+1; maxH _ 0}; cc.row _ row; cc.x _ x; cc.y _ y; x _ x+cc.w+15; ENDLOOP; height _ 0; FOR c: ControlList _ controls, c.rest WHILE c # NIL AND c.first # NIL DO temp: INTEGER _ c.first.h+c.first.y+12; IF c.first.type = vert OR c.first.type = circ THEN { IF c.first.name # NIL THEN temp _ temp+15; IF c.first.report THEN temp _ temp+15; }; height _ MAX[height, temp]; ENDLOOP; }; ControlViewerList: PUBLIC PROC [parent, graphics: Viewer _ NIL, controls: Controls.ControlList, data: REF ANY] ~ { FOR c: ControlList _ controls, c.rest WHILE c # NIL AND c.first # NIL DO ControlViewer[parent, graphics, c.first, data]; ENDLOOP; }; ControlViewer: PUBLIC PROC [parent, graphics: Viewer _ NIL, control: ControlData, data: REF ANY _ NIL, outerData: OuterData _ NIL] ~ { viewer: Viewer; IF control.dummy THEN RETURN; FOR detents: LIST OF Detents _ control.detents, detents.rest WHILE detents # NIL DO detents.first.t _ (detents.first.val-control.min)/(control.max-control.min); ENDLOOP; control.parent _ parent; control.graphics _ graphics; control.outerData _ outerData; control.t _ (control.init-control.min)/(control.max-control.min); control.val _ control.init; IF outerData # NIL THEN outerData.val _ control.init; control.rad _ MIN[control.w, control.h]/2-2; control.cx _ control.w/2; control.cy _ control.cx; viewer _ ViewerOps.CreateViewer[ flavor: $Control, paint: FALSE, info: [ data: control, wx: control.x, wy: control.y, ww: control.w, wh: control.h, border: control.type # circ, scrollable: FALSE, parent: parent]]; control.viewer _ viewer; IF control.name # NIL THEN { control.title _ NameViewer[control]; ViewerTools.SetContents[control.title, control.name]; }; IF control.report THEN control.status _ StatusViewer[control]; }; SetControlVal: PUBLIC PROC [c: ControlData, val: REAL, repaint: BOOL _ TRUE] ~ { c.preval _ c.val; c.val _ val; IF repaint THEN ViewerOps.PaintViewer[c.viewer, client, FALSE, c]; }; GetControlVal: PUBLIC PROC [c: ControlData] RETURNS [REAL] ~ { RETURN[c.val]; }; GetControlValInt: PUBLIC PROC [c: ControlData] RETURNS [INTEGER] ~ { RETURN[Real.RoundI[c.val]]; }; ControlReset: PUBLIC PROC [c1, c2, c3, c4, c5, c6: Controls.ControlData _ NIL] ~ { IF c1 # NIL THEN SetControlVal[c1, 0.0]; IF c2 # NIL THEN SetControlVal[c2, 0.0]; IF c3 # NIL THEN SetControlVal[c3, 0.0]; IF c4 # NIL THEN SetControlVal[c4, 0.0]; IF c5 # NIL THEN SetControlVal[c5, 0.0]; IF c6 # NIL THEN SetControlVal[c6, 0.0]; }; NameViewer: PROC [c: ControlData] RETURNS [v: Viewer] ~ { font: Imager.Font _ VFonts.DefaultFont[]; v _ ViewerTools.MakeNewTextViewer[[ parent: c.parent, ww: VFonts.StringWidth[c.name, font]+10, wx: IF c.type = horiz THEN c.x+c.w+15 ELSE c.x, wy: 13 + (IF c.type = horiz THEN c.y ELSE c.y+c.h+3), wh: 13, scrollable: FALSE, border: FALSE]]; }; StatusViewer: PROC [c: ControlData] RETURNS [v: Viewer] ~ { v _ ViewerTools.MakeNewTextViewer[[ parent: c.parent, ww: IF c.type = horiz THEN 40 ELSE IF c.type = vert THEN 40 ELSE c.w, wx: IF c.type = horiz THEN c.x+c.w+15 ELSE c.x, wy: (IF c.type = horiz THEN c.y ELSE c.y+c.h+3) + (IF c.name = NIL THEN 13 ELSE 0), wh: 13, scrollable: FALSE, border: FALSE]]; }; SetMouse: PUBLIC PROC [a: ATOM, t: TIPUser.TIPScreenCoords] RETURNS [Mouse] ~ { RETURN[[ t.mouseX, t.mouseY, SELECT a FROM $downLeft, $downMid, $downRite => down, $heldLeft, $heldMid, $heldRite => held, $upLeft, $upMid, $upRite => up, ENDCASE => none, SELECT a FROM $downLeft, $heldLeft, $upLeft => left, $downMid, $heldMid, $upMid => middle, $downRite, $heldRite, $upRite => right, ENDCASE => none ]]; }; Quit: PUBLIC ClickProc ~ {EndViewer[NARROW[parent, Controls.Viewer].parent]}; EndViewer: PUBLIC PROC [viewer: REF ANY] ~ { ViewerOps.DestroyViewer[NARROW[viewer]]; }; DestroyOuter: ViewerClasses.DestroyProc ~ { outer: OuterData _ NARROW[self.data]; outer.destroyed _ TRUE; IF outer.destroyProc # NIL THEN outer.destroyProc[outer]; }; Restore: PUBLIC ClickProc ~ { data: OuterData _ NARROW[clientData]; FOR c: ControlList _ data.controls, c.rest WHILE c # NIL DO c.first.val _ c.first.init; ViewerOps.PaintViewer[c.first.viewer, client, FALSE, c.first]; ENDLOOP; }; UnTick: PUBLIC PROC[context: Imager.Context, c: ControlData] ~ { Imager.SetColor[context, Imager.white]; Tick[context, c, c.preval, c.predetented AND NOT c.detented, 2]; Imager.SetColor[context, Imager.black]; }; Tick: PUBLIC PROC [context: Imager.Context, c: ControlData, val: REAL, detent: BOOL _ FALSE, width: INT _ 1] ~ { SELECT c.type FROM vert => { y: REAL _ c.h*(val-c.min)/(c.max-c.min); context.MaskRectangle[[0, y-width/2, c.w, width]]; IF detent THEN Square[context, c.w/2, y, 3.0]; }; horiz => { x: REAL _ c.w*(val-c.min)/(c.max-c.min); context.MaskRectangle[[x-width/2, 0, width, c.h]]; IF detent THEN Square[context, x+1, c.h/2-1, 3.0]; }; circ => { rad: REAL _ c.rad-3; deg: REAL _ 360.0*(val-c.min)/(c.max-c.min); Imager.SetStrokeWidth[context, width]; context.MaskVector[[c.cx+rad*RealFns.CosDeg[deg], c.cy+rad*RealFns.SinDeg[deg]], [c.cx, c.cy]]; IF detent THEN Circle[context, c.cx, c.cy, 3.0, TRUE]; }; ENDCASE => NULL; }; Circle: PUBLIC PROC [context: Imager.Context, x, y, rad: REAL, fill: BOOL _ FALSE] ~ { t: Imager.Trajectory _ ImagerPath.MoveTo[[x+rad, y]]; t _ ImagerPath.ArcTo[t, [x, y+rad], [x-rad, y]]; t _ ImagerPath.ArcTo[t, [x, y-rad], [x+rad, y]]; Imager.SetStrokeWidth[context, 1.15]; IF fill THEN Imager.MaskFillTrajectory[context, t] ELSE Imager.MaskStrokeTrajectory[context, t, TRUE]; }; Square: PUBLIC PROC [context: Imager.Context, x, y, size: REAL] ~ { context.MaskRectangle[[x-size-1, y-size, 2*size, 2*size]]; }; ComputeControlVal: PROC [c: ControlData, x, y: INT] ~ { t, val0, val1: REAL; SELECT c.type FROM vert => c.t _ REAL[y]/REAL[c.h-3]; horiz => c.t _ REAL[x]/REAL[c.w-2]; ENDCASE => { c.t _ RealFns.ArcTan[y-c.cy, x-c.cx]/(2.0*3.1415926535); IF y-c.cy < 0.0 THEN c.t _ c.t+1.0; }; c.t _ MIN[1.0, MAX[0.0, c.t]]; c.detented _ FALSE; IF c.detents = NIL THEN {t _ c.t; val0 _ c.min; val1 _ c.max} ELSE { grain: REAL ~ 0.05; detents: LIST OF Detents _ c.detents; t0, t1: REAL _ 0.0; val1 _ c.min; WHILE detents # NIL DO t0 _ t1; t1 _ detents.first.t; val0 _ val1; val1 _ detents.first.val; IF c.t < t1 THEN EXIT; detents _ detents.rest; ENDLOOP; IF detents = NIL THEN {t1 _ 1.0; val1 _ c.max}; IF t0 > 0.0 AND c.t-t0 < grain THEN {t _ 0.0; c.detented _ TRUE} ELSE IF t1 < 1.0 AND t1-c.t < grain THEN {t _ 1.0; c.detented _ TRUE} ELSE { IF t0 > 0.0 THEN t0 _ t0+grain; IF t1 < 1.0 THEN t1 _ t1-grain; t _ (c.t-t0)/(t1-t0); }; }; IF c.taper = log THEN t _ Real.SqRt[t] ELSE IF c.taper = exp THEN t _ t*t; c.preval _ c.val; c.val _ (1.0-t)*val0+t*val1; IF c.truncate THEN c.val _ Real.Round[c.val]; }; Append: PUBLIC PROC [control: ControlData, list: ControlList _ NIL] RETURNS [ControlList] ~ { tail: ControlList _ list; List: TYPE ~ RECORD[first: ControlData, rest: REF List _ NIL]; IF tail = NIL THEN RETURN[LIST[control]]; WHILE tail.rest # NIL DO tail _ tail.rest; ENDLOOP; tail.rest _ LIST[control]; RETURN[list]; }; TRUSTED {Process.Detach[FORK WatchControl]}; TRUSTED {Process.Detach[FORK WatchGraphics]}; ViewerOps.RegisterViewerClass[$Outer, NEW[ViewerClasses.ViewerClassRec _ [ paint: PaintOuter, adjust: AdjustOuter, destroy: DestroyOuter]]]; ViewerOps.RegisterViewerClass[$Graphics, NEW[ViewerClasses.ViewerClassRec _ [ paint: PaintGraphics, notify: NotifyGraphics, tipTable: TIPUser.InstantiateNewTIPTable["Controls.TIP"]]]]; ViewerOps.RegisterViewerClass[$Control, NEW[ViewerClasses.ViewerClassRec _ [ paint: PaintControl, notify: NotifyControl, tipTable: TIPUser.InstantiateNewTIPTable["Controls.TIP"]]]]; END. ‚ControlsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, May 19, 1986 11:19:08 pm PDT Κ˜šœ™Jšœ Οmœ1™˜VJ˜—J˜J˜—šΟb œ˜)Jšœžœ ˜!J˜Jšœ˜J˜šžœžœžœ˜Jšœ;˜;J˜ JšœT˜TJ˜—J˜šžœž˜JšžœO˜S—J˜šžœ žœž˜š žœžœžœžœžœž˜9K˜JšœN˜NJšžœ˜——J˜J˜—š  œ˜*Jšœžœ ˜$Jšœ?˜?J˜J˜—š  œ˜)Jšœžœ ˜#š œžœ˜Kšžœžœžœ$žœ˜Vš žœ žœžœ#žœ žœž˜MKšœ$žœ˜.Kšžœ˜—K˜Jšœ'˜'J˜cedaršžœ žœžœž˜Lšœ9žœ žœžœ˜WJšœ(˜(J˜—J˜—Jšœ@˜@J˜J˜—Jšœžœžœ˜Jš œžœžœžœžœ˜Jšœžœ˜Jšœž œ˜$J˜Jš‘ œA˜NJ˜š œžœžœžœžœ žœžœžœžœ˜GJšœ˜Jšœ˜Jšžœ˜ Jšœžœ˜Jšœ˜—K˜š œžœžœžœ˜>Jšžœž œ˜AKšœžœ˜Kšœ žœ˜Kšžœžœž ˜#Kšœžœžœ˜XKšœ˜K˜—š  œžœ˜šžœ˜Jšœ#˜#Jšœ+˜+Jšžœžœžœ˜2Jšœ(žœ˜2Jšžœ žœžœ ˜Jšžœ˜—Jšœ˜—J˜Jšœžœžœ˜Jš œžœžœžœžœ˜ Jšœžœ˜Jšœž œ˜%J˜Jš‘œB˜PJ˜š‘œžœžœžœžœ žœžœžœžœ˜HJšœ˜Jšœ˜Jšœžœ˜Jšžœ˜!Jšœ˜—J˜š œžœžœžœ˜AJšžœž œ˜CKšœžœ˜ Kšœ žœ˜!Kšžœžœžœžœ˜$Kšœžœžœ˜YKšœ˜K˜—š  œžœ˜šžœ˜Jšœ%˜%Jšžœ ž œ ˜Jšœ(žœ˜2Jšžœ˜—Jšœ˜—J˜š  œžœžœ˜Jšœžœžœ˜Jšœ%˜%Jšœ žœžœ žœ˜Jšœžœ˜Jšœ+˜+Jšœžœ˜Jšœžœ˜!Jšœžœ˜!Jšœžœ˜Jšœ žœžœ˜Jšœžœžœž˜Jšœžœžœ˜Jšžœ˜J˜JšœžœD˜^J˜Jšœ:˜:šœžœ(žœž˜JKšœ!˜!Kšžœžœ˜—J˜J˜>J˜%Jšœžœ žœ žœ˜3J˜+šœ˜JšœP˜P—J˜J˜J˜šœ ˜ Jšœ˜Jšœžœ˜ šœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ žœ˜Jšœ˜Jšœžœ˜ —J˜—J™šžœ žœ˜JšœBžœ˜JJšœ@žœ˜[J˜J˜—šžœžœ˜Jšœv˜vJšœžœ˜9J˜—K˜K˜,K˜CJ˜Jšœ$˜$Jšœ˜Jšžœžœžœ˜.J˜J˜—š œžœ˜"Jšœ˜Jšœ0˜0Jšœ,˜,Jšœ#˜#J˜J˜—š œžœžœžœ4žœžœžœ˜šœžœ˜4Jšœ5˜5—J˜šœ ˜ Jšœ˜Jšœžœ˜ šœ˜Jšœ˜Jšœ žœ˜J˜J˜J˜Jšœž˜Jšœ˜——J˜Jšœ˜J˜J˜—š  œžœžœ˜Jšœžœžœ˜Jšœ˜J˜Jšœžœ˜Jšœž œ˜Jšœ ž œ˜Jšœ žœžœ ž˜Jšœžœ˜Jšœžœžœžœ˜Jšœžœ˜Jšœ žœ˜Jšœžœžœ˜Jšžœ˜Jšœ˜Jšœžœ˜%Jšžœ žœ žœ˜&šœ˜Jšœ ˜ Jšœ ˜ J˜ Jšœ*˜*Jšœ˜Jšœ˜Jšœ˜J˜ J˜ Jšœ˜Jšœ˜—Jšžœ žœ˜#Jšžœ˜ K˜—K˜š  œžœžœ*žœ˜Lš žœžœžœ#žœžœž˜Ašžœ)˜+Jšžœ*˜.—Jšžœ˜—J˜J˜—š  œž œžœžœ˜[šžœ˜Jšžœ-˜1Jšžœ/˜3—J˜J˜—š   œžœžœžœ žœ˜Kš žœžœžœ#žœžœž˜Ašžœ&˜(Jšžœ0˜4—Jšžœ˜—J˜J˜—š œžœžœ žœžœžœžœ˜WJšœžœ˜Jš œ žœžœžœžœžœ˜RJ˜š žœžœžœžœžœž˜7J˜5Jšžœžœ6˜KJšžœžœ'˜J˜J˜—š   œžœžœžœ žœžœ˜PJ˜J˜ Jšžœ žœ(žœ˜CJšœ˜J˜—š  œž œžœžœ˜>Kšžœ˜K˜K˜—š œž œžœžœ˜DKšžœ˜K˜K˜—š  œžœžœ1žœ˜RKšžœžœ˜(Kšžœžœ˜(Kšžœžœ˜(Kšžœžœ˜(Kšžœžœ˜(Kšžœžœ˜(K˜—J˜š  œžœžœ˜9J˜)šœ#˜#Jšœ˜Jšœ(˜(Jšœžœžœ žœ˜/Jšœ žœžœžœ ˜5Jšœ˜Jšœ žœ˜Jšœžœ˜—K˜K˜—š‘ œžœžœ˜;šœ#˜#Jšœ˜Jš œžœžœžœžœžœžœ˜EJšœžœžœ žœ˜/Jšœžœžœžœžœ žœžœžœ˜SJšœ˜Jšœ žœ˜Jšœžœ˜—K˜K˜—š œž œžœžœ ˜Ošžœ˜J˜ J˜ šžœž˜ Jšœ'˜'Jšœ'˜'Jšœ˜Jšžœ ˜—šžœž˜ Jšœ&˜&Jšœ%˜%Jšœ'˜'Jšžœ˜—Jšœ˜—J˜—J˜š‘œžœžœ#˜MJ˜—š’ œž œ žœžœ˜,Jšœžœ ˜(Jšœ˜J˜—š‘ œ˜+Jšœžœ ˜%Jšœžœ˜Jšžœžœžœ˜9Jšœ˜J˜—š‘œžœ˜Jšœžœ ˜%šžœ(žœžœž˜;Jšœ˜Jšœ.žœ ˜>Kšžœ˜—Jšœ˜—J˜š œž œ-˜@Jšœ'˜'Jšœ)žœ˜@Jšœ'˜'J˜J˜—š ’œž œ0žœ žœžœ žœ ˜pšžœž˜˜ Jšœžœ!˜(Jšœ2˜2Jšžœžœ ˜.K˜—˜ Jšœžœ!˜(Jšœ2˜2Jšžœžœ$˜2K˜—šœ ˜ Jšœžœ ˜Jšœžœ#˜,Jšœ&˜&Jšœ_˜_Jšžœžœ"žœ˜6K˜—Kšžœžœ˜—J˜J˜—š  œž œ&žœžœžœ˜VJ˜5J˜0J˜0Jšœ%˜%Jšžœžœ'˜3Jšžœ)žœ˜3J˜J˜—š œž œ'žœ˜CJšœ:˜:J˜J˜—š’œžœžœ˜7Jšœžœ˜šžœž˜Kšœžœžœ˜"Kšœžœžœ˜#šžœ˜ Kšœ8˜8Kšžœžœ˜#Kšœ˜——Kšœžœžœ ˜Kšœ žœ˜Jšžœ žœžœ&˜=šžœ˜Kšœžœ˜Kšœ žœžœ˜%Kšœžœ˜Kšœ ˜ šžœ žœž˜K˜Kšœ&˜&Kšžœ žœžœ˜Jšœ˜Kšžœ˜—Kšžœ žœžœ˜/Kšžœ žœžœžœ˜@Kšžœ žœžœžœ˜Ešžœ˜Kšžœ žœžœ žœ˜?Kšœ˜K˜—K˜—Kšžœžœ˜&Kšžœžœžœ ˜$J˜Kšœ˜Kšžœ žœ˜-Kšœ˜—K˜š œž œ,žœžœ˜]J˜Jš œžœžœžœžœ˜>Jš žœžœžœžœžœ ˜)Jšžœ žœžœžœ˜3Jšœ žœ ˜Jšžœ˜ ˜J˜——Jšžœžœ˜,Jšžœžœ˜-JšΟc˜šœ&žœ!˜JJšœ˜Jšœ˜Jšœ˜—J˜šœ)žœ!˜MJšœ˜Jšœ˜Jšœ<˜<—J˜šœ(žœ!˜LJšœ˜Jšœ˜Jšœ<˜