From a4f48873f6c5861a7ddbad5a6bdbbfb924b8a7b9 Mon Sep 17 00:00:00 2001 From: nds Date: Fri, 13 Feb 2015 10:46:10 +0300 Subject: [PATCH] Issue #394 Undo-ing a Sketch element Update Undo/Redo action enable state. --- src/ModuleBase/ModuleBase_IModule.cpp | 13 +++ src/ModuleBase/ModuleBase_IModule.h | 12 ++- src/PartSet/PartSet_Module.cpp | 24 +++++ src/PartSet/PartSet_Module.h | 8 ++ src/PartSet/PartSet_SketcherMgr.cpp | 104 ++++++++++++++++---- src/PartSet/PartSet_SketcherMgr.h | 20 +++- src/PartSet/PartSet_WidgetPoint2d.h | 11 ++- src/PartSet/PartSet_WidgetPoint2dDistance.h | 11 ++- src/XGUI/XGUI_Workshop.cpp | 4 +- 9 files changed, 173 insertions(+), 34 deletions(-) diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index f7637f9d7..315be9178 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -116,6 +117,18 @@ bool ModuleBase_IModule::canDisplayObject(const ObjectPtr& theObject) const return anOperation && anOperation->hasObject(theObject); } +bool ModuleBase_IModule::canUndo() const +{ + SessionPtr aMgr = ModelAPI_Session::get(); + return aMgr->hasModuleDocument() && aMgr->canUndo() && !aMgr->isOperation(); +} + +bool ModuleBase_IModule::canRedo() const +{ + SessionPtr aMgr = ModelAPI_Session::get(); + return aMgr->hasModuleDocument() && aMgr->canRedo() && !aMgr->isOperation(); +} + void ModuleBase_IModule::onFeatureTriggered() { QAction* aCmd = dynamic_cast(sender()); diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index b500dd6f8..3c3d33878 100644 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -100,6 +100,12 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject /// It is called as on clearing of property panel as on filling with new widgets virtual void propertyPanelDefined(ModuleBase_Operation* theOperation) {} + //! Returns True if there are available Undos and there is not an active operation + virtual bool canUndo() const; + + //! Returns True if there are available Redos and there is not an active operation + virtual bool canRedo() const; + /// Returns whether the object can be displayed at the bounds of the active operation. /// Display only current operation results /// \param theObject a model object @@ -127,9 +133,9 @@ protected slots: /// Register selection filters for this module virtual void registerFilters() {} - - /// Register properties of this module - virtual void registerProperties() {} + + /// Register properties of this module + virtual void registerProperties() {} /// Returns new instance of operation object (used in createOperation for customization) virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index f3ccdf4f7..05409232e 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -209,6 +209,30 @@ void PartSet_Module::operationStopped(ModuleBase_Operation* theOperation) myWorkshop->viewer()->removeSelectionFilter(myDocumentShapeFilter); } +bool PartSet_Module::canUndo() const +{ + bool aCanUndo = false; + SessionPtr aMgr = ModelAPI_Session::get(); + if (aMgr->hasModuleDocument() && aMgr->canUndo()) { + aCanUndo = !aMgr->isOperation(); + if (!aCanUndo) // check the enable state additionally by sketch manager + aCanUndo = aMgr->canUndo(); + } + return aCanUndo; +} + +bool PartSet_Module::canRedo() const +{ + bool aCanRedo = false; + SessionPtr aMgr = ModelAPI_Session::get(); + if (aMgr->hasModuleDocument() && aMgr->canRedo()) { + aCanRedo = !aMgr->isOperation(); + if (!aCanRedo) // check the enable state additionally by sketch manager + aCanRedo = aMgr->canRedo(); + } + return aCanRedo; +} + bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const { bool aCanDisplay = false; diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index 13cfba1d9..e8ad83d7f 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -80,6 +80,14 @@ public: /// \param theOperation a stopped operation virtual void operationStopped(ModuleBase_Operation* theOperation); + /// Returns True if there are available Undos and the sketch manager allows undo + /// \return the boolean result + virtual bool canUndo() const; + + //! Returns True if there are available Redos and the sketch manager allows redo + /// \return the boolean result + virtual bool canRedo() const; + /// Returns whether the object can be displayed at the bounds of the active operation. /// Display only current operation results for usual operation and ask the sketcher manager /// if it is a sketch operation diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 6ce573b0d..2bbd22d09 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -7,6 +7,7 @@ #include "PartSet_SketcherMgr.h" #include "PartSet_Module.h" #include "PartSet_WidgetPoint2d.h" +#include "PartSet_WidgetPoint2dDistance.h" #include "PartSet_Tools.h" #include @@ -109,7 +110,7 @@ void fillFeature2Attribute(const QList& theList, PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false), - myIsMouseOverWindow(false), myIsPropertyPanelValueChanged(false) + myIsPropertyPanelValueChanged(false), myIsMouseOverViewProcessed(true) { ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = anIWorkshop->viewer(); @@ -141,31 +142,45 @@ PartSet_SketcherMgr::~PartSet_SketcherMgr() void PartSet_SketcherMgr::onMouseMoveOverWindow(bool theOverWindow) { - ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); - if (!aOperation || aOperation->isEditOperation()) + if (!isNestedCreateOperation() || theOverWindow) return; - - myIsMouseOverWindow = theOverWindow; - if (theOverWindow) + // 1. if the mouse over window, update the next flag. Do not perform update visibility of + // created feature because it should be done in onMouseMove(). Some widgets watch + // the mouse move and use the cursor position to update own values. If the presentaion is + // redisplayed before this update, the feature presentation jumps from reset value to current. + if (theOverWindow) { myIsPropertyPanelValueChanged = false; - else { - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); - if(aActiveWgt) { - aActiveWgt->reset(); - } - } + return; + } + myIsMouseOverViewProcessed = false; + + // 2. if the mouse IS NOT over window, reset the active widget value and hide the presentation + ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); + XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); + // disable the viewer update in order to avoid visualization of redisplayed feature in viewer + // obtained after reset value + bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false); + ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); + if (aActiveWgt) { + aActiveWgt->reset(); + } + aDisplayer->enableUpdateViewer(isEnableUpdateViewer); + + // hides the presentation of the current operation feature + myIsPropertyPanelValueChanged = false; updateVisibilityOfCreatedFeature(); } void PartSet_SketcherMgr::onValuesChangedInPropertyPanel() { - ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); - if (!aOperation || aOperation->isEditOperation()) + if (!isNestedCreateOperation()) return; + // visualize the current operation feature myIsPropertyPanelValueChanged = true; - updateVisibilityOfCreatedFeature(); } @@ -293,6 +308,26 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { + if (isNestedCreateOperation() && !myIsMouseOverViewProcessed) { + myIsMouseOverViewProcessed = true; + // 1. perform the widget mouse move functionality and display the presentation + ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_ModelWidget* anActiveWdg = aPanel->activeWidget(); + // the mouse move should be processed in the widget, if it can in order to visualize correct + // presentation. These widgets correct the feature attribute according to the mouse position + PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(anActiveWdg); + if (aPoint2DWdg) { + aPoint2DWdg->onMouseMove(theWnd, theEvent); + } + PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast + (anActiveWdg); + if (aDistanceWdg) { + aDistanceWdg->onMouseMove(theWnd, theEvent); + } + updateVisibilityOfCreatedFeature(); + } + myClickedPoint.clear(); if (myIsDragging) { @@ -608,11 +643,38 @@ void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* ) void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* ) { connectToPropertyPanel(false); + myIsPropertyPanelValueChanged = false; + myIsMouseOverViewProcessed = true; +} + +bool PartSet_SketcherMgr::canUndo() const +{ + return isNestedCreateOperation(); +} + +bool PartSet_SketcherMgr::canRedo() const +{ + return isNestedCreateOperation(); } bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const { - return myIsMouseOverWindow || myIsPropertyPanelValueChanged; + bool aCanDisplay = true; + if (!isNestedCreateOperation()) + return aCanDisplay; + + // during a nested create operation, the feature is redisplayed only if the mouse over view + // of there was a value modified in the property panel after the mouse left the view + aCanDisplay = myIsPropertyPanelValueChanged; + if (!aCanDisplay) { + ModuleBase_IWorkshop* anIWorkshop = myModule->workshop(); + XGUI_ModuleConnector* aConnector = dynamic_cast(anIWorkshop); + XGUI_Workshop* aWorkshop = aConnector->workshop(); + AppElements_MainWindow* aMainWindow = aWorkshop->mainWindow(); + + aCanDisplay = aMainWindow->isMouseOverWindow(); + } + return aCanDisplay; } void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr& thePln) @@ -758,6 +820,12 @@ void PartSet_SketcherMgr::connectToPropertyPanel(const bool isToConnect) } } +bool PartSet_SketcherMgr::isNestedCreateOperation() const +{ + ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation(); + return aOperation && !aOperation->isEditOperation() && isNestedSketchOperation(aOperation); +} + void PartSet_SketcherMgr::updateVisibilityOfCreatedFeature() { ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); @@ -779,4 +847,4 @@ void PartSet_SketcherMgr::updateVisibilityOfCreatedFeature() } } aDisplayer->updateViewer(); -} \ No newline at end of file +} diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index a08cf3941..59ed0f8fb 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -110,6 +110,14 @@ public: /// Stops sketch operation void stopNestedSketch(ModuleBase_Operation* ); + /// Returns True if there are available Undos and the sketch manager allows undo + /// \return the boolean result + bool canUndo() const; + + //! Returns True if there are available Redos and the sketch manager allows redo + /// \return the boolean result + bool canRedo() const; + /// Returns whether the object can be displayed at the bounds of the active operation. /// Display only current operation results for usual operation and ask the sketcher manager /// if it is a sketch operation @@ -193,6 +201,16 @@ private: /// \param isToConnect a boolean value whether connect or disconnect void connectToPropertyPanel(const bool isToConnect); + /// Returns true if the created feature is visible + /// \param + bool isVisibleCreatedFeature() const; + + /// Returns true if the current operation is create a nested feature + //// \return boolean value + bool isNestedCreateOperation() const; + + /// Erase or display the feature of the current operation. If the mouse over the active view or + /// a current value is changed by property panel, the feature is displayed otherwise it is hidden void updateVisibilityOfCreatedFeature(); private: @@ -201,8 +219,8 @@ private: bool myPreviousSelectionEnabled; // the previous selection enabled state in the viewer bool myIsDragging; bool myDragDone; - bool myIsMouseOverWindow; /// the state that mouse is over view bool myIsPropertyPanelValueChanged; /// the state that value in the property panel is changed + bool myIsMouseOverViewProcessed; /// the state whether the over view state is processed by mouseMove method Point myCurrentPoint; Point myClickedPoint; diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index b976abf18..de3ab120d 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -98,16 +98,17 @@ signals: /// Signal about selection of an existing vertex from an object void vertexSelected(); -protected slots: - /// Process mouse release event +public slots: + /// Process mouse move event /// \param theWnd a view window /// \param theEvent a mouse event - void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); - /// Process mouse move event +protected slots: + /// Process mouse release event /// \param theWnd a view window /// \param theEvent a mouse event - void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); protected: /// Saves the internal parameters to the given feature diff --git a/src/PartSet/PartSet_WidgetPoint2dDistance.h b/src/PartSet/PartSet_WidgetPoint2dDistance.h index 5ebfb4d1c..7d6a497c6 100644 --- a/src/PartSet/PartSet_WidgetPoint2dDistance.h +++ b/src/PartSet/PartSet_WidgetPoint2dDistance.h @@ -66,16 +66,17 @@ Q_OBJECT /// Set sketch instance void setSketch(CompositeFeaturePtr theSketch) { mySketch = theSketch; } - protected slots: - /// Process of mouse release +public slots: + /// Process of mouse move /// \param theWnd a pointer to a window /// \param theEvent a mouse event - void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); - /// Process of mouse move + protected slots: + /// Process of mouse release /// \param theWnd a pointer to a window /// \param theEvent a mouse event - void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); + void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent); protected: /// The methiod called when widget is activated diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index f7b254dea..b6ba2aa71 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1058,8 +1058,8 @@ void XGUI_Workshop::updateCommandStatus() // Enable all commands aCmd->setEnabled(true); } - aUndoCmd->setEnabled(aMgr->canUndo() && !aMgr->isOperation()); - aRedoCmd->setEnabled(aMgr->canRedo() && !aMgr->isOperation()); + aUndoCmd->setEnabled(myModule->canUndo()); + aRedoCmd->setEnabled(myModule->canRedo()); updateHistory(); -- 2.39.2