X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_SketcherReetntrantMgr.cpp;h=4cfcf167d8f49f9726c1ca2cb94d447d257c2013;hb=6da8c412d0102f5997e2af9734edf23627daf937;hp=15cf843d3072df5989d5dd1d08db2db2f0d81a1e;hpb=fcefcf6d4c59e6eb9117cd009b3029e96e23c1ee;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp index 15cf843d3..4cfcf167d 100755 --- a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp +++ b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp @@ -6,6 +6,10 @@ #include "PartSet_WidgetPoint2d.h" #include "ModelAPI_Session.h" +#include "ModelAPI_AttributeString.h" +#include "ModelAPI_AttributeRefAttr.h" + +#include "GeomDataAPI_Point2D.h" #include #include @@ -16,14 +20,21 @@ #include #include #include +#include "ModuleBase_ToolBox.h" +#include "ModuleBase_ISelection.h" #include #include +#include +#include +#include #include #include #include #include +#include +#include #include @@ -47,12 +58,14 @@ ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::internalActiveWidget() co if (!isActiveMgr()) return aWidget; - ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); - if (aOperation) { - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); - ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); - if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector())) - aWidget = myInternalActiveWidget; + ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) { // check for case when the operation is started but property panel is not filled + ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); + if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector())) + aWidget = myInternalActiveWidget; + } } return aWidget; } @@ -62,6 +75,26 @@ bool PartSet_SketcherReetntrantMgr::isInternalEditActive() const return myIsInternalEditOperation; } +void PartSet_SketcherReetntrantMgr::updateInternalEditActiveState() +{ + if (myIsInternalEditOperation) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myWorkshop->currentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + QString anError = myWorkshop->module()->getFeatureError(aFeature); + // stop started internal edit operation as soon as the operation becomes invalid + // it is especially important for the sketch tangent arc feature + if (!anError.isEmpty()) { + aFOperation->setEditOperation(false); + //workshop()->operationMgr()->updateApplyOfOperations(); + myIsInternalEditOperation = false; + updateAcceptAllAction(); + } + } + } +} + bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation) { bool aProcessed = false; @@ -79,6 +112,12 @@ void PartSet_SketcherReetntrantMgr::operationStarted(ModuleBase_Operation* theOp if (!isActiveMgr()) return; + if (myPreviousFeature.get() && myRestartingMode == RM_LastFeatureUsed) { + ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast( + myWorkshop->currentOperation()); + CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch(); + copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch); + } resetFlags(); } @@ -90,31 +129,57 @@ void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOp resetFlags(); } -bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* /* theWnd*/, - QMouseEvent* /* theEvent*/) +bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* theWnd, + QMouseEvent* theEvent) { bool aProcessed = false; if (!isActiveMgr()) return aProcessed; if (myIsInternalEditOperation) { - PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(module()->activeWidget()); - if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) { - ModuleBase_OperationFeature* aFOperation = dynamic_cast + ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->currentOperation()); - FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr(); - restartOperation(); - aProcessed = true; - - if (aLastFeature) { - ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel(); - PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(aPanel->activeWidget()); - if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) { - QList aSelection; - aSelection.append(ModuleBase_ViewerPrs(aLastFeature, TopoDS_Shape(), NULL)); - if (aPoint2DWdg->setSelection(aSelection, true)) - aPanel->activateNextWidget(aPoint2DWdg); + FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() + : FeaturePtr(); + if (aLastFeature) { + ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget(); + ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel(); + + FeaturePtr aCurrentFeature = aFOperation->feature(); + bool isLineFeature = false, isArcFeature = false; + std::string anAttributeOnStart; + if (aCurrentFeature->getKind() == SketchPlugin_Line::ID()) { + anAttributeOnStart = SketchPlugin_Line::START_ID(); + isLineFeature = anActiveWidget->attributeID() == anAttributeOnStart; + } + else if (isTangentArc(aFOperation, module()->sketchMgr()->activeSketch())) { + anAttributeOnStart = SketchPlugin_Arc::TANGENT_POINT_ID(); + isArcFeature = anActiveWidget->attributeID() == anAttributeOnStart; + } + bool aCanBeActivatedByMove = isLineFeature || isArcFeature; + if (aCanBeActivatedByMove) { + /// before restarting of operation we need to clear selection, as it may take part in + /// new feature creation, e.g. tangent arc. But it is not necessary as it was processed + /// by mouse release when the operation was restarted. + workshop()->selector()->clearSelection(); + + myPreviousFeature = aFOperation->feature(); + restartOperation(); + myPreviousFeature = FeaturePtr(); + + anActiveWidget = module()->activeWidget(); + aCurrentFeature = anActiveWidget->feature(); + aProcessed = true; + if (anActiveWidget->attributeID() == anAttributeOnStart) { + // it was not deactivated by preselection processing + aPanel->activateNextWidget(anActiveWidget); } + } else { + // processing mouse move in active widget of restarted operation + ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget(); + PartSet_MouseProcessor* aProcessor = dynamic_cast(anActiveWidget); + if (aProcessor) + aProcessor->mouseMoved(theWnd, theEvent); } } } @@ -140,7 +205,26 @@ bool PartSet_SketcherReetntrantMgr::processMouseReleased(ModuleBase_IViewWindow* ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); if (!anActiveWidget || !anActiveWidget->isViewerSelector()) { + + // block of viewer update + // we need to block update content of the viewer because of Sketch Point feature + // in activate() the value of the point is initialized and it can be displayed + // but the default value is [0, 0]. So, we block update viewer contentent until + // onMouseRelease happens, which correct the point position + ModuleBase_Tools::blockUpdateViewer(true); + + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myWorkshop->currentOperation()); + myPreviousFeature = aFOperation->feature(); + + /// selection should be obtained from workshop before ask if the operation can be started as + /// the canStartOperation method performs commit/abort of previous operation. Sometimes commit/abort + /// may cause selection clear(Sketch operation) as a result it will be lost and is not used for preselection. + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + QList aPreSelected = aSelection->getSelected(ModuleBase_ISelection::AllControls); + restartOperation(); + myPreviousFeature = FeaturePtr(); aProcessed = true; // fill the first widget by the mouse event point @@ -149,8 +233,14 @@ bool PartSet_SketcherReetntrantMgr::processMouseReleased(ModuleBase_IViewWindow* PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast(module()->activeWidget()); ModuleBase_ModelWidget* aFirstWidget = aPanel->findFirstAcceptingValueWidget(); if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) { - aPoint2DWdg->onMouseRelease(theWnd, theEvent); + if (!aPreSelected.empty()) + aPoint2DWdg->setPreSelection(aPreSelected.front()); + aPoint2DWdg->mouseReleased(theWnd, theEvent); + if (!aPreSelected.empty()) + aPoint2DWdg->setPreSelection(ModuleBase_ViewerPrsPtr()); } + // unblock viewer update + ModuleBase_Tools::blockUpdateViewer(false); } } @@ -193,7 +283,7 @@ void PartSet_SketcherReetntrantMgr::onNoMoreWidgets(const std::string& thePrevio if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) return; - if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) { + if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) { bool isStarted = false; if (!module()->sketchMgr()->sketchSolverError()) { if (myRestartingMode != RM_Forbided) { @@ -238,10 +328,12 @@ void PartSet_SketcherReetntrantMgr::onVertexSelected() if (!isActiveMgr()) return; - ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); - if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) { + ModuleBase_Operation* anOperation = myWorkshop->currentOperation(); + std::string anOperationId = anOperation->id().toStdString(); + if (anOperationId == SketchPlugin_Line::ID() || + isTangentArc(anOperation, module()->sketchMgr()->activeSketch())) { /// If last line finished on vertex the lines creation sequence has to be break - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget(); const QList& aWidgets = aPanel->modelWidgets(); QList::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end(); @@ -271,13 +363,18 @@ bool PartSet_SketcherReetntrantMgr::canBeCommittedByPreselection() return !isActiveMgr() || myRestartingMode == RM_None; } +bool PartSet_SketcherReetntrantMgr::isInternalEditStarted() const +{ + return myIsInternalEditOperation; +} + bool PartSet_SketcherReetntrantMgr::isActiveMgr() const { ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation(); bool anActive = PartSet_SketcherMgr::isSketchOperation(aCurrentOperation); if (!anActive) { - anActive = PartSet_SketcherMgr::isNestedSketchOperation(aCurrentOperation); + anActive = module()->sketchMgr()->isNestedSketchOperation(aCurrentOperation); if (anActive) { // the manager is not active when the current operation is a usual Edit ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->currentOperation()); @@ -300,13 +397,13 @@ bool PartSet_SketcherReetntrantMgr::startInternalEdit(const std::string& thePrev ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->currentOperation()); - if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) { - aFOperation->setEditOperation(false); - workshop()->operationMgr()->updateApplyOfOperations(); - + if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) { + aFOperation->setEditOperation(true/*, false*/); createInternalFeature(); myIsInternalEditOperation = true; + updateAcceptAllAction(); + isDone = true; connect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped())); connect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped())); @@ -322,8 +419,12 @@ bool PartSet_SketcherReetntrantMgr::startInternalEdit(const std::string& thePrev ModuleBase_ModelWidget* aPreviousAttributeWidget = 0; QList aWidgets = aPanel->modelWidgets(); for (int i = 0, aNb = aWidgets.size(); i < aNb && !aPreviousAttributeWidget; i++) { - if (aWidgets[i]->attributeID() == thePreviousAttributeID) + if (aWidgets[i]->attributeID() == thePreviousAttributeID) { + /// workaround for the same attributes used in different stacked widgets(attribute types) + if (ModuleBase_ToolBox::isOffToolBoxParent(aWidgets[i])) + continue; aPreviousAttributeWidget = aWidgets[i]; + } } // If the current widget is a selector, do nothing, it processes the mouse press if (aPreviousAttributeWidget) { @@ -341,7 +442,7 @@ bool PartSet_SketcherReetntrantMgr::startInternalEdit(const std::string& thePrev } // if there is no the next widget to be automatically activated, the Ok button in property // panel should accept the focus(example is parallel constraint on sketch lines) - QToolButton* anOkBtn = aPanel->findChild(PROP_PANEL_OK); + QToolButton* anOkBtn = dynamic_cast(aPanel)->findButton(PROP_PANEL_OK); if (anOkBtn) anOkBtn->setFocus(Qt::TabFocusReason); } @@ -375,7 +476,6 @@ void PartSet_SketcherReetntrantMgr::restartOperation() if (aFOperation) { myNoMoreWidgetsAttribute = ""; myIsFlagsBlocked = true; - aFOperation->commit(); module()->launchOperation(aFOperation->id()); myIsFlagsBlocked = false; resetFlags(); @@ -396,11 +496,14 @@ void PartSet_SketcherReetntrantMgr::createInternalFeature() ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->currentOperation()); - if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) { + if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) { FeaturePtr anOperationFeature = aFOperation->feature(); CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch(); myInternalFeature = aSketch->addFeature(anOperationFeature->getKind()); + + bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature, + aSketch, false); XGUI_PropertyPanel* aPropertyPanel = dynamic_cast (aFOperation->propertyPanel()); @@ -420,7 +523,10 @@ void PartSet_SketcherReetntrantMgr::createInternalFeature() !aWidget->getDefaultValue().empty() && !aWidget->isComputedDefault(); aWidget->setFeature(myInternalFeature, isStoreValue); + if (!isStoreValue && isFeatureChanged) + aWidget->restoreValue(); } + ModuleBase_ModelWidget* aFirstWidget = ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget (aWidgets); if (aFirstWidget) @@ -442,16 +548,109 @@ void PartSet_SketcherReetntrantMgr::deleteInternalFeature() QObjectPtrList anObjects; anObjects.append(myInternalFeature); workshop()->deleteFeatures(anObjects); + myInternalFeature = FeaturePtr(); } void PartSet_SketcherReetntrantMgr::resetFlags() { if (!myIsFlagsBlocked) { myIsInternalEditOperation = false; + updateAcceptAllAction(); myRestartingMode = RM_None; } } +bool PartSet_SketcherReetntrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature, + const FeaturePtr& theNewFeature, + const CompositeFeaturePtr& theSketch, + const bool isTemporary) +{ + bool aChanged = false; + if (!theSourceFeature.get() || !theSourceFeature->data().get() || + !theSourceFeature->data()->isValid()) + return aChanged; + + std::string aFeatureKind = theSourceFeature->getKind(); + if (aFeatureKind == SketchPlugin_Line::ID()) { + // Initialize new line with first point equal to end of previous + std::shared_ptr aSFData = theSourceFeature->data(); + std::shared_ptr aSPoint = std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aNFData = theNewFeature->data(); + std::shared_ptr aNPoint = std::dynamic_pointer_cast( + aNFData->attribute(SketchPlugin_Line::START_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint); + + aNPoint = std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + } + else if (aFeatureKind == SketchPlugin_Circle::ID()) { + // set circle type + std::string aTypeAttributeId = SketchPlugin_Circle::CIRCLE_TYPE(); + AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId); + AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId); + aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value()); + //ModuleBase_Tools::flushUpdated(theNewFeature); + aChanged = true; + } + else if (aFeatureKind == SketchPlugin_Arc::ID()) { + // set arc type + std::string aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE(); + AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId); + AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId); + aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value()); + + // if the arc is tangent, set coincidence to end point of the previous arc + std::string anArcType = aSourceFeatureTypeAttr->value(); + if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) { + // get the last point of the previuos arc feature(geom point 2d) + std::shared_ptr aSData = theSourceFeature->data(); + std::shared_ptr aSPointAttr = + std::dynamic_pointer_cast( + aSData->attribute(SketchPlugin_Arc::END_ID())); + // get point attribute on the current feature + AttributeRefAttrPtr aTangentPointAttr = theNewFeature->data()->refattr( + SketchPlugin_Arc::TANGENT_POINT_ID()); + aTangentPointAttr->setAttr(aSPointAttr); + + std::shared_ptr aNPointAttr = + std::dynamic_pointer_cast( + theNewFeature->data()->attribute(SketchPlugin_Arc::END_ID())); + aNPointAttr->setValue(aSPointAttr->x(), aSPointAttr->y()); + + } + //ModuleBase_Tools::flushUpdated(theNewFeature); + aChanged = true; + } + return aChanged; +} + +bool PartSet_SketcherReetntrantMgr::isTangentArc(ModuleBase_Operation* theOperation, + const CompositeFeaturePtr& /*theSketch*/) const +{ + bool aTangentArc = false; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) { + FeaturePtr aFeature = aFOperation->feature(); + if (aFeature.get() && aFeature->getKind() == SketchPlugin_Arc::ID()) { + AttributeStringPtr aTypeAttr = aFeature->data()->string(SketchPlugin_Arc::ARC_TYPE()); + std::string anArcType = aTypeAttr.get() ? aTypeAttr->value() : ""; + aTangentArc = anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT(); + } + } + return aTangentArc; +} + +void PartSet_SketcherReetntrantMgr::updateAcceptAllAction() +{ + CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch(); + if (aSketch.get()) + workshop()->errorMgr()->updateAcceptAllAction(aSketch); +} + XGUI_Workshop* PartSet_SketcherReetntrantMgr::workshop() const { XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop);