diff --git a/src/App/Extension.h b/src/App/Extension.h index e6e3b048f..65583ef83 100644 --- a/src/App/Extension.h +++ b/src/App/Extension.h @@ -26,6 +26,7 @@ #include "PropertyContainer.h" #include "PropertyPythonObject.h" +#include "ExtensionContainer.h" #include "Base/Interpreter.h" #include @@ -253,6 +254,9 @@ protected: Base::Type::instantiationMethod method=0); //@} + virtual void extensionOnChanged(const Property* p) {(void)(p);}; + + friend class App::ExtensionContainer; protected: void initExtension(Base::Type type); diff --git a/src/App/ExtensionContainer.cpp b/src/App/ExtensionContainer.cpp index 6fd4e9487..5c5fc835b 100644 --- a/src/App/ExtensionContainer.cpp +++ b/src/App/ExtensionContainer.cpp @@ -265,17 +265,11 @@ const char* ExtensionContainer::getPropertyDocumentation(const char* name) const } void ExtensionContainer::onChanged(const Property* prop) { - /* - //we need to make sure that the proxy we use is always the proxy of the extended class. This - //is needed as only the extended class proxy (either c++ or python) is managed and ensured to - //be the python implementation class - //Note: this property only exist if the created object is FeaturePythonT<>, this won't work for - //any default document object. But this doesnt matter much as there is a proxy object set anyway - //if a extension gets registered from python. This is only for synchronisation. - if(strcmp(prop->getName(), "Proxy")) { - for(auto entry : _extensions) - entry.second->extensionGetExtensionPyObject().setValue(static_cast(prop)->getValue()); - }*/ + + //inform all extensions about changed property. This includes all properties from the + //extended object (this) as well as all extension properties + for(auto entry : _extensions) + entry.second->extensionOnChanged(prop); App::PropertyContainer::onChanged(prop); } diff --git a/src/Mod/Part/App/AttachableObject.cpp b/src/Mod/Part/App/AttachableObject.cpp index 972915507..30629db3c 100644 --- a/src/Mod/Part/App/AttachableObject.cpp +++ b/src/Mod/Part/App/AttachableObject.cpp @@ -31,43 +31,43 @@ #include #include -#include "AttachableObjectPy.h" +#include "AttachableObjecty.h" using namespace Part; using namespace Attacher; -PROPERTY_SOURCE(Part::AttachableObject, Part::Feature); +EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, Part::Feature); -AttachableObject::AttachableObject() +AttachExtension::AttachExtension() : _attacher(0) { - ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment."); + EXTENSION_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"); + EXTENSION_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"); + EXTENSION_ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object"); MapMode.setEnums(AttachEngine::eMapModeStrings); //a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum. assert(MapMode.getEnumVector().size() == mmDummy_NumberOfModes); - ADD_PROPERTY_TYPE(MapReversed, (false), "Attachment", App::Prop_None, "Reverse Z direction (flip sketch upside down)"); + EXTENSION_ADD_PROPERTY_TYPE(MapReversed, (false), "Attachment", App::Prop_None, "Reverse Z direction (flip sketch upside down)"); - ADD_PROPERTY_TYPE(MapPathParameter, (0.0), "Attachment", App::Prop_None, "Sets point of curve to map the sketch to. 0..1 = start..end"); + EXTENSION_ADD_PROPERTY_TYPE(MapPathParameter, (0.0), "Attachment", App::Prop_None, "Sets point of curve to map the sketch to. 0..1 = start..end"); - ADD_PROPERTY_TYPE(superPlacement, (Base::Placement()), "Attachment", App::Prop_None, "Extra placement to apply in addition to attachment (in local coordinates)"); + EXTENSION_ADD_PROPERTY_TYPE(superPlacement, (Base::Placement()), "Attachment", App::Prop_None, "Extra placement to apply in addition to attachment (in local coordinates)"); setAttacher(new AttachEngine3D);//default attacher } -AttachableObject::~AttachableObject() +AttachExtension::~AttachExtension() { if(_attacher) delete _attacher; } -void AttachableObject::setAttacher(AttachEngine* attacher) +void AttachExtension::setAttacher(AttachEngine* attacher) { if (_attacher) delete _attacher; @@ -84,7 +84,7 @@ void AttachableObject::setAttacher(AttachEngine* attacher) } } -bool AttachableObject::changeAttacherType(const char* typeName) +bool AttachExtension::changeAttacherType(const char* typeName) { //check if we need to actually change anything if (_attacher){ @@ -112,13 +112,13 @@ bool AttachableObject::changeAttacherType(const char* typeName) return false; } -bool AttachableObject::positionBySupport() +bool AttachExtension::positionBySupport() { if (!_attacher) - throw Base::Exception("AttachableObject: can't positionBySupport, because no AttachEngine is set."); + throw Base::Exception("AttachExtension: can't positionBySupport, because no AttachEngine is set."); updateAttacherVals(); try{ - this->Placement.setValue(_attacher->calculateAttachedPlacement(this->Placement.getValue())); + getPlacement().setValue(_attacher->calculateAttachedPlacement(getPlacement().getValue())); return true; } catch (ExceptionCancel) { //disabled, don't do anything @@ -126,7 +126,7 @@ bool AttachableObject::positionBySupport() }; } -App::DocumentObjectExecReturn *AttachableObject::execute() +App::DocumentObjectExecReturn *AttachExtension::exttensionExecute() { if(this->isTouched_Mapping()) { try{ @@ -137,12 +137,12 @@ App::DocumentObjectExecReturn *AttachableObject::execute() return new App::DocumentObjectExecReturn(e.GetMessageString()); } } - return Part::Feature::execute(); + return App::DocumentObjectExtension::extensionExecute(); } -void AttachableObject::onChanged(const App::Property* prop) +void AttachExtension::extensionOnChanged(const App::Property* prop) { - if(! this->isRestoring()){ + if(! getExtendedObject()->isRestoring()){ if ((prop == &Support || prop == &MapMode || prop == &MapPathParameter @@ -163,7 +163,7 @@ void AttachableObject::onChanged(const App::Property* prop) eMapMode mmode = eMapMode(this->MapMode.getValue()); this->superPlacement.setReadOnly(!bAttached); - this->Placement.setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached. + getPlacement().setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached. } } @@ -172,10 +172,10 @@ void AttachableObject::onChanged(const App::Property* prop) this->changeAttacherType(this->AttacherType.getValue()); } - Part::Feature::onChanged(prop); + App::DocumentObjectExtension::extensionOnChanged(prop); } -void AttachableObject::updateAttacherVals() +void AttachExtension::updateAttacherVals() { if (!_attacher) return; @@ -187,22 +187,31 @@ void AttachableObject::updateAttacherVals() this->superPlacement.getValue()); } +App::PropertyPlacement& AttachExtension::getPlacement() { + + if(!getExtendedObject()->isDerivedFrom(App::GeoFeature::getClassTypeId())) + throw Base::Exception("AttachExtension not added to GeooFeature!"); + + return static_cast(getExtendedObject())->Placement; +} + + namespace App { /// @cond DOXERR - PROPERTY_SOURCE_TEMPLATE(Part::AttachableObjectPython, Part::AttachableObject) - template<> const char* Part::AttachableObjectPython::getViewProviderName(void) const { + EXTENSION_PROPERTY_SOURCE_TEMPLATE(Part::AttachExtensionPython, Part::AttachExtension) + template<> const char* Part::AttachExtensionPython::getViewProviderName(void) const { return "PartGui::ViewProviderPython"; } - template<> PyObject* Part::AttachableObjectPython::getPyObject(void) { + template<> PyObject* Part::AttachExtensionPython::getPyObject(void) { if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FeaturePythonPyT(this),true); + PythonObject = Py::Object(new FeaturePythonPyT(this),true); } return Py::new_reference_to(PythonObject); } /// @endcond // explicit template instantiation - template class PartExport FeaturePythonT; + template class PartExport FeaturePythonT; } diff --git a/src/Mod/Part/App/AttachableObject.h b/src/Mod/Part/App/AttachableObject.h index ed68a3958..3f883134a 100644 --- a/src/Mod/Part/App/AttachableObject.h +++ b/src/Mod/Part/App/AttachableObject.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -46,20 +47,16 @@ namespace Part { /** - * @brief The AttachableObject class is the thing to be inherited by an object + * @brief The AttachableObject class is the thing to extend an object with * that should be attachable. It includes the required properties, and * shortcuts for accessing the attachment math class. - * - * Todos to make it work: - * - call Attacher::execute() when executing derived object. Make sure to deal - * with its return value, otherwise it will leak memory upon fails. */ -class PartExport AttachableObject : public Part::Feature +class PartExport AttachExtension : public App::DocumentObjectExtension { - PROPERTY_HEADER(Part::AttachableObject); + EXTENSION_PROPERTY_HEADER(Part::AttachableObject); public: - AttachableObject(); - virtual ~AttachableObject(); + AttachExtension(); + virtual ~AttachExtension(); /** * @brief setAttacher sets the AttachEngine object. The class takes the @@ -103,9 +100,11 @@ public: virtual bool isTouched_Mapping() {return true; /*support.isTouched isn't true when linked objects are changed... why?..*/}; - App::DocumentObjectExecReturn *execute(void); + App::DocumentObjectExecReturn *extensionExecute(void); protected: - virtual void onChanged(const App::Property* /*prop*/); + virtual void extensionOnChanged(const App::Property* /*prop*/); + + App::PropertyPlacement& getPlacement(); public: void updateAttacherVals(); @@ -115,7 +114,7 @@ private: }; -typedef App::FeaturePythonT AttachableObjectPython; +typedef App::ExtensionPythonT AttachExtensionPython; } // namespace Part