Salome HOME
Issue #3092: Do not relaunch editing on multi-selection if editing feature is still...
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
index f76e254c6b761baa74904b6bec71dfeaa33047e4..bd4c35fae988df2c1cceee69b11d42889015f27b 100644 (file)
@@ -70,6 +70,8 @@
 #include <SketchPlugin_Point.h>
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
 #include <SketchPlugin_ConstraintLength.h>
 #include <SketchPlugin_ConstraintDistance.h>
 #include <SketchPlugin_ConstraintParallel.h>
 #include <QMessageBox>
 #include <QMainWindow>
 
+#include <set>
+
 //#define DEBUG_DO_NOT_BY_ENTER
 //#define DEBUG_SKETCHER_ENTITIES
 //#define DEBUG_SKETCH_ENTITIES_ON_MOVE
@@ -168,7 +172,8 @@ 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)
+    myIsPopupMenuActive(false), myExternalPointsMgr(0), myNoDragMoving(false),
+    myIsSketchStarted(false)
 {
   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
@@ -199,6 +204,8 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
 
   registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop));
   registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter());
+
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_DOF_OBJECTS));
 }
 
 PartSet_SketcherMgr::~PartSet_SketcherMgr()
@@ -218,15 +225,17 @@ void PartSet_SketcherMgr::onEnterViewPort()
   return;
   #endif
 
-  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
-    }
-  }
+  // 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));
+  //#ifdef DEBUG_CURSOR
+  //      qDebug("onEnterViewPort() : Qt::CrossCursor");
+  //#endif
+  //    }
+  //  }
 
   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
     return;
@@ -258,12 +267,12 @@ void PartSet_SketcherMgr::onLeaveViewPort()
   return;
   #endif
 
-  if (canChangeCursor(getCurrentOperation())) {
-    QApplication::restoreOverrideCursor();
-#ifdef DEBUG_CURSOR
-    qDebug("onLeaveViewPort() : None");
-#endif
-  }
+//  if (canChangeCursor(getCurrentOperation())) {
+//    QApplication::restoreOverrideCursor();
+//#ifdef DEBUG_CURSOR
+//    qDebug("onLeaveViewPort() : None");
+//#endif
+//  }
 
   if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
     return;
@@ -353,15 +362,23 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
-  if (!aViewer->canDragByMouse())
-    return;
+  //if (!aViewer->canDragByMouse())
+  //  return;
 
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                (getCurrentOperation());
   if (!aFOperation)
     return;
 
-  if (aFOperation->isEditOperation()) {
+  bool isEditing = aFOperation->isEditOperation();
+  bool aCanDrag = aViewer->canDragByMouse();
+
+  //if (!aViewer->canDragByMouse() && isEditing) {
+  //  // Do not edit by dragging
+  //  return;
+  //}
+
+  if (isEditing) {
     // If the current widget is a selector, do nothing, it processes the mouse press
     ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
     if(anActiveWidget && anActiveWidget->isViewerSelector()) {
@@ -381,16 +398,10 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
     if ((!isSketchOpe) && (!isSketcher))
       return;
 
-    bool isEditing = aFOperation->isEditOperation();
-
     // Ignore creation sketch operation
     if ((!isSketcher) && (!isEditing))
       return;
 
-    Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
-    // Remember highlighted objects for editing
-    ModuleBase_ISelection* aSelect = aWorkshop->selection();
-
     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
     storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection);
 
@@ -403,12 +414,12 @@ 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) {
-      myIsDragging = true;
-      myDragDone = false;
-
+      if (aCanDrag) {
+        myIsDragging = true;
+        myDragDone = false;
+      }
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
       launchEditing();
       if (aFeature.get() != NULL) {
@@ -432,13 +443,33 @@ 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();
 
-      myIsDragging = true;
-      myDragDone = false;
+      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
+        isRelaunchEditing = !myCurrentSelection.contains(aSPFeature);
 
+      if (isRelaunchEditing)
+        aFOperation->commit();
+
+      if (aCanDrag) {
+        myIsDragging = true;
+        myDragDone = false;
+      }
       myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
-      launchEditing();
+      if (isRelaunchEditing)
+        launchEditing();
       myIsEditLaunching = aPrevLaunchingState;
       if (aFeature.get() != NULL) {
         std::shared_ptr<SketchPlugin_Feature> aSPFeature =
@@ -460,33 +491,50 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+  ModuleBase_IViewer* aViewer = aWorkshop->viewer();
   if (myIsDragging)
-    aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
+    aViewer->enableDrawMode(myPreviousDrawModeEnabled);
 
   bool aWasDragging = myIsDragging;
   myIsDragging = false;
 
-  if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
+  if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) {
     return;
-
+  }
   // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
-  if (!myIsMouseOverViewProcessed)
-    return;
-
-  ModuleBase_IViewer* aViewer = aWorkshop->viewer();
-  if (!aViewer->canDragByMouse())
+  if (!myIsMouseOverViewProcessed) {
     return;
-  ModuleBase_Operation* aOp = getCurrentOperation();
+  }
+  //if (!aViewer->canDragByMouse())
+  //  return;
+  ModuleBase_OperationFeature* aOp =
+    dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
   if (aOp) {
-    if (isNestedSketchOperation(aOp)) {
-      // Only for sketcher operations
-      if (aWasDragging) {
-        if (myDragDone) {
-          /// the previous selection is lost by mouse release in the viewer(Select method), but
-          /// it is still stored in myCurrentSelection. So, it is possible to restore selection
-          /// It is important for drag(edit with mouse) of sketch entities.
-          restoreSelection(myCurrentSelection);
-          myCurrentSelection.clear();
+    bool aStartNoDragOperation = !aViewer->canDragByMouse() && aOp->isEditOperation();
+    if (aStartNoDragOperation || myNoDragMoving) {
+      // Process edit operation without dragging
+      if (myCurrentSelection.size() > 0)
+        myNoDragMoving = !myNoDragMoving;
+      else
+        myNoDragMoving = false;
+      if (myNoDragMoving)
+        return;
+      else {
+        restoreSelection(myCurrentSelection);
+        myCurrentSelection.clear();
+      }
+    }
+    else {
+      if (isNestedSketchOperation(aOp)) {
+        // Only for sketcher operations
+        if (aWasDragging) {
+          if (myDragDone) {
+            /// the previous selection is lost by mouse release in the viewer(Select method), but
+            /// it is still stored in myCurrentSelection. So, it is possible to restore selection
+            /// It is important for drag(edit with mouse) of sketch entities.
+            restoreSelection(myCurrentSelection);
+            myCurrentSelection.clear();
+          }
         }
       }
     }
@@ -514,10 +562,13 @@ 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;
 
+  ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
   if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {
 #ifdef DRAGGING_DEBUG
     QTime t;
@@ -536,44 +587,46 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
       // the feature is to be erased here, but it is correct to call canDisplayObject because
       // there can be additional check (e.g. editor widget in distance constraint)
       ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                 (getCurrentOperation());
+        (getCurrentOperation());
       if (aFOperation) {
         FeaturePtr aFeature = aFOperation->feature();
         visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
       }
     }
+    aDisplayer->updateViewer();
 #ifdef DRAGGING_DEBUG
     cout << "Mouse move processing " << t.elapsed() << endl;
 #endif
   }
   //myClickedPoint.clear();
 
-  if (myIsDragging) {
+  if (myIsDragging || myNoDragMoving) {
     // 1. the current selection is saved in the mouse press method in order to restore it after
     //    moving
     // 2. the enable selection in the viewer should be temporary switched off in order to ignore
     // 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.
-
     ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
     if (!aCurrentOperation)
       return;
     if (isSketchOperation(aCurrentOperation))
       return; // No edit operation activated
 
+#ifdef DRAGGING_DEBUG
+    QTime t;
+    t.start();
+#endif
+
     Handle(V3d_View) aView = theWnd->v3dView();
     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
     Point aMousePnt;
     get2dPoint(theWnd, theEvent, aMousePnt);
 
     std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(
-                            new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
+      new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
     std::shared_ptr<GeomAPI_Pnt2d> aCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(
-                            new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
+      new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
 
-    ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
-    XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
-    XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
     // 3. the flag to disable the update viewer should be set in order to avoid blinking in the
     // viewer happens by deselect/select the modified objects. The flag should be restored after
     // the selection processing. The update viewer should be also called.
@@ -582,7 +635,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
     //static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
     FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
-                                          aLast = myCurrentSelection.end();
+      aLast = myCurrentSelection.end();
     // 4. the features and attributes modification(move)
     bool isModified = false;
     for (; anIt != aLast; anIt++) {
@@ -592,7 +645,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
       // Process selection by attribute: the priority to the attribute
       if (!anAttributes.empty()) {
         std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
-                                               anAttLast = anAttributes.end();
+          anAttLast = anAttributes.end();
         for (; anAttIt != anAttLast; anAttIt++) {
           AttributePtr anAttr = *anAttIt;
           if (anAttr.get() == NULL)
@@ -606,7 +659,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
               bool isImmutable = aPoint->setImmutable(true);
 
               std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
-                       <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+                <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
               aMessage->setMovedAttribute(aPoint);
               aMessage->setOriginalPosition(anOriginalPosition);
               aMessage->setCurrentPosition(aCurrentPosition);
@@ -617,13 +670,14 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
             }
           }
         }
-      } else {
+      }
+      else {
         // Process selection by feature
         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
         if (aSketchFeature) {
           std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
-                    <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+            <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
           aMessage->setMovedObject(aFeature);
           aMessage->setOriginalPosition(anOriginalPosition);
           aMessage->setCurrentPosition(aCurrentPosition);
@@ -646,6 +700,10 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve
     aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
     aDisplayer->updateViewer();
 
+#ifdef DRAGGING_DEBUG
+    cout << "Mouse move processing " << t.elapsed() << endl;
+#endif
+
     myDragDone = true;
     myCurrentPoint = aMousePnt;
   }
@@ -850,13 +908,15 @@ void PartSet_SketcherMgr::sketchSelectionModes(const CompositeFeaturePtr& theSke
   theModes.append(TopAbs_EDGE);
 }
 
-Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult)
+Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ObjectPtr& theObj)
 {
   Handle(AIS_InteractiveObject) aPrs;
 
-  FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
   if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) {
-    aPrs = new PartSet_ResultSketchPrs(theResult);
+    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
+    if (aResult.get())
+      aPrs = new PartSet_ResultSketchPrs(aResult);
   }
   return aPrs;
 }
@@ -926,7 +986,11 @@ bool PartSet_SketcherMgr::isEntity(const std::string& theId)
   return (theId == SketchPlugin_Line::ID()) ||
          (theId == SketchPlugin_Point::ID()) ||
          (theId == SketchPlugin_Arc::ID()) ||
-         (theId == SketchPlugin_Circle::ID());
+         (theId == SketchPlugin_Circle::ID()) ||
+         (theId == SketchPlugin_Ellipse::ID()) ||
+         (theId == SketchPlugin_Projection::ID()) ||
+         (theId == SketchPlugin_IntersectionPoint::ID()) ||
+         (theId == SketchPlugin_EllipticArc::ID());
 }
 
 bool PartSet_SketcherMgr::isExternalFeature(const FeaturePtr& theFeature)
@@ -956,11 +1020,17 @@ bool PartSet_SketcherMgr::isDistanceKind(std::string& theKind)
 
 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
 {
+  static Events_ID EVENT_ATTR = Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES);
+  static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                (getCurrentOperation());
   if (!aFOperation)
     return;
 
+  myIsSketchStarted = true;
+  SketcherPrs_Tools::setPixelRatio(ModuleBase_Tools::currentPixelRatio());
+
   myModule->onViewTransformed();
 
   // Display all sketcher sub-Objects
@@ -1026,7 +1096,6 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   myModule->overconstraintListener()->setActive(true);
   // Display sketcher objects
   QStringList anInfo;
-  Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
   aNumberOfSubs = myCurrentSketch->numberOfSubs();
   for (int i = 0; i < aNumberOfSubs; i++) {
@@ -1047,6 +1116,7 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
       aECreator->sendUpdated(aFeature, EVENT_DISP);
     else
       aFeature->setDisplayed(true);
+    aECreator->sendUpdated(aFeature, EVENT_ATTR);
   }
 #ifdef DEBUG_SKETCHER_ENTITIES
   QString anInfoStr = anInfo.join(";\t");
@@ -1063,15 +1133,26 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   workshop()->selectionActivate()->updateSelectionFilters();
   workshop()->selectionActivate()->updateSelectionModes();
 
-  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  Events_Loop::loop()->flush(EVENT_DISP);
+  Events_Loop::loop()->flush(EVENT_ATTR);
 
   myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
 
   workshop()->viewer()->set2dMode(true);
+
+  PartSet_Fitter* aFitter = new PartSet_Fitter(this);
+  myModule->workshop()->viewer()->setFitter(aFitter);
 }
 
 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
 {
+  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
+  PartSet_Fitter* aFitter = (PartSet_Fitter*)myModule->workshop()->viewer()->fitter();
+  myModule->workshop()->viewer()->setFitter(0);
+  delete aFitter;
+
+  myIsSketchStarted = false;
+
   myIsMouseOverWindow = false;
   myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
   myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
@@ -1083,8 +1164,6 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   }
   onShowPoints(false);
 
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-
   DataPtr aData = myCurrentSketch->data();
   if (!aData->isValid()) {
     XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
@@ -1141,18 +1220,18 @@ 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));
-#ifdef DEBUG_CURSOR
-      qDebug("startNestedSketch() : Qt::CrossCursor");
-#endif
-    }
-  }
-}
+//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));
+//#ifdef DEBUG_CURSOR
+//      qDebug("startNestedSketch() : Qt::CrossCursor");
+//#endif
+//    }
+//  }
+//}
 
 void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
 {
@@ -1160,7 +1239,7 @@ void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
   operationMgr()->onValidateOperation();
   // when sketch nested operation is stopped the cursor should be restored unconditionally
   //if (canChangeCursor(theOperation)) {
-    QApplication::restoreOverrideCursor();
+    //QApplication::restoreOverrideCursor();
 #ifdef DEBUG_CURSOR
     qDebug("stopNestedSketch() : None");
 #endif
@@ -1732,26 +1811,26 @@ 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) ||
-                      isNestedSketchOperation(aFOperation)))
-    SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
-
-  // update entities selection priorities
-  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
-  if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
-    // update priority for feature
-    updateSelectionPriority(aFeature, aFeature);
-    // update priority for results of the feature
-    std::list<ResultPtr> aResults = aFeature->results();
-    std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();
-    for (; anIt != aLastIt; anIt++)
-      updateSelectionPriority(*anIt, aFeature);
-  }
-}
+//void PartSet_SketcherMgr::customisePresentation(const ObjectPtr& theObject)
+//{
+//  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+//                                                                           (getCurrentOperation());
+//  if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
+//                      isNestedSketchOperation(aFOperation)))
+//    SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
+//
+//  // update entities selection priorities
+//  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+//  if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
+//    // update priority for feature
+//    updateSelectionPriority(aFeature, aFeature);
+//    // update priority for results of the feature
+//    std::list<ResultPtr> aResults = aFeature->results();
+//    std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();
+//    for (; anIt != aLastIt; anIt++)
+//      updateSelectionPriority(*anIt, aFeature);
+//  }
+//}
 
 ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
 {
@@ -1907,6 +1986,7 @@ void PartSet_SketcherMgr::onShowConstraintsToggle(int theType, bool theState)
   PartSet_Tools::ConstraintVisibleState aType = (PartSet_Tools::ConstraintVisibleState)theType;
 
   updateBySketchParameters(aType, theState);
+  myModule->workshop()->viewer()->update();
 }
 
 void PartSet_SketcherMgr::updateBySketchParameters(
@@ -1941,6 +2021,8 @@ 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::
+          sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
         Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
         PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);
       }
@@ -2069,3 +2151,213 @@ void PartSet_SketcherMgr::onShowPoints(bool toShow)
   if (aToUpdate)
     aViewer->update();
 }
+
+void PartSet_SketcherMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOF_OBJECTS)) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+      std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    std::set<ObjectPtr> aObjects = anUpdateMsg->objects();
+    std::set<ObjectPtr>::const_iterator aIt;
+    QList<ModuleBase_ViewerPrsPtr> aPrsList;
+    for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
+      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));
+          aPrsList.append(aPrsPtr);
+        }
+      }
+    }
+    if (aPrsList.size() > 0) {
+      myModule->workshop()->setSelected(aPrsList);
+    }
+  }
+}
+
+bool isExternal(const ObjectPtr& theObject)
+{
+  AttributeSelectionPtr aAttr =
+    theObject->data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
+  if (aAttr)
+    return aAttr->context().get() != NULL && !aAttr->isInvalid();
+  return false;
+}
+
+bool isCopy(const ObjectPtr& theObject)
+{
+  AttributeBooleanPtr anAttr = theObject->data()->boolean(SketchPlugin_SketchEntity::COPY_ID());
+  if (anAttr.get())
+    return anAttr->value();
+  return false;
+}
+
+bool isIncludeToResult(const ObjectPtr& theObject)
+{
+  AttributeBooleanPtr anAttr;
+  std::set<AttributePtr> aRefsToMe = theObject->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aIt;
+  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()) {
+        anAttr = aFeature->data()->boolean(SketchPlugin_Projection::INCLUDE_INTO_RESULT());
+        if (anAttr.get())
+          return anAttr->value();
+      }
+    }
+  }
+  return true;
+}
+
+//**************************************************************************************
+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 (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");
+  }
+  return Config_PropManager::color("Visualization", "sketch_entity_color");
+}
+
+//**************************************************************************************
+void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject,
+  const AISObjectPtr& thePrs) const
+{
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+
+  // set color from preferences
+  std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
+    aFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
+  bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
+
+  std::vector<int> aColor = colorOfObject(theObject, aFeature, isConstruction);
+  if (!aColor.empty()) {
+    // The code below causes redisplay again
+    if (ModelAPI_Session::get()->isOperation()) {
+      AttributeIntArrayPtr aColorAttr = theObject->data()->intArray(ModelAPI_Result::COLOR_ID());
+      if (aColorAttr.get()) {
+        aColorAttr->setSize(3, false);
+        // Set the color attribute in order do not use default colors in the presentation object
+        for (int i = 0; i < 3; i++)
+          aColorAttr->setValue(i, aColor[i], false);
+      }
+    }
+    thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+  }
+
+  int aShapeType = thePrs->getShapeType();
+  // a compound is processed like the edge because the
+  // arc feature uses the compound for presentable AIS
+  if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/)
+    return;
+
+  if (isExternal(aFeature)) {
+    thePrs->setWidth(1);
+    return;
+  }
+  std::string aKind = aFeature->getKind();
+  if (isDistanceKind(aKind))
+    return;
+
+  if (aShapeType == 6 || aShapeType == 0) { // if this is an edge or a compound
+    if (isConstruction) {
+      // Set axilliary line
+      thePrs->setWidth(SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY());
+      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());
+    }
+  }
+  else if (aShapeType == 7) { // otherwise this is a vertex
+                              // The width value do not have effect on the point presentation.
+                              // It is defined in order to extend selection area of the object.
+    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);
+  }
+
+  double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+  thePrs->setDeflection(aDeflection);
+}
+
+//*************************************************************************************
+void PartSet_Fitter::fitAll(Handle(V3d_View) theView)
+{
+  CompositeFeaturePtr aSketch = mySketchMgr->activeSketch();
+
+  ModuleBase_IWorkshop* aWorkshop = mySketchMgr->module()->workshop();
+  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
+  Bnd_Box aBndBox;
+  int aNumberOfSubs = aSketch->numberOfSubs();
+  double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+  for (int i = 0; i < aNumberOfSubs; i++) {
+    FeaturePtr aFeature = aSketch->subFeature(i);
+    if (aDisplayer->isVisible(aFeature)) {
+      AISObjectPtr aAisPtr = aDisplayer->getAISObject(aFeature);
+      Handle(AIS_InteractiveObject) aAisObj = aAisPtr->impl<Handle(AIS_InteractiveObject)>();
+      if (!aAisObj->IsInfinite()) {
+        Bnd_Box aBox;
+        aAisObj->BoundingBox(aBox);
+        aBndBox.Add(aBox);
+      }
+    }
+    else {
+      std::list<ResultPtr> aResults = aFeature->results();
+      std::list<ResultPtr>::const_iterator aIt;
+      ResultPtr aRes;
+      for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+        aRes = (*aIt);
+        if (aRes->isDisplayed()) {
+          FeaturePtr aFeature = ModelAPI_Feature::feature(aRes);
+          if (aFeature.get()) {
+            std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+              std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+            if (aSPFeature.get()) {
+              bool isAxiliary =
+                aSPFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value();
+              if (!(aSPFeature->isExternal() || isAxiliary)) {
+                GeomShapePtr aShape = aRes->shape();
+                aShape->computeSize(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+                Bnd_Box aBox;
+                aBox.Update(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+                aBndBox.Add(aBox);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (aBndBox.IsVoid())
+    theView->FitAll();
+  else
+    theView->FitAll(aBndBox, 0.01);
+}