Salome HOME
Additional check redundant constraints in PlaneGCS to show the "Conflicting constrain...
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
index 236124f63403168fd4daa1802849363696ff6d4b..7fcebed5a10f52421f9874413936c0f65e1b59a4 100755 (executable)
@@ -12,6 +12,7 @@
 #include "PartSet_Tools.h"
 #include "PartSet_WidgetSketchLabel.h"
 #include "PartSet_WidgetEditor.h"
+#include "PartSet_ResultSketchPrs.h"
 
 #include <XGUI_ModuleConnector.h>
 #include <XGUI_Displayer.h>
@@ -35,6 +36,8 @@
 #include <ModuleBase_OperationFeature.h>
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_WidgetEditor.h>
+#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
 
 #include <GeomDataAPI_Point2D.h>
 
 //#define DEBUG_CURSOR
 
 /// Returns list of unique objects by sum of objects from List1 and List2
-/*QList<ModuleBase_ViewerPrs> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
-                                       const QList<ModuleBase_ViewerPrs>& theList2)
+/*QList<ModuleBase_ViewerPrsPtr> getSumList(const QList<ModuleBase_ViewerPrsPtr>& theList1,
+                                       const QList<ModuleBase_ViewerPrsPtr>& theList2)
 {
-  QList<ModuleBase_ViewerPrs> aRes;
-  foreach (ModuleBase_ViewerPrs aPrs, theList1) {
+  QList<ModuleBase_ViewerPrsPtr> aRes;
+  foreach (ModuleBase_ViewerPrsPtr aPrs, theList1) {
     if (!aRes.contains(aPrs))
       aRes.append(aPrs);
   }
-  foreach (ModuleBase_ViewerPrs aPrs, theList2) {
+  foreach (ModuleBase_ViewerPrsPtr aPrs, theList2) {
     if (!aRes.contains(aPrs))
       aRes.append(aPrs);
   }
 // \param theSketch a sketch to project a vertex shape of a presentation to the plane
 // and find the corresponded attribute
 // \param theFeatureList  an output list of features
-void fillFeatureList(const QList<ModuleBase_ViewerPrs>& theList,
+void fillFeatureList(const QList<ModuleBase_ViewerPrsPtr>& theList,
                      const FeaturePtr theSketch,
                      QList<FeaturePtr>& theFeatureList)
 {
-  QList<ModuleBase_ViewerPrs> aRes;
+  QList<ModuleBase_ViewerPrsPtr> aRes;
 
-  QList<ModuleBase_ViewerPrs>::const_iterator anIt = theList.begin(),
+  QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theList.begin(),
                                               aLast = theList.end();
   for (; anIt != aLast; anIt++)
   {
-    ModuleBase_ViewerPrs aPrs = *anIt;
-    FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
+    ModuleBase_ViewerPrsPtr aPrs = *anIt;
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs->object());
     if (aFeature.get()  && !theFeatureList.contains(aFeature))
       theFeatureList.append(aFeature);
   }
@@ -189,6 +192,7 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
 
   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
+  myIsConstraintsShown[PartSet_Tools::Expressions] = false;
 }
 
 PartSet_SketcherMgr::~PartSet_SketcherMgr()
@@ -244,9 +248,6 @@ void PartSet_SketcherMgr::onLeaveViewPort()
 {
   myIsMouseOverViewProcessed = false;
   myIsMouseOverWindow = false;
-  // it is important to validate operation here only if sketch entity create operation is active
-  // because at this operation we reacts to the mouse leave/enter view port
-  //operationMgr()->onValidateOperation();
 
   #ifdef DEBUG_DO_NOT_BY_ENTER
   return;
@@ -267,6 +268,8 @@ void PartSet_SketcherMgr::onLeaveViewPort()
   if (myIsPopupMenuActive)
     return;
 
+  // it is important to validate operation here only if sketch entity create operation is active
+  // because at this operation we reacts to the mouse leave/enter view port
   operationMgr()->onValidateOperation();
 
   // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation
@@ -384,6 +387,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
     if (!aContext.IsNull()) {
       // MoveTo in order to highlight current object
       aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
+      ModuleBase_Tools::selectionInfo(aContext, "PartSet_SketcherMgr::onMousePressed -- MoveTo");
     }
     // Remember highlighted objects for editing
     ModuleBase_ISelection* aSelect = aWorkshop->selection();
@@ -611,8 +615,8 @@ void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMo
       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
       // Find corresponded widget to activate value editing
       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
-        if (aWgt->attributeID() == "ConstraintValue" ||
-            aWgt->attributeID() == "AngleValue") {
+        if (aWgt->attributeID() == SketchPlugin_Constraint::VALUE() ||
+            aWgt->attributeID() == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) {
           PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
           if (anEditor)
             anEditor->showPopupEditor();
@@ -694,7 +698,7 @@ void PartSet_SketcherMgr::launchEditing()
     FeaturePtr aFeature = myCurrentSelection.begin().key();
     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-    if (aSPFeature) {
+    if (aSPFeature && (!aSPFeature->isExternal())) {
       myModule->editFeature(aSPFeature);
     }
   }
@@ -744,34 +748,43 @@ const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
     // TODO
     // SketchRectangle is a python feature, so its ID is passed just as a string
     aIds << "SketchRectangle";
+    aIds.append(replicationsIdList());
     aIds.append(constraintsIdList());
   }
   return aIds;
 }
 
+const QStringList& PartSet_SketcherMgr::replicationsIdList()
+{
+  static QStringList aReplicationIds;
+  if (aReplicationIds.size() == 0) {
+    aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str();
+    aReplicationIds << SketchPlugin_MultiRotation::ID().c_str();
+    aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str();
+  }
+  return aReplicationIds;
+}
+
 const QStringList& PartSet_SketcherMgr::constraintsIdList()
 {
-  static QStringList aIds;
-  if (aIds.size() == 0) {
-    aIds << SketchPlugin_ConstraintLength::ID().c_str();
-    aIds << SketchPlugin_ConstraintDistance::ID().c_str();
-    aIds << SketchPlugin_ConstraintRigid::ID().c_str();
-    aIds << SketchPlugin_ConstraintRadius::ID().c_str();
-    aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
-    aIds << SketchPlugin_ConstraintParallel::ID().c_str();
-    aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
-    aIds << SketchPlugin_ConstraintVertical::ID().c_str();
-    aIds << SketchPlugin_ConstraintEqual::ID().c_str();
-    aIds << SketchPlugin_ConstraintTangent::ID().c_str();
-    aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
-    aIds << SketchPlugin_ConstraintMirror::ID().c_str();
-    aIds << SketchPlugin_ConstraintAngle::ID().c_str();
-    aIds << SketchPlugin_MultiRotation::ID().c_str();
-    aIds << SketchPlugin_MultiTranslation::ID().c_str();
-    aIds << SketchPlugin_ConstraintCollinear::ID().c_str();
-    aIds << SketchPlugin_ConstraintMiddle::ID().c_str();
+  static QStringList aConstraintIds;
+  if (aConstraintIds.size() == 0) {
+    aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str();
+    aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str();
   }
-  return aIds;
+  return aConstraintIds;
 }
 
 void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
@@ -785,6 +798,17 @@ void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
   theModes.append(TopAbs_EDGE);
 }
 
+Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult)
+{
+  Handle(AIS_InteractiveObject) aPrs;
+
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
+  if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) {
+    aPrs = new PartSet_ResultSketchPrs(theResult);
+  }
+  return aPrs;
+}
+
 bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
 {
   return theOperation && theOperation->id().toStdString() == SketchPlugin_Sketch::ID();
@@ -845,7 +869,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   // Display all sketcher sub-Objects
   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-  aConnector->workshop()->displayer()->activateTrihedron(true);
 
   // Hide sketcher result
   std::list<ResultPtr> aResults = myCurrentSketch->results();
@@ -878,18 +901,13 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
   bool aHasPlane = false;
   std::shared_ptr<GeomAPI_Pln> aPln;
-  if (aFOperation->isEditOperation()) {
-    // If it is editing of sketch then it means that plane is already defined
-    aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
-    if (aPln.get())
-      aHasPlane = true;
-  }
+  aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
   myPlaneFilter->setPlane(aPln);
 
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  // all sketch objects should be activated in the sketch selection modes by edit operation start
-  // in case of creation operation, there is an active widget, which activates own selection mode
-  if (aFOperation->isEditOperation() && aHasPlane)
+  // all displayed objects should be activated in current selection modes according to switched
+  // plane filter
+  if (aPln.get())
     aConnector->activateModuleSelectionModes();
 }
 
@@ -898,6 +916,7 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   myIsMouseOverWindow = false;
   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
+  myIsConstraintsShown[PartSet_Tools::Expressions] = false;
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
 
@@ -958,7 +977,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   }
   // restore the module selection modes, which were changed on startSketch
   aConnector->activateModuleSelectionModes();
-  aConnector->workshop()->displayer()->activateTrihedron(false);
 }
 
 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
@@ -1023,8 +1041,12 @@ bool PartSet_SketcherMgr::operationActivatedByPreselection()
     bool aCanCommitOperation = true;
     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                             (anOperation);
-    if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation))
-      aCanCommitOperation = setDistanceValueByPreselection(anOperation, myModule->workshop());
+    if (aFOperation && PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {
+      bool aValueAccepted = setDistanceValueByPreselection(anOperation, myModule->workshop(),
+                                                           aCanCommitOperation);
+      if (!aValueAccepted)
+        return isOperationStopped;
+    }
 
     if (aCanCommitOperation)
       isOperationStopped = anOperation->commit();
@@ -1081,6 +1103,11 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
     if (aFeature.get() != NULL && aFeature == activeSketch()) {
       aCanDisplay = false;
     }
+    std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+                            std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+    /// some sketch entities should be never shown, e.g. projection feature
+    if (aSketchFeature.get())
+      aCanDisplay = aSketchFeature->canBeDisplayed();
   }
   else { // there are no an active sketch
     // 2. sketch sub-features should not be visualized if the sketch operation is not active
@@ -1096,43 +1123,45 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
 
   // 3. the method should not filter the objects, which are not related to the current operation.
   // The object is filtered just if it is a current operation feature or this feature result
-  bool isObjectFound = false;
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                               (getCurrentOperation());
-  if (aFOperation) {
-    FeaturePtr aFeature = aFOperation->feature();
-    if (aFeature.get()) {
-      std::list<ResultPtr> aResults = aFeature->results();
-      if (theObject == aFeature)
-        isObjectFound = true;
-      else {
-        std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
-        for (; anIt != aLast && !isObjectFound; anIt++) {
-          isObjectFound = *anIt == theObject;
+  if (aCanDisplay) {
+    bool isObjectFound = false;
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                 (getCurrentOperation());
+    if (aFOperation) {
+      FeaturePtr aFeature = aFOperation->feature();
+      if (aFeature.get()) {
+        std::list<ResultPtr> aResults = aFeature->results();
+        if (theObject == aFeature)
+          isObjectFound = true;
+        else {
+          std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLast = aResults.end();
+          for (; anIt != aLast && !isObjectFound; anIt++) {
+            isObjectFound = *anIt == theObject;
+          }
         }
       }
     }
-  }
-  if (isObjectFound) {
-    // 4. For created nested feature operation do not display the created feature if
-    // the mouse curstor leaves the OCC window.
-    // The correction cases, which ignores this condition:
-    // a. the property panel values modification
-    // b. the popup menu activated
-    // c. widget editor control
-    #ifndef DEBUG_DO_NOT_BY_ENTER
-    if (aCanDisplay && isNestedCreateOperation(getCurrentOperation())) {
-      ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
-      ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;
-      // the active widget editor should not influence here. The presentation should be visible always
-      // when this widget is active.
-      if (!anEditorWdg && !myIsPopupMenuActive) {
-        // during a nested create operation, the feature is redisplayed only if the mouse over view
-        // of there was a value modified in the property panel after the mouse left the view
-        aCanDisplay = canDisplayCurrentCreatedFeature();
+    if (isObjectFound) {
+      // 4. For created nested feature operation do not display the created feature if
+      // the mouse curstor leaves the OCC window.
+      // The correction cases, which ignores this condition:
+      // a. the property panel values modification
+      // b. the popup menu activated
+      // c. widget editor control
+      #ifndef DEBUG_DO_NOT_BY_ENTER
+      if (isNestedCreateOperation(getCurrentOperation())) {
+        ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
+        ModuleBase_WidgetEditor* anEditorWdg = anActiveWidget ? dynamic_cast<ModuleBase_WidgetEditor*>(anActiveWidget) : 0;
+        // the active widget editor should not influence here. The presentation should be visible always
+        // when this widget is active.
+        if (!anEditorWdg && !myIsPopupMenuActive) {
+          // during a nested create operation, the feature is redisplayed only if the mouse over view
+          // of there was a value modified in the property panel after the mouse left the view
+          aCanDisplay = canDisplayCurrentCreatedFeature();
+        }
       }
+      #endif
     }
-    #endif
   }
 
   // checks the sketcher constraints visibility according to active sketch check box states
@@ -1194,7 +1223,7 @@ bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature,
   return aSwitchedOn;
 }
 
-void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
+/*void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
 {
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                            (getCurrentOperation());
@@ -1270,7 +1299,7 @@ will be hidden: %1. Would you like to delete them?")
       }
     }
   }
-}
+}*/
 
 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
 {
@@ -1318,9 +1347,11 @@ void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& th
 }
 
 bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* theOperation,
-                                                         ModuleBase_IWorkshop* theWorkshop)
+                                                         ModuleBase_IWorkshop* theWorkshop,
+                                                         bool& theCanCommitOperation)
 {
   bool isValueAccepted = false;
+  theCanCommitOperation = false;
 
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                               (theOperation);
@@ -1382,6 +1413,7 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t
             }
             anEditor->setCursorPosition(aX, anY);
             isValueAccepted = anEditor->showPopupEditor(false);
+            theCanCommitOperation = true;
           }
         }
       }
@@ -1536,6 +1568,15 @@ void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
   }
 }
 
+void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject)
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                           (getCurrentOperation());
+  if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
+                      PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)))
+    SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
+}
+
 ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
 {
   return myModule->workshop()->currentOperation();
@@ -1599,7 +1640,7 @@ void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   ModuleBase_ISelection* aSelect = aWorkshop->selection();
-  QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
+  QList<ModuleBase_ViewerPrsPtr> aHighlighted = aSelect->getHighlighted();
 
   QList<FeaturePtr> aFeatureList;
   if (theHighlightedOnly) {
@@ -1608,7 +1649,7 @@ void PartSet_SketcherMgr::storeSelection(const bool theHighlightedOnly)
   else {
     fillFeatureList(aHighlighted, myCurrentSketch, aFeatureList);
 
-    QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls);
+    QList<ModuleBase_ViewerPrsPtr> aSelected = aSelect->getSelected(ModuleBase_ISelection::AllControls);
     fillFeatureList(aSelected, myCurrentSketch, aFeatureList);
   }
 
@@ -1643,24 +1684,47 @@ void PartSet_SketcherMgr::restoreSelection()
 void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState)
 {
   PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
-  if (myIsConstraintsShown.contains(aType) && myIsConstraintsShown[aType] == theState)
-    return;
-  if (myCurrentSketch.get() == NULL)
-    return;
 
-  myIsConstraintsShown[aType] = theState;
+  updateBySketchParameters(aType, theState);
+}
 
-  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+void PartSet_SketcherMgr::updateBySketchParameters(
+                                   const PartSet_Tools::ConstraintVisibleState& theType,
+                                   bool theState)
+{
+  if (myCurrentSketch.get() == NULL)
+    return;
 
-  for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
-    FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
-    bool aProcessed = false;
-    bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, aType, aProcessed);
-    if (aProcessed)
-      aSubFeature->setDisplayed(aConstraintDisplayed);
+  bool aPrevState = myIsConstraintsShown[theType];
+  myIsConstraintsShown[theType] = theState;
+
+  switch (theType) {
+    case PartSet_Tools::Geometrical:
+    case PartSet_Tools::Dimensional: {
+      if (aPrevState != theState) {
+        ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+        XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+        for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
+          FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
+          bool aProcessed = false;
+          bool aConstraintDisplayed = canDisplayConstraint(aSubFeature, theType, aProcessed);
+          if (aProcessed)
+            aSubFeature->setDisplayed(aConstraintDisplayed);
+        }
+        Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+      }
+    }
+    break;
+    case PartSet_Tools::Expressions: {
+      if (aPrevState != theState) {
+        /// call all sketch features redisplay, the expression state will be corrected in customize
+        /// of distance presentation
+        Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+        PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);
+      }
+    }
+    break;
   }
-  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 XGUI_Workshop* PartSet_SketcherMgr::workshop() const