diff options
-rw-r--r-- | scene/gui/control.cpp | 27 | ||||
-rw-r--r-- | scene/gui/control.h | 3 | ||||
-rw-r--r-- | scene/main/window.cpp | 19 | ||||
-rw-r--r-- | scene/theme/theme_owner.cpp | 37 | ||||
-rw-r--r-- | scene/theme/theme_owner.h | 2 |
5 files changed, 56 insertions, 32 deletions
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 6a4b61fad0..d6251872c0 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2789,21 +2789,6 @@ Control *Control::make_custom_tooltip(const String &p_text) const { // Base object overrides. -void Control::add_child_notify(Node *p_child) { - // We propagate when this node uses a custom theme, so it can pass it on to its children. - if (has_theme_owner_node()) { - // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. - data.theme_owner->propagate_theme_changed(p_child, get_theme_owner_node(), false, true); - } -} - -void Control::remove_child_notify(Node *p_child) { - // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. - if (has_theme_owner_node()) { - data.theme_owner->propagate_theme_changed(p_child, nullptr, false, true); - } -} - void Control::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_POSTINITIALIZE: { @@ -2811,10 +2796,16 @@ void Control::_notification(int p_notification) { _update_theme_item_cache(); } break; + case NOTIFICATION_PARENTED: { + data.theme_owner->assign_theme_on_parented(this); + } break; + + case NOTIFICATION_UNPARENTED: { + data.theme_owner->clear_theme_on_unparented(this); + } break; + case NOTIFICATION_ENTER_TREE: { - // Need to defer here, because theme owner information might be set in - // add_child_notify, which doesn't get called until right after this. - call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); + notification(NOTIFICATION_THEME_CHANGED); } break; case NOTIFICATION_POST_ENTER_TREE: { diff --git a/scene/gui/control.h b/scene/gui/control.h index 3e0b1d7ea3..3fb1494d66 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -327,9 +327,6 @@ protected: // Base object overrides. - virtual void add_child_notify(Node *p_child) override; - virtual void remove_child_notify(Node *p_child) override; - void _notification(int p_notification); static void _bind_methods(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8be6fe3e1c..84e4162c00 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -805,6 +805,14 @@ void Window::_notification(int p_what) { _update_theme_item_cache(); } break; + case NOTIFICATION_PARENTED: { + theme_owner->assign_theme_on_parented(this); + } break; + + case NOTIFICATION_UNPARENTED: { + theme_owner->clear_theme_on_unparented(this); + } break; + case NOTIFICATION_ENTER_TREE: { bool embedded = false; { @@ -1290,23 +1298,12 @@ Rect2i Window::get_usable_parent_rect() const { } void Window::add_child_notify(Node *p_child) { - // We propagate when this node uses a custom theme, so it can pass it on to its children. - if (has_theme_owner_node()) { - // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. - theme_owner->propagate_theme_changed(p_child, get_theme_owner_node(), false, true); - } - if (is_inside_tree() && wrap_controls) { child_controls_changed(); } } void Window::remove_child_notify(Node *p_child) { - // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. - if (has_theme_owner_node()) { - theme_owner->propagate_theme_changed(p_child, nullptr, false, true); - } - if (is_inside_tree() && wrap_controls) { child_controls_changed(); } diff --git a/scene/theme/theme_owner.cpp b/scene/theme/theme_owner.cpp index 1ac1d0f9fe..e89aa1b28d 100644 --- a/scene/theme/theme_owner.cpp +++ b/scene/theme/theme_owner.cpp @@ -68,6 +68,43 @@ bool ThemeOwner::has_owner_node() const { // Theme propagation. +void ThemeOwner::assign_theme_on_parented(Node *p_for_node) { + // We check if there are any themes affecting the parent. If that's the case + // its children also need to be affected. + // We don't notify here because `NOTIFICATION_THEME_CHANGED` will be handled + // a bit later by `NOTIFICATION_ENTER_TREE`. + + Node *parent = p_for_node->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c && parent_c->has_theme_owner_node()) { + propagate_theme_changed(p_for_node, parent_c->get_theme_owner_node(), false, true); + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w && parent_w->has_theme_owner_node()) { + propagate_theme_changed(p_for_node, parent_w->get_theme_owner_node(), false, true); + } + } +} + +void ThemeOwner::clear_theme_on_unparented(Node *p_for_node) { + // We check if there were any themes affecting the parent. If that's the case + // its children need were also affected and need to be updated. + // We don't notify because we're exiting the tree, and it's not important. + + Node *parent = p_for_node->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c && parent_c->has_theme_owner_node()) { + propagate_theme_changed(p_for_node, nullptr, false, true); + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w && parent_w->has_theme_owner_node()) { + propagate_theme_changed(p_for_node, nullptr, false, true); + } + } +} + void ThemeOwner::propagate_theme_changed(Node *p_to_node, Node *p_owner_node, bool p_notify, bool p_assign) { Control *c = Object::cast_to<Control>(p_to_node); Window *w = c == nullptr ? Object::cast_to<Window>(p_to_node) : nullptr; diff --git a/scene/theme/theme_owner.h b/scene/theme/theme_owner.h index 38344c3d9e..59b72c1627 100644 --- a/scene/theme/theme_owner.h +++ b/scene/theme/theme_owner.h @@ -53,6 +53,8 @@ public: // Theme propagation. + void assign_theme_on_parented(Node *p_for_node); + void clear_theme_on_unparented(Node *p_for_node); void propagate_theme_changed(Node *p_to_node, Node *p_owner_node, bool p_notify, bool p_assign); // Theme lookup. |