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