133 lines
3.2 KiB
C++
133 lines
3.2 KiB
C++
#include "pch.h"
|
|
#include "log.h"
|
|
#include "layout.h"
|
|
#include "util.h"
|
|
#include "asset.h"
|
|
#include "node.h"
|
|
#include "node_border.h"
|
|
|
|
void LayoutManager::unload()
|
|
{
|
|
for (auto& l : m_layouts)
|
|
l.second->destroy_immediate();
|
|
m_layouts.clear();
|
|
}
|
|
|
|
void LayoutManager::create()
|
|
{
|
|
m_layouts[const_hash("main")] = std::make_unique<Node>();
|
|
}
|
|
|
|
bool LayoutManager::load(const char* path)
|
|
{
|
|
auto abs_path = Asset::absolute(path);
|
|
#if _WIN32 || __OSX__
|
|
struct stat tmp_info;
|
|
if (stat(abs_path.c_str(), &tmp_info) != 0)
|
|
return false;
|
|
if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
|
return false;
|
|
m_file_info = tmp_info;
|
|
#else
|
|
if (m_loaded)
|
|
return true; // already loaded
|
|
#endif // __ANDROID__
|
|
|
|
if (!m_layouts.empty() && on_reloading)
|
|
on_reloading();
|
|
|
|
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;
|
|
LOG("parsing xml failed");
|
|
}
|
|
|
|
LOG("parsing loaded xml");
|
|
|
|
tinyxml2::XMLElement* current = xml.RootElement()->FirstChildElement();
|
|
while (current)
|
|
{
|
|
auto id_str = current->Attribute("id");
|
|
if (!id_str)
|
|
{
|
|
LOG("Layout node without id");
|
|
return false;
|
|
}
|
|
if (auto os = current->Attribute("os"))
|
|
{
|
|
auto osv = split(os, ',');
|
|
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
|
|
{
|
|
LOG("Layout %s not for this os(%s), skipping", id_str, PP_OS)
|
|
current = current->NextSiblingElement("layout");
|
|
continue;
|
|
}
|
|
}
|
|
//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();
|
|
}
|