Bläddra i källkod

Un-defer the initial theme changed notification

Co-authored-by: Rindbee <[email protected]>
Yuri Sizov 3 år sedan
förälder
incheckning
8b128081e8
5 ändrade filer med 56 tillägg och 32 borttagningar
  1. 9 18
      scene/gui/control.cpp
  2. 0 3
      scene/gui/control.h
  3. 8 11
      scene/main/window.cpp
  4. 37 0
      scene/theme/theme_owner.cpp
  5. 2 0
      scene/theme/theme_owner.h

+ 9 - 18
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: {

+ 0 - 3
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();
 

+ 8 - 11
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();
 	}

+ 37 - 0
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;

+ 2 - 0
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.