summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scene/gui/control.cpp27
-rw-r--r--scene/gui/control.h3
-rw-r--r--scene/main/window.cpp19
-rw-r--r--scene/theme/theme_owner.cpp37
-rw-r--r--scene/theme/theme_owner.h2
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.