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