0025695: Visualization, AIS_InteractiveContext - define default HilightMode
[occt.git] / src / AIS / AIS_LocalContext_1.cxx
1 // Created on: 1996-10-30
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1996-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 // Modified by rob Thu Apr 02 1998 
18 //              - use of optimisation in SelectMgr_ViewerSelector
19 //              -> Best management in detected entities...
20
21 #include <AIS_InteractiveContext.hxx>
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_LocalContext.hxx>
24 #include <AIS_LocalStatus.hxx>
25 #include <AIS_Selection.hxx>
26 #include <AIS_Shape.hxx>
27 #include <Aspect_Grid.hxx>
28 #include <Geom_Transformation.hxx>
29 #include <Graphic3d_ArrayOfTriangles.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <NCollection_Map.hxx>
32 #include <OSD_Environment.hxx>
33 #include <Prs3d_Drawer.hxx>
34 #include <Prs3d_Presentation.hxx>
35 #include <Prs3d_ShadingAspect.hxx>
36 #include <Select3D_SensitiveTriangulation.hxx>
37 #include <SelectBasics_SensitiveEntity.hxx>
38 #include <SelectMgr_EntityOwner.hxx>
39 #include <SelectMgr_Filter.hxx>
40 #include <SelectMgr_OrFilter.hxx>
41 #include <SelectMgr_SelectableObject.hxx>
42 #include <SelectMgr_Selection.hxx>
43 #include <SelectMgr_SelectionManager.hxx>
44 #include <SelectMgr_SequenceOfOwner.hxx>
45 #include <Standard_Transient.hxx>
46 #include <StdSelect_BRepOwner.hxx>
47 #include <StdSelect_ViewerSelector3d.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <TColStd_ListIteratorOfListOfInteger.hxx>
50 #include <TColStd_ListOfInteger.hxx>
51 #include <TColStd_MapIteratorOfMapOfTransient.hxx>
52 #include <TColStd_MapOfTransient.hxx>
53 #include <V3d_View.hxx>
54
55 namespace
56 {
57   TopoDS_Shape AIS_myDummyShape;
58 }
59
60 //==================================================
61 // Function: MoveTo
62 // Purpose :
63 //==================================================
64 AIS_StatusOfDetection AIS_LocalContext::MoveTo (const Standard_Integer  theXpix,
65                                                 const Standard_Integer  theYpix,
66                                                 const Handle(V3d_View)& theView,
67                                                 const Standard_Boolean  theToRedrawImmediate)
68 {
69   // check that ViewerSelector gives
70   if (theView->Viewer() != myCTX->CurrentViewer())
71   {
72     return AIS_SOD_Error;
73   }
74
75   myAISCurDetected = 0;
76   myAISDetectedSeq.Clear();
77
78   myCurDetected = 0;
79   myDetectedSeq.Clear();
80   myFilters->SetDisabledObjects (theView->View()->HiddenObjects());
81   myMainVS->Pick (theXpix, theYpix, theView);
82
83   const Standard_Integer aDetectedNb = myMainVS->NbPicked();
84   for (Standard_Integer aDetIter = 1; aDetIter <= aDetectedNb; ++aDetIter)
85   {
86     Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (aDetIter);
87     if (anOwner.IsNull()
88      || !myFilters->IsOk (anOwner))
89     {
90       continue;
91     }
92
93     myDetectedSeq.Append (aDetIter); // normally they are already arranged in correct order...
94     Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
95     if (!anObj.IsNull())
96     {
97       myAISDetectedSeq.Append (anObj);
98     }
99   }
100
101   // result of courses..
102   if (aDetectedNb == 0 || myDetectedSeq.IsEmpty())
103   {
104     if (mylastindex != 0 && mylastindex <= myMapOfOwner->Extent())
105     {
106       myMainPM->ClearImmediateDraw();
107       Unhilight (myMapOfOwner->FindKey (mylastindex), theView);
108       if (theToRedrawImmediate)
109       {
110         theView->RedrawImmediate();
111       }
112     }
113
114     mylastindex = 0;
115     return aDetectedNb == 0
116          ? AIS_SOD_Nothing
117          : AIS_SOD_AllBad;
118   }
119
120   // all owners detected by the selector are passed to the
121   // filters and correct ones are preserved...
122   myCurDetected = 1;
123   Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
124   manageDetected (anOwner, theView, theToRedrawImmediate);
125   if (myDetectedSeq.Length() == 1)
126   {
127     return aDetectedNb == 1
128          ? AIS_SOD_OnlyOneDetected
129          : AIS_SOD_OnlyOneGood;
130   }
131   else
132   {
133     return AIS_SOD_SeveralGood;
134   }
135 }
136
137 //=======================================================================
138 //function : AddSelect
139 //purpose  : 
140 //=======================================================================
141 AIS_StatusOfPick AIS_LocalContext::AddSelect (const Handle(SelectMgr_EntityOwner)& theObject)
142 {
143   mySelection->AddSelect (theObject);
144
145   Standard_Integer aSelNum = mySelection->Extent();
146   return (aSelNum == 1) ? AIS_SOP_OneSelected
147                         : (aSelNum > 1) ? AIS_SOP_SeveralSelected
148                                         : AIS_SOP_Error;
149 }
150
151 //=======================================================================
152 //function : Select
153 //purpose  : 
154 //=======================================================================
155 AIS_StatusOfPick AIS_LocalContext::Select (const Standard_Boolean toUpdateViewer)
156 {
157   if (myAutoHilight)
158   {
159     UnhilightPicked (Standard_False);
160   }
161
162   Standard_Integer aDetIndex = DetectedIndex();
163   if (aDetIndex <= 0)
164   {
165     ClearSelected (toUpdateViewer);
166     return mySelection->IsEmpty() ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
167   }
168
169   const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (aDetIndex);
170
171   ClearSelected (Standard_False);
172
173   if (!anOwner->IsSelected()) // anOwner is not selected
174   {
175     anOwner->SetSelected (Standard_True);
176     mySelection->Select (anOwner);
177   }
178
179   if (myAutoHilight)
180   {
181     const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
182     for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
183     {
184       Unhilight (anOwner, anActiveViewIter.Value());
185     }
186
187     // advanced selection highlighting mechanism
188     if (!anOwner->IsAutoHilight() && anOwner->HasSelectable())
189     {
190       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
191       UpdateSelected (anIO, Standard_False);
192     }
193
194     if (toUpdateViewer)
195     {
196       myCTX->CurrentViewer()->Update();
197     }
198   }
199
200   return (mySelection->Extent() == 1) ? AIS_SOP_OneSelected : AIS_SOP_SeveralSelected;
201 }
202
203 //=======================================================================
204 //function : Select
205 //purpose  : 
206 //=======================================================================
207 AIS_StatusOfPick AIS_LocalContext::Select (const Standard_Integer  theXPMin,
208                                            const Standard_Integer  theYPMin,
209                                            const Standard_Integer  theXPMax,
210                                            const Standard_Integer  theYPMax,
211                                            const Handle(V3d_View)& theView,
212                                            const Standard_Boolean  toUpdateViewer)
213 {
214   if (theView->Viewer() == myCTX->CurrentViewer())
215   {
216     myMainVS->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
217     if (myAutoHilight)
218     {
219       UnhilightPicked (Standard_False);
220     }
221
222     Standard_Integer aSelNum = mySelection->Extent();
223     if (myMainVS->NbPicked() == 0)
224     {
225       ClearSelected (toUpdateViewer);
226       mylastindex = 0;
227       return aSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
228     }
229
230     ClearSelected (Standard_False);
231
232     for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
233     {
234       const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
235       if (myFilters->IsOk (anOwner))
236       {
237         // it can be helpful to classify this owner immediately...
238         if (!anOwner->IsSelected())
239         {
240           anOwner->SetSelected (Standard_True);
241           mySelection->Select (anOwner);
242         }
243       }
244     }
245
246     if (myAutoHilight)
247     {
248       HilightPicked (toUpdateViewer);
249     }
250   }
251
252   Standard_Integer aSelNum = mySelection->Extent();
253
254   return (aSelNum == 1) ? AIS_SOP_OneSelected
255                         : (aSelNum > 1) ? AIS_SOP_SeveralSelected
256                                         : AIS_SOP_Error;
257 }
258
259 //==================================================
260 // Function: Select
261 // Purpose : Selection by polyline
262 //==================================================
263 AIS_StatusOfPick AIS_LocalContext::Select (const TColgp_Array1OfPnt2d& thePolyline,
264                                            const Handle(V3d_View)& theView,
265                                            const Standard_Boolean toUpdateViewer)
266 {
267   if (theView->Viewer() == myCTX->CurrentViewer())
268   {
269     myMainVS->Pick (thePolyline, theView);
270
271     Standard_Integer aLastSelNum = mySelection->Extent();
272     if (myMainVS->NbPicked() == 0)
273     {
274       // Nothing is selected clear selection.
275       ClearSelected (toUpdateViewer);
276       mylastindex = 0;
277
278       // Return state to know if something was unselected
279       return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
280     }
281
282     if (myAutoHilight)
283     {
284       UnhilightPicked (Standard_False);
285     }
286
287     // Clear previous selection without update to process this selection
288     ClearSelected (Standard_False);
289
290     for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
291     {
292       const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
293       if (myFilters->IsOk (anOwner))
294       {
295         // it can be helpful to classify this owner immediately...
296         if (!anOwner->IsSelected())
297         {
298           mySelection->AddSelect (anOwner);
299           anOwner->SetSelected (Standard_True);
300         }
301       }
302     }
303
304     if (myAutoHilight)
305     {
306       HilightPicked (toUpdateViewer);
307     }
308   }
309
310   Standard_Integer aSelNum = mySelection->Extent();
311   return (aSelNum == 1) ? AIS_SOP_OneSelected
312                         : (aSelNum > 1) ? AIS_SOP_SeveralSelected
313                                         : AIS_SOP_Error;
314 }
315
316 //=======================================================================
317 //function : ShiftSelect
318 //purpose  : 
319 //=======================================================================
320 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const Standard_Boolean toUpdateViewer)
321 {
322   Standard_Integer aDetIndex = DetectedIndex();
323
324   if(aDetIndex > 0)
325   {
326     Standard_Integer aSelNum = mySelection->Extent();
327     const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (aDetIndex);
328     Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
329     mySelection->Select (anOwner);
330     anOwner->SetSelected (toSelect);
331
332     if(myAutoHilight)
333     {
334       myMainPM->ClearImmediateDraw();
335       const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
336       for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
337       {
338         Unhilight (anOwner, anActiveViewIter.Value());
339       }
340
341       // advanced selection highlighting mechanism
342       if (!anOwner->IsAutoHilight() && anOwner->HasSelectable())
343       {
344         Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
345         UpdateSelected (anIO, Standard_False);
346       }
347
348       if (toUpdateViewer)
349       {
350         myCTX->CurrentViewer()->Update();
351       }
352     } 
353
354     Standard_Integer NS = mySelection->Extent();
355     if( NS == 1 ) return AIS_SOP_OneSelected;
356     else if( NS > 1 ) return AIS_SOP_SeveralSelected;
357     return aSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
358   }
359   return AIS_SOP_Error;
360 }
361
362 //=======================================================================
363 //function : ShiftSelect
364 //purpose  : 
365 //=======================================================================
366 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const Standard_Integer  theXPMin,
367                                                 const Standard_Integer  theYPMin,
368                                                 const Standard_Integer  theXPMax,
369                                                 const Standard_Integer  theYPMax,
370                                                 const Handle(V3d_View)& theView,
371                                                 const Standard_Boolean  toUpdateViewer)
372 {
373   myMainPM->ClearImmediateDraw();
374
375   if (theView->Viewer() == myCTX->CurrentViewer())
376   {
377     myMainVS->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
378
379     Standard_Integer aLastSelNum = mySelection->Extent();
380     if (myMainVS->NbPicked() == 0)
381     {
382       // Nothing is selected clear selection, but don't clear the selection
383       // as it is shift selection and previous selection matters.
384       // Return state to know if something was unselected
385       return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
386     }
387
388     if (myAutoHilight)
389     {
390       UnhilightPicked (Standard_False);
391     }
392
393     for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
394     {
395       const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
396       if(myFilters->IsOk (anOwner))
397       {
398         Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
399         mySelection->Select (anOwner);
400         anOwner->SetSelected (toSelect);
401       }
402     }
403
404     if (myAutoHilight)
405     {
406       HilightPicked (toUpdateViewer);
407     }
408   }
409
410   Standard_Integer aSelNum = mySelection->Extent();
411
412   return (aSelNum == 1) ? AIS_SOP_OneSelected
413                         : (aSelNum > 1) ? AIS_SOP_SeveralSelected
414                                         : AIS_SOP_Error;
415 }
416
417 //==================================================
418 // Function: Select
419 // Purpose : Selection by polyline
420 //==================================================
421 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const TColgp_Array1OfPnt2d& thePolyline,
422                                                 const Handle(V3d_View)&     theView,
423                                                 const Standard_Boolean      toUpdateViewer)
424 {
425   if (theView->Viewer() == myCTX->CurrentViewer())
426   {
427     myMainVS->Pick (thePolyline, theView);
428
429     Standard_Integer aLastSelNum = mySelection->Extent();
430     if (myMainVS->NbPicked() == 0)
431     {
432       // Nothing is selected clear selection, but don't clear the selection
433       // as it is shift selection and previous selection matters.
434       // Return state to know if something was unselected
435       return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
436     }
437
438     if (myAutoHilight)
439     {
440       UnhilightPicked (Standard_False);
441     }
442
443     for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
444     {
445       const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
446       if (myFilters->IsOk (anOwner))
447       {
448         Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
449         mySelection->Select (anOwner);
450         anOwner->SetSelected (toSelect);
451       }
452     }
453     if (myAutoHilight)
454     {
455       HilightPicked (toUpdateViewer);
456     }
457   }
458
459   Standard_Integer aSelNum = mySelection->Extent();
460
461   return (aSelNum == 1) ? AIS_SOP_OneSelected
462                         : (aSelNum > 1) ? AIS_SOP_SeveralSelected
463                                         : AIS_SOP_Error;
464 }
465
466 //==================================================
467 // Function: Hilight
468 // Purpose :
469 //==================================================
470 void AIS_LocalContext::Hilight (const Handle(SelectMgr_EntityOwner)& theOwner,
471                                 const Handle(V3d_View)&              theView)
472 {
473   if (theView.IsNull())
474   {
475     return;
476   }
477
478   const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast(theOwner->Selectable());
479   const Handle(Prs3d_Drawer)& aHiStyle = myCTX->getHiStyle (anObj, theOwner);
480   const Standard_Integer aHiMode = myCTX->getHilightMode (anObj, aHiStyle, -1);
481   myMainPM->BeginImmediateDraw();
482   theOwner->HilightWithColor (myMainPM, aHiStyle, aHiMode);
483   myMainPM->EndImmediateDraw (theView->Viewer());
484 }
485
486 //==================================================
487 // Function: Unhilight
488 // Purpose :
489 //==================================================
490 void AIS_LocalContext::Unhilight (const Handle(SelectMgr_EntityOwner)& theOwner,
491                                   const Handle(V3d_View)&              theView)
492 {
493   if (theView.IsNull())
494   {
495     return;
496   }
497
498   const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable());
499   if (IsSelected (theOwner))
500   {
501     if (theOwner->IsAutoHilight())
502     {
503       const Handle(Prs3d_Drawer)& aSelStyle = myCTX->getSelStyle (anObj, theOwner);
504       const Standard_Integer aHiMode = myCTX->getHilightMode (anObj, aSelStyle, -1);
505       theOwner->HilightWithColor (myMainPM, aSelStyle, aHiMode);
506     }
507   }
508   else
509   {
510     theOwner->Unhilight (myMainPM);
511   }
512 }
513
514 //=======================================================================
515 //function : HilightPicked
516 //purpose  :
517 //=======================================================================
518 void AIS_LocalContext::HilightPicked (const Standard_Boolean theToUpdateviewer)
519 {
520   if (mySelection.IsNull())
521   {
522     return;
523   }
524   
525   typedef NCollection_Shared<SelectMgr_SequenceOfOwner> SelectMgr_HSequenceOfOwner;
526   typedef NCollection_DataMap <Handle(SelectMgr_SelectableObject), Handle(SelectMgr_HSequenceOfOwner) > SelectMgr_DataMapOfObjectOwners;
527   SelectMgr_DataMapOfObjectOwners aMap;
528
529   // to avoid problems when there is a loop searching for selected objects...
530   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
531   {
532     const Handle(SelectMgr_EntityOwner)& anOwner = aSelIter.Value();
533     Handle(SelectMgr_SelectableObject) aSelObj = anOwner->Selectable();
534     if (anOwner->IsAutoHilight())
535     {
536       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(aSelObj);
537       const Handle(Prs3d_Drawer)& aSelStyle = myCTX->getSelStyle (anIO, anOwner);
538       const Standard_Integer aHiMode = myCTX->getHilightMode (anIO, aSelStyle, -1);
539       anOwner->HilightWithColor (myMainPM, aSelStyle, aHiMode);
540       continue;
541     }
542
543     Handle(SelectMgr_HSequenceOfOwner) aSeq;
544     if (aMap.Find (aSelObj, aSeq))
545     {
546       aSeq->Append (anOwner);
547     }
548     else
549     {
550       aSeq = new SelectMgr_HSequenceOfOwner();
551       aSeq->Append (anOwner);
552       aMap.Bind (aSelObj, aSeq);
553     }
554   }
555
556   for (SelectMgr_DataMapOfObjectOwners::Iterator aMapIter (aMap); aMapIter.More(); aMapIter.Next())
557   {
558     aMapIter.Key()->HilightSelected (myMainPM, *aMapIter.Value());
559   }
560
561   if (theToUpdateviewer)
562   {
563     myCTX->CurrentViewer()->Update();
564   }
565 }
566
567 //==================================================
568 // Function: UnhilightPicked
569 // Purpose :
570 //==================================================
571 void AIS_LocalContext::UnhilightPicked (const Standard_Boolean theToUpdateViewer)
572 {
573   myMainPM->ClearImmediateDraw();
574   if (mySelection.IsNull())
575   {
576     return;
577   }
578
579   NCollection_Map<Handle(SelectMgr_SelectableObject)> anObjMap;
580   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
581   {
582     const Handle(SelectMgr_EntityOwner)& anOwner = aSelIter.Value();
583     Handle(SelectMgr_SelectableObject) aSelObj = anOwner->Selectable();
584     Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (aSelObj);
585     anObjMap.Add (aSelObj);
586     anOwner->Unhilight (myMainPM);
587   }
588
589   for (NCollection_Map<Handle(SelectMgr_SelectableObject)>::Iterator aMapIter (anObjMap);
590        aMapIter.More(); aMapIter.Next())
591   {
592     if (!aMapIter.Key()->IsAutoHilight())
593     {
594       aMapIter.Key()->ClearSelected();
595     }
596   }
597
598   if (theToUpdateViewer)
599   {
600     myCTX->CurrentViewer()->Update();
601   }
602 }
603
604 //=======================================================================
605 //function : IsSelected
606 //purpose  : 
607 //=======================================================================
608 Standard_Boolean AIS_LocalContext::IsSelected(const Handle(AIS_InteractiveObject)& anIObj) const 
609 {
610   return (!FindSelectedOwnerFromIO(anIObj).IsNull());
611 }
612
613 //=======================================================================
614 //function : IsSelected
615 //purpose  : 
616 //=======================================================================
617
618 Standard_Boolean AIS_LocalContext::IsSelected (const Handle(SelectMgr_EntityOwner)& theOwner) const 
619 {
620   return !theOwner.IsNull() && theOwner->IsSelected();
621 }
622
623 //==================================================
624 // Function: 
625 // Purpose :
626 //==================================================
627 void AIS_LocalContext::
628 InitSelected()
629 {
630   mySelection->Init();
631 }
632
633 //==================================================
634 // Function: 
635 // Purpose :
636 //==================================================
637 Standard_Boolean AIS_LocalContext::
638 MoreSelected() const 
639 {
640   return mySelection->More();
641 }
642
643 //==================================================
644 // Function: 
645 // Purpose :
646 //==================================================
647 void AIS_LocalContext::
648 NextSelected()
649 {
650   mySelection->Next();
651 }
652
653 //==================================================
654 // Function: HasShape
655 // Purpose :
656 //==================================================
657 Standard_Boolean AIS_LocalContext::HasShape() const
658 {
659   if (!mySelection->More())
660   {
661     return Standard_False;
662   }
663
664   Handle(StdSelect_BRepOwner) aBROwner = Handle(StdSelect_BRepOwner)::DownCast(mySelection->Value());
665   return !aBROwner.IsNull()
666        && aBROwner->HasShape()
667        && aBROwner->ComesFromDecomposition();
668 }
669
670 //================================================================
671 // Function : HasSelectedShape
672 // Purpose  : Checks if there is a selected shape regardless of its decomposition status
673 //================================================================
674 Standard_Boolean AIS_LocalContext::HasSelectedShape() const
675 {
676   if (!mySelection->More())
677   {
678     return Standard_False;
679   }
680
681   Handle(StdSelect_BRepOwner) aBrepOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
682   return !aBrepOwner.IsNull()
683       && aBrepOwner->HasShape();
684 }
685
686 //==================================================
687 // Function: SelectedShape
688 // Purpose :
689 //==================================================
690 TopoDS_Shape AIS_LocalContext::SelectedShape() const 
691 {
692   if (!mySelection->More())
693   {
694     return TopoDS_Shape();
695   }
696
697   Handle(StdSelect_BRepOwner) aBRO = Handle(StdSelect_BRepOwner)::DownCast(mySelection->Value());
698   if (aBRO.IsNull())
699   {
700     return TopoDS_Shape();
701   }
702
703   return aBRO->Shape().Located (aBRO->Location() * aBRO->Shape().Location());
704 }
705
706 //==================================================
707 // Function: SelectedInteractive
708 // Purpose :
709 //==================================================
710 Handle(AIS_InteractiveObject) AIS_LocalContext::SelectedInteractive() const
711 {
712   return !mySelection->More()
713        ?  Handle(AIS_InteractiveObject)()
714        :  Handle(AIS_InteractiveObject)::DownCast (mySelection->Value()->Selectable());
715 }
716
717 //==================================================
718 // Function: SelectedOwner
719 // Purpose :
720 //==================================================
721 Handle(SelectMgr_EntityOwner) AIS_LocalContext::SelectedOwner() const
722 {
723   return !mySelection->More()
724        ?  Handle(SelectMgr_EntityOwner)()
725        :  mySelection->Value();
726 }
727
728 //==================================================
729 // Function: 
730 // Purpose :
731 //==================================================
732 Standard_Boolean AIS_LocalContext::HasApplicative() const
733 {
734   Handle(AIS_InteractiveObject) anIO = SelectedInteractive();
735   return !anIO.IsNull()
736        && anIO->HasOwner();
737 }
738
739 //==================================================
740 // Function: 
741 // Purpose :
742 //==================================================
743 const Handle(Standard_Transient)& AIS_LocalContext::
744 SelectedApplicative() const 
745 {
746   return SelectedInteractive()->GetOwner();
747 }
748
749
750
751 //=======================================================================
752 //function : UpdateSelection
753 //purpose  : should disappear...
754 //=======================================================================
755 void AIS_LocalContext::UpdateSelected(const Standard_Boolean updateviewer)
756 {
757   UnhilightPicked(Standard_False);
758   HilightPicked(updateviewer);
759 }
760
761 //================================================================
762 // Function : UpdateSelected
763 // Purpose  : Part of advanced selection mechanism.
764 //            Highlightes or clears selection presentation for the given IO
765 //================================================================
766 void AIS_LocalContext::UpdateSelected(const Handle(AIS_InteractiveObject)& anobj,
767                                       const Standard_Boolean updateviewer)
768 {
769   if (anobj.IsNull() || anobj->IsAutoHilight())
770     return;
771
772   SelectMgr_SequenceOfOwner aSeq;
773   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
774   {
775     if (aSelIter.Value()->IsSameSelectable (anobj))
776     {
777       aSeq.Append (aSelIter.Value());
778     }
779   }
780
781   if ( aSeq.Length() )
782     anobj->HilightSelected( myMainPM, aSeq );
783   else
784     anobj->ClearSelected();
785
786   if(updateviewer){
787      myCTX->CurrentViewer()->Update();
788   }
789 }
790
791 //==================================================
792 // Function: ClearSelected
793 // Purpose :
794 //==================================================
795 void AIS_LocalContext::ClearSelected (const Standard_Boolean updateviewer)
796 {
797   UnhilightPicked(updateviewer);
798   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
799   {
800     aSelIter.Value()->SetSelected (Standard_False);
801   }
802   mySelection->Clear();
803   mylastindex = 0;
804 }
805
806 //==================================================
807 // Function: ClearOutdatedSelection
808 // Purpose :
809 //==================================================
810 void AIS_LocalContext::ClearOutdatedSelection (const Handle(AIS_InteractiveObject)& theIO,
811                                                const Standard_Boolean toClearDeactivated)
812 {
813   // 1. Collect selectable entities
814   SelectMgr_IndexedMapOfOwner aValidOwners;
815
816   const TColStd_ListOfInteger& aModes = SelectionModes (theIO);
817
818   TColStd_ListIteratorOfListOfInteger aModeIter (aModes);
819   for (; aModeIter.More(); aModeIter.Next())
820   {
821     int aMode = aModeIter.Value();
822     if (!theIO->HasSelection(aMode))
823     {
824       continue;
825     }
826
827     if (toClearDeactivated && !mySM->IsActivated(theIO, aMode, myMainVS))
828     {
829       continue;
830     }
831
832     Handle(SelectMgr_Selection) aSelection = theIO->Selection(aMode);
833     for (aSelection->Init(); aSelection->More(); aSelection->Next())
834     {
835       Handle(SelectBasics_SensitiveEntity) anEntity = aSelection->Sensitive()->BaseSensitive();
836       if (anEntity.IsNull())
837       {
838         continue;
839       }
840
841       Handle(SelectMgr_EntityOwner) anOwner =
842         Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
843
844       if (anOwner.IsNull())
845       {
846         continue;
847       }
848
849       aValidOwners.Add(anOwner);
850     }
851   }
852
853   // 2. Refresh context's detection and selection and keep only active owners.
854   // Keep last detected object for lastindex initialization.
855   Handle(SelectMgr_EntityOwner) aLastPicked;
856   if (IsValidIndex (mylastindex))
857   {
858     aLastPicked = myMapOfOwner->FindKey (mylastindex);
859   }
860
861   // Remove entity owners from detected sequences
862   for (Standard_Integer anIdx = 1; anIdx <= myDetectedSeq.Length(); ++anIdx)
863   {
864     Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (anIdx));
865     if (anOwner.IsNull() || !anOwner->IsSameSelectable (theIO) || aValidOwners.Contains (anOwner))
866     {
867       continue;
868     }
869
870     myDetectedSeq.Remove (anIdx--);
871
872     if (anIdx < myCurDetected)
873     {
874       myCurDetected--;
875     }
876   }
877   myCurDetected = Max (myCurDetected, 1);
878
879   Standard_Boolean isAISRemainsDetected = Standard_False;
880
881   // 3. AIS_Selection : remove entity owners from AIS_Selection
882   const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
883   NCollection_List<Handle(SelectMgr_EntityOwner)> aRemoveEntites;
884   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
885   {
886     Handle(SelectMgr_EntityOwner) anOwner = aSelIter.Value();
887     if (!anOwner->IsSameSelectable (theIO))
888     {
889       continue;
890     }
891
892     if (aValidOwners.Contains (anOwner))
893     {
894       isAISRemainsDetected = Standard_True;
895     }
896     else
897     {
898       aRemoveEntites.Append (anOwner);
899       anOwner->SetSelected (Standard_False);
900       for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
901       {
902         Unhilight (anOwner, anActiveViewIter.Value());
903       }
904     }
905   }
906
907   for (NCollection_List<Handle(SelectMgr_EntityOwner)>::Iterator anIterRemove (aRemoveEntites);
908        anIterRemove.More(); anIterRemove.Next())
909   {
910     mySelection->Select (anIterRemove.Value());
911   }
912
913   // 4. AIS_LocalContext - myMapOfOwner : remove entity owners from myMapOfOwner
914   SelectMgr_IndexedMapOfOwner anOwnersToKeep;
915   for (Standard_Integer anIdx = 1; anIdx <= myMapOfOwner->Extent(); anIdx++)
916   {
917     Handle(SelectMgr_EntityOwner) anOwner = myMapOfOwner->FindKey (anIdx);
918     if (anOwner.IsNull())
919     {
920       continue;
921     }
922
923     if (!anOwner->IsSameSelectable (theIO) || aValidOwners.Contains (anOwner))
924     {
925       anOwnersToKeep.Add (anOwner);
926     }
927     else
928     {
929       for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
930       {
931         Unhilight (anOwner, anActiveViewIter.Value());
932       }
933     }
934   }
935   myMapOfOwner->Clear();
936   myMapOfOwner->Assign (anOwnersToKeep);
937
938   if (myDetectedSeq.IsEmpty() && !aLastPicked.IsNull())
939   {
940     myMainPM->ClearImmediateDraw();
941     mylastindex = 0;
942   }
943   else if (!aLastPicked.IsNull())
944   {
945     // For a case when the last detected owner was unhilighted and removed as outdated we
946     // need to check if there were other detected owners with less priority. If yes then
947     // one from the remaining should be treated.
948     Standard_Integer anIndex = 1, aDetectedSeqLength = myDetectedSeq.Length();
949     for (; anIndex <= aDetectedSeqLength; anIndex++)
950     {
951       if (aLastPicked == myMainVS->Picked (myDetectedSeq.Value(anIndex)))
952       {
953         break; // detected owner was not removed
954       }
955     }
956     if (anIndex <= aDetectedSeqLength)
957     {
958       // Last detected owner was not removed, update mylastindex variable
959       mylastindex = myMapOfOwner->FindIndex (aLastPicked);
960     }
961     else
962     {
963       // Last detected owner was removed. First object from sequence become detected.
964       // Pass any active view because in current implementation the highlighting is
965       // synchronized in all view.
966       manageDetected (myMainVS->Picked (myDetectedSeq.First()),
967                       aViewer->ActiveViewIterator().Value(),
968                       Standard_False);
969     }
970   }
971
972   // Renew iterator of ::DetectedCurrentObject()
973   if (!isAISRemainsDetected)
974   {
975     // Remove the interactive object from detected sequences
976     for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
977     {
978       Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
979       if (aDetectedIO.IsNull() || aDetectedIO != theIO)
980       {
981         continue;
982       }
983
984       myAISDetectedSeq.Remove (anIdx--);
985
986       if (anIdx < myAISCurDetected)
987       {
988         myAISCurDetected--;
989       }
990     }
991     myAISCurDetected = Max (myAISCurDetected, 1);
992   }
993 }
994
995 //=======================================================================
996 //function : SetSelected
997 //purpose  : 
998 //=======================================================================
999 void AIS_LocalContext::SetSelected(const Handle(AIS_InteractiveObject)& anIObj,
1000                                    const Standard_Boolean updateviewer)
1001 {
1002   if(!IsValidForSelection(anIObj)) return;
1003   UnhilightPicked(Standard_False);
1004   
1005   //1st case, owner already <anIObj> as owner  
1006   // and not separated is found...
1007
1008   Handle(SelectMgr_EntityOwner) EO = FindSelectedOwnerFromIO(anIObj);
1009   if(EO.IsNull()){
1010     //check if global selection there is an owner that can be triturated...
1011     if (anIObj->HasSelection (anIObj->GlobalSelectionMode()))
1012     {
1013       EO = anIObj->GlobalSelOwner();
1014     }
1015     if(EO.IsNull()) 
1016       EO = new SelectMgr_EntityOwner((const Handle(SelectMgr_SelectableObject)&)anIObj);
1017   }
1018   
1019   ClearSelected(Standard_False);
1020
1021   mySelection->Select(EO);
1022   EO->SetSelected (Standard_True);
1023
1024   HilightPicked(updateviewer);
1025 }
1026
1027 //=======================================================================
1028 //function : AddOrRemoveSelected
1029 //purpose  : 
1030 //=======================================================================
1031
1032 void AIS_LocalContext::AddOrRemoveSelected(const Handle(AIS_InteractiveObject)& anIObj,
1033                                            const Standard_Boolean updateviewer)
1034 {
1035   if(!IsValidForSelection(anIObj)) return;
1036   UnhilightPicked(Standard_False);
1037   // first check if it is selected...
1038   Handle(SelectMgr_EntityOwner) EO;
1039
1040   EO = FindSelectedOwnerFromIO(anIObj);
1041
1042   if (EO.IsNull())
1043   {
1044     if(anIObj->HasSelection (anIObj->GlobalSelectionMode()))
1045     {
1046       EO = anIObj->GlobalSelOwner();
1047     }
1048     if(EO.IsNull())
1049     {
1050       EO = new SelectMgr_EntityOwner((const Handle(SelectMgr_SelectableObject)&)anIObj);
1051     }
1052   }
1053
1054   if (!mySelection.IsNull())
1055   {
1056     AIS_SelectStatus aStatus = mySelection->Select(EO);
1057     EO->SetSelected (aStatus == AIS_SS_Added);
1058   }
1059
1060   HilightPicked(updateviewer);
1061 }
1062
1063 //=======================================================================
1064 //function : AddOrRemoveSelected
1065 //purpose  : To check...
1066 //=======================================================================
1067 void AIS_LocalContext::AddOrRemoveSelected(const TopoDS_Shape& Sh,
1068                                            const Standard_Boolean updateviewer)
1069 {     
1070   UnhilightPicked (Standard_False);
1071   Handle(SelectMgr_EntityOwner) EO = FindSelectedOwnerFromShape(Sh);
1072   if (!EO.IsNull())
1073   {
1074     mySelection->Select(EO);
1075     EO->SetSelected (Standard_True);
1076   }
1077   HilightPicked (updateviewer);
1078 }
1079
1080 void AIS_LocalContext::AddOrRemoveSelected (const Handle(SelectMgr_EntityOwner)& theOwner,
1081                                            const Standard_Boolean toUpdateViewer)
1082 {
1083   if(myAutoHilight)
1084   {
1085     UnhilightPicked (Standard_False);
1086   }
1087
1088   Standard_Boolean toSelect = theOwner->IsSelected() ? Standard_False : Standard_True;
1089
1090   mySelection->Select(theOwner);
1091   theOwner->SetSelected (toSelect);
1092
1093   if(myAutoHilight)
1094   {
1095     HilightPicked (toUpdateViewer);
1096   }
1097 }
1098
1099 //==================================================
1100 // Function: manageDetected
1101 // Purpose :
1102 //==================================================
1103 void AIS_LocalContext::manageDetected (const Handle(SelectMgr_EntityOwner)& thePickOwner,
1104                                        const Handle(V3d_View)&              theView,
1105                                        const Standard_Boolean               theToRedrawImmediate)
1106 {
1107   if (thePickOwner.IsNull())
1108   {
1109     myMainPM->ClearImmediateDraw();
1110     if (theToRedrawImmediate)
1111     {
1112       theView->RedrawImmediate();
1113     }
1114     return;
1115   }
1116
1117   if (!myFilters->IsOk (thePickOwner))
1118   {
1119     if (mylastindex != 0)
1120     {
1121       mylastgood = mylastindex;
1122     }
1123     if (theToRedrawImmediate)
1124     {
1125       theView->RedrawImmediate();
1126     }
1127     return;
1128   }
1129
1130   //=======================================================================================================
1131   // 2 cases : a- object is in the map of picks:
1132   //             1. this is the same index as the last detected: -> Do nothing
1133   //             2. otherwise :
1134   //                  - if lastindex = 0 (no object was detected at the last step)
1135   //                    the object presentation is highlighted and lastindex = index(objet)
1136   //                  - othrwise :
1137   //                           the presentation of the object corresponding to lastindex is "unhighlighted"
1138   //                           it is removed if the object is not visualized but only active
1139   //                           then the presentation of the detected object is highlighted and lastindex = index(objet)
1140   //         b- the object is not in the map of picked objects
1141   //                  - if lastindex != 0 (object detected at the last step) it is unhighlighted ...
1142   //            if the object was decomposed, presentation is created for the detected shape and the couple
1143   //             (Proprietaire,Prs)is added in the map.
1144   //           otherwise the couple(proprietaire, NullPrs) is placed in the map and the interactive object
1145   //           itself is highlighted.
1146   //
1147   //=======================================================================================================
1148
1149   const Standard_Integer aNewIndex = myMapOfOwner->Contains  (thePickOwner)
1150                                    ? myMapOfOwner->FindIndex (thePickOwner)
1151                                    : myMapOfOwner->Add       (thePickOwner);
1152
1153   // For the advanced mesh selection mode the owner indices comparison
1154   // is not effective because in that case only one owner manage the
1155   // selection in current selection mode. It is necessary to check the current detected
1156   // entity and hilight it only if the detected entity is not the same as
1157   // previous detected (IsForcedHilight call)
1158   if (aNewIndex != mylastindex
1159    || thePickOwner->IsForcedHilight())
1160   {
1161     myMainPM->ClearImmediateDraw();
1162     if (mylastindex != 0
1163      && mylastindex <= myMapOfOwner->Extent())
1164     {
1165       const Handle(SelectMgr_EntityOwner)& aLastOwner = myMapOfOwner->FindKey (mylastindex);
1166       Unhilight (aLastOwner, theView);
1167     }
1168
1169     if (myAutoHilight)
1170     {
1171       if (!thePickOwner->IsSelected() || myCTX->ToHilightSelected())
1172       {
1173         Hilight (thePickOwner, theView);
1174       }
1175       if (theToRedrawImmediate)
1176       {
1177         theView->RedrawImmediate();
1178       }
1179     }
1180
1181     mylastindex = aNewIndex;
1182   }
1183
1184   if (mylastindex != 0)
1185   {
1186     mylastgood = mylastindex;
1187   }
1188 }
1189
1190 //=======================================================================
1191 //function : HasDetectedShape
1192 //purpose  : 
1193 //=======================================================================
1194
1195 Standard_Boolean AIS_LocalContext::HasDetectedShape() const 
1196 {
1197   if(mylastindex==0) return Standard_False;
1198   return IsShape(mylastindex);
1199 }
1200
1201 //=======================================================================
1202 //function : DetectedShape
1203 //purpose  : 
1204 //=======================================================================
1205
1206 const TopoDS_Shape&
1207 AIS_LocalContext::DetectedShape() const
1208 {
1209   if(mylastindex != 0)
1210   {
1211     Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(myMapOfOwner->FindKey (mylastindex));
1212     if(BROwnr.IsNull()) return AIS_myDummyShape;
1213     return BROwnr->Shape();
1214   }
1215   return AIS_myDummyShape;
1216 }                                           
1217
1218 //=======================================================================
1219 //function : DetectedInteractive
1220 //purpose  : 
1221 //=======================================================================
1222
1223 Handle(AIS_InteractiveObject) 
1224 AIS_LocalContext::DetectedInteractive() const 
1225 {
1226   Handle(AIS_InteractiveObject) Iobj;
1227   if(IsValidIndex(mylastindex)){
1228     Handle(SelectMgr_SelectableObject) SO = myMapOfOwner->FindKey(mylastindex)->Selectable();
1229     Iobj = Handle(AIS_InteractiveObject)::DownCast (SO);
1230   }
1231   return Iobj;
1232 }
1233 //=======================================================================
1234 //function : DetectedInteractive
1235 //purpose  : 
1236 //=======================================================================
1237 Handle(SelectMgr_EntityOwner) AIS_LocalContext::DetectedOwner() const 
1238 {
1239   Handle(SelectMgr_EntityOwner) bid;
1240   if(!IsValidIndex(mylastindex)) return bid;
1241   return myMapOfOwner->FindKey(mylastindex);
1242 }
1243
1244
1245 //=======================================================================
1246 //function : ComesFromDecomposition
1247 //purpose  : 
1248 //=======================================================================
1249
1250 Standard_Boolean AIS_LocalContext::ComesFromDecomposition(const Standard_Integer PickedIndex) const 
1251 {
1252   const Handle(SelectMgr_EntityOwner)& OWN = myMapOfOwner->FindKey(PickedIndex);
1253   Handle(SelectMgr_SelectableObject) aSel  = OWN->Selectable();
1254   if (myActiveObjects.IsBound (aSel)) { // debug of jmi
1255     const Handle(AIS_LocalStatus)& Stat      = myActiveObjects(aSel);    
1256     return Stat->Decomposed();
1257   }
1258   return Standard_False;
1259 }
1260
1261 //=======================================================================
1262 //function : DisplaySensitive
1263 //purpose  : 
1264 //=======================================================================
1265
1266 void AIS_LocalContext::DisplaySensitive(const Handle(V3d_View)& aviou)
1267 {
1268     myMainVS->DisplaySensitive(aviou);
1269 }
1270
1271 //=======================================================================
1272 //function : ClearSensitive
1273 //purpose  : 
1274 //=======================================================================
1275
1276 void AIS_LocalContext::ClearSensitive(const Handle(V3d_View)& aviou)
1277 {
1278     myMainVS->ClearSensitive(aviou);
1279 }
1280
1281
1282 //=======================================================================
1283 //function : IsShape
1284 //purpose  : 
1285 //=======================================================================
1286 Standard_Boolean AIS_LocalContext::IsShape(const Standard_Integer Index) const
1287 {
1288   Handle(SelectMgr_EntityOwner) aEO (myMapOfOwner->FindKey(Index));
1289   if (aEO.IsNull() || ! aEO->IsKind(STANDARD_TYPE(StdSelect_BRepOwner)))
1290     return Standard_False;
1291   return 
1292     ComesFromDecomposition(Index);
1293 }
1294
1295 Standard_Boolean AIS_LocalContext::IsValidForSelection(const Handle(AIS_InteractiveObject)& anIObj) const 
1296 {
1297   const Handle(SelectMgr_SelectableObject)& aSelObj = anIObj; // to avoid ambiguity
1298   // Shape was not transfered from AIS_Shape to EntityOwner
1299   Handle(AIS_Shape) shape = Handle(AIS_Shape)::DownCast(anIObj);
1300   if( !shape.IsNull() ) 
1301     return myFilters->IsOk(new StdSelect_BRepOwner(shape->Shape(), aSelObj));
1302   return myFilters->IsOk(new SelectMgr_EntityOwner(aSelObj));
1303 }
1304
1305
1306 //=======================================================================
1307 //function : HilightNextDetected
1308 //purpose  :
1309 //=======================================================================
1310 Standard_Integer AIS_LocalContext::HilightNextDetected (const Handle(V3d_View)& theView,
1311                                                         const Standard_Boolean  theToRedrawImmediate)
1312 {
1313   // go to the next owner
1314   if (myDetectedSeq.IsEmpty())
1315   {
1316     return 0;
1317   }
1318
1319   const Standard_Integer aLen = myDetectedSeq.Length();
1320   if (++myCurDetected > aLen)
1321   {
1322     myCurDetected = 1;
1323   }
1324   Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
1325   if (anOwner.IsNull())
1326   {
1327     return 0;
1328   }
1329   manageDetected (anOwner, theView, theToRedrawImmediate);
1330   return myCurDetected;
1331 }
1332
1333 //=======================================================================
1334 //function : HilightPreviousDetected
1335 //purpose  :
1336 //=======================================================================
1337 Standard_Integer AIS_LocalContext::HilightPreviousDetected (const Handle(V3d_View)& theView,
1338                                                             const Standard_Boolean  theToRedrawImmediate)
1339 {
1340   if (myDetectedSeq.IsEmpty())
1341   {
1342     return 0;
1343   }
1344
1345   const Standard_Integer aLen = myDetectedSeq.Length();
1346   if (--myCurDetected < 1)
1347   {
1348     myCurDetected = aLen;
1349   }
1350   Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
1351   if (anOwner.IsNull())
1352   {
1353     return 0;
1354   }
1355
1356   manageDetected (anOwner, theView, theToRedrawImmediate);
1357   return myCurDetected;
1358 }
1359
1360 //=======================================================================
1361 //function : UnhilightLastDetected
1362 //purpose  :
1363 //=======================================================================
1364 Standard_Boolean AIS_LocalContext::UnhilightLastDetected (const Handle(V3d_View)& theView)
1365 {
1366   if (!IsValidIndex (mylastindex))
1367   {
1368     return Standard_False;
1369   }
1370
1371   myMainPM->BeginImmediateDraw();
1372   const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (mylastindex);
1373   anOwner->Unhilight (myMainPM);
1374   myMainPM->EndImmediateDraw (theView->Viewer());
1375   mylastindex = 0;
1376   return Standard_True;
1377 }
1378
1379 //=======================================================================
1380 //function : FindSelectedOwnerFromIO
1381 //purpose  : it is checked if one of the selected owners really presents IObj
1382 //=======================================================================
1383 Handle(SelectMgr_EntityOwner) AIS_LocalContext::FindSelectedOwnerFromIO (const Handle(AIS_InteractiveObject)& theObj) const
1384 {
1385   Handle(SelectMgr_EntityOwner) EO,bid;
1386   if (theObj.IsNull()
1387    || mySelection.IsNull())
1388   {
1389     return Handle(SelectMgr_EntityOwner)();
1390   }
1391
1392   for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
1393   {
1394     if (!aSelIter.Value()->IsSameSelectable (theObj))
1395     {
1396       continue;
1397     }
1398
1399     Handle(StdSelect_BRepOwner) aBROwner = Handle(StdSelect_BRepOwner)::DownCast(aSelIter.Value());
1400     if (aBROwner.IsNull()
1401     || !aBROwner->ComesFromDecomposition())
1402     {
1403       return aSelIter.Value();
1404     }
1405   }
1406   return Handle(SelectMgr_EntityOwner)();
1407 }
1408
1409 //=======================================================================
1410 //function : FindSelectedOwnerFromShape
1411 //purpose  : it is checked if one of the selected owners really presents IObj
1412 //=======================================================================
1413 Handle(SelectMgr_EntityOwner) AIS_LocalContext::FindSelectedOwnerFromShape(const TopoDS_Shape& sh) const 
1414 {
1415   Handle(SelectMgr_EntityOwner) EO, bid;
1416   if (sh.IsNull()) return EO;
1417   
1418   if(mySelection.IsNull()) {
1419     return EO;
1420   }
1421   
1422   Standard_Boolean found(Standard_False);
1423
1424   if (!found) {
1425     NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
1426     myMainVS->ActiveOwners (anActiveOwners);
1427     for (NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners); anOwnersIt.More(); anOwnersIt.Next())
1428     {
1429       EO = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
1430       Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(EO);
1431       if (!BROwnr.IsNull() && BROwnr->HasShape() && BROwnr->Shape() == sh) {
1432          found = Standard_True;
1433          break;
1434       }
1435     }
1436   }
1437
1438   if(found)  return EO;
1439   return bid;
1440 }
1441
1442 //=======================================================================
1443 //function : AIS_LocalContext::InitDetected
1444 //purpose  :
1445 //=======================================================================
1446 void AIS_LocalContext::InitDetected()
1447 {
1448   myAISCurDetected = myAISDetectedSeq.Length()? 1 : 0;
1449 }
1450
1451 //=======================================================================
1452 //function : AIS_LocalContext::MoreDetected
1453 //purpose  :
1454 //=======================================================================
1455 Standard_Boolean AIS_LocalContext::MoreDetected() const
1456 {
1457   return (myAISCurDetected > 0 && myAISCurDetected <= myAISDetectedSeq.Length());
1458 }
1459
1460 //=======================================================================
1461 //function : AIS_LocalContext::NextDetected
1462 //purpose  :
1463 //=======================================================================
1464 void AIS_LocalContext::NextDetected()
1465 {
1466   myAISCurDetected++;
1467 }
1468
1469 //=======================================================================
1470 //function : DetectedCurrentShape
1471 //purpose  :
1472 //=======================================================================
1473 const TopoDS_Shape& AIS_LocalContext::DetectedCurrentShape() const
1474 {
1475   Handle(AIS_Shape) aCurrentShape = Handle(AIS_Shape)::DownCast (DetectedCurrentObject());
1476
1477   if (aCurrentShape.IsNull())
1478   {
1479     return AIS_myDummyShape;
1480   }
1481
1482   return aCurrentShape->Shape();
1483 }
1484 //=======================================================================
1485 //function : DetectedCurrentObject
1486 //purpose  :
1487 //=======================================================================
1488 Handle(AIS_InteractiveObject) AIS_LocalContext::DetectedCurrentObject() const
1489 {
1490   return MoreDetected() ? myAISDetectedSeq(myAISCurDetected) : NULL;
1491 }
1492
1493 //=======================================================================
1494 //function : RestoreActivatedModes
1495 //purpose  :
1496 //=======================================================================
1497 void AIS_LocalContext::RestoreActivatedModes() const
1498 {
1499   for (AIS_DataMapOfSelStat::Iterator anIter (myActiveObjects); anIter.More(); anIter.Next())
1500   {
1501     const TColStd_ListOfInteger& anActivatedModes = anIter.Value()->SelectionModes();
1502     for (TColStd_ListIteratorOfListOfInteger aModesIter (anActivatedModes); aModesIter.More(); aModesIter.Next())
1503     {
1504       mySM->Activate (anIter.Key(), aModesIter.Value(), myMainVS);
1505     }
1506   }
1507 }