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