6684a35586990ef376884234d2c4ba2370b26461
[occt.git] / src / AIS / AIS_InteractiveContext_1.cxx
1 // Created on: 1997-01-29
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <AIS_DataMapIteratorOfDataMapOfIOStatus.hxx>
19 #include <AIS_GlobalStatus.hxx>
20 #include <AIS_InteractiveContext.hxx>
21 #include <AIS_InteractiveObject.hxx>
22 #include <AIS_MapIteratorOfMapOfInteractive.hxx>
23 #include <AIS_MapOfInteractive.hxx>
24 #include <AIS_Selection.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_StatusOfDetection.hxx>
27 #include <AIS_StatusOfPick.hxx>
28 #include <Aspect_Grid.hxx>
29 #include <Prs3d_BasicAspect.hxx>
30 #include <Prs3d_LineAspect.hxx>
31 #include <Prs3d_Presentation.hxx>
32 #include <Quantity_Color.hxx>
33 #include <Select3D_SensitiveEntity.hxx>
34 #include <SelectMgr_EntityOwner.hxx>
35 #include <SelectMgr_Filter.hxx>
36 #include <SelectMgr_OrFilter.hxx>
37 #include <SelectMgr_Selection.hxx>
38 #include <SelectMgr_SelectionManager.hxx>
39 #include <Standard_Transient.hxx>
40 #include <StdSelect_BRepOwner.hxx>
41 #include <StdSelect_ViewerSelector3d.hxx>
42 #include <TCollection_AsciiString.hxx>
43 #include <TCollection_ExtendedString.hxx>
44 #include <TColStd_ListIteratorOfListOfInteger.hxx>
45 #include <TopLoc_Location.hxx>
46 #include <V3d_AmbientLight.hxx>
47 #include <V3d_DirectionalLight.hxx>
48 #include <V3d_Light.hxx>
49 #include <V3d_PositionalLight.hxx>
50 #include <V3d_SpotLight.hxx>
51 #include <V3d_View.hxx>
52 #include <V3d_Viewer.hxx>
53
54 typedef NCollection_DataMap<Handle(AIS_InteractiveObject), NCollection_Handle<SelectMgr_SequenceOfOwner> > AIS_MapOfObjSelectedOwners;
55
56 namespace
57 {
58   TopoDS_Shape AIS_InteractiveContext_myDummyShape;
59 }
60
61 //=======================================================================
62 //function : highlightWithColor
63 //purpose  :
64 //=======================================================================
65 void AIS_InteractiveContext::highlightWithColor (const Handle(SelectMgr_EntityOwner)& theOwner,
66                                                  const Handle(V3d_Viewer)& theViewer)
67 {
68   const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable());
69   if (anObj.IsNull())
70   {
71     return;
72   }
73
74   const Handle(Prs3d_Drawer)& aStyle = getHiStyle (anObj, theOwner);
75   const Standard_Integer aHiMode = getHilightMode (anObj, aStyle, -1);
76
77   myMainPM->BeginImmediateDraw();
78   theOwner->HilightWithColor (myMainPM, aStyle, aHiMode);
79   myMainPM->EndImmediateDraw (theViewer.IsNull() ? myMainVwr : theViewer);
80 }
81
82 //=======================================================================
83 //function : highlightSelected
84 //purpose  :
85 //=======================================================================
86 void AIS_InteractiveContext::highlightSelected (const Handle(SelectMgr_EntityOwner)& theOwner)
87 {
88   const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable());
89   if (anObj.IsNull())
90   {
91     return;
92   }
93
94   if (!theOwner->IsAutoHilight())
95   {
96     SelectMgr_SequenceOfOwner aSeq;
97     for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
98     {
99       if (aSelIter.Value()->IsSameSelectable (anObj))
100       {
101         aSeq.Append (aSelIter.Value());
102       }
103     }
104     anObj->HilightSelected (myMainPM, aSeq);
105   }
106   else
107   {
108     const Handle(Prs3d_Drawer)& aStyle = getSelStyle (anObj, theOwner);
109     const Standard_Integer aHiMode = getHilightMode (anObj, aStyle, -1);
110     theOwner->HilightWithColor (myMainPM, aStyle, aHiMode);
111   }
112 }
113
114 //=======================================================================
115 //function : highlightGlobal
116 //purpose  :
117 //=======================================================================
118 void AIS_InteractiveContext::highlightGlobal (const Handle(AIS_InteractiveObject)& theObj,
119                                               const Handle(Prs3d_Drawer)& theStyle,
120                                               const Standard_Integer theDispMode) const
121 {
122   if (theObj.IsNull())
123   {
124     return;
125   }
126
127   const Standard_Integer aHiMode = getHilightMode (theObj, theStyle, theDispMode);
128   const Handle(SelectMgr_EntityOwner)& aGlobOwner = theObj->GlobalSelOwner();
129
130   if (aGlobOwner.IsNull())
131   {
132     myMainPM->Color (theObj, theStyle, aHiMode);
133     return;
134   }
135
136   if (!aGlobOwner->IsAutoHilight())
137   {
138     SelectMgr_SequenceOfOwner aSeq;
139     for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
140     {
141       if (aSelIter.Value()->IsSameSelectable (theObj))
142       {
143         aSeq.Append (aSelIter.Value());
144       }
145     }
146     theObj->HilightSelected (myMainPM, aSeq);
147   }
148   else
149   {
150     aGlobOwner->HilightWithColor (myMainPM, theStyle, aHiMode);
151   }
152 }
153
154 //=======================================================================
155 //function : unhighlightSelected
156 //purpose  :
157 //=======================================================================
158 void AIS_InteractiveContext::unhighlightSelected (const Standard_Boolean theIsToHilightSubIntensity)
159 {
160   NCollection_IndexedMap<Handle(AIS_InteractiveObject)> anObjToClear;
161   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
162   {
163     const Handle(SelectMgr_EntityOwner) anOwner = aSelIter.Value();
164     const Handle(AIS_InteractiveObject) anInteractive = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
165     Handle(AIS_GlobalStatus) aStatus;
166     if (!myObjects.Find (anInteractive, aStatus))
167     {
168       continue;
169     }
170
171     if (anOwner->IsAutoHilight())
172     {
173       anOwner->Unhilight (myMainPM);
174       if (theIsToHilightSubIntensity)
175       {
176         if (aStatus->IsSubIntensityOn())
177         {
178           const Standard_Integer aHiMode = getHilightMode (anInteractive, aStatus->HilightStyle(), aStatus->DisplayMode());
179           highlightWithSubintensity (anOwner, aHiMode);
180         }
181       }
182     }
183     else
184     {
185       anObjToClear.Add (anInteractive);
186     }
187     if (anOwner == anInteractive->GlobalSelOwner())
188     {
189       myObjects.ChangeFind (anInteractive)->SetHilightStatus (Standard_False);
190     }
191   }
192   for (NCollection_IndexedMap<Handle(AIS_InteractiveObject)>::Iterator anIter (anObjToClear); anIter.More(); anIter.Next())
193   {
194     const Handle(AIS_InteractiveObject)& anObj = anIter.Value();
195     myMainPM->Unhighlight (anObj);
196     anObj->ClearSelected();
197   }
198 }
199
200 //=======================================================================
201 //function : unhighlightGlobal
202 //purpose  :
203 //=======================================================================
204 void AIS_InteractiveContext::unhighlightGlobal (const Handle(AIS_InteractiveObject)& theObj) const
205 {
206   if (theObj.IsNull())
207   {
208     return;
209   }
210
211   const Handle(SelectMgr_EntityOwner)& aGlobOwner = theObj->GlobalSelOwner();
212   if (aGlobOwner.IsNull())
213   {
214     myMainPM->Unhighlight (theObj);
215     return;
216   }
217
218   if (aGlobOwner->IsAutoHilight())
219   {
220     aGlobOwner->Unhilight (myMainPM);
221   }
222   else
223   {
224     myMainPM->Unhighlight (theObj);
225     theObj->ClearSelected();
226   }
227 }
228
229 //=======================================================================
230 //function : turnOnSubintensity
231 //purpose  :
232 //=======================================================================
233 void AIS_InteractiveContext::turnOnSubintensity (const Handle(AIS_InteractiveObject)& theObject,
234                                                  const Standard_Integer theDispMode,
235                                                  const Standard_Boolean theIsDisplayedOnly) const
236 {
237   // the only differ with selection highlight is color, so sync transparency values
238   const Handle(Prs3d_Drawer)& aSubStyle = myStyles[Prs3d_TypeOfHighlight_SubIntensity];
239   aSubStyle->SetTransparency (myStyles[Prs3d_TypeOfHighlight_Selected]->Transparency());
240
241   if (theObject.IsNull())
242   {
243     for (AIS_DataMapIteratorOfDataMapOfIOStatus anObjsIter (myObjects); anObjsIter.More(); anObjsIter.Next())
244     {
245       const Handle(AIS_GlobalStatus)& aStatus = anObjsIter.Value();
246       if (aStatus->GraphicStatus() != AIS_DS_Displayed && theIsDisplayedOnly)
247         continue;
248
249       aStatus->SubIntensityOn();
250       myMainPM->Color (anObjsIter.Key(), aSubStyle, theDispMode != -1 ? theDispMode : aStatus->DisplayMode());
251     }
252   }
253   else
254   {
255     Handle(AIS_GlobalStatus) aStatus;
256     if (!myObjects.Find (theObject, aStatus))
257       return;
258
259     if (aStatus->GraphicStatus() != AIS_DS_Displayed && theIsDisplayedOnly)
260       return;
261
262     aStatus->SubIntensityOn();
263     myMainPM->Color (theObject, aSubStyle, theDispMode != -1 ? theDispMode : aStatus->DisplayMode());
264   }
265 }
266
267 //=======================================================================
268 //function : highlightWithSubintensity
269 //purpose  :
270 //=======================================================================
271 void AIS_InteractiveContext::highlightWithSubintensity (const Handle(AIS_InteractiveObject)& theObject,
272                                                         const Standard_Integer theMode) const
273 {
274   // the only differ with selection highlight is color, so
275   // sync transparency values
276   myStyles[Prs3d_TypeOfHighlight_SubIntensity]->SetTransparency (myStyles[Prs3d_TypeOfHighlight_Selected]->Transparency());
277
278   myMainPM->Color (theObject, myStyles[Prs3d_TypeOfHighlight_SubIntensity], theMode);
279 }
280
281 //=======================================================================
282 //function : highlightWithSubintensity
283 //purpose  :
284 //=======================================================================
285 void AIS_InteractiveContext::highlightWithSubintensity (const Handle(SelectMgr_EntityOwner)& theOwner,
286                                                         const Standard_Integer theMode) const
287 {
288   // the only differ with selection highlight is color, so
289   // sync transparency values
290   myStyles[Prs3d_TypeOfHighlight_SubIntensity]->SetTransparency (myStyles[Prs3d_TypeOfHighlight_Selected]->Transparency());
291
292   theOwner->HilightWithColor (myMainPM, myStyles[Prs3d_TypeOfHighlight_SubIntensity], theMode);
293 }
294
295 //=======================================================================
296 //function : isSlowHiStyle
297 //purpose  :
298 //=======================================================================
299 Standard_Boolean AIS_InteractiveContext::isSlowHiStyle (const Handle(SelectMgr_EntityOwner)& theOwner,
300                                                         const Handle(V3d_Viewer)& theViewer) const
301 {
302   if (const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable()))
303   {
304     const Handle(Prs3d_Drawer)& aHiStyle = getHiStyle (anObj, myLastPicked);
305     return aHiStyle->ZLayer() == Graphic3d_ZLayerId_UNKNOWN
306        || !theViewer->ZLayerSettings (aHiStyle->ZLayer()).IsImmediate();
307   }
308   return Standard_False;
309 }
310
311 //=======================================================================
312 //function : MoveTo
313 //purpose  :
314 //=======================================================================
315 AIS_StatusOfDetection AIS_InteractiveContext::MoveTo (const Standard_Integer  theXPix,
316                                                       const Standard_Integer  theYPix,
317                                                       const Handle(V3d_View)& theView,
318                                                       const Standard_Boolean  theToRedrawOnUpdate)
319 {
320   if (theView->Viewer() != myMainVwr)
321   {
322     throw Standard_ProgramError ("AIS_InteractiveContext::MoveTo() - invalid argument");
323   }
324
325   myCurDetected = 0;
326   myCurHighlighted = 0;
327   myDetectedSeq.Clear();
328   myLastActiveView = theView.get();
329
330   // preliminaires
331   AIS_StatusOfDetection aStatus        = AIS_SOD_Nothing;
332   Standard_Boolean      toUpdateViewer = Standard_False;
333
334   myFilters->SetDisabledObjects (theView->View()->HiddenObjects());
335   myMainSel->Pick (theXPix, theYPix, theView);
336
337   // filling of myAISDetectedSeq sequence storing information about detected AIS objects
338   // (the objects must be AIS_Shapes)
339   const Standard_Integer aDetectedNb = myMainSel->NbPicked();
340   Standard_Integer aNewDetected = 0;
341   Standard_Boolean toIgnoreDetTop = Standard_False;
342   for (Standard_Integer aDetIter = 1; aDetIter <= aDetectedNb; ++aDetIter)
343   {
344     Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aDetIter);
345     if (anOwner.IsNull()
346      || !myFilters->IsOk (anOwner))
347     {
348       if (myPickingStrategy == SelectMgr_PickingStrategy_OnlyTopmost)
349       {
350         toIgnoreDetTop = Standard_True;
351       }
352       continue;
353     }
354
355     if (aNewDetected < 1
356     && !toIgnoreDetTop)
357     {
358       aNewDetected = aDetIter;
359     }
360
361     myDetectedSeq.Append (aDetIter);
362   }
363
364   if (aNewDetected >= 1)
365   {
366     myCurHighlighted = myDetectedSeq.Lower();
367
368     // Does nothing if previously detected object is equal to the current one.
369     // However in advanced selection modes the owners comparison
370     // is not effective because in that case only one owner manage the
371     // selection in current selection mode. It is necessary to check the current detected
372     // entity and hilight it only if the detected entity is not the same as
373     // previous detected (IsForcedHilight call)
374     Handle(SelectMgr_EntityOwner) aNewPickedOwner = myMainSel->Picked (aNewDetected);
375     if (aNewPickedOwner == myLastPicked && !aNewPickedOwner->IsForcedHilight())
376     {
377       return myLastPicked->IsSelected()
378            ? AIS_SOD_Selected
379            : AIS_SOD_OnlyOneDetected;
380     }
381  
382     // Previously detected object is unhilighted if it is not selected or hilighted 
383     // with selection color if it is selected. Such highlighting with selection color 
384     // is needed only if myToHilightSelected flag is true. In this case previously detected
385     // object has been already highlighted with myHilightColor during previous MoveTo() 
386     // method call. As result it is necessary to rehighligt it with mySelectionColor.
387     if (!myLastPicked.IsNull() && myLastPicked->HasSelectable())
388     {
389       if (isSlowHiStyle (myLastPicked, theView->Viewer()))
390       {
391         theView->Viewer()->Invalidate();
392       }
393
394       clearDynamicHighlight();
395       toUpdateViewer = Standard_True;
396     }
397
398     // initialize myLastPicked field with currently detected object
399     myLastPicked = aNewPickedOwner;
400
401     // highlight detected object if it is not selected or myToHilightSelected flag is true
402     if (myLastPicked->HasSelectable())
403     {
404       if (myAutoHilight
405        && (!myLastPicked->IsSelected()
406          || myToHilightSelected))
407       {
408         if (isSlowHiStyle (myLastPicked, theView->Viewer()))
409         {
410           theView->Viewer()->Invalidate();
411         }
412
413         highlightWithColor (myLastPicked, theView->Viewer());
414         toUpdateViewer = Standard_True;
415       }
416
417       aStatus = myLastPicked->IsSelected()
418               ? AIS_SOD_Selected
419               : AIS_SOD_OnlyOneDetected;
420     }
421   }
422   else
423   {
424     // previously detected object is unhilighted if it is not selected or hilighted
425     // with selection color if it is selected
426     aStatus = AIS_SOD_Nothing;
427     if (myAutoHilight
428     && !myLastPicked.IsNull()
429      && myLastPicked->HasSelectable())
430     {
431       if (isSlowHiStyle (myLastPicked, theView->Viewer()))
432       {
433         theView->Viewer()->Invalidate();
434       }
435
436       clearDynamicHighlight();
437       toUpdateViewer = Standard_True;
438     }
439
440     myLastPicked.Nullify();
441   }
442
443   if (toUpdateViewer
444    && theToRedrawOnUpdate)
445   {
446     if (theView->ComputedMode())
447     {
448       theView->Viewer()->Update();
449     }
450     else
451     {
452       if (theView->IsInvalidated())
453       {
454         theView->Viewer()->Redraw();
455       }
456       else
457       {
458         theView->Viewer()->RedrawImmediate();
459       }
460     }
461   }
462
463   return aStatus;
464 }
465
466 //=======================================================================
467 //function : AddSelect
468 //purpose  : 
469 //=======================================================================
470 AIS_StatusOfPick AIS_InteractiveContext::AddSelect (const Handle(SelectMgr_EntityOwner)& theObject)
471 {
472   mySelection->AddSelect (theObject);
473
474   Standard_Integer aSelNum = NbSelected();
475   return (aSelNum == 0) ? AIS_SOP_NothingSelected
476                         : (aSelNum == 1) ? AIS_SOP_OneSelected
477                                          : AIS_SOP_SeveralSelected;
478 }
479
480 //=======================================================================
481 //function : Select
482 //purpose  : 
483 //=======================================================================
484 AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Integer  theXPMin,
485                                                  const Standard_Integer  theYPMin,
486                                                  const Standard_Integer  theXPMax,
487                                                  const Standard_Integer  theYPMax,
488                                                  const Handle(V3d_View)& theView,
489                                                  const Standard_Boolean  toUpdateViewer)
490 {
491   if (theView->Viewer() != myMainVwr)
492   {
493     throw Standard_ProgramError ("AIS_InteractiveContext::Select() - invalid argument");
494   }
495
496   // all objects detected by the selector are taken, previous current objects are emptied,
497   // new objects are put...
498   ClearSelected (Standard_False);
499   myLastActiveView = theView.get();
500   myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
501   for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
502   {
503     const Handle(SelectMgr_EntityOwner)& aCurOwner = myMainSel->Picked (aPickIter);
504     if (aCurOwner.IsNull() || !aCurOwner->HasSelectable() || !myFilters->IsOk (aCurOwner))
505       continue;
506
507     mySelection->Select (aCurOwner);
508   }
509
510   if (myAutoHilight)
511   {
512     HilightSelected (toUpdateViewer);
513   }
514
515   Standard_Integer aSelNum = NbSelected();
516
517   return (aSelNum == 0) ? AIS_SOP_NothingSelected
518                         : (aSelNum == 1) ? AIS_SOP_OneSelected
519                                          : AIS_SOP_SeveralSelected;
520   
521 }
522
523 //=======================================================================
524 //function : Select
525 //purpose  : Selection by polyline
526 //=======================================================================
527 AIS_StatusOfPick AIS_InteractiveContext::Select (const TColgp_Array1OfPnt2d& thePolyline,
528                                                  const Handle(V3d_View)&     theView,
529                                                  const Standard_Boolean      toUpdateViewer)
530 {
531   if (theView->Viewer() != myMainVwr)
532   {
533     throw Standard_ProgramError ("AIS_InteractiveContext::Select() - invalid argument");
534   }
535
536   // all objects detected by the selector are taken, previous current objects are emptied,
537   // new objects are put...
538   ClearSelected (Standard_False);
539   myLastActiveView = theView.get();
540   myMainSel->Pick (thePolyline, theView);
541   for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
542   {
543     const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter);
544     if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner))
545       continue;
546
547     mySelection->Select (anOwner);
548   }
549
550   if (myAutoHilight)
551   {
552     HilightSelected (toUpdateViewer);
553   }
554
555   Standard_Integer aSelNum = NbSelected();
556
557   return (aSelNum == 0) ? AIS_SOP_NothingSelected
558                         : (aSelNum == 1) ? AIS_SOP_OneSelected
559                                          : AIS_SOP_SeveralSelected;
560   
561 }
562
563 //=======================================================================
564 //function : Select
565 //purpose  : 
566 //=======================================================================
567 AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean toUpdateViewer)
568 {
569   if (!myLastPicked.IsNull())
570   {
571     Graphic3d_Vec2i aMousePos (-1, -1);
572     if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
573     {
574       aMousePos.SetValues ((Standard_Integer )myMainSel->GetManager().GetMousePosition().X(),
575                            (Standard_Integer )myMainSel->GetManager().GetMousePosition().Y());
576     }
577     if (myLastPicked->HandleMouseClick (aMousePos, Aspect_VKeyMouse_LeftButton, Aspect_VKeyFlags_NONE, false))
578     {
579       return AIS_SOP_NothingSelected;
580     }
581
582     if (myAutoHilight)
583     {
584       clearDynamicHighlight();
585     }
586     if (!myLastPicked->IsSelected()
587       || myLastPicked->IsForcedHilight()
588       || NbSelected() > 1)
589     {
590       SetSelected (myLastPicked, Standard_False);
591       if(toUpdateViewer)
592       {
593         UpdateCurrentViewer();
594       }
595     }
596   }
597   else
598   {
599     ClearSelected (toUpdateViewer);
600   }
601
602   Standard_Integer aSelNum = NbSelected();
603
604   return (aSelNum == 0) ? AIS_SOP_NothingSelected
605                         : (aSelNum == 1) ? AIS_SOP_OneSelected
606                                          : AIS_SOP_SeveralSelected;
607 }
608
609 //=======================================================================
610 //function : ShiftSelect
611 //purpose  : 
612 //=======================================================================
613 AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Boolean toUpdateViewer)
614 {
615   if (myAutoHilight)
616   {
617     clearDynamicHighlight();
618   }
619   if (!myLastPicked.IsNull())
620   {
621     AddOrRemoveSelected (myLastPicked, toUpdateViewer);
622   }
623
624   Standard_Integer aSelNum = NbSelected();
625
626   return (aSelNum == 0) ? AIS_SOP_NothingSelected
627                         : (aSelNum == 1) ? AIS_SOP_OneSelected
628                         : AIS_SOP_SeveralSelected;
629 }
630
631 //=======================================================================
632 //function : ShiftSelect
633 //purpose  : 
634 //=======================================================================
635 AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Integer theXPMin,
636                                                       const Standard_Integer theYPMin,
637                                                       const Standard_Integer theXPMax,
638                                                       const Standard_Integer theYPMax,
639                                                       const Handle(V3d_View)& theView,
640                                                       const Standard_Boolean toUpdateViewer)
641 {
642   if (theView->Viewer() != myMainVwr)
643   {
644     throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument");
645   }
646
647   myLastActiveView = theView.get();
648   if (myAutoHilight)
649   {
650     UnhilightSelected (Standard_False);
651   }
652   myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
653   for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
654   {
655     const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter);
656     if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner))
657       continue;
658
659     mySelection->Select (anOwner);
660   }
661
662   if (myAutoHilight)
663   {
664     HilightSelected (toUpdateViewer);
665   }
666
667   Standard_Integer aSelNum = NbSelected();
668
669   return (aSelNum == 0) ? AIS_SOP_NothingSelected
670                         : (aSelNum == 1) ? AIS_SOP_OneSelected
671                                          : AIS_SOP_SeveralSelected;
672
673 }
674
675 //=======================================================================
676 //function : ShiftSelect
677 //purpose  : 
678 //=======================================================================
679 AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const TColgp_Array1OfPnt2d& thePolyline,
680                                                       const Handle(V3d_View)& theView,
681                                                       const Standard_Boolean toUpdateViewer)
682 {
683   if (theView->Viewer() != myMainVwr)
684   {
685     throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument");
686   }
687
688   myLastActiveView = theView.get();
689   if (myAutoHilight)
690   {
691     UnhilightSelected (Standard_False);
692   }
693   myMainSel->Pick (thePolyline, theView);
694   for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter)
695   {
696     const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter);
697     if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner))
698       continue;
699
700     mySelection->Select (anOwner);
701   }
702
703   if (myAutoHilight)
704   {
705     HilightSelected (toUpdateViewer);
706   }
707
708   Standard_Integer aSelNum = NbSelected();
709
710   return (aSelNum == 0) ? AIS_SOP_NothingSelected
711                         : (aSelNum == 1) ? AIS_SOP_OneSelected
712                                          : AIS_SOP_SeveralSelected;
713 }
714
715 //=======================================================================
716 //function : HilightSelected
717 //purpose  :
718 //=======================================================================
719 void AIS_InteractiveContext::HilightSelected (const Standard_Boolean theToUpdateViewer)
720 {
721   // In case of selection without using local context
722   clearDynamicHighlight();
723   AIS_MapOfObjSelectedOwners anObjOwnerMap;
724   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
725   {
726     const Handle(SelectMgr_EntityOwner) anOwner = aSelIter.Value();
727     const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
728     const Handle(Prs3d_Drawer)& anObjSelStyle = getSelStyle (anObj, anOwner);
729     Handle(AIS_GlobalStatus)& aState = myObjects.ChangeFind(anObj);
730     if (anOwner == anObj->GlobalSelOwner())
731     {
732       aState->SetHilightStatus (Standard_True);
733       aState->SetHilightStyle (anObjSelStyle);
734     }
735     if (!anOwner->IsAutoHilight())
736     {
737       NCollection_Handle<SelectMgr_SequenceOfOwner> aSeq;
738       if (anObjOwnerMap.Find (anObj, aSeq))
739       {
740         aSeq->Append (anOwner);
741       }
742       else
743       {
744         aSeq = new SelectMgr_SequenceOfOwner();
745         aSeq->Append (anOwner);
746         anObjOwnerMap.Bind (anObj, aSeq);
747       }
748     }
749     else
750     {
751       const Standard_Integer aHiMode = getHilightMode (anObj, anObjSelStyle, aState->DisplayMode());
752       anOwner->HilightWithColor (myMainPM, anObjSelStyle, aHiMode);
753     }
754   }
755
756   if (!anObjOwnerMap.IsEmpty())
757   {
758     for (AIS_MapOfObjSelectedOwners::Iterator anIter (anObjOwnerMap); anIter.More(); anIter.Next())
759     {
760       anIter.Key()->HilightSelected (myMainPM, *anIter.Value());
761     }
762     anObjOwnerMap.Clear();
763   }
764
765   if (theToUpdateViewer)
766     UpdateCurrentViewer();
767 }
768
769 //=======================================================================
770 //function : UnhilightSelected
771 //purpose  :
772 //=======================================================================
773 void AIS_InteractiveContext::UnhilightSelected (const Standard_Boolean theToUpdateViewer)
774 {
775   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
776   {
777     const Handle(SelectMgr_EntityOwner) anOwner = aSelIter.Value();
778     const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
779     if (anOwner == anObj->GlobalSelOwner())
780     {
781       myObjects.ChangeFind (anObj)->SetHilightStatus (Standard_False);
782     }
783
784     anOwner->Unhilight (myMainPM);
785   }
786
787   if (theToUpdateViewer)
788     UpdateCurrentViewer();
789 }
790
791
792 //=======================================================================
793 //function : ClearSelected
794 //purpose  :
795 //=======================================================================
796 void AIS_InteractiveContext::ClearSelected (const Standard_Boolean theToUpdateViewer)
797 {
798   if (NbSelected() == 0)
799     return;
800
801   if (myAutoHilight)
802   {
803     unhighlightSelected();
804   }
805
806   mySelection->Clear();
807   if (myAutoHilight)
808   {
809     clearDynamicHighlight();
810   }
811
812   if (theToUpdateViewer)
813     UpdateCurrentViewer();
814 }
815
816 //=======================================================================
817 //function : SetSelected
818 //purpose  : Sets the whole object as selected and highlights it with selection color
819 //=======================================================================
820 void AIS_InteractiveContext::SetSelected (const Handle(AIS_InteractiveObject)& theObject,
821                                           const Standard_Boolean theToUpdateViewer)
822 {
823   if (theObject.IsNull())
824   {
825     return;
826   }
827
828   if (!myObjects.IsBound (theObject))
829   {
830     return;
831   }
832
833   Handle(SelectMgr_EntityOwner) anOwner = theObject->GlobalSelOwner();
834   if (anOwner.IsNull())
835   {
836     return;
837   }
838
839   const Handle(Prs3d_Drawer)& anObjSelStyle = getSelStyle (theObject, anOwner);
840   if (NbSelected() == 1 && myObjects (theObject)->IsHilighted() && myAutoHilight)
841   {
842     Handle(Prs3d_Drawer) aCustomStyle;
843     if (HighlightStyle (theObject, aCustomStyle))
844     {
845       if (!aCustomStyle.IsNull() && anObjSelStyle != aCustomStyle)
846       {
847         HilightWithColor (theObject, anObjSelStyle, theToUpdateViewer);
848       }
849     }
850     return;
851   }
852
853   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
854   {
855     const Handle(SelectMgr_EntityOwner)& aSelOwner = aSelIter.Value();
856     if (!myFilters->IsOk (aSelOwner))
857     {
858       continue;
859     }
860
861     Handle(AIS_InteractiveObject) aSelectable = Handle(AIS_InteractiveObject)::DownCast (aSelOwner->Selectable());
862     if (myAutoHilight)
863     {
864       Unhilight (aSelectable, Standard_False);
865     }
866     if (aSelOwner == aSelectable->GlobalSelOwner())
867     {
868       myObjects.ChangeFind (aSelectable)->SetHilightStatus (Standard_False);
869     }
870   }
871
872   // added to avoid untimely viewer update...
873   mySelection->ClearAndSelect (anOwner);
874
875   if (myAutoHilight)
876   {
877     Handle(Prs3d_Drawer) aCustomStyle;
878     if (HighlightStyle (theObject, aCustomStyle))
879     {
880       if (!aCustomStyle.IsNull() && anObjSelStyle != aCustomStyle)
881       {
882         HilightWithColor (theObject, anObjSelStyle, Standard_False);
883       }
884     }
885     else
886     {
887       HilightWithColor (theObject, anObjSelStyle, Standard_False);
888     }
889   }
890
891   if (theToUpdateViewer)
892     UpdateCurrentViewer();
893 }
894
895 //=======================================================================
896 //function : SetSelected
897 //purpose  : Sets the whole object as selected and highlights it with selection color
898 //=======================================================================
899 void AIS_InteractiveContext::SetSelected (const Handle(SelectMgr_EntityOwner)& theOwner,
900                                           const Standard_Boolean theToUpdateViewer)
901 {
902   if (theOwner.IsNull() || !theOwner->HasSelectable() || !myFilters->IsOk (theOwner))
903     return;
904
905   const Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable());
906   const Handle(Prs3d_Drawer)& anObjSelStyle = getSelStyle (anObject, theOwner);
907   if (NbSelected() == 1 && theOwner->IsSelected() && !theOwner->IsForcedHilight())
908   {
909     Handle(Prs3d_Drawer) aCustomStyle;
910     if (myAutoHilight && HighlightStyle (theOwner, aCustomStyle))
911     {
912       if (!aCustomStyle.IsNull() && anObjSelStyle != aCustomStyle)
913       {
914         const Standard_Integer aHiMode = anObject->HasHilightMode() ? anObject->HilightMode() : 0;
915         theOwner->HilightWithColor (myMainPM, anObjSelStyle, aHiMode);
916       }
917     }
918     return;
919   }
920
921   if (!myObjects.IsBound (anObject))
922     return;
923
924   if (myAutoHilight)
925   {
926     unhighlightSelected();
927   }
928
929   mySelection->ClearAndSelect (theOwner);
930   if (myAutoHilight)
931   {
932     Handle(Prs3d_Drawer) aCustomStyle;
933     if (!HighlightStyle (theOwner, aCustomStyle) ||
934       (!aCustomStyle.IsNull() && aCustomStyle != anObjSelStyle))
935     {
936       highlightSelected (theOwner);
937     }
938   }
939
940   if (myAutoHilight && theOwner == anObject->GlobalSelOwner())
941   {
942     Handle(AIS_GlobalStatus)& aState = myObjects.ChangeFind (anObject);
943     aState->SetHilightStatus (Standard_True);
944     aState->SetHilightStyle (anObjSelStyle);
945   }
946
947   if (theToUpdateViewer)
948     UpdateCurrentViewer();
949 }
950
951 //=======================================================================
952 //function : AddOrRemoveSelected
953 //purpose  : Adds or removes current object from AIS selection and highlights/unhighlights it.
954 //           Since this method makes sence only for neutral point selection of a whole object,
955 //           if 0 selection of the object is empty this method simply does nothing.
956 //=======================================================================
957 void AIS_InteractiveContext::AddOrRemoveSelected (const Handle(AIS_InteractiveObject)& theObject,
958                                                   const Standard_Boolean theToUpdateViewer)
959 {
960   if (theObject.IsNull()
961   || !myObjects.IsBound (theObject))
962   {
963     return;
964   }
965
966   const Handle(SelectMgr_EntityOwner) anOwner = theObject->GlobalSelOwner();
967   if (!anOwner.IsNull()
968     && anOwner->HasSelectable())
969   {
970     AddOrRemoveSelected (anOwner, theToUpdateViewer);
971   }
972 }
973
974 //=======================================================================
975 //function : AddOrRemoveSelected
976 //purpose  : Allows to highlight or unhighlight the owner given depending on
977 //           its selection status
978 //=======================================================================
979 void AIS_InteractiveContext::AddOrRemoveSelected (const Handle(SelectMgr_EntityOwner)& theOwner,
980                                                   const Standard_Boolean theToUpdateViewer)
981 {
982   if (theOwner.IsNull() || !theOwner->HasSelectable())
983     return;
984
985   if (!myFilters->IsOk(theOwner) && !theOwner->IsSelected())
986     return;
987
988   mySelection->Select (theOwner);
989
990   if (myAutoHilight)
991   {
992     const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable());
993     const Standard_Boolean isGlobal = anObj->GlobalSelOwner() == theOwner;
994     Handle(AIS_GlobalStatus)& aStatus = myObjects.ChangeFind (anObj);
995     if (theOwner->IsSelected())
996     {
997       highlightSelected (theOwner);
998       if (isGlobal)
999       {
1000         aStatus->SetHilightStatus (Standard_True);
1001         aStatus->SetHilightStyle (getSelStyle (anObj, theOwner));
1002       }
1003     }
1004     else
1005     {
1006       if (theOwner->IsAutoHilight())
1007       {
1008         theOwner->Unhilight (myMainPM);
1009       }
1010       else
1011       {
1012         anObj->ClearSelected();
1013       }
1014       aStatus->SetHilightStatus (Standard_False);
1015       aStatus->SetHilightStyle (Handle(Prs3d_Drawer)());
1016     }
1017   }
1018
1019   if (theToUpdateViewer)
1020     UpdateCurrentViewer();
1021 }
1022
1023 // =======================================================================
1024 // function : SetSelectedState
1025 // purpose  :
1026 // =======================================================================
1027 Standard_Boolean AIS_InteractiveContext::SetSelectedState (const Handle(SelectMgr_EntityOwner)& theEntity,
1028                                                            const Standard_Boolean theIsSelected)
1029 {
1030   if (theEntity.IsNull())
1031   {
1032     throw Standard_ProgramError ("Internal error: AIS_InteractiveContext::SetSelectedState() called with NO object");
1033   }
1034
1035   if (!theEntity->HasSelectable()
1036     || mySelection->IsSelected (theEntity) == theIsSelected)
1037   {
1038     return false;
1039   }
1040
1041   if (theEntity->IsAutoHilight())
1042   {
1043     AddOrRemoveSelected (theEntity, false);
1044     return true;
1045   }
1046
1047   if (theIsSelected)
1048   {
1049     const AIS_SelectStatus aSelStatus = mySelection->AddSelect (theEntity);
1050     theEntity->SetSelected (true);
1051     return aSelStatus == AIS_SS_Added;
1052   }
1053   else
1054   {
1055     const AIS_SelectStatus aSelStatus = mySelection->Select (theEntity);
1056     theEntity->SetSelected (false);
1057     return aSelStatus == AIS_SS_Removed;
1058   }
1059 }
1060
1061 //=======================================================================
1062 //function : IsSelected
1063 //purpose  :
1064 //=======================================================================
1065 Standard_Boolean AIS_InteractiveContext::IsSelected (const Handle(AIS_InteractiveObject)& theObj) const
1066 {
1067   if (theObj.IsNull())
1068   {
1069     return Standard_False;
1070   }
1071
1072   const Handle(AIS_GlobalStatus)* aStatus = myObjects.Seek (theObj);
1073   if (aStatus == NULL)
1074   {
1075     return Standard_False;
1076   }
1077
1078   const Standard_Integer aGlobalSelMode = theObj->GlobalSelectionMode();
1079   const TColStd_ListOfInteger& anActivatedModes = (*aStatus)->SelectionModes();
1080   for (TColStd_ListIteratorOfListOfInteger aModeIter (anActivatedModes); aModeIter.More(); aModeIter.Next())
1081   {
1082     if (aModeIter.Value() == aGlobalSelMode)
1083     {
1084       if (Handle(SelectMgr_EntityOwner) aGlobOwner = theObj->GlobalSelOwner())
1085       {
1086         return aGlobOwner->IsSelected();
1087       }
1088       return Standard_False;
1089     }
1090   }
1091   return Standard_False;
1092 }
1093
1094 //=======================================================================
1095 //function : FirstSelectedObject
1096 //purpose  :
1097 //=======================================================================
1098 Handle(AIS_InteractiveObject) AIS_InteractiveContext::FirstSelectedObject() const
1099 {
1100   return !mySelection->Objects().IsEmpty()
1101         ? Handle(AIS_InteractiveObject)::DownCast (mySelection->Objects().First()->Selectable())
1102         : Handle(AIS_InteractiveObject)();
1103 }
1104
1105 //=======================================================================
1106 //function : HasSelectedShape
1107 //purpose  :
1108 //=======================================================================
1109 Standard_Boolean AIS_InteractiveContext::HasSelectedShape() const
1110 {
1111   if (!mySelection->More())
1112     return Standard_False;
1113
1114   const Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
1115   return !anOwner.IsNull() && anOwner->HasShape();
1116 }
1117
1118 //=======================================================================
1119 //function : SelectedShape
1120 //purpose  :
1121 //=======================================================================
1122 TopoDS_Shape AIS_InteractiveContext::SelectedShape() const
1123 {
1124   if (!mySelection->More())
1125     return TopoDS_Shape();
1126
1127   const Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
1128   if (anOwner.IsNull() || !anOwner->HasSelectable())
1129     return TopoDS_Shape();
1130
1131   return anOwner->Shape().Located (anOwner->Location() * anOwner->Shape().Location());
1132 }
1133
1134 //=======================================================================
1135 //function : EntityOwners
1136 //purpose  : 
1137 //=======================================================================
1138 void AIS_InteractiveContext::EntityOwners(Handle(SelectMgr_IndexedMapOfOwner)& theOwners,
1139                                           const Handle(AIS_InteractiveObject)& theIObj,
1140                                           const Standard_Integer theMode) const 
1141 {
1142   if (theIObj.IsNull())
1143   {
1144     return;
1145   }
1146
1147   TColStd_ListOfInteger aModes;
1148   if (theMode == -1)
1149   {
1150     ActivatedModes (theIObj, aModes);
1151   }
1152   else
1153   {
1154     aModes.Append (theMode);
1155   }
1156
1157   if (theOwners.IsNull())
1158   {
1159     theOwners = new SelectMgr_IndexedMapOfOwner();
1160   }
1161
1162   for (TColStd_ListIteratorOfListOfInteger anItr (aModes); anItr.More(); anItr.Next())
1163   {
1164     const int aMode = anItr.Value();
1165     const Handle(SelectMgr_Selection)& aSel = theIObj->Selection (aMode);
1166     if (aSel.IsNull())
1167     {
1168       continue;
1169     }
1170
1171     for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
1172     {
1173       if (Handle(Select3D_SensitiveEntity) aEntity = aSelEntIter.Value()->BaseSensitive())
1174       {
1175         if (const Handle(SelectMgr_EntityOwner)& aOwner = aEntity->OwnerId())
1176         {
1177           theOwners->Add (aOwner);
1178         }
1179       }
1180     }
1181   }
1182 }
1183
1184 //=======================================================================
1185 //function : HasDetectedShape
1186 //purpose  : 
1187 //=======================================================================
1188 Standard_Boolean AIS_InteractiveContext::HasDetectedShape() const 
1189 {
1190   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (myLastPicked);
1191   return !anOwner.IsNull()
1192        && anOwner->HasShape();
1193 }
1194
1195 //=======================================================================
1196 //function : DetectedShape
1197 //purpose  : 
1198 //=======================================================================
1199 const TopoDS_Shape& AIS_InteractiveContext::DetectedShape() const
1200 {
1201   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (myLastPicked);
1202   return anOwner->Shape();
1203 }
1204
1205 //=======================================================================
1206 //function : HilightNextDetected
1207 //purpose  :
1208 //=======================================================================
1209 Standard_Integer AIS_InteractiveContext::HilightNextDetected (const Handle(V3d_View)& theView,
1210                                                               const Standard_Boolean  theToRedrawImmediate)
1211 {
1212   myMainPM->ClearImmediateDraw();
1213   if (myDetectedSeq.IsEmpty())
1214   {
1215     return 0;
1216   }
1217
1218   if (++myCurHighlighted > myDetectedSeq.Upper())
1219   {
1220     myCurHighlighted = myDetectedSeq.Lower();
1221   }
1222   const Handle(SelectMgr_EntityOwner)& anOwner = myMainSel->Picked (myDetectedSeq (myCurHighlighted));
1223   if (anOwner.IsNull())
1224   {
1225     return 0;
1226   }
1227
1228   highlightWithColor (anOwner, theView->Viewer());
1229   myLastPicked = anOwner;
1230
1231   if (theToRedrawImmediate)
1232   {
1233     myMainPM->RedrawImmediate (theView->Viewer());
1234     myMainVwr->RedrawImmediate();
1235   }
1236
1237   return myCurHighlighted;
1238 }
1239
1240 //=======================================================================
1241 //function : HilightPreviousDetected
1242 //purpose  :
1243 //=======================================================================
1244 Standard_Integer AIS_InteractiveContext::HilightPreviousDetected (const Handle(V3d_View)& theView,
1245                                                                   const Standard_Boolean  theToRedrawImmediate)
1246 {
1247   myMainPM->ClearImmediateDraw();
1248   if (myDetectedSeq.IsEmpty())
1249   {
1250     return 0;
1251   }
1252
1253   if (--myCurHighlighted < myDetectedSeq.Lower())
1254   {
1255     myCurHighlighted = myDetectedSeq.Upper();
1256   }
1257   const Handle(SelectMgr_EntityOwner)& anOwner = myMainSel->Picked (myDetectedSeq (myCurHighlighted));
1258   if (anOwner.IsNull())
1259   {
1260     return 0;
1261   }
1262
1263   highlightWithColor (anOwner, theView->Viewer());
1264   myLastPicked = anOwner;
1265
1266   if (theToRedrawImmediate)
1267   {
1268     myMainPM->RedrawImmediate (theView->Viewer());
1269     myMainVwr->RedrawImmediate();
1270   }
1271
1272   return myCurHighlighted;
1273 }
1274
1275 //=======================================================================
1276 //function : DetectedCurrentOwner
1277 //purpose  :
1278 //=======================================================================
1279 Handle(SelectMgr_EntityOwner) AIS_InteractiveContext::DetectedCurrentOwner() const
1280 {
1281   return MoreDetected()
1282        ? myMainSel->Picked (myDetectedSeq (myCurDetected))
1283        : Handle(SelectMgr_EntityOwner)();
1284 }
1285
1286 //=======================================================================
1287 //function : DetectedCurrentShape
1288 //purpose  :
1289 //=======================================================================
1290 const TopoDS_Shape& AIS_InteractiveContext::DetectedCurrentShape() const
1291 {
1292   Standard_DISABLE_DEPRECATION_WARNINGS
1293   Handle(AIS_Shape) aCurrentShape = Handle(AIS_Shape)::DownCast (DetectedCurrentObject());
1294   Standard_ENABLE_DEPRECATION_WARNINGS
1295   return !aCurrentShape.IsNull()
1296         ? aCurrentShape->Shape()
1297         : AIS_InteractiveContext_myDummyShape;
1298 }
1299
1300 //=======================================================================
1301 //function : DetectedCurrentObject
1302 //purpose  :
1303 //=======================================================================
1304 Handle(AIS_InteractiveObject) AIS_InteractiveContext::DetectedCurrentObject() const
1305 {
1306   return MoreDetected()
1307        ? Handle(AIS_InteractiveObject)::DownCast (myMainSel->Picked (myDetectedSeq (myCurDetected))->Selectable())
1308        : Handle(AIS_InteractiveObject)();
1309 }