a9d4b02d19678801f194a8ba5b0db9bb054dbf91
[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 #if !defined USE_MAP && !defined OCC189
75 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
76 #endif
77 myNb(0)
78 {
79 #ifdef USE_MAP 
80   myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
81 #endif
82 }
83
84 //=======================================================================
85 //function : CreateSelection
86 //purpose  : 
87 //=======================================================================
88 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
89
90   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
91   if(!S.IsNull())
92     return Standard_False;
93   S = new AIS_Selection(aName);
94   AIS_Sel_GetSelections().Prepend(S);
95   AIS_Sel_CurrentSelection(S);
96   return Standard_True;
97 }
98
99
100 //=======================================================================
101 //function : Selection
102 //purpose  : 
103 //=======================================================================
104 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName) 
105 {
106   Handle(AIS_Selection) S;
107   if(AIS_Sel_GetSelections().IsEmpty()) return S;
108   
109   Handle(Standard_Transient) curobj;
110   Handle(AIS_Selection) Sel;
111 //  Standard_Boolean found(Standard_False);
112   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
113     curobj = AIS_Sel_GetSelections().Value(I);
114     Sel = *((Handle(AIS_Selection)*)&curobj);
115     if(Sel->myName.IsEqual(aName))
116       return Sel;
117   }
118   
119   return S;
120 }
121
122 //=======================================================================
123 //function : Find
124 //purpose  : 
125 //=======================================================================
126 Standard_Boolean AIS_Selection::Find(const Standard_CString aName) 
127 {
128   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
129   return !S.IsNull();
130 }
131
132 //=======================================================================
133 //function : SetCurrentSelection
134 //purpose  : 
135 //=======================================================================
136 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName) 
137 {  
138   AIS_Selection::CreateSelection(aName); 
139
140
141   Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
142   AIS_Sel_CurrentSelection ( anAISSelection ) ;
143   return Standard_True;
144 }
145
146 //=======================================================================
147 //function : Select
148 //purpose  : 
149 //=======================================================================
150 void AIS_Selection::Select() 
151 {
152   Handle(AIS_Selection) S;
153   AIS_Sel_CurrentSelection (S);
154   if(!S.IsNull()){
155     S->myNb=0;
156 #if defined OCC189 || defined USE_MAP
157     S->myresult.Clear();
158 #ifdef USE_MAP
159     S->myResultMap.Clear();
160 #endif
161 #endif
162   }
163 }
164
165 //=======================================================================
166 //function : CurrentSelection
167 //purpose  : 
168 //=======================================================================
169 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
170   Handle(AIS_Selection) S;
171   AIS_Sel_CurrentSelection (S);
172   return S;
173 }
174 //=======================================================================
175 //function : Select
176 //purpose  : 
177 //=======================================================================
178 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject) 
179 {
180   Handle(AIS_Selection) S;
181   AIS_Sel_CurrentSelection (S);
182   if(S.IsNull()) return AIS_SS_NotDone;
183   Handle(AIS_InteractiveObject) anAISObj;
184   Handle(SelectMgr_EntityOwner) owner = Handle(SelectMgr_EntityOwner)::DownCast( anObject );
185   if ( owner.IsNull() )
186     anAISObj = Handle(AIS_InteractiveObject)::DownCast( anObject );
187 #ifndef OCC189
188   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
189   
190   Standard_Integer Found(-1);
191   Standard_Integer i ;
192
193 #ifdef BUC60953
194   
195   Standard_Boolean selected = Standard_False;
196   if ( !owner.IsNull() )
197     selected = owner->State() != 0;
198 #ifdef OCC138
199   else if(!anAISObj.IsNull())
200     selected = anAISObj->State();
201   }
202 #endif
203
204   if ( selected ) // looking up index of object
205 #endif
206
207   for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
208     if(arr(i)==anObject)
209       Found=i;
210   }
211   // If it is not inside, it is added...
212
213 #ifdef BUC60953
214   if ( !selected || Found == -1 ) {
215 #else
216   if(Found==-1){
217 #endif  
218     if((S->myNb)+1>arr.Length()){
219       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
220       for(i=arr.Lower();i<=S->myNb;i++){
221         const Handle(Standard_Transient)& T = S->myresult->Value(i);
222         NiouTab->SetValue(i,T);
223       }
224 #ifdef BUC60953
225       S->myresult = NiouTab;
226 #endif
227     }
228     (S->myNb)++;
229     S->myresult->SetValue(S->myNb,anObject);
230     return AIS_SS_Added;
231   }
232   // it was inside and it is removed...
233   for(i=Found;i<=S->myNb;i++)
234     arr(i)=arr(i+1);
235   S->myNb--;
236 #elif !defined USE_MAP //OCC189
237   AIS_NListTransient::Iterator anIter ( S->myresult );
238   for ( ; anIter.More(); anIter.Next() )
239     if ( anIter.Value() == anObject ) {
240       S->myresult.Remove( anIter );
241       return AIS_SS_Removed;
242     }
243       
244   S->myresult.Append( anObject );
245   return AIS_SS_Added;
246 #else //USE_MAP
247   if ( S->myResultMap.IsBound( anObject ) ){
248     AIS_NListTransient::Iterator aListIter = S->myResultMap.Find( anObject );
249 //skt-----------------------------------------------------------------
250     if( S->myIterator == aListIter ) {
251       if( S->myIterator.More() )
252           S->myIterator.Next();
253       else
254           S->myIterator = AIS_NListTransient::Iterator();
255     }
256 //--------------------------------------------------------------------
257 #ifdef BUC60953
258     // In the mode of advanced mesh selection only one owner is created
259     // for all selection modes. It is necessary to check the current detected
260     // entity and remove the owner from map only if the detected entity is
261     // the same as previous selected (IsForcedHilight call)
262     if( !anAISObj.IsNull() || ( !owner.IsNull() && !owner->IsForcedHilight() ) )
263     {
264 #endif  
265       S->myresult.Remove( aListIter );
266       S->myResultMap.UnBind( anObject );
267     
268       // update list iterator for next object in <myresult> list if any
269       if ( aListIter.More() ){
270         const Handle(Standard_Transient)& aNextObject = aListIter.Value();
271         if ( S->myResultMap.IsBound( aNextObject ) )
272           S->myResultMap( aNextObject ) = aListIter;
273         else
274           S->myResultMap.Bind( aNextObject, aListIter );
275       }
276       return AIS_SS_Removed;
277     }
278     else
279       return AIS_SS_Added;
280   }
281   
282   AIS_NListTransient::Iterator aListIter;
283   S->myresult.Append( anObject, aListIter );
284   S->myResultMap.Bind( anObject, aListIter );
285   return AIS_SS_Added;
286 #endif //USE_MAP  
287 }
288
289 //=======================================================================
290 //function : AddSelect
291 //purpose  : Always add int the selection
292 //=======================================================================
293 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject) 
294 {
295   Handle(AIS_Selection) S;
296   AIS_Sel_CurrentSelection (S);
297   if(S.IsNull()) return AIS_SS_NotDone;
298
299 #ifndef OCC189
300   TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
301   Standard_Integer i;
302   if((S->myNb)+1>arr.Length()){
303       Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
304       for(i=arr.Lower();i<=S->myNb;i++){
305         const Handle(Standard_Transient)& T = S->myresult->Value(i);
306         NiouTab->SetValue(i,T);
307       }
308       S->myresult = NiouTab;
309   }
310   (S->myNb)++;
311   S->myresult->SetValue(S->myNb,anObject);
312 #elif !defined USE_MAP //OCC189
313   S->myresult.Append( anObject );
314 #else //USE_MAP
315   if ( S->myResultMap.IsBound( anObject ) )
316     return AIS_SS_NotDone;
317       
318   AIS_NListTransient::Iterator aListIter;
319   S->myresult.Append( anObject, aListIter );
320   S->myResultMap.Bind( anObject, aListIter );
321 #endif
322   return AIS_SS_Added;
323 }
324
325
326 //=======================================================================
327 //function : ClearAndSelect
328 //purpose  : 
329 //=======================================================================
330
331 void AIS_Selection::ClearAndSelect(const Handle(Standard_Transient)& anObject) {
332   Handle(AIS_Selection) S;
333   AIS_Sel_CurrentSelection (S);
334   if(S.IsNull()) return;
335   
336   Select();
337   Select(anObject);
338
339 }
340
341
342 //=======================================================================
343 //function : Extent
344 //purpose  : 
345 //=======================================================================
346 Standard_Integer AIS_Selection::Extent() {
347   Handle(AIS_Selection) S;
348   AIS_Sel_CurrentSelection (S);
349 #if !defined OCC189 && !defined USE_MAP
350   return S->myNb;
351 #else
352   return S->myresult.Extent();
353 #endif
354 }
355
356 //=======================================================================
357 //function : Single
358 //purpose  : 
359 //=======================================================================
360 Handle(Standard_Transient)  AIS_Selection::Single() 
361 {
362   Handle(AIS_Selection) S;
363   AIS_Sel_CurrentSelection (S);
364   
365   S->Init();
366   return S->Value();
367 }
368 //=======================================================================
369 //function : IsSelected
370 //purpose  : 
371 //=======================================================================
372 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
373 {
374   Handle(AIS_Selection) S;
375   AIS_Sel_CurrentSelection (S);
376   if(S.IsNull()) return Standard_False;
377 #ifndef USE_MAP  
378   for(S->Init();S->More();S->Next()){
379     if(S->Value()==anObject)
380       return Standard_True;
381   }
382   return Standard_False;
383 #else
384   return S->myResultMap.IsBound( anObject );
385 #endif
386 }
387
388 //=======================================================================
389 //function : Index
390 //purpose  : 
391 //=======================================================================
392
393 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
394 {
395   Handle (Standard_Transient) curobj;
396   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
397     curobj = AIS_Sel_GetSelections().Value(I);
398     if((*((Handle(AIS_Selection)*)&curobj))->myName.IsEqual(aName))
399       return I;
400   }
401   return 0;
402 }
403
404 //=======================================================================
405 //function : Remove
406 //purpose  : 
407 //=======================================================================
408
409 void AIS_Selection::Remove(const Standard_CString aName) 
410 {
411   Standard_Integer I = AIS_Selection::Index(aName);
412   if(I!=0) {
413 #ifdef OCC1039
414     Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
415     Standard_Integer stored = selection->NbStored();
416     if ( stored )
417       selection->Select();
418 #endif
419     AIS_Sel_GetSelections().Remove(I);
420   }
421   
422 }
423