Salome HOME
Merge branch 'Dev_1.2.0' of newgeom:newgeom into Dev_1.2.0
[modules/shaper.git] / src / XGUI / XGUI_Displayer.cpp
index d920f4630516a99986b86978b39c80be5dbe03e5..1fef7d318df56218a33259c935498e3c42dcbea8 100644 (file)
@@ -20,6 +20,7 @@
 #include <ModelAPI_AttributeIntArray.h>
 
 #include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_Tools.h>
 
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_IPresentable.h>
@@ -46,7 +47,8 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10;  ///< defines the local context mouse
 //#define DEBUG_DISPLAY
 //#define DEBUG_ACTIVATE
 //#define DEBUG_FEATURE_REDISPLAY
-#define DEBUG_SELECTION_FILTERS
+//#define DEBUG_SELECTION_FILTERS
+//#define DEBUG_USE_CLEAR_OUTDATED_SELECTION
 
 // Workaround for bug #25637
 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
@@ -92,14 +94,6 @@ void XGUI_Displayer::display(ObjectPtr theObject, bool isUpdateViewer)
   if (isVisible(theObject)) {
     redisplay(theObject, isUpdateViewer);
   } else {
-#ifdef DEBUG_DISPLAY
-    FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
-    if (aFeature.get() != NULL) {
-      qDebug(QString("display feature: %1, displayed: %2").
-        arg(aFeature->data()->name().c_str()).
-        arg(displayedObjects().size()).toStdString().c_str());
-    }
-#endif
     AISObjectPtr anAIS;
 
     GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
@@ -151,7 +145,8 @@ void XGUI_Displayer::display(ObjectPtr theObject, AISObjectPtr theAIS,
 
   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
   if (!anAISIO.IsNull()) {
-    myResult2AISObjectMap[theObject] = theAIS;
+    appendResultObject(theObject, theAIS);
+
     bool aCanBeShaded = ::canBeShaded(anAISIO);
     // In order to avoid extra closing/opening context
     SelectMgr_IndexedMapOfOwner aSelectedOwners;
@@ -216,7 +211,7 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer)
       return;
     }
     if (aAIS_Obj != aAISObj) {
-      myResult2AISObjectMap[theObject] = aAIS_Obj;
+      appendResultObject(theObject, aAIS_Obj);
     }
     aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
   }
@@ -240,19 +235,16 @@ void XGUI_Displayer::redisplay(ObjectPtr theObject, bool isUpdateViewer)
       if (!aShapePrs.IsNull()) {
         std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
         if (aShapePtr.get()) {
-          const TopoDS_Shape& aShape = aShapePrs->Shape();
-          std::shared_ptr<GeomAPI_Shape> anAISShapePtr(new GeomAPI_Shape());
-          anAISShapePtr->setImpl(new TopoDS_Shape(aShape));
-
-          isEqualShapes = aShapePtr->isEqual(anAISShapePtr);
+          const TopoDS_Shape& aOldShape = aShapePrs->Shape();
+          isEqualShapes = aOldShape.IsEqual(aShapePtr->impl<TopoDS_Shape>());
         }
       }
     }
     // Customization of presentation
     bool isCustomized = customizeObject(theObject);
     #ifdef DEBUG_FEATURE_REDISPLAY
-      qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
-        arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str());
+      //qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
+      //  arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str());
     #endif
     if (!isEqualShapes || isCustomized) {
       aContext->Redisplay(aAISIO, false);
@@ -275,6 +267,10 @@ void XGUI_Displayer::deactivate(ObjectPtr theObject)
     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
     aContext->Deactivate(anAIS);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+    aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
+    updateViewer();
+#endif
   }
 }
 
@@ -335,7 +331,7 @@ void XGUI_Displayer::getModesOfActivation(ObjectPtr theObject, QIntList& theMode
   }
 }
 
-void XGUI_Displayer::activateObjects(const QIntList& theModes)
+void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList)
 {
 #ifdef DEBUG_ACTIVATE
   qDebug(QString("activate all features: theModes: %2, myActiveSelectionModes: %3").
@@ -360,15 +356,24 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes)
   //aContext->UseDisplayedObjects();
   //myUseExternalObjects = true;
 
+  Handle(AIS_InteractiveObject) anAISIO;
   AIS_ListOfInteractive aPrsList;
-  ::displayedObjects(aContext, aPrsList);
+  if (theObjList.isEmpty())
+    ::displayedObjects(aContext, aPrsList);
+  else {
+    foreach(ObjectPtr aObj, theObjList) {
+      if (myResult2AISObjectMap.contains(aObj))
+        aPrsList.Append(myResult2AISObjectMap[aObj]->impl<Handle(AIS_InteractiveObject)>());
+    }
+  }
 
   Handle(AIS_Trihedron) aTrihedron;
   AIS_ListIteratorOfListOfInteractive aLIt(aPrsList);
-  Handle(AIS_InteractiveObject) anAISIO;
   for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
     anAISIO = aLIt.Value();
-    activate(anAISIO, myActiveSelectionModes);
+    aTrihedron = Handle(AIS_Trihedron)::DownCast(anAISIO);
+    if (aTrihedron.IsNull())
+      activate(anAISIO, myActiveSelectionModes);
   }
 }
 
@@ -391,6 +396,10 @@ void XGUI_Displayer::deactivateObjects()
   for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
     anAISIO = aLIt.Value();
     aContext->Deactivate(anAISIO);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+    aContext->LocalContext()->ClearOutdatedSelection(anAISIO, true);
+    updateViewer();
+#endif
   }
 }
 
@@ -410,7 +419,7 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const
   return aModes.Extent() > 0;
 }
 
-void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool isUpdateViewer)
+void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrs>& theValues, bool isUpdateViewer)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (aContext.IsNull())
@@ -418,19 +427,35 @@ void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool is
   if (aContext->HasOpenedContext()) {
     aContext->UnhilightSelected();
     aContext->ClearSelected();
-    foreach(ObjectPtr aResult, theResults) {
-      if (isVisible(aResult)) {
-        AISObjectPtr anObj = myResult2AISObjectMap[aResult];
-        Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
-        if (!anAIS.IsNull())
-          aContext->SetSelected(anAIS, false);
+    //if (aSelected.size() > 0) {
+    foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+      const TopoDS_Shape& aShape = aPrs.shape();
+      if (!aShape.IsNull()) {
+        aContext->AddOrRemoveSelected(aShape, false);
+      } else {
+        ObjectPtr anObject = aPrs.object();
+        ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+        if (aResult.get() && isVisible(aResult)) {
+          AISObjectPtr anObj = myResult2AISObjectMap[aResult];
+          Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
+          if (!anAIS.IsNull()) {
+            // The methods are replaced in order to provide multi-selection, e.g. restore selection
+            // by activating multi selector widget. It also gives an advantage that the multi
+            // selection in OB gives multi-selection in the viewer
+            //aContext->SetSelected(anAIS, false);
+            // The selection in the context was cleared, so the method sets the objects are selected
+            aContext->AddOrRemoveSelected(anAIS, false);
+          }
+        }
       }
     }
   } else {
     aContext->UnhilightCurrents();
     aContext->ClearCurrents();
-    foreach(ObjectPtr aResult, theResults) {
-      if (isVisible(aResult)) {
+    foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+      ObjectPtr anObject = aPrs.object();
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+      if (aResult.get() && isVisible(aResult)) {
         AISObjectPtr anObj = myResult2AISObjectMap[aResult];
         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
         if (!anAIS.IsNull())
@@ -442,7 +467,6 @@ void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool is
     updateViewer();
 }
 
-
 void XGUI_Displayer::clearSelected()
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -591,7 +615,7 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   return aWasEnabled;
 }
 
-void XGUI_Displayer::updateViewer()
+void XGUI_Displayer::updateViewer() const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (!aContext.IsNull() && myEnableUpdateViewer)
@@ -673,6 +697,8 @@ void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bo
     closeLocalContexts(false);
   }
   aContext->SetDisplayMode(aAISIO, theMode, false);
+  // Redisplay in order to update new mode because it could be not computed before
+  aContext->Redisplay(aAISIO, false);
   if (aCanBeShaded) {
     openLocalContext();
     activateObjects(myActiveSelectionModes);
@@ -707,7 +733,13 @@ void XGUI_Displayer::addSelectionFilter(const Handle(SelectMgr_Filter)& theFilte
     if (theFilter.Access() == aIt.Value().Access())
       return;
   }
-  GetFilter()->Add(theFilter);
+  Handle(SelectMgr_CompositionFilter) aCompFilter = GetFilter();
+  const SelectMgr_ListOfFilter& aStoredFilters = aCompFilter->StoredFilters();
+  for (aIt.Initialize(aStoredFilters); aIt.More(); aIt.Next()) {
+    if (theFilter.Access() == aIt.Value().Access())
+      return;
+  }
+  aCompFilter->Add(theFilter);
 #ifdef DEBUG_SELECTION_FILTERS
   int aCount = GetFilter()->StoredFilters().Extent();
   qDebug(QString("addSelectionFilter: filters.count() = %1").arg(aCount).toStdString().c_str());
@@ -783,6 +815,7 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
   aContext->ActivatedModes(theIO, aTColModes);
   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
   QIntList aModesActivatedForIO;
+  //bool isDeactivated = false;
   for (; itr.More(); itr.Next() ) {
     Standard_Integer aMode = itr.Value();
     if (!theModes.contains(aMode)) {
@@ -790,6 +823,7 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
       qDebug(QString("deactivate: %1").arg(aMode).toStdString().c_str());
 #endif
       aContext->Deactivate(theIO, aMode);
+      //isDeactivated = true;
     }
     else {
       aModesActivatedForIO.append(aMode);
@@ -798,30 +832,32 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
 #endif
     }
   }
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+  if (isDeactivated) {
+    aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
+    updateViewer();
+  }
+#endif
   // loading the interactive object allowing the decomposition
   if (aTColModes.IsEmpty())
     aContext->Load(theIO, -1, true);
 
-  Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(theIO);
-  //Deactivate trihedron which can be activated in local selector
-  if (aTrihedron.IsNull()) {
     //aContext->Load(anAISIO, -1, true);
     // In order to clear active modes list
-    if (theModes.size() == 0) {
-      //aContext->Load(anAISIO, 0, true);
-      aContext->Activate(theIO);
+  if (theModes.size() == 0) {
+    //aContext->Load(anAISIO, 0, true);
+    aContext->Activate(theIO);
 #ifdef DEBUG_ACTIVATE
-      qDebug("activate in all modes");
+    qDebug("activate in all modes");
 #endif
-    } else {
-      foreach(int aMode, theModes) {
-        //aContext->Load(anAISIO, aMode, true);
-        if (!aModesActivatedForIO.contains(aMode)) {
-          aContext->Activate(theIO, aMode);
+  } else {
+    foreach(int aMode, theModes) {
+      //aContext->Load(anAISIO, aMode, true);
+      if (!aModesActivatedForIO.contains(aMode)) {
+        aContext->Activate(theIO, aMode);
 #ifdef DEBUG_ACTIVATE
-          qDebug(QString("activate: %1").arg(aMode).toStdString().c_str());
+        qDebug(QString("activate: %1").arg(aMode).toStdString().c_str());
 #endif
-        }
       }
     }
   }
@@ -865,3 +901,31 @@ QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject, const QColor& theColo
     updateViewer();
   return QColor(aR, aG, aB);
 }
+
+void XGUI_Displayer::appendResultObject(ObjectPtr theObject, AISObjectPtr theAIS)
+{
+  myResult2AISObjectMap[theObject] = theAIS;
+
+#ifdef DEBUG_DISPLAY
+  std::ostringstream aPtrStr;
+  aPtrStr << theObject.get();
+  qDebug(QString("display object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
+  qDebug(getResult2AISObjectMapInfo().c_str());
+#endif
+}
+
+std::string XGUI_Displayer::getResult2AISObjectMapInfo() const
+{
+  QStringList aContent;
+  foreach (ObjectPtr aObj, myResult2AISObjectMap.keys()) {
+    AISObjectPtr aAISObj = myResult2AISObjectMap[aObj];
+    std::ostringstream aPtrStr;
+    aPtrStr << "aObj = " << aObj.get() << ":";
+    aPtrStr << "anAIS = " << aAISObj.get() << ":";
+    aPtrStr << "[" << ModuleBase_Tools::objectInfo(aObj).toStdString().c_str() << "]";
+    
+    aContent.append(aPtrStr.str().c_str());
+  }
+  return QString("myResult2AISObjectMap: size = %1\n%2").arg(myResult2AISObjectMap.size()).
+                                            arg(aContent.join("\n")).toStdString().c_str();
+}