Salome HOME
#1347 Fatal error when rename group
[modules/shaper.git] / src / XGUI / XGUI_Displayer.cpp
index 4fb6a729bdba4c794c1beda317f8bda876aeb36f..978d6154936421e9f0332bbd4520b7a4e65fb3b4 100644 (file)
@@ -38,6 +38,9 @@
 #include <AIS_Shape.hxx>
 #include <AIS_Dimension.hxx>
 #include <AIS_Trihedron.hxx>
+#include <AIS_Axis.hxx>
+#include <AIS_Plane.hxx>
+#include <AIS_Point.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
 #include <SelectMgr_ListOfFilter.hxx>
 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
@@ -100,11 +103,10 @@ QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QS
 }
 
 XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
-  : myWorkshop(theWorkshop), myEnableUpdateViewer(true), myNeedUpdate(false),
-  myIsTrihedronActive(false)
+  : myWorkshop(theWorkshop), myNeedUpdate(false),
+  myIsTrihedronActive(false), myViewerBlockedRecursiveCount(0)
 {
-  enableUpdateViewer(true);
-  myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs());
+  myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs(theWorkshop));
 }
 
 XGUI_Displayer::~XGUI_Displayer()
@@ -250,7 +252,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
     Handle(AIS_InteractiveObject) anAIS = anObject->impl<Handle(AIS_InteractiveObject)>();
     if (!anAIS.IsNull()) {
       emit beforeObjectErase(theObject, anObject);
-      aContext->Remove(anAIS, theUpdateViewer);
+      aContext->Remove(anAIS, false/*update viewer*/);
       aErased = true;
     }
   }
@@ -262,6 +264,10 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer)
   qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str());
   qDebug(getResult2AISObjectMapInfo().c_str());
 #endif
+
+  if (theUpdateViewer)
+    updateViewer();
+
   return aErased;
 }
 
@@ -316,7 +322,16 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
         arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str());
     #endif
     if (!isEqualShapes || isCustomized) {
+      /// if shapes are equal and presentation are customized, selection should be restored
+      bool aNeedToRestoreSelection = isEqualShapes && isCustomized;
+      if (aNeedToRestoreSelection)
+        myWorkshop->module()->storeSelection();
+
       aContext->Redisplay(aAISIO, false);
+
+      if (aNeedToRestoreSelection)
+        myWorkshop->module()->restoreSelection();
+
       aRedisplayed = true;
       #ifdef DEBUG_FEATURE_REDISPLAY
         qDebug("  Redisplay happens");
@@ -404,6 +419,40 @@ int XGUI_Displayer::getSelectionMode(int theShapeType)
     AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType);
 }
 
+bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& theObject)
+{
+  bool aVisible = false;
+  GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  if (aPrs.get() || aResult.get()) {
+    aVisible = theDisplayer->isVisible(theObject);
+    // compsolid is not visualized in the viewer, but should have presentation when all sub solids are
+    // visible. It is useful for highlight presentation where compsolid shape is selectable
+    if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) {
+      ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResult);
+      if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
+        bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0;
+        for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) {
+          anAllSubsVisible = theDisplayer->isVisible(aCompsolidResult->subResult(i));
+        }
+        aVisible = anAllSubsVisible;
+      }
+    }
+  }
+  else {
+    // check if all results of the feature are visible
+    FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+    std::list<ResultPtr> aResults = aFeature->results();
+    std::list<ResultPtr>::const_iterator aIt;
+    aVisible = !aResults.empty();
+    for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+      aVisible = aVisible && theDisplayer->isVisible(*aIt);
+    }
+  }
+  return aVisible;
+}
+
+
 void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList,
                                      const bool theUpdateViewer)
 {
@@ -457,7 +506,7 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL
   Handle(AIS_InteractiveObject) aTrihedron;
   if (isTrihedronActive()) {
     aTrihedron = getTrihedron();
-    if (!aTrihedron.IsNull())
+    if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron))
       aPrsList.Append(aTrihedron);
   }
   if (aPrsList.Extent() == 0)
@@ -498,8 +547,8 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrs>& theValues,
   if (aContext.IsNull())
     return;
   if (aContext->HasOpenedContext()) {
-    aContext->UnhilightSelected();
-    aContext->ClearSelected();
+    aContext->UnhilightSelected(false);
+    aContext->ClearSelected(false);
     foreach (ModuleBase_ViewerPrs aPrs, theValues) {
       const TopoDS_Shape& aShape = aPrs.shape();
       if (!aShape.IsNull()) {
@@ -522,8 +571,8 @@ void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrs>& theValues,
       }
     }
   } else {
-    aContext->UnhilightCurrents();
-    aContext->ClearCurrents();
+    aContext->UnhilightCurrents(false);
+    aContext->ClearCurrents(false);
     foreach (ModuleBase_ViewerPrs aPrs, theValues) {
       ObjectPtr anObject = aPrs.object();
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
@@ -559,7 +608,7 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
       Handle(AIS_InteractiveObject) anIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
       if (!anIO.IsNull()) {
         emit beforeObjectErase(aObj, aAISObj);
-        aContext->Remove(anIO, false);
+        aContext->Remove(anIO, false/*update viewer*/);
         aErased = true;
       }
     }
@@ -574,42 +623,47 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer)
   return aErased;
 }
 
-#define DEACTVATE_COMP(TheComp) \
-  if (!TheComp.IsNull()) \
-    aContext->Deactivate(TheComp);
+void deactivateObject(Handle(AIS_InteractiveContext) theContext,
+                      Handle(AIS_InteractiveObject) theObject,
+                      const bool theClear = true)
+{
+  if (!theObject.IsNull()) {
+    theContext->Deactivate(theObject);
+    //if (theClear) {
+      //theObject->ClearSelected();
+      //  theContext->LocalContext()->ClearOutdatedSelection(theObject, true);
+    //}
+  }
+}
 
-void XGUI_Displayer::deactivateTrihedron() const
+void XGUI_Displayer::deactivateTrihedron(const bool theUpdateViewer) const
 {
   Handle(AIS_InteractiveObject) aTrihedron = getTrihedron();
-  if (!aTrihedron.IsNull()) {
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) {
     Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron);
-    Handle(AIS_InteractiveContext) aContext = AISContext();
-    aContext->Deactivate(aTrie);
-    DEACTVATE_COMP(aTrie->XAxis());
-    DEACTVATE_COMP(aTrie->YAxis());
-    DEACTVATE_COMP(aTrie->Axis());
-    DEACTVATE_COMP(aTrie->Position());
-    DEACTVATE_COMP(aTrie->XYPlane());
-    DEACTVATE_COMP(aTrie->XZPlane());
-    DEACTVATE_COMP(aTrie->YZPlane());
+    deactivateObject(aContext, aTrie);
+
+    /// #1136 hidden axis are selected in sketch
+    /// workaround for Cascade: there is a crash in AIS_LocalContext::ClearOutdatedSelection
+    /// for Position AIS object in SelectionModes.
+    deactivateObject(aContext, aTrie->XAxis());
+    deactivateObject(aContext, aTrie->YAxis());
+    deactivateObject(aContext, aTrie->Axis());
+    deactivateObject(aContext, aTrie->Position());
+
+    deactivateObject(aContext, aTrie->XYPlane());
+    deactivateObject(aContext, aTrie->XZPlane());
+    deactivateObject(aContext, aTrie->YZPlane());
+
+    if (theUpdateViewer)
+      updateViewer();
   }
 }
 
 Handle(AIS_InteractiveObject) XGUI_Displayer::getTrihedron() const
 {
-  Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aContext.IsNull()) {
-    AIS_ListOfInteractive aList;
-    aContext->DisplayedObjects(aList, true);
-    AIS_ListIteratorOfListOfInteractive aIt;
-    for (aIt.Initialize(aList); aIt.More(); aIt.Next()) {
-      Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aIt.Value());
-      if (!aTrihedron.IsNull()) {
-        return aTrihedron;
-      }
-    }
-  }
-  return Handle(AIS_InteractiveObject)();
+  return myWorkshop->viewer()->trihedron();
 }
 
 void XGUI_Displayer::openLocalContext()
@@ -736,20 +790,28 @@ ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO)
 
 bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
 {
-  bool aWasEnabled = myEnableUpdateViewer;
+  bool aWasEnabled = isUpdateEnabled();
+  if (isEnabled)
+    myViewerBlockedRecursiveCount--;
+  else
+    myViewerBlockedRecursiveCount++;
 
-  myEnableUpdateViewer = isEnabled;
-  if (myNeedUpdate && myEnableUpdateViewer) {
+  if (myNeedUpdate && isUpdateEnabled()) {
     updateViewer();
     myNeedUpdate = false;
   }
   return aWasEnabled;
 }
 
+bool XGUI_Displayer::isUpdateEnabled() const
+{
+  return myViewerBlockedRecursiveCount == 0;
+}
+
 void XGUI_Displayer::updateViewer() const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
-  if (!aContext.IsNull() && myEnableUpdateViewer) {
+  if (!aContext.IsNull() && isUpdateEnabled()) {
     myWorkshop->viewer()->Zfitall();
     aContext->UpdateCurrentViewer();
   } else {
@@ -762,13 +824,15 @@ void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO,
 {
   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
   if (!aContext.IsNull()) {
-    aContext->Activate(theIO, theMode, theUpdateViewer);
+    aContext->Activate(theIO, theMode, false);
 
 #ifdef DEBUG_ACTIVATE_AIS
     ObjectPtr anObject = getObject(theIO);
     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
     qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str());
 #endif
+    if (theUpdateViewer)
+      updateViewer();
   }
 }
 
@@ -795,7 +859,7 @@ Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
   if (!aContext.IsNull() && !aContext->HasOpenedContext()) {
     aContext->OpenLocalContext();
     if (!isTrihedronActive())
-      deactivateTrihedron();
+      deactivateTrihedron(true);
     aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
     aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
   }
@@ -819,7 +883,7 @@ bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele
   Handle(AIS_InteractiveContext) aContext = AISContext();
   Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
   if (!aContext.IsNull() && !anAISIO.IsNull()) {
-    aContext->Display(anAISIO, 0/*wireframe*/, 0, theUpdateViewer, true, AIS_DS_Displayed);
+    aContext->Display(anAISIO, 0/*wireframe*/, 0, false/*update viewer*/, true, AIS_DS_Displayed);
     aDisplayed = true;
     aContext->Deactivate(anAISIO);
     aContext->Load(anAISIO);
@@ -834,6 +898,8 @@ bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele
         }
       }
     }
+    if (theUpdateViewer)
+      updateViewer();
   }
   return aDisplayed;
 }
@@ -845,10 +911,12 @@ bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer)
   if (!aContext.IsNull()) {
     Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
     if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) {
-      aContext->Remove(anAISIO, theUpdateViewer);
+      aContext->Remove(anAISIO, false/*update viewer*/);
       aErased = true;
     }
   }
+  if (aErased && theUpdateViewer)
+    updateViewer();
   return aErased;
 }
 
@@ -1141,6 +1209,38 @@ void XGUI_Displayer::activateTrihedron(bool theIsActive)
 {  
   myIsTrihedronActive = theIsActive; 
   if (!myIsTrihedronActive) {
-    deactivateTrihedron();
+    deactivateTrihedron(true);
   }
 }
+
+void XGUI_Displayer::displayTrihedron(bool theToDisplay) const
+{
+  Handle(AIS_InteractiveContext) aContext = AISContext();
+  if (aContext.IsNull())
+    return;
+
+  Handle(AIS_Trihedron) aTrihedron = myWorkshop->viewer()->trihedron();
+
+  if (theToDisplay) {
+    if (!aContext->IsDisplayed(aTrihedron))
+      aContext->Display(aTrihedron,
+                        0 /*wireframe*/,
+                        -1 /* selection mode */,
+                        Standard_True /* update viewer*/,
+                        Standard_False /* allow decomposition */,
+                        AIS_DS_Displayed /* xdisplay status */);
+
+    if (!isTrihedronActive())
+      deactivateTrihedron(false);
+    else
+      activate(aTrihedron, myActiveSelectionModes, false);
+  } else {
+    deactivateTrihedron(false);
+    //aContext->LocalContext()->ClearOutdatedSelection(aTrihedron, true);
+    // the selection from the previous activation modes should be cleared manually (#26172)
+
+    aContext->Erase(aTrihedron);
+  }
+
+  updateViewer();
+}