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