<> <> <> DIRECTORY Buttons USING [ButtonProc, Create], Containers USING [ChildXBound, --ChildYBound, --Create], Convert USING [RopeFromInt, RopeFromReal], ChoiceButtons USING [BuildEnumTypeSelection, SelectionNotifierProc], Graph USING [Entity, ROPE, Viewer], GraphConvert USING [AngleFromRope, JustifXFromRope, JustifYFromRope, MarkFromRope, OperandFromRope, RopeOfSlope], GraphPrivate USING [CallWithLock, ControlAction, Controller, GraphAtomProc, GraphHandle, GraphProc, LockedAtomProc, Operate, PanelRemove, Resume, Update], GraphUtil USING [GetIntField, HandleNotNil, RaiseError, SetIntField, SetToggleColor], Imager USING [Font], Labels USING [Create], PopUpMenu USING [RequestSelection], <> VFonts USING [EstablishFont], ViewerOps USING [AddProp, FetchProp], ViewerTools USING [MakeNewTextViewer, SetContents, SetSelection]; GraphPanel: CEDAR PROGRAM IMPORTS Buttons, ChoiceButtons, Containers, Convert, GraphConvert, GraphPrivate, GraphUtil, Labels, PopUpMenu, VFonts, ViewerOps, ViewerTools EXPORTS GraphPrivate = { OPEN Graph, GraphPrivate, GraphUtil; FlipToggleOnPanel: PUBLIC GraphAtomProc = { <> IF HandleNotNil[handle] THEN { OPEN handle.controller; SELECT atom FROM $AutoDiv => auto[divisions] _ SetToggleColor[swDivisions, ~auto[divisions]]; $AutoBounds => auto[bounds] _ SetToggleColor[swBounds, ~auto[bounds]]; $Primary => caretOn[primary] _ SetToggleColor[swCaret[primary], ~caretOn[primary]]; $Secondary => caretOn[secondary] _ SetToggleColor[swCaret[secondary], ~caretOn[secondary]]; $Slope => slopeOn _ SetToggleColor[swSlope, ~slopeOn]; $TextCaret => caretOn[text] _ SetToggleColor[swCaret[text], ~caretOn[text]]; $TargetXOn => targetOn[x] _ SetToggleColor[swTarget[x], ~targetOn[x]]; $TargetYOn => targetOn[y] _ SetToggleColor[swTarget[y], ~targetOn[y]]; $GridX => gridOn[x] _ SetToggleColor[swGrid[x], ~gridOn[x]]; $GridY => gridOn[y] _ SetToggleColor[swGrid[y], ~gridOn[y]]; $Bold => boldOn _ SetToggleColor[swBold, boldOn]; $Italic => italicOn _ SetToggleColor[swItalic, ~italicOn]; ENDCASE => RaiseError[$UnknownAtom]; }; }; -- FlipToggleOnPanel <<>> MakePanel: PUBLIC PROC [handle: GraphHandle] RETURNS [lastHeight: INTEGER] = { <> OPEN handle; entryHeight: CARDINAL = 14; twiceEntryHeight: CARDINAL = 24; entryVSpace: CARDINAL = 6; entryHSpace: CARDINAL = 10; level1X: CARDINAL = 70; level2X: CARDINAL = 20; boldFont: Imager.Font _ VFonts.EstablishFont[family: "TimesRoman", size: 10, bold: TRUE]; mathFont: Imager.Font _ VFonts.EstablishFont[family: "Math", size: 10, bold: FALSE]; prev, panelViewer: Viewer; NextX: PROC[] RETURNS [INTEGER] = { RETURN[prev.wx + prev.ww + entryHSpace]}; EntryButton: PROC[name: ROPE, atom: ATOM, autoX: BOOL _ TRUE, x: INTEGER _ 0, proc: Buttons.ButtonProc _ EntryButtonProc] RETURNS [Viewer] = { prev _ Buttons.Create[ info: [ name: name, parent: panelViewer, wx: IF autoX THEN 0 ELSE x, wy: lastHeight, wh: entryHeight, -- default the width so that it will be computed for us border: FALSE ], clientData: atom, font: boldFont, proc: proc, paint: FALSE]; ViewerOps.AddProp[prev, atom, handle]; RETURN[prev] }; -- EntryButton Toggle: PROC[name: ROPE, atom: ATOM, on, autoX: BOOL _ TRUE, x: INTEGER _ level1X] RETURNS [viewer: Viewer, bool: BOOL] = { prev _ Buttons.Create[ info: [ name: name, parent: panelViewer, wx: IF autoX THEN NextX[] ELSE x, wy: lastHeight, wh: entryHeight, border: TRUE ], clientData: atom, proc: ToggleProc, paint: FALSE]; ViewerOps.AddProp[prev, atom, handle]; RETURN[prev, SetToggleColor[prev, on, FALSE]] }; -- Toggle IntField: PROC [label, contents: ROPE _ NIL, width: INTEGER _ 0, autoX: BOOL _ TRUE, x: INTEGER _ level1X, height: INTEGER _ entryHeight, scrollable: BOOL _ FALSE] RETURNS [viewer: Viewer] = { RETURN[Field[label, contents, width, autoX, x, height, scrollable, IntFieldPrompt]]; }; Field: PROC [label, contents: ROPE _ NIL, width: INTEGER _ 0, autoX: BOOL _ TRUE, x: INTEGER _ level1X, height: INTEGER _ entryHeight, scrollable: BOOL _ FALSE, prompt: Buttons.ButtonProc _ FieldPrompt] RETURNS [Viewer] = { labelViewer: Viewer _ prev _ Buttons.Create[ info: [ name: label, parent: panelViewer, wx: IF autoX THEN NextX[] ELSE x, wy: lastHeight, wh: entryHeight, border: FALSE ], clientData: NIL, proc: prompt, paint: FALSE]; prev _ ViewerTools.MakeNewTextViewer[ info: [ parent: panelViewer, wx: NextX[], wy: lastHeight, ww: width, wh: height, data: contents, scrollable: scrollable, border: FALSE], paint: FALSE]; ViewerOps.AddProp[labelViewer, $Contents, prev]; ViewerOps.AddProp[prev, $Label, label]; RETURN[prev]; }; -- Field Label: PROC[name: ROPE _ NIL, width: INTEGER _ 0, autoX: BOOL _ TRUE, x: INTEGER _ 0, font: Imager.Font _ NIL] RETURNS [Viewer] = { prev _ Labels.Create[ info: [ name: name, parent: panelViewer, wx: IF autoX THEN NextX[] ELSE x, wy: lastHeight, ww: width, wh: entryHeight, border: FALSE ], font: font, paint: FALSE]; RETURN[prev]; }; -- Label OpButton: PROC[name: ROPE, atom: ATOM, autoX: BOOL _ TRUE, x: INTEGER _ 0, font: Imager.Font _ NIL] RETURNS [Viewer] = { prev _ Buttons.Create[ info: [ name: name, parent: panelViewer, wx: IF autoX THEN NextX[] ELSE x, wy: lastHeight, wh: entryHeight, -- default the width so that it will be computed for us border: FALSE ], clientData: atom, proc: OperationProc, font: font, paint: FALSE]; ViewerOps.AddProp[prev, atom, handle]; RETURN[prev] }; -- OpButton panelViewer _ controller.panel _ Containers.Create[ info: [ wx: 0, wy: 0, ww: , wh: controller.panelHeight, border: TRUE, scrollable: TRUE, parent: handle.controller.viewer ], paint: FALSE ]; Containers.ChildXBound[controller.viewer, panelViewer]; <> <> lastHeight _ entryVSpace; [] _ EntryButton["Divisions:", $Divisions]; [controller.swDivisions, controller.auto[divisions]] _ Toggle["Auto", $AutoDiv, graph.auto[divisions], FALSE, level1X]; controller.divX _ IntField["x:", Convert.RopeFromInt[graph.division[x]], 60]; controller.divY _ IntField["y:", Convert.RopeFromInt[graph.division[y]], 60]; <<>> <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Bounds:", $Bounds]; [controller.swBounds, controller.auto[bounds]] _ Toggle["Auto", $AutoBounds, graph.auto[bounds], FALSE, level1X]; controller.xmin _ Field["xmin:", Convert.RopeFromReal[graph.bounds.xmin], 50]; controller.ymin _ Field["ymin:", Convert.RopeFromReal[graph.bounds.ymin], 50]; controller.xmax _ Field["xmax:", Convert.RopeFromReal[graph.bounds.xmax], 50]; controller.ymax _ Field["ymax:", Convert.RopeFromReal[graph.bounds.ymax], 50]; <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Carets:", $Carets]; [controller.swCaret[primary], controller.caretOn[primary]] _ Toggle["primary", $Primary, graph.caret[primary].on, FALSE, level1X]; controller.caretPlace[primary][x] _ Field["x:", Convert.RopeFromReal[graph.caret[primary].place.x], 40]; controller.caretPlace[primary][y] _ Field["y:", Convert.RopeFromReal[graph.caret[primary].place.y], 40]; [controller.swCaret[secondary], controller.caretOn[secondary]] _ Toggle["secondary", $Secondary, graph.caret[secondary].on]; controller.caretPlace[secondary][x] _ Field[ "x:", Convert.RopeFromReal[graph.caret[secondary].place.x], 40]; controller.caretPlace[secondary][y] _ Field[ "y:", Convert.RopeFromReal[graph.caret[secondary].place.y], 40]; <> lastHeight _ lastHeight + entryHeight; [controller.swSlope, controller.slopeOn] _ Toggle["slope", $Slope, graph.showSlope, FALSE, level1X]; [] _ Label["between crosshairs ="]; controller.slope _ Label[ name: IF NOT graph.showSlope THEN NIL ELSE GraphConvert.RopeOfSlope[ graph.caret[primary].place, graph.caret[secondary].place], width: 120]; <> lastHeight _ lastHeight + entryHeight; [controller.swCaret[text], controller.caretOn[text]] _ Toggle["text caret", $TextCaret, graph.caret[text].on, FALSE, level1X]; controller.caretPlace[text][x] _ Field[ "x:", Convert.RopeFromReal[graph.caret[text].place.x], 40]; controller.caretPlace[text][y] _ Field[ "y:", Convert.RopeFromReal[graph.caret[text].place.y], 40]; <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Targets:", $Targets]; [controller.swTarget[x], controller.targetOn[x]] _ Toggle["x", $TargetXOn, graph.target[x].on, FALSE, level1X]; controller.targetWidth[x] _ Field["width:", Convert.RopeFromReal[graph.target[x].width], 40]; controller.targetColor[x] _ Field["color:", Convert.RopeFromInt[graph.target[x].colorIndex], 40]; controller.targetValue[x] _ Field["value:", Convert.RopeFromReal[graph.target[x].value], 200]; lastHeight _ lastHeight + entryHeight; [controller.swTarget[y], controller.targetOn[y]] _ Toggle["y", $TargetYOn, graph.target[y].on, FALSE, level1X]; controller.targetWidth[y] _ Field["width:", Convert.RopeFromReal[graph.target[y].width], 40]; controller.targetColor[y] _ Field["color:", Convert.RopeFromInt[graph.target[y].colorIndex], 40]; controller.targetValue[y] _ Field["value:", Convert.RopeFromReal[graph.target[y].value], 200]; <<>> <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Grids:", $Grids]; [controller.swGrid[x], controller.gridOn[x]] _ Toggle["x", $GridX, graph.grids[x], FALSE, level1X]; [controller.swGrid[y], controller.gridOn[y]] _ Toggle["x", $GridY, graph.grids[y]]; <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Color(", $Color]; controller.colorIndex _ IntField["index:", "0", 40]; [] _ Label[name: "):", font: boldFont]; lastHeight _ lastHeight + entryHeight; controller.red _ Field["red:", Convert.RopeFromReal[graph.color[0].R], 40, FALSE, level2X]; controller.green _ Field["green:", Convert.RopeFromReal[graph.color[0].G], 40]; controller.blue _ Field["blue:", Convert.RopeFromReal[graph.color[0].B], 40]; <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Font(", $Font]; controller.fontIndex _ IntField["index:", "0", 40]; [] _ Label[name: "):", font: boldFont]; lastHeight _ lastHeight + entryHeight; controller.fontFamily _ Field["family:", graph.font[0].family, 100, FALSE, level2X]; [controller.swBold, controller.boldOn] _ Toggle["bold", $Bold, graph.font[0].bold]; [controller.swItalic, controller.italicOn] _ Toggle["italic", $Italic, graph.font[0].italic]; controller.vFontSize _ IntField["screen size:", Convert.RopeFromInt[graph.font[0].vFontSize], 40]; controller.pFontScale _ Field["print scale:", Convert.RopeFromReal[graph.font[0].pFontScale], 100]; <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton["Text(", $Text]; controller.textId _ IntField["id:", NIL, 70]; [] _ Label[name: "):", font: boldFont]; lastHeight _ lastHeight + entryHeight; controller.textContent _ Field["name:", NIL, 2000, FALSE, level2X]; Containers.ChildXBound[panelViewer, controller.textContent]; lastHeight _ lastHeight + entryHeight; controller.textPlaceX _ Field["place x:", NIL, 60, FALSE, level2X]; controller.justifXRef _ ChoiceButtons.BuildEnumTypeSelection[ viewer: panelViewer, x: NextX[], y: lastHeight, title: "", buttonNames: LIST["left", "center", "right"], default: "center", notifyClientProc: JustifXNotify, clientdata: handle, style: menuSelection]; <<[] _ Label[name: "),", autoX: FALSE, x: controller.justifXRef.nextx];>> controller.textPlaceY _ Field["y:", NIL, 60, FALSE, controller.justifXRef.nextx + 10]; controller.justifYRef _ ChoiceButtons.BuildEnumTypeSelection[ viewer: panelViewer, x: NextX[], y: lastHeight, title: "", buttonNames: LIST["top", "center", "bottom"], default: "bottom", notifyClientProc: JustifYNotify, clientdata: handle, style: menuSelection]; <<[] _ Label[name: "),", autoX: FALSE, x: controller.justifYRef.nextx];>> lastHeight _ lastHeight + entryHeight; controller.textColor _ IntField["color:", NIL, 40, FALSE, level2X]; controller.textFont _ IntField["font:", NIL, 40]; <<>> <> lastHeight _ lastHeight + entryHeight; [] _ EntryButton[name: "Curve(", atom: $Entity]; controller.entityId _ IntField["id:", NIL, 100]; [] _ Label[name: "):", font: boldFont]; lastHeight _ lastHeight + entryHeight; controller.entityName _ Field["name:", NIL, 2000, FALSE, level2X]; Containers.ChildXBound[panelViewer, controller.entityName]; lastHeight _ lastHeight + entryHeight; controller.entityColor _ IntField["color:", NIL, 40, FALSE, level2X]; controller.entityWidth _ Field["width:", NIL, 100]; controller.markRef _ ChoiceButtons.BuildEnumTypeSelection[ viewer: panelViewer, x: NextX[], y: lastHeight, title: "mark:", buttonNames: LIST["none", "round", "square", "diamond", "cross", "dollar", "percent"], default: "none", notifyClientProc: MarkNotify, clientdata: handle, borderOnButtons: FALSE, style: flipThru]; <<[] _ FieldLabel["group id:", $EntityGroupId, FALSE, controller.markRef.nextx];>> <> lastHeight _ lastHeight + entryHeight; controller.entityValues _ Field[ label: "values:", contents: NIL, width: 2000, autoX: FALSE, x: level2X, height: twiceEntryHeight, scrollable: TRUE]; Containers.ChildXBound[panelViewer, controller.entityValues]; <> lastHeight _ lastHeight + twiceEntryHeight; [] _ EntryButton[name: "X", atom: $XEntry]; controller.xValues _ Field[ label: "values:", contents: NIL, width: 2000, autoX: FALSE, x: level2X, height: twiceEntryHeight, scrollable: TRUE]; Containers.ChildXBound[panelViewer, controller.xValues]; <<>> <> <> <<[] _ EntryButton["Curve Group:", $Group];>> <<[] _ FieldLabel["(id:", $GroupId];>> <> <<[] _ Label[")"];>> <<>> <> <<[] _ FieldLabel["name:", $GroupName, FALSE, level2X];>> <> <> <<>> <> <<[] _ FieldLabel["x id:", $XId, FALSE, level2X];>> <> <<>> <> <<[] _ FieldLabel["y id's:", $YId, FALSE, level2X];>> <> <> <> <> lastHeight _ lastHeight + twiceEntryHeight; [] _ EntryButton["Cross-section(", $Crosssection]; controller.xsectionX _ Field["at x =", NIL, 100]; [] _ Label[name: "):", font: boldFont]; lastHeight _ lastHeight + entryHeight; controller.xsectionYs _ Field[label: "y's:", autoX: FALSE, x: level2X, width: 2000, height: twiceEntryHeight, scrollable: TRUE]; Containers.ChildXBound[panelViewer, controller.xsectionYs]; <> lastHeight _ lastHeight + twiceEntryHeight; [] _ OpButton["+", $Plus, FALSE, 0]; [] _ OpButton["-", $Minus]; [] _ OpButton[name: " [] _ OpButton[name: "÷", atom: $Divide, font: mathFont]; [] _ OpButton[name: "±", atom: $Sign, font: mathFont]; [] _ OpButton["1/r", $Reciprocal]; [] _ OpButton["e", $Exponential]; [] _ OpButton["log", $Logarithm]; [] _ OpButton["ln", $NaturalLog]; [] _ OpButton[name: " [] _ OpButton["root", $Root]; [] _ OpButton["power", $Power]; [] _ OpButton["sin", $Sine]; [] _ OpButton["cos", $Cosine]; [] _ OpButton["tan", $Tangent]; [] _ OpButton["arctan", $ArcTan]; [] _ OpButton["Original", $Original]; <> lastHeight _ lastHeight + entryHeight; controller.operandRef _ ChoiceButtons.BuildEnumTypeSelection[ viewer: panelViewer, x: level2X, y: lastHeight, title: "operand:", buttonNames: LIST["x", "y", "all y"], default: "all y", notifyClientProc: OperandNotify, clientdata: handle, style: menuSelection]; <> controller.argument _ Field["argument:", NIL, 50, FALSE, controller.operandRef.nextx + entryHSpace]; <> controller.angleRef _ ChoiceButtons.BuildEnumTypeSelection[ viewer: panelViewer, x: NextX[], y: lastHeight, title: "angle:", buttonNames: LIST["degrees", "radians"], default: "radians", notifyClientProc: AngleNotify, clientdata: handle, style: menuSelection]; <> lastHeight _ lastHeight + entryHeight + entryVSpace; <> <> <> <> <<>> lastHeight _ lastHeight + 1; -- _ lastHeight + entryHeight; }; -- MakePanel << >> EntryButtonProc: Buttons.ButtonProc -- PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] -- = { atom: ATOM _ NARROW[clientData]; handle: GraphHandle _ NARROW[ViewerOps.FetchProp[NARROW[parent], atom]]; IF HandleNotNil[handle] AND NOT shift THEN { action: ControlAction _ noop; IF shift THEN RETURN; SELECT atom FROM $Divisions, $Bounds, $Carets, $Targets, $Grids, $XEntry, $Color, $Font => { SELECT mouseButton FROM red => action _ IF control THEN update ELSE resume; yellow => IF NOT control THEN SELECT PopUpMenu.RequestSelection[ "Options", LIST["Show", "Apply"], 1] FROM 1 => action _ resume; 2 => action _ update; ENDCASE; ENDCASE; }; $Crosssection=> { SELECT mouseButton FROM red => IF NOT control THEN action _ resume; yellow => IF NOT control THEN SELECT PopUpMenu.RequestSelection[ "Option", LIST["Show"], 1] FROM 1 => action _ resume; ENDCASE; ENDCASE; }; $Text, $Entity => { SELECT mouseButton FROM red => action _ IF control THEN update ELSE resume; yellow => IF NOT control THEN SELECT PopUpMenu.RequestSelection["Options", LIST["Show", "Apply", "Remove"], 1] FROM 1 => action _ resume; 2 => action _ update; 3 => action _ remove; ENDCASE; blue => IF NOT control THEN action _ remove; ENDCASE; }; ENDCASE; SELECT action FROM resume => LockedAtomProc[handle, atom, Resume]; update => LockedAtomProc[handle, atom, Update]; remove => LockedAtomProc[handle, atom, PanelRemove]; noop => NULL; ENDCASE => RaiseError[$UnknowAction]; }; }; -- EntryButtonProc ToggleProc: Buttons.ButtonProc = { atom: ATOM _ NARROW[clientData]; handle: GraphHandle _ NARROW[ViewerOps.FetchProp[NARROW[parent], atom]]; LockedAtomProc[handle, atom, FlipToggleOnPanel]; }; -- ToggleProc FieldPrompt: Buttons.ButtonProc = { contentsViewer: Viewer _ NARROW[ViewerOps.FetchProp[NARROW[parent], $Contents]]; IF mouseButton = blue THEN ViewerTools.SetContents[contentsViewer, NIL]; ViewerTools.SetSelection[contentsViewer]; }; -- FieldPrompt IntFieldPrompt: Buttons.ButtonProc = { contentsViewer: Viewer _ NARROW[ViewerOps.FetchProp[NARROW[parent], $Contents]]; IF shift THEN { msg: ROPE; old: INT; [msg, old] _ GetIntField[contentsViewer]; IF msg = NIL THEN { SELECT mouseButton FROM red => SetIntField[contentsViewer, old + 1]; blue => SetIntField[contentsViewer, old - 1]; ENDCASE => ViewerTools.SetSelection[contentsViewer]; }; } ELSE { SELECT mouseButton FROM blue => ViewerTools.SetContents[contentsViewer, NIL]; ENDCASE; ViewerTools.SetSelection[contentsViewer]; }; }; -- IntFieldPrompt OperationProc: Buttons.ButtonProc = { atom: ATOM _ NARROW[clientData]; handle: GraphHandle _ NARROW[ViewerOps.FetchProp[NARROW[parent], atom]]; LockedAtomProc[handle, atom, Operate]; }; -- OperationProc JustifXNotify: ChoiceButtons.SelectionNotifierProc = { <> handle: GraphHandle _ NARROW[clientdata]; IF HandleNotNil[handle] THEN { proc: GraphProc = { handle.controller.justifX _ GraphConvert.JustifXFromRope[name]; }; CallWithLock[handle, proc]; }; }; -- JustifXNotify JustifYNotify: ChoiceButtons.SelectionNotifierProc = { handle: GraphHandle _ NARROW[clientdata]; IF HandleNotNil[handle] THEN { proc: GraphProc = { handle.controller.justifY _ GraphConvert.JustifYFromRope[name]; }; CallWithLock[handle, proc]; }; }; -- JustifYNotify MarkNotify: ChoiceButtons.SelectionNotifierProc = { handle: GraphHandle _ NARROW[clientdata]; IF HandleNotNil[handle] THEN { proc: GraphProc = { handle.controller.mark _ GraphConvert.MarkFromRope[name]; }; CallWithLock[handle, proc]; }; }; -- MarkNotify OperandNotify: ChoiceButtons.SelectionNotifierProc = { handle: GraphHandle _ NARROW[clientdata]; IF HandleNotNil[handle] THEN { proc: GraphProc = { handle.controller.operand _ GraphConvert.OperandFromRope[name]; }; CallWithLock[handle, proc]; }; }; -- OperandNotify AngleNotify: ChoiceButtons.SelectionNotifierProc = { handle: GraphHandle _ NARROW[clientdata]; IF HandleNotNil[handle] THEN { proc: GraphProc = { handle.controller.angle _ GraphConvert.AngleFromRope[name]; }; CallWithLock[handle, proc]; }; }; -- AngleNotify }. LOG. SChen, created at October 9, 1985 6:49:24 pm PDT.