<> <> <> <> <> <<>> DIRECTORY BasicTime, CubicSplines, FS, GGBasicTypes, GGBoundBox, GGBuiltinShapes, AtomButtons, GGCaret, GGError, GGEvent, GGGraphicsButton, GGInterface, GGInterfaceTypes, GGModelTypes, GGObjects, GGOutline, GGParseIn, GGRefresh, GGSegment, GGSegmentTypes, GGSelect, GGSequence, GGSlice, GGStatistics, GGTraj, GGTransform, GGVector, GGWindow, Imager, ImagerArtwork, ImagerTransformation, ImagerInterpress, IO, List, Rope, TIPUser, ViewerClasses, ViewerTools; GGEventImplC: CEDAR PROGRAM IMPORTS BasicTime, FS, GGCaret, GGBoundBox, GGBuiltinShapes, GGError, GGEvent, GGInterface, GGObjects, GGOutline, GGSelect, GGSequence, GGStatistics, GGParseIn, GGRefresh, GGSegment, GGSlice, GGTraj, GGTransform, GGVector, GGWindow, Imager, ImagerArtwork, ImagerTransformation, ImagerInterpress, IO, List, Rope, ViewerTools, TIPUser EXPORTS GGEvent = BEGIN BitVector: TYPE = GGModelTypes.BitVector; BoundBox: TYPE = GGModelTypes.BoundBox; ControlPointGenerator: TYPE = GGModelTypes.ControlPointGenerator; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGSegmentTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Point: TYPE = GGBasicTypes.Point; ScalarButtonClient: TYPE = AtomButtons.ScalarButtonClient; ScalarButtonHandle: TYPE = AtomButtons.ScalarButtonHandle; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = GGModelTypes.Traj; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; TrajPartType: TYPE = GGModelTypes.TrajPartType; TwoState: TYPE = AtomButtons.TwoState; Vector: TYPE = GGBasicTypes.Vector; Viewer: TYPE = ViewerClasses.Viewer; ReloadTipTable: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { gargoyleData: GargoyleData _ NARROW[clientData]; newTable: TIPUser.TIPTable; actionArea: ViewerClasses.Viewer; bad: BOOL _ FALSE; tableName, msg: Rope.ROPE; GGError.Append[gargoyleData.feedback, "Reloading tip table...", begin]; tableName _ Rope.Concat[gargoyleData.originalWDir, "Gargoyle.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 {GGError.Append[gargoyleData.feedback, msg, oneLiner]; RETURN}; GGError.Append[gargoyleData.feedback, "Done.", end]; IF newTable = NIL THEN ERROR; actionArea _ gargoyleData.actionArea; actionArea.tipTable _ newTable; }; SawTextFinish: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { gargoyleData: GargoyleData _ NARROW[clientData]; slice: Slice _ gargoyleData.refresh.textInProgress; IF slice#NIL AND Rope.Length[GGSlice.GetText[slice: slice]]=0 THEN { -- backspaced to nothing GGSelect.DeselectEntityAllClasses[slice, gargoyleData.scene]; GGSlice.DeleteSlice[gargoyleData.scene, slice]; }; IF gargoyleData.refresh.textInProgress#NIL THEN { -- fix up alignment triggers GGWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsSelected, gargoyleData: gargoyleData, remake: triggerBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: FALSE]; slice _ gargoyleData.refresh.textInProgress _ NIL; -- terminates typed input }; }; <> PolygonInCircle: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { outline: Outline; bBox: BoundBox; gargoyleData: GargoyleData _ NARROW[clientData]; caretPoint: Point _ GGCaret.GetPoint[gargoyleData.caret]; sideCount: INT _ NARROW[event.rest.first, REF INT]^; IF sideCount=-1 THEN { rRope: Rope.ROPE _ ViewerTools.GetSelectionContents[]; sideCount _ IO.GetInt[IO.RIS[rRope] ! IO.EndOfStream, IO.Error => sideCount _ -1]; }; IF sideCount<=0 THEN RETURN; outline _ GGBuiltinShapes.PolygonInCircle[sideCount, caretPoint, gargoyleData.hitTest.scaleUnit]; GGObjects.AddOutline[gargoyleData.scene, outline, -1]; GGSelect.DeselectAll[gargoyleData.scene, normal]; GGSelect.SelectEntireOutline[outline, gargoyleData.scene, normal]; bBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; gargoyleData.refresh.startBoundBox^ _ bBox^; gargoyleData.refresh.addedObject _ outline; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; NewBox: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { slice: Slice; sliceParts: SliceParts; bBox: BoundBox; gargoyleData: GargoyleData _ NARROW[clientData]; caretPoint: Point _ GGCaret.GetPoint[gargoyleData.caret]; sideLength: REAL _ NARROW[event.rest.first, REF REAL]^; slice _ GGBuiltinShapes.Box[caretPoint, sideLength*gargoyleData.hitTest.scaleUnit]; GGObjects.AddSlice[gargoyleData.scene, slice, -1]; GGSelect.DeselectAll[gargoyleData.scene, normal]; sliceParts _ slice.class.newParts[slice, NIL, slice]; GGSelect.SelectSlice[slice, sliceParts, gargoyleData.scene, normal]; bBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; gargoyleData.refresh.startBoundBox^ _ bBox^; gargoyleData.refresh.addedObject _ slice; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; NewCircle: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { slice: Slice; sliceParts: SliceParts; bBox: BoundBox; gargoyleData: GargoyleData _ NARROW[clientData]; caretPoint: Point _ GGCaret.GetPoint[gargoyleData.caret]; radius: REAL _ NARROW[event.rest.first, REF REAL]^; slice _ GGBuiltinShapes.Circle[caretPoint, radius*gargoyleData.hitTest.scaleUnit]; GGObjects.AddSlice[gargoyleData.scene, slice, -1]; GGSelect.DeselectAll[gargoyleData.scene, normal]; sliceParts _ slice.class.newParts[slice, NIL, slice]; GGSelect.SelectSlice[slice, sliceParts, gargoyleData.scene, normal]; bBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; gargoyleData.refresh.startBoundBox^ _ bBox^; gargoyleData.refresh.addedObject _ slice; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; NewKnotchedLine: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { outline: Outline; bBox: BoundBox; gargoyleData: GargoyleData _ NARROW[clientData]; caretPoint: Point _ GGCaret.GetPoint[gargoyleData.caret]; length: REAL _ NARROW[event.rest.first, REF REAL]^; segCount: INT _ NARROW[event.rest.rest.first, REF INT]^; p1: Point; p1 _ GGVector.Add[caretPoint, [length*gargoyleData.hitTest.scaleUnit, 0.0]]; outline _ GGBuiltinShapes.KnotchedLine[p0: caretPoint, p1: p1, segmentCount: segCount]; GGObjects.AddOutline[gargoyleData.scene, outline, -1]; GGSelect.DeselectAll[gargoyleData.scene, normal]; GGSelect.SelectEntireOutline[outline, gargoyleData.scene, normal]; bBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; gargoyleData.refresh.startBoundBox^ _ bBox^; gargoyleData.refresh.addedObject _ outline; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; NewArrow: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { OPEN GGVector; outline: Outline; traj: Traj; seg: Segment; bBox: BoundBox; success: BOOL; gargoyleData: GargoyleData _ NARROW[clientData]; shaftLength: REAL _ NARROW[event.rest.first, REF REAL]^; barbLength: REAL _ NARROW[event.rest.rest.first, REF REAL]^; shaftBottom, shaftTop, barbLeft, barbRight: Point; shaftBottom _ GGCaret.GetPoint[gargoyleData.caret]; shaftLength _ shaftLength * gargoyleData.hitTest.scaleUnit; -- convert to screen dots. barbLength _ barbLength * gargoyleData.hitTest.scaleUnit; -- convert to screen dots. shaftTop _ Add[shaftBottom, [0.0, shaftLength]]; barbLeft _ Add[shaftBottom, Scale[Normalize[[-1.0,1.0]], barbLength]]; barbRight _ Add[shaftBottom, Scale[Normalize[[1.0,1.0]], barbLength]]; traj _ GGTraj.CreateTraj[shaftTop]; seg _ GGSegment.MakeLine[shaftTop, shaftBottom, NIL]; success _ GGTraj.AddSegment[traj, hi, seg, lo]; IF NOT success THEN ERROR; seg _ GGSegment.MakeLine[shaftBottom, barbLeft, NIL]; success _ GGTraj.AddSegment[traj, hi, seg, lo]; IF NOT success THEN ERROR; seg _ GGSegment.MakeLine[barbLeft, shaftBottom, NIL]; success _ GGTraj.AddSegment[traj, hi, seg, lo]; IF NOT success THEN ERROR; seg _ GGSegment.MakeLine[shaftBottom, barbRight, NIL]; success _ GGTraj.AddSegment[traj, hi, seg, lo]; IF NOT success THEN ERROR; outline _ GGOutline.CreateOutline[traj: traj, lineEnds: round, fillColor: Imager.black]; GGObjects.AddOutline[gargoyleData.scene, outline, -1]; GGSelect.DeselectAll[gargoyleData.scene, normal]; GGSelect.SelectEntireOutline[outline, gargoyleData.scene, normal]; bBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; gargoyleData.refresh.startBoundBox^ _ bBox^; gargoyleData.refresh.addedObject _ outline; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; Frame: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { <> gargoyleData: GargoyleData _ NARROW[clientData]; halfStrokeWidth: REAL = 9.0/2.0; frameWidth: REAL _ NARROW[event.rest.first, REF REAL]^; -- in Gargoyle units (points) frameLength: REAL _ NARROW[event.rest.rest.first, REF REAL]^; -- in Gargoyle units (points) box: GGBoundBox.BoundBox _ GGBoundBox.CreateBoundBox[0.0-halfStrokeWidth, 0.0-halfStrokeWidth, frameWidth+halfStrokeWidth, frameLength+halfStrokeWidth]; sliceD: SliceDescriptor _ GGSlice.MakeBoxSlice[box, none, GGTransform.Identity[], 9.0]; GGObjects.AddSlice[gargoyleData.scene, sliceD.slice, -1]; gargoyleData.refresh.startBoundBox^ _ sliceD.slice.boundBox^; gargoyleData.refresh.addedObject _ sliceD.slice; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectAdded, gargoyleData: gargoyleData, remake: sceneBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; <<>> <> Weld: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { gargoyleData: GargoyleData _ NARROW[clientData]; <> outSeqGen: GGSelect.OutlineSequenceGenerator; firstTraj, secondTraj, newTraj: Traj; firstOutline, secondOutline, newOutline: Outline; firstOutSeq, secondOutSeq: GGSelect.OutlineSequence; weldPoint: Point; firstEnd, secondEnd: TrajEnd; firstBox, secondBox, newBox: BoundBox; success: BOOL; outSeqGen _ GGSelect.SelectedOutlineSequences[gargoyleData.scene, normal]; [firstOutSeq, secondOutSeq, firstTraj, secondTraj, success] _ GetWeldArguments[gargoyleData, outSeqGen]; IF NOT success THEN RETURN; IF secondOutSeq = NIL THEN {WeldToSelf[gargoyleData, firstTraj]; RETURN;}; [firstEnd, secondEnd] _ ClosestEnds[firstTraj, secondTraj]; firstOutline _ GGOutline.OutlineOfTraj[firstTraj]; secondOutline _ GGOutline.OutlineOfTraj[secondTraj]; <> newTraj _ GGTraj.Concat[firstTraj, firstEnd, secondTraj, secondEnd]; newOutline _ GGOutline.CreateOutline[traj: newTraj, lineEnds: firstOutline.lineEnds, fillColor: firstOutline.fillColor]; GGInterface.DeleteOutline[firstOutline, gargoyleData.scene]; GGInterface.DeleteOutline[secondOutline, gargoyleData.scene]; GGObjects.AddOutline[gargoyleData.scene, newOutline, -1]; <> GGSelect.DeselectAll[gargoyleData.scene, normal]; GGSelect.SelectAll[gargoyleData.scene, normal]; GGEvent.SawTextFinish[NIL, gargoyleData]; GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, gargoyleData: gargoyleData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; -- end AreaSelectAll AreaSelectNew: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { gargoyleData: GargoyleData _ NARROW[clientData]; <> selectedGen: EntityGenerator _ GGSelect.SelectedStuff[gargoyleData.scene, normal]; -- save original selection startBox: BoundBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, normal]; AreaSelectAux[gargoyleData: gargoyleData, new: TRUE, paint: FALSE]; FOR formerSelected: REF ANY _ GGObjects.NextEntity[selectedGen], GGObjects.NextEntity[selectedGen] UNTIL formerSelected=NIL DO WITH formerSelected SELECT FROM outlineD: OutlineDescriptor => { <> GGSelect.DeselectEntityAllClasses[outlineD.slice, gargoyleData.scene]; GGObjects.DeleteOutline[gargoyleData.scene, outlineD.slice]; }; sliceD: SliceDescriptor => { GGSelect.DeselectEntityAllClasses[sliceD.slice, gargoyleData.scene]; GGSlice.DeleteSlice[gargoyleData.scene, sliceD.slice]; }; ENDCASE => ERROR; ENDLOOP; IF NOT startBox.null THEN { -- there were some original selections gargoyleData.refresh.startBoundBox^ _ startBox^; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, gargoyleData: gargoyleData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; }; AreaSelectDegenerate: PUBLIC PROC [event: LIST OF REF ANY, clientData: REF ANY] = { gargoyleData: GargoyleData _ NARROW[clientData]; <