4 #include <unordered_map>
84 using std::unordered_map;
162 #define AVOID_NULLPTR_STRING(arg) (arg == nullptr?"":arg)
164 unordered_map<string, GUIElement*> GUIParser::elements = unordered_map<string, GUIElement*>();
168 const string GUIParser::getRootNode(
const string& pathName,
const string& fileName) {
169 return getRootNode(FileSystem::getInstance()->getContentAsString(pathName, fileName));
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);
183 auto rootNode = string(xmlRoot->
Value());
187 GUIScreenNode*
GUIParser::parse(
const string& pathName,
const string& fileName,
const unordered_map<string, string>& variables,
const MiniScript::ScriptVariable& miniScriptArguments,
Context* context)
189 return parse(FileSystem::getInstance()->getContentAsString(pathName, fileName), variables, pathName, fileName, miniScriptArguments, context);
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)
194 auto applicationRootPath = Tools::getApplicationRootPathName(pathName);
195 auto applicationSubPathName = Tools::getApplicationSubPathName(pathName);
200 for (
const auto& [variableName, variableValue]: variables) {
201 newXML = StringTools::replace(newXML,
"{$" + variableName +
"}",
escape(variableValue));
204 for (
const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
205 newXML = StringTools::replace(newXML,
"{$" + themePropertyName +
"}",
escape(themePropertyValue));
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);
218 if (
string(xmlRoot->
Value()) !=
string(
"screen")) {
224 (pathName.empty() ==
false?pathName +
"/":
"") + fileName,
225 applicationRootPath.empty() ==
true?
".":FileSystem::getInstance()->getCanonicalURI(applicationRootPath,
""),
226 applicationSubPathName,
231 GUINode::createAlignments(
235 GUINode::createRequestedConstraints(
244 GUINode::createScale9Grid(
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(
265 GUINode::createPadding(
272 GUIScreenNode::createSizeConstraints(
290 parseGUINode(guiScreenNode,
string(), xmlRoot,
nullptr);
294 vector<GUINode*> childControllerNodes;
296 for (
auto node: childControllerNodes) node->getController()->onSubTreeChange();
299 return guiScreenNode;
304 string xml = FileSystem::getInstance()->getContentAsString(pathName, fileName);
305 parse(parentNode, xml);
315 for (
const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
316 newXML = StringTools::replace(newXML,
"{$" + themePropertyName +
"}",
escape(themePropertyValue));
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);
333 if (type ==
"color") {
342 static_cast<GUIColorEffect*
>(effect)->setYoyo(node->
Attribute(
"yoyo") ==
nullptr?
false:StringTools::toLowerCase(StringTools::trim(node->
Attribute(
"yoyo"))) ==
"true");
348 if (type ==
"position") {
364 if (effect !=
nullptr && action.empty() ==
false) {
365 class EffectAction:
public virtual Action
368 EffectAction(
GUIScreenNode* guiScreenNode,
const string& expression): guiScreenNode(guiScreenNode), expression(expression) {
370 void performAction()
override {
371 GUIElementNode::executeExpression(guiScreenNode, expression);
383 string nodeTagName = string(node->Value());
384 if (nodeTagName ==
"effect-in") {
385 parseEffect(guiNode,
"tdme.xmleffect.in",
true, node);
387 if (nodeTagName ==
"effect-out") {
388 parseEffect(guiNode,
"tdme.xmleffect.out",
true, node);
390 if (nodeTagName ==
"effect-default") {
391 parseEffect(guiNode,
"tdme.xmleffect.default",
false, node);
400 auto guiElementControllerInstalled =
false;
404 string nodeTagName = string(node->Value());
405 if (nodeTagName ==
"defaults") {
408 if (nodeTagName ==
"effect-in") {
409 parseEffect(guiParentNode,
"tdme.xmleffect.in",
true, node);
411 if (nodeTagName ==
"effect-out") {
412 parseEffect(guiParentNode,
"tdme.xmleffect.out",
true, node);
414 if (nodeTagName ==
"effect-default") {
415 parseEffect(guiParentNode,
"tdme.xmleffect.default",
false, node);
417 if (nodeTagName ==
"panel") {
425 GUINode::createAlignments(
429 GUIParentNode::createRequestedConstraints(
436 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))),
GUIColor(themeProperties.get(
"color.panel",
"#F0F0F0"))),
438 GUINode::createScale9Grid(
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(
459 GUINode::createPadding(
472 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
474 if (guiElementController !=
nullptr) {
475 guiPanelNode->setController(guiElementController);
477 guiElementControllerInstalled =
true;
481 if (nodeTagName ==
"layer") {
489 GUIElementNode::createAlignments(
493 GUIParentNode::createRequestedConstraints(
500 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
502 GUINode::createScale9Grid(
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(
523 GUINode::createPadding(
535 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
537 if (guiElementController !=
nullptr) {
538 guiLayerNode->setController(guiElementController);
540 guiElementControllerInstalled =
true;
544 if (nodeTagName ==
"layout") {
552 GUINode::createAlignments(
556 GUIParentNode::createRequestedConstraints(
563 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
565 GUINode::createScale9Grid(
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(
586 GUINode::createPadding(
599 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
601 if (guiElementController !=
nullptr) {
602 guiLayoutNode->setController(guiElementController);
604 guiElementControllerInstalled =
true;
608 if (nodeTagName ==
"space") {
614 GUINode::createAlignments(
618 GUIParentNode::createRequestedConstraints(
625 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
627 GUINode::createScale9Grid(
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(
648 GUINode::createPadding(
660 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
662 if (guiElementController !=
nullptr) {
663 guiSpaceNode->setController(guiElementController);
665 guiElementControllerInstalled =
true;
669 if (nodeTagName ==
"element") {
677 GUIElementNode::createAlignments(
681 GUIParentNode::createRequestedConstraints(
688 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
690 GUINode::createScale9Grid(
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(
711 GUINode::createPadding(
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"),
737 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
739 if (guiElementController !=
nullptr) {
740 guiElementNode->setController(guiElementController);
742 guiElementControllerInstalled =
true;
744 parseGUINode(guiElementNode, guiElementNode->getId(), node,
nullptr);
746 if (nodeTagName ==
"image") {
752 GUINode::createAlignments(
756 GUIParentNode::createRequestedConstraints(
763 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
765 GUINode::createScale9Grid(
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(
786 GUINode::createPadding(
797 GUIImageNode::createRequestedDimensionConstraints(
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(
812 GUIImageNode::createClipping(
821 node->Attribute(
"rotation") !=
nullptr?Float::parse(node->Attribute(
"rotation")):0.0f
824 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
826 if (guiElementController !=
nullptr) {
827 guiImageNode->setController(guiElementController);
829 guiElementControllerInstalled =
true;
833 if (nodeTagName ==
"video") {
839 GUINode::createAlignments(
843 GUIParentNode::createRequestedConstraints(
850 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
852 GUINode::createScale9Grid(
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(
873 GUINode::createPadding(
884 GUIImageNode::createRequestedDimensionConstraints(
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(
899 GUIImageNode::createClipping(
910 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
912 if (guiElementController !=
nullptr) {
913 guiVideoNode->setController(guiElementController);
915 guiElementControllerInstalled =
true;
919 if (nodeTagName ==
"gradient") {
925 GUINode::createAlignments(
929 GUIParentNode::createRequestedConstraints(
936 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
938 GUINode::createScale9Grid(
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(
959 GUINode::createPadding(
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(
983 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
985 if (guiElementController !=
nullptr) {
986 guiGradientNode->setController(guiElementController);
988 guiElementControllerInstalled =
true;
992 if (nodeTagName ==
"text") {
998 GUINode::createAlignments(
1002 GUIParentNode::createRequestedConstraints(
1009 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1011 GUINode::createScale9Grid(
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(
1032 GUINode::createPadding(
1048 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1050 if (guiElementController !=
nullptr) {
1051 guiTextNode->setController(guiElementController);
1053 guiElementControllerInstalled =
true;
1057 if (nodeTagName ==
"styled-text") {
1063 GUINode::createAlignments(
1067 GUIParentNode::createRequestedConstraints(
1074 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1076 GUINode::createScale9Grid(
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(
1097 GUINode::createPadding(
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",
1114 guiParentNode->
addSubNode(guiStyledTextNode);
1119 guiStyledTextNode->getController()->initialize();
1122 if (nodeTagName ==
"table") {
1130 GUINode::createAlignments(
1134 GUIParentNode::createRequestedConstraints(
1141 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1143 GUINode::createScale9Grid(
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(
1164 GUINode::createPadding(
1176 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1178 if (guiElementController !=
nullptr) {
1179 guiTableNode->setController(guiElementController);
1181 guiElementControllerInstalled =
true;
1185 if (nodeTagName ==
"table-cell") {
1193 GUINode::createAlignments(
1197 GUITableCellNode::createRequestedConstraints(
1204 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1206 GUINode::createScale9Grid(
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(
1227 GUINode::createPadding(
1240 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1242 if (guiElementController !=
nullptr) {
1243 guiTableCellNode->setController(guiElementController);
1245 guiElementControllerInstalled =
true;
1247 parseGUINode(guiTableCellNode,
string(), node,
nullptr);
1249 if (nodeTagName ==
"table-row") {
1257 GUINode::createAlignments(
1261 GUITableRowNode::createRequestedConstraints(
1268 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1270 GUINode::createScale9Grid(
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(
1291 GUINode::createPadding(
1303 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1305 if (guiElementController !=
nullptr) {
1306 guiTableRowNode->setController(guiElementController);
1308 guiElementControllerInstalled =
true;
1310 parseGUINode(guiTableRowNode,
string(), node,
nullptr);
1312 if (nodeTagName ==
"input-internal") {
1318 GUINode::createAlignments(
1322 GUIParentNode::createRequestedConstraints(
1329 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1331 GUINode::createScale9Grid(
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(
1352 GUINode::createPadding(
1367 GUIInputInternalNode::createMaxLength(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"maxlength"))))
1369 guiParentNode->
addSubNode(guiInputInternalNode);
1370 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1372 if (guiElementController !=
nullptr) {
1373 guiInputInternalNode->setController(guiElementController);
1375 guiElementControllerInstalled =
true;
1379 if (nodeTagName ==
"vertical-scrollbar-internal") {
1385 GUINode::createAlignments(
1389 GUIParentNode::createRequestedConstraints(
1396 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1398 GUINode::createScale9Grid(
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(
1419 GUINode::createPadding(
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)
1433 guiParentNode->
addSubNode(guiVerticalScrollbarInternalNode);
1434 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1435 guiElementController = guiElement->
createController(guiVerticalScrollbarInternalNode);
1436 if (guiElementController !=
nullptr) {
1437 guiVerticalScrollbarInternalNode->setController(guiElementController);
1439 guiElementControllerInstalled =
true;
1443 if (nodeTagName ==
"horizontal-scrollbar-internal") {
1449 GUINode::createAlignments(
1453 GUIParentNode::createRequestedConstraints(
1460 GUINode::getRequestedColor(
string(
AVOID_NULLPTR_STRING(node->Attribute(
"background-color"))), GUIColor::GUICOLOR_TRANSPARENT),
1462 GUINode::createScale9Grid(
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(
1483 GUINode::createPadding(
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)
1497 guiParentNode->
addSubNode(guiHorizontalScrollbarInternalNode);
1498 if (guiElement !=
nullptr && guiElementControllerInstalled ==
false) {
1499 guiElementController = guiElement->
createController(guiHorizontalScrollbarInternalNode);
1500 if (guiElementController !=
nullptr) {
1501 guiHorizontalScrollbarInternalNode->setController(guiElementController);
1503 guiElementControllerInstalled =
true;
1505 parseEffects(guiHorizontalScrollbarInternalNode, node);
1507 if (nodeTagName ==
"inner-xml") {
1508 unordered_map<string, string> attributes;
1518 if (nodeTagName ==
"template") {
1520 unordered_map<string, string> attributes;
1525 FileSystem::getInstance()->getContentAsString(
1527 FileSystem::getInstance()->getFileName(src)
1533 auto nodeTagNameString = nodeTagName;
1534 const auto guiElementIt =
elements.find(nodeTagNameString);
1535 if (guiElementIt ==
elements.end()) {
1537 "Unknown element '" +
1538 (nodeTagNameString) +
1546 guiElementIt->second->getTemplate(
1551 guiElementIt->second->getAttributes(guiParentNode->
screenNode),
1552 guiElementIt->second
1557 if (guiElementController !=
nullptr) {
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";
1569 newTemplateXML =
"<template>\n" + templateXML +
"</template>\n";
1574 auto templateAttributes = attributes;
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);
1585 for (
auto defaultsNode: defaultsNodes) {
1587 auto nodeTagName = string(node->
Value());
1588 if (nodeTagName ==
"attribute") {
1591 if (templateAttributes.find(name) == templateAttributes.end()) {
1592 templateAttributes[name] = value;
1595 Console::println(
"GUIParser::parseTemplate(): unknown defaults node: " + nodeTagName);
1605 for (
const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
1606 newTemplateXML = StringTools::replace(newTemplateXML,
"{$" + themePropertyName +
"}",
escape(themePropertyValue));
1611 auto attributeKey = string(attribute->Name());
1612 auto attributeValue = string(attribute->Value());
1613 newTemplateXML = StringTools::replace(newTemplateXML,
"{$" + attributeKey +
"}",
escape(attributeValue));
1617 for (
const auto& [attributeName, attributeValue] : templateAttributes) {
1618 newTemplateXML = StringTools::replace(newTemplateXML,
"{$" + attributeName +
"}",
escape(attributeValue));
1622 newTemplateXML = StringTools::regexReplace(newTemplateXML,
"\\{\\$[a-zA-Z\\-_0-9]{1,}\\}",
"");
1625 newTemplateXML = StringTools::replace(newTemplateXML,
"{__InnerXML__}",
getInnerXml(node));
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);
1639 auto newInnerXML = innerXML;
1640 auto newParentElementId = parentElementId;
1646 for (
const auto& [themePropertyName, themePropertyValue]: themeProperties.getProperties()) {
1647 newInnerXML = StringTools::replace(newInnerXML,
"{$" + themePropertyName +
"}",
escape(themePropertyValue));
1652 auto attributeKey = string(attribute->Name());
1653 auto attributeValue = string(attribute->Value());
1654 newInnerXML = StringTools::replace(newInnerXML,
"{$" + attributeKey +
"}",
escape(attributeValue));
1656 if (attributeKey ==
"parent-id") newParentElementId = attributeValue;
1660 for (
const auto& [attributeName, attributeValue]: attributes) {
1661 newInnerXML = StringTools::replace(newInnerXML,
"{$" + attributeName +
"}",
escape(attributeValue));
1665 newInnerXML = StringTools::regexReplace(newInnerXML,
"\\{\\$[a-zA-Z\\-_0-9]{1,}\\}",
"");
1668 newInnerXML = StringTools::replace(newInnerXML,
"{__InnerXML__}",
getInnerXml(node));
1671 newInnerXML =
"<inner-xml>\n" + newInnerXML +
"</inner-xml>\n";
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;
1684 if (factor.empty() ==
true) {
1687 if (factor ==
"{__TreeDepth__}") {
1689 auto _guiParentNode = guiParentNode;
1690 while (_guiParentNode !=
nullptr) {
1691 parentElementNode =
dynamic_cast<GUIElementNode*
>(_guiParentNode);
1692 if (parentElementNode !=
nullptr)
break;
1698 if (parentElementNode !=
nullptr) {
1704 return Integer::parse(factor);
1710 return Integer::parse(value);
1712 Console::println(
"GUIParser::parseInteger(): Unknown integer value: '" + value +
"': using default value: " + to_string(defaultValue));
1713 return defaultValue;
1719 vector<TiXmlElement*> elementList;
1721 elementList.push_back(child);
1728 std::stringstream ss;
1730 if (firstChildNode ==
nullptr) {
1731 if (node->
GetText() !=
nullptr) {
1735 for (
auto childNode = firstChildNode; childNode !=
nullptr; childNode = childNode->NextSiblingElement()) {
1744 auto newTemplateXML = templateXML;
1745 if (StringTools::regexSearch(newTemplateXML,
"^\\s*(\\<\\s*template\\s*\\>)") ==
false) {
1746 newTemplateXML =
"<template>\n" + templateXML +
"</template>\n";
1750 unordered_map<string, string> templateAttributes;
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);
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") {
1767 templateAttributes[name] = value;
1769 Console::println(
"GUIParser::parseTemplateAttributes(): unknown defaults node: " + nodeTagName);
1775 return templateAttributes;
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);
1795 result = StringTools::replace(str,
""",
"\"");
1796 result = StringTools::replace(result,
"'",
"'");
1797 result = StringTools::replace(result,
"<",
"<");
1798 result = StringTools::replace(result,
">",
">");
1799 result = StringTools::replace(result,
"&",
"&");
1806 result = StringTools::replace(str,
"&",
"&");
1807 result = StringTools::replace(result,
"\"",
""");
1808 result = StringTools::replace(result,
"'",
"'");
1809 result = StringTools::replace(result,
"<",
"<");
1810 result = StringTools::replace(result,
">",
">");
1818 "Element with given name '" +
1831 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1832 Console::println(
string(exception.what()));
1837 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1838 Console::println(
string(exception.what()));
1844 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1845 Console::println(
string(exception.what()));
1851 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1852 Console::println(
string(exception.what()));
1858 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1859 Console::println(
string(exception.what()));
1865 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1866 Console::println(
string(exception.what()));
1872 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1873 Console::println(
string(exception.what()));
1879 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1880 Console::println(
string(exception.what()));
1886 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1887 Console::println(
string(exception.what()));
1890 auto guiElement =
new GUITabs();
1893 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1894 Console::println(
string(exception.what()));
1900 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1901 Console::println(
string(exception.what()));
1904 auto guiElement =
new GUITab();
1907 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1908 Console::println(
string(exception.what()));
1914 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1915 Console::println(
string(exception.what()));
1921 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1922 Console::println(
string(exception.what()));
1928 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1929 Console::println(
string(exception.what()));
1935 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1936 Console::println(
string(exception.what()));
1942 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1943 Console::println(
string(exception.what()));
1949 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1950 Console::println(
string(exception.what()));
1956 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1957 Console::println(
string(exception.what()));
1960 auto guiElement =
new GUIKnob();
1963 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1964 Console::println(
string(exception.what()));
1970 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1971 Console::println(
string(exception.what()));
1977 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1978 Console::println(
string(exception.what()));
1984 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1985 Console::println(
string(exception.what()));
1991 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1992 Console::println(
string(exception.what()));
1998 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
1999 Console::println(
string(exception.what()));
2005 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2006 Console::println(
string(exception.what()));
2012 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2013 Console::println(
string(exception.what()));
2019 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2020 Console::println(
string(exception.what()));
2026 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2027 Console::println(
string(exception.what()));
2033 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2034 Console::println(
string(exception.what()));
2040 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2041 Console::println(
string(exception.what()));
2047 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2048 Console::println(
string(exception.what()));
2051 auto guiElement =
new GUIGrid();
2054 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2055 Console::println(
string(exception.what()));
2061 Console::print(
string(
"GUIParser::initialize(): An error occurred: "));
2062 Console::println(
string(exception.what()));
2067 for (
const auto& [elementId, element]:
elements)
delete element;
2075 Console::print(
string(
"GUIParser::loadProjectThemeProperties(): An error occurred: "));
2076 Console::println(
string(exception.what()));
#define AVOID_NULLPTR_STRING(arg)
static void parseEffects(GUINode *guiNode, TiXmlElement *xmlParentNode)
Parse GUI effect.
static void parseInnerXML(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *node, const string &innerXML, const unordered_map< string, string > &attributes, GUIElement *guiElement)
Parse inner XML.
static const string getInnerXml(TiXmlElement *node)
Get inner XML.
static const string unescape(const string &str)
Unescape quotes and other special html characters.
static void initialize()
Initialize GUI elements.
static STATIC_DLL_IMPEXT Properties projectThemeProperties
static void addElement(GUIElement *guiElement)
Add GUI element.
static int parseInteger(const string &value, int defaultValue)
Parse integer.
static STATIC_DLL_IMPEXT unordered_map< string, GUIElement * > elements
static int parseFactor(GUIParentNode *guiParentNode, const string &factor)
Parse factor.
static void parseGUINode(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *xmlParentNode, GUIElement *guiElement)
Parse GUI node.
static const string escape(const string &str)
Escape quotes and other special html characters.
static void dispose()
Dispose GUI elements.
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.
static void loadProjectThemeProperties(const string &pathName)
Load project theme properties.
static void parseTemplate(GUIParentNode *guiParentNode, const string &parentElementId, TiXmlElement *node, const string &templateXML, const unordered_map< string, string > &attributes, GUIElement *guiElement)
Parse template.
static constexpr int FONTSIZE_FALLBACK
static const vector< TiXmlElement * > getChildrenByTagName(TiXmlElement *parent, const char *name)
Returns immediate children tags.
static STATIC_DLL_IMPEXT Properties engineThemeProperties
static unordered_map< string, string > parseTemplateAttributes(const string &templateXML)
Parse template attributes.
static void parseEffect(GUINode *guiNode, const string &effectPrefix, bool requiresCondition, TiXmlElement *node)
Parse GUI effect.
void setAction(Action *action)
Set action to be performed on effect end.
GUI drop down option element.
virtual GUINodeController * createController(GUINode *node)=0
Create controller which is attached to this node.
virtual const string & getName()=0
GUI select box option element.
GUI select box parent option element.
GUI selector horizontal option element.
GUI selector horizontal element.
GUI horizontal slider element.
GUI vertical slider element.
GUI tabs content element.
const string & getParentElementNodeId()
GUI node controller base class.
virtual void initialize()=0
Initialize controller after element has been created.
void addEffect(const string &id, GUIEffect *effect)
Add effect, effect already registered with the is will be removed.
GUIParentNode * getParentNode()
GUIScreenNode * screenNode
void setBackgroundImage(const string &backgroundImage)
Set background image.
GUIScreenNode * getScreenNode()
GUI panel node TODO: remove me!
GUI parent node base class thats supporting child nodes.
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.
const string & getApplicationRootPathName()
const string & getApplicationSubPathName()
const string allocateNodeId()
Allocate node id.
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
GUI styled text node controller.
File system singleton class.
Mutable utf8 aware string class.
Properties class, which helps out with storeing or loading key value pairs from/to property files.
void load(const string &pathName, const string &fileName, FileSystemInterface *fileSystem=nullptr)
Load property file.
An attribute is a name-value pair.
const TiXmlAttribute * Next() const
Get the next sibling attribute in the DOM. Returns null at end.
Always the top level node.
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.
const TiXmlElement * RootElement() const
Get the root element – the only top level element – of the document.
bool Error() const
If an error occurs, Error will be set to true.
The element is a container class.
const char * Attribute(const char *name) const
Given an attribute name, Attribute() returns the value for the attribute of that name,...
const char * GetText() const
Convenience function for easy access to the text inside an element.
const TiXmlAttribute * FirstAttribute() const
Access the first attribute in this element.
const char * Value() const
The meaning of 'value' changes for the specific type of TiXmlNode.
const TiXmlElement * NextSiblingElement() const
Convenience function to get through elements.
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
std::exception Exception
Exception base class.