summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2021-05-09 14:21:37 +0200
committerGitHub <noreply@github.com>2021-05-09 14:21:37 +0200
commita8a51cd75c94268b7ca8fa1a82a144fd9da9d69e (patch)
treeca3d51aeca18f63e10342176e5f1a94d2d2a3ff7 /editor/plugins
parent8fa82c722694c49c75ba74d8b0e8a2240ad37513 (diff)
parent912420b078fe1727c58cee5de435b3ee6e79fcb6 (diff)
Merge pull request #46808 from pycbouh/theme-editor-better-create-ui
Refactor Create Theme menu in Theme Editor
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/theme_editor_plugin.cpp1698
-rw-r--r--editor/plugins/theme_editor_plugin.h172
2 files changed, 1444 insertions, 426 deletions
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index c765aa0319..36c1bf3a09 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -34,12 +34,1187 @@
#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor/editor_scale.h"
+#include "editor/progress_dialog.h"
#include "scene/gui/progress_bar.h"
+void ThemeItemImportTree::_update_items_tree() {
+ import_items_tree->clear();
+ TreeItem *root = import_items_tree->create_item();
+
+ if (base_theme.is_null()) {
+ return;
+ }
+
+ String filter_text = import_items_filter->get_text();
+
+ List<StringName> types;
+ List<StringName> names;
+ List<StringName> filtered_names;
+ base_theme->get_type_list(&types);
+ types.sort_custom<StringName::AlphCompare>();
+
+ int color_amount = 0;
+ int constant_amount = 0;
+ int font_amount = 0;
+ int font_size_amount = 0;
+ int icon_amount = 0;
+ int stylebox_amount = 0;
+
+ tree_color_items.clear();
+ tree_constant_items.clear();
+ tree_font_items.clear();
+ tree_font_size_items.clear();
+ tree_icon_items.clear();
+ tree_stylebox_items.clear();
+
+ for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ String type_name = (String)E->get();
+
+ TreeItem *type_node = import_items_tree->create_item(root);
+ type_node->set_meta("_can_be_imported", false);
+ type_node->set_collapsed(true);
+ type_node->set_text(0, type_name);
+ type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ type_node->set_checked(IMPORT_ITEM, false);
+ type_node->set_editable(IMPORT_ITEM, true);
+ type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ type_node->set_checked(IMPORT_ITEM_DATA, false);
+ type_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1);
+ bool has_filtered_items = false;
+ bool any_checked = false;
+ bool any_checked_with_data = false;
+
+ for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
+ Theme::DataType dt = (Theme::DataType)i;
+
+ names.clear();
+ filtered_names.clear();
+ base_theme->get_theme_item_list(dt, E->get(), &names);
+
+ bool data_type_has_filtered_items = false;
+
+ for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
+ String item_name = (String)F->get();
+ bool is_item_matching_filter = (item_name.findn(filter_text) > -1);
+ if (!filter_text.is_empty() && !is_matching_filter && !is_item_matching_filter) {
+ continue;
+ }
+
+ // Only mark this if actual items match the filter and not just the type group.
+ if (!filter_text.is_empty() && is_item_matching_filter) {
+ has_filtered_items = true;
+ data_type_has_filtered_items = true;
+ }
+ filtered_names.push_back(F->get());
+ }
+
+ if (filtered_names.size() == 0) {
+ continue;
+ }
+
+ TreeItem *data_type_node = import_items_tree->create_item(type_node);
+ data_type_node->set_meta("_can_be_imported", false);
+ data_type_node->set_metadata(0, i);
+ data_type_node->set_collapsed(!data_type_has_filtered_items);
+ data_type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ data_type_node->set_checked(IMPORT_ITEM, false);
+ data_type_node->set_editable(IMPORT_ITEM, true);
+ data_type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ data_type_node->set_checked(IMPORT_ITEM_DATA, false);
+ data_type_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ List<TreeItem *> *item_list;
+
+ switch (dt) {
+ case Theme::DATA_TYPE_COLOR:
+ data_type_node->set_icon(0, get_theme_icon("Color", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Colors"));
+
+ item_list = &tree_color_items;
+ color_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ data_type_node->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Constants"));
+
+ item_list = &tree_constant_items;
+ constant_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ data_type_node->set_icon(0, get_theme_icon("Font", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Fonts"));
+
+ item_list = &tree_font_items;
+ font_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ data_type_node->set_icon(0, get_theme_icon("FontSize", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Font Sizes"));
+
+ item_list = &tree_font_size_items;
+ font_size_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ data_type_node->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Icons"));
+
+ item_list = &tree_icon_items;
+ icon_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ data_type_node->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ data_type_node->set_text(0, TTR("Styleboxes"));
+
+ item_list = &tree_stylebox_items;
+ stylebox_amount += filtered_names.size();
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ bool data_type_any_checked = false;
+ bool data_type_any_checked_with_data = false;
+
+ filtered_names.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *F = filtered_names.front(); F; F = F->next()) {
+ TreeItem *item_node = import_items_tree->create_item(data_type_node);
+ item_node->set_meta("_can_be_imported", true);
+ item_node->set_text(0, F->get());
+ item_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
+ item_node->set_checked(IMPORT_ITEM, false);
+ item_node->set_editable(IMPORT_ITEM, true);
+ item_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK);
+ item_node->set_checked(IMPORT_ITEM_DATA, false);
+ item_node->set_editable(IMPORT_ITEM_DATA, true);
+
+ _restore_selected_item(item_node);
+ if (item_node->is_checked(IMPORT_ITEM)) {
+ data_type_any_checked = true;
+ any_checked = true;
+ }
+ if (item_node->is_checked(IMPORT_ITEM_DATA)) {
+ data_type_any_checked_with_data = true;
+ any_checked_with_data = true;
+ }
+
+ item_list->push_back(item_node);
+ }
+
+ data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked);
+ data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data);
+ }
+
+ // Remove the item if it doesn't match the filter in any way.
+ if (!is_matching_filter && !has_filtered_items) {
+ root->remove_child(type_node);
+ memdelete(type_node);
+ continue;
+ }
+
+ // Show one level inside of a type group if there are matches in items.
+ if (!filter_text.is_empty() && has_filtered_items) {
+ type_node->set_collapsed(false);
+ }
+
+ type_node->set_checked(IMPORT_ITEM, any_checked);
+ type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
+ }
+
+ if (color_amount > 0) {
+ Array arr;
+ arr.push_back(color_amount);
+ select_colors_label->set_text(TTRN("One color", "{num} colors", color_amount).format(arr, "{num}"));
+ select_all_colors_button->set_visible(true);
+ select_full_colors_button->set_visible(true);
+ deselect_all_colors_button->set_visible(true);
+ } else {
+ select_colors_label->set_text(TTR("No colors found."));
+ select_all_colors_button->set_visible(false);
+ select_full_colors_button->set_visible(false);
+ deselect_all_colors_button->set_visible(false);
+ }
+
+ if (constant_amount > 0) {
+ Array arr;
+ arr.push_back(constant_amount);
+ select_constants_label->set_text(TTRN("One constant", "{num} constants", constant_amount).format(arr, "{num}"));
+ select_all_constants_button->set_visible(true);
+ select_full_constants_button->set_visible(true);
+ deselect_all_constants_button->set_visible(true);
+ } else {
+ select_constants_label->set_text(TTR("No constants found."));
+ select_all_constants_button->set_visible(false);
+ select_full_constants_button->set_visible(false);
+ deselect_all_constants_button->set_visible(false);
+ }
+
+ if (font_amount > 0) {
+ Array arr;
+ arr.push_back(font_amount);
+ select_fonts_label->set_text(TTRN("One font", "{num} fonts", font_amount).format(arr, "{num}"));
+ select_all_fonts_button->set_visible(true);
+ select_full_fonts_button->set_visible(true);
+ deselect_all_fonts_button->set_visible(true);
+ } else {
+ select_fonts_label->set_text(TTR("No fonts found."));
+ select_all_fonts_button->set_visible(false);
+ select_full_fonts_button->set_visible(false);
+ deselect_all_fonts_button->set_visible(false);
+ }
+
+ if (font_size_amount > 0) {
+ Array arr;
+ arr.push_back(font_size_amount);
+ select_font_sizes_label->set_text(TTRN("One font size", "{num} font sizes", font_size_amount).format(arr, "{num}"));
+ select_all_font_sizes_button->set_visible(true);
+ select_full_font_sizes_button->set_visible(true);
+ deselect_all_font_sizes_button->set_visible(true);
+ } else {
+ select_font_sizes_label->set_text(TTR("No font sizes found."));
+ select_all_font_sizes_button->set_visible(false);
+ select_full_font_sizes_button->set_visible(false);
+ deselect_all_font_sizes_button->set_visible(false);
+ }
+
+ if (icon_amount > 0) {
+ Array arr;
+ arr.push_back(icon_amount);
+ select_icons_label->set_text(TTRN("One icon", "{num} icons", icon_amount).format(arr, "{num}"));
+ select_all_icons_button->set_visible(true);
+ select_full_icons_button->set_visible(true);
+ deselect_all_icons_button->set_visible(true);
+ select_icons_warning_hb->set_visible(true);
+ } else {
+ select_icons_label->set_text(TTR("No icons found."));
+ select_all_icons_button->set_visible(false);
+ select_full_icons_button->set_visible(false);
+ deselect_all_icons_button->set_visible(false);
+ select_icons_warning_hb->set_visible(false);
+ }
+
+ if (stylebox_amount > 0) {
+ Array arr;
+ arr.push_back(stylebox_amount);
+ select_styleboxes_label->set_text(TTRN("One stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}"));
+ select_all_styleboxes_button->set_visible(true);
+ select_full_styleboxes_button->set_visible(true);
+ deselect_all_styleboxes_button->set_visible(true);
+ } else {
+ select_styleboxes_label->set_text(TTR("No styleboxes found."));
+ select_all_styleboxes_button->set_visible(false);
+ select_full_styleboxes_button->set_visible(false);
+ deselect_all_styleboxes_button->set_visible(false);
+ }
+}
+
+void ThemeItemImportTree::_toggle_type_items(bool p_collapse) {
+ TreeItem *root = import_items_tree->get_root();
+ if (!root) {
+ return;
+ }
+
+ TreeItem *type_node = root->get_children();
+ while (type_node) {
+ type_node->set_collapsed(p_collapse);
+ type_node = type_node->get_next();
+ }
+}
+
+void ThemeItemImportTree::_filter_text_changed(const String &p_value) {
+ _update_items_tree();
+}
+
+void ThemeItemImportTree::_store_selected_item(TreeItem *p_tree_item) {
+ if (!p_tree_item->get_meta("_can_be_imported")) {
+ return;
+ }
+
+ TreeItem *data_type_node = p_tree_item->get_parent();
+ if (!data_type_node || data_type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ TreeItem *type_node = data_type_node->get_parent();
+ if (!type_node || type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ ThemeItem ti;
+ ti.item_name = p_tree_item->get_text(0);
+ ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0);
+ ti.type_name = type_node->get_text(0);
+
+ bool import = p_tree_item->is_checked(IMPORT_ITEM);
+ bool with_data = p_tree_item->is_checked(IMPORT_ITEM_DATA);
+
+ if (import && with_data) {
+ selected_items[ti] = SELECT_IMPORT_FULL;
+ } else if (import) {
+ selected_items[ti] = SELECT_IMPORT_DEFINITION;
+ } else {
+ selected_items.erase(ti);
+ }
+
+ _update_total_selected(ti.data_type);
+}
+
+void ThemeItemImportTree::_restore_selected_item(TreeItem *p_tree_item) {
+ if (!p_tree_item->get_meta("_can_be_imported")) {
+ return;
+ }
+
+ TreeItem *data_type_node = p_tree_item->get_parent();
+ if (!data_type_node || data_type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ TreeItem *type_node = data_type_node->get_parent();
+ if (!type_node || type_node == import_items_tree->get_root()) {
+ return;
+ }
+
+ ThemeItem ti;
+ ti.item_name = p_tree_item->get_text(0);
+ ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0);
+ ti.type_name = type_node->get_text(0);
+
+ if (!selected_items.has(ti)) {
+ p_tree_item->set_checked(IMPORT_ITEM, false);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, false);
+ return;
+ }
+
+ if (selected_items[ti] == SELECT_IMPORT_FULL) {
+ p_tree_item->set_checked(IMPORT_ITEM, true);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, true);
+ } else if (selected_items[ti] == SELECT_IMPORT_DEFINITION) {
+ p_tree_item->set_checked(IMPORT_ITEM, true);
+ p_tree_item->set_checked(IMPORT_ITEM_DATA, false);
+ }
+}
+
+void ThemeItemImportTree::_update_total_selected(Theme::DataType p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ Label *total_selected_items_label;
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ total_selected_items_label = total_selected_colors_label;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ total_selected_items_label = total_selected_constants_label;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ total_selected_items_label = total_selected_fonts_label;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ total_selected_items_label = total_selected_font_sizes_label;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ total_selected_items_label = total_selected_icons_label;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ total_selected_items_label = total_selected_styleboxes_label;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ if (!total_selected_items_label) {
+ return;
+ }
+
+ int count = 0;
+ for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) {
+ ThemeItem ti = E->key();
+ if (ti.data_type == p_data_type) {
+ count++;
+ }
+ }
+
+ if (count == 0) {
+ total_selected_items_label->hide();
+ } else {
+ Array arr;
+ arr.push_back(count);
+ total_selected_items_label->set_text(TTRN("{num} currently selected", "{num} currently selected", count).format(arr, "{num}"));
+ total_selected_items_label->show();
+ }
+}
+
+void ThemeItemImportTree::_tree_item_edited() {
+ if (updating_tree) {
+ return;
+ }
+
+ TreeItem *edited_item = import_items_tree->get_edited();
+ if (!edited_item) {
+ return;
+ }
+
+ updating_tree = true;
+
+ int edited_column = import_items_tree->get_edited_column();
+ bool is_checked = edited_item->is_checked(edited_column);
+ if (is_checked) {
+ if (edited_column == IMPORT_ITEM_DATA) {
+ edited_item->set_checked(IMPORT_ITEM, true);
+ }
+
+ _select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA));
+ } else {
+ if (edited_column == IMPORT_ITEM) {
+ edited_item->set_checked(IMPORT_ITEM_DATA, false);
+ }
+
+ _deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM));
+ }
+
+ _update_parent_items(edited_item);
+ _store_selected_item(edited_item);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
+ TreeItem *child_item = p_root_item->get_children();
+ while (child_item) {
+ child_item->set_checked(IMPORT_ITEM, true);
+ if (p_select_with_data) {
+ child_item->set_checked(IMPORT_ITEM_DATA, true);
+ }
+ _store_selected_item(child_item);
+
+ _select_all_subitems(child_item, p_select_with_data);
+ child_item = child_item->get_next();
+ }
+}
+
+void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely) {
+ TreeItem *child_item = p_root_item->get_children();
+ while (child_item) {
+ child_item->set_checked(IMPORT_ITEM_DATA, false);
+ if (p_deselect_completely) {
+ child_item->set_checked(IMPORT_ITEM, false);
+ }
+ _store_selected_item(child_item);
+
+ _deselect_all_subitems(child_item, p_deselect_completely);
+ child_item = child_item->get_next();
+ }
+}
+
+void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) {
+ TreeItem *parent_item = p_root_item->get_parent();
+ if (!parent_item) {
+ return;
+ }
+
+ bool any_checked = false;
+ bool any_checked_with_data = false;
+
+ TreeItem *child_item = parent_item->get_children();
+ while (child_item) {
+ if (child_item->is_checked(IMPORT_ITEM)) {
+ any_checked = true;
+ }
+ if (child_item->is_checked(IMPORT_ITEM_DATA)) {
+ any_checked_with_data = true;
+ }
+
+ child_item = child_item->get_next();
+ }
+
+ parent_item->set_checked(IMPORT_ITEM, any_checked);
+ parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
+ _update_parent_items(parent_item);
+}
+
+void ThemeItemImportTree::_select_all_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _select_all_subitems(root, false);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_full_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _select_all_subitems(root, true);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_deselect_all_items_pressed() {
+ if (updating_tree) {
+ return;
+ }
+
+ updating_tree = true;
+
+ TreeItem *root = import_items_tree->get_root();
+ _deselect_all_subitems(root, true);
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, true);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, true);
+ child_item->set_checked(IMPORT_ITEM_DATA, true);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ if (updating_tree) {
+ return;
+ }
+
+ Theme::DataType data_type = (Theme::DataType)p_data_type;
+ List<TreeItem *> *item_list;
+
+ switch (data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_list = &tree_color_items;
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_list = &tree_constant_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_list = &tree_font_items;
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_list = &tree_font_size_items;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_list = &tree_icon_items;
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_list = &tree_stylebox_items;
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ return; // Can't happen, but silences warning.
+ }
+
+ updating_tree = true;
+
+ for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) {
+ TreeItem *child_item = E->get();
+ if (!child_item) {
+ continue;
+ }
+
+ child_item->set_checked(IMPORT_ITEM, false);
+ child_item->set_checked(IMPORT_ITEM_DATA, false);
+ _update_parent_items(child_item);
+ _store_selected_item(child_item);
+ }
+
+ updating_tree = false;
+}
+
+void ThemeItemImportTree::_import_selected() {
+ if (selected_items.size() == 0) {
+ EditorNode::get_singleton()->show_accept(TTR("Nothing was selected for the import."), TTR("OK"));
+ return;
+ }
+
+ ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size());
+
+ int idx = 0;
+ for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) {
+ // Arbitrary number of items to skip from reporting.
+ // Reduces the number of UI updates that this causes when copying large themes.
+ if (idx % 10 == 0) {
+ Array arr;
+ arr.push_back(idx + 1);
+ arr.push_back(selected_items.size());
+ ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Importing items {n}/{n}").format(arr, "{n}"), idx);
+ }
+
+ ItemCheckedState cs = E->get();
+ ThemeItem ti = E->key();
+
+ if (cs == SELECT_IMPORT_DEFINITION || cs == SELECT_IMPORT_FULL) {
+ Variant item_value = Variant();
+
+ if (cs == SELECT_IMPORT_FULL) {
+ item_value = base_theme->get_theme_item(ti.data_type, ti.item_name, ti.type_name);
+ } else {
+ switch (ti.data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ item_value = Color();
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ item_value = 0;
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ item_value = Ref<Font>();
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ item_value = -1;
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ item_value = Ref<Texture2D>();
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ item_value = Ref<StyleBox>();
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+ }
+
+ edited_theme->set_theme_item(ti.data_type, ti.item_name, ti.type_name, item_value);
+ }
+
+ idx++;
+ }
+
+ ProgressDialog::get_singleton()->end_task("import_theme_items");
+ emit_signal("items_imported");
+}
+
+void ThemeItemImportTree::set_edited_theme(const Ref<Theme> &p_theme) {
+ edited_theme = p_theme;
+}
+
+void ThemeItemImportTree::set_base_theme(const Ref<Theme> &p_theme) {
+ base_theme = p_theme;
+}
+
+void ThemeItemImportTree::reset_item_tree() {
+ import_items_filter->clear();
+ selected_items.clear();
+
+ total_selected_colors_label->hide();
+ total_selected_constants_label->hide();
+ total_selected_fonts_label->hide();
+ total_selected_font_sizes_label->hide();
+ total_selected_icons_label->hide();
+ total_selected_styleboxes_label->hide();
+
+ _update_items_tree();
+}
+
+bool ThemeItemImportTree::has_selected_items() const {
+ return (selected_items.size() > 0);
+}
+
+void ThemeItemImportTree::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ select_icons_warning_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons"));
+ select_icons_warning->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor"));
+
+ // Bottom panel buttons.
+ import_collapse_types_button->set_icon(get_theme_icon("CollapseTree", "EditorIcons"));
+ import_expand_types_button->set_icon(get_theme_icon("ExpandTree", "EditorIcons"));
+
+ import_select_all_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ import_select_full_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+ import_deselect_all_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+
+ // Side panel buttons.
+ select_colors_icon->set_texture(get_theme_icon("Color", "EditorIcons"));
+ deselect_all_colors_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_colors_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_colors_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_constants_icon->set_texture(get_theme_icon("MemberConstant", "EditorIcons"));
+ deselect_all_constants_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_constants_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_constants_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_fonts_icon->set_texture(get_theme_icon("Font", "EditorIcons"));
+ deselect_all_fonts_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_fonts_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_fonts_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_font_sizes_icon->set_texture(get_theme_icon("FontSize", "EditorIcons"));
+ deselect_all_font_sizes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_font_sizes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_font_sizes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_icons_icon->set_texture(get_theme_icon("ImageTexture", "EditorIcons"));
+ deselect_all_icons_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_icons_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_icons_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+
+ select_styleboxes_icon->set_texture(get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ deselect_all_styleboxes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons"));
+ select_all_styleboxes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons"));
+ select_full_styleboxes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons"));
+ } break;
+ }
+}
+
+void ThemeItemImportTree::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("items_imported"));
+}
+
+ThemeItemImportTree::ThemeItemImportTree() {
+ HBoxContainer *import_items_filter_hb = memnew(HBoxContainer);
+ add_child(import_items_filter_hb);
+ Label *import_items_filter_label = memnew(Label);
+ import_items_filter_label->set_text(TTR("Filter:"));
+ import_items_filter_hb->add_child(import_items_filter_label);
+ import_items_filter = memnew(LineEdit);
+ import_items_filter->set_clear_button_enabled(true);
+ import_items_filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_items_filter_hb->add_child(import_items_filter);
+ import_items_filter->connect("text_changed", callable_mp(this, &ThemeItemImportTree::_filter_text_changed));
+
+ HBoxContainer *import_main_hb = memnew(HBoxContainer);
+ import_main_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(import_main_hb);
+
+ import_items_tree = memnew(Tree);
+ import_items_tree->set_hide_root(true);
+ import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_main_hb->add_child(import_items_tree);
+ import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited));
+
+ import_items_tree->set_columns(3);
+ import_items_tree->set_column_titles_visible(true);
+ import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import"));
+ import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data"));
+ import_items_tree->set_column_expand(0, true);
+ import_items_tree->set_column_expand(IMPORT_ITEM, false);
+ import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false);
+ import_items_tree->set_column_min_width(0, 160 * EDSCALE);
+ import_items_tree->set_column_min_width(IMPORT_ITEM, 80 * EDSCALE);
+ import_items_tree->set_column_min_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+
+ ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
+ import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
+ import_bulk_sc->set_enable_h_scroll(false);
+ import_main_hb->add_child(import_bulk_sc);
+ VBoxContainer *import_bulk_vb = memnew(VBoxContainer);
+ import_bulk_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_bulk_sc->add_child(import_bulk_vb);
+
+ Label *import_bulk_label = memnew(Label);
+ import_bulk_label->set_text(TTR("Select by data type:"));
+ import_bulk_vb->add_child(import_bulk_label);
+
+ select_colors_icon = memnew(TextureRect);
+ select_colors_label = memnew(Label);
+ deselect_all_colors_button = memnew(Button);
+ select_all_colors_button = memnew(Button);
+ select_full_colors_button = memnew(Button);
+ total_selected_colors_label = memnew(Label);
+
+ select_constants_icon = memnew(TextureRect);
+ select_constants_label = memnew(Label);
+ deselect_all_constants_button = memnew(Button);
+ select_all_constants_button = memnew(Button);
+ select_full_constants_button = memnew(Button);
+ total_selected_constants_label = memnew(Label);
+
+ select_fonts_icon = memnew(TextureRect);
+ select_fonts_label = memnew(Label);
+ deselect_all_fonts_button = memnew(Button);
+ select_all_fonts_button = memnew(Button);
+ select_full_fonts_button = memnew(Button);
+ total_selected_fonts_label = memnew(Label);
+
+ select_font_sizes_icon = memnew(TextureRect);
+ select_font_sizes_label = memnew(Label);
+ deselect_all_font_sizes_button = memnew(Button);
+ select_all_font_sizes_button = memnew(Button);
+ select_full_font_sizes_button = memnew(Button);
+ total_selected_font_sizes_label = memnew(Label);
+
+ select_icons_icon = memnew(TextureRect);
+ select_icons_label = memnew(Label);
+ deselect_all_icons_button = memnew(Button);
+ select_all_icons_button = memnew(Button);
+ select_full_icons_button = memnew(Button);
+ total_selected_icons_label = memnew(Label);
+
+ select_styleboxes_icon = memnew(TextureRect);
+ select_styleboxes_label = memnew(Label);
+ deselect_all_styleboxes_button = memnew(Button);
+ select_all_styleboxes_button = memnew(Button);
+ select_full_styleboxes_button = memnew(Button);
+ total_selected_styleboxes_label = memnew(Label);
+
+ for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
+ Theme::DataType dt = (Theme::DataType)i;
+
+ TextureRect *select_items_icon;
+ Label *select_items_label;
+ Button *deselect_all_items_button;
+ Button *select_all_items_button;
+ Button *select_full_items_button;
+ Label *total_selected_items_label;
+
+ String items_title = "";
+ String select_all_items_tooltip = "";
+ String select_full_items_tooltip = "";
+ String deselect_all_items_tooltip = "";
+
+ switch (dt) {
+ case Theme::DATA_TYPE_COLOR:
+ select_items_icon = select_colors_icon;
+ select_items_label = select_colors_label;
+ deselect_all_items_button = deselect_all_colors_button;
+ select_all_items_button = select_all_colors_button;
+ select_full_items_button = select_full_colors_button;
+ total_selected_items_label = total_selected_colors_label;
+
+ items_title = TTR("Colors");
+ select_all_items_tooltip = TTR("Select all visible color items.");
+ select_full_items_tooltip = TTR("Select all visible color items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible color items.");
+ break;
+
+ case Theme::DATA_TYPE_CONSTANT:
+ select_items_icon = select_constants_icon;
+ select_items_label = select_constants_label;
+ deselect_all_items_button = deselect_all_constants_button;
+ select_all_items_button = select_all_constants_button;
+ select_full_items_button = select_full_constants_button;
+ total_selected_items_label = total_selected_constants_label;
+
+ items_title = TTR("Constants");
+ select_all_items_tooltip = TTR("Select all visible constant items.");
+ select_full_items_tooltip = TTR("Select all visible constant items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible constant items.");
+ break;
+
+ case Theme::DATA_TYPE_FONT:
+ select_items_icon = select_fonts_icon;
+ select_items_label = select_fonts_label;
+ deselect_all_items_button = deselect_all_fonts_button;
+ select_all_items_button = select_all_fonts_button;
+ select_full_items_button = select_full_fonts_button;
+ total_selected_items_label = total_selected_fonts_label;
+
+ items_title = TTR("Fonts");
+ select_all_items_tooltip = TTR("Select all visible font items.");
+ select_full_items_tooltip = TTR("Select all visible font items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible font items.");
+ break;
+
+ case Theme::DATA_TYPE_FONT_SIZE:
+ select_items_icon = select_font_sizes_icon;
+ select_items_label = select_font_sizes_label;
+ deselect_all_items_button = deselect_all_font_sizes_button;
+ select_all_items_button = select_all_font_sizes_button;
+ select_full_items_button = select_full_font_sizes_button;
+ total_selected_items_label = total_selected_font_sizes_label;
+
+ items_title = TTR("Font sizes");
+ select_all_items_tooltip = TTR("Select all visible font size items.");
+ select_full_items_tooltip = TTR("Select all visible font size items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible font size items.");
+ break;
+
+ case Theme::DATA_TYPE_ICON:
+ select_items_icon = select_icons_icon;
+ select_items_label = select_icons_label;
+ deselect_all_items_button = deselect_all_icons_button;
+ select_all_items_button = select_all_icons_button;
+ select_full_items_button = select_full_icons_button;
+ total_selected_items_label = total_selected_icons_label;
+
+ items_title = TTR("Icons");
+ select_all_items_tooltip = TTR("Select all visible icon items.");
+ select_full_items_tooltip = TTR("Select all visible icon items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible icon items.");
+ break;
+
+ case Theme::DATA_TYPE_STYLEBOX:
+ select_items_icon = select_styleboxes_icon;
+ select_items_label = select_styleboxes_label;
+ deselect_all_items_button = deselect_all_styleboxes_button;
+ select_all_items_button = select_all_styleboxes_button;
+ select_full_items_button = select_full_styleboxes_button;
+ total_selected_items_label = total_selected_styleboxes_label;
+
+ items_title = TTR("Styleboxes");
+ select_all_items_tooltip = TTR("Select all visible stylebox items.");
+ select_full_items_tooltip = TTR("Select all visible stylebox items and their data.");
+ deselect_all_items_tooltip = TTR("Deselect all visible stylebox items.");
+ break;
+
+ case Theme::DATA_TYPE_MAX:
+ continue; // Can't happen, but silences warning.
+ }
+
+ if (i > 0) {
+ import_bulk_vb->add_child(memnew(HSeparator));
+ }
+
+ HBoxContainer *all_set = memnew(HBoxContainer);
+ import_bulk_vb->add_child(all_set);
+
+ HBoxContainer *label_set = memnew(HBoxContainer);
+ label_set->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ all_set->add_child(label_set);
+ select_items_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ label_set->add_child(select_items_icon);
+ select_items_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_items_label->set_clip_text(true);
+ select_items_label->set_text(items_title);
+ label_set->add_child(select_items_label);
+
+ HBoxContainer *button_set = memnew(HBoxContainer);
+ button_set->set_alignment(BoxContainer::ALIGN_END);
+ all_set->add_child(button_set);
+ select_all_items_button->set_flat(true);
+ select_all_items_button->set_tooltip(select_all_items_tooltip);
+ button_set->add_child(select_all_items_button);
+ select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed), varray(i));
+ select_full_items_button->set_flat(true);
+ select_full_items_button->set_tooltip(select_full_items_tooltip);
+ button_set->add_child(select_full_items_button);
+ select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed), varray(i));
+ deselect_all_items_button->set_flat(true);
+ deselect_all_items_button->set_tooltip(deselect_all_items_tooltip);
+ button_set->add_child(deselect_all_items_button);
+ deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed), varray(i));
+
+ total_selected_items_label->set_align(Label::ALIGN_RIGHT);
+ total_selected_items_label->hide();
+ import_bulk_vb->add_child(total_selected_items_label);
+
+ if (dt == Theme::DATA_TYPE_ICON) {
+ select_icons_warning_hb = memnew(HBoxContainer);
+ import_bulk_vb->add_child(select_icons_warning_hb);
+
+ select_icons_warning_icon = memnew(TextureRect);
+ select_icons_warning_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ select_icons_warning_hb->add_child(select_icons_warning_icon);
+
+ select_icons_warning = memnew(Label);
+ select_icons_warning->set_text(TTR("Caution: Adding icon data may considerably increase the size of your Theme resource."));
+ select_icons_warning->set_autowrap(true);
+ select_icons_warning->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_icons_warning_hb->add_child(select_icons_warning);
+ }
+ }
+
+ add_child(memnew(HSeparator));
+
+ HBoxContainer *import_buttons = memnew(HBoxContainer);
+ add_child(import_buttons);
+
+ import_collapse_types_button = memnew(Button);
+ import_collapse_types_button->set_flat(true);
+ import_collapse_types_button->set_tooltip(TTR("Collapse types."));
+ import_buttons->add_child(import_collapse_types_button);
+ import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(true));
+ import_expand_types_button = memnew(Button);
+ import_expand_types_button->set_flat(true);
+ import_expand_types_button->set_tooltip(TTR("Expand types."));
+ import_buttons->add_child(import_expand_types_button);
+ import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(false));
+
+ import_buttons->add_child(memnew(VSeparator));
+
+ import_select_all_button = memnew(Button);
+ import_select_all_button->set_flat(true);
+ import_select_all_button->set_text(TTR("Select All"));
+ import_select_all_button->set_tooltip(TTR("Select all Theme items."));
+ import_buttons->add_child(import_select_all_button);
+ import_select_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_items_pressed));
+ import_select_full_button = memnew(Button);
+ import_select_full_button->set_flat(true);
+ import_select_full_button->set_text(TTR("Select With Data"));
+ import_select_full_button->set_tooltip(TTR("Select all Theme items with item data."));
+ import_buttons->add_child(import_select_full_button);
+ import_select_full_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_items_pressed));
+ import_deselect_all_button = memnew(Button);
+ import_deselect_all_button->set_flat(true);
+ import_deselect_all_button->set_text(TTR("Deselect All"));
+ import_deselect_all_button->set_tooltip(TTR("Deselect all Theme items."));
+ import_buttons->add_child(import_deselect_all_button);
+ import_deselect_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_items_pressed));
+
+ import_buttons->add_spacer();
+
+ Button *import_add_selected_button = memnew(Button);
+ import_add_selected_button->set_text(TTR("Import Selected"));
+ import_buttons->add_child(import_add_selected_button);
+ import_add_selected_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_import_selected));
+}
+
+void ThemeItemEditorDialog::ok_pressed() {
+ if (import_default_theme_items->has_selected_items() || import_editor_theme_items->has_selected_items() || import_other_theme_items->has_selected_items()) {
+ confirm_closing_dialog->set_text(TTR("Import Items tab has some items selected. Selection will be lost upon closing this window.\nClose anyway?"));
+ confirm_closing_dialog->popup_centered(Size2i(380, 120) * EDSCALE);
+ return;
+ }
+
+ hide();
+}
+
+void ThemeItemEditorDialog::_close_dialog() {
+ hide();
+}
+
void ThemeItemEditorDialog::_dialog_about_to_show() {
ERR_FAIL_COND(edited_theme.is_null());
_update_edit_types();
+
+ import_default_theme_items->set_edited_theme(edited_theme);
+ import_default_theme_items->set_base_theme(Theme::get_default());
+ import_default_theme_items->reset_item_tree();
+
+ import_editor_theme_items->set_edited_theme(edited_theme);
+ import_editor_theme_items->set_base_theme(EditorNode::get_singleton()->get_theme_base()->get_theme());
+ import_editor_theme_items->reset_item_tree();
+
+ import_other_theme_items->set_edited_theme(edited_theme);
+ import_other_theme_items->reset_item_tree();
}
void ThemeItemEditorDialog::_update_edit_types() {
@@ -79,11 +1254,6 @@ void ThemeItemEditorDialog::_update_edit_types() {
base_theme->get_type_list(&default_types);
default_types.sort_custom<StringName::AlphCompare>();
- edit_add_class_options->clear();
- for (List<StringName>::Element *E = default_types.front(); E; E = E->next()) {
- edit_add_class_options->add_item(E->get());
- }
-
String selected_type = "";
Vector<int> selected_ids = edit_type_list->get_selected_items();
if (selected_ids.size() > 0) {
@@ -127,7 +1297,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
List<StringName> names;
- {
+ { // Colors.
names.clear();
edited_theme->get_color_list(p_item_type, &names);
@@ -148,7 +1318,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Constants.
names.clear();
edited_theme->get_constant_list(p_item_type, &names);
@@ -169,7 +1339,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Fonts.
names.clear();
edited_theme->get_font_list(p_item_type, &names);
@@ -190,7 +1360,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Font sizes.
names.clear();
edited_theme->get_font_size_list(p_item_type, &names);
@@ -211,7 +1381,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Icons.
names.clear();
edited_theme->get_icon_list(p_item_type, &names);
@@ -232,7 +1402,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
}
}
- {
+ { // Styleboxes.
names.clear();
edited_theme->get_stylebox_list(p_item_type, &names);
@@ -280,64 +1450,13 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu
_update_edit_item_tree(edited_item_type);
}
-void ThemeItemEditorDialog::_add_class_type_items() {
- int selected_idx = edit_add_class_options->get_selected();
- String type_name = edit_add_class_options->get_item_text(selected_idx);
- List<StringName> names;
-
- {
- names.clear();
- Theme::get_default()->get_icon_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_icon(E->get(), type_name, Ref<Texture2D>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_stylebox_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_stylebox(E->get(), type_name, Ref<StyleBox>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_font(E->get(), type_name, Ref<Font>());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_size_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_font_size(E->get(), type_name, Theme::get_default()->get_font_size(E->get(), type_name));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_color_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_color(E->get(), type_name, Theme::get_default()->get_color(E->get(), type_name));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_constant_list(type_name, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->set_constant(E->get(), type_name, Theme::get_default()->get_constant(E->get(), type_name));
- }
- }
-
- _update_edit_types();
-}
-
-void ThemeItemEditorDialog::_add_custom_type() {
- edited_theme->add_icon_type(edit_add_custom_value->get_text());
- edited_theme->add_stylebox_type(edit_add_custom_value->get_text());
- edited_theme->add_font_type(edit_add_custom_value->get_text());
- edited_theme->add_font_size_type(edit_add_custom_value->get_text());
- edited_theme->add_color_type(edit_add_custom_value->get_text());
- edited_theme->add_constant_type(edit_add_custom_value->get_text());
+void ThemeItemEditorDialog::_add_theme_type() {
+ edited_theme->add_icon_type(edit_add_type_value->get_text());
+ edited_theme->add_stylebox_type(edit_add_type_value->get_text());
+ edited_theme->add_font_type(edit_add_type_value->get_text());
+ edited_theme->add_font_size_type(edit_add_type_value->get_text());
+ edited_theme->add_color_type(edit_add_type_value->get_text());
+ edited_theme->add_constant_type(edit_add_type_value->get_text());
_update_edit_types();
}
@@ -536,6 +1655,26 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_
}
}
+void ThemeItemEditorDialog::_open_select_another_theme() {
+ import_another_theme_dialog->popup_file_dialog();
+}
+
+void ThemeItemEditorDialog::_select_another_theme_cbk(const String &p_path) {
+ Ref<Theme> loaded_theme = ResourceLoader::load(p_path);
+ if (loaded_theme.is_null()) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, not a Theme resource."));
+ return;
+ }
+ if (loaded_theme == edited_theme) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, same as the edited Theme resource."));
+ return;
+ }
+
+ import_another_theme_value->set_text(p_path);
+ import_other_theme_items->set_base_theme(loaded_theme);
+ import_other_theme_items->reset_item_tree();
+}
+
void ThemeItemEditorDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -553,6 +1692,8 @@ void ThemeItemEditorDialog::_notification(int p_what) {
edit_items_remove_class->set_icon(get_theme_icon("Control", "EditorIcons"));
edit_items_remove_custom->set_icon(get_theme_icon("ThemeRemoveCustomItems", "EditorIcons"));
edit_items_remove_all->set_icon(get_theme_icon("ThemeRemoveAllItems", "EditorIcons"));
+
+ import_another_theme_button->set_icon(get_theme_icon("Folder", "EditorIcons"));
} break;
}
}
@@ -562,10 +1703,18 @@ void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) {
}
ThemeItemEditorDialog::ThemeItemEditorDialog() {
- set_title(TTR("Edit Theme Items"));
+ set_title(TTR("Manage Theme Items"));
+ get_ok_button()->set_text(TTR("Close"));
+ set_hide_on_ok(false); // Closing may require a confirmation in some cases.
+ TabContainer *tc = memnew(TabContainer);
+ tc->set_tab_align(TabContainer::TabAlign::ALIGN_LEFT);
+ add_child(tc);
+
+ // Edit Items tab.
HSplitContainer *edit_dialog_hs = memnew(HSplitContainer);
- add_child(edit_dialog_hs);
+ tc->add_child(edit_dialog_hs);
+ tc->set_tab_title(0, TTR("Edit Items"));
VBoxContainer *edit_dialog_side_vb = memnew(VBoxContainer);
edit_dialog_side_vb->set_custom_minimum_size(Size2(200.0, 0.0) * EDSCALE);
@@ -580,33 +1729,19 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_dialog_side_vb->add_child(edit_type_list);
edit_type_list->connect("item_selected", callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected));
- Label *edit_add_class_label = memnew(Label);
- edit_add_class_label->set_text(TTR("Add Type from Class:"));
- edit_dialog_side_vb->add_child(edit_add_class_label);
-
- HBoxContainer *edit_add_class = memnew(HBoxContainer);
- edit_dialog_side_vb->add_child(edit_add_class);
- edit_add_class_options = memnew(OptionButton);
- edit_add_class_options->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- edit_add_class->add_child(edit_add_class_options);
- Button *edit_add_class_button = memnew(Button);
- edit_add_class_button->set_text(TTR("Add"));
- edit_add_class->add_child(edit_add_class_button);
- edit_add_class_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_class_type_items));
-
- Label *edit_add_custom_label = memnew(Label);
- edit_add_custom_label->set_text(TTR("Add Custom Type:"));
- edit_dialog_side_vb->add_child(edit_add_custom_label);
-
- HBoxContainer *edit_add_custom = memnew(HBoxContainer);
- edit_dialog_side_vb->add_child(edit_add_custom);
- edit_add_custom_value = memnew(LineEdit);
- edit_add_custom_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- edit_add_custom->add_child(edit_add_custom_value);
- Button *edit_add_custom_button = memnew(Button);
- edit_add_custom_button->set_text(TTR("Add"));
- edit_add_custom->add_child(edit_add_custom_button);
- edit_add_custom_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_custom_type));
+ Label *edit_add_type_label = memnew(Label);
+ edit_add_type_label->set_text(TTR("Add Type:"));
+ edit_dialog_side_vb->add_child(edit_add_type_label);
+
+ HBoxContainer *edit_add_type_hb = memnew(HBoxContainer);
+ edit_dialog_side_vb->add_child(edit_add_type_hb);
+ edit_add_type_value = memnew(LineEdit);
+ edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ edit_add_type_hb->add_child(edit_add_type_value);
+ Button *edit_add_type_button = memnew(Button);
+ edit_add_type_button->set_text(TTR("Add"));
+ edit_add_type_hb->add_child(edit_add_type_button);
+ edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type));
VBoxContainer *edit_items_vb = memnew(VBoxContainer);
edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -616,7 +1751,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_items_vb->add_child(edit_items_toolbar);
Label *edit_items_toolbar_add_label = memnew(Label);
- edit_items_toolbar_add_label->set_text(TTR("Add:"));
+ edit_items_toolbar_add_label->set_text(TTR("Add Item:"));
edit_items_toolbar->add_child(edit_items_toolbar_add_label);
edit_items_add_color = memnew(Button);
@@ -664,7 +1799,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_items_toolbar->add_child(memnew(VSeparator));
Label *edit_items_toolbar_remove_label = memnew(Label);
- edit_items_toolbar_remove_label->set_text(TTR("Remove:"));
+ edit_items_toolbar_remove_label->set_text(TTR("Remove Items:"));
edit_items_toolbar->add_child(edit_items_toolbar_remove_label);
edit_items_remove_class = memnew(Button);
@@ -716,6 +1851,57 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
edit_theme_item_vb->add_child(theme_item_name);
theme_item_name->connect("gui_input", callable_mp(this, &ThemeItemEditorDialog::_edit_theme_item_gui_input));
edit_theme_item_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_confirm_edit_theme_item));
+
+ // Import Items tab.
+ TabContainer *import_tc = memnew(TabContainer);
+ tc->add_child(import_tc);
+ tc->set_tab_title(1, TTR("Import Items"));
+
+ import_default_theme_items = memnew(ThemeItemImportTree);
+ import_tc->add_child(import_default_theme_items);
+ import_tc->set_tab_title(0, TTR("Default Theme"));
+ import_default_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ import_editor_theme_items = memnew(ThemeItemImportTree);
+ import_tc->add_child(import_editor_theme_items);
+ import_tc->set_tab_title(1, TTR("Editor Theme"));
+ import_editor_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ VBoxContainer *import_another_theme_vb = memnew(VBoxContainer);
+
+ HBoxContainer *import_another_file_hb = memnew(HBoxContainer);
+ import_another_theme_vb->add_child(import_another_file_hb);
+ import_another_theme_value = memnew(LineEdit);
+ import_another_theme_value->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ import_another_theme_value->set_editable(false);
+ import_another_file_hb->add_child(import_another_theme_value);
+ import_another_theme_button = memnew(Button);
+ import_another_file_hb->add_child(import_another_theme_button);
+ import_another_theme_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_select_another_theme));
+
+ import_another_theme_dialog = memnew(EditorFileDialog);
+ import_another_theme_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ import_another_theme_dialog->set_title(TTR("Select Another Theme Resource:"));
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type("Theme", &ext);
+ for (List<String>::Element *E = ext.front(); E; E = E->next()) {
+ import_another_theme_dialog->add_filter("*." + E->get() + "; Theme Resource");
+ }
+ import_another_file_hb->add_child(import_another_theme_dialog);
+ import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk));
+
+ import_other_theme_items = memnew(ThemeItemImportTree);
+ import_other_theme_items->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ import_another_theme_vb->add_child(import_other_theme_items);
+
+ import_tc->add_child(import_another_theme_vb);
+ import_tc->set_tab_title(2, TTR("Another Theme"));
+ import_other_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types));
+
+ confirm_closing_dialog = memnew(ConfirmationDialog);
+ confirm_closing_dialog->set_autowrap(true);
+ add_child(confirm_closing_dialog);
+ confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog));
}
void ThemeEditor::edit(const Ref<Theme> &p_theme) {
@@ -742,299 +1928,8 @@ void ThemeEditor::_refresh_interval() {
_propagate_redraw(main_container);
}
-struct _TECategory {
- template <class T>
- struct RefItem {
- Ref<T> item;
- StringName name;
- bool operator<(const RefItem<T> &p) const { return item->get_instance_id() < p.item->get_instance_id(); }
- };
-
- template <class T>
- struct Item {
- T item;
- String name;
- bool operator<(const Item<T> &p) const { return name < p.name; }
- };
-
- Set<RefItem<StyleBox>> stylebox_items;
- Set<RefItem<Font>> font_items;
- Set<Item<int>> font_size_items;
- Set<RefItem<Texture2D>> icon_items;
-
- Set<Item<Color>> color_items;
- Set<Item<int>> constant_items;
-};
-
-void ThemeEditor::_save_template_cbk(String fname) {
- String filename = file_dialog->get_current_path();
-
- Map<String, _TECategory> categories;
-
- // Fill types.
- List<StringName> type_list;
- Theme::get_default()->get_type_list(&type_list);
- for (List<StringName>::Element *E = type_list.front(); E; E = E->next()) {
- categories.insert(E->get(), _TECategory());
- }
-
- // Fill default theme.
- for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
- _TECategory &tc = E->get();
-
- List<StringName> stylebox_list;
- Theme::get_default()->get_stylebox_list(E->key(), &stylebox_list);
- for (List<StringName>::Element *F = stylebox_list.front(); F; F = F->next()) {
- _TECategory::RefItem<StyleBox> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_stylebox(F->get(), E->key());
- tc.stylebox_items.insert(it);
- }
-
- List<StringName> font_list;
- Theme::get_default()->get_font_list(E->key(), &font_list);
- for (List<StringName>::Element *F = font_list.front(); F; F = F->next()) {
- _TECategory::RefItem<Font> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_font(F->get(), E->key());
- tc.font_items.insert(it);
- }
-
- List<StringName> font_size_list;
- Theme::get_default()->get_font_size_list(E->key(), &font_list);
- for (List<StringName>::Element *F = font_size_list.front(); F; F = F->next()) {
- _TECategory::Item<int> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_font_size(F->get(), E->key());
- tc.font_size_items.insert(it);
- }
-
- List<StringName> icon_list;
- Theme::get_default()->get_icon_list(E->key(), &icon_list);
- for (List<StringName>::Element *F = icon_list.front(); F; F = F->next()) {
- _TECategory::RefItem<Texture2D> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_icon(F->get(), E->key());
- tc.icon_items.insert(it);
- }
-
- List<StringName> color_list;
- Theme::get_default()->get_color_list(E->key(), &color_list);
- for (List<StringName>::Element *F = color_list.front(); F; F = F->next()) {
- _TECategory::Item<Color> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_color(F->get(), E->key());
- tc.color_items.insert(it);
- }
-
- List<StringName> constant_list;
- Theme::get_default()->get_constant_list(E->key(), &constant_list);
- for (List<StringName>::Element *F = constant_list.front(); F; F = F->next()) {
- _TECategory::Item<int> it;
- it.name = F->get();
- it.item = Theme::get_default()->get_constant(F->get(), E->key());
- tc.constant_items.insert(it);
- }
- }
-
- FileAccess *file = FileAccess::open(filename, FileAccess::WRITE);
-
- ERR_FAIL_COND_MSG(!file, "Can't save theme to file '" + filename + "'.");
-
- file->store_line("; ******************* ");
- file->store_line("; Template Theme File ");
- file->store_line("; ******************* ");
- file->store_line("; ");
- file->store_line("; Theme Syntax: ");
- file->store_line("; ------------- ");
- file->store_line("; ");
- file->store_line("; Must be placed in section [theme]");
- file->store_line("; ");
- file->store_line("; Type.item = [value] ");
- file->store_line("; ");
- file->store_line("; [value] examples:");
- file->store_line("; ");
- file->store_line("; Type.item = 6 ; numeric constant. ");
- file->store_line("; Type.item = #FF00FF ; HTML color (magenta).");
- file->store_line("; Type.item = #FF00FF55 ; HTML color (magenta with alpha 0x55).");
- file->store_line("; Type.item = icon(image.png) ; icon in a png file (relative to theme file).");
- file->store_line("; Type.item = font(font.xres) ; font in a resource (relative to theme file).");
- file->store_line("; Type.item = sbox(stylebox.xres) ; stylebox in a resource (relative to theme file).");
- file->store_line("; Type.item = sboxf(2,#FF00FF) ; flat stylebox with margin 2.");
- file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF) ; flat stylebox with margin 2 and border.");
- file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF,#000000) ; flat stylebox with margin 2, light & dark borders.");
- file->store_line("; Type.item = sboxt(base.png,2,2,2,2) ; textured stylebox with 3x3 stretch and stretch margins.");
- file->store_line("; -Additionally, 4 extra integers can be added to sboxf and sboxt to specify custom padding of contents:");
- file->store_line("; Type.item = sboxt(base.png,2,2,2,2,5,4,2,4) ;");
- file->store_line("; -Order for all is always left, top, right, bottom.");
- file->store_line("; ");
- file->store_line("; Special values:");
- file->store_line("; Type.item = default ; use the value in the default theme (must exist there).");
- file->store_line("; Type.item = @somebutton_color ; reference to a library value previously defined.");
- file->store_line("; ");
- file->store_line("; Library Syntax: ");
- file->store_line("; --------------- ");
- file->store_line("; ");
- file->store_line("; Must be placed in section [library], but usage is optional.");
- file->store_line("; ");
- file->store_line("; item = [value] ; same as Theme, but assign to library.");
- file->store_line("; ");
- file->store_line("; examples:");
- file->store_line("; ");
- file->store_line("; [library]");
- file->store_line("; ");
- file->store_line("; default_button_color = #FF00FF");
- file->store_line("; ");
- file->store_line("; [theme]");
- file->store_line("; ");
- file->store_line("; Button.color = @default_button_color ; used reference.");
- file->store_line("; ");
- file->store_line("; ******************* ");
- file->store_line("; ");
- file->store_line("; Template Generated Using: " + String(VERSION_FULL_BUILD));
- file->store_line("; ");
- file->store_line("; ");
- file->store_line("");
- file->store_line("[library]");
- file->store_line("");
- file->store_line("; place library stuff here");
- file->store_line("");
- file->store_line("[theme]");
- file->store_line("");
- file->store_line("");
-
- // Write default theme.
- for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
- _TECategory &tc = E->get();
-
- String underline = "; ";
- for (int i = 0; i < E->key().length(); i++) {
- underline += "*";
- }
-
- file->store_line("");
- file->store_line(underline);
- file->store_line("; " + E->key());
- file->store_line(underline);
-
- if (tc.stylebox_items.size()) {
- file->store_line("\n; StyleBox Items:\n");
- }
-
- for (Set<_TECategory::RefItem<StyleBox>>::Element *F = tc.stylebox_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.font_items.size()) {
- file->store_line("\n; Font Items:\n");
- }
-
- for (Set<_TECategory::RefItem<Font>>::Element *F = tc.font_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.font_size_items.size()) {
- file->store_line("\n; Font Size Items:\n");
- }
-
- for (Set<_TECategory::Item<int>>::Element *F = tc.font_size_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.icon_items.size()) {
- file->store_line("\n; Icon Items:\n");
- }
-
- for (Set<_TECategory::RefItem<Texture2D>>::Element *F = tc.icon_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.color_items.size()) {
- file->store_line("\n; Color Items:\n");
- }
-
- for (Set<_TECategory::Item<Color>>::Element *F = tc.color_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
-
- if (tc.constant_items.size()) {
- file->store_line("\n; Constant Items:\n");
- }
-
- for (Set<_TECategory::Item<int>>::Element *F = tc.constant_items.front(); F; F = F->next()) {
- file->store_line(E->key() + "." + F->get().name + " = default");
- }
- }
-
- file->close();
- memdelete(file);
-}
-
-void ThemeEditor::_theme_create_menu_cbk(int p_option) {
- bool import = (p_option == POPUP_IMPORT_EDITOR_THEME);
-
- Ref<Theme> base_theme;
-
- if (p_option == POPUP_CREATE_EMPTY) {
- base_theme = Theme::get_default();
- } else {
- base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme();
- }
-
- {
- List<StringName> types;
- base_theme->get_type_list(&types);
-
- for (List<StringName>::Element *T = types.front(); T; T = T->next()) {
- StringName type = T->get();
-
- List<StringName> icons;
- base_theme->get_icon_list(type, &icons);
-
- for (List<StringName>::Element *E = icons.front(); E; E = E->next()) {
- theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture2D>());
- }
-
- List<StringName> styleboxs;
- base_theme->get_stylebox_list(type, &styleboxs);
-
- for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) {
- theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>());
- }
-
- List<StringName> fonts;
- base_theme->get_font_list(type, &fonts);
-
- for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) {
- theme->set_font(E->get(), type, Ref<Font>());
- }
-
- List<StringName> font_sizes;
- base_theme->get_font_size_list(type, &font_sizes);
-
- for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) {
- theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type));
- }
-
- List<StringName> colors;
- base_theme->get_color_list(type, &colors);
-
- for (List<StringName>::Element *E = colors.front(); E; E = E->next()) {
- theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color());
- }
-
- List<StringName> constants;
- base_theme->get_constant_list(type, &constants);
-
- for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type));
- }
- }
- }
-}
-
void ThemeEditor::_theme_edit_button_cbk() {
- theme_edit_dialog->popup_centered(Size2(800, 640) * EDSCALE);
+ theme_edit_dialog->popup_centered(Size2(850, 760) * EDSCALE);
}
void ThemeEditor::_notification(int p_what) {
@@ -1059,19 +1954,9 @@ ThemeEditor::ThemeEditor() {
top_menu->add_child(memnew(Label(TTR("Preview:"))));
top_menu->add_spacer(false);
- theme_create_menu = memnew(MenuButton);
- theme_create_menu->set_text(TTR("Create Theme..."));
- theme_create_menu->set_tooltip(TTR("Create a new Theme."));
- theme_create_menu->get_popup()->add_item(TTR("Empty Template"), POPUP_CREATE_EMPTY);
- theme_create_menu->get_popup()->add_separator();
- theme_create_menu->get_popup()->add_item(TTR("Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
- theme_create_menu->get_popup()->add_item(TTR("From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME);
- top_menu->add_child(theme_create_menu);
- theme_create_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_create_menu_cbk));
-
theme_edit_button = memnew(Button);
- theme_edit_button->set_text(TTR("Edit Theme Items"));
- theme_edit_button->set_tooltip(TTR("Customize Theme items."));
+ theme_edit_button->set_text(TTR("Manage Items"));
+ theme_edit_button->set_tooltip(TTR("Add, remove, organize and import Theme items."));
theme_edit_button->set_flat(true);
theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk));
top_menu->add_child(theme_edit_button);
@@ -1260,11 +2145,6 @@ ThemeEditor::ThemeEditor() {
theme_edit_dialog = memnew(ThemeItemEditorDialog);
theme_edit_dialog->hide();
add_child(theme_edit_dialog);
-
- file_dialog = memnew(EditorFileDialog);
- file_dialog->add_filter("*.theme ; " + TTR("Theme File"));
- add_child(file_dialog);
- file_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_save_template_cbk));
}
void ThemeEditorPlugin::edit(Object *p_node) {
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 0a840aecd7..5f4de68f45 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -41,14 +41,148 @@
#include "editor/editor_node.h"
+class ThemeItemImportTree : public VBoxContainer {
+ GDCLASS(ThemeItemImportTree, VBoxContainer);
+
+ Ref<Theme> edited_theme;
+ Ref<Theme> base_theme;
+
+ struct ThemeItem {
+ String type_name;
+ Theme::DataType data_type;
+ String item_name;
+
+ bool operator<(const ThemeItem &p_item) const {
+ if (type_name == p_item.type_name && data_type == p_item.data_type) {
+ return item_name < p_item.item_name;
+ }
+ if (type_name == p_item.type_name) {
+ return data_type < p_item.data_type;
+ }
+ return type_name < p_item.type_name;
+ }
+ };
+
+ enum ItemCheckedState {
+ SELECT_IMPORT_DEFINITION,
+ SELECT_IMPORT_FULL,
+ };
+
+ Map<ThemeItem, ItemCheckedState> selected_items;
+
+ LineEdit *import_items_filter;
+
+ Tree *import_items_tree;
+ List<TreeItem *> tree_color_items;
+ List<TreeItem *> tree_constant_items;
+ List<TreeItem *> tree_font_items;
+ List<TreeItem *> tree_font_size_items;
+ List<TreeItem *> tree_icon_items;
+ List<TreeItem *> tree_stylebox_items;
+
+ bool updating_tree = false;
+
+ enum ItemActionFlag {
+ IMPORT_ITEM = 1,
+ IMPORT_ITEM_DATA = 2,
+ };
+
+ TextureRect *select_colors_icon;
+ Label *select_colors_label;
+ Button *select_all_colors_button;
+ Button *select_full_colors_button;
+ Button *deselect_all_colors_button;
+ Label *total_selected_colors_label;
+
+ TextureRect *select_constants_icon;
+ Label *select_constants_label;
+ Button *select_all_constants_button;
+ Button *select_full_constants_button;
+ Button *deselect_all_constants_button;
+ Label *total_selected_constants_label;
+
+ TextureRect *select_fonts_icon;
+ Label *select_fonts_label;
+ Button *select_all_fonts_button;
+ Button *select_full_fonts_button;
+ Button *deselect_all_fonts_button;
+ Label *total_selected_fonts_label;
+
+ TextureRect *select_font_sizes_icon;
+ Label *select_font_sizes_label;
+ Button *select_all_font_sizes_button;
+ Button *select_full_font_sizes_button;
+ Button *deselect_all_font_sizes_button;
+ Label *total_selected_font_sizes_label;
+
+ TextureRect *select_icons_icon;
+ Label *select_icons_label;
+ Button *select_all_icons_button;
+ Button *select_full_icons_button;
+ Button *deselect_all_icons_button;
+ Label *total_selected_icons_label;
+
+ TextureRect *select_styleboxes_icon;
+ Label *select_styleboxes_label;
+ Button *select_all_styleboxes_button;
+ Button *select_full_styleboxes_button;
+ Button *deselect_all_styleboxes_button;
+ Label *total_selected_styleboxes_label;
+
+ HBoxContainer *select_icons_warning_hb;
+ TextureRect *select_icons_warning_icon;
+ Label *select_icons_warning;
+
+ Button *import_collapse_types_button;
+ Button *import_expand_types_button;
+ Button *import_select_all_button;
+ Button *import_select_full_button;
+ Button *import_deselect_all_button;
+
+ void _update_items_tree();
+ void _toggle_type_items(bool p_collapse);
+ void _filter_text_changed(const String &p_value);
+
+ void _store_selected_item(TreeItem *p_tree_item);
+ void _restore_selected_item(TreeItem *p_tree_item);
+ void _update_total_selected(Theme::DataType p_data_type);
+
+ void _tree_item_edited();
+ void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
+ void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
+ void _update_parent_items(TreeItem *p_root_item);
+
+ void _select_all_items_pressed();
+ void _select_full_items_pressed();
+ void _deselect_all_items_pressed();
+
+ void _select_all_data_type_pressed(int p_data_type);
+ void _select_full_data_type_pressed(int p_data_type);
+ void _deselect_all_data_type_pressed(int p_data_type);
+
+ void _import_selected();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_edited_theme(const Ref<Theme> &p_theme);
+ void set_base_theme(const Ref<Theme> &p_theme);
+ void reset_item_tree();
+
+ bool has_selected_items() const;
+
+ ThemeItemImportTree();
+};
+
class ThemeItemEditorDialog : public AcceptDialog {
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
Ref<Theme> edited_theme;
ItemList *edit_type_list;
- OptionButton *edit_add_class_options;
- LineEdit *edit_add_custom_value;
+ LineEdit *edit_add_type_value;
String edited_item_type;
Button *edit_items_add_color;
@@ -83,6 +217,19 @@ class ThemeItemEditorDialog : public AcceptDialog {
String edit_item_old_name;
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
+ ThemeItemImportTree *import_default_theme_items;
+ ThemeItemImportTree *import_editor_theme_items;
+ ThemeItemImportTree *import_other_theme_items;
+
+ LineEdit *import_another_theme_value;
+ Button *import_another_theme_button;
+ EditorFileDialog *import_another_theme_dialog;
+
+ ConfirmationDialog *confirm_closing_dialog;
+
+ void ok_pressed() override;
+ void _close_dialog();
+
void _dialog_about_to_show();
void _update_edit_types();
void _edited_type_selected(int p_item_idx);
@@ -90,8 +237,7 @@ class ThemeItemEditorDialog : public AcceptDialog {
void _update_edit_item_tree(String p_item_type);
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id);
- void _add_class_type_items();
- void _add_custom_type();
+ void _add_theme_type();
void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type);
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
void _remove_class_items();
@@ -103,6 +249,9 @@ class ThemeItemEditorDialog : public AcceptDialog {
void _confirm_edit_theme_item();
void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event);
+ void _open_select_another_theme();
+ void _select_another_theme_cbk(const String &p_path);
+
protected:
void _notification(int p_what);
@@ -115,29 +264,18 @@ public:
class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer);
- Panel *main_panel;
- MarginContainer *main_container;
Ref<Theme> theme;
- EditorFileDialog *file_dialog;
-
double time_left = 0;
Button *theme_edit_button;
- MenuButton *theme_create_menu;
ThemeItemEditorDialog *theme_edit_dialog;
- enum CreatePopupMode {
- POPUP_CREATE_EMPTY,
- POPUP_CREATE_EDITOR_EMPTY,
- POPUP_IMPORT_EDITOR_THEME,
- };
-
+ Panel *main_panel;
+ MarginContainer *main_container;
Tree *test_tree;
- void _save_template_cbk(String fname);
void _theme_edit_button_cbk();
- void _theme_create_menu_cbk(int p_option);
void _propagate_redraw(Control *p_at);
void _refresh_interval();