X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_SketcherReetntrantMgr.cpp;h=95a68cf42f054cc7f186305f12054787aa28e29f;hb=8634847ac05ce637193ec2f5234c3c8996762f94;hp=c749c930df6f3b9a78e742e381c14dfea350c063;hpb=cbde248859fb0072f6012907391ea90cfc254574;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp index c749c930d..95a68cf42 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,20 @@ #include #include #include +#include "ModuleBase_ToolBox.h" #include #include +#include +#include #include #include #include #include +#include + +#include PartSet_SketcherReetntrantMgr::PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop) : QObject(theWorkshop), @@ -45,12 +55,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; } @@ -60,6 +72,27 @@ 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(); + beforeStopInternalEdit(); + myIsInternalEditOperation = false; + updateAcceptAllAction(); + } + } + } +} + bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation) { bool aProcessed = false; @@ -77,6 +110,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(); } @@ -88,31 +127,52 @@ 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) { + 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); } } } @@ -138,7 +198,19 @@ 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(); restartOperation(); + myPreviousFeature = FeaturePtr(); aProcessed = true; // fill the first widget by the mouse event point @@ -147,8 +219,10 @@ 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); + aPoint2DWdg->mouseReleased(theWnd, theEvent); } + // unblock viewer update + ModuleBase_Tools::blockUpdateViewer(false); } } @@ -191,7 +265,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) { @@ -211,12 +285,18 @@ bool PartSet_SketcherReetntrantMgr::processEnter(const std::string& thePreviousA if (!isActiveMgr()) return isDone; + // empty previous attribute means that the Apply/Ok button has focus and the enter + // should not lead to start edition mode of the previous operation + if (thePreviousAttributeID.empty()) + return isDone; + ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->currentOperation()); if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) return isDone; bool isSketchSolverError = module()->sketchMgr()->sketchSolverError(); + if (!isSketchSolverError) { myRestartingMode = RM_EmptyFeatureUsed; isDone = startInternalEdit(thePreviousAttributeID); @@ -230,10 +310,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(); @@ -263,13 +345,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()); @@ -292,13 +379,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())); @@ -314,13 +401,33 @@ 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 && !aPreviousAttributeWidget->isViewerSelector()) { - aPreviousAttributeWidget->focusTo(); - aPreviousAttributeWidget->selectContent(); + if (aPreviousAttributeWidget) { + if (!aPreviousAttributeWidget->isViewerSelector()) { + aPreviousAttributeWidget->focusTo(); + aPreviousAttributeWidget->selectContent(); + } + else { + // in case of shape multi selector, the widget does not lose focus by filling + // like it is in shape selector. So, if enter is pressed, the multi shape selector + // control should be deactivated. The focus is moved to Apply button and there + // should not be active control visualized in property panel + if (aPreviousAttributeWidget == aPanel->activeWidget()) { + aPanel->activateWidget(NULL, false); + } + // if there is no the next widget to be automatically activated, the Ok button in property + // panel should accept the focus(example is parallel constraint on sketch lines) + QToolButton* anOkBtn = dynamic_cast(aPanel)->findButton(PROP_PANEL_OK); + if (anOkBtn) + anOkBtn->setFocus(Qt::TabFocusReason); + } } } } @@ -351,7 +458,6 @@ void PartSet_SketcherReetntrantMgr::restartOperation() if (aFOperation) { myNoMoreWidgetsAttribute = ""; myIsFlagsBlocked = true; - aFOperation->commit(); module()->launchOperation(aFOperation->id()); myIsFlagsBlocked = false; resetFlags(); @@ -372,11 +478,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()); @@ -392,8 +501,14 @@ void PartSet_SketcherReetntrantMgr::createInternalFeature() QList aWidgets = aFactory.getModelWidgets(); foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - aWidget->setFeature(myInternalFeature, true); + bool isStoreValue = !aFOperation->isEditOperation() && + !aWidget->getDefaultValue().empty() && + !aWidget->isComputedDefault(); + aWidget->setFeature(myInternalFeature, isStoreValue); + if (!isStoreValue && isFeatureChanged) + aWidget->restoreValue(); } + ModuleBase_ModelWidget* aFirstWidget = ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget (aWidgets); if (aFirstWidget) @@ -415,16 +530,108 @@ 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()) + 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);