GGEventImplB.mesa
Last edited by Bier on October 1, 1985 9:31:38 pm PDT
Contents: Once an event reaches the front of the slack-process queue, it is dispatched to one of the procedures in this module.
Stone, August 9, 1985 2:38:57 pm PDT
DIRECTORY
CubicSplines, GGButtons, GGCaret, GGError, GGEvent, GGGraphicsButton, GGInterfaceTypes, GGModelTypes, GGObjects, GGSelect, GGVector, GGViewerOps, GGWindow, Imager, ImagerColor, IO, Rope, TiogaButtons, ViewerClasses, ViewerTools;
GGEventImplB: CEDAR PROGRAM
IMPORTS GGButtons, GGCaret, GGError, GGGraphicsButton, GGObjects, GGSelect, GGVector, GGViewerOps, GGWindow, Imager, ImagerColor, IO, Rope, TiogaButtons, ViewerTools
EXPORTS GGEvent =
BEGIN
Cluster: TYPE = GGModelTypes.Cluster;
EntityGenerator: TYPE = GGModelTypes.EntityGenerator;
GargoyleData: TYPE = GGInterfaceTypes.GargoyleData;
Outline: TYPE = GGModelTypes.Outline;
Point: TYPE = GGModelTypes.Point;
ScalarButtonClient: TYPE = GGInterfaceTypes.ScalarButtonClient;
Segment: TYPE = GGModelTypes.Segment;
Sequence: TYPE = GGModelTypes.Sequence;
Traj: TYPE = GGModelTypes.Traj;
TrajGenerator: TYPE = GGModelTypes.TrajGenerator;
TwoState: TYPE = GGInterfaceTypes.TwoState;
SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator;
SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator;
Vector: TYPE = GGModelTypes.Vector;
Viewer: TYPE = ViewerClasses.Viewer;
NotYetImplemented: PUBLIC SIGNAL = CODE;
Style Operations
LineWidth: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
strokeWidth: REAL;
msgRope: Rope.ROPE;
sequenceGen: SequenceGenerator;
widthRef: REF INTNARROW[event.rest.first];
width: NAT ← widthRef^;
strokeWidth ← width;
msgRope ← IO.PutFR["Selected objects will have line width %g.", [real[strokeWidth]]];
GGError.Append[msgRope, oneLiner];
sequenceGen ← GGSelect.SelectedSequences[gargoyleData, normal];
FOR sequence: Sequence ← GGObjects.NextSequence[sequenceGen], GGObjects.NextSequence[sequenceGen] UNTIL sequence = NIL DO
GGObjects.SetStrokeWidth[sequence, strokeWidth];
ENDLOOP;
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
AreaColorBlack: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
outline: Outline;
entityGen: EntityGenerator;
entityGen ← GGSelect.SelectedEntities[gargoyleData, normal];
FOR entity: REF ANY ← GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
seq: Sequence => outline ← GGObjects.OutlineOfTraj[seq.traj];
traj: Traj => outline ← GGObjects.OutlineOfTraj[traj];
o: Outline => outline ← o;
cluster: Cluster => ERROR NotYetImplemented;
ENDCASE => ERROR;
GGObjects.SetFillColor[outline, Imager.black];
ENDLOOP;
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
AreaColorWhite: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
outline: Outline;
entityGen: EntityGenerator;
entityGen ← GGSelect.SelectedEntities[gargoyleData, normal];
FOR entity: REF ANY ← GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
seq: Sequence => outline ← GGObjects.OutlineOfTraj[seq.traj];
traj: Traj => outline ← GGObjects.OutlineOfTraj[traj];
o: Outline => outline ← o;
cluster: Cluster => ERROR NotYetImplemented;
ENDCASE => ERROR;
GGObjects.SetFillColor[outline, Imager.white];
ENDLOOP;
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
AreaColorGray: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
outline: Outline;
entityGen: EntityGenerator;
entityGen ← GGSelect.SelectedEntities[gargoyleData, normal];
FOR entity: REF ANY ← GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
seq: Sequence => outline ← GGObjects.OutlineOfTraj[seq.traj];
traj: Traj => outline ← GGObjects.OutlineOfTraj[traj];
o: Outline => outline ← o;
cluster: Cluster => ERROR NotYetImplemented;
ENDCASE => ERROR;
GGObjects.SetFillColor[outline, ImagerColor.ColorFromGray[0.5]];
ENDLOOP;
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
Alignment Operations
MakeHot: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
entityGen: EntityGenerator;
entityGen ← GGSelect.SelectedEntities[gargoyleData, normal];
FOR entity: REF ANY ← GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
GGSelect.SelectEntity[entity, gargoyleData, hot];
ENDLOOP;
};
MakeCold: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
entityGen: EntityGenerator;
entityGen ← GGSelect.SelectedEntities[gargoyleData, normal];
FOR entity: REF ANY ← GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
GGSelect.DeselectEntity[entity, gargoyleData, hot];
ENDLOOP;
};
DropAnchor: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
GGCaret.Copy[gargoyleData.anchor, gargoyleData.caret];
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
KillAnchor: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
GGCaret.Kill[gargoyleData.anchor];
GGWindow.Painter[$PaintEntireScene, gargoyleData];
};
GravityChoiceChange: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
info: GGInterfaceTypes.EnumTypeRef ← gargoyleData.hitTest.gravityTypeMenu;
name: Rope.ROPE;
IF event.rest.first = $FlipForward THEN
GGButtons.TimeToFlipThru[LIST[$FlipForward, info]]
ELSE
GGButtons.TimeToFlipThru[LIST[$FlipBackward, info]];
name ← info.flipLabel.name;
SELECT TRUE FROM
Rope.Equal[name, "StrictDistance", TRUE] => gargoyleData.hitTest.gravityType ← strictDistance;
Rope.Equal[name, "PointsPreferred", TRUE] => gargoyleData.hitTest.gravityType ← innerCircle;
Rope.Equal[name, "Sectors", TRUE] => gargoyleData.hitTest.gravityType ← sectors;
Rope.Equal[name, "None", TRUE] => gargoyleData.hitTest.gravityType ← none;
ENDCASE => ERROR;
};
GravityExtentChange: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
value: REAL;
msgRope: Rope.ROPE;
graphicsState: GGGraphicsButton.GraphicsState ← gargoyleData.hitTest.gravityExtentButton;
value ← GGGraphicsButton.GetValue[graphicsState];
SELECT event.rest.first FROM
$ValueUp => {
value ← value*2.0;
msgRope ← IO.PutFR["Gravity extent is now %g screen dots.", [real[value]] ];
GGError.Append[msgRope, oneLiner];
GGGraphicsButton.SetButtonValueAndPaint[graphicsState, value];
};
$ValueDown => {
value ← value/2.0;
msgRope ← IO.PutFR["Gravity extent is now %g screen dots.", [real[value]] ];
GGError.Append[msgRope, oneLiner];
GGGraphicsButton.SetButtonValueAndPaint[graphicsState, value];
};
$InitialValue => {};
ENDCASE => ERROR;
gargoyleData.hitTest.tolerance ← value;
gargoyleData.hitTest.criticalR ← value;
gargoyleData.hitTest.innerR ← value;
};
ToggleAlwaysOn: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
stateInfo: TwoState ← gargoyleData.hitTest.linesAlwaysOn;
GGButtons.SwitchState[stateInfo];
};
ToggleDoubleBuffer: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
stateInfo: TwoState ← gargoyleData.refresh.doubleBuffer;
GGButtons.SwitchState[stateInfo];
};
SlopePrompt: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
viewer: Viewer ← gargoyleData.hitTest.slopeText;
ViewerTools.SetSelection[viewer];
};
AddSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
Doesn't properly handle end conditions. Assumes that some buttons already exist.
slope: REAL;
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
slope ← GGViewerOps.GetReal[gargoyleData.hitTest.slopeText, 90.0];
thisButton ← gargoyleData.hitTest.slopeButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, slope, LIST[$ToggleSlope, NEW[REAL ← slope]], FALSE, gargoyleData];
};
GetSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
seqGen: SequenceGenerator;
segGen: SegmentGenerator;
seq, next: Sequence;
direction: Vector;
degrees: REAL;
seqGen ← GGSelect.SelectedSequences[gargoyleData, normal];
seq ← GGObjects.NextSequence[seqGen];
next ← GGObjects.NextSequence[seqGen];
IF seq = NIL OR next # NIL THEN {
GGError.Append["Select a single sequence for a GetSlope.", oneLiner];
GGError.Blink[];
RETURN;
};
segGen ← GGObjects.SegmentsInSequence[seq];
FOR seg: Segment ← GGObjects.NextSegment[segGen], GGObjects.NextSegment[segGen] UNTIL seg = NIL DO
direction ← GGVector.VectorFromPoints[seg.lo, seg.hi];
degrees ← GGVector.AngleFromVector[direction];
IF degrees < 0.0 THEN degrees ← degrees + 180.0;
BEGIN
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
thisButton ← gargoyleData.hitTest.slopeButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, degrees, LIST[$ToggleSlope, NEW[REAL ← degrees]], FALSE, gargoyleData];
END
ENDLOOP;
};
ToggleSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
slope: REAL;
firstButton, pushedButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
WITH event.rest.first SELECT FROM
int: REF INT => slope ← int^;
real: REF REAL => slope ← real^;
ENDCASE => ERROR;
firstButton ← gargoyleData.hitTest.slopeButtons;
FOR thisButton: ScalarButtonClient ← firstButton, thisButton.next UNTIL thisButton = NIL DO
IF thisButton.value = slope THEN {
pushedButton ← thisButton;
EXIT;
};
REPEAT
FINISHED => ERROR;
ENDLOOP;
tiogaButton ← pushedButton.button;
IF pushedButton.on THEN {
pushedButton.on ← FALSE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "", "b"];
}
ELSE {
pushedButton.on ← TRUE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "b", ""];
};
};
DeleteSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {};
RadiusPrompt: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
viewer: Viewer ← gargoyleData.hitTest.radiusText;
ViewerTools.SetSelection[viewer];
};
AddRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
Doesn't properly handle end conditions. Assumes that some buttons already exist.
radius: REAL;
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
radius ← GGViewerOps.GetReal[gargoyleData.hitTest.radiusText, 72.0];
thisButton ← gargoyleData.hitTest.radiusButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, radius, LIST[$ToggleRadius, NEW[REAL ← radius]], FALSE, gargoyleData];
};
GetRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
seqGen: SequenceGenerator;
segGen: SegmentGenerator;
seq, next: Sequence;
radius: REAL;
seqGen ← GGSelect.SelectedSequences[gargoyleData, normal];
seq ← GGObjects.NextSequence[seqGen];
next ← GGObjects.NextSequence[seqGen];
IF next # NIL THEN {
GGError.Append["Select a single sequence for a GetRadius.", oneLiner];
GGError.Blink[];
};
segGen ← GGObjects.SegmentsInSequence[seq];
FOR seg: Segment ← GGObjects.NextSegment[segGen], GGObjects.NextSegment[segGen] UNTIL seg = NIL DO
radius ← GGVector.Distance[seg.lo, seg.hi];
BEGIN
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
thisButton ← gargoyleData.hitTest.radiusButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, radius, LIST[$ToggleRadius, NEW[REAL ← radius]], FALSE, gargoyleData];
END
ENDLOOP;
};
ToggleRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
radius: REAL;
epsilon: REAL = 0.01;
firstButton, pushedButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
WITH event.rest.first SELECT FROM
int: REF INT => radius ← int^;
real: REF REAL => radius ← real^;
ENDCASE => ERROR;
firstButton ← gargoyleData.hitTest.radiusButtons;
FOR thisButton: ScalarButtonClient ← firstButton, thisButton.next UNTIL thisButton = NIL DO
IF ABS[thisButton.value-radius] < epsilon THEN {
pushedButton ← thisButton;
EXIT;
};
REPEAT
FINISHED => ERROR;
ENDLOOP;
tiogaButton ← pushedButton.button;
IF pushedButton.on THEN {
pushedButton.on ← FALSE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "", "b"];
}
ELSE {
pushedButton.on ← TRUE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "b", ""];
};
};
DeleteRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {};
DistancePrompt: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
viewer: Viewer ← gargoyleData.hitTest.distanceText;
ViewerTools.SetSelection[viewer];
};
AddDistance: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
Doesn't properly handle end conditions. Assumes that some buttons already exist.
dist: REAL;
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
dist ← GGViewerOps.GetReal[gargoyleData.hitTest.distanceText, 0.0];
thisButton ← gargoyleData.hitTest.distanceButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, dist, LIST[$ToggleDistance, NEW[REAL ← dist]], FALSE, gargoyleData];
};
GetDistance: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
seqGen: SequenceGenerator;
segGen: SegmentGenerator;
seq, next: Sequence;
dist: REAL;
seqGen ← GGSelect.SelectedSequences[gargoyleData, normal];
seq ← GGObjects.NextSequence[seqGen];
next ← GGObjects.NextSequence[seqGen];
IF next # NIL THEN {
GGError.Append["Select a single sequence for a GetRadius.", oneLiner];
GGError.Blink[];
};
segGen ← GGObjects.SegmentsInSequence[seq];
FOR seg: Segment ← GGObjects.NextSegment[segGen], GGObjects.NextSegment[segGen] UNTIL seg = NIL DO
dist ← GGVector.Distance[seg.lo, seg.hi];
BEGIN
thisButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
thisButton ← gargoyleData.hitTest.distanceButtons;
UNTIL thisButton.next = NIL DO thisButton ← thisButton.next ENDLOOP;
tiogaButton ← thisButton.button;
[] ← GGButtons.AddScalarButton[tiogaButton, dist, LIST[$ToggleDistance, NEW[REAL ← dist]], FALSE, gargoyleData];
END
ENDLOOP;
};
ToggleDistance: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
dist: REAL;
epsilon: REAL = 0.01;
firstButton, pushedButton: ScalarButtonClient;
tiogaButton: TiogaButtons.TiogaButton;
WITH event.rest.first SELECT FROM
int: REF INT => dist ← int^;
real: REF REAL => dist ← real^;
ENDCASE => ERROR;
firstButton ← gargoyleData.hitTest.distanceButtons;
FOR thisButton: ScalarButtonClient ← firstButton, thisButton.next UNTIL thisButton = NIL DO
IF ABS[thisButton.value-dist] < epsilon THEN {
pushedButton ← thisButton;
EXIT;
};
REPEAT
FINISHED => ERROR;
ENDLOOP;
tiogaButton ← pushedButton.button;
IF pushedButton.on THEN {
pushedButton.on ← FALSE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "", "b"];
}
ELSE {
pushedButton.on ← TRUE;
TiogaButtons.ChangeButtonLooks[tiogaButton, "b", ""];
};
};
DeleteDistance: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {};
Miscellaneous
Erase: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {
GGWindow.Painter[$EraseAll, gargoyleData];
};
END.