SVMenusImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on January 28, 1987 11:16:05 pm PST
Contents: Routines for building the control panel on each solid viewer.
DIRECTORY
AtomButtons, AtomButtonsTypes, CodeTimer, Feedback, FS, GraphicsButton, Imager, IO, Menus, PopUpSelection, Rope, SlackProcess, SV2d, SV3d, SVDraw, SVEditTool, SVEditUser, SVEvent, SVFiles, SVInterfaceTypes, SVMenus, SVModelTypes, SVMouseEvent, SVSceneTypes, SVState, SVUserInput, SVWindow, VFonts, ViewerClasses, ViewerTools;
SVMenusImpl: CEDAR PROGRAM
IMPORTS AtomButtons, CodeTimer, Feedback, FS, GraphicsButton, Imager, IO, PopUpSelection, Rope, SlackProcess, SVDraw, SVEditTool, SVEditUser, SVEvent, SVFiles, SVMouseEvent, SVState, SVUserInput, SVWindow, VFonts, ViewerTools
EXPORTS SVMenus =
BEGIN
Camera: TYPE = SVModelTypes.Camera;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
FileCamera: TYPE = SVSceneTypes.FileCamera;
GravityExtentData: TYPE = REF GravityExtentDataObj;
GravityExtentDataObj: TYPE = SVInterfaceTypes.GravityExtentDataObj;
MouseButton: TYPE = Menus.MouseButton;
Plane: TYPE = SV3d.Plane;
Point2d: TYPE = SV2d.Point2d;
Scene: TYPE = SVSceneTypes.Scene;
TwoState: TYPE = AtomButtonsTypes.TwoState;
Viewer: TYPE = ViewerClasses.Viewer;
SVData: TYPE = SVInterfaceTypes.SVData;
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;
smallNumberSize: CARDINAL = 60;
scalarButtonColumn: CARDINAL = 180;
getScalarColumn: CARDINAL = 75;
newScalarColumn: CARDINAL = 40;
fullColumn: CARDINAL = 600; -- the width of the standard large left column.
boldFont: VFonts.Font; -- initialized in Init below;
popUpFont: 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, svData: SVData, 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 {
SVUserInput.EventNotify[svData, entries.first.input];
EXIT;
};
index ← index - 1;
REPEAT
FINISHED => ERROR;
ENDLOOP;
IF onceOnly THEN RETURN;
ENDLOOP;
};
BuildControlPanel: PUBLIC PROC [svData: SVData, windowMenu: Menus.Menu, workingDirectory: Rope.ROPE] = {
BuildFileMenuLine[svData];
BuildMasterMenuLine[svData];
BuildStyleMenuLine[svData];
BuildGravityLine[svData];
BuildSpecial3DLine[svData];
BuildAzimuthLine[svData];
BuildSlopeLine[svData];
BuildSlopeLineLine[svData];
BuildSlopePlaneLine[svData];
BuildMeasureLine[svData];
BuildFeedbackLine[svData];
};
Build All of the Control Panel Menus
BuildFileMenuLine: PROC [svData: SVData] = {
Clear, Restore, Get, Store, Save, Split, Erase, Interpress, Script, CastRays, Revive!
nextX: INTEGER;
interpressMenu: AtomButtons.ButtonLineEntry ← [popUpButton[
"Interpress",
LIST[
[LIST[$ToIP], "ToIP", "Writes an interpress master to selected filename", boldFont],
[LIST[$StorePoly], "StorePoly", "Stores a polygonal scene representation to selected filename"]
],
-1, FALSE, popUpFont]];
svData.height ← svData.height + entryVSpace;
Space down from the top of the viewer.
nextX ← AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Clear", LIST[LIST[$Clear]], -1, FALSE, NIL, ConfirmClear]],
[button["Restore", LIST[LIST[$Restore]], -1, FALSE, NIL, ConfirmReset]],
[button["Get", LIST[LIST[$Get]], -1, FALSE, NIL, ConfirmGet]],
[button["Store", LIST[LIST[$Store]], -1, FALSE, NIL, ConfirmStore]],
[button["Save", LIST[LIST[$Save]]]],
[button["Split", LIST[LIST[$Split]]]],
[button["Erase", LIST[LIST[$Erase]]]],
interpressMenu
]];
nextX ← AtomButtons.BuildUnQueuedButtonLine [svData.outer, nextX + entryHSpace, svData.height, svData, LIST[
["Script", button, ScriptMenu, NIL, 0, -1, FALSE, NIL, boldFont],
["CastRays", button, CastRaysMenu, NIL, 0, -1, FALSE, NIL, boldFont],
["Revive!", button, ReviveButton]
]];
nextX ← AtomButtons.BuildButtonLine [svData.outer, nextX + entryHSpace, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Refresh!", LIST[LIST[$DrawSceneButton]]]]
]];
svData.height ← svData.height + entryVSpace + entryHeight;
};
BuildMasterMenuLine: PROC [svData: SVData] = {
This section implements a set of buttons, text windows, and options listers in this format:
Draw: BBox BSphere Scene Coords Point Cross Color B&W Dither CoordsMode
nextX: INTEGER;
transformMenu: AtomButtons.ButtonLineEntry ←
[popUpButton["Transform", LIST [
[LIST [$RotX, $Do], "RotX", "Rotate selected objects about anchor's x axis"],
[LIST [$RotY, $Do], "RotY", "Rotate selected objects about anchor's y axis"],
[LIST [$RotZ, $Do], "RotZ", "Rotate selected objects about anchor's z axis"],
[LIST [$RotX, $Undo], "UnRotX", "Rotate selected objects about anchor's x axis by negated angle"],
[LIST [$RotY, $Undo], "UnRotY", "Rotate selected objects about anchor's y axis by negated angle"],
[LIST [$RotZ, $Undo], "UnRotZ", "Rotate selected objects about anchor's z axis by negated angle"],
[LIST [$Trans, $Do], "Translate", "Translate selected objects relative to anchor"],
[LIST [$Align], "Align", "Rotate selected objects to anchor's orientation or 90 degrees from it"],
[LIST [$EvenScale, $Do], "EvenScale", "Scale selected objects about anchor's origin"],
[LIST [$Trans, $Undo], "UnTranslate", "Translate selected objects relative to anchor by negated vector"],
[LIST [$NoOp], "", "There is no undo for Align."],
[LIST [$EvenScale, $Undo], "UnEvenScale", "Scale selected objects about anchor's origin by reciprocal scalar"],
[LIST [$Abut], "Abut", "Translate selected objects to anchor's origin"],
[LIST [$NormalizeRot], "NormalizeRot", "Rotate selected objects to anchor's orientation"],
[LIST [$Normalize], "Normalize", "Move selected objects to anchor's position & orientation"],
[LIST [$AbutX], "AbutX", "Translate selected objects to anchor's x=0 plane"],
[LIST [$AbutY], "AbutY", "Translate selected objects to anchor's y=0 plane"],
[LIST [$AbutZ], "AbutZ", "Translate selected objects to anchor's z=0 plane"]
],
-1, FALSE, NIL]];
nextX ← AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["DrawColor", LIST[LIST[$DrawColor]]]],
[button["DrawB&W", LIST[LIST[$DrawBlackAndWhite]]]],
transformMenu
]];
nextX ← AtomButtons.BuildUnQueuedButtonLine [svData.outer, nextX + entryHSpace, svData.height, svData, LIST[
["Shapes", button, ShapesMenu, NIL, 0, -1, FALSE, NIL, boldFont],
["Debug", button, DebugMenu, NIL, 0, -1, FALSE, NIL, boldFont]
]];
svData.height ← svData.height + entryVSpace + entryHeight;
}; -- end of BuildMasterMenuLine
BuildStyleMenuLine: PROC [svData: SVData] = {
nextX: INTEGER;
smallStringSize: NAT ← VFonts.StringWidth["WireframeStyle"];
noOpChoice: AtomButtons.PopUpChoice ← [LIST [$NoOp], "", "no-op" ];
quickClickMode: BOOL ← SVState.GetQuickClickMode[];
selectMenu: AtomButtons.ButtonLineEntry ←
[popUpButton["Select", LIST [
[LIST [$CycleSelection, $Forward], "CycleSelection", "Select a different object that is near the selected one."],
[LIST [$NoOp], "", "Does nothing."],
[LIST [$NoOp], "", "Does nothing."],
[LIST [$CycleSelection, $Backward], "UnCycleSelection", "Select a different object that is near the selected one."]
],
-1, FALSE, popUpFont]];
hotSpotsMenu: AtomButtons.ButtonLineEntry ←
[popUpButton["MakeHot", LIST [
[LIST [$MakeHot], "Make Hot (^s) [G]", "Make all selected objects hot"],
noOpChoice,
[LIST [$MakeCold], "Make Cold (^S) [G]", "Make all selected objects cold"],
[LIST [$DropAnchor], "Drop Anchor (^a)", "Drop anchor at caret"],
noOpChoice,
[LIST [$LiftAnchor], "Lift Anchor (^A)", "Remove anchor"],
[LIST [$MakeAllHot], "Make All Hot (^ss)", "Make all objects hot"],
noOpChoice,
[LIST [$MakeAllCold], "Make All Cold (^SS)", "Make all objects cold"],
[LIST [$StandardAlignments], "Standard Alignments", "Restore standard alignments"]
],
-1, FALSE, popUpFont, NIL, quickClickMode]];
unitsMenu: AtomButtons.ButtonLineEntry ←
[popUpButton["Units", LIST [
[LIST [$InchScaleUnit], "Inches", "Set unit value to 1 inch"],
[LIST [$PrintScaleUnit], "ShowValue", "Print current unit value"],
[LIST [$PointsScaleUnit], "Points", "Set unit value to 1 point"],
[LIST [$RadiusUnitFromSegment], "FromSegment [G]", "Set unit value to length of selected segment"],
[LIST [$RadiusUnitFromValue], "FromRadiusValue", "Set unit value from number in RadiusValue"],
[LIST [$RadiusUnitFromSelection], "FromSelection [T]", "Set unit value from number in the Tioga selection"],
[LIST [$CentimeterScaleUnit], "Centimeters", "Set unit value to 1 centimeter"]
],
-1, FALSE, popUpFont, NIL, quickClickMode]];
nextX ← AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
selectMenu,
hotSpotsMenu,
unitsMenu,
[twoState["ShowColors", LIST[$ToggleShowColors], FALSE, ShowColorsInit]],
[button["ViewStyle:", LIST[LIST[$StylePrompt]] ]],
[label["Shaded", ViewStyleInSVData, smallStringSize]],
[button["Selected", LIST[LIST[$Selected]], -1, FALSE, NIL, NIL, SelectedInSVData]]
]];
svData.height ← svData.height + entryVSpace + entryHeight;
};
BuildGravityLine: PROC [svData: SVData] = {
nextX: NAT ← 0;
svData.hitTest.gravityTypeMenu ←
AtomButtons.BuildEnumTypeSelection[viewer: svData.outer, x: 0, y: svData.height, maxWidth: 144,
clientData: svData,
handleProc: SVUserInput.EventNotify,
title: "GravType:", default: "PreferPoints",
borderOnButtons: TRUE, style: flipThru, allInOneRow: TRUE,
buttonNames: LIST["PreferFaces", "PreferLines", "PreferPoints"],
atom: $GravityChoiceChange];
svData.hitTest.gravityType ← pointsPreferred;
nextX ← svData.hitTest.gravityTypeMenu.nextx;
nextX ← AtomButtons.BuildButtonLine[
svData.outer, nextX + entryHSpace, svData.height, svData, SVUserInput.EventNotify, LIST[
[label["GravExtent:"]]
]];
nextX ← GraphicsButton.BuildGraphicsButton[
container: svData.outer,
x: nextX + entryHSpace,
y: svData.height,
w: 60, -- changed from 72 to make more room in line
h: entryHeight,
clientData: svData,
choices: LIST[
[LIST[$GravityExtentChange, $ValueUp]],
[LIST[$GravityExtentChange, $InitialValue]],
[LIST[$GravityExtentChange, $ValueDown]]],
handleProc: SVUserInput.EventNotify,
repaintProc: GravityExtentRepaint,
buttonData: NEW[GravityExtentDataObj ← [extent: SVEditUser.GetDefaultGravityExtent[]]],
updateProc: GravityExtentInSVData
];
nextX ← AtomButtons.BuildButtonLine[
svData.outer, nextX + 2*entryHSpace, svData.height, svData, SVUserInput.EventNotify, LIST[
[twoState["Gravity", LIST[$ToggleGravity], TRUE, GravityButtonInit]],
[twoState["Midpoints", LIST[$ToggleMidpoints], FALSE, MidpointsButtonInit]],
[twoState["Heuristics", LIST[$ToggleHeuristics], SVState.GetDefaultHeuristics[], HeuristicsButtonInit]]
]];
svData.height ← svData.height + entryHeight;
};
BuildSpecial3DLine: PROC [svData: SVData] = {
nextX: INTEGER;
bigStringSize: NAT ← VFonts.StringWidth["///Users/Name.pa/Solidviews/PictureName.pic"];
threeNumberSize: NAT ← VFonts.StringWidth["18, 18, 18"];
nextX ← AtomButtons.BuildButtonLine [svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["CoordsMode", LIST[LIST[$ShowCoordsMode]], -1, FALSE, NIL, NIL, ShowCoordsInSVData]],
[button["x,y,z:", LIST[LIST[$XYZPrompt]]]],
[text["0, 0, 0", XYZViewInSVData, threeNumberSize]]
]];
svData.height ← svData.height + entryVSpace + entryHeight;
}; -- end of BuildSpecial3DLine
BuildAzimuthLine: PROC [svData: SVData] = {
buttonHandle: AtomButtons.SortedButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Azimuth:", LIST[LIST[$AzimuthPrompt]] ]],
[button["Get!", LIST[LIST[$GetAzimuth]], getScalarColumn ]],
[button["Add!", LIST[LIST[$AddAzimuth]] ]],
[button["Delete!", LIST[LIST[$DeleteAzimuth]] ]]
]];
buttonHandle ← AtomButtons.CreateSortedButtonViewer[svData.outer, scalarButtonColumn, svData.height];
svData.hitTest.azimuthHandle ← buttonHandle;
SVEvent.StandardAzimuths[LIST[$StandardAzimuths], svData];
svData.height ← svData.height + entryHeight;
};
BuildSlopeLine: PROC [svData: SVData] = {
buttonHandle: AtomButtons.SortedButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Slope:", LIST[LIST[$SlopePrompt]] ]],
[button["Get!", LIST[LIST[$GetSlope]], getScalarColumn ]],
[button["Add!", LIST[LIST[$AddSlope]] ]],
[button["Delete!", LIST[LIST[$DeleteSlope]] ]]
]];
buttonHandle ← AtomButtons.CreateSortedButtonViewer[svData.outer, scalarButtonColumn, svData.height];
svData.hitTest.slopeHandle ← buttonHandle;
SVEvent.StandardSlopes[LIST[$StandardSlopes], svData];
svData.height ← svData.height + entryHeight;
};
BuildSlopeLineLine: PROC [svData: SVData] = {
buttonHandle: AtomButtons.SortedButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Line:", LIST[LIST[$SlopeLinePrompt]] ]],
[button["New!", LIST[LIST[$NewSlopeLine]], newScalarColumn ]],
[button["Get!", LIST[LIST[$GetLine]], getScalarColumn ]],
[button["Add!", LIST[LIST[$AddSlopeLine]] ]],
[button["Delete!", LIST[LIST[$DeleteSlopeLine]] ]]
]];
buttonHandle ← AtomButtons.CreateSortedButtonViewer[svData.outer, scalarButtonColumn, svData.height];
svData.hitTest.slopeLineHandle ← buttonHandle;
SVEvent.StandardSlopeLines[LIST[$StandardSlopeLines], svData];
svData.height ← svData.height + entryHeight;
};
BuildSlopePlaneLine: PROC [svData: SVData] = {
buttonHandle: AtomButtons.SortedButtonHandle;
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["Plane:", LIST[LIST[$SlopePlanePrompt]] ]],
[button["New!", LIST[LIST[$NewSlopePlane]], newScalarColumn ]],
[button["Get!", LIST[LIST[$GetLine]], getScalarColumn ]],
[button["Add!", LIST[LIST[$AddSlopePlane]] ]],
[button["Delete!", LIST[LIST[$DeleteSlopePlane]] ]]
]];
buttonHandle ← AtomButtons.CreateSortedButtonViewer[svData.outer, scalarButtonColumn, svData.height];
svData.hitTest.slopePlaneHandle ← buttonHandle;
SVEvent.StandardSlopePlanes[LIST[$StandardSlopePlanes], svData];
svData.height ← svData.height + entryHeight;
};
BuildMeasureLine: PROC [svData: SVData] = {
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[button["AzimuthValue:", LIST[LIST[$MeasureAzimuthHit]] ]],
[text["0.0", AzimuthViewInSVData, smallNumberSize]],
[button["SlopeValue:", LIST[LIST[$MeasureSlopeHit]] ]],
[text["0.0", SlopeViewInSVData, smallNumberSize]]
]];
svData.height ← svData.height + entryHeight;
};
BuildFeedbackLine: PROC [svData: SVData] = {
nextX: NAT ← AtomButtons.BuildButtonLine[svData.outer, 0, svData.height, svData, SVUserInput.EventNotify, LIST[
[label["Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Line", FeedbackLineInSVData, fullColumn]]
]];
svData.height ← svData.height + entryHeight;
};
File Line Menus:
ConfirmClear: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
scene: Scene ← svData.scene;
rope: Rope.ROPE;
dirty: BOOL;
dirty ← svData.outer.newVersion;
IF dirty THEN rope ← "Confirm discard of edits"
ELSE rope ← "Confirm emptying of viewer";
Feedback.AppendHerald[svData.feedback, rope, oneLiner];
};
ConfirmReset: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
scene: Scene ← svData.scene;
dirty: BOOL;
dirty ← svData.outer.newVersion;
IF dirty THEN Feedback.PutFHerald[svData.feedback, oneLiner, "Confirm discard of edits"]
ELSE Feedback.PutFHerald[svData.feedback, oneLiner, "Confirm reset of %g", [rope[scene.name]]];
}; -- end of ConfirmReset
ConfirmSave: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
scene: Scene ← svData.scene;
exists: BOOL;
rope: Rope.ROPE;
exists ← SVFiles.FileExists[scene.name];
IF exists THEN rope ← IO.PutFR["Confirm Save to %g [Old File]", [rope[scene.name]]]
ELSE {
rope ← IO.PutFR["%g doesn't exist. Use Store", [rope[scene.name]]];
Feedback.Blink[svData.feedback]
};
Feedback.Append[svData.feedback, rope, oneLiner];
};
ConfirmStore: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
editToolData: EditToolData ← NARROW[svData.editToolData];
scene: Scene ← svData.scene;
picName: Rope.ROPE ← ViewerTools.GetSelectionContents[];
fullName, wdir: Rope.ROPE;
exists: BOOL;
success: BOOLTRUE;
rope: Rope.ROPE;
IF Rope.Length[picName] = 0 THEN {
Feedback.Append[svData.feedback, "Please select a file name.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
wdir ← editToolData.originalWorkingDirectory;
[fullName,,] ← FS.ExpandName[picName, wdir
! FS.Error => IF error.group = user THEN {
Feedback.Append[svData.feedback, Rope.Concat["Store: ", error.explanation], oneLiner];
success ← FALSE;
CONTINUE;
}
];
exists ← SVFiles.FileExists[fullName];
IF exists THEN rope ← IO.PutFR["Confirm Store of %g [Old File]", [rope[fullName]]]
ELSE rope ← IO.PutFR["Confirm Store to %g [New File]", [rope[fullName]]];
Feedback.AppendHerald[svData.feedback, rope, oneLiner];
};
ConfirmGet: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
editToolData: EditToolData ← NARROW[svData.editToolData];
scene: Scene ← svData.scene;
picName: Rope.ROPE ← ViewerTools.GetSelectionContents[];
fullName, wdir: Rope.ROPE;
success: BOOLTRUE;
dirty: BOOL;
IF Rope.Length[picName] = 0 THEN {
Feedback.Append[svData.feedback, "Please select a file name.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
wdir ← editToolData.originalWorkingDirectory;
[fullName,,] ← FS.ExpandName[picName, wdir
! FS.Error => IF error.group = user THEN {
Feedback.Append[svData.feedback, Rope.Concat["Get: ", error.explanation], oneLiner];
success ← FALSE;
CONTINUE;
}
];
IF NOT success THEN RETURN;
dirty ← svData.outer.newVersion;
IF dirty THEN Feedback.PutF[svData.feedback, oneLiner, "Confirm discard of edits and load of %g", [rope[fullName]]]
ELSE Feedback.PutF[svData.feedback, oneLiner, "Confirm load of %g", [rope[fullName]]];
}; -- end of ConfirmGet
Master Line Menus:
ShapesMenu: Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Block", LIST [$AddBlock, $Add]]
];
QueuePopUpMenuAction["Shapes", menu, svData, mouseButton#blue];
};
DebugMenu: Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["DrawBoundBoxes", LIST [$DrawBoundBoxes]],
["DrawBoundSpheres", LIST [$DrawBoundSpheres]],
["DrawCoordSystems", LIST [$DrawCoordSystems]],
["DrawPoint", LIST [$DrawPoint]],
["Draw Selection Box", LIST [$DrawSelectionBox]],
["CrossHairs", LIST [$CrossHairs]],
["KillSelections", LIST [$KillSelectionsButton]],
["DeleteJacks", LIST [$DeleteJacksButton]],
["TestGravity", LIST [$TestGravity]],
["Reset Statistics", LIST [$ResetStatistics]],
["Print Statistics", LIST [$PrintStatistics]],
["Raise SIGNAL", LIST [$RaiseSIGNAL]]
];
QueuePopUpMenuAction["Debug", menu, svData, mouseButton#blue];
};
CastRaysMenu: Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry ← LIST [
["RayCast", LIST [$RayCast]],
["StopRays", LIST [$StopRays]],
["ARay", LIST [$ARay]]
];
choices: LIST OF Rope.ROPE ← ExtractChoiceList[menu];
index: NAT ← PopUpSelection.Request[header: "SVCastRays", choice: choices];
SELECT index FROM
=0 => RETURN;
=1 => SVEvent.RayCast[LIST[$RayCast], svData];
=2 => SVEvent.StopRays[LIST[$StopRays], svData];
=3 => SVEvent.ARay[LIST[$ARay], svData];
ENDCASE => ERROR;
QueuePopUpMenuAction["SVCastRays", menu, svData, mouseButton#blue];
};
ScriptMenu: Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry ← LIST [
["OpenScript", LIST [$ScriptAction, $Open]],
["AppendToScript", LIST [$ScriptAction, $Append]],
["CloseScript", LIST [$ScriptAction, $Close]],
["PlaybackScript", LIST [$ScriptAction, $Playback]],
["FastPlayScript", LIST [$ScriptAction, $FastPlay]]
];
choices: LIST OF Rope.ROPE ← ExtractChoiceList[menu];
index: NAT ← PopUpSelection.Request[header: "Script", choice: choices];
SELECT index FROM
=0 => RETURN;
=1 => SVEvent.OpenScript[parent, clientData, mouseButton, shift, control];
=2 => SVEvent.AppendToScript[parent, clientData, mouseButton, shift, control];
=3 => SVEvent.CloseScript[parent, clientData, mouseButton, shift, control];
=4 => SVEvent.PlaybackScript[parent, clientData, mouseButton, shift, control];
=5 => SVEvent.FastPlayScript[parent, clientData, mouseButton, shift, control];
ENDCASE => ERROR;
};
ConfirmRayCast: PUBLIC PROC [clientData: REF ANY] = {
svData: SVData ← NARROW[clientData];
exists: BOOL;
aisFileRope: Rope.ROPE;
redRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-red.ais"];
greenRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-green.ais"];
blueRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisFileRope], "-blue.ais"];
rope: Rope.ROPE;
IF mouseButton = blue THEN { -- black and white only
exists ← SVFiles.FileExists[aisFileRope];
rope ← IO.PutFR["Confirm raycast to %g.", [rope[aisFileRope]]];
IF exists THEN rope ← Rope.Concat[rope, " [Old File]"]
ELSE rope ← Rope.Concat[rope, " [New File]"];
}
ELSE {
exists ← SVFiles.FileExists[aisFileRope] OR SVFiles.FileExists[redRope] OR SVFiles.FileExists[greenRope] OR SVFiles.FileExists[blueRope];
rope ← IO.PutFR["Confirm raycast to %g [-red, -green, -blue, plain].ais", [rope[SVFiles.FilenameMinusExtension[aisFileRope]]]];
IF exists THEN rope ← Rope.Concat[rope, " [Old Files]"]
ELSE rope ← Rope.Concat[rope, " [New Files]"];
};
Feedback.AppendHerald[svData.feedback, rope, oneLiner];
};
ReviveButton: Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
SVMouseEvent.ResetMouseMachinery[svData];
CodeTimer.ResetTable[CodeTimer.GetTable[$Solidviews]];
SlackProcess.Restart[svData.slackHandle];
svData.refresh.suppressRefresh ← FALSE;
svData.aborted ← ALL[FALSE];
IF mouseButton#blue THEN SVWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE]
};
Style Line Menus:
ShowColorsInit: AtomButtonsTypes.InitTwoStateProc = {
svData: SVData ← NARROW[clientData];
AtomButtons.SetBinaryState[twoState, FALSE];
svData.refresh.showColors ← twoState;
};
Gravity Line Menus:
GravityExtentInSVData: AtomButtonsTypes.UpdateGraphicsButtonProc = {
svData: SVData ← NARROW[clientData];
svData.hitTest.gravityExtentButton ← stateInfo;
};
GravityExtentRepaint: PROC [dc: Imager.Context, clientData: REF ANY, buttonData: REF ANY, button: Viewer] = {
caretPoint: Point2d;
ged: GravityExtentData ← NARROW[buttonData];
extent: REAL ← ged.extent;
Imager.TranslateT[dc, [button.ww, button.wh/2.0]];
caretPoint ← [-extent, 0.0];
SVDraw.DrawCaret[dc, caretPoint];
};
GravityButtonInit: AtomButtons.InitTwoStateProc = {
svData: SVData ← NARROW[clientData];
svData.hitTest.gravButton ← twoState;
};
MidpointsButtonInit: AtomButtons.InitTwoStateProc = {
svData: SVData ← NARROW[clientData];
svData.hitTest.midpointButton ← twoState;
};
HeuristicsButtonInit: AtomButtons.InitTwoStateProc = {
svData: SVData ← NARROW[clientData];
svData.hitTest.heuristicsButton ← twoState;
};
AzimuthViewInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.measure.azimuthView ← button;
};
SlopeViewInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.measure.slopeView ← button;
};
Feedback Line
FeedbackLineInSVData: AtomButtonsTypes.InitButtonProc = {
svData: SVData ← NARROW[clientData];
feedback: FeedbackData ← Feedback.RegisterFeedback[button, $Solidviews];
svData.feedback ← feedback;
};
Wiring Up Buttons to the Container:
ShowCoordsInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.textSection.showCoords ← button;
};
ViewStyleInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.textSection.viewStyle ← button;
};
SelectedInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.textSection.selected ← button;
};
XYZViewInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.textSection.xyz ← button;
};
DoubleBufferInSVData: AtomButtons.InitButtonProc = {
svData: SVData ← NARROW[clientData];
svData.textSection.doubleBuffer ← button;
Buttons.SetDisplayStyle[svData.textSection.doubleBuffer, $WhiteOnBlack];
};
Init: PROC = {
boldFont ← VFonts.EstablishFont[family: "Helvetica", size: 10, bold: TRUE,
italic: FALSE, defaultOnFailure: TRUE];
popUpFont ← VFonts.EstablishFont[family: "Helvetica", size: 10, bold: FALSE,
italic: TRUE, defaultOnFailure: TRUE];
};
Init[];
END.