From: nds Date: Mon, 3 Apr 2017 05:59:04 +0000 (+0300) Subject: Issues #2027, #2024, #2063, #2067: reentrant message to fill new operation by result... X-Git-Tag: V_2.7.0~103 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a87ec82289d152ffd66b1cb7133bfb5cbfe92281;p=modules%2Fshaper.git Issues #2027, #2024, #2063, #2067: reentrant message to fill new operation by result of the previous one. Issue #2064(PartSet_OperationPrs) --- diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index e227fdeab..fea8bb975 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -28,10 +28,12 @@ SET(PROJECT_HEADERS ModelAPI_CompositeFeature.h ModelAPI_Data.h ModelAPI_Document.h + ModelAPI_EventReentrantMessage.h ModelAPI_Events.h ModelAPI_Expression.h ModelAPI_Feature.h ModelAPI_FeatureValidator.h + ModelAPI_IReentrant.h ModelAPI_Object.h ModelAPI_Plugin.h ModelAPI_Result.h @@ -69,10 +71,12 @@ SET(PROJECT_SOURCES ModelAPI_CompositeFeature.cpp ModelAPI_Data.cpp ModelAPI_Document.cpp + ModelAPI_EventReentrantMessage.cpp ModelAPI_Events.cpp ModelAPI_Expression.cpp ModelAPI_Feature.cpp ModelAPI_FeatureValidator.cpp + ModelAPI_IReentrant.cpp ModelAPI_Object.cpp ModelAPI_Plugin.cpp ModelAPI_Result.cpp diff --git a/src/ModelAPI/ModelAPI_EventReentrantMessage.cpp b/src/ModelAPI/ModelAPI_EventReentrantMessage.cpp new file mode 100644 index 000000000..b527e7016 --- /dev/null +++ b/src/ModelAPI/ModelAPI_EventReentrantMessage.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: ModelAPI_EventReentrantMessage.cpp +// Created: 30 Mar 2017 +// Author: Natalia ERMOLAEVA + +#include + +ModelAPI_EventReentrantMessage::ModelAPI_EventReentrantMessage( + const Events_ID theID, + const void* theSender) +: Events_Message(theID, theSender) +{ +} diff --git a/src/ModelAPI/ModelAPI_EventReentrantMessage.h b/src/ModelAPI/ModelAPI_EventReentrantMessage.h new file mode 100644 index 000000000..ded9c8b99 --- /dev/null +++ b/src/ModelAPI/ModelAPI_EventReentrantMessage.h @@ -0,0 +1,85 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: ModelAPI_EventReentrantMessage.h +// Created: 30 Mar 2017 +// Author: Natalia ERMOLAEVA + +#ifndef ModelAPI_EventReentrantMessage_H_ +#define ModelAPI_EventReentrantMessage_H_ + +#include +#include + +#include + +#include + +class ModelAPI_Object; +class ModelAPI_Feature; +class ModelAPI_Attribute; +class GeomAPI_Pnt2d; + +/// Message that style of visualization of parameter is changed. +/// It will be shown as expression or value +class ModelAPI_EventReentrantMessage : public Events_Message +{ +public: + /// Creates an empty message + MODELAPI_EXPORT ModelAPI_EventReentrantMessage(const Events_ID theID, + const void* theSender = 0); + /// The virtual destructor + MODELAPI_EXPORT virtual ~ModelAPI_EventReentrantMessage() {} + /// Static. Returns EventID of the message. + MODELAPI_EXPORT static Events_ID eventId() + { + static const char * MY_EVENT_REENTRANT_MESSAGE_ID("EventReentrantMessage"); + return Events_Loop::eventByName(MY_EVENT_REENTRANT_MESSAGE_ID); + } + + /// Fills previous feature parameter + MODELAPI_EXPORT void setCreatedFeature(const std::shared_ptr& theFeature) + { myCreatedFeature = theFeature; } + + /// Returns previous feature parameter + MODELAPI_EXPORT const std::shared_ptr& createdFeature() const + { return myCreatedFeature; } + + /// Fills selected object parameter + /// \theObject a feature or result + MODELAPI_EXPORT void setSelectedObject(const std::shared_ptr& theObject) + { mySelectedObject = theObject; } + + /// Returns selected object parameter + MODELAPI_EXPORT const std::shared_ptr& selectedObject() const + { return mySelectedObject; } + + /// Fills selected attribute parameter + /// \theAttribute + MODELAPI_EXPORT void setSelectedAttribute + (const std::shared_ptr& theAttribute) + { mySelectedAttribute = theAttribute; } + + /// Returns selected attribute parameter + MODELAPI_EXPORT const std::shared_ptr& selectedAttribute() + { return mySelectedAttribute; } + + /// Fills clicked point + /// \thePoint + MODELAPI_EXPORT void setClickedPoint(const std::shared_ptr& thePoint) + { myClickedPoint = thePoint; } + + /// Returns clicked point + MODELAPI_EXPORT const std::shared_ptr& clickedPoint() + { return myClickedPoint; } + +private: + std::shared_ptr myCreatedFeature; ///< previous object + std::shared_ptr mySelectedObject; ///< selected object + std::shared_ptr mySelectedAttribute; ///< selected attribute + std::shared_ptr myClickedPoint; ///< clicked point +}; + +typedef std::shared_ptr ReentrantMessagePtr; + + +#endif diff --git a/src/ModelAPI/ModelAPI_IReentrant.cpp b/src/ModelAPI/ModelAPI_IReentrant.cpp new file mode 100644 index 000000000..53697f937 --- /dev/null +++ b/src/ModelAPI/ModelAPI_IReentrant.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_IReentrant.cpp +// Created: 30 Mar 2017 +// Author: Natalia ERMOLAEVA + +#include + +ModelAPI_IReentrant::~ModelAPI_IReentrant() +{ +} diff --git a/src/ModelAPI/ModelAPI_IReentrant.h b/src/ModelAPI/ModelAPI_IReentrant.h new file mode 100644 index 000000000..b556193ba --- /dev/null +++ b/src/ModelAPI/ModelAPI_IReentrant.h @@ -0,0 +1,34 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: ModelAPI_IReentrant.hxx +// Created: 30 Mar 2017 +// Author: Natalia ERMOLAEVA + +#ifndef ModelAPI_IReentrant_H +#define ModelAPI_IReentrant_H + +#include "ModelAPI.h" + +#include +#include + +class Events_Message; + +/** \class ModelAPI_IReentrant + * \ingroup DataModel + * \brief Interface of a class which can process specific messages + */ +class ModelAPI_IReentrant +{ +public: + MODELAPI_EXPORT virtual ~ModelAPI_IReentrant(); + + /// Apply information of the message to current object. + /// \param theMessage a container of information + /// \return a next active attribute name + virtual std::string processEvent(const std::shared_ptr& theMessage) = 0; +}; + +typedef std::shared_ptr ModelReentrantPtr; + +#endif diff --git a/src/ModuleBase/ModuleBase_IErrorMgr.h b/src/ModuleBase/ModuleBase_IErrorMgr.h index 9f595fdbb..c41b0b523 100644 --- a/src/ModuleBase/ModuleBase_IErrorMgr.h +++ b/src/ModuleBase/ModuleBase_IErrorMgr.h @@ -8,9 +8,13 @@ #define ModuleBase_IErrorMgr_H #include "ModuleBase.h" + #include +#include + class ModuleBase_IPropertyPanel; +class ModelAPI_Feature; /** * \class ModuleBase_IErrorMgr @@ -34,6 +38,10 @@ public: /// \return Currently installed property panel ModuleBase_IPropertyPanel* propertyPanel() const { return myPropertyPanel; } + /// Update actions for the given feature + /// \param theFeature a feature + virtual void updateActions(const std::shared_ptr& theFeature) = 0; + protected slots: /// Process values changed event for processing feature attribute validation errors. virtual void onWidgetChanged() = 0; diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index 3a5aebb6a..7dc2d8f82 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -1,10 +1,13 @@ // Copyright (C) 2014-20xx CEA/DEN, EDF R&D +#include "ModelAPI_IReentrant.h" +#include "ModelAPI_EventReentrantMessage.h" #include "ModuleBase_IModule.h" #include "ModuleBase_IViewer.h" #include "ModuleBase_ViewerPrs.h" #include "ModuleBase_Operation.h" +#include "ModuleBase_IPropertyPanel.h" #include "ModuleBase_ISelection.h" #include "ModuleBase_OperationDescription.h" #include "ModuleBase_OperationFeature.h" @@ -12,8 +15,10 @@ #include "ModuleBase_WidgetFactory.h" #include "ModuleBase_PageWidget.h" #include "ModuleBase_Dialog.h" +#include "ModuleBase_IErrorMgr.h" #include +#include #include #include @@ -85,9 +90,30 @@ void ModuleBase_IModule::launchOperation(const QString& theCmdId) ModuleBase_OperationFeature* aFOperation = dynamic_cast (createOperation(theCmdId.toStdString())); if (aFOperation) { - aFOperation->initSelection(aPreSelected); + std::shared_ptr aMessage = reentrantMessage(); + if (aMessage.get()) { + setReentrantPreSelection(aMessage); + } + else + aFOperation->initSelection(aPreSelected); workshop()->processLaunchOperation(aFOperation); + + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + ModelReentrantPtr aReentrantFeature = + std::dynamic_pointer_cast(aFeature); + if (aReentrantFeature.get()) { + if (aMessage.get()) { + ModuleBase_IPropertyPanel* aPanel = workshop()->propertyPanel(); + std::string aPrevAttribute = aReentrantFeature->processEvent(aMessage); + workshop()->errorMgr()->updateActions(aFeature); + + ModuleBase_ModelWidget* aPrevWidget = aPanel->modelWidget(aPrevAttribute); + aPanel->activateNextWidget(aPrevWidget); + } + } + } } } diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index f72ad02fd..62b746eab 100755 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -28,8 +28,11 @@ class QMenu; class Config_WidgetAPI; class ModuleBase_ModelWidget; class ModuleBase_Operation; +class ModuleBase_ViewerPrs; + class ModuleBase_IWorkshop; class ModelAPI_Result; +class Events_Message; class AIS_InteractiveObject; @@ -317,6 +320,13 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject virtual AttributePtr findAttribute(const ObjectPtr& theObject, const GeomShapePtr& theGeomShape) = 0; + /// Returns reentrant message if it was accepted + virtual std::shared_ptr reentrantMessage() = 0; + + /// Put current selection into reentrant message + /// \param theMessage a message of reentrant operation + virtual void setReentrantPreSelection(const std::shared_ptr& theMessage) = 0; + /// Returns XML information by the feature index /// \param theFeatureId a feature id /// \param theXmlCfg XML configuration diff --git a/src/ModuleBase/ModuleBase_IPropertyPanel.cpp b/src/ModuleBase/ModuleBase_IPropertyPanel.cpp index bb6d2276a..37230d33d 100644 --- a/src/ModuleBase/ModuleBase_IPropertyPanel.cpp +++ b/src/ModuleBase/ModuleBase_IPropertyPanel.cpp @@ -17,7 +17,24 @@ ModuleBase_IPropertyPanel::ModuleBase_IPropertyPanel(QWidget* theParent) : QDockWidget(theParent), myIsEditing(false) { +} + +ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::modelWidget( + const std::string& theAttributeId) const +{ + ModuleBase_ModelWidget* aWidget = 0; + QList aWidgets = modelWidgets(); + ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); + for (QList::const_iterator anIt = aWidgets.begin(); + anIt != aWidgets.end() && !aWidget; anIt++) { + ModuleBase_ModelWidget* aCurrentWidget = *anIt; + if (aCurrentWidget->attributeID() == theAttributeId && + aCurrentWidget->canAcceptFocus() && + aValidators->isCase(aCurrentWidget->feature(), aCurrentWidget->attributeID())) + aWidget = aCurrentWidget; + } + return aWidget; } ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget() diff --git a/src/ModuleBase/ModuleBase_IPropertyPanel.h b/src/ModuleBase/ModuleBase_IPropertyPanel.h index 58683af41..123e5084e 100644 --- a/src/ModuleBase/ModuleBase_IPropertyPanel.h +++ b/src/ModuleBase/ModuleBase_IPropertyPanel.h @@ -38,6 +38,10 @@ public: /// Returns all property panel's widget created by WidgetFactory virtual const QList& modelWidgets() const = 0; + /// Returns widget, that has the given attribute index + /// \param theAttributeId an attribute from XML + virtual ModuleBase_ModelWidget* modelWidget(const std::string& theAttributeId) const; + /// Removes all widgets in the widget area of the property panel virtual void cleanContent() = 0; diff --git a/src/ModuleBase/ModuleBase_IWorkshop.h b/src/ModuleBase/ModuleBase_IWorkshop.h index 8c5695aa8..a9c66405d 100644 --- a/src/ModuleBase/ModuleBase_IWorkshop.h +++ b/src/ModuleBase/ModuleBase_IWorkshop.h @@ -21,6 +21,7 @@ class ModuleBase_IModule; class ModuleBase_ISelection; class ModuleBase_IViewer; class ModuleBase_IPropertyPanel; +class ModuleBase_IErrorMgr; class ModuleBase_Operation; class ModuleBase_ViewerPrs; class QMainWindow; @@ -62,6 +63,9 @@ Q_OBJECT //! Returns property panel virtual ModuleBase_IPropertyPanel* propertyPanel() const = 0; + //! Returns error manager + virtual ModuleBase_IErrorMgr* errorMgr() const = 0; + /// A filter to process an attribute validators /// \return a filter Handle(ModuleBase_FilterValidated) validatorFilter(); diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index aa0470f7a..f0be4ae9e 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -51,7 +51,7 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent, myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false); - myIsModifiedInEdit = theData->getBooleanAttribute(ATTR_MODIFIED_IN_EDIT, true); + myIsModifiedInEdit = theData->getProperty(ATTR_MODIFIED_IN_EDIT); myDefaultValue = theData->getProperty(ATTR_DEFAULT); myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true); @@ -315,8 +315,18 @@ bool ModuleBase_ModelWidget::storeValue() bool isDone = false; // value is stored only in creation mode and in edition if there is not // XML flag prohibited modification in edit mode(macro feature circle/arc) - if (!isEditingMode() || isModifiedInEdit()) + if (!isEditingMode() || isModifiedInEdit().empty()) isDone = storeValueCustom(); + else { + /// store value in an alternative attribute if possible(attribute has the same type) + std::string aWidgetAttribute = attributeID(); + myAttributeID = isModifiedInEdit(); + storeValueCustom(); + myAttributeID = aWidgetAttribute; + // operation will be restarted but if isDone == true, PagedContainer will try to set focus + // to the current widget, but will be already deleted + isDone = false; + } emit afterValuesChanged(); diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index fcd2ad508..0b409e6fe 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -95,7 +95,7 @@ Q_OBJECT /// Returns this parameter value in the xml file /// \return the boolean result - bool isModifiedInEdit() const { return myIsModifiedInEdit; } + std::string isModifiedInEdit() const { return myIsModifiedInEdit; } /// Returns this widget value state /// \return the enumeration result @@ -364,7 +364,7 @@ private: bool myIsInternal; // an XML state, the value is not stored into model if the widget is in edit mode - bool myIsModifiedInEdit; + std::string myIsModifiedInEdit; /// the reset state. If it is false, the reset method of the widget is not performed bool myUseReset; diff --git a/src/PartSet/PartSet_CustomPrs.cpp b/src/PartSet/PartSet_CustomPrs.cpp index cc52284cc..ded37014d 100755 --- a/src/PartSet/PartSet_CustomPrs.cpp +++ b/src/PartSet/PartSet_CustomPrs.cpp @@ -96,6 +96,7 @@ bool PartSet_CustomPrs::displayPresentation( break; case ModuleBase_IModule::CustomizeResults: PartSet_OperationPrs::getResultShapes(myFeature, myWorkshop, aFeatureShapes); + PartSet_OperationPrs::getPresentationShapes(myFeature, myWorkshop, aFeatureShapes); break; case ModuleBase_IModule::CustomizeHighlightedObjects: PartSet_OperationPrs::getHighlightedShapes(myWorkshop, aFeatureShapes); diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 4382fca68..41c2d3b04 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -552,6 +552,17 @@ void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes) theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire); } +void PartSet_Module::getGeomSelection(const std::shared_ptr& theSelected, + ObjectPtr& theObject, AttributePtr& theAttribute) +{ + ObjectPtr anObject = theSelected->object(); + GeomShapePtr aShape = theSelected->shape(); + + theAttribute = findAttribute(anObject, aShape); + // TODO: try to create result if object is an external object + theObject = anObject; +} + bool PartSet_Module::isMouseOverWindow() { return mySketchMgr->isMouseOverWindow(); @@ -1424,6 +1435,18 @@ AttributePtr PartSet_Module::findAttribute(const ObjectPtr& theObject, return anAttribute; } +//****************************************************** +std::shared_ptr PartSet_Module::reentrantMessage() +{ + return sketchReentranceMgr()->reentrantMessage(); +} + +//****************************************************** +void PartSet_Module::setReentrantPreSelection(const std::shared_ptr& theMessage) +{ + sketchReentranceMgr()->setReentrantPreSelection(theMessage); +} + //****************************************************** void PartSet_Module::onChoiceChanged(ModuleBase_ModelWidget* theWidget, int theIndex) diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index 2795d2965..7292bb30a 100755 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -30,6 +30,8 @@ class ModuleBase_Operation; class ModuleBase_IViewWindow; +class ModuleBase_ViewerPrs; + class XGUI_Workshop; class PartSet_MenuMgr; class PartSet_CustomPrs; @@ -205,6 +207,13 @@ public: /// Returns sketch reentrant manager PartSet_SketcherReentrantMgr* sketchReentranceMgr() const { return mySketchReentrantMgr; } + /// Find object and attribute(if selected) for the given viewer selection + /// \param theSelected a viewer selection + /// \param theObject a selected model object + /// \param theAttribute a selected model attribute + virtual void getGeomSelection(const std::shared_ptr& theSelected, + ObjectPtr& theObject, AttributePtr& theAttribute); + /// Returns listener of overconstraint signal /// \return the listener PartSet_OverconstraintListener* overconstraintListener() { return myOverconstraintListener; } @@ -329,6 +338,13 @@ public: /// \return theAttribute virtual AttributePtr findAttribute(const ObjectPtr& theObject, const GeomShapePtr& theGeomShape); + /// Returns reentrant message if it was accepted + virtual std::shared_ptr reentrantMessage(); + + /// Put current selection into reentrant message + /// \param theMessage a message of reentrant operation + virtual void setReentrantPreSelection(const std::shared_ptr& theMessage); + /// Returns the workshop XGUI_Workshop* getWorkshop() const; diff --git a/src/PartSet/PartSet_OperationPrs.cpp b/src/PartSet/PartSet_OperationPrs.cpp index 31efa6041..706806318 100755 --- a/src/PartSet/PartSet_OperationPrs.cpp +++ b/src/PartSet/PartSet_OperationPrs.cpp @@ -348,6 +348,41 @@ void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature, } } +void PartSet_OperationPrs::getPresentationShapes(const FeaturePtr& theFeature, + ModuleBase_IWorkshop* theWorkshop, + QMap >& theObjectShapes, + const bool theListShouldBeCleared) +{ + if (theListShouldBeCleared) + theObjectShapes.clear(); + + if (!theFeature.get() || !theFeature->data()->isValid()) // if feature is already removed + return; + + XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer(); + + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theFeature); + if (!aPrs.get()) + return; + + AISObjectPtr anAIS = aPrs->getAISObject(aDisplayer->getAISObject(theFeature)); + if (!anAIS.get()) + return; + + Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl(); + if (!anAISPrs.IsNull()) { + Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs); + if (!aShapePrs.IsNull()) { + TopoDS_Shape aShape = aShapePrs->Shape(); + if (!aShape.IsNull()) { + std::shared_ptr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(aShape)); + appendShapeIfVisible(theWorkshop, theFeature, aGeomShape, theObjectShapes); + } + } + } +} + void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorkshop, QMap >& theObjectShapes) diff --git a/src/PartSet/PartSet_OperationPrs.h b/src/PartSet/PartSet_OperationPrs.h index 95ce374ef..7e871fc5d 100755 --- a/src/PartSet/PartSet_OperationPrs.h +++ b/src/PartSet/PartSet_OperationPrs.h @@ -100,6 +100,16 @@ private: QMap >& theObjectShapes, const bool theListShouldBeCleared = true); + /// Fills the map by the feature presentation if the feature is presentable + /// \param theFeature a current feature + /// \param theWorkshop a current workshop + /// \param theObjectShapes an output map + /// \param theObjectShape an output map of objects + static void getPresentationShapes(const FeaturePtr& theFeature, + ModuleBase_IWorkshop* theWorkshop, + QMap >& theObjectShapes, + const bool theListShouldBeCleared = true); + /// Fills the map by the feature object and shapes, which should be visuaziled /// Gets the active widget, obtain the highlighted presentations if it has such and /// fill map by object and shapes diff --git a/src/PartSet/PartSet_OverconstraintListener.cpp b/src/PartSet/PartSet_OverconstraintListener.cpp index 41ee6b2a2..768dff3c7 100755 --- a/src/PartSet/PartSet_OverconstraintListener.cpp +++ b/src/PartSet/PartSet_OverconstraintListener.cpp @@ -18,11 +18,13 @@ #include "SketcherPrs_SymbolPrs.h" #include "SketchPlugin_SketchEntity.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include "Events_Loop.h" #include #include +#include #include #include @@ -39,7 +41,8 @@ PartSet_OverconstraintListener::PartSet_OverconstraintListener(ModuleBase_IWorks aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_UNDER_CONSTRAINED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_FULLY_CONSTRAINED)); - aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + aLoop->registerListener(this, ModelAPI_EventReentrantMessage::eventId()); + aLoop->registerListener(this, SketchPlugin_MacroArcReentrantMessage::eventId()); } void PartSet_OverconstraintListener::getCustomColor(const ObjectPtr& theObject, @@ -123,16 +126,13 @@ void PartSet_OverconstraintListener::processEvent( } } } - else if (anEventID == Events_Loop::eventByName(EVENT_OBJECT_CREATED)) { + else if (anEventID == ModelAPI_EventReentrantMessage::eventId() || + anEventID == SketchPlugin_MacroArcReentrantMessage::eventId()) { PartSet_Module* aModule = dynamic_cast(myWorkshop->module()); PartSet_SketcherReentrantMgr* aReentrantMgr = aModule->sketchReentranceMgr(); - if (aReentrantMgr->isInternalEditActive()) { - std::shared_ptr aUpdMsg = - std::dynamic_pointer_cast(theMessage); - std::set anObjects = aUpdMsg->objects(); - aReentrantMgr->appendCreatedObjects(anObjects); - } + aReentrantMgr->setReentrantMessage(theMessage); } + #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER aCurrentInfoStr = getObjectsInfo(myConflictingObjects); qDebug(QString("RESULT: current objects count = %1:%2\n") diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.cpp b/src/PartSet/PartSet_SketcherReentrantMgr.cpp index dc1ec3678..8af09b3fa 100644 --- a/src/PartSet/PartSet_SketcherReentrantMgr.cpp +++ b/src/PartSet/PartSet_SketcherReentrantMgr.cpp @@ -8,6 +8,7 @@ #include "ModelAPI_Session.h" #include "ModelAPI_AttributeString.h" #include "ModelAPI_AttributeRefAttr.h" +#include "ModelAPI_EventReentrantMessage.h" #include "GeomDataAPI_Point2D.h" @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,13 +40,14 @@ #include +//#define DEBUG_RESTART + PartSet_SketcherReentrantMgr::PartSet_SketcherReentrantMgr(ModuleBase_IWorkshop* theWorkshop) : QObject(theWorkshop), myWorkshop(theWorkshop), myRestartingMode(RM_None), myIsFlagsBlocked(false), myIsInternalEditOperation(false), - myIsValueChangedBlocked(false), myInternalActiveWidget(0), myNoMoreWidgetsAttribute("") { @@ -118,7 +121,8 @@ void PartSet_SketcherReentrantMgr::operationStarted(ModuleBase_Operation* theOpe ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast( myWorkshop->currentOperation()); CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch(); - copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch); + if (myPreviousFeature.get() && myPreviousFeature->data()->isValid()) // it is not removed + copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch); } resetFlags(); } @@ -194,8 +198,8 @@ bool PartSet_SketcherReentrantMgr::processMousePressed(ModuleBase_IViewWindow* / return isActiveMgr() && myIsInternalEditOperation; } -bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWnd, - QMouseEvent* theEvent) +bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWindow, + QMouseEvent* theEvent) { bool aProcessed = false; if (!isActiveMgr()) @@ -228,7 +232,16 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* QList aPreSelected = aSelection->getSelected(ModuleBase_ISelection::AllControls); + myClickedSketchPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, + module()->sketchMgr()->activeSketch()); + if (!aPreSelected.empty()) + module()->getGeomSelection(aPreSelected.first(), mySelectedObject, mySelectedAttribute); + restartOperation(); + myClickedSketchPoint = std::shared_ptr(); + mySelectedObject = ObjectPtr(); + mySelectedAttribute = AttributePtr(); + myPreviousFeature = FeaturePtr(); aProcessed = true; @@ -252,8 +265,8 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* // there are created objects to replace the object depending on created feature kind aSelectedPrs = generatePreSelection(); } - aMouseProcessor->setPreSelection(aSelectedPrs, theWnd, theEvent); - //aPoint2DWdg->mouseReleased(theWnd, theEvent); + aMouseProcessor->setPreSelection(aSelectedPrs, theWindow, theEvent); + //aPoint2DWdg->mouseReleased(theWindow, theEvent); //if (!aPreSelected.empty()) // aPoint2DWdg->setPreSelection(ModuleBase_ViewerPrsPtr()); } @@ -264,6 +277,20 @@ bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* return aProcessed; } +//****************************************************** +void PartSet_SketcherReentrantMgr::setReentrantPreSelection( + const std::shared_ptr& theMessage) +{ + ReentrantMessagePtr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (!aReentrantMessage.get()) + return; + + aReentrantMessage->setSelectedObject(mySelectedObject); + aReentrantMessage->setSelectedAttribute(mySelectedAttribute); + aReentrantMessage->setClickedPoint(myClickedSketchPoint); +} + void PartSet_SketcherReentrantMgr::onWidgetActivated() { if (!isActiveMgr()) @@ -283,6 +310,10 @@ void PartSet_SketcherReentrantMgr::onWidgetActivated() void PartSet_SketcherReentrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID) { +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::onNoMoreWidgets" << std::endl; +#endif + if (!isActiveMgr()) return; @@ -369,14 +400,12 @@ void PartSet_SketcherReentrantMgr::onVertexSelected() void PartSet_SketcherReentrantMgr::onAfterValuesChangedInPropertyPanel() { - // blocked flag in order to avoid circling when storeValue will be applied in - // this method to cached widget - if (myIsValueChangedBlocked) - return; if (isInternalEditActive()) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myWorkshop->currentOperation()); ModuleBase_ModelWidget* aWidget = (ModuleBase_ModelWidget*)sender(); - if (!aWidget->isModifiedInEdit()) + if (!aWidget->isModifiedInEdit().empty()) restartOperation(); } } @@ -394,28 +423,6 @@ bool PartSet_SketcherReentrantMgr::canBeCommittedByPreselection() return !isActiveMgr() || myRestartingMode == RM_None; } -void PartSet_SketcherReentrantMgr::appendCreatedObjects(const std::set& theObjects) -{ - if (!myIsFlagsBlocked) // we need to collect objects only when launch operation is called - return; - - FeaturePtr aCurrentFeature; - ModuleBase_OperationFeature* aFOperation = dynamic_cast - (myWorkshop->currentOperation()); - if (aFOperation) - aCurrentFeature = aFOperation->feature(); - - - for (std::set::const_iterator anIt = theObjects.begin(); - anIt != theObjects.end(); ++anIt) { - FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); - if (aFeature == aCurrentFeature) - continue; - if (myCreatedFeatures.find(aFeature) == myCreatedFeatures.end()) - myCreatedFeatures.insert(aFeature); - } -} - bool PartSet_SketcherReentrantMgr::isActiveMgr() const { ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation(); @@ -435,6 +442,10 @@ bool PartSet_SketcherReentrantMgr::isActiveMgr() const bool PartSet_SketcherReentrantMgr::startInternalEdit(const std::string& thePreviousAttributeID) { +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::startInternalEdit" << std::endl; +#endif + 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 @@ -520,32 +531,30 @@ void PartSet_SketcherReentrantMgr::beforeStopInternalEdit() void PartSet_SketcherReentrantMgr::restartOperation() { +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::restartOperation" << std::endl; +#endif + if (myIsInternalEditOperation) { ModuleBase_OperationFeature* aFOperation = dynamic_cast( myWorkshop->currentOperation()); if (aFOperation) { - // obtain widgets(attributes) which content should be applied to attributes of new feature - ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); - ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); - const QList& aWidgets = aPanel->modelWidgets(); - QList aValueWidgets; - for (int i = 0, aSize = aWidgets.size(); i < aSize; i++) { - ModuleBase_ModelWidget* aWidget = aWidgets[i]; - if (!aWidget->isModifiedInEdit()) { - aValueWidgets.append(aWidget); - // the widget is cashed to fill feature of new operation by the current widget value - // we set empty parent to the widget in order to remove it ourselves. Reason: restart - // operation will clear property panel and delete all widgets. This widget should be - // removed only after applying value of the widget to new created feature. - aWidget->setParent(0); - } - } + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + QList aPreSelected = + aSelection->getSelected(ModuleBase_ISelection::AllControls); + + + + if (myInternalFeature.get()) + copyReetntrantAttributes(myInternalFeature, aFOperation->feature(), + module()->sketchMgr()->activeSketch()); 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 @@ -554,21 +563,6 @@ void PartSet_SketcherReentrantMgr::restartOperation() onNoMoreWidgets(myNoMoreWidgetsAttribute); myNoMoreWidgetsAttribute = ""; } - - // filling new feature by the previous value of active widget - // (e.g. circle_type in macro Circle) - ModuleBase_OperationFeature* aFOperation = dynamic_cast( - myWorkshop->currentOperation()); - myIsValueChangedBlocked = true; // flag to avoid onAfterValuesChangedInPropertyPanel slot - for (int i = 0, aSize = aValueWidgets.size(); i < aSize; i++) { - ModuleBase_ModelWidget* aWidget = aValueWidgets[i]; - aWidget->setEditingMode(false); - aWidget->setFeature(aFOperation->feature()); - aWidget->storeValue(); - // we must delete this widget - delete aWidget; - } - myIsValueChangedBlocked = false; } } } @@ -584,6 +578,11 @@ void PartSet_SketcherReentrantMgr::createInternalFeature() CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch(); myInternalFeature = aSketch->addFeature(anOperationFeature->getKind()); +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::createInternalFeature: " + << myInternalFeature->data()->name() << std::endl; +#endif + bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature, aSketch, false); XGUI_PropertyPanel* aPropertyPanel = dynamic_cast @@ -618,6 +617,10 @@ void PartSet_SketcherReentrantMgr::createInternalFeature() void PartSet_SketcherReentrantMgr::deleteInternalFeature() { +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::deleteInternalFeature: " + << myInternalFeature->data()->name() << std::endl; +#endif if (myInternalActiveWidget) { ModuleBase_WidgetSelector* aWSelector = dynamic_cast(myInternalActiveWidget); @@ -640,22 +643,28 @@ void PartSet_SketcherReentrantMgr::resetFlags() myIsInternalEditOperation = false; updateAcceptAllAction(); myRestartingMode = RM_None; - myCreatedFeatures.clear(); + myReentrantMessage = std::shared_ptr(); } } bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature, const FeaturePtr& theNewFeature, const CompositeFeaturePtr& theSketch, - const bool isTemporary) + const bool /*isTemporary*/) { bool aChanged = false; if (!theSourceFeature.get() || !theSourceFeature->data().get() || !theSourceFeature->data()->isValid()) return aChanged; +#ifdef DEBUG_RESTART + std::cout << "PartSet_SketcherReentrantMgr::copyReetntrantAttributes from '" + << theSourceFeature->data()->name() << "' to '" << theNewFeature->data()->name() + << "'" << std::endl; +#endif + std::string aFeatureKind = theSourceFeature->getKind(); - if (aFeatureKind == SketchPlugin_Line::ID()) { + /*if (aFeatureKind == SketchPlugin_Line::ID()) { // Initialize new line with first point equal to end of previous std::shared_ptr aSFData = theSourceFeature->data(); std::shared_ptr aSPoint = std::dynamic_pointer_cast( @@ -670,22 +679,23 @@ bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& th aSFData->attribute(SketchPlugin_Line::END_ID())); aNPoint->setValue(aSPoint->x(), aSPoint->y()); } - else if (aFeatureKind == SketchPlugin_MacroCircle::ID()) { + else*/ if (aFeatureKind == SketchPlugin_MacroCircle::ID()) { // set circle type - std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE(); + /*std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE(); AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId); AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId); - aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value()); + if (aNewFeatureTypeAttr->value() != aTypeAttributeId) // do nothing if there is no changes + aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value()); //ModuleBase_Tools::flushUpdated(theNewFeature); - aChanged = true; + aChanged = true;*/ } else if (aFeatureKind == SketchPlugin_MacroArc::ID()) { // set arc type std::string aTypeAttributeId = SketchPlugin_MacroArc::ARC_TYPE(); AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId); AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId); - aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value()); - + if (aNewFeatureTypeAttr->value() != aTypeAttributeId) // do nothing if there is no changes + 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()) { @@ -708,6 +718,41 @@ bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& th //ModuleBase_Tools::flushUpdated(theNewFeature); aChanged = true; } + else if (aFeatureKind == SketchPlugin_Trim::ID()) { + /*std::shared_ptr aRefSelectedAttr = + std::dynamic_pointer_cast( + theSourceFeature->data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); + std::shared_ptr aNRefSelectedAttr = + std::dynamic_pointer_cast( + theNewFeature->data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); + aNRefSelectedAttr->setValue(aRefSelectedAttr->value());*/ + + std::shared_ptr aRefPreviewAttr = + std::dynamic_pointer_cast( + theSourceFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + std::shared_ptr aNRefPreviewAttr = + std::dynamic_pointer_cast( + theNewFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + aNRefPreviewAttr->setValue(aRefPreviewAttr->value()); + + /*std::shared_ptr aPointSelectedAttr = + std::dynamic_pointer_cast( + theSourceFeature->data()->attribute(SketchPlugin_Trim::SELECTED_POINT())); + std::shared_ptr aNPointSelectedAttr = + std::dynamic_pointer_cast( + theNewFeature->data()->attribute(SketchPlugin_Trim::SELECTED_POINT())); + aNPointSelectedAttr->setValue(aPointSelectedAttr->x(), aPointSelectedAttr->y()); + */ + std::shared_ptr aPointPreviewAttr = + std::dynamic_pointer_cast( + theSourceFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); + std::shared_ptr aNPointPreviewAttr = + std::dynamic_pointer_cast( + theNewFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); + aNPointPreviewAttr->setValue(aPointPreviewAttr->x(), aPointPreviewAttr->y()); + + aChanged = true; + } return aChanged; } diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.h b/src/PartSet/PartSet_SketcherReentrantMgr.h index 96ff87753..3fc5c2246 100644 --- a/src/PartSet/PartSet_SketcherReentrantMgr.h +++ b/src/PartSet/PartSet_SketcherReentrantMgr.h @@ -8,6 +8,7 @@ #include #include +#include #include @@ -23,6 +24,9 @@ class QMouseEvent; class XGUI_Workshop; class PartSet_Module; class ModuleBase_ViewerPrs; +class Events_Message; +class ModelAPI_Attribute; +class GeomAPI_Pnt2d; /// \ingroup PartSet_SketcherReentrantMgr /// It provides reentrant create operations in sketch, that is when all inputs are valid, @@ -102,10 +106,17 @@ public: /// Returns false if the reentrant mode of the operation is not empty. bool canBeCommittedByPreselection(); - /// Put information about created objects into a cash. It will be processed in - /// restart operation. - /// \param theObjects a list of created objects - void appendCreatedObjects(const std::set& theObjects); + /// Fills reentrant message during restarting operation + /// \param theMessage reentrant message + void setReentrantMessage(const std::shared_ptr& theMessage) + { myReentrantMessage = theMessage; } + + /// Returnss reentrant message + std::shared_ptr reentrantMessage() const { return myReentrantMessage; } + + /// Put current selection into reentrant message + /// \param theMessage a message of reentrant operation + void setReentrantPreSelection(const std::shared_ptr& theMessage); private slots: /// SLOT, that is called by a widget activating in the property panel @@ -195,14 +206,17 @@ private: RestartingMode myRestartingMode; /// automatical restarting mode flag bool myIsFlagsBlocked; /// true when reset of flags should not be perfromed bool myIsInternalEditOperation; /// true when the 'internal' edit is started - bool myIsValueChangedBlocked; /// blocked flag to avoid circling by value changed FeaturePtr myPreviousFeature; /// feature of the previous operation, which is restarted - std::set myCreatedFeatures; /// list of created features by restart operation FeaturePtr myInternalFeature; QWidget* myInternalWidget; ModuleBase_ModelWidget* myInternalActiveWidget; std::string myNoMoreWidgetsAttribute; + + std::shared_ptr myReentrantMessage; /// message obtained by operation restart + ObjectPtr mySelectedObject; /// cashed selected object + std::shared_ptr mySelectedAttribute; /// cashed selected attribute + std::shared_ptr myClickedSketchPoint; /// cashed clicked point }; #endif diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index 37cee3d67..0976d01ce 100755 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include #include @@ -73,6 +75,8 @@ #include #include +#include + #ifdef _DEBUG #include #endif @@ -643,6 +647,18 @@ std::shared_ptr PartSet_Tools::getPoint( return std::shared_ptr(); } +std::shared_ptr PartSet_Tools::getPnt2d(QMouseEvent* theEvent, + ModuleBase_IViewWindow* theWindow, + const FeaturePtr& theSketch) +{ + gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); + double aX, anY; + Handle(V3d_View) aView = theWindow->v3dView(); + PartSet_Tools::convertTo2D(aPnt, theSketch, aView, aX, anY); + + return std::shared_ptr(new GeomAPI_Pnt2d(aX, anY)); +} + FeaturePtr findFirstCoincidenceByData(const DataPtr& theData, std::shared_ptr thePoint) { diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index 1b9937dd1..1429f9d29 100755 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -25,6 +25,7 @@ #include class V3d_View; +class ModuleBase_IViewWindow; class ModuleBase_ViewerPrs; class ModuleBase_IWorkshop; class GeomDataAPI_Point2D; @@ -36,6 +37,8 @@ class GeomAPI_Edge; class GeomAPI_Vertex; class ModelAPI_Result; +class QMouseEvent; + /*! * \class PartSet_Tools * \ingroup Modules @@ -214,6 +217,16 @@ public: static std::shared_ptr getPoint(std::shared_ptr& theFeature, const std::string& theAttribute); + /** + * Convertes parameters into a geom point + * \theEvent a Qt event to find mouse position + * \param theWindow view window to define eye of view + * \param theSketch to convert 3D point coordinates into coorditates of the sketch plane + */ + static std::shared_ptr getPnt2d(QMouseEvent* theEvent, + ModuleBase_IViewWindow* theWindow, + const FeaturePtr& theSketch); + /** * Gets all references to the feature, take coincidence constraint features, get point 2d attributes * and compare the point value to be equal with the given. Returns the first feature, which has diff --git a/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp b/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp index e8c4abf8c..0fecb7ed7 100644 --- a/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp +++ b/src/PartSet/PartSet_WidgetFeaturePointSelector.cpp @@ -170,11 +170,6 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature( if (!anObject.get()) return aFilled; - gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); - double aX, anY; - Handle(V3d_View) aView = theWindow->v3dView(); - PartSet_Tools::convertTo2D(aPnt, mySketch, aView, aX, anY); - std::shared_ptr aRef = std::dynamic_pointer_cast( feature()->data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); @@ -183,7 +178,8 @@ bool PartSet_WidgetFeaturePointSelector::fillFeature( std::shared_ptr anAttributePoint = std::dynamic_pointer_cast( feature()->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); - anAttributePoint->setValue(aX, anY); + std::shared_ptr aPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch); + anAttributePoint->setValue(aPoint); // redisplay AIS presentation in viewer #ifndef HIGHLIGHT_STAYS_PROBLEM // an attempt to clear highlighted item in the viewer: but of OCCT diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 8ac8414ee..96e7591c9 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -31,6 +31,7 @@ SET(PROJECT_HEADERS SketchPlugin_IntersectionPoint.h SketchPlugin_Line.h SketchPlugin_MacroArc.h + SketchPlugin_MacroArcReentrantMessage.h SketchPlugin_MacroCircle.h SketchPlugin_MultiRotation.h SketchPlugin_MultiTranslation.h diff --git a/src/SketchPlugin/SketchPlugin_Line.cpp b/src/SketchPlugin/SketchPlugin_Line.cpp index 10e1ed235..025a98b43 100644 --- a/src/SketchPlugin/SketchPlugin_Line.cpp +++ b/src/SketchPlugin/SketchPlugin_Line.cpp @@ -6,7 +6,10 @@ #include "SketchPlugin_Line.h" #include "SketchPlugin_Sketch.h" +#include "SketchPlugin_ConstraintCoincidence.h" + #include +#include #include #include #include @@ -64,6 +67,14 @@ void SketchPlugin_Line::execute() aConstr->setShape(anEdge); aConstr->setIsInHistory(false); setResult(aConstr); + + static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new ModelAPI_EventReentrantMessage(anId, 0)); + aMessage->setCreatedFeature(ModelAPI_Feature::feature( + data()->attribute(START_ID())->owner())); + Events_Loop::loop()->send(aMessage); + Events_Loop::loop()->flush(anId); } } } @@ -83,6 +94,33 @@ void SketchPlugin_Line::move(double theDeltaX, double theDeltaY) aPoint2->move(theDeltaX, theDeltaY); } +std::string SketchPlugin_Line::processEvent(const std::shared_ptr& theMessage) +{ + std::string aFilledAttributeName; + + std::shared_ptr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage.get()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + + // Initialize new line with first point equal to end of previous + std::shared_ptr aSFData = aCreatedFeature->data(); + std::shared_ptr aSPoint = std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aNFData = data(); + std::shared_ptr aNPoint = std::dynamic_pointer_cast( + aNFData->attribute(SketchPlugin_Line::START_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + SketchPlugin_ConstraintCoincidence::createCoincidenceFeature(sketch(), aSPoint, aNPoint); + + aNPoint = std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + + } + return aFilledAttributeName; +} + double SketchPlugin_Line::distanceToPoint(const std::shared_ptr& thePoint) { double aDelta = 0; diff --git a/src/SketchPlugin/SketchPlugin_Line.h b/src/SketchPlugin/SketchPlugin_Line.h index e24e90e54..173c2c356 100644 --- a/src/SketchPlugin/SketchPlugin_Line.h +++ b/src/SketchPlugin/SketchPlugin_Line.h @@ -7,6 +7,8 @@ #ifndef SketchPlugin_Line_H_ #define SketchPlugin_Line_H_ +#include + #include "SketchPlugin.h" #include #include @@ -18,7 +20,8 @@ class GeomAPI_Pnt2d; * \ingroup Plugins * \brief Feature for creation of the new part in PartSet. */ -class SketchPlugin_Line : public SketchPlugin_SketchEntity +class SketchPlugin_Line : public SketchPlugin_SketchEntity, + public ModelAPI_IReentrant { public: /// Arc feature kind @@ -64,6 +67,11 @@ class SketchPlugin_Line : public SketchPlugin_SketchEntity /// \param theDeltaY the delta for Y coordinate is moved SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + /// Apply information of the message to current object. It fills start attribute of + /// the currrent feature by last attribute of the message feature, build coincidence + /// if message has selected object + virtual std::string processEvent(const std::shared_ptr& theMessage); + /// Return the distance between the feature and the point /// \param thePoint the point double distanceToPoint(const std::shared_ptr& thePoint); diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.cpp b/src/SketchPlugin/SketchPlugin_MacroArc.cpp index cd199d936..6a0fff2dc 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroArc.cpp @@ -10,10 +10,12 @@ #include "SketchPlugin_ConstraintTangent.h" #include "SketchPlugin_Sketch.h" #include "SketchPlugin_Tools.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include #include #include +#include #include #include @@ -82,12 +84,16 @@ void SketchPlugin_MacroArc::initAttributes() data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(EDIT_ARC_TYPE_ID(), ModelAPI_AttributeString::typeId()); + boolean(REVERSED_ID())->setValue(false); + string(EDIT_ARC_TYPE_ID())->setValue(""); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ARC_TYPE_ID()); } void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) @@ -268,6 +274,81 @@ void SketchPlugin_MacroArc::execute() ObjectPtr(), false); } + + // message to init reentrant operation + static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new SketchPlugin_MacroArcReentrantMessage(anId, 0)); + + std::string anEditArcType = string(EDIT_ARC_TYPE_ID())->value(); + aMessage->setTypeOfCreation(!anEditArcType.empty() ? anEditArcType : anArcType); + aMessage->setCreatedFeature(anArcFeature); + Events_Loop::loop()->send(aMessage); + Events_Loop::loop()->flush(anId); +} + +std::string SketchPlugin_MacroArc::processEvent(const std::shared_ptr& theMessage) +{ + std::string aFilledAttributeName; + std::shared_ptr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage.get()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + std::string anArcType = aReentrantMessage->typeOfCreation(); + + string(ARC_TYPE())->setValue(anArcType); + + aFilledAttributeName = ARC_TYPE(); + if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) { + aFilledAttributeName = TANGENT_POINT_ID(); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + aRefAttr->setAttr(aCreatedFeature->attribute(SketchPlugin_Arc::END_ID())); + } + else { + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) { + if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS() || + anArcType == ARC_TYPE_BY_THREE_POINTS()) { + std::string aReferenceAttributeName; + if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) { + aFilledAttributeName = CENTER_POINT_ID(); + aReferenceAttributeName = CENTER_POINT_REF_ID(); + } + else { + aFilledAttributeName = START_POINT_2_ID(); + aReferenceAttributeName = START_POINT_REF_ID(); + } + // fill 2d point attribute + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + aPointAttr->setValue(aClickedPoint); + // fill reference attribute + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aReferenceAttributeName)); + if (aRefAttr.get()) { + if (anAttribute.get()) + aRefAttr->setAttr(anAttribute); + else if (anObject.get()) { + // if presentation of previous reentrant macro arc is used, the object is invalid, + // we should use result of previous feature of the message(Arc) + if (!anObject->data()->isValid()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + anObject = aCreatedFeature->lastResult(); + } + aRefAttr->setObject(anObject); + } + } + } + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; } FeaturePtr SketchPlugin_MacroArc::createArcFeature() diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.h b/src/SketchPlugin/SketchPlugin_MacroArc.h index cc49b0e02..812978381 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.h +++ b/src/SketchPlugin/SketchPlugin_MacroArc.h @@ -7,8 +7,9 @@ #ifndef SketchPlugin_MacroArc_H_ #define SketchPlugin_MacroArc_H_ -#include "SketchPlugin.h" +#include +#include "SketchPlugin.h" #include "SketchPlugin_SketchEntity.h" #include @@ -24,7 +25,8 @@ class GeomAPI_Pnt2d; * it is calculated if all attributes are initialized. */ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, - public GeomAPI_IPresentable + public GeomAPI_IPresentable, + public ModelAPI_IReentrant { public: /// Arc feature kind @@ -157,6 +159,13 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, return ID; } + /// Arc angle. + static const std::string& EDIT_ARC_TYPE_ID() + { + static const std::string ID("edit_arc_type"); + return ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { @@ -189,6 +198,10 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;}; + /// Apply information of the message to current object. It fills reference object, + /// tangent type and tangent point refence in case of tangent arc + virtual std::string processEvent(const std::shared_ptr& theMessage); + /// Use plugin manager for features creation. SketchPlugin_MacroArc(); diff --git a/src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h b/src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h new file mode 100644 index 000000000..5ad9a8ca1 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MacroArcReentrantMessage.h @@ -0,0 +1,50 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MacroArcReentrantMessage.h +// Created: 01 Apr 2017 +// Author: Natalia ERMOLAEVA + +#ifndef SketchPlugin_MacroArcReentrantMessage_H_ +#define SketchPlugin_MacroArcReentrantMessage_H_ + +#include +#include + +#include + +#include + +/// Message that style of visualization of parameter is changed. +/// It will be shown as expression or value +class SketchPlugin_MacroArcReentrantMessage : public ModelAPI_EventReentrantMessage +{ +public: + /// Creates an empty message + SKETCHPLUGIN_EXPORT SketchPlugin_MacroArcReentrantMessage(const Events_ID theID, + const void* theSender = 0) + : ModelAPI_EventReentrantMessage(theID, theSender) {} + /// The virtual destructor + SKETCHPLUGIN_EXPORT virtual ~SketchPlugin_MacroArcReentrantMessage() {} + /// Static. Returns EventID of the message. + + inline static Events_ID eventId() + { + static const char * MY_EVENT_MACRO_ARC_MESSAGE_ID("MacroArcReentrantMessage"); + return Events_Loop::eventByName(MY_EVENT_MACRO_ARC_MESSAGE_ID); + } + + /// Stores type of creation + /// \param the type + SKETCHPLUGIN_EXPORT void setTypeOfCreation(const std::string& theType) + { myTypeOfCreation = theType; } + + /// Returns type of creation + /// \return the type + SKETCHPLUGIN_EXPORT std::string typeOfCreation() const { return myTypeOfCreation; } + +private: + std::string myTypeOfCreation; ///< to know what parameters of new feature should be filled +}; + + +#endif diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp index da9625e23..b865ec374 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp @@ -9,12 +9,14 @@ #include "SketchPlugin_Circle.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Tools.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include #include #include #include #include +#include #include #include @@ -54,6 +56,7 @@ SketchPlugin_MacroCircle::SketchPlugin_MacroCircle() void SketchPlugin_MacroCircle::initAttributes() { data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(EDIT_CIRCLE_TYPE(), ModelAPI_AttributeString::typeId()); data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); @@ -70,11 +73,14 @@ void SketchPlugin_MacroCircle::initAttributes() data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); + string(EDIT_CIRCLE_TYPE())->setValue(""); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_CIRCLE_TYPE()); } void SketchPlugin_MacroCircle::execute() @@ -86,6 +92,69 @@ void SketchPlugin_MacroCircle::execute() constraintsForCircleByCenterAndPassed(aCircle); else if (aType == CIRCLE_TYPE_BY_THREE_POINTS()) constraintsForCircleByThreePoints(aCircle); + + // message to init reentrant operation + static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new SketchPlugin_MacroArcReentrantMessage(anId, 0)); + + std::string anEditType = string(EDIT_CIRCLE_TYPE())->value(); + aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType); + aMessage->setCreatedFeature(aCircle); + Events_Loop::loop()->send(aMessage); + Events_Loop::loop()->flush(anId); +} + +std::string SketchPlugin_MacroCircle::processEvent(const std::shared_ptr& theMessage) +{ + std::string aFilledAttributeName; + std::shared_ptr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage.get()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + std::string aCircleType = aReentrantMessage->typeOfCreation(); + + string(CIRCLE_TYPE())->setValue(aCircleType); + + aFilledAttributeName = CIRCLE_TYPE(); + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) { + std::string aReferenceAttributeName; + if (aCircleType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) { + aFilledAttributeName = CENTER_POINT_ID(); + aReferenceAttributeName = CENTER_POINT_REF_ID(); + } + else { + aFilledAttributeName = FIRST_POINT_ID(); + aReferenceAttributeName = FIRST_POINT_REF_ID(); + } + // fill 2d point attribute + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + aPointAttr->setValue(aClickedPoint); + // fill reference attribute + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aReferenceAttributeName)); + if (aRefAttr.get()) { + if (anAttribute.get()) + aRefAttr->setAttr(anAttribute); + else if (anObject.get()) { + // if presentation of previous reentrant macro arc is used, the object is invalid, + // we should use result of previous feature of the message(Arc) + if (!anObject->data()->isValid()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + anObject = aCreatedFeature->lastResult(); + } + aRefAttr->setObject(anObject); + } + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; } void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature) diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.h b/src/SketchPlugin/SketchPlugin_MacroCircle.h index 6bf46f36c..4e1bfeb22 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.h +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.h @@ -7,6 +7,8 @@ #ifndef SketchPlugin_MacroCircle_H_ #define SketchPlugin_MacroCircle_H_ +#include + #include "SketchPlugin.h" #include "SketchPlugin_SketchEntity.h" @@ -21,7 +23,8 @@ class GeomAPI_Pnt2d; * \brief Feature for creation of the new circle in Sketch. */ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity, - public GeomAPI_IPresentable + public GeomAPI_IPresentable, + public ModelAPI_IReentrant { public: /// Circle feature kind @@ -37,6 +40,12 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity, return ID; } + inline static const std::string& EDIT_CIRCLE_TYPE() + { + static const std::string ID("edit_circle_type"); + return ID; + } + /// Creation method by center and passed point. inline static const std::string& CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS() { @@ -159,6 +168,10 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity, SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;}; + /// Apply information of the message to current object. It fills reference object, + /// tangent type and tangent point refence in case of tangent arc + virtual std::string processEvent(const std::shared_ptr& theMessage); + /// Use plugin manager for features creation SketchPlugin_MacroCircle(); diff --git a/src/SketchPlugin/SketchPlugin_Trim.cpp b/src/SketchPlugin/SketchPlugin_Trim.cpp index 46b01dee1..e94f4b10c 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.cpp +++ b/src/SketchPlugin/SketchPlugin_Trim.cpp @@ -41,6 +41,8 @@ #include #include +#include + #include #include #include @@ -51,11 +53,17 @@ #include -#define DEBUG_TRIM +//#define DEBUG_TRIM_METHODS +//#define DEBUG_TRIM + #ifdef DEBUG_TRIM #include #endif +#ifdef DEBUG_TRIM_METHODS +#include +#endif + static const double PI = 3.141592653589793238463; static const std::string OPERATION_HIGHLIGHT_COLOR() { return "128, 0, 0"; } @@ -174,8 +182,8 @@ std::shared_ptr SketchPlugin_Trim::convertPoint( void SketchPlugin_Trim::execute() { -#ifdef DEBUG_TRIM - std::cout << "SketchPlugin_Trim::execute" << std::endl; +#ifdef DEBUG_TRIM_METHODS + std::cout << "SketchPlugin_Trim::execute: " << data()->name() << std::endl; #endif SketchPlugin_Sketch* aSketch = sketch(); @@ -199,8 +207,16 @@ void SketchPlugin_Trim::execute() AttributeReferencePtr aPreviewObjectAttr = std::dynamic_pointer_cast( data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + + ObjectPtr aPreviewObject = aPreviewObjectAttr->value(); + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( + data()->attribute(PREVIEW_POINT())); + std::shared_ptr aPreviewPnt2d = aPoint->pnt(); + // nullify pointer of preview attribute aPreviewObjectAttr->setValue(ResultPtr()); + bool anIsEqualPreviewAndSelected = aPreviewObject == aBaseObject; + /// points of trim std::shared_ptr aStartShapePoint, aLastShapePoint; #ifdef DEBUG_TRIM @@ -269,7 +285,7 @@ void SketchPlugin_Trim::execute() std::set aFurtherCoincidences; std::set> aModifiedAttributes; const std::string& aKind = aBaseFeature->getKind(); - FeaturePtr aReplacingFeature; + FeaturePtr aReplacingFeature, aNewFeature; if (aKind == SketchPlugin_Circle::ID()) { aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d, aFurtherCoincidences, aModifiedAttributes); @@ -281,12 +297,12 @@ void SketchPlugin_Trim::execute() aBaseObjectAttr->setObject(ResultPtr()); } else if (aKind == SketchPlugin_Line::ID()) { - trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, - aFurtherCoincidences, aModifiedAttributes); + aNewFeature = trimLine(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } else if (aKind == SketchPlugin_Arc::ID()) { - trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, - aFurtherCoincidences, aModifiedAttributes); + aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes, + aFurtherCoincidences, aModifiedAttributes); } // constraints to end points of trim feature @@ -398,11 +414,116 @@ void SketchPlugin_Trim::execute() Events_Loop::loop()->setFlushed(anUpdateEvent, true); } + if (anIsEqualPreviewAndSelected) { + // equal preview and selected objects + // nothing to do if the preview and selected objects are different + if (aReplacingResult.get()) { // base object was removed + aPreviewObject = aReplacingResult; + //aMessage->setSelectedObject(aReplacingResult); + + GeomShapePtr aSelectedShape = aReplacingResult->shape(); + std::shared_ptr aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(), + aPreviewPnt2d->y()); + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aSelectedShape, aPreviewPnt, aProjectedPoint)) { + bool aValue = true; + } + //aBaseShape = aShape; + +#ifdef DEBUG_TRIM_METHODS + if (!aSelectedShape.get()) + std::cout << "Set empty selected object" << std::endl; + else + std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl; +#endif + bool aValue = true; + } + else { + aPreviewObject = ObjectPtr(); + + aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one + aBaseObject = getFeatureResult(aBaseFeature); + std::shared_ptr aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(), + aPreviewPnt2d->y()); + ResultPtr aBaseResult = std::dynamic_pointer_cast(aBaseObject); + if (aBaseResult) { + GeomShapePtr aShape = aBaseResult->shape(); + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint)) + aPreviewObject = aBaseResult; + } + if (!aPreviewObject.get() && aNewFeature.get()) { + ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature); + if (aNewFeatureResult.get()) { + GeomShapePtr aShape = aNewFeatureResult->shape(); + std::shared_ptr aProjectedPoint; + if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPreviewPnt, aProjectedPoint)) + aPreviewObject = aNewFeatureResult; + } + } + } + } + if (aPreviewObject.get()) { + static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new ModelAPI_EventReentrantMessage(anId, 0)); + aMessage->setSelectedObject(aPreviewObject); + Events_Loop::loop()->send(aMessage); + Events_Loop::loop()->flush(anId); + } #ifdef DEBUG_TRIM std::cout << "SketchPlugin_Trim::done" << std::endl; #endif } +std::string SketchPlugin_Trim::processEvent(const std::shared_ptr& theMessage) +{ +#ifdef DEBUG_TRIM_METHODS + std::cout << "SketchPlugin_Trim::processEvent:" << data()->name() << std::endl; +#endif + + std::string aFilledAttributeName; + + std::shared_ptr aMessage = + std::dynamic_pointer_cast(theMessage); + if (aMessage.get()) { + ObjectPtr anObject = aMessage->selectedObject(); + std::shared_ptr aPoint = aMessage->clickedPoint(); + + if (anObject.get() && aPoint.get()) { + std::shared_ptr aRefSelectedAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); + std::shared_ptr aRefPreviewAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::PREVIEW_OBJECT())); + aRefSelectedAttr->setValue(anObject); + aRefPreviewAttr->setValue(anObject); + + std::shared_ptr aPointSelectedAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::SELECTED_POINT())); + std::shared_ptr aPointPreviewAttr = + std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Trim::PREVIEW_POINT())); + aPointSelectedAttr->setValue(aPoint); + aPointPreviewAttr->setValue(aPoint); + + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + + GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT()); +#ifdef DEBUG_TRIM_METHODS + if (!aSelectedShape.get()) + std::cout << "Set empty selected object" << std::endl; + else + std::cout << "Set shape with ShapeType: " << aSelectedShape->shapeTypeStr() << std::endl; +#endif + aFilledAttributeName = SketchPlugin_Trim::SELECTED_OBJECT(); + } + } + return aFilledAttributeName; +} + bool SketchPlugin_Trim::setCoincidenceToAttribute(const AttributePtr& theAttribute, const std::set& theFurtherCoincidences) { @@ -470,6 +591,10 @@ bool SketchPlugin_Trim::isMacro() const AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious) { +#ifdef DEBUG_TRIM_METHODS + std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl; +#endif + AISObjectPtr anAIS = thePrevious; std::list > aShapes; @@ -744,12 +869,14 @@ void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttri Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED)); } -void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartShapePoint, +FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::map >& theBaseRefAttributes, std::set& thePoints, std::set>& theModifiedAttributes) { + FeaturePtr anNewFeature; + // Check the base objects are initialized. AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); @@ -809,7 +936,7 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS // result is two lines: start line point - start shape point, // last shape point - last line point // create second line - FeaturePtr anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint); + anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint); thePoints.insert(std::dynamic_pointer_cast (anNewFeature->attribute(SketchPlugin_Line::START_ID()))); @@ -830,14 +957,16 @@ void SketchPlugin_Trim::trimLine(const std::shared_ptr& theStartS getFeatureResult(anNewFeature)); } + return anNewFeature; } -void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartShapePoint, +FeaturePtr SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::map >& theBaseRefAttributes, std::set& thePoints, std::set>& theModifiedAttributes) { + FeaturePtr anNewFeature; // Check the base objects are initialized. AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast( data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT())); @@ -892,14 +1021,14 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh else { // result is two arcs: start arc point - start shape point, last shape point - last arc point // create second arc - FeaturePtr anArcFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint); + anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); std::string aModifiedAttribute = SketchPlugin_Arc::END_ID(); theModifiedAttributes.insert( std::make_pair(aBaseFeature->attribute(aModifiedAttribute), - anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + anNewFeature->attribute(SketchPlugin_Arc::END_ID()))); // modify base arc fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint); @@ -908,20 +1037,22 @@ void SketchPlugin_Trim::trimArc(const std::shared_ptr& theStartSh (aBaseFeature->attribute(aModifiedAttribute))); // equal Radius constraint for arcs - anArcFeature->execute(); // we need the created arc result to set equal constraint + anNewFeature->execute(); // we need the created arc result to set equal constraint createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(), getFeatureResult(aBaseFeature), - getFeatureResult(anArcFeature)); + getFeatureResult(anNewFeature)); // coincident centers constraint createConstraint(SketchPlugin_ConstraintCoincidence::ID(), aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID()), - anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID())); + anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())); +#ifdef DEBUG_TRIM std::cout << "Created arc on points:" << std::endl; std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " << aStartShapePoint->y() << "]" << std::endl; - +#endif } + return anNewFeature; } FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& theStartShapePoint, @@ -940,20 +1071,20 @@ FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr& t //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase); /// trim feature - FeaturePtr anArcFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); + FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint); // arc created by trim of circle is always correct, that means that it is not inversed - anArcFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false); + anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false); theModifiedAttributes.insert( std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()), - anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); + anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID()))); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::START_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::START_ID()))); thePoints.insert(std::dynamic_pointer_cast - (anArcFeature->attribute(SketchPlugin_Arc::END_ID()))); + (anNewFeature->attribute(SketchPlugin_Arc::END_ID()))); - return anArcFeature; + return anNewFeature; } void SketchPlugin_Trim::arrangePointsOnLine(const AttributePoint2DPtr& theStartPointAttr, diff --git a/src/SketchPlugin/SketchPlugin_Trim.h b/src/SketchPlugin/SketchPlugin_Trim.h index 532731b39..5791ff690 100644 --- a/src/SketchPlugin/SketchPlugin_Trim.h +++ b/src/SketchPlugin/SketchPlugin_Trim.h @@ -7,9 +7,11 @@ #ifndef SketchPlugin_Trim_H_ #define SketchPlugin_Trim_H_ +#include + #include "SketchPlugin.h" -#include #include "SketchPlugin_ConstraintBase.h" +#include class GeomDataAPI_Point2D; class ModelAPI_Feature; @@ -22,7 +24,8 @@ typedef std::pair > IdToPointP * \ingroup Plugins * \brief Feature for creation of a new constraint trimming object. Entities for split: */ -class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentable +class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentable, + public ModelAPI_IReentrant { public: /// Split constraint kind @@ -89,11 +92,8 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab /// Moves the feature : Empty SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {}; - bool setCoincidenceToAttribute(const AttributePtr& theAttribute, - const std::set >& theFurtherCoincidences); - - bool replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, - const std::set>& theModifiedAttributes); + /// Apply information of the message to current object. It fills selected point and object + virtual std::string processEvent(const std::shared_ptr& theMessage); typedef std::map, std::pair >, @@ -105,6 +105,12 @@ class SketchPlugin_Trim : public SketchPlugin_Feature, public GeomAPI_IPresentab std::map, PointToRefsMap>& theObjectToPoints); private: + bool setCoincidenceToAttribute(const AttributePtr& theAttribute, + const std::set >& theFurtherCoincidences); + + bool replaceCoincidenceAttribute(const AttributePtr& theCoincidenceAttribute, + const std::set>& theModifiedAttributes); + GeomShapePtr getSubShape(const std::string& theObjectAttributeId, const std::string& thePointAttributeId); @@ -160,7 +166,8 @@ private: /// \param thePoints a list of points where coincidences will be build /// \param theModifiedAttributes a container of attribute on base /// feature to attribute on new feature - void trimLine(const std::shared_ptr& theStartShapePoint, + /// \return new line if it was created + FeaturePtr trimLine(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::map >& theBaseRefAttributes, std::set >& thePoints, @@ -168,7 +175,8 @@ private: /// Make the base object is splitted by the point attributes /// \param thePoints a list of points where coincidences will be build - void trimArc(const std::shared_ptr& theStartShapePoint, + /// \return new line if it was created + FeaturePtr trimArc(const std::shared_ptr& theStartShapePoint, const std::shared_ptr& theLastShapePoint, std::map >& theBaseRefAttributes, std::set >& thePoints, diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 7dadf303c..2bf0fa121 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -877,14 +877,17 @@ bool SketchPlugin_TrimValidator::isValid(const AttributePtr& theAttribute, AttributePtr aPreviewAttr = aTrimFeature->attribute(SketchPlugin_Trim::PREVIEW_OBJECT()); aBaseObjectAttr = std::dynamic_pointer_cast(aPreviewAttr); aBaseObject = aBaseObjectAttr->value(); - - //return aValid; } FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject); if (!aBaseFeature) return aValid; + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aBaseFeature); + if (!aSketchFeature.get() || aSketchFeature->isCopy()) + return aValid; + std::string aKind = aBaseFeature->getKind(); if (aKind != SketchPlugin_Line::ID() && aKind != SketchPlugin_Arc::ID() && diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index e19081739..57d57f82e 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -76,7 +76,7 @@ icon="icons/Sketch/circle.png" title="Circle" tooltip="Create circle"> - + @@ -195,7 +195,7 @@ title="Arc" tooltip="Create arc" icon="icons/Sketch/arc.png"> - + diff --git a/src/XGUI/XGUI_ErrorMgr.h b/src/XGUI/XGUI_ErrorMgr.h index 3a320c4b0..f9ad34c09 100644 --- a/src/XGUI/XGUI_ErrorMgr.h +++ b/src/XGUI/XGUI_ErrorMgr.h @@ -38,7 +38,7 @@ public: /// Update actions for the given feature /// \param theFeature a feature - void updateActions(const FeaturePtr& theFeature); + virtual void updateActions(const FeaturePtr& theFeature); /// Update enable state of AcceptAll action if the feature uses it /// \param theFeature a feature diff --git a/src/XGUI/XGUI_ModuleConnector.cpp b/src/XGUI/XGUI_ModuleConnector.cpp index 7231a1b28..e6b6cf73f 100644 --- a/src/XGUI/XGUI_ModuleConnector.cpp +++ b/src/XGUI/XGUI_ModuleConnector.cpp @@ -13,6 +13,7 @@ #include "XGUI_Displayer.h" #include "XGUI_PropertyPanel.h" #include "XGUI_ActionsMgr.h" +#include "XGUI_ErrorMgr.h" #include #include @@ -58,6 +59,11 @@ ModuleBase_IPropertyPanel* XGUI_ModuleConnector::propertyPanel() const return myWorkshop->propertyPanel(); } +ModuleBase_IErrorMgr* XGUI_ModuleConnector::errorMgr() const +{ + return myWorkshop->errorMgr(); +} + ModuleBase_Operation* XGUI_ModuleConnector::currentOperation() const { return myWorkshop->operationMgr()->currentOperation(); diff --git a/src/XGUI/XGUI_ModuleConnector.h b/src/XGUI/XGUI_ModuleConnector.h index b86c0ef8b..eb4c37c4f 100644 --- a/src/XGUI/XGUI_ModuleConnector.h +++ b/src/XGUI/XGUI_ModuleConnector.h @@ -50,6 +50,9 @@ Q_OBJECT //! Returns property panel virtual ModuleBase_IPropertyPanel* propertyPanel() const; + //! Returns error manager + virtual ModuleBase_IErrorMgr* errorMgr() const; + //! Returns currently active operation virtual ModuleBase_Operation* currentOperation() const;