Salome HOME
7ab8db1f9a4bc76ac6c2471d0936e742cb2d0563
[modules/geom.git] / src / GEOMGUI / GEOMGUI_OCCSelector.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 // File   : GEOMGUI_OCCSelector.cxx
24 // Author : Alexander SOLOVYOV, Open CASCADE S.A.S. (alexander.solovyov@opencascade.com)
25 //
26 #include "GEOMGUI_OCCSelector.h"
27 #include "GEOM_Annotation.hxx"
28
29 #include <LightApp_DataSubOwner.h>
30
31 #include <OCCViewer_ViewModel.h>
32
33 #include <SUIT_Session.h>
34 #include <SUIT_ResourceMgr.h>
35 #include <SalomeApp_Study.h>
36 #include <SALOME_InteractiveObject.hxx>
37
38 #include <StdSelect_BRepOwner.hxx>
39 #include <SelectMgr_Selection.hxx>
40 #include <SelectMgr_EntityOwner.hxx>
41 #include <SelectMgr_IndexedMapOfOwner.hxx>
42 #include <SelectBasics_SensitiveEntity.hxx>
43
44 #include <AIS_Shape.hxx>
45 #include <AIS_ListOfInteractive.hxx>
46 #include <AIS_ListIteratorOfListOfInteractive.hxx>
47 #include <TopExp.hxx>
48 #include <TopTools_IndexedMapOfShape.hxx>
49 #include <TColStd_ListIteratorOfListOfInteger.hxx>
50 #include <TColStd_IndexedMapOfInteger.hxx>
51 #include <NCollection_DataMap.hxx>
52
53
54 //================================================================
55 // Function : GEOMGUI_OCCSelector
56 // Purpose  :
57 //================================================================
58 GEOMGUI_OCCSelector::GEOMGUI_OCCSelector( OCCViewer_Viewer* viewer, SUIT_SelectionMgr* mgr )
59 : LightApp_OCCSelector( viewer, mgr )
60 {
61 }
62
63 //================================================================
64 // Function : ~GEOMGUI_OCCSelector
65 // Purpose  :
66 //================================================================
67 GEOMGUI_OCCSelector::~GEOMGUI_OCCSelector()
68 {
69 }
70
71 //================================================================
72 // Function : getSelection
73 // Purpose  :
74 //================================================================
75 void GEOMGUI_OCCSelector::getSelection( SUIT_DataOwnerPtrList& aList ) const
76 {
77   OCCViewer_Viewer* vw = viewer();
78   if (!vw)
79     return;
80
81   Handle(AIS_InteractiveContext) ic = vw->getAISContext();
82
83   if (ic->HasOpenedContext())
84   {
85     TopoDS_Shape curBigShape;
86     TopTools_IndexedMapOfShape subShapes;
87
88     for (ic->InitSelected(); ic->MoreSelected(); ic->NextSelected())
89     {
90       Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(ic->SelectedOwner());
91       if (anOwner.IsNull())
92         continue;
93
94       Handle(AIS_InteractiveObject) io = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
95
96       QString entryStr = entry(io);
97       int index = -1;
98
99       if (anOwner->ComesFromDecomposition()) // == Local Selection
100       {
101         TopoDS_Shape subShape = anOwner->Shape();
102         Handle(AIS_Shape) aisShape = Handle(AIS_Shape)::DownCast(io);
103         if (!aisShape.IsNull())
104         {
105           TopoDS_Shape bigShape = aisShape->Shape();
106
107           if (!bigShape.IsEqual(curBigShape))
108           {
109             curBigShape = bigShape;
110             subShapes.Clear();
111             TopExp::MapShapes(bigShape, subShapes);
112           }
113           index = subShapes.FindIndex(subShape);
114         }
115       }
116
117       if (!entryStr.isEmpty())
118       {
119         Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast(io->GetOwner()); 
120         LightApp_DataOwner* owner;
121         if (index > -1) // Local Selection
122           owner = new LightApp_DataSubOwner (entryStr, index);
123         else if ( !anIO.IsNull() ) // Global Selection
124           owner = new LightApp_DataOwner( anIO );
125
126         aList.append(SUIT_DataOwnerPtr(owner));
127       }
128     }
129   }
130   else
131   {
132     for (ic->InitCurrent(); ic->MoreCurrent(); ic->NextCurrent())
133     {
134       Handle(AIS_InteractiveObject) io = ic->Current();
135
136       QString entryStr = entry( io );
137
138       if ( !entryStr.isEmpty() )
139       {
140         Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast(io->GetOwner()); 
141         if ( !anIO.IsNull() ) {
142           LightApp_DataOwner* owner = new LightApp_DataOwner( anIO );
143           aList.append( SUIT_DataOwnerPtr( owner ) );
144         }
145       }
146     }
147   }
148
149   // add externally selected objects
150   SUIT_DataOwnerPtrList::const_iterator anExtIter;
151   for (anExtIter = mySelectedExternals.begin(); anExtIter != mySelectedExternals.end(); anExtIter++)
152   {
153     aList.append(*anExtIter);
154   }
155 }
156
157 //================================================================
158 // Function : getEntityOwners
159 // Purpose  :
160 //================================================================
161 static void getEntityOwners( const Handle(AIS_InteractiveObject)& theObj,
162                              const Handle(AIS_InteractiveContext)& theIC,
163                              SelectMgr_IndexedMapOfOwner& theMap )
164 {
165   if ( theObj.IsNull() || theIC.IsNull() )
166     return;
167
168   TColStd_ListOfInteger modes;
169   theIC->ActivatedModes( theObj, modes );
170
171   TColStd_ListIteratorOfListOfInteger itr( modes );
172   for (; itr.More(); itr.Next() ) {
173     int m = itr.Value();
174     if ( !theObj->HasSelection( m ) )
175       continue;
176
177     Handle(SelectMgr_Selection) sel = theObj->Selection( m );
178
179     for ( sel->Init(); sel->More(); sel->Next() ) {
180       const Handle(SelectMgr_SensitiveEntity) aHSenEntity = sel->Sensitive();
181       if( aHSenEntity.IsNull() )
182         continue;
183
184       Handle(SelectBasics_SensitiveEntity) entity = aHSenEntity->BaseSensitive();
185       if ( entity.IsNull() )
186         continue;
187
188       Handle(SelectMgr_EntityOwner) owner =
189         Handle(SelectMgr_EntityOwner)::DownCast(entity->OwnerId());
190       if ( !owner.IsNull() )
191         theMap.Add( owner );
192     }
193   }
194 }
195
196 //================================================================
197 // Function : setSelection
198 // Purpose  :
199 //================================================================
200 void GEOMGUI_OCCSelector::setSelection( const SUIT_DataOwnerPtrList& aList )
201 {
202   OCCViewer_Viewer* vw = viewer();
203   if ( !vw || !vw->isSelectionEnabled())
204     return;
205
206   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
207   bool anAutoBringToFront = aResourceMgr->booleanValue( "Geometry", "auto_bring_to_front", false );
208
209   Handle(AIS_InteractiveContext) ic = vw->getAISContext();
210
211   // "entry - list_of_int" map for LOCAL selection
212   NCollection_DataMap<TCollection_AsciiString, TColStd_IndexedMapOfInteger> indexesMap;
213
214   QMap<QString,int> globalSelMap; // only Key=entry from this map is used.  value(int) is NOT used at all.
215   SelectMgr_IndexedMapOfOwner ownersmap; // map of owners to be selected
216
217   AIS_ListOfInteractive aDispList;
218   ic->DisplayedObjects( aDispList );
219
220   // build a map of data owner indexes to be selected.
221   // "entry - to - list_of_ids" map
222   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(); itr != aList.end(); ++itr )
223   {
224     const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
225     if ( subOwner )
226     {
227       QString entry = subOwner->entry();
228       if ( indexesMap.IsBound( TCollection_AsciiString(entry.toLatin1().data())))
229       {
230         TColStd_IndexedMapOfInteger& subIndexes = indexesMap.ChangeFind(entry.toLatin1().data());
231         subIndexes.Add( subOwner->index() );
232         //indexesMap.replace( entry, subIndexes );
233       }
234       else
235       {
236         TColStd_IndexedMapOfInteger subIndexes;
237         subIndexes.Add( subOwner->index() );
238         indexesMap.Bind(entry.toLatin1().data(), subIndexes);
239       }
240     }
241     else // the owner is NOT a sub owner, maybe it is a DataOwner == GLOBAL selection
242     {
243       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
244       if ( owner )
245       {
246         SalomeApp_Study* appStudy =
247           dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
248         QString anEntry = appStudy->referencedToEntry( owner->entry() );
249
250         globalSelMap[anEntry] = 1;
251       }
252     }
253   }
254
255   // get all owners.  Fill "entry - list_of_owners" map.
256   for ( AIS_ListIteratorOfListOfInteractive it( aDispList ); it.More(); it.Next() )
257   {
258     Handle(AIS_InteractiveObject) io = it.Value();
259     QString entryStr = entry( io );
260     if ( !entryStr.isEmpty() )
261     {
262       //EntryToListOfOwnerMap entryOwnersMap; // "entry - list_of_owners" map.  temporary use.
263       SelectMgr_IndexedMapOfOwner owners;
264       getEntityOwners( io, ic, owners ); // get all owners
265
266       int i, n = owners.Extent();
267
268       // 1. Prepare map of shapes for local selection
269       TopTools_IndexedMapOfShape aMapOfShapes;
270       bool isLocal = false;
271
272       Handle(StdSelect_BRepOwner) anOwner;
273       for (i = 1; i <= n && !isLocal; i++)
274       {
275         anOwner = Handle(StdSelect_BRepOwner)::DownCast(owners( i ));
276         if (!anOwner.IsNull() && anOwner->HasShape())
277         {
278           if (anOwner->ComesFromDecomposition() || !globalSelMap.contains(entryStr))
279           {
280             // has a local selection
281             Handle(AIS_Shape) aisShape = Handle(AIS_Shape)::DownCast( io );
282             if (!aisShape.IsNull() && indexesMap.IsBound(entryStr.toLatin1().data()))
283             {
284               isLocal = true;
285               TopoDS_Shape shape = aisShape->Shape();
286               aMapOfShapes.Clear();
287               TopExp::MapShapes(shape, aMapOfShapes);
288             }
289           }
290         }
291       }
292
293       // 2. Process all owners
294       for (i = 1; i <= n; i++)
295       {
296         anOwner = Handle(StdSelect_BRepOwner)::DownCast(owners( i ));
297
298         if ( anOwner.IsNull() || !anOwner->HasShape() ) {
299           if ( globalSelMap.contains( entryStr ) ) {
300             Handle(GEOM_Annotation::GEOM_AnnotationOwner) anAnnotationOwner =
301                                Handle(GEOM_Annotation::GEOM_AnnotationOwner)::DownCast(owners( i ));
302             if ( !anAnnotationOwner.IsNull() ) {
303               ownersmap.Add( anAnnotationOwner );
304             }
305           }
306           continue;
307         }
308
309         // GLOBAL selection
310         if ( !anOwner->ComesFromDecomposition() && globalSelMap.contains( entryStr ) )
311         {
312           ownersmap.Add( anOwner );
313           globalSelMap[entryStr]++;
314         }
315         // LOCAL selection
316         else
317         {
318           if (isLocal)
319           {
320             const TColStd_IndexedMapOfInteger& subIndexes =
321               indexesMap.ChangeFind(entryStr.toLatin1().data());
322
323             const TopoDS_Shape& aSubShape = anOwner->Shape();
324             int aSubShapeId = aMapOfShapes.FindIndex( aSubShape );
325
326             // check if the "sub_shape_index" is found in the "map of indexes for this entry",
327             // which was passes in the parameter
328             if ( subIndexes.Contains( aSubShapeId ) )
329             {
330               ownersmap.Add( anOwner );
331             }
332           }
333         } // end of LOCAL selection
334       } // end of for(owners)
335     } // end of if(entry)
336   } // end of for(AIS_all_ios)
337
338   vw->unHighlightAll( false );
339
340   // DO the selection
341   int i = 1, n = ownersmap.Extent();
342   bool isAutoHilight = ic->AutomaticHilight();
343   ic->SetAutomaticHilight(Standard_False); //Bug 17269: for better performance
344   for  (; i <= n; i++)
345   {
346     Handle(SelectMgr_EntityOwner) owner = ownersmap( i );
347     if ( owner->State() )
348       continue;
349
350     if ( ic->HasOpenedContext() )
351       ic->AddOrRemoveSelected( owner, false );
352     else
353       ic->AddOrRemoveSelected( Handle(AIS_InteractiveObject)::DownCast(owner->Selectable()), false );
354   }
355
356   ic->SetAutomaticHilight(isAutoHilight); //Bug 17269: restore mode
357
358   //rnv: In case Automatic Bring To Front viewer will be updated later
359   if(!anAutoBringToFront) {
360     if (n < 3000)
361       ic->HilightSelected(Standard_True);
362     else
363       vw->update();
364   }
365
366   // fill extra selected
367   mySelectedExternals.clear();
368   for ( SUIT_DataOwnerPtrList::const_iterator itr2 = aList.begin(); itr2 != aList.end(); ++itr2 )
369   {
370     const LightApp_DataSubOwner* subOwner =
371       dynamic_cast<const LightApp_DataSubOwner*>( (*itr2).operator->() );
372     if ( !subOwner )
373     {
374       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr2).operator->() );
375       if ( owner )
376       {
377         SalomeApp_Study* appStudy =
378           dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
379         QString anEntry = appStudy->referencedToEntry( owner->entry() );
380         if (globalSelMap[anEntry] == 1) mySelectedExternals.append(*itr2);
381       }
382     }
383   }
384 }