Refactor and remove excessive calls of NOTIFICATION_THEME_CHANGED

This commit is contained in:
Aaron Record 2022-07-08 13:29:36 -06:00
parent 6d196c1ce3
commit 74eb2a70bd
7 changed files with 170 additions and 182 deletions

View File

@ -1145,6 +1145,7 @@
</signal>
<signal name="theme_changed">
<description>
Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent.
</description>
</signal>
</signals>
@ -1174,7 +1175,12 @@
Sent when the node loses focus.
</constant>
<constant name="NOTIFICATION_THEME_CHANGED" value="45">
Sent when the node's [member theme] changes, right before Godot redraws the control. Happens when you call one of the [code]add_theme_*_override[/code] methods.
Sent when the node needs to refresh its theme items. This happens in one of the following cases:
- The [member theme] property is changed on this node or any of its ancestors.
- The [member theme_type_variation] property is changed on this node.
- One of the node's theme property overrides is changed.
- The node enters the scene tree.
[b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree.
</constant>
<constant name="NOTIFICATION_SCROLL_BEGIN" value="47">
Sent when this node is inside a [ScrollContainer] which has begun being scrolled.

View File

@ -448,7 +448,7 @@
</signal>
<signal name="theme_changed">
<description>
Emitted when the [member theme] is modified or changed to another [Theme].
Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent.
</description>
</signal>
<signal name="visibility_changed">
@ -467,6 +467,13 @@
<constant name="NOTIFICATION_VISIBILITY_CHANGED" value="30">
Emitted when [Window]'s visibility changes, right before [signal visibility_changed].
</constant>
<constant name="NOTIFICATION_THEME_CHANGED" value="32">
Sent when the node needs to refresh its theme items. This happens in one of the following cases:
- The [member theme] property is changed on this node or any of its ancestors.
- The [member theme_type_variation] property is changed on this node.
- The node enters the scene tree.
[b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree.
</constant>
<constant name="MODE_WINDOWED" value="0" enum="Mode">
Windowed mode, i.e. [Window] doesn't occupy whole screen (unless set to the size of the screen).
</constant>

View File

@ -252,6 +252,11 @@ void EditorLog::_rebuild_log() {
}
void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
if (!is_inside_tree()) {
// The log will be built all at once when it enters the tree and has its theme items.
return;
}
// Only add the message to the log if it passes the filters.
bool filter_active = type_filter_map[p_message.type]->is_active();
String search_text = search_box->get_text();

View File

@ -252,36 +252,36 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
if (name.begins_with("theme_override_icons/")) {
String dname = name.get_slicec('/', 1);
if (data.icon_override.has(dname)) {
data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.icon_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_styles/")) {
String dname = name.get_slicec('/', 1);
if (data.style_override.has(dname)) {
data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.style_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_fonts/")) {
String dname = name.get_slicec('/', 1);
if (data.font_override.has(dname)) {
data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.font_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_font_sizes/")) {
String dname = name.get_slicec('/', 1);
data.font_size_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_colors/")) {
String dname = name.get_slicec('/', 1);
data.color_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else if (name.begins_with("theme_override_constants/")) {
String dname = name.get_slicec('/', 1);
data.constant_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
_notify_theme_override_changed();
} else {
return false;
}
@ -2260,62 +2260,62 @@ bool Control::is_clipping_contents() {
// Theming.
void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign) {
Control *c = Object::cast_to<Control>(p_at);
if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated
return;
}
Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated
if (!c && !w) {
// Theme inheritance chains are broken by nodes that aren't Control or Window.
return;
}
for (int i = 0; i < p_at->get_child_count(); i++) {
CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i));
if (child) {
_propagate_theme_changed(child, p_owner, p_owner_window, p_assign);
} else {
Window *window = Object::cast_to<Window>(p_at->get_child(i));
if (window) {
_propagate_theme_changed(window, p_owner, p_owner_window, p_assign);
}
}
}
bool assign = p_assign;
if (c) {
if (p_assign) {
if (c != p_owner && c->data.theme.is_valid()) {
// Has a theme, so we don't want to change the theme owner,
// but we still want to propagate in case this child has theme items
// it inherits from the theme this node uses.
// See https://github.com/godotengine/godot/issues/62844.
assign = false;
}
if (assign) {
c->data.theme_owner = p_owner;
c->data.theme_owner_window = p_owner_window;
}
c->notification(Control::NOTIFICATION_THEME_CHANGED);
c->emit_signal(SceneStringNames::get_singleton()->theme_changed);
}
if (w) {
if (p_assign) {
if (p_notify) {
c->notification(Control::NOTIFICATION_THEME_CHANGED);
}
} else if (w) {
if (w != p_owner_window && w->theme.is_valid()) {
// Same as above.
assign = false;
}
if (assign) {
w->theme_owner = p_owner;
w->theme_owner_window = p_owner_window;
}
w->notification(Window::NOTIFICATION_THEME_CHANGED);
w->emit_signal(SceneStringNames::get_singleton()->theme_changed);
if (p_notify) {
w->notification(Window::NOTIFICATION_THEME_CHANGED);
}
}
for (int i = 0; i < p_at->get_child_count(); i++) {
_propagate_theme_changed(p_at->get_child(i), p_owner, p_owner_window, p_notify, assign);
}
}
void Control::_theme_changed() {
_propagate_theme_changed(this, this, nullptr, false);
if (is_inside_tree()) {
_propagate_theme_changed(this, this, nullptr, true, false);
}
}
void Control::_theme_property_override_changed() {
notification(NOTIFICATION_THEME_CHANGED);
emit_signal(SceneStringNames::get_singleton()->theme_changed);
update_minimum_size(); // Overrides are likely to affect minimum size.
}
void Control::_notify_theme_changed() {
if (!data.bulk_theme_override) {
void Control::_notify_theme_override_changed() {
if (!data.bulk_theme_override && is_inside_tree()) {
notification(NOTIFICATION_THEME_CHANGED);
}
}
@ -2339,28 +2339,25 @@ void Control::set_theme(const Ref<Theme> &p_theme) {
}
data.theme = p_theme;
if (!p_theme.is_null()) {
data.theme_owner = this;
data.theme_owner_window = nullptr;
_propagate_theme_changed(this, this, nullptr);
} else {
Control *parent_c = Object::cast_to<Control>(get_parent());
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
} else {
Window *parent_w = cast_to<Window>(get_parent());
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
} else {
Control::_propagate_theme_changed(this, nullptr, nullptr);
}
}
}
if (data.theme.is_valid()) {
_propagate_theme_changed(this, this, nullptr, is_inside_tree(), true);
data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED);
return;
}
Control *parent_c = Object::cast_to<Control>(get_parent());
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true);
return;
}
Window *parent_w = cast_to<Window>(get_parent());
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true);
return;
}
_propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true);
}
Ref<Theme> Control::get_theme() const {
@ -2372,7 +2369,9 @@ void Control::set_theme_type_variation(const StringName &p_theme_type) {
return;
}
data.theme_type_variation = p_theme_type;
_propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
if (is_inside_tree()) {
notification(NOTIFICATION_THEME_CHANGED);
}
}
StringName Control::get_theme_type_variation() const {
@ -2697,93 +2696,93 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur
ERR_FAIL_COND(!p_icon.is_valid());
if (data.icon_override.has(p_name)) {
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.icon_override[p_name] = p_icon;
data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_changed();
data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_changed();
}
void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
ERR_FAIL_COND(!p_style.is_valid());
if (data.style_override.has(p_name)) {
data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.style_override[p_name] = p_style;
data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_changed();
data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_changed();
}
void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) {
ERR_FAIL_COND(!p_font.is_valid());
if (data.font_override.has(p_name)) {
data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.font_override[p_name] = p_font;
data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_changed();
data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED);
_notify_theme_override_changed();
}
void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) {
data.font_size_override[p_name] = p_font_size;
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
data.color_override[p_name] = p_color;
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::add_theme_constant_override(const StringName &p_name, int p_constant) {
data.constant_override[p_name] = p_constant;
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_icon_override(const StringName &p_name) {
if (data.icon_override.has(p_name)) {
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.icon_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_style_override(const StringName &p_name) {
if (data.style_override.has(p_name)) {
data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.style_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_font_override(const StringName &p_name) {
if (data.font_override.has(p_name)) {
data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
data.font_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_font_size_override(const StringName &p_name) {
data.font_size_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_color_override(const StringName &p_name) {
data.color_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
void Control::remove_theme_constant_override(const StringName &p_name) {
data.constant_override.erase(p_name);
_notify_theme_changed();
_notify_theme_override_changed();
}
bool Control::has_theme_icon_override(const StringName &p_name) const {
@ -2981,7 +2980,7 @@ void Control::end_bulk_theme_override() {
ERR_FAIL_COND(!data.bulk_theme_override);
data.bulk_theme_override = false;
_notify_theme_changed();
_notify_theme_override_changed();
}
// Internationalization.
@ -3087,37 +3086,26 @@ Control *Control::make_custom_tooltip(const String &p_text) const {
// Base object overrides.
void Control::add_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
_propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
}
Window *child_w = Object::cast_to<Window>(p_child);
if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
_propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
// We propagate when this node uses a custom theme, so it can pass it on to its children.
if (data.theme_owner || data.theme_owner_window) {
// `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`.
_propagate_theme_changed(p_child, data.theme_owner, data.theme_owner_window, false, true);
}
}
void Control::remove_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
_propagate_theme_changed(child_c, nullptr, nullptr);
}
Window *child_w = Object::cast_to<Window>(p_child);
if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
_propagate_theme_changed(child_w, nullptr, nullptr);
// If the removed child isn't inheriting any theme items through this node, then there's no need to propagate.
if (data.theme_owner || data.theme_owner_window) {
_propagate_theme_changed(p_child, nullptr, nullptr, false, true);
}
}
void Control::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_ENTER_TREE: {
_invalidate_theme_cache();
// 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);
} break;
case NOTIFICATION_POST_ENTER_TREE: {
@ -3142,18 +3130,6 @@ void Control::_notification(int p_notification) {
data.parent_window = Object::cast_to<Window>(get_parent());
data.is_rtl_dirty = true;
if (data.theme.is_null()) {
if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) {
data.theme_owner = data.parent->data.theme_owner;
data.theme_owner_window = data.parent->data.theme_owner_window;
notification(NOTIFICATION_THEME_CHANGED);
} else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) {
data.theme_owner = data.parent_window->theme_owner;
data.theme_owner_window = data.parent_window->theme_owner_window;
notification(NOTIFICATION_THEME_CHANGED);
}
}
CanvasItem *node = this;
bool has_parent_control = false;
@ -3257,6 +3233,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_THEME_CHANGED: {
emit_signal(SceneStringNames::get_singleton()->theme_changed);
_invalidate_theme_cache();
update_minimum_size();
update();
@ -3626,13 +3603,13 @@ void Control::_bind_methods() {
Control::~Control() {
// Resources need to be disconnected.
for (KeyValue<StringName, Ref<Texture2D>> &E : data.icon_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
for (KeyValue<StringName, Ref<StyleBox>> &E : data.style_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
for (KeyValue<StringName, Ref<Font>> &E : data.font_override) {
E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed));
}
// Then override maps can be simply cleared.

View File

@ -300,11 +300,10 @@ private:
// Theming.
void _theme_changed();
void _theme_property_override_changed();
void _notify_theme_changed();
void _notify_theme_override_changed();
void _invalidate_theme_cache();
static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true);
static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign);
template <class T>
static T get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types);

View File

@ -848,21 +848,13 @@ void Window::_notification(int p_what) {
RS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
}
if (theme.is_null()) {
Control *parent_c = cast_to<Control>(get_parent());
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
theme_owner = parent_c->data.theme_owner;
theme_owner_window = parent_c->data.theme_owner_window;
notification(NOTIFICATION_THEME_CHANGED);
} else {
Window *parent_w = cast_to<Window>(get_parent());
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
theme_owner = parent_w->theme_owner;
theme_owner_window = parent_w->theme_owner_window;
notification(NOTIFICATION_THEME_CHANGED);
}
}
}
// 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);
} break;
case NOTIFICATION_THEME_CHANGED: {
emit_signal(SceneStringNames::get_singleton()->theme_changed);
} break;
case NOTIFICATION_READY: {
@ -1250,16 +1242,10 @@ Rect2i Window::get_usable_parent_rect() const {
}
void Window::add_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) {
Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
}
Window *child_w = Object::cast_to<Window>(p_child);
if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) {
Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
// We propagate when this node uses a custom theme, so it can pass it on to its children.
if (theme_owner || theme_owner_window) {
// `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`.
Control::_propagate_theme_changed(this, theme_owner, theme_owner_window, false, true);
}
if (is_inside_tree() && wrap_controls) {
@ -1268,16 +1254,9 @@ void Window::add_child_notify(Node *p_child) {
}
void Window::remove_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
Control::_propagate_theme_changed(child_c, nullptr, nullptr);
}
Window *child_w = Object::cast_to<Window>(p_child);
if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
Control::_propagate_theme_changed(child_w, nullptr, nullptr);
// If the removed child isn't inheriting any theme items through this node, then there's no need to propagate.
if (theme_owner || theme_owner_window) {
Control::_propagate_theme_changed(this, nullptr, nullptr, false, true);
}
if (is_inside_tree() && wrap_controls) {
@ -1290,34 +1269,47 @@ void Window::set_theme(const Ref<Theme> &p_theme) {
return;
}
theme = p_theme;
if (!p_theme.is_null()) {
theme_owner = nullptr;
theme_owner_window = this;
Control::_propagate_theme_changed(this, nullptr, this);
} else {
Control *parent_c = cast_to<Control>(get_parent());
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
} else {
Window *parent_w = cast_to<Window>(get_parent());
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
} else {
Control::_propagate_theme_changed(this, nullptr, nullptr);
}
}
if (theme.is_valid()) {
theme->disconnect("changed", callable_mp(this, &Window::_theme_changed));
}
theme = p_theme;
if (theme.is_valid()) {
Control::_propagate_theme_changed(this, nullptr, this, is_inside_tree(), true);
theme->connect("changed", callable_mp(this, &Window::_theme_changed), CONNECT_DEFERRED);
return;
}
Control *parent_c = Object::cast_to<Control>(get_parent());
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true);
return;
}
Window *parent_w = cast_to<Window>(get_parent());
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true);
return;
}
Control::_propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true);
}
Ref<Theme> Window::get_theme() const {
return theme;
}
void Window::_theme_changed() {
if (is_inside_tree()) {
Control::_propagate_theme_changed(this, nullptr, this, true, false);
}
}
void Window::set_theme_type_variation(const StringName &p_theme_type) {
theme_type_variation = p_theme_type;
Control::_propagate_theme_changed(this, theme_owner, theme_owner_window);
if (is_inside_tree()) {
notification(NOTIFICATION_THEME_CHANGED);
}
}
StringName Window::get_theme_type_variation() const {
@ -1712,6 +1704,7 @@ void Window::_bind_methods() {
ADD_SIGNAL(MethodInfo("theme_changed"));
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
BIND_CONSTANT(NOTIFICATION_THEME_CHANGED);
BIND_ENUM_CONSTANT(MODE_WINDOWED);
BIND_ENUM_CONSTANT(MODE_MINIMIZED);

View File

@ -253,6 +253,7 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
void _theme_changed();
void set_theme_type_variation(const StringName &p_theme_type);
StringName get_theme_type_variation() const;