Salome HOME
Sepate reentant functionality to a separate manager.
authornds <nds@opencascade.com>
Wed, 28 Oct 2015 10:48:24 +0000 (13:48 +0300)
committernds <nds@opencascade.com>
Wed, 28 Oct 2015 10:48:24 +0000 (13:48 +0300)
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherReetntrantMgr.cpp [new file with mode: 0755]
src/PartSet/PartSet_SketcherReetntrantMgr.h [new file with mode: 0755]
src/PartSet/PartSet_WidgetPoint2d.cpp

index 350924e1f5bee3d03736244da490efa7a5ce68ea..35275b60f003e428ceb999addf6e0f82a07e418c 100644 (file)
@@ -26,6 +26,7 @@ SET(PROJECT_HEADERS
        PartSet_LockApplyMgr.h
        PartSet_FilterInfinite.h
        PartSet_SketcherMgr.h
+       PartSet_SketcherReetntrantMgr.h
        PartSet_MenuMgr.h
        PartSet_WidgetSketchCreator.h
        PartSet_IconFactory.h
@@ -51,6 +52,7 @@ SET(PROJECT_SOURCES
        PartSet_LockApplyMgr.cpp
        PartSet_FilterInfinite.cpp
        PartSet_SketcherMgr.cpp
+       PartSet_SketcherReetntrantMgr.cpp
        PartSet_MenuMgr.cpp
        PartSet_WidgetSketchCreator.cpp
        PartSet_IconFactory.cpp
index 7e940adefe097a97258d4a0724d1014b6bffd219..d55095a44a6c1df1dc646df3161de63a52bc8ac7 100755 (executable)
@@ -14,6 +14,7 @@
 #include "PartSet_WidgetFileSelector.h"
 #include "PartSet_WidgetSketchCreator.h"
 #include "PartSet_SketcherMgr.h"
+#include "PartSet_SketcherReetntrantMgr.h"
 #include "PartSet_MenuMgr.h"
 #include "PartSet_CustomPrs.h"
 #include "PartSet_IconFactory.h"
 
 #include <SketchPlugin_Feature.h>
 #include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Point.h>
 #include <SketchPlugin_ConstraintAngle.h>
 #include <SketchPlugin_ConstraintLength.h>
 #include <SketchPlugin_ConstraintDistance.h>
@@ -123,13 +120,13 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop*
 }
 
 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
-  : ModuleBase_IModule(theWshop),
-  myRestartingMode(RM_None), myVisualLayerId(0), myHasConstraintShown(true),
-  myIsInternalEditOperation(false)
+: ModuleBase_IModule(theWshop),
+  myVisualLayerId(0), myHasConstraintShown(true)
 {
   new PartSet_IconFactory();
 
   mySketchMgr = new PartSet_SketcherMgr(this);
+  mySketchReentrantMgr = new PartSet_SketcherReetntrantMgr(theWshop);
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
@@ -253,82 +250,21 @@ void PartSet_Module::onOperationCommitted(ModuleBase_Operation* theOperation)
     mySketchMgr->commitNestedSketch(theOperation);
   }
 
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
-  if (!aFOperation)
-    return;
-  // the clear selection is obsolete because during restart of the creation operation
-  // we would like to use selected object, e.g. a line in a parallel constraint
-
-  // the selection is cleared after commit the create operation
-  // in order to do not use the same selected objects in the restarted operation
-  // for common behaviour, the selection is cleared even if the operation is not restarted
-  /*XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
-  XGUI_Workshop* aWorkshop = aConnector->workshop();
-  aWorkshop->selector()->clearSelection();*/
-
   /// Restart sketcher operations automatically
-  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();
-    myLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr();
-    if (!sketchMgr()->sketchSolverError()) {
-      if (!aFOperation->isEditOperation()) {
-        FeaturePtr anOperationFeature = aFOperation->feature();
-        if (anOperationFeature.get() != NULL) {
-          editFeature(anOperationFeature);
-          myIsInternalEditOperation = true;
-          onInternalActivateFirstWidgetSelection();
-
-          // activate the last active widget in the Property Panel
-          if (!myPreviousAttributeID.empty()) {
-            ModuleBase_Operation* anEditOperation = 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
-        myIsInternalEditOperation = false;
-        launchOperation(myLastOperationId);
-        breakOperationSequence();
-      }
-    }
+  if (!mySketchReentrantMgr->operationCommitted(theOperation)) {
+    // the selection is cleared after commit the create operation
+    // in order to do not use the same selected objects in the restarted operation
+    // for common behaviour, the selection is cleared even if the operation is not restarted
+    XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
+    XGUI_Workshop* aWorkshop = aConnector->workshop();
+    aWorkshop->selector()->clearSelection();
   }
 }
 
-void PartSet_Module::breakOperationSequence()
-{
-  myLastOperationId = "";
-  myLastFeature = FeaturePtr();
-  myRestartingMode = RM_None;
-}
-
 void PartSet_Module::onOperationAborted(ModuleBase_Operation* theOperation)
 {
-  if (myIsInternalEditOperation) {
-    // abort the created feature, which is currently edited
-    SessionPtr aMgr = ModelAPI_Session::get();
-    if (aMgr->hasModuleDocument() && aMgr->canUndo()) {
-      aMgr->undo();
-    }
-  }
-
-  myIsInternalEditOperation = false;
-  breakOperationSequence();
+  /// Restart sketcher operations automatically
+  mySketchReentrantMgr->operationAborted(theOperation);
 }
 
 void PartSet_Module::onOperationStarted(ModuleBase_Operation* theOperation)
@@ -525,36 +461,7 @@ void PartSet_Module::clearViewer()
 
 void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation)
 {
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
-  if (!aFOperation)
-    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());
-      return;
-  }
-
-  // Restart last operation type 
-  if ((aFOperation->id() == myLastOperationId) && myLastFeature) {
-    ModuleBase_ModelWidget* aWgt = aPanel->activeWidget();
-    if (aFOperation->id().toStdString() == SketchPlugin_Line::ID()) {
-      // Initialise new line with first point equal to end of previous
-      PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
-      if (aPnt2dWgt) {
-        std::shared_ptr<ModelAPI_Data> aData = myLastFeature->data();
-        std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
-          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::END_ID()));
-        if (aPoint) {
-          aPnt2dWgt->setPoint(aPoint->x(), aPoint->y());
-          PartSet_Tools::setConstraints(mySketchMgr->activeSketch(), aFOperation->feature(), 
-            aWgt->attributeID(), aPoint->x(), aPoint->y());
-          aPanel->activateNextWidget(aPnt2dWgt);
-        }
-      }
-    }
-  }
+  mySketchReentrantMgr->propertyPanelDefined(theOperation);
 }
 
 
@@ -600,15 +507,12 @@ void PartSet_Module::onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* the
 
 void PartSet_Module::onEnterReleased()
 {
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                                  (currentOperation());
-  if (/*!aFOperation->isEditOperation() || */myIsInternalEditOperation)
-    myRestartingMode = RM_EmptyFeatureUsed;
+  mySketchReentrantMgr->enterReleased();
 }
 
 void PartSet_Module::onOperationActivatedByPreselection()
 {
-  if (myRestartingMode != RM_None)
+  if (!mySketchReentrantMgr->canBeCommittedByPreselection())
     return;
 
   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
@@ -623,57 +527,12 @@ void PartSet_Module::onOperationActivatedByPreselection()
 
 void PartSet_Module::onNoMoreWidgets(const std::string& thePreviousAttributeID)
 {
-  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-  if (anOperation) {
-    if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
-      if (myRestartingMode != RM_Forbided) {
-        myRestartingMode = RM_LastFeatureUsed;
-        myPreviousAttributeID = thePreviousAttributeID;
-      }
-      XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
-      XGUI_Workshop* aWorkshop = aConnector->workshop();
-      XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
-      // do nothing if the feature can not be applyed
-      if (anOpMgr->isApplyEnabled())
-        anOperation->commit();
-    }
-  }
-}
-
-void PartSet_Module::onInternalActivateFirstWidgetSelection()
-{
-  if (!myIsInternalEditOperation)
-    return;
-
-  ModuleBase_ModelWidget* aFirstWidget = activeWidget();
-  ModuleBase_IPropertyPanel* aPanel = currentOperation()->propertyPanel();
-  if (aFirstWidget != aPanel->activeWidget()) {
-    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
-    if (aWSelector)
-      aWSelector->activateSelectionAndFilters(true);
-  }
+  mySketchReentrantMgr->noMoreWidgets(thePreviousAttributeID);
 }
 
 void PartSet_Module::onVertexSelected()
 {
-  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
-  if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
-    /// If last line finished on vertex the lines creation sequence has to be break
-    ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
-    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-    const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
-    QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
-    bool aFoundWidget = false;
-    bool aFoundObligatory = false;
-    for (; anIt != aLast && !aFoundObligatory; anIt++) {
-      if (!aFoundWidget)
-        aFoundWidget = *anIt == anActiveWidget;
-      else
-        aFoundObligatory = (*anIt)->isObligatory();
-    }
-    if (!aFoundObligatory)
-      myRestartingMode = RM_Forbided;
-  }
+  mySketchReentrantMgr->vertexSelected();
 }
 
 ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& theType, QWidget* theParent,
@@ -736,26 +595,15 @@ ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& th
 ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
 {
   ModuleBase_ModelWidget* anActiveWidget = 0;
-  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
-  if (aOperation) {
-    ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
-    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)
-        anActiveWidget = aFirstWidget;
+
+  anActiveWidget = mySketchReentrantMgr->activeWidget();
+  if (!anActiveWidget) {
+    ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
+    if (aOperation) {
+      ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+      anActiveWidget = aPanel->activeWidget();
     }
   }
-
   return anActiveWidget;
 }
 
index eac6dad27ce20415da65288c05baee08d894c8bd..8db2d83052fce596706389ca42463c960a9c9364 100644 (file)
@@ -31,6 +31,7 @@ class ModuleBase_IViewWindow;
 class PartSet_MenuMgr;
 class PartSet_CustomPrs;
 class PartSet_SketcherMgr;
+class PartSet_SketcherReetntrantMgr;
 
 class QAction;
 
@@ -162,6 +163,9 @@ public:
   /// Returns sketch manager object
   PartSet_SketcherMgr* sketchMgr() const { return mySketchMgr; }
 
+  /// Returns sketch reentrant manager
+  PartSet_SketcherReetntrantMgr* sketchReentranceMgr() { return mySketchReentrantMgr; }
+
   /// Performs functionality on closing document
   virtual void closeDocument();
 
@@ -207,15 +211,11 @@ public:
   /// Returns list of granted operation indices
   virtual void grantedOperationIds(ModuleBase_Operation* theOperation, QStringList& theIds) const;
 
-  bool isInternalEditOperation() { return myIsInternalEditOperation; }
-
 public slots:
   /// SLOT, that is called by no more widget signal emitted by property panel
   /// Set a specific flag to restart the sketcher operation
   void onNoMoreWidgets(const std::string& thePreviousAttributeID);
 
-  void onInternalActivateFirstWidgetSelection();
-
   /// Redefines the parent method in order to customize the next case:
   /// If the sketch nested operation is active and the presentation is not visualized in the viewer,
   /// the operation should be always aborted.
@@ -272,26 +272,15 @@ protected slots:
    void onTreeViewDoubleClick(const QModelIndex&);
 
  private:
-  /// Breaks sequense of automatically resterted operations
-  void breakOperationSequence();
 
   //! Delete features
   virtual bool deleteObjects();
 
  private:
-  QString myLastOperationId;
-  FeaturePtr myLastFeature;
-
-  std::string myPreviousAttributeID;
-
-  // Automatical restarting mode flag
-  RestartingMode myRestartingMode;
-
-  bool myIsInternalEditOperation;
-
   SelectMgr_ListOfFilter mySelectionFilters;
 
   PartSet_SketcherMgr* mySketchMgr;
+  PartSet_SketcherReetntrantMgr* mySketchReentrantMgr;
   PartSet_MenuMgr* myMenuMgr;
   /// A default custom presentation, which is used for references objects of started operation
   PartSet_CustomPrs* myCustomPrs;
index 2e0435d62213b51ae745232b15a37ae6ea37fbd1..572bea5a273b211b2a77a10013b311474ba6a9a3 100644 (file)
@@ -5,6 +5,7 @@
 // Author:      Vitaly SMETANNIKOV
 
 #include "PartSet_SketcherMgr.h"
+#include "PartSet_SketcherReetntrantMgr.h"
 #include "PartSet_Module.h"
 #include "PartSet_WidgetPoint2d.h"
 #include "PartSet_WidgetPoint2dDistance.h"
@@ -336,7 +337,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
   if (!(theEvent->buttons() & Qt::LeftButton))
     return;
 
-  if (myModule->isInternalEditOperation()) // it should be processed by mouse release
+  if (myModule->sketchReentranceMgr()->processMousePressed())
     return;
 
   // Clear dragging mode
@@ -437,12 +438,8 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE
 
 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
-  if (myModule->isInternalEditOperation()) {
-    ModuleBase_Operation* anOperation = getCurrentOperation();
-    //if (operationMgr()->isApplyEnabled())
-    anOperation->commit();
+  if (myModule->sketchReentranceMgr()->processMouseReleased())
     return;
-  }
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
@@ -479,15 +476,8 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse
 
 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
 {
-  if (myModule->isInternalEditOperation()) {
-    PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(myModule->activeWidget());
-    if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) {
-      ModuleBase_Operation* anOperation = getCurrentOperation();
-      //if (operationMgr()->isApplyEnabled())
-      anOperation->commit();
-      return;
-    }
-  }
+  if (myModule->sketchReentranceMgr()->processMouseMoved())
+    return;
 
   if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) {
     myIsMouseOverViewProcessed = true;
diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp
new file mode 100755 (executable)
index 0000000..b4b926a
--- /dev/null
@@ -0,0 +1,278 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include "PartSet_SketcherReetntrantMgr.h"
+#include "PartSet_Module.h"
+#include "PartSet_SketcherMgr.h"
+#include "PartSet_WidgetPoint2D.h"
+
+#include "ModelAPI_Session.h"
+
+#include <ModuleBase_IPropertyPanel.h>
+#include <ModuleBase_OperationFeature.h>
+#include <ModuleBase_ModelWidget.h>
+#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_WidgetSelector.h>
+
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Line.h>
+
+#include <XGUI_Workshop.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_OperationMgr.h>
+
+PartSet_SketcherReetntrantMgr::PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop)
+: QObject(theWorkshop),
+  myWorkshop(theWorkshop),
+  myIsInternalEditOperation(false),
+  myLastOperationId(""),
+  myPreviousAttributeID(""),
+  myRestartingMode(RM_None)
+{
+}
+
+PartSet_SketcherReetntrantMgr::~PartSet_SketcherReetntrantMgr()
+{
+}
+
+ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::activeWidget() const
+{
+  ModuleBase_ModelWidget* aWidget = 0;
+
+  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;
+    }
+  }
+  return aWidget;
+}
+
+bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation)
+{
+  bool aProcessed = false;
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+  if (!aFOperation)
+    return aProcessed;
+
+  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
+        myIsInternalEditOperation = false;
+        aModule->launchOperation(myLastOperationId.c_str());
+        breakOperationSequence();
+        aProcessed = true;
+      }
+    }
+  }
+
+  if (!aProcessed)
+    breakOperationSequence();
+
+  return aProcessed;
+}
+
+void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOperation)
+{
+  if (myIsInternalEditOperation) {
+    // abort the created feature, which is currently edited
+    SessionPtr aMgr = ModelAPI_Session::get();
+    if (aMgr->hasModuleDocument() && aMgr->canUndo()) {
+      aMgr->undo();
+    }
+  }
+  myIsInternalEditOperation = false;
+  breakOperationSequence();
+}
+
+bool PartSet_SketcherReetntrantMgr::processMouseMoved()
+{
+  bool isProcessed = false;
+  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();
+      isProcessed = true;
+    }
+  }
+  return isProcessed;
+}
+
+bool PartSet_SketcherReetntrantMgr::processMousePressed()
+{
+  return myIsInternalEditOperation;
+}
+
+bool PartSet_SketcherReetntrantMgr::processMouseReleased()
+{
+  bool isProcessed = false;
+  if (myIsInternalEditOperation) {
+    ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+    //if (operationMgr()->isApplyEnabled())
+    anOperation->commit();
+    isProcessed = true;
+  }
+  return isProcessed;
+}
+
+void PartSet_SketcherReetntrantMgr::propertyPanelDefined(ModuleBase_Operation* theOperation)
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+  if (!aFOperation)
+    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());
+      return;
+  }
+
+  // Restart last operation type 
+  if ((aFOperation->id() == myLastOperationId.c_str()) && myLastFeature) {
+    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);
+    }
+  }
+}
+
+void PartSet_SketcherReetntrantMgr::noMoreWidgets(const std::string& thePreviousAttributeID)
+{
+  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+  if (anOperation) {
+    if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
+      if (myRestartingMode != RM_Forbided) {
+        myRestartingMode = RM_LastFeatureUsed;
+        myPreviousAttributeID = thePreviousAttributeID;
+      }
+      XGUI_Workshop* aWorkshop = workshop();
+      XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
+      // do nothing if the feature can not be applyed
+      if (anOpMgr->isApplyEnabled())
+        anOperation->commit();
+    }
+  }
+}
+
+void PartSet_SketcherReetntrantMgr::vertexSelected()
+{
+  ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
+  if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
+    /// If last line finished on vertex the lines creation sequence has to be break
+    ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+    const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
+    QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
+    bool aFoundWidget = false;
+    bool aFoundObligatory = false;
+    for (; anIt != aLast && !aFoundObligatory; anIt++) {
+      if (!aFoundWidget)
+        aFoundWidget = *anIt == anActiveWidget;
+      else
+        aFoundObligatory = (*anIt)->isObligatory();
+    }
+    if (!aFoundObligatory)
+      myRestartingMode = RM_Forbided;
+  }
+}
+
+void PartSet_SketcherReetntrantMgr::enterReleased()
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                      (myWorkshop->currentOperation());
+  if (/*!aFOperation->isEditOperation() || */myIsInternalEditOperation)
+    myRestartingMode = RM_EmptyFeatureUsed;
+}
+
+bool PartSet_SketcherReetntrantMgr::canBeCommittedByPreselection()
+{
+  return myRestartingMode == RM_None;
+}
+
+void PartSet_SketcherReetntrantMgr::onInternalActivateFirstWidgetSelection()
+{
+  if (!myIsInternalEditOperation)
+    return;
+
+  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::breakOperationSequence()
+{
+  myLastOperationId = "";
+  myLastFeature = FeaturePtr();
+  myRestartingMode = RM_None;
+}
+
+XGUI_Workshop* PartSet_SketcherReetntrantMgr::workshop()
+{
+  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+  return aConnector->workshop();
+}
+
+PartSet_Module* PartSet_SketcherReetntrantMgr::module()
+{
+  return dynamic_cast<PartSet_Module*>(myWorkshop->module());
+}
diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.h b/src/PartSet/PartSet_SketcherReetntrantMgr.h
new file mode 100755 (executable)
index 0000000..a3513ac
--- /dev/null
@@ -0,0 +1,121 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#ifndef PartSet_SketcherReetntrantMgr_H
+#define PartSet_SketcherReetntrantMgr_H
+
+#include "PartSet.h"
+
+#include <ModelAPI_Feature.h>
+
+#include <string>
+
+#include <QObject>
+
+class ModuleBase_IWorkshop;
+class ModuleBase_Operation;
+class ModuleBase_ModelWidget;
+
+class XGUI_Workshop;
+class PartSet_Module;
+
+/// \ingroup PartSet_SketcherReetntrantMgr
+/// It provides reentrant create operations in sketch, that is when all inputs are valid,
+/// automatic validation of the creation and switch the created entity to edit mode
+/// ('internal' edit operation),
+/// with the ability to simultaneously create the next entity of same type (re-entrance of the operation).
+/// OK valids the current edition and exits from the operation (no re-entrance).
+/// Cancel removes (undo) the entity currently edited and exits from the operation (no re-entrance).
+class PARTSET_EXPORT PartSet_SketcherReetntrantMgr : public QObject
+{
+Q_OBJECT
+
+/// Enumeration to specify the restart operation properties.
+enum RestartingMode {
+  RM_None, /// the operation should not be restarted
+  RM_Forbided, /// the operation should not be restarted after there is no active widget
+  RM_LastFeatureUsed, /// the operation is restarted and use the previous feature for own initialization
+  RM_EmptyFeatureUsed /// the operation is restarted and does not use the previous feature
+};
+
+public:
+  /// Constructor
+  /// \param theParent a parent object
+  PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop);
+  virtual ~PartSet_SketcherReetntrantMgr();
+
+public:
+  /// If the internal edit operation is started, this is the first widget of the operation
+  ModuleBase_ModelWidget* activeWidget() const;
+
+  /// Restarts sketcher operation automatically. If the commited operation is created, it starts
+  /// an 'internal' edit operation for the created feature. If an 'internal' operation is committed,
+  /// a create operation for a new feature with the current feature kind is started.
+  /// Some internal flags are taken into accout, such as whether the previous feature should be
+  /// used for initialization of created one or whether the restart of operation is forbidden.
+  /// \param theOperation a committed operation
+  /// \return true if an operation restarted
+  bool operationCommitted(ModuleBase_Operation* theOperation);
+
+  /// \param theOperation a committed operation
+  void operationAborted(ModuleBase_Operation* theOperation);
+
+  /// Return true if the manager processes the mouse move event
+  /// It happens if the current operation is an internal edit operation and the first
+  /// control can be filled by the mouse move event. The operation is committed.
+  /// \return true if operation is committed.
+  bool processMouseMoved();
+
+  /// Return true if the manager processes the mouse press event
+  /// \return true if the current operation is an internal edit operation.
+  bool processMousePressed();
+
+  /// Return true if the manager processes the mouse enter event
+  /// It happens if the current operation is an internal edit operation.
+  /// The operation is committed.
+  /// \return true if operation is committed.
+  bool processMouseReleased();
+
+  /// Activates the operation widgets relatively the internal reentrant flags
+  void propertyPanelDefined(ModuleBase_Operation* theOperation);
+
+  /// It is called by no more widget signal emitted by property panel
+  /// Set a specific flag to restart the sketcher operation
+  void noMoreWidgets(const std::string& thePreviousAttributeID);
+
+  /// Processing of vertex selected, if the feature is line, save flags to stop reentrant operation
+  void vertexSelected();
+
+  /// It is called by enter key released
+  /// Set a specific type of restarting the current operation
+  void enterReleased();
+
+  /// It is called by the current operation filling with the preselection.
+  /// Returns false if the reentrant mode of the operation is not empty.
+  bool canBeCommittedByPreselection();
+
+public slots:
+  void onInternalActivateFirstWidgetSelection();
+
+private:
+  /// Breaks sequense of automatically resterted operations
+  void breakOperationSequence();
+
+  /// Returns the workshop
+  XGUI_Workshop* workshop();
+
+  /// Returns the workshop module
+  PartSet_Module* module();
+
+private:
+  ModuleBase_IWorkshop* myWorkshop; /// the workshop
+
+  bool myIsInternalEditOperation; /// true when the 'internal' edit is started
+
+  std::string myLastOperationId;
+  FeaturePtr myLastFeature;
+
+  std::string myPreviousAttributeID;
+  RestartingMode myRestartingMode;  /// Automatical restarting mode flag
+};
+
+#endif
index 40b221c452eb195f902de26886874bb1f5a15e0f..cbd3c97340ae571113effbd1827455b1cc9d8c36 100644 (file)
@@ -147,17 +147,36 @@ PartSet_WidgetPoint2D::~PartSet_WidgetPoint2D()
 bool PartSet_WidgetPoint2D::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
                                          const bool theToValidate)
 {
+  bool isDone = false;
   if (theValues.empty())
-    return false;
+    return isDone;
 
   ModuleBase_ViewerPrs aValue = theValues.takeFirst();
-
-  Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
-  bool isDone = false;
   TopoDS_Shape aShape = aValue.shape();
-  double aX, aY;
-  if (getPoint2d(aView, aShape, aX, aY)) {
-    isDone = setPoint(aX, aY);
+  if (!aShape.IsNull()) {
+    Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
+    double aX, aY;
+    if (getPoint2d(aView, aShape, aX, aY)) {
+      isDone = setPoint(aX, aY);
+    }
+  }
+  else if (canBeActivatedByMove()) {
+    if (feature()->getKind() == SketchPlugin_Line::ID()) {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aValue.object());
+      // Initialise new line with first point equal to end of previous
+      if (aFeature.get()) {
+        std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+        std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                       aData->attribute(SketchPlugin_Line::END_ID()));
+        if (aPoint) {
+          setPoint(aPoint->x(), aPoint->y());
+          PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aPoint->x(),
+                                        aPoint->y());
+          isDone = true;
+        }
+      }
+    }
   }
   return isDone;
 }