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;
66 myCellPicker->Delete();
78 To invoke selectionChanged signals
84 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
88 To invoke selectionChanged signals
94 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
98 To change current Selection_Mode (as outside effect, it invokes selectionChange signal)
102 ::SetSelectionMode(Selection_Mode theMode)
104 if(mySelectionMode != theMode){
105 mySelectionMode = theMode;
106 myMapIOSubIndex.clear();
107 this->EndPickCallback();
120 myMapIOSubIndex.clear();
124 \return true if the SALOME_InteractiveObject presents into selection
128 ::IsSelected(const Handle(SALOME_InteractiveObject)& theIO) const
130 return !theIO.IsNull() && (myIObjects.find(theIO) != myIObjects.end());
134 \return true if the SALOME_Actor presents into selection
138 ::IsSelected(SALOME_Actor* theActor) const
140 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
141 return IsSelected(anIO) && myIO2Actors.find(anIO) != myIO2Actors.end();
145 \return corresponding SALOME_Actor for SALOME_InteractiveObject
146 \param theIO - SALOME_InteractiveObject
150 ::GetActor(const Handle(SALOME_InteractiveObject)& theIO) const
152 TIO2Actors::const_iterator anIter = myIO2Actors.find(theIO);
153 if(anIter != myIO2Actors.end())
154 return anIter->second.GetPointer();
159 Adds SALOME_InteractiveObject into selection
160 \param theIO - SALOME_InteractiveObject
164 ::AddIObject(const Handle(SALOME_InteractiveObject)& theIO)
166 if(!IsSelected(theIO)){
167 myIObjects.insert(theIO);
174 Adds SALOME_Actor into selection
175 \param theActor - SALOME_Actor
179 ::AddIObject(SALOME_Actor* theActor)
181 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
183 bool anIsIOBound = IsSelected(anIO);
185 myIObjects.insert(anIO);
187 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
189 myIO2Actors[anIO] = theActor;
191 return !anIsIOBound || !anIsActorBound;
195 Removes SALOME_InteractiveObject from selection
196 \param theIO - SALOME_InteractiveObject
200 ::RemoveIObject(const Handle(SALOME_InteractiveObject)& theIO)
202 bool anIsIOBound = myIObjects.find(theIO) != myIObjects.end();
204 myIObjects.erase(theIO);
205 myIO2Actors.erase(theIO);
206 myMapIOSubIndex.erase(theIO);
212 Removes SALOME_Actor from selection
213 \param theActor - SALOME_Actor
217 ::RemoveIObject(SALOME_Actor* theActor)
219 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
221 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
223 myIO2Actors.erase(anIO);
225 return RemoveIObject(anIO) || anIsActorBound;
229 \return list of all SALOME_InteractiveObject presenting in selection
233 ::StoredIObjects() const
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);
241 return myIObjectList;
245 \return number of selected objects
249 ::IObjectCount() const
251 return myIObjects.size();
255 \return true if the SALOME_InteractiveObject has a subselection
256 \param theIO - SALOME_InteractiveObject
260 ::HasIndex( const Handle(SALOME_InteractiveObject)& theIO) const
262 return myMapIOSubIndex.find(theIO) != myMapIOSubIndex.end();
266 Gets indices of subselection for SALOME_InteractiveObject
267 \param theIO - SALOME_InteractiveObject
271 ::GetIndex( const Handle(SALOME_InteractiveObject)& theIO,
272 TColStd_IndexedMapOfInteger& theIndex)
274 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
275 if(anIter != myMapIOSubIndex.end())
276 theIndex = anIter->second.myMap;
282 \return true if the index presents in subselection
283 \param theIO - SALOME_InteractiveObject
284 \param theIndex - index
288 ::IsIndexSelected(const Handle(SALOME_InteractiveObject)& theIO,
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;
300 static bool removeIndex(TColStd_IndexedMapOfInteger& theMapIndex, const int theIndex)
302 int anId = theMapIndex.FindIndex(theIndex); // i==0 if Index is not in the MapIndex
304 // only the last key can be removed
305 int aLastId = theMapIndex.FindKey(theMapIndex.Extent());
307 theMapIndex.RemoveLast();
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 );
316 theMapIndex = aNewMap;
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
330 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
331 const TColStd_IndexedMapOfInteger& theIndices,
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;
340 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
345 for(int i = 1, iEnd = theIndices.Extent(); i <= iEnd; i++)
346 aMapIndex.Add(theIndices(i));
348 if(aMapIndex.IsEmpty()) {
349 myMapIOSubIndex.erase(theIO);
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
365 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
366 const TColStd_MapOfInteger& theIndices,
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;
375 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
380 TColStd_MapIteratorOfMapOfInteger anIter(theIndices);
381 for(; anIter.More(); anIter.Next())
382 aMapIndex.Add(anIter.Key());
384 if(aMapIndex.IsEmpty()) {
385 myMapIOSubIndex.erase(theIO);
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
401 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
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;
411 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
413 bool anIsConatains = aMapIndex.Contains( theIndex ) == Standard_True;
415 removeIndex( aMapIndex, theIndex );
417 if ( !theIsModeShift )
420 if ( !anIsConatains )
421 aMapIndex.Add( theIndex );
423 if ( aMapIndex.IsEmpty() )
424 myMapIOSubIndex.erase( theIO );
431 Removes index of subselection for SALOME_InteractiveObject
432 \param theIO - SALOME_InteractiveObject
433 \param theIndex - index
437 ::RemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
440 if(IsIndexSelected(theIO,theIndex)){
441 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
442 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
443 removeIndex(aMapIndex,theIndex);
448 Clears all indices of subselection
454 myMapIOSubIndex.clear();
458 To apply a filter on the selection
459 \param theFilter - new filter
463 ::SetFilter(const Handle(VTKViewer_Filter)& theFilter)
465 myFilters.insert(TFilters::value_type(theFilter->GetId(),theFilter));
469 \return true if filter with given number is applyed
470 \param theId - filter id
474 ::IsFilterPresent(const TFilterID theId) const
476 return myFilters.find(theId) != myFilters.end();
480 To remove a filter from the selection
481 \param theId - filter id
485 ::RemoveFilter(const TFilterID theId)
487 if(IsFilterPresent(theId))
488 myFilters.erase(theId);
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
499 ::IsValid(SALOME_Actor* theActor,
500 const TFilterID theId,
501 const bool theIsNode) const
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))
514 \return filter by it's id
515 \param theId - filter id
517 Handle(VTKViewer_Filter)
519 ::GetFilter(const TFilterID theId) const
521 TFilters::const_iterator anIter = myFilters.find(theId);
522 if(anIter != myFilters.end()){
523 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
526 return Handle(VTKViewer_Filter)();
531 ::Pick(const SVTK_SelectionEvent* theEvent, vtkRenderer* theRenderer) const
533 vtkActorCollection* aListActors = NULL;
535 if ( GetDynamicPreSelection() ) {
536 myCellPicker->Pick(theEvent->myX,
541 aListActors = myCellPicker->GetActors();
544 if ( !aListActors || !aListActors->GetNumberOfItems() ) {
545 myPicker->Pick(theEvent->myX,
549 aListActors = myPicker->GetActors();
557 ::SetTolerance(const double& theTolerance)
559 myPicker->SetTolerance(theTolerance);
560 myCellPicker->SetTolerance(theTolerance);
565 ::SetDynamicPreSelection( bool theIsDynPreselect )
567 myDynamicPreselection = theIsDynPreselect;
572 ::GetDynamicPreSelection() const
574 return myDynamicPreselection;