File: GGMenusImpl.mesa
Author: Eric Bier on June 5, 1985 11:34:50 pm PDT
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last edited by Bier on January 28, 1987 3:03:16 pm PST
Contents: Code to create a Gargoyle window. Calls GGContainer to make the container and adds menus at the top. The graphics part of the Gargoyle window is a new viewer of class $ActionArea. The paint proc for a $ActionArea is defined herein.
Stone, July 15, 1985 11:39:29 am PDT
Pier, February 3, 1987 12:48:47 pm PST
Jcbeatty, March 10, 1986 8:17:31 pm PST
Kurlander August 24, 1986 1:02:25 pm PDT
DIRECTORY
FS, GGBasicTypes, AtomButtons, GGCircleCache, GGContainer, GGEditTool, SlackProcess, GGError, GGEvent, GGGraphicsButton, GGInterfaceTypes, GGMenus, GGModelTypes, GGMouseEvent, GGSegmentTypes, GGStatistics, GGSessionLog, GGUserInput, GGWindow, IO, Menus, PopUpSelection, Rope, Rules, TiogaMenuOps, VFonts, ViewerClasses, ViewerOps, ViewerTools;
GGMenusImpl: CEDAR PROGRAM
IMPORTS FS, AtomButtons, GGCircleCache, GGEvent, SlackProcess, GGContainer, GGEditTool, GGError, GGGraphicsButton, GGMouseEvent, GGStatistics, GGSessionLog, GGUserInput, GGWindow, IO, Rope, PopUpSelection, Rules, TiogaMenuOps, VFonts, ViewerOps, ViewerTools
EXPORTS GGMenus = BEGIN
Caret: TYPE = REF CaretObj;
CaretObj: TYPE = GGInterfaceTypes.CaretObj;
ImagerProc: TYPE = GGInterfaceTypes.ImagerProc;
MouseButton: TYPE = Menus.MouseButton;
Outline: TYPE = GGModelTypes.Outline;
Point: TYPE = GGBasicTypes.Point;
Scene: TYPE = REF SceneObj;
SceneObj: TYPE = GGModelTypes.SceneObj;
Segment: TYPE = GGSegmentTypes.Segment;
Sequence: TYPE = GGModelTypes.Sequence;
Traj: TYPE = GGModelTypes.Traj;
GargoyleData: TYPE = REF GargoyleDataObj;
GargoyleDataObj: TYPE = GGInterfaceTypes.GargoyleDataObj;
Viewer: TYPE = ViewerClasses.Viewer;
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;
numberSize: CARDINAL = 80;
bigNumberSize: CARDINAL = 160;
smallNumberSize: CARDINAL = 60;
pointSize: CARDINAL = 160;
boldFont: VFonts.Font; -- initialized in Init below;
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;
Non-destructive (copies the menu names).
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, onceOnly: BOOLTRUE] = {
index: NAT;
choices: LIST OF Rope.ROPE ← ExtractChoiceList[menu];
DO
index ← PopUpSelection.Request[header: label, choice: choices];
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.MenuNotify[gargoyleData, entries.first.input];
EXIT;
};
index ← index - 1;
REPEAT
FINISHED => ERROR;
ENDLOOP;
IF onceOnly THEN RETURN;
ENDLOOP;
};
BuildControlPanel: PUBLIC PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = {
BuildFileMenuLine[gargoyleData, windowMenu];
BuildMasterMenuLine[gargoyleData];
BuildStyleMenuLine[gargoyleData];
BuildGravityLine[gargoyleData];
BuildSlopeLine[gargoyleData];
BuildAngleLine[gargoyleData];
BuildRadiusLine[gargoyleData];
BuildDistanceLine[gargoyleData];
BuildMeasureLine[gargoyleData];
BuildFeedbackLine[gargoyleData];
AddARule[gargoyleData];
};
AddARule: PROC [gargoyleData: GargoyleData] = {
rule: Rules.Rule;
rule ← Rules.Create[[
parent: gargoyleData.outer,
wy: gargoyleData.height,
ww: gargoyleData.outer.cw,
wh: 2
]];
GGContainer.ChildXBound[gargoyleData.outer, rule];
gargoyleData.height ← gargoyleData.height + rule.wh + entryVSpace;
}; -- end of AddARule
fudgeX: INTEGER ← 2;
Build All of the Control Panel Menus
BuildFileMenuLine: PROC [gargoyleData: GargoyleData, windowMenu: Menus.Menu] = {
Files: Clear, Reset, Get, Store, Save, Split, Interpress
nextX: INTEGER ← AtomButtons.BuildButtonLine [gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["Clear", button, LIST[$Clear], NIL, 0, FALSE, ConfirmClear],
["Restore", button, LIST[$Reset], NIL, 0, FALSE, ConfirmReset],
["Get", button, LIST[$Get], NIL, 0, FALSE, ConfirmGet], -- guarded in spite of Tioga viewers menus
["Merge", button, LIST[$Merge], NIL, 0, FALSE, ConfirmMerge],
["Store", button, LIST[$Store], NIL, 0, FALSE, ConfirmStore],
["Save", button, LIST[$Save]],
["Split", button, LIST[$Split]],
["Stuff", button, LIST[$Stuff], NIL, 0, FALSE, NIL, NIL, LIST[$StuffScreen]] -- KAP. 8/11/86
]];
nextX ← nextX+fudgeX;
nextX ← AtomButtons.BuildUnQueuedButtonLine [gargoyleData.outer, nextX, gargoyleData.height, gargoyleData, LIST[
["Interpress", button, InterpressMenu, NIL, 0, FALSE, NIL, boldFont],
["Script", button, ScriptMenu, NIL, 0, FALSE, NIL, boldFont],
]];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildMasterMenuLine: PROC [gargoyleData: GargoyleData] = {
Master: Hierarchy Curve Transform Overlap EditCurve View Debug Abort Revive
nextX: INTEGER ← AtomButtons.BuildUnQueuedButtonLine [gargoyleData.outer, 0, gargoyleData.height, gargoyleData, LIST[
["Hierarchy", button, HierarchyMenu, NIL, 0, FALSE, NIL, boldFont],
["Transform", button, TransformMenu, NIL, 0, FALSE, NIL, boldFont],
["Overlap", button, OverlapMenu, NIL, 0, FALSE, NIL, boldFont],
["Curves", button, CurveTypeMenu, NIL, 0, FALSE, NIL, boldFont],
["Shapes", button, ShapesMenu, NIL, 0, FALSE, NIL, boldFont],
["Text", button, TextOpsMenu, NIL, 0, FALSE, NIL, boldFont],
["Fonts", button, FontOpsMenu, NIL, 0, FALSE, NIL, boldFont],
["Groups", button, GroupOpsMenu, NIL, 0, FALSE, NIL, boldFont],
["Debug", button, DebugMenu, NIL, 0, FALSE, NIL, boldFont],
["Refresh!", button, RefreshButton],
["Abort!", button, AbortButton],
["Revive!", button, ReviveButton],
["Help!", button, HelpMenu]
]];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildStyleMenuLine: PROC [gargoyleData: GargoyleData] = {
Style: LineEnds LineWidth LineColor Fill TextAlign Font
nextX: INTEGER ← AtomButtons.BuildUnQueuedButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, LIST[
["Width", button, LineWidthMenu, NIL, 0, FALSE, NIL, boldFont],
["Color", button, LineColorMenu, NIL, 0, FALSE, NIL, boldFont],
["Arrows", button, ArrowsMenu, NIL, 0, FALSE, NIL, boldFont],
["Fill", button, AreaColorMenu, NIL, 0, FALSE, NIL, boldFont],
["Select", button, AreaSelectMenu, NIL, 0, FALSE, NIL, boldFont],
["Edit", button, EditMenu, NIL, 0, FALSE, NIL, boldFont],
["HotSpots", button, HotSpotsMenu, NIL, 0, FALSE, NIL, boldFont],
["Units", button, UnitsMenu, NIL, 0, FALSE, NIL, boldFont]
]];
[gargoyleData.refresh.showColors, nextX] ← AtomButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height, clientData: gargoyleData, handleProc: GGUserInput.MenuNotify, name: "ShowColors", action: LIST[$ToggleShowColors], init: off];
gargoyleData.refresh.screenStyle ← AtomButtons.BuildEnumTypeSelection[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height, maxWidth: 144, clientData: gargoyleData, handleProc: GGUserInput.MenuNotify, title: "ScreenStyle:", default: "PrintFonts", borderOnButtons: TRUE, style: flipThru, allInOneRow: TRUE, buttonNames: LIST["PrintFonts", "ScreenFonts", "WYSIWYG"], atom: $ScreenChoiceChange];
gargoyleData.height ← gargoyleData.height + entryHeight + entryVSpace;
};
BuildGravityLine: PROC [gargoyleData: GargoyleData] = {
nextX: NAT ← 0;
gargoyleData.hitTest.gravityTypeMenu ←
AtomButtons.BuildEnumTypeSelection[viewer: gargoyleData.outer, x: 0, y: gargoyleData.height, maxWidth: 144,
clientData: gargoyleData,
handleProc: GGUserInput.MenuNotify,
title: "GravType:", default: "PreferPoints",
borderOnButtons: TRUE, style: flipThru, allInOneRow: TRUE,
buttonNames: LIST["StrictDistance", "PreferPoints"],
atom: $GravityChoiceChange];
gargoyleData.hitTest.gravityType ← innerCircle;
nextX ← gargoyleData.hitTest.gravityTypeMenu.nextx;
nextX ← AtomButtons.BuildButtonLine[
gargoyleData.outer, nextX + entryHSpace, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["GravExtent:", label]]];
nextX ← GGGraphicsButton.BuildGraphicsButton[
viewer: gargoyleData.outer,
x: nextX + entryHSpace,
y: gargoyleData.height,
w: 60, -- changed from 72 to make more room in line
h: entryHeight,
name: "GravExtent",
atom: $GravityExtentChange,
initValue: GGEditTool.GetDefaultGravityExtent[],
clientData: gargoyleData];
[gargoyleData.hitTest.gravButton, nextX] ←
AtomButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + 2*entryHSpace, y: gargoyleData.height,
clientData: gargoyleData,
handleProc: GGUserInput.MenuNotify,
name: "Gravity",
action: LIST[$ToggleGravity],
init: on];
[gargoyleData.refresh.alignments, nextX] ←
AtomButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height,
clientData: gargoyleData,
handleProc: GGUserInput.MenuNotify,
name: "Alignments",
action: LIST[$ToggleAlignments],
init: on];
[gargoyleData.hitTest.midpointButton, nextX] ←
AtomButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height,
clientData: gargoyleData,
handleProc: GGUserInput.MenuNotify,
name: "Midpoints",
action: LIST[$ToggleMidpoints],
init: off];
[gargoyleData.hitTest.heuristicsButton, nextX] ←
AtomButtons.BuildTwoStateButton[viewer: gargoyleData.outer, x: nextX + entryHSpace, y: gargoyleData.height,
clientData: gargoyleData,
handleProc: GGUserInput.MenuNotify,
name: "Heuristics",
action: LIST[$ToggleHeuristics],
init: IF GGEditTool.GetDefaultHeuristics[] THEN on ELSE off];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildSlopeLine: PROC [gargoyleData: GargoyleData] = {
buttonHandle: AtomButtons.ScalarButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify,LIST[
["Slope:", button, LIST[$SlopePrompt]],
["Get!", button, LIST[$GetSlope]],
["Add!", button, LIST[$AddSlope]],
["Delete!", button, LIST[$DeleteSlope]]
]];
buttonHandle ← AtomButtons.CreateScalarButtonViewer[gargoyleData.outer, nextX, gargoyleData.height];
gargoyleData.hitTest.slopeHeader ← buttonHandle;
GGEvent.StandardSlopes[LIST[$StandardSlopes], gargoyleData];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildAngleLine: PROC [gargoyleData: GargoyleData] = {
buttonHandle: AtomButtons.ScalarButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify,LIST[
["Angle:", button, LIST[$AnglePrompt]],
["Get!", button, LIST[$GetAngle]],
["Add!", button, LIST[$AddAngle]],
["Delete!", button, LIST[$DeleteAngle]]
]];
buttonHandle ← AtomButtons.CreateScalarButtonViewer[gargoyleData.outer, nextX, gargoyleData.height];
gargoyleData.hitTest.angleHeader ← buttonHandle;
GGEvent.StandardAngles[LIST[$StandardAngles], gargoyleData];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildRadiusLine: PROC [gargoyleData: GargoyleData] = {
buttonHandle: AtomButtons.ScalarButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["Radius:", button, LIST[$RadiusPrompt]],
["Get!", button, LIST[$GetRadius]],
["Add!", button, LIST[$AddRadius]],
["Delete!", button, LIST[$DeleteRadius]]
]];
buttonHandle ← AtomButtons.CreateScalarButtonViewer[gargoyleData.outer, nextX, gargoyleData.height];
gargoyleData.hitTest.radiusHeader ← buttonHandle;
GGEvent.StandardRadii[LIST[$StandardRadii], gargoyleData];
gargoyleData.hitTest.radiusCircleCache ← GGCircleCache.Create[];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildDistanceLine: PROC [gargoyleData: GargoyleData] = {
buttonHandle: AtomButtons.ScalarButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["LineDistance:", button, LIST[$DistancePrompt]],
["Get!", button, LIST[$GetDistance]],
["Add!", button, LIST[$AddDistance]],
["Delete!", button, LIST[$DeleteDistance]]
]];
buttonHandle ← AtomButtons.CreateScalarButtonViewer[gargoyleData.outer, nextX, gargoyleData.height];
gargoyleData.hitTest.distanceHeader ← buttonHandle;
GGEvent.StandardDistances[LIST[$StandardDistances], gargoyleData];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildMeasureLine: PROC [gargoyleData: GargoyleData] = {
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["SlopeValue:", button, LIST[$MeasureSlopeHit]],
["0.0", text, NIL, SlopeViewInGGData, smallNumberSize],
["AngleValue:", button, LIST[$MeasureAngleHit]],
["0.0", text, NIL, AngleViewInGGData, smallNumberSize],
["RadiusValue:", button, LIST[$MeasureRadiusHit]],
["0.0", text, NIL, DistanceViewInGGData, smallNumberSize],
["LineDistanceValue:", button, LIST[$MeasureLineDistHit]],
["0.0", text, NIL, LineDistViewInGGData, smallNumberSize]
]];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
BuildFeedbackLine: PROC [gargoyleData: GargoyleData] = {
nextX: NAT ← AtomButtons.BuildButtonLine[gargoyleData.outer, 0, gargoyleData.height, gargoyleData, GGUserInput.MenuNotify, LIST[
["Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Line", label, NIL, FeedbackLineInGGData, column3]
]];
gargoyleData.height ← gargoyleData.height + entryHeight;
};
Dummy: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
GGError.AppendHerald[gargoyleData.feedback, "Menu Level: This feature not yet implemented", oneLiner];
GGError.Blink[gargoyleData.feedback];
};
File Line:
InterpressMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["MergeIPEditable", LIST [$MergeIPEditable]],
["MergeIPSlice", LIST [$MergeIPSlice]],
["ToIP", LIST [$ToIP]],
["ToIPScreen", LIST [$ToIPScreen]],
["IncludeIPByReference", LIST[$IncludeIPByReference]],
["IncludeIPByValue", LIST[$IncludeIPByValue]],
["ShowIPIncludeMode", LIST[$ShowIPIncludeMode]]
];
QueuePopUpMenuAction["Interpress", menu, gargoyleData, mouseButton#blue];
};
ScriptMenu: Menus.ClickProc = {
ClickProc: TYPE = PROC [parent: REF ANY, clientData: REF ANYNIL,
mouseButton: MouseButton ← red, shift, control: BOOLFALSE];
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry ← LIST [
["OpenScript", LIST [$ScriptAction, $Open]],
["CloseScript", LIST [$ScriptAction, $Close]],
["PlaybackScript", LIST [$ScriptAction, $Playback]],
["FastPlayScript", LIST [$ScriptAction, $FastPlay]]
];
QueuePopUpMenuAction["Script", menu, gargoyleData, mouseButton#blue];
choices: LIST OF Rope.ROPE ← ExtractChoiceList[menu];
index: NAT ← PopUpSelection.Request[header: "Script", choice: choices];
SELECT index FROM
<0 => ERROR;
=0 => RETURN;
=1 => OpenSessionLog[parent, clientData, mouseButton, shift, control];
=2 => CloseSessionLog[parent, clientData, mouseButton, shift, control];
=3 => PlaybackLog[parent, clientData, mouseButton, shift, control];
=4 => FastPlaybackLog[parent, clientData, mouseButton, shift, control];
ENDCASE => ERROR;
};
ConfirmClear: PROC [clientData: REF ANY] = {
gargoyleData: GargoyleData ← NARROW[clientData];
GGError.AppendHerald[gargoyleData.feedback, "Confirm deletion of all objects", oneLiner];
};
ConfirmReset: PROC [clientData: REF ANY] = {
gargoyleData: GargoyleData ← NARROW[clientData];
GGError.AppendHerald[gargoyleData.feedback, "Confirm reset to original file", oneLiner];
};
ConfirmGet: PROC [clientData: REF ANY] = {
gargoyleData: GargoyleData ← NARROW[clientData];
filename: Rope.ROPE ← ViewerTools.GetSelectionContents[];
GGError.AppendHerald[gargoyleData.feedback, Rope.Cat["Confirm getting of file ", filename, " to the current scene."], oneLiner];
};
ConfirmMerge: PROC [clientData: REF ANY] = {
gargoyleData: GargoyleData ← NARROW[clientData];
filename: Rope.ROPE ← ViewerTools.GetSelectionContents[];
GGError.AppendHerald[gargoyleData.feedback, Rope.Cat["Confirm addition of file ", filename, " to the current scene."], oneLiner];
};
ConfirmStore: PROC [clientData: REF ANY] = {
gargoyleData: GargoyleData ← NARROW[clientData];
fullName, msg: Rope.ROPE;
success, exists: BOOL;
[fullName, success] ← GetGargoyleFileName[gargoyleData];
IF NOT success THEN RETURN;
exists ← FileExists[fullName];
IF exists THEN msg ← IO.PutFR["Confirm Store of %g [Old File]", [rope[fullName]]]
ELSE msg ← IO.PutFR["Confirm Store to %g [New File]", [rope[fullName]]];
GGError.AppendHerald[gargoyleData.feedback, msg, oneLiner];
};
GetGargoyleFileName: PROC [gargoyleData: GargoyleData] RETURNS [fullName: Rope.ROPENIL, success: BOOLTRUE] = {
cp: FS.ComponentPositions;
fileName: Rope.ROPE ← ViewerTools.GetSelectionContents[];
IF Rope.Length[fileName]=0 OR Rope.Equal[fileName, ""] THEN RETURN[NIL, FALSE];
[fullName, cp, ] ← FS.ExpandName[fileName, gargoyleData.currentWDir ! FS.Error => {
GGError.Append[gargoyleData.feedback, " FS Error during name expansion", oneLiner];
GGError.Blink[gargoyleData.feedback];
success ← FALSE;
CONTINUE;
}
];
IF success AND cp.ext.length=0 THEN fullName ← Rope.Concat[fullName, ".gargoyle"]; -- add gargoyle extension
};
FileExists: PROC [fileName: Rope.ROPE] RETURNS [answer: BOOL] = {
answer ← TRUE;
[----, ----, ----, ----] ← FS.FileInfo[fileName
! FS.Error => {IF error.code = $unknownFile THEN {answer ← FALSE; CONTINUE}
ELSE ERROR}];
};
Master Line:
HierarchyMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Delete (DEL)", LIST [$Delete]],
["UnDelete", LIST [$Undelete]],
["AddHoles (^h)", LIST [$AddHoles]],
["UnionCombine", LIST [$UnionCombine]],
["Extend Select (^v)", LIST [$ExtendSelect]],
["Undo (SHIFT-ESC)", LIST [$Undo]],
["Redo (ESC)", LIST [$Redo]],
["Cluster", LIST [$Cluster]],
["Un Cluster", LIST [$UnCluster]],
["DescribeSelected", LIST [$DescribeCurve, $Selected]]
];
QueuePopUpMenuAction["Hierarchy", menu, gargoyleData, mouseButton#blue];
};
TransformMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Rotate", LIST [$Rotate]],
["Scale", LIST [$Scale]],
["ScaleX", LIST [$ScaleX]],
["ScaleY", LIST [$ScaleY]],
["TranslateX", LIST [$TranslateX]],
["TranslateY", LIST [$TranslateY]],
["SixPoint", LIST [$SixPointTransform]],
["FourPoint", LIST [$FourPointTransform]]
];
QueuePopUpMenuAction["Transform", menu, gargoyleData, mouseButton#blue];
};
OverlapMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Top", LIST [$Top]],
["Bottom", LIST [$Bottom]],
["UpOne", LIST [$UpOne]],
["DownOne", LIST [$DownOne]]
];
QueuePopUpMenuAction["Overlap", menu, gargoyleData, mouseButton#blue];
};
ShapesMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Triangle", LIST [$PolygonInCircle, NEW[INT ← 3] ]],
["Square", LIST [$PolygonInCircle, NEW[INT ← 4] ]],
["Pentagon", LIST [$PolygonInCircle, NEW[INT ← 5] ]],
["Hexagon", LIST [$PolygonInCircle, NEW[INT ← 6] ]],
["Octagon", LIST [$PolygonInCircle, NEW[INT ← 8] ]],
["FromSelectedCount", LIST [$PolygonInCircle, NEW[INT ← -1] ]],
["Knotched Line", LIST [$KnotchedLine, NEW[REAL ← 4.0], NEW[INT ← 8]] ],
["Box", LIST [$NewBox, NEW[REAL ← 1.0] ]],
["Circle", LIST [$NewCircle, NEW[REAL ← 1.0] ]],
["Arrow", LIST [$NewArrow, NEW[REAL ← 0.5], NEW[REAL ← 0.125] ]],
The first parameter is shaft length. The second is barb length. Both in inches.
["8.5 by 11", LIST [$Frame, NEW[REAL ← 8.5*72.0], NEW[REAL ← 11.0*72.0] ]],
["11 by 14", LIST [$Frame, NEW[REAL ← 11.0*72.0], NEW[REAL ← 14.0*72.0] ]],
["38 by 50.66 (Versatec)", LIST [$Frame, NEW[REAL ← 38.0*72.0], NEW[REAL ← 50.666667*72.0] ]],
["640 x 480", LIST [$Frame, NEW[REAL ← 640.0], NEW[REAL ← 480.0] ]],
["1024 x 768", LIST [$Frame, NEW[REAL ← 1024.0], NEW[REAL ← 768.0] ]]
];
QueuePopUpMenuAction["Shapes", menu, gargoyleData, mouseButton#blue];
};
DebugMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Typescript", LIST [$Typescript]],
["Draw Tight Boxes", LIST [$DrawTightBoxes]],
["Draw Bounding Boxes", LIST [$DrawBoundBoxes]],
["Draw Outline Boxes", LIST [$DrawOutlineBoxes]],
["Draw Selection Box", LIST [$DrawSelectionBox]],
["Draw Moving Box", LIST [$DrawMovingBox]],
["Test Gravity", LIST [$TestGravity]],
["ToIPTestGravity", LIST [$ToIPTestGravity]],
["Performance Stats", LIST [$Statistics]],
["Reset Stats", LIST [$ResetStatistics]],
["SlackLog", LIST [$SlackLog]],
["Describe Caret Object", LIST [$DescribeCaretObject]],
["FSM Info", LIST [$FSMInfo]],
["Print All Input", LIST [$PrintAllInput]],
["Reset All Input", LIST [$ResetAllInput]],
["CauseAnError", LIST [$CauseAnError]]
];
QueuePopUpMenuAction["Debug", menu, gargoyleData, mouseButton#blue];
};
HelpMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
openHeight: INTEGER ← 140;
help: ViewerClasses.Viewer;
name: Rope.ROPE ← "GGHelp.Tioga";
IF (help ← ViewerOps.FindViewer[FS.ExpandName[name, gargoyleData.originalWDir].fullFName])#NIL THEN { -- viewer already exists
IF help.column#right THEN ViewerOps.ChangeColumn[help, right];
}
ELSE {
help ← ViewerOps.CreateViewer[flavor: $Text, info: [iconic: TRUE, column: right, openHeight: openHeight], paint: FALSE];
TiogaMenuOps.Load[viewer: help, fileName: Rope.Concat[gargoyleData.originalWDir, "GGHelp.Tioga"]];
};
ViewerOps.SetOpenHeight[viewer: help, clientHeight: openHeight];
ViewerOps.OpenIcon[icon: help, bottom: FALSE, paint: FALSE]; -- must do Open before Top
ViewerOps.TopViewer[viewer: help, paint: FALSE];
ViewerOps.ComputeColumn[right]; -- repaint right column
};
RefreshButton: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, gargoyleData: gargoyleData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE]
};
AbortButton: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.aborted ← ALL[TRUE];
};
ReviveButton: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
GGMouseEvent.ResetMouseMachinery[gargoyleData];
GGStatistics.ResetTable[GGStatistics.GlobalTable[]];
SlackProcess.Restart[gargoyleData.slackHandle];
gargoyleData.refresh.suppressRefresh ← FALSE;
gargoyleData.aborted ← ALL[FALSE];
IF mouseButton#blue THEN GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, gargoyleData: gargoyleData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE]
};
Style Line:
LineWidthMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["0 pt (LOOK 0)", LIST[$LineWidth, NEW[REAL ← 0.0]]],
["1 pt (LOOK 1)", LIST[$LineWidth, NEW[REAL ← 1.0]]],
["2 pt (LOOK 2)" , LIST[$LineWidth, NEW[REAL ← 2.0]]],
["3 pt (LOOK 3)", LIST[$LineWidth, NEW[REAL ← 3.0]]],
["4 pt (LOOK 4)", LIST[$LineWidth, NEW[REAL ← 4.0]]],
["FromSelection", LIST[$LineWidth]],
["ShowValue", LIST[$PrintLineWidth]],
["DashesFromSelection", LIST[$DashesFromSelection]],
["DashesOff", LIST[$DashesOff]],
["FindMatching", LIST[$SelectMatchingWidth]]
];
QueuePopUpMenuAction["Line Width", menu, gargoyleData, mouseButton#blue];
};
LineColorMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["none", LIST[$LineColorNone]],
["black" , LIST[$LineColorBlack]],
["white", LIST[$LineColorWhite]],
["gray", LIST[$LineColorGray]],
["FromColorTool", LIST[$LineColorFromColorTool]],
["FollowColorTool", LIST[$LineColorFollowColorTool]],
["ToColorTool", LIST[$LineColorToColorTool]],
["FromSelectedName", LIST[$LineColorFromSelectedName]],
["FromSelectedRGB", LIST[$LineColorFromSelectedRGB]],
["ShowValue", LIST[$PrintLineColor]],
["FindMatchingName", LIST[$SelectMatchingLineCNS]],
["FindMatchingRGB", LIST[$SelectMatchingLineRGB]]
];
QueuePopUpMenuAction["Line Color", menu, gargoyleData, mouseButton#blue];
};
AreaColorMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["none", LIST[$AreaColorNone]],
["black" , LIST[$AreaColorBlack]],
["white", LIST[$AreaColorWhite]],
["gray", LIST[$AreaColorGray]],
["FromColorTool", LIST[$AreaColorFromColorTool]],
["FollowColorTool", LIST[$AreaColorFollowColorTool]],
["ToColorTool", LIST[$AreaColorToColorTool]],
["FromSelectedName", LIST[$AreaColorFromSelectedName]],
["FromSelectedRGB", LIST[$AreaColorFromSelectedRGB]],
["ShowValue", LIST[$PrintAreaColor]],
["FindMatchingName", LIST[$SelectMatchingAreaCNS]],
["FindMatchingRGB", LIST[$SelectMatchingAreaRGB]]
];
QueuePopUpMenuAction["Fill", menu, gargoyleData, mouseButton#blue];
};
ArrowsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["none", LIST[$Arrows, NEW[INT ← 0]]],
["left/down", LIST[$Arrows, NEW[INT ← 1]]],
["right/up" , LIST[$Arrows, NEW[INT ← 2]]],
["both", LIST[$Arrows, NEW[INT ← 3]]]
];
QueuePopUpMenuAction["Arrows", menu, gargoyleData, mouseButton#blue];
};
AreaSelectMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["New", LIST [$AreaSelectNew]],
["NewWithDelete", LIST [$AreaSelectNewAndDelete]],
["Extend", LIST [$AreaSelectExtend]],
["All (^d)", LIST [$AreaSelectAll]],
["Degenerate", LIST [$AreaSelectDegenerate]]
];
QueuePopUpMenuAction["Area Select", menu, gargoyleData, mouseButton#blue];
};
TextOpsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["AddText", LIST [$AddText]],
["DropShadowOn 1 pt", LIST [$DropShadowOn, NEW[REAL ← -1.0], NEW[REAL ← -1.0]]],
["DropShadowOn 2 pt", LIST [$DropShadowOn, NEW[REAL ← -2.0], NEW[REAL ← -2.0]]],
["DropShadowOn 3 pt", LIST [$DropShadowOn, NEW[REAL ← -3.0], NEW[REAL ← -3.0]]],
["Drop Shadow From Selection", LIST [$DropShadowFromSelection]],
["DropShadowOff", LIST [$DropShadowOff]],
["AmplifySpaceFromSelection", LIST [$AmplifySpaceFromSelection]],
["ShowAmplifySpace", LIST [$PrintAmplifySpace]]
];
QueuePopUpMenuAction["Text", menu, gargoyleData, mouseButton#blue];
};
FontOpsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["SetPressFont", LIST [$SetPressFont]],
["SetScreenFont", LIST [$SetScreenFont]],
["SetPrintFont", LIST [$SetPrintFont]],
["ChangeFont", LIST [$ChangeFont]],
["MakeLookAlikes", LIST [$SetLookAlikes]],
["MakeDefault", LIST [$SetDefaultFontValues]],
["SetFontDetailed", LIST [$SetFontDetailed]],
["SetFontLiteral", LIST [$SetFontLiteral]],
["ShowValues", LIST [$ShowFontValues]],
["ShowValuesLiteral", LIST [$ShowFontValuesLiteral]],
["ShowDefaultValues", LIST [$ShowDefaultFontValues]],
["FindTextMatchingSelected", LIST[$FindTextMatchingSelected]],
["FindTextMatchingValues", LIST[$FindTextMatchingValues]],
["FindTextMatchingFamily", LIST[$FindTextMatchingFamily]]
];
QueuePopUpMenuAction["Fonts", menu, gargoyleData, mouseButton#blue];
};
GroupOpsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["AddToGroup", LIST [$AddToGroup]],
["FindGroup", LIST [$SelectGroup]],
["RemoveFromGroup", LIST [$RemoveFromGroup]],
["PrintGroupsOfSelected", LIST [$PrintGroupsOfSelected]],
["PrintAllGroups", LIST [$PrintAllGroups]]
];
QueuePopUpMenuAction["Groups", menu, gargoyleData, mouseButton#blue];
};
CurveTypeMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Line (LOOK l)", LIST [$SetStraight]],
["Arc (LOOK a)", LIST [$SetArc]],
["Conic (LOOK c)", LIST [$SetConic]],
["Bezier (LOOK z)", LIST [$SetBezier]],
["B-Spline (LOOK b)", LIST [$SetBSpline]],
["Natural Spline (LOOK n)", LIST [$SetNaturalSpline]],
["FindMatching", LIST [$SelectMatchingCurve]]
];
QueuePopUpMenuAction["Curves", menu, gargoyleData, mouseButton#blue];
};
EditMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Close (^c)", LIST [$Close]],
["Weld (^w)", LIST [$Weld]],
["Add CP (^p)", LIST [$AddControlPoint]],
["Delete CP (^P)", LIST [$DeleteControlPoint]],
["Add Joint (^j)", LIST [$AddJoint]],
["ReplaceSegment", LIST [$SplitSegment]],
["Splice", LIST [$Splice]]
];
QueuePopUpMenuAction["Edit", menu, gargoyleData, mouseButton#blue];
};
OpenSessionLog: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
GGSessionLog.OpenSessionLog[name, gargoyleData];
[] ← SlackProcess.EnableSessionLogging[gargoyleData.slackHandle];
};
CloseSessionLog: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
[] ← SlackProcess.DisableSessionLogging[gargoyleData.slackHandle];
GGSessionLog.CloseSessionLog[gargoyleData];
};
PlaybackLog: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
GGSessionLog.PlaybackFromFile[name, gargoyleData];
};
FastPlaybackLog: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
GGUserInput.MenuNotify[gargoyleData, LIST[$DisableRefresh]];
GGSessionLog.PlaybackFromFile[name, gargoyleData];
GGUserInput.MenuNotify[gargoyleData, LIST[$EnableRefresh]];
GGUserInput.MenuNotify[gargoyleData, LIST[$Refresh, $DoNotClearFeedback]];
};
Alignment Line:
HotSpotsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Make Hot (^s)", LIST[$MakeHot]],
["Make All Hot (^ss)", LIST[$MakeAllHot]],
["Make Cold (^S)" , LIST[$MakeCold]],
["Make All Cold (^SS)" , LIST[$MakeAllCold]],
["Show Hot", LIST [$ShowHot]],
["Hide Hot", LIST [$HideHot]],
["Drop Anchor (^a)" , LIST[$DropAnchor]],
["Lift Anchor (^A)" , LIST[$LiftAnchor]],
["Standard Alignments" , LIST[$StandardAlignments]]
];
QueuePopUpMenuAction["Hot Spots", menu, gargoyleData, mouseButton#blue];
};
UnitsMenu: Menus.ClickProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["FromSegment", LIST[$RadiusUnitFromSegment]],
["FromRadiusValue", LIST[$RadiusUnitFromValue]],
["FromSelection", LIST[$RadiusUnitFromSelection]],
["Inches", LIST[$InchScaleUnit]],
["Centimeters", LIST[$CentimeterScaleUnit]],
["PrintCurrent", LIST[$PrintScaleUnit]]
];
QueuePopUpMenuAction["Units", menu, gargoyleData, mouseButton#blue];
};
Distance Line:
Caret2InGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.measure.caret2← button;
};
SlopeViewInGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.measure.slopeView ← button;
gargoyleData.hitTest.slopeText ← button;
};
AngleViewInGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.measure.angleView ← button;
gargoyleData.hitTest.angleText ← button;
};
DistanceViewInGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.measure.radiusView ← button;
gargoyleData.hitTest.radiusText ← button;
};
LineDistViewInGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.measure.lineDistView ← button;
gargoyleData.hitTest.distanceText ← button;
};
FeedbackLineInGGData: AtomButtons.UpdateProc = {
gargoyleData: GargoyleData ← NARROW[clientData];
gargoyleData.feedback ← button;
};
DistanceOfInterest: Menus.ClickProc = {
};
Init: PROC = {
boldFont ← VFonts.EstablishFont[family: "Helvetica", size: 10, bold: TRUE,
italic: FALSE, defaultOnFailure: TRUE];
};
Init[];
END.