#include "pch.h" #include "log.h" #include "layout.h" #include "util.h" #include "asset.h" #include "node.h" #include "node_border.h" bool LayoutManager::load(const char* path) { // if (m_loaded) // return true; // already loaded #if !defined(__ANDROID__) struct stat tmp_info; if (stat(path, &tmp_info) != 0) return false; if (tmp_info.st_mtime <= m_file_info.st_mtime) return false; m_file_info = tmp_info; #endif // __ANDROID__ m_path = path; auto old = std::move(m_layouts); Asset file; if (!(file.open(path) && file.read_all())) return false; tinyxml2::XMLDocument xml; auto ret = xml.Parse((char*)file.m_data, file.m_len); file.close(); if (ret != tinyxml2::XMLError::XML_SUCCESS) return false; tinyxml2::XMLElement* current = xml.RootElement()->FirstChildElement(); while (current) { auto id_str = current->Attribute("id"); if (!id_str) { LOG("Layout node without id"); return false; } LOG("Parsing layout: %s", id_str); uint16_t id = const_hash(id_str); auto p = m_layouts.find(id); if (p == m_layouts.end()) { auto& node = m_layouts[id]; kWidget node_id = (kWidget)const_hash(current->Name()); switch (node_id) { case kWidget::Border: node.reset(new NodeBorder()); break; default: node.reset(new Node()); break; } node->m_manager = this; // try to copy the old size values if (old.count(id)) { const auto& old_node = *old[id]; YGNodeCopyStyle(node->y_node, old_node.y_node); } node->load_internal(current); } else { LOG("Layout id \"%s\" duplicated", id_str); } current = current->NextSiblingElement("layout"); } if (on_loaded) on_loaded(); m_loaded = true; return true; } bool LayoutManager::reload() { // avoid conflict when assigning the same string from c_str std::string path_copy = m_path; return load(path_copy.c_str()); } void LayoutManager::restore_context() { for (auto& node : m_layouts) node.second->restore_context(); } void LayoutManager::clear_context() { for (auto& node : m_layouts) node.second->clear_context(); }