1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <AIS_Selection.ixx>
16 #include <TCollection_AsciiString.hxx>
17 #include <TColStd_SequenceOfTransient.hxx>
19 #define BUC60953 // SAV_050701 : the array of selected objects has always the same length
20 // independently of number of objects selected. Thus, if there were selected
21 // more than MaxSizeOfResult objects we have got an exception.
22 // Moreover, Select method was optimized a little bit.
23 // Now it checks the state of incoming owner. If the state is 0
24 // there is no searching for object in <myresult> array.
28 #define OCC189 //SAV: 18//03/02 array was replaced with list.
30 #define OCC1039 //SAV: 25/11/02 clearing selected objects if any on the AIS_Selection remove.
32 #define USE_MAP //san : 18/04/03 USE_MAP - additional datamap is used to speed up access
33 //to certain owners in <myresult> list
36 #include <SelectMgr_EntityOwner.hxx>
39 #ifdef OCC138 //VTN Avoding infinit loop in AddOrRemoveSelected and AddOrRemoveCurrentObject methods.
40 #include <AIS_InteractiveObject.hxx>
44 #define MaxSizeOfResult 10000
46 #define MaxSizeOfResult 100000
49 //current selection (handle)
50 static Handle(AIS_Selection) theCurrentSelection;
51 static void AIS_Sel_CurrentSelection (Handle(AIS_Selection)& InputSel)
53 if(!InputSel.IsNull())
54 theCurrentSelection = InputSel;
56 InputSel = theCurrentSelection;
59 static TColStd_SequenceOfTransient& AIS_Sel_GetSelections()
61 static TColStd_SequenceOfTransient Selections;
65 //=======================================================================
66 //function : AIS_Selection
68 //=======================================================================
69 AIS_Selection::AIS_Selection(const Standard_CString aName) :
70 myName(TCollection_AsciiString(aName)),
71 #if !defined USE_MAP && !defined OCC189
72 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
77 myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
81 //=======================================================================
82 //function : CreateSelection
84 //=======================================================================
85 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
87 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
89 return Standard_False;
90 S = new AIS_Selection(aName);
91 AIS_Sel_GetSelections().Prepend(S);
92 AIS_Sel_CurrentSelection(S);
97 //=======================================================================
98 //function : Selection
100 //=======================================================================
101 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName)
103 Handle(AIS_Selection) S;
104 if(AIS_Sel_GetSelections().IsEmpty()) return S;
106 Handle(Standard_Transient) curobj;
107 Handle(AIS_Selection) Sel;
108 // Standard_Boolean found(Standard_False);
109 for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
110 curobj = AIS_Sel_GetSelections().Value(I);
111 Sel = *((Handle(AIS_Selection)*)&curobj);
112 if(Sel->myName.IsEqual(aName))
119 //=======================================================================
122 //=======================================================================
123 Standard_Boolean AIS_Selection::Find(const Standard_CString aName)
125 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
129 //=======================================================================
130 //function : SetCurrentSelection
132 //=======================================================================
133 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName)
135 AIS_Selection::CreateSelection(aName);
138 Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
139 AIS_Sel_CurrentSelection ( anAISSelection ) ;
140 return Standard_True;
143 //=======================================================================
146 //=======================================================================
147 void AIS_Selection::Select()
149 Handle(AIS_Selection) S;
150 AIS_Sel_CurrentSelection (S);
153 #if defined OCC189 || defined USE_MAP
156 S->myResultMap.Clear();
162 //=======================================================================
163 //function : CurrentSelection
165 //=======================================================================
166 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
167 Handle(AIS_Selection) S;
168 AIS_Sel_CurrentSelection (S);
171 //=======================================================================
174 //=======================================================================
175 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject)
177 Handle(AIS_Selection) S;
178 AIS_Sel_CurrentSelection (S);
179 if(S.IsNull()) return AIS_SS_NotDone;
180 Handle(AIS_InteractiveObject) anAISObj;
181 Handle(SelectMgr_EntityOwner) owner = Handle(SelectMgr_EntityOwner)::DownCast( anObject );
182 if ( owner.IsNull() )
183 anAISObj = Handle(AIS_InteractiveObject)::DownCast( anObject );
185 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
187 Standard_Integer Found(-1);
192 Standard_Boolean selected = Standard_False;
193 if ( !owner.IsNull() )
194 selected = owner->State() != 0;
196 else if(!anAISObj.IsNull())
197 selected = anAISObj->State();
201 if ( selected ) // looking up index of object
204 for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
208 // If it is not inside, it is added...
211 if ( !selected || Found == -1 ) {
215 if((S->myNb)+1>arr.Length()){
216 Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
217 for(i=arr.Lower();i<=S->myNb;i++){
218 const Handle(Standard_Transient)& T = S->myresult->Value(i);
219 NiouTab->SetValue(i,T);
222 S->myresult = NiouTab;
226 S->myresult->SetValue(S->myNb,anObject);
229 // it was inside and it is removed...
230 for(i=Found;i<=S->myNb;i++)
233 #elif !defined USE_MAP //OCC189
234 AIS_NListTransient::Iterator anIter ( S->myresult );
235 for ( ; anIter.More(); anIter.Next() )
236 if ( anIter.Value() == anObject ) {
237 S->myresult.Remove( anIter );
238 return AIS_SS_Removed;
241 S->myresult.Append( anObject );
244 if ( S->myResultMap.IsBound( anObject ) ){
245 AIS_NListTransient::Iterator aListIter = S->myResultMap.Find( anObject );
246 //skt-----------------------------------------------------------------
247 if( S->myIterator == aListIter ) {
248 if( S->myIterator.More() )
249 S->myIterator.Next();
251 S->myIterator = AIS_NListTransient::Iterator();
253 //--------------------------------------------------------------------
255 // In the mode of advanced mesh selection only one owner is created
256 // for all selection modes. It is necessary to check the current detected
257 // entity and remove the owner from map only if the detected entity is
258 // the same as previous selected (IsForcedHilight call)
259 if( !anAISObj.IsNull() || ( !owner.IsNull() && !owner->IsForcedHilight() ) )
262 S->myresult.Remove( aListIter );
263 S->myResultMap.UnBind( anObject );
265 // update list iterator for next object in <myresult> list if any
266 if ( aListIter.More() ){
267 const Handle(Standard_Transient)& aNextObject = aListIter.Value();
268 if ( S->myResultMap.IsBound( aNextObject ) )
269 S->myResultMap( aNextObject ) = aListIter;
271 S->myResultMap.Bind( aNextObject, aListIter );
273 return AIS_SS_Removed;
279 AIS_NListTransient::Iterator aListIter;
280 S->myresult.Append( anObject, aListIter );
281 S->myResultMap.Bind( anObject, aListIter );
286 //=======================================================================
287 //function : AddSelect
288 //purpose : Always add int the selection
289 //=======================================================================
290 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject)
292 Handle(AIS_Selection) S;
293 AIS_Sel_CurrentSelection (S);
294 if(S.IsNull()) return AIS_SS_NotDone;
297 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
299 if((S->myNb)+1>arr.Length()){
300 Handle(TColStd_HArray1OfTransient) NiouTab = new TColStd_HArray1OfTransient(1,arr.Length()+MaxSizeOfResult);
301 for(i=arr.Lower();i<=S->myNb;i++){
302 const Handle(Standard_Transient)& T = S->myresult->Value(i);
303 NiouTab->SetValue(i,T);
305 S->myresult = NiouTab;
308 S->myresult->SetValue(S->myNb,anObject);
309 #elif !defined USE_MAP //OCC189
310 S->myresult.Append( anObject );
312 if ( S->myResultMap.IsBound( anObject ) )
313 return AIS_SS_NotDone;
315 AIS_NListTransient::Iterator aListIter;
316 S->myresult.Append( anObject, aListIter );
317 S->myResultMap.Bind( anObject, aListIter );
323 //=======================================================================
324 //function : ClearAndSelect
326 //=======================================================================
328 void AIS_Selection::ClearAndSelect(const Handle(Standard_Transient)& anObject) {
329 Handle(AIS_Selection) S;
330 AIS_Sel_CurrentSelection (S);
331 if(S.IsNull()) return;
339 //=======================================================================
342 //=======================================================================
343 Standard_Integer AIS_Selection::Extent() {
344 Handle(AIS_Selection) S;
345 AIS_Sel_CurrentSelection (S);
346 #if !defined OCC189 && !defined USE_MAP
349 return S->myresult.Extent();
353 //=======================================================================
356 //=======================================================================
357 Handle(Standard_Transient) AIS_Selection::Single()
359 Handle(AIS_Selection) S;
360 AIS_Sel_CurrentSelection (S);
365 //=======================================================================
366 //function : IsSelected
368 //=======================================================================
369 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
371 Handle(AIS_Selection) S;
372 AIS_Sel_CurrentSelection (S);
373 if(S.IsNull()) return Standard_False;
375 for(S->Init();S->More();S->Next()){
376 if(S->Value()==anObject)
377 return Standard_True;
379 return Standard_False;
381 return S->myResultMap.IsBound( anObject );
385 //=======================================================================
388 //=======================================================================
390 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
392 Handle (Standard_Transient) curobj;
393 for(Standard_Integer I =1; I<= AIS_Sel_GetSelections().Length();I++){
394 curobj = AIS_Sel_GetSelections().Value(I);
395 if((*((Handle(AIS_Selection)*)&curobj))->myName.IsEqual(aName))
401 //=======================================================================
404 //=======================================================================
406 void AIS_Selection::Remove(const Standard_CString aName)
408 Standard_Integer I = AIS_Selection::Index(aName);
411 Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
412 Standard_Integer stored = selection->NbStored();
416 AIS_Sel_GetSelections().Remove(I);
420 // clean the static current selection handle
421 void AIS_Selection::ClearCurrentSelection()
423 theCurrentSelection.Nullify();