<> <> <> <> <> <> DIRECTORY FS, GGButtons, GGDrawProcess, GGError, GGGraphicsButton, GGInterfaceTypes, GGMenus, GGModelTypes, GGMouseEvent, GGSessionLog, GGUserInput, IO, Menus, PopUpMenu, Rope, TiogaButtons, ViewerClasses, ViewerTools; GGMenusImpl: CEDAR PROGRAM IMPORTS FS, GGButtons, GGDrawProcess, GGError, GGGraphicsButton, GGMouseEvent, GGSessionLog, GGUserInput, Rope, PopUpMenu, ViewerTools EXPORTS GGMenus = BEGIN Camera: TYPE = REF CameraObj; CameraObj: TYPE = GGModelTypes.CameraObj; Caret: TYPE = REF CaretObj; CaretObj: TYPE = GGInterfaceTypes.CaretObj; Cluster: TYPE = GGModelTypes.Cluster; ImagerProc: TYPE = GGInterfaceTypes.ImagerProc; MouseButton: TYPE = Menus.MouseButton; Outline: TYPE = GGModelTypes.Outline; PaintQueue: TYPE = REF PaintQueueObj; PaintQueueObj: TYPE = GGInterfaceTypes.PaintQueueObj; Point: TYPE = GGModelTypes.Point; Scene: TYPE = REF SceneObj; SceneObj: TYPE = GGModelTypes.SceneObj; Segment: TYPE = GGModelTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; Traj: TYPE = GGModelTypes.Traj; Viewer: TYPE = ViewerClasses.Viewer; GargoyleData: TYPE = REF GargoyleDataObj; GargoyleDataObj: TYPE = GGInterfaceTypes.GargoyleDataObj; entryHeight: CARDINAL = 15; -- height of a line of items entryVSpace: CARDINAL = 2; -- vertical leading between lines entryHSpace: CARDINAL = 2; -- horizontal space between items on a line column1: CARDINAL = 200; -- horizontal space between margin and column 1; column2: CARDINAL = 250; -- horizontal space between margin and column 2. column3: CARDINAL = 500; -- horizontal space between margin and column 3; nameSize: CARDINAL = 140; smallNumberSize: CARDINAL = 45; numberSize: CARDINAL = 80; bigNumberSize: CARDINAL = 160; pointSize: CARDINAL = 160; PopUpMenuEntry: TYPE = RECORD [ name: Rope.ROPE, input: LIST OF REF ANY ]; ExtractChoiceList: PROC [menu: LIST OF PopUpMenuEntry] RETURNS [choices: LIST OF Rope.ROPE] = { pos: LIST OF Rope.ROPE; newCell: LIST OF Rope.ROPE; <> IF menu = NIL THEN ERROR; choices _ CONS[menu.first.name, NIL]; pos _ choices; FOR l: LIST OF PopUpMenuEntry _ menu.rest, l.rest UNTIL l = NIL DO newCell _ CONS[l.first.name, NIL]; pos.rest _ newCell; pos _ newCell; ENDLOOP; }; QueuePopUpMenuAction: PROC [label: Rope.ROPE, menu: LIST OF PopUpMenuEntry, gargoyleData: GargoyleData] = { choices: LIST OF Rope.ROPE; index: NAT; choices _ ExtractChoiceList[menu]; index _ PopUpMenu.RequestSelection[ label: label, choice: choices, default: 0, mouse: NIL]; IF index < 0 THEN ERROR; IF index = 0 THEN RETURN; FOR entries: LIST OF PopUpMenuEntry _ menu, entries.rest UNTIL entries = NIL DO IF index = 1 THEN { GGUserInput.GeneralDispatch[entries.first.input, gargoyleData]; RETURN; }; index _ index - 1; REPEAT FINISHED => ERROR; ENDLOOP; }; BuildControlPanel: PUBLIC PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = { BuildFileMenuLine[gargoyleData, windowMenu]; BuildMasterMenuLine[gargoyleData, windowMenu]; BuildStyleMenuLine[gargoyleData, windowMenu]; BuildGravityLine[gargoyleData]; BuildAddLine[gargoyleData]; BuildSlopeLine[gargoyleData]; BuildRadiusLine[gargoyleData]; BuildDistanceLine[gargoyleData]; BuildCoordinateLine[gargoyleData]; }; BuildFileMenuLine: PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = { <> GGButtons.BuildQueuedMenuLine [windowMenu, 0, gargoyleData, LIST[ ["Clear", LIST[$Clear], confirmClear], ["Reset", LIST[$Reset], confirmReset], ["Get", LIST[$Get], confirmGet], ["Store", LIST[$Store], confirmStore], ["Save", LIST[$Save]], ["Split", LIST[$Split]], ["Interpress", LIST[$Interpress]] ]]; GGButtons.BuildMenuLine[windowMenu, 0, gargoyleData, LIST[ ["OpenLog", OpenSessionLog], ["CloseLog", CloseSessionLog], ["Playback", PlaybackLog], ["FastPlay", FastPlaybackLog] ]]; }; BuildMasterMenuLine: PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = { <> GGButtons.BuildMenuLine [windowMenu, 1, gargoyleData, LIST[ ["Hierarchy", HierarchyMenu], ["Curve", CurveTypeMenu], ["Transform", Dummy], ["Overlap", OverlapMenu], ["EditCurve", EditCurveMenu], ["View", ViewMenu], ["Debug", DebugMenu], ["Abort!", AbortButton], ["Revive!", ReviveButton], ["Help", TIPTableMenu] ]]; }; BuildStyleMenuLine: PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = { <> GGButtons.BuildMenuLine[windowMenu, 2, gargoyleData, LIST[ ["LineWidth", LineWidthMenu], ["AreaColor", AreaColorMenu] ]]; }; BuildGravityLine: PROC [gargoyleData: GargoyleData] = { nextX: NAT; gargoyleData.hitTest.gravityTypeMenu _ GGButtons.BuildEnumTypeSelection[viewer: gargoyleData.outer, y: gargoyleData.height, title: "GravityChoice:", buttonNames: LIST["StrictDistance", "PointsPreferred", "None"], default: "PointsPreferred", borderOnButtons: TRUE, atom: $GravityChoiceChange, clientdata: gargoyleData, style: flipThru, allInOneRow: TRUE]; gargoyleData.hitTest.gravityType _ innerCircle; nextX _ gargoyleData.hitTest.gravityTypeMenu.nextx; nextX _ GGButtons.BuildButtonLine[gargoyleData.outer, nextX + entryHSpace, gargoyleData.height, gargoyleData, LIST[ ["GravityExtent:", label] ]]; nextX _ GGGraphicsButton.BuildGraphicsButton[ viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height, w: 72, h: entryHeight, name: "GravityExtent", atom: $GravityExtentChange, initValue: 25.0, clientData: gargoyleData]; nextX _ GGButtons.BuildLineOfPopUps[gargoyleData.outer, nextX + entryHSpace, gargoyleData.height, gargoyleData, LIST[ ["HotSpots", button, NIL, HotSpotsMenu] ]]; [gargoyleData.refresh.doubleBuffer, nextX] _ GGButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height, name: "DoubleBuffer", action: LIST[$ToggleDoubleBuffer], clientData: gargoyleData, init: on]; [gargoyleData.hitTest.linesAlwaysOn, nextX] _ GGButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height, name: "AlwaysOn", action: LIST[$ToggleAlwaysOn], clientData: gargoyleData, init: on]; gargoyleData.height _ gargoyleData.height + entryHeight; }; BuildAddLine: PROC [gargoyleData: GargoyleData] = { nextX: NAT; nextX _ GGButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, LIST[ [" Slope:", button, LIST[$SlopePrompt]], ["0.0", text, NIL, SlopeInGargoyleData, smallNumberSize], ["Add!", button, LIST[$AddSlope]], ["GetSlope!", button, LIST[$GetSlope]], ["Radius:", button, LIST[$RadiusPrompt]], ["0.0", text, NIL, RadiusInGargoyleData, smallNumberSize], ["Add!", button, LIST[$AddRadius]], ["GetRadius!", button, LIST[$GetRadius]], ["Distance:", button, LIST[$DistancePrompt]], ["0.0", text, NIL, DistanceInGargoyleData, smallNumberSize], ["Add!", button, LIST[$AddDistance]], ["GetDistance!", button, LIST[$GetDistance]], <<["Delete!", button, LIST[$DeleteRadius]]>> ]]; gargoyleData.height _ gargoyleData.height + entryHeight; }; BuildSlopeLine: PROC [gargoyleData: GargoyleData] = { gargoyleData.hitTest.slopeButtons _ GGButtons.BuildScalarButtons[gargoyleData, "Slopes: ", LIST[ ["0", 0.0, LIST[$ToggleSlope, NEW[REAL _ 0.0]], off], ["30", 30.0, LIST[$ToggleSlope, NEW[REAL _ 30.0]], off], ["45", 45.0, LIST[$ToggleSlope, NEW[REAL _ 45.0]], off], ["60", 60.0, LIST[$ToggleSlope, NEW[REAL _ 60.0]], off], ["90", 90.0, LIST[$ToggleSlope, NEW[REAL _ 90.0]], off], ["120", 120.0, LIST[$ToggleSlope, NEW[REAL _ 120.0]], off], ["135", 135.0, LIST[$ToggleSlope, NEW[REAL _ 135.0]], off], ["150", 150.0, LIST[$ToggleSlope, NEW[REAL _ 150.0]], off] ]]; }; BuildCoordinateLine: PROC [gargoyleData: GargoyleData] = { nextX: NAT; nextX _ GGButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, LIST[ [" Coordinates:", label], ["lastCaret:", label], ["[-999.99, -999.99]", label, NIL, CoordLabelInGargoyleData], ["currentCaret:", label], ["[-999.98, -999.98]", label, NIL, CoordLabelInGargoyleData], ["distance:", label], ["0.0", text, NIL, CoordLabelInGargoyleData, smallNumberSize] ]]; gargoyleData.height _ gargoyleData.height + entryHeight; }; BuildRadiusLine: PROC [gargoyleData: GargoyleData] = { gargoyleData.hitTest.radiusButtons _ GGButtons.BuildScalarButtons[gargoyleData, "Radius: ", LIST[ ["72", 72.0, LIST[$ToggleRadius, NEW[REAL _ 72.0]], off], ["144", 144.0, LIST[$ToggleRadius, NEW[REAL _ 144.0]], off] ]]; }; BuildDistanceLine: PROC [gargoyleData: GargoyleData] = { gargoyleData.hitTest.distanceButtons _ GGButtons.BuildScalarButtons[gargoyleData, "Distance: ", LIST[ ["0", 0.0, LIST[$ToggleDistance, NEW[REAL _ 0.0]], off] ]]; }; Dummy: Menus.ClickProc = { GGError.Append["Menu Level: This feature not yet implemented", oneLiner]; }; <> <<>> confirmReset: REF Menus.ClickProc _ NEW[Menus.ClickProc _ ConfirmReset]; confirmSave: REF Menus.ClickProc _ NEW[Menus.ClickProc _ ConfirmSave]; confirmGet: REF Menus.ClickProc _ NEW[Menus.ClickProc _ ConfirmGet]; confirmStore: REF Menus.ClickProc _ NEW[Menus.ClickProc _ ConfirmStore]; confirmClear: REF Menus.ClickProc _ NEW[Menus.ClickProc _ ConfirmClear]; ConfirmClear: Menus.ClickProc = {}; ConfirmReset: Menus.ClickProc = {}; ConfirmGet: Menus.ClickProc = {}; ConfirmStore: Menus.ClickProc = {}; ConfirmSave: Menus.ClickProc = {}; <<>> <> <<>> HierarchyMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Delete (DEL)", LIST [$Delete]], ["Extend Select (^V)", LIST [$ExtendSelect]], ["Undo (SHIFT-ESC)", LIST [$Undo]], ["Redo (ESC)", LIST [$Redo]], ["AddHoles", LIST [$AddHoles]], ["FreeHoles", LIST [$FreeHoles]], ["Cluster", LIST [$Cluster]], ["Un Cluster", LIST [$UnCluster]] ]; QueuePopUpMenuAction["Hierarchy", menu, gargoyleData]; }; CurveTypeMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Straight", LIST [$SetStraight]], ["Arc", LIST [$SetArc]], ["Conic", LIST [$SetConic]], ["Bezier", LIST [$SetBezier]], ["Spline", LIST [$SetSpline]] ]; QueuePopUpMenuAction["Curve", menu, gargoyleData]; }; OverlapMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Top", LIST [$Top]], ["Bottom", LIST [$Bottom]], ["Up One", LIST [$UpOne]], ["Down One", LIST [$DownOne]] ]; QueuePopUpMenuAction["Overlap", menu, gargoyleData]; }; EditCurveMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Show Points", LIST [$ShowPoints]], ["Hide Points", LIST [$HidePoints]], ["Smooth", LIST [$Smooth]], ["Corner", LIST [$Corner]], ["Close (^C)", LIST [$Close]], ["Open", LIST [$Open]] ]; QueuePopUpMenuAction["EditCurve", menu, gargoyleData]; }; ViewMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Refresh", LIST [$Refresh]], ["Rubberband On", LIST [$RubberbandOn]], ["Rubberband Off", LIST [$RubberbandOff]], ["Show Hot", LIST [$RubberbandOff]], ["Hide Hot", LIST [$RubberbandOff]] ]; QueuePopUpMenuAction["View", menu, gargoyleData]; }; DebugMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ ["Test Gravity", LIST [$TestGravity]], ["Draw Touch Points", LIST [$DrawTouchPoints]], ["Describe Touch Points", LIST [$DescribeTouchPoints]], ["Draw Bounding Boxes", LIST [$DrawBoundBoxes]], ["Draw Selection Box", LIST [$DrawSelectionBox]], ["Typescript", LIST [$Typescript]], ["SlackLog", LIST [$SlackLog]], ["Describe Caret Object", LIST [$DescribeCaretObject]] ]; QueuePopUpMenuAction["Debug", menu, gargoyleData]; }; TIPTableMenu: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; menu: LIST OF PopUpMenuEntry; menu _ LIST [ [" Left Middle Right", LIST [$NoOp]], ["Plain: SelectPoint SelectTrajectory ExtendSelect", LIST [$NoOp]], ["SHIFT: CopySelectPoint CopySelectTrajectory ExtendCopySelect", LIST [$NoOp]], ["CTRL: AddLine Drag Rotate", LIST [$NoOp]], ["CTRL-SHIFT: Scale", LIST [$NoOp]] ]; QueuePopUpMenuAction["TIP Table", menu, gargoyleData]; }; ReviveButton: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; GGMouseEvent.ResetMouseMachinery[gargoyleData]; gargoyleData.refresh.suppressRefresh _ FALSE; GGDrawProcess.Restart[]; }; AbortButton: Menus.ClickProc = { gargoyleData: GargoyleData _ NARROW[clientData]; gargoyleData.aborted _ TRUE; }; <<>> <