1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-06 12:20:30 +00:00

Add type variations to Theme

This commit is contained in:
Yuri Sizov
2021-07-04 23:42:23 +03:00
parent 30d4732623
commit 4ee0e6ddf5
18 changed files with 757 additions and 199 deletions

View File

@@ -1943,6 +1943,117 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
void ThemeTypeDialog::_dialog_about_to_show() {
add_type_filter->set_text("");
add_type_filter->grab_focus();
_update_add_type_options();
}
void ThemeTypeDialog::ok_pressed() {
emit_signal("type_selected", add_type_filter->get_text().strip_edges());
}
void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
add_type_options->clear();
List<StringName> names;
Theme::get_default()->get_type_list(&names);
if (include_own_types) {
edited_theme->get_type_list(&names);
}
names.sort_custom<StringName::AlphCompare>();
Vector<StringName> unique_names;
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
// Filter out undesired values.
if (!p_filter.is_subsequence_ofi(String(E->get()))) {
continue;
}
// Skip duplicate values.
if (unique_names.has(E->get())) {
continue;
}
unique_names.append(E->get());
Ref<Texture2D> item_icon;
if (E->get() == "") {
item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
} else {
item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
}
add_type_options->add_item(E->get(), item_icon);
}
}
void ThemeTypeDialog::_add_type_filter_cbk(const String &p_value) {
_update_add_type_options(p_value);
}
void ThemeTypeDialog::_add_type_options_cbk(int p_index) {
add_type_filter->set_text(add_type_options->get_item_text(p_index));
}
void ThemeTypeDialog::_add_type_dialog_entered(const String &p_value) {
emit_signal("type_selected", p_value.strip_edges());
hide();
}
void ThemeTypeDialog::_add_type_dialog_activated(int p_index) {
emit_signal("type_selected", add_type_options->get_item_text(p_index));
hide();
}
void ThemeTypeDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
connect("about_to_popup", callable_mp(this, &ThemeTypeDialog::_dialog_about_to_show));
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
_update_add_type_options();
} break;
}
}
void ThemeTypeDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo("type_selected", PropertyInfo(Variant::STRING, "type_name")));
}
void ThemeTypeDialog::set_edited_theme(const Ref<Theme> &p_theme) {
edited_theme = p_theme;
}
void ThemeTypeDialog::set_include_own_types(bool p_enable) {
include_own_types = p_enable;
}
ThemeTypeDialog::ThemeTypeDialog() {
VBoxContainer *add_type_vb = memnew(VBoxContainer);
add_child(add_type_vb);
Label *add_type_filter_label = memnew(Label);
add_type_filter_label->set_text(TTR("Name:"));
add_type_vb->add_child(add_type_filter_label);
add_type_filter = memnew(LineEdit);
add_type_vb->add_child(add_type_filter);
add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeDialog::_add_type_filter_cbk));
add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_entered));
Label *add_type_options_label = memnew(Label);
add_type_options_label->set_text(TTR("Node Types:"));
add_type_vb->add_child(add_type_options_label);
add_type_options = memnew(ItemList);
add_type_options->set_v_size_flags(Control::SIZE_EXPAND_FILL);
add_type_vb->add_child(add_type_options);
add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeDialog::_add_type_options_cbk));
add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_activated));
}
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
VBoxContainer *items_tab = memnew(VBoxContainer);
items_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
@@ -2048,36 +2159,18 @@ void ThemeTypeEditor::_update_type_list_debounced() {
update_debounce_timer->start();
}
void ThemeTypeEditor::_update_add_type_options(const String &p_filter) {
add_type_options->clear();
List<StringName> names;
Theme::get_default()->get_type_list(&names);
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!p_filter.is_subsequence_ofi(String(E->get()))) {
continue;
}
Ref<Texture2D> item_icon;
if (E->get() == "") {
item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
} else {
item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
}
add_type_options->add_item(E->get(), item_icon);
}
}
OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
OrderedHashMap<StringName, bool> items;
List<StringName> names;
if (include_default) {
names.clear();
(Theme::get_default().operator->()->*get_list_func)(p_type_name, &names);
String default_type = p_type_name;
if (edited_theme->get_type_variation_base(p_type_name) != StringName()) {
default_type = edited_theme->get_type_variation_base(p_type_name);
}
(Theme::get_default().operator->()->*get_list_func)(default_type, &names);
names.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
items[E->get()] = false;
@@ -2435,6 +2528,20 @@ void ThemeTypeEditor::_update_type_items() {
stylebox_items_list->add_child(item_control);
}
}
// Various type settings.
if (ClassDB::class_exists(edited_type)) {
type_variation_edit->set_editable(false);
type_variation_edit->set_tooltip(TTR("A type associated with a built-in class cannot be marked as a variation of another type."));
type_variation_edit->set_text("");
type_variation_button->hide();
} else {
type_variation_edit->set_editable(true);
type_variation_edit->set_tooltip("");
type_variation_edit->set_text(edited_theme->get_type_variation_base(edited_type));
_add_focusable(type_variation_edit);
type_variation_button->show();
}
}
void ThemeTypeEditor::_list_type_selected(int p_index) {
@@ -2443,34 +2550,18 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
}
void ThemeTypeEditor::_add_type_button_cbk() {
add_type_mode = ADD_THEME_TYPE;
add_type_dialog->set_title(TTR("Add Item Type"));
add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
add_type_filter->grab_focus();
}
void ThemeTypeEditor::_add_type_filter_cbk(const String &p_value) {
_update_add_type_options(p_value);
}
void ThemeTypeEditor::_add_type_options_cbk(int p_index) {
add_type_filter->set_text(add_type_options->get_item_text(p_index));
}
void ThemeTypeEditor::_add_type_dialog_confirmed() {
select_type(add_type_filter->get_text().strip_edges());
}
void ThemeTypeEditor::_add_type_dialog_entered(const String &p_value) {
select_type(p_value.strip_edges());
add_type_dialog->hide();
}
void ThemeTypeEditor::_add_type_dialog_activated(int p_index) {
select_type(add_type_options->get_item_text(p_index));
add_type_dialog->hide();
}
void ThemeTypeEditor::_add_default_type_items() {
List<StringName> names;
String default_type = edited_type;
if (edited_theme->get_type_variation_base(edited_type) != StringName()) {
default_type = edited_theme->get_type_variation_base(edited_type);
}
updating = true;
// Prevent changes from immediatelly being reported while the operation is still ongoing.
@@ -2478,7 +2569,7 @@ void ThemeTypeEditor::_add_default_type_items() {
{
names.clear();
Theme::get_default()->get_icon_list(edited_type, &names);
Theme::get_default()->get_icon_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_icon(E->get(), edited_type)) {
edited_theme->set_icon(E->get(), edited_type, Ref<Texture2D>());
@@ -2487,7 +2578,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
Theme::get_default()->get_stylebox_list(edited_type, &names);
Theme::get_default()->get_stylebox_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_stylebox(E->get(), edited_type)) {
edited_theme->set_stylebox(E->get(), edited_type, Ref<StyleBox>());
@@ -2496,7 +2587,7 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
Theme::get_default()->get_font_list(edited_type, &names);
Theme::get_default()->get_font_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font(E->get(), edited_type)) {
edited_theme->set_font(E->get(), edited_type, Ref<Font>());
@@ -2505,28 +2596,28 @@ void ThemeTypeEditor::_add_default_type_items() {
}
{
names.clear();
Theme::get_default()->get_font_size_list(edited_type, &names);
Theme::get_default()->get_font_size_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_font_size(E->get(), edited_type)) {
edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), edited_type));
edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), default_type));
}
}
}
{
names.clear();
Theme::get_default()->get_color_list(edited_type, &names);
Theme::get_default()->get_color_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_color(E->get(), edited_type)) {
edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), edited_type));
edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), default_type));
}
}
}
{
names.clear();
Theme::get_default()->get_constant_list(edited_type, &names);
Theme::get_default()->get_constant_list(default_type, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
if (!edited_theme->has_constant(E->get(), edited_type)) {
edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), edited_type));
edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), default_type));
}
}
}
@@ -2817,6 +2908,30 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
edited_theme->_unfreeze_and_propagate_changes();
}
void ThemeTypeEditor::_type_variation_changed(const String p_value) {
if (p_value.is_empty()) {
edited_theme->clear_type_variation(edited_type);
} else {
edited_theme->set_type_variation(edited_type, StringName(p_value));
}
}
void ThemeTypeEditor::_add_type_variation_cbk() {
add_type_mode = ADD_VARIATION_BASE;
add_type_dialog->set_title(TTR("Add Variation Base Type"));
add_type_dialog->set_include_own_types(true);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
void ThemeTypeEditor::_add_type_dialog_selected(const String p_type_name) {
if (add_type_mode == ADD_THEME_TYPE) {
select_type(p_type_name);
} else if (add_type_mode == ADD_VARIATION_BASE) {
_type_variation_changed(p_type_name);
_update_type_items();
}
}
void ThemeTypeEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
@@ -2829,11 +2944,12 @@ void ThemeTypeEditor::_notification(int p_what) {
data_type_tabs->set_tab_icon(3, get_theme_icon("FontSize", "EditorIcons"));
data_type_tabs->set_tab_icon(4, get_theme_icon("ImageTexture", "EditorIcons"));
data_type_tabs->set_tab_icon(5, get_theme_icon("StyleBoxFlat", "EditorIcons"));
data_type_tabs->set_tab_icon(6, get_theme_icon("Tools", "EditorIcons"));
data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox("tab_selected_odd", "TabContainer"));
data_type_tabs->add_theme_style_override("panel", get_theme_stylebox("panel_odd", "TabContainer"));
_update_add_type_options();
type_variation_button->set_icon(get_theme_icon("Add", "EditorIcons"));
} break;
}
}
@@ -2846,6 +2962,8 @@ void ThemeTypeEditor::set_edited_theme(const Ref<Theme> &p_theme) {
edited_theme = p_theme;
edited_theme->connect("changed", callable_mp(this, &ThemeTypeEditor::_update_type_list_debounced));
_update_type_list();
add_type_dialog->set_edited_theme(edited_theme);
}
void ThemeTypeEditor::select_type(String p_type_name) {
@@ -2892,34 +3010,10 @@ ThemeTypeEditor::ThemeTypeEditor() {
theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected));
add_type_button = memnew(Button);
add_type_button->set_tooltip(TTR("Add Type"));
add_type_button->set_tooltip(TTR("Add a type from a list of available types or create a new one."));
type_list_hb->add_child(add_type_button);
add_type_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk));
add_type_dialog = memnew(ConfirmationDialog);
add_type_dialog->set_title(TTR("Add Item Type"));
type_list_hb->add_child(add_type_dialog);
add_type_dialog->connect("confirmed", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_confirmed));
VBoxContainer *add_type_vb = memnew(VBoxContainer);
add_type_dialog->add_child(add_type_vb);
Label *add_type_filter_label = memnew(Label);
add_type_filter_label->set_text(TTR("Name:"));
add_type_vb->add_child(add_type_filter_label);
add_type_filter = memnew(LineEdit);
add_type_vb->add_child(add_type_filter);
add_type_filter->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_add_type_filter_cbk));
add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_entered));
Label *add_type_options_label = memnew(Label);
add_type_options_label->set_text(TTR("Node Types:"));
add_type_vb->add_child(add_type_options_label);
add_type_options = memnew(ItemList);
add_type_options->set_v_size_flags(SIZE_EXPAND_FILL);
add_type_vb->add_child(add_type_options);
add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_add_type_options_cbk));
add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_activated));
HBoxContainer *type_controls = memnew(HBoxContainer);
main_vb->add_child(type_controls);
@@ -2950,6 +3044,39 @@ ThemeTypeEditor::ThemeTypeEditor() {
icon_items_list = _create_item_list(Theme::DATA_TYPE_ICON);
stylebox_items_list = _create_item_list(Theme::DATA_TYPE_STYLEBOX);
VBoxContainer *type_settings_tab = memnew(VBoxContainer);
type_settings_tab->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
data_type_tabs->add_child(type_settings_tab);
data_type_tabs->set_tab_title(data_type_tabs->get_tab_count() - 1, "");
ScrollContainer *type_settings_sc = memnew(ScrollContainer);
type_settings_sc->set_v_size_flags(SIZE_EXPAND_FILL);
type_settings_sc->set_enable_h_scroll(false);
type_settings_tab->add_child(type_settings_sc);
VBoxContainer *type_settings_list = memnew(VBoxContainer);
type_settings_list->set_h_size_flags(SIZE_EXPAND_FILL);
type_settings_sc->add_child(type_settings_list);
HBoxContainer *type_variation_hb = memnew(HBoxContainer);
type_settings_list->add_child(type_variation_hb);
Label *type_variation_label = memnew(Label);
type_variation_hb->add_child(type_variation_label);
type_variation_label->set_text(TTR("Base Type"));
type_variation_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
type_variation_edit = memnew(LineEdit);
type_variation_hb->add_child(type_variation_edit);
type_variation_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
type_variation_edit->connect("text_changed", callable_mp(this, &ThemeTypeEditor::_type_variation_changed));
type_variation_edit->connect("focus_exited", callable_mp(this, &ThemeTypeEditor::_update_type_items));
type_variation_button = memnew(Button);
type_variation_hb->add_child(type_variation_button);
type_variation_button->set_tooltip(TTR("Select the variation base type from a list of available types."));
type_variation_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_variation_cbk));
add_type_dialog = memnew(ThemeTypeDialog);
add_child(add_type_dialog);
add_type_dialog->connect("type_selected", callable_mp(this, &ThemeTypeEditor::_add_type_dialog_selected));
update_debounce_timer = memnew(Timer);
update_debounce_timer->set_one_shot(true);
update_debounce_timer->set_wait_time(0.5);