]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_Displayer.cpp
Salome HOME
Selection in Sketch with SHIFT pressed.
[modules/shaper.git] / src / XGUI / XGUI_Displayer.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        XGUI_Displayer.cpp
4 // Created:     20 Apr 2014
5 // Author:      Natalia ERMOLAEVA
6
7 #include "XGUI_Displayer.h"
8 #include "XGUI_Workshop.h"
9 #include "XGUI_ViewerProxy.h"
10 #include "XGUI_SelectionMgr.h"
11 #include "XGUI_Selection.h"
12 #include "XGUI_CustomPrs.h"
13
14 #ifndef HAVE_SALOME
15 #include <AppElements_Viewer.h>
16 #endif
17
18 #ifdef VINSPECTOR
19 #include <VInspectorAPI_PluginMgr.h>
20 #include <VInspectorAPI_Communicator.h>
21 #include <AppElements_MainWindow.h>
22 static bool VInspector_FirstCall = true;
23 #endif
24
25 #include <ModelAPI_Document.h>
26 #include <ModelAPI_Data.h>
27 #include <ModelAPI_Object.h>
28 #include <ModelAPI_Tools.h>
29 #include <ModelAPI_AttributeIntArray.h>
30 #include <ModelAPI_ResultCompSolid.h>
31
32 #include <ModuleBase_ResultPrs.h>
33 #include <ModuleBase_Tools.h>
34 #include <ModuleBase_IModule.h>
35 #include <ModuleBase_ViewerPrs.h>
36 #include <ModuleBase_Preferences.h>
37
38 #include <GeomAPI_Shape.h>
39 #include <GeomAPI_IPresentable.h>
40 #include <GeomAPI_ICustomPrs.h>
41
42 #include <SUIT_ResourceMgr.h>
43
44 #include <AIS_InteractiveContext.hxx>
45 #include <AIS_ListOfInteractive.hxx>
46 #include <AIS_ListIteratorOfListOfInteractive.hxx>
47 #include <AIS_DimensionSelectionMode.hxx>
48 #include <AIS_Shape.hxx>
49 #include <AIS_Dimension.hxx>
50 #include <AIS_Trihedron.hxx>
51 #include <AIS_Axis.hxx>
52 #include <AIS_Plane.hxx>
53 #include <AIS_Point.hxx>
54 #include <AIS_Selection.hxx>
55 #include <TColStd_ListIteratorOfListOfInteger.hxx>
56 #include <SelectMgr_ListOfFilter.hxx>
57 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
58 #include <Prs3d_Drawer.hxx>
59 #include <Prs3d_IsoAspect.hxx>
60 #include <SelectMgr_SelectionManager.hxx>
61
62 #include <StdSelect_ViewerSelector3d.hxx>
63
64 #include <TColStd_MapOfTransient.hxx>
65 #include <TColStd_MapIteratorOfMapOfTransient.hxx>
66
67 #ifdef VINSPECTOR
68 #include <VInspectorAPI_CallBack.h>
69 #endif
70
71 #include <Events_Loop.h>
72 #include <ModelAPI_Events.h>
73
74 #include <set>
75
76 /// defines the local context mouse selection sensitivity
77 const int MOUSE_SENSITIVITY_IN_PIXEL = 10;
78
79 //#define DEBUG_ACTIVATE_OBJECTS
80 //#define DEBUG_DEACTIVATE
81 //#define DEBUG_ACTIVATE_AIS
82 //#define DEBUG_DEACTIVATE_AIS
83
84 //#define DEBUG_DISPLAY
85 //#define DEBUG_FEATURE_REDISPLAY
86 //#define DEBUG_SELECTION_FILTERS
87
88 //#define DEBUG_COMPOSILID_DISPLAY
89
90 //#define DEBUG_OCCT_SHAPE_SELECTION
91
92 //#define DEBUG_OCCT_26172
93
94 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
95 {
96   // Get from null point
97   theAIS->DisplayedObjects(theList, true);
98 }
99
100 QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QString(", "))
101 {
102   QStringList anInfo;
103   QIntList::const_iterator anIt = theValues.begin(), aLast = theValues.end();
104   for (; anIt != aLast; anIt++) {
105     anInfo.append(QString::number(*anIt));
106   }
107   return anInfo.join(theSeparator);
108 }
109
110 XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
111   : myWorkshop(theWorkshop), myNeedUpdate(false),
112   myIsTrihedronActive(true), myViewerBlockedRecursiveCount(0),
113   myIsFirstAISContextUse(true)
114 {
115   #ifdef VINSPECTOR
116   myCommunicator = 0;
117   #endif
118   myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs(theWorkshop));
119 }
120
121 XGUI_Displayer::~XGUI_Displayer()
122 {
123 }
124
125 bool XGUI_Displayer::isVisible(ObjectPtr theObject) const
126 {
127   return myResult2AISObjectMap.contains(theObject);
128 }
129
130 bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
131 {
132   bool aDisplayed = false;
133   if (isVisible(theObject)) {
134 #ifdef DEBUG_COMPOSILID_DISPLAY
135     ResultCompSolidPtr aCompsolidResult =
136       std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
137     if (aCompsolidResult.get()) {
138       for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
139         ResultPtr aSubResult = aCompsolidResult->subResult(i);
140         if (aSubResult.get())
141           redisplay(aSubResult, false);
142       }
143       if (theUpdateViewer)
144         updateViewer();
145     }
146     else
147 #endif
148     aDisplayed = redisplay(theObject, theUpdateViewer);
149   } else {
150     AISObjectPtr anAIS;
151     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
152     bool isShading = false;
153     if (aPrs.get() != NULL) {
154       anAIS = aPrs->getAISObject(anAIS);
155       if (anAIS.get()) {
156         // correct deviation coefficient for
157         /*Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl<Handle(AIS_InteractiveObject)>();
158         if (!anAISPrs.IsNull()) {
159           Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
160           if (!aShapePrs.IsNull()) {
161             TopoDS_Shape aShape = aShapePrs->Shape();
162             if (!aShape.IsNull())
163               //ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, anAISPrs->Attributes());
164           }
165         }*/
166       }
167     } else {
168       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
169       if (aResult.get() != NULL) {
170 #ifdef DEBUG_COMPOSILID_DISPLAY
171         ResultCompSolidPtr aCompsolidResult =
172           std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
173         if (aCompsolidResult.get()) {
174           for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
175             ResultPtr aSubResult = aCompsolidResult->subResult(i);
176             if (aSubResult.get())
177               display(aSubResult, false);
178           }
179           if (theUpdateViewer)
180             updateViewer();
181         }
182         else {
183 #endif
184         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
185         if (aShapePtr.get() != NULL) {
186           anAIS = AISObjectPtr(new GeomAPI_AISObject());
187           Handle(AIS_InteractiveObject) anAISPrs =
188             myWorkshop->module()->createPresentation(aResult);
189           if (anAISPrs.IsNull())
190             anAISPrs = new ModuleBase_ResultPrs(aResult);
191           else {
192             Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
193             if (!aShapePrs.IsNull())
194               ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*) aShapePrs.get());
195           }
196           anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs));
197           //anAIS->createShape(aShapePtr);
198           isShading = true;
199         }
200 #ifdef DEBUG_COMPOSILID_DISPLAY
201         } // close else
202 #endif
203       }
204     }
205     if (anAIS)
206       aDisplayed = display(theObject, anAIS, isShading, theUpdateViewer);
207   }
208   return aDisplayed;
209 }
210
211 bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theModule)
212 {
213   Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS);
214   if (!aShapePrs.IsNull()) {
215     TopoDS_Shape aShape = aShapePrs->Shape();
216     if (aShape.IsNull())
217       return false;
218     TopAbs_ShapeEnum aType = aShape.ShapeType();
219     if ((aType == TopAbs_VERTEX) || (aType == TopAbs_EDGE) || (aType == TopAbs_WIRE))
220       return false;
221     else {
222       // Check that the presentation is not a sketch
223       return theModule->canBeShaded(theAIS);
224     }
225   }
226   return false;
227 }
228
229 bool XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
230                              bool isShading, bool theUpdateViewer)
231 {
232   bool aDisplayed = false;
233
234   Handle(AIS_InteractiveContext) aContext = AISContext();
235   if (aContext.IsNull())
236     return aDisplayed;
237
238   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
239   if (!anAISIO.IsNull()) {
240     appendResultObject(theObject, theAIS);
241
242     bool isCustomized = customizeObject(theObject);
243
244     int aDispMode = isShading? Shading : Wireframe;
245     if (isShading)
246       anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
247     anAISIO->SetDisplayMode(aDispMode);
248     aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed);
249     #ifdef VINSPECTOR
250     if (getCallBack()) getCallBack()->Display(anAISIO);
251     #endif
252     aDisplayed = true;
253
254     emit objectDisplayed(theObject, theAIS);
255     activate(anAISIO, myActiveSelectionModes, theUpdateViewer);
256   }
257   if (theUpdateViewer)
258     updateViewer();
259
260   return aDisplayed;
261 }
262
263 bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
264 {
265   bool aErased = false;
266   if (!isVisible(theObject))
267     return aErased;
268
269   Handle(AIS_InteractiveContext) aContext = AISContext();
270   if (aContext.IsNull())
271     return aErased;
272
273   AISObjectPtr anObject = myResult2AISObjectMap[theObject];
274   if (anObject) {
275     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
276     if (!anAIS.IsNull()) {
277       emit beforeObjectErase(theObject, anObject);
278       aContext->Remove(anAIS, false/*update viewer*/);
279       #ifdef VINSPECTOR
280       if (getCallBack()) getCallBack()->Remove(anAIS);
281       #endif
282       aErased = true;
283     }
284   }
285   myResult2AISObjectMap.remove(theObject);
286
287 #ifdef DEBUG_DISPLAY
288   std::ostringstream aPtrStr;
289   aPtrStr << theObject.get();
290   qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
291   qDebug(getResult2AISObjectMapInfo().c_str());
292 #endif
293
294   if (theUpdateViewer)
295     updateViewer();
296
297   return aErased;
298 }
299
300 bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
301 {
302   bool aRedisplayed = false;
303   if (!isVisible(theObject))
304     return aRedisplayed;
305
306   AISObjectPtr aAISObj = getAISObject(theObject);
307   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
308
309   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
310   if (aPrs) {
311     AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj);
312     if (!aAIS_Obj) {
313       aRedisplayed = erase(theObject, theUpdateViewer);
314       return aRedisplayed;
315     }
316     if (aAIS_Obj != aAISObj) {
317       appendResultObject(theObject, aAIS_Obj);
318     }
319     aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
320   }
321
322   Handle(AIS_InteractiveContext) aContext = AISContext();
323   if (!aContext.IsNull() && !aAISIO.IsNull()) {
324     // Check that the visualized shape is the same and the redisplay is not necessary
325     // Redisplay of AIS object leads to this object selection compute and the selection
326     // in the browser is lost
327     // this check is not necessary anymore because the selection store/restore is realized
328     // before and after the values modification.
329     // Moreother, this check avoids customize and redisplay presentation if the presentable
330     // parameter is changed.
331     bool isEqualShapes = false;
332     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
333     if (aResult.get() != NULL) {
334       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aAISIO);
335       if (!aShapePrs.IsNull()) {
336         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
337         if (aShapePtr.get()) {
338           const TopoDS_Shape& aOldShape = aShapePrs->Shape();
339           if (!aOldShape.IsNull())
340             isEqualShapes = aOldShape.IsEqual(aShapePtr->impl<TopoDS_Shape>());
341         }
342       }
343     }
344     // Customization of presentation
345     bool isCustomized = customizeObject(theObject);
346     #ifdef DEBUG_FEATURE_REDISPLAY
347       qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
348         arg(!isEqualShapes || isCustomized).arg(isEqualShapes)
349         .arg(isCustomized).toStdString().c_str());
350     #endif
351     if (!isEqualShapes || isCustomized) {
352       /// if shapes are equal and presentation are customized, selection should be restored
353       bool aNeedToRestoreSelection = isEqualShapes && isCustomized;
354       if (aNeedToRestoreSelection)
355         myWorkshop->module()->storeSelection();
356
357       aContext->Redisplay(aAISIO, false);
358
359       #ifdef VINSPECTOR
360       if (getCallBack()) getCallBack()->Redisplay(aAISIO);
361       #endif
362
363       if (aNeedToRestoreSelection)
364         myWorkshop->module()->restoreSelection();
365
366       aRedisplayed = true;
367       #ifdef DEBUG_FEATURE_REDISPLAY
368         qDebug("  Redisplay happens");
369       #endif
370       if (theUpdateViewer)
371         updateViewer();
372     }
373   }
374   return aRedisplayed;
375 }
376
377 void XGUI_Displayer::redisplayObjects()
378 {
379   // redisplay objects visualized in the viewer
380   static Events_ID EVENT_DISP = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
381   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
382   QObjectPtrList aDisplayed = myWorkshop->displayer()->displayedObjects();
383   QObjectPtrList::const_iterator anIt = aDisplayed.begin(), aLast = aDisplayed.end();
384   for (; anIt != aLast; anIt++) {
385     aECreator->sendUpdated(*anIt, EVENT_DISP);
386   }
387   Events_Loop::loop()->flush(EVENT_DISP);
388 }
389
390 void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer)
391 {
392 #ifdef DEBUG_DEACTIVATE
393   QString anInfoStr = ModuleBase_Tools::objectInfo(theObject);
394   qDebug(QString("deactivate: myActiveSelectionModes[%1]: %2, objects = ").
395     arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)).
396     arg(anInfoStr).
397     toStdString().c_str());
398 #endif
399   Handle(AIS_InteractiveContext) aContext = AISContext();
400   if (!aContext.IsNull() && isVisible(theObject)) {
401     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
402     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
403
404     deactivateAIS(anAIS);
405     if (theUpdateViewer)
406       updateViewer();
407   }
408 }
409
410 void XGUI_Displayer::deactivateObjects(const QObjectPtrList& theObjList,
411                                        const bool theUpdateViewer)
412 {
413   //Handle(AIS_InteractiveObject) aTrihedron = getTrihedron();
414   //if (!aTrihedron.IsNull())
415   //  deactivateAIS(aTrihedron);
416
417   QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
418   for (; anIt != aLast; anIt++) {
419     deactivate(*anIt, false);
420   }
421   //VSV It seems that there is no necessity to update viewer on deactivation
422   //if (theUpdateViewer)
423   //  updateViewer();
424 }
425
426 void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theModes)
427 {
428   Handle(AIS_InteractiveContext) aContext = AISContext();
429   if (aContext.IsNull() || !isVisible(theObject))
430     return;
431
432   AISObjectPtr aAISObj = getAISObject(theObject);
433
434   if (aAISObj.get() != NULL) {
435     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
436     TColStd_ListOfInteger aTColModes;
437     aContext->ActivatedModes(anAISIO, aTColModes);
438     TColStd_ListIteratorOfListOfInteger itr( aTColModes );
439     for (; itr.More(); itr.Next() ) {
440       theModes.append(itr.Value());
441     }
442   }
443 }
444
445 int XGUI_Displayer::getSelectionMode(int theShapeType)
446 {
447   return (theShapeType > TopAbs_SHAPE) ? theShapeType :
448                                          AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType);
449 }
450
451 bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& theObject)
452 {
453   bool aVisible = false;
454   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
455   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
456   if (aPrs.get() || aResult.get()) {
457     aVisible = theDisplayer->isVisible(theObject);
458     // compsolid is not visualized in the viewer,
459     // but should have presentation when all sub solids are
460     // visible. It is useful for highlight presentation where compsolid shape is selectable
461     if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) {
462       ResultCompSolidPtr aCompsolidResult =
463         std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
464       if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
465         bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0;
466         for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) {
467           anAllSubsVisible = theDisplayer->isVisible(aCompsolidResult->subResult(i));
468         }
469         aVisible = anAllSubsVisible;
470       }
471     }
472   }
473   // it is possible that feature is presentable and has results, so we should check visibility
474   // of results if presentation is not shown (e.g. Sketch Circle/Arc features)
475   if (!aVisible) {
476     // check if all results of the feature are visible
477     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
478     std::list<ResultPtr> aResults;
479     ModelAPI_Tools::allResults(aFeature, aResults);
480     std::list<ResultPtr>::const_iterator aIt;
481     aVisible = !aResults.empty();
482     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
483       aVisible = aVisible && theDisplayer->isVisible(*aIt);
484     }
485   }
486   return aVisible;
487 }
488
489 #ifdef DEBUG_ACTIVATE_OBJECTS
490 QString getModeInfo(const int theMode)
491 {
492   QString anInfo = "Undefined";
493   switch(theMode) {
494     case 0: anInfo = "SHAPE(0)"; break;
495     case 1: anInfo = "VERTEX(1)"; break;
496     case 2: anInfo = "EDGE(2)"; break;
497     case 3: anInfo = "WIRE(3)"; break;
498     case 4: anInfo = "FACE(4)"; break;
499     case 5: anInfo = "SHELL(5)"; break;
500     case 6: anInfo = "SOLID(6)"; break;
501     case 7: anInfo = "COMPSOLID(7)"; break;
502     case 8: anInfo = "COMPOUND(8)"; break;
503     case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools
504     case 101: anInfo = "Sel_Constraint(101)"; break;
505     case 102: anInfo = "Sel_Dimension_All(102)"; break;
506     case 103: anInfo = "Sel_Dimension_Line(103)"; break;
507     case 104: anInfo = "Sel_Dimension_Text(104)"; break;
508     default: break;
509   }
510   return anInfo;
511 }
512
513 QString getModesInfo(const QIntList& theModes)
514 {
515   QStringList aModesInfo;
516   for (int i = 0, aSize = theModes.size(); i < aSize; i++)
517     aModesInfo.append(getModeInfo(theModes[i]));
518   return QString("[%1] = %2").arg(aModesInfo.size()).arg(aModesInfo.join(", "));
519 }
520 #endif
521
522 void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
523                                      const bool theUpdateViewer)
524 {
525   // Convert shape types to selection types
526   QIntList aModes;
527   foreach(int aType, theModes) {
528     aModes.append(getSelectionMode(aType));
529   }
530
531 #ifdef DEBUG_ACTIVATE_OBJECTS
532   QStringList anInfo;
533   QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
534   for (; anIt != aLast; ++anIt) {
535     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
536   }
537   QString anInfoStr = anInfo.join(", ");
538
539   qDebug(QString("activateObjects: new modes%1, active modes%2, objects[%3] = %4").
540     arg(getModesInfo(aModes)).
541     arg(getModesInfo(myActiveSelectionModes)).
542     arg(theObjList.size()).
543     arg(anInfoStr).
544     toStdString().c_str());
545 #endif
546   // In order to avoid doblications of selection modes
547   QIntList aNewModes;
548   foreach (int aMode, aModes) {
549     if (!aNewModes.contains(aMode))
550       aNewModes.append(aMode);
551   }
552   myActiveSelectionModes = aNewModes;
553   Handle(AIS_InteractiveContext) aContext = AISContext();
554   // Open local context if there is no one
555   if (aContext.IsNull())
556     return;
557
558   //aContext->UseDisplayedObjects();
559   //myUseExternalObjects = true;
560
561   Handle(AIS_InteractiveObject) anAISIO;
562   AIS_ListOfInteractive aPrsList;
563   //if (aObjList.isEmpty())
564   //  return;
565   //else {
566   foreach(ObjectPtr aObj, theObjList) {
567     if (myResult2AISObjectMap.contains(aObj))
568       aPrsList.Append(myResult2AISObjectMap[aObj]->impl<Handle(AIS_InteractiveObject)>());
569   }
570   //}
571
572   // Add trihedron because it has to partisipate in selection
573   Handle(AIS_InteractiveObject) aTrihedron;
574   if (isTrihedronActive()) {
575     aTrihedron = getTrihedron();
576     if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron))
577       aPrsList.Append(aTrihedron);
578   }
579   if (aPrsList.Extent() == 0)
580     return;
581
582   AIS_ListIteratorOfListOfInteractive aLIt(aPrsList);
583   bool isActivationChanged = false;
584   for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
585     anAISIO = aLIt.Value();
586     if (activate(anAISIO, myActiveSelectionModes, false))
587       isActivationChanged = true;
588   }
589 }
590
591 bool XGUI_Displayer::isActive(ObjectPtr theObject) const
592 {
593   Handle(AIS_InteractiveContext) aContext = AISContext();
594   if (aContext.IsNull() || !isVisible(theObject))
595     return false;
596
597   AISObjectPtr anObj = myResult2AISObjectMap[theObject];
598   Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
599
600   TColStd_ListOfInteger aModes;
601   aContext->ActivatedModes(anAIS, aModes);
602   #ifdef VINSPECTOR
603   if (getCallBack()) getCallBack()->ActivatedModes(anAIS, aModes);
604   #endif
605
606   return aModes.Extent() > 0;
607 }
608
609
610 void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrsPtr>& theValues,
611                                  bool theUpdateViewer)
612 {
613   Handle(AIS_InteractiveContext) aContext = AISContext();
614   if (aContext.IsNull())
615     return;
616   aContext->UnhilightSelected(false);
617   aContext->ClearSelected(false);
618   #ifdef VINSPECTOR
619   if (getCallBack()) getCallBack()->ClearSelected();
620   #endif
621   NCollection_DataMap<TopoDS_Shape, NCollection_Map<Handle(AIS_InteractiveObject)>>
622     aShapesToBeSelected;
623
624   foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) {
625     const GeomShapePtr& aGeomShape = aPrs->shape();
626     if (aGeomShape.get() && !aGeomShape->isNull()) {
627       const TopoDS_Shape& aShape = aGeomShape->impl<TopoDS_Shape>();
628 #ifdef DEBUG_OCCT_SHAPE_SELECTION
629       // problem 1: performance
630       // problem 2: IO is not specified, so the first found owner is selected, as a result
631       // it might belong to another result
632       aContext->AddOrRemoveSelected(aShape, false);
633       #ifdef VINSPECTOR
634       if (getCallBack()) getCallBack()->AddOrRemoveSelected(aShape);
635       #endif
636 #else
637       NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations;
638       if (aShapesToBeSelected.IsBound(aShape))
639         aPresentations = aShapesToBeSelected.Find(aShape);
640       ObjectPtr anObject = aPrs->object();
641       getPresentations(anObject, aPresentations);
642
643       aShapesToBeSelected.Bind(aShape, aPresentations);
644 #endif
645     } else {
646       ObjectPtr anObject = aPrs->object();
647       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
648       if (aResult.get() && isVisible(aResult)) {
649         AISObjectPtr anObj = myResult2AISObjectMap[aResult];
650         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
651         if (!anAIS.IsNull()) {
652           // The methods are replaced in order to provide multi-selection, e.g. restore selection
653           // by activating multi selector widget. It also gives an advantage that the multi
654           // selection in OB gives multi-selection in the viewer
655           //aContext->SetSelected(anAIS, false);
656           // The selection in the context was cleared, so the method sets the objects are selected
657           aContext->AddOrRemoveSelected(anAIS, false);
658           #ifdef VINSPECTOR
659           if (getCallBack()) getCallBack()->AddOrRemoveSelected(anAIS);
660           #endif
661         }
662       }
663     }
664   }
665   if (!aShapesToBeSelected.IsEmpty())
666     XGUI_Displayer::AddOrRemoveSelectedShapes(aContext, aShapesToBeSelected);
667
668   if (theUpdateViewer)
669     updateViewer();
670 }
671
672 void XGUI_Displayer::clearSelected(const bool theUpdateViewer)
673 {
674   Handle(AIS_InteractiveContext) aContext = AISContext();
675   if (!aContext.IsNull()) {
676     aContext->UnhilightCurrents(false);
677     aContext->ClearSelected(theUpdateViewer);
678     #ifdef VINSPECTOR
679     if (getCallBack()) getCallBack()->ClearSelected();
680     #endif
681   }
682 }
683
684 bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
685 {
686   bool aErased = false;
687   Handle(AIS_InteractiveContext) aContext = AISContext();
688   if (!aContext.IsNull()) {
689     foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
690       AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
691       // erase an object
692       Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
693       if (!anIO.IsNull()) {
694         emit beforeObjectErase(aObj, aAISObj);
695         aContext->Remove(anIO, false/*update viewer*/);
696         #ifdef VINSPECTOR
697         if (getCallBack()) getCallBack()->Remove(anIO);
698         #endif
699         aErased = true;
700       }
701     }
702     if (theUpdateViewer)
703       updateViewer();
704   }
705   myResult2AISObjectMap.clear();
706 #ifdef DEBUG_DISPLAY
707   qDebug("eraseAll");
708   qDebug(getResult2AISObjectMapInfo().c_str());
709 #endif
710   return aErased;
711 }
712
713 void deactivateObject(Handle(AIS_InteractiveContext) theContext,
714                       Handle(AIS_InteractiveObject) theObject
715 #ifdef VINSPECTOR
716                       , VInspectorAPI_CallBack* theCallBack
717 #endif
718                       )
719 {
720   if (!theObject.IsNull()) {
721     theContext->Deactivate(theObject);
722     #ifdef VINSPECTOR
723     if (theCallBack) theCallBack->Deactivate(theObject);
724     #endif
725   }
726 }
727
728 void XGUI_Displayer::deactivateTrihedron(const bool theUpdateViewer) const
729 {
730   Handle(AIS_InteractiveObject) aTrihedron = getTrihedron();
731   Handle(AIS_InteractiveContext) aContext = AISContext();
732   if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) {
733     Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron);
734     deactivateObject(aContext, aTrie
735     #ifdef VINSPECTOR
736       , getCallBack()
737     #endif
738       );
739
740     /// #1136 hidden axis are selected in sketch
741     deactivateObject(aContext, aTrie->XAxis()
742     #ifdef VINSPECTOR
743       , getCallBack()
744     #endif
745     );
746     deactivateObject(aContext, aTrie->YAxis()
747     #ifdef VINSPECTOR
748       , getCallBack()
749     #endif
750     );
751     deactivateObject(aContext, aTrie->Axis()
752     #ifdef VINSPECTOR
753       , getCallBack()
754     #endif
755     );
756     deactivateObject(aContext, aTrie->Position()
757     #ifdef VINSPECTOR
758       , getCallBack()
759     #endif
760     );
761
762     deactivateObject(aContext, aTrie->XYPlane()
763     #ifdef VINSPECTOR
764       , getCallBack()
765     #endif
766     );
767     deactivateObject(aContext, aTrie->XZPlane()
768     #ifdef VINSPECTOR
769       , getCallBack()
770     #endif
771     );
772     deactivateObject(aContext, aTrie->YZPlane()
773     #ifdef VINSPECTOR
774       , getCallBack()
775     #endif
776     );
777
778     if (theUpdateViewer)
779       updateViewer();
780   }
781 }
782
783 Handle(AIS_InteractiveObject) XGUI_Displayer::getTrihedron() const
784 {
785   return myWorkshop->viewer()->trihedron();
786 }
787
788 /*void XGUI_Displayer::openLocalContext()
789 {
790   Handle(AIS_InteractiveContext) aContext = AISContext();
791   // Open local context if there is no one
792   if (!aContext.IsNull() && !aContext->HasOpenedContext()) {
793     // Preserve selected objects
794     //AIS_ListOfInteractive aAisList;
795     //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent())
796     //  aAisList.Append(aContext->Current());
797
798     // get the filters from the global context and append them to the local context
799     // a list of filters in the global context is not cleared and should be cleared here
800     SelectMgr_ListOfFilter aFilters;
801     aFilters.Assign(aContext->Filters());
802     // it is important to remove the filters in the global context, because there is a code
803     // in the closeLocalContex, which restore the global context filters
804     aContext->RemoveFilters();
805
806     //aContext->ClearCurrents();
807     aContext->OpenLocalContext();
808     //deactivateTrihedron();
809     //aContext->NotUseDisplayedObjects();
810
811     //myUseExternalObjects = false;
812
813     SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
814     for (;aIt.More(); aIt.Next()) {
815       aContext->AddFilter(aIt.Value());
816     }
817     // Restore selection
818     //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
819     //for(; aIt2.More(); aIt2.Next()) {
820     //  aContext->SetSelected(aIt2.Value(), false);
821     //}
822   }
823 }*/
824
825 /*void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer)
826 {
827   Handle(AIS_InteractiveContext) aContext = AISContext();
828   if (!aContext.IsNull() && aContext->HasOpenedContext()) {
829     // Preserve selected objects
830     //AIS_ListOfInteractive aAisList;
831     //for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
832     //  aAisList.Append(aContext->SelectedInteractive());
833
834     // get the filters from the local context and append them to the global context
835     // a list of filters in the local context is cleared
836     SelectMgr_ListOfFilter aFilters;
837     aFilters.Assign(aContext->Filters());
838
839     //aContext->ClearSelected();
840     aContext->CloseAllContexts(false);
841
842     // From the moment when the AIS_DS_Displayed flag is used in the Display of AIS object,
843     // this code is obsolete. It is temporaty commented and should be removed after
844     // the test campaign.
845     // Redisplay all object if they were displayed in localContext
846     /*Handle(AIS_InteractiveObject) aAISIO;
847     foreach (AISObjectPtr aAIS, myResult2AISObjectMap) {
848       aAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
849       if (aContext->DisplayStatus(aAISIO) != AIS_DS_Displayed) {
850         aContext->Display(aAISIO, false);
851         aContext->SetDisplayMode(aAISIO, Shading, false);
852       }
853     }*+/
854
855     // Append the filters from the local selection in the global selection context
856     SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
857     for (;aIt.More(); aIt.Next()) {
858       Handle(SelectMgr_Filter) aFilter = aIt.Value();
859       aContext->AddFilter(aFilter);
860     }
861
862     if (theUpdateViewer)
863       updateViewer();
864     //myUseExternalObjects = false;
865
866     // Restore selection
867     //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
868     //for(; aIt2.More(); aIt2.Next()) {
869     //  if (aContext->IsDisplayed(aIt2.Value()))
870     //    aContext->SetCurrentObject(aIt2.Value(), false);
871     //}
872   }
873 }*/
874
875 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
876 {
877   AISObjectPtr anIO;
878   if (myResult2AISObjectMap.contains(theObject))
879     anIO = myResult2AISObjectMap[theObject];
880   return anIO;
881 }
882
883 ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
884 {
885   Handle(AIS_InteractiveObject) aRefAIS = theIO->impl<Handle(AIS_InteractiveObject)>();
886   return getObject(aRefAIS);
887 }
888
889 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
890 {
891   ObjectPtr anObject;
892   foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) {
893     AISObjectPtr aAIS = myResult2AISObjectMap[anObj];
894     Handle(AIS_InteractiveObject) anAIS = aAIS->impl<Handle(AIS_InteractiveObject)>();
895     if (anAIS == theIO)
896       anObject = anObj;
897     if (anObject.get())
898       break;
899   }
900   if (!anObject.get()) {
901     std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
902     if (!theIO.IsNull()) {
903       anAISObj->setImpl(new Handle(AIS_InteractiveObject)(theIO));
904     }
905     anObject = myWorkshop->module()->findPresentedObject(anAISObj);
906   }
907   return anObject;
908 }
909
910 bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
911 {
912   bool aWasEnabled = isUpdateEnabled();
913   if (isEnabled)
914     myViewerBlockedRecursiveCount--;
915   else
916     myViewerBlockedRecursiveCount++;
917
918   if (myNeedUpdate && isUpdateEnabled()) {
919     updateViewer();
920     myNeedUpdate = false;
921   }
922   return aWasEnabled;
923 }
924
925 bool XGUI_Displayer::isUpdateEnabled() const
926 {
927   return myViewerBlockedRecursiveCount == 0;
928 }
929
930 void XGUI_Displayer::updateViewer() const
931 {
932   Handle(AIS_InteractiveContext) aContext = AISContext();
933   if (!aContext.IsNull() && isUpdateEnabled()) {
934     myWorkshop->viewer()->Zfitall();
935     aContext->UpdateCurrentViewer();
936   } else {
937     myNeedUpdate = true;
938   }
939 }
940
941 void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
942                                  const int theMode, const bool theUpdateViewer) const
943 {
944   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
945   if (!theIO.IsNull() && theIO == getTrihedron()) {
946     if (theMode != AIS_Shape::SelectionType(TopAbs_EDGE) &&
947         theMode != AIS_Shape::SelectionType(TopAbs_VERTEX))
948       return;
949   }
950   if (!aContext.IsNull()) {
951     if (myWorkshop->module()) {
952       int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode);
953       aContext->Activate(theIO, theMode, false);
954     } else
955       aContext->Activate(theIO, theMode, false);
956     #ifdef VINSPECTOR
957     if (getCallBack()) getCallBack()->Activate(theIO, theMode);
958     #endif
959
960     // the fix from VPA for more suitable selection of sketcher lines
961     if (theIO->Width() > 1) {
962       double aPrecision = theIO->Width() + 2;
963       if (theMode == getSelectionMode(TopAbs_VERTEX))
964         aPrecision = ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
965                                                                     "point-selection-sensitivity",
966                                                                         12);
967       else if ((theMode == getSelectionMode(TopAbs_EDGE)) ||
968                (theMode == getSelectionMode(TopAbs_WIRE)))
969         aPrecision = theIO->Width() +
970            ModuleBase_Preferences::resourceMgr()->doubleValue("Viewer",
971                                                               "edge-selection-sensitivity", 2);
972       aContext->SetSelectionSensitivity(theIO, theMode, aPrecision);
973     }
974
975 #ifdef DEBUG_ACTIVATE_AIS
976     ObjectPtr anObject = getObject(theIO);
977     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
978     qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode)
979       .arg(anInfo).toStdString().c_str());
980 #endif
981     if (theUpdateViewer)
982       updateViewer();
983   }
984 }
985
986 void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO,
987                                    const int theMode) const
988 {
989   Handle(AIS_InteractiveContext) aContext = AISContext();
990   if (!aContext.IsNull()) {
991     if (theMode == -1) {
992       aContext->Deactivate(theIO);
993       #ifdef VINSPECTOR
994       if (getCallBack()) getCallBack()->Deactivate(theIO);
995       #endif
996     }
997     else {
998       aContext->Deactivate(theIO, theMode);
999       #ifdef VINSPECTOR
1000       if (getCallBack()) getCallBack()->Deactivate(theIO, theMode);
1001       #endif
1002     }
1003
1004 #ifdef DEBUG_DEACTIVATE_AIS
1005     ObjectPtr anObject = getObject(theIO);
1006     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
1007     qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode)
1008       .arg(anInfo).toStdString().c_str());
1009 #endif
1010   }
1011 }
1012
1013 Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
1014 {
1015   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
1016   if (!aContext.IsNull() && myIsFirstAISContextUse/*&& !aContext->HasOpenedContext()*/) {
1017 #ifdef VINSPECTOR
1018     if (VInspector_FirstCall) {
1019       XGUI_Displayer* aDisplayer = (XGUI_Displayer*)this;
1020       VInspectorAPI_Communicator* aCommunicator = VInspectorAPI_PluginMgr::activateVInspector(
1021                                         "VInspector.dll", aContext);
1022       aDisplayer->setCommunicator(aCommunicator);
1023       #ifndef HAVE_SALOME
1024       AppElements_Viewer* aViewer = myWorkshop->mainWindow()->viewer();
1025       if (aViewer)
1026         aViewer->setCallBack(aCommunicator->getCallBack());
1027       #endif
1028       VInspector_FirstCall = false;
1029     }
1030 #endif
1031     XGUI_Displayer* aDisplayer = (XGUI_Displayer*)this;
1032     aDisplayer->myIsFirstAISContextUse = false;
1033     //aContext->OpenLocalContext();
1034     if (!isTrihedronActive())
1035       deactivateTrihedron(true);
1036     aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
1037     aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
1038   }
1039   return aContext;
1040 }
1041
1042 Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter()
1043 {
1044   Handle(AIS_InteractiveContext) aContext = AISContext();
1045   if (!aContext.IsNull() && myAndFilter.IsNull()) {
1046     myAndFilter = new SelectMgr_AndFilter();
1047     aContext->AddFilter(myAndFilter);
1048   }
1049   return myAndFilter;
1050 }
1051
1052 bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes,
1053                                 bool theUpdateViewer)
1054 {
1055   bool aDisplayed = false;
1056   Handle(AIS_InteractiveContext) aContext = AISContext();
1057   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
1058   if (!aContext.IsNull() && !anAISIO.IsNull()) {
1059     aContext->Display(anAISIO, 0/*wireframe*/, 0, false/*update viewer*/, true, AIS_DS_Displayed);
1060     #ifdef VINSPECTOR
1061     if (getCallBack()) getCallBack()->Display(anAISIO);
1062     #endif
1063     aDisplayed = true;
1064     aContext->Deactivate(anAISIO);
1065     #ifdef VINSPECTOR
1066     if (getCallBack()) getCallBack()->Deactivate(anAISIO);
1067     #endif
1068     aContext->Load(anAISIO);
1069     #ifdef VINSPECTOR
1070     if (getCallBack()) getCallBack()->Load(anAISIO);
1071     #endif
1072     if (toActivateInSelectionModes) {
1073       if (myActiveSelectionModes.size() == 0)
1074         activateAIS(anAISIO, 0, theUpdateViewer);
1075       else {
1076         foreach(int aMode, myActiveSelectionModes) {
1077           activateAIS(anAISIO, aMode, theUpdateViewer);
1078         }
1079       }
1080     }
1081     if (theUpdateViewer)
1082       updateViewer();
1083   }
1084   return aDisplayed;
1085 }
1086
1087 bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
1088 {
1089   bool aErased = false;
1090   Handle(AIS_InteractiveContext) aContext = AISContext();
1091   if (!aContext.IsNull()) {
1092     Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
1093     if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) {
1094       aContext->Remove(anAISIO, false/*update viewer*/);
1095       #ifdef VINSPECTOR
1096       if (getCallBack()) getCallBack()->Remove(anAISIO);
1097       #endif
1098       aErased = true;
1099     }
1100   }
1101   if (aErased && theUpdateViewer)
1102     updateViewer();
1103   return aErased;
1104 }
1105
1106
1107 void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer)
1108 {
1109   if (theMode == NoMode)
1110     return;
1111
1112   Handle(AIS_InteractiveContext) aContext = AISContext();
1113   if (aContext.IsNull())
1114     return;
1115
1116   AISObjectPtr aAISObj = getAISObject(theObject);
1117   if (!aAISObj)
1118     return;
1119
1120   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1121   aContext->SetDisplayMode(aAISIO, theMode, false);
1122   // Redisplay in order to update new mode because it could be not computed before
1123   if (theUpdateViewer)
1124     updateViewer();
1125 }
1126
1127 XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const
1128 {
1129   Handle(AIS_InteractiveContext) aContext = AISContext();
1130   if (aContext.IsNull())
1131     return NoMode;
1132
1133   AISObjectPtr aAISObj = getAISObject(theObject);
1134   if (!aAISObj)
1135     return NoMode;
1136
1137   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1138   return (XGUI_Displayer::DisplayMode) aAISIO->DisplayMode();
1139 }
1140
1141 void XGUI_Displayer::deactivateSelectionFilters()
1142 {
1143   Handle(AIS_InteractiveContext) aContext = AISContext();
1144   if (!myAndFilter.IsNull()) {
1145     bool aFound = false;
1146     if (!aContext.IsNull()) {
1147       const SelectMgr_ListOfFilter& aFilters = aContext->Filters();
1148       SelectMgr_ListIteratorOfListOfFilter anIt(aFilters);
1149       for (; anIt.More() && !aFound; anIt.Next()) {
1150         Handle(SelectMgr_Filter) aFilter = anIt.Value();
1151         aFound = aFilter == myAndFilter;
1152       }
1153       if (aFound)
1154         aContext->RemoveFilter(myAndFilter);
1155     }
1156     myAndFilter.Nullify();
1157   }
1158 }
1159
1160 void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
1161 {
1162   Handle(AIS_InteractiveContext) aContext = AISContext();
1163   if (aContext.IsNull() || hasSelectionFilter(theFilter))
1164     return;
1165
1166   Handle(SelectMgr_CompositionFilter) aCompositeFilter = GetFilter();
1167   if (!aCompositeFilter.IsNull()) {
1168     aCompositeFilter->Add(theFilter);
1169 #ifdef DEBUG_SELECTION_FILTERS
1170     int aCount = aCompositeFilter->StoredFilters().Extent();
1171     qDebug(QString("addSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
1172 #endif
1173   }
1174 }
1175
1176 void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
1177 {
1178   Handle(AIS_InteractiveContext) aContext = AISContext();
1179   if (aContext.IsNull())
1180     return;
1181
1182   Handle(SelectMgr_AndFilter) aCompositeFilter = GetFilter();
1183   if (!aCompositeFilter.IsNull() && aCompositeFilter->IsIn(theFilter)) {
1184     aCompositeFilter->Remove(theFilter);
1185 #ifdef DEBUG_SELECTION_FILTERS
1186     int aCount = aCompositeFilter->StoredFilters().Extent();
1187     qDebug(QString("removeSelectionFilter: filters.count() = %1")
1188       .arg(aCount).toStdString().c_str());
1189 #endif
1190   }
1191 }
1192
1193 bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
1194 {
1195   bool aFilterFound = false;
1196
1197   Handle(AIS_InteractiveContext) aContext = AISContext();
1198   if (aContext.IsNull())
1199     return aFilterFound;
1200   const SelectMgr_ListOfFilter& aFilters = aContext->Filters();
1201   SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
1202   for (; aIt.More() && !aFilterFound; aIt.Next()) {
1203     if (theFilter.get() == aIt.Value().get())
1204       aFilterFound = true;
1205   }
1206   Handle(SelectMgr_CompositionFilter) aCompositeFilter = GetFilter();
1207   if (!aCompositeFilter.IsNull()) {
1208     const SelectMgr_ListOfFilter& aStoredFilters = aCompositeFilter->StoredFilters();
1209     for (aIt.Initialize(aStoredFilters); aIt.More() && !aFilterFound; aIt.Next()) {
1210       if (theFilter.get() == aIt.Value().get())
1211         aFilterFound = true;
1212     }
1213   }
1214   return aFilterFound;
1215 }
1216
1217 void XGUI_Displayer::removeFilters()
1218 {
1219   Handle(AIS_InteractiveContext) aContext = AISContext();
1220   if (aContext.IsNull())
1221     return;
1222
1223   Handle(SelectMgr_CompositionFilter) aCompositeFilter = GetFilter();
1224   if (!aCompositeFilter.IsNull())
1225     aCompositeFilter->Clear();
1226 }
1227
1228 void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
1229 {
1230   QObjectPtrList aDispList = myResult2AISObjectMap.keys();
1231   foreach(ObjectPtr aObj, aDispList) {
1232     if (!theList.contains(aObj))
1233       erase(aObj, false);
1234   }
1235   foreach(ObjectPtr aObj, theList) {
1236     if (!isVisible(aObj))
1237       display(aObj, false);
1238   }
1239   updateViewer();
1240 }
1241
1242 bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const
1243 {
1244   if (!isVisible(theObject))
1245     return false;
1246
1247   AISObjectPtr aAISObj = getAISObject(theObject);
1248   if (aAISObj.get() == NULL)
1249     return false;
1250
1251   Handle(AIS_InteractiveObject) anAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1252   return ::canBeShaded(anAIS, myWorkshop->module());
1253 }
1254
1255 bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
1256                               const QIntList& theModes,
1257                               const bool theUpdateViewer) const
1258 {
1259   Handle(AIS_InteractiveContext) aContext = AISContext();
1260   if (aContext.IsNull() || theIO.IsNull())
1261     return false;
1262
1263   bool isActivationChanged = false;
1264   // deactivate object in all modes, which are not in the list of activation
1265   // It seems that after the IO deactivation the selected state of the IO's owners
1266   // is modified in OCC(version: 6.8.0) and the selection of the object later is lost.
1267   // By this reason, the number of the IO deactivate is decreased and the object is deactivated
1268   // only if there is a difference in the current modes and the parameters modes.
1269   // If the selection problem happens again, it is possible to write a test scenario and create
1270   // a bug. The bug steps are the following:
1271   // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both,
1272   // with clicked SHIFT select the second object.
1273   // The result is the selection of the first IO is lost.
1274   TColStd_ListOfInteger aTColModes;
1275   aContext->ActivatedModes(theIO, aTColModes);
1276   #ifdef VINSPECTOR
1277   if (getCallBack()) getCallBack()->ActivatedModes(theIO, aTColModes);
1278   #endif
1279   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
1280   QIntList aModesActivatedForIO;
1281   bool isDeactivated = false;
1282   bool aHasValidMode = false;
1283   for (; itr.More(); itr.Next() ) {
1284     Standard_Integer aMode = itr.Value();
1285     aHasValidMode = aHasValidMode || aMode != -1;
1286     int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
1287     if (!theModes.contains(aMode)) {
1288       deactivateAIS(theIO, aMode);
1289       isDeactivated = true;
1290     }
1291     else {
1292       aModesActivatedForIO.append(aMode);
1293     }
1294   }
1295   if (isDeactivated) {
1296 #ifdef DEBUG_OCCT_26172
1297     // the selection from the previous activation modes should be cleared manually (#26172)
1298     theIO->ClearSelected();
1299     #ifdef VINSPECTOR
1300     if (getCallBack()) getCallBack()->ClearSelected(theIO);
1301     #endif
1302 #endif
1303     // For performance issues
1304     //if (theUpdateViewer)
1305     //  updateViewer();
1306     isActivationChanged = true;
1307   }
1308
1309   // loading the interactive object allowing the decomposition
1310   if (aTColModes.IsEmpty() || !aHasValidMode) {
1311     aContext->Load(theIO, -1, true);
1312     #ifdef VINSPECTOR
1313     if (getCallBack()) getCallBack()->Load(theIO);
1314     #endif
1315   }
1316
1317   // trihedron AIS check should be after the AIS loading.
1318   // If it is not loaded, it is steel selectable in the viewer.
1319   Handle(AIS_Trihedron) aTrihedron;
1320   if (!isTrihedronActive())
1321     aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
1322   if (aTrihedron.IsNull()) {
1323       // In order to clear active modes list
1324     if (theModes.size() == 0) {
1325       activateAIS(theIO, 0, theUpdateViewer);
1326     } else {
1327       foreach(int aMode, theModes) {
1328         if (!aModesActivatedForIO.contains(aMode)) {
1329           activateAIS(theIO, aMode, theUpdateViewer);
1330           isActivationChanged = true;
1331         }
1332       }
1333     }
1334   }
1335   return isActivationChanged;
1336 }
1337
1338 bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
1339 {
1340   AISObjectPtr anAISObj = getAISObject(theObject);
1341   // correct the result's color it it has the attribute
1342   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1343
1344   // Customization of presentation
1345   GeomCustomPrsPtr aCustomPrs;
1346   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
1347   if (aFeature.get() != NULL) {
1348     GeomCustomPrsPtr aCustPrs = std::dynamic_pointer_cast<GeomAPI_ICustomPrs>(aFeature);
1349     if (aCustPrs.get() != NULL)
1350       aCustomPrs = aCustPrs;
1351   }
1352   if (aCustomPrs.get() == NULL) {
1353     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
1354     // we ignore presentable not customized objects
1355     if (aPrs.get() == NULL)
1356       aCustomPrs = myCustomPrs;
1357   }
1358   bool isCustomized = aCustomPrs.get() &&
1359                       aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
1360   return isCustomized;
1361 }
1362
1363
1364 QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
1365                                       const QColor& theColor,
1366                                       bool theUpdateViewer)
1367 {
1368   if (!isVisible(theObject))
1369     return Qt::black;
1370
1371   AISObjectPtr anAISObj = getAISObject(theObject);
1372   int aR, aG, aB;
1373   anAISObj->getColor(aR, aG, aB);
1374   anAISObj->setColor(theColor.red(), theColor.green(), theColor.blue());
1375   if (theUpdateViewer)
1376     updateViewer();
1377   return QColor(aR, aG, aB);
1378 }
1379
1380 void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
1381 {
1382   myResult2AISObjectMap[theObject] = theAIS;
1383
1384 #ifdef DEBUG_DISPLAY
1385   std::ostringstream aPtrStr;
1386   aPtrStr << theObject.get();
1387   qDebug(QString("display object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
1388   qDebug(getResult2AISObjectMapInfo().c_str());
1389 #endif
1390 }
1391
1392 #ifdef _DEBUG
1393 std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
1394 {
1395   QStringList aContent;
1396   foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
1397     AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
1398     std::ostringstream aPtrStr;
1399     aPtrStr << "aObj = " << aObj.get() << ":";
1400     aPtrStr << "anAIS = " << aAISObj.get() << ":";
1401     aPtrStr << "[" << ModuleBase_Tools::objectInfo(aObj).toStdString().c_str() << "]";
1402
1403     aContent.append(aPtrStr.str().c_str());
1404   }
1405   return QString("myResult2AISObjectMap: size = %1\n%2\n").arg(myResult2AISObjectMap.size()).
1406                                             arg(aContent.join("\n")).toStdString().c_str();
1407 }
1408 #endif
1409
1410 void XGUI_Displayer::getPresentations(const ObjectPtr& theObject,
1411                                   NCollection_Map<Handle(AIS_InteractiveObject)>& thePresentations)
1412 {
1413   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1414   if (aResult.get()) {
1415     AISObjectPtr aAISObj = getAISObject(aResult);
1416     if (aAISObj.get() != NULL) {
1417       Handle(AIS_InteractiveObject) anAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1418       if (!anAIS.IsNull() && !thePresentations.Contains(anAIS))
1419         thePresentations.Add(anAIS);
1420     }
1421   }
1422   else {
1423     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
1424     // find presentation of the feature
1425     AISObjectPtr aAISObj = getAISObject(aFeature);
1426     if (aAISObj.get() != NULL) {
1427       Handle(AIS_InteractiveObject) anAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1428       if (!anAIS.IsNull() && !thePresentations.Contains(anAIS))
1429         thePresentations.Add(anAIS);
1430     }
1431     // find presentations of the feature results
1432     std::list<ResultPtr> aResults;
1433     ModelAPI_Tools::allResults(aFeature, aResults);
1434     std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
1435     for (; anIt != aLast; ++anIt) {
1436       AISObjectPtr aAISObj = getAISObject(*anIt);
1437       if (aAISObj.get() != NULL) {
1438         Handle(AIS_InteractiveObject) anAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
1439         if (!anAIS.IsNull() && !thePresentations.Contains(anAIS))
1440           thePresentations.Add(anAIS);
1441       }
1442     }
1443   }
1444 }
1445
1446 void XGUI_Displayer::activateTrihedron(bool theIsActive)
1447 {
1448   myIsTrihedronActive = theIsActive;
1449   if (!myIsTrihedronActive) {
1450     deactivateTrihedron(true);
1451   }
1452 }
1453
1454 void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
1455 {
1456   Handle(AIS_InteractiveContext) aContext = AISContext();
1457   if (aContext.IsNull())
1458     return;
1459
1460   Handle(AIS_Trihedron) aTrihedron = myWorkshop->viewer()->trihedron();
1461
1462   if (theToDisplay) {
1463     if (!aContext->IsDisplayed(aTrihedron))
1464       aContext->Display(aTrihedron,
1465                         0 /*wireframe*/,
1466                         -1 /* selection mode */,
1467                         Standard_True /* update viewer*/,
1468                         Standard_False /* allow decomposition */,
1469                         AIS_DS_Displayed /* xdisplay status */);
1470     #ifdef VINSPECTOR
1471     if (getCallBack()) getCallBack()->Display(aTrihedron);
1472     #endif
1473
1474     if (!isTrihedronActive())
1475       deactivateTrihedron(false);
1476     else
1477       activate(aTrihedron, myActiveSelectionModes, false);
1478   } else {
1479     deactivateTrihedron(false);
1480
1481     aContext->Erase(aTrihedron);
1482     #ifdef VINSPECTOR
1483     if (getCallBack()) getCallBack()->Remove(aTrihedron);
1484     #endif
1485   }
1486
1487   updateViewer();
1488 }
1489
1490 QIntList XGUI_Displayer::activeSelectionModes() const
1491 {
1492   QIntList aModes;
1493   foreach (int aMode, myActiveSelectionModes) {
1494     // aMode < 9 is a Shape Enum values
1495     aModes << ((aMode < 9)? AIS_Shape::SelectionType(aMode) : aMode);
1496   }
1497   return aModes;
1498 }
1499
1500 #ifdef VINSPECTOR
1501 void XGUI_Displayer::setCommunicator(VInspectorAPI_Communicator* theCommunicator)
1502 {
1503   myCommunicator = theCommunicator;
1504 }
1505
1506 void XGUI_Displayer::setVInspectorVisible(const bool theVisible)
1507 {
1508   if (myCommunicator)
1509     myCommunicator->setVisible(true);
1510 }
1511
1512 VInspectorAPI_CallBack* XGUI_Displayer::getCallBack() const
1513 {
1514   return myCommunicator ? myCommunicator->getCallBack() : NULL;
1515 }
1516 #endif
1517
1518 void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext,
1519                            const NCollection_DataMap<TopoDS_Shape,
1520                            NCollection_Map<Handle(AIS_InteractiveObject)>>& theShapesToBeSelected)
1521 {
1522   NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
1523   theContext->MainSelector()->ActiveOwners(anActiveOwners);
1524   NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners);
1525   Handle(SelectMgr_EntityOwner) anOwner;
1526
1527   /// It is very important to check that the owner is processed only once and has a map of
1528   /// processed owners because SetSelected works as a switch.
1529   /// If count of calls setSelectec is even, the object stays in the previous state
1530   /// (selected, deselected)
1531   /// OCCT: to write about the problem that active owners method returns one owner several times
1532   QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
1533   for (; anOwnersIt.More(); anOwnersIt.Next()) {
1534     anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
1535     if (aSelectedIds.contains((long)anOwner.get()))
1536       continue;
1537     aSelectedIds.append((long)anOwner.get());
1538
1539     Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
1540     if (!BROwnr.IsNull() && BROwnr->HasShape()) {
1541       const TopoDS_Shape& aShape = BROwnr->Shape();
1542       if (!aShape.IsNull() && theShapesToBeSelected.IsBound(aShape)) {
1543         Handle(AIS_InteractiveObject) anOwnerPresentation =
1544                                     Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
1545         NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
1546                                     theShapesToBeSelected.Find(aShape);
1547         if (aPresentations.Contains(anOwnerPresentation)) {
1548           theContext->AddOrRemoveSelected(anOwner);
1549           anOwner->SetSelected (Standard_True);
1550         }
1551       }
1552     }
1553   }
1554 }