Salome HOME
updated copyright message
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
index 9369a736221796580f5e91c594c0cbaf24f5e9d0..d47d1ec75589c66af6aed3931e8c8cb605776c98 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -60,6 +60,7 @@
 #include <ModuleBase_ViewerFilters.h>
 
 #include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Point2DArray.h>
 
 #include <GeomAPI_Shape.h>
 
 #include <SelectMgr_IndexedMapOfOwner.hxx>
 #include <StdSelect_BRepOwner.hxx>
 
-//#include <AIS_DimensionSelectionMode.hxx>
 #include <AIS_Shape.hxx>
-#include <AIS_Dimension.hxx>
+#include <PrsDim_Dimension.hxx>
 
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
                             const FeaturePtr& theFeature, const FeaturePtr& theSketch,
                             const ResultPtr& theResult,
-                            std::set<AttributePtr>& theSelectedAttributes,
+                            std::map<AttributePtr, int>& theSelectedAttributes,
                             std::set<ResultPtr>& theSelectedResults,
                             TopTools_MapOfShape& theShapes)
 {
@@ -156,10 +156,10 @@ void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
     theShapes.Add(aShape);
     TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
     if (aShapeType == TopAbs_VERTEX) {
-      AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theFeature,
-                                                                    aShape, theSketch);
-      if (aPntAttr.get() != NULL)
-        theSelectedAttributes.insert(aPntAttr);
+      std::pair<AttributePtr, int> aPntAttrIndex =
+          PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);
+      if (aPntAttrIndex.first.get() != NULL)
+        theSelectedAttributes[aPntAttrIndex.first] = aPntAttrIndex.second;
     }
     else if (aShapeType == TopAbs_EDGE &&
              theSelectedResults.find(theResult) == theSelectedResults.end()) {
@@ -169,11 +169,17 @@ void getAttributesOrResults(const Handle(SelectMgr_EntityOwner)& theOwner,
 }
 
 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
-  : QObject(theModule), myModule(theModule), myIsEditLaunching(false), myIsDragging(false),
-    myDragDone(false), myIsMouseOverWindow(false),
-    myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
-    myIsPopupMenuActive(false), myExternalPointsMgr(0), myNoDragMoving(false),
-    myIsSketchStarted(false)
+  : QObject(theModule),
+    myModule(theModule),
+    myIsEditLaunching(false),
+    myIsDragging(false),
+    myDragDone(false),
+    myIsMouseOverWindow(false),
+    myIsMouseOverViewProcessed(true),
+    myIsPopupMenuActive(false),
+    myPreviousUpdateViewerEnabled(true),
+    myExternalPointsMgr(0),
+    myNoDragMoving(false)
 {
   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
@@ -227,15 +233,15 @@ void PartSet_SketcherMgr::onEnterViewPort()
 
   // It is switched off because of
   // Task #3067: 5.2.2 Drawing in the sketcher: change the mouse cursor arrow
-  //  if (canChangeCursor(getCurrentOperation())) {
-  //    QCursor* aCurrentCursor = QApplication::overrideCursor();
-  //    if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
-  //      QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+    if (canChangeCursor(getCurrentOperation())) {
+      QCursor* aCurrentCursor = QApplication::overrideCursor();
+      if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+        QApplication::setOverrideCursor(PartSet_Tools::getOperationCursor());
   //#ifdef DEBUG_CURSOR
   //      qDebug("onEnterViewPort() : Qt::CrossCursor");
   //#endif
-  //    }
-  //  }
+      }
+    }
 
   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
     return;
@@ -267,12 +273,12 @@ void PartSet_SketcherMgr::onLeaveViewPort()
   return;
   #endif
 
-//  if (canChangeCursor(getCurrentOperation())) {
-//    QApplication::restoreOverrideCursor();
+  if (canChangeCursor(getCurrentOperation())) {
+    QApplication::restoreOverrideCursor();
 //#ifdef DEBUG_CURSOR
 //    qDebug("onLeaveViewPort() : None");
 //#endif
-//  }
+  }
 
   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
     return;
@@ -349,11 +355,35 @@ void PartSet_SketcherMgr::onAfterValuesChangedInPropertyPanel()
 }
 */
 
+bool PartSet_SketcherMgr::isDragModeCreation() const
+{
+  ModuleBase_Operation* aOp = getCurrentOperation();
+  if (!aOp)
+    return false;
+  bool aUserPref = Config_PropManager::boolean(SKETCH_TAB_NAME, "create_by_dragging");
+  if (!aUserPref)
+    return false;
+  QString aId = aOp->id();
+  // Acceptable features;
+  QStringList aList;
+  aList << "SketchLine" << "SketchMacroCircle" << "SketchMacroArc" <<
+    "SketchMacroEllipse" << "SketchMacroEllipticArc" << "SketchMacroRectangle";
+  return aList.contains(aId);
+}
+
+static bool MyModeByDrag = false;
+static bool MyMultiselectionState = true;
+
 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
+  MyModeByDrag = isDragModeCreation();
+
   // Clear dragging mode
   myIsDragging = false;
 
+  myMousePoint.setX(theEvent->x());
+  myMousePoint.setY(theEvent->y());
+
   if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
     return;
   //get2dPoint(theWnd, theEvent, myClickedPoint);
@@ -399,9 +429,24 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       return;
 
     // Ignore creation sketch operation
-    if ((!isSketcher) && (!isEditing))
+    if ((!isSketcher) && (!isEditing)) {
+      if (MyModeByDrag) {
+        ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
+        PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+        if (aProcessor) {
+          MyMultiselectionState = aViewer->isMultiSelectionEnabled();
+          aViewer->enableMultiselection(false);
+          myIsDragging = true;
+          ModuleBase_ISelection* aSelection = aWorkshop->selection();
+          QList<ModuleBase_ViewerPrsPtr> aPreSelected = aSelection->getHighlighted();
+          if (!aPreSelected.empty())
+            aProcessor->setPreSelection(aPreSelected.first(), theWnd, theEvent);
+          else
+            aProcessor->mouseReleased(theWnd, theEvent);
+        }
+      }
       return;
-
+    }
     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
     storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection);
 
@@ -414,7 +459,6 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
     }
     // Init flyout point for radius rotation
     FeaturePtr aFeature = myCurrentSelection.begin().key();
-
     get2dPoint(theWnd, theEvent, myCurrentPoint);
     if (isSketcher) {
       if (aCanDrag) {
@@ -423,19 +467,6 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       }
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
       launchEditing();
-      if (aFeature.get() != NULL) {
-        std::shared_ptr<SketchPlugin_Feature> aSPFeature =
-                  std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-        if (aSPFeature.get() &&
-          (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() ||
-           aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) {
-          DataPtr aData = aSPFeature->data();
-          AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
-          std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
-            std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
-          aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
-        }
-      }
     } else if (isSketchOpe && isEditing) {
       // If selected another object commit current result
       bool aPrevLaunchingState = myIsEditLaunching;
@@ -444,22 +475,46 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
       /// Internal edit should not be stored as editing operation as the result will be a
       /// creation operation, where previous selection should not be used(and will be cleared)
       myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive();
-      aFOperation->commit();
+
+      std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+        std::dynamic_pointer_cast<SketchPlugin_Feature>(aFOperation->feature());
+      bool isRelaunchEditing = true;
+      if (aSPFeature->isExternal()) {
+        foreach(FeaturePtr aF, myCurrentSelection.keys()) {
+          FeaturePtr aProducerFeature = PartSet_Tools::findRefsToMeFeature(aF,
+            aSPFeature->getKind());
+          if (aProducerFeature == aSPFeature) {
+            isRelaunchEditing = false;
+            break;
+          }
+        }
+      }
+      else {
+        if (myCurrentSelection.size() > 1)
+          isRelaunchEditing = !myCurrentSelection.contains(aSPFeature);
+      }
+      if (isRelaunchEditing)
+        aFOperation->commit();
 
       if (aCanDrag) {
         myIsDragging = true;
         myDragDone = false;
       }
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
-      launchEditing();
+      if (isRelaunchEditing)
+        launchEditing();
+      else {
+        if (myCurrentSelection.size() > 1)
+          aFOperation->propertyPanel()->cleanContent();
+      }
       myIsEditLaunching = aPrevLaunchingState;
       if (aFeature.get() != NULL) {
-        std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+        std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
                   std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-        if (aSPFeature.get() &&
-          (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID() ||
-           aSPFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) {
-          DataPtr aData = aSPFeature->data();
+        if (aSketchFeature.get() &&
+           (aSketchFeature->getKind() == SketchPlugin_ConstraintRadius::ID() ||
+            aSketchFeature->getKind() == SketchPlugin_ConstraintAngle::ID())) {
+          DataPtr aData = aSketchFeature->data();
           AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
           std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
@@ -487,12 +542,13 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
   if (!myIsMouseOverViewProcessed) {
     return;
   }
-  //if (!aViewer->canDragByMouse())
-  //  return;
+
   ModuleBase_OperationFeature* aOp =
     dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
+  bool isEditing = false;
   if (aOp) {
-    bool aStartNoDragOperation = !aViewer->canDragByMouse() && aOp->isEditOperation();
+    isEditing = aOp->isEditOperation();
+    bool aStartNoDragOperation = !aViewer->canDragByMouse() && isEditing;
     if (aStartNoDragOperation || myNoDragMoving) {
       // Process edit operation without dragging
       if (myCurrentSelection.size() > 0)
@@ -522,11 +578,32 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
     }
   }
 
-
   ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
   PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
-  if (aProcessor)
-    aProcessor->mouseReleased(theWnd, theEvent);
+  if (aProcessor) {
+    ModuleBase_ISelection* aSelection = aWorkshop->selection();
+    QList<ModuleBase_ViewerPrsPtr> aPreSelected = aSelection->getHighlighted();
+    if (MyModeByDrag && !aPreSelected.empty() && !isEditing)
+      aProcessor->setPreSelection(aPreSelected.first(), theWnd, theEvent);
+    else
+      aProcessor->mouseReleased(theWnd, theEvent);
+  }
+  if (MyModeByDrag && aOp) {
+    aViewer->enableMultiselection(true);
+    QString aOpId = aOp->id();
+    if (aOpId == "Sketch")
+      return;
+    QPoint aPnt(theEvent->x(), theEvent->y());
+    anActiveWidget = getActiveWidget();
+    if ((aPnt == myMousePoint) && anActiveWidget) {
+      aOp->abort();
+      return;
+    }
+    bool aCanRestart = !anActiveWidget && !isEditing;
+    if (aCanRestart) {
+      module()->launchOperation(aOpId, true);
+    }
+  }
 }
 
 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
@@ -544,6 +621,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
   }
 #endif
+
   if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
     return;
 
@@ -600,7 +678,6 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
 #endif
 
     Handle(V3d_View) aView = theWnd->v3dView();
-    gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
     Point aMousePnt;
     get2dPoint(theWnd, theEvent, aMousePnt);
 
@@ -623,26 +700,26 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     for (; anIt != aLast; anIt++) {
       FeaturePtr aFeature = anIt.key();
 
-      std::set<AttributePtr> anAttributes = anIt.value().myAttributes;
+      std::map<AttributePtr, int> anAttributes = anIt.value().myAttributes;
       // Process selection by attribute: the priority to the attribute
       if (!anAttributes.empty()) {
-        std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
+        std::map<AttributePtr, int>::const_iterator anAttIt = anAttributes.begin(),
           anAttLast = anAttributes.end();
         for (; anAttIt != anAttLast; anAttIt++) {
-          AttributePtr anAttr = *anAttIt;
+          AttributePtr anAttr = anAttIt->first;
           if (anAttr.get() == NULL)
             continue;
           std::string aAttrId = anAttr->id();
           DataPtr aData = aFeature->data();
           if (aData->isValid()) {
-            std::shared_ptr<GeomDataAPI_Point2D> aPoint =
-              std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
-            if (aPoint.get() != NULL) {
+            AttributePtr aPoint = aData->attribute(aAttrId);
+            if (aPoint->attributeType() == GeomDataAPI_Point2D::typeId() ||
+                aPoint->attributeType() == GeomDataAPI_Point2DArray::typeId()) {
               bool isImmutable = aPoint->setImmutable(true);
 
               std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
                 <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
-              aMessage->setMovedAttribute(aPoint);
+              aMessage->setMovedAttribute(aPoint, anAttIt->second);
               aMessage->setOriginalPosition(anOriginalPosition);
               aMessage->setCurrentPosition(aCurrentPosition);
               Events_Loop::loop()->send(aMessage);
@@ -970,6 +1047,8 @@ bool PartSet_SketcherMgr::isEntity(const std::string& theId)
          (theId == SketchPlugin_Arc::ID()) ||
          (theId == SketchPlugin_Circle::ID()) ||
          (theId == SketchPlugin_Ellipse::ID()) ||
+         (theId == SketchPlugin_Projection::ID()) ||
+         (theId == SketchPlugin_IntersectionPoint::ID()) ||
          (theId == SketchPlugin_EllipticArc::ID());
 }
 
@@ -1008,7 +1087,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   if (!aFOperation)
     return;
 
-  myIsSketchStarted = true;
   SketcherPrs_Tools::setPixelRatio(ModuleBase_Tools::currentPixelRatio());
 
   myModule->onViewTransformed();
@@ -1017,6 +1095,8 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
   double aSizeOfView = 0;
   std::shared_ptr<GeomAPI_Pnt> aCentralPoint;
+  // Reset size of view from previous launches
+  mySketchPlane->setSizeOfView(aSizeOfView, false, aCentralPoint);
   if (aFOperation->isEditOperation() &&
       mySketchPlane->getDefaultSizeOfView(myCurrentSketch, aSizeOfView, aCentralPoint)) {
     mySketchPlane->setSizeOfView(aSizeOfView, true, aCentralPoint);
@@ -1055,7 +1135,7 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
     for (; anIt != aLast; anIt++) {
       FeaturePtr aFeature = *anIt;
       if (aFeature.get())
-        anInvalidFeatureNames.append(aFeature->name().c_str());
+        anInvalidFeatureNames.append(QString::fromStdWString(aFeature->name()));
     }
     std::string aPrefixInfo = QString("Invalid features of the sketch will be deleted: %1.\n\n").
                                   arg(anInvalidFeatureNames.join(", ")).toStdString().c_str();
@@ -1083,9 +1163,8 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
 #ifdef DEBUG_SKETCHER_ENTITIES
     anInfo.append(ModuleBase_Tools::objectInfo(aFeature));
 #endif
-    std::list<ResultPtr> aResults = aFeature->results();
-    std::list<ResultPtr>::const_iterator aIt;
-    for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+    std::list<ResultPtr> aFeatResults = aFeature->results();
+    for (aIt = aFeatResults.begin(); aIt != aFeatResults.end(); ++aIt) {
       if ((*aIt)->isDisplayed())
         // Display object if it was created outside of GUI
         aECreator->sendUpdated((*aIt), EVENT_DISP);
@@ -1103,7 +1182,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   qDebug(QString("startSketch: %1, %2").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
 #endif
 
-  bool aHasPlane = false;
   std::shared_ptr<GeomAPI_Pln> aPln;
   aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
   Handle(SelectMgr_Filter) aFilter = myModule->selectionFilter(SF_SketchPlaneFilter);
@@ -1113,8 +1191,8 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   workshop()->selectionActivate()->updateSelectionFilters();
   workshop()->selectionActivate()->updateSelectionModes();
 
-  Events_Loop::loop()->flush(EVENT_DISP);
   Events_Loop::loop()->flush(EVENT_ATTR);
+  Events_Loop::loop()->flush(EVENT_DISP);
 
   myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
 
@@ -1131,8 +1209,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   myModule->workshop()->viewer()->setFitter(0);
   delete aFitter;
 
-  myIsSketchStarted = false;
-
   myIsMouseOverWindow = false;
   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
@@ -1200,30 +1276,30 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   workshop()->viewer()->set2dMode(false);
 }
 
-//void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
-//{
-//  if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
-//    QCursor* aCurrentCursor = QApplication::overrideCursor();
-//    if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
-//      QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
+{
+  if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
+    QCursor* aCurrentCursor = QApplication::overrideCursor();
+    if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+      QApplication::setOverrideCursor(PartSet_Tools::getOperationCursor());
 //#ifdef DEBUG_CURSOR
 //      qDebug("startNestedSketch() : Qt::CrossCursor");
 //#endif
-//    }
-//  }
-//}
+    }
+  }
+}
 
 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
 {
   myIsMouseOverViewProcessed = true;
   operationMgr()->onValidateOperation();
   // when sketch nested operation is stopped the cursor should be restored unconditionally
-  //if (canChangeCursor(theOperation)) {
-    //QApplication::restoreOverrideCursor();
+  if (canChangeCursor(theOperation)) {
+    QApplication::restoreOverrideCursor();
 #ifdef DEBUG_CURSOR
     qDebug("stopNestedSketch() : None");
 #endif
-  //}
+  }
   /// improvement to deselect automatically all eventual selected objects, when
   // returning to the neutral point of the Sketcher
   bool isClearSelectionPossible = true;
@@ -1421,8 +1497,6 @@ bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature,
 
   std::string aKind = theFeature->getKind();
   if (aConstrIds.contains(QString(aKind.c_str()))) {
-    bool isTypedConstraint = false;
-
     switch (theState) {
       case PartSet_Tools::Dimensional: {
         bool isDistance = isDistanceKind(aKind);
@@ -1558,17 +1632,19 @@ const QMap<PartSet_Tools::ConstraintVisibleState, bool>& PartSet_SketcherMgr::sh
 
 bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
 {
-  bool isFoundObject = false;
-
+  if (!myCurrentSketch.get())
+    return false;
   FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
   if (anObjectFeature.get()) {
     int aSize = myCurrentSketch->numberOfSubs();
-    for (int i = 0; i < aSize && !isFoundObject; i++) {
-      FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
-      isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
+    FeaturePtr aCurrentFeature;
+    for (int i = 0; i < aSize; i++) {
+      aCurrentFeature = myCurrentSketch->subFeature(i);
+      if (myCurrentSketch->subFeature(i) == anObjectFeature)
+        return true;
     }
   }
-  return isFoundObject;
+  return false;
 }
 
 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePlane)
@@ -1627,10 +1703,10 @@ bool PartSet_SketcherMgr::setDistanceValueByPreselection(ModuleBase_Operation* t
             anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
           }
           if (anAIS.get() != NULL) {
-            Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
+            anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
 
             if (!anAISIO.IsNull()) {
-              Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast(anAISIO);
+              Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast(anAISIO);
               if (!aDim.IsNull()) {
                 gp_Pnt aPosition = aDim->GetTextPosition();
 
@@ -1667,11 +1743,9 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
 
   FeatureToSelectionMap::const_iterator anIt = theSelection.find(theFeature);
   SelectionInfo anInfo = anIt.value();
-  std::set<AttributePtr> aSelectedAttributes = anInfo.myAttributes;
+  std::map<AttributePtr, int> aSelectedAttributes = anInfo.myAttributes;
   std::set<ResultPtr> aSelectedResults = anInfo.myResults;
 
-  ModuleBase_IViewer* aViewer = theWorkshop->viewer();
-
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
@@ -1703,10 +1777,10 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
   }
   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
     ResultPtr aResult = *aIt;
-    AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
-    if (aAISObj.get() == NULL)
+    AISObjectPtr aResAISObj = aDisplayer->getAISObject(aResult);
+    if (aResAISObj.get() == NULL)
       continue;
-    Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+    Handle(AIS_InteractiveObject) anAISIO = aResAISObj->impl<Handle(AIS_InteractiveObject)>();
 
     SelectMgr_IndexedMapOfOwner aSelectedOwners;
     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
@@ -1719,10 +1793,10 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
       const TopoDS_Shape& aShape = anOwner->Shape();
       TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
       if (aShapeType == TopAbs_VERTEX) {
-        AttributePtr aPntAttr =
+        std::pair<AttributePtr, int> aPntAttrIndex =
           PartSet_Tools::findAttributeBy2dPoint(theFeature, aShape, theSketch);
-        if (aPntAttr.get() != NULL &&
-            aSelectedAttributes.find(aPntAttr) != aSelectedAttributes.end())
+        if (aPntAttrIndex.first.get() != NULL &&
+            aSelectedAttributes.find(aPntAttrIndex.first) != aSelectedAttributes.end())
           theOwnersToSelect.Add(anOwner);
         else if (isSameShape && anInfo.myLocalSelectedShapes.Contains(aShape)) {
           theOwnersToSelect.Add(anOwner);
@@ -1742,13 +1816,13 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
       // result owners are put in the list of selection only if local selected shapes were not
       // found
       if (aSelectedResults.find(aResult) != aSelectedResults.end()) {
-        for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
+        for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
           Handle(StdSelect_BRepOwner) anOwner =
-            Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
-          if ( anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner))
+              Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
+          if (anOwner.IsNull() || !anOwner->HasShape() || theOwnersToSelect.FindIndex(anOwner))
             continue;
-            // select whole result
-            theOwnersToSelect.Add(anOwner);
+          // select whole result
+          theOwnersToSelect.Add(anOwner);
         }
       }
     }
@@ -1782,8 +1856,8 @@ void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                            (getCurrentOperation());
   if (aFOperation) {
-    if (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
-        isNestedSketchOperation(aFOperation) &&
+    if ((PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
+         isNestedSketchOperation(aFOperation)) &&
         thePreviousState == ModuleBase_ModelWidget::ModifiedInPP) {
       FeaturePtr aFeature = aFOperation->feature();
       visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
@@ -1842,9 +1916,6 @@ void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature,
   if (isEditOperation || !theFeature.get())
     return;
 
-  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
-
   // 1. change visibility of the object itself, here the presentable object is processed,
   // e.g. constraints features
   //FeaturePtr aFeature = aFOperation->feature();
@@ -1931,8 +2002,8 @@ void PartSet_SketcherMgr::storeSelection(const SelectionType theType,
       std::list<ResultPtr> aResults = aFeature->results();
       std::list<ResultPtr>::const_iterator aIt;
       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
-        ResultPtr aResult = *aIt;
-        getAttributesOrResults(anOwner, aFeature, aSketch, aResult,
+        ResultPtr aCurResult = *aIt;
+        getAttributesOrResults(anOwner, aFeature, aSketch, aCurResult,
           anInfo.myAttributes, anInfo.myResults, anInfo.myLocalSelectedShapes);
       }
     }
@@ -1983,8 +2054,6 @@ void PartSet_SketcherMgr::updateBySketchParameters(
     case PartSet_Tools::Geometrical:
     case PartSet_Tools::Dimensional: {
       if (aPrevState != theState) {
-        ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
-        XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
         int aNumberOfSubs = myCurrentSketch->numberOfSubs();
         for (int i = 0; i < aNumberOfSubs; i++) {
           FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
@@ -2001,11 +2070,16 @@ void PartSet_SketcherMgr::updateBySketchParameters(
       if (aPrevState != theState) {
         /// call all sketch features redisplay, the expression state will be corrected in customize
         /// of distance presentation
+        SketcherPrs_Tools::ParameterStyle aStyle = myIsConstraintsShown[PartSet_Tools::Expressions]
+          ? SketcherPrs_Tools::ParameterText : SketcherPrs_Tools::ParameterValue;
+        SketcherPrs_Tools::setParameterStyle(aStyle);
         Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
         PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);
       }
     }
     break;
+    default: // [to avoid compilation warning]
+      break;
   }
 }
 
@@ -2142,9 +2216,9 @@ void PartSet_SketcherMgr::processEvent(const std::shared_ptr<Events_Message>& th
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*aIt);
       if (aFeature.get()) {
         std::list<ResultPtr> aRes = aFeature->results();
-        std::list<ResultPtr>::const_iterator aIt;
-        for (aIt = aRes.cbegin(); aIt != aRes.cend(); ++aIt) {
-          ModuleBase_ViewerPrsPtr aPrsPtr(new ModuleBase_ViewerPrs(*aIt));
+        std::list<ResultPtr>::const_iterator aRIt;
+        for (aRIt = aRes.cbegin(); aRIt != aRes.cend(); ++aRIt) {
+          ModuleBase_ViewerPrsPtr aPrsPtr(new ModuleBase_ViewerPrs(*aRIt));
           aPrsList.append(aPrsPtr);
         }
       }
@@ -2180,7 +2254,7 @@ bool isIncludeToResult(const ObjectPtr& theObject)
   for (aIt = aRefsToMe.cbegin(); aIt != aRefsToMe.cend(); ++aIt) {
     if ((*aIt)->id() == SketchPlugin_Projection::PROJECTED_FEATURE_ID()) {
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
-      if (aFeature.get()) {
+      if (aFeature.get() && !aFeature->isMacro()) {
         anAttr = aFeature->data()->boolean(SketchPlugin_Projection::INCLUDE_INTO_RESULT());
         if (anAttr.get())
           return anAttr->value();
@@ -2194,26 +2268,27 @@ bool isIncludeToResult(const ObjectPtr& theObject)
 std::vector<int> PartSet_SketcherMgr::colorOfObject(const ObjectPtr& theObject,
   const FeaturePtr& theFeature, bool isConstruction) const
 {
-  static const QStringList& aConstrIds = constraintsIdList();
   PartSet_OverconstraintListener* aOCListener = myModule->overconstraintListener();
   std::string aKind = theFeature->getKind();
 
+  if (aOCListener->isConflictingObject(theObject)) {
+    return Config_PropManager::color("Visualization", "sketch_overconstraint_color");
+  }
   if (isDistanceKind(aKind)) {
-    if (aOCListener->isConflictingObject(theObject))
-      return Config_PropManager::color("Visualization", "sketch_overconstraint_color");
     return Config_PropManager::color("Visualization", "sketch_dimension_color");
   }
   if (isExternal(theFeature))
     return Config_PropManager::color("Visualization", "sketch_external_color");
-  if (isConstruction)
-    return Config_PropManager::color("Visualization", "sketch_auxiliary_color");
 
   if (aOCListener->isFullyConstrained()) {
     return Config_PropManager::color("Visualization", "sketch_fully_constrained_color");
   }
-  else if (aOCListener->isConflictingObject(theObject)) {
-    return Config_PropManager::color("Visualization", "sketch_overconstraint_color");
-  }
+  if (aKind == SketchPlugin_ConstraintCoincidence::ID())
+    return std::vector<int>(3, 0);
+
+  if (isConstruction)
+    return Config_PropManager::color("Visualization", "sketch_auxiliary_color");
+
   return Config_PropManager::color("Visualization", "sketch_entity_color");
 }
 
@@ -2249,8 +2324,9 @@ void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject
   if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/)
     return;
 
+  int aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
   if (isExternal(aFeature)) {
-    thePrs->setWidth(1);
+    thePrs->setWidth(isIncludeToResult(aFeature)? aWidth : 1);
     return;
   }
   std::string aKind = aFeature->getKind();
@@ -2264,7 +2340,6 @@ void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject
       thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
     }
     else {
-      int aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
       thePrs->setWidth(aWidth);
       thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
     }
@@ -2275,9 +2350,9 @@ void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject
     thePrs->setWidth(17);
     //  thePrs->setPointMarker(1, 1.); // Set point as a '+' symbol
   }
-  if (isCopy(aFeature) && !isIncludeToResult(aFeature)) {
-    double aWidth = thePrs->width();
-    thePrs->setWidth(aWidth / 2.5);
+  if (isCopy(aFeature) || !isIncludeToResult(aFeature)) {
+    double aPrsWidth = thePrs->width();
+    thePrs->setWidth(aPrsWidth / 2.5);
   }
 
   double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
@@ -2314,10 +2389,10 @@ void PartSet_Fitter::fitAll(Handle(V3d_View) theView)
       for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
         aRes = (*aIt);
         if (aRes->isDisplayed()) {
-          FeaturePtr aFeature = ModelAPI_Feature::feature(aRes);
-          if (aFeature.get()) {
+          FeaturePtr aCurFeature = ModelAPI_Feature::feature(aRes);
+          if (aCurFeature.get()) {
             std::shared_ptr<SketchPlugin_Feature> aSPFeature =
-              std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+                std::dynamic_pointer_cast<SketchPlugin_Feature>(aCurFeature);
             if (aSPFeature.get()) {
               bool isAxiliary =
                 aSPFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value();