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