From f4870a6999547ac314abbe4fd5da1803f5ec9841 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 25 Aug 2015 10:23:53 +0300 Subject: [PATCH] Make the invalid selection makes the referenced object in state "invalid arguments" --- .../FeaturesPlugin_Extrusion.cpp | 4 +- src/Model/Model_AttributeSelection.cpp | 58 ++++++++++++----- src/Model/Model_AttributeSelection.h | 4 ++ src/Model/Model_ResultConstruction.cpp | 2 +- src/Model/Model_Update.cpp | 63 +++++++++++-------- src/ModelAPI/ModelAPI_AttributeSelection.h | 3 + 6 files changed, 90 insertions(+), 44 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index f76a68460..c9c567081 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -86,7 +86,9 @@ void FeaturesPlugin_Extrusion::execute() for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { std::shared_ptr aBaseShape; if (aFacesNum == -1) { - aFacesList.push_back(aFaceShape); + if (!aFaceShape->isNull()) { + aFacesList.push_back(aFaceShape); + } break; } else { aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 07b913161..4fcb26fae 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -68,6 +68,8 @@ Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28"); // reference to Part sub-object Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); +// selection is invalid after recomputation +Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d"); // on this label is stored: // TNaming_NamedShape - selected shape @@ -101,6 +103,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); + aSelLab.ForgetAttribute(kINVALID_SELECTION); bool isDegeneratedEdge = false; // do not use the degenerated edge as a shape, a null context and shape is used in the case @@ -157,8 +160,11 @@ std::shared_ptr Model_AttributeSelection::value() } std::shared_ptr aResult; + TDF_Label aSelLab = selectionLabel(); + if (aSelLab.IsAttribute(kINVALID_SELECTION)) + return aResult; + if (myRef.isInitialized()) { - TDF_Label aSelLab = selectionLabel(); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); if (!aContext.get()) @@ -201,6 +207,11 @@ std::shared_ptr Model_AttributeSelection::value() return aResult; } +bool Model_AttributeSelection::isInvalid() +{ + return selectionLabel().IsAttribute(kINVALID_SELECTION) == Standard_True; +} + bool Model_AttributeSelection::isInitialized() { if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized @@ -311,21 +322,33 @@ int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge) return 0; // unknown } +/// Sets the invalid flag if flag is false, or removes it if "true" +/// Returns theFlag +static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) { + if (theFlag) { + theLab.ForgetAttribute(kINVALID_SELECTION); + } else { + TDataStd_UAttribute::Set(theLab, kINVALID_SELECTION); + } + return theFlag; +} + bool Model_AttributeSelection::update() { - ResultPtr aContext = context(); - if (!aContext.get()) return false; TDF_Label aSelLab = selectionLabel(); + ResultPtr aContext = context(); + if (!aContext.get()) + return setInvalidIfFalse(aSelLab, false); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape - return aContext->shape() && !aContext->shape()->isNull(); + return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape - return aContext->shape() && !aContext->shape()->isNull(); + return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object std::shared_ptr aNoSelection; - return selectPart(aContext, aNoSelection, true); + return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true)); } if (aContext->groupName() == ModelAPI_ResultBody::group()) { @@ -333,7 +356,7 @@ bool Model_AttributeSelection::update() TNaming_Selector aSelector(aSelLab); bool aResult = aSelector.Solve(scope()) == Standard_True; owner()->data()->sendAttributeUpdated(this); - return aResult; + return setInvalidIfFalse(aSelLab, aResult); } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { // construction: identification by the results indexes, recompute faces and // take the face that more close by the indexes @@ -348,7 +371,7 @@ bool Model_AttributeSelection::update() // getting a type of selected shape Handle(TDataStd_Integer) aTypeAttr; if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { - return false; + return setInvalidIfFalse(aSelLab, false); } TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); // selected indexes will be needed in each "if" @@ -360,13 +383,13 @@ bool Model_AttributeSelection::update() CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); if (!aComposite.get() || aComposite->numberOfSubs() == 0) { - return false; + return setInvalidIfFalse(aSelLab, false); } if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection // If this is a wire with plane defined thin it is a sketch-like object if (!aConstructionContext->facesNum()) // no faces, update can not work correctly - return false; + return setInvalidIfFalse(aSelLab, false); // if there is no edges indexes, any face can be used: take the first std::shared_ptr aNewSelected; if (aNoIndexes) { @@ -446,7 +469,10 @@ bool Model_AttributeSelection::update() if (aNewSelected) { // store this new selection selectConstruction(aContext, aNewSelected); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); + } else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one + TNaming_Builder anEmptyBuilder(selectionLabel()); + return setInvalidIfFalse(aSelLab, false); } } else if (aShapeType == TopAbs_EDGE) { // just reselect the edge by the id @@ -464,7 +490,7 @@ bool Model_AttributeSelection::update() if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! selectConstruction(aContext, aRes->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } } @@ -493,7 +519,7 @@ bool Model_AttributeSelection::update() if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! selectConstruction(aContext, aRes->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } else if (aRes->shape()->isEdge() && aVertexNum > 0) { const TopoDS_Shape& anEdge = aRes->shape()->impl(); int aVIndex = 1; @@ -503,7 +529,7 @@ bool Model_AttributeSelection::update() aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); selectConstruction(aContext, aVertex); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } aVIndex++; } @@ -516,10 +542,10 @@ bool Model_AttributeSelection::update() } else { // simple construction element: the selected is that needed selectConstruction(aContext, aContext->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } - return false; // unknown case + return setInvalidIfFalse(aSelLab, false); // unknown case } diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index 1340a34d0..fba911b92 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -64,6 +64,10 @@ public: /// Returns true if attribute was initialized by some value MODEL_EXPORT virtual bool isInitialized(); + /// Returns true if recomute of selection become impossible + MODEL_EXPORT virtual bool isInvalid(); + + protected: /// Objects are created for features automatically MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel); diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index 41e1a9b16..11cf883cd 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -68,7 +68,7 @@ int Model_ResultConstruction::facesNum() std::list >::iterator aFIter = aFaces.begin(); for(; aFIter != aFaces.end(); aFIter++) { std::shared_ptr aFace(new GeomAPI_Face(*aFIter)); - if (aFace.get()) + if (aFace.get() && !aFace->isNull()) myFaces.push_back(aFace); } } diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index a1a840381..25dc969b7 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -110,7 +110,7 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag if (anUpdated->isPreviewNeeded() || myIsFinish) { ModelAPI_ExecState aState = anUpdated->data()->execState(); static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); - if (aFactory->validate(anUpdated)) { + if (aFactory->validate(anUpdated) && aState != ModelAPI_StateInvalidArgument) { #ifdef DEB_UPDATE std::cout<<"Execute immideately "<name()<::iterator aRefsIter = aRefs.begin(); for (; aRefsIter != aRefs.end(); aRefsIter++) { std::shared_ptr aSel = - std::dynamic_pointer_cast(*aRefsIter); - ObjectPtr aContext = aSel->context(); - // update argument only if the referenced object is changed - if (aContext.get() && !aContext->isDisabled() && - (myJustUpdated.find(aContext) != myJustUpdated.end() || - aContext->data()->updateID() > theFeature->data()->updateID())) { - if (aState == ModelAPI_StateDone) - aState = ModelAPI_StateMustBeUpdated; - if (!aSel->update()) { // this must be done on execution since it may be long operation - if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)) && - aFactory->isCase(theFeature, theFeature->data()->id(aSel))) - aState = ModelAPI_StateInvalidArgument; - } + std::dynamic_pointer_cast(*aRefsIter); + bool isObligatory = !aFactory->isNotObligatory( + theFeature->getKind(), theFeature->data()->id(aSel)) && + aFactory->isCase(theFeature, theFeature->data()->id(aSel)); + if (aSel->isInvalid()) { + aState = ModelAPI_StateInvalidArgument; + } else { + ObjectPtr aContext = aSel->context(); + // update argument only if the referenced object is changed + if (aContext.get() && !aContext->isDisabled() && + (myJustUpdated.find(aContext) != myJustUpdated.end() || + aContext->data()->updateID() > theFeature->data()->updateID())) { + if (aState == ModelAPI_StateDone) + aState = ModelAPI_StateMustBeUpdated; + if (!aSel->update()) { // this must be done on execution since it may be long operation + if (isObligatory) + aState = ModelAPI_StateInvalidArgument; + } + } } } aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId()); @@ -473,19 +479,24 @@ void Model_Update::updateArguments(FeaturePtr theFeature) { std::shared_ptr aSelAttr = std::dynamic_pointer_cast(aSel->value(a)); if (aSelAttr) { - ObjectPtr aContext = aSelAttr->context(); - // update argument onlt if the referenced object is changed - if (aContext.get() && !aContext->isDisabled() && - (myJustUpdated.find(aContext) != myJustUpdated.end() || - aContext->data()->updateID() > theFeature->data()->updateID())) { - if (aState == ModelAPI_StateDone) - aState = ModelAPI_StateMustBeUpdated; - if (!aSelAttr->update()) { - if (!aFactory->isNotObligatory( + bool isObligatory = !aFactory->isNotObligatory( theFeature->getKind(), theFeature->data()->id(aSel)) && - aFactory->isCase(theFeature, theFeature->data()->id(aSel))) - aState = ModelAPI_StateInvalidArgument; - } + aFactory->isCase(theFeature, theFeature->data()->id(aSel)); + if (aSelAttr->isInvalid()) { + aState = ModelAPI_StateInvalidArgument; + } else { + ObjectPtr aContext = aSelAttr->context(); + // update argument onlt if the referenced object is changed + if (aContext.get() && !aContext->isDisabled() && + (myJustUpdated.find(aContext) != myJustUpdated.end() || + aContext->data()->updateID() > theFeature->data()->updateID())) { + if (aState == ModelAPI_StateDone) + aState = ModelAPI_StateMustBeUpdated; + if (!aSelAttr->update()) { + if (isObligatory) + aState = ModelAPI_StateInvalidArgument; + } + } } } } diff --git a/src/ModelAPI/ModelAPI_AttributeSelection.h b/src/ModelAPI/ModelAPI_AttributeSelection.h index eccafa5f6..fccb6b018 100644 --- a/src/ModelAPI/ModelAPI_AttributeSelection.h +++ b/src/ModelAPI/ModelAPI_AttributeSelection.h @@ -57,6 +57,9 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute /// Selects sub-shape by the textual Name virtual void selectSubShape(const std::string& theType, const std::string& theSubShapeName) = 0; + /// Returns true if recomute of selection become impossible + virtual bool isInvalid() = 0; + /// To virtually destroy the fields of successors MODELAPI_EXPORT virtual ~ModelAPI_AttributeSelection(); -- 2.39.2