<> <> <> <> <> <> <<>> DIRECTORY GGBasicTypes, GGBoundBox, GGInterfaceTypes, GGModelTypes, GGOutline, GGScene, GGSceneType, GGSegmentTypes, GGSelect, GGSequence, GGSlice, GGTraj, GGUtility; GGSelectImpl: CEDAR PROGRAM IMPORTS GGBoundBox, GGOutline, GGScene, GGSelect, GGSequence, GGSlice, GGTraj, GGUtility EXPORTS GGModelTypes, GGSelect = BEGIN BoundBox: TYPE = GGBasicTypes.BoundBox; Caret: TYPE = GGInterfaceTypes.Caret; EntityGenerator: TYPE = REF EntityGeneratorObj; EntityGeneratorObj: TYPE = GGModelTypes.EntityGeneratorObj; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptorGenerator: TYPE = GGModelTypes.OutlineDescriptorGenerator; OutlineDescriptor: TYPE = REF OutlineDescriptorObj; OutlineDescriptorObj: TYPE = GGModelTypes.OutlineDescriptorObj; SceneRef: TYPE = REF SceneObj; SceneObj: PUBLIC TYPE = GGSceneType.SceneObj; SegAndIndex: TYPE = GGSequence.SegAndIndex; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SelectionClass: TYPE = GGInterfaceTypes.SelectionClass; Sequence: TYPE = REF SequenceObj; SequenceGenerator: TYPE = REF SequenceGeneratorObj; SequenceGeneratorObj: TYPE = GGModelTypes.SequenceGeneratorObj; SequenceObj: TYPE = GGModelTypes.SequenceObj; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceDescriptorGeneratorObj: TYPE = GGModelTypes.SliceDescriptorGeneratorObj; SliceDescriptorObj: TYPE = GGModelTypes.SliceDescriptorObj; SliceGenerator: TYPE = REF SliceGeneratorObj; SliceGeneratorObj: TYPE = GGModelTypes.SliceGeneratorObj; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = GGModelTypes.Traj; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajGenerator: TYPE = REF TrajGeneratorObj; TrajGeneratorObj: TYPE = GGModelTypes.TrajGeneratorObj; NotYetImplemented: PUBLIC SIGNAL = CODE; OutlineSequenceGenerator: TYPE = REF OutlineSequenceGeneratorObj; OutlineSequenceGeneratorObj: TYPE = GGSelect.OutlineSequenceGeneratorObj; OutlineSequence: TYPE = REF OutlineSequenceObj; OutlineSequenceObj: TYPE = GGSelect.OutlineSequenceObj; <> <> <> <> <> <<1) If an OutlineDescriptor is on the selected list, all of the selectedInFull fields of its joints, segments, and control points should be TRUE. The selected fields are maintained for efficiency only. The information they represent is always obtainable from the selected list as well.>> <> <<2) Only one sequence per trajectory may appear on the selected list.>> <> <<3) A non-gargoyle slice may only appear once on the selected list.>> <<4) Iff a sequence representing a trajectory is on the selected list, the "selectedInPart" field of the trajectory will TRUE.>> <<5) Iff a non-Gargoyle slice is on the selected list, the "selectedInFull" field of that slice will be true.>> <> <<>> <> <> < {>> <> <<};>> < {>> <> <<};>> < { -- this case needed for ReselectTraj>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> < ERROR;>> <<};>> <<>> <> <<>> 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; }; <> <> < slice.normalSelectedParts _ NIL;>> < slice.hotSelectedParts _ NIL;>> < slice.activeSelectedParts _ NIL;>> <> <<};>> <<>> SelectAll: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] = { sliceGen: SliceGenerator _ GGScene.TopLevelSlicesInScene[scene]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO SelectEntireSlice[slice, scene, selectClass]; ENDLOOP; }; SelectSlice: PUBLIC PROC [sliceD: SliceDescriptor, scene: SceneRef, selectClass: SelectionClass] = { oldSliceD, union: SliceDescriptor; slice: Slice _ sliceD.slice; IF slice.class.isEmptyParts[sliceD] THEN RETURN; oldSliceD _ FindSelectedSlice[slice, scene, selectClass]; IF oldSliceD#NIL THEN { union _ slice.class.unionParts[oldSliceD, sliceD]; DeselectSlice[slice, oldSliceD.parts, scene, selectClass]; -- throw away old selection } ELSE union _ sliceD; IF selectClass = normal THEN union _ slice.class.augmentParts[union, selectClass]; AppendSelection[scene, union, selectClass]; ChangeDonkeyTail[union, selectClass]; }; -- end SelectSlice <> <> <> <> <> <> <> <> <<}>> <> <> <> <> <<}; -- end SelectOutline>> <<>> <> <> <> <> <<};>> <<>> SelectEntireSlice: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] = { allParts: SliceDescriptor _ slice.class.newParts[slice, NIL, slice]; SelectSlice[allParts, scene, selectClass]; }; <<>> SelectSequence: PUBLIC PROC [seq: Sequence, scene: SceneRef, selectClass: SelectionClass] = { outline: Outline _ GGOutline.OutlineOfTraj[seq.traj]; parts: SliceParts; seqD: OutlineDescriptor; IF GGSequence.IsEmpty[seq] THEN RETURN; parts _ GGOutline.PartsFromSequence[outline, seq]; seqD _ GGSlice.DescriptorFromParts[outline, parts]; SelectSlice[seqD, scene, selectClass]; }; SelectTraj: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] = { <> wholeSeq: Sequence; wholeSeq _ GGSequence.CreateComplete[traj]; SelectSequence[wholeSeq, scene, selectClass]; }; <<>> DuplicateSelections: PROC [scene: SceneRef, fromClass: SelectionClass, toClass: SelectionClass] = { sliceDescGen: GGSelect.SliceDescriptorGenerator; seqGen: SequenceGenerator; sliceDescGen _ SelectedSlices[scene, fromClass]; FOR sliceD: SliceDescriptor _ NextSliceDescriptor[sliceDescGen], NextSliceDescriptor[sliceDescGen] UNTIL sliceD = NIL DO SelectSlice[sliceD, scene, toClass]; ENDLOOP; seqGen _ SelectedSequences[scene, fromClass]; FOR seq: Sequence _ GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq = NIL DO SelectSequence[seq, scene, toClass]; ENDLOOP; }; DeselectAll: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] = { <> FOR sliceD: LIST OF SliceDescriptor _ ListSelected[scene, selectClass], sliceD.rest UNTIL sliceD = NIL DO <> NoDonkeyTail[sliceD.first.slice, selectClass]; ENDLOOP; SetSelectedList[scene, NIL, selectClass]; }; DeselectEntity: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] = { WITH entity SELECT FROM seq: Sequence => DeselectSequence[seq, scene, selectClass]; traj: Traj => DeselectTraj[traj, scene, selectClass]; slice: Slice => DeselectEntireSlice[slice, scene, selectClass]; sliceD: SliceDescriptor => DeselectSlice[sliceD.slice, sliceD.parts, scene, selectClass]; < DeselectEntireOutline[outline, scene, selectClass];>> < DeselectOutline[outlineD.slice, outlineD.parts, scene, selectClass];>> ENDCASE => ERROR; }; DeselectEntityAllClasses: PUBLIC PROC [entity: REF ANY, scene: SceneRef] = { DeselectEntity[entity, scene, normal]; DeselectEntity[entity, scene, active]; DeselectEntity[entity, scene, hot]; }; DeselectAllAllClasses: PUBLIC PROC [scene: SceneRef] = { DeselectAll[scene, normal]; DeselectAll[scene, active]; DeselectAll[scene, hot]; }; <> <> <> <> <> <> <> <> <<};>> <<};>> <<>> DeselectEntireSlice: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] = { <> sliceD: SliceDescriptor _ FindSelectedSlice[slice, scene, selectClass]; IF sliceD # NIL THEN { DeleteSelection[scene, sliceD, selectClass]; NoDonkeyTail[sliceD.slice, selectClass]; }; }; DeselectSlice: PUBLIC PROC [slice: Slice, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = { oldD, newD, tempD: SliceDescriptor; oldD _ FindSelectedSlice[slice, scene, selectClass]; IF oldD # NIL THEN { tempD _ GGSlice.DescriptorFromParts[slice, parts]; newD _ slice.class.differenceParts[oldD, tempD]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTail[oldD.slice, selectClass]; IF NOT slice.class.isEmptyParts[newD] THEN { IF selectClass = normal THEN newD _ slice.class.augmentParts[newD, selectClass]; AppendSelection[scene, newD, selectClass]; ChangeDonkeyTail[newD, selectClass]; }; }; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> DeselectSequence: PUBLIC PROC [seq: Sequence, scene: SceneRef, selectClass: SelectionClass] = { outline: Outline _ GGOutline.OutlineOfTraj[seq.traj]; seqParts: SliceParts _ GGOutline.PartsFromSequence[outline, seq]; DeselectSlice[outline, seqParts, scene, selectClass]; }; <> <> <> <> <> <> <<};>> <<};>> <<>> DeselectTraj: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] = { <> outline: Outline _ GGOutline.OutlineOfTraj[traj]; oldD, newD: OutlineDescriptor; oldD _ FindSelectedSlice[outline, scene, selectClass]; IF oldD # NIL THEN { newD _ GGOutline.RemoveTraj[oldD, traj]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTail[outline, selectClass]; IF NOT outline.class.isEmptyParts[newD] THEN { AppendSelection[scene, newD, selectClass]; ChangeDonkeyTail[newD, selectClass]; }; }; }; <<>> <> <<>> ReselectTraj: PUBLIC PROC [traj: Traj, trajEnd: TrajEnd, scene: SceneRef, extend: BOOL] RETURNS [newHot: Sequence] = { selSeq, newSeq: Sequence; selSeq _ FindSelectedSequence[traj, scene, normal]; <> IF selSeq # NIL THEN { newSeq _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.traj, scene, normal]; SelectSequence[newSeq, scene, normal]; }; <> selSeq _ FindSelectedSequence[traj, scene, hot]; IF selSeq # NIL THEN { newHot _ newSeq _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.traj, scene, hot]; SelectSequence[newSeq, scene, hot]; }; <> selSeq _ FindSelectedSequence[traj, scene, active]; IF selSeq # NIL THEN { ERROR; -- I don't think ReselectTraj should be used for active }; }; <> <<>> DeleteSelection: PROC [scene: SceneRef, entity: SliceDescriptor, selectClass: SelectionClass] = { <> SetSelectedList[scene, DRemove[entity, ListSelected[scene, selectClass]], selectClass]; }; ListSelected: PUBLIC PROC [scene: SceneRef, 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; }; <> <> <> <> <> <> <> <> <<};>> <> <<};>> <> <<>> <> <> < RETURN[slice.selectedInFull.normal];>> < RETURN[slice.selectedInFull.hot];>> < RETURN[slice.selectedInFull.active];>> < ERROR;>> <<};>> < {>> <> <> <> <> <> <> <<};>> < {>> <> <> <> <> <<};>> < ERROR;>> <<};>> <<>> IsSelectedInFull: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] RETURNS [BOOL] = { donkeyTail: SliceDescriptor _ SELECT selectClass FROM active => slice.activeSelectedParts, hot => slice.hotSelectedParts, normal => slice.normalSelectedParts, ENDCASE => ERROR; IF donkeyTail = NIL THEN RETURN[FALSE]; RETURN[slice.class.isCompleteParts[donkeyTail]]; }; IsSelectedInPart: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] RETURNS [BOOL] = { <> <<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.>> WITH entity SELECT FROM slice: Slice => { sliceD: SliceDescriptor; sliceD _ FindSelectedSlice[slice, scene, selectClass]; RETURN[sliceD # NIL]; }; < {>> <> <> <> <<};>> traj: Traj => { seq: Sequence; seq _ FindSelectedSequence[traj, scene, selectClass]; RETURN[seq # NIL]; }; seq: Sequence => { selSeq: Sequence; selSeq _ FindSelectedSequence[seq.traj, scene, selectClass]; IF selSeq = seq THEN RETURN[TRUE]; IF selSeq = NIL THEN RETURN[FALSE]; RETURN[GGSequence.Overlap[seq, selSeq]]; }; ENDCASE => ERROR; }; <<>> NoSelections: PUBLIC PROC [scene: SceneRef, 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; }; FindSelectedSequence: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] RETURNS [seq: Sequence] = { FOR sliceDList: LIST OF SliceDescriptor _ ListSelected[scene, selectClass], sliceDList.rest UNTIL sliceDList = NIL DO sliceD: SliceDescriptor _ sliceDList.first; seq _ IF sliceD.slice.class.type=$Outline THEN GGOutline.FindTrajInDescriptor[sliceD, traj] ELSE NIL; IF seq # NIL THEN RETURN[seq]; ENDLOOP; RETURN[NIL]; }; FindSequenceInList: PUBLIC PROC [traj: Traj, selectedList: LIST OF SliceDescriptor] RETURNS [seq: Sequence] = { FOR sliceDList: LIST OF SliceDescriptor _ selectedList, sliceDList.rest UNTIL sliceDList = NIL DO sliceD: SliceDescriptor _ sliceDList.first; seq _ IF sliceD.slice.class.type=$Outline THEN GGOutline.FindTrajInDescriptor[sliceD, traj] ELSE NIL; IF seq # NIL THEN RETURN[seq]; ENDLOOP; RETURN[NIL]; }; SelectedSequences: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [seqGen: SequenceGenerator] = { ptr, seqList: LIST OF Sequence; seqGen _ NEW[SequenceGeneratorObj]; [seqGen.list, ptr] _ GGUtility.StartSequenceList[]; FOR sliceDList: LIST OF SliceDescriptor _ ListSelected[scene, selectClass], sliceDList.rest UNTIL sliceDList = NIL DO IF sliceDList.first.slice.class.type=$Outline THEN { seqList _ GGOutline.SequencesOfOutline[sliceDList.first]; FOR list: LIST OF Sequence _ seqList, list.rest UNTIL list = NIL DO [seqGen.list, ptr] _ GGUtility.AddSequence[list.first, seqGen.list, ptr]; ENDLOOP; }; ENDLOOP; }; SelectedOutlines: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [outDGen: OutlineDescriptorGenerator] = { sliceD: OutlineDescriptor _ NIL; ptr: LIST OF OutlineDescriptor _ NIL; outDGen _ NEW[GGModelTypes.OutlineDescriptorGeneratorObj]; FOR sliceDList: LIST OF SliceDescriptor _ ListSelected[scene, selectClass], sliceDList.rest UNTIL sliceDList = NIL DO IF sliceDList.first.slice.class.type=$Outline THEN { [outDGen.list, ptr] _ AddSliceDescriptor[sliceDList.first, outDGen.list, ptr]; }; ENDLOOP; }; <> <