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 "PropertyPythonObject.h"
#include "ExtensionContainer.h"
#include "Base/Interpreter.h"
#include <CXX/Objects.hxx>
@ -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);

View File

@ -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<const PropertyPythonObject*>(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);
}

View File

@ -31,43 +31,43 @@
#include <App/Application.h>
#include <App/FeaturePythonPyImp.h>
#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<App::GeoFeature*>(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<Part::AttachableObjectPy>(this),true);
PythonObject = Py::Object(new FeaturePythonPyT<Part::AttachExtensionPy>(this),true);
}
return Py::new_reference_to(PythonObject);
}
/// @endcond
// 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/PropertyLinks.h>
#include <App/GeoFeature.h>
#include <App/DocumentObjectExtension.h>
#include <Base/Vector3D.h>
#include <Base/Placement.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
* 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<AttachableObject> AttachableObjectPython;
typedef App::ExtensionPythonT<AttachExtension> AttachExtensionPython;
} // namespace Part