GGCaretImpl.mesa
Copyright © 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).
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] = {
This caret no longer exists. It should disappear from the screen.
caret.exists ← FALSE;
};
Exists: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = {
RETURN[caret.exists];
};
For use by GGRefreshImpl.
TellOnOverlay: PUBLIC PROC [caret: Caret, onOverlay: BOOL] = {
caret.onOverlay ← onOverlay;
};
IsOnOverlay: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = {
RETURN[caret.onOverlay];
};
The Chair.
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;
};
The Attractor.
Update: PUBLIC PROC [gargoyleData: GargoyleData, point: Point, attractor: Traj, onJoint: BOOLTRUE, attractorJointNum: NAT ← 999, attractorSegNum: NAT ← 999] = {
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.
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;
};
GetAttractorJointNum: PUBLIC PROC [caret: Caret] RETURNS [jointNum: NAT] = {
jointNum ← caret.attractorJointNum;
};
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[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] = {
Not yet implemented.
};
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;
};
Used for placing the anchor, for instance.
Copy: PUBLIC PROC [to, from: Caret] = {
Used for dropping the anchor.
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;
};
These procedures will be replaced by adding a field to GargoyleData.
GetSequence: PUBLIC PROC [caret: Caret] RETURNS [seq: Sequence] = {
seq ← caret.seq;
};
SetSequence: PUBLIC PROC [caret: Caret, seq: Sequence] = {
caret.seq ← seq;
};
END.