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