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