DIRECTORY GGBasicTypes, GGBoundBox, GGCaret, GGInterfaceTypes, GGModelTypes, GGOutline, GGSegmentTypes, GGTraj; GGCaretImpl: CEDAR PROGRAM IMPORTS GGBoundBox, GGOutline, GGTraj EXPORTS GGCaret = BEGIN Caret: TYPE = REF CaretObj; CaretObj: TYPE = GGInterfaceTypes.CaretObj; CaretOn: TYPE = GGInterfaceTypes.CaretOn; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGModelTypes.Joint; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Point: TYPE = GGBasicTypes.Point; Segment: TYPE = GGSegmentTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; Traj: TYPE = GGModelTypes.Traj; TrajPartType: TYPE = GGModelTypes.TrajPartType; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; NotYetImplemented: PUBLIC SIGNAL = CODE; Copy: PUBLIC PROC [to, from: Caret] = { to.exists _ from.exists; to.point _ from.point; to.chair _ from.chair; to.attractor _ from.attractor; to.onOverlay _ from.onOverlay; }; Kill: PUBLIC PROC [caret: Caret] = { caret.exists _ FALSE; }; Exists: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = { RETURN[caret.exists]; }; BoundBoxOfCaret: PUBLIC PROC [caret: Caret, gargoyleData: GargoyleData] RETURNS [box: GGBoundBox.BoundBox _ NIL] = { leftOffset, rightOffset, topOffset, bottomOffset: REAL _ 0.0; IF caret=NIL OR gargoyleData=NIL THEN ERROR; SELECT TRUE FROM caret=gargoyleData.caret => { leftOffset _ GGCaret.caretWidth/2.0; rightOffset _ leftOffset; topOffset _ 0.0; bottomOffset _ GGCaret.caretHeight; }; caret=gargoyleData.anchor => { leftOffset _ GGCaret.anchorWidth/2.0; rightOffset _ leftOffset; topOffset _ GGCaret.anchorHeight/2.0; bottomOffset _ topOffset; }; ENDCASE => RETURN[NIL]; leftOffset _ leftOffset+fudge; rightOffset _ rightOffset+fudge; bottomOffset _ bottomOffset+fudge; topOffset _ topOffset+fudge; RETURN[GGBoundBox.CreateBoundBox[ caret.point.x-leftOffset, caret.point.y-bottomOffset, caret.point.x+rightOffset, caret.point.y+topOffset ]]; }; fudge: REAL _ 4.0; -- needed to make control points erase properly TellOnOverlay: PUBLIC PROC [caret: Caret, onOverlay: BOOL] = { caret.onOverlay _ onOverlay; }; IsOnOverlay: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = { RETURN[caret.onOverlay]; }; SitOn: PUBLIC PROC [caret: Caret, chair: REF ANY _ NIL] = { caret.chair _ chair; }; GetChair: PUBLIC PROC [caret: Caret] RETURNS [chair: REF ANY] = { chair _ caret.chair; }; SittingOnEnd: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = { success: BOOL; partType: TrajPartType; jointNum: NAT; traj: Traj; IF caret.chair = NIL THEN RETURN[FALSE]; WITH caret.chair SELECT FROM outlineD: OutlineDescriptor => { [success, partType, traj, ----, jointNum] _ GGOutline.UnpackSimpleDescriptorOld[outlineD]; IF NOT success OR partType # joint THEN RETURN[FALSE]; RETURN[GGTraj.IsEndJoint[traj, jointNum]]; }; sliceD: SliceDescriptor => { IF sliceD.slice.class.type # $Outline THEN RETURN[FALSE]; [success, partType, traj, ----, jointNum] _ GGOutline.UnpackSimpleDescriptor[sliceD]; IF NOT success OR partType # joint THEN RETURN[FALSE]; RETURN[GGTraj.IsEndJoint[traj, jointNum]]; }; ENDCASE => ERROR; }; NoAttractor: PUBLIC PROC [caret: Caret] = { caret.attractor _ NIL; }; SetAttractor: PUBLIC PROC [caret: Caret, point: Point, attractor: REF ANY] = { caret.exists _ TRUE; caret.point _ point; caret.attractor _ attractor; }; GetAttractor: PUBLIC PROC [caret: Caret] RETURNS [attractor: REF ANY] = { attractor _ caret.attractor; }; GetPoint: PUBLIC PROC [caret: Caret] RETURNS [point: Point] = { point _ caret.point; }; END. "GGCaretImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by Bier on January 14, 1987 11:29:07 pm PST Contents: Facilities for moving the caret and storing information about the neighborhood it inhabits (such as what trajectory it is sitting on). Pier, August 22, 1986 5:01:17 pm PDT Used for dropping the anchor. This caret no longer exists. It should disappear from the screen. For use by GGRefreshImpl. The Chair. GetChair: PUBLIC PROC [caret: Caret] RETURNS [chair: REF ANY, on: CaretOn, joint: Joint _ NIL, jointNum: NAT _ 999, cp: Point, cpNum: NAT _ 999, seg: Segment _ NIL, segNum: NAT _ 999] = { chair _ caret.chair; on _ caret.chairOn; jointNum _ caret.chairJointNum; cpNum _ caret.chairCPNum; segNum _ caret.chairSegNum; IF chair#NIL THEN WITH chair SELECT FROM traj: Traj => SELECT on FROM nothing => NULL; joint => joint _ GGTraj.FetchJoint[traj, jointNum]; seg => seg _ GGTraj.FetchSegment[traj, segNum]; cp => { seg _ GGTraj.FetchSegment[traj, segNum]; cp _ seg.class.controlPointGet[seg, cpNum]; }; slice => ERROR; ENDCASE; outlineD: OutlineDescriptor => SELECT on FROM nothing => NULL; slice => NULL; -- may do something more clever in the future joint, seg, cp=> ERROR; ENDCASE; sliceD: SliceDescriptor => SELECT on FROM nothing => NULL; slice => NULL; -- may do something more clever in the future joint, seg, cp=> ERROR; ENDCASE; ENDCASE => ERROR; -- chairs can only be trajs and sliceDescriptors }; The Attractor. GetAttractor: PUBLIC PROC [caret: Caret] RETURNS [attractor: REF ANY] = { attractor _ caret.attractor; on _ caret.attractorOn; jointNum _ caret.attractorJointNum; cpNum _ caret.attractorCPNum; segNum _ caret.attractorSegNum; IF attractor#NIL THEN WITH attractor SELECT FROM traj: Traj => SELECT on FROM nothing => NULL; joint => joint _ GGTraj.FetchJoint[traj, jointNum]; seg => seg _ GGTraj.FetchSegment[traj, segNum]; cp => { seg _ GGTraj.FetchSegment[traj, segNum]; cp _ seg.class.controlPointGet[seg, cpNum]; }; slice => ERROR; ENDCASE; sliceD: SliceDescriptor => SELECT on FROM nothing => NULL; slice => NULL; -- may do something more clever in the future joint, seg, cp=> ERROR; ENDCASE; ENDCASE => ERROR; -- chairs can only be trajs and sliceDescriptors }; Touching. 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 { joint1 already belongs to a group. Add joint2 to this group. 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 { Merge the two groups. 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.x - p2.x] < epsilon OR ABS[p1.y - p2.y] < 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] = { Not yet implemented. }; MakeChairTouchAttractor: PUBLIC PROC [caret: Caret, gargoyleData: GargoyleData] = { }; MakeChairTouchTrajJoint: PUBLIC PROC [caret: Caret, gargoyleData: GargoyleData, traj: Traj, jointNum: NAT] = { }; Ê ÿ˜code™Kšœ Ïmœ1™Kšœ˜K˜K˜—š Ÿ œžœžœžœžœ˜:Kšžœ˜K˜—K˜™ K™—š Ÿœžœžœžœžœžœ˜;KšœÏtœ¡˜K˜K˜—šŸœžœžœžœ žœžœžœ žœžœžœ žœ ™»Kšœ™Kšœ™Kšœ™Kšœ™Kšœ™š žœžœžœžœžœž™(šœžœž™Kšœ žœ™Kšœ3™3Kšœ/™/šœ™Kšœ(™(Kšœ+™+K™—Kšœ žœ™Kšž™—šœžœž™-Kšœ žœ™Kšœ žœ -™=Kšœžœ™Kšž™—šœžœž™)Kšœ žœ™Kšœ žœ -™=Kšœžœ™Kšž™—Kšžœžœ 0™B—K™K™—š Ÿœžœžœžœ žœžœ˜AKšœ˜K˜K˜—š Ÿ œžœžœžœžœ˜;Kšœ žœ˜Kšœ˜Kšœ žœ˜K˜ Kš žœžœžœžœžœ˜(šžœ žœž˜˜ Kšœ œ<˜ZKš žœžœ žœžœžœžœ˜6Kšžœ$˜*K˜—˜Kšžœ$žœžœžœ˜9Kšœ œ7˜UKš žœžœ žœžœžœžœ˜6Kšžœ$˜*K˜—Kšžœžœ˜—K˜—K™™K˜—šŸ œžœžœ˜+Kšœžœ˜K˜K˜—š Ÿ œžœžœ)žœžœ˜NKšœžœ˜Kšœ˜Kšœ˜K˜K˜—š Ÿ œžœžœžœ žœžœ˜IKšœ˜K˜K˜—š Ÿ œžœžœžœ žœžœ™IKšœ™Kšœ™Kšœ#™#Kšœ™Kšœ™š žœ žœžœžœ žœž™0šœžœž™Kšœ žœ™Kšœ3™3Kšœ/™/šœ™Kšœ(™(Kšœ+™+K™—Kšœ žœ™Kšž™—šœžœž™)Kšœ žœ™Kšœ žœ -™=Kšœžœ™Kšž™—Kšžœžœ 0™B—K™—K˜šŸœžœžœžœ˜?Kšœ˜K˜K˜—K™™ K™—šŸœžœZ™sKšœ'™'š žœžœžœžœžœ™;Kšœ=™=Kšœ8™8Kšœ?™?K™—š žœžœžœžœžœžœ™@Kšœ8™8Kšœ?™?K™—š žœžœžœžœžœžœ™@K™Kšœ4™4Kšœ4™4Kšœ2™2K™—šžœ™Kšœ;™;Kšœ?™?Kšœ?™?K™—K™K™—šŸ œžœžœžœ™4Kšœ žœ ™Kšžœžœžœžœ™AK™K™—š Ÿœžœžœžœ žœ™^š žœžœžœ&žœžœž™JKšžœ)žœžœ ™B—Kšžœ™Kšžœžœ™ K™K™—šŸœžœ_™zK™Kšœ'™'Kšœ:™:š žœžœžœžœžœ™7Kšœ7™7KšœžœG™_K™—š žœžœžœžœžœžœ™