Merge pull request #49512 from pycbouh/editor-better-theme-management-3.x
[3.x] Refactor `Theme` item management in the theme editor
1
editor/icons/icon_collapse_tree.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 9.669-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m8 6.355-3.536-2.583h2.536v-2.537h2v2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>
|
After Width: | Height: | Size: 360 B |
1
editor/icons/icon_expand_tree.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 16-3.536-2.597h2.536v-2.523h2v2.523h2.536z"/><path d="m8 0-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg>
|
After Width: | Height: | Size: 353 B |
1
editor/icons/icon_node_disabled.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#999"/></svg>
|
After Width: | Height: | Size: 240 B |
1
editor/icons/icon_theme_deselect_all.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5.952 6.976h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z"/><path d="m5.952 1.956h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/><path d="m5.952 11.996h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/></g></svg>
|
After Width: | Height: | Size: 582 B |
1
editor/icons/icon_theme_remove_all_items.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#8eef97"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff4545"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffe345"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#80ff45"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#45ffa2"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#45d7ff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff4596"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#8045ff"/></g></svg>
|
After Width: | Height: | Size: 1.7 KiB |
1
editor/icons/icon_theme_remove_custom_items.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffe345"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#80ff45"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#45ffa2"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#45d7ff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff4596"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#8045ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff4545"/></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
editor/icons/icon_theme_select_all.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m5.952 6.976h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m5.952 1.956h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.952 11.996h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/></svg>
|
After Width: | Height: | Size: 874 B |
1
editor/icons/icon_theme_select_full.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m11 6.976h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m11 1.956h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m11 11.996h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.995 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 5.995h4.01v4.01h-4.01zm.968.968h2.074v2.074h-2.074z" fill="#e0e0e0"/><path d="m5.995.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995.974h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/><path d="m5.995 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 11.015h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -31,8 +31,6 @@
|
|||
#ifndef THEME_EDITOR_PLUGIN_H
|
||||
#define THEME_EDITOR_PLUGIN_H
|
||||
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/file_dialog.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
|
@ -41,49 +39,233 @@
|
|||
|
||||
#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_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_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;
|
||||
|
||||
TabContainer *tc;
|
||||
|
||||
ItemList *edit_type_list;
|
||||
LineEdit *edit_add_type_value;
|
||||
String edited_item_type;
|
||||
|
||||
Button *edit_items_add_color;
|
||||
Button *edit_items_add_constant;
|
||||
Button *edit_items_add_font;
|
||||
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;
|
||||
|
||||
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();
|
||||
void _close_dialog();
|
||||
|
||||
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_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();
|
||||
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<InputEvent> &p_event);
|
||||
|
||||
void _open_select_another_theme();
|
||||
void _select_another_theme_cbk(const String &p_path);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_edited_theme(const Ref<Theme> &p_theme);
|
||||
|
||||
ThemeItemEditorDialog();
|
||||
};
|
||||
|
||||
class ThemeEditor : public VBoxContainer {
|
||||
GDCLASS(ThemeEditor, VBoxContainer);
|
||||
|
||||
Ref<Theme> theme;
|
||||
double time_left = 0;
|
||||
|
||||
ThemeItemEditorDialog *theme_edit_dialog;
|
||||
|
||||
void _theme_edit_button_cbk();
|
||||
|
||||
Panel *main_panel;
|
||||
MarginContainer *main_container;
|
||||
Ref<Theme> theme;
|
||||
|
||||
EditorFileDialog *file_dialog;
|
||||
|
||||
double time_left;
|
||||
|
||||
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;
|
||||
|
||||
enum PopupMode {
|
||||
POPUP_ADD,
|
||||
POPUP_CLASS_ADD,
|
||||
POPUP_REMOVE,
|
||||
POPUP_CLASS_REMOVE,
|
||||
POPUP_CREATE_EMPTY,
|
||||
POPUP_CREATE_EDITOR_EMPTY,
|
||||
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 _propagate_redraw(Control *p_at);
|
||||
void _refresh_interval();
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
#include "core/print_string.h"
|
||||
|
||||
void Theme::_emit_theme_changed() {
|
||||
if (no_change_propagation) {
|
||||
return;
|
||||
}
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
|
@ -381,8 +386,7 @@ void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
|
|||
default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Ref<Font> Theme::get_default_theme_font() const {
|
||||
|
@ -424,8 +428,6 @@ void Theme::set_default_font(const Ref<Font> &p_font) {
|
|||
}
|
||||
|
||||
void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon) {
|
||||
bool new_value = !icon_map.has(p_node_type) || !icon_map[p_node_type].has(p_name);
|
||||
|
||||
if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
|
||||
icon_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
|
||||
}
|
||||
|
@ -436,10 +438,7 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, co
|
|||
icon_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -454,6 +453,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.");
|
||||
|
@ -462,8 +465,7 @@ void Theme::rename_icon(const StringName &p_old_name, const StringName &p_name,
|
|||
icon_map[p_node_type][p_name] = icon_map[p_node_type][p_old_name];
|
||||
icon_map[p_node_type].erase(p_old_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type) {
|
||||
|
@ -476,8 +478,7 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_node_type)
|
|||
|
||||
icon_map[p_node_type].erase(p_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_icon_list(StringName p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -511,14 +512,9 @@ void Theme::get_icon_types(List<StringName> *p_list) const {
|
|||
}
|
||||
|
||||
void Theme::set_shader(const StringName &p_name, const StringName &p_node_type, const Ref<Shader> &p_shader) {
|
||||
bool new_value = !shader_map.has(p_node_type) || !shader_map[p_node_type].has(p_name);
|
||||
|
||||
shader_map[p_node_type][p_name] = p_shader;
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -538,8 +534,8 @@ void Theme::clear_shader(const StringName &p_name, const StringName &p_node_type
|
|||
ERR_FAIL_COND(!shader_map[p_node_type].has(p_name));
|
||||
|
||||
shader_map[p_node_type].erase(p_name);
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -557,8 +553,6 @@ void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_l
|
|||
}
|
||||
|
||||
void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) {
|
||||
bool new_value = !style_map.has(p_node_type) || !style_map[p_node_type].has(p_name);
|
||||
|
||||
if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) {
|
||||
style_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
|
||||
}
|
||||
|
@ -569,10 +563,7 @@ void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type
|
|||
style_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
}
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -587,6 +578,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.");
|
||||
|
@ -595,8 +590,7 @@ void Theme::rename_stylebox(const StringName &p_old_name, const StringName &p_na
|
|||
style_map[p_node_type][p_name] = style_map[p_node_type][p_old_name];
|
||||
style_map[p_node_type].erase(p_old_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_type) {
|
||||
|
@ -609,8 +603,7 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_node_ty
|
|||
|
||||
style_map[p_node_type].erase(p_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_stylebox_list(StringName p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -644,8 +637,6 @@ void Theme::get_stylebox_types(List<StringName> *p_list) const {
|
|||
}
|
||||
|
||||
void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) {
|
||||
bool new_value = !font_map.has(p_node_type) || !font_map[p_node_type].has(p_name);
|
||||
|
||||
if (font_map[p_node_type][p_name].is_valid()) {
|
||||
font_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
|
||||
}
|
||||
|
@ -656,10 +647,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_node_type, co
|
|||
font_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -676,6 +664,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());
|
||||
}
|
||||
|
||||
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.");
|
||||
|
@ -684,8 +676,7 @@ void Theme::rename_font(const StringName &p_old_name, const StringName &p_name,
|
|||
font_map[p_node_type][p_name] = font_map[p_node_type][p_old_name];
|
||||
font_map[p_node_type].erase(p_old_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear_font(const StringName &p_name, const StringName &p_node_type) {
|
||||
|
@ -697,8 +688,8 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_node_type)
|
|||
}
|
||||
|
||||
font_map[p_node_type].erase(p_name);
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_font_list(StringName p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -732,14 +723,9 @@ void Theme::get_font_types(List<StringName> *p_list) const {
|
|||
}
|
||||
|
||||
void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) {
|
||||
bool new_value = !color_map.has(p_node_type) || !color_map[p_node_type].has(p_name);
|
||||
|
||||
color_map[p_node_type][p_name] = p_color;
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
Color Theme::get_color(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -754,6 +740,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.");
|
||||
|
@ -762,8 +752,7 @@ void Theme::rename_color(const StringName &p_old_name, const StringName &p_name,
|
|||
color_map[p_node_type][p_name] = color_map[p_node_type][p_old_name];
|
||||
color_map[p_node_type].erase(p_old_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear_color(const StringName &p_name, const StringName &p_node_type) {
|
||||
|
@ -771,8 +760,8 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_node_type)
|
|||
ERR_FAIL_COND_MSG(!color_map[p_node_type].has(p_name), "Cannot clear the color '" + String(p_name) + "' because it does not exist.");
|
||||
|
||||
color_map[p_node_type].erase(p_name);
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_color_list(StringName p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -806,13 +795,9 @@ void Theme::get_color_types(List<StringName> *p_list) const {
|
|||
}
|
||||
|
||||
void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) {
|
||||
bool new_value = !constant_map.has(p_node_type) || !constant_map[p_node_type].has(p_name);
|
||||
constant_map[p_node_type][p_name] = p_constant;
|
||||
|
||||
if (new_value) {
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
}
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
int Theme::get_constant(const StringName &p_name, const StringName &p_node_type) const {
|
||||
|
@ -827,6 +812,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.");
|
||||
|
@ -835,8 +824,7 @@ void Theme::rename_constant(const StringName &p_old_name, const StringName &p_na
|
|||
constant_map[p_node_type][p_name] = constant_map[p_node_type][p_old_name];
|
||||
constant_map[p_node_type].erase(p_old_name);
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear_constant(const StringName &p_name, const StringName &p_node_type) {
|
||||
|
@ -844,8 +832,8 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_node_ty
|
|||
ERR_FAIL_COND_MSG(!constant_map[p_node_type].has(p_name), "Cannot clear the constant '" + String(p_name) + "' because it does not exist.");
|
||||
|
||||
constant_map[p_node_type].erase(p_name);
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::get_constant_list(StringName p_node_type, List<StringName> *p_list) const {
|
||||
|
@ -953,6 +941,25 @@ 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_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:
|
||||
|
@ -1063,6 +1070,15 @@ void Theme::get_theme_item_types(DataType p_data_type, List<StringName> *p_list)
|
|||
}
|
||||
}
|
||||
|
||||
void Theme::_freeze_change_propagation() {
|
||||
no_change_propagation = true;
|
||||
}
|
||||
|
||||
void Theme::_unfreeze_and_propagate_changes() {
|
||||
no_change_propagation = false;
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::clear() {
|
||||
//these need disconnecting
|
||||
{
|
||||
|
@ -1111,8 +1127,7 @@ void Theme::clear() {
|
|||
color_map.clear();
|
||||
constant_map.clear();
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_emit_theme_changed();
|
||||
}
|
||||
|
||||
void Theme::copy_default_theme() {
|
||||
|
@ -1126,6 +1141,8 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
|
|||
return;
|
||||
}
|
||||
|
||||
_freeze_change_propagation();
|
||||
|
||||
// These items need reconnecting, so add them normally.
|
||||
{
|
||||
const StringName *K = nullptr;
|
||||
|
@ -1162,8 +1179,7 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
|
|||
constant_map = p_other->constant_map;
|
||||
shader_map = p_other->shader_map;
|
||||
|
||||
_change_notify();
|
||||
emit_changed();
|
||||
_unfreeze_and_propagate_changes();
|
||||
}
|
||||
|
||||
void Theme::get_type_list(List<StringName> *p_list) const {
|
||||
|
|
|
@ -42,6 +42,11 @@ class Theme : public Resource {
|
|||
GDCLASS(Theme, Resource);
|
||||
RES_BASE_EXTENSION("theme");
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
friend class ThemeItemImportTree;
|
||||
friend class ThemeItemEditorDialog;
|
||||
#endif
|
||||
|
||||
public:
|
||||
enum DataType {
|
||||
DATA_TYPE_COLOR,
|
||||
|
@ -53,6 +58,8 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
bool no_change_propagation = false;
|
||||
|
||||
void _emit_theme_changed();
|
||||
|
||||
HashMap<StringName, HashMap<StringName, Ref<Texture>>> icon_map;
|
||||
|
@ -92,6 +99,9 @@ protected:
|
|||
|
||||
static void _bind_methods();
|
||||
|
||||
void _freeze_change_propagation();
|
||||
void _unfreeze_and_propagate_changes();
|
||||
|
||||
public:
|
||||
static Ref<Theme> get_default();
|
||||
static void set_default(const Ref<Theme> &p_default);
|
||||
|
@ -109,6 +119,7 @@ public:
|
|||
void set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon);
|
||||
Ref<Texture> 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<StringName> *p_list) const;
|
||||
|
@ -124,6 +135,7 @@ public:
|
|||
void set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style);
|
||||
Ref<StyleBox> 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<StringName> *p_list) const;
|
||||
|
@ -133,6 +145,7 @@ public:
|
|||
void set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font);
|
||||
Ref<Font> 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<StringName> *p_list) const;
|
||||
|
@ -142,6 +155,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<StringName> *p_list) const;
|
||||
|
@ -151,6 +165,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<StringName> *p_list) const;
|
||||
|
@ -160,6 +175,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<StringName> *p_list) const;
|
||||
|
|