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