Salome HOME
78c94989d531f51a6a8eb21682456e7e94d828cd
[modules/gui.git] / src / SVTK / SVTK_Selector.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : SALOME_Selection.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29
30 #include "SVTK_SelectorDef.h"
31
32 #include "SALOME_Actor.h"
33
34 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
35 #include <TColStd_IndexedMapOfInteger.hxx>
36
37 #include <vtkCallbackCommand.h>
38
39 /*!
40   \return new SVTK_Selector
41 */
42 SVTK_Selector* 
43 SVTK_Selector
44 ::New()
45 {
46   return new SVTK_SelectorDef();
47 }
48
49 /*!
50   Default constructor
51 */
52 SVTK_SelectorDef
53 ::SVTK_SelectorDef()
54 {
55   mySelectionMode = ActorSelection;
56 }
57
58 /*!
59   Destructor
60 */
61 SVTK_SelectorDef
62 ::~SVTK_SelectorDef()
63 {
64 }
65
66 /*!
67   To invoke selectionChanged signals
68 */
69 void 
70 SVTK_SelectorDef
71 ::StartPickCallback()
72 {
73   this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
74 }
75
76 /*!
77   To invoke selectionChanged signals
78 */
79 void 
80 SVTK_SelectorDef
81 ::EndPickCallback()
82 {
83   this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
84 }
85
86 /*!
87   To change current Selection_Mode (as outside effect, it invokes selectionChange signal)
88 */
89 void 
90 SVTK_SelectorDef
91 ::SetSelectionMode(Selection_Mode theMode)
92 {
93   if(mySelectionMode != theMode){
94     mySelectionMode = theMode;
95     myMapIOSubIndex.clear();
96     this->EndPickCallback();
97   }
98 }
99
100 /*!
101   Clear selection
102 */
103 void 
104 SVTK_SelectorDef
105 ::ClearIObjects() 
106 {
107   myIO2Actors.clear();
108   myIObjects.clear();
109   myMapIOSubIndex.clear();
110 }
111
112 /*!
113   \return true if the SALOME_InteractiveObject presents into selection
114 */
115 bool
116 SVTK_SelectorDef
117 ::IsSelected(const Handle(SALOME_InteractiveObject)& theIO) const
118 {
119   return !theIO.IsNull() && (myIObjects.find(theIO) != myIObjects.end());
120 }
121
122 /*!
123   \return true if the SALOME_Actor presents into selection
124 */
125 bool
126 SVTK_SelectorDef
127 ::IsSelected(SALOME_Actor* theActor) const
128 {
129   const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
130   return IsSelected(anIO) && myIO2Actors.find(anIO) != myIO2Actors.end();
131 }
132
133 /*!
134   \return corresponding SALOME_Actor for SALOME_InteractiveObject
135   \param theIO - SALOME_InteractiveObject
136 */
137 SALOME_Actor*
138 SVTK_SelectorDef
139 ::GetActor(const Handle(SALOME_InteractiveObject)& theIO) const
140 {
141   TIO2Actors::const_iterator anIter = myIO2Actors.find(theIO);
142   if(anIter != myIO2Actors.end())
143     return anIter->second.GetPointer();
144   return NULL;
145 }
146
147 /*!
148   Adds SALOME_InteractiveObject into selection
149   \param theIO - SALOME_InteractiveObject
150 */
151 bool 
152 SVTK_SelectorDef
153 ::AddIObject(const Handle(SALOME_InteractiveObject)& theIO) 
154 {
155   if(!IsSelected(theIO)){
156     myIObjects.insert(theIO);
157     return true;
158   }
159   return false;
160 }
161
162 /*!
163   Adds SALOME_Actor into selection
164   \param theActor - SALOME_Actor
165 */
166 bool 
167 SVTK_SelectorDef
168 ::AddIObject(SALOME_Actor* theActor) 
169 {
170   const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
171
172   bool anIsIOBound = IsSelected(anIO);
173   if(!anIsIOBound)
174     myIObjects.insert(anIO);
175
176   bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
177   if(!anIsActorBound)
178     myIO2Actors[anIO] = theActor;
179   
180   return !anIsIOBound || !anIsActorBound;
181 }
182
183 /*!
184   Removes SALOME_InteractiveObject from selection
185   \param theIO - SALOME_InteractiveObject
186 */
187 bool 
188 SVTK_SelectorDef
189 ::RemoveIObject(const Handle(SALOME_InteractiveObject)& theIO) 
190 {
191   bool anIsIOBound = myIObjects.find(theIO) != myIObjects.end();
192
193   myIObjects.erase(theIO);
194   myIO2Actors.erase(theIO);
195   myMapIOSubIndex.erase(theIO);
196
197   return anIsIOBound;
198 }
199
200 /*!
201   Removes SALOME_Actor from selection
202   \param theActor - SALOME_Actor
203 */
204 bool 
205 SVTK_SelectorDef
206 ::RemoveIObject(SALOME_Actor* theActor) 
207 {
208   const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
209
210   bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
211   if(anIsActorBound)
212     myIO2Actors.erase(anIO);
213
214   return RemoveIObject(anIO) || anIsActorBound;
215 }
216
217 /*!
218   \return list of all SALOME_InteractiveObject presenting in selection
219 */
220 const SALOME_ListIO& 
221 SVTK_SelectorDef
222 ::StoredIObjects() const
223 {
224   myIObjectList.Clear();
225   TIObjects::const_iterator anIter = myIObjects.begin();
226   TIObjects::const_iterator anIterEnd = myIObjects.end();
227   for(; anIter != anIterEnd; anIter++)
228     myIObjectList.Append(*anIter);
229
230   return myIObjectList;
231 }
232
233 /*!
234   \return number of selected objects
235 */
236 int
237 SVTK_SelectorDef
238 ::IObjectCount() const
239 {
240   return myIObjects.size();
241 }
242
243 /*!
244   \return true if the SALOME_InteractiveObject has a subselection
245   \param theIO - SALOME_InteractiveObject
246 */
247 bool 
248 SVTK_SelectorDef
249 ::HasIndex( const Handle(SALOME_InteractiveObject)& theIO) const
250 {
251   return myMapIOSubIndex.find(theIO) != myMapIOSubIndex.end();
252 }
253
254 /*!
255   Gets indices of subselection for SALOME_InteractiveObject
256   \param theIO - SALOME_InteractiveObject
257 */
258 void 
259 SVTK_SelectorDef
260 ::GetIndex( const Handle(SALOME_InteractiveObject)& theIO, 
261             TColStd_IndexedMapOfInteger& theIndex)
262 {
263   TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
264   if(anIter != myMapIOSubIndex.end())
265     theIndex = anIter->second.myMap;
266   else
267     theIndex.Clear();
268 }
269
270 /*!
271   \return true if the index presents in subselection 
272   \param theIO - SALOME_InteractiveObject
273   \param theIndex - index
274 */
275 bool
276 SVTK_SelectorDef
277 ::IsIndexSelected(const Handle(SALOME_InteractiveObject)& theIO, 
278                   int theIndex) const
279 {
280   TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
281   if(anIter != myMapIOSubIndex.end()){
282     const TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
283     return aMapIndex.Contains(theIndex);
284   }
285
286   return false;
287 }
288
289 static 
290 bool
291 removeIndex(TColStd_IndexedMapOfInteger& theMapIndex,
292             const int theIndex)
293 {
294   int anId = theMapIndex.FindIndex(theIndex); // i==0 if Index is not in the MapIndex
295   if(anId){
296     // only the last key can be removed
297     int aLastId = theMapIndex.FindKey(theMapIndex.Extent());
298     if(aLastId == anId)
299       theMapIndex.RemoveLast();
300     else{
301       TColStd_IndexedMapOfInteger aNewMap;
302       aNewMap.ReSize(theMapIndex.Extent()-1);
303       for(int j = 1; j <= theMapIndex.Extent(); j++){
304         int anIndex = theMapIndex(j);
305         if ( anIndex != theIndex )
306           aNewMap.Add( anIndex );
307       }
308       theMapIndex = aNewMap;
309     }
310   }
311   return anId;
312 }
313
314 /*!
315   Changes indices of subselection for SALOME_InteractiveObject
316   \param theIO - SALOME_InteractiveObject
317   \param theIndices - indices
318   \param theIsModeShift - if it is false, then map will be cleared before indices are added
319 */
320 bool
321 SVTK_SelectorDef
322 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO, 
323                     const TColStd_IndexedMapOfInteger& theIndices, 
324                     bool theIsModeShift)
325 {
326   TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
327   if(aMapIter == myMapIOSubIndex.end()){
328     TIndexedMapOfInteger anEmpty;
329     aMapIter = myMapIOSubIndex.
330       insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
331   }
332   TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
333
334   if(!theIsModeShift)
335     aMapIndex.Clear();
336   
337   for(int i = 1, iEnd = theIndices.Extent(); i <= iEnd; i++)
338     aMapIndex.Add(theIndices(i));
339   
340   if(aMapIndex.IsEmpty()) {
341     myMapIOSubIndex.erase(theIO);
342     return false;
343   }
344
345   return true;
346 }
347
348
349 /*!
350   Changes indices of subselection for SALOME_InteractiveObject
351   \param theIO - SALOME_InteractiveObject
352   \param theIndices - indices
353   \param theIsModeShift - if it is false, then map will be cleared before indices are added
354 */
355 bool
356 SVTK_SelectorDef
357 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO, 
358                     const TColStd_MapOfInteger& theIndices, 
359                     bool theIsModeShift)
360 {
361   TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
362   if(aMapIter == myMapIOSubIndex.end()){
363     TIndexedMapOfInteger anEmpty;
364     aMapIter = myMapIOSubIndex.
365       insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
366   }
367   TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
368
369   if(!theIsModeShift)
370     aMapIndex.Clear();
371   
372   TColStd_MapIteratorOfMapOfInteger anIter(theIndices);
373   for(; anIter.More(); anIter.Next())
374     aMapIndex.Add(anIter.Key());
375   
376   if(aMapIndex.IsEmpty()) {
377     myMapIOSubIndex.erase(theIO);
378     return false;
379   }
380
381   return true;
382 }
383
384
385 /*!
386   Changes indices of subselection for SALOME_InteractiveObject
387   \param theIO - SALOME_InteractiveObject
388   \param theIndex - index
389   \param theIsModeShift - if it is false, then map will be cleared before indices are added
390 */
391 bool 
392 SVTK_SelectorDef
393 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO, 
394                     int theIndex, 
395                     bool theIsModeShift)
396 {
397   TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
398   if(anIter == myMapIOSubIndex.end()){
399     TIndexedMapOfInteger anEmpty;
400     anIter = myMapIOSubIndex.
401       insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
402   }
403   TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
404
405   bool anIsConatains = aMapIndex.Contains(theIndex);
406   if(anIsConatains)
407     removeIndex(aMapIndex,theIndex);
408   
409   if(!theIsModeShift)
410     aMapIndex.Clear();
411   
412   if(!anIsConatains)
413     aMapIndex.Add( theIndex );
414
415   if( aMapIndex.IsEmpty())
416     myMapIOSubIndex.erase(theIO);
417
418   return false;
419 }
420
421
422 /*!
423   Removes index of subselection for SALOME_InteractiveObject
424   \param theIO - SALOME_InteractiveObject
425   \param theIndex - index
426 */
427 void
428 SVTK_SelectorDef
429 ::RemoveIndex( const Handle(SALOME_InteractiveObject)& theIO, 
430                int theIndex)
431 {
432   if(IsIndexSelected(theIO,theIndex)){
433     TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
434     TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
435     removeIndex(aMapIndex,theIndex);
436   }
437 }
438
439 /*!
440   Clears all indices of subselection
441 */
442 void 
443 SVTK_SelectorDef
444 ::ClearIndex()
445 {
446   myMapIOSubIndex.clear();  
447 }
448
449 /*!
450   To apply a filter on the selection
451   \param theFilter - new filter
452 */
453 void
454 SVTK_SelectorDef
455 ::SetFilter(const Handle(VTKViewer_Filter)& theFilter)
456 {
457   myFilters.insert(TFilters::value_type(theFilter->GetId(),theFilter));
458 }
459
460 /*!
461   \return true if filter with given number is applyed
462   \param theId - filter id
463 */
464 bool
465 SVTK_SelectorDef
466 ::IsFilterPresent(const TFilterID theId) const
467 {
468   return myFilters.find(theId) != myFilters.end();
469 }
470
471 /*!
472   To remove a filter from the selection
473   \param theId - filter id
474 */
475 void  
476 SVTK_SelectorDef
477 ::RemoveFilter(const TFilterID theId)
478 {
479   if(IsFilterPresent(theId))
480     myFilters.erase(theId);
481 }
482
483 /*!
484   \return true if the index satisfy installed filters
485   \param theActor - actor
486   \param theId - filter id
487   \param theIsNode - whether it is node
488 */
489 bool
490 SVTK_SelectorDef
491 ::IsValid(SALOME_Actor* theActor,
492           const TFilterID theId,
493           const bool theIsNode) const
494 {
495   TFilters::const_iterator anIter = myFilters.begin();
496   for(; anIter != myFilters.end(); ++anIter){
497     const Handle(VTKViewer_Filter)& aFilter = anIter->second;
498     if(theIsNode == aFilter->IsNodeFilter() &&
499        !aFilter->IsValid(theActor,theId))
500       return false;
501   }
502   return true;
503 }
504
505 /*!
506   \return filter by it's id
507   \param theId - filter id
508 */
509 Handle(VTKViewer_Filter) 
510 SVTK_SelectorDef
511 ::GetFilter(const TFilterID theId) const
512 {
513   TFilters::const_iterator anIter = myFilters.find(theId);
514   if(anIter != myFilters.end()){
515     const Handle(VTKViewer_Filter)& aFilter = anIter->second;
516     return aFilter;
517   }
518   return Handle(VTKViewer_Filter)();
519 }
520