Replacing french comments by english one
[occt.git] / src / AIS / AIS_Selection.cxx
1 #include <AIS_Selection.ixx>
2 #include <TCollection_AsciiString.hxx>
3 #include <TColStd_SequenceOfTransient.hxx>
4
5 #define BUC60953   // SAV_050701 : the array of selected objects has always the same length
6                    // independently of number of objects selected. Thus, if there were selected
7                    // more than MaxSizeOfResult objects we have got an exception.
8                    // 
9                    // Moreover, Select method was optimized a little bit.
10                    // Now it checks the state of incoming owner. If the state is 0
11                    // there is no searching for object in <myresult> array.
12
13 #define OCC138
14
15 #define OCC189     //SAV: 18//03/02 array was replaced with list.
16
17 #define OCC1039    //SAV: 25/11/02 clearing selected objects if any on the AIS_Selection remove.
18
19 #define USE_MAP    //san : 18/04/03 USE_MAP - additional datamap is used to speed up access 
20                    //to certain owners in <myresult> list
21
22 #ifdef BUC60953
23 #include <SelectMgr_EntityOwner.hxx>
24 #endif
25
26 #ifdef OCC138      //VTN Avoding infinit loop in AddOrRemoveSelected and AddOrRemoveCurrentObject methods.
27 #include <AIS_InteractiveObject.hxx>
28 #endif
29
30 #ifndef USE_MAP
31 #define MaxSizeOfResult 10000
32 #else
33 #define MaxSizeOfResult 100000
34 #endif
35
36 static void AIS_Sel_CurrentSelection (Handle(AIS_Selection)& InputSel)     
37 {
38   static Handle(AIS_Selection) theCurrentSelection;
39   if(!InputSel.IsNull())
40     theCurrentSelection = InputSel;
41   else
42     InputSel = theCurrentSelection;
43 }
44
45 static TColStd_SequenceOfTransient&  AIS_Sel_GetSelections()
46 {
47   static TColStd_SequenceOfTransient Selections;
48   return Selections;
49 }
50
51 //=======================================================================
52 //function : AIS_Selection
53 //purpose  : 
54 //=======================================================================
55 AIS_Selection::AIS_Selection(const Standard_CString aName) :
56 myName(TCollection_AsciiString(aName)),
57 mycuri(0), 
58 #if !defined USE_MAP && !defined OCC189
59 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
60 #endif
61 myNb(0)
62 {
63 #ifdef USE_MAP 
64   myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
65 #endif
66 }
67
68 //=======================================================================
69 //function : CreateSelection
70 //purpose  : 
71 //=======================================================================
72 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
73
74   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
75   if(!S.IsNull())
76     return Standard_False;
77   S = new AIS_Selection(aName);
78   AIS_Sel_GetSelections().Prepend(S);
79   AIS_Sel_CurrentSelection(S);
80   return Standard_True;
81 }
82
83
84 //=======================================================================
85 //function : Selection
86 //purpose  : 
87 //=======================================================================
88 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName) 
89 {
90   Handle(AIS_Selection) S;
91   if(AIS_Sel_GetSelections().IsEmpty()) return S;
92   
93   Handle(Standard_Transient) curobj;
94   Handle(AIS_Selection) Sel;
95 //  Standard_Boolean found(Standard_False);
96   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
97     curobj = AIS_Sel_GetSelections().Value(I);
98     Sel = *((Handle(AIS_Selection)*)&curobj);
99     if(Sel->myName.IsEqual(aName))
100       return Sel;
101   }
102   
103   return S;
104 }
105
106 //=======================================================================
107 //function : Find
108 //purpose  : 
109 //=======================================================================
110 Standard_Boolean AIS_Selection::Find(const Standard_CString aName) 
111 {
112   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
113   return !S.IsNull();
114 }
115
116 //=======================================================================
117 //function : SetCurrentSelection
118 //purpose  : 
119 //=======================================================================
120 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName) 
121 {  
122   AIS_Selection::CreateSelection(aName); 
123
124
125   Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
126   AIS_Sel_CurrentSelection ( anAISSelection ) ;
127   return Standard_True;
128 }
129
130 //=======================================================================
131 //function : Select
132 //purpose  : 
133 //=======================================================================
134 void AIS_Selection::Select() 
135 {
136   Handle(AIS_Selection) S;
137   AIS_Sel_CurrentSelection (S);
138   if(!S.IsNull()){
139     S->myNb=0;
140 #if defined OCC189 || defined USE_MAP
141     S->myresult.Clear();
142 #ifdef USE_MAP
143     S->myResultMap.Clear();
144 #endif
145 #endif
146   }
147 }
148
149 //=======================================================================
150 //function : CurrentSelection
151 //purpose  : 
152 //=======================================================================
153 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
154   Handle(AIS_Selection) S;
155   AIS_Sel_CurrentSelection (S);
156   return S;
157 }
158 //=======================================================================
159 //function : Select
160 //purpose  : 
161 //=======================================================================
162 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject) 
163 {
164   Handle(AIS_Selection) S;
165   AIS_Sel_CurrentSelection (S);
166   if(S.IsNull()) return AIS_SS_NotDone;
167   Handle(AIS_InteractiveObject) anAISObj;
168   Handle(SelectMgr_EntityOwner) owner = Handle(SelectMgr_EntityOwner)::DownCast( anObject );
169   if ( owner.IsNull() )
170     anAISObj = Handle(AIS_InteractiveObject)::DownCast( anObject );
171 #ifndef OCC189
172   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
173   
174   Standard_Integer Found(-1);
175   Standard_Integer i ;
176
177 #ifdef BUC60953
178   
179   Standard_Boolean selected = Standard_False;
180   if ( !owner.IsNull() )
181     selected = owner->State() != 0;
182 #ifdef OCC138
183   else if(!anAISObj.IsNull())
184     selected = anAISObj->State();
185   }
186 #endif
187
188   if ( selected ) // looking up index of object
189 #endif
190
191   for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
192     if(arr(i)==anObject)
193       Found=i;
194   }
195   // If it is not inside, it is added...
196
197 #ifdef BUC60953
198   if ( !selected || Found == -1 ) {
199 #else
200   if(Found==-1){
201 #endif  
202     if((S->myNb)+1>arr.Length()){
203       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
204       for(i=arr.Lower();i<=S->myNb;i++){
205         const Handle(Standard_Transient)& T = S->myresult->Value(i);
206         NiouTab->SetValue(i,T);
207       }
208 #ifdef BUC60953
209       S->myresult = NiouTab;
210 #endif
211     }
212     (S->myNb)++;
213     S->myresult->SetValue(S->myNb,anObject);
214     return AIS_SS_Added;
215   }
216   // it was inside and it is removed...
217   for(i=Found;i<=S->myNb;i++)
218     arr(i)=arr(i+1);
219   S->myNb--;
220 #elif !defined USE_MAP //OCC189
221   AIS_NListTransient::Iterator anIter ( S->myresult );
222   for ( ; anIter.More(); anIter.Next() )
223     if ( anIter.Value() == anObject ) {
224       S->myresult.Remove( anIter );
225       return AIS_SS_Removed;
226     }
227       
228   S->myresult.Append( anObject );
229   return AIS_SS_Added;
230 #else //USE_MAP
231   if ( S->myResultMap.IsBound( anObject ) ){
232     AIS_NListTransient::Iterator aListIter = S->myResultMap.Find( anObject );
233 //skt-----------------------------------------------------------------
234     if( S->myIterator == aListIter )
235         if( S->myIterator.More() )
236             S->myIterator.Next();
237         else
238             S->myIterator = AIS_NListTransient::Iterator();
239 //--------------------------------------------------------------------
240 #ifdef BUC60953
241     // In the mode of advanced mesh selection only one owner is created
242     // for all selection modes. It is necessary to check the current detected
243     // entity and remove the owner from map only if the detected entity is
244     // the same as previous selected (IsForcedHilight call)
245     if( !anAISObj.IsNull() || ( !owner.IsNull() && !owner->IsForcedHilight() ) )
246     {
247 #endif  
248       S->myresult.Remove( aListIter );
249       S->myResultMap.UnBind( anObject );
250     
251       // update list iterator for next object in <myresult> list if any
252       if ( aListIter.More() ){
253         const Handle(Standard_Transient)& aNextObject = aListIter.Value();
254         if ( S->myResultMap.IsBound( aNextObject ) )
255           S->myResultMap( aNextObject ) = aListIter;
256         else
257           S->myResultMap.Bind( aNextObject, aListIter );
258       }
259       return AIS_SS_Removed;
260     }
261     else
262       return AIS_SS_Added;
263   }
264   
265   AIS_NListTransient::Iterator aListIter;
266   S->myresult.Append( anObject, aListIter );
267   S->myResultMap.Bind( anObject, aListIter );
268   return AIS_SS_Added;
269 #endif //USE_MAP
270   return AIS_SS_Removed;
271   
272 }
273
274 //=======================================================================
275 //function : AddSelect
276 //purpose  : Always add int the selection
277 //=======================================================================
278 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject) 
279 {
280   Handle(AIS_Selection) S;
281   AIS_Sel_CurrentSelection (S);
282   if(S.IsNull()) return AIS_SS_NotDone;
283
284 #ifndef OCC189
285   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
286   Standard_Integer i;
287   if((S->myNb)+1>arr.Length()){
288       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
289       for(i=arr.Lower();i<=S->myNb;i++){
290         const Handle(Standard_Transient)& T = S->myresult->Value(i);
291         NiouTab->SetValue(i,T);
292       }
293       S->myresult = NiouTab;
294   }
295   (S->myNb)++;
296   S->myresult->SetValue(S->myNb,anObject);
297 #elif !defined USE_MAP //OCC189
298   S->myresult.Append( anObject );
299 #else //USE_MAP
300   if ( S->myResultMap.IsBound( anObject ) )
301     return AIS_SS_NotDone;
302       
303   AIS_NListTransient::Iterator aListIter;
304   S->myresult.Append( anObject, aListIter );
305   S->myResultMap.Bind( anObject, aListIter );
306 #endif
307   return AIS_SS_Added;
308 }
309
310
311 //=======================================================================
312 //function : ClearAndSelect
313 //purpose  : 
314 //=======================================================================
315
316 void AIS_Selection::ClearAndSelect(const Handle(Standard_Transient)& anObject) {
317   Handle(AIS_Selection) S;
318   AIS_Sel_CurrentSelection (S);
319   if(S.IsNull()) return;
320   
321   Select();
322   Select(anObject);
323
324 }
325
326
327 //=======================================================================
328 //function : Extent
329 //purpose  : 
330 //=======================================================================
331 Standard_Integer AIS_Selection::Extent() {
332   Handle(AIS_Selection) S;
333   AIS_Sel_CurrentSelection (S);
334 #if !defined OCC189 && !defined USE_MAP
335   return S->myNb;
336 #else
337   return S->myresult.Extent();
338 #endif
339 }
340
341 //=======================================================================
342 //function : Single
343 //purpose  : 
344 //=======================================================================
345 Handle(Standard_Transient)  AIS_Selection::Single() 
346 {
347   Handle(AIS_Selection) S;
348   AIS_Sel_CurrentSelection (S);
349   
350   S->Init();
351   return S->Value();
352 }
353 //=======================================================================
354 //function : IsSelected
355 //purpose  : 
356 //=======================================================================
357 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
358 {
359   Handle(AIS_Selection) S;
360   AIS_Sel_CurrentSelection (S);
361   if(S.IsNull()) return Standard_False;
362 #ifndef USE_MAP  
363   for(S->Init();S->More();S->Next()){
364     if(S->Value()==anObject)
365       return Standard_True;
366   }
367   return Standard_False;
368 #else
369   return S->myResultMap.IsBound( anObject );
370 #endif
371 }
372
373 //=======================================================================
374 //function : Index
375 //purpose  : 
376 //=======================================================================
377
378 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
379 {
380   Handle (Standard_Transient) curobj;
381   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
382     curobj = AIS_Sel_GetSelections().Value(I);
383     if((*((Handle(AIS_Selection)*)&curobj))->myName.IsEqual(aName))
384       return I;
385   }
386   return 0;
387 }
388
389 //=======================================================================
390 //function : Remove
391 //purpose  : 
392 //=======================================================================
393
394 void AIS_Selection::Remove(const Standard_CString aName) 
395 {
396   Standard_Integer I = AIS_Selection::Index(aName);
397   if(I!=0) {
398 #ifdef OCC1039
399     Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
400     Standard_Integer stored = selection->NbStored();
401     if ( stored )
402       selection->Select();
403 #endif
404     AIS_Sel_GetSelections().Remove(I);
405   }
406   
407 }
408