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:
BOOL ←
TRUE, 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.