mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-11 00:39:59 +00:00
148 lines
4.5 KiB
C++
148 lines
4.5 KiB
C++
#include "element.hpp"
|
|
|
|
#include <MyGUI_Gui.h>
|
|
|
|
#include "content.hpp"
|
|
#include "widgetlist.hpp"
|
|
|
|
namespace LuaUi
|
|
{
|
|
|
|
std::string widgetType(const sol::table& layout)
|
|
{
|
|
return layout.get_or("type", std::string("LuaWidget"));
|
|
}
|
|
|
|
Content content(const sol::table& layout)
|
|
{
|
|
auto optional = layout.get<sol::optional<Content>>("content");
|
|
if (optional.has_value())
|
|
return optional.value();
|
|
else
|
|
return Content();
|
|
}
|
|
|
|
void setProperties(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
{
|
|
ext->setProperties(layout.get<sol::object>("props"));
|
|
}
|
|
|
|
void setEventCallbacks(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
{
|
|
ext->clearCallbacks();
|
|
auto events = layout.get<sol::optional<sol::table>>("events");
|
|
if (events.has_value())
|
|
{
|
|
events.value().for_each([ext](const sol::object& name, const sol::object& callback)
|
|
{
|
|
if (name.is<std::string>() && callback.is<LuaUtil::Callback>())
|
|
ext->setCallback(name.as<std::string>(), callback.as<LuaUtil::Callback>());
|
|
else if (!name.is<std::string>())
|
|
Log(Debug::Warning) << "UI event key must be a string";
|
|
else if (!callback.is<LuaUtil::Callback>())
|
|
Log(Debug::Warning) << "UI event handler for key \"" << name.as<std::string>()
|
|
<< "\" must be an openmw.async.callback";
|
|
});
|
|
}
|
|
}
|
|
|
|
void setLayout(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
{
|
|
ext->setLayout(layout);
|
|
}
|
|
|
|
LuaUi::WidgetExtension* createWidget(const sol::table& layout, LuaUi::WidgetExtension* parent)
|
|
{
|
|
std::string type = widgetType(layout);
|
|
std::string skin = layout.get_or("skin", std::string());
|
|
std::string layer = layout.get_or("layer", std::string("Windows"));
|
|
std::string name = layout.get_or("name", std::string());
|
|
|
|
static auto widgetTypeMap = widgetTypeToName();
|
|
if (widgetTypeMap.find(type) == widgetTypeMap.end())
|
|
throw std::logic_error(std::string("Invalid widget type ") += type);
|
|
|
|
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT(
|
|
type, skin,
|
|
MyGUI::IntCoord(), MyGUI::Align::Default,
|
|
layer, name);
|
|
|
|
LuaUi::WidgetExtension* ext = dynamic_cast<LuaUi::WidgetExtension*>(widget);
|
|
if (!ext)
|
|
throw std::runtime_error("Invalid widget!");
|
|
|
|
ext->create(layout.lua_state(), widget);
|
|
if (parent != nullptr)
|
|
widget->attachToWidget(parent->widget());
|
|
|
|
setEventCallbacks(ext, layout);
|
|
setProperties(ext, layout);
|
|
setLayout(ext, layout);
|
|
|
|
Content cont = content(layout);
|
|
for (size_t i = 0; i < cont.size(); i++)
|
|
ext->addChild(createWidget(cont.at(i), ext));
|
|
|
|
return ext;
|
|
}
|
|
|
|
void destroyWidget(LuaUi::WidgetExtension* ext)
|
|
{
|
|
ext->destroy();
|
|
MyGUI::Gui::getInstancePtr()->destroyWidget(ext->widget());
|
|
}
|
|
|
|
void updateWidget(const sol::table& layout, LuaUi::WidgetExtension* ext)
|
|
{
|
|
setEventCallbacks(ext, layout);
|
|
setProperties(ext, layout);
|
|
setLayout(ext, layout);
|
|
|
|
Content newContent = content(layout);
|
|
|
|
size_t oldSize = ext->childCount();
|
|
size_t newSize = newContent.size();
|
|
size_t minSize = std::min(oldSize, newSize);
|
|
for (size_t i = 0; i < minSize; i++)
|
|
{
|
|
LuaUi::WidgetExtension* oldWidget = ext->childAt(i);
|
|
sol::table newChild = newContent.at(i);
|
|
|
|
if (oldWidget->widget()->getTypeName() != widgetType(newChild))
|
|
{
|
|
destroyWidget(oldWidget);
|
|
ext->assignChild(i, createWidget(newChild, ext));
|
|
}
|
|
else
|
|
updateWidget(newChild, oldWidget);
|
|
}
|
|
|
|
for (size_t i = minSize; i < oldSize; i++)
|
|
destroyWidget(ext->eraseChild(i));
|
|
|
|
for (size_t i = minSize; i < newSize; i++)
|
|
ext->addChild(createWidget(newContent.at(i), ext));
|
|
}
|
|
|
|
void Element::create()
|
|
{
|
|
assert(!mRoot);
|
|
if (!mRoot)
|
|
mRoot = createWidget(mLayout, nullptr);
|
|
}
|
|
|
|
void Element::update()
|
|
{
|
|
if (mRoot && mUpdate)
|
|
updateWidget(mLayout, mRoot);
|
|
mUpdate = false;
|
|
}
|
|
|
|
void Element::destroy()
|
|
{
|
|
if (mRoot)
|
|
destroyWidget(mRoot);
|
|
mRoot = nullptr;
|
|
}
|
|
}
|