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