Merge branch 'invalidparentage' into 'master'

Prevent iterator invalidation when updating Lua UI and increase const correctness

Closes #7880

See merge request OpenMW/openmw!3992
animationblending
psi29a 2 months ago
commit 6f8123998c

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

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

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save