App: add New APIs for future Link function
DocumentObject: * getSubObject(): the most important API for Link to work with hierarchies. The function is a inspired from and replaces the getPySubObjects(). It returns a child object following a dot separated subname reference, and can optionally return accumulated transformation, and/or a python object of the refered sub-object/element. The default implementation here is to look for link type property, and search for the referenced object. This patch also include other specialized implementation of this API, such as (GeoFeature)GroupExtension (through extensionGetSubObject()), PartDesign::Body, and so on. A link type object is expected to call the linked object's getSubObject() for resolving. * getSubObjectList(): helper function to return a list of object referenced in the given subname. * getSubObjects(): return a list of subname references of all children objects. The purpose of this function is similar to ViewProvider::claimChildren(). Container type object is expected to implement this function. The reason it returns subname references instead of just object is to allow the container to skip hierarchies. For example, the Assembly3 container uses this to skip the constraint and element group. * getLinkedObject(), obtain the linked object, and optionally with the accumulated transformation. It is expected to return a linked object or the object itself if it is not a link. In case there are multiple levels of linking involved, this function allows the caller to retrieve the linked object recursively. * hasChildElement(), set/isElementVisible(), controls the children visibility for a group type object. Because the child object may be claimed by other objects, it is essential to have independent control of children visibilities. These APIs are designed to abstract how group manages the child visibility. For performance reason, these function are meant to control only the immediate child object. * resolve(), helper function to parse subname reference and resolve the final object, and optionally the immediate parent of the final object, the final object reference name (for calling `set/isElementVisible()`), and the subname reference if there is one. * touch(), add optional argument 'noRecompute' for better backward compatibility with the NoRecompute flag. By default, touch() causes recompute unless noRecompute is true * signalChanged/signalBeforeChange, two new signal for tracking changes of a specific object. * getViewProviderNameOverride(), return a string of the view provider type of this object. This allows Python class to override the view provider of an object. This feature will be used by ViewProviderLink which is designed to work with any object that has LinkBaseExtension. * canLinkProperties(), will be used by Gui::PropertyView to display linked object properties together with the object's own properties. * redirectSubname(), will be used by Gui::Tree to allow an object to redirect selection to some other object when (pre)selected in the tree view. * Visibility, new property serve as the same purpose as view provider property of the same name. It is added here so that App namespace code can check for visibility without Gui module. This is useful, for example, when constructing a compound shape of a container that respects the children visibility. * (has)hasHiddenMarker(), return or check for a special sub-element name used as marker for overriding sub-object visibility. Will be used by Gui::ViewProvider, it is put here for the same reason as adding Visibility property. * getID(), return object internal identifier. Each object is now assigned an integer identifier that is unique within its containing document. Document: * ShowHidden, new property to tell tree view whether to show hidden object items. * signalTouchedObject, new signal triggered when manually touch an object when calling its touch() function * getObjectByID(), get object by its identifier * addObject() is modified to allow overriding view provider * has/getLinksTo(), helper function to obtain links to a given object. Application: * checkLinkDepth(), helper function to check recursive depth for link traversal. The depth is checked against the total object count of all opened documents. The count (_objCount) is internally updated whenever object is added or removed. * has/getLinksTo(), same as Document::has/getLinksTo() but return links from all opened documents. GroupExtension/OriginGroupExtension/DatumFeature/DatumCS/Part::Feature: implement sepcialized getSubObject/getSubObjects().
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include <App/PropertyExpressionEngine.h>
|
||||
|
||||
#include <Base/TimeInfo.h>
|
||||
#include <Base/Matrix.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
#include <bitset>
|
||||
@@ -46,7 +47,7 @@ enum ObjectStatus {
|
||||
Touch = 0,
|
||||
Error = 1,
|
||||
New = 2,
|
||||
Recompute = 3,
|
||||
Recompute = 3, // set when the object is currently being recomputed
|
||||
Restore = 4,
|
||||
Remove = 5,
|
||||
PythonCall = 6,
|
||||
@@ -86,18 +87,35 @@ class AppExport DocumentObject: public App::TransactionalObject
|
||||
public:
|
||||
|
||||
PropertyString Label;
|
||||
PropertyString Label2;
|
||||
PropertyExpressionEngine ExpressionEngine;
|
||||
|
||||
/// Allow control visibility status in App name space
|
||||
PropertyBool Visibility;
|
||||
|
||||
/// signal before changing a property of this object
|
||||
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalBeforeChange;
|
||||
/// signal on changed property of this object
|
||||
boost::signals2::signal<void (const App::DocumentObject&, const App::Property&)> signalChanged;
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "";
|
||||
}
|
||||
/// This function is introduced to allow Python feature override its view provider
|
||||
virtual const char *getViewProviderNameOverride() const {
|
||||
return getViewProviderName();
|
||||
}
|
||||
/// Constructor
|
||||
DocumentObject(void);
|
||||
virtual ~DocumentObject();
|
||||
|
||||
/// returns the name which is set in the document for this object (not the name property!)
|
||||
const char *getNameInDocument(void) const;
|
||||
/// Return the object ID that is unique within its owner document
|
||||
long getID() const {return _Id;}
|
||||
/// Return the object full name of the form DocName#ObjName
|
||||
std::string getFullName() const;
|
||||
virtual bool isAttachedToDocument() const;
|
||||
virtual const char* detachFromDocument();
|
||||
/// gets the document in which this Object is handled
|
||||
@@ -107,7 +125,7 @@ public:
|
||||
*/
|
||||
//@{
|
||||
/// set this document object touched (cause recomputation on dependent features)
|
||||
void touch(void);
|
||||
void touch(bool noRecompute=false);
|
||||
/// test if this document object is touched
|
||||
bool isTouched(void) const;
|
||||
/// Enforce this document object to be recomputed
|
||||
@@ -137,6 +155,31 @@ public:
|
||||
void setStatus(ObjectStatus pos, bool on) {StatusBits.set((size_t)pos, on);}
|
||||
//@}
|
||||
|
||||
/** Child element handling
|
||||
*/
|
||||
//@{
|
||||
/** Set sub-element visibility
|
||||
*
|
||||
* For performance reason, \c element must not contain any further
|
||||
* sub-elements, i.e. there should be no '.' inside \c element.
|
||||
*
|
||||
* @return -1 if element visiblity is not supported, 0 if element is not
|
||||
* found, 1 if success
|
||||
*/
|
||||
virtual int setElementVisible(const char *element, bool visible);
|
||||
|
||||
/** Get sub-element visibility
|
||||
*
|
||||
* @return -1 if element visiblity is not supported or element not found, 0
|
||||
* if element is invisible, or else 1
|
||||
*/
|
||||
virtual int isElementVisible(const char *element) const;
|
||||
|
||||
/// return true to activate tree view group object handling and element visibility
|
||||
virtual bool hasChildElement() const;
|
||||
//@}
|
||||
|
||||
|
||||
/** DAG handling
|
||||
This part of the interface deals with viewing the document as
|
||||
a DAG (directed acyclic graph).
|
||||
@@ -214,8 +257,89 @@ public:
|
||||
*/
|
||||
virtual void onLostLinkToObject(DocumentObject*);
|
||||
virtual PyObject *getPyObject(void);
|
||||
/// its used to get the python sub objects by name (e.g. by the selection)
|
||||
virtual std::vector<PyObject *> getPySubObjects(const std::vector<std::string>&) const;
|
||||
|
||||
/** Get the sub element/object by name
|
||||
*
|
||||
* @param subname: a string which is dot separated name to refer to a sub
|
||||
* element or object. An empty string can be used to refer to the object
|
||||
* itself
|
||||
*
|
||||
* @param pyObj: if non zero, returns the python object corresponding to
|
||||
* this sub object. The actual type of this python object is implementation
|
||||
* dependent. For example, The current implementation of Part::Feature will
|
||||
* return the TopoShapePy, event if there is no sub-element reference, in
|
||||
* which case it returns the whole shape.
|
||||
*
|
||||
* @param mat: If non zero, it is used as the current transformation matrix
|
||||
* on input. And output as the accumulated transformation up until and
|
||||
* include the transformation applied by the final object reference in \c
|
||||
* subname. For Part::Feature, the transformation is applied to the
|
||||
* TopoShape inside \c pyObj before returning.
|
||||
*
|
||||
* @param transform: if false, then it will not apply the object's own
|
||||
* transformation to \c mat, which lets you override the object's placement
|
||||
* (and possibly scale).
|
||||
*
|
||||
* @param depth: depth limitation as hint for cyclic link detection
|
||||
*
|
||||
* @return The last document object refered in subname. If subname is empty,
|
||||
* then it shall return itself. If subname is invalid, then it shall return
|
||||
* zero.
|
||||
*/
|
||||
virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj=0,
|
||||
Base::Matrix4D *mat=0, bool transform=true, int depth=0) const;
|
||||
|
||||
/// Return a list of objects referenced by a given subname including this object
|
||||
std::vector<DocumentObject*> getSubObjectList(const char *subname) const;
|
||||
|
||||
/// reason of calling getSubObjects()
|
||||
enum GSReason {
|
||||
/// default, mostly for exporting shape objects
|
||||
GS_DEFAULT,
|
||||
/// for element selection
|
||||
GS_SELECT,
|
||||
};
|
||||
|
||||
/** Return name reference of all sub-objects
|
||||
*
|
||||
* @param reason: indicate reason of obtaining the sub objects
|
||||
*
|
||||
* The default implementation returns all object references in
|
||||
* PropertyLink, and PropertyLinkList, if any
|
||||
*
|
||||
* @return Return a vector of subname references for all sub-objects. In
|
||||
* most cases, the name returned will be the object name plus an ending
|
||||
* '.', which can be passed directly to getSubObject() to retrieve the
|
||||
* name. The reason to return the name reference instead of the sub object
|
||||
* itself is because there may be no real sub object, or the sub object
|
||||
* need special transformation. For example, sub objects of an array type
|
||||
* of object.
|
||||
*/
|
||||
virtual std::vector<std::string> getSubObjects(int reason=0) const;
|
||||
|
||||
///Obtain top parents and subnames of this object using its InList
|
||||
std::vector<std::pair<App::DocumentObject*,std::string> > getParents(int depth=0) const;
|
||||
|
||||
/** Return the linked object with optional transformation
|
||||
*
|
||||
* @param recurse: If false, return the immediate linked object, or else
|
||||
* recursively call this function to return the final linked object.
|
||||
*
|
||||
* @param mat: If non zero, it is used as the current transformation matrix
|
||||
* on input. And output as the accumulated transformation till the final
|
||||
* linked object.
|
||||
*
|
||||
* @param transform: if false, then it will not accumulate the object's own
|
||||
* placement into \c mat, which lets you override the object's placement.
|
||||
*
|
||||
* @return Return the linked object. This function must return itself if the
|
||||
* it is not a link or the link is invalid.
|
||||
*/
|
||||
virtual DocumentObject *getLinkedObject(bool recurse=true,
|
||||
Base::Matrix4D *mat=0, bool transform=false, int depth=0) const;
|
||||
|
||||
/* Return true to cause PropertyView to show linked object's property */
|
||||
virtual bool canLinkProperties() const {return true;}
|
||||
|
||||
friend class Document;
|
||||
friend class Transaction;
|
||||
@@ -237,6 +361,51 @@ public:
|
||||
|
||||
const std::string & getOldLabel() const { return oldLabel; }
|
||||
|
||||
const char *getViewProviderNameStored() const {
|
||||
return _pcViewProviderName.c_str();
|
||||
}
|
||||
|
||||
/** Resolve the last document object referenced in the subname
|
||||
*
|
||||
* @param subname: dot separated subname
|
||||
* @param parent: return the direct parent of the object
|
||||
* @param childName: return child name to be passed to is/setElementVisible()
|
||||
* @param subElement: return non-object sub-element name if found. The
|
||||
* pointer is guaranteed to be within the buffer pointed to by 'subname'
|
||||
*
|
||||
* @sa getSubObject()
|
||||
* @return Returns the last referenced document object in the subname. If no
|
||||
* such object in subname, return pObject.
|
||||
*/
|
||||
App::DocumentObject *resolve(const char *subname, App::DocumentObject **parent=0,
|
||||
std::string *childName=0, const char **subElement=0,
|
||||
PyObject **pyObj=0, Base::Matrix4D *mat=0, bool transform=true, int depth=0) const;
|
||||
|
||||
/** Allow object to redirect a subname path
|
||||
*
|
||||
* @param ss: input as the current subname path from \a topParent leading
|
||||
* just before this object, i.e. ends at the parent of this object. This
|
||||
* function should append its own name to this path, or redirect the
|
||||
* subname to other place.
|
||||
* @param topParent: top parent of this subname path
|
||||
* @param child: the immediate child object in the path
|
||||
*
|
||||
* This function is called by tree view to generate a subname path when an
|
||||
* item is selected in the tree. Document object can use this function to
|
||||
* redirect the selection to some other objects.
|
||||
*/
|
||||
virtual bool redirectSubName(std::ostringstream &ss,
|
||||
DocumentObject *topParent, DocumentObject *child) const;
|
||||
|
||||
/** Sepecial marker to mark the object has hidden
|
||||
*
|
||||
* It is used by Gui::ViewProvider::getElementColors(), but exposed here
|
||||
* for convenience
|
||||
*/
|
||||
static const std::string &hiddenMarker();
|
||||
/// Check if the subname reference ends with hidden marker.
|
||||
static const char *hasHiddenMarker(const char *subname);
|
||||
|
||||
protected:
|
||||
/// recompute only this object
|
||||
virtual App::DocumentObjectExecReturn *recompute(void);
|
||||
@@ -301,6 +470,13 @@ protected: // attributes
|
||||
// pointer to the document name string (for performance)
|
||||
const std::string *pcNameInDocument;
|
||||
|
||||
private:
|
||||
// accessed by App::Document to record and restore the correct view provider type
|
||||
std::string _pcViewProviderName;
|
||||
|
||||
// unique identifier (ammong a document) of this object.
|
||||
long _Id;
|
||||
|
||||
private:
|
||||
// Back pointer to all the fathers in a DAG of the document
|
||||
// this is used by the document (via friend) to have a effective DAG handling
|
||||
|
||||
Reference in New Issue
Block a user