0032205: Visualization - implementing new selection scheme in context - replace extra
[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.hxx>
16
17 #include <AIS_InteractiveObject.hxx>
18 #include <AIS_SelectionScheme.hxx>
19 #include <SelectMgr_Filter.hxx>
20
21 IMPLEMENT_STANDARD_RTTIEXT(AIS_Selection, Standard_Transient)
22
23 namespace
24 {
25   static const Standard_Integer THE_MaxSizeOfResult = 100000;
26 }
27
28 //=======================================================================
29 //function : AIS_Selection
30 //purpose  :
31 //=======================================================================
32 AIS_Selection::AIS_Selection()
33 {
34   // for maximum performance on medium selections (< 100000 objects)
35   myResultMap.ReSize (THE_MaxSizeOfResult);
36 }
37
38 //=======================================================================
39 //function : Clear
40 //purpose  :
41 //=======================================================================
42 void AIS_Selection::Clear()
43 {
44   for (AIS_NListOfEntityOwner::Iterator aSelIter (Objects()); aSelIter.More(); aSelIter.Next())
45   {
46     const Handle(SelectMgr_EntityOwner) anObject = aSelIter.Value();
47     anObject->SetSelected (Standard_False);
48   }
49   myresult.Clear();
50   myResultMap.Clear();
51   myIterator = AIS_NListOfEntityOwner::Iterator();
52 }
53
54 //=======================================================================
55 //function : Select
56 //purpose  :
57 //=======================================================================
58 AIS_SelectStatus AIS_Selection::Select (const Handle(SelectMgr_EntityOwner)& theObject)
59 {
60   if (theObject.IsNull()
61   || !theObject->HasSelectable())
62   {
63     return AIS_SS_NotDone;
64   }
65
66   if (!myResultMap.IsBound (theObject))
67   {
68     AIS_NListOfEntityOwner::Iterator aListIter;
69     myresult.Append  (theObject, aListIter);
70     myResultMap.Bind (theObject, aListIter);
71     theObject->SetSelected (Standard_True);
72     return AIS_SS_Added;
73   }
74
75   AIS_NListOfEntityOwner::Iterator aListIter = myResultMap.Find (theObject);
76   if (myIterator == aListIter)
77   {
78     if (myIterator.More())
79     {
80       myIterator.Next();
81     }
82     else
83     {
84       myIterator = AIS_NListOfEntityOwner::Iterator();
85     }
86   }
87
88   // In the mode of advanced mesh selection only one owner is created for all selection modes.
89   // It is necessary to check the current detected entity
90   // and remove the owner from map only if the detected entity is the same as previous selected (IsForcedHilight call)
91   if (theObject->IsForcedHilight())
92   {
93     return AIS_SS_Added;
94   }
95
96   myresult.Remove (aListIter);
97   myResultMap.UnBind (theObject);
98   theObject->SetSelected (Standard_False);
99
100   // update list iterator for next object in <myresult> list if any
101   if (aListIter.More())
102   {
103     const Handle(SelectMgr_EntityOwner)& aNextObject = aListIter.Value();
104     if (myResultMap.IsBound (aNextObject))
105     {
106       myResultMap (aNextObject) = aListIter;
107     }
108     else
109     {
110       myResultMap.Bind (aNextObject, aListIter);
111     }
112   }
113   return AIS_SS_Removed;
114 }
115
116 //=======================================================================
117 //function : AddSelect
118 //purpose  :
119 //=======================================================================
120 AIS_SelectStatus AIS_Selection::AddSelect (const Handle(SelectMgr_EntityOwner)& theObject)
121 {
122   if (theObject.IsNull()
123   || !theObject->HasSelectable()
124   ||  myResultMap.IsBound (theObject))
125   {
126     return AIS_SS_NotDone;
127   }
128
129   AIS_NListOfEntityOwner::Iterator aListIter;
130   myresult.Append  (theObject, aListIter);
131   myResultMap.Bind (theObject, aListIter);
132   theObject->SetSelected (Standard_True);
133   return AIS_SS_Added;
134 }
135
136 //=======================================================================
137 //function : SelectOwners
138 //purpose  :
139 //=======================================================================
140 void AIS_Selection::SelectOwners (const AIS_NArray1OfEntityOwner& thePickedOwners,
141                                   const AIS_SelectionScheme theSelScheme,
142                                   const Standard_Boolean theToAllowSelOverlap,
143                                   const Handle(SelectMgr_Filter)& theFilter)
144 {
145   (void )theToAllowSelOverlap;
146   switch (theSelScheme)
147   {
148     case AIS_SelectionScheme_UNKNOWN:
149     {
150       return;
151     }
152     case AIS_SelectionScheme_ReplaceExtra:
153     {
154       // If picked owners is equivalent to the selected then just clear selected
155       // Else go to AIS_SelectionScheme_Replace
156       if (thePickedOwners.Size() == myresult.Size())
157       {
158         Standard_Boolean isTheSame = Standard_True;
159         for (AIS_NArray1OfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next())
160         {
161           if (!myResultMap.IsBound (aSelIter.Value()))
162           {
163             isTheSame = Standard_False;
164             break;
165           }
166         }
167         if (isTheSame)
168         {
169           Clear();
170           return;
171         }
172       }
173     }
174     Standard_FALLTHROUGH
175     case AIS_SelectionScheme_Replace:
176     {
177       Clear();
178       for (AIS_NArray1OfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next())
179       {
180         appendOwner (aSelIter.Value(), theFilter);
181       }
182
183       return;
184     }
185     case AIS_SelectionScheme_Add:
186     {
187       for (AIS_NArray1OfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next())
188       {
189         appendOwner (aSelIter.Value(), theFilter);
190       }
191       return;
192     }
193     case AIS_SelectionScheme_Remove:
194     {
195       for (AIS_NArray1OfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next())
196       {
197         if (myResultMap.IsBound (aSelIter.Value()))
198         {
199           Select (aSelIter.Value());
200         }
201       }
202       return;
203     }
204     case AIS_SelectionScheme_XOR:
205     {
206       for (AIS_NArray1OfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next())
207       {
208         const Handle(SelectMgr_EntityOwner)& anOwner = aSelIter.Value();
209         if (anOwner.IsNull()
210         || !anOwner->HasSelectable()
211         || !theFilter->IsOk (anOwner))
212         {
213           continue;
214         }
215
216         Select (anOwner);
217       }
218       return;
219     }
220     case AIS_SelectionScheme_Clear:
221     {
222       Clear();
223       return;
224     }
225   }
226 }
227
228 //=======================================================================
229 //function : appendOwner
230 //purpose  :
231 //=======================================================================
232 AIS_SelectStatus AIS_Selection::appendOwner (const Handle(SelectMgr_EntityOwner)& theOwner,
233                                              const Handle(SelectMgr_Filter)& theFilter)
234 {
235   if (theOwner.IsNull()
236   || !theOwner->HasSelectable()
237   || !theFilter->IsOk (theOwner))
238   {
239     return AIS_SS_NotDone;
240   }
241
242   return AddSelect (theOwner);
243 }