<> <> <> <<>> DIRECTORY <> Icons USING [IconFlavor, NewIconFromFile], Imager USING [ConstantColor, Context], InputFocus USING [SetInputFocus], MessageWindow USING [Append], Graph USING [BackgroundIndex, CaretIndex, ColorIndex, GraphColors, GraphColorsArray, GraphFonts, GraphFontsArray, GraphHandle, GraphProc, OutputType, PaintInfo, ROPE, ValueList, Viewer], GraphCarets USING [GetFocus, Init, SetFocus], GraphCleanUp USING [CleanUpHandle], GraphOps USING [Lock, Unlock], GraphPrivate USING [ChartMenus, Draw, EraseSelEntity, EraseSelText, JumpDownAnyCurve, JumpLeftAnyCurve, JumpLeftSameCurve, JumpRightAnyCurve, JumpRightSameCurve, JumpUpAnyCurve, MoveSelText, MoveXhair2To1, PaintAll, RemoveAllCurves, RotateSelTextCCW, RotateSelTextCW, SelectPoint, SelectEntity, SelectText, ShowSelEntityOnSpec, ShowSelTextOnSpec, SlideLeftNSteps, SlideOnSameCurve, SlideRightNSteps, SwitchAuto, SwitchCaretBlinking, SwitchCaretVisibility, SwitchGrid, SwitchTarget, UserEditAllowed, Wait, ZoomIn, ZoomOut, ZoomPoint], GraphUtil USING [HandleFromViewer, HandleNotNil, SetCursorForBackgroundIndex, UseDefaultColors, UseMyColors, UseMyFonts], Process USING [Abort], Rope USING [Cat, Equal], TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords], UserProfile USING [CallWhenProfileChanges, ProfileChangedProc, Token], ViewerClasses USING [Column, NotifyProc, PaintProc, PaintRectangle, Viewer, ViewerClass, ViewerClassRec], ViewerEvents USING [EventProc, RegisterEventProc], ViewerOps USING [CreateViewer, EnumerateViewers, EnumProc, OpenIcon, PaintViewer, RegisterViewerClass, SwapIconAndViewer, TopViewer], WindowManager USING [colorDisplayOn]; GraphViewer: CEDAR PROGRAM IMPORTS Icons, InputFocus, MessageWindow, GraphCarets, GraphCleanUp, GraphOps, GraphPrivate, GraphUtil, Process, Rope, TIPUser, UserProfile, ViewerEvents, ViewerOps, WindowManager EXPORTS GraphPrivate = { OPEN Graph, GraphOps, GraphPrivate, GraphUtil; <<(constant) variables>> graphIcon: Icons.IconFlavor _ Icons.NewIconFromFile["Graph.icons", 0]; graphViewerClass: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec _ [paint: GraphPaint, icon: graphIcon, cursor: textPointer, tipTable: TIPUser.InstantiateNewTIPTable["Graph.TIP"], notify: GraphNotify <> ]]; <<>> <> initialColumn: ViewerClasses.Column; -- {static, left, right, color} createOption: {closeOtherViewers, swapLastViewer, iconic, badCreateOption}; backgroundIndex: BackgroundIndex; -- {white, gray, darkGray, black, unknown} defaultColors: PUBLIC GraphColors _ NEW[GraphColorsArray _ [ [R: 1.0, G: 1.0, B: 1.0], -- 0, white, reserved for color cursor, foreground or background. <> [R: 1.0, G: 0.0, B: 0.8], -- 1, purple red [R: 0.4, G: 0.0, B: 1.0], -- 2, purple [R: 0.0, G: 0.0, B: 1.0], -- 3, blue [R: 0.0, G: 0.56, B: 1.0], -- 4, greenish blue [R: 0.0, G: 1.0, B: 1.0], -- 5, green blue [R: 0.0, G: 1.0, B: 0.0], -- 6, green [R: 0.52, G: 1.0, B: 0.0], -- 7, yellow green [R: 1.0, G: 1.0, B: 0.0], -- 8, yellow [R: 1.0, G: 0.60, B: 0.0], -- 9, orange yellow [R: 1.0, G: 0.42, B: 0.0], -- 10, yellowish orange [R: 1.0, G: 0.25, B: 0.0], -- 11, orange [R: 1.0, G: 0.0, B: 0.0], -- 12, red <> [R: 0.5, G: 0.5, B: 0.5], -- 13, gray, reserved for background. (default target color.) [R: 0.17, G: 0.17, B: 0.17], -- 14, dark gray, reserved for background. [R: 0.0, G: 0.0, B: 0.0] -- 15, black, reserved for color cursor, foreground or background. ]]; defaultFonts: PUBLIC GraphFonts _ NEW[GraphFontsArray _ [ <<[family, bold, italic, vFontSize, pFontScale]>> ["TimesRoman", FALSE, FALSE, 10, 11.0], -- 0, TimesRoman10, reserved. ["TimesRoman", FALSE, FALSE, 8, 9.0], -- 1, TimesRoman8, reserved. ["TimesRoman", TRUE, FALSE, 12, 13.0], -- 2, 12b, reserved. ["TimesRoman", FALSE, TRUE, 10, 11.0], -- 3, ~10i ["TimesRoman", TRUE, FALSE, 10, 11.0], -- 4, ~10b ["Helvetica", FALSE, FALSE, 8, 9.0], -- 5, Helvetica8 ["Helvetica", FALSE, FALSE, 6, 7.0], -- 6, ~6 ["Helvetica", TRUE, FALSE, 14, 15.0], -- 7, ~14b ["Gacha", FALSE, FALSE, 8, 9.0], -- 8, Gacha8 ["Hippo", FALSE, FALSE, 8, 9.0], -- 9, Hippo8 ["Logo", FALSE, FALSE, 12, 14.0], -- 10, Logo12 ["Math", FALSE, FALSE, 8, 9.0] -- 11, Math8, reserved. ]]; systemColor: PUBLIC ARRAY ColorIndex OF Imager.ConstantColor; <> ShowChart: PUBLIC GraphProc = { <> <> <> <> IF HandleNotNil[handle] THEN { OPEN handle; viewer: Viewer _ chart.viewer; IF viewer = NIL THEN { UseMyColors[handle]; UseMyFonts[handle]; <> NewChartViewer[handle]; <> } ELSE { <> IF viewer.iconic THEN ViewerOps.OpenIcon[icon: viewer, bottom: FALSE] ELSE ViewerOps.TopViewer[viewer]; }; }; }; -- ShowChart NewChartViewer: GraphProc = { OPEN handle; viewer: Viewer _ chart.viewer _ ViewerOps.CreateViewer[ flavor: $Graph, info: [ class: graphViewerClass, name: graph.fileName, menu: ChartMenus[], column: initialColumn, iconic: TRUE, <> data: handle], paint: TRUE]; <> SELECT createOption FROM iconic => { <> <> }; closeOtherViewers => ViewerOps.OpenIcon[icon: viewer, closeOthers: TRUE, bottom: TRUE, paint: TRUE]; swapLastViewer => { vLast: Viewer _ NIL; LastViewer: ViewerOps.EnumProc = { IF v.column = initialColumn AND NOT v.iconic THEN {vLast _ v; RETURN[FALSE]}; }; -- LastViewer ViewerOps.EnumerateViewers[LastViewer]; IF vLast = NIL THEN ViewerOps.OpenIcon[icon: viewer, closeOthers: TRUE, bottom: TRUE, paint: TRUE] ELSE { ViewerOps.SwapIconAndViewer[icon: viewer, openViewer: vLast, paint: TRUE]; -- this paints the new viewer only. ViewerOps.PaintViewer[vLast, all, TRUE, NIL]; -- paint the last viewer. }; }; ENDCASE; }; -- NewChartViewer <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<}>> <> <> <<};>> <> <<};>> <> <<};>> <<}; -- AddEntity>> IsGraphViewer: PUBLIC PROC [viewer: Viewer] RETURNS [BOOL] = { IF viewer = NIL THEN RETURN[FALSE]; RETURN[viewer.class.flavor = $Graph]; }; -- IsGraphViewer <> GraphPaint: ViewerClasses.PaintProc = { <<[self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL]>> IF IsGraphViewer[self] AND context # NIL AND NOT self.iconic THEN { <> handle: GraphHandle _ HandleFromViewer[self]; IF handle # NIL THEN { OPEN handle; IF clear THEN paintInfo.clear _ FALSE; IF whatChanged # NIL AND ISTYPE[whatChanged, PaintInfo] THEN { paintInfo.output _ screen; Draw[context, handle]; } ELSE { <> paintInfo.output _ screen; paintInfo.action _ paint; FOR i: CaretIndex IN CaretIndex DO chart.caretState[i].visible _ FALSE; ENDLOOP; IF whatChanged = NIL THEN paintInfo.item _ all ELSE IF ISTYPE[whatChanged, ViewerClasses.PaintRectangle] THEN { vr: ViewerClasses.PaintRectangle _ NARROW[whatChanged]; paintInfo.item _ rectangle; paintInfo.rect _ [vr.x, vr.y, vr.w, vr.h]; }; Draw[context, handle]; IF whatChanged = NIL THEN mergingBounds _ FALSE; <> <> }; }; -- handle # nil }; }; -- GraphPaint GraphBeforeDestroy: ViewerEvents.EventProc = { handle: GraphHandle _ HandleFromViewer[viewer]; IF handle # NIL AND event=destroy AND IsGraphViewer[viewer] AND before THEN { Lock[handle]; IF GraphCarets.GetFocus[] = handle THEN GraphCarets.SetFocus[NIL]; IF handle.selectProc # NIL THEN { TRUSTED {Process.Abort[handle.selectProc]}; Unlock[handle]; UNTIL handle.selectProc = NIL DO Wait[]; ENDLOOP; Lock[handle]; }; handle.chart.viewer _ NIL; Unlock[handle]; }; }; -- GraphBeforeDestroy GraphAfterDestroy: ViewerEvents.EventProc = { handle: GraphHandle _ HandleFromViewer[viewer]; IF handle # NIL AND event=destroy AND IsGraphViewer[viewer] AND NOT before THEN { Lock[handle]; IF handle.controller = NIL THEN handle _ GraphCleanUp.CleanUpHandle[handle, TRUE] ELSE Unlock[handle]; }; }; -- GraphAfterDestroy <> <> <> <> <<}; -- GraphOpen>> <<>> GraphNotify: ViewerClasses.NotifyProc= { IF IsGraphViewer[self] AND NOT self.iconic THEN { handle: GraphHandle _ HandleFromViewer[self]; IF HandleNotNil[handle] THEN { mx, my: INTEGER; nArg: INT; FOR params: LIST OF REF ANY _ input, params.rest UNTIL params = NIL DO Lock[handle]; WITH params.first SELECT FROM xy: TIPUser.TIPScreenCoords => { mx _ xy.mouseX; my _ xy.mouseY; }; n: REF LONG INTEGER => nArg _ n^; a: ATOM => { SELECT a FROM $SetFocus => InputFocus.SetInputFocus[handle.chart.viewer]; $SelectText => SelectText[handle, mx, my]; $Slide => SlideOnSameCurve[handle, mx, my]; $SelectCurve => SelectEntity[handle, mx, my]; $SelectPoint => SelectPoint[handle, mx, my]; $ZoomPoint => ZoomPoint[handle, mx, my]; $ShowSelTextOnSpec => ShowSelTextOnSpec[handle]; $ShowSelEntityOnSpec => ShowSelEntityOnSpec[handle]; $JumpLeftSameCurve => JumpLeftSameCurve[handle]; $JumpLeftAnyCurve => JumpLeftAnyCurve[handle]; $JumpUp => JumpUpAnyCurve[handle]; $ZoomIn => ZoomIn[handle, mx, my]; $LeftStep => SlideLeftNSteps[handle, nArg]; $RemoveCurve => IF UserEditAllowed[handle] THEN EraseSelEntity[handle]; $RemoveAllCurves => IF UserEditAllowed[handle] THEN RemoveAllCurves[handle]; $JumpRightSameCurve => JumpRightSameCurve[handle]; $JumpRightAnyCurve => JumpRightAnyCurve[handle]; $ClearText => EraseSelText[handle]; $RotateSelTextCW => RotateSelTextCW[handle, nArg]; $RotateSelTextCCW => RotateSelTextCCW[handle, nArg]; $MoveSelText => MoveSelText[handle, mx, my]; $JumpDown => JumpDownAnyCurve[handle]; $ZoomOut => ZoomOut[handle, mx, my]; $RightStep => SlideRightNSteps[handle, nArg]; $PrimaryVisibility, $SecondaryVisibility, $TextCaretVisibility => SwitchCaretVisibility[handle, SELECT a FROM $PrimaryVisibility => primary, $SecondaryVisibility => secondary, ENDCASE => text ]; $PrimaryBlinking, $SecondaryBlinking, $TextCaretBlinking => SwitchCaretBlinking[handle, SELECT a FROM $PrimaryBlinking => primary, $SecondaryBlinking => secondary, ENDCASE => text ]; $SaveCrosshair => MoveXhair2To1[handle]; $ToggleAutoBounds => SwitchAuto[handle, bounds]; $ToggleAutoDiv => SwitchAuto[handle, divisions]; $ToggleTargetX, $ToggleTargetY => SwitchTarget[handle, IF a = $ToggleTargetX THEN x ELSE y]; $ToggleGridX, $ToggleGridY => SwitchGrid[handle, IF a = $ToggleGridX THEN x ELSE y]; $CleanAndPaint => PaintAll[handle, TRUE]; $Repaint => PaintAll[handle, FALSE]; ENDCASE; }; ENDCASE; Unlock[handle]; ENDLOOP; }; }; }; -- GraphNotify ProcessUserProfile: PUBLIC UserProfile.ProfileChangedProc = { <> rope: ROPE _ UserProfile.Token[key: "Graph.Column", default: "color"]; initialColumn _ SELECT TRUE FROM rope.Equal["color", FALSE] => color, rope.Equal["left", FALSE] => left, rope.Equal["right", FALSE] => right, ENDCASE => static; IF initialColumn = static THEN { MessageWindow.Append[ Rope.Cat["Warning: Illegal entry in user profile, Graph.Column: ", rope, "."], TRUE]; initialColumn _ color; }; IF initialColumn = color AND NOT WindowManager.colorDisplayOn THEN initialColumn _ left; <> rope _ UserProfile.Token[key: "Graph.CreateOption", default: "closeOtherViewers"]; createOption _ SELECT TRUE FROM rope.Equal["closeOtherViewers", FALSE] => closeOtherViewers, rope.Equal["swapLastViewer", FALSE] => swapLastViewer, rope.Equal["iconic", FALSE] => iconic, ENDCASE => badCreateOption; IF createOption = badCreateOption THEN { MessageWindow.Append[ Rope.Cat["Warning: Illegal entry in user profile, Graph.CreateOption: ", rope, "."], TRUE]; createOption _ closeOtherViewers; }; <> rope _ UserProfile.Token[key: "Graph.Background", default: "white"]; backgroundIndex _ SELECT TRUE FROM rope.Equal["white", FALSE] => white, rope.Equal["gray", FALSE] => gray, rope.Equal["darkGray", FALSE] => darkGray, rope.Equal["black", FALSE] => black, ENDCASE => unknown; IF backgroundIndex = unknown THEN { MessageWindow.Append[ Rope.Cat["Warning: Illegal entry in user profile, Graph.Background: ", rope, "."], TRUE]; backgroundIndex _ white; }; <> IF reason = firstTime THEN UseDefaultColors[]; SetCursorForBackgroundIndex[backgroundIndex]; }; -- ProcessUserProfile Init: PROC [] = { ViewerOps.RegisterViewerClass[$Graph, graphViewerClass]; [] _ ViewerEvents.RegisterEventProc[proc: GraphBeforeDestroy, event: destroy, before: TRUE]; [] _ ViewerEvents.RegisterEventProc[proc: GraphAfterDestroy, event: destroy, before: FALSE]; <<[] _ ViewerEvents.RegisterEventProc[proc: GraphOpen, event: open, before: FALSE];>> ProcessUserProfile[firstTime]; UserProfile.CallWhenProfileChanges[ProcessUserProfile]; GraphCarets.Init[]; }; -- Init Init[]; }. CHANGE LOG. SChen, October 19, 1985 10:09:23 pm PDT, created.