]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Processing of "case" xml nodes for paiged containers (toolbox, switchcase)
authorsbh <sergey.belash@opencascade.com>
Fri, 27 Feb 2015 10:12:47 +0000 (13:12 +0300)
committersbh <sergey.belash@opencascade.com>
Fri, 27 Feb 2015 10:12:47 +0000 (13:12 +0300)
src/Config/Config_AttributeMessage.cpp
src/Config/Config_AttributeMessage.h
src/Config/Config_Common.cpp
src/Config/Config_Common.h
src/Config/Config_FeatureReader.cpp
src/Config/Config_FeatureReader.h
src/Config/Config_XMLReader.cpp
src/Config/Config_XMLReader.h

index 3b37a27bdcef9d45009b941ae70c779403bed470..8009b12e49514ad900f7b43d5ca27d181415dc66 100644 (file)
@@ -5,10 +5,11 @@
 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()
@@ -55,3 +56,13 @@ void Config_AttributeMessage::setObligatory(bool theObligatory)
 {
   this->myIsObligatory = theObligatory;
 }
+
+const std::string& Config_AttributeMessage::caseId() const
+{
+  return myCaseId;
+}
+
+void Config_AttributeMessage::setCaseId(const std::string& theId)
+{
+  this->myCaseId = theId;
+}
index bfb9b64b1b5c1deb55c6986c7184c8ca78ffaa9e..7b2bd12b6014c223bd1f7161fd5ca4b5986706d4 100644 (file)
@@ -22,6 +22,7 @@ class Config_AttributeMessage : public Events_Message
   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()
@@ -45,15 +46,20 @@ class Config_AttributeMessage : public Events_Message
   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
index 9c4df7f57c539174f1496979685e7d8b48c113e9..8ffc9e126b6938135b3cde07239281aae9969115 100644 (file)
@@ -27,7 +27,6 @@ bool isElementNode(xmlNodePtr theNode)
 \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
@@ -50,19 +49,44 @@ bool isNode(xmlNodePtr theNode, const char* theNodeName, ...)
   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
@@ -74,6 +98,48 @@ bool hasChild(xmlNodePtr theNode)
   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
index c53586eb50cef0e721ad49aceabe5a703cd6f936..52fc1e1726fa0adbfedd95f72a7f3a930995c362 100644 (file)
@@ -44,10 +44,21 @@ CONFIG_EXPORT bool isElementNode(xmlNodePtr theNode);
 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.
@@ -57,6 +68,17 @@ CONFIG_EXPORT bool isWidgetNode(xmlNodePtr theNode);
  */
 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.
  */
index 7f51d34ab8b0aae14e11c4672439ef9f62c68863..adf8f5e7abb8623d3edc81e1f442ec2393ef7835 100644 (file)
@@ -61,27 +61,49 @@ void Config_FeatureReader::processNode(xmlNodePtr theNode)
   } 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;
 }
@@ -139,3 +161,23 @@ std::string Config_FeatureReader::restoreAttribute(const char* theNodeName,
   }
   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;
+}
+
index 7f7889aaabfbd07fe0ab741f22162b226c354765..75eb376e5cdd88ba8a6249a863e522e7ec1c3163 100644 (file)
@@ -39,6 +39,10 @@ class Config_FeatureReader : public Config_XMLReader
  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);
 
@@ -54,6 +58,9 @@ class Config_FeatureReader : public Config_XMLReader
   /// 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"
index 03af8f4c7e5c4d8b43f1a5e6f7ec5ad1447c881e..768232b7457e05006f7e9b44caf1ba726fb124bd 100644 (file)
@@ -86,6 +86,11 @@ void Config_XMLReader::processNode(xmlNodePtr theNode)
   }
 }
 
+void Config_XMLReader::cleanup(xmlNodePtr)
+{
+  // do nothing;
+}
+
 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
 {
   return true;
@@ -126,6 +131,7 @@ void Config_XMLReader::readRecursively(xmlNodePtr theParent)
     if (processChildren(aNode)) {
       readRecursively(aNode);
     }
+    cleanup(aNode);
   }
 }
 
index 01e64c39494cecb606212073c5daec89c38fd8a9..603ce7d1faea03605dcebf388af0af69105f8bc3 100644 (file)
@@ -61,6 +61,12 @@ class Config_XMLReader
    * "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.