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
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
}
std::shared_ptr<GeomAPI_Shape> 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())
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
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<GeomAPI_Shape> aNoSelection;
- return selectPart(aContext, aNoSelection, true);
+ return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true));
}
if (aContext->groupName() == ModelAPI_ResultBody::group()) {
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
// 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"
CompositeFeaturePtr aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(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<GeomAPI_Shape> aNewSelected;
if (aNoIndexes) {
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
if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
selectConstruction(aContext, aRes->shape());
owner()->data()->sendAttributeUpdated(this);
- return true;
+ return setInvalidIfFalse(aSelLab, true);
}
}
}
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<TopoDS_Shape>();
int aVIndex = 1;
aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
selectConstruction(aContext, aVertex);
owner()->data()->sendAttributeUpdated(this);
- return true;
+ return setInvalidIfFalse(aSelLab, true);
}
aVIndex++;
}
} 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
}
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 "<<anUpdated->name()<<std::endl;
#endif
list<AttributePtr>::iterator aRefsIter = aRefs.begin();
for (; aRefsIter != aRefs.end(); aRefsIter++) {
std::shared_ptr<ModelAPI_AttributeSelection> aSel =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*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<ModelAPI_AttributeSelection>(*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());
std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(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;
+ }
+ }
}
}
}