Config_AttributeMessage::Config_AttributeMessage(const Events_ID theId, const void* theParent)
: Events_Message(theId, theParent)
{
- myAttributeId = ""; // Attribute unique id
- myFeatureId = ""; // Feature unique id
+ myAttributeId = std::string(); // Attribute unique id
+ myFeatureId = std::string(); // Feature unique id
myIsObligatory = true;
myIsConcealment = false;
+ myCaseId = std::string();
}
Config_AttributeMessage::~Config_AttributeMessage()
{
this->myIsObligatory = theObligatory;
}
+
+const std::string& Config_AttributeMessage::caseId() const
+{
+ return myCaseId;
+}
+
+void Config_AttributeMessage::setCaseId(const std::string& theId)
+{
+ this->myCaseId = theId;
+}
std::string myFeatureId; ///< Attribute's feature's unique id
bool myIsObligatory; ///< Required to be set by user, else it's feature is invalid.
bool myIsConcealment; ///< If true, conceals features used as input
+ std::string myCaseId; ///< Attribute's case's id, if it placed inside a paged containers
public:
/// Same event as Config_FeatureMessage::MODEL_EVENT()
CONFIG_EXPORT bool isObligatory() const;
/// Returns true if attribute should conceal input features
CONFIG_EXPORT bool isConcealment() const;
+ /// Returns id of a case which contain the attribute
+ CONFIG_EXPORT const std::string& caseId() const;
/// Set attribute's unique id
CONFIG_EXPORT void setAttributeId(const std::string& theId);
/// Set attribute's feature's unique id
CONFIG_EXPORT void setFeatureId(const std::string& id);
- /// Returns attribute's concealment state
+ /// Set attribute's concealment state
CONFIG_EXPORT void setConcealment(bool isConcealment);
- /// Returns attribute's obligatory state
+ /// Set attribute's obligatory state
CONFIG_EXPORT void setObligatory(bool isObligatory);
+ /// Set attribute's case
+ CONFIG_EXPORT void setCaseId(const std::string& id);
+
};
#endif // ATTRIBUTE_MESSAGE_H
\r
bool isNode(xmlNodePtr theNode, const char* theNodeName, ...)\r
{\r
- bool result = false;\r
const xmlChar* aName = theNode->name;\r
if (!aName || !isElementNode(theNode)) {\r
return false;\r
return false;\r
}\r
\r
+bool isAttributeNode(xmlNodePtr theNode)\r
+{\r
+ if(!isElementNode(theNode))\r
+ return false;\r
+ // it's parent is "feature" or "source" or page ("case" or "box")\r
+ if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, \r
+ WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL))\r
+ return false;\r
+\r
+ //it should not be a "source" or a "validator" node\r
+ bool isLogical = isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL);\r
+ bool isPagedContainer = isNode(theNode, WDG_TOOLBOX, WDG_TOOLBOX_BOX,\r
+ WDG_SWITCH, WDG_SWITCH_CASE, NULL);\r
+ return !isLogical && !isPagedContainer;\r
+}\r
+\r
bool isWidgetNode(xmlNodePtr theNode)\r
{\r
if(!isElementNode(theNode))\r
return false;\r
// it's parent is "feature" or "source"\r
- xmlNodePtr aParentNode = theNode->parent;\r
- if(!isNode(aParentNode, NODE_FEATURE, NODE_SOURCE, NULL))\r
+ if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, \r
+ WDG_TOOLBOX_BOX, WDG_SWITCH_CASE, NULL))\r
return false;\r
\r
//it should not be a "source" or a "validator" node\r
return !isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NODE_SELFILTER, NULL);\r
}\r
\r
+// widget api?\r
+bool isCaseNode(xmlNodePtr theNode)\r
+{\r
+ if(!isElementNode(theNode))\r
+ return false;\r
+\r
+ return isNode(theNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL);\r
+}\r
+\r
bool hasChild(xmlNodePtr theNode)\r
{\r
xmlNodePtr aNode = theNode->children;\r
return false;\r
}\r
\r
+bool hasParent(xmlNodePtr theNode)\r
+{\r
+ xmlNodePtr aNode = theNode->parent;\r
+ if (!aNode) {\r
+ return false;\r
+ }\r
+ for (; aNode; aNode = aNode->next) {\r
+ if (isElementNode(theNode)) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...)\r
+{\r
+ if (!hasParent(theNode)) {\r
+ return false; // have no parents at all\r
+ }\r
+ xmlNodePtr aNode = theNode->parent;\r
+ const xmlChar* aName = aNode->name;\r
+ if (!aName || !isElementNode(aNode)) {\r
+ return false;\r
+ }\r
+ if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) {\r
+ return true;\r
+ }\r
+ va_list args; // define argument list variable\r
+ va_start(args, theNodeName); // init list; point to last defined argument\r
+ while (true) {\r
+ char *anArg = va_arg (args, char*); // get next argument\r
+ if (anArg == NULL)\r
+ break;\r
+ if (!xmlStrcmp(aName, (const xmlChar *) anArg)) {\r
+ va_end(args); // cleanup the system stack\r
+ return true;\r
+ }\r
+ }\r
+ va_end(args); // cleanup the system stack\r
+ return false;\r
+}\r
+\r
bool getParametersInfo(xmlNodePtr theNode, std::string& outPropertyId,\r
std::list<std::string>& outValidatorParameters)\r
{\r
CONFIG_EXPORT bool isNode(xmlNodePtr theNode, const char* theNodeName, ...);
/*!
- * Checks is the given node is attribute (widget) node.
+ * Checks if the given node is attribute node.
+ * Attribute node represents a widget, that is able to store/restore
+ * values from the model. Actually it's every widget, displayed
+ * in the XGUI_PropertyPanel, except paged containers (toolbox, switch/case).
+ */
+CONFIG_EXPORT bool isAttributeNode(xmlNodePtr theNode);
+
+/*!
+ * Checks if the given node is widget node.
+ * Widget nodes are attribute node + paged containers nodes.
*/
CONFIG_EXPORT bool isWidgetNode(xmlNodePtr theNode);
+CONFIG_EXPORT bool isCaseNode(xmlNodePtr theNode);
+
/*!
* Every xml node has child. Even if there is no explicit
* child nodes libxml gives the "Text node" as child.
*/
CONFIG_EXPORT bool hasChild(xmlNodePtr theNode);
+
+/*!
+ * Checks if the given node has a valid parent.
+ */
+CONFIG_EXPORT bool hasParent(xmlNodePtr theNode);
+
+/*!
+ * Checks if the given node has a valid parent with any of the given node names.
+ */
+CONFIG_EXPORT bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...);
+
/*!
* Returns named property for an id node as std::string and the parameters of the node.
*/
} else if (isNode(theNode, NODE_WORKBENCH, NODE_GROUP, NULL)) {
storeAttribute(theNode, _ID);
storeAttribute(theNode, WORKBENCH_DOC);
- } else if (myIsProcessWidgets && isWidgetNode(theNode)) {
- std::shared_ptr<Config_AttributeMessage> aMessage(new Config_AttributeMessage(aMenuItemEvent, this));
- aMessage->setFeatureId(restoreAttribute(NODE_FEATURE, _ID));
- std::string anAttributeID = getProperty(theNode, _ID);
- if (!anAttributeID.empty()) {
- aMessage->setAttributeId(anAttributeID);
- aMessage->setObligatory(getBooleanAttribute(theNode, ATTR_OBLIGATORY, true));
- aMessage->setConcealment(getBooleanAttribute(theNode, ATTR_CONCEALMENT, false));
- //aMessage->setCaseId
- Events_Loop::loop()->send(aMessage);
+ } else if (myIsProcessWidgets) {
+ // widgets, like shape_selector or containers, like toolbox
+ if (isAttributeNode(theNode)) {
+ std::shared_ptr<Config_AttributeMessage> aMessage(new Config_AttributeMessage(aMenuItemEvent, this));
+ aMessage->setFeatureId(restoreAttribute(NODE_FEATURE, _ID));
+ std::string anAttributeID = getProperty(theNode, _ID);
+ if (!anAttributeID.empty()) {
+ aMessage->setAttributeId(anAttributeID);
+ aMessage->setObligatory(getBooleanAttribute(theNode, ATTR_OBLIGATORY, true));
+ aMessage->setConcealment(getBooleanAttribute(theNode, ATTR_CONCEALMENT, false));
+ // nested "paged" widgets are not allowed, this issue may be resolved here:
+ if (hasParent(theNode, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX, NULL)) {
+ const char* kWdgCase = hasParent(theNode, WDG_SWITCH_CASE, NULL)
+ ? WDG_SWITCH_CASE
+ : WDG_TOOLBOX_BOX;
+ aMessage->setCaseId(restoreAttribute(kWdgCase, _ID));
+ }
+ Events_Loop::loop()->send(aMessage);
+ }
+ // container pages, like "case" or "box"
+ } else if (isCaseNode(theNode)) {
+ storeAttribute(theNode, _ID); // save case:caseId (or box:boxId)
}
}
//Process SOURCE, VALIDATOR nodes.
Config_XMLReader::processNode(theNode);
}
+void Config_FeatureReader::cleanup(xmlNodePtr theNode)
+{
+ if (isCaseNode(theNode)) {
+ // cleanup id of cases when leave case node
+ cleanupAttribute(theNode, _ID);
+ }
+}
+
bool Config_FeatureReader::processChildren(xmlNodePtr theNode)
{
bool result = isNode(theNode, NODE_WORKBENCH, NODE_GROUP, NULL);
if(!result && myIsProcessWidgets) {
- result = isNode(theNode, NODE_FEATURE, NULL);
+ result = isNode(theNode, NODE_FEATURE,
+ WDG_TOOLBOX, WDG_TOOLBOX_BOX,
+ WDG_SWITCH, WDG_SWITCH_CASE, NULL);
}
return result;
}
}
return result;
}
+
+bool Config_FeatureReader::cleanupAttribute(xmlNodePtr theNode,
+ const char* theNodeAttribute)
+{
+ return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute);
+}
+
+bool Config_FeatureReader::cleanupAttribute(const char* theNodeName,
+ const char* theNodeAttribute)
+{
+ std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute);
+ bool result = false;
+ std::map<std::string, std::string>::iterator anEntry = myParentAttributes.find(aKey);
+ if( anEntry != myParentAttributes.end()) {
+ myParentAttributes.erase(anEntry);
+ result = true;
+ }
+ return result;
+}
+
protected:
/// Overloaded method. Defines how to process each node
virtual void processNode(xmlNodePtr aNode);
+
+ /// Overloaded method. Clears attribute cache on extit from attribute's node
+ virtual void cleanup(xmlNodePtr aNode);
+
/// Overloaded method. Defines if the given node should be parsed recursively
virtual bool processChildren(xmlNodePtr aNode);
/// Restores an attribute from internal map.
std::string restoreAttribute(const char* theNodeName, const char* theNodeAttribute);
+ bool cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute);
+ bool cleanupAttribute(const char* theNodeName, const char* theNodeAttribute);
+
private:
/// A map to store all parent's attributes.
/// The key has from "Node_Name:Node_Attribute"
}
}
+void Config_XMLReader::cleanup(xmlNodePtr)
+{
+ // do nothing;
+}
+
bool Config_XMLReader::processChildren(xmlNodePtr aNode)
{
return true;
if (processChildren(aNode)) {
readRecursively(aNode);
}
+ cleanup(aNode);
}
}
* "selection_filter" nodes.
*/
virtual void processNode(xmlNodePtr aNode);
+
+ /*!
+ * This method gives an ability to finalize processing of a node,
+ * when reader is about to leave the node (node and all it's children are processed)
+ */
+ virtual void cleanup(xmlNodePtr aNode);
/*!
* \brief Defines which nodes should be processed recursively. Virtual.
* The default impl is to read all nodes.