Salome HOME
Feature selector widget for recover feature.
[modules/shaper.git] / src / PartSet / PartSet_SketcherReetntrantMgr.cpp
index a243e762f79bfa0cdf73035d0c0639c60edfbf0a..95a68cf42f054cc7f186305f12054787aa28e29f 100755 (executable)
@@ -3,30 +3,45 @@
 #include "PartSet_SketcherReetntrantMgr.h"
 #include "PartSet_Module.h"
 #include "PartSet_SketcherMgr.h"
-#include "PartSet_WidgetPoint2D.h"
+#include "PartSet_WidgetPoint2d.h"
 
 #include "ModelAPI_Session.h"
+#include "ModelAPI_AttributeString.h"
+#include "ModelAPI_AttributeRefAttr.h"
+
+#include "GeomDataAPI_Point2D.h"
 
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_OperationFeature.h>
 #include <ModuleBase_ModelWidget.h>
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_WidgetSelector.h>
+#include <ModuleBase_PageWidget.h>
+#include <ModuleBase_PageBase.h>
+#include <ModuleBase_WidgetFactory.h>
+#include <ModuleBase_OperationDescription.h>
+#include "ModuleBase_ToolBox.h"
 
 #include <SketchPlugin_Feature.h>
 #include <SketchPlugin_Line.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
 
 #include <XGUI_Workshop.h>
 #include <XGUI_ModuleConnector.h>
 #include <XGUI_OperationMgr.h>
+#include <XGUI_PropertyPanel.h>
+#include <XGUI_ErrorMgr.h>
+
+#include <QToolButton>
 
 PartSet_SketcherReetntrantMgr::PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop)
 : QObject(theWorkshop),
   myWorkshop(theWorkshop),
+  myRestartingMode(RM_None),
+  myIsFlagsBlocked(false),
   myIsInternalEditOperation(false),
-  myLastOperationId(""),
-  myPreviousAttributeID(""),
-  myRestartingMode(RM_None)
+  myNoMoreWidgetsAttribute("")
 {
 }
 
@@ -34,137 +49,144 @@ PartSet_SketcherReetntrantMgr::~PartSet_SketcherReetntrantMgr()
 {
 }
 
-ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::activeWidget() const
+ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::internalActiveWidget() const
 {
   ModuleBase_ModelWidget* aWidget = 0;
   if (!isActiveMgr())
     return aWidget;
 
-  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
-  if (aOperation) {
-    ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
-    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-    if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector())) {
-      // finds the first widget which can accept a value
-      QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
-      ModuleBase_ModelWidget* aFirstWidget = 0;
-      ModuleBase_ModelWidget* aWgt;
-      QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
-      for (aWIt = aWidgets.begin(); aWIt != aWidgets.end() && !aFirstWidget; ++aWIt) {
-        aWgt = (*aWIt);
-        if (aWgt->canSetValue())
-          aFirstWidget = aWgt;
-      }
-      if (aFirstWidget)
-        aWidget = aFirstWidget;
+  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+  if (anOperation) {
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
+    if (aPanel) { // check for case when the operation is started but property panel is not filled
+      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+      if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
+        aWidget = myInternalActiveWidget;
     }
   }
   return aWidget;
 }
 
-bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation)
+bool PartSet_SketcherReetntrantMgr::isInternalEditActive() const
 {
-  bool aProcessed = false;
-  if (!isActiveMgr())
-    return aProcessed;
-
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
-  if (!aFOperation)
-    return aProcessed;
+  return myIsInternalEditOperation;
+}
 
-  FeaturePtr aFeature = aFOperation->feature();
-  std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
-            std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-  if (aSPFeature && (myRestartingMode == RM_LastFeatureUsed ||
-                     myRestartingMode == RM_EmptyFeatureUsed)) {
-    myLastOperationId = aFOperation->id().toStdString();
-    myLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr();
-    PartSet_Module* aModule = module();
-    if (!aModule->sketchMgr()->sketchSolverError()) {
-      if (!aFOperation->isEditOperation()) {
-        FeaturePtr anOperationFeature = aFOperation->feature();
-        if (anOperationFeature.get() != NULL) {
-          aModule->editFeature(anOperationFeature);
-          aProcessed = true;
-
-          myIsInternalEditOperation = true;
-          // activate selection filters of the first widget in the viewer
-          onInternalActivateFirstWidgetSelection();
-
-          // activate the last active widget in the Property Panel
-          if (!myPreviousAttributeID.empty()) {
-            ModuleBase_Operation* anEditOperation = aModule->currentOperation();
-            if (anEditOperation) {
-              ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
-              ModuleBase_ModelWidget* aPreviousAttributeWidget = 0;
-              QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
-              for (int i = 0, aNb = aWidgets.size(); i < aNb && !aPreviousAttributeWidget; i++) {
-                if (aWidgets[i]->attributeID() == myPreviousAttributeID)
-                  aPreviousAttributeWidget = aWidgets[i];
-              }
-              // If the current widget is a selector, do nothing, it processes the mouse press
-              if (aPreviousAttributeWidget && !aPreviousAttributeWidget->isViewerSelector())
-                aPreviousAttributeWidget->focusTo();
-            }
-          }
-        }
-      }
-      else {
-        // the flag should be reset before start to do not react to the widget deactivate
+void PartSet_SketcherReetntrantMgr::updateInternalEditActiveState()
+{
+  if  (myIsInternalEditOperation) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                         (myWorkshop->currentOperation());
+    if (aFOperation) {
+      FeaturePtr aFeature = aFOperation->feature();
+      QString anError = myWorkshop->module()->getFeatureError(aFeature);
+      // stop started internal edit operation as soon as the operation becomes invalid
+      // it is especially important for the sketch tangent arc feature
+      if (!anError.isEmpty()) {
+        aFOperation->setEditOperation(false);
+        //workshop()->operationMgr()->updateApplyOfOperations();
+        beforeStopInternalEdit();
         myIsInternalEditOperation = false;
-        aModule->launchOperation(myLastOperationId.c_str());
-        breakOperationSequence();
-        aProcessed = true;
+        updateAcceptAllAction();
       }
     }
   }
+}
 
-  if (!aProcessed)
-    breakOperationSequence();
+bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation)
+{
+  bool aProcessed = false;
+  if (!isActiveMgr())
+    return aProcessed;
+
+  aProcessed = myIsInternalEditOperation;
+  resetFlags();
 
   return aProcessed;
 }
 
-void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOperation)
+void PartSet_SketcherReetntrantMgr::operationStarted(ModuleBase_Operation* theOperation)
 {
   if (!isActiveMgr())
     return;
 
-  if (myIsInternalEditOperation) {
-    // abort the created feature, which is currently edited
-    SessionPtr aMgr = ModelAPI_Session::get();
-    if (aMgr->hasModuleDocument() && aMgr->canUndo()) {
-      aMgr->undo();
-    }
+  if (myPreviousFeature.get() && myRestartingMode == RM_LastFeatureUsed) {
+    ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+                                                                myWorkshop->currentOperation());
+    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+    copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
   }
-  myIsInternalEditOperation = false;
-  breakOperationSequence();
+  resetFlags();
 }
 
-bool PartSet_SketcherReetntrantMgr::processMouseMoved()
+void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOperation)
+{
+  if (!isActiveMgr())
+    return;
+
+  resetFlags();
+}
+
+bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* theWnd,
+                                                      QMouseEvent* theEvent)
 {
   bool aProcessed = false;
   if (!isActiveMgr())
     return aProcessed;
 
   if  (myIsInternalEditOperation) {
-    PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
-    if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) {
-    ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-      //if (operationMgr()->isApplyEnabled())
-      anOperation->commit();
-      aProcessed = true;
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                         (myWorkshop->currentOperation());
+    FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature()
+                                                                     : FeaturePtr();
+    if (aLastFeature) {
+      ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
+      ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
+
+      FeaturePtr aCurrentFeature = aFOperation->feature();
+      bool isLineFeature = false, isArcFeature = false;
+      std::string anAttributeOnStart;
+      if (aCurrentFeature->getKind() == SketchPlugin_Line::ID()) {
+        anAttributeOnStart = SketchPlugin_Line::START_ID();
+        isLineFeature = anActiveWidget->attributeID() == anAttributeOnStart;
+      }
+      else if (isTangentArc(aFOperation, module()->sketchMgr()->activeSketch())) {
+        anAttributeOnStart = SketchPlugin_Arc::TANGENT_POINT_ID();
+        isArcFeature = anActiveWidget->attributeID() == anAttributeOnStart;
+      }
+      bool aCanBeActivatedByMove = isLineFeature || isArcFeature;
+      if (aCanBeActivatedByMove) {
+        myPreviousFeature = aFOperation->feature();
+        restartOperation();
+        myPreviousFeature = FeaturePtr();
+
+        anActiveWidget = module()->activeWidget();
+        aCurrentFeature = anActiveWidget->feature();
+        aProcessed = true;
+        if (anActiveWidget->attributeID() == anAttributeOnStart) {
+          // it was not deactivated by preselection processing
+          aPanel->activateNextWidget(anActiveWidget);
+        }
+      } else {
+        // processing mouse move in active widget of restarted operation
+        ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
+        PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+        if (aProcessor)
+          aProcessor->mouseMoved(theWnd, theEvent);
+      }
     }
   }
   return aProcessed;
 }
 
-bool PartSet_SketcherReetntrantMgr::processMousePressed()
+bool PartSet_SketcherReetntrantMgr::processMousePressed(ModuleBase_IViewWindow* /* theWnd*/,
+                                                        QMouseEvent* /* theEvent*/)
 {
   return isActiveMgr() && myIsInternalEditOperation;
 }
 
-bool PartSet_SketcherReetntrantMgr::processMouseReleased()
+bool PartSet_SketcherReetntrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWnd,
+                                                         QMouseEvent* theEvent)
 {
   bool aProcessed = false;
   if (!isActiveMgr())
@@ -172,69 +194,128 @@ bool PartSet_SketcherReetntrantMgr::processMouseReleased()
 
   if (myIsInternalEditOperation) {
     ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-    //if (operationMgr()->isApplyEnabled())
-    anOperation->commit();
-    aProcessed = true;
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
+
+    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+    if (!anActiveWidget || !anActiveWidget->isViewerSelector()) {
+
+      // block of viewer update
+      // we need to block update content of the viewer because of Sketch Point feature
+      // in activate() the value of the point is initialized and it can be displayed
+      // but the default value is [0, 0]. So, we block update viewer contentent until
+      // onMouseRelease happens, which correct the point position
+      ModuleBase_Tools::blockUpdateViewer(true);
+
+      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                           (myWorkshop->currentOperation());
+      myPreviousFeature = aFOperation->feature();
+      restartOperation();
+      myPreviousFeature = FeaturePtr();
+      aProcessed = true;
+
+      // fill the first widget by the mouse event point
+      // if the active widget is not the first, it means that the restarted operation is filled by
+      // the current preselection.
+      PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
+      ModuleBase_ModelWidget* aFirstWidget = aPanel->findFirstAcceptingValueWidget();
+      if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) {
+        aPoint2DWdg->mouseReleased(theWnd, theEvent);
+      }
+      // unblock viewer update
+      ModuleBase_Tools::blockUpdateViewer(false);
+    }
   }
+
   return aProcessed;
 }
 
-void PartSet_SketcherReetntrantMgr::propertyPanelDefined(ModuleBase_Operation* theOperation)
+void PartSet_SketcherReetntrantMgr::onWidgetActivated()
 {
   if (!isActiveMgr())
     return;
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
-  if (!aFOperation)
+  if (!myIsInternalEditOperation)
     return;
 
-  ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
-  if (PartSet_SketcherMgr::isSketchOperation(aFOperation) &&  (aFOperation->isEditOperation())) {
-    // we have to manually activate the sketch label in edit mode
-    aPanel->activateWidget(aPanel->modelWidgets().first());
-  }
-  else if ((aFOperation->id() == myLastOperationId.c_str()) && myLastFeature) {
-    // Restart last operation type 
-    ModuleBase_ModelWidget* aWgt = aPanel->activeWidget();
-    PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
-    if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) {
-      QList<ModuleBase_ViewerPrs> aSelection;
-      aSelection.append(ModuleBase_ViewerPrs(myLastFeature, TopoDS_Shape(), NULL));
-      if (aPoint2DWdg->setSelection(aSelection, true))
-        aPanel->activateNextWidget(aPoint2DWdg);
-    }
+  PartSet_Module* aModule = module();
+  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
+  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
+  if (aFirstWidget != aPanel->activeWidget()) {
+    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
+    if (aWSelector)
+      aWSelector->activateSelectionAndFilters(true);
   }
 }
 
-void PartSet_SketcherReetntrantMgr::noMoreWidgets(const std::string& thePreviousAttributeID)
+void PartSet_SketcherReetntrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID)
 {
   if (!isActiveMgr())
     return;
 
-  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-  if (anOperation) {
-    if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
+  // we should avoid processing of the signal about no more widgets attributes and 
+  // do this after the restart operaion is finished if it was called
+  // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
+  // if it should be called after restart
+  if (myIsFlagsBlocked) {
+    myNoMoreWidgetsAttribute = thePreviousAttributeID;
+    return;
+  }
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
+    return;
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    bool isStarted = false;
+    if (!module()->sketchMgr()->sketchSolverError()) {
       if (myRestartingMode != RM_Forbided) {
         myRestartingMode = RM_LastFeatureUsed;
-        myPreviousAttributeID = thePreviousAttributeID;
+        isStarted = startInternalEdit(thePreviousAttributeID);
       }
-      XGUI_Workshop* aWorkshop = workshop();
-      XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
-      // do nothing if the feature can not be applyed
-      if (anOpMgr->isApplyEnabled())
-        anOperation->commit();
     }
+    if (!isStarted)
+      aFOperation->commit();
   }
 }
 
-void PartSet_SketcherReetntrantMgr::vertexSelected()
+bool PartSet_SketcherReetntrantMgr::processEnter(const std::string& thePreviousAttributeID)
+{
+  bool isDone = false;
+
+  if (!isActiveMgr())
+    return isDone;
+
+  // empty previous attribute means that the Apply/Ok button has focus and the enter
+  // should not lead to start edition mode of the previous operation
+  if (thePreviousAttributeID.empty())
+    return isDone;
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
+    return isDone;
+
+  bool isSketchSolverError = module()->sketchMgr()->sketchSolverError();
+
+  if (!isSketchSolverError) {
+    myRestartingMode = RM_EmptyFeatureUsed;
+    isDone = startInternalEdit(thePreviousAttributeID);
+  }
+
+  return isDone;
+}
+
+void PartSet_SketcherReetntrantMgr::onVertexSelected()
 {
   if (!isActiveMgr())
     return;
 
-  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
-  if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
+  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+  std::string anOperationId = anOperation->id().toStdString();
+  if (anOperationId == SketchPlugin_Line::ID() ||
+      isTangentArc(anOperation, module()->sketchMgr()->activeSketch())) {
     /// If last line finished on vertex the lines creation sequence has to be break
-    ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
     ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
     const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
     QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
@@ -251,15 +332,12 @@ void PartSet_SketcherReetntrantMgr::vertexSelected()
   }
 }
 
-void PartSet_SketcherReetntrantMgr::enterReleased()
+void PartSet_SketcherReetntrantMgr::onBeforeStopped()
 {
-  if (!isActiveMgr())
+  if (!isActiveMgr() || !myIsInternalEditOperation)
     return;
 
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                      (myWorkshop->currentOperation());
-  if (/*!aFOperation->isEditOperation() || */myIsInternalEditOperation)
-    myRestartingMode = RM_EmptyFeatureUsed;
+  beforeStopInternalEdit();
 }
 
 bool PartSet_SketcherReetntrantMgr::canBeCommittedByPreselection()
@@ -267,37 +345,291 @@ bool PartSet_SketcherReetntrantMgr::canBeCommittedByPreselection()
   return !isActiveMgr() || myRestartingMode == RM_None;
 }
 
-void PartSet_SketcherReetntrantMgr::onInternalActivateFirstWidgetSelection()
+bool PartSet_SketcherReetntrantMgr::isInternalEditStarted() const
 {
-  if (!isActiveMgr())
-    return;
+  return myIsInternalEditOperation;
+}
 
-  if (!myIsInternalEditOperation)
-    return;
+bool PartSet_SketcherReetntrantMgr::isActiveMgr() const
+{
+  ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
 
-  PartSet_Module* aModule = module();
-  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
-  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
-  if (aFirstWidget != aPanel->activeWidget()) {
-    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
+  bool anActive = PartSet_SketcherMgr::isSketchOperation(aCurrentOperation);
+  if (!anActive) {
+    anActive = module()->sketchMgr()->isNestedSketchOperation(aCurrentOperation);
+    if (anActive) { // the manager is not active when the current operation is a usual Edit
+      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+      if (aFOperation->isEditOperation())
+        anActive = myIsInternalEditOperation;
+    }
+  }
+  return anActive;
+}
+
+bool PartSet_SketcherReetntrantMgr::startInternalEdit(const std::string& thePreviousAttributeID)
+{
+  bool isDone = false;
+  /// this is workaround for ModuleBase_WidgetEditor, used in SALOME mode. Sometimes key enter
+  /// event comes two times, so we should not start another internal edit operation
+  /// the Apply button becomes disabled becase the second additional internal feature is created
+  if (myIsInternalEditOperation)
+    return true;
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                     (myWorkshop->currentOperation());
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    aFOperation->setEditOperation(true/*, false*/);
+    createInternalFeature();
+
+    myIsInternalEditOperation = true;
+    updateAcceptAllAction();
+
+    isDone = true;
+    connect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
+    connect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
+
+    // activate selection filters of the first widget in the viewer
+    onWidgetActivated();
+
+    // activate the last active widget in the Property Panel
+    if (!thePreviousAttributeID.empty()) {
+      ModuleBase_Operation* anEditOperation = module()->currentOperation();
+      if (anEditOperation) {
+        ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
+        ModuleBase_ModelWidget* aPreviousAttributeWidget = 0;
+        QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
+        for (int i = 0, aNb = aWidgets.size(); i < aNb && !aPreviousAttributeWidget; i++) {
+          if (aWidgets[i]->attributeID() == thePreviousAttributeID) {
+          /// workaround for the same attributes used in different stacked widgets(attribute types)
+          if (ModuleBase_ToolBox::isOffToolBoxParent(aWidgets[i]))
+            continue;
+            aPreviousAttributeWidget = aWidgets[i];
+          }
+        }
+        // If the current widget is a selector, do nothing, it processes the mouse press
+        if (aPreviousAttributeWidget) {
+          if (!aPreviousAttributeWidget->isViewerSelector()) {
+            aPreviousAttributeWidget->focusTo();
+            aPreviousAttributeWidget->selectContent();
+          }
+          else {
+            // in case of shape multi selector, the widget does not lose focus by filling
+            // like it is in shape selector. So, if enter is pressed, the multi shape selector
+            // control should be deactivated. The focus is moved to Apply button and there
+            // should not be active control visualized in property panel
+            if (aPreviousAttributeWidget == aPanel->activeWidget()) {
+              aPanel->activateWidget(NULL, false);
+            }
+            // if there is no the next widget to be automatically activated, the Ok button in property
+            // panel should accept the focus(example is parallel constraint on sketch lines)
+            QToolButton* anOkBtn = dynamic_cast<XGUI_PropertyPanel*>(aPanel)->findButton(PROP_PANEL_OK);
+            if (anOkBtn)
+              anOkBtn->setFocus(Qt::TabFocusReason);
+          }
+        }
+      }
+    }
+  }
+  if (isDone)
+    module()->sketchMgr()->clearClickedFlags();
+
+  return isDone;
+}
+
+void PartSet_SketcherReetntrantMgr::beforeStopInternalEdit()
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                      (myWorkshop->currentOperation());
+  if (aFOperation) {
+    disconnect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
+    disconnect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
+  }
+
+  deleteInternalFeature();
+}
+
+void PartSet_SketcherReetntrantMgr::restartOperation()
+{
+  if (myIsInternalEditOperation) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+                                                                  myWorkshop->currentOperation());
+    if (aFOperation) {
+      myNoMoreWidgetsAttribute = "";
+      myIsFlagsBlocked = true;
+      module()->launchOperation(aFOperation->id());
+      myIsFlagsBlocked = false;
+      resetFlags();
+      // we should avoid processing of the signal about no more widgets attributes and 
+      // do this after the restart operaion is finished if it was called
+      // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
+      // if it should be called after restart
+      if (!myNoMoreWidgetsAttribute.empty()) {
+        onNoMoreWidgets(myNoMoreWidgetsAttribute);
+        myNoMoreWidgetsAttribute = "";
+      }
+    }
+  }
+}
+
+void PartSet_SketcherReetntrantMgr::createInternalFeature()
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                     (myWorkshop->currentOperation());
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    FeaturePtr anOperationFeature = aFOperation->feature();
+
+    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+    myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
+
+    bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature,
+                                                     aSketch, false);
+    XGUI_PropertyPanel* aPropertyPanel = dynamic_cast<XGUI_PropertyPanel*>
+                                                  (aFOperation->propertyPanel());
+
+    myInternalWidget = new QWidget(aPropertyPanel->contentWidget()->pageWidget());
+    myInternalWidget->setVisible(false);
+
+    ModuleBase_PageWidget* anInternalPage = new ModuleBase_PageWidget(myInternalWidget);
+
+    QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
+    ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myWorkshop);
+
+    aFactory.createWidget(anInternalPage);
+    QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
+
+    foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
+      bool isStoreValue = !aFOperation->isEditOperation() &&
+                          !aWidget->getDefaultValue().empty() &&
+                          !aWidget->isComputedDefault();
+      aWidget->setFeature(myInternalFeature, isStoreValue);
+      if (!isStoreValue && isFeatureChanged)
+        aWidget->restoreValue();
+    }
+
+    ModuleBase_ModelWidget* aFirstWidget = ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget
+                                                                                        (aWidgets);
+    if (aFirstWidget)
+      myInternalActiveWidget = aFirstWidget;
+  }
+}
+
+void PartSet_SketcherReetntrantMgr::deleteInternalFeature()
+{
+  if (myInternalActiveWidget) {
+    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(myInternalActiveWidget);
     if (aWSelector)
-      aWSelector->activateSelectionAndFilters(true);
+      aWSelector->activateSelectionAndFilters(false);
+    myInternalActiveWidget = 0;
   }
+  delete myInternalWidget;
+  myInternalWidget = 0;
+
+  QObjectPtrList anObjects;
+  anObjects.append(myInternalFeature);
+  workshop()->deleteFeatures(anObjects);
+  myInternalFeature = FeaturePtr();
 }
 
-bool PartSet_SketcherReetntrantMgr::isActiveMgr() const
+void PartSet_SketcherReetntrantMgr::resetFlags()
 {
-  PartSet_SketcherMgr* aSketcherMgr = module()->sketchMgr();
-  ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
-  return PartSet_SketcherMgr::isSketchOperation(aCurrentOperation) ||
-         PartSet_SketcherMgr::isNestedSketchOperation(aCurrentOperation);
+  if (!myIsFlagsBlocked) {
+    myIsInternalEditOperation = false;
+    updateAcceptAllAction();
+    myRestartingMode = RM_None;
+  }
 }
 
-void PartSet_SketcherReetntrantMgr::breakOperationSequence()
+bool PartSet_SketcherReetntrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
+                                                             const FeaturePtr& theNewFeature,
+                                                             const CompositeFeaturePtr& theSketch,
+                                                             const bool isTemporary)
 {
-  myLastOperationId = "";
-  myLastFeature = FeaturePtr();
-  myRestartingMode = RM_None;
+  bool aChanged = false;
+  if (!theSourceFeature.get())
+    return aChanged;
+
+  std::string aFeatureKind = theSourceFeature->getKind();
+  if (aFeatureKind == SketchPlugin_Line::ID()) {
+    // Initialize new line with first point equal to end of previous
+    std::shared_ptr<ModelAPI_Data> aSFData = theSourceFeature->data();
+    std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
+    std::shared_ptr<ModelAPI_Data> aNFData = theNewFeature->data();
+    std::shared_ptr<GeomDataAPI_Point2D> aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aNFData->attribute(SketchPlugin_Line::START_ID()));
+    aNPoint->setValue(aSPoint->x(), aSPoint->y());
+    PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint);
+
+    aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
+    aNPoint->setValue(aSPoint->x(), aSPoint->y());
+  }
+  else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+    // set circle type
+    std::string aTypeAttributeId = SketchPlugin_Circle::CIRCLE_TYPE();
+    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
+    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
+    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+    //ModuleBase_Tools::flushUpdated(theNewFeature);
+    aChanged = true;
+  }
+  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+    // set arc type
+    std::string aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE();
+    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
+    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
+    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+
+    // if the arc is tangent, set coincidence to end point of the previous arc
+    std::string anArcType = aSourceFeatureTypeAttr->value();
+    if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) {
+      // get the last point of the previuos arc feature(geom point 2d)
+      std::shared_ptr<ModelAPI_Data> aSData = theSourceFeature->data();
+      std::shared_ptr<GeomDataAPI_Point2D> aSPointAttr = 
+                                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                      aSData->attribute(SketchPlugin_Arc::END_ID()));
+      // get point attribute on the current feature
+      AttributeRefAttrPtr aTangentPointAttr = theNewFeature->data()->refattr(
+                                                    SketchPlugin_Arc::TANGENT_POINT_ID());
+      aTangentPointAttr->setAttr(aSPointAttr);
+
+      std::shared_ptr<GeomDataAPI_Point2D> aNPointAttr = 
+                                    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                    theNewFeature->data()->attribute(SketchPlugin_Arc::END_ID()));
+      aNPointAttr->setValue(aSPointAttr->x(), aSPointAttr->y());
+
+    }
+    //ModuleBase_Tools::flushUpdated(theNewFeature);
+    aChanged = true;
+  }
+  return aChanged;
+}
+
+bool PartSet_SketcherReetntrantMgr::isTangentArc(ModuleBase_Operation* theOperation,
+                                                 const CompositeFeaturePtr& /*theSketch*/) const
+{
+  bool aTangentArc = false;
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                        (theOperation);
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    FeaturePtr aFeature = aFOperation->feature();
+    if (aFeature.get() && aFeature->getKind() == SketchPlugin_Arc::ID()) {
+      AttributeStringPtr aTypeAttr = aFeature->data()->string(SketchPlugin_Arc::ARC_TYPE());
+      std::string anArcType = aTypeAttr.get() ? aTypeAttr->value() : "";
+      aTangentArc = anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT();
+    }
+  }
+  return aTangentArc;
+}
+
+void PartSet_SketcherReetntrantMgr::updateAcceptAllAction()
+{
+  CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+  if (aSketch.get())
+    workshop()->errorMgr()->updateAcceptAllAction(aSketch);
 }
 
 XGUI_Workshop* PartSet_SketcherReetntrantMgr::workshop() const
@@ -310,3 +642,4 @@ PartSet_Module* PartSet_SketcherReetntrantMgr::module() const
 {
   return dynamic_cast<PartSet_Module*>(myWorkshop->module());
 }
+