Extensions: Add changed property handling

This commit is contained in:
Stefan Tröger 2016-11-29 17:40:17 +01:00
parent 26e1a24060
commit cc6bc1b8d9
4 changed files with 56 additions and 50 deletions

View File

@ -26,6 +26,7 @@
#include "PropertyContainer.h" #include "PropertyContainer.h"
#include "PropertyPythonObject.h" #include "PropertyPythonObject.h"
#include "ExtensionContainer.h"
#include "Base/Interpreter.h" #include "Base/Interpreter.h"
#include <CXX/Objects.hxx> #include <CXX/Objects.hxx>
@ -253,6 +254,9 @@ protected:
Base::Type::instantiationMethod method=0); Base::Type::instantiationMethod method=0);
//@} //@}
virtual void extensionOnChanged(const Property* p) {(void)(p);};
friend class App::ExtensionContainer;
protected: protected:
void initExtension(Base::Type type); void initExtension(Base::Type type);

View File

@ -265,17 +265,11 @@ const char* ExtensionContainer::getPropertyDocumentation(const char* name) const
} }
void ExtensionContainer::onChanged(const Property* prop) { 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 //inform all extensions about changed property. This includes all properties from the
//is needed as only the extended class proxy (either c++ or python) is managed and ensured to //extended object (this) as well as all extension properties
//be the python implementation class for(auto entry : _extensions)
//Note: this property only exist if the created object is FeaturePythonT<>, this won't work for entry.second->extensionOnChanged(prop);
//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<const PropertyPythonObject*>(prop)->getValue());
}*/
App::PropertyContainer::onChanged(prop); App::PropertyContainer::onChanged(prop);
} }

View File

@ -31,43 +31,43 @@
#include <App/Application.h> #include <App/Application.h>
#include <App/FeaturePythonPyImp.h> #include <App/FeaturePythonPyImp.h>
#include "AttachableObjectPy.h" #include "AttachableObjecty.h"
using namespace Part; using namespace Part;
using namespace Attacher; using namespace Attacher;
PROPERTY_SOURCE(Part::AttachableObject, Part::Feature); EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, Part::Feature);
AttachableObject::AttachableObject() AttachExtension::AttachExtension()
: _attacher(0) : _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); 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); MapMode.setEnums(AttachEngine::eMapModeStrings);
//a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum. //a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum.
assert(MapMode.getEnumVector().size() == mmDummy_NumberOfModes); 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 setAttacher(new AttachEngine3D);//default attacher
} }
AttachableObject::~AttachableObject() AttachExtension::~AttachExtension()
{ {
if(_attacher) if(_attacher)
delete _attacher; delete _attacher;
} }
void AttachableObject::setAttacher(AttachEngine* attacher) void AttachExtension::setAttacher(AttachEngine* attacher)
{ {
if (_attacher) if (_attacher)
delete _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 //check if we need to actually change anything
if (_attacher){ if (_attacher){
@ -112,13 +112,13 @@ bool AttachableObject::changeAttacherType(const char* typeName)
return false; return false;
} }
bool AttachableObject::positionBySupport() bool AttachExtension::positionBySupport()
{ {
if (!_attacher) 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(); updateAttacherVals();
try{ try{
this->Placement.setValue(_attacher->calculateAttachedPlacement(this->Placement.getValue())); getPlacement().setValue(_attacher->calculateAttachedPlacement(getPlacement().getValue()));
return true; return true;
} catch (ExceptionCancel) { } catch (ExceptionCancel) {
//disabled, don't do anything //disabled, don't do anything
@ -126,7 +126,7 @@ bool AttachableObject::positionBySupport()
}; };
} }
App::DocumentObjectExecReturn *AttachableObject::execute() App::DocumentObjectExecReturn *AttachExtension::exttensionExecute()
{ {
if(this->isTouched_Mapping()) { if(this->isTouched_Mapping()) {
try{ try{
@ -137,12 +137,12 @@ App::DocumentObjectExecReturn *AttachableObject::execute()
return new App::DocumentObjectExecReturn(e.GetMessageString()); 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 if ((prop == &Support
|| prop == &MapMode || prop == &MapMode
|| prop == &MapPathParameter || prop == &MapPathParameter
@ -163,7 +163,7 @@ void AttachableObject::onChanged(const App::Property* prop)
eMapMode mmode = eMapMode(this->MapMode.getValue()); eMapMode mmode = eMapMode(this->MapMode.getValue());
this->superPlacement.setReadOnly(!bAttached); 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()); this->changeAttacherType(this->AttacherType.getValue());
} }
Part::Feature::onChanged(prop); App::DocumentObjectExtension::extensionOnChanged(prop);
} }
void AttachableObject::updateAttacherVals() void AttachExtension::updateAttacherVals()
{ {
if (!_attacher) if (!_attacher)
return; return;
@ -187,22 +187,31 @@ void AttachableObject::updateAttacherVals()
this->superPlacement.getValue()); this->superPlacement.getValue());
} }
App::PropertyPlacement& AttachExtension::getPlacement() {
if(!getExtendedObject()->isDerivedFrom(App::GeoFeature::getClassTypeId()))
throw Base::Exception("AttachExtension not added to GeooFeature!");
return static_cast<App::GeoFeature*>(getExtendedObject())->Placement;
}
namespace App { namespace App {
/// @cond DOXERR /// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(Part::AttachableObjectPython, Part::AttachableObject) EXTENSION_PROPERTY_SOURCE_TEMPLATE(Part::AttachExtensionPython, Part::AttachExtension)
template<> const char* Part::AttachableObjectPython::getViewProviderName(void) const { template<> const char* Part::AttachExtensionPython::getViewProviderName(void) const {
return "PartGui::ViewProviderPython"; return "PartGui::ViewProviderPython";
} }
template<> PyObject* Part::AttachableObjectPython::getPyObject(void) { template<> PyObject* Part::AttachExtensionPython::getPyObject(void) {
if (PythonObject.is(Py::_None())) { if (PythonObject.is(Py::_None())) {
// ref counter is set to 1 // ref counter is set to 1
PythonObject = Py::Object(new FeaturePythonPyT<Part::AttachableObjectPy>(this),true); PythonObject = Py::Object(new FeaturePythonPyT<Part::AttachExtensionPy>(this),true);
} }
return Py::new_reference_to(PythonObject); return Py::new_reference_to(PythonObject);
} }
/// @endcond /// @endcond
// explicit template instantiation // explicit template instantiation
template class PartExport FeaturePythonT<Part::AttachableObject>; template class PartExport FeaturePythonT<Part::AttachExtension>;
} }

View File

@ -31,6 +31,7 @@
#include <App/PropertyStandard.h> #include <App/PropertyStandard.h>
#include <App/PropertyLinks.h> #include <App/PropertyLinks.h>
#include <App/GeoFeature.h> #include <App/GeoFeature.h>
#include <App/DocumentObjectExtension.h>
#include <Base/Vector3D.h> #include <Base/Vector3D.h>
#include <Base/Placement.h> #include <Base/Placement.h>
#include <Base/Exception.h> #include <Base/Exception.h>
@ -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 * that should be attachable. It includes the required properties, and
* shortcuts for accessing the attachment math class. * 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: public:
AttachableObject(); AttachExtension();
virtual ~AttachableObject(); virtual ~AttachExtension();
/** /**
* @brief setAttacher sets the AttachEngine object. The class takes the * @brief setAttacher sets the AttachEngine object. The class takes the
@ -103,9 +100,11 @@ public:
virtual bool isTouched_Mapping() virtual bool isTouched_Mapping()
{return true; /*support.isTouched isn't true when linked objects are changed... why?..*/}; {return true; /*support.isTouched isn't true when linked objects are changed... why?..*/};
App::DocumentObjectExecReturn *execute(void); App::DocumentObjectExecReturn *extensionExecute(void);
protected: protected:
virtual void onChanged(const App::Property* /*prop*/); virtual void extensionOnChanged(const App::Property* /*prop*/);
App::PropertyPlacement& getPlacement();
public: public:
void updateAttacherVals(); void updateAttacherVals();
@ -115,7 +114,7 @@ private:
}; };
typedef App::FeaturePythonT<AttachableObject> AttachableObjectPython; typedef App::ExtensionPythonT<AttachExtension> AttachExtensionPython;
} // namespace Part } // namespace Part