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