Files
Nuake-custom/Nuake/src/UI/InterfaceParser.cpp
Antoine Pilote cdfee1981c Various improvements:
Framebuffer resize queued to next frame to fix flickering
Wren VM init moved to on play event
Added new Wren modules
Added missing components to the editor
Changed how the wren scripts gets initialized
2021-06-12 13:01:07 -04:00

282 lines
6.2 KiB
C++

#include "InterfaceParser.h"
#include "Styling/Stylesheet.h"
Ref<Canvas> InterfaceParser::Root = CreateRef<Canvas>();
void InterfaceParser::Iterate(const pugi::xml_node& xml_node, Ref<Node> node, int depth)
{
int currentDepth = depth + 1;
for (auto& e : xml_node.children())
{
std::string type = e.name();
Ref<Node> newNode;
if (type == "Canvas")
newNode = CreateCanvas(e);
else if (type == "Rect")
newNode = CreateNode(e);
else if (type == "p")
newNode = CreateTextNode(e);
else
continue;
newNode->Depth = currentDepth;
node->Childrens.push_back(newNode);
Iterate(e, newNode, currentDepth);
}
}
Ref<Canvas> InterfaceParser::Parse(const std::string path)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str());
std::string name = doc.first_child().name();
if (name != "Canvas")
{
Logger::Log("InterfaceParser error: First child should be a canvas - " + path);
return nullptr;
}
Root = CreateCanvas(doc.first_child());
Root->Depth = 0;
Iterate(doc.first_child(), Root, 0);
return Root;
}
Ref<TextNode> InterfaceParser::CreateTextNode(const pugi::xml_node& xml_node)
{
Ref<TextNode> node = CreateRef<TextNode>();
node->content = xml_node.text().as_string();
node->Type = NodeType::Text;
TextStyle style{
FontManager::GetFont("resources/Fonts/RobotoMono-Regular.ttf"),
2.0,
Color(255, 255, 255, 255)
};
node->SetTextStyle(style);
for (auto& a : xml_node.attributes())
{
std::string name = a.name();
if (name == "groups")
{
for (auto& g : split(a.value(), ' '))
{
node->AddGroup(g);
}
}
if (name == "height")
node->Height = GetUnit(a.value());
if (name == "width")
node->Width = GetUnit(a.value());
if (name == "margin")
node->Margin = GetVec4Unit(a.value());
if (name == "padding")
node->Padding = GetVec4Unit(a.value());
if (name == "border")
node->Border = GetVec4Unit(a.value());
if (name == "position")
node->Position = GetVec4Unit(a.value());
if (name == "color")
node->BackgroundColor = GetColor(a.value());
}
return node;
}
Ref<Node> InterfaceParser::CreateNode(const pugi::xml_node& xml_node)
{
Ref<Node> node = CreateRef<Node>();
node->Root = Root;
for (auto& a : xml_node.attributes())
{
std::string name = a.name();
if (name == "groups")
{
for (auto& g : split(a.value(), ' '))
{
node->AddGroup(g);
}
}
if (name == "height")
node->Height = GetUnit(a.value());
if (name == "width")
node->Width = GetUnit(a.value());
if (name == "margin")
node->Margin = GetVec4Unit(a.value());
if (name == "padding")
node->Padding = GetVec4Unit(a.value());
if (name == "border")
node->Border = GetVec4Unit(a.value());
if (name == "position")
node->Position = GetVec4Unit(a.value());
if (name == "color")
node->BackgroundColor = GetColor(a.value());
if (name == "onclick")
{
std::string signature = a.value();
Root->Script->RegisterMethod(a.value());
node->OnClickSignature = a.value();
}
}
return node;
}
Layout::LayoutUnit InterfaceParser::GetUnit(const std::string& value)
{
std::regex only_number("[0-9]+");
std::regex not_number("[^0-9]+");
// is percentage
std::smatch match_value;
if (std::regex_search(value.begin(), value.end(), match_value, only_number))
{
std::smatch match_type;
if (std::regex_search(value.begin(), value.end(), match_type, not_number))
{
float value = std::stof(match_value[0]);
if (match_type[0] == "%")
{
return Layout::LayoutUnit{
value,
Layout::Unit::PERCENT
};
}
else if (match_type[0] == "px")
{
return Layout::LayoutUnit{
value,
Layout::Unit::PIXEL
};
}
}
}
}
std::vector<std::string> InterfaceParser::split(std::string const& str, const char delim)
{
std::vector<std::string> result;
size_t start;
size_t end = 0;
while ((start = str.find_first_not_of(delim, end)) != std::string::npos)
{
end = str.find(delim, start);
result.push_back(str.substr(start, end - start));
}
return result;
}
Layout::LayoutVec4 InterfaceParser::GetVec4Unit(const std::string& value)
{
std::regex regex("[0-9]+[^ ]+");
std::smatch match_value;
Layout::LayoutVec4 result;
std::vector<std::string> splits = split(value, ' ');
int idx = 0;
for (auto& s : splits)
{
if (std::regex_search(value.begin(), value.end(), match_value, regex))
{
if (idx == 0)
{
result.Left = GetUnit(s);
}
else if (idx == 1)
{
result.Right = GetUnit(s);
}
else if (idx == 2)
{
result.Top = GetUnit(s);
}
else
{
result.Bottom = GetUnit(s);
}
idx++;
}
}
return result;
}
Color InterfaceParser::GetColor(const std::string& value)
{
std::regex regex("[0-9]+[^ ]+");
std::smatch match_value;
Color result;
std::vector<std::string> splits = split(value, ' ');
int idx = 0;
for (auto& s : splits)
{
if (std::regex_search(value.begin(), value.end(), match_value, regex))
{
if (idx == 0)
{
result.r = std::stof(s);
}
else if (idx == 1)
{
result.g = std::stof(s);
}
else if (idx == 2)
{
result.b = std::stof(s);
}
else
{
result.a = std::stof(s);
}
idx++;
}
}
return result;
}
Ref<Canvas> InterfaceParser::CreateCanvas(const pugi::xml_node& xml_node)
{
Ref<Canvas> node = CreateRef<Canvas>();
node->Root = Root;
for (auto& a : xml_node.attributes())
{
std::string name = a.name();
if (name == "groups")
{
for (auto& g : split(a.value(), ' '))
{
node->AddGroup(g);
}
}
if (name == "height")
node->Height = GetUnit(a.value());
if (name == "width")
node->Width = GetUnit(a.value());
if (name == "margin")
node->Margin = GetVec4Unit(a.value());
if (name == "padding")
node->Padding = GetVec4Unit(a.value());
if (name == "border")
node->Border = GetVec4Unit(a.value());
if (name == "position")
node->Position = GetVec4Unit(a.value());
if (name == "color")
node->BackgroundColor = GetColor(a.value());
if (name == "script")
{
auto s = split(a.value(), ' ');
std::string path = s[0];
std::string module = s[1];
node->Script = ScriptingEngine::RegisterScript(path, module);
}
if (name == "stylesheet")
{
std::string path = a.value();
node->StyleSheet = UI::StyleSheet::New(path);
}
}
return node;
}