0ea8f3af6f2a344ae5c90735a654aac662992a8a
[occt.git] / src / AIS / AIS_Selection.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_Selection.ixx>
16 #include <TCollection_AsciiString.hxx>
17 #include <TColStd_SequenceOfTransient.hxx>
18
19 #include <SelectMgr_EntityOwner.hxx>
20
21 #include <AIS_InteractiveObject.hxx>
22
23 #define MaxSizeOfResult 100000
24
25 //current selection (handle)
26 static Handle(AIS_Selection) theCurrentSelection;
27 static void AIS_Sel_CurrentSelection (Handle(AIS_Selection)& InputSel)     
28 {
29   if(!InputSel.IsNull())
30     theCurrentSelection = InputSel;
31   else
32     InputSel = theCurrentSelection;
33 }
34
35 static TColStd_SequenceOfTransient&  AIS_Sel_GetSelections()
36 {
37   static TColStd_SequenceOfTransient Selections;
38   return Selections;
39 }
40
41 //=======================================================================
42 //function : AIS_Selection
43 //purpose  : 
44 //=======================================================================
45 AIS_Selection::AIS_Selection(const Standard_CString aName) :
46 myName(TCollection_AsciiString(aName)),
47 myNb(0)
48 {
49   myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
50 }
51
52 //=======================================================================
53 //function : CreateSelection
54 //purpose  : 
55 //=======================================================================
56 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
57
58   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
59   if(!S.IsNull())
60     return Standard_False;
61   S = new AIS_Selection(aName);
62   AIS_Sel_GetSelections().Prepend(S);
63   AIS_Sel_CurrentSelection(S);
64   return Standard_True;
65 }
66
67
68 //=======================================================================
69 //function : Selection
70 //purpose  : 
71 //=======================================================================
72 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName) 
73 {
74   Handle(AIS_Selection) S;
75   if(AIS_Sel_GetSelections().IsEmpty()) return S;
76   
77   Handle(Standard_Transient) curobj;
78   Handle(AIS_Selection) Sel;
79 //  Standard_Boolean found(Standard_False);
80   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
81     curobj = AIS_Sel_GetSelections().Value(I);
82     Sel = *((Handle(AIS_Selection)*)&curobj);
83     if(Sel->myName.IsEqual(aName))
84       return Sel;
85   }
86   
87   return S;
88 }
89
90 //=======================================================================
91 //function : Find
92 //purpose  : 
93 //=======================================================================
94 Standard_Boolean AIS_Selection::Find(const Standard_CString aName) 
95 {
96   Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
97   return !S.IsNull();
98 }
99
100 //=======================================================================
101 //function : SetCurrentSelection
102 //purpose  : 
103 //=======================================================================
104 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName) 
105 {  
106   AIS_Selection::CreateSelection(aName); 
107
108
109   Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
110   AIS_Sel_CurrentSelection ( anAISSelection ) ;
111   return Standard_True;
112 }
113
114 //=======================================================================
115 //function : Select
116 //purpose  : 
117 //=======================================================================
118 void AIS_Selection::Select() 
119 {
120   Handle(AIS_Selection) S;
121   AIS_Sel_CurrentSelection (S);
122   if(!S.IsNull()){
123     S->myNb=0;
124     S->myresult.Clear();
125     S->myResultMap.Clear();
126   }
127 }
128
129 //=======================================================================
130 //function : CurrentSelection
131 //purpose  : 
132 //=======================================================================
133 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
134   Handle(AIS_Selection) S;
135   AIS_Sel_CurrentSelection (S);
136   return S;
137 }
138 //=======================================================================
139 //function : Select
140 //purpose  : 
141 //=======================================================================
142 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject) 
143 {
144   Handle(AIS_Selection) S;
145   AIS_Sel_CurrentSelection (S);
146   if(S.IsNull()) return AIS_SS_NotDone;
147   Handle(AIS_InteractiveObject) anAISObj;
148   Handle(SelectMgr_EntityOwner) owner = Handle(SelectMgr_EntityOwner)::DownCast( anObject );
149   if ( owner.IsNull() )
150     anAISObj = Handle(AIS_InteractiveObject)::DownCast( anObject );
151   if ( S->myResultMap.IsBound( anObject ) ){
152     AIS_NListTransient::Iterator aListIter = S->myResultMap.Find( anObject );
153 //skt-----------------------------------------------------------------
154     if( S->myIterator == aListIter ) {
155       if( S->myIterator.More() )
156           S->myIterator.Next();
157       else
158           S->myIterator = AIS_NListTransient::Iterator();
159     }
160 //--------------------------------------------------------------------
161     // In the mode of advanced mesh selection only one owner is created
162     // for all selection modes. It is necessary to check the current detected
163     // entity and remove the owner from map only if the detected entity is
164     // the same as previous selected (IsForcedHilight call)
165     if( !anAISObj.IsNull() || ( !owner.IsNull() && !owner->IsForcedHilight() ) )
166     {
167       S->myresult.Remove( aListIter );
168       S->myResultMap.UnBind( anObject );
169     
170       // update list iterator for next object in <myresult> list if any
171       if ( aListIter.More() ){
172         const Handle(Standard_Transient)& aNextObject = aListIter.Value();
173         if ( S->myResultMap.IsBound( aNextObject ) )
174           S->myResultMap( aNextObject ) = aListIter;
175         else
176           S->myResultMap.Bind( aNextObject, aListIter );
177       }
178       return AIS_SS_Removed;
179     }
180     else
181       return AIS_SS_Added;
182   }
183   
184   AIS_NListTransient::Iterator aListIter;
185   S->myresult.Append( anObject, aListIter );
186   S->myResultMap.Bind( anObject, aListIter );
187   return AIS_SS_Added;
188 }
189
190 //=======================================================================
191 //function : AddSelect
192 //purpose  : Always add int the selection
193 //=======================================================================
194 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject) 
195 {
196   Handle(AIS_Selection) S;
197   AIS_Sel_CurrentSelection (S);
198   if(S.IsNull()) return AIS_SS_NotDone;
199
200   if ( S->myResultMap.IsBound( anObject ) )
201     return AIS_SS_NotDone;
202       
203   AIS_NListTransient::Iterator aListIter;
204   S->myresult.Append( anObject, aListIter );
205   S->myResultMap.Bind( anObject, aListIter );
206   return AIS_SS_Added;
207 }
208
209
210 //=======================================================================
211 //function : ClearAndSelect
212 //purpose  : 
213 //=======================================================================
214
215 void AIS_Selection::ClearAndSelect(const Handle(Standard_Transient)& anObject) {
216   Handle(AIS_Selection) S;
217   AIS_Sel_CurrentSelection (S);
218   if(S.IsNull()) return;
219   
220   Select();
221   Select(anObject);
222
223 }
224
225
226 //=======================================================================
227 //function : Extent
228 //purpose  : 
229 //=======================================================================
230 Standard_Integer AIS_Selection::Extent() {
231   Handle(AIS_Selection) S;
232   AIS_Sel_CurrentSelection (S);
233
234   if (S.IsNull())
235     return 0;
236
237   return S->myresult.Extent();
238 }
239
240 //=======================================================================
241 //function : Single
242 //purpose  : 
243 //=======================================================================
244 Handle(Standard_Transient)  AIS_Selection::Single() 
245 {
246   Handle(AIS_Selection) S;
247   AIS_Sel_CurrentSelection (S);
248
249   if (S.IsNull())
250     return Handle(Standard_Transient)();
251
252   S->Init();
253   return S->Value();
254 }
255 //=======================================================================
256 //function : IsSelected
257 //purpose  : 
258 //=======================================================================
259 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
260 {
261   Handle(AIS_Selection) S;
262   AIS_Sel_CurrentSelection (S);
263   if(S.IsNull()) return Standard_False;
264   return S->myResultMap.IsBound( anObject );
265 }
266
267 //=======================================================================
268 //function : Index
269 //purpose  : 
270 //=======================================================================
271
272 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
273 {
274   Handle (Standard_Transient) curobj;
275   for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
276     curobj = AIS_Sel_GetSelections().Value(I);
277     if((*((Handle(AIS_Selection)*)&curobj))->myName.IsEqual(aName))
278       return I;
279   }
280   return 0;
281 }
282
283 //=======================================================================
284 //function : Remove
285 //purpose  : 
286 //=======================================================================
287
288 void AIS_Selection::Remove(const Standard_CString aName) 
289 {
290   Standard_Integer I = AIS_Selection::Index(aName);
291   if(I!=0) {
292     Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
293     Standard_Integer stored = selection->NbStored();
294     if ( stored )
295       selection->Select();
296     AIS_Sel_GetSelections().Remove(I);
297   }
298 }
299
300 // clean the static current selection handle
301 void AIS_Selection::ClearCurrentSelection()
302 {
303     theCurrentSelection.Nullify();
304 }
305