Salome HOME
Merge branch V7_3_1_BR
[modules/hexablock.git] / src / HEXABLOCKGUI / HEXABLOCKGUI_OCCSelector.cxx
1 // Copyright (C) 2013-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : HEXABLOCKGUI_OCCSelector.cxx
21 //
22
23 #include "HEXABLOCKGUI_OCCSelector.h"
24 #include "HEXABLOCKGUI_SalomeTools.hxx"
25
26 #include <LightApp_DataSubOwner.h>
27
28 #include <OCCViewer_ViewModel.h>
29
30 #include <SUIT_Session.h>
31 #include <SalomeApp_Study.h>
32 #include <SALOME_InteractiveObject.hxx>
33
34 #include <StdSelect_BRepOwner.hxx>
35 #include <SelectMgr_Selection.hxx>
36 #include <SelectMgr_EntityOwner.hxx>
37 #include <SelectMgr_IndexedMapOfOwner.hxx>
38 #include <SelectBasics_SensitiveEntity.hxx>
39
40 #include <AIS_Shape.hxx>
41 #include <AIS_ListOfInteractive.hxx>
42 #include <AIS_ListIteratorOfListOfInteractive.hxx>
43 #include <TopExp.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TColStd_ListIteratorOfListOfInteger.hxx>
46 #include <TColStd_IndexedMapOfInteger.hxx>
47 #include <NCollection_DataMap.hxx>
48
49
50 using namespace HEXABLOCK::GUI;
51
52 //================================================================
53 // Function : HEXABLOCKGUI_OCCSelector
54 // Purpose  :
55 //================================================================
56 HEXABLOCKGUI_OCCSelector::HEXABLOCKGUI_OCCSelector( OCCViewer_Viewer* viewer, SUIT_SelectionMgr* mgr )
57 : LightApp_OCCSelector( viewer, mgr )
58 {
59 }
60
61 //================================================================
62 // Function : ~HEXABLOCKGUI_OCCSelector
63 // Purpose  :
64 //================================================================
65 HEXABLOCKGUI_OCCSelector::~HEXABLOCKGUI_OCCSelector()
66 {
67 }
68
69 //================================================================
70 // Function : getSelection
71 // Purpose  :
72 //================================================================
73 void HEXABLOCKGUI_OCCSelector::getSelection( SUIT_DataOwnerPtrList& aList ) const
74 {
75   OCCViewer_Viewer* vw = viewer();
76   if (!vw)
77     return;
78
79   Handle(AIS_InteractiveContext) ic = vw->getAISContext();
80
81   if (ic->HasOpenedContext())
82   {
83     TopoDS_Shape curBigShape;
84     TopTools_IndexedMapOfShape subShapes;
85
86     for (ic->InitSelected(); ic->MoreSelected(); ic->NextSelected())
87     {
88       Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(ic->SelectedOwner());
89       if (anOwner.IsNull())
90         continue;
91
92       Handle(AIS_InteractiveObject) io = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
93
94       QString entryStr = entry(io);
95       int index = -1;
96
97       if (anOwner->ComesFromDecomposition()) // == Local Selection
98       {
99         TopoDS_Shape subShape = anOwner->Shape();
100         Handle(AIS_Shape) aisShape = Handle(AIS_Shape)::DownCast(io);
101         if (!aisShape.IsNull())
102         {
103           TopoDS_Shape bigShape = aisShape->Shape();
104
105           if (!bigShape.IsEqual(curBigShape))
106           {
107             curBigShape = bigShape;
108             subShapes.Clear();
109             TopExp::MapShapes(bigShape, subShapes);
110           }
111           index = subShapes.FindIndex(subShape);
112         }
113       }
114
115       if (!entryStr.isEmpty())
116       {
117         Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast(io->GetOwner()); 
118         LightApp_DataOwner* owner;
119         if (index > -1) // Local Selection
120           owner = new LightApp_DataSubOwner (entryStr, index);
121         else if ( !anIO.IsNull() ) // Global Selection
122           owner = new LightApp_DataOwner( anIO );
123
124         aList.append(SUIT_DataOwnerPtr(owner));
125       }
126     }
127   }
128   else
129   {
130     for (ic->InitCurrent(); ic->MoreCurrent(); ic->NextCurrent())
131     {
132       Handle(AIS_InteractiveObject) io = ic->Current();
133
134       QString entryStr = entry( io );
135
136       if ( !entryStr.isEmpty() )
137       {
138         Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast(io->GetOwner()); 
139         if ( !anIO.IsNull() ) {
140           LightApp_DataOwner* owner = new LightApp_DataOwner( anIO );
141           aList.append( SUIT_DataOwnerPtr( owner ) );
142         }
143       }
144     }
145   }
146
147   // add externally selected objects
148   SUIT_DataOwnerPtrList::const_iterator anExtIter, itEnd;
149   for (anExtIter = mySelectedExternals.begin(), itEnd = mySelectedExternals.end(); anExtIter != itEnd; anExtIter++)
150   {
151     aList.append(*anExtIter);
152   }
153 }
154
155 //================================================================
156 // Function : setSelection
157 // Purpose  :
158 //================================================================
159 void HEXABLOCKGUI_OCCSelector::setSelection( const SUIT_DataOwnerPtrList& aList )
160 {
161   OCCViewer_Viewer* vw = viewer();
162   if ( !vw )
163     return;
164
165   Handle(AIS_InteractiveContext) ic = vw->getAISContext();
166
167   // "entry - list_of_int" map for LOCAL selection
168   NCollection_DataMap<TCollection_AsciiString, TColStd_IndexedMapOfInteger> indexesMap;
169
170   QMap<QString,int> globalSelMap; // only Key=entry from this map is used.  value(int) is NOT used at all.
171   SelectMgr_IndexedMapOfOwner ownersmap; // map of owners to be selected
172
173   AIS_ListOfInteractive aDispList;
174   ic->DisplayedObjects( aDispList );
175
176   // build a map of data owner indexes to be selected.
177   // "entry - to - list_of_ids" map
178   for ( SUIT_DataOwnerPtrList::const_iterator itr = aList.begin(), itEnd = aList.end(); itr != itEnd; ++itr )
179   {
180     const LightApp_DataSubOwner* subOwner = dynamic_cast<const LightApp_DataSubOwner*>( (*itr).operator->() );
181     if ( subOwner )
182     {
183       QString entry = subOwner->entry();
184       if ( indexesMap.IsBound( TCollection_AsciiString(entry.toLatin1().data())))
185       {
186         TColStd_IndexedMapOfInteger& subIndexes = indexesMap.ChangeFind(entry.toLatin1().data());
187         subIndexes.Add( subOwner->index() );
188         //indexesMap.replace( entry, subIndexes );
189       }
190       else
191       {
192         TColStd_IndexedMapOfInteger subIndexes;
193         subIndexes.Add( subOwner->index() );
194         indexesMap.Bind(entry.toLatin1().data(), subIndexes);
195       }
196     }
197     else // the owner is NOT a sub owner, maybe it is a DataOwner == GLOBAL selection
198     {
199       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr).operator->() );
200       if ( owner )
201       {
202         SalomeApp_Study* appStudy =
203           dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
204         QString anEntry = appStudy->referencedToEntry( owner->entry() );
205
206         globalSelMap[anEntry] = 1;
207       }
208     }
209   }
210
211   // get all owners.  Fill "entry - list_of_owners" map.
212   for ( AIS_ListIteratorOfListOfInteractive it( aDispList ); it.More(); it.Next() )
213   {
214     Handle(AIS_InteractiveObject) io = it.Value();
215     QString entryStr = entry( io );
216     if ( !entryStr.isEmpty() )
217     {
218       //EntryToListOfOwnerMap entryOwnersMap; // "entry - list_of_owners" map.  temporary use.
219       SelectMgr_IndexedMapOfOwner owners;
220       getEntityOwners( io, ic, owners ); // get all owners
221
222       int i, n = owners.Extent();
223
224       // 1. Prepare map of shapes for local selection
225       TopTools_IndexedMapOfShape aMapOfShapes;
226       bool isLocal = false;
227
228       Handle(StdSelect_BRepOwner) anOwner;
229       for (i = 1; i <= n && !isLocal; i++)
230       {
231         anOwner = Handle(StdSelect_BRepOwner)::DownCast(owners( i ));
232         if (!anOwner.IsNull() && anOwner->HasShape())
233         {
234           if (anOwner->ComesFromDecomposition() || !globalSelMap.contains(entryStr))
235           {
236             // has a local selection
237             Handle(AIS_Shape) aisShape = Handle(AIS_Shape)::DownCast( io );
238             if (!aisShape.IsNull() && indexesMap.IsBound(entryStr.toLatin1().data()))
239             {
240               isLocal = true;
241               TopoDS_Shape shape = aisShape->Shape();
242               aMapOfShapes.Clear();
243               TopExp::MapShapes(shape, aMapOfShapes);
244             }
245           }
246         }
247       }
248
249       // 2. Process all owners
250       for (i = 1; i <= n; i++)
251       {
252         anOwner = Handle(StdSelect_BRepOwner)::DownCast(owners( i ));
253
254         if ( anOwner.IsNull() || !anOwner->HasShape() )
255           continue;
256
257         // GLOBAL selection
258         if ( !anOwner->ComesFromDecomposition() && globalSelMap.contains( entryStr ) )
259         {
260           ownersmap.Add( anOwner );
261           globalSelMap[entryStr]++;
262         }
263         // LOCAL selection
264         else
265         {
266           if (isLocal)
267           {
268             const TColStd_IndexedMapOfInteger& subIndexes =
269               indexesMap.ChangeFind(entryStr.toLatin1().data());
270
271             const TopoDS_Shape& aSubShape = anOwner->Shape();
272             int aSubShapeId = aMapOfShapes.FindIndex( aSubShape );
273
274             // check if the "sub_shape_index" is found in the "map of indexes for this entry",
275             // which was passes in the parameter
276             if ( subIndexes.Contains( aSubShapeId ) )
277             {
278               ownersmap.Add( anOwner );
279             }
280           }
281         } // end of LOCAL selection
282       } // end of for(owners)
283     } // end of if(entry)
284   } // end of for(AIS_all_ios)
285
286   vw->unHighlightAll( false );
287
288   // DO the selection
289   int i = 1, n = ownersmap.Extent();
290   bool isAutoHilight = ic->AutomaticHilight();
291   ic->SetAutomaticHilight(Standard_False); //Bug 17269: for better performance
292   for  (; i <= n; i++)
293   {
294     Handle(SelectMgr_EntityOwner) owner = ownersmap( i );
295     if ( owner->State() )
296       continue;
297
298     if ( ic->HasOpenedContext() )
299       ic->AddOrRemoveSelected( owner, false );
300     else
301       ic->AddOrRemoveSelected( Handle(AIS_InteractiveObject)::DownCast(owner->Selectable()), false );
302   }
303   ic->SetAutomaticHilight(isAutoHilight); //Bug 17269: restore mode
304   if (n < 3000)
305     ic->HilightSelected(/*updateviewer*/Standard_True);
306   else
307     vw->update();
308
309   // fill extra selected
310   mySelectedExternals.clear();
311   for ( SUIT_DataOwnerPtrList::const_iterator itr2 = aList.begin(), itEnd = aList.end(); itr2 != itEnd; ++itr2 )
312   {
313     const LightApp_DataSubOwner* subOwner =
314       dynamic_cast<const LightApp_DataSubOwner*>( (*itr2).operator->() );
315     if ( !subOwner )
316     {
317       const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*itr2).operator->() );
318       if ( owner )
319       {
320         SalomeApp_Study* appStudy =
321           dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
322         QString anEntry = appStudy->referencedToEntry( owner->entry() );
323         if (globalSelMap[anEntry] == 1) mySelectedExternals.append(*itr2);
324       }
325     }
326   }
327 }