Salome HOME
c79aeafacef1eda8f17476e08c88047584c69a7c
[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 #include <AppElements_Viewer.h>
15
16 #include <ModelAPI_Document.h>
17 #include <ModelAPI_Data.h>
18 #include <ModelAPI_Object.h>
19 #include <ModelAPI_Tools.h>
20 #include <ModelAPI_AttributeIntArray.h>
21 #include <ModelAPI_ResultCompSolid.h>
22
23 #include <ModuleBase_ResultPrs.h>
24 #include <ModuleBase_Tools.h>
25 #include <ModuleBase_IModule.h>
26
27 #include <GeomAPI_Shape.h>
28 #include <GeomAPI_IPresentable.h>
29 #include <GeomAPI_ICustomPrs.h>
30
31 #include <AIS_InteractiveContext.hxx>
32 #include <AIS_LocalContext.hxx>
33 #include <AIS_ListOfInteractive.hxx>
34 #include <AIS_ListIteratorOfListOfInteractive.hxx>
35 #include <AIS_DimensionSelectionMode.hxx>
36 #include <AIS_Shape.hxx>
37 #include <AIS_Dimension.hxx>
38 #include <TColStd_ListIteratorOfListOfInteger.hxx>
39 #include <SelectMgr_ListOfFilter.hxx>
40 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
41 #include <Prs3d_Drawer.hxx>
42 #include <Prs3d_IsoAspect.hxx>
43
44 #include <StdSelect_ViewerSelector3d.hxx>
45
46 #include <TColStd_MapOfTransient.hxx>
47 #include <TColStd_MapIteratorOfMapOfTransient.hxx>
48
49 #include <Events_Loop.h>
50 #include <ModelAPI_Events.h>
51
52 #include <set>
53
54 const int MOUSE_SENSITIVITY_IN_PIXEL = 10;  ///< defines the local context mouse selection sensitivity
55
56 //#define DEBUG_ACTIVATE_OBJECTS
57 //#define DEBUG_DEACTIVATE
58 //#define DEBUG_ACTIVATE_AIS
59 //#define DEBUG_DEACTIVATE_AIS
60
61 //#define DEBUG_DISPLAY
62 //#define DEBUG_FEATURE_REDISPLAY
63 //#define DEBUG_SELECTION_FILTERS
64
65 //#define DEBUG_COMPOSILID_DISPLAY
66 // Workaround for bug #25637
67 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
68 {
69   // Get from null point
70   theAIS->DisplayedObjects(theList, true);
71   if (theAIS->HasOpenedContext()) {
72     // get from local context
73     const Handle(AIS_LocalContext)& aLC = theAIS->LocalContext();
74     TColStd_MapOfTransient aMap;
75     int NbDisp = aLC->DisplayedObjects(aMap);
76     TColStd_MapIteratorOfMapOfTransient aIt(aMap);
77
78     Handle(AIS_InteractiveObject) curIO;
79     Handle(Standard_Transient) Tr;
80     for(; aIt.More(); aIt.Next()){
81       Tr = aIt.Key();
82       curIO = *((Handle(AIS_InteractiveObject)*) &Tr);
83       theList.Append(curIO);
84     }
85   }
86 }
87
88 QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QString(", "))
89 {
90   QStringList anInfo;
91   QIntList::const_iterator anIt = theValues.begin(), aLast = theValues.end();
92   for (; anIt != aLast; anIt++) {
93     anInfo.append(QString::number(*anIt));
94   }
95   return anInfo.join(theSeparator);
96 }
97
98 XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
99   : myWorkshop(theWorkshop)
100 {
101   enableUpdateViewer(true);
102   myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs());
103 }
104
105 XGUI_Displayer::~XGUI_Displayer()
106 {
107 }
108
109 bool XGUI_Displayer::isVisible(ObjectPtr theObject) const
110 {
111   return myResult2AISObjectMap.contains(theObject);
112 }
113
114 void XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer)
115 {
116   if (isVisible(theObject)) {
117 #ifdef DEBUG_COMPOSILID_DISPLAY
118     ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
119     if (aCompsolidResult.get()) {
120       for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
121         ResultPtr aSubResult = aCompsolidResult->subResult(i);
122         if (aSubResult.get())
123           redisplay(aSubResult, false);
124       }
125       if (theUpdateViewer)
126         updateViewer();
127     }
128     else
129 #endif
130       redisplay(theObject, theUpdateViewer);
131   } else {
132     AISObjectPtr anAIS;
133
134     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
135     bool isShading = false;
136     if (aPrs.get() != NULL) {
137       anAIS = aPrs->getAISObject(anAIS);
138     } else {
139       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
140       if (aResult.get() != NULL) {
141 #ifdef DEBUG_COMPOSILID_DISPLAY
142         ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
143         if (aCompsolidResult.get()) {
144           for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
145             ResultPtr aSubResult = aCompsolidResult->subResult(i);
146             if (aSubResult.get())
147               display(aSubResult, false);
148           }
149           if (theUpdateViewer)
150             updateViewer();
151         }
152         else {
153 #endif
154         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
155         if (aShapePtr.get() != NULL) {
156           anAIS = AISObjectPtr(new GeomAPI_AISObject());
157           anAIS->setImpl(new Handle(AIS_InteractiveObject)(new ModuleBase_ResultPrs(aResult)));
158           //anAIS->createShape(aShapePtr);
159           isShading = true;
160         }
161 #ifdef DEBUG_COMPOSILID_DISPLAY
162         } // close else
163 #endif
164       }
165     }
166     if (anAIS)
167       display(theObject, anAIS, isShading, theUpdateViewer);
168   }
169 }
170
171 bool canBeShaded(Handle(AIS_InteractiveObject) theAIS)
172 {
173   Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS);
174   if (!aShapePrs.IsNull()) {
175     TopoDS_Shape aShape = aShapePrs->Shape();
176     if (aShape.IsNull())
177       return false;
178     TopAbs_ShapeEnum aType = aShape.ShapeType();
179     if ((aType == TopAbs_VERTEX) || (aType == TopAbs_EDGE) || (aType == TopAbs_WIRE))
180       return false;
181     else {
182       // Check that the presentation is not a sketch
183       Handle(ModuleBase_ResultPrs) aPrs = Handle(ModuleBase_ResultPrs)::DownCast(theAIS);
184       if (!aPrs.IsNull()) 
185         return !aPrs->isSketchMode();
186       return true;
187     }
188   }
189   return false;
190 }
191
192 void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS, 
193                              bool isShading, bool theUpdateViewer)
194 {
195   Handle(AIS_InteractiveContext) aContext = AISContext();
196   if (aContext.IsNull())
197     return;
198
199   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
200   if (!anAISIO.IsNull()) {
201     appendResultObject(theObject, theAIS);
202
203     bool isCustomized = customizeObject(theObject);
204
205     int aDispMode = isShading? Shading : Wireframe;
206     if (isShading)
207       anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
208     anAISIO->SetDisplayMode(aDispMode);
209     aContext->Display(anAISIO, aDispMode, 0, false, true, AIS_DS_Displayed); 
210
211     emit objectDisplayed(theObject, theAIS);
212     activate(anAISIO, myActiveSelectionModes, theUpdateViewer);
213  } 
214   if (theUpdateViewer)
215     updateViewer();
216 }
217
218 void XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
219 {
220   if (!isVisible(theObject))
221     return;
222
223   Handle(AIS_InteractiveContext) aContext = AISContext();
224   if (aContext.IsNull())
225     return;
226   AISObjectPtr anObject = myResult2AISObjectMap[theObject];
227   if (anObject) {
228     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
229     if (!anAIS.IsNull()) {
230       emit beforeObjectErase(theObject, anObject);
231       aContext->Remove(anAIS, theUpdateViewer);
232     }
233   }
234   myResult2AISObjectMap.remove(theObject);
235
236 #ifdef DEBUG_DISPLAY
237   std::ostringstream aPtrStr;
238   aPtrStr << theObject.get();
239   qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
240   qDebug(getResult2AISObjectMapInfo().c_str());
241 #endif
242 }
243
244 void XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
245 {
246   if (!isVisible(theObject))
247     return;
248
249   AISObjectPtr aAISObj = getAISObject(theObject);
250   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
251
252   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
253   if (aPrs) {
254     AISObjectPtr aAIS_Obj = aPrs->getAISObject(aAISObj);
255     if (!aAIS_Obj) {
256       erase(theObject, theUpdateViewer);
257       return;
258     }
259     if (aAIS_Obj != aAISObj) {
260       appendResultObject(theObject, aAIS_Obj);
261     }
262     aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
263   }
264
265   if (!aAISIO.IsNull()) {
266     Handle(AIS_InteractiveContext) aContext = AISContext();
267     if (aContext.IsNull())
268       return;
269     // Check that the visualized shape is the same and the redisplay is not necessary
270     // Redisplay of AIS object leads to this object selection compute and the selection 
271     // in the browser is lost
272
273     // this check is not necessary anymore because the selection store/restore is realized
274     // before and after the values modification.
275     // Moreother, this check avoids customize and redisplay presentation if the presentable
276     // parameter is changed.
277     bool isEqualShapes = false;
278     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
279     if (aResult.get() != NULL) {
280       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aAISIO);
281       if (!aShapePrs.IsNull()) {
282         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
283         if (aShapePtr.get()) {
284           const TopoDS_Shape& aOldShape = aShapePrs->Shape();
285           if (!aOldShape.IsNull())
286             isEqualShapes = aOldShape.IsEqual(aShapePtr->impl<TopoDS_Shape>());
287         }
288       }
289     }
290     // Customization of presentation
291     bool isCustomized = customizeObject(theObject);
292     #ifdef DEBUG_FEATURE_REDISPLAY
293       qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
294         arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str());
295     #endif
296     if (!isEqualShapes || isCustomized) {
297       aContext->Redisplay(aAISIO, false);
298       #ifdef DEBUG_FEATURE_REDISPLAY
299         qDebug("  Redisplay happens");
300       #endif
301       if (theUpdateViewer)
302         updateViewer();
303     }
304   }
305 }
306
307 void XGUI_Displayer::redisplayObjects()
308 {
309   // redisplay objects visualized in the viewer
310   static Events_ID EVENT_DISP = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
311   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
312   QObjectPtrList aDisplayed = myWorkshop->displayer()->displayedObjects();
313   QObjectPtrList::const_iterator anIt = aDisplayed.begin(), aLast = aDisplayed.end();
314   for (; anIt != aLast; anIt++) {
315     aECreator->sendUpdated(*anIt, EVENT_DISP);
316   }
317   Events_Loop::loop()->flush(EVENT_DISP);
318 }
319
320 void XGUI_Displayer::deactivate(ObjectPtr theObject, const bool theUpdateViewer)
321 {
322 #ifdef DEBUG_DEACTIVATE
323   QString anInfoStr = ModuleBase_Tools::objectInfo(theObject);
324   qDebug(QString("deactivate: myActiveSelectionModes[%1]: %2, objects = ").
325     arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)).
326     arg(anInfoStr).
327     toStdString().c_str());
328 #endif
329   if (isVisible(theObject)) {
330     Handle(AIS_InteractiveContext) aContext = AISContext();
331     if (aContext.IsNull())
332       return;
333
334     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
335     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
336
337     deactivateAIS(anAIS);
338     // the selection from the previous activation modes should be cleared manually (#26172)
339     aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
340     if (theUpdateViewer)
341       updateViewer();
342   }
343 }
344
345 void XGUI_Displayer::deactivateObjects(const QObjectPtrList& theObjList,
346                                        const bool theUpdateViewer)
347 {
348   QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
349   for (; anIt != aLast; anIt++) {
350     deactivate(*anIt, false);
351   }
352   if (theUpdateViewer)
353     updateViewer();
354 }
355
356 void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theModes)
357 {
358   if (!isVisible(theObject))
359     return;
360
361   Handle(AIS_InteractiveContext) aContext = AISContext();
362   if (aContext.IsNull())
363     return;
364
365   AISObjectPtr aAISObj = getAISObject(theObject);
366
367   if (aAISObj.get() != NULL) {
368     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
369     TColStd_ListOfInteger aTColModes;
370     aContext->ActivatedModes(anAISIO, aTColModes);
371     TColStd_ListIteratorOfListOfInteger itr( aTColModes );
372     for (; itr.More(); itr.Next() ) {
373       theModes.append(itr.Value());
374     }
375   }
376 }
377
378 void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
379                                      const bool theUpdateViewer)
380 {
381   // Convert shape types to selection types
382   QIntList aModes;
383   foreach(int aType, theModes) {
384     if (aType >= TopAbs_SHAPE) 
385       aModes.append(aType);
386     else
387       aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum)aType));
388   }
389
390 #ifdef DEBUG_ACTIVATE_OBJECTS
391   QStringList anInfo;
392   QObjectPtrList::const_iterator anIt = theObjList.begin(), aLast = theObjList.end();
393   for (; anIt != aLast; ++anIt) {
394     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
395   }
396   QString anInfoStr = anInfo.join(", ");
397
398   qDebug(QString("activateObjects: aModes[%1] = %2, myActiveSelectionModes[%3] = %4, objects = %5").
399     arg(aModes.size()).arg(qIntListInfo(aModes)).
400     arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)).
401     arg(anInfoStr).
402     toStdString().c_str());
403 #endif
404   // In order to avoid doblications of selection modes
405   QIntList aNewModes;
406   foreach (int aMode, aModes) {
407     if (!aNewModes.contains(aMode))
408       aNewModes.append(aMode);
409   }
410   myActiveSelectionModes = aNewModes;
411   Handle(AIS_InteractiveContext) aContext = AISContext();
412   if (aContext.IsNull())
413     return;
414   // Open local context if there is no one
415   if (!aContext->HasOpenedContext()) 
416     return;
417
418   //aContext->UseDisplayedObjects();
419   //myUseExternalObjects = true;
420
421   Handle(AIS_InteractiveObject) anAISIO;
422   AIS_ListOfInteractive aPrsList;
423   if (theObjList.isEmpty())
424     return;
425   else {
426     foreach(ObjectPtr aObj, theObjList) {
427       if (myResult2AISObjectMap.contains(aObj))
428         aPrsList.Append(myResult2AISObjectMap[aObj]->impl<Handle(AIS_InteractiveObject)>());
429     }
430   }
431
432   AIS_ListIteratorOfListOfInteractive aLIt(aPrsList);
433   for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
434     anAISIO = aLIt.Value();
435     activate(anAISIO, myActiveSelectionModes, false);
436   }
437   if (theUpdateViewer)
438     updateViewer();
439 }
440
441 bool XGUI_Displayer::isActive(ObjectPtr theObject) const
442 {
443   Handle(AIS_InteractiveContext) aContext = AISContext();
444   if (aContext.IsNull())
445     return false;
446   if (!isVisible(theObject))
447     return false;
448     
449   AISObjectPtr anObj = myResult2AISObjectMap[theObject];
450   Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
451
452   TColStd_ListOfInteger aModes;
453   aContext->ActivatedModes(anAIS, aModes);
454   return aModes.Extent() > 0;
455 }
456 void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrs>& theValues, bool theUpdateViewer)
457 {
458   Handle(AIS_InteractiveContext) aContext = AISContext();
459   if (aContext.IsNull())
460     return;
461   if (aContext->HasOpenedContext()) {
462     aContext->UnhilightSelected();
463     aContext->ClearSelected();
464     foreach (ModuleBase_ViewerPrs aPrs, theValues) {
465       const TopoDS_Shape& aShape = aPrs.shape();
466       if (!aShape.IsNull()) {
467         aContext->AddOrRemoveSelected(aShape, false);
468       } else {
469         ObjectPtr anObject = aPrs.object();
470         ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
471         if (aResult.get() && isVisible(aResult)) {
472           AISObjectPtr anObj = myResult2AISObjectMap[aResult];
473           Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
474           if (!anAIS.IsNull()) {
475             // The methods are replaced in order to provide multi-selection, e.g. restore selection
476             // by activating multi selector widget. It also gives an advantage that the multi
477             // selection in OB gives multi-selection in the viewer
478             //aContext->SetSelected(anAIS, false);
479             // The selection in the context was cleared, so the method sets the objects are selected
480             aContext->AddOrRemoveSelected(anAIS, false);
481           }
482         }
483       }
484     }
485   } else {
486     aContext->UnhilightCurrents();
487     aContext->ClearCurrents();
488     foreach (ModuleBase_ViewerPrs aPrs, theValues) {
489       ObjectPtr anObject = aPrs.object();
490       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
491       if (aResult.get() && isVisible(aResult)) {
492         AISObjectPtr anObj = myResult2AISObjectMap[aResult];
493         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
494         if (!anAIS.IsNull())
495           aContext->SetCurrentObject(anAIS, false);
496       }
497     }
498   }
499   if (theUpdateViewer)
500     updateViewer();
501 }
502
503 void XGUI_Displayer::clearSelected()
504 {
505   Handle(AIS_InteractiveContext) aContext = AISContext();
506   if (aContext) {
507     aContext->UnhilightCurrents(false);
508     aContext->ClearSelected();
509   }
510 }
511
512 void XGUI_Displayer::eraseAll(const bool theUpdateViewer)
513 {
514   Handle(AIS_InteractiveContext) aContext = AISContext();
515   if (!aContext.IsNull()) {
516     foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
517       AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
518       // erase an object
519       Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
520       if (!anIO.IsNull()) {
521         emit beforeObjectErase(aObj, aAISObj);
522         aContext->Remove(anIO, false);
523       }
524     }
525     if (theUpdateViewer)
526       updateViewer();
527   }
528   myResult2AISObjectMap.clear();
529 #ifdef DEBUG_DISPLAY
530   qDebug("eraseAll");
531   qDebug(getResult2AISObjectMapInfo().c_str());
532 #endif
533 }
534
535 void XGUI_Displayer::deactivateTrihedron() const
536 {
537   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
538
539   AIS_ListOfInteractive aList;
540   aContext->DisplayedObjects(aList, true);
541   AIS_ListIteratorOfListOfInteractive aIt;
542   for (aIt.Initialize(aList); aIt.More(); aIt.Next()) {
543     Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aIt.Value());
544     if (!aTrihedron.IsNull()) {
545       aContext->Deactivate(aTrihedron);
546     }
547   }
548 }
549
550 void XGUI_Displayer::openLocalContext()
551 {
552   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
553   if (aContext.IsNull())
554     return;
555   // Open local context if there is no one
556   if (!aContext->HasOpenedContext()) {
557     // Preserve selected objects
558     //AIS_ListOfInteractive aAisList;
559     //for (aContext->InitCurrent(); aContext->MoreCurrent(); aContext->NextCurrent())
560     //  aAisList.Append(aContext->Current());
561
562     // get the filters from the global context and append them to the local context
563     // a list of filters in the global context is not cleared and should be cleared here
564     SelectMgr_ListOfFilter aFilters;
565     aFilters.Assign(aContext->Filters());
566     // it is important to remove the filters in the global context, because there is a code
567     // in the closeLocalContex, which restore the global context filters
568     aContext->RemoveFilters();
569
570     //aContext->ClearCurrents();
571     aContext->OpenLocalContext();
572     deactivateTrihedron();
573     //aContext->NotUseDisplayedObjects();
574
575     //myUseExternalObjects = false;
576
577     SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
578     for (;aIt.More(); aIt.Next()) {
579       aContext->AddFilter(aIt.Value());
580     }
581     // Restore selection
582     //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
583     //for(; aIt2.More(); aIt2.Next()) {
584     //  aContext->SetSelected(aIt2.Value(), false);
585     //}
586   }
587 }
588
589 void XGUI_Displayer::closeLocalContexts(const bool theUpdateViewer)
590 {
591   Handle(AIS_InteractiveContext) aContext = AISContext();
592   if ( (!aContext.IsNull()) && (aContext->HasOpenedContext()) ) {
593     // Preserve selected objects
594     //AIS_ListOfInteractive aAisList;
595     //for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
596     //  aAisList.Append(aContext->SelectedInteractive());
597
598     // get the filters from the local context and append them to the global context
599     // a list of filters in the local context is cleared
600     SelectMgr_ListOfFilter aFilters;
601     aFilters.Assign(aContext->Filters());
602
603     //aContext->ClearSelected();
604     aContext->CloseAllContexts(false);
605
606     // From the moment when the AIS_DS_Displayed flag is used in the Display of AIS object,
607     // this code is obsolete. It is temporaty commented and should be removed after
608     // the test campaign.
609     // Redisplay all object if they were displayed in localContext
610     /*Handle(AIS_InteractiveObject) aAISIO;
611     foreach (AISObjectPtr aAIS, myResult2AISObjectMap) {
612       aAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
613       if (aContext->DisplayStatus(aAISIO) != AIS_DS_Displayed) {
614         aContext->Display(aAISIO, false);
615         aContext->SetDisplayMode(aAISIO, Shading, false);
616       }
617     }*/
618
619     // Append the filters from the local selection in the global selection context
620     SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
621     for (;aIt.More(); aIt.Next()) {
622       Handle(SelectMgr_Filter) aFilter = aIt.Value();
623       aContext->AddFilter(aFilter);
624     }
625
626     if (theUpdateViewer)
627       updateViewer();
628     //myUseExternalObjects = false;
629
630     // Restore selection
631     //AIS_ListIteratorOfListOfInteractive aIt2(aAisList);
632     //for(; aIt2.More(); aIt2.Next()) {
633     //  if (aContext->IsDisplayed(aIt2.Value()))
634     //    aContext->SetCurrentObject(aIt2.Value(), false);
635     //}
636   }
637 }
638
639 AISObjectPtr XGUI_Displayer::getAISObject(ObjectPtr theObject) const
640 {
641   AISObjectPtr anIO;
642   if (myResult2AISObjectMap.contains(theObject))
643     anIO = myResult2AISObjectMap[theObject];
644   return anIO;
645 }
646
647 ObjectPtr XGUI_Displayer::getObject(const AISObjectPtr& theIO) const
648 {
649   Handle(AIS_InteractiveObject) aRefAIS = theIO->impl<Handle(AIS_InteractiveObject)>();
650   return getObject(aRefAIS);
651 }
652
653 ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) const
654 {
655   ObjectPtr anObject;
656   foreach (ObjectPtr anObj, myResult2AISObjectMap.keys()) {
657     AISObjectPtr aAIS = myResult2AISObjectMap[anObj];
658     Handle(AIS_InteractiveObject) anAIS = aAIS->impl<Handle(AIS_InteractiveObject)>();
659     if (anAIS == theIO)
660       anObject = anObj;
661     if (anObject.get())
662       break;
663   }
664   if (!anObject.get()) {
665     std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
666     if (!theIO.IsNull()) {
667       anAISObj->setImpl(new Handle(AIS_InteractiveObject)(theIO));
668     }
669     anObject = myWorkshop->module()->findPresentedObject(anAISObj);
670   }
671   return anObject;
672 }
673
674 bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
675 {
676   bool aWasEnabled = myEnableUpdateViewer;
677
678   myEnableUpdateViewer = isEnabled;
679
680   return aWasEnabled;
681 }
682
683 void XGUI_Displayer::updateViewer() const
684 {
685   Handle(AIS_InteractiveContext) aContext = AISContext();
686   if (!aContext.IsNull() && myEnableUpdateViewer) {
687     myWorkshop->viewer()->Zfitall();
688     aContext->UpdateCurrentViewer();
689   }
690 }
691
692 void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
693                                  const int theMode, const bool theUpdateViewer) const
694 {
695   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
696   aContext->Activate(theIO, theMode, theUpdateViewer);
697
698 #ifdef DEBUG_ACTIVATE_AIS
699   ObjectPtr anObject = getObject(theIO);
700   anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
701   qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str());
702 #endif
703 }
704
705 void XGUI_Displayer::deactivateAIS(const Handle(AIS_InteractiveObject)& theIO, const int theMode) const
706 {
707   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
708   if (theMode == -1)
709     aContext->Deactivate(theIO);
710   else
711     aContext->Deactivate(theIO, theMode);
712
713 #ifdef DEBUG_DEACTIVATE_AIS
714   ObjectPtr anObject = getObject(theIO);
715   anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
716   qDebug(QString("deactivateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str());
717 #endif
718 }
719
720 Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
721 {
722   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
723   if ((!aContext.IsNull()) && (!aContext->HasOpenedContext())) {
724     aContext->OpenLocalContext();
725     deactivateTrihedron();
726     aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
727     aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
728   }
729   return aContext;
730 }
731
732 Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter()
733 {
734   Handle(AIS_InteractiveContext) aContext = AISContext();
735   if (myAndFilter.IsNull() && !aContext.IsNull()) {
736     myAndFilter = new SelectMgr_AndFilter();
737     aContext->AddFilter(myAndFilter);
738   }
739   return myAndFilter;
740 }
741
742 void XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes,
743                                 bool theUpdateViewer)
744 {
745   Handle(AIS_InteractiveContext) aContext = AISContext();
746   if (aContext.IsNull())
747     return;
748   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
749   if (!anAISIO.IsNull()) {
750     aContext->Display(anAISIO, 0/*wireframe*/, 0, theUpdateViewer, true, AIS_DS_Displayed);
751     aContext->Deactivate(anAISIO);
752     aContext->Load(anAISIO);
753     if (toActivateInSelectionModes) {
754       if (aContext->HasOpenedContext()) {
755         if (myActiveSelectionModes.size() == 0)
756           activateAIS(anAISIO, 0, theUpdateViewer);
757         else {
758           foreach(int aMode, myActiveSelectionModes) {
759             activateAIS(anAISIO, aMode, theUpdateViewer);
760           }
761         }
762       }
763     }
764   }
765 }
766
767 void XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
768 {
769   Handle(AIS_InteractiveContext) aContext = AISContext();
770   if (aContext.IsNull())
771     return;
772   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
773   if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) {
774     aContext->Remove(anAISIO, theUpdateViewer);
775   }
776 }
777
778
779 void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer)
780 {
781   if (theMode == NoMode)
782     return;
783
784   Handle(AIS_InteractiveContext) aContext = AISContext();
785   if (aContext.IsNull())
786     return;
787
788   AISObjectPtr aAISObj = getAISObject(theObject);
789   if (!aAISObj)
790     return;
791
792   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
793   aContext->SetDisplayMode(aAISIO, theMode, false);
794   // Redisplay in order to update new mode because it could be not computed before
795   if (theUpdateViewer)
796     updateViewer();
797 }
798
799 XGUI_Displayer::DisplayMode XGUI_Displayer::displayMode(ObjectPtr theObject) const
800 {
801   Handle(AIS_InteractiveContext) aContext = AISContext();
802   if (aContext.IsNull())
803     return NoMode;
804
805   AISObjectPtr aAISObj = getAISObject(theObject);
806   if (!aAISObj)
807     return NoMode;
808
809   Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
810   return (XGUI_Displayer::DisplayMode) aAISIO->DisplayMode();
811 }
812
813 void XGUI_Displayer::deactivateSelectionFilters()
814 {
815   Handle(AIS_InteractiveContext) aContext = AISContext();
816   if (!myAndFilter.IsNull() && !aContext.IsNull()) {
817     bool aFound = false;
818     const SelectMgr_ListOfFilter& aFilters = aContext->Filters();
819     SelectMgr_ListIteratorOfListOfFilter anIt(aFilters);
820     for (; anIt.More() && !aFound; anIt.Next()) {
821       Handle(SelectMgr_Filter) aFilter = anIt.Value();
822       aFound = aFilter == myAndFilter;
823     }
824     if (aFound) {
825       aContext->RemoveFilter(myAndFilter);
826       myAndFilter.Nullify();
827     }
828   }
829 }
830
831 void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
832 {
833   Handle(AIS_InteractiveContext) aContext = AISContext();
834   if (aContext.IsNull() || hasSelectionFilter(theFilter))
835     return;
836
837   Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter();
838   aCompFilter->Add(theFilter);
839 #ifdef DEBUG_SELECTION_FILTERS
840   int aCount = GetFilter()->StoredFilters().Extent();
841   qDebug(QString("addSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
842 #endif
843 }
844
845 void XGUI_Displayer::removeSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
846 {
847   Handle(AIS_InteractiveContext) aContext = AISContext();
848   if (aContext.IsNull())
849     return;
850   Handle(SelectMgr_AndFilter) aCompositeFilter = GetFilter();
851   if (aCompositeFilter->IsIn(theFilter))
852     aCompositeFilter->Remove(theFilter);
853 #ifdef DEBUG_SELECTION_FILTERS
854   int aCount = GetFilter()->StoredFilters().Extent();
855   qDebug(QString("removeSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
856 #endif
857 }
858
859 bool XGUI_Displayer::hasSelectionFilter(const Handle(SelectMgr_Filter)& theFilter)
860 {
861   bool aFilterFound = false;
862
863   Handle(AIS_InteractiveContext) aContext = AISContext();
864   if (aContext.IsNull())
865     return aFilterFound;
866   const SelectMgr_ListOfFilter& aFilters = aContext->Filters();
867   SelectMgr_ListIteratorOfListOfFilter aIt(aFilters);
868   for (; aIt.More() && !aFilterFound; aIt.Next()) {
869     if (theFilter.Access() == aIt.Value().Access())
870       aFilterFound = true;
871   }
872   Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter();
873   const SelectMgr_ListOfFilter& aStoredFilters = aCompFilter->StoredFilters();
874   for (aIt.Initialize(aStoredFilters); aIt.More() && !aFilterFound; aIt.Next()) {
875     if (theFilter.Access() == aIt.Value().Access())
876       aFilterFound = true;
877   }
878   return aFilterFound;
879 }
880
881 void XGUI_Displayer::removeFilters()
882 {
883   Handle(AIS_InteractiveContext) aContext = AISContext();
884   if (aContext.IsNull())
885     return;
886   GetFilter()->Clear();
887 }
888
889 void XGUI_Displayer::showOnly(const QObjectPtrList& theList)
890 {
891   QObjectPtrList aDispList = myResult2AISObjectMap.keys();
892   foreach(ObjectPtr aObj, aDispList) {
893     if (!theList.contains(aObj))
894       erase(aObj, false);
895   }
896   foreach(ObjectPtr aObj, theList) {
897     if (!isVisible(aObj))
898       display(aObj, false);
899   }
900   updateViewer();
901 }
902
903 bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const
904
905   if (!isVisible(theObject))
906     return false;
907
908   AISObjectPtr aAISObj = getAISObject(theObject);
909   if (aAISObj.get() == NULL)
910     return false;
911
912   Handle(AIS_InteractiveObject) anAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
913   return ::canBeShaded(anAIS);
914 }
915
916 void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
917                               const QIntList& theModes,
918                               const bool theUpdateViewer) const
919 {
920   Handle(AIS_InteractiveContext) aContext = AISContext();
921   if (aContext.IsNull() || theIO.IsNull())
922     return;
923
924   // deactivate object in all modes, which are not in the list of activation
925   // It seems that after the IO deactivation the selected state of the IO's owners
926   // is modified in OCC(version: 6.8.0) and the selection of the object later is lost.
927   // By this reason, the number of the IO deactivate is decreased and the object is deactivated
928   // only if there is a difference in the current modes and the parameters modes.
929   // If the selection problem happens again, it is possible to write a test scenario and create
930   // a bug. The bug steps are the following:
931   // Create two IO, activate them in 5 modes, select the first IO, deactivate 3 modes for both,
932   // with clicked SHIFT select the second object. The result is the selection of the first IO is lost.
933   TColStd_ListOfInteger aTColModes;
934   aContext->ActivatedModes(theIO, aTColModes);
935   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
936   QIntList aModesActivatedForIO;
937   bool isDeactivated = false;
938   for (; itr.More(); itr.Next() ) {
939     Standard_Integer aMode = itr.Value();
940     if (!theModes.contains(aMode)) {
941       deactivateAIS(theIO, aMode);
942       isDeactivated = true;
943     }
944     else {
945       aModesActivatedForIO.append(aMode);
946     }
947   }
948   if (isDeactivated) {
949     // the selection from the previous activation modes should be cleared manually (#26172)
950     aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
951     if (theUpdateViewer)
952       updateViewer();
953   }
954
955   // loading the interactive object allowing the decomposition
956   if (aTColModes.IsEmpty()) {
957     aContext->Load(theIO, -1, true);
958   }
959
960   // trihedron AIS check should be after the AIS loading.
961   // If it is not loaded, it is steel selectable in the viewer.
962   Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
963   if (aTrihedron.IsNull()) {
964       //aContext->Load(anAISIO, -1, true);
965       // In order to clear active modes list
966     if (theModes.size() == 0) {
967       //aContext->Load(anAISIO, 0, true);
968       activateAIS(theIO, 0, theUpdateViewer);
969     } else {
970       foreach(int aMode, theModes) {
971         //aContext->Load(anAISIO, aMode, true);
972         if (!aModesActivatedForIO.contains(aMode)) {
973           activateAIS(theIO, aMode, theUpdateViewer);
974         }
975       }
976     }
977   }
978 }
979
980 bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
981 {
982   AISObjectPtr anAISObj = getAISObject(theObject);
983   // correct the result's color it it has the attribute
984   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
985
986   // Customization of presentation
987   GeomCustomPrsPtr aCustomPrs;
988   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
989   if (aFeature.get() != NULL) {
990     GeomCustomPrsPtr aCustPrs = std::dynamic_pointer_cast<GeomAPI_ICustomPrs>(aFeature);
991     if (aCustPrs.get() != NULL)
992       aCustomPrs = aCustPrs;
993   }
994   if (aCustomPrs.get() == NULL) {
995     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
996     // we ignore presentable not customized objects
997     if (aPrs.get() == NULL)
998       aCustomPrs = myCustomPrs;
999   }
1000   bool isCustomized = aCustomPrs.get() &&
1001                       aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
1002   return isCustomized;
1003 }
1004
1005
1006 QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject, const QColor& theColor, bool theUpdateViewer)
1007 {
1008   if (!isVisible(theObject))
1009     return Qt::black;
1010
1011   AISObjectPtr anAISObj = getAISObject(theObject);
1012   int aR, aG, aB;
1013   anAISObj->getColor(aR, aG, aB);
1014   anAISObj->setColor(theColor.red(), theColor.green(), theColor.blue());
1015   if (theUpdateViewer)
1016     updateViewer();
1017   return QColor(aR, aG, aB);
1018 }
1019
1020 void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
1021 {
1022   myResult2AISObjectMap[theObject] = theAIS;
1023
1024 #ifdef DEBUG_DISPLAY
1025   std::ostringstream aPtrStr;
1026   aPtrStr << theObject.get();
1027   qDebug(QString("display object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
1028   qDebug(getResult2AISObjectMapInfo().c_str());
1029 #endif
1030 }
1031
1032 std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
1033 {
1034   QStringList aContent;
1035   foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
1036     AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
1037     std::ostringstream aPtrStr;
1038     aPtrStr << "aObj = " << aObj.get() << ":";
1039     aPtrStr << "anAIS = " << aAISObj.get() << ":";
1040     aPtrStr << "[" << ModuleBase_Tools::objectInfo(aObj).toStdString().c_str() << "]";
1041     
1042     aContent.append(aPtrStr.str().c_str());
1043   }
1044   return QString("myResult2AISObjectMap: size = %1\n%2\n").arg(myResult2AISObjectMap.size()).
1045                                             arg(aContent.join("\n")).toStdString().c_str();
1046 }