#include "gui_xml.h" #include #include #include "elements/containers.h" #include "elements/controls.h" #include "../../frontend/locale/langs.h" #include "../../logic/scripting/scripting.h" #include "../../logic/scripting/Environment.h" #include "../../util/stringutil.h" using namespace gui; static Align align_from_string(const std::string& str, Align def) { if (str == "left") return Align::left; if (str == "center") return Align::center; if (str == "right") return Align::right; if (str == "top") return Align::top; if (str == "bottom") return Align::bottom; return def; } static Gravity gravity_from_string(const std::string& str) { static const std::unordered_map gravity_names { {"top-left", Gravity::top_left}, {"top-center", Gravity::top_center}, {"top-right", Gravity::top_right}, {"center-left", Gravity::center_left}, {"center-center", Gravity::center_center}, {"center-right", Gravity::center_right}, {"bottom-left", Gravity::bottom_left}, {"bottom-center", Gravity::bottom_center}, {"bottom-right", Gravity::bottom_right}, }; auto found = gravity_names.find(str); if (found == gravity_names.end()) { return found->second; } return Gravity::none; } /* Read basic UINode properties */ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& node) { if (element->has("id")) { node.setId(element->attr("id").getText()); } if (element->has("pos")) { node.setPos(element->attr("pos").asVec2()); } if (element->has("size")) { node.setSize(element->attr("size").asVec2()); } if (element->has("color")) { glm::vec4 color = element->attr("color").asColor(); glm::vec4 hoverColor = color; glm::vec4 pressedColor = color; if (element->has("hover-color")) { hoverColor = node.getHoverColor(); } if (element->has("pressed-color")) { pressedColor = node.getPressedColor(); } node.setColor(color); node.setHoverColor(hoverColor); node.setPressedColor(pressedColor); } if (element->has("margin")) { node.setMargin(element->attr("margin").asVec4()); } if (element->has("z-index")) { node.setZIndex(element->attr("z-index").asInt()); } if (element->has("interactive")) { node.setInteractive(element->attr("interactive").asBool()); } if (element->has("visible")) { node.setVisible(element->attr("visible").asBool()); } if (element->has("position-func")) { auto supplier = scripting::create_vec2_supplier( reader.getEnvironment().getId(), element->attr("position-func").getText(), reader.getFilename()+".lua" ); node.setPositionFunc(supplier); } if (element->has("hover-color")) { node.setHoverColor(element->attr("hover-color").asColor()); } if (element->has("pressed-color")) { node.setPressedColor(element->attr("pressed-color").asColor()); } std::string alignName = element->attr("align", "").getText(); node.setAlign(align_from_string(alignName, node.getAlign())); if (element->has("gravity")) { node.setGravity(gravity_from_string( element->attr("gravity").getText() )); } if (element->has("onclick")) { auto callback = scripting::create_runnable( reader.getEnvironment().getId(), element->attr("onclick").getText(), reader.getFilename() ); node.listenAction([callback](GUI*) { callback(); }); } } static void _readContainer(UiXmlReader& reader, xml::xmlelement element, Container& container) { _readUINode(reader, element, container); if (element->has("scrollable")) { container.setScrollable(element->attr("scrollable").asBool()); } for (auto& sub : element->getElements()) { if (sub->isText()) continue; auto subnode = reader.readUINode(sub); if (subnode) { container.add(subnode); } } } void UiXmlReader::readUINode(UiXmlReader& reader, xml::xmlelement element, Container& container) { _readContainer(reader, element, container); } void UiXmlReader::readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& node) { _readUINode(reader, element, node); } static void _readPanel(UiXmlReader& reader, xml::xmlelement element, Panel& panel, bool subnodes=true) { _readUINode(reader, element, panel); if (element->has("padding")) { glm::vec4 padding = element->attr("padding").asVec4(); panel.setPadding(padding); glm::vec2 size = panel.getSize(); panel.setSize(glm::vec2( size.x + padding.x + padding.z, size.y + padding.y + padding.w )); } if (element->has("size")) { panel.setResizing(false); } if (element->has("max-length")) { panel.setMaxLength(element->attr("max-length").asInt()); } if (element->has("orientation")) { auto oname = element->attr("orientation").getText(); if (oname == "horizontal") { panel.setOrientation(Orientation::horizontal); } } if (subnodes) { for (auto& sub : element->getElements()) { if (sub->isText()) continue; auto subnode = reader.readUINode(sub); if (subnode) { panel.add(subnode); } } } } static std::wstring readAndProcessInnerText(xml::xmlelement element, const std::string& context) { std::wstring text = L""; if (element->size() == 1) { std::string source = element->sub(0)->attr("#").getText(); util::trim(source); text = util::str2wstr_utf8(source); if (text[0] == '@') { if (context.empty()) { text = langs::get(text.substr(1)); } else { text = langs::get(text.substr(1), util::str2wstr_utf8(context)); } } } return text; } static std::shared_ptr readLabel(UiXmlReader& reader, xml::xmlelement element) { std::wstring text = readAndProcessInnerText(element, reader.getContext()); auto label = std::make_shared