1 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
3 // Copyright (C) 2003 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
24 // File : SALOME_Selection.cxx
25 // Author : Nicolas REJNERI
30 #include "SVTK_SelectorDef.h"
32 #include "SALOME_Actor.h"
34 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
35 #include <TColStd_IndexedMapOfInteger.hxx>
37 #include <vtkCallbackCommand.h>
38 #include <vtkActorCollection.h>
39 #include <vtkCellPicker.h>
43 Find first SALOME_Actor from the end of actors collection
47 GetLastSALOMEActor(vtkActorCollection* theCollection)
50 for (int i = theCollection->GetNumberOfItems() - 1; i >= 0; i--) {
51 if (SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theCollection->GetItemAsObject(i)))
61 \return new SVTK_Selector
67 return new SVTK_SelectorDef();
75 myPicker(vtkPicker::New()),
76 myCellPicker(vtkCellPicker::New())
78 mySelectionMode = ActorSelection;
81 myCellPicker->Delete();
93 To invoke selectionChanged signals
99 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
103 To invoke selectionChanged signals
109 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
113 To change current Selection_Mode (as outside effect, it invokes selectionChange signal)
117 ::SetSelectionMode(Selection_Mode theMode)
119 if(mySelectionMode != theMode){
120 mySelectionMode = theMode;
121 myMapIOSubIndex.clear();
122 this->EndPickCallback();
135 myMapIOSubIndex.clear();
139 \return true if the SALOME_InteractiveObject presents into selection
143 ::IsSelected(const Handle(SALOME_InteractiveObject)& theIO) const
145 return !theIO.IsNull() && (myIObjects.find(theIO) != myIObjects.end());
149 \return true if the SALOME_Actor presents into selection
153 ::IsSelected(SALOME_Actor* theActor) const
155 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
156 return IsSelected(anIO) && myIO2Actors.find(anIO) != myIO2Actors.end();
160 \return corresponding SALOME_Actor for SALOME_InteractiveObject
161 \param theIO - SALOME_InteractiveObject
165 ::GetActor(const Handle(SALOME_InteractiveObject)& theIO) const
167 TIO2Actors::const_iterator anIter = myIO2Actors.find(theIO);
168 if(anIter != myIO2Actors.end())
169 return anIter->second.GetPointer();
174 Adds SALOME_InteractiveObject into selection
175 \param theIO - SALOME_InteractiveObject
179 ::AddIObject(const Handle(SALOME_InteractiveObject)& theIO)
181 if(!IsSelected(theIO)){
182 myIObjects.insert(theIO);
189 Adds SALOME_Actor into selection
190 \param theActor - SALOME_Actor
194 ::AddIObject(SALOME_Actor* theActor)
196 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
198 bool anIsIOBound = IsSelected(anIO);
200 myIObjects.insert(anIO);
202 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
204 myIO2Actors[anIO] = theActor;
206 return !anIsIOBound || !anIsActorBound;
210 Removes SALOME_InteractiveObject from selection
211 \param theIO - SALOME_InteractiveObject
215 ::RemoveIObject(const Handle(SALOME_InteractiveObject)& theIO)
217 bool anIsIOBound = myIObjects.find(theIO) != myIObjects.end();
219 myIObjects.erase(theIO);
220 myIO2Actors.erase(theIO);
221 myMapIOSubIndex.erase(theIO);
227 Removes SALOME_Actor from selection
228 \param theActor - SALOME_Actor
232 ::RemoveIObject(SALOME_Actor* theActor)
234 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
236 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
238 myIO2Actors.erase(anIO);
240 return RemoveIObject(anIO) || anIsActorBound;
244 \return list of all SALOME_InteractiveObject presenting in selection
248 ::StoredIObjects() const
250 myIObjectList.Clear();
251 TIObjects::const_iterator anIter = myIObjects.begin();
252 TIObjects::const_iterator anIterEnd = myIObjects.end();
253 for(; anIter != anIterEnd; anIter++)
254 myIObjectList.Append(*anIter);
256 return myIObjectList;
260 \return number of selected objects
264 ::IObjectCount() const
266 return myIObjects.size();
270 \return true if the SALOME_InteractiveObject has a subselection
271 \param theIO - SALOME_InteractiveObject
275 ::HasIndex( const Handle(SALOME_InteractiveObject)& theIO) const
277 return myMapIOSubIndex.find(theIO) != myMapIOSubIndex.end();
281 Gets indices of subselection for SALOME_InteractiveObject
282 \param theIO - SALOME_InteractiveObject
286 ::GetIndex( const Handle(SALOME_InteractiveObject)& theIO,
287 TColStd_IndexedMapOfInteger& theIndex)
289 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
290 if(anIter != myMapIOSubIndex.end())
291 theIndex = anIter->second.myMap;
297 \return true if the index presents in subselection
298 \param theIO - SALOME_InteractiveObject
299 \param theIndex - index
303 ::IsIndexSelected(const Handle(SALOME_InteractiveObject)& theIO,
306 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
307 if(anIter != myMapIOSubIndex.end()){
308 const TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
309 return aMapIndex.Contains( theIndex ) == Standard_True;
315 static bool removeIndex(TColStd_IndexedMapOfInteger& theMapIndex, const int theIndex)
317 int anId = theMapIndex.FindIndex(theIndex); // i==0 if Index is not in the MapIndex
319 // only the last key can be removed
320 int aLastId = theMapIndex.FindKey(theMapIndex.Extent());
322 theMapIndex.RemoveLast();
324 TColStd_IndexedMapOfInteger aNewMap;
325 aNewMap.ReSize(theMapIndex.Extent()-1);
326 for(int j = 1; j <= theMapIndex.Extent(); j++){
327 int anIndex = theMapIndex(j);
328 if ( anIndex != theIndex )
329 aNewMap.Add( anIndex );
331 theMapIndex = aNewMap;
338 Changes indices of subselection for SALOME_InteractiveObject
339 \param theIO - SALOME_InteractiveObject
340 \param theIndices - indices
341 \param theIsModeShift - if it is false, then map will be cleared before indices are added
345 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
346 const TColStd_IndexedMapOfInteger& theIndices,
349 TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
350 if(aMapIter == myMapIOSubIndex.end()){
351 TIndexedMapOfInteger anEmpty;
352 aMapIter = myMapIOSubIndex.
353 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
355 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
360 for(int i = 1, iEnd = theIndices.Extent(); i <= iEnd; i++)
361 aMapIndex.Add(theIndices(i));
363 if(aMapIndex.IsEmpty()) {
364 myMapIOSubIndex.erase(theIO);
373 Changes indices of subselection for SALOME_InteractiveObject
374 \param theIO - SALOME_InteractiveObject
375 \param theIndices - indices
376 \param theIsModeShift - if it is false, then map will be cleared before indices are added
380 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
381 const TColStd_MapOfInteger& theIndices,
384 TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
385 if(aMapIter == myMapIOSubIndex.end()){
386 TIndexedMapOfInteger anEmpty;
387 aMapIter = myMapIOSubIndex.
388 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
390 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
395 TColStd_MapIteratorOfMapOfInteger anIter(theIndices);
396 for(; anIter.More(); anIter.Next())
397 aMapIndex.Add(anIter.Key());
399 if(aMapIndex.IsEmpty()) {
400 myMapIOSubIndex.erase(theIO);
409 Changes indices of subselection for SALOME_InteractiveObject
410 \param theIO - SALOME_InteractiveObject
411 \param theIndex - index
412 \param theIsModeShift - if it is false, then map will be cleared before indices are added
416 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
420 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
421 if(anIter == myMapIOSubIndex.end()){
422 TIndexedMapOfInteger anEmpty;
423 anIter = myMapIOSubIndex.
424 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
426 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
428 bool anIsConatains = aMapIndex.Contains( theIndex ) == Standard_True;
430 removeIndex( aMapIndex, theIndex );
432 if ( !theIsModeShift )
435 if ( !anIsConatains )
436 aMapIndex.Add( theIndex );
438 if ( aMapIndex.IsEmpty() )
439 myMapIOSubIndex.erase( theIO );
446 Removes index of subselection for SALOME_InteractiveObject
447 \param theIO - SALOME_InteractiveObject
448 \param theIndex - index
452 ::RemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
455 if(IsIndexSelected(theIO,theIndex)){
456 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
457 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
458 removeIndex(aMapIndex,theIndex);
463 Clears all indices of subselection
469 myMapIOSubIndex.clear();
473 To apply a filter on the selection
474 \param theFilter - new filter
478 ::SetFilter(const Handle(VTKViewer_Filter)& theFilter)
480 myFilters.insert(TFilters::value_type(theFilter->GetId(),theFilter));
484 \return true if filter with given number is applyed
485 \param theId - filter id
489 ::IsFilterPresent(const TFilterID theId) const
491 return myFilters.find(theId) != myFilters.end();
495 To remove a filter from the selection
496 \param theId - filter id
500 ::RemoveFilter(const TFilterID theId)
502 if(IsFilterPresent(theId))
503 myFilters.erase(theId);
507 \return true if the index satisfy installed filters
508 \param theActor - actor
509 \param theId - filter id
510 \param theIsNode - whether it is node
514 ::IsValid(SALOME_Actor* theActor,
515 const TFilterID theId,
516 const bool theIsNode) const
518 TFilters::const_iterator anIter = myFilters.begin();
519 for(; anIter != myFilters.end(); ++anIter){
520 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
521 if(theIsNode == aFilter->IsNodeFilter() &&
522 !aFilter->IsValid(theActor,theId))
529 \return filter by it's id
530 \param theId - filter id
532 Handle(VTKViewer_Filter)
534 ::GetFilter(const TFilterID theId) const
536 TFilters::const_iterator anIter = myFilters.find(theId);
537 if(anIter != myFilters.end()){
538 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
541 return Handle(VTKViewer_Filter)();
546 ::Pick(const SVTK_SelectionEvent* theEvent, vtkRenderer* theRenderer) const
548 myCellPicker->Pick(theEvent->myX,
553 vtkActorCollection* aListActors = myCellPicker->GetActors();
554 SALOME_Actor* anActor = GetLastSALOMEActor(aListActors);
557 myPicker->Pick(theEvent->myX,
561 aListActors = myPicker->GetActors();
562 anActor = GetLastSALOMEActor(aListActors);
570 ::SetTolerance(const double& theTolerance)
572 myPicker->SetTolerance(theTolerance);
573 myCellPicker->SetTolerance(theTolerance);