704 lines
25 KiB
C++
704 lines
25 KiB
C++
/****************************************************************************
|
|
* Copyright (c) 2017 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#ifndef APP_LINK_H
|
|
#define APP_LINK_H
|
|
|
|
#include <unordered_set>
|
|
#include <Base/Parameter.h>
|
|
#include <Base/Bitmask.h>
|
|
#include "DocumentObject.h"
|
|
#include "DocumentObjectExtension.h"
|
|
#include "FeaturePython.h"
|
|
#include "GroupExtension.h"
|
|
#include "PropertyLinks.h"
|
|
|
|
|
|
//FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic push
|
|
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
|
#endif
|
|
|
|
#define LINK_THROW(_type,_msg) do{\
|
|
if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))\
|
|
FC_ERR(_msg);\
|
|
throw _type(_msg);\
|
|
}while(0)
|
|
|
|
namespace App
|
|
{
|
|
|
|
class AppExport LinkBaseExtension : public App::DocumentObjectExtension
|
|
{
|
|
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension);
|
|
using inherited = App::DocumentObjectExtension;
|
|
|
|
public:
|
|
LinkBaseExtension();
|
|
~LinkBaseExtension() override = default;
|
|
|
|
PropertyBool _LinkTouched;
|
|
PropertyInteger _LinkOwner;
|
|
PropertyLinkList _ChildCache; // cache for plain group expansion
|
|
|
|
enum {
|
|
LinkModeNone,
|
|
LinkModeAutoDelete,
|
|
LinkModeAutoLink,
|
|
LinkModeAutoUnlink,
|
|
};
|
|
|
|
/** \name Parameter definition
|
|
*
|
|
* Parameter definition (Name, Type, Property Type, Default, Document).
|
|
* The variadic is here so that the parameter can be extended by adding
|
|
* extra fields. See LINK_PARAM_EXT() for an example
|
|
*/
|
|
//@{
|
|
|
|
#define LINK_PARAM_LINK_PLACEMENT(...) \
|
|
(LinkPlacement, Base::Placement, App::PropertyPlacement, Base::Placement(), "Link placement", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_PLACEMENT(...) \
|
|
(Placement, Base::Placement, App::PropertyPlacement, Base::Placement(), \
|
|
"Alias to LinkPlacement to make the link object compatibale with other objects", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_OBJECT(...) \
|
|
(LinkedObject, App::DocumentObject*, App::PropertyLink, 0, "Linked object", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_TRANSFORM(...) \
|
|
(LinkTransform, bool, App::PropertyBool, false, \
|
|
"Set to false to override linked object's placement", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_CLAIM_CHILD(...) \
|
|
(LinkClaimChild, bool, App::PropertyBool, false, \
|
|
"Claim the linked object as a child", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COPY_ON_CHANGE(...) \
|
|
(LinkCopyOnChange, long, App::PropertyEnumeration, ((long)0), \
|
|
"Disabled: disable copy on change\n"\
|
|
"Enabled: enable copy linked object on change of any of its properties marked as CopyOnChange\n"\
|
|
"Owned: indicate the linked object has been copied and is own owned by the link. And the\n"\
|
|
" the link will try to sync any change of the original linked object back to the copy.",\
|
|
##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COPY_ON_CHANGE_SOURCE(...) \
|
|
(LinkCopyOnChangeSource, App::DocumentObject*, App::PropertyLink, 0, "The copy on change source object", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COPY_ON_CHANGE_GROUP(...) \
|
|
(LinkCopyOnChangeGroup, App::DocumentObject*, App::PropertyLink, 0, \
|
|
"Linked to a internal group object for holding on change copies", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COPY_ON_CHANGE_TOUCHED(...) \
|
|
(LinkCopyOnChangeTouched, bool, App::PropertyBool, 0, "Indicating the copy on change source object has been changed", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_SCALE(...) \
|
|
(Scale, double, App::PropertyFloat, 1.0, "Scale factor", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_SCALE_VECTOR(...) \
|
|
(ScaleVector, Base::Vector3d, App::PropertyVector, Base::Vector3d(1,1,1), "Scale factors", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_PLACEMENTS(...) \
|
|
(PlacementList, std::vector<Base::Placement>, App::PropertyPlacementList, std::vector<Base::Placement>(),\
|
|
"The placement for each link element", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_SCALES(...) \
|
|
(ScaleList, std::vector<Base::Vector3d>, App::PropertyVectorList, std::vector<Base::Vector3d>(),\
|
|
"The scale factors for each link element", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_VISIBILITIES(...) \
|
|
(VisibilityList, boost::dynamic_bitset<>, App::PropertyBoolList, boost::dynamic_bitset<>(),\
|
|
"The visibility state of each link element", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COUNT(...) \
|
|
(ElementCount, int, App::PropertyInteger, 0, "Link element count", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_ELEMENTS(...) \
|
|
(ElementList, std::vector<App::DocumentObject*>, App::PropertyLinkList, std::vector<App::DocumentObject*>(),\
|
|
"The link element object list", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_SHOW_ELEMENT(...) \
|
|
(ShowElement, bool, App::PropertyBool, true, "Enable link element list", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_MODE(...) \
|
|
(LinkMode, long, App::PropertyEnumeration, ((long)0), "Link group mode", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_LINK_EXECUTE(...) \
|
|
(LinkExecute, const char*, App::PropertyString, (""),\
|
|
"Link execute function. Default to 'appLinkExecute'. 'None' to disable.", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM_COLORED_ELEMENTS(...) \
|
|
(ColoredElements, App::DocumentObject*, App::PropertyLinkSubHidden, \
|
|
0, "Link colored elements", ##__VA_ARGS__)
|
|
|
|
#define LINK_PARAM(_param) (LINK_PARAM_##_param())
|
|
|
|
#define LINK_PNAME(_param) BOOST_PP_TUPLE_ELEM(0,_param)
|
|
#define LINK_PTYPE(_param) BOOST_PP_TUPLE_ELEM(1,_param)
|
|
#define LINK_PPTYPE(_param) BOOST_PP_TUPLE_ELEM(2,_param)
|
|
#define LINK_PDEF(_param) BOOST_PP_TUPLE_ELEM(3,_param)
|
|
#define LINK_PDOC(_param) BOOST_PP_TUPLE_ELEM(4,_param)
|
|
|
|
#define LINK_PINDEX(_param) BOOST_PP_CAT(Prop,LINK_PNAME(_param))
|
|
//@}
|
|
|
|
#define LINK_PARAMS \
|
|
LINK_PARAM(PLACEMENT)\
|
|
LINK_PARAM(LINK_PLACEMENT)\
|
|
LINK_PARAM(OBJECT)\
|
|
LINK_PARAM(CLAIM_CHILD)\
|
|
LINK_PARAM(TRANSFORM)\
|
|
LINK_PARAM(SCALE)\
|
|
LINK_PARAM(SCALE_VECTOR)\
|
|
LINK_PARAM(PLACEMENTS)\
|
|
LINK_PARAM(SCALES)\
|
|
LINK_PARAM(VISIBILITIES)\
|
|
LINK_PARAM(COUNT)\
|
|
LINK_PARAM(ELEMENTS)\
|
|
LINK_PARAM(SHOW_ELEMENT)\
|
|
LINK_PARAM(MODE)\
|
|
LINK_PARAM(LINK_EXECUTE)\
|
|
LINK_PARAM(COLORED_ELEMENTS)\
|
|
LINK_PARAM(COPY_ON_CHANGE)\
|
|
LINK_PARAM(COPY_ON_CHANGE_SOURCE)\
|
|
LINK_PARAM(COPY_ON_CHANGE_GROUP)\
|
|
LINK_PARAM(COPY_ON_CHANGE_TOUCHED)\
|
|
|
|
enum PropIndex {
|
|
#define LINK_PINDEX_DEFINE(_1,_2,_param) LINK_PINDEX(_param),
|
|
|
|
// defines Prop##Name enumeration value
|
|
BOOST_PP_SEQ_FOR_EACH(LINK_PINDEX_DEFINE,_,LINK_PARAMS)
|
|
PropMax
|
|
};
|
|
|
|
virtual void setProperty(int idx, Property *prop);
|
|
Property *getProperty(int idx);
|
|
Property *getProperty(const char *);
|
|
|
|
struct PropInfo {
|
|
int index;
|
|
const char *name;
|
|
Base::Type type;
|
|
const char *doc;
|
|
|
|
PropInfo(int index, const char *name,Base::Type type,const char *doc)
|
|
: index(index), name(name), type(type), doc(doc)
|
|
{}
|
|
|
|
PropInfo() : index(0), name(nullptr), doc(nullptr) {}
|
|
};
|
|
|
|
#define LINK_PROP_INFO(_1,_var,_param) \
|
|
_var.push_back(PropInfo(BOOST_PP_CAT(Prop,LINK_PNAME(_param)),\
|
|
BOOST_PP_STRINGIZE(LINK_PNAME(_param)),\
|
|
LINK_PPTYPE(_param)::getClassTypeId(), \
|
|
LINK_PDOC(_param)));
|
|
|
|
virtual const std::vector<PropInfo> &getPropertyInfo() const;
|
|
|
|
using PropInfoMap = std::map<std::string, PropInfo>;
|
|
virtual const PropInfoMap &getPropertyInfoMap() const;
|
|
|
|
enum LinkCopyOnChangeType {
|
|
CopyOnChangeDisabled = 0,
|
|
CopyOnChangeEnabled = 1,
|
|
CopyOnChangeOwned = 2,
|
|
CopyOnChangeTracking = 3
|
|
};
|
|
|
|
#define LINK_PROP_GET(_1,_2,_param) \
|
|
LINK_PTYPE(_param) BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Value)) () const {\
|
|
auto prop = props[LINK_PINDEX(_param)];\
|
|
if(!prop) return LINK_PDEF(_param);\
|
|
return static_cast<const LINK_PPTYPE(_param) *>(prop)->getValue();\
|
|
}\
|
|
const LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () const {\
|
|
auto prop = props[LINK_PINDEX(_param)];\
|
|
return static_cast<const LINK_PPTYPE(_param) *>(prop);\
|
|
}\
|
|
LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () {\
|
|
auto prop = props[LINK_PINDEX(_param)];\
|
|
return static_cast<LINK_PPTYPE(_param) *>(prop);\
|
|
}\
|
|
|
|
// defines get##Name##Property() and get##Name##Value() accessor
|
|
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET,_,LINK_PARAMS)
|
|
|
|
PropertyLinkList *_getElementListProperty() const;
|
|
const std::vector<App::DocumentObject*> &_getElementListValue() const;
|
|
|
|
PropertyBool *_getShowElementProperty() const;
|
|
bool _getShowElementValue() const;
|
|
|
|
PropertyInteger *_getElementCountProperty() const;
|
|
int _getElementCountValue() const;
|
|
|
|
std::vector<DocumentObject*> getLinkedChildren(bool filter=true) const;
|
|
|
|
const char *flattenSubname(const char *subname) const;
|
|
void expandSubname(std::string &subname) const;
|
|
|
|
DocumentObject *getLink(int depth=0) const;
|
|
|
|
Base::Matrix4D getTransform(bool transform) const;
|
|
Base::Vector3d getScaleVector() const;
|
|
|
|
App::GroupExtension *linkedPlainGroup() const;
|
|
|
|
bool linkTransform() const;
|
|
|
|
const char *getSubName() const {
|
|
parseSubName();
|
|
return !mySubName.empty()?mySubName.c_str():nullptr;
|
|
}
|
|
|
|
const std::vector<std::string> &getSubElements() const {
|
|
parseSubName();
|
|
return mySubElements;
|
|
}
|
|
|
|
bool extensionGetSubObject(DocumentObject *&ret, const char *subname,
|
|
PyObject **pyObj=nullptr, Base::Matrix4D *mat=nullptr, bool transform=false, int depth=0) const override;
|
|
|
|
bool extensionGetSubObjects(std::vector<std::string>&ret, int reason) const override;
|
|
|
|
bool extensionGetLinkedObject(DocumentObject *&ret,
|
|
bool recurse, Base::Matrix4D *mat, bool transform, int depth) const override;
|
|
|
|
App::DocumentObjectExecReturn *extensionExecute() override;
|
|
short extensionMustExecute() override;
|
|
void extensionOnChanged(const Property* p) override;
|
|
void onExtendedUnsetupObject () override;
|
|
void onExtendedDocumentRestored() override;
|
|
|
|
int extensionSetElementVisible(const char *, bool) override;
|
|
int extensionIsElementVisible(const char *) override;
|
|
bool extensionHasChildElement() const override;
|
|
|
|
PyObject* getExtensionPyObject() override;
|
|
|
|
Property *extensionGetPropertyByName(const char* name) const override;
|
|
|
|
static int getArrayIndex(const char *subname, const char **psubname=nullptr);
|
|
int getElementIndex(const char *subname, const char **psubname=nullptr) const;
|
|
void elementNameFromIndex(int idx, std::ostream &ss) const;
|
|
|
|
DocumentObject *getContainer();
|
|
const DocumentObject *getContainer() const;
|
|
|
|
void setLink(int index, DocumentObject *obj, const char *subname=nullptr,
|
|
const std::vector<std::string> &subs = std::vector<std::string>());
|
|
|
|
DocumentObject *getTrueLinkedObject(bool recurse,
|
|
Base::Matrix4D *mat=nullptr,int depth=0, bool noElement=false) const;
|
|
|
|
using LinkPropMap = std::map<const Property*,std::pair<LinkBaseExtension*,int> >;
|
|
|
|
bool hasPlacement() const {
|
|
return getLinkPlacementProperty() || getPlacementProperty();
|
|
}
|
|
|
|
void cacheChildLabel(int enable=-1) const;
|
|
|
|
static bool setupCopyOnChange(App::DocumentObject *obj, App::DocumentObject *linked,
|
|
std::vector<boost::signals2::scoped_connection> *copyOnChangeConns, bool checkExisting);
|
|
|
|
static bool isCopyOnChangeProperty(App::DocumentObject *obj, const Property &prop);
|
|
|
|
void syncCopyOnChange();
|
|
|
|
/** Options used in setOnChangeCopyObject()
|
|
* Multiple options can be combined by bitwise or operator
|
|
*/
|
|
enum class OnChangeCopyOptions {
|
|
/// No options set
|
|
None = 0,
|
|
/// If set, then exclude the input from object list to copy on change, or else, include the input object.
|
|
Exclude = 1,
|
|
/// If set , then apply the setting to all links to the input object, or else, apply only to this link.
|
|
ApplyAll = 2,
|
|
};
|
|
|
|
/** Include or exclude object from list of objects to copy on change
|
|
* @param obj: input object
|
|
* @param options: control options. @sa OnChangeCopyOptions.
|
|
*/
|
|
void setOnChangeCopyObject(App::DocumentObject *obj, OnChangeCopyOptions options);
|
|
|
|
std::vector<App::DocumentObject *> getOnChangeCopyObjects(
|
|
std::vector<App::DocumentObject *> *excludes = nullptr,
|
|
App::DocumentObject *src = nullptr);
|
|
|
|
bool isLinkedToConfigurableObject() const;
|
|
|
|
void monitorOnChangeCopyObjects(const std::vector<App::DocumentObject*> &objs);
|
|
|
|
/// Check if the linked object is a copy on change
|
|
bool isLinkMutated() const;
|
|
|
|
protected:
|
|
void _handleChangedPropertyName(Base::XMLReader &reader,
|
|
const char * TypeName, const char *PropName);
|
|
void parseSubName() const;
|
|
void update(App::DocumentObject *parent, const Property *prop);
|
|
void checkCopyOnChange(App::DocumentObject *parent, const App::Property &prop);
|
|
void setupCopyOnChange(App::DocumentObject *parent, bool checkSource = false);
|
|
App::DocumentObject *makeCopyOnChange();
|
|
void syncElementList();
|
|
void detachElement(App::DocumentObject *obj);
|
|
void detachElements();
|
|
void checkGeoElementMap(const App::DocumentObject *obj,
|
|
const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const;
|
|
void updateGroup();
|
|
void slotChangedPlainGroup(const App::DocumentObject &, const App::Property &);
|
|
|
|
protected:
|
|
std::vector<Property *> props;
|
|
std::unordered_set<const App::DocumentObject*> myHiddenElements;
|
|
mutable std::vector<std::string> mySubElements;
|
|
mutable std::string mySubName;
|
|
|
|
std::unordered_map<const App::DocumentObject*,
|
|
boost::signals2::scoped_connection> plainGroupConns;
|
|
|
|
long prevLinkedObjectID = 0;
|
|
|
|
mutable std::unordered_map<std::string,int> myLabelCache; // for label based subname lookup
|
|
mutable bool enableLabelCache{false};
|
|
bool hasOldSubElement{false};
|
|
|
|
std::vector<boost::signals2::scoped_connection> copyOnChangeConns;
|
|
std::vector<boost::signals2::scoped_connection> copyOnChangeSrcConns;
|
|
bool hasCopyOnChange{true};
|
|
|
|
mutable bool checkingProperty = false;
|
|
bool pauseCopyOnChange = false;
|
|
|
|
boost::signals2::scoped_connection connCopyOnChangeSource;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
using LinkBaseExtensionPython = ExtensionPythonT<LinkBaseExtension>;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
class AppExport LinkExtension : public LinkBaseExtension
|
|
{
|
|
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension);
|
|
using inherited = LinkBaseExtension;
|
|
|
|
public:
|
|
LinkExtension();
|
|
~LinkExtension() override = default;
|
|
|
|
/** \name Helpers for defining extended parameter
|
|
*
|
|
* extended parameter definition
|
|
* (Name, Type, Property_Type, Default, Document, Property_Name,
|
|
* Derived_Property_Type, App_Property_Type, Group)
|
|
*
|
|
* This helper simply reuses Name as Property_Name, Property_Type as
|
|
* Derived_Property_type, Prop_None as App_Propert_Type
|
|
*
|
|
* Note: Because PropertyView will merge linked object's properties into
|
|
* ours, we set the default group name as ' Link' with a leading space to
|
|
* try to make our group before others
|
|
*/
|
|
//@{
|
|
|
|
#define LINK_ENAME(_param) BOOST_PP_TUPLE_ELEM(5,_param)
|
|
#define LINK_ETYPE(_param) BOOST_PP_TUPLE_ELEM(6,_param)
|
|
#define LINK_EPTYPE(_param) BOOST_PP_TUPLE_ELEM(7,_param)
|
|
#define LINK_EGROUP(_param) BOOST_PP_TUPLE_ELEM(8,_param)
|
|
|
|
#define _LINK_PROP_ADD(_add_property, _param) \
|
|
_add_property(BOOST_PP_STRINGIZE(LINK_ENAME(_param)),LINK_ENAME(_param),\
|
|
(LINK_PDEF(_param)),LINK_EGROUP(_param),LINK_EPTYPE(_param),LINK_PDOC(_param));\
|
|
setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param));
|
|
|
|
#define LINK_PROP_ADD(_1,_2,_param) \
|
|
_LINK_PROP_ADD(_ADD_PROPERTY_TYPE,_param);
|
|
|
|
#define LINK_PROP_ADD_EXTENSION(_1,_2,_param) \
|
|
_LINK_PROP_ADD(_EXTENSION_ADD_PROPERTY_TYPE,_param);
|
|
|
|
#define LINK_PROPS_ADD(_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD,_,_seq)
|
|
|
|
#define LINK_PROPS_ADD_EXTENSION(_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD_EXTENSION,_,_seq)
|
|
|
|
#define _LINK_PROP_SET(_1,_2,_param) \
|
|
setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param));
|
|
|
|
#define LINK_PROPS_SET(_seq) BOOST_PP_SEQ_FOR_EACH(_LINK_PROP_SET,_,_seq)
|
|
|
|
/// Helper for defining default extended parameter
|
|
#define _LINK_PARAM_EXT(_name,_type,_ptype,_def,_doc,...) \
|
|
((_name,_type,_ptype,_def,_doc,_name,_ptype,App::Prop_None," Link"))
|
|
|
|
/** Define default extended parameter
|
|
* It simply reuses Name as Property_Name, Property_Type as
|
|
* Derived_Property_Type, and App::Prop_None as App::PropertyType
|
|
*/
|
|
#define LINK_PARAM_EXT(_param) BOOST_PP_EXPAND(_LINK_PARAM_EXT LINK_PARAM_##_param())
|
|
|
|
/// Helper for extended parameter with app property type
|
|
#define _LINK_PARAM_EXT_ATYPE(_name,_type,_ptype,_def,_doc,_atype) \
|
|
((_name,_type,_ptype,_def,_doc,_name,_ptype,_atype," Link"))
|
|
|
|
/// Define extended parameter with app property type
|
|
#define LINK_PARAM_EXT_ATYPE(_param,_atype) \
|
|
BOOST_PP_EXPAND(_LINK_PARAM_EXT_ATYPE LINK_PARAM_##_param(_atype))
|
|
|
|
/// Helper for extended parameter with derived property type
|
|
#define _LINK_PARAM_EXT_TYPE(_name,_type,_ptype,_def,_doc,_dtype) \
|
|
((_name,_type,_ptype,_def,_doc,_name,_dtype,App::Prop_None," Link"))
|
|
|
|
/// Define extended parameter with derived property type
|
|
#define LINK_PARAM_EXT_TYPE(_param,_dtype) \
|
|
BOOST_PP_EXPAND(_LINK_PARAM_EXT_TYPE LINK_PARAM_##_param(_dtype))
|
|
|
|
/// Helper for extended parameter with a different property name
|
|
#define _LINK_PARAM_EXT_NAME(_name,_type,_ptype,_def,_doc,_pname) \
|
|
((_name,_type,_ptype,_def,_doc,_pname,_ptype,App::Prop_None," Link"))
|
|
|
|
/// Define extended parameter with a different property name
|
|
#define LINK_PARAM_EXT_NAME(_param,_pname) BOOST_PP_EXPAND(_LINK_PARAM_EXT_NAME LINK_PARAM_##_param(_pname))
|
|
//@}
|
|
|
|
#define LINK_PARAMS_EXT \
|
|
LINK_PARAM_EXT(SCALE)\
|
|
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\
|
|
LINK_PARAM_EXT(SCALES)\
|
|
LINK_PARAM_EXT(VISIBILITIES)\
|
|
LINK_PARAM_EXT(PLACEMENTS)\
|
|
LINK_PARAM_EXT(ELEMENTS)
|
|
|
|
#define LINK_PROP_DEFINE(_1,_2,_param) LINK_ETYPE(_param) LINK_ENAME(_param);
|
|
#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE,_,_seq)
|
|
|
|
// defines the actual properties
|
|
LINK_PROPS_DEFINE(LINK_PARAMS_EXT)
|
|
|
|
void onExtendedDocumentRestored() override {
|
|
LINK_PROPS_SET(LINK_PARAMS_EXT);
|
|
inherited::onExtendedDocumentRestored();
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
using LinkExtensionPython = ExtensionPythonT<LinkExtension>;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
class AppExport Link : public App::DocumentObject, public App::LinkExtension
|
|
{
|
|
PROPERTY_HEADER_WITH_EXTENSIONS(App::Link);
|
|
using inherited = App::DocumentObject;
|
|
public:
|
|
|
|
#define LINK_PARAMS_LINK \
|
|
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\
|
|
LINK_PARAM_EXT(CLAIM_CHILD)\
|
|
LINK_PARAM_EXT(TRANSFORM)\
|
|
LINK_PARAM_EXT(LINK_PLACEMENT)\
|
|
LINK_PARAM_EXT(PLACEMENT)\
|
|
LINK_PARAM_EXT(SHOW_ELEMENT)\
|
|
LINK_PARAM_EXT_TYPE(COUNT,App::PropertyIntegerConstraint)\
|
|
LINK_PARAM_EXT(LINK_EXECUTE)\
|
|
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE)\
|
|
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\
|
|
|
|
LINK_PROPS_DEFINE(LINK_PARAMS_LINK)
|
|
|
|
Link();
|
|
|
|
const char* getViewProviderName() const override{
|
|
return "Gui::ViewProviderLink";
|
|
}
|
|
|
|
void onDocumentRestored() override {
|
|
LINK_PROPS_SET(LINK_PARAMS_LINK);
|
|
inherited::onDocumentRestored();
|
|
}
|
|
|
|
void handleChangedPropertyName(Base::XMLReader &reader,
|
|
const char * TypeName, const char *PropName) override
|
|
{
|
|
_handleChangedPropertyName(reader,TypeName,PropName);
|
|
}
|
|
|
|
bool canLinkProperties() const override;
|
|
};
|
|
|
|
using LinkPython = App::FeaturePythonT<Link>;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
class AppExport LinkElement : public App::DocumentObject, public App::LinkBaseExtension {
|
|
PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkElement);
|
|
using inherited = App::DocumentObject;
|
|
public:
|
|
|
|
#define LINK_PARAMS_ELEMENT \
|
|
LINK_PARAM_EXT(SCALE)\
|
|
LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\
|
|
LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\
|
|
LINK_PARAM_EXT(TRANSFORM) \
|
|
LINK_PARAM_EXT(LINK_PLACEMENT)\
|
|
LINK_PARAM_EXT(PLACEMENT)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE)\
|
|
LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\
|
|
LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\
|
|
|
|
// defines the actual properties
|
|
LINK_PROPS_DEFINE(LINK_PARAMS_ELEMENT)
|
|
|
|
LinkElement();
|
|
const char* getViewProviderName() const override{
|
|
return "Gui::ViewProviderLink";
|
|
}
|
|
|
|
void onDocumentRestored() override {
|
|
LINK_PROPS_SET(LINK_PARAMS_ELEMENT);
|
|
inherited::onDocumentRestored();
|
|
}
|
|
|
|
bool canDelete() const;
|
|
|
|
void handleChangedPropertyName(Base::XMLReader &reader,
|
|
const char * TypeName, const char *PropName) override
|
|
{
|
|
_handleChangedPropertyName(reader,TypeName,PropName);
|
|
}
|
|
};
|
|
|
|
using LinkElementPython = App::FeaturePythonT<LinkElement>;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
class AppExport LinkGroup : public App::DocumentObject, public App::LinkBaseExtension {
|
|
PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkGroup);
|
|
using inherited = App::DocumentObject;
|
|
public:
|
|
|
|
#define LINK_PARAMS_GROUP \
|
|
LINK_PARAM_EXT(ELEMENTS)\
|
|
LINK_PARAM_EXT(PLACEMENT)\
|
|
LINK_PARAM_EXT(VISIBILITIES)\
|
|
LINK_PARAM_EXT(MODE)\
|
|
LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden)
|
|
|
|
// defines the actual properties
|
|
LINK_PROPS_DEFINE(LINK_PARAMS_GROUP)
|
|
|
|
LinkGroup();
|
|
|
|
const char* getViewProviderName() const override{
|
|
return "Gui::ViewProviderLink";
|
|
}
|
|
|
|
void onDocumentRestored() override {
|
|
LINK_PROPS_SET(LINK_PARAMS_GROUP);
|
|
inherited::onDocumentRestored();
|
|
}
|
|
};
|
|
|
|
using LinkGroupPython = App::FeaturePythonT<LinkGroup>;
|
|
|
|
} //namespace App
|
|
|
|
ENABLE_BITMASK_OPERATORS(App::Link::OnChangeCopyOptions)
|
|
|
|
/*[[[cog
|
|
import LinkParams
|
|
LinkParams.declare()
|
|
]]]*/
|
|
|
|
namespace App {
|
|
/** Convenient class to obtain App::Link related parameters
|
|
|
|
* The parameters are under group "User parameter:BaseApp/Preferences/Link"
|
|
*
|
|
* This class is auto generated by LinkParams.py. Modify that file
|
|
* instead of this one, if you want to add any parameter. You need
|
|
* to install Cog Python package for code generation:
|
|
* @code
|
|
* pip install cogapp
|
|
* @endcode
|
|
*
|
|
* Once modified, you can regenerate the header and the source file,
|
|
* @code
|
|
* python3 -m cogapp -r Link.h Link.cpp
|
|
* @endcode
|
|
*
|
|
* You can add a new parameter by adding lines in LinkParams.py. Available
|
|
* parameter types are 'Int, UInt, String, Bool, Float'. For example, to add
|
|
* a new Int type parameter,
|
|
* @code
|
|
* ParamInt(parameter_name, default_value, documentation, on_change=False)
|
|
* @endcode
|
|
*
|
|
* If there is special handling on parameter change, pass in on_change=True.
|
|
* And you need to provide a function implementation in Link.cpp with
|
|
* the following signature.
|
|
* @code
|
|
* void LinkParams:on<parameter_name>Changed()
|
|
* @endcode
|
|
*/
|
|
class AppExport LinkParams {
|
|
public:
|
|
static ParameterGrp::handle getHandle();
|
|
|
|
//@{
|
|
/// Accessor for parameter CopyOnChangeApplyToAll
|
|
///
|
|
/// Stores the last user choice of whether to apply CopyOnChange setup to all link
|
|
/// that links to the same configurable object
|
|
static const bool & getCopyOnChangeApplyToAll();
|
|
static const bool & defaultCopyOnChangeApplyToAll();
|
|
static void removeCopyOnChangeApplyToAll();
|
|
static void setCopyOnChangeApplyToAll(const bool &v);
|
|
static const char *docCopyOnChangeApplyToAll();
|
|
//@}
|
|
|
|
// Auto generated code. See class document of LinkParams.
|
|
};
|
|
} // namespace App
|
|
//[[[end]]]
|
|
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic pop
|
|
#endif
|
|
|
|
#endif // APP_LINK_H
|