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. &GGCaretImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by Bier on August 19, 1985 2:04:33 pm PDT Contents: Facilities for moving the caret and storing information about the neighborhood it inhabits (such as what trajectory it is sitting on). This caret no longer exists. It should disappear from the screen. For use by GGRefreshImpl. The Chair. The Attractor. This caret exists. IF traj # NIL, then the caret is sitting on a trajectory. If the caret is sitting on a trajectory and onJoint then joint is the number of the joint on which the caret is sitting. Otherwise, segNum is the number of the segment on which the caret is sitting. GetAttractorJointNum: PUBLIC PROC [caret: Caret] RETURNS [jointNum: NAT] = { jointNum _ caret.attractorJointNum; }; Touching. joint1 already belongs to a group. Add joint2 to this group. Merge the two groups. Not yet implemented. Used for placing the anchor, for instance. Used for dropping the anchor. These procedures will be replaced by adding a field to GargoyleData. Κά˜head1™Icodešœ Οmœ1™Jšœ˜J˜—š Ÿ œžœžœžœžœ˜:Jšžœ˜J˜J˜—J˜J™ šŸ œžœžœ'žœ˜FJšœ˜Jšœžœ˜Jšœ˜JšœΟc˜)J˜J˜—šŸ œžœžœ%žœ˜FJšœ˜Jšœžœ˜Jšœ ˜+Jšœ˜J˜J˜—šŸœžœžœ˜(Jšœžœ˜J˜J˜—š Ÿœžœžœžœžœžœ˜xJšœ˜Jšœ˜Jšœ˜š žœžœžœ žœ žœ&˜RJšžœ žœ˜—š žœžœžœžœ žœ7˜XJšžœžœ˜—J˜J˜—J™J™J˜šŸœžœžœFžœžœžœžœ ˜£Jšœ–™–Jšœ"˜"Jšœžœ˜Jšœ˜Jšœ˜Jšœ!˜!Jšœ,˜,Jšœ(˜(Jšœ#˜#J˜J˜—š Ÿ œžœžœžœžœžœ˜€Jšœ˜Jšœ!˜!Jšœ#˜#š žœ žœžœ žœ žœ*˜ZJšžœ žœ˜—š žœ žœžœžœ žœ?˜dJšžœžœ˜—J˜J˜—š Ÿœžœžœžœ žœ™LJšœ#™#J™—J˜J™ J™šŸœžœZ˜sJšœ'˜'š žœžœžœžœžœ˜;Jšœ=™=Jšœ8˜8Jšœ?˜?J˜—š žœžœžœžœžœžœ˜@Jšœ8˜8Jšœ?˜?J˜—š žœžœžœžœžœžœ˜@J™Jšœ4˜4Jšœ4˜4Jšœ2˜2J˜—šžœ˜Jšœ;˜;Jšœ?˜?Jšœ?˜?J˜—J˜J˜—procšŸ œžœžœžœ˜4Mšœ žœ ˜Mšžœžœžœžœ˜EM˜M˜—š Ÿœžœžœžœ žœ˜^š žœžœžœ&žœžœž˜JJšžœ)žœžœ ˜B—Jšžœ˜Jšžœžœ˜ J˜J˜—šŸœžœ_˜zJ˜Jšœ'˜'Jšœ:˜:š žœžœžœžœžœ˜7Jšœ7˜7JšœžœG˜_J˜—š žœžœžœžœžœžœ˜