diff options
Diffstat (limited to 'scene/theme/theme_owner.cpp')
| -rw-r--r-- | scene/theme/theme_owner.cpp | 193 |
1 files changed, 119 insertions, 74 deletions
diff --git a/scene/theme/theme_owner.cpp b/scene/theme/theme_owner.cpp index 40855c6a3e..1ba9a055fc 100644 --- a/scene/theme/theme_owner.cpp +++ b/scene/theme/theme_owner.cpp @@ -66,6 +66,52 @@ bool ThemeOwner::has_owner_node() const { return bool(owner_control || owner_window); } +void ThemeOwner::set_owner_context(ThemeContext *p_context, bool p_propagate) { + ThemeContext *default_context = ThemeDB::get_singleton()->get_default_theme_context(); + + if (owner_context && owner_context->is_connected("changed", callable_mp(this, &ThemeOwner::_owner_context_changed))) { + owner_context->disconnect("changed", callable_mp(this, &ThemeOwner::_owner_context_changed)); + } else if (default_context->is_connected("changed", callable_mp(this, &ThemeOwner::_owner_context_changed))) { + default_context->disconnect("changed", callable_mp(this, &ThemeOwner::_owner_context_changed)); + } + + owner_context = p_context; + + if (owner_context) { + owner_context->connect("changed", callable_mp(this, &ThemeOwner::_owner_context_changed)); + } else { + default_context->connect("changed", callable_mp(this, &ThemeOwner::_owner_context_changed)); + } + + if (p_propagate) { + _owner_context_changed(); + } +} + +void ThemeOwner::_owner_context_changed() { + if (!holder->is_inside_tree()) { + // We ignore theme changes outside of tree, because NOTIFICATION_ENTER_TREE covers everything. + return; + } + + Control *c = Object::cast_to<Control>(holder); + Window *w = c == nullptr ? Object::cast_to<Window>(holder) : nullptr; + + if (c) { + c->notification(Control::NOTIFICATION_THEME_CHANGED); + } else if (w) { + w->notification(Window::NOTIFICATION_THEME_CHANGED); + } +} + +ThemeContext *ThemeOwner::_get_active_owner_context() const { + if (owner_context) { + return owner_context; + } + + return ThemeDB::get_singleton()->get_default_theme_context(); +} + // Theme propagation. void ThemeOwner::assign_theme_on_parented(Node *p_for_node) { @@ -158,9 +204,7 @@ void ThemeOwner::get_theme_type_dependencies(const Node *p_for_node, const Strin const Window *for_w = Object::cast_to<Window>(p_for_node); ERR_FAIL_COND_MSG(!for_c && !for_w, "Only Control and Window nodes and derivatives can be polled for theming."); - Ref<Theme> default_theme = ThemeDB::get_singleton()->get_default_theme(); - Ref<Theme> project_theme = ThemeDB::get_singleton()->get_project_theme(); - + StringName type_name = p_for_node->get_class_name(); StringName type_variation; if (for_c) { type_variation = for_c->get_theme_type_variation(); @@ -168,31 +212,23 @@ void ThemeOwner::get_theme_type_dependencies(const Node *p_for_node, const Strin type_variation = for_w->get_theme_type_variation(); } - if (p_theme_type == StringName() || p_theme_type == p_for_node->get_class_name() || p_theme_type == type_variation) { - if (project_theme.is_valid() && project_theme->get_type_variation_base(type_variation) != StringName()) { - project_theme->get_type_dependencies(p_for_node->get_class_name(), type_variation, r_list); - } else { - default_theme->get_type_dependencies(p_for_node->get_class_name(), type_variation, r_list); + // If we are looking for dependencies of the current class (or a variantion of it), check themes from the context. + if (p_theme_type == StringName() || p_theme_type == type_name || p_theme_type == type_variation) { + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid() && theme->get_type_variation_base(type_variation) != StringName()) { + theme->get_type_dependencies(type_name, type_variation, r_list); + return; + } } - } else { - default_theme->get_type_dependencies(p_theme_type, StringName(), r_list); - } -} -Node *ThemeOwner::_get_next_owner_node(Node *p_from_node) const { - Node *parent = p_from_node->get_parent(); - - Control *parent_c = Object::cast_to<Control>(parent); - if (parent_c) { - return parent_c->get_theme_owner_node(); - } else { - Window *parent_w = Object::cast_to<Window>(parent); - if (parent_w) { - return parent_w->get_theme_owner_node(); - } + // If nothing was found, get the native dependencies for the current class. + ThemeDB::get_singleton()->get_native_type_dependencies(type_name, r_list); + return; } - return nullptr; + // Otherwise, get the native dependencies for the provided theme type. + ThemeDB::get_singleton()->get_native_type_dependencies(p_theme_type, r_list); } Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { @@ -215,24 +251,20 @@ Variant ThemeOwner::get_theme_item_in_types(Theme::DataType p_data_type, const S owner_node = _get_next_owner_node(owner_node); } - // Secondly, check the project-defined Theme resource. - if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { - for (const StringName &E : p_theme_types) { - if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) { - return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(p_data_type, p_name, E); + // Second, check global themes from the appropriate context. + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid()) { + for (const StringName &E : p_theme_types) { + if (theme->has_theme_item(p_data_type, p_name, E)) { + return theme->get_theme_item(p_data_type, p_name, E); + } } } } - // Lastly, fall back on the items defined in the default Theme, if they exist. - for (const StringName &E : p_theme_types) { - if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) { - return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, E); - } - } - - // If they don't exist, use any type to return the default/empty value. - return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, p_theme_types[0]); + // Finally, if no match exists, use any type to return the default/empty value. + return global_context->get_fallback_theme()->get_theme_item(p_data_type, p_name, StringName()); } bool ThemeOwner::has_theme_item_in_types(Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { @@ -255,22 +287,19 @@ bool ThemeOwner::has_theme_item_in_types(Theme::DataType p_data_type, const Stri owner_node = _get_next_owner_node(owner_node); } - // Secondly, check the project-defined Theme resource. - if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { - for (const StringName &E : p_theme_types) { - if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) { - return true; + // Second, check global themes from the appropriate context. + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid()) { + for (const StringName &E : p_theme_types) { + if (theme->has_theme_item(p_data_type, p_name, E)) { + return true; + } } } } - // Lastly, fall back on the items defined in the default Theme, if they exist. - for (const StringName &E : p_theme_types) { - if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) { - return true; - } - } - + // Finally, if no match exists, return false. return false; } @@ -290,17 +319,17 @@ float ThemeOwner::get_theme_default_base_scale() { owner_node = _get_next_owner_node(owner_node); } - // Secondly, check the project-defined Theme resource. - if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { - if (ThemeDB::get_singleton()->get_project_theme()->has_default_base_scale()) { - return ThemeDB::get_singleton()->get_project_theme()->get_default_base_scale(); + // Second, check global themes from the appropriate context. + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid()) { + if (theme->has_default_base_scale()) { + return theme->get_default_base_scale(); + } } } - // Lastly, fall back on the default Theme. - if (ThemeDB::get_singleton()->get_default_theme()->has_default_base_scale()) { - return ThemeDB::get_singleton()->get_default_theme()->get_default_base_scale(); - } + // Finally, if no match exists, return the universal default. return ThemeDB::get_singleton()->get_fallback_base_scale(); } @@ -320,17 +349,17 @@ Ref<Font> ThemeOwner::get_theme_default_font() { owner_node = _get_next_owner_node(owner_node); } - // Secondly, check the project-defined Theme resource. - if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { - if (ThemeDB::get_singleton()->get_project_theme()->has_default_font()) { - return ThemeDB::get_singleton()->get_project_theme()->get_default_font(); + // Second, check global themes from the appropriate context. + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid()) { + if (theme->has_default_font()) { + return theme->get_default_font(); + } } } - // Lastly, fall back on the default Theme. - if (ThemeDB::get_singleton()->get_default_theme()->has_default_font()) { - return ThemeDB::get_singleton()->get_default_theme()->get_default_font(); - } + // Finally, if no match exists, return the universal default. return ThemeDB::get_singleton()->get_fallback_font(); } @@ -350,17 +379,17 @@ int ThemeOwner::get_theme_default_font_size() { owner_node = _get_next_owner_node(owner_node); } - // Secondly, check the project-defined Theme resource. - if (ThemeDB::get_singleton()->get_project_theme().is_valid()) { - if (ThemeDB::get_singleton()->get_project_theme()->has_default_font_size()) { - return ThemeDB::get_singleton()->get_project_theme()->get_default_font_size(); + // Second, check global themes from the appropriate context. + ThemeContext *global_context = _get_active_owner_context(); + for (const Ref<Theme> &theme : global_context->get_themes()) { + if (theme.is_valid()) { + if (theme->has_default_font_size()) { + return theme->get_default_font_size(); + } } } - // Lastly, fall back on the default Theme. - if (ThemeDB::get_singleton()->get_default_theme()->has_default_font_size()) { - return ThemeDB::get_singleton()->get_default_theme()->get_default_font_size(); - } + // Finally, if no match exists, return the universal default. return ThemeDB::get_singleton()->get_fallback_font_size(); } @@ -377,3 +406,19 @@ Ref<Theme> ThemeOwner::_get_owner_node_theme(Node *p_owner_node) const { return Ref<Theme>(); } + +Node *ThemeOwner::_get_next_owner_node(Node *p_from_node) const { + Node *parent = p_from_node->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + if (parent_c) { + return parent_c->get_theme_owner_node(); + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + return parent_w->get_theme_owner_node(); + } + } + + return nullptr; +} |
