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