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