diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index efc80081e3..96e64459db 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -256,7 +256,7 @@ add_component_dir (fallback add_component_dir (lua_ui registerscriptsettings scriptsettings properties widget element util layers content alignment resources - adapter text textedit window image container + adapter text textedit window image container flex ) diff --git a/components/lua_ui/alignment.cpp b/components/lua_ui/alignment.cpp index dfd09b752d..358c5ba14b 100644 --- a/components/lua_ui/alignment.cpp +++ b/components/lua_ui/alignment.cpp @@ -9,9 +9,9 @@ namespace LuaUi align |= MyGUI::Align::Left; if (horizontal == Alignment::End) align |= MyGUI::Align::Right; - if (horizontal == Alignment::Start) + if (vertical == Alignment::Start) align |= MyGUI::Align::Top; - if (horizontal == Alignment::End) + if (vertical == Alignment::End) align |= MyGUI::Align::Bottom; return align; } diff --git a/components/lua_ui/container.cpp b/components/lua_ui/container.cpp index 867378744b..11b9c1b360 100644 --- a/components/lua_ui/container.cpp +++ b/components/lua_ui/container.cpp @@ -29,7 +29,7 @@ namespace LuaUi size.width = std::max(size.width, coord.left + coord.width); size.height = std::max(size.height, coord.top + coord.height); } - setForcedSize(size); + forceSize(size); updateCoord(); } } diff --git a/components/lua_ui/element.cpp b/components/lua_ui/element.cpp index 47dd0a3d38..a939ccdc51 100644 --- a/components/lua_ui/element.cpp +++ b/components/lua_ui/element.cpp @@ -136,8 +136,8 @@ namespace LuaUi setTemplate(ext, layout.get(LayoutKeys::templateLayout)); ext->setProperties(layout.get(LayoutKeys::props)); setEventCallbacks(ext, layout.get(LayoutKeys::events)); - ext->setChildren(updateContent(ext->children(), layout.get(LayoutKeys::content))); + ext->updateCoord(); } std::string setLayer(WidgetExtension* ext, const sol::table& layout) diff --git a/components/lua_ui/flex.cpp b/components/lua_ui/flex.cpp new file mode 100644 index 0000000000..bbbf70cb98 --- /dev/null +++ b/components/lua_ui/flex.cpp @@ -0,0 +1,106 @@ +#include "flex.hpp" + +namespace LuaUi +{ + void LuaFlex::updateProperties() + { + mHorizontal = propertyValue("horizontal", false); + mAutoSized = propertyValue("autoSize", true); + mAlign = propertyValue("align", Alignment::Start); + mArrange = propertyValue("arrange", Alignment::Start); + WidgetExtension::updateProperties(); + } + + namespace + { + MyGUI::IntPoint alignSize(const MyGUI::IntSize& container, const MyGUI::IntSize& content, Alignment alignment) + { + MyGUI::IntPoint alignedPosition; + { + MyGUI::IntSize alignSize = container; + switch (alignment) + { + case Alignment::Start: + alignedPosition = MyGUI::IntPoint(0, 0); + break; + case Alignment::Center: + alignSize -= content; + alignedPosition = { alignSize.width / 2, alignSize.height / 2 }; + break; + case Alignment::End: + alignSize -= content; + alignedPosition = { alignSize.width, alignSize.height }; + break; + } + } + return alignedPosition; + } + } + + void LuaFlex::updateChildren() + { + float totalGrow = 0; + MyGUI::IntSize childrenSize; + for (auto* w: children()) + { + w->clearForced(); + childrenSize += w->calculateSize(); + totalGrow += w->externalValue("grow", 0.0f); + } + mChildrenSize = childrenSize; + + MyGUI::IntSize flexSize = calculateSize(); + MyGUI::IntSize growSize; + MyGUI::FloatSize growFactor; + if (totalGrow > 0) + { + growSize = flexSize - childrenSize; + growFactor = { growSize.width / totalGrow, growSize.height / totalGrow }; + } + if (mHorizontal) + flexSize.width -= growSize.width; + else + flexSize.height-= growSize.height; + + MyGUI::IntPoint alignedPosition = alignSize(flexSize, childrenSize, mAlign); + MyGUI::IntPoint arrangedPosition = alignSize(flexSize, childrenSize, mArrange); + MyGUI::IntPoint childPosition; + if (mHorizontal) + childPosition = { alignedPosition.left, arrangedPosition.top }; + else + childPosition = { arrangedPosition.left, alignedPosition.top }; + for (auto* w : children()) + { + w->forcePosition(childPosition); + float grow = w->externalValue("grow", 0); + MyGUI::IntSize growth(growFactor.width * grow, growFactor.height * grow); + if (mHorizontal) + { + int width = w->widget()->getWidth(); + width += growth.width; + w->forceSize({width, w->widget()->getHeight()}); + childPosition.left += width; + } + else + { + int height = w->widget()->getHeight(); + height += growth.height; + w->forceSize({ w->widget()->getWidth(), height }); + childPosition.top += height; + } + } + WidgetExtension::updateProperties(); + } + + MyGUI::IntSize LuaFlex::calculateSize() + { + MyGUI::IntSize size = WidgetExtension::calculateSize(); + if (mAutoSized) { + if (mHorizontal) + size.width = mChildrenSize.width; + else + size.height = mChildrenSize.height; + } + return size; + } +} diff --git a/components/lua_ui/flex.hpp b/components/lua_ui/flex.hpp new file mode 100644 index 0000000000..6cff6f0695 --- /dev/null +++ b/components/lua_ui/flex.hpp @@ -0,0 +1,27 @@ +#ifndef OPENMW_LUAUI_FLEX +#define OPENMW_LUAUI_FLEX + +#include "widget.hpp" +#include "alignment.hpp" + +namespace LuaUi +{ + class LuaFlex : public MyGUI::Widget, public WidgetExtension + { + MYGUI_RTTI_DERIVED(LuaFlex) + + protected: + MyGUI::IntSize calculateSize() override; + void updateProperties() override; + void updateChildren() override; + + private: + bool mHorizontal; + bool mAutoSized; + MyGUI::IntSize mChildrenSize; + Alignment mAlign; + Alignment mArrange; + }; +} + +#endif // OPENMW_LUAUI_FLEX diff --git a/components/lua_ui/util.cpp b/components/lua_ui/util.cpp index cd2cb2c077..d7e7390647 100644 --- a/components/lua_ui/util.cpp +++ b/components/lua_ui/util.cpp @@ -9,6 +9,7 @@ #include "window.hpp" #include "image.hpp" #include "container.hpp" +#include "flex.hpp" #include "element.hpp" #include "registerscriptsettings.hpp" @@ -24,8 +25,9 @@ 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"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); } const std::unordered_map& widgetTypeToName() @@ -36,6 +38,7 @@ namespace LuaUi { "LuaTextEdit", "TextEdit" }, { "LuaWindow", "Window" }, { "LuaImage", "Image" }, + { "LuaFlex", "Flex" }, }; return types; } diff --git a/components/lua_ui/widget.cpp b/components/lua_ui/widget.cpp index 74ac8640e0..87b1636d74 100644 --- a/components/lua_ui/widget.cpp +++ b/components/lua_ui/widget.cpp @@ -10,7 +10,9 @@ namespace LuaUi { WidgetExtension::WidgetExtension() - : mPropagateEvents(true) + : mForcePosition(false) + , mForceSize(false) + , mPropagateEvents(true) , mLua(nullptr) , mWidget(nullptr) , mSlot(this) @@ -85,7 +87,6 @@ namespace LuaUi ext->mParent = this; ext->mTemplateChild = false; ext->widget()->attachToWidget(mSlot->widget()); - ext->updateCoord(); } void WidgetExtension::attachTemplate(WidgetExtension* ext) @@ -93,7 +94,6 @@ namespace LuaUi ext->mParent = this; ext->mTemplateChild = true; ext->widget()->attachToWidget(widget()); - ext->updateCoord(); } WidgetExtension* WidgetExtension::findDeep(std::string_view flagName) @@ -219,16 +219,30 @@ namespace LuaUi return mForcedCoord; } - void WidgetExtension::setForcedCoord(const MyGUI::IntCoord& offset) + void WidgetExtension::forceCoord(const MyGUI::IntCoord& offset) { + mForcePosition = true; + mForceSize = true; mForcedCoord = offset; } - void WidgetExtension::setForcedSize(const MyGUI::IntSize& size) + void WidgetExtension::forcePosition(const MyGUI::IntPoint& pos) { + mForcePosition = true; + mForcedCoord = pos; + } + + void WidgetExtension::forceSize(const MyGUI::IntSize& size) + { + mForceSize = true; mForcedCoord = size; } + void WidgetExtension::clearForced() { + mForcePosition = false; + mForceSize = false; + } + void WidgetExtension::updateCoord() { MyGUI::IntCoord oldCoord = mWidget->getCoord(); @@ -246,7 +260,6 @@ namespace LuaUi { mProperties = props; updateProperties(); - updateCoord(); } void WidgetExtension::updateProperties() @@ -281,9 +294,12 @@ namespace LuaUi MyGUI::IntSize WidgetExtension::calculateSize() { + if (mForceSize) + return mForcedCoord.size(); + MyGUI::IntSize pSize = parentSize(); MyGUI::IntSize newSize; - newSize = mAbsoluteCoord.size() + mForcedCoord.size(); + newSize = mAbsoluteCoord.size(); newSize.width += mRelativeCoord.width * pSize.width; newSize.height += mRelativeCoord.height * pSize.height; return newSize; @@ -291,9 +307,11 @@ namespace LuaUi MyGUI::IntPoint WidgetExtension::calculatePosition(const MyGUI::IntSize& size) { + if (mForcePosition) + return mForcedCoord.point(); MyGUI::IntSize pSize = parentSize(); MyGUI::IntPoint newPosition; - newPosition = mAbsoluteCoord.point() + mForcedCoord.point(); + newPosition = mAbsoluteCoord.point(); newPosition.left += mRelativeCoord.left * pSize.width - mAnchor.width * size.width; newPosition.top += mRelativeCoord.top * pSize.height - mAnchor.height * size.height; return newPosition; diff --git a/components/lua_ui/widget.hpp b/components/lua_ui/widget.hpp index c712d18ccd..33bf52cd78 100644 --- a/components/lua_ui/widget.hpp +++ b/components/lua_ui/widget.hpp @@ -47,8 +47,11 @@ namespace LuaUi void setExternal(sol::object external) { mExternal = external; } MyGUI::IntCoord forcedCoord(); - void setForcedCoord(const MyGUI::IntCoord& offset); - void setForcedSize(const MyGUI::IntSize& size); + void forceCoord(const MyGUI::IntCoord& offset); + void forceSize(const MyGUI::IntSize& size); + void forcePosition(const MyGUI::IntPoint& pos); + void clearForced(); + void updateCoord(); const sol::table& getLayout() { return mLayout; } @@ -65,6 +68,9 @@ namespace LuaUi mOnCoordChange = callback; } + virtual MyGUI::IntSize calculateSize(); + virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size); + protected: virtual void initialize(); sol::table makeTable() const; @@ -72,8 +78,6 @@ namespace LuaUi 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(); @@ -113,6 +117,8 @@ namespace LuaUi } } + bool mForcePosition; + bool mForceSize; // offsets the position and size, used only in C++ widget code MyGUI::IntCoord mForcedCoord; // position and size in pixels diff --git a/components/lua_ui/window.cpp b/components/lua_ui/window.cpp index 41281208d4..a9fff5ff47 100644 --- a/components/lua_ui/window.cpp +++ b/components/lua_ui/window.cpp @@ -39,8 +39,7 @@ namespace LuaUi if (mCaption) mCaption->setCaption(propertyValue("caption", std::string())); mMoveResize = MyGUI::IntCoord(); - setForcedCoord(mMoveResize); - + clearForced(); WidgetExtension::updateProperties(); } @@ -70,11 +69,8 @@ namespace LuaUi change.width *= (left - mPreviousMouse.left); change.height *= (top - mPreviousMouse.top); - mMoveResize = mMoveResize + change.size(); - setForcedCoord(mMoveResize); - // position can change based on size changes - mMoveResize = mMoveResize + change.point() + getPosition() - calculateCoord().point(); - setForcedCoord(mMoveResize); + mMoveResize = mMoveResize + change; + forceCoord(mMoveResize); updateCoord(); mPreviousMouse.left = left;