mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 08:56:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			151 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
	
		
			4.8 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)
 | |
|     {
 | |
|         auto props = layout.get<sol::optional<sol::table>>("props");
 | |
|         if (props.has_value())
 | |
|         {
 | |
|             props.value().for_each([ext](const sol::object& key, const sol::object& value)
 | |
|                 {
 | |
|                     if (key.is<std::string_view>())
 | |
|                         ext->setProperty(key.as<std::string_view>(), value);
 | |
|                     else
 | |
|                         Log(Debug::Warning) << "UI property key must be a string";
 | |
|                 });
 | |
|             ext->updateCoord();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     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";
 | |
|                 });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     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);
 | |
| 
 | |
|         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);
 | |
| 
 | |
|         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;
 | |
|     }
 | |
| }
 |