<> <> <> <> <<>> DIRECTORY GGCaret, GGInterfaceTypes, GGModelTypes, GGObjects, GGTouch, GGWindow, Rosary; GGCaretImpl: CEDAR PROGRAM IMPORTS GGObjects, GGTouch, GGWindow, Rosary EXPORTS GGCaret = BEGIN Caret: TYPE = REF CaretObj; CaretObj: TYPE = GGInterfaceTypes.CaretObj; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGModelTypes.Joint; Point: TYPE = GGModelTypes.Point; Segment: TYPE = GGModelTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; TouchItem: TYPE = GGModelTypes.TouchItem; TouchGroup: TYPE = GGModelTypes.TouchGroup; Traj: TYPE = GGModelTypes.Traj; NotYetImplemented: PUBLIC SIGNAL = CODE; GetPoint: PUBLIC PROC [caret: Caret] RETURNS [point: Point] = { point _ caret.point; }; Kill: PUBLIC PROC [caret: Caret] = { <> caret.exists _ FALSE; }; <<>> Exists: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = { RETURN[caret.exists]; }; <> TellOnOverlay: PUBLIC PROC [caret: Caret, onOverlay: BOOL] = { caret.onOverlay _ onOverlay; }; IsOnOverlay: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = { RETURN[caret.onOverlay]; }; <> SitOnJoint: PUBLIC PROC [caret: Caret, chair: Traj, jointNum: NAT] = { caret.chair _ chair; caret.chairOnJoint _ TRUE; caret.chairJointNum _ jointNum; caret.chairSegNum _ 999; -- for debugging }; SitOnSegment: PUBLIC PROC [caret: Caret, chair: Traj, segNum: NAT] = { caret.chair _ chair; caret.chairOnJoint _ FALSE; caret.chairJointNum _ 999; -- for debugging caret.chairSegNum _ segNum; }; DoNotSit: PUBLIC PROC [caret: Caret] = { caret.chair _ NIL; }; GetChair: PUBLIC PROC [caret: Caret] RETURNS [chair: Traj, isJoint: BOOL, joint: Joint, jointNum: NAT, seg: Segment] = { chair _ caret.chair; isJoint _ caret.chairOnJoint; jointNum _ caret.chairJointNum; IF chair#NIL AND isJoint THEN joint _ NARROW[Rosary.Fetch[chair.joints, jointNum]] ELSE joint _ NIL; IF chair#NIL AND NOT isJoint THEN seg _ GGObjects.FetchSegment[chair, caret.chairSegNum] ELSE seg _ NIL; }; <<>> <> Update: PUBLIC PROC [gargoyleData: GargoyleData, point: Point, attractor: Traj, onJoint: BOOL _ TRUE, attractorJointNum: NAT _ 999, attractorSegNum: NAT _ 999] = { <> caret: Caret _ gargoyleData.caret; caret.exists _ TRUE; caret.point _ point; caret.attractor _ attractor; caret.attractorOnJoint _ onJoint; caret.attractorJointNum _ attractorJointNum; caret.attractorSegNum _ attractorSegNum; GGWindow.NewCaretPos[gargoyleData]; }; GetAttractor: PUBLIC PROC [caret: Caret] RETURNS [attractor: Traj, isJoint: BOOL, joint: Joint, jointNum: NAT, seg: Segment] = { attractor _ caret.attractor; isJoint _ caret.attractorOnJoint; jointNum _ caret.attractorJointNum; IF attractor#NIL AND isJoint THEN joint _ NARROW[Rosary.Fetch[attractor.joints, jointNum]] ELSE joint _ NIL; IF attractor#NIL AND NOT isJoint THEN seg _ GGObjects.FetchSegment[attractor, caret.attractorSegNum] ELSE seg _ NIL; }; <> <> <<};>> <> <<>> MakeJointTouchJoint: PROC [traj1, traj2: Traj, joint1, joint2: Joint, point: Point, gargoyleData: GargoyleData] = { touchGroup, group1, group2: TouchGroup; IF joint1.touchItem # NIL AND joint2.touchItem = NIL THEN { <> touchGroup _ GGTouch.TouchGroupOfItem[joint1.touchItem]; joint2.touchItem _ GGTouch.AddJoint[traj2, joint2, touchGroup]; } ELSE IF joint1.touchItem = NIL AND joint2.touchItem # NIL THEN { touchGroup _ GGTouch.TouchGroupOfItem[joint2.touchItem]; joint1.touchItem _ GGTouch.AddJoint[traj1, joint1, touchGroup]; } ELSE IF joint1.touchItem # NIL AND joint2.touchItem # NIL THEN { <> group1 _ GGTouch.TouchGroupOfItem[joint1.touchItem]; group2 _ GGTouch.TouchGroupOfItem[joint2.touchItem]; GGTouch.MergeGroups[group1, group2, gargoyleData]; } ELSE { touchGroup _ GGTouch.CreateTouchGroup[gargoyleData, point]; joint1.touchItem _ GGTouch.AddJoint[traj1, joint1, touchGroup]; joint2.touchItem _ GGTouch.AddJoint[traj2, joint2, touchGroup]; }; }; RatherClose: PROC [p1, p2: Point] RETURNS [BOOL] = { epsilon: REAL = 1.0e-5; RETURN[ABS[p1[1] - p2[1]] < epsilon OR ABS[p1[2] - p2[2]] < epsilon]; }; FindItemAtPoint: PROC [point: Point, touchItemList: LIST OF TouchItem] RETURNS [TouchItem] = { FOR list: LIST OF TouchItem _ touchItemList, list.rest UNTIL list = NIL DO IF RatherClose[list.first.segPoint, point] THEN RETURN[list.first] ENDLOOP; RETURN[NIL]; }; MakeJointTouchSegment: PROC [traj1, traj2: Traj, joint: Joint, seg: Segment, point: Point, gargoyleData: GargoyleData] = { samePointItem: TouchItem; touchGroup, group1, group2: TouchGroup; samePointItem _ FindItemAtPoint[point, seg.touchItemList]; IF joint.touchItem # NIL AND samePointItem = NIL THEN { touchGroup _ GGTouch.TouchGroupOfItem[joint.touchItem]; seg.touchItemList _ CONS[GGTouch.AddSegment[traj2, seg, point, touchGroup], seg.touchItemList]; } ELSE IF joint.touchItem = NIL AND samePointItem # NIL THEN { touchGroup _ GGTouch.TouchGroupOfItem[samePointItem]; joint.touchItem _ GGTouch.AddJoint[traj1, joint, touchGroup]; } ELSE IF joint.touchItem # NIL AND samePointItem # NIL THEN { group1 _ GGTouch.TouchGroupOfItem[joint.touchItem]; group2 _ GGTouch.TouchGroupOfItem[samePointItem]; GGTouch.MergeGroups[group1, group2, gargoyleData]; } ELSE { touchGroup _ GGTouch.CreateTouchGroup[gargoyleData, point]; joint.touchItem _ GGTouch.AddJoint[traj1, joint, touchGroup]; seg.touchItemList _ CONS[GGTouch.AddSegment[traj2, seg, point, touchGroup], seg.touchItemList]; }; }; MakeSegmentTouchSegment: PROC [chair, attractor: Traj, chairSeg, attractorSeg: Segment, point: Point, gargoyleData: GargoyleData] = { <> }; MakeChairTouchAttractor: PUBLIC PROC [caret: Caret, gargoyleData: GargoyleData] = { chair, attractor: Traj; chairJoint, attractorJoint: Joint; chairSeg, attractorSeg: Segment; chairOnJoint, attractorOnJoint: BOOL; [chair, chairOnJoint, chairJoint, ----, chairSeg] _ GetChair[caret]; IF chair = NIL THEN RETURN; [attractor, attractorOnJoint, attractorJoint, ----, attractorSeg] _ GetAttractor[caret]; IF attractor = NIL THEN RETURN; SELECT TRUE FROM chairOnJoint AND attractorOnJoint => MakeJointTouchJoint[chair, attractor, chairJoint, attractorJoint, caret.point, gargoyleData]; chairOnJoint AND NOT attractorOnJoint => MakeJointTouchSegment[chair, attractor, chairJoint, attractorSeg, caret.point, gargoyleData]; NOT chairOnJoint AND attractorOnJoint => MakeJointTouchSegment[attractor, chair, attractorJoint, chairSeg, caret.point, gargoyleData]; NOT chairOnJoint AND NOT attractorOnJoint => MakeSegmentTouchSegment[chair, attractor, chairSeg, attractorSeg, caret.point, gargoyleData]; ENDCASE => ERROR; }; MakeChairTouchTrajJoint: PUBLIC PROC [caret: Caret, gargoyleData: GargoyleData, traj: Traj, jointNum: NAT] = { chair: Traj; trajJoint, chairJoint: Joint; chairSeg: Segment; isJoint: BOOL; [chair, isJoint, chairJoint, ----, chairSeg] _ GetChair[caret]; IF chair = NIL THEN RETURN; trajJoint _ NARROW[Rosary.Fetch[traj.joints, jointNum]]; SELECT TRUE FROM isJoint => MakeJointTouchJoint[chair, traj, chairJoint, trajJoint, caret.point, gargoyleData]; NOT isJoint => MakeJointTouchSegment[traj, chair, trajJoint, chairSeg, caret.point, gargoyleData]; ENDCASE => ERROR; }; <<>> <> Copy: PUBLIC PROC [to, from: Caret] = { <> to.exists _ from.exists; to.point _ from.point; to.chair _ from.chair; to.chairJointNum _ from.chairJointNum; to.chairSegNum _ from.chairSegNum; to.chairOnJoint _ from.chairOnJoint; to.attractor _ from.attractor; to.attractorJointNum _ from.attractorJointNum; to.attractorSegNum _ from.attractorSegNum; to.attractorOnJoint _ from.attractorOnJoint; to.seq _ from.seq; to.onOverlay _ from.onOverlay; }; <<>> <> GetSequence: PUBLIC PROC [caret: Caret] RETURNS [seq: Sequence] = { seq _ caret.seq; }; SetSequence: PUBLIC PROC [caret: Caret, seq: Sequence] = { caret.seq _ seq; }; <<>> END.