From 41bae90d28cd43382b680709e304adaeefb434ea Mon Sep 17 00:00:00 2001 From: DeepSOIC Date: Fri, 6 May 2016 21:52:23 +0300 Subject: [PATCH] Attacher: Py: add interface for changing attacher type Plus a mechanism to remember attacher type of AttachableObject through save-restore cycle. --- src/Mod/Part/App/AttachableObject.cpp | 46 +++++++++++++++++++++- src/Mod/Part/App/AttachableObject.h | 13 +++++- src/Mod/Part/App/AttachableObjectPy.xml | 10 +++++ src/Mod/Part/App/AttachableObjectPyImp.cpp | 19 +++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/AttachableObject.cpp b/src/Mod/Part/App/AttachableObject.cpp index 9a4e90913d..52fff96c97 100644 --- a/src/Mod/Part/App/AttachableObject.cpp +++ b/src/Mod/Part/App/AttachableObject.cpp @@ -42,6 +42,9 @@ PROPERTY_SOURCE(Part::AttachableObject, Part::Feature); AttachableObject::AttachableObject() : _attacher(0) { + ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment."); + this->AttacherType.setStatus(App::Property::Status::Hidden, true); + ADD_PROPERTY_TYPE(Support, (0,0), "Attachment",(App::PropertyType)(App::Prop_None),"Support of the 2D geometry"); ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object"); @@ -69,7 +72,44 @@ void AttachableObject::setAttacher(AttachEngine* attacher) if (_attacher) delete _attacher; _attacher = attacher; - updateAttacherVals(); + if (_attacher){ + const char* typeName = attacher->getTypeId().getName(); + if(strcmp(this->AttacherType.getValue(),typeName)!=0) //make sure we need to change, to break recursive onChange->changeAttacherType->onChange... + this->AttacherType.setValue(typeName); + updateAttacherVals(); + } else { + if (strlen(AttacherType.getValue()) != 0){ //make sure we need to change, to break recursive onChange->changeAttacherType->onChange... + this->AttacherType.setValue(""); + } + } +} + +bool AttachableObject::changeAttacherType(const char* typeName) +{ + //check if we need to actually change anything + if (_attacher){ + if (strcmp(_attacher->getTypeId().getName(),typeName)==0){ + return false; + } + } else if (strlen(typeName) == 0){ + return false; + } + if (strlen(typeName) == 0){ + setAttacher(nullptr); + return true; + } + Base::Type t = Base::Type::fromName(typeName); + if (t.isDerivedFrom(AttachEngine::getClassTypeId())){ + AttachEngine* pNewAttacher = static_cast(Base::Type::createInstanceByName(typeName)); + this->setAttacher(pNewAttacher); + return true; + } else { + std::stringstream errMsg; + errMsg << "Object if this type is not derived from AttachEngine: " << typeName; + throw Base::Exception(errMsg.str()); + } + assert(false);//exec shouldn't ever get here + return false; } bool AttachableObject::positionBySupport() @@ -138,6 +178,10 @@ void AttachableObject::onChanged(const App::Property* prop) } + if(prop == &(this->AttacherType)){ + this->changeAttacherType(this->AttacherType.getValue()); + } + Part::Feature::onChanged(prop); } diff --git a/src/Mod/Part/App/AttachableObject.h b/src/Mod/Part/App/AttachableObject.h index 251df56a38..83bababa07 100644 --- a/src/Mod/Part/App/AttachableObject.h +++ b/src/Mod/Part/App/AttachableObject.h @@ -68,9 +68,20 @@ public: * @param attacher. AttachableObject takes ownership and will delete it eventually. */ virtual void setAttacher(Attacher::AttachEngine* attacher); + + /** + * @brief changeAttacherType + * @param typeName is the typename of new attacher class. Must be derived + * from Attacher::AttachEngine. + * @return true if attacher was changed. false if attacher is already of the + * type requested. Throws if invalid type is supplied. + */ + bool changeAttacherType(const char* typeName); + Attacher::AttachEngine &attacher(void) const {return *_attacher;} - /// if the 2DObject lies on the Face of an other object this links to it + + App::PropertyString AttacherType; App::PropertyLinkSubList Support; App::PropertyEnumeration MapMode; //see AttachEngine::eMapMode App::PropertyBool MapReversed; //inverts Z and X internal axes diff --git a/src/Mod/Part/App/AttachableObjectPy.xml b/src/Mod/Part/App/AttachableObjectPy.xml index 443f5a6450..664fbf7a7f 100644 --- a/src/Mod/Part/App/AttachableObjectPy.xml +++ b/src/Mod/Part/App/AttachableObjectPy.xml @@ -20,5 +20,15 @@ Returns True if attachment calculation was successful, false if object is not at and raises an exception if attachment calculation fails. + + + changeAttacherType(typename): Changes Attacher class of this object. +typename: string. The following are accepted so far: +'Attacher::AttachEngine3D' +'Attacher::AttachEnginePlane' +'Attacher::AttachEngineLine' +'Attacher::AttachEnginePoint' + + diff --git a/src/Mod/Part/App/AttachableObjectPyImp.cpp b/src/Mod/Part/App/AttachableObjectPyImp.cpp index 349274d7bb..82ed1d6ea7 100644 --- a/src/Mod/Part/App/AttachableObjectPyImp.cpp +++ b/src/Mod/Part/App/AttachableObjectPyImp.cpp @@ -34,6 +34,25 @@ PyObject* AttachableObjectPy::positionBySupport(PyObject *args) return Py::new_reference_to(Py::Boolean(bAttached)); } +PyObject* AttachableObjectPy::changeAttacherType(PyObject *args) +{ + const char* typeName; + if (!PyArg_ParseTuple(args, "s", &typeName)) + return 0; + bool ret; + try{ + ret = this->getAttachableObjectPtr()->changeAttacherType(typeName); + } catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); + return NULL; + } catch (Base::Exception &e) { + PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); + return NULL; + } + return Py::new_reference_to(Py::Boolean(ret)); +} + PyObject *AttachableObjectPy::getCustomAttributes(const char* /*attr*/) const {