1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-19 20:11:36 +00:00

Prevent iterator invalidation when updating Lua UI and increase const correctness

This commit is contained in:
Evil Eye 2024-03-28 20:01:50 +01:00
parent 2497164b2b
commit 8cbcb82dd4
11 changed files with 81 additions and 56 deletions

View file

@ -10,12 +10,12 @@ namespace LuaUi
updateSizeToFit(); updateSizeToFit();
} }
MyGUI::IntSize LuaContainer::childScalingSize() MyGUI::IntSize LuaContainer::childScalingSize() const
{ {
return MyGUI::IntSize(); return MyGUI::IntSize();
} }
MyGUI::IntSize LuaContainer::templateScalingSize() MyGUI::IntSize LuaContainer::templateScalingSize() const
{ {
return mInnerSize; return mInnerSize;
} }
@ -23,14 +23,14 @@ namespace LuaUi
void LuaContainer::updateSizeToFit() void LuaContainer::updateSizeToFit()
{ {
MyGUI::IntSize innerSize = MyGUI::IntSize(); MyGUI::IntSize innerSize = MyGUI::IntSize();
for (auto w : children()) for (const auto w : children())
{ {
MyGUI::IntCoord coord = w->calculateCoord(); MyGUI::IntCoord coord = w->calculateCoord();
innerSize.width = std::max(innerSize.width, coord.left + coord.width); innerSize.width = std::max(innerSize.width, coord.left + coord.width);
innerSize.height = std::max(innerSize.height, coord.top + coord.height); innerSize.height = std::max(innerSize.height, coord.top + coord.height);
} }
MyGUI::IntSize outerSize = innerSize; MyGUI::IntSize outerSize = innerSize;
for (auto w : templateChildren()) for (const auto w : templateChildren())
{ {
MyGUI::IntCoord coord = w->calculateCoord(); MyGUI::IntCoord coord = w->calculateCoord();
outerSize.width = std::max(outerSize.width, coord.left + coord.width); outerSize.width = std::max(outerSize.width, coord.left + coord.width);
@ -40,7 +40,7 @@ namespace LuaUi
mOuterSize = outerSize; mOuterSize = outerSize;
} }
MyGUI::IntSize LuaContainer::calculateSize() MyGUI::IntSize LuaContainer::calculateSize() const
{ {
return mOuterSize; return mOuterSize;
} }

View file

@ -10,13 +10,13 @@ namespace LuaUi
MYGUI_RTTI_DERIVED(LuaContainer) MYGUI_RTTI_DERIVED(LuaContainer)
public: public:
MyGUI::IntSize calculateSize() override; MyGUI::IntSize calculateSize() const override;
void updateCoord() override; void updateCoord() override;
protected: protected:
void updateChildren() override; void updateChildren() override;
MyGUI::IntSize childScalingSize() override; MyGUI::IntSize childScalingSize() const override;
MyGUI::IntSize templateScalingSize() override; MyGUI::IntSize templateScalingSize() const override;
private: private:
void updateSizeToFit(); void updateSizeToFit();

View file

@ -54,25 +54,19 @@ namespace LuaUi
if (!ext->isRoot()) if (!ext->isRoot())
destroyWidget(ext); destroyWidget(ext);
else else
ext->detachFromParent(); ext->detachFromParent(false);
} }
void detachElements(WidgetExtension* ext) void detachElements(WidgetExtension* ext)
{ {
for (auto* child : ext->children()) auto predicate = [](WidgetExtension* child) {
{
if (child->isRoot()) if (child->isRoot())
child->detachFromParent(); return true;
else
detachElements(child); detachElements(child);
} return false;
for (auto* child : ext->templateChildren()) };
{ ext->detachChildrenIf(predicate);
if (child->isRoot()) ext->detachTemplateChildrenIf(predicate);
child->detachFromParent();
else
detachElements(child);
}
} }
void destroyRoot(WidgetExtension* ext) void destroyRoot(WidgetExtension* ext)
@ -194,8 +188,8 @@ namespace LuaUi
throw std::logic_error(std::string("Invalid widget type ") += type); throw std::logic_error(std::string("Invalid widget type ") += type);
std::string name = layout.get_or(LayoutKeys::name, std::string()); std::string name = layout.get_or(LayoutKeys::name, std::string());
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT( MyGUI::Widget* widget
type, "", MyGUI::IntCoord(), MyGUI::Align::Default, std::string(), name); = MyGUI::Gui::getInstancePtr()->createWidgetT(type, {}, {}, MyGUI::Align::Default, {}, name);
WidgetExtension* ext = dynamic_cast<WidgetExtension*>(widget); WidgetExtension* ext = dynamic_cast<WidgetExtension*>(widget);
if (!ext) if (!ext)

View file

@ -79,7 +79,7 @@ namespace LuaUi
WidgetExtension::updateChildren(); WidgetExtension::updateChildren();
} }
MyGUI::IntSize LuaFlex::childScalingSize() MyGUI::IntSize LuaFlex::childScalingSize() const
{ {
// Call the base method to prevent relativeSize feedback loop // Call the base method to prevent relativeSize feedback loop
MyGUI::IntSize size = WidgetExtension::calculateSize(); MyGUI::IntSize size = WidgetExtension::calculateSize();
@ -88,7 +88,7 @@ namespace LuaUi
return size; return size;
} }
MyGUI::IntSize LuaFlex::calculateSize() MyGUI::IntSize LuaFlex::calculateSize() const
{ {
MyGUI::IntSize size = WidgetExtension::calculateSize(); MyGUI::IntSize size = WidgetExtension::calculateSize();
if (mAutoSized) if (mAutoSized)

View file

@ -11,10 +11,10 @@ namespace LuaUi
MYGUI_RTTI_DERIVED(LuaFlex) MYGUI_RTTI_DERIVED(LuaFlex)
protected: protected:
MyGUI::IntSize calculateSize() override; MyGUI::IntSize calculateSize() const override;
void updateProperties() override; void updateProperties() override;
void updateChildren() override; void updateChildren() override;
MyGUI::IntSize childScalingSize() override; MyGUI::IntSize childScalingSize() const override;
void updateCoord() override; void updateCoord() override;
@ -26,25 +26,37 @@ namespace LuaUi
Alignment mArrange; Alignment mArrange;
template <typename T> template <typename T>
T& primary(MyGUI::types::TPoint<T>& point) T& primary(MyGUI::types::TPoint<T>& point) const
{ {
return mHorizontal ? point.left : point.top; return mHorizontal ? point.left : point.top;
} }
template <typename T> template <typename T>
T& secondary(MyGUI::types::TPoint<T>& point) T& secondary(MyGUI::types::TPoint<T>& point) const
{ {
return mHorizontal ? point.top : point.left; return mHorizontal ? point.top : point.left;
} }
template <typename T> template <typename T>
T& primary(MyGUI::types::TSize<T>& size) T& primary(MyGUI::types::TSize<T>& size) const
{ {
return mHorizontal ? size.width : size.height; return mHorizontal ? size.width : size.height;
} }
template <typename T> template <typename T>
T& secondary(MyGUI::types::TSize<T>& size) T& secondary(MyGUI::types::TSize<T>& size) const
{
return mHorizontal ? size.height : size.width;
}
template <typename T>
T primary(const MyGUI::types::TSize<T>& size) const
{
return mHorizontal ? size.width : size.height;
}
template <typename T>
T secondary(const MyGUI::types::TSize<T>& size) const
{ {
return mHorizontal ? size.height : size.width; return mHorizontal ? size.height : size.width;
} }

View file

@ -46,7 +46,7 @@ namespace LuaUi
updateCoord(); updateCoord();
} }
MyGUI::IntSize LuaText::calculateSize() MyGUI::IntSize LuaText::calculateSize() const
{ {
if (mAutoSized) if (mAutoSized)
return getTextSize(); return getTextSize();

View file

@ -21,7 +21,7 @@ namespace LuaUi
bool mAutoSized; bool mAutoSized;
protected: protected:
MyGUI::IntSize calculateSize() override; MyGUI::IntSize calculateSize() const override;
}; };
} }

View file

@ -63,7 +63,7 @@ namespace LuaUi
mEditBox->attachToWidget(this); mEditBox->attachToWidget(this);
} }
MyGUI::IntSize LuaTextEdit::calculateSize() MyGUI::IntSize LuaTextEdit::calculateSize() const
{ {
MyGUI::IntSize normalSize = WidgetExtension::calculateSize(); MyGUI::IntSize normalSize = WidgetExtension::calculateSize();
if (mAutoSize) if (mAutoSize)

View file

@ -20,7 +20,7 @@ namespace LuaUi
void updateProperties() override; void updateProperties() override;
void updateCoord() override; void updateCoord() override;
void updateChildren() override; void updateChildren() override;
MyGUI::IntSize calculateSize() override; MyGUI::IntSize calculateSize() const override;
private: private:
void textChange(MyGUI::EditBox*); void textChange(MyGUI::EditBox*);

View file

@ -101,7 +101,7 @@ namespace LuaUi
void WidgetExtension::attach(WidgetExtension* ext) void WidgetExtension::attach(WidgetExtension* ext)
{ {
if (ext->mParent != this) if (ext->mParent != this)
ext->detachFromParent(); ext->detachFromParent(true);
ext->mParent = this; ext->mParent = this;
ext->mTemplateChild = false; ext->mTemplateChild = false;
ext->widget()->attachToWidget(mSlot->widget()); ext->widget()->attachToWidget(mSlot->widget());
@ -114,13 +114,16 @@ namespace LuaUi
ext->widget()->attachToWidget(widget()); ext->widget()->attachToWidget(widget());
} }
void WidgetExtension::detachFromParent() void WidgetExtension::detachFromParent(bool updateParent)
{ {
if (mParent) if (mParent)
{
if (updateParent)
{ {
auto children = mParent->children(); auto children = mParent->children();
std::erase(children, this); std::erase(children, this);
mParent->setChildren(children); mParent->setChildren(children);
}
mParent = nullptr; mParent = nullptr;
} }
widget()->detachFromWidget(); widget()->detachFromWidget();
@ -307,7 +310,7 @@ namespace LuaUi
w->updateCoord(); w->updateCoord();
} }
MyGUI::IntSize WidgetExtension::parentSize() MyGUI::IntSize WidgetExtension::parentSize() const
{ {
if (!mParent) if (!mParent)
return widget()->getParentSize(); // size of the layer return widget()->getParentSize(); // size of the layer
@ -317,7 +320,7 @@ namespace LuaUi
return mParent->childScalingSize(); return mParent->childScalingSize();
} }
MyGUI::IntSize WidgetExtension::calculateSize() MyGUI::IntSize WidgetExtension::calculateSize() const
{ {
if (mForceSize) if (mForceSize)
return mForcedCoord.size(); return mForcedCoord.size();
@ -330,7 +333,7 @@ namespace LuaUi
return newSize; return newSize;
} }
MyGUI::IntPoint WidgetExtension::calculatePosition(const MyGUI::IntSize& size) MyGUI::IntPoint WidgetExtension::calculatePosition(const MyGUI::IntSize& size) const
{ {
if (mForcePosition) if (mForcePosition)
return mForcedCoord.point(); return mForcedCoord.point();
@ -342,7 +345,7 @@ namespace LuaUi
return newPosition; return newPosition;
} }
MyGUI::IntCoord WidgetExtension::calculateCoord() MyGUI::IntCoord WidgetExtension::calculateCoord() const
{ {
MyGUI::IntCoord newCoord; MyGUI::IntCoord newCoord;
newCoord = calculateSize(); newCoord = calculateSize();
@ -350,12 +353,12 @@ namespace LuaUi
return newCoord; return newCoord;
} }
MyGUI::IntSize WidgetExtension::childScalingSize() MyGUI::IntSize WidgetExtension::childScalingSize() const
{ {
return mSlot->widget()->getSize(); return mSlot->widget()->getSize();
} }
MyGUI::IntSize WidgetExtension::templateScalingSize() MyGUI::IntSize WidgetExtension::templateScalingSize() const
{ {
return widget()->getSize(); return widget()->getSize();
} }

View file

@ -31,11 +31,13 @@ namespace LuaUi
virtual void deinitialize(); virtual void deinitialize();
MyGUI::Widget* widget() const { return mWidget; } MyGUI::Widget* widget() const { return mWidget; }
WidgetExtension* slot() const { return mSlot; }
bool isRoot() const { return mElementRoot; } bool isRoot() const { return mElementRoot; }
WidgetExtension* getParent() const { return mParent; } WidgetExtension* getParent() const { return mParent; }
void detachFromParent(); void detachFromParent(bool updateParent);
void detachChildrenIf(auto&& predicate) { detachChildrenIf(predicate, mChildren); }
void detachTemplateChildrenIf(auto&& predicate) { detachChildrenIf(predicate, mTemplateChildren); }
void reset(); void reset();
@ -65,14 +67,14 @@ namespace LuaUi
void setLayout(const sol::table& layout) { mLayout = layout; } void setLayout(const sol::table& layout) { mLayout = layout; }
template <typename T> template <typename T>
T externalValue(std::string_view name, const T& defaultValue) T externalValue(std::string_view name, const T& defaultValue) const
{ {
return parseExternal(mExternal, name, defaultValue); return parseExternal(mExternal, name, defaultValue);
} }
virtual MyGUI::IntSize calculateSize(); virtual MyGUI::IntSize calculateSize() const;
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size); virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size) const;
MyGUI::IntCoord calculateCoord(); MyGUI::IntCoord calculateCoord() const;
virtual bool isTextInput() { return false; } virtual bool isTextInput() { return false; }
@ -85,9 +87,9 @@ namespace LuaUi
sol::object keyEvent(MyGUI::KeyCode) const; sol::object keyEvent(MyGUI::KeyCode) const;
sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const; sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const;
MyGUI::IntSize parentSize(); MyGUI::IntSize parentSize() const;
virtual MyGUI::IntSize childScalingSize(); virtual MyGUI::IntSize childScalingSize() const;
virtual MyGUI::IntSize templateScalingSize(); virtual MyGUI::IntSize templateScalingSize() const;
template <typename T> template <typename T>
T propertyValue(std::string_view name, const T& defaultValue) T propertyValue(std::string_view name, const T& defaultValue)
@ -176,6 +178,20 @@ namespace LuaUi
void focusLoss(MyGUI::Widget*, MyGUI::Widget*); void focusLoss(MyGUI::Widget*, MyGUI::Widget*);
void updateVisible(); void updateVisible();
void detachChildrenIf(auto&& predicate, std::vector<WidgetExtension*> children)
{
for (auto it = children.begin(); it != children.end();)
{
if (predicate(*it))
{
(*it)->detachFromParent(false);
it = children.erase(it);
}
else
++it;
}
}
}; };
class LuaWidget : public MyGUI::Widget, public WidgetExtension class LuaWidget : public MyGUI::Widget, public WidgetExtension