Salome HOME
#1119 Confirmation box for deleting parts
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
index a9a2232fac40c1dfdd86215523cfa9a4de2c435e..936c30afcf40d0f48135c87027979881a1a2e5c6 100755 (executable)
 #include <SketchPlugin_ConstraintFillet.h>
 #include <SketchPlugin_ConstraintMirror.h>
 #include <SketchPlugin_ConstraintAngle.h>
+#include <SketchPlugin_ConstraintCollinear.h>
+#include <SketchPlugin_ConstraintMiddle.h>
 #include <SketchPlugin_MultiRotation.h>
 #include <SketchPlugin_MultiTranslation.h>
+#include <SketchPlugin_IntersectionPoint.h>
 
 #include <SketcherPrs_Tools.h>
 
@@ -68,6 +71,7 @@
 
 //#include <AIS_DimensionSelectionMode.hxx>
 #include <AIS_Shape.hxx>
+#include <AIS_Dimension.hxx>
 
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 
 #include <QMouseEvent>
 #include <QApplication>
+#include <QCursor>
+#include <QMessageBox>
 
 //#define DEBUG_DO_NOT_BY_ENTER
 
+//#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)
@@ -155,7 +163,7 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
   : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false),
     myIsMouseOverWindow(false),
     myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
-    myIsPopupMenuActive(false), myIsConstraintsShown(true)
+    myIsPopupMenuActive(false)
 {
   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
@@ -177,6 +185,9 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
   connect(aWorkshop, SIGNAL(applicationStarted()), this, SLOT(onApplicationStarted()));
+
+  myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
+  myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
 }
 
 PartSet_SketcherMgr::~PartSet_SketcherMgr()
@@ -197,8 +208,15 @@ void PartSet_SketcherMgr::onEnterViewPort()
   return;
   #endif
 
-  if (canChangeCursor(getCurrentOperation()))
-    QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+  if (canChangeCursor(getCurrentOperation())) {
+    QCursor* aCurrentCursor = QApplication::overrideCursor();
+    if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+      QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+#ifdef DEBUG_CURSOR
+      qDebug("onEnterViewPort() : Qt::CrossCursor");
+#endif
+    }
+  }
 
   if (!isNestedCreateOperation(getCurrentOperation()))
     return;
@@ -233,8 +251,12 @@ void PartSet_SketcherMgr::onLeaveViewPort()
   return;
   #endif
 
-  if (canChangeCursor(getCurrentOperation()))
+  if (canChangeCursor(getCurrentOperation())) {
     QApplication::restoreOverrideCursor();
+#ifdef DEBUG_CURSOR
+    qDebug("onLeaveViewPort() : None");
+#endif
+  }
 
   if (!isNestedCreateOperation(getCurrentOperation()))
     return;
@@ -256,7 +278,6 @@ void PartSet_SketcherMgr::onLeaveViewPort()
   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
   if (anActiveWidget)
     anActiveWidget->reset();
-  aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
 
   // hides the presentation of the current operation feature
   // the feature is to be erased here, but it is correct to call canDisplayObject because
@@ -267,11 +288,15 @@ void PartSet_SketcherMgr::onLeaveViewPort()
     FeaturePtr aFeature = aFOperation->feature();
     visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
   }
+  // we should update viewer after the presentation are hidden in the viewer
+  // otherwise the reset presentation(line) appears in the viewer(by quick move from viewer to PP)
+  aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
 }
 
 void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
 {
-  if (isNestedCreateOperation(getCurrentOperation()))
+  if (!isNestedEditOperation(getCurrentOperation()) ||
+      myModule->sketchReentranceMgr()->isInternalEditActive())
     return;
   // it is necessary to save current selection in order to restore it after the values are modifed
   storeSelection();
@@ -284,7 +309,8 @@ void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel()
 
 void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
 {
-  if (isNestedCreateOperation(getCurrentOperation()))
+  if (!isNestedEditOperation(getCurrentOperation()) ||
+      myModule->sketchReentranceMgr()->isInternalEditActive())
     return;
   // it is necessary to restore current selection in order to restore it after the values are modified
   restoreSelection();
@@ -305,7 +331,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
   if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
     return;
 
-  get2dPoint(theWnd, theEvent, myClickedPoint);
+  //get2dPoint(theWnd, theEvent, myClickedPoint);
 
   if (!(theEvent->buttons() & Qt::LeftButton))
     return;
@@ -374,7 +400,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       myIsDragging = true;
       get2dPoint(theWnd, theEvent, myCurrentPoint);
       myDragDone = false;
-      // TODO: Has to be uncommented when SALOME patch on draw mode become avialable
+
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
       launchEditing();
       if (aFeature.get() != NULL) {
@@ -395,11 +421,15 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       myIsDragging = true;
       get2dPoint(theWnd, theEvent, myCurrentPoint);
       myDragDone = false;
-      // TODO: Has to be uncommented when SALOME patch on draw mode become avialable
+
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
 
+      // this is temporary commented in order to avoid the following wrong case:
+      // Distance constraint is under edition, double click on the digit -> nothing happens
+      // because QApplication::processEvents() calls onMouseDoubleClick, which try to show editor
+      // but as the prev edit is commited an new one is not started, editor is not shown.
       // This is necessary in order to finalize previous operation
-      QApplication::processEvents();
+      //QApplication::processEvents();
       launchEditing();
     }
   }
@@ -417,7 +447,7 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
   ModuleBase_Operation* aOp = getCurrentOperation();
   if (aOp) {
     if (isNestedSketchOperation(aOp)) {
-      get2dPoint(theWnd, theEvent, myClickedPoint);
+      //get2dPoint(theWnd, theEvent, myClickedPoint);
 
       // Only for sketcher operations
       if (myIsDragging) {
@@ -437,9 +467,8 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
       }
     }
   }
-      // TODO: Has to be uncommented when SALOME patch on draw mode become avialable
+
   aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
-  //aWorkshop->viewer()->enableSelection(myPreviousDrawModeEnabled);
   myIsDragging = false;
 }
 
@@ -473,7 +502,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     }
   }
 
-  myClickedPoint.clear();
+  //myClickedPoint.clear();
 
   if (myIsDragging) {
     // 1. the current selection is saved in the mouse press method in order to restore it after moving
@@ -481,10 +510,6 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     // mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
     // deselected). This flag should be restored in the slot, processed the mouse release signal.
 
-    // TODO: Has to be commented out when SALOME patch on draw mode become avialable
-    //ModuleBase_IViewer* aViewer = myModule->workshop()->viewer();
-    //aViewer->enableSelection(false);
-
     ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
     if (!aCurrentOperation)
       return;
@@ -601,8 +626,8 @@ void PartSet_SketcherMgr::onApplicationStarted()
 
   XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
   if (aPropertyPanel) {
-    connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
-            this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
+    //connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
+    //        this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
 
     connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
             aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
@@ -619,23 +644,23 @@ void PartSet_SketcherMgr::onApplicationStarted()
   connect(aContextMenuMgr, SIGNAL(afterContextMenu()), this, SLOT(onAfterContextMenu()));
 }
 
-void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
-{
-  if (!myClickedPoint.myIsInitialized)
-    return;
+//void PartSet_SketcherMgr::onBeforeWidgetActivated(ModuleBase_ModelWidget* theWidget)
+//{
+  //if (!myClickedPoint.myIsInitialized)
+  //  return;
 
-  ModuleBase_Operation* aOperation = getCurrentOperation();
+  //ModuleBase_Operation* aOperation = getCurrentOperation();
   // the distance constraint feature should not use the clickedd point
   // this is workaround in order to don't throw down the flyout point value,
   // set by execute() method of these type of features
-  if (isDistanceOperation(aOperation))
-    return;
+  //if (isDistanceOperation(aOperation))
+  //  return;
 
-  PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
-  if (aPnt2dWgt) {
-    aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
-  }
-}
+  //PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(theWidget);
+  //if (aPnt2dWgt) {
+  //  aPnt2dWgt->setPoint(myClickedPoint.myCurX, myClickedPoint.myCurY);
+  //}
+//}
 
 void PartSet_SketcherMgr::onBeforeContextMenu()
 {
@@ -680,7 +705,7 @@ bool PartSet_SketcherMgr::sketchSolverError()
   return anError;
 }
 
-QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI)
+QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
 {
   QString anError = "";
   if (!theFeature.get() || !theFeature->data()->isValid())
@@ -691,38 +716,12 @@ QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature, const
     AttributeStringPtr aAttributeString = aSketch->string(SketchPlugin_Sketch::SOLVER_ERROR());
     anError = aAttributeString->value().c_str();
   }
-  else {
-    ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
-    if (isCheckGUI && anActiveWidget) {
-      ModuleBase_ModelWidget::ValueState aState = anActiveWidget->getValueState();
-      if (aState != ModuleBase_ModelWidget::Stored) {
-        AttributePtr anAttr = anActiveWidget->feature()->attribute(anActiveWidget->attributeID());
-        if (anAttr.get()) {
-          QString anAttributeName = anAttr->id().c_str();
-          switch (aState) {
-            case ModuleBase_ModelWidget::ModifiedInPP:
-              anError = "Attribute \"" + anAttributeName +
-                        "\" modification is not applyed. Please click \"Enter\" or \"Tab\".";
-              break;
-            case ModuleBase_ModelWidget::ModifiedInViewer:
-              anError = "Attribute \"" + anAttributeName +
-                        "\" is locked by modification value in the viewer.";
-              break;
-            case ModuleBase_ModelWidget::Reset:
-              anError = "Attribute \"" + anAttributeName + "\" is not initialized.";
-              break;
-          }
-        }
-      }
-    }
-  }
   return anError;
 }
 
 void PartSet_SketcherMgr::clearClickedFlags()
 {
-  return;
-  myClickedPoint.clear();
+  //myClickedPoint.clear();
   myCurrentPoint.clear();
 }
 
@@ -735,6 +734,10 @@ const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
     aIds << SketchPlugin_Arc::ID().c_str();
     aIds << SketchPlugin_Circle::ID().c_str();
     aIds << SketchPlugin_ConstraintFillet::ID().c_str();
+    aIds << SketchPlugin_IntersectionPoint::ID().c_str();
+    // TODO
+    // SketchRectangle is a python feature, so its ID is passed just as a string
+    aIds << "SketchRectangle";
     aIds.append(constraintsIdList());
   }
   return aIds;
@@ -759,6 +762,8 @@ const QStringList& PartSet_SketcherMgr::constraintsIdList()
     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();
   }
   return aIds;
 }
@@ -792,6 +797,13 @@ bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOpera
   return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
 }
 
+bool PartSet_SketcherMgr::isNestedEditOperation(ModuleBase_Operation* theOperation)
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                               (theOperation);
+  return aFOperation && aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation);
+}
+
 bool PartSet_SketcherMgr::isEntity(const std::string& theId)
 {
   return (theId == SketchPlugin_Line::ID()) ||
@@ -802,12 +814,17 @@ bool PartSet_SketcherMgr::isEntity(const std::string& theId)
 
 bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation)
 {
-  std::string aId = theOperation ? theOperation->id().toStdString() : "";
+  std::string anId = theOperation ? theOperation->id().toStdString() : "";
 
-  return (aId == SketchPlugin_ConstraintLength::ID()) ||
-         (aId == SketchPlugin_ConstraintDistance::ID()) ||
-         (aId == SketchPlugin_ConstraintRadius::ID()) ||
-         (aId == SketchPlugin_ConstraintAngle::ID());
+  return isDistanceKind(anId);
+}
+
+bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
+{
+  return (theKind == SketchPlugin_ConstraintLength::ID()) ||
+         (theKind == SketchPlugin_ConstraintDistance::ID()) ||
+         (theKind == SketchPlugin_ConstraintRadius::ID()) ||
+         (theKind == SketchPlugin_ConstraintAngle::ID());
 }
 
 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
@@ -847,7 +864,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
     myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
 
   myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
-
   bool aHasPlane = false;
   std::shared_ptr<GeomAPI_Pln> aPln;
   if (aFOperation->isEditOperation()) {
@@ -868,7 +884,8 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
 {
   myIsMouseOverWindow = false;
-  myIsConstraintsShown = true;
+  myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
+  myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
 
@@ -930,16 +947,27 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
 
 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
 {
-  if (canChangeCursor(theOperation) && myIsMouseOverWindow)
-    QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+  if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
+    QCursor* aCurrentCursor = QApplication::overrideCursor();
+    if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+      QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+#ifdef DEBUG_CURSOR
+      qDebug("startNestedSketch() : Qt::CrossCursor");
+#endif
+    }
+  }
 }
 
 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
 {
   myIsMouseOverViewProcessed = true;
   operationMgr()->onValidateOperation();
-  if (canChangeCursor(theOperation))
+  if (canChangeCursor(theOperation)) {
     QApplication::restoreOverrideCursor();
+#ifdef DEBUG_CURSOR
+    qDebug("stopNestedSketch() : None");
+#endif
+  }
 }
 
 void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
@@ -958,6 +986,95 @@ void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation)
   }
 }
 
+void PartSet_SketcherMgr::activatePlaneFilter(const bool& toActivate)
+{
+  if (toActivate)
+    myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
+  else
+    myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
+}
+
+void PartSet_SketcherMgr::operationActivatedByPreselection()
+{
+  ModuleBase_Operation* anOperation = getCurrentOperation();
+  if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
+    // Set final definitions if they are necessary
+    //propertyPanelDefined(aOperation);
+    /// Commit sketcher operations automatically
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                            (anOperation);
+    if (aFOperation) {
+      if (PartSet_SketcherMgr::isDistanceOperation(aFOperation)) {
+        FeaturePtr aFeature = aFOperation->feature();
+        // editor is shown only if all attribute references are filled by preseletion
+        bool anAllRefAttrInitialized = true;
+
+        std::list<AttributePtr> aRefAttrs = aFeature->data()->attributes(
+                                                    ModelAPI_AttributeRefAttr::typeId());
+        std::list<AttributePtr>::const_iterator anIt = aRefAttrs.begin(), aLast = aRefAttrs.end();
+        for (; anIt != aLast && anAllRefAttrInitialized; anIt++) {
+          anAllRefAttrInitialized = (*anIt)->isInitialized();
+        }
+        if (anAllRefAttrInitialized) {
+          // Activate dimension value editing on double click
+          ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
+          QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
+          // Find corresponded widget to activate value editing
+          foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
+            if (aWgt->attributeID() == "ConstraintValue") {
+              // the featue should be displayed in order to find the AIS text position,
+              // the place where the editor will be shown
+              aFeature->setDisplayed(true);
+              /// the execute is necessary to perform in the feature compute for flyout position
+              aFeature->execute();
+
+              Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+              Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
+              PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
+              if (anEditor) {
+                int aX = 0, anY = 0;
+
+                ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+                XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+                XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+                AISObjectPtr anAIS = aDisplayer->getAISObject(aFeature);
+                Handle(AIS_InteractiveObject) anAISIO;
+                if (anAIS.get() != NULL) {
+                  anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
+                }
+                if (anAIS.get() != NULL) {
+                  Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
+
+                  if (!anAISIO.IsNull()) {
+                    Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);
+                    if (!aDim.IsNull()) {
+                      gp_Pnt aPosition = aDim->GetTextPosition();
+
+                      ModuleBase_IViewer* aViewer = aWorkshop->viewer();
+                      Handle(V3d_View) aView = aViewer->activeView();
+                      int aCX, aCY;
+                      aView->Convert(aPosition.X(), aPosition.Y(), aPosition.Z(), aCX, aCY);
+
+                      QWidget* aViewPort = aViewer->activeViewPort();
+                      QPoint aGlPoint = aViewPort->mapToGlobal(QPoint(aCX, aCY));
+                      aX = aGlPoint.x();
+                      anY = aGlPoint.y();
+                    }
+                  }
+                  anEditor->setCursorPosition(aX, anY);
+                  anEditor->showPopupEditor(false);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    anOperation->commit();
+  }
+}
+
 bool PartSet_SketcherMgr::canUndo() const
 {
   return isNestedCreateOperation(getCurrentOperation());
@@ -1060,6 +1177,84 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
   return aCanDisplay;
 }
 
+void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                           (getCurrentOperation());
+  if (aFOperation && myCurrentSketch.get()) {
+    // find results of the current operation
+    // these results should not be proposed to be deleted
+    FeaturePtr anOperationFeature = aFOperation->feature();
+    std::list<ResultPtr> anOperationResultList = anOperationFeature->results();
+    std::set<ResultPtr> anOperationResults;
+    std::list<ResultPtr>::const_iterator aRIt = anOperationResultList.begin(),
+                                        aRLast = anOperationResultList.end();
+    for (; aRIt != aRLast; aRIt++)
+      anOperationResults.insert(*aRIt);
+
+    std::set<FeaturePtr> anObjectsToBeDeleted;
+    QStringList anObjectsToBeDeletedNames;
+    std::list<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
+    for (; anIt != aLast; anIt++) {
+      ObjectPtr anObject = *anIt;
+      bool aCanErase = true;
+      // when the sketch operation is active, results of sketch sub-feature can not be hidden
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+      // the result is found between current feature results
+      if (anOperationResults.find(aResult) != anOperationResults.end())
+        continue;
+
+      if (aResult.get()) {
+        // Display sketcher objects
+        for (int i = 0; i < myCurrentSketch->numberOfSubs() && aCanErase; i++) {
+          FeaturePtr aFeature = myCurrentSketch->subFeature(i);
+          std::list<ResultPtr> aResults = aFeature->results();
+          std::list<ResultPtr>::const_iterator anIt;
+          for (anIt = aResults.begin(); anIt != aResults.end() && aCanErase; ++anIt) {
+            aCanErase = *anIt != aResult;
+          }
+        }
+      }
+      if (!aCanErase) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+        if (aFeature.get() && anObjectsToBeDeleted.find(aFeature) == anObjectsToBeDeleted.end()) {
+          anObjectsToBeDeleted.insert(aFeature);
+          anObjectsToBeDeletedNames.append(aFeature->name().c_str());
+        }
+      }
+    }
+    if (!anObjectsToBeDeleted.empty()) {
+      QString aFeatureNames = anObjectsToBeDeletedNames.join(", ");
+      QString aMessage = tr("The following features have incorrect presentation and \
+will be hidden: %1. Would you like to delete them?")
+                         .arg(aFeatureNames);
+      int anAnswer = QMessageBox::question(qApp->activeWindow(), tr("Features hide"),
+                                           aMessage, QMessageBox::Ok | QMessageBox::Cancel,
+                                           QMessageBox::Cancel);
+      if (anAnswer == QMessageBox::Ok) {
+        QObjectPtrList anObjects;
+        std::set<FeaturePtr>::const_iterator anIt = anObjectsToBeDeleted.begin(),
+                                             aLast = anObjectsToBeDeleted.end();
+        for (; anIt != aLast; anIt++)
+          anObjects.append(*anIt);
+        SessionPtr aMgr = ModelAPI_Session::get();
+        DocumentPtr aDoc = aMgr->activeDocument();
+        bool aIsOp = aMgr->isOperation();
+        if (!aIsOp)
+          aMgr->startOperation();
+        workshop()->deleteFeatures(anObjects);
+        //static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+        //static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+        //Events_Loop::loop()->flush(aDeletedEvent);
+        //Events_Loop::loop()->flush(aRedispEvent);
+
+        if (!aIsOp)
+          aMgr->finishOperation();
+      }
+    }
+  }
+}
+
 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
 {
   bool aCanDisplay = myIsMouseOverWindow;
@@ -1077,6 +1272,11 @@ bool PartSet_SketcherMgr::canChangeCursor(ModuleBase_Operation* theOperation) co
          myModule->sketchReentranceMgr()->isInternalEditActive();
 }
 
+const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::showConstraintStates()
+{
+  return myIsConstraintsShown;
+}
+
 bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
 {
   bool isFoundObject = false;
@@ -1344,14 +1544,15 @@ void PartSet_SketcherMgr::restoreSelection()
   }
 }
 
-void PartSet_SketcherMgr::onShowConstraintsToggle(bool theOn)
+void PartSet_SketcherMgr::onShowConstraintsToggle(bool theState, int theType)
 {
-  if (myIsConstraintsShown == theOn)
+  PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
+  if (myIsConstraintsShown.contains(aType) && myIsConstraintsShown[aType] == theState)
     return;
   if (myCurrentSketch.get() == NULL)
     return;
 
-  myIsConstraintsShown = theOn;
+  myIsConstraintsShown[aType] = theState;
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
@@ -1359,22 +1560,35 @@ void PartSet_SketcherMgr::onShowConstraintsToggle(bool theOn)
   const QStringList& aConstrIds = constraintsIdList();
   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
     FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
-    if (aConstrIds.contains(QString(aSubFeature->getKind().c_str()))) {
-      if (myIsConstraintsShown) 
-        aSubFeature->setDisplayed(true);
+    std::string aKind = aSubFeature->getKind();
+    if (aConstrIds.contains(QString(aKind.c_str()))) {
+      bool isTypedConstraint = false;
+      if (aType == PartSet_Tools::Dimensional) {
+        isTypedConstraint = isDistanceKind(aKind);
+      }
       else
-        aSubFeature->setDisplayed(false);
+        isTypedConstraint = !isDistanceKind(aKind);
+
+      if (isTypedConstraint) {
+        if (theState)
+          aSubFeature->setDisplayed(true);
+        else
+          aSubFeature->setDisplayed(false);
+      }
     }
   }
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
-XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
+XGUI_Workshop* PartSet_SketcherMgr::workshop() const
 {
   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
-  XGUI_Workshop* aWorkshop = aConnector->workshop();
+  return aConnector->workshop();
+}
 
-  return aWorkshop->operationMgr();
+XGUI_OperationMgr* PartSet_SketcherMgr::operationMgr() const
+{
+  return workshop()->operationMgr();
 }