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