diff --git a/editor/icons/FontSize.svg b/editor/icons/FontSize.svg
new file mode 100644
index 00000000000..e608d89b6ad
--- /dev/null
+++ b/editor/icons/FontSize.svg
@@ -0,0 +1 @@
+
diff --git a/editor/icons/ThemeRemoveAllItems.svg b/editor/icons/ThemeRemoveAllItems.svg
new file mode 100644
index 00000000000..47ed624d04c
--- /dev/null
+++ b/editor/icons/ThemeRemoveAllItems.svg
@@ -0,0 +1 @@
+
diff --git a/editor/icons/ThemeRemoveCustomItems.svg b/editor/icons/ThemeRemoveCustomItems.svg
new file mode 100644
index 00000000000..bb8a8bd0263
--- /dev/null
+++ b/editor/icons/ThemeRemoveCustomItems.svg
@@ -0,0 +1 @@
+
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index dfa8c041453..c765aa03191 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -31,12 +31,696 @@
#include "theme_editor_plugin.h"
#include "core/os/file_access.h"
+#include "core/os/keyboard.h"
#include "core/version.h"
#include "editor/editor_scale.h"
#include "scene/gui/progress_bar.h"
+void ThemeItemEditorDialog::_dialog_about_to_show() {
+ ERR_FAIL_COND(edited_theme.is_null());
+
+ _update_edit_types();
+}
+
+void ThemeItemEditorDialog::_update_edit_types() {
+ Ref base_theme = Theme::get_default();
+
+ List theme_types;
+ edited_theme->get_type_list(&theme_types);
+ theme_types.sort_custom();
+
+ bool item_reselected = false;
+ edit_type_list->clear();
+ int e_idx = 0;
+ for (List::Element *E = theme_types.front(); E; E = E->next()) {
+ Ref item_icon;
+ if (E->get() == "") {
+ item_icon = get_theme_icon("NodeDisabled", "EditorIcons");
+ } else {
+ item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ }
+ edit_type_list->add_item(E->get(), item_icon);
+
+ if (E->get() == edited_item_type) {
+ edit_type_list->select(e_idx);
+ item_reselected = true;
+ }
+ e_idx++;
+ }
+ if (!item_reselected) {
+ edited_item_type = "";
+
+ if (edit_type_list->get_item_count() > 0) {
+ edit_type_list->select(0);
+ }
+ }
+
+ List default_types;
+ base_theme->get_type_list(&default_types);
+ default_types.sort_custom();
+
+ edit_add_class_options->clear();
+ for (List::Element *E = default_types.front(); E; E = E->next()) {
+ edit_add_class_options->add_item(E->get());
+ }
+
+ String selected_type = "";
+ Vector selected_ids = edit_type_list->get_selected_items();
+ if (selected_ids.size() > 0) {
+ selected_type = edit_type_list->get_item_text(selected_ids[0]);
+
+ edit_items_add_color->set_disabled(false);
+ edit_items_add_constant->set_disabled(false);
+ edit_items_add_font->set_disabled(false);
+ edit_items_add_font_size->set_disabled(false);
+ edit_items_add_icon->set_disabled(false);
+ edit_items_add_stylebox->set_disabled(false);
+
+ edit_items_remove_class->set_disabled(false);
+ edit_items_remove_custom->set_disabled(false);
+ edit_items_remove_all->set_disabled(false);
+ } else {
+ edit_items_add_color->set_disabled(true);
+ edit_items_add_constant->set_disabled(true);
+ edit_items_add_font->set_disabled(true);
+ edit_items_add_font_size->set_disabled(true);
+ edit_items_add_icon->set_disabled(true);
+ edit_items_add_stylebox->set_disabled(true);
+
+ edit_items_remove_class->set_disabled(true);
+ edit_items_remove_custom->set_disabled(true);
+ edit_items_remove_all->set_disabled(true);
+ }
+ _update_edit_item_tree(selected_type);
+}
+
+void ThemeItemEditorDialog::_edited_type_selected(int p_item_idx) {
+ String selected_type = edit_type_list->get_item_text(p_item_idx);
+ _update_edit_item_tree(selected_type);
+}
+
+void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
+ edited_item_type = p_item_type;
+
+ edit_items_tree->clear();
+ TreeItem *root = edit_items_tree->create_item();
+
+ List names;
+
+ {
+ names.clear();
+ edited_theme->get_color_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *color_root = edit_items_tree->create_item(root);
+ color_root->set_metadata(0, Theme::DATA_TYPE_COLOR);
+ color_root->set_icon(0, get_theme_icon("Color", "EditorIcons"));
+ color_root->set_text(0, TTR("Colors"));
+ color_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Color Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(color_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+
+ {
+ names.clear();
+ edited_theme->get_constant_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *constant_root = edit_items_tree->create_item(root);
+ constant_root->set_metadata(0, Theme::DATA_TYPE_CONSTANT);
+ constant_root->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons"));
+ constant_root->set_text(0, TTR("Constants"));
+ constant_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Constant Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(constant_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+
+ {
+ names.clear();
+ edited_theme->get_font_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *font_root = edit_items_tree->create_item(root);
+ font_root->set_metadata(0, Theme::DATA_TYPE_FONT);
+ font_root->set_icon(0, get_theme_icon("Font", "EditorIcons"));
+ font_root->set_text(0, TTR("Fonts"));
+ font_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(font_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+
+ {
+ names.clear();
+ edited_theme->get_font_size_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *font_size_root = edit_items_tree->create_item(root);
+ font_size_root->set_metadata(0, Theme::DATA_TYPE_FONT_SIZE);
+ font_size_root->set_icon(0, get_theme_icon("FontSize", "EditorIcons"));
+ font_size_root->set_text(0, TTR("Font Sizes"));
+ font_size_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Size Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(font_size_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+
+ {
+ names.clear();
+ edited_theme->get_icon_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *icon_root = edit_items_tree->create_item(root);
+ icon_root->set_metadata(0, Theme::DATA_TYPE_ICON);
+ icon_root->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons"));
+ icon_root->set_text(0, TTR("Icons"));
+ icon_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Icon Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(icon_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+
+ {
+ names.clear();
+ edited_theme->get_stylebox_list(p_item_type, &names);
+
+ if (names.size() > 0) {
+ TreeItem *stylebox_root = edit_items_tree->create_item(root);
+ stylebox_root->set_metadata(0, Theme::DATA_TYPE_STYLEBOX);
+ stylebox_root->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons"));
+ stylebox_root->set_text(0, TTR("Styleboxes"));
+ stylebox_root->add_button(0, get_theme_icon("Clear", "EditorIcons"), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All StyleBox Items"));
+
+ names.sort_custom();
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ TreeItem *item = edit_items_tree->create_item(stylebox_root);
+ item->set_text(0, E->get());
+ item->add_button(0, get_theme_icon("Edit", "EditorIcons"), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
+ item->add_button(0, get_theme_icon("Remove", "EditorIcons"), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
+ }
+ }
+ }
+}
+
+void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_column, int p_id) {
+ TreeItem *item = Object::cast_to(p_item);
+ if (!item) {
+ return;
+ }
+
+ switch (p_id) {
+ case ITEMS_TREE_RENAME_ITEM: {
+ String item_name = item->get_text(0);
+ int data_type = item->get_parent()->get_metadata(0);
+ _open_rename_theme_item_dialog((Theme::DataType)data_type, item_name);
+ } break;
+ case ITEMS_TREE_REMOVE_ITEM: {
+ String item_name = item->get_text(0);
+ int data_type = item->get_parent()->get_metadata(0);
+ edited_theme->clear_theme_item((Theme::DataType)data_type, item_name, edited_item_type);
+ } break;
+ case ITEMS_TREE_REMOVE_DATA_TYPE: {
+ int data_type = item->get_metadata(0);
+ _remove_data_type_items((Theme::DataType)data_type, edited_item_type);
+ } break;
+ }
+
+ _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 names;
+
+ {
+ names.clear();
+ Theme::get_default()->get_icon_list(type_name, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ edited_theme->set_icon(E->get(), type_name, Ref());
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_stylebox_list(type_name, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ edited_theme->set_stylebox(E->get(), type_name, Ref());
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_font_list(type_name, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ edited_theme->set_font(E->get(), type_name, Ref());
+ }
+ }
+ {
+ names.clear();
+ Theme::get_default()->get_font_size_list(type_name, &names);
+ for (List::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::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::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());
+ _update_edit_types();
+}
+
+void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type) {
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_ICON:
+ edited_theme->set_icon(p_item_name, p_item_type, Ref());
+ break;
+ case Theme::DATA_TYPE_STYLEBOX:
+ edited_theme->set_stylebox(p_item_name, p_item_type, Ref());
+ break;
+ case Theme::DATA_TYPE_FONT:
+ edited_theme->set_font(p_item_name, p_item_type, Ref());
+ break;
+ case Theme::DATA_TYPE_FONT_SIZE:
+ edited_theme->set_font_size(p_item_name, p_item_type, -1);
+ break;
+ case Theme::DATA_TYPE_COLOR:
+ edited_theme->set_color(p_item_name, p_item_type, Color());
+ break;
+ case Theme::DATA_TYPE_CONSTANT:
+ edited_theme->set_constant(p_item_name, p_item_type, 0);
+ break;
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+}
+
+void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type, String p_item_type) {
+ List names;
+
+ edited_theme->get_theme_item_list(p_data_type, p_item_type, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ edited_theme->clear_theme_item(p_data_type, E->get(), p_item_type);
+ }
+}
+
+void ThemeItemEditorDialog::_remove_class_items() {
+ List names;
+
+ for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
+ Theme::DataType data_type = (Theme::DataType)dt;
+
+ names.clear();
+ Theme::get_default()->get_theme_item_list(data_type, edited_item_type, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ if (edited_theme->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) {
+ edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ }
+ }
+ }
+
+ _update_edit_item_tree(edited_item_type);
+}
+
+void ThemeItemEditorDialog::_remove_custom_items() {
+ List names;
+
+ for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
+ Theme::DataType data_type = (Theme::DataType)dt;
+
+ names.clear();
+ edited_theme->get_theme_item_list(data_type, edited_item_type, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ if (!Theme::get_default()->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) {
+ edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ }
+ }
+ }
+
+ _update_edit_item_tree(edited_item_type);
+}
+
+void ThemeItemEditorDialog::_remove_all_items() {
+ List names;
+
+ for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
+ Theme::DataType data_type = (Theme::DataType)dt;
+
+ names.clear();
+ edited_theme->get_theme_item_list(data_type, edited_item_type, &names);
+ for (List::Element *E = names.front(); E; E = E->next()) {
+ edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ }
+ }
+
+ _update_edit_item_tree(edited_item_type);
+}
+
+void ThemeItemEditorDialog::_open_add_theme_item_dialog(int p_data_type) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ item_popup_mode = CREATE_THEME_ITEM;
+ edit_item_data_type = (Theme::DataType)p_data_type;
+
+ switch (edit_item_data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ edit_theme_item_dialog->set_title(TTR("Add Color Item"));
+ break;
+ case Theme::DATA_TYPE_CONSTANT:
+ edit_theme_item_dialog->set_title(TTR("Add Constant Item"));
+ break;
+ case Theme::DATA_TYPE_FONT:
+ edit_theme_item_dialog->set_title(TTR("Add Font Item"));
+ break;
+ case Theme::DATA_TYPE_FONT_SIZE:
+ edit_theme_item_dialog->set_title(TTR("Add Font Size Item"));
+ break;
+ case Theme::DATA_TYPE_ICON:
+ edit_theme_item_dialog->set_title(TTR("Add Icon Item"));
+ break;
+ case Theme::DATA_TYPE_STYLEBOX:
+ edit_theme_item_dialog->set_title(TTR("Add Stylebox Item"));
+ break;
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ edit_theme_item_old_vb->hide();
+ theme_item_name->clear();
+ edit_theme_item_dialog->popup_centered(Size2(380, 110) * EDSCALE);
+ theme_item_name->grab_focus();
+}
+
+void ThemeItemEditorDialog::_open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name) {
+ ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds.");
+
+ item_popup_mode = RENAME_THEME_ITEM;
+ edit_item_data_type = p_data_type;
+ edit_item_old_name = p_item_name;
+
+ switch (edit_item_data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ edit_theme_item_dialog->set_title(TTR("Rename Color Item"));
+ break;
+ case Theme::DATA_TYPE_CONSTANT:
+ edit_theme_item_dialog->set_title(TTR("Rename Constant Item"));
+ break;
+ case Theme::DATA_TYPE_FONT:
+ edit_theme_item_dialog->set_title(TTR("Rename Font Item"));
+ break;
+ case Theme::DATA_TYPE_FONT_SIZE:
+ edit_theme_item_dialog->set_title(TTR("Rename Font Size Item"));
+ break;
+ case Theme::DATA_TYPE_ICON:
+ edit_theme_item_dialog->set_title(TTR("Rename Icon Item"));
+ break;
+ case Theme::DATA_TYPE_STYLEBOX:
+ edit_theme_item_dialog->set_title(TTR("Rename Stylebox Item"));
+ break;
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ edit_theme_item_old_vb->show();
+ theme_item_old_name->set_text(p_item_name);
+ theme_item_name->set_text(p_item_name);
+ edit_theme_item_dialog->popup_centered(Size2(380, 140) * EDSCALE);
+ theme_item_name->grab_focus();
+}
+
+void ThemeItemEditorDialog::_confirm_edit_theme_item() {
+ if (item_popup_mode == CREATE_THEME_ITEM) {
+ _add_theme_item(edit_item_data_type, theme_item_name->get_text(), edited_item_type);
+ } else if (item_popup_mode == RENAME_THEME_ITEM) {
+ edited_theme->rename_theme_item(edit_item_data_type, edit_item_old_name, theme_item_name->get_text(), edited_item_type);
+ }
+
+ item_popup_mode = ITEM_POPUP_MODE_MAX;
+ edit_item_data_type = Theme::DATA_TYPE_MAX;
+ edit_item_old_name = "";
+
+ _update_edit_item_tree(edited_item_type);
+}
+
+void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref &p_event) {
+ Ref k = p_event;
+
+ if (k.is_valid()) {
+ if (!k->is_pressed()) {
+ return;
+ }
+
+ switch (k->get_keycode()) {
+ case KEY_KP_ENTER:
+ case KEY_ENTER: {
+ _confirm_edit_theme_item();
+ edit_theme_item_dialog->hide();
+ edit_theme_item_dialog->set_input_as_handled();
+ } break;
+ case KEY_ESCAPE: {
+ edit_theme_item_dialog->hide();
+ edit_theme_item_dialog->set_input_as_handled();
+ } break;
+ }
+ }
+}
+
+void ThemeItemEditorDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ connect("about_to_popup", callable_mp(this, &ThemeItemEditorDialog::_dialog_about_to_show));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
+ edit_items_add_color->set_icon(get_theme_icon("Color", "EditorIcons"));
+ edit_items_add_constant->set_icon(get_theme_icon("MemberConstant", "EditorIcons"));
+ edit_items_add_font->set_icon(get_theme_icon("Font", "EditorIcons"));
+ edit_items_add_font_size->set_icon(get_theme_icon("FontSize", "EditorIcons"));
+ edit_items_add_icon->set_icon(get_theme_icon("ImageTexture", "EditorIcons"));
+ edit_items_add_stylebox->set_icon(get_theme_icon("StyleBoxFlat", "EditorIcons"));
+
+ 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"));
+ } break;
+ }
+}
+
+void ThemeItemEditorDialog::set_edited_theme(const Ref &p_theme) {
+ edited_theme = p_theme;
+}
+
+ThemeItemEditorDialog::ThemeItemEditorDialog() {
+ set_title(TTR("Edit Theme Items"));
+
+ HSplitContainer *edit_dialog_hs = memnew(HSplitContainer);
+ add_child(edit_dialog_hs);
+
+ VBoxContainer *edit_dialog_side_vb = memnew(VBoxContainer);
+ edit_dialog_side_vb->set_custom_minimum_size(Size2(200.0, 0.0) * EDSCALE);
+ edit_dialog_hs->add_child(edit_dialog_side_vb);
+
+ Label *edit_type_label = memnew(Label);
+ edit_type_label->set_text(TTR("Types:"));
+ edit_dialog_side_vb->add_child(edit_type_label);
+
+ edit_type_list = memnew(ItemList);
+ edit_type_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ 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));
+
+ VBoxContainer *edit_items_vb = memnew(VBoxContainer);
+ edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ edit_dialog_hs->add_child(edit_items_vb);
+
+ HBoxContainer *edit_items_toolbar = memnew(HBoxContainer);
+ 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_child(edit_items_toolbar_add_label);
+
+ edit_items_add_color = memnew(Button);
+ edit_items_add_color->set_tooltip(TTR("Add Color Item"));
+ edit_items_add_color->set_flat(true);
+ edit_items_add_color->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_color);
+ edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_COLOR));
+
+ edit_items_add_constant = memnew(Button);
+ edit_items_add_constant->set_tooltip(TTR("Add Constant Item"));
+ edit_items_add_constant->set_flat(true);
+ edit_items_add_constant->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_constant);
+ edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_CONSTANT));
+
+ edit_items_add_font = memnew(Button);
+ edit_items_add_font->set_tooltip(TTR("Add Font Item"));
+ edit_items_add_font->set_flat(true);
+ edit_items_add_font->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_font);
+ edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT));
+
+ edit_items_add_font_size = memnew(Button);
+ edit_items_add_font_size->set_tooltip(TTR("Add Font Size Item"));
+ edit_items_add_font_size->set_flat(true);
+ edit_items_add_font_size->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_font_size);
+ edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_FONT_SIZE));
+
+ edit_items_add_icon = memnew(Button);
+ edit_items_add_icon->set_tooltip(TTR("Add Icon Item"));
+ edit_items_add_icon->set_flat(true);
+ edit_items_add_icon->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_icon);
+ edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_ICON));
+
+ edit_items_add_stylebox = memnew(Button);
+ edit_items_add_stylebox->set_tooltip(TTR("Add StyleBox Item"));
+ edit_items_add_stylebox->set_flat(true);
+ edit_items_add_stylebox->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_add_stylebox);
+ edit_items_add_stylebox->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog), varray(Theme::DATA_TYPE_STYLEBOX));
+
+ 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->add_child(edit_items_toolbar_remove_label);
+
+ edit_items_remove_class = memnew(Button);
+ edit_items_remove_class->set_tooltip(TTR("Remove Class Items"));
+ edit_items_remove_class->set_flat(true);
+ edit_items_remove_class->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_remove_class);
+ edit_items_remove_class->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_class_items));
+
+ edit_items_remove_custom = memnew(Button);
+ edit_items_remove_custom->set_tooltip(TTR("Remove Custom Items"));
+ edit_items_remove_custom->set_flat(true);
+ edit_items_remove_custom->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_remove_custom);
+ edit_items_remove_custom->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_custom_items));
+
+ edit_items_remove_all = memnew(Button);
+ edit_items_remove_all->set_tooltip(TTR("Remove All Items"));
+ edit_items_remove_all->set_flat(true);
+ edit_items_remove_all->set_disabled(true);
+ edit_items_toolbar->add_child(edit_items_remove_all);
+ edit_items_remove_all->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_all_items));
+
+ edit_items_tree = memnew(Tree);
+ edit_items_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ edit_items_tree->set_hide_root(true);
+ edit_items_tree->set_columns(1);
+ edit_items_vb->add_child(edit_items_tree);
+ edit_items_tree->connect("button_pressed", callable_mp(this, &ThemeItemEditorDialog::_item_tree_button_pressed));
+
+ edit_theme_item_dialog = memnew(ConfirmationDialog);
+ edit_theme_item_dialog->set_title(TTR("Add Theme Item"));
+ add_child(edit_theme_item_dialog);
+ VBoxContainer *edit_theme_item_vb = memnew(VBoxContainer);
+ edit_theme_item_dialog->add_child(edit_theme_item_vb);
+
+ edit_theme_item_old_vb = memnew(VBoxContainer);
+ edit_theme_item_vb->add_child(edit_theme_item_old_vb);
+ Label *edit_theme_item_old = memnew(Label);
+ edit_theme_item_old->set_text(TTR("Old Name:"));
+ edit_theme_item_old_vb->add_child(edit_theme_item_old);
+ theme_item_old_name = memnew(Label);
+ edit_theme_item_old_vb->add_child(theme_item_old_name);
+
+ Label *edit_theme_item_label = memnew(Label);
+ edit_theme_item_label->set_text(TTR("Name:"));
+ edit_theme_item_vb->add_child(edit_theme_item_label);
+ theme_item_name = memnew(LineEdit);
+ 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));
+}
+
void ThemeEditor::edit(const Ref &p_theme) {
theme = p_theme;
+ theme_edit_dialog->set_edited_theme(p_theme);
main_panel->set_theme(p_theme);
main_container->set_theme(p_theme);
}
@@ -58,55 +742,6 @@ void ThemeEditor::_refresh_interval() {
_propagate_redraw(main_container);
}
-void ThemeEditor::_type_menu_cbk(int p_option) {
- type_edit->set_text(type_menu->get_popup()->get_item_text(p_option));
-}
-
-void ThemeEditor::_name_menu_about_to_show() {
- String fromtype = type_edit->get_text();
- List names;
-
- if (popup_mode == POPUP_ADD) {
- switch (type_select->get_selected()) {
- case 0:
- Theme::get_default()->get_icon_list(fromtype, &names);
- break;
- case 1:
- Theme::get_default()->get_stylebox_list(fromtype, &names);
- break;
- case 2:
- Theme::get_default()->get_font_list(fromtype, &names);
- break;
- case 3:
- Theme::get_default()->get_font_size_list(fromtype, &names);
- break;
- case 4:
- Theme::get_default()->get_color_list(fromtype, &names);
- break;
- case 5:
- Theme::get_default()->get_constant_list(fromtype, &names);
- break;
- }
- } else if (popup_mode == POPUP_REMOVE) {
- theme->get_icon_list(fromtype, &names);
- theme->get_stylebox_list(fromtype, &names);
- theme->get_font_list(fromtype, &names);
- theme->get_font_size_list(fromtype, &names);
- theme->get_color_list(fromtype, &names);
- theme->get_constant_list(fromtype, &names);
- }
-
- name_menu->get_popup()->clear();
- name_menu->get_popup()->set_size(Size2());
- for (List::Element *E = names.front(); E; E = E->next()) {
- name_menu->get_popup()->add_item(E->get());
- }
-}
-
-void ThemeEditor::_name_menu_cbk(int p_option) {
- name_edit->set_text(name_menu->get_popup()->get_item_text(p_option));
-}
-
struct _TECategory {
template
struct RefItem {
@@ -335,296 +970,71 @@ void ThemeEditor::_save_template_cbk(String fname) {
memdelete(file);
}
-void ThemeEditor::_dialog_cbk() {
- switch (popup_mode) {
- case POPUP_ADD: {
- switch (type_select->get_selected()) {
- case 0:
- theme->set_icon(name_edit->get_text(), type_edit->get_text(), Ref());
- break;
- case 1:
- theme->set_stylebox(name_edit->get_text(), type_edit->get_text(), Ref());
- break;
- case 2:
- theme->set_font(name_edit->get_text(), type_edit->get_text(), Ref());
- break;
- case 3:
- theme->set_font_size(name_edit->get_text(), type_edit->get_text(), -1);
- break;
- case 4:
- theme->set_color(name_edit->get_text(), type_edit->get_text(), Color());
- break;
- case 5:
- theme->set_constant(name_edit->get_text(), type_edit->get_text(), 0);
- break;
- }
-
- } break;
- case POPUP_CLASS_ADD: {
- StringName fromtype = type_edit->get_text();
- List names;
-
- {
- names.clear();
- Theme::get_default()->get_icon_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_icon(E->get(), fromtype, Ref());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_stylebox_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_stylebox(E->get(), fromtype, Ref());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_font(E->get(), fromtype, Ref());
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_size_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_font_size(E->get(), fromtype, Theme::get_default()->get_font_size(E->get(), fromtype));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_color_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_color(E->get(), fromtype, Theme::get_default()->get_color(E->get(), fromtype));
- }
- }
- {
- names.clear();
- Theme::get_default()->get_constant_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->set_constant(E->get(), fromtype, Theme::get_default()->get_constant(E->get(), fromtype));
- }
- }
- } break;
- case POPUP_REMOVE: {
- switch (type_select->get_selected()) {
- case 0:
- theme->clear_icon(name_edit->get_text(), type_edit->get_text());
- break;
- case 1:
- theme->clear_stylebox(name_edit->get_text(), type_edit->get_text());
- break;
- case 2:
- theme->clear_font(name_edit->get_text(), type_edit->get_text());
- break;
- case 3:
- theme->clear_font_size(name_edit->get_text(), type_edit->get_text());
- break;
- case 4:
- theme->clear_color(name_edit->get_text(), type_edit->get_text());
- break;
- case 5:
- theme->clear_constant(name_edit->get_text(), type_edit->get_text());
- break;
- }
-
- } break;
- case POPUP_CLASS_REMOVE: {
- StringName fromtype = type_edit->get_text();
- List names;
-
- {
- names.clear();
- Theme::get_default()->get_icon_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_icon(E->get(), fromtype);
- }
- }
- {
- names.clear();
- Theme::get_default()->get_stylebox_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_stylebox(E->get(), fromtype);
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_font(E->get(), fromtype);
- }
- }
- {
- names.clear();
- Theme::get_default()->get_font_size_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_font_size(E->get(), fromtype);
- }
- }
- {
- names.clear();
- Theme::get_default()->get_color_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_color(E->get(), fromtype);
- }
- }
- {
- names.clear();
- Theme::get_default()->get_constant_list(fromtype, &names);
- for (List::Element *E = names.front(); E; E = E->next()) {
- theme->clear_constant(E->get(), fromtype);
- }
- }
-
- } break;
- }
-}
-
-void ThemeEditor::_theme_menu_cbk(int p_option) {
- if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY || p_option == POPUP_IMPORT_EDITOR_THEME) {
- bool import = (p_option == POPUP_IMPORT_EDITOR_THEME);
-
- Ref 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 types;
- base_theme->get_type_list(&types);
-
- for (List::Element *T = types.front(); T; T = T->next()) {
- StringName type = T->get();
-
- List icons;
- base_theme->get_icon_list(type, &icons);
-
- for (List::Element *E = icons.front(); E; E = E->next()) {
- theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref());
- }
-
- List styleboxs;
- base_theme->get_stylebox_list(type, &styleboxs);
-
- for (List::Element *E = styleboxs.front(); E; E = E->next()) {
- theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref());
- }
-
- List fonts;
- base_theme->get_font_list(type, &fonts);
-
- for (List::Element *E = fonts.front(); E; E = E->next()) {
- theme->set_font(E->get(), type, Ref());
- }
-
- List font_sizes;
- base_theme->get_font_size_list(type, &font_sizes);
-
- for (List::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 colors;
- base_theme->get_color_list(type, &colors);
-
- for (List::Element *E = colors.front(); E; E = E->next()) {
- theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color());
- }
-
- List constants;
- base_theme->get_constant_list(type, &constants);
-
- for (List::Element *E = constants.front(); E; E = E->next()) {
- theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type));
- }
- }
- }
- return;
- }
+void ThemeEditor::_theme_create_menu_cbk(int p_option) {
+ bool import = (p_option == POPUP_IMPORT_EDITOR_THEME);
Ref base_theme;
- name_select_label->show();
- name_hbc->show();
- type_select_label->show();
- type_select->show();
-
- if (p_option == POPUP_ADD) { // Add.
-
- add_del_dialog->set_title(TTR("Add Item"));
- add_del_dialog->get_ok_button()->set_text(TTR("Add"));
- add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE);
-
+ if (p_option == POPUP_CREATE_EMPTY) {
base_theme = Theme::get_default();
-
- } else if (p_option == POPUP_CLASS_ADD) { // Add.
-
- add_del_dialog->set_title(TTR("Add All Items"));
- add_del_dialog->get_ok_button()->set_text(TTR("Add All"));
- add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE);
-
- base_theme = Theme::get_default();
-
- name_select_label->hide();
- name_hbc->hide();
- type_select_label->hide();
- type_select->hide();
-
- } else if (p_option == POPUP_REMOVE) {
- add_del_dialog->set_title(TTR("Remove Item"));
- add_del_dialog->get_ok_button()->set_text(TTR("Remove"));
- add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE);
-
- base_theme = theme;
-
- } else if (p_option == POPUP_CLASS_REMOVE) {
- add_del_dialog->set_title(TTR("Remove All Items"));
- add_del_dialog->get_ok_button()->set_text(TTR("Remove All"));
- add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE);
-
- base_theme = Theme::get_default();
-
- name_select_label->hide();
- name_hbc->hide();
- type_select_label->hide();
- type_select->hide();
+ } else {
+ base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme();
}
- popup_mode = p_option;
- ERR_FAIL_COND(theme.is_null());
+ {
+ List types;
+ base_theme->get_type_list(&types);
- List types;
- base_theme->get_type_list(&types);
+ for (List::Element *T = types.front(); T; T = T->next()) {
+ StringName type = T->get();
- type_menu->get_popup()->clear();
+ List icons;
+ base_theme->get_icon_list(type, &icons);
- if (p_option == 0 || p_option == 1) { // Add.
-
- List new_types;
- theme->get_type_list(&new_types);
- for (List::Element *F = new_types.front(); F; F = F->next()) {
- bool found = false;
- for (List::Element *E = types.front(); E; E = E->next()) {
- if (E->get() == F->get()) {
- found = true;
- break;
- }
+ for (List::Element *E = icons.front(); E; E = E->next()) {
+ theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref());
}
- if (!found) {
- types.push_back(F->get());
+ List styleboxs;
+ base_theme->get_stylebox_list(type, &styleboxs);
+
+ for (List::Element *E = styleboxs.front(); E; E = E->next()) {
+ theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref());
+ }
+
+ List fonts;
+ base_theme->get_font_list(type, &fonts);
+
+ for (List::Element *E = fonts.front(); E; E = E->next()) {
+ theme->set_font(E->get(), type, Ref());
+ }
+
+ List font_sizes;
+ base_theme->get_font_size_list(type, &font_sizes);
+
+ for (List::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 colors;
+ base_theme->get_color_list(type, &colors);
+
+ for (List::Element *E = colors.front(); E; E = E->next()) {
+ theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color());
+ }
+
+ List constants;
+ base_theme->get_constant_list(type, &constants);
+
+ for (List::Element *E = constants.front(); E; E = E->next()) {
+ theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type));
}
}
}
+}
- types.sort_custom();
- for (List::Element *E = types.front(); E; E = E->next()) {
- type_menu->get_popup()->add_item(E->get());
- }
+void ThemeEditor::_theme_edit_button_cbk() {
+ theme_edit_dialog->popup_centered(Size2(800, 640) * EDSCALE);
}
void ThemeEditor::_notification(int p_what) {
@@ -636,9 +1046,6 @@ void ThemeEditor::_notification(int p_what) {
_refresh_interval();
}
} break;
- case NOTIFICATION_THEME_CHANGED: {
- theme_menu->set_icon(get_theme_icon("Theme", "EditorIcons"));
- } break;
}
}
@@ -646,27 +1053,28 @@ void ThemeEditor::_bind_methods() {
}
ThemeEditor::ThemeEditor() {
- time_left = 0;
-
HBoxContainer *top_menu = memnew(HBoxContainer);
add_child(top_menu);
top_menu->add_child(memnew(Label(TTR("Preview:"))));
top_menu->add_spacer(false);
- theme_menu = memnew(MenuButton);
- theme_menu->set_text(TTR("Edit Theme"));
- theme_menu->set_tooltip(TTR("Theme editing menu."));
- theme_menu->get_popup()->add_item(TTR("Add Item"), POPUP_ADD);
- theme_menu->get_popup()->add_item(TTR("Add Class Items"), POPUP_CLASS_ADD);
- theme_menu->get_popup()->add_item(TTR("Remove Item"), POPUP_REMOVE);
- theme_menu->get_popup()->add_item(TTR("Remove Class Items"), POPUP_CLASS_REMOVE);
- theme_menu->get_popup()->add_separator();
- theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY);
- theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
- theme_menu->get_popup()->add_item(TTR("Create From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME);
- top_menu->add_child(theme_menu);
- theme_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_menu_cbk));
+ 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_flat(true);
+ theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk));
+ top_menu->add_child(theme_edit_button);
ScrollContainer *scroll = memnew(ScrollContainer);
add_child(scroll);
@@ -849,66 +1257,9 @@ ThemeEditor::ThemeEditor() {
main_hb->add_theme_constant_override("separation", 20 * EDSCALE);
- ////////
-
- add_del_dialog = memnew(ConfirmationDialog);
- add_del_dialog->hide();
- add_child(add_del_dialog);
-
- VBoxContainer *dialog_vbc = memnew(VBoxContainer);
- add_del_dialog->add_child(dialog_vbc);
-
- Label *l = memnew(Label);
- l->set_text(TTR("Type:"));
- dialog_vbc->add_child(l);
-
- type_hbc = memnew(HBoxContainer);
- dialog_vbc->add_child(type_hbc);
-
- type_edit = memnew(LineEdit);
- type_edit->set_h_size_flags(SIZE_EXPAND_FILL);
- type_hbc->add_child(type_edit);
- type_menu = memnew(MenuButton);
- type_menu->set_flat(false);
- type_menu->set_text("...");
- type_hbc->add_child(type_menu);
-
- type_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_type_menu_cbk));
-
- l = memnew(Label);
- l->set_text(TTR("Name:"));
- dialog_vbc->add_child(l);
- name_select_label = l;
-
- name_hbc = memnew(HBoxContainer);
- dialog_vbc->add_child(name_hbc);
-
- name_edit = memnew(LineEdit);
- name_edit->set_h_size_flags(SIZE_EXPAND_FILL);
- name_hbc->add_child(name_edit);
- name_menu = memnew(MenuButton);
- type_menu->set_flat(false);
- name_menu->set_text("...");
- name_hbc->add_child(name_menu);
-
- name_menu->get_popup()->connect("about_to_popup", callable_mp(this, &ThemeEditor::_name_menu_about_to_show));
- name_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_name_menu_cbk));
-
- type_select_label = memnew(Label);
- type_select_label->set_text(TTR("Data Type:"));
- dialog_vbc->add_child(type_select_label);
-
- type_select = memnew(OptionButton);
- type_select->add_item(TTR("Icon"));
- type_select->add_item(TTR("Style"));
- type_select->add_item(TTR("Font"));
- type_select->add_item(TTR("Font Size"));
- type_select->add_item(TTR("Color"));
- type_select->add_item(TTR("Constant"));
-
- dialog_vbc->add_child(type_select);
-
- add_del_dialog->get_ok_button()->connect("pressed", callable_mp(this, &ThemeEditor::_dialog_cbk));
+ 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"));
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index ab199f8e516..0a840aecd72 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -41,6 +41,77 @@
#include "editor/editor_node.h"
+class ThemeItemEditorDialog : public AcceptDialog {
+ GDCLASS(ThemeItemEditorDialog, AcceptDialog);
+
+ Ref edited_theme;
+
+ ItemList *edit_type_list;
+ OptionButton *edit_add_class_options;
+ LineEdit *edit_add_custom_value;
+ String edited_item_type;
+
+ Button *edit_items_add_color;
+ Button *edit_items_add_constant;
+ Button *edit_items_add_font;
+ Button *edit_items_add_font_size;
+ Button *edit_items_add_icon;
+ Button *edit_items_add_stylebox;
+ Button *edit_items_remove_class;
+ Button *edit_items_remove_custom;
+ Button *edit_items_remove_all;
+ Tree *edit_items_tree;
+
+ enum ItemsTreeAction {
+ ITEMS_TREE_RENAME_ITEM,
+ ITEMS_TREE_REMOVE_ITEM,
+ ITEMS_TREE_REMOVE_DATA_TYPE,
+ };
+
+ ConfirmationDialog *edit_theme_item_dialog;
+ VBoxContainer *edit_theme_item_old_vb;
+ Label *theme_item_old_name;
+ LineEdit *theme_item_name;
+
+ enum ItemPopupMode {
+ CREATE_THEME_ITEM,
+ RENAME_THEME_ITEM,
+ ITEM_POPUP_MODE_MAX
+ };
+
+ ItemPopupMode item_popup_mode = ITEM_POPUP_MODE_MAX;
+ String edit_item_old_name;
+ Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
+
+ void _dialog_about_to_show();
+ void _update_edit_types();
+ void _edited_type_selected(int p_item_idx);
+
+ 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_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();
+ void _remove_custom_items();
+ void _remove_all_items();
+
+ void _open_add_theme_item_dialog(int p_data_type);
+ void _open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name);
+ void _confirm_edit_theme_item();
+ void _edit_theme_item_gui_input(const Ref &p_event);
+
+protected:
+ void _notification(int p_what);
+
+public:
+ void set_edited_theme(const Ref &p_theme);
+
+ ThemeItemEditorDialog();
+};
+
class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer);
@@ -50,40 +121,23 @@ class ThemeEditor : public VBoxContainer {
EditorFileDialog *file_dialog;
- double time_left;
+ double time_left = 0;
- MenuButton *theme_menu;
- ConfirmationDialog *add_del_dialog;
- HBoxContainer *type_hbc;
- MenuButton *type_menu;
- LineEdit *type_edit;
- HBoxContainer *name_hbc;
- MenuButton *name_menu;
- LineEdit *name_edit;
- OptionButton *type_select;
- Label *type_select_label;
- Label *name_select_label;
+ Button *theme_edit_button;
+ MenuButton *theme_create_menu;
+ ThemeItemEditorDialog *theme_edit_dialog;
- enum PopupMode {
- POPUP_ADD,
- POPUP_CLASS_ADD,
- POPUP_REMOVE,
- POPUP_CLASS_REMOVE,
+ enum CreatePopupMode {
POPUP_CREATE_EMPTY,
POPUP_CREATE_EDITOR_EMPTY,
- POPUP_IMPORT_EDITOR_THEME
+ POPUP_IMPORT_EDITOR_THEME,
};
- int popup_mode;
-
Tree *test_tree;
void _save_template_cbk(String fname);
- void _dialog_cbk();
- void _type_menu_cbk(int p_option);
- void _name_menu_about_to_show();
- void _name_menu_cbk(int p_option);
- void _theme_menu_cbk(int p_option);
+ void _theme_edit_button_cbk();
+ void _theme_create_menu_cbk(int p_option);
void _propagate_redraw(Control *p_at);
void _refresh_interval();
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 036d11574cb..e8b203417ef 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -508,6 +508,10 @@ bool Theme::has_icon(const StringName &p_name, const StringName &p_node_type) co
return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid());
}
+bool Theme::has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (icon_map.has(p_node_type) && icon_map[p_node_type].has(p_name));
+}
+
void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!icon_map.has(p_node_type), "Cannot rename the icon '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(icon_map[p_node_type].has(p_name), "Cannot rename the icon '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -592,6 +596,10 @@ bool Theme::has_stylebox(const StringName &p_name, const StringName &p_node_type
return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid());
}
+bool Theme::has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (style_map.has(p_node_type) && style_map[p_node_type].has(p_name));
+}
+
void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!style_map.has(p_node_type), "Cannot rename the stylebox '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(style_map[p_node_type].has(p_name), "Cannot rename the stylebox '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -678,6 +686,10 @@ bool Theme::has_font(const StringName &p_name, const StringName &p_node_type) co
return ((font_map.has(p_node_type) && font_map[p_node_type].has(p_name) && font_map[p_node_type][p_name].is_valid()) || default_theme_font.is_valid());
}
+bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (font_map.has(p_node_type) && font_map[p_node_type].has(p_name));
+}
+
void Theme::rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!font_map.has(p_node_type), "Cannot rename the font '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(font_map[p_node_type].has(p_name), "Cannot rename the font '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -755,6 +767,10 @@ bool Theme::has_font_size(const StringName &p_name, const StringName &p_node_typ
return ((font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name) && (font_size_map[p_node_type][p_name] > 0)) || (default_theme_font_size > 0));
}
+bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (font_size_map.has(p_node_type) && font_size_map[p_node_type].has(p_name));
+}
+
void Theme::rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!font_size_map.has(p_node_type), "Cannot rename the font size '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(font_size_map[p_node_type].has(p_name), "Cannot rename the font size '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -826,6 +842,10 @@ bool Theme::has_color(const StringName &p_name, const StringName &p_node_type) c
return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
}
+bool Theme::has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (color_map.has(p_node_type) && color_map[p_node_type].has(p_name));
+}
+
void Theme::rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!color_map.has(p_node_type), "Cannot rename the color '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(color_map[p_node_type].has(p_name), "Cannot rename the color '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -896,6 +916,10 @@ bool Theme::has_constant(const StringName &p_name, const StringName &p_node_type
return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
}
+bool Theme::has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const {
+ return (constant_map.has(p_node_type) && constant_map[p_node_type].has(p_name));
+}
+
void Theme::rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
ERR_FAIL_COND_MSG(!constant_map.has(p_node_type), "Cannot rename the constant '" + String(p_old_name) + "' because the node type '" + String(p_node_type) + "' does not exist.");
ERR_FAIL_COND_MSG(constant_map[p_node_type].has(p_name), "Cannot rename the constant '" + String(p_old_name) + "' because the new name '" + String(p_name) + "' already exists.");
@@ -1029,6 +1053,27 @@ bool Theme::has_theme_item(DataType p_data_type, const StringName &p_name, const
return false;
}
+bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const {
+ switch (p_data_type) {
+ case DATA_TYPE_COLOR:
+ return has_color_nocheck(p_name, p_node_type);
+ case DATA_TYPE_CONSTANT:
+ return has_constant_nocheck(p_name, p_node_type);
+ case DATA_TYPE_FONT:
+ return has_font_nocheck(p_name, p_node_type);
+ case DATA_TYPE_FONT_SIZE:
+ return has_font_size_nocheck(p_name, p_node_type);
+ case DATA_TYPE_ICON:
+ return has_icon_nocheck(p_name, p_node_type);
+ case DATA_TYPE_STYLEBOX:
+ return has_stylebox_nocheck(p_name, p_node_type);
+ case DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ return false;
+}
+
void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
switch (p_data_type) {
case DATA_TYPE_COLOR:
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index eb918fac691..7e887b6343c 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -119,6 +119,7 @@ public:
void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref &p_icon);
Ref get_icon(const StringName &p_name, const StringName &p_node_type) const;
bool has_icon(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_icon_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_icon(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_icon(const StringName &p_name, const StringName &p_node_type);
void get_icon_list(StringName p_node_type, List *p_list) const;
@@ -128,6 +129,7 @@ public:
void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref &p_style);
Ref get_stylebox(const StringName &p_name, const StringName &p_node_type) const;
bool has_stylebox(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_stylebox_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_stylebox(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_stylebox(const StringName &p_name, const StringName &p_node_type);
void get_stylebox_list(StringName p_node_type, List *p_list) const;
@@ -137,6 +139,7 @@ public:
void set_font(const StringName &p_name, const StringName &p_node_type, const Ref &p_font);
Ref get_font(const StringName &p_name, const StringName &p_node_type) const;
bool has_font(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_font_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_font(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_font(const StringName &p_name, const StringName &p_node_type);
void get_font_list(StringName p_node_type, List *p_list) const;
@@ -146,6 +149,7 @@ public:
void set_font_size(const StringName &p_name, const StringName &p_node_type, int p_font_size);
int get_font_size(const StringName &p_name, const StringName &p_node_type) const;
bool has_font_size(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_font_size_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_font_size(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_font_size(const StringName &p_name, const StringName &p_node_type);
void get_font_size_list(StringName p_node_type, List *p_list) const;
@@ -155,6 +159,7 @@ public:
void set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color);
Color get_color(const StringName &p_name, const StringName &p_node_type) const;
bool has_color(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_color_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_color(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_color(const StringName &p_name, const StringName &p_node_type);
void get_color_list(StringName p_node_type, List *p_list) const;
@@ -164,6 +169,7 @@ public:
void set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant);
int get_constant(const StringName &p_name, const StringName &p_node_type) const;
bool has_constant(const StringName &p_name, const StringName &p_node_type) const;
+ bool has_constant_nocheck(const StringName &p_name, const StringName &p_node_type) const;
void rename_constant(const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_constant(const StringName &p_name, const StringName &p_node_type);
void get_constant_list(StringName p_node_type, List *p_list) const;
@@ -173,6 +179,7 @@ public:
void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value);
Variant get_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
bool has_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
+ bool has_theme_item_nocheck(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) const;
void rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type);
void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type);
void get_theme_item_list(DataType p_data_type, StringName p_node_type, List *p_list) const;