1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
19 #include <AIS_Selection.ixx>
20 #include <TCollection_AsciiString.hxx>
21 #include <TColStd_SequenceOfTransient.hxx>
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.
32 #define OCC189 //SAV: 18//03/02 array was replaced with list.
34 #define OCC1039 //SAV: 25/11/02 clearing selected objects if any on the AIS_Selection remove.
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
40 #include <SelectMgr_EntityOwner.hxx>
43 #ifdef OCC138 //VTN Avoding infinit loop in AddOrRemoveSelected and AddOrRemoveCurrentObject methods.
44 #include <AIS_InteractiveObject.hxx>
48 #define MaxSizeOfResult 10000
50 #define MaxSizeOfResult 100000
53 static void AIS_Sel_CurrentSelection (Handle(AIS_Selection)& InputSel)
55 static Handle(AIS_Selection) theCurrentSelection;
56 if(!InputSel.IsNull())
57 theCurrentSelection = InputSel;
59 InputSel = theCurrentSelection;
62 static TColStd_SequenceOfTransient& AIS_Sel_GetSelections()
64 static TColStd_SequenceOfTransient Selections;
68 //=======================================================================
69 //function : AIS_Selection
71 //=======================================================================
72 AIS_Selection::AIS_Selection(const Standard_CString aName) :
73 myName(TCollection_AsciiString(aName)),
75 #if !defined USE_MAP && !defined OCC189
76 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
81 myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
85 //=======================================================================
86 //function : CreateSelection
88 //=======================================================================
89 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
91 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
93 return Standard_False;
94 S = new AIS_Selection(aName);
95 AIS_Sel_GetSelections().Prepend(S);
96 AIS_Sel_CurrentSelection(S);
101 //=======================================================================
102 //function : Selection
104 //=======================================================================
105 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName)
107 Handle(AIS_Selection) S;
108 if(AIS_Sel_GetSelections().IsEmpty()) return S;
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))
123 //=======================================================================
126 //=======================================================================
127 Standard_Boolean AIS_Selection::Find(const Standard_CString aName)
129 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
133 //=======================================================================
134 //function : SetCurrentSelection
136 //=======================================================================
137 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName)
139 AIS_Selection::CreateSelection(aName);
142 Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
143 AIS_Sel_CurrentSelection ( anAISSelection ) ;
144 return Standard_True;
147 //=======================================================================
150 //=======================================================================
151 void AIS_Selection::Select()
153 Handle(AIS_Selection) S;
154 AIS_Sel_CurrentSelection (S);
157 #if defined OCC189 || defined USE_MAP
160 S->myResultMap.Clear();
166 //=======================================================================
167 //function : CurrentSelection
169 //=======================================================================
170 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
171 Handle(AIS_Selection) S;
172 AIS_Sel_CurrentSelection (S);
175 //=======================================================================
178 //=======================================================================
179 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject)
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 );
189 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
191 Standard_Integer Found(-1);
196 Standard_Boolean selected = Standard_False;
197 if ( !owner.IsNull() )
198 selected = owner->State() != 0;
200 else if(!anAISObj.IsNull())
201 selected = anAISObj->State();
205 if ( selected ) // looking up index of object
208 for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
212 // If it is not inside, it is added...
215 if ( !selected || Found == -1 ) {
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);
226 S->myresult = NiouTab;
230 S->myresult->SetValue(S->myNb,anObject);
233 // it was inside and it is removed...
234 for(i=Found;i<=S->myNb;i++)
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;
245 S->myresult.Append( anObject );
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();
255 S->myIterator = AIS_NListTransient::Iterator();
257 //--------------------------------------------------------------------
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() ) )
266 S->myresult.Remove( aListIter );
267 S->myResultMap.UnBind( anObject );
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;
275 S->myResultMap.Bind( aNextObject, aListIter );
277 return AIS_SS_Removed;
283 AIS_NListTransient::Iterator aListIter;
284 S->myresult.Append( anObject, aListIter );
285 S->myResultMap.Bind( anObject, aListIter );
290 //=======================================================================
291 //function : AddSelect
292 //purpose : Always add int the selection
293 //=======================================================================
294 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject)
296 Handle(AIS_Selection) S;
297 AIS_Sel_CurrentSelection (S);
298 if(S.IsNull()) return AIS_SS_NotDone;
301 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
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);
309 S->myresult = NiouTab;
312 S->myresult->SetValue(S->myNb,anObject);
313 #elif !defined USE_MAP //OCC189
314 S->myresult.Append( anObject );
316 if ( S->myResultMap.IsBound( anObject ) )
317 return AIS_SS_NotDone;
319 AIS_NListTransient::Iterator aListIter;
320 S->myresult.Append( anObject, aListIter );
321 S->myResultMap.Bind( anObject, aListIter );
327 //=======================================================================
328 //function : ClearAndSelect
330 //=======================================================================
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;
343 //=======================================================================
346 //=======================================================================
347 Standard_Integer AIS_Selection::Extent() {
348 Handle(AIS_Selection) S;
349 AIS_Sel_CurrentSelection (S);
350 #if !defined OCC189 && !defined USE_MAP
353 return S->myresult.Extent();
357 //=======================================================================
360 //=======================================================================
361 Handle(Standard_Transient) AIS_Selection::Single()
363 Handle(AIS_Selection) S;
364 AIS_Sel_CurrentSelection (S);
369 //=======================================================================
370 //function : IsSelected
372 //=======================================================================
373 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
375 Handle(AIS_Selection) S;
376 AIS_Sel_CurrentSelection (S);
377 if(S.IsNull()) return Standard_False;
379 for(S->Init();S->More();S->Next()){
380 if(S->Value()==anObject)
381 return Standard_True;
383 return Standard_False;
385 return S->myResultMap.IsBound( anObject );
389 //=======================================================================
392 //=======================================================================
394 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
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))
405 //=======================================================================
408 //=======================================================================
410 void AIS_Selection::Remove(const Standard_CString aName)
412 Standard_Integer I = AIS_Selection::Index(aName);
415 Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
416 Standard_Integer stored = selection->NbStored();
420 AIS_Sel_GetSelections().Remove(I);