0030726: Visualization - change Selected state of owner in AIS_Selection
[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 //=======================================================================
1009 //function : IsSelected
1010 //purpose  :
1011 //=======================================================================
1012 Standard_Boolean AIS_InteractiveContext::IsSelected (const Handle(AIS_InteractiveObject)& theObj) const
1013 {
1014   if (theObj.IsNull())
1015   {
1016     return Standard_False;
1017   }
1018
1019   const Handle(AIS_GlobalStatus)* aStatus = myObjects.Seek (theObj);
1020   if (aStatus == NULL)
1021   {
1022     return Standard_False;
1023   }
1024
1025   const Standard_Integer aGlobalSelMode = theObj->GlobalSelectionMode();
1026   const TColStd_ListOfInteger& anActivatedModes = (*aStatus)->SelectionModes();
1027   for (TColStd_ListIteratorOfListOfInteger aModeIter (anActivatedModes); aModeIter.More(); aModeIter.Next())
1028   {
1029     if (aModeIter.Value() == aGlobalSelMode)
1030     {
1031       if (Handle(SelectMgr_EntityOwner) aGlobOwner = theObj->GlobalSelOwner())
1032       {
1033         return aGlobOwner->IsSelected();
1034       }
1035       return Standard_False;
1036     }
1037   }
1038   return Standard_False;
1039 }
1040
1041 //=======================================================================
1042 //function : FirstSelectedObject
1043 //purpose  :
1044 //=======================================================================
1045 Handle(AIS_InteractiveObject) AIS_InteractiveContext::FirstSelectedObject() const
1046 {
1047   return !mySelection->Objects().IsEmpty()
1048         ? Handle(AIS_InteractiveObject)::DownCast (mySelection->Objects().First()->Selectable())
1049         : Handle(AIS_InteractiveObject)();
1050 }
1051
1052 //=======================================================================
1053 //function : HasSelectedShape
1054 //purpose  :
1055 //=======================================================================
1056 Standard_Boolean AIS_InteractiveContext::HasSelectedShape() const
1057 {
1058   if (!mySelection->More())
1059     return Standard_False;
1060
1061   const Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
1062   return !anOwner.IsNull() && anOwner->HasShape();
1063 }
1064
1065 //=======================================================================
1066 //function : SelectedShape
1067 //purpose  :
1068 //=======================================================================
1069 TopoDS_Shape AIS_InteractiveContext::SelectedShape() const
1070 {
1071   if (!mySelection->More())
1072     return TopoDS_Shape();
1073
1074   const Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
1075   if (anOwner.IsNull() || !anOwner->HasSelectable())
1076     return TopoDS_Shape();
1077
1078   return anOwner->Shape().Located (anOwner->Location() * anOwner->Shape().Location());
1079 }
1080
1081 //=======================================================================
1082 //function : EntityOwners
1083 //purpose  : 
1084 //=======================================================================
1085 void AIS_InteractiveContext::EntityOwners(Handle(SelectMgr_IndexedMapOfOwner)& theOwners,
1086                                           const Handle(AIS_InteractiveObject)& theIObj,
1087                                           const Standard_Integer theMode) const 
1088 {
1089   if (theIObj.IsNull())
1090   {
1091     return;
1092   }
1093
1094   TColStd_ListOfInteger aModes;
1095   if (theMode == -1)
1096   {
1097     ActivatedModes (theIObj, aModes);
1098   }
1099   else
1100   {
1101     aModes.Append (theMode);
1102   }
1103
1104   if (theOwners.IsNull())
1105   {
1106     theOwners = new SelectMgr_IndexedMapOfOwner();
1107   }
1108
1109   for (TColStd_ListIteratorOfListOfInteger anItr (aModes); anItr.More(); anItr.Next())
1110   {
1111     const int aMode = anItr.Value();
1112     const Handle(SelectMgr_Selection)& aSel = theIObj->Selection (aMode);
1113     if (aSel.IsNull())
1114     {
1115       continue;
1116     }
1117
1118     for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
1119     {
1120       if (Handle(Select3D_SensitiveEntity) aEntity = aSelEntIter.Value()->BaseSensitive())
1121       {
1122         if (const Handle(SelectMgr_EntityOwner)& aOwner = aEntity->OwnerId())
1123         {
1124           theOwners->Add (aOwner);
1125         }
1126       }
1127     }
1128   }
1129 }
1130
1131 //=======================================================================
1132 //function : HasDetectedShape
1133 //purpose  : 
1134 //=======================================================================
1135 Standard_Boolean AIS_InteractiveContext::HasDetectedShape() const 
1136 {
1137   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (myLastPicked);
1138   return !anOwner.IsNull()
1139        && anOwner->HasShape();
1140 }
1141
1142 //=======================================================================
1143 //function : DetectedShape
1144 //purpose  : 
1145 //=======================================================================
1146 const TopoDS_Shape& AIS_InteractiveContext::DetectedShape() const
1147 {
1148   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast (myLastPicked);
1149   return anOwner->Shape();
1150 }
1151
1152 //=======================================================================
1153 //function : HilightNextDetected
1154 //purpose  :
1155 //=======================================================================
1156 Standard_Integer AIS_InteractiveContext::HilightNextDetected (const Handle(V3d_View)& theView,
1157                                                               const Standard_Boolean  theToRedrawImmediate)
1158 {
1159   myMainPM->ClearImmediateDraw();
1160   if (myDetectedSeq.IsEmpty())
1161   {
1162     return 0;
1163   }
1164
1165   if (++myCurHighlighted > myDetectedSeq.Upper())
1166   {
1167     myCurHighlighted = myDetectedSeq.Lower();
1168   }
1169   const Handle(SelectMgr_EntityOwner)& anOwner = myMainSel->Picked (myDetectedSeq (myCurHighlighted));
1170   if (anOwner.IsNull())
1171   {
1172     return 0;
1173   }
1174
1175   highlightWithColor (anOwner, theView->Viewer());
1176   myLastPicked = anOwner;
1177
1178   if (theToRedrawImmediate)
1179   {
1180     myMainPM->RedrawImmediate (theView->Viewer());
1181     myMainVwr->RedrawImmediate();
1182   }
1183
1184   return myCurHighlighted;
1185 }
1186
1187 //=======================================================================
1188 //function : HilightPreviousDetected
1189 //purpose  :
1190 //=======================================================================
1191 Standard_Integer AIS_InteractiveContext::HilightPreviousDetected (const Handle(V3d_View)& theView,
1192                                                                   const Standard_Boolean  theToRedrawImmediate)
1193 {
1194   myMainPM->ClearImmediateDraw();
1195   if (myDetectedSeq.IsEmpty())
1196   {
1197     return 0;
1198   }
1199
1200   if (--myCurHighlighted < myDetectedSeq.Lower())
1201   {
1202     myCurHighlighted = myDetectedSeq.Upper();
1203   }
1204   const Handle(SelectMgr_EntityOwner)& anOwner = myMainSel->Picked (myDetectedSeq (myCurHighlighted));
1205   if (anOwner.IsNull())
1206   {
1207     return 0;
1208   }
1209
1210   highlightWithColor (anOwner, theView->Viewer());
1211   myLastPicked = anOwner;
1212
1213   if (theToRedrawImmediate)
1214   {
1215     myMainPM->RedrawImmediate (theView->Viewer());
1216     myMainVwr->RedrawImmediate();
1217   }
1218
1219   return myCurHighlighted;
1220 }
1221
1222 //=======================================================================
1223 //function : DetectedCurrentOwner
1224 //purpose  :
1225 //=======================================================================
1226 Handle(SelectMgr_EntityOwner) AIS_InteractiveContext::DetectedCurrentOwner() const
1227 {
1228   return MoreDetected()
1229        ? myMainSel->Picked (myDetectedSeq (myCurDetected))
1230        : Handle(SelectMgr_EntityOwner)();
1231 }
1232
1233 //=======================================================================
1234 //function : DetectedCurrentShape
1235 //purpose  :
1236 //=======================================================================
1237 const TopoDS_Shape& AIS_InteractiveContext::DetectedCurrentShape() const
1238 {
1239   Standard_DISABLE_DEPRECATION_WARNINGS
1240   Handle(AIS_Shape) aCurrentShape = Handle(AIS_Shape)::DownCast (DetectedCurrentObject());
1241   Standard_ENABLE_DEPRECATION_WARNINGS
1242   return !aCurrentShape.IsNull()
1243         ? aCurrentShape->Shape()
1244         : AIS_InteractiveContext_myDummyShape;
1245 }
1246
1247 //=======================================================================
1248 //function : DetectedCurrentObject
1249 //purpose  :
1250 //=======================================================================
1251 Handle(AIS_InteractiveObject) AIS_InteractiveContext::DetectedCurrentObject() const
1252 {
1253   return MoreDetected()
1254        ? Handle(AIS_InteractiveObject)::DownCast (myMainSel->Picked (myDetectedSeq (myCurDetected))->Selectable())
1255        : Handle(AIS_InteractiveObject)();
1256 }