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