diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 58e6d52ead..3ca08c4b7b 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -166,7 +166,7 @@ add_component_dir (queries add_component_dir (lua_ui properties widget element util layers content scriptsettings - adapter text textedit window image + adapter text textedit window image container ) diff --git a/components/lua_ui/adapter.cpp b/components/lua_ui/adapter.cpp index 9a109d5d1f..9d37e2cb1a 100644 --- a/components/lua_ui/adapter.cpp +++ b/components/lua_ui/adapter.cpp @@ -3,6 +3,7 @@ #include #include "element.hpp" +#include "container.hpp" namespace LuaUi { @@ -15,18 +16,12 @@ namespace LuaUi : mElement(nullptr) , mContent(nullptr) { - MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT( - "LuaWidget", "", - MyGUI::IntCoord(), MyGUI::Align::Default, - std::string(), ""); - - mContent = dynamic_cast(widget); - if (!mContent) - throw std::runtime_error("Invalid widget!"); - mContent->initialize(luaState, widget); - mContent->onSizeChange([this](MyGUI::IntSize size) + mContent = MyGUI::Gui::getInstancePtr()->createWidget( + "", MyGUI::IntCoord(), MyGUI::Align::Default, "", ""); + mContent->initialize(luaState, mContent); + mContent->onCoordChange([this](WidgetExtension* ext, MyGUI::IntCoord coord) { - setSize(size); + setSize(coord.size()); }); mContent->widget()->attachToWidget(this); } diff --git a/components/lua_ui/adapter.hpp b/components/lua_ui/adapter.hpp index 2ff206464d..e18f04c1f9 100644 --- a/components/lua_ui/adapter.hpp +++ b/components/lua_ui/adapter.hpp @@ -5,7 +5,7 @@ namespace LuaUi { - class WidgetExtension; + class LuaContainer; struct Element; class LuaAdapter : public MyGUI::Widget { @@ -19,7 +19,7 @@ namespace LuaUi bool empty() { return mElement.get() == nullptr; } private: - WidgetExtension* mContent; + LuaContainer* mContent; std::shared_ptr mElement; void attachElement(); void detachElement(); diff --git a/components/lua_ui/container.cpp b/components/lua_ui/container.cpp new file mode 100644 index 0000000000..867378744b --- /dev/null +++ b/components/lua_ui/container.cpp @@ -0,0 +1,35 @@ +#include "container.hpp" + +#include + +namespace LuaUi +{ + void LuaContainer::updateChildren() + { + WidgetExtension::updateChildren(); + for (auto w : children()) + { + w->onCoordChange([this](WidgetExtension* child, MyGUI::IntCoord coord) + { updateSizeToFit(); }); + } + updateSizeToFit(); + } + + MyGUI::IntSize LuaContainer::childScalingSize() + { + return MyGUI::IntSize(); + } + + void LuaContainer::updateSizeToFit() + { + MyGUI::IntSize size; + for (auto w : children()) + { + MyGUI::IntCoord coord = w->widget()->getCoord(); + size.width = std::max(size.width, coord.left + coord.width); + size.height = std::max(size.height, coord.top + coord.height); + } + setForcedSize(size); + updateCoord(); + } +} diff --git a/components/lua_ui/container.hpp b/components/lua_ui/container.hpp new file mode 100644 index 0000000000..a005b7ae53 --- /dev/null +++ b/components/lua_ui/container.hpp @@ -0,0 +1,21 @@ +#ifndef OPENMW_LUAUI_CONTAINER +#define OPENMW_LUAUI_CONTAINER + +#include "widget.hpp" + +namespace LuaUi +{ + class LuaContainer : public WidgetExtension, public MyGUI::Widget + { + MYGUI_RTTI_DERIVED(LuaContainer) + + protected: + virtual void updateChildren() override; + virtual MyGUI::IntSize childScalingSize() override; + + private: + void updateSizeToFit(); + }; +} + +#endif // !OPENMW_LUAUI_CONTAINER diff --git a/components/lua_ui/element.cpp b/components/lua_ui/element.cpp index 9baec82269..59a3b13d55 100644 --- a/components/lua_ui/element.cpp +++ b/components/lua_ui/element.cpp @@ -221,10 +221,7 @@ namespace LuaUi void Element::detachFromWidget() { if (mRoot) - { - mRoot->onSizeChange({}); mRoot->widget()->detachFromWidget(); - } if (mAttachedTo) mAttachedTo->setChildren({}); mAttachedTo = nullptr; @@ -239,16 +236,7 @@ namespace LuaUi if (!mLayer.empty()) Log(Debug::Warning) << "Ignoring element's layer " << mLayer << " because it's attached to a widget"; mAttachedTo->setChildren({ mRoot }); - auto callback = [this](MyGUI::IntSize size) - { - if (!mAttachedTo) - return; - mAttachedTo->setForcedSize(mRoot->widget()->getSize()); - mAttachedTo->updateCoord(); - }; - mRoot->onSizeChange(callback); mRoot->updateCoord(); - callback(mRoot->widget()->getSize()); } } } diff --git a/components/lua_ui/util.cpp b/components/lua_ui/util.cpp index 24a1442a53..7e81fc579c 100644 --- a/components/lua_ui/util.cpp +++ b/components/lua_ui/util.cpp @@ -8,6 +8,7 @@ #include "textedit.hpp" #include "window.hpp" #include "image.hpp" +#include "container.hpp" #include "element.hpp" #include "scriptsettings.hpp" @@ -23,6 +24,7 @@ namespace LuaUi MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("BasisSkin"); } @@ -34,6 +36,7 @@ namespace LuaUi { "LuaTextEdit", "TextEdit" }, { "LuaWindow", "Window" }, { "LuaImage", "Image" }, + { "LuaContainer", "Container" }, }; return types; } diff --git a/components/lua_ui/widget.cpp b/components/lua_ui/widget.cpp index 4224598ca1..b021c688fa 100644 --- a/components/lua_ui/widget.cpp +++ b/components/lua_ui/widget.cpp @@ -14,10 +14,11 @@ namespace LuaUi , mAbsoluteCoord() , mRelativeCoord() , mAnchor() - , mLua{ nullptr } - , mWidget{ nullptr } + , mLua(nullptr) + , mWidget(nullptr) , mSlot(this) - , mLayout{ sol::nil } + , mParent(nullptr) + , mLayout(sol::nil) {} void WidgetExtension::initialize(lua_State* lua, MyGUI::Widget* self) @@ -64,6 +65,8 @@ namespace LuaUi mWidget->eventKeySetFocus.clear(); mWidget->eventKeyLostFocus.clear(); + mOnSizeChange.reset(); + for (WidgetExtension* w : mChildren) w->deinitialize(); for (WidgetExtension* w : mTemplateChildren) @@ -72,6 +75,7 @@ namespace LuaUi void WidgetExtension::attach(WidgetExtension* ext) { + ext->mParent = this; ext->widget()->attachToWidget(mSlot->widget()); ext->updateCoord(); } @@ -150,6 +154,7 @@ namespace LuaUi mChildren[i] = children[i]; attach(mChildren[i]); } + updateChildren(); } void WidgetExtension::setTemplateChildren(const std::vector& children) @@ -212,6 +217,8 @@ namespace LuaUi if (mOnSizeChange.has_value()) mOnSizeChange.value()(newCoord.size()); } + if (oldCoord != newCoord && mOnCoordChange.has_value()) + mOnCoordChange.value()(this, newCoord); } void WidgetExtension::setProperties(sol::object props) @@ -240,23 +247,31 @@ namespace LuaUi w->updateCoord(); } + MyGUI::IntSize WidgetExtension::parentSize() + { + if (mParent) + return mParent->childScalingSize(); + else + return widget()->getParentSize(); + } + MyGUI::IntSize WidgetExtension::calculateSize() { - const MyGUI::IntSize& parentSize = mWidget->getParentSize(); + MyGUI::IntSize pSize = parentSize(); MyGUI::IntSize newSize; newSize = mAbsoluteCoord.size() + mForcedCoord.size(); - newSize.width += mRelativeCoord.width * parentSize.width; - newSize.height += mRelativeCoord.height * parentSize.height; + newSize.width += mRelativeCoord.width * pSize.width; + newSize.height += mRelativeCoord.height * pSize.height; return newSize; } MyGUI::IntPoint WidgetExtension::calculatePosition(const MyGUI::IntSize& size) { - const MyGUI::IntSize& parentSize = mWidget->getParentSize(); + MyGUI::IntSize pSize = parentSize(); MyGUI::IntPoint newPosition; newPosition = mAbsoluteCoord.point() + mForcedCoord.point(); - newPosition.left += mRelativeCoord.left * parentSize.width - mAnchor.width * size.width; - newPosition.top += mRelativeCoord.top * parentSize.height - mAnchor.height * size.height; + newPosition.left += mRelativeCoord.left * pSize.width - mAnchor.width * size.width; + newPosition.top += mRelativeCoord.top * pSize.height - mAnchor.height * size.height; return newPosition; } @@ -268,6 +283,11 @@ namespace LuaUi return newCoord; } + MyGUI::IntSize WidgetExtension::childScalingSize() + { + return widget()->getSize(); + } + void WidgetExtension::triggerEvent(std::string_view name, const sol::object& argument = sol::nil) const { auto it = mCallbacks.find(name); diff --git a/components/lua_ui/widget.hpp b/components/lua_ui/widget.hpp index 1eff2a113b..a5adb33130 100644 --- a/components/lua_ui/widget.hpp +++ b/components/lua_ui/widget.hpp @@ -57,6 +57,11 @@ namespace LuaUi return parseExternal(mExternal, name, defaultValue); } + void onCoordChange(const std::optional>& callback) + { + mOnCoordChange = callback; + } + void onSizeChange(const std::optional>& callback) { mOnSizeChange = callback; @@ -68,9 +73,11 @@ namespace LuaUi sol::object keyEvent(MyGUI::KeyCode) const; sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const; + MyGUI::IntSize parentSize(); virtual MyGUI::IntSize calculateSize(); virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size); MyGUI::IntCoord calculateCoord(); + virtual MyGUI::IntSize childScalingSize(); template T propertyValue(std::string_view name, const T& defaultValue) @@ -83,6 +90,7 @@ namespace LuaUi virtual void updateTemplate(); virtual void updateProperties(); + virtual void updateChildren() {}; void triggerEvent(std::string_view name, const sol::object& argument) const; @@ -108,6 +116,7 @@ namespace LuaUi sol::object mProperties; sol::object mTemplateProperties; sol::object mExternal; + WidgetExtension* mParent; void attach(WidgetExtension* ext); @@ -127,6 +136,7 @@ namespace LuaUi void focusGain(MyGUI::Widget*, MyGUI::Widget*); void focusLoss(MyGUI::Widget*, MyGUI::Widget*); + std::optional> mOnCoordChange; std::optional> mOnSizeChange; };