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