SVSelectImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on March 11, 1987 4:43:56 pm PST
Contents: To provide a selection mechanism for Solidviews similar to the one found in Gargoyle. In particular, we maintain a list of the selected objects and offer generators and structure browsers to walk through this list.
DIRECTORY
GList, SVAssembly, SVScene, SVSceneTypes, SVSelect;
SVSelectImpl:
CEDAR
PROGRAM
IMPORTS GList, SVAssembly, SVScene
EXPORTS SVSelect
=
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
AssemblyGenerator: TYPE = SVScene.AssemblyGenerator;
Scene: TYPE = SVSceneTypes.Scene;
SliceGenerator: TYPE = SVSceneTypes.SliceGenerator;
SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor;
SliceParts: TYPE = SVSceneTypes.SliceParts;
SelectionClass: TYPE = SVSelect.SelectionClass;
SliceDescriptorGenerator: TYPE = SVSceneTypes.SliceDescriptorGenerator;
SliceDescriptorGeneratorObj: TYPE = SVSceneTypes.SliceDescriptorGeneratorObj;
ChangeDonkeyTail:
PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] = {
SELECT selectClass
FROM
normal => sliceD.slice.normalSelectedParts ← sliceD;
hot => sliceD.slice.hotSelectedParts ← sliceD;
active => sliceD.slice.activeSelectedParts ← sliceD;
ENDCASE;
};
NoDonkeyTail:
PROC [slice: Slice, selectClass: SelectionClass] = {
SELECT selectClass
FROM
normal => slice.normalSelectedParts ← NIL;
hot => slice.hotSelectedParts ← NIL;
active => slice.activeSelectedParts ← NIL;
ENDCASE;
};
SelectAll:
PUBLIC
PROC [scene: Scene, selectClass: SelectionClass] = {
g: AssemblyGenerator;
g ← SVScene.PrimAssembliesInScene[scene];
FOR slice: Slice ← SVScene.NextAssembly[g], SVScene.NextAssembly[g]
UNTIL slice =
NIL
DO
SelectEntireSlice[slice, scene, selectClass];
ENDLOOP;
};
SelectSlice:
PUBLIC
PROC [sliceD: SliceDescriptor, scene: Scene, selectClass: SelectionClass] = {
oldSliceD, union: SliceDescriptor;
slice: Slice ← sliceD.slice;
IF SVAssembly.EmptyParts[sliceD] THEN RETURN;
oldSliceD ← FindSelectedSlice[slice, scene, selectClass];
IF oldSliceD#
NIL
THEN {
union ← SVAssembly.UnionParts[oldSliceD, sliceD];
DeselectSlice[slice, oldSliceD.parts, scene, selectClass]; -- throw away old selection
}
ELSE union ← sliceD;
IF selectClass = normal THEN union ← SVAssembly.AugmentParts[union, selectClass];
AppendSelection[scene, union, selectClass];
ChangeDonkeyTail[union, selectClass];
};
SelectEntireSlice:
PUBLIC PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] = {
allParts: SliceDescriptor ← SVAssembly.NewParts[slice, NIL, [0,0,0], slice];
SelectSlice[allParts, scene, selectClass];
};
DeselectAll:
PUBLIC
PROC [scene: Scene, selectClass: SelectionClass] = {
sliceD: SliceDescriptor;
FOR selected:
LIST
OF SliceDescriptor ← ListSelected[scene, selectClass], selected.rest
UNTIL selected =
NIL
DO
sliceD ← selected.first;
NoDonkeyTail[sliceD.slice, selectClass];
ENDLOOP;
SetSelectedList[scene, NIL, selectClass];
};
DeselectAllAllClasses:
PUBLIC
PROC [scene: Scene] = {
DeselectAll[scene, normal];
DeselectAll[scene, active];
DeselectAll[scene, hot];
};
DeselectEntireSlice:
PUBLIC
PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] = {
oldD: SliceDescriptor;
oldD ← FindSelectedSlice[slice, scene, selectClass];
IF oldD #
NIL
THEN {
DeleteSelection[scene, oldD, selectClass];
NoDonkeyTail[oldD.slice, selectClass];
};
};
DeselectSlice:
PUBLIC
PROC [slice: Slice, parts: SliceParts, scene: Scene, selectClass: SelectionClass] = {
oldD, newD, tempD: SliceDescriptor;
oldD ← FindSelectedSlice[slice, scene, selectClass];
IF oldD #
NIL
THEN {
tempD ← SVAssembly.DescriptorFromParts[slice, parts];
newD ← SVAssembly.DifferenceParts[oldD, tempD];
DeleteSelection[scene, oldD, selectClass];
NoDonkeyTail[oldD.slice, selectClass];
IF
NOT SVAssembly.EmptyParts[newD]
THEN {
IF selectClass = normal THEN newD ← SVAssembly.AugmentParts[newD, selectClass];
AppendSelection[scene, newD, selectClass];
ChangeDonkeyTail[newD, selectClass];
};
};
};
AppendSelection: PROC [scene: Scene, sliceD: SliceDescriptor, selectClass: SelectionClass] = {
Build the selection list in the proper order and keep it that way.
SELECT selectClass FROM
normal => scene.selected.normal ← NARROW[GList.Nconc[scene.selected.normal, LIST[sliceD]]];
hot => scene.selected.hot ← NARROW[GList.Nconc[scene.selected.hot, LIST[sliceD]]];
active => scene.selected.active ← NARROW[GList.Nconc[scene.selected.active, LIST[sliceD]]];
ENDCASE => ERROR;
};
Utilities
DeleteSelection:
PROC [scene: Scene, sliceD: SliceDescriptor, selectClass: SelectionClass] = {
Deletes entity from list. If it is not on the list, do nothing.
SetSelectedList[scene,
NARROW[GList.DRemove[sliceD, ListSelected[scene, selectClass]]],
selectClass];
};
ListSelected:
PUBLIC
PROC [scene: Scene, selectClass: SelectionClass]
RETURNS [selectedList:
LIST
OF SliceDescriptor] = {
SELECT selectClass
FROM
normal => selectedList ← scene.selected.normal;
hot => selectedList ← scene.selected.hot;
active => selectedList ← scene.selected.active;
ENDCASE => ERROR;
};
OPERATIONS THAT ALTER THE SELECTED LISTS
AppendSelection:
PROC [scene: Scene, entity: SliceDescriptor, selectClass: SelectionClass] = {
Build the selection list in the proper order and keep it that way.
SELECT selectClass
FROM
normal => {
IF scene.selected.normal =
NIL
THEN {
scene.selected.normal ← LIST[entity];
scene.selected.normalPtr ← scene.selected.normal;
scene.selected.normalPtrValid ← TRUE;
}
ELSE
IF scene.selected.normalPtrValid
THEN {
scene.selected.normalPtr.rest ← LIST[entity];
scene.selected.normalPtr ← scene.selected.normalPtr.rest;
}
ELSE {
scene.selected.normalPtr ← LastSliceDescriptor[scene.selected.normal];
scene.selected.normalPtr.rest ← LIST[entity];
scene.selected.normalPtr ← scene.selected.normalPtr.rest;
scene.selected.normalPtrValid ← TRUE;
};
};
hot => {
IF scene.selected.hot =
NIL
THEN {
scene.selected.hot ← LIST[entity];
scene.selected.hotPtr ← scene.selected.hot;
scene.selected.hotPtrValid ← TRUE;
}
ELSE
IF scene.selected.hotPtrValid
THEN {
scene.selected.hotPtr.rest ← LIST[entity];
scene.selected.hotPtr ← scene.selected.hotPtr.rest;
}
ELSE {
scene.selected.hotPtr ← LastSliceDescriptor[scene.selected.hot];
scene.selected.hotPtr.rest ← LIST[entity];
scene.selected.hotPtr ← scene.selected.hotPtr.rest;
scene.selected.hotPtrValid ← TRUE;
};
};
active => {
IF scene.selected.active =
NIL
THEN {
scene.selected.active ← LIST[entity];
scene.selected.activePtr ← scene.selected.active;
scene.selected.activePtrValid ← TRUE;
}
ELSE
IF scene.selected.activePtrValid
THEN {
scene.selected.activePtr.rest ← LIST[entity];
scene.selected.activePtr ← scene.selected.activePtr.rest;
}
ELSE {
scene.selected.activePtr ← LastSliceDescriptor[scene.selected.active];
scene.selected.activePtr.rest ← LIST[entity];
scene.selected.activePtr ← scene.selected.activePtr.rest;
scene.selected.activePtrValid ← TRUE;
};
};
ENDCASE => ERROR;
};
LastSliceDescriptor:
PROC [sliceDList:
LIST
OF SliceDescriptor]
RETURNS [last:
LIST
OF SliceDescriptor] = {
FOR last ← sliceDList, last.rest UNTIL last.rest = NIL DO ENDLOOP;
};
SetSelectedList:
PROC [scene: Scene, value:
LIST
OF SliceDescriptor, selectClass: SelectionClass] = {
SELECT selectClass
FROM
normal => {
scene.selected.normal ← value;
scene.selected.normalPtrValid ← FALSE;
};
hot => {
scene.selected.hot ← value;
scene.selected.hotPtrValid ← FALSE;
};
active => {
scene.selected.active ← value;
scene.selected.activePtrValid ← FALSE;
};
ENDCASE => ERROR;
};
Enumerate Selected Objects
IsSelectedInPart:
PUBLIC
PROC [slice: Slice, scene: Scene, selectClass: SelectionClass]
RETURNS [
BOOL] = {
Returns TRUE if all or part of entity is selected. These are the cases:
1) entity is a slice. Some outline is selected all or in part.
2) entity is an outline. Some trajectory is selected all or in part.
3) entity is a trajectory. Some joint or segment is selected.
4) entity is a sequence. Some joint or segment is selected.
sliceD: SliceDescriptor;
sliceD ← FindSelectedSlice[slice, scene, selectClass];
RETURN[sliceD # NIL];
};
FindSelectedSlice:
PUBLIC
PROC [slice: Slice, scene: Scene, selectClass: SelectionClass]
RETURNS [sliceD: SliceDescriptor] = {
SELECT selectClass
FROM
normal => sliceD ← IF slice.normalSelectedParts = NIL THEN NIL ELSE slice.normalSelectedParts;
hot => sliceD ← IF slice.hotSelectedParts = NIL THEN NIL ELSE slice.hotSelectedParts;
active => sliceD ← IF slice.activeSelectedParts = NIL THEN NIL ELSE slice.activeSelectedParts;
ENDCASE => ERROR;
};
SelectedSlices:
PUBLIC
PROC [scene: Scene, selectClass: SelectionClass]
RETURNS [sliceDescGen: SliceDescriptorGenerator] = {
sliceD: SliceDescriptor ← NIL;
ptr: LIST OF SliceDescriptor ← NIL;
sliceDescGen ← NEW[SliceDescriptorGeneratorObj];
FOR entityList:
LIST
OF SliceDescriptor ← ListSelected[scene, selectClass], entityList.rest
UNTIL entityList =
NIL
DO
sliceD ← NARROW[entityList.first];
[sliceDescGen.list, ptr] ← AddSliceDescriptor[sliceD, sliceDescGen.list, ptr];
ENDLOOP;
};
AddSliceDescriptor:
PROC [entity: SliceDescriptor, entityList, ptr:
LIST
OF SliceDescriptor]
RETURNS [newList, newPtr:
LIST
OF SliceDescriptor] = {
IF ptr =
NIL
THEN {
IF NOT entityList = NIL THEN ERROR;
newPtr ← newList ← CONS[entity, NIL];
RETURN;
}
ELSE {
newList ← entityList;
ptr.rest ← CONS[entity, NIL];
newPtr ← ptr.rest;
};
};
NextSliceDescriptor:
PUBLIC PROC [g: SliceDescriptorGenerator]
RETURNS [next: SliceDescriptor] = {
IF g.list = NIL THEN RETURN[NIL]
ELSE {
next ← g.list.first;
g.list ← g.list.rest;
};
};
NextSlice:
PUBLIC PROC [g: SliceDescriptorGenerator]
RETURNS [next: Slice] = {
IF g.list = NIL THEN RETURN[NIL]
ELSE {
next ← g.list.first.slice;
g.list ← g.list.rest;
};
};
NoSelections:
PUBLIC
PROC [scene: Scene, selectClass: SelectionClass]
RETURNS [
BOOL] = {
SELECT selectClass
FROM
normal => RETURN[scene.selected.normal = NIL];
hot => RETURN[scene.selected.hot = NIL];
active => RETURN[scene.selected.active = NIL];
ENDCASE => ERROR;
};
END.