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)),
74 #if !defined USE_MAP && !defined OCC189
75 myresult(new TColStd_HArray1OfTransient(1,MaxSizeOfResult)),
80 myResultMap.ReSize( MaxSizeOfResult ); // for maximum performnace on medium selections ( < 100000 objects )
84 //=======================================================================
85 //function : CreateSelection
87 //=======================================================================
88 Standard_Boolean AIS_Selection::CreateSelection(const Standard_CString aName)
90 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
92 return Standard_False;
93 S = new AIS_Selection(aName);
94 AIS_Sel_GetSelections().Prepend(S);
95 AIS_Sel_CurrentSelection(S);
100 //=======================================================================
101 //function : Selection
103 //=======================================================================
104 Handle(AIS_Selection) AIS_Selection::Selection(const Standard_CString aName)
106 Handle(AIS_Selection) S;
107 if(AIS_Sel_GetSelections().IsEmpty()) return S;
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))
122 //=======================================================================
125 //=======================================================================
126 Standard_Boolean AIS_Selection::Find(const Standard_CString aName)
128 Handle(AIS_Selection) S = AIS_Selection::Selection(aName);
132 //=======================================================================
133 //function : SetCurrentSelection
135 //=======================================================================
136 Standard_Boolean AIS_Selection::SetCurrentSelection (const Standard_CString aName)
138 AIS_Selection::CreateSelection(aName);
141 Handle(AIS_Selection) anAISSelection = AIS_Selection::Selection(aName) ;
142 AIS_Sel_CurrentSelection ( anAISSelection ) ;
143 return Standard_True;
146 //=======================================================================
149 //=======================================================================
150 void AIS_Selection::Select()
152 Handle(AIS_Selection) S;
153 AIS_Sel_CurrentSelection (S);
156 #if defined OCC189 || defined USE_MAP
159 S->myResultMap.Clear();
165 //=======================================================================
166 //function : CurrentSelection
168 //=======================================================================
169 Handle(AIS_Selection) AIS_Selection::CurrentSelection() {
170 Handle(AIS_Selection) S;
171 AIS_Sel_CurrentSelection (S);
174 //=======================================================================
177 //=======================================================================
178 AIS_SelectStatus AIS_Selection::Select(const Handle(Standard_Transient)& anObject)
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 );
188 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
190 Standard_Integer Found(-1);
195 Standard_Boolean selected = Standard_False;
196 if ( !owner.IsNull() )
197 selected = owner->State() != 0;
199 else if(!anAISObj.IsNull())
200 selected = anAISObj->State();
204 if ( selected ) // looking up index of object
207 for( i=arr.Lower() && Found==-1;i<=S->myNb;i++){
211 // If it is not inside, it is added...
214 if ( !selected || Found == -1 ) {
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);
225 S->myresult = NiouTab;
229 S->myresult->SetValue(S->myNb,anObject);
232 // it was inside and it is removed...
233 for(i=Found;i<=S->myNb;i++)
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;
244 S->myresult.Append( anObject );
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();
254 S->myIterator = AIS_NListTransient::Iterator();
256 //--------------------------------------------------------------------
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() ) )
265 S->myresult.Remove( aListIter );
266 S->myResultMap.UnBind( anObject );
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;
274 S->myResultMap.Bind( aNextObject, aListIter );
276 return AIS_SS_Removed;
282 AIS_NListTransient::Iterator aListIter;
283 S->myresult.Append( anObject, aListIter );
284 S->myResultMap.Bind( anObject, aListIter );
289 //=======================================================================
290 //function : AddSelect
291 //purpose : Always add int the selection
292 //=======================================================================
293 AIS_SelectStatus AIS_Selection::AddSelect(const Handle(Standard_Transient)& anObject)
295 Handle(AIS_Selection) S;
296 AIS_Sel_CurrentSelection (S);
297 if(S.IsNull()) return AIS_SS_NotDone;
300 TColStd_Array1OfTransient& arr = S->myresult->ChangeArray1();
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);
308 S->myresult = NiouTab;
311 S->myresult->SetValue(S->myNb,anObject);
312 #elif !defined USE_MAP //OCC189
313 S->myresult.Append( anObject );
315 if ( S->myResultMap.IsBound( anObject ) )
316 return AIS_SS_NotDone;
318 AIS_NListTransient::Iterator aListIter;
319 S->myresult.Append( anObject, aListIter );
320 S->myResultMap.Bind( anObject, aListIter );
326 //=======================================================================
327 //function : ClearAndSelect
329 //=======================================================================
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;
342 //=======================================================================
345 //=======================================================================
346 Standard_Integer AIS_Selection::Extent() {
347 Handle(AIS_Selection) S;
348 AIS_Sel_CurrentSelection (S);
349 #if !defined OCC189 && !defined USE_MAP
352 return S->myresult.Extent();
356 //=======================================================================
359 //=======================================================================
360 Handle(Standard_Transient) AIS_Selection::Single()
362 Handle(AIS_Selection) S;
363 AIS_Sel_CurrentSelection (S);
368 //=======================================================================
369 //function : IsSelected
371 //=======================================================================
372 Standard_Boolean AIS_Selection::IsSelected(const Handle(Standard_Transient)& anObject)
374 Handle(AIS_Selection) S;
375 AIS_Sel_CurrentSelection (S);
376 if(S.IsNull()) return Standard_False;
378 for(S->Init();S->More();S->Next()){
379 if(S->Value()==anObject)
380 return Standard_True;
382 return Standard_False;
384 return S->myResultMap.IsBound( anObject );
388 //=======================================================================
391 //=======================================================================
393 Standard_Integer AIS_Selection::Index(const Standard_CString aName)
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))
404 //=======================================================================
407 //=======================================================================
409 void AIS_Selection::Remove(const Standard_CString aName)
411 Standard_Integer I = AIS_Selection::Index(aName);
414 Handle(AIS_Selection) selection = Handle(AIS_Selection)::DownCast( AIS_Sel_GetSelections().Value(I) );
415 Standard_Integer stored = selection->NbStored();
419 AIS_Sel_GetSelections().Remove(I);