1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
24 // File : SALOME_Selection.cxx
25 // Author : Nicolas REJNERI
27 #include "SVTK_SelectorDef.h"
29 #include <VTKViewer_Filter.h>
31 #include "SALOME_Actor.h"
33 #include <SUIT_Session.h>
34 #include <SUIT_ResourceMgr.h>
36 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
37 #include <TColStd_IndexedMapOfInteger.hxx>
39 #include <vtkCallbackCommand.h>
40 #include <vtkActorCollection.h>
41 #include <vtkCellPicker.h>
45 \return new SVTK_Selector
51 return new SVTK_SelectorDef();
59 myPicker(vtkPicker::New()),
60 myCellPicker(vtkCellPicker::New())
62 mySelectionMode = ActorSelection;
63 myDynamicPreselection = true;
64 myPreselectionEnabled = true;
65 mySelectionEnabled = true;
68 myCellPicker->Delete();
80 To invoke selectionChanged signals
86 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
90 To invoke selectionChanged signals
96 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
100 To change current Selection_Mode (as outside effect, it invokes selectionChange signal)
104 ::SetSelectionMode(Selection_Mode theMode)
106 if(mySelectionMode != theMode){
107 mySelectionMode = theMode;
108 myMapIOSubIndex.clear();
109 this->EndPickCallback();
122 myMapIOSubIndex.clear();
126 \return true if the SALOME_InteractiveObject presents into selection
130 ::IsSelected(const Handle(SALOME_InteractiveObject)& theIO) const
132 return !theIO.IsNull() && (myIObjects.find(theIO) != myIObjects.end());
136 \return true if the SALOME_Actor presents into selection
140 ::IsSelected(SALOME_Actor* theActor) const
142 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
143 return IsSelected(anIO) && myIO2Actors.find(anIO) != myIO2Actors.end();
147 \return corresponding SALOME_Actor for SALOME_InteractiveObject
148 \param theIO - SALOME_InteractiveObject
152 ::GetActor(const Handle(SALOME_InteractiveObject)& theIO) const
154 TIO2Actors::const_iterator anIter = myIO2Actors.find(theIO);
155 if(anIter != myIO2Actors.end())
156 return anIter->second.GetPointer();
161 Adds SALOME_InteractiveObject into selection
162 \param theIO - SALOME_InteractiveObject
166 ::AddIObject(const Handle(SALOME_InteractiveObject)& theIO)
168 if(!IsSelected(theIO)){
169 myIObjects.insert(theIO);
176 Adds SALOME_Actor into selection
177 \param theActor - SALOME_Actor
181 ::AddIObject(SALOME_Actor* theActor)
183 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
185 bool anIsIOBound = IsSelected(anIO);
187 myIObjects.insert(anIO);
189 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
191 myIO2Actors[anIO] = theActor;
193 return !anIsIOBound || !anIsActorBound;
197 Removes SALOME_InteractiveObject from selection
198 \param theIO - SALOME_InteractiveObject
202 ::RemoveIObject(const Handle(SALOME_InteractiveObject)& theIO)
204 bool anIsIOBound = myIObjects.find(theIO) != myIObjects.end();
206 myIObjects.erase(theIO);
207 myIO2Actors.erase(theIO);
208 myMapIOSubIndex.erase(theIO);
214 Removes SALOME_Actor from selection
215 \param theActor - SALOME_Actor
219 ::RemoveIObject(SALOME_Actor* theActor)
221 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
223 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
225 myIO2Actors.erase(anIO);
227 return RemoveIObject(anIO) || anIsActorBound;
231 \return list of all SALOME_InteractiveObject presenting in selection
235 ::StoredIObjects() const
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);
243 return myIObjectList;
247 \return number of selected objects
251 ::IObjectCount() const
253 return myIObjects.size();
257 \return true if the SALOME_InteractiveObject has a subselection
258 \param theIO - SALOME_InteractiveObject
262 ::HasIndex( const Handle(SALOME_InteractiveObject)& theIO) const
264 return myMapIOSubIndex.find(theIO) != myMapIOSubIndex.end();
268 Gets indices of subselection for SALOME_InteractiveObject
269 \param theIO - SALOME_InteractiveObject
273 ::GetIndex( const Handle(SALOME_InteractiveObject)& theIO,
274 TColStd_IndexedMapOfInteger& theIndex)
276 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
277 if(anIter != myMapIOSubIndex.end())
278 theIndex = anIter->second.myMap;
284 \return true if the index presents in subselection
285 \param theIO - SALOME_InteractiveObject
286 \param theIndex - index
290 ::IsIndexSelected(const Handle(SALOME_InteractiveObject)& theIO,
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;
302 static bool removeIndex(TColStd_IndexedMapOfInteger& theMapIndex, const int theIndex)
304 int anId = theMapIndex.FindIndex(theIndex); // i==0 if Index is not in the MapIndex
306 // only the last key can be removed
307 int aLastId = theMapIndex.FindKey(theMapIndex.Extent());
309 theMapIndex.RemoveLast();
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 );
318 theMapIndex = aNewMap;
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
332 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
333 const TColStd_IndexedMapOfInteger& theIndices,
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;
342 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
347 for(int i = 1, iEnd = theIndices.Extent(); i <= iEnd; i++)
348 aMapIndex.Add(theIndices(i));
350 if(aMapIndex.IsEmpty()) {
351 myMapIOSubIndex.erase(theIO);
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
367 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
368 const TColStd_MapOfInteger& theIndices,
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;
377 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
382 TColStd_MapIteratorOfMapOfInteger anIter(theIndices);
383 for(; anIter.More(); anIter.Next())
384 aMapIndex.Add(anIter.Key());
386 if(aMapIndex.IsEmpty()) {
387 myMapIOSubIndex.erase(theIO);
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
403 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
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;
413 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
415 bool anIsConatains = aMapIndex.Contains( theIndex ) == Standard_True;
417 removeIndex( aMapIndex, theIndex );
419 if ( !theIsModeShift )
422 if ( !anIsConatains )
423 aMapIndex.Add( theIndex );
425 if ( aMapIndex.IsEmpty() )
426 myMapIOSubIndex.erase( theIO );
433 Removes index of subselection for SALOME_InteractiveObject
434 \param theIO - SALOME_InteractiveObject
435 \param theIndex - index
439 ::RemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
442 if(IsIndexSelected(theIO,theIndex)){
443 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
444 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
445 removeIndex(aMapIndex,theIndex);
450 Clears all indices of subselection
456 myMapIOSubIndex.clear();
460 To apply a filter on the selection
461 \param theFilter - new filter
465 ::SetFilter(const Handle(VTKViewer_Filter)& theFilter)
467 myFilters.insert(TFilters::value_type(theFilter->GetId(),theFilter));
471 \return true if filter with given number is applyed
472 \param theId - filter id
476 ::IsFilterPresent(const TFilterID theId) const
478 return myFilters.find(theId) != myFilters.end();
482 To remove a filter from the selection
483 \param theId - filter id
487 ::RemoveFilter(const TFilterID theId)
489 if(IsFilterPresent(theId))
490 myFilters.erase(theId);
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
501 ::IsValid(SALOME_Actor* theActor,
502 const TFilterID theId,
503 const bool theIsNode) const
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))
516 \return filter by it's id
517 \param theId - filter id
519 Handle(VTKViewer_Filter)
521 ::GetFilter(const TFilterID theId) const
523 TFilters::const_iterator anIter = myFilters.find(theId);
524 if(anIter != myFilters.end()){
525 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
528 return Handle(VTKViewer_Filter)();
533 ::Pick(const SVTK_SelectionEvent* theEvent, vtkRenderer* theRenderer) const
535 vtkActorCollection* aListActors = NULL;
537 if ( GetDynamicPreSelection() ) {
538 myCellPicker->Pick(theEvent->myX,
543 aListActors = myCellPicker->GetActors();
546 if ( !aListActors || !aListActors->GetNumberOfItems() ) {
547 myPicker->Pick(theEvent->myX,
551 aListActors = myPicker->GetActors();
559 ::SetTolerance(const double& theTolerance)
561 myPicker->SetTolerance(theTolerance);
562 myCellPicker->SetTolerance(theTolerance);
567 ::SetDynamicPreSelection( bool theIsDynPreselect )
569 myDynamicPreselection = theIsDynPreselect;
574 ::GetDynamicPreSelection() const
576 return myDynamicPreselection;
581 ::SetPreSelectionEnabled( bool theEnabled )
583 myPreselectionEnabled = theEnabled;
588 ::IsPreSelectionEnabled() const
590 return mySelectionEnabled && myPreselectionEnabled;
595 ::SetSelectionEnabled( bool theEnabled )
597 mySelectionEnabled = theEnabled;
602 ::IsSelectionEnabled() const
604 return mySelectionEnabled;