<> <> <> <> <> DIRECTORY BufferedRefresh, Cursors, Feedback, FileNames, FS, FunctionCache, GGBoundBox, Icons, Imager, ImagerTransformation, Menus, Rope, SlackProcess, SV2d, SV3d, SVAlign, SVArtwork, SVCaret, SVCoordSys, SVDrawMonitor, SVGravity, SVInterfaceTypes, SVMatrix3d, SVMeasure, SVMenus, SVModelTypes, SVMouseEvent, SVRefresh, SVScene, SVSceneTypes, SVSessionLog, SVState, SVTransforms, SVUserInput, SVVector3d, SVViewerTool, SVViewerTools, SVWindow, Terminal, TIPUser, ViewerClasses, ViewerOps; SVWindowImpl: CEDAR PROGRAM IMPORTS BufferedRefresh, SVCoordSys, Cursors, Feedback, FileNames, FunctionCache, FS, GGBoundBox, Icons, Imager, ImagerTransformation, SVMatrix3d, Menus, Rope, SlackProcess, SVAlign, SVArtwork, SVCaret, SVGravity, SVMeasure, SVMenus, SVMouseEvent, SVRefresh, SVScene, SVSessionLog, SVState, SVTransforms, SVUserInput, SVVector3d, SVViewerTool, SVViewerTools, Terminal, TIPUser, ViewerOps EXPORTS SVWindow SHARES ViewerClasses = BEGIN Camera: TYPE = SVModelTypes.Camera; CoordSystem: TYPE = SVModelTypes.CoordSystem; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FileCamera: TYPE = SVSceneTypes.FileCamera; Filters: TYPE = SVInterfaceTypes.Filters; FiltersObj: TYPE = SVInterfaceTypes.FiltersObj; ForegroundParts: TYPE = SVWindow.ForegroundParts; Matrix4by4: TYPE = SV3d.Matrix4by4; MouseButton: TYPE = Menus.MouseButton; Plane: TYPE = SV3d.Plane; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Scene: TYPE = SVSceneTypes.Scene; SkitterObj: TYPE = SVInterfaceTypes.SkitterObj; Viewer: TYPE = ViewerClasses.Viewer; SVData: TYPE = REF SVDataObj; SVDataObj: TYPE = SVInterfaceTypes.SVDataObj; PlaceOrigin: PROC [viewer: Viewer] = { <> << Find the center of the solid window in solid window coordinates.>> originX, originY: REAL; transMat: Matrix4by4; svData: SVData _ NARROW[viewer.data]; screenCS: CoordSystem; camera: Camera _ svData.camera; screenCS _ camera.screenCS; originX _ viewer.cw;-- convert window width to real originY _ viewer.ch;-- convert window height to real originX _ originX/2.0;-- find the midpoint in window coords originY _ originY/2.0; transMat _ SVMatrix3d.MakeTranslateMat[-originX,-originY,0]; SVTransforms.AbsTransfScreen[screenCS, transMat]; }; -- end of PlaceOrigin SVActionAreaPaint: PROC [self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL] RETURNS [quit: BOOL _ FALSE] = { <> <> PaintEntireViewer: PROC = { PlaceOrigin[self]; BufferedRefresh.FitSandwichToScreen[svData.refresh.sandwich, self.cw, self.ch]; RestoreScreenAndInvariants[paintAction: $PaintEntireScene, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; clientToViewer: Imager.Transformation _ ImagerTransformation.Scale[1.0]; svData: SVData; IF whatChanged = NIL THEN { --scrolling, opening or reopening svData _ NARROW[self.data]; PlaceOrigin[self]; BufferedRefresh.FitSandwichToScreen[svData.refresh.sandwich, self.cw, self.ch]; Imager.SetFont[context, svData.editToolData.screenFont]; IF svData.refresh.lastCW = self.cw AND svData.refresh.lastCH = self.ch THEN { -- Window Motion RestoreScreenAndInvariants[paintAction: $ViewersPaintAllPlanes, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; } ELSE { -- Scrolling RestoreScreenAndInvariants[paintAction: $ViewersPaintEntireScene, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; } ELSE { svData _ NARROW[whatChanged]; Imager.SetFont[context, svData.editToolData.screenFont]; SELECT svData.refresh.paintAction FROM $PaintEntireViewer => PaintEntireViewer[]; $CallAProc => { paintProc: SVInterfaceTypes.DisplayContextProc _ svData.refresh.paintProc; paintProc[context]; }; ENDCASE => SVRefresh.ActionAreaPaint[context, svData.refresh.paintAction, svData]; }; svData.refresh.lastCW _ self.cw; svData.refresh.lastCH _ self.ch; }; RestoreScreenAndInvariants: PUBLIC PROC [paintAction: ATOM, svData: SVData, remake: ForegroundParts _ triggerBag, backgndOK: BOOL _ FALSE, edited: BOOL _ TRUE, okToClearFeedback: BOOL _ TRUE] = { <> SELECT remake FROM none => NULL; triggerBag => { SVAlign.SetStaticBags[svData]; BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Foreground, FALSE]; }; alignBag => { SVAlign.FlushAlignBag[svData.hitTest.alignBag]; SVAlign.FillStaticAlignBag[svData.hitTest.triggerBag, svData.hitTest.sceneBag, svData.hitTest, NOT SVState.GetShowAlignments[svData], SVState.GetMidpoints[svData], svData.hitTest.alignBag]; BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Foreground, FALSE]; }; bitMap => { BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Foreground, FALSE]; }; sceneBag => { SVAlign.FlushTriggerBag[svData.hitTest.sceneBag]; SVAlign.FillStaticSceneBag[svData.scene, svData.hitTest.sceneBag]; }; ENDCASE => ERROR; IF edited THEN { FOR list: LIST OF EditedProcItem _ globalEditedProcList, list.rest UNTIL list = NIL DO list.first.editedProc[svData, list.first.clientData]; ENDLOOP; }; <> svData.refresh.paintAction _ paintAction; ViewerOps.PaintViewer[ viewer: svData.actionArea, hint: client, whatChanged: svData, clearClient: FALSE] }; SVEdited: PROC [svData: SVData, clientData: REF ANY] = { IF NOT svData.outer.newVersion THEN { <> svData.outer.icon _ IF svData.outer.file=NIL THEN dirtyNoNameIcon ELSE dirtyIcon; svData.outer.newVersion _ TRUE; ViewerOps.PaintViewer[svData.outer, caption]; }; }; globalEditedProcList: LIST OF EditedProcItem; EditedProc: TYPE = SVWindow.EditedProc; EditedProcItem: TYPE = REF EditedProcItemObj; EditedProcItemObj: TYPE = RECORD [ editedProc: EditedProc, clientData: REF ANY ]; RegisterEditedProc: PUBLIC PROC [editedProc: EditedProc, clientData: REF ANY] = { <> editedProcItem: EditedProcItem _ NEW[EditedProcItemObj _ [editedProc, clientData]]; globalEditedProcList _ CONS[editedProcItem, globalEditedProcList]; }; RawPaint: PUBLIC PROC [paintProc: SVInterfaceTypes.DisplayContextProc, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; svData.refresh.paintProc _ paintProc; svData.refresh.paintAction _ $CallAProc; ViewerOps.PaintViewer[viewer: svData.actionArea, hint: client, whatChanged: svData, clearClient: FALSE]; }; CreateWindow: PUBLIC PROC [editToolData: EditToolData, scene: Scene, iconic: BOOL, paint: BOOL, workingDirectory: Rope.ROPE] RETURNS [svData: SVData, viewerPicture: Viewer] = { <> <> <> <<#BBox #Scene #Coords #Point #Cross #Color #B&W Coords>> screenCS, worldCS: CoordSystem; success: BOOL; fileCamera: FileCamera; iconFileName: Rope.ROPE; windowMenu: Menus.Menu; svData _ NEW[SVDataObj]; svData.currentWDir _ workingDirectory; svData.originalWDir _ originalWDir; --global windowMenu _ Menus.CreateMenu[0]; svData.editToolData _ NARROW[editToolData]; svData.scene _ scene; iconFileName _ Rope.Concat[editToolData.originalWorkingDirectory, "SolidViews.icons"]; <> svData.outer _ SVViewerTool.Create[ info: [ name: Rope.Concat["Solid Scene: ", svData.scene.name], menu: windowMenu, data: svData, iconic: TRUE, column: left, scrollable: FALSE, icon: Icons.NewIconFromFile[iconFileName, 0] ], paint: FALSE]; <> screenCS _ SVCoordSys.CreateRoot["SCREEN"]; IF scene.cameraOrder # NIL THEN [fileCamera, ----] _ SVScene.FindFileCameraFromName[scene.cameraOrder.first, svData.scene] ELSE { [fileCamera, success] _ SVScene.FindFileCameraFromName["Front", svData.scene]; IF NOT success THEN ERROR; }; worldCS _ scene.coordSysRoot; svData.slackHandle _ SlackProcess.Create[queueSize: 50, logSize: 50, optimizeProc: OptimizeQueue, loggingProc: SVSessionLog.EnterAction, abortProc: NIL, abortData: NIL, abortViewer: NIL]; SVMouseEvent.InitializeFSM[svData]; svData.drag.savedCaret _ NEW[SkitterObj]; svData.camera _ SVScene.CreateCamera[worldCS, screenCS, shaded]; SVScene.StuffCameraFromFileCamera[svData.camera, fileCamera, shaded, scene]; svData.sceneStyleIndex _ 2; -- shaded svData.mode _ cast; svData.showCoordSys _ FALSE; svData.refresh.startBoundBox _ GGBoundBox.NullBoundBox[]; svData.refresh.sandwich _ SVRefresh.CreateSandwich[]; svData.defaults _ NEW[SVInterfaceTypes.DefaultDataObj _ [ strokeWidth: 2.0, strokeColor: Imager.black, fillColor: SVArtwork.CreateColorArtwork[Imager.white, chalk] ]]; svData.hitTest _ NEW[FiltersObj]; svData.hitTest.triggerBag _ SVAlign.CreateTriggerBag[svData.scene]; svData.hitTest.sceneBag _ SVAlign.CreateTriggerBag[svData.scene]; svData.hitTest.alignBag _ SVAlign.CreateAlignBag[]; svData.refresh.lineCache _ FunctionCache.Create[maxEntries: 200]; svData.gravityPool _ SVGravity.NewGravityPool[]; SVMenus.BuildControlPanel[svData, windowMenu, workingDirectory]; BuildPictureSection[svData]; viewerPicture _ svData.actionArea; IF NOT iconic THEN ViewerOps.OpenIcon[icon: svData.outer, closeOthers: FALSE, bottom: FALSE, paint: TRUE]; }; OptimizeQueue: SlackProcess.OptimizeProc = { <> <> atom, nextAtom: ATOM; optimizeHint: REF ANY; hintList: LIST OF REF ANY; IF actionsOnQueue < 2 THEN RETURN [0]; skipActions _ 0; FOR i: NAT IN [0..actionsOnQueue-2] DO [----, optimizeHint, ----] _ SlackProcess.GetQueueEntry[qeGen, i]; hintList _ IF optimizeHint = NIL THEN NIL ELSE NARROW[optimizeHint]; atom _ IF hintList = NIL THEN $None ELSE NARROW[hintList.first]; [----, optimizeHint, ----] _ SlackProcess.GetQueueEntry[qeGen, i+1]; hintList _ IF optimizeHint = NIL THEN NIL ELSE NARROW[optimizeHint]; nextAtom _ IF hintList = NIL THEN $None ELSE NARROW[hintList.first]; IF atom = $During AND nextAtom = $During THEN { skipActions _ skipActions + 1; } ELSE RETURN; ENDLOOP; }; BuildPictureSection: PRIVATE PROC [svData: SVData] = { <> svData.actionArea _ ViewerOps.CreateViewer[ flavor: $SolidWindow, info: [ parent: svData.outer, wx: 0, wy: svData.height, ww: svData.outer.ww, wh: svData.outer.wh, -- only initial values for ww and wh. They are constrained below data: svData, -- contains the current scene scrollable: FALSE ] ]; SVViewerTool.ChildXBound[svData.outer, svData.actionArea]; SVViewerTool.ChildYBound[svData.outer, svData.actionArea]; svData.height _ svData.height + svData.actionArea.wh; }; -- end of BuildDrawSection ReloadTipTable: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { newTable: TIPUser.TIPTable; editToolData: EditToolData _ NARROW[svData.editToolData]; solidviewer: ViewerClasses.Viewer; bad: BOOL _ FALSE; tableName, msg: Rope.ROPE; Feedback.Append[svData.feedback, "Reloading tip table...", begin]; tableName _ Rope.Concat[editToolData.originalWorkingDirectory, "Solidviews.TIP"]; newTable _ TIPUser.InstantiateNewTIPTable[tableName ! FS.Error => { bad _ TRUE; msg _ Rope.Concat["Cannot read TIP table file: ", tableName]; CONTINUE}; TIPUser.InvalidTable => { bad _ TRUE; msg _ Rope.Concat["Error(s) saved on TIP.Errors for: ", tableName]; CONTINUE}]; IF bad THEN {Feedback.Append[svData.feedback, msg, oneLiner]; RETURN}; Feedback.Append[svData.feedback, "Done.", end]; IF newTable = NIL THEN ERROR; solidviewer _ svData.actionArea; solidviewer.tipTable _ newTable; }; SetCursorLooks: PUBLIC PROC [type: SVInterfaceTypes.GravityType, svData: SVData, on: BOOL _ TRUE] = { <> newCursor: Cursors.CursorType; mouseViewer: ViewerClasses.Viewer; client: BOOL; terminal: Terminal.Virtual _ Terminal.Current[]; mousePos: Terminal.Position _ Terminal.GetMousePosition[terminal]; -- mouse origin in upper left tipScreenCoords: TIPUser.TIPScreenCoords _ NEW[TIPUser.TIPScreenCoordsRec _ [mouseX: mousePos.x, mouseY: mousePos.y, color: svData.actionArea.column=color] ]; tipScreenCoords.mouseY _ IF svData.actionArea.column=color THEN terminal.colorHeight-mousePos.y ELSE terminal.bwHeight-mousePos.y; -- move mouse origin to lower left [mouseViewer, client] _ ViewerOps.MouseInViewer[tipScreenCoords]; svData.actionArea.class.cursor _ newCursor _ IF NOT on THEN offCursor ELSE SELECT type FROM pointsPreferred => pointsPreferredCursor, linesPreferred => strictDistanceCursor, facesPreferred => offCursor, ENDCASE => ERROR; <> IF mouseViewer=svData.actionArea AND client THEN Cursors.SetCursor[newCursor]; }; NewCaretPos: PUBLIC PROC [svData: SVData] = { caret0, caret1, caret2Pos: Point3d; slope, azimuth, radius: REAL; editToolData: EditToolData _ svData.editToolData; caret0 _ svData.measure.caret0; caret1 _ svData.measure.caret1; caret2Pos _ SVVector3d.Scale[SVCaret.GetPoint[editToolData.skitter], 1.0/svData.hitTest.scaleUnit]; svData.measure.caret2Value _ caret2Pos; SVViewerTools.SetPoint[svData.measure.caret2, caret2Pos]; [azimuth, slope] _ SVMeasure.AzimuthAndSlopeOfPoints[caret1, caret2Pos]; radius _ SVMeasure.DistanceBetweenPoints[caret1, caret2Pos]; svData.measure.azimuthViewValue _ azimuth; SVViewerTools.SetReal[svData.measure.azimuthView, azimuth]; svData.measure.slopeViewValue _ slope; SVViewerTools.SetReal[svData.measure.slopeView, slope]; svData.measure.radiusViewValue _ radius; SVViewerTools.SetReal[svData.measure.radiusView, radius]; }; SaveCaretPos: PUBLIC PROC [svData: SVData] = { editToolData: EditToolData _ svData.editToolData; caret2Pos: Point3d _ SVVector3d.Scale[SVCaret.GetPoint[editToolData.skitter], 1.0/svData.hitTest.scaleUnit]; svData.measure.caret2Value _ caret2Pos; SVViewerTools.SetPoint[svData.measure.caret2, caret2Pos]; svData.measure.caret0 _ svData.measure.caret1; svData.measure.caret1 _ caret2Pos; }; BuildCursors: PROC [] = { pointsPreferredArray: Cursors.CursorArray = [600B+1100B, 600B+1100B+2040B, 2040B+4020B, 4020B+10010B, 10010B+20004B, 20004B+40002B, 40002B+100001B, 40002B+100001B, 40002B+100001B, 40002B+100001B, 20004B+40002B, 10010B+20004B, 4020B+10010B, 2040B+4020B, 600B+1100B+2040B, 600B+1100B]; -- diamond strictDistanceArray: Cursors.CursorArray = [100001B+40002B, 40002B+20004B, 20004B+10010B, 10010B+4020B, 4020B+2040B, 2040B, 0, 0, 0, 0, 2040B, 4020B+2040B, 10010B+4020B, 20004B+10010B, 40002B+20004B, 100001B+40002B]; -- folded diamond offArray: Cursors.CursorArray = [177777B, 177777B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 140003B, 177777B, 177777B]; -- square pointsPreferredCursor _ Cursors.NewCursor[bits: pointsPreferredArray, hotX: -8, hotY: -6]; strictDistanceCursor _ Cursors.NewCursor[bits: strictDistanceArray, hotX: -8, hotY: -5]; offCursor _ Cursors.NewCursor[bits: offArray, hotX: -8, hotY: -6]; }; noNameIcon: Icons.IconFlavor _ unInit; -- filled in by Init dirtyNoNameIcon: Icons.IconFlavor _ unInit; -- filled in by Init dirtyIcon: Icons.IconFlavor _ unInit; -- filled in by Init Init: PROC = { solidWindowClass: ViewerClasses.ViewerClass; solidWindowClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: SVActionAreaPaint, notify: SVUserInput.InputNotify, tipTable: TIPUser.InstantiateNewTIPTable["SolidViews.TIP"] ]]; ViewerOps.RegisterViewerClass[$SolidWindow, solidWindowClass]; BuildCursors[]; originalWDir _ FileNames.CurrentWorkingDirectory[]; RegisterEditedProc[SVEdited, NIL]; noNameIcon _ Icons.NewIconFromFile["SolidViews.icons", 0]; dirtyNoNameIcon _ Icons.NewIconFromFile["SolidViews.icons", 0]; dirtyIcon _ Icons.NewIconFromFile["SolidViews.icons", 0]; }; offCursor: Cursors.CursorType; -- filled in by BuildCursors pointsPreferredCursor: Cursors.CursorType; -- filled in by BuildCursors strictDistanceCursor: Cursors.CursorType; -- filled in by BuildCursors originalWDir: Rope.ROPE _ NIL; -- filled in by Init Init[]; END.