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