<<>> <> <> <> DIRECTORY Atom, Buttons, CedarProcess, Commander, Containers, Controls, ControlsPrivate, Convert, FileNames, G2dBasic, Imager, IO, Labels, PopUpSelection, ProcessProps, Real, Rope, TiogaExtraOps, TiogaOps, TIPUser, TypeScript, VFonts, ViewerClasses, ViewerIO, ViewerOps, ViewerSpecs, ViewerTools; ControlsOuterImpl: CEDAR MONITOR IMPORTS Atom, Buttons, CedarProcess, Containers, Controls, ControlsPrivate, Convert, FileNames, Imager, IO, Labels, PopUpSelection, ProcessProps, Real, Rope, TiogaExtraOps, TiogaOps, TIPUser, TypeScript, VFonts, ViewerIO, ViewerOps, ViewerSpecs, ViewerTools EXPORTS Controls ~ BEGIN <> Button: TYPE ~ Controls.Button; ButtonList: TYPE ~ Controls.ButtonList; ButtonRep: TYPE ~ Controls.ButtonRep; Choice: TYPE ~ Controls.Choice; ClickProc: TYPE ~ Controls.ClickProc; Column: TYPE ~ Controls.Column; Control: TYPE ~ Controls.Control; ControlList: TYPE ~ Controls.ControlList; ControlSizes: TYPE ~ Controls.ControlSizes; DestroyProc: TYPE ~ Controls.DestroyProc; DrawProc: TYPE ~ Controls.DrawProc; GraphicsData: TYPE ~ Controls.GraphicsData; GraphicsDataRep: TYPE ~ Controls.GraphicsDataRep; IntegerPair: TYPE ~ Controls.IntegerPair; MouseButton: TYPE ~ Controls.MouseButton; MouseProc: TYPE ~ Controls.MouseProc; OuterData: TYPE ~ Controls.OuterData; OuterDataRep: TYPE ~ Controls.OuterDataRep; RealSequence: TYPE ~ Controls.RealSequence; RealSequenceRep: TYPE ~ Controls.RealSequenceRep; RopeSequence: TYPE ~ Controls.RopeSequence; RopeSequenceRep: TYPE ~ Controls.RopeSequenceRep; Request: TYPE ~ Controls.Request; Triple: TYPE ~ Controls.Triple; TSValue: TYPE ~ Controls.TSValue; Typescript: TYPE ~ Controls.Typescript; TypescriptRep: TYPE ~ Controls.TypescriptRep; Font: TYPE ~ Imager.Font; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; IconFlavor: TYPE ~ ViewerClasses.IconFlavor; Viewer: TYPE ~ ViewerClasses.Viewer; <> maxNRows: INTEGER ~ 10; capHeight: INTEGER ~ 14; <> ControlError: PUBLIC ERROR [reason: ROPE] = CODE; <> AvailableHeight: PROC [column: ViewerClasses.Column] RETURNS [ht: INTEGER] ~ { nViewers: INTEGER ¬ 1; -- count oneself too EnumProc: ViewerOps.EnumProc ~ { IF v.column = column AND NOT v.iconic THEN nViewers ¬ nViewers+1; }; ViewerOps.EnumerateViewers[EnumProc]; ht ¬ ViewerSpecs.openTopY-ViewerSpecs.openBottomY-nViewers*ViewerSpecs.captionHeight; }; PaintOuter: ViewerClasses.PaintProc ~ { Action: PROC ~ { o: OuterData ¬ NARROW[self.data]; Imager.MaskRectangleI[context, 0, self.wh-capHeight, self.ww, 1]; IF o.buttons # NIL THEN Imager.MaskRectangleI[context, 0, o.buttonsY, self.ww, 1]; IF o.typescript # NIL AND o.typescript.viewer # 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]; }; IF whatChanged = NIL THEN Imager.DoWithBuffer[context, Action, 0, 0, self.ww, self.wh]; }; AdjustProc: ViewerClasses.AdjustProc ~ {AdjustOuter[NARROW[self.data], self.ww, self.wh]}; AdjustOuter: PROC [o: OuterData, w, h: INTEGER] ~ { SetV: PROC[v: Viewer, x, y, w, h: INT] ~ {ViewerOps.EstablishViewerPosition[v,x,y,w,h]}; EstablishOuterChild: ViewerOps.EnumProc ~ { <> newY: INTEGER ¬ v.wy+h-o.outerH; IF ViewerOps.FetchProp[v, $CreatedInOuterViewer] = NIL THEN SetV[v, v.wx, v.wy ¬ newY, v.ww, v.wh]; }; oldGraphicsH: INT ¬ o.graphicsH; o.graphicsH ¬ h-capHeight-o.controlsH-o.buttonsH-o.tsH; SetYs[o]; IF o.typescript # NIL AND o.typescript.viewer # NIL THEN SetV[o.typescript.viewer, 0, o.tsY+1, w, o.tsH-2]; IF o.buttons # NIL THEN FOR b: ButtonList ¬ o.buttons, b.rest WHILE b # NIL DO SetV[b.first.viewer, b.first.x, o.buttonsY+b.first.y, b.first.w, b.first.h]; ENDLOOP; IF o.parent # NIL THEN ViewerOps.EnumerateChildren[o.parent, EstablishOuterChild]; IF o.graphics # NIL AND NOT o.parent.iconic THEN { refWidth: REF ANY ¬ ViewerOps.FetchProp[o.graphics, $Width]; refHeight: REF ANY ¬ ViewerOps.FetchProp[o.graphics, $Height]; SetV[o.graphics, 0, o.graphicsY, w, o.graphicsH]; IF refWidth # NIL AND refHeight # NIL THEN { EstablishGraphicsChild: ViewerOps.EnumProc ~ { I: PROC [r: REAL] RETURNS [i: INT] ~ {i ¬ Real.Round[r]}; SetV[v, I[sx*v.wx], I[sy*v.wy], I[sx*v.ww], I[sy*v.wh]]; }; sx: REAL ¬ REAL[w]/REAL[NARROW[refWidth, REF INTEGER]­]; sy: REAL ¬ REAL[o.graphicsH]/REAL[NARROW[refHeight, REF INTEGER]­]; ViewerOps.EnumerateChildren[o.graphics, EstablishGraphicsChild]; }; ViewerOps.AddProp[o.graphics, $Width, NEW[INTEGER ¬ w]]; ViewerOps.AddProp[o.graphics, $Height, NEW[INTEGER ¬ o.graphicsH]]; }; o.outerH ¬ h; }; CopyControlList: PROC [controls: ControlList] RETURNS [ControlList] ~ { new: ControlList ¬ NIL; FOR c: ControlList ¬ controls, c.rest WHILE c # NIL DO new ¬ Controls.Append[c.first, new]; ENDLOOP; RETURN[new]; }; ChangeOuterViewer: PUBLIC PROC [outerData: OuterData, controls: ControlList] ~ { NotInList: PROC [controls: ControlList, control: Control] RETURNS [BOOL] ~ { FOR c: ControlList ¬ controls, c.rest WHILE c # NIL DO IF c.first = control THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; destroy: BOOL ¬ FALSE; parent: Viewer ¬ outerData.parent; oldControlHeight: INTEGER ¬ outerData.controlsH; FOR c: ControlList ¬ outerData.controls, c.rest WHILE c # NIL DO -- do this everytime IF NotInList[controls, c.first] THEN {destroy ¬ TRUE; EXIT}; ENDLOOP; FOR c: ControlList ¬ outerData.controls, c.rest WHILE c # NIL DO ViewerOps.DestroyViewer[c.first.viewer, FALSE]; ViewerOps.DestroyViewer[c.first.title, FALSE]; ViewerOps.DestroyViewer[c.first.status, FALSE]; ENDLOOP; outerData.controlsH ¬ Controls.ControlPositions[controls, outerData.controlSizes, ColumnWidth[outerData.column]]; IF outerData.controlsH # oldControlHeight THEN { SetOuterHeight[outerData]; AdjustOuter[outerData, outerData.parent.ww, outerData.outerH]; ViewerOps.SetOpenHeight[parent, outerData.outerH-capHeight+1]; ViewerOps.ComputeColumn[outerData.column, TRUE]; }; outerData.controls ¬ CopyControlList[controls]; FOR c: ControlList ¬ controls, c.rest WHILE c # NIL DO Controls.ControlViewer[parent, c.first, outerData.graphics, outerData]; ENDLOOP; IF outerData.controlsH = oldControlHeight AND destroy THEN ViewerOps.PaintViewer[parent, client, TRUE, NIL]; }; OuterViewer: PUBLIC PROC [ name: ROPE ¬ NIL, column: Column ¬ left, buttons: ButtonList ¬ NIL, controls: ControlList ¬ NIL, controlSizes: ControlSizes ¬ [25, 200, 60, 25, 60, 150, 150], graphicsHeight: INTEGER ¬ 0, mouseProc: MouseProc ¬ NIL, drawProc: DrawProc ¬ NIL, destroyProc: DestroyProc ¬ NIL, typescriptHeight: INTEGER ¬ 0, biScrollable: BOOL ¬ FALSE, clientData: REF ANY ¬ NIL, noOpen: BOOL ¬ FALSE, icon: IconFlavor ¬ document] RETURNS [outerData: OuterData] ~ { viewer: Viewer; <> outerData ¬ OuterDataInit[ NIL, column, buttons, controls, controlSizes, graphicsHeight, mouseProc, drawProc, destroyProc, typescriptHeight, clientData]; viewer ¬ outerData.parent ¬ ViewerOps.CreateViewer[ flavor: $Outer, paint: FALSE, info: [ name: name, data: outerData, openHeight: MIN[AvailableHeight[column], outerData.outerH], scrollable: FALSE, column: column, iconic: TRUE] ]; IF icon # document THEN viewer.icon ¬ icon; ViewerOps.AddProp[viewer, $WorkingDirectory, ProcessProps.GetProp[$WorkingDirectory]]; SetYs[outerData]; IF outerData.tsH # 0 THEN { ts: Typescript ¬ outerData.typescript ¬ NEW[TypescriptRep]; v: Viewer ¬ ts.viewer ¬ TypescriptViewer[viewer, outerData.tsH]; [ts.in, ts.out] ¬ ViewerIO.CreateViewerStreams[NIL, v]; }; IF graphicsHeight # 0 THEN { outerData.graphics ¬ GraphicsViewer[viewer, outerData.controlsH, graphicsHeight, mouseProc, drawProc, biScrollable, outerData.clientData]; ViewerOps.AddProp[outerData.graphics, $Width, NEW[INTEGER ¬ viewer.ww]]; ViewerOps.AddProp[outerData.graphics, $Height, NEW[INTEGER ¬ graphicsHeight]]; outerData.graphicsData ¬ GetGraphicsData[outerData.graphics]; }; FOR b: ButtonList ¬ outerData.buttons, b.rest WHILE b # NIL DO v: Viewer ¬ b.first.viewer ¬ ButtonViewer[viewer, b.first]; IF b.first.type = click AND b.first.style # $BlackOnWhite THEN Buttons.SetDisplayStyle[b.first.viewer, b.first.style]; ENDLOOP; FOR c: ControlList ¬ outerData.controls, c.rest WHILE c # NIL DO Controls.ControlViewer[viewer, c.first, outerData.graphics, outerData]; ENDLOOP; IF NOT noOpen THEN ViewerOps.OpenIcon[viewer]; }; OuterDataInit: PROC [ outerData: OuterData ¬ NIL, -- use if non-nil column: Column ¬ left, buttons: ButtonList ¬ NIL, controls: ControlList ¬ NIL, controlSizes: ControlSizes ¬ [25, 200, 60, 25, 60, 150, 150], graphicsHeight: INTEGER ¬ 0, mouseProc: MouseProc ¬ NIL, drawProc: DrawProc ¬ NIL, destroyProc: DestroyProc ¬ NIL, typescriptHeight: INTEGER ¬ 0, data: REF ANY ¬ NIL] RETURNS [OuterData] ~ { widthLim: NAT ¬ SELECT column FROM left => ViewerSpecs.openLeftWidth, right => ViewerSpecs.openRightWidth, ENDCASE => ViewerSpecs.colorScreenWidth; IF outerData = NIL THEN outerData ¬ NEW[OuterDataRep]; outerData.controls ¬ CopyControlList[controls]; outerData.buttons ¬ buttons; outerData.clientData ¬ data; outerData.destroyProc ¬ destroyProc; outerData.controlSizes ¬ controlSizes; outerData.directory ¬ FileNames.CurrentWorkingDirectory[]; outerData.cmdOut ¬ WITH ProcessProps.GetProp[$CommanderHandle] SELECT FROM cmd: Commander.Handle => cmd.err, ENDCASE => NIL; outerData.controlsH ¬ Controls.ControlPositions[controls, controlSizes, ColumnWidth[column]]; outerData.graphicsH ¬ graphicsHeight; outerData.tsH ¬ typescriptHeight; outerData.buttonsH ¬ ButtonsPreparation[buttons, widthLim]; SetOuterHeight[outerData]; RETURN[outerData]; }; ColumnWidth: PROC [column: Column] RETURNS [INTEGER] ~ { RETURN[SELECT column FROM color => ViewerSpecs.colorScreenWidth, left => ViewerSpecs.openLeftWidth, right => ViewerSpecs.openRightWidth, ENDCASE => 600]; }; SetYs: PROC [outerData: OuterData] ~ { outerData.controlsY ¬ 0; outerData.graphicsY ¬ outerData.controlsY+outerData.controlsH; outerData.tsY ¬ outerData.graphicsY+outerData.graphicsH; outerData.buttonsY ¬ outerData.tsY+outerData.tsH; }; SetOuterHeight: PROC [outerData: OuterData] ~ { outerData.outerH ¬ outerData.controlsH+outerData.graphicsH+outerData.tsH+outerData.buttonsH+capHeight; }; <> gGraphicsData: REF ANY; gGraphicsInput: LIST OF REF ANY; newGraphicsInputBoolean: BOOL; newGraphicsInputCondition: CONDITION; NotifyGraphics: ViewerClasses.NotifyProc ~ { NewGraphicsInput[GetGraphicsData[self], 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 graphics.mouse ¬ Controls.SetMouse[ atom: NARROW[gGraphicsInput.rest.first], position: WITH gGraphicsInput.first SELECT FROM p: TIPUser.TIPScreenCoords => [p.mouseX, p.mouseY], < [Real.InlineRoundI[p.x], Real.InlineRoundI[p.y]],>> ENDCASE => ERROR]; }; WatchGraphics: CedarProcess.ForkableProc ~ { DO g: GraphicsData ¬ GetGraphicsInput[]; IF g.mouseProc # NIL THEN g.mouseProc[g.mouse, g.viewer, g.clientData]; ENDLOOP; }; GetGraphicsData: PROC [viewer: Viewer] RETURNS [GraphicsData] ~ { <> <> <> RETURN[NARROW[viewer.data]]; }; PaintGraphics: ViewerClasses.PaintProc ~ { v: Viewer; d: GraphicsData; <> <> <> <> <<}>> <> d ¬ NARROW[self.data]; v ¬ self; <<};>> IF d # NIL AND d.drawProc # NIL THEN d.drawProc[context, d.clientData, whatChanged, v]; }; GraphicsViewer: PUBLIC PROC [ parent: Viewer, y, h: INTEGER ¬ 0, mouseProc: MouseProc, drawProc: DrawProc, biScrollable: BOOL ¬ FALSE, clientData: REF ANY] RETURNS [viewer: Viewer] ~ { graphicsData: GraphicsData ¬ NEW[GraphicsDataRep ¬ [ mouseProc: mouseProc, drawProc: drawProc, clientData: clientData, parent: parent]]; <> <> <> <> <> <> <> <> <> <> <> <> <> <<];>> <> <<}>> -- ELSE -- 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; ViewerOps.AddProp[viewer, $CreatedInOuterViewer, $True]; }; <