TDME2  1.9.200
GUIParser.cpp
Go to the documentation of this file.
1 #include <tdme/gui/GUIParser.h>
2 
3 #include <string>
4 #include <unordered_map>
5 
6 #include <tdme/tdme.h>
50 #include <tdme/gui/nodes/GUINode.h>
71 #include <tdme/utilities/Action.h>
72 #include <tdme/utilities/Console.h>
74 #include <tdme/utilities/Float.h>
75 #include <tdme/utilities/Integer.h>
79 
80 #include <ext/tinyxml/tinyxml.h>
81 
82 using std::string;
83 using std::to_string;
84 using std::unordered_map;
85 
157 
161 
162 #define AVOID_NULLPTR_STRING(arg) (arg == nullptr?"":arg)
163 
164 unordered_map<string, GUIElement*> GUIParser::elements = unordered_map<string, GUIElement*>();
165 Properties GUIParser::engineThemeProperties;
166 Properties GUIParser::projectThemeProperties;
167 
168 const string GUIParser::getRootNode(const string& pathName, const string& fileName) {
169  return getRootNode(FileSystem::getInstance()->getContentAsString(pathName, fileName));
170 }
171 
172 const string GUIParser::getRootNode(const string& xml) {
173  //
174  TiXmlDocument xmlDocument;
175  xmlDocument.Parse(xml.c_str());
176  if (xmlDocument.Error() == true) {
177  string message = string("GUIParser::getRootNode(): Could not parse XML. Error='") + string(xmlDocument.ErrorDesc()) + "':\n\n" + xml;
178  Console::println(message);
179  throw GUIParserException(message);
180  }
181  //
182  TiXmlElement* xmlRoot = xmlDocument.RootElement();
183  auto rootNode = string(xmlRoot->Value());
184  return rootNode;
185 }
186 
187 GUIScreenNode* GUIParser::parse(const string& pathName, const string& fileName, const unordered_map<string, string>& variables, const MiniScript::ScriptVariable& miniScriptArguments, Context* context)
188 {
189  return parse(FileSystem::getInstance()->getContentAsString(pathName, fileName), variables, pathName, fileName, miniScriptArguments, context);
190 }
191 
192 GUIScreenNode* GUIParser::parse(const string& xml, const unordered_map<string, string>& variables, const string& pathName, const string& fileName, const MiniScript::ScriptVariable& miniScriptArguments, Context* context)
193 {
194  auto applicationRootPath = Tools::getApplicationRootPathName(pathName);
195  auto applicationSubPathName = Tools::getApplicationSubPathName(pathName);
196  auto themeProperties = applicationSubPathName == "project"?projectThemeProperties:engineThemeProperties;
197 
198  // replace with variables
199  auto newXML = xml;
200  for (const auto& [variableName, variableValue]: variables) {
201  newXML = StringTools::replace(newXML, "{$" + variableName + "}", escape(variableValue));
202  }
203  // replace with theme properties
204  for (const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
205  newXML = StringTools::replace(newXML, "{$" + themePropertyName + "}", escape(themePropertyValue));
206  }
207 
208  //
209  TiXmlDocument xmlDocument;
210  xmlDocument.Parse(newXML.c_str());
211  if (xmlDocument.Error() == true) {
212  string message = string("GUIParser::parse(): Could not parse XML. Error='") + string(xmlDocument.ErrorDesc()) + "':\n\n" + newXML;
213  Console::println(message);
214  throw GUIParserException(message);
215  }
216  TiXmlElement* xmlRoot = xmlDocument.RootElement();
217  GUIScreenNode* guiScreenNode = nullptr;
218  if (string(xmlRoot->Value()) != string("screen")) {
219  throw GUIParserException("XML root node must be <screen>");
220  }
221 
222  //
223  guiScreenNode = new GUIScreenNode(
224  (pathName.empty() == false?pathName + "/":"") + fileName,
225  applicationRootPath.empty() == true?".":FileSystem::getInstance()->getCanonicalURI(applicationRootPath, ""),
226  applicationSubPathName,
227  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("id"))),
228  GUINode::createFlow(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("flow")))),
229  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("overflow-x")))),
230  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("overflow-y")))),
231  GUINode::createAlignments(
232  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("horizontal-align"))),
233  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("vertical-align")))
234  ),
235  GUINode::createRequestedConstraints(
236  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("left"))),
237  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("top"))),
238  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("width"))),
239  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("height"))),
240  parseFactor(nullptr, StringTools::trim(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("factor")))))
241  ),
242  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
243  "",
244  GUINode::createScale9Grid(
245  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-scale9"))),
246  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-scale9-left"))),
247  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-scale9-top"))),
248  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-scale9-right"))),
249  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-scale9-bottom")))
250  ),
251  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
252  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
253  GUINode::createBorder(
254  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border"))),
255  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-left"))),
256  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-top"))),
257  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-right"))),
258  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-bottom"))),
259  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-color"))),
260  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-color-left"))),
261  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-color-top"))),
262  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-color-right"))),
263  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("border-color-bottom")))
264  ),
265  GUINode::createPadding(
266  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("padding"))),
267  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("padding-left"))),
268  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("padding-top"))),
269  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("padding-right"))),
270  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("padding-bottom")))
271  ),
272  GUIScreenNode::createSizeConstraints(
273  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("min-width"))),
274  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("min-height"))),
275  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("max-width"))),
276  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("max-height")))
277  ),
278  GUINode::createConditions(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("show-on")))),
279  GUINode::createConditions(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("hide-on")))),
280  unescape(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("tooltip")))),
281  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("scrollable")))), "true"),
282  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("popup")))), "true"),
283  string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("script"))),
284  miniScriptArguments,
285  context
286  );
287  // workaround for having GUINode constructor to be called before GUIScreenNode constructor
288  // so GUIScreenNode::applicationRootPath is not available at GUIScreenNode::GUINode construction time
289  guiScreenNode->setBackgroundImage(string(AVOID_NULLPTR_STRING(xmlRoot->Attribute("background-image"))));
290  parseGUINode(guiScreenNode, string(), xmlRoot, nullptr);
291  guiScreenNode->setConditionsMet();
292 
293  //
294  vector<GUINode*> childControllerNodes;
295  guiScreenNode->getChildControllerNodes(childControllerNodes);
296  for (auto node: childControllerNodes) node->getController()->onSubTreeChange();
297 
298  //
299  return guiScreenNode;
300 }
301 
302 void GUIParser::parse(GUIParentNode* parentNode, const string& pathName, const string& fileName)
303 {
304  string xml = FileSystem::getInstance()->getContentAsString(pathName, fileName);
305  parse(parentNode, xml);
306 }
307 
308 void GUIParser::parse(GUIParentNode* parentNode, const string& xml)
309 {
310  //
311  auto themeProperties = parentNode->getScreenNode()->getApplicationSubPathName() == "project"?projectThemeProperties:engineThemeProperties;
312  //
313  auto newXML = xml;
314  // replace with theme properties
315  for (const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
316  newXML = StringTools::replace(newXML, "{$" + themePropertyName + "}", escape(themePropertyValue));
317  }
318 
319  TiXmlDocument xmlDocument;
320  xmlDocument.Parse((string("<gui-element>") + newXML + string("</gui-element>")).c_str());
321  if (xmlDocument.Error() == true) {
322  auto message = "GUIParser::parse(): Could not parse XML. Error='" + string(xmlDocument.ErrorDesc()) + "':\n\n" + newXML;
323  Console::println(message);
324  throw GUIParserException(message);
325  }
326  TiXmlElement* xmlNode = xmlDocument.RootElement();
327  parseGUINode(parentNode, string(), xmlNode, nullptr);
328 }
329 
330 void GUIParser::parseEffect(GUINode* guiNode, const string& effectPrefix, bool requiresCondition, TiXmlElement* node) {
331  GUIEffect* effect = nullptr;
332  auto type = string(AVOID_NULLPTR_STRING(node->Attribute("type")));
333  if (type == "color") {
334  effect = new GUIColorEffect(guiNode);
335  static_cast<GUIColorEffect*>(effect)->setPersistant(StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("persistant")))), "true"));
336  static_cast<GUIColorEffect*>(effect)->setColorMul(GUIColor(AVOID_NULLPTR_STRING(node->Attribute("effect-color-mul"))));
337  static_cast<GUIColorEffect*>(effect)->setColorAdd(GUIColor(AVOID_NULLPTR_STRING(node->Attribute("effect-color-add"))));
338  static_cast<GUIColorEffect*>(effect)->setStartColorMul(GUIColor(AVOID_NULLPTR_STRING(node->Attribute("start-effect-color-mul"))));
339  static_cast<GUIColorEffect*>(effect)->setStartColorAdd(GUIColor(AVOID_NULLPTR_STRING(node->Attribute("start-effect-color-add"))));
340  static_cast<GUIColorEffect*>(effect)->setTimeTotal(Float::parse(node->Attribute("time")));
341  static_cast<GUIColorEffect*>(effect)->setRepeat(node->Attribute("repeat") == nullptr?0:Integer::parse(node->Attribute("repeat")));
342  static_cast<GUIColorEffect*>(effect)->setYoyo(node->Attribute("yoyo") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("yoyo"))) == "true");
343  guiNode->addEffect(
344  effectPrefix + (requiresCondition == true?string(".") + type + ".on." + AVOID_NULLPTR_STRING(node->Attribute("on")):string()),
345  effect
346  );
347  } else
348  if (type == "position") {
349  effect = new GUIPositionEffect(guiNode);
350  static_cast<GUIPositionEffect*>(effect)->setPersistant(StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("persistant")))), "true"));
351  static_cast<GUIPositionEffect*>(effect)->setPositionX(Integer::parse(AVOID_NULLPTR_STRING(node->Attribute("effect-position-x"))));
352  static_cast<GUIPositionEffect*>(effect)->setPositionY(Integer::parse(AVOID_NULLPTR_STRING(node->Attribute("effect-position-y"))));
353  static_cast<GUIPositionEffect*>(effect)->setStartPositionX(Integer::parse(AVOID_NULLPTR_STRING(node->Attribute("start-effect-position-x"))));
354  static_cast<GUIPositionEffect*>(effect)->setStartPositionY(Integer::parse(AVOID_NULLPTR_STRING(node->Attribute("start-effect-position-y"))));
355  static_cast<GUIPositionEffect*>(effect)->setTimeTotal(Float::parse(node->Attribute("time")));
356  static_cast<GUIPositionEffect*>(effect)->setRepeat(node->Attribute("repeat") == nullptr?0:Integer::parse(node->Attribute("repeat")));
357  static_cast<GUIPositionEffect*>(effect)->setYoyo(node->Attribute("yoyo") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("yoyo"))) == "true");
358  guiNode->addEffect(
359  effectPrefix + (requiresCondition == true?string(".") + type + ".on." + AVOID_NULLPTR_STRING(node->Attribute("on")):string()),
360  effect
361  );
362  }
363  auto action = string(AVOID_NULLPTR_STRING(node->Attribute("action")));
364  if (effect != nullptr && action.empty() == false) {
365  class EffectAction: public virtual Action
366  {
367  public:
368  EffectAction(GUIScreenNode* guiScreenNode, const string& expression): guiScreenNode(guiScreenNode), expression(expression) {
369  }
370  void performAction() override {
371  GUIElementNode::executeExpression(guiScreenNode, expression);
372  }
373  private:
374  GUIScreenNode* guiScreenNode;
375  string expression;
376  };
377  effect->setAction(new EffectAction(guiNode->getScreenNode(), action));
378  }
379 }
380 
381 void GUIParser::parseEffects(GUINode* guiNode, TiXmlElement* xmlParentNode) {
382  for (auto node = xmlParentNode->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) {
383  string nodeTagName = string(node->Value());
384  if (nodeTagName == "effect-in") {
385  parseEffect(guiNode, "tdme.xmleffect.in", true, node);
386  } else
387  if (nodeTagName == "effect-out") {
388  parseEffect(guiNode, "tdme.xmleffect.out", true, node);
389  } else
390  if (nodeTagName == "effect-default") {
391  parseEffect(guiNode, "tdme.xmleffect.default", false, node);
392  }
393  }
394 }
395 
396 void GUIParser::parseGUINode(GUIParentNode* guiParentNode, const string& parentElementId, TiXmlElement* xmlParentNode, GUIElement* guiElement)
397 {
398  auto themeProperties = guiParentNode->getScreenNode()->getApplicationSubPathName() == "project"?projectThemeProperties:engineThemeProperties;
399  GUINodeController* guiElementController = nullptr;
400  auto guiElementControllerInstalled = false;
401  parseEffects(guiParentNode, xmlParentNode);
402  for (auto node = xmlParentNode->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) {
403  {
404  string nodeTagName = string(node->Value());
405  if (nodeTagName == "defaults") {
406  // no op
407  } else
408  if (nodeTagName == "effect-in") {
409  parseEffect(guiParentNode, "tdme.xmleffect.in", true, node);
410  } else
411  if (nodeTagName == "effect-out") {
412  parseEffect(guiParentNode, "tdme.xmleffect.out", true, node);
413  } else
414  if (nodeTagName == "effect-default") {
415  parseEffect(guiParentNode, "tdme.xmleffect.default", false, node);
416  } else
417  if (nodeTagName == "panel") {
418  auto guiPanelNode = new GUIPanelNode(
419  guiParentNode->getScreenNode(),
420  guiParentNode,
421  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
422  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
423  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
424  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
425  GUINode::createAlignments(
426  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
427  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
428  ),
429  GUIParentNode::createRequestedConstraints(
430  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
431  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
432  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
433  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
434  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
435  ),
436  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor(themeProperties.get("color.panel", "#F0F0F0"))),
437  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
438  GUINode::createScale9Grid(
439  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
440  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
441  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
442  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
443  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
444  ),
445  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
446  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
447  GUINode::createBorder(
448  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
449  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
450  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
451  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
452  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
453  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
454  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
455  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
456  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
457  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
458  ),
459  GUINode::createPadding(
460  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
461  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
462  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
463  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
464  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
465  ),
466  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
467  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
468  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
469  GUILayoutNode::createAlignment(string(AVOID_NULLPTR_STRING(node->Attribute("alignment"))))
470  );
471  guiParentNode->addSubNode(guiPanelNode);
472  if (guiElement != nullptr && guiElementControllerInstalled == false) {
473  guiElementController = guiElement->createController(guiPanelNode);
474  if (guiElementController != nullptr) {
475  guiPanelNode->setController(guiElementController);
476  }
477  guiElementControllerInstalled = true;
478  }
479  parseGUINode(guiPanelNode, string(), node, nullptr);
480  } else
481  if (nodeTagName == "layer") {
482  auto guiLayerNode = new GUILayerNode(
483  guiParentNode->getScreenNode(),
484  guiParentNode,
485  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
486  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
487  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
488  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
489  GUIElementNode::createAlignments(
490  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
491  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
492  ),
493  GUIParentNode::createRequestedConstraints(
494  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
495  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
496  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
497  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
498  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
499  ),
500  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
501  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
502  GUINode::createScale9Grid(
503  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
504  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
505  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
506  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
507  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
508  ),
509  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
510  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
511  GUINode::createBorder(
512  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
513  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
514  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
515  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
516  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
517  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
518  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
519  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
520  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
521  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
522  ),
523  GUINode::createPadding(
524  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
525  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
526  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
527  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
528  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
529  ),
530  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
531  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
532  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip"))))
533  );
534  guiParentNode->addSubNode(guiLayerNode);
535  if (guiElement != nullptr && guiElementControllerInstalled == false) {
536  guiElementController = guiElement->createController(guiLayerNode);
537  if (guiElementController != nullptr) {
538  guiLayerNode->setController(guiElementController);
539  }
540  guiElementControllerInstalled = true;
541  }
542  parseGUINode(guiLayerNode, string(), node, nullptr);
543  } else
544  if (nodeTagName == "layout") {
545  auto guiLayoutNode = new GUILayoutNode(
546  guiParentNode->getScreenNode(),
547  guiParentNode,
548  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
549  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
550  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
551  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
552  GUINode::createAlignments(
553  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
554  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
555  ),
556  GUIParentNode::createRequestedConstraints(
557  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
558  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
559  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
560  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
561  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
562  ),
563  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
564  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
565  GUINode::createScale9Grid(
566  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
567  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
568  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
569  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
570  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
571  ),
572  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
573  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
574  GUINode::createBorder(
575  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
576  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
577  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
578  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
579  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
580  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
581  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
582  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
583  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
584  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
585  ),
586  GUINode::createPadding(
587  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
588  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
589  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
590  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
591  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
592  ),
593  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
594  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
595  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
596  GUILayoutNode::createAlignment(string(AVOID_NULLPTR_STRING(node->Attribute("alignment"))))
597  );
598  guiParentNode->addSubNode(guiLayoutNode);
599  if (guiElement != nullptr && guiElementControllerInstalled == false) {
600  guiElementController = guiElement->createController(guiLayoutNode);
601  if (guiElementController != nullptr) {
602  guiLayoutNode->setController(guiElementController);
603  }
604  guiElementControllerInstalled = true;
605  }
606  parseGUINode(guiLayoutNode, string(), node, nullptr);
607  } else
608  if (nodeTagName == "space") {
609  auto guiSpaceNode = new GUISpaceNode(
610  guiParentNode->getScreenNode(),
611  guiParentNode,
612  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
613  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
614  GUINode::createAlignments(
615  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
616  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
617  ),
618  GUIParentNode::createRequestedConstraints(
619  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
620  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
621  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
622  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
623  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
624  ),
625  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
626  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
627  GUINode::createScale9Grid(
628  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
629  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
630  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
631  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
632  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
633  ),
634  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
635  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
636  GUINode::createBorder(
637  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
638  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
639  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
640  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
641  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
642  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
643  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
644  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
645  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
646  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
647  ),
648  GUINode::createPadding(
649  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
650  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
651  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
652  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
653  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
654  ),
655  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
656  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
657  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip"))))
658  );
659  guiParentNode->addSubNode(guiSpaceNode);
660  if (guiElement != nullptr && guiElementControllerInstalled == false) {
661  guiElementController = guiElement->createController(guiSpaceNode);
662  if (guiElementController != nullptr) {
663  guiSpaceNode->setController(guiElementController);
664  }
665  guiElementControllerInstalled = true;
666  }
667  parseEffects(guiSpaceNode, node);
668  } else
669  if (nodeTagName == "element") {
670  auto guiElementNode = new GUIElementNode(
671  guiParentNode->getScreenNode(),
672  guiParentNode,
673  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
674  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
675  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
676  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
677  GUIElementNode::createAlignments(
678  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
679  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
680  ),
681  GUIParentNode::createRequestedConstraints(
682  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
683  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
684  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
685  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
686  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
687  ),
688  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
689  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
690  GUINode::createScale9Grid(
691  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
692  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
693  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
694  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
695  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
696  ),
697  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
698  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
699  GUINode::createBorder(
700  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
701  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
702  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
703  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
704  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
705  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
706  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
707  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
708  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
709  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
710  ),
711  GUINode::createPadding(
712  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
713  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
714  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
715  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
716  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
717  ),
718  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
719  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
720  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
721  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("name")))),
722  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("value")))),
723  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("selected")))), "true"),
724  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("disabled")))), "true"),
725  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("focusable")))), "true"),
726  StringTools::equalsIgnoreCase(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("ignore-events")))), "true"),
727  string(AVOID_NULLPTR_STRING(node->Attribute("on-initialize"))),
728  string(AVOID_NULLPTR_STRING(node->Attribute("on-mouse-click"))),
729  string(AVOID_NULLPTR_STRING(node->Attribute("on-mouse-doubleclick"))),
730  string(AVOID_NULLPTR_STRING(node->Attribute("on-mouse-over"))),
731  string(AVOID_NULLPTR_STRING(node->Attribute("on-mouse-out"))),
732  string(AVOID_NULLPTR_STRING(node->Attribute("on-change"))),
733  parentElementId,
734  string(AVOID_NULLPTR_STRING(node->Attribute("options")))
735  );
736  guiParentNode->addSubNode(guiElementNode);
737  if (guiElement != nullptr && guiElementControllerInstalled == false) {
738  guiElementController = guiElement->createController(guiElementNode);
739  if (guiElementController != nullptr) {
740  guiElementNode->setController(guiElementController);
741  }
742  guiElementControllerInstalled = true;
743  }
744  parseGUINode(guiElementNode, guiElementNode->getId(), node, nullptr);
745  } else
746  if (nodeTagName == "image") {
747  auto guiImageNode = new GUIImageNode(
748  guiParentNode->getScreenNode(),
749  guiParentNode,
750  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
751  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
752  GUINode::createAlignments(
753  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
754  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
755  ),
756  GUIParentNode::createRequestedConstraints(
757  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
758  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
759  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
760  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
761  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
762  ),
763  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
764  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
765  GUINode::createScale9Grid(
766  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
767  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
768  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
769  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
770  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
771  ),
772  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
773  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
774  GUINode::createBorder(
775  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
776  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
777  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
778  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
779  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
780  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
781  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
782  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
783  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
784  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
785  ),
786  GUINode::createPadding(
787  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
788  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
789  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
790  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
791  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
792  ),
793  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
794  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
795  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
796  StringTools::trim(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("src"))))),
797  GUIImageNode::createRequestedDimensionConstraints(
798  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-scale")))),
799  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("vertical-scale"))))
800  ),
801  node->Attribute("mirror-x") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("mirror-x"))) == "true",
802  node->Attribute("mirror-y") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("mirror-y"))) == "true",
803  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
804  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
805  GUINode::createScale9Grid(
806  string(AVOID_NULLPTR_STRING(node->Attribute("scale9"))),
807  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-left"))),
808  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-top"))),
809  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-right"))),
810  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-bottom")))
811  ),
812  GUIImageNode::createClipping(
813  string(AVOID_NULLPTR_STRING(node->Attribute("clipping"))),
814  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-left"))),
815  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-top"))),
816  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-right"))),
817  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-bottom")))
818  ),
819  StringTools::trim(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("mask"))))),
820  Float::parse(string(AVOID_NULLPTR_STRING(node->Attribute("mask-max-value")))),
821  node->Attribute("rotation") != nullptr?Float::parse(node->Attribute("rotation")):0.0f
822  );
823  guiParentNode->addSubNode(guiImageNode);
824  if (guiElement != nullptr && guiElementControllerInstalled == false) {
825  guiElementController = guiElement->createController(guiImageNode);
826  if (guiElementController != nullptr) {
827  guiImageNode->setController(guiElementController);
828  }
829  guiElementControllerInstalled = true;
830  }
831  parseEffects(guiImageNode, node);
832  } else
833  if (nodeTagName == "video") {
834  auto guiVideoNode = new GUIVideoNode(
835  guiParentNode->getScreenNode(),
836  guiParentNode,
837  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
838  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
839  GUINode::createAlignments(
840  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
841  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
842  ),
843  GUIParentNode::createRequestedConstraints(
844  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
845  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
846  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
847  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
848  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
849  ),
850  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
851  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
852  GUINode::createScale9Grid(
853  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
854  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
855  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
856  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
857  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
858  ),
859  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
860  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
861  GUINode::createBorder(
862  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
863  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
864  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
865  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
866  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
867  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
868  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
869  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
870  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
871  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
872  ),
873  GUINode::createPadding(
874  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
875  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
876  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
877  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
878  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
879  ),
880  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
881  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
882  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
883  StringTools::trim(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("src"))))),
884  GUIImageNode::createRequestedDimensionConstraints(
885  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-scale")))),
886  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("vertical-scale"))))
887  ),
888  node->Attribute("mirror-x") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("mirror-x"))) == "true",
889  node->Attribute("mirror-y") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("mirror-y"))) == "true",
890  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
891  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
892  GUINode::createScale9Grid(
893  string(AVOID_NULLPTR_STRING(node->Attribute("scale9"))),
894  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-left"))),
895  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-top"))),
896  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-right"))),
897  string(AVOID_NULLPTR_STRING(node->Attribute("scale9-bottom")))
898  ),
899  GUIImageNode::createClipping(
900  string(AVOID_NULLPTR_STRING(node->Attribute("clipping"))),
901  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-left"))),
902  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-top"))),
903  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-right"))),
904  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-bottom")))
905  ),
906  StringTools::trim(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("mask"))))),
907  Float::parse(string(AVOID_NULLPTR_STRING(node->Attribute("mask-max-value"))))
908  );
909  guiParentNode->addSubNode(guiVideoNode);
910  if (guiElement != nullptr && guiElementControllerInstalled == false) {
911  guiElementController = guiElement->createController(guiVideoNode);
912  if (guiElementController != nullptr) {
913  guiVideoNode->setController(guiElementController);
914  }
915  guiElementControllerInstalled = true;
916  }
917  parseEffects(guiVideoNode, node);
918  } else
919  if (nodeTagName == "gradient") {
920  auto guiGradientNode = new GUIGradientNode(
921  guiParentNode->getScreenNode(),
922  guiParentNode,
923  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
924  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
925  GUINode::createAlignments(
926  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
927  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
928  ),
929  GUIParentNode::createRequestedConstraints(
930  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
931  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
932  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
933  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
934  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
935  ),
936  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
937  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
938  GUINode::createScale9Grid(
939  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
940  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
941  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
942  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
943  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
944  ),
945  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
946  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
947  GUINode::createBorder(
948  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
949  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
950  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
951  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
952  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
953  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
954  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
955  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
956  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
957  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
958  ),
959  GUINode::createPadding(
960  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
961  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
962  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
963  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
964  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
965  ),
966  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
967  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
968  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
969  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
970  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
971  GUIGradientNode::createClipping(
972  string(AVOID_NULLPTR_STRING(node->Attribute("clipping"))),
973  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-left"))),
974  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-top"))),
975  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-right"))),
976  string(AVOID_NULLPTR_STRING(node->Attribute("clipping-bottom")))
977  ),
978  StringTools::trim(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("mask"))))),
979  Float::parse(string(AVOID_NULLPTR_STRING(node->Attribute("mask-max-value")))),
980  GUIGradientNode::createGradient(string(AVOID_NULLPTR_STRING(node->Attribute("colors"))), string(AVOID_NULLPTR_STRING(node->Attribute("rotation"))))
981  );
982  guiParentNode->addSubNode(guiGradientNode);
983  if (guiElement != nullptr && guiElementControllerInstalled == false) {
984  guiElementController = guiElement->createController(guiGradientNode);
985  if (guiElementController != nullptr) {
986  guiGradientNode->setController(guiElementController);
987  }
988  guiElementControllerInstalled = true;
989  }
990  parseEffects(guiGradientNode, node);
991  } else
992  if (nodeTagName == "text") {
993  auto guiTextNode = new GUITextNode(
994  guiParentNode->getScreenNode(),
995  guiParentNode,
996  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
997  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
998  GUINode::createAlignments(
999  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1000  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1001  ),
1002  GUIParentNode::createRequestedConstraints(
1003  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1004  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1005  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1006  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1007  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1008  ),
1009  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1010  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1011  GUINode::createScale9Grid(
1012  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1013  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1014  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1015  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1016  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1017  ),
1018  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1019  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1020  GUINode::createBorder(
1021  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1022  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1023  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1024  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1025  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1026  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1027  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1028  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1029  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1030  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1031  ),
1032  GUINode::createPadding(
1033  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1034  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1035  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1036  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1037  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1038  ),
1039  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1040  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1041  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1042  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("font")))),
1043  parseInteger(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("size")))), FONTSIZE_FALLBACK),
1044  string(AVOID_NULLPTR_STRING(node->Attribute("color"))),
1045  MutableString(unescape(string(StringTools::trim(AVOID_NULLPTR_STRING(node->Attribute("text"))))))
1046  );
1047  guiParentNode->addSubNode(guiTextNode);
1048  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1049  guiElementController = guiElement->createController(guiTextNode);
1050  if (guiElementController != nullptr) {
1051  guiTextNode->setController(guiElementController);
1052  }
1053  guiElementControllerInstalled = true;
1054  }
1055  parseEffects(guiTextNode, node);
1056  } else
1057  if (nodeTagName == "styled-text") {
1058  auto guiStyledTextNode = new GUIStyledTextNode(
1059  guiParentNode->getScreenNode(),
1060  guiParentNode,
1061  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1062  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1063  GUINode::createAlignments(
1064  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1065  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1066  ),
1067  GUIParentNode::createRequestedConstraints(
1068  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1069  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1070  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1071  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1072  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1073  ),
1074  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1075  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1076  GUINode::createScale9Grid(
1077  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1078  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1079  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1080  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1081  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1082  ),
1083  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1084  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1085  GUINode::createBorder(
1086  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1087  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1088  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1089  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1090  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1091  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1092  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1093  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1094  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1095  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1096  ),
1097  GUINode::createPadding(
1098  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1099  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1100  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1101  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1102  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1103  ),
1104  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1105  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1106  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1107  node->Attribute("editable") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("editable"))) == "true",
1108  node->Attribute("preformatted") == nullptr?false:StringTools::toLowerCase(StringTools::trim(node->Attribute("preformatted"))) == "true",
1109  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("font")))),
1110  parseInteger(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("size")))), FONTSIZE_FALLBACK),
1111  string(AVOID_NULLPTR_STRING(node->Attribute("color"))),
1112  MutableString(unescape(StringTools::trim(AVOID_NULLPTR_STRING(node->GetText()))))
1113  );
1114  guiParentNode->addSubNode(guiStyledTextNode);
1115  // TODO: we dont support element controllers here, actually later element controllers should
1116  // only be attachable to element nodes
1117  // here we attach the StyledText controller
1118  guiStyledTextNode->setController(new GUIStyledTextNodeController(guiStyledTextNode));
1119  guiStyledTextNode->getController()->initialize();
1120  parseEffects(guiStyledTextNode, node);
1121  } else
1122  if (nodeTagName == "table") {
1123  auto guiTableNode = new GUITableNode(
1124  guiParentNode->getScreenNode(),
1125  guiParentNode,
1126  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1127  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1128  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
1129  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
1130  GUINode::createAlignments(
1131  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1132  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1133  ),
1134  GUIParentNode::createRequestedConstraints(
1135  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1136  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1137  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1138  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1139  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1140  ),
1141  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1142  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1143  GUINode::createScale9Grid(
1144  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1145  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1146  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1147  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1148  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1149  ),
1150  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1151  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1152  GUINode::createBorder(
1153  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1154  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1155  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1156  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1157  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1158  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1159  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1160  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1161  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1162  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1163  ),
1164  GUINode::createPadding(
1165  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1166  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1167  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1168  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1169  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1170  ),
1171  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1172  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1173  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip"))))
1174  );
1175  guiParentNode->addSubNode(guiTableNode);
1176  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1177  guiElementController = guiElement->createController(guiTableNode);
1178  if (guiElementController != nullptr) {
1179  guiTableNode->setController(guiElementController);
1180  }
1181  guiElementControllerInstalled = true;
1182  }
1183  parseGUINode(guiTableNode, string(), node, nullptr);
1184  } else
1185  if (nodeTagName == "table-cell") {
1186  auto guiTableCellNode = new GUITableCellNode(
1187  guiParentNode->getScreenNode(),
1188  guiParentNode,
1189  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1190  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1191  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
1192  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
1193  GUINode::createAlignments(
1194  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1195  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1196  ),
1197  GUITableCellNode::createRequestedConstraints(
1198  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1199  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1200  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1201  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1202  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1203  ),
1204  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1205  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1206  GUINode::createScale9Grid(
1207  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1208  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1209  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1210  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1211  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1212  ),
1213  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1214  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1215  GUINode::createBorder(
1216  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1217  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1218  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1219  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1220  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1221  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1222  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1223  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1224  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1225  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1226  ),
1227  GUINode::createPadding(
1228  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1229  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1230  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1231  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1232  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1233  ),
1234  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1235  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1236  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1237  GUILayoutNode::createAlignment(string(AVOID_NULLPTR_STRING(node->Attribute("alignment"))))
1238  );
1239  guiParentNode->addSubNode(guiTableCellNode);
1240  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1241  guiElementController = guiElement->createController(guiTableCellNode);
1242  if (guiElementController != nullptr) {
1243  guiTableCellNode->setController(guiElementController);
1244  }
1245  guiElementControllerInstalled = true;
1246  }
1247  parseGUINode(guiTableCellNode, string(), node, nullptr);
1248  } else
1249  if (nodeTagName == "table-row") {
1250  auto guiTableRowNode = new GUITableRowNode(
1251  guiParentNode->getScreenNode(),
1252  guiParentNode,
1253  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1254  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1255  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-x")))),
1256  GUIParentNode::createOverflow(string(AVOID_NULLPTR_STRING(node->Attribute("overflow-y")))),
1257  GUINode::createAlignments(
1258  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1259  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1260  ),
1261  GUITableRowNode::createRequestedConstraints(
1262  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1263  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1264  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1265  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1266  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1267  ),
1268  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1269  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1270  GUINode::createScale9Grid(
1271  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1272  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1273  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1274  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1275  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1276  ),
1277  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1278  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1279  GUINode::createBorder(
1280  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1281  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1282  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1283  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1284  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1285  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1286  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1287  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1288  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1289  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1290  ),
1291  GUINode::createPadding(
1292  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1293  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1294  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1295  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1296  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1297  ),
1298  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1299  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1300  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip"))))
1301  );
1302  guiParentNode->addSubNode(guiTableRowNode);
1303  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1304  guiElementController = guiElement->createController(guiTableRowNode);
1305  if (guiElementController != nullptr) {
1306  guiTableRowNode->setController(guiElementController);
1307  }
1308  guiElementControllerInstalled = true;
1309  }
1310  parseGUINode(guiTableRowNode, string(), node, nullptr);
1311  } else
1312  if (nodeTagName == "input-internal") {
1313  auto guiInputInternalNode = new GUIInputInternalNode(
1314  guiParentNode->getScreenNode(),
1315  guiParentNode,
1316  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1317  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1318  GUINode::createAlignments(
1319  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1320  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1321  ),
1322  GUIParentNode::createRequestedConstraints(
1323  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1324  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1325  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1326  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1327  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1328  ),
1329  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1330  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1331  GUINode::createScale9Grid(
1332  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1333  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1334  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1335  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1336  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1337  ),
1338  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1339  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1340  GUINode::createBorder(
1341  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1342  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1343  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1344  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1345  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1346  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1347  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1348  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1349  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1350  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1351  ),
1352  GUINode::createPadding(
1353  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1354  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1355  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1356  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1357  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1358  ),
1359  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1360  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1361  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1362  StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("font")))),
1363  parseInteger(StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("size")))), FONTSIZE_FALLBACK),
1364  string(AVOID_NULLPTR_STRING(node->Attribute("color"))),
1365  string(AVOID_NULLPTR_STRING(node->Attribute("color-disabled"))),
1366  MutableString(unescape(string(AVOID_NULLPTR_STRING(node->Attribute("text"))))),
1367  GUIInputInternalNode::createMaxLength(string(AVOID_NULLPTR_STRING(node->Attribute("maxlength"))))
1368  );
1369  guiParentNode->addSubNode(guiInputInternalNode);
1370  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1371  guiElementController = guiElement->createController(guiInputInternalNode);
1372  if (guiElementController != nullptr) {
1373  guiInputInternalNode->setController(guiElementController);
1374  }
1375  guiElementControllerInstalled = true;
1376  }
1377  parseEffects(guiInputInternalNode, node);
1378  } else
1379  if (nodeTagName == "vertical-scrollbar-internal") {
1380  auto guiVerticalScrollbarInternalNode = new GUIVerticalScrollbarInternalNode(
1381  guiParentNode->getScreenNode(),
1382  guiParentNode,
1383  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1384  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1385  GUINode::createAlignments(
1386  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1387  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1388  ),
1389  GUIParentNode::createRequestedConstraints(
1390  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1391  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1392  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1393  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1394  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1395  ),
1396  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1397  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1398  GUINode::createScale9Grid(
1399  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1400  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1401  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1402  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1403  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1404  ),
1405  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1406  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1407  GUINode::createBorder(
1408  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1409  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1410  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1411  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1412  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1413  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1414  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1415  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1416  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1417  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1418  ),
1419  GUINode::createPadding(
1420  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1421  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1422  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1423  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1424  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1425  ),
1426  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1427  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1428  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1429  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-none"))), GUIColor::GUICOLOR_BLACK),
1430  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-mouseover"))), GUIColor::GUICOLOR_BLACK),
1431  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-dragging"))), GUIColor::GUICOLOR_BLACK)
1432  );
1433  guiParentNode->addSubNode(guiVerticalScrollbarInternalNode);
1434  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1435  guiElementController = guiElement->createController(guiVerticalScrollbarInternalNode);
1436  if (guiElementController != nullptr) {
1437  guiVerticalScrollbarInternalNode->setController(guiElementController);
1438  }
1439  guiElementControllerInstalled = true;
1440  }
1441  parseEffects(guiVerticalScrollbarInternalNode, node);
1442  } else
1443  if (nodeTagName == "horizontal-scrollbar-internal") {
1444  auto guiHorizontalScrollbarInternalNode = new GUIHorizontalScrollbarInternalNode(
1445  guiParentNode->getScreenNode(),
1446  guiParentNode,
1447  string(node->Attribute("id") == nullptr?guiParentNode->getScreenNode()->allocateNodeId():node->Attribute("id")),
1448  GUINode::createFlow(string(AVOID_NULLPTR_STRING(node->Attribute("flow")))),
1449  GUINode::createAlignments(
1450  string(AVOID_NULLPTR_STRING(node->Attribute("horizontal-align"))),
1451  string(AVOID_NULLPTR_STRING(node->Attribute("vertical-align")))
1452  ),
1453  GUIParentNode::createRequestedConstraints(
1454  string(AVOID_NULLPTR_STRING(node->Attribute("left"))),
1455  string(AVOID_NULLPTR_STRING(node->Attribute("top"))),
1456  string(AVOID_NULLPTR_STRING(node->Attribute("width"))),
1457  string(AVOID_NULLPTR_STRING(node->Attribute("height"))),
1458  parseFactor(guiParentNode, StringTools::trim(string(AVOID_NULLPTR_STRING(node->Attribute("factor")))))
1459  ),
1460  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1461  string(AVOID_NULLPTR_STRING(node->Attribute("background-image"))),
1462  GUINode::createScale9Grid(
1463  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9"))),
1464  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-left"))),
1465  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-top"))),
1466  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-right"))),
1467  string(AVOID_NULLPTR_STRING(node->Attribute("background-image-scale9-bottom")))
1468  ),
1469  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-mul"))), GUIColor::GUICOLOR_EFFECT_COLOR_MUL),
1470  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("background-image-effect-color-add"))), GUIColor::GUICOLOR_EFFECT_COLOR_ADD),
1471  GUINode::createBorder(
1472  string(AVOID_NULLPTR_STRING(node->Attribute("border"))),
1473  string(AVOID_NULLPTR_STRING(node->Attribute("border-left"))),
1474  string(AVOID_NULLPTR_STRING(node->Attribute("border-top"))),
1475  string(AVOID_NULLPTR_STRING(node->Attribute("border-right"))),
1476  string(AVOID_NULLPTR_STRING(node->Attribute("border-bottom"))),
1477  string(AVOID_NULLPTR_STRING(node->Attribute("border-color"))),
1478  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-left"))),
1479  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-top"))),
1480  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-right"))),
1481  string(AVOID_NULLPTR_STRING(node->Attribute("border-color-bottom")))
1482  ),
1483  GUINode::createPadding(
1484  string(AVOID_NULLPTR_STRING(node->Attribute("padding"))),
1485  string(AVOID_NULLPTR_STRING(node->Attribute("padding-left"))),
1486  string(AVOID_NULLPTR_STRING(node->Attribute("padding-top"))),
1487  string(AVOID_NULLPTR_STRING(node->Attribute("padding-right"))),
1488  string(AVOID_NULLPTR_STRING(node->Attribute("padding-bottom")))
1489  ),
1490  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("show-on")))),
1491  GUINode::createConditions(string(AVOID_NULLPTR_STRING(node->Attribute("hide-on")))),
1492  unescape(string(AVOID_NULLPTR_STRING(node->Attribute("tooltip")))),
1493  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-none"))), GUIColor::GUICOLOR_BLACK),
1494  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-mouseover"))), GUIColor::GUICOLOR_BLACK),
1495  GUINode::getRequestedColor(string(AVOID_NULLPTR_STRING(node->Attribute("color-dragging"))), GUIColor::GUICOLOR_BLACK)
1496  );
1497  guiParentNode->addSubNode(guiHorizontalScrollbarInternalNode);
1498  if (guiElement != nullptr && guiElementControllerInstalled == false) {
1499  guiElementController = guiElement->createController(guiHorizontalScrollbarInternalNode);
1500  if (guiElementController != nullptr) {
1501  guiHorizontalScrollbarInternalNode->setController(guiElementController);
1502  }
1503  guiElementControllerInstalled = true;
1504  }
1505  parseEffects(guiHorizontalScrollbarInternalNode, node);
1506  } else
1507  if (nodeTagName == "inner-xml") {
1508  unordered_map<string, string> attributes;
1509  parseInnerXML(
1510  guiParentNode,
1511  parentElementId,
1512  node,
1513  node->GetText(),
1514  attributes,
1515  nullptr
1516  );
1517  } else
1518  if (nodeTagName == "template") {
1519  auto src = string(AVOID_NULLPTR_STRING(node->Attribute("src")));
1520  unordered_map<string, string> attributes;
1521  parseTemplate(
1522  guiParentNode,
1523  parentElementId,
1524  node,
1525  FileSystem::getInstance()->getContentAsString(
1526  guiParentNode->getScreenNode()->getApplicationRootPathName() + "/" + FileSystem::getInstance()->getPathName(src),
1527  FileSystem::getInstance()->getFileName(src)
1528  ),
1529  attributes,
1530  nullptr
1531  );
1532  } else {
1533  auto nodeTagNameString = nodeTagName;
1534  const auto guiElementIt = elements.find(nodeTagNameString);
1535  if (guiElementIt == elements.end()) {
1536  throw GUIParserException(
1537  "Unknown element '" +
1538  (nodeTagNameString) +
1539  "'"
1540  );
1541  }
1542  parseTemplate(
1543  guiParentNode,
1544  parentElementId,
1545  node,
1546  guiElementIt->second->getTemplate(
1547  guiParentNode->getScreenNode()->getApplicationRootPathName(),
1548  guiParentNode->getScreenNode()->getApplicationSubPathName(),
1549  AVOID_NULLPTR_STRING(node->Attribute("template"))
1550  ),
1551  guiElementIt->second->getAttributes(guiParentNode->screenNode),
1552  guiElementIt->second
1553  );
1554  }
1555  }
1556  }
1557  if (guiElementController != nullptr) {
1558  guiElementController->initialize();
1559  }
1560 }
1561 
1562 void GUIParser::parseTemplate(GUIParentNode* parentNode, const string& parentElementId, TiXmlElement* node, const string& templateXML, const unordered_map<string, string>& attributes, GUIElement* guiElement) {
1563  // add optiomal root tag, newer tdme requires to have a <template> tag surrounding the content
1564  auto newTemplateXML = templateXML;
1565  if (StringTools::regexSearch(newTemplateXML, "^\\s*(\\<\\s*template\\s*\\>)") == false) {
1566  if (guiElement != nullptr) {
1567  newTemplateXML = "<" + guiElement->getName() + ">\n" + templateXML + "</" + guiElement->getName() + ">\n";
1568  } else {
1569  newTemplateXML = "<template>\n" + templateXML + "</template>\n";
1570  }
1571  }
1572 
1573  //
1574  auto templateAttributes = attributes;
1575  {
1576  // parse defaults
1577  TiXmlDocument newTemplateDocument;
1578  newTemplateDocument.Parse(newTemplateXML.c_str());
1579  if (newTemplateDocument.Error() == true) {
1580  string message = "GUIParser::parseTemplate(): Could not parse XML. Error='" + string(newTemplateDocument.ErrorDesc()) + ":\n\n" + templateXML;
1581  Console::println(message);
1582  throw GUIParserException(message);
1583  }
1584  auto defaultsNodes = getChildrenByTagName(newTemplateDocument.RootElement(), "defaults");
1585  for (auto defaultsNode: defaultsNodes) {
1586  for (auto node = defaultsNode->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) {
1587  auto nodeTagName = string(node->Value());
1588  if (nodeTagName == "attribute") {
1589  auto name = string(AVOID_NULLPTR_STRING(node->Attribute("name")));
1590  auto value = string(AVOID_NULLPTR_STRING(node->Attribute("value")));
1591  if (templateAttributes.find(name) == templateAttributes.end()) {
1592  templateAttributes[name] = value;
1593  }
1594  } else {
1595  Console::println("GUIParser::parseTemplate(): unknown defaults node: " + nodeTagName);
1596  }
1597  }
1598  }
1599  }
1600 
1601  //
1602  auto themeProperties = parentNode->getScreenNode()->getApplicationSubPathName() == "project"?projectThemeProperties:engineThemeProperties;
1603 
1604  // replace with theme properties
1605  for (const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
1606  newTemplateXML = StringTools::replace(newTemplateXML, "{$" + themePropertyName + "}", escape(themePropertyValue));
1607  }
1608 
1609  // replace attributes given
1610  for (TiXmlAttribute* attribute = node->FirstAttribute(); attribute != nullptr; attribute = attribute->Next()) {
1611  auto attributeKey = string(attribute->Name());
1612  auto attributeValue = string(attribute->Value());
1613  newTemplateXML = StringTools::replace(newTemplateXML, "{$" + attributeKey + "}", escape(attributeValue));
1614  }
1615 
1616  // replace attributes from element
1617  for (const auto& [attributeName, attributeValue] : templateAttributes) {
1618  newTemplateXML = StringTools::replace(newTemplateXML, "{$" + attributeName + "}", escape(attributeValue));
1619  }
1620 
1621  // replace remaining unset variables with empty spaces
1622  newTemplateXML = StringTools::regexReplace(newTemplateXML, "\\{\\$[a-zA-Z\\-_0-9]{1,}\\}", "");
1623 
1624  // replace inner XML
1625  newTemplateXML = StringTools::replace(newTemplateXML, "{__InnerXML__}", getInnerXml(node));
1626 
1627  // parse
1628  TiXmlDocument newTemplateDocument;
1629  newTemplateDocument.Parse(newTemplateXML.c_str());
1630  if (newTemplateDocument.Error() == true) {
1631  string message = "GUIParser::parseTemplate(): Could not parse XML. Error='" + string(newTemplateDocument.ErrorDesc()) + ":\n\n" + newTemplateXML;
1632  Console::println(message);
1633  throw GUIParserException(message);
1634  }
1635  parseGUINode(parentNode, parentElementId, newTemplateDocument.RootElement(), guiElement);
1636 }
1637 
1638 void GUIParser::parseInnerXML(GUIParentNode* parentNode, const string& parentElementId, TiXmlElement* node, const string& innerXML, const unordered_map<string, string>& attributes, GUIElement* guiElement) {
1639  auto newInnerXML = innerXML;
1640  auto newParentElementId = parentElementId;
1641 
1642  //
1643  auto themeProperties = parentNode->getScreenNode()->getApplicationSubPathName() == "project"?projectThemeProperties:engineThemeProperties;
1644 
1645  // replace with theme properties
1646  for (const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
1647  newInnerXML = StringTools::replace(newInnerXML, "{$" + themePropertyName + "}", escape(themePropertyValue));
1648  }
1649 
1650  // replace attributes given
1651  for (TiXmlAttribute* attribute = node->FirstAttribute(); attribute != nullptr; attribute = attribute->Next()) {
1652  auto attributeKey = string(attribute->Name());
1653  auto attributeValue = string(attribute->Value());
1654  newInnerXML = StringTools::replace(newInnerXML, "{$" + attributeKey + "}", escape(attributeValue));
1655  // also store parent-id as such if given
1656  if (attributeKey == "parent-id") newParentElementId = attributeValue;
1657  }
1658 
1659  // replace attributes from element
1660  for (const auto& [attributeName, attributeValue]: attributes) {
1661  newInnerXML = StringTools::replace(newInnerXML, "{$" + attributeName + "}", escape(attributeValue));
1662  }
1663 
1664  // replace remaining unset variables with empty spaces
1665  newInnerXML = StringTools::regexReplace(newInnerXML, "\\{\\$[a-zA-Z\\-_0-9]{1,}\\}", "");
1666 
1667  // replace inner XML
1668  newInnerXML = StringTools::replace(newInnerXML, "{__InnerXML__}", getInnerXml(node));
1669 
1670  // add root tag
1671  newInnerXML = "<inner-xml>\n" + newInnerXML + "</inner-xml>\n";
1672 
1673  // parse
1674  TiXmlDocument newInnerXMLDocument;
1675  newInnerXMLDocument.Parse(newInnerXML.c_str());
1676  if (newInnerXMLDocument.Error() == true) {
1677  auto message = "GUIParser::parseInnerXML(): Could not parse XML. Error='" + string(newInnerXMLDocument.ErrorDesc()) + ":\n\n" + newInnerXML;
1678  throw GUIParserException(message);
1679  }
1680  parseGUINode(parentNode, newParentElementId, newInnerXMLDocument.RootElement(), guiElement);
1681 }
1682 
1683 int GUIParser::parseFactor(GUIParentNode* guiParentNode, const string& factor) {
1684  if (factor.empty() == true) {
1685  return 1;
1686  } else
1687  if (factor == "{__TreeDepth__}") {
1688  GUIElementNode* parentElementNode = nullptr;
1689  auto _guiParentNode = guiParentNode;
1690  while (_guiParentNode != nullptr) {
1691  parentElementNode = dynamic_cast<GUIElementNode*>(_guiParentNode);
1692  if (parentElementNode != nullptr) break;
1693  _guiParentNode = _guiParentNode->getParentNode();
1694  }
1695  auto childIdx = 0;
1696  while (parentElementNode != nullptr && parentElementNode->getParentElementNodeId().empty() == false) {
1697  parentElementNode = dynamic_cast<GUIElementNode*>(guiParentNode->getScreenNode()->getNodeById(parentElementNode->getParentElementNodeId()));
1698  if (parentElementNode != nullptr) {
1699  childIdx++;
1700  }
1701  }
1702  return childIdx;
1703  } else {
1704  return Integer::parse(factor);
1705  }
1706 }
1707 
1708 int GUIParser::parseInteger(const string& value, int defaultValue) {
1709  try {
1710  return Integer::parse(value);
1711  } catch (Exception& exception) {
1712  Console::println("GUIParser::parseInteger(): Unknown integer value: '" + value + "': using default value: " + to_string(defaultValue));
1713  return defaultValue;
1714  }
1715 }
1716 
1717 const vector<TiXmlElement*> GUIParser::getChildrenByTagName(TiXmlElement* parent, const char* name)
1718 {
1719  vector<TiXmlElement*> elementList;
1720  for (auto child = parent->FirstChildElement(name); child != nullptr; child = child->NextSiblingElement(name)) {
1721  elementList.push_back(child);
1722  }
1723  return elementList;
1724 }
1725 
1727 {
1728  std::stringstream ss;
1729  auto firstChildNode = node->FirstChildElement();
1730  if (firstChildNode == nullptr) {
1731  if (node->GetText() != nullptr) {
1732  ss << node->GetText();
1733  }
1734  } else {
1735  for (auto childNode = firstChildNode; childNode != nullptr; childNode = childNode->NextSiblingElement()) {
1736  ss << *childNode;
1737  }
1738  }
1739  return ss.str();
1740 }
1741 
1742 unordered_map<string, string> GUIParser::parseTemplateAttributes(const string& templateXML) {
1743  // add optiomal root tag, newer tdme requires to have a <template> tag surrounding the content
1744  auto newTemplateXML = templateXML;
1745  if (StringTools::regexSearch(newTemplateXML, "^\\s*(\\<\\s*template\\s*\\>)") == false) {
1746  newTemplateXML = "<template>\n" + templateXML + "</template>\n";
1747  }
1748 
1749  //
1750  unordered_map<string, string> templateAttributes;
1751 
1752  // parse defaults
1753  TiXmlDocument newTemplateDocument;
1754  newTemplateDocument.Parse(newTemplateXML.c_str());
1755  if (newTemplateDocument.Error() == true) {
1756  string message = "GUIParser::parseTemplateAttributes(): Could not parse XML. Error='" + string(newTemplateDocument.ErrorDesc()) + ":\n\n" + templateXML;
1757  Console::println(message);
1758  throw GUIParserException(message);
1759  }
1760  auto defaultsNodes = getChildrenByTagName(newTemplateDocument.RootElement(), "defaults");
1761  for (auto defaultsNode: defaultsNodes) {
1762  for (auto node = defaultsNode->FirstChildElement(); node != nullptr; node = node->NextSiblingElement()) {
1763  auto nodeTagName = string(node->Value());
1764  if (nodeTagName == "attribute") {
1765  auto name = string(AVOID_NULLPTR_STRING(node->Attribute("name")));
1766  auto value = string(AVOID_NULLPTR_STRING(node->Attribute("value")));
1767  templateAttributes[name] = value;
1768  } else {
1769  Console::println("GUIParser::parseTemplateAttributes(): unknown defaults node: " + nodeTagName);
1770  }
1771  }
1772  }
1773 
1774  //
1775  return templateAttributes;
1776 }
1777 
1778 const string GUIParser::getInnerXml(const string& xml) {
1779  //
1780  TiXmlDocument xmlDocument;
1781  xmlDocument.Parse(xml.c_str());
1782  if (xmlDocument.Error() == true) {
1783  string message = string("GUIParser::getInnerXml(): Could not parse XML. Error='") + string(xmlDocument.ErrorDesc()) + "':\n\n" + xml;
1784  Console::println(message);
1785  throw GUIParserException(message);
1786  }
1787  //
1788  TiXmlElement* xmlRoot = xmlDocument.RootElement();
1789  return getInnerXml(xmlRoot);
1790 }
1791 
1792 const string GUIParser::unescape(const string& str)
1793 {
1794  string result;
1795  result = StringTools::replace(str, "&quot;", "\"");
1796  result = StringTools::replace(result, "&#39;", "'");
1797  result = StringTools::replace(result, "&lt;", "<");
1798  result = StringTools::replace(result, "&gt;", ">");
1799  result = StringTools::replace(result, "&amp;", "&");
1800  return result;
1801 }
1802 
1803 const string GUIParser::escape(const string& str)
1804 {
1805  string result;
1806  result = StringTools::replace(str, "&", "&amp;");
1807  result = StringTools::replace(result, "\"", "&quot;");
1808  result = StringTools::replace(result, "'", "&#39;");
1809  result = StringTools::replace(result, "<", "&lt;");
1810  result = StringTools::replace(result, ">", "&gt;");
1811  return result;
1812 }
1813 
1815 {
1816  if (elements.find(guiElement->getName()) != elements.end()) {
1817  throw GUIParserException(
1818  "Element with given name '" +
1819  (guiElement->getName()) +
1820  "' already exists"
1821  );
1822  }
1823  elements.emplace(guiElement->getName(), guiElement);
1824 }
1825 
1827 {
1828  try {
1829  engineThemeProperties.load("./resources/engine/gui/themes", "theme_default.properties");
1830  } catch (Exception& exception) {
1831  Console::print(string("GUIParser::initialize(): An error occurred: "));
1832  Console::println(string(exception.what()));
1833  }
1834  try {
1835  projectThemeProperties.load("./resources/project/gui/themes", "theme_default.properties");
1836  } catch (Exception& exception) {
1837  Console::print(string("GUIParser::initialize(): An error occurred: "));
1838  Console::println(string(exception.what()));
1839  }
1840  try {
1841  auto guiElement = new GUICheckbox();
1842  addElement(guiElement);
1843  } catch (Exception& exception) {
1844  Console::print(string("GUIParser::initialize(): An error occurred: "));
1845  Console::println(string(exception.what()));
1846  }
1847  try {
1848  auto guiElement = new GUIRadioButton();
1849  addElement(guiElement);
1850  } catch (Exception& exception) {
1851  Console::print(string("GUIParser::initialize(): An error occurred: "));
1852  Console::println(string(exception.what()));
1853  }
1854  try {
1855  auto guiElement = new GUISelectBox();
1856  addElement(guiElement);
1857  } catch (Exception& exception) {
1858  Console::print(string("GUIParser::initialize(): An error occurred: "));
1859  Console::println(string(exception.what()));
1860  }
1861  try {
1862  auto guiElement = new GUISelectBoxOption();
1863  addElement(guiElement);
1864  } catch (Exception& exception) {
1865  Console::print(string("GUIParser::initialize(): An error occurred: "));
1866  Console::println(string(exception.what()));
1867  }
1868  try {
1869  auto guiElement = new GUISelectBoxParentOption();
1870  addElement(guiElement);
1871  } catch (Exception& exception) {
1872  Console::print(string("GUIParser::initialize(): An error occurred: "));
1873  Console::println(string(exception.what()));
1874  }
1875  try {
1876  auto guiElement = new GUIDropDown();
1877  addElement(guiElement);
1878  } catch (Exception& exception) {
1879  Console::print(string("GUIParser::initialize(): An error occurred: "));
1880  Console::println(string(exception.what()));
1881  }
1882  try {
1883  auto guiElement = new GUIDropDownOption();
1884  addElement(guiElement);
1885  } catch (Exception& exception) {
1886  Console::print(string("GUIParser::initialize(): An error occurred: "));
1887  Console::println(string(exception.what()));
1888  }
1889  try {
1890  auto guiElement = new GUITabs();
1891  addElement(guiElement);
1892  } catch (Exception& exception) {
1893  Console::print(string("GUIParser::initialize(): An error occurred: "));
1894  Console::println(string(exception.what()));
1895  }
1896  try {
1897  auto guiElement = new GUITabsHeader();
1898  addElement(guiElement);
1899  } catch (Exception& exception) {
1900  Console::print(string("GUIParser::initialize(): An error occurred: "));
1901  Console::println(string(exception.what()));
1902  }
1903  try {
1904  auto guiElement = new GUITab();
1905  addElement(guiElement);
1906  } catch (Exception& exception) {
1907  Console::print(string("GUIParser::initialize(): An error occurred: "));
1908  Console::println(string(exception.what()));
1909  }
1910  try {
1911  auto guiElement = new GUITabsContent();
1912  addElement(guiElement);
1913  } catch (Exception& exception) {
1914  Console::print(string("GUIParser::initialize(): An error occurred: "));
1915  Console::println(string(exception.what()));
1916  }
1917  try {
1918  auto guiElement = new GUITabContent();
1919  addElement(guiElement);
1920  } catch (Exception& exception) {
1921  Console::print(string("GUIParser::initialize(): An error occurred: "));
1922  Console::println(string(exception.what()));
1923  }
1924  try {
1925  auto guiElement = new GUIButton();
1926  addElement(guiElement);
1927  } catch (Exception& exception) {
1928  Console::print(string("GUIParser::initialize(): An error occurred: "));
1929  Console::println(string(exception.what()));
1930  }
1931  try {
1932  auto guiElement = new GUIInput();
1933  addElement(guiElement);
1934  } catch (Exception& exception) {
1935  Console::print(string("GUIParser::initialize(): An error occurred: "));
1936  Console::println(string(exception.what()));
1937  }
1938  try {
1939  auto guiElement = new GUIScrollArea();
1940  addElement(guiElement);
1941  } catch (Exception& exception) {
1942  Console::print(string("GUIParser::initialize(): An error occurred: "));
1943  Console::println(string(exception.what()));
1944  }
1945  try {
1946  auto guiElement = new GUISliderH();
1947  addElement(guiElement);
1948  } catch (Exception& exception) {
1949  Console::print(string("GUIParser::initialize(): An error occurred: "));
1950  Console::println(string(exception.what()));
1951  }
1952  try {
1953  auto guiElement = new GUISliderV();
1954  addElement(guiElement);
1955  } catch (Exception& exception) {
1956  Console::print(string("GUIParser::initialize(): An error occurred: "));
1957  Console::println(string(exception.what()));
1958  }
1959  try {
1960  auto guiElement = new GUIKnob();
1961  addElement(guiElement);
1962  } catch (Exception& exception) {
1963  Console::print(string("GUIParser::initialize(): An error occurred: "));
1964  Console::println(string(exception.what()));
1965  }
1966  try {
1967  auto guiElement = new GUIImageButton();
1968  addElement(guiElement);
1969  } catch (Exception& exception) {
1970  Console::print(string("GUIParser::initialize(): An error occurred: "));
1971  Console::println(string(exception.what()));
1972  }
1973  try {
1974  auto guiElement = new GUIProgressBar();
1975  addElement(guiElement);
1976  } catch (Exception& exception) {
1977  Console::print(string("GUIParser::initialize(): An error occurred: "));
1978  Console::println(string(exception.what()));
1979  }
1980  try {
1981  auto guiElement = new GUIMenuHeader();
1982  addElement(guiElement);
1983  } catch (Exception& exception) {
1984  Console::print(string("GUIParser::initialize(): An error occurred: "));
1985  Console::println(string(exception.what()));
1986  }
1987  try {
1988  auto guiElement = new GUIMenuHeaderItem();
1989  addElement(guiElement);
1990  } catch (Exception& exception) {
1991  Console::print(string("GUIParser::initialize(): An error occurred: "));
1992  Console::println(string(exception.what()));
1993  }
1994  try {
1995  auto guiElement = new GUIMenuItem();
1996  addElement(guiElement);
1997  } catch (Exception& exception) {
1998  Console::print(string("GUIParser::initialize(): An error occurred: "));
1999  Console::println(string(exception.what()));
2000  }
2001  try {
2002  auto guiElement = new GUIMenuSeparator();
2003  addElement(guiElement);
2004  } catch (Exception& exception) {
2005  Console::print(string("GUIParser::initialize(): An error occurred: "));
2006  Console::println(string(exception.what()));
2007  }
2008  try {
2009  auto guiElement = new GUIContextMenu();
2010  addElement(guiElement);
2011  } catch (Exception& exception) {
2012  Console::print(string("GUIParser::initialize(): An error occurred: "));
2013  Console::println(string(exception.what()));
2014  }
2015  try {
2016  auto guiElement = new GUIContextMenuItem();
2017  addElement(guiElement);
2018  } catch (Exception& exception) {
2019  Console::print(string("GUIParser::initialize(): An error occurred: "));
2020  Console::println(string(exception.what()));
2021  }
2022  try {
2023  auto guiElement = new GUISelectorH();
2024  addElement(guiElement);
2025  } catch (Exception& exception) {
2026  Console::print(string("GUIParser::initialize(): An error occurred: "));
2027  Console::println(string(exception.what()));
2028  }
2029  try {
2030  auto guiElement = new GUISelectorHOption();
2031  addElement(guiElement);
2032  } catch (Exception& exception) {
2033  Console::print(string("GUIParser::initialize(): An error occurred: "));
2034  Console::println(string(exception.what()));
2035  }
2036  try {
2037  auto guiElement = new GUIStyledInput();
2038  addElement(guiElement);
2039  } catch (Exception& exception) {
2040  Console::print(string("GUIParser::initialize(): An error occurred: "));
2041  Console::println(string(exception.what()));
2042  }
2043  try {
2044  auto guiElement = new GUIMoveable();
2045  addElement(guiElement);
2046  } catch (Exception& exception) {
2047  Console::print(string("GUIParser::initialize(): An error occurred: "));
2048  Console::println(string(exception.what()));
2049  }
2050  try {
2051  auto guiElement = new GUIGrid();
2052  addElement(guiElement);
2053  } catch (Exception& exception) {
2054  Console::print(string("GUIParser::initialize(): An error occurred: "));
2055  Console::println(string(exception.what()));
2056  }
2057  try {
2058  auto guiElement = new GUIGridItem();
2059  addElement(guiElement);
2060  } catch (Exception& exception) {
2061  Console::print(string("GUIParser::initialize(): An error occurred: "));
2062  Console::println(string(exception.what()));
2063  }
2064 }
2065 
2067  for (const auto& [elementId, element]: elements) delete element;
2068  elements.clear();
2069 }
2070 
2071 void GUIParser::loadProjectThemeProperties(const string& pathName) {
2072  try {
2073  projectThemeProperties.load(pathName + "/resources/project/gui/themes", "theme_default.properties");
2074  } catch (Exception& exception) {
2075  Console::print(string("GUIParser::loadProjectThemeProperties(): An error occurred: "));
2076  Console::println(string(exception.what()));
2077  }
2078 }
#define AVOID_NULLPTR_STRING(arg)
Definition: GUIParser.cpp:162
GUI parser.
Definition: GUIParser.h:40
static void parseEffects(GUINode *guiNode, TiXmlElement *xmlParentNode)
Parse GUI effect.
Definition: GUIParser.cpp:381
static void parseInnerXML(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *node, const string &innerXML, const unordered_map< string, string > &attributes, GUIElement *guiElement)
Parse inner XML.
Definition: GUIParser.cpp:1638
static const string getInnerXml(TiXmlElement *node)
Get inner XML.
Definition: GUIParser.cpp:1726
static const string unescape(const string &str)
Unescape quotes and other special html characters.
Definition: GUIParser.cpp:1792
static void initialize()
Initialize GUI elements.
Definition: GUIParser.cpp:1826
static STATIC_DLL_IMPEXT Properties projectThemeProperties
Definition: GUIParser.h:45
static void addElement(GUIElement *guiElement)
Add GUI element.
Definition: GUIParser.cpp:1814
static int parseInteger(const string &value, int defaultValue)
Parse integer.
Definition: GUIParser.cpp:1708
static STATIC_DLL_IMPEXT unordered_map< string, GUIElement * > elements
Definition: GUIParser.h:43
static int parseFactor(GUIParentNode *guiParentNode, const string &factor)
Parse factor.
Definition: GUIParser.cpp:1683
static void parseGUINode(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *xmlParentNode, GUIElement *guiElement)
Parse GUI node.
Definition: GUIParser.cpp:396
static const string escape(const string &str)
Escape quotes and other special html characters.
Definition: GUIParser.cpp:1803
static void dispose()
Dispose GUI elements.
Definition: GUIParser.cpp:2066
static GUIScreenNode * parse(const string &pathName, const string &fileName, const unordered_map< string, string > &variables={}, const EngineMiniScript::ScriptVariable &miniScriptArguments=EngineMiniScript::ScriptVariable(), Context *context=nullptr)
Parses a GUI XML file.
static const string getRootNode(const string &pathName, const string &fileName)
Parses a XML file and returns root node as string.
Definition: GUIParser.cpp:168
static void loadProjectThemeProperties(const string &pathName)
Load project theme properties.
Definition: GUIParser.cpp:2071
static void parseTemplate(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *node, const string &templateXML, const unordered_map< string, string > &attributes, GUIElement *guiElement)
Parse template.
Definition: GUIParser.cpp:1562
static constexpr int FONTSIZE_FALLBACK
Definition: GUIParser.h:47
static const vector< TiXmlElement * > getChildrenByTagName(TiXmlElement *parent, const char *name)
Returns immediate children tags.
Definition: GUIParser.cpp:1717
static STATIC_DLL_IMPEXT Properties engineThemeProperties
Definition: GUIParser.h:44
static unordered_map< string, string > parseTemplateAttributes(const string &templateXML)
Parse template attributes.
Definition: GUIParser.cpp:1742
static void parseEffect(GUINode *guiNode, const string &effectPrefix, bool requiresCondition, TiXmlElement *node)
Parse GUI effect.
Definition: GUIParser.cpp:330
GUI effect base class.
Definition: GUIEffect.h:26
void setAction(Action *action)
Set action to be performed on effect end.
Definition: GUIEffect.h:151
GUI button element.
Definition: GUIButton.h:29
GUI check box element.
Definition: GUICheckbox.h:27
GUI context menu item element.
GUI context menu element.
GUI drop down option element.
GUI drop down element.
Definition: GUIDropDown.h:27
GUI element base class.
Definition: GUIElement.h:23
virtual GUINodeController * createController(GUINode *node)=0
Create controller which is attached to this node.
virtual const string & getName()=0
GUI grid item element.
Definition: GUIGridItem.h:27
GUI grid element.
Definition: GUIGrid.h:28
GUI image button element.
GUI input element.
Definition: GUIInput.h:27
GUI knob element.
Definition: GUIKnob.h:28
GUI menu header item element.
GUI menu header element.
Definition: GUIMenuHeader.h:27
GUI menu item element.
Definition: GUIMenuItem.h:27
GUI menu separator element.
GUI moveable element.
Definition: GUIMoveable.h:28
GUI radio button element.
GUI scroll area element.
Definition: GUIScrollArea.h:27
GUI select box option element.
GUI select box element.
Definition: GUISelectBox.h:28
GUI selector horizontal option element.
GUI selector horizontal element.
Definition: GUISelectorH.h:27
GUI horizontal slider element.
Definition: GUISliderH.h:29
GUI vertical slider element.
Definition: GUISliderV.h:28
GUI styled input element.
GUI tab content element.
Definition: GUITabContent.h:27
GUI tab element.
Definition: GUITab.h:27
GUI tabs content element.
GUI tabs header element.
Definition: GUITabsHeader.h:27
GUI tabs element.
Definition: GUITabs.h:27
GUI node controller base class.
virtual void initialize()=0
Initialize controller after element has been created.
GUI node base class.
Definition: GUINode.h:64
void addEffect(const string &id, GUIEffect *effect)
Add effect, effect already registered with the is will be removed.
Definition: GUINode.cpp:1316
GUIParentNode * getParentNode()
Definition: GUINode.h:332
GUIScreenNode * screenNode
Definition: GUINode.h:147
void setBackgroundImage(const string &backgroundImage)
Set background image.
Definition: GUINode.cpp:1304
GUIScreenNode * getScreenNode()
Definition: GUINode.h:325
GUI panel node TODO: remove me!
Definition: GUIPanelNode.h:38
GUI parent node base class thats supporting child nodes.
Definition: GUIParentNode.h:42
void getChildControllerNodes(vector< GUINode * > &childControllerNodes, bool requireConditionsMet=false)
Get child controller nodes.
void setConditionsMet() override
Set conditions met for this node and its subnodes.
void addSubNode(GUINode *node)
Add sub node.
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:72
const string & getApplicationRootPathName()
const string & getApplicationSubPathName()
const string allocateNodeId()
Allocate node id.
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
File system singleton class.
Definition: FileSystem.h:17
Console class.
Definition: Console.h:29
Float class.
Definition: Float.h:27
Integer class.
Definition: Integer.h:25
Mutable utf8 aware string class.
Definition: MutableString.h:23
Properties class, which helps out with storeing or loading key value pairs from/to property files.
Definition: Properties.h:23
void load(const string &pathName, const string &fileName, FileSystemInterface *fileSystem=nullptr)
Load property file.
Definition: Properties.cpp:24
String tools class.
Definition: StringTools.h:22
An attribute is a name-value pair.
Definition: tinyxml.h:734
const TiXmlAttribute * Next() const
Get the next sibling attribute in the DOM. Returns null at end.
Definition: tinyxml.cpp:1138
Always the top level node.
Definition: tinyxml.h:1317
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Parse the given null terminated block of xml data.
const char * ErrorDesc() const
Contains a textual (english) description of the error if one occurs.
Definition: tinyxml.h:1382
const TiXmlElement * RootElement() const
Get the root element – the only top level element – of the document.
Definition: tinyxml.h:1371
bool Error() const
If an error occurs, Error will be set to true.
Definition: tinyxml.h:1379
The element is a container class.
Definition: tinyxml.h:886
const char * Attribute(const char *name) const
Given an attribute name, Attribute() returns the value for the attribute of that name,...
Definition: tinyxml.cpp:564
const char * GetText() const
Convenience function for easy access to the text inside an element.
Definition: tinyxml.cpp:870
const TiXmlAttribute * FirstAttribute() const
Access the first attribute in this element.
Definition: tinyxml.h:1021
const char * Value() const
The meaning of 'value' changes for the specific type of TiXmlNode.
Definition: tinyxml.h:457
const TiXmlElement * NextSiblingElement() const
Convenience function to get through elements.
Definition: tinyxml.cpp:471
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
Definition: tinyxml.cpp:441
std::exception Exception
Exception base class.
Definition: Exception.h:18
Action Interface.
Definition: Action.h:11