diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 56371a8c02..3ea44f1f11 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -162,7 +162,8 @@ add_component_dir (queries ) add_component_dir (lua_ui - widget widgetlist element content text textedit window + widget widgetlist element content + text textedit window ) diff --git a/components/lua_ui/element.cpp b/components/lua_ui/element.cpp index 258da5269f..1a1b38e4dc 100644 --- a/components/lua_ui/element.cpp +++ b/components/lua_ui/element.cpp @@ -24,18 +24,7 @@ namespace LuaUi void setProperties(LuaUi::WidgetExtension* ext, const sol::table& layout) { - auto props = layout.get>("props"); - if (props.has_value()) - { - props.value().for_each([ext](const sol::object& key, const sol::object& value) - { - if (key.is()) - ext->setProperty(key.as(), value); - else - Log(Debug::Warning) << "UI property key must be a string"; - }); - ext->updateCoord(); - } + ext->setProperties(layout.get("props")); } void setEventCallbacks(LuaUi::WidgetExtension* ext, const sol::table& layout) diff --git a/components/lua_ui/properties.hpp b/components/lua_ui/properties.hpp new file mode 100644 index 0000000000..7f23a5ce6c --- /dev/null +++ b/components/lua_ui/properties.hpp @@ -0,0 +1,64 @@ +#ifndef OPENMW_LUAUI_PROPERTIES +#define OPENMW_LUAUI_PROPERTIES + +#include +#include +#include + +#include + +namespace LuaUi +{ + template + sol::optional getProperty(sol::object from, std::string_view field) { + sol::object value = LuaUtil::getFieldOrNil(from, field); + if (value == sol::nil) + return sol::nullopt; + if (value.is()) + return value.as(); + std::string error("Property \""); + error += field; + error += "\" has an invalid value \""; + error += LuaUtil::toString(value); + error += "\""; + throw std::logic_error(error); + } + + template + T parseProperty(sol::object from, std::string_view field, const T& defaultValue) + { + sol::optional opt = getProperty(from, field); + if (opt.has_value()) + return opt.value(); + else + return defaultValue; + } + + template + MyGUI::types::TPoint parseProperty( + sol::object from, + std::string_view field, + const MyGUI::types::TPoint& defaultValue) + { + auto v = getProperty(from, field); + if (v.has_value()) + return MyGUI::types::TPoint(v.value().x(), v.value().y()); + else + return defaultValue; + } + + template + MyGUI::types::TSize parseProperty( + sol::object from, + std::string_view field, + const MyGUI::types::TSize& defaultValue) + { + auto v = getProperty(from, field); + if (v.has_value()) + return MyGUI::types::TSize(v.value().x(), v.value().y()); + else + return defaultValue; + } +} + +#endif // !OPENMW_LUAUI_PROPERTIES diff --git a/components/lua_ui/text.cpp b/components/lua_ui/text.cpp index 571bdaf403..4ae9865ac3 100644 --- a/components/lua_ui/text.cpp +++ b/components/lua_ui/text.cpp @@ -12,25 +12,11 @@ namespace LuaUi WidgetExtension::initialize(); } - bool LuaText::setPropertyRaw(std::string_view name, sol::object value) + void LuaText::setProperties(sol::object props) { - if (name == "caption") - { - if (!value.is()) - return false; - setCaption(value.as()); - } - else if (name == "autoSize") - { - if (!value.is()) - return false; - mAutoSized = value.as(); - } - else - { - return WidgetExtension::setPropertyRaw(name, value); - } - return true; + setCaption(parseProperty(props, "caption", std::string())); + mAutoSized = parseProperty(props, "autoSize", true); + WidgetExtension::setProperties(props); } MyGUI::IntSize LuaText::calculateSize() diff --git a/components/lua_ui/text.hpp b/components/lua_ui/text.hpp index 90a3fc563c..d87a9001a2 100644 --- a/components/lua_ui/text.hpp +++ b/components/lua_ui/text.hpp @@ -14,13 +14,13 @@ namespace LuaUi public: LuaText(); virtual void initialize() override; + virtual void setProperties(sol::object) override; private: bool mAutoSized; protected: virtual MyGUI::IntSize calculateSize() override; - bool setPropertyRaw(std::string_view name, sol::object value) override; }; } diff --git a/components/lua_ui/textedit.cpp b/components/lua_ui/textedit.cpp index 2324a770c2..9cdc716ce4 100644 --- a/components/lua_ui/textedit.cpp +++ b/components/lua_ui/textedit.cpp @@ -2,18 +2,9 @@ namespace LuaUi { - bool LuaTextEdit::setPropertyRaw(std::string_view name, sol::object value) + void LuaTextEdit::setProperties(sol::object props) { - if (name == "caption") - { - if (!value.is()) - return false; - setCaption(value.as()); - } - else - { - return WidgetExtension::setPropertyRaw(name, value); - } - return true; + setCaption(parseProperty(props, "caption", std::string())); + WidgetExtension::setProperties(props); } } diff --git a/components/lua_ui/textedit.hpp b/components/lua_ui/textedit.hpp index 3eb5b471c3..d14f54d659 100644 --- a/components/lua_ui/textedit.hpp +++ b/components/lua_ui/textedit.hpp @@ -11,8 +11,7 @@ namespace LuaUi { MYGUI_RTTI_DERIVED(LuaTextEdit) - protected: - bool setPropertyRaw(std::string_view name, sol::object value) override; + virtual void setProperties(sol::object) override; }; } diff --git a/components/lua_ui/widget.cpp b/components/lua_ui/widget.cpp index 3ce07273f8..ef876e8a06 100644 --- a/components/lua_ui/widget.cpp +++ b/components/lua_ui/widget.cpp @@ -142,19 +142,12 @@ namespace LuaUi mCallbacks.clear(); } - void WidgetExtension::setProperty(std::string_view name, sol::object value) - { - if (!setPropertyRaw(name, value)) - Log(Debug::Error) << "Invalid value of property " << name - << ": " << LuaUtil::toString(value); - } - - MyGUI::IntCoord WidgetExtension::forcedOffset() + MyGUI::IntCoord WidgetExtension::forcedCoord() { return mForcedCoord; } - void WidgetExtension::setForcedOffset(const MyGUI::IntCoord& offset) + void WidgetExtension::setForcedCoord(const MyGUI::IntCoord& offset) { mForcedCoord = offset; } @@ -164,55 +157,16 @@ namespace LuaUi mWidget->setCoord(calculateCoord()); } - bool WidgetExtension::setPropertyRaw(std::string_view name, sol::object value) + void WidgetExtension::setProperties(sol::object props) { - if (name == "position") - { - if (!value.is()) - return false; - auto v = value.as(); - mAbsoluteCoord.left = v.x(); - mAbsoluteCoord.top = v.y(); - } - else if (name == "size") - { - if (!value.is()) - return false; - auto v = value.as(); - mAbsoluteCoord.width = v.x(); - mAbsoluteCoord.height = v.y(); - } - else if (name == "relativePosition") - { - if (!value.is()) - return false; - auto v = value.as(); - mRelativeCoord.left = v.x(); - mRelativeCoord.top = v.y(); - } - else if (name == "relativeSize") - { - if (!value.is()) - return false; - auto v = value.as(); - mRelativeCoord.width = v.x(); - mRelativeCoord.height = v.y(); - } - else if (name == "anchor") - { - if (!value.is()) - return false; - auto v = value.as(); - mAnchor.width = v.x(); - mAnchor.height = v.y(); - } - else if (name == "visible") - { - if (!value.is()) - return false; - mWidget->setVisible(value.as()); - } - return true; + mAbsoluteCoord = parseProperty(props, "position", MyGUI::IntPoint()); + mAbsoluteCoord = parseProperty(props, "size", MyGUI::IntSize()); + mRelativeCoord = parseProperty(props, "relativePosition", MyGUI::FloatPoint()); + mRelativeCoord = parseProperty(props, "relativeSize", MyGUI::FloatSize()); + mAnchor = parseProperty(props, "anchor", MyGUI::FloatSize()); + mWidget->setVisible(parseProperty(props, "visible", true)); + + updateCoord(); } void WidgetExtension::updateChildrenCoord(MyGUI::Widget* _widget) diff --git a/components/lua_ui/widget.hpp b/components/lua_ui/widget.hpp index 48b169572f..360c6483ba 100644 --- a/components/lua_ui/widget.hpp +++ b/components/lua_ui/widget.hpp @@ -5,10 +5,11 @@ #include #include -#include #include +#include "properties.hpp" + namespace LuaUi { /* @@ -36,17 +37,16 @@ namespace LuaUi void setCallback(const std::string&, const LuaUtil::Callback&); void clearCallbacks(); - void setProperty(std::string_view, sol::object value); + virtual void setProperties(sol::object); - MyGUI::IntCoord forcedOffset(); - void setForcedOffset(const MyGUI::IntCoord& offset); + MyGUI::IntCoord forcedCoord(); + void setForcedCoord(const MyGUI::IntCoord& offset); void updateCoord(); protected: sol::table makeTable() const; sol::object keyEvent(MyGUI::KeyCode) const; sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const; - virtual bool setPropertyRaw(std::string_view name, sol::object value); virtual void initialize(); virtual void deinitialize(); virtual MyGUI::IntSize calculateSize(); @@ -55,9 +55,14 @@ namespace LuaUi void triggerEvent(std::string_view name, const sol::object& argument) const; + // offsets the position and size, used only in C++ widget code MyGUI::IntCoord mForcedCoord; + // position and size in pixels MyGUI::IntCoord mAbsoluteCoord; + // position and size as a ratio of parent size MyGUI::FloatCoord mRelativeCoord; + // negative position offset as a ratio of this widget's size + // used in combination with relative coord to align the widget, e. g. center it MyGUI::FloatSize mAnchor; private: diff --git a/components/lua_ui/window.cpp b/components/lua_ui/window.cpp index b7bb426a63..5d34bf8212 100644 --- a/components/lua_ui/window.cpp +++ b/components/lua_ui/window.cpp @@ -8,6 +8,7 @@ namespace LuaUi : mCaption() , mPreviousMouse() , mChangeScale() + , mMoveResize() {} void LuaWindow::initialize() @@ -43,20 +44,13 @@ namespace LuaUi } } - bool LuaWindow::setPropertyRaw(std::string_view name, sol::object value) + void LuaWindow::setProperties(sol::object props) { - if (name == "caption") - { - if (!value.is()) - return false; - if (mCaption) - mCaption->setCaption(value.as()); - } - else - { - return WidgetExtension::setPropertyRaw(name, value); - } - return true; + if (mCaption) + mCaption->setCaption(parseProperty(props, "caption", std::string())); + mMoveResize = MyGUI::IntCoord(); + setForcedCoord(mMoveResize); + WidgetExtension::setProperties(props); } void LuaWindow::notifyMousePress(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id) @@ -84,9 +78,11 @@ namespace LuaUi change.width *= (left - mPreviousMouse.left); change.height *= (top - mPreviousMouse.top); - setForcedOffset(forcedOffset() + change.size()); - MyGUI::IntPoint positionOffset = change.point() + getPosition() - calculateCoord().point(); - setForcedOffset(forcedOffset() + positionOffset); + mMoveResize = mMoveResize + change.size(); + setForcedCoord(mMoveResize); + // position can change based on size changes + mMoveResize = mMoveResize + change.point() + getPosition() - calculateCoord().point(); + setForcedCoord(mMoveResize); updateCoord(); mPreviousMouse.left = left; diff --git a/components/lua_ui/window.hpp b/components/lua_ui/window.hpp index c04b0a6055..f34779c8f7 100644 --- a/components/lua_ui/window.hpp +++ b/components/lua_ui/window.hpp @@ -15,6 +15,7 @@ namespace LuaUi public: LuaWindow(); + virtual void setProperties(sol::object) override; private: // \todo replace with LuaText when skins are properly implemented @@ -22,12 +23,12 @@ namespace LuaUi MyGUI::IntPoint mPreviousMouse; MyGUI::IntCoord mChangeScale; + MyGUI::IntCoord mMoveResize; + protected: virtual void initialize() override; virtual void deinitialize() override; - bool setPropertyRaw(std::string_view name, sol::object value) override; - void notifyMousePress(MyGUI::Widget*, int, int, MyGUI::MouseButton); void notifyMouseDrag(MyGUI::Widget*, int, int, MyGUI::MouseButton); };