Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/scene/gui/theme_editor_plugin.h
21327 views
1
/**************************************************************************/
2
/* theme_editor_plugin.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "editor/docks/editor_dock.h"
34
#include "editor/plugins/editor_plugin.h"
35
#include "editor/scene/gui/theme_editor_preview.h"
36
#include "scene/gui/dialogs.h"
37
#include "scene/gui/margin_container.h"
38
#include "scene/gui/tree.h"
39
#include "scene/resources/theme.h"
40
41
class Button;
42
class CheckButton;
43
class EditorFileDialog;
44
class FilterLineEdit;
45
class HSplitContainer;
46
class ItemList;
47
class Label;
48
class LineEdit;
49
class OptionButton;
50
class PanelContainer;
51
class TabBar;
52
class TabContainer;
53
class ThemeEditorPlugin;
54
class TextureRect;
55
56
class ThemeItemImportTree : public VBoxContainer {
57
GDCLASS(ThemeItemImportTree, VBoxContainer);
58
59
Ref<Theme> edited_theme;
60
Ref<Theme> base_theme;
61
62
struct ThemeItem {
63
String type_name;
64
Theme::DataType data_type;
65
String item_name;
66
67
bool operator<(const ThemeItem &p_item) const {
68
if (type_name == p_item.type_name && data_type == p_item.data_type) {
69
return item_name < p_item.item_name;
70
}
71
if (type_name == p_item.type_name) {
72
return data_type < p_item.data_type;
73
}
74
return type_name < p_item.type_name;
75
}
76
};
77
78
enum ItemCheckedState {
79
SELECT_IMPORT_DEFINITION,
80
SELECT_IMPORT_FULL,
81
};
82
83
RBMap<ThemeItem, ItemCheckedState> selected_items;
84
85
LineEdit *import_items_filter = nullptr;
86
87
Tree *import_items_tree = nullptr;
88
List<TreeItem *> tree_color_items;
89
List<TreeItem *> tree_constant_items;
90
List<TreeItem *> tree_font_items;
91
List<TreeItem *> tree_font_size_items;
92
List<TreeItem *> tree_icon_items;
93
List<TreeItem *> tree_stylebox_items;
94
95
bool updating_tree = false;
96
97
enum ItemActionFlag {
98
IMPORT_ITEM = 1,
99
IMPORT_ITEM_DATA = 2,
100
};
101
102
TextureRect *select_colors_icon = nullptr;
103
Label *select_colors_label = nullptr;
104
Button *select_all_colors_button = nullptr;
105
Button *select_full_colors_button = nullptr;
106
Button *deselect_all_colors_button = nullptr;
107
Label *total_selected_colors_label = nullptr;
108
109
TextureRect *select_constants_icon = nullptr;
110
Label *select_constants_label = nullptr;
111
Button *select_all_constants_button = nullptr;
112
Button *select_full_constants_button = nullptr;
113
Button *deselect_all_constants_button = nullptr;
114
Label *total_selected_constants_label = nullptr;
115
116
TextureRect *select_fonts_icon = nullptr;
117
Label *select_fonts_label = nullptr;
118
Button *select_all_fonts_button = nullptr;
119
Button *select_full_fonts_button = nullptr;
120
Button *deselect_all_fonts_button = nullptr;
121
Label *total_selected_fonts_label = nullptr;
122
123
TextureRect *select_font_sizes_icon = nullptr;
124
Label *select_font_sizes_label = nullptr;
125
Button *select_all_font_sizes_button = nullptr;
126
Button *select_full_font_sizes_button = nullptr;
127
Button *deselect_all_font_sizes_button = nullptr;
128
Label *total_selected_font_sizes_label = nullptr;
129
130
TextureRect *select_icons_icon = nullptr;
131
Label *select_icons_label = nullptr;
132
Button *select_all_icons_button = nullptr;
133
Button *select_full_icons_button = nullptr;
134
Button *deselect_all_icons_button = nullptr;
135
Label *total_selected_icons_label = nullptr;
136
137
TextureRect *select_styleboxes_icon = nullptr;
138
Label *select_styleboxes_label = nullptr;
139
Button *select_all_styleboxes_button = nullptr;
140
Button *select_full_styleboxes_button = nullptr;
141
Button *deselect_all_styleboxes_button = nullptr;
142
Label *total_selected_styleboxes_label = nullptr;
143
144
HBoxContainer *select_icons_warning_hb = nullptr;
145
TextureRect *select_icons_warning_icon = nullptr;
146
Label *select_icons_warning = nullptr;
147
148
Button *import_collapse_types_button = nullptr;
149
Button *import_expand_types_button = nullptr;
150
Button *import_select_all_button = nullptr;
151
Button *import_select_full_button = nullptr;
152
Button *import_deselect_all_button = nullptr;
153
154
void _update_items_tree();
155
void _toggle_type_items(bool p_collapse);
156
void _filter_text_changed(const String &p_value);
157
158
void _store_selected_item(TreeItem *p_tree_item);
159
void _restore_selected_item(TreeItem *p_tree_item);
160
void _update_total_selected(Theme::DataType p_data_type);
161
162
void _tree_item_edited();
163
void _check_propagated_to_tree_item(Object *p_obj, int p_column);
164
void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
165
void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
166
167
void _select_all_items_pressed();
168
void _select_full_items_pressed();
169
void _deselect_all_items_pressed();
170
171
void _select_all_data_type_pressed(int p_data_type);
172
void _select_full_data_type_pressed(int p_data_type);
173
void _deselect_all_data_type_pressed(int p_data_type);
174
175
void _import_selected();
176
177
protected:
178
void _notification(int p_what);
179
static void _bind_methods();
180
181
public:
182
void set_edited_theme(const Ref<Theme> &p_theme);
183
void set_base_theme(const Ref<Theme> &p_theme);
184
void reset_item_tree();
185
186
bool has_selected_items() const;
187
188
ThemeItemImportTree();
189
};
190
191
class ThemeTypeEditor;
192
193
class ThemeItemEditorDialog : public AcceptDialog {
194
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
195
196
ThemeTypeEditor *theme_type_editor = nullptr;
197
198
Ref<Theme> edited_theme;
199
200
TabContainer *tc = nullptr;
201
202
enum TypesTreeAction {
203
TYPES_TREE_REMOVE_ITEM,
204
};
205
206
Tree *edit_type_list = nullptr;
207
LineEdit *edit_add_type_value = nullptr;
208
Button *edit_add_type_button = nullptr;
209
String edited_item_type;
210
211
Button *edit_items_add_color = nullptr;
212
Button *edit_items_add_constant = nullptr;
213
Button *edit_items_add_font = nullptr;
214
Button *edit_items_add_font_size = nullptr;
215
Button *edit_items_add_icon = nullptr;
216
Button *edit_items_add_stylebox = nullptr;
217
Button *edit_items_remove_class = nullptr;
218
Button *edit_items_remove_custom = nullptr;
219
Button *edit_items_remove_all = nullptr;
220
Tree *edit_items_tree = nullptr;
221
Label *edit_items_message = nullptr;
222
223
enum ItemsTreeAction {
224
ITEMS_TREE_RENAME_ITEM,
225
ITEMS_TREE_REMOVE_ITEM,
226
ITEMS_TREE_REMOVE_DATA_TYPE,
227
};
228
229
ConfirmationDialog *edit_theme_item_dialog = nullptr;
230
VBoxContainer *edit_theme_item_old_vb = nullptr;
231
Label *theme_item_old_name = nullptr;
232
LineEdit *theme_item_name = nullptr;
233
234
enum ItemPopupMode {
235
CREATE_THEME_ITEM,
236
RENAME_THEME_ITEM,
237
ITEM_POPUP_MODE_MAX
238
};
239
240
ItemPopupMode item_popup_mode = ITEM_POPUP_MODE_MAX;
241
String edit_item_old_name;
242
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
243
244
ThemeItemImportTree *import_default_theme_items = nullptr;
245
ThemeItemImportTree *import_editor_theme_items = nullptr;
246
ThemeItemImportTree *import_other_theme_items = nullptr;
247
248
LineEdit *import_another_theme_value = nullptr;
249
Button *import_another_theme_button = nullptr;
250
EditorFileDialog *import_another_theme_dialog = nullptr;
251
252
ConfirmationDialog *confirm_closing_dialog = nullptr;
253
254
void ok_pressed() override;
255
void _close_dialog();
256
257
void _dialog_about_to_show();
258
void _update_edit_types();
259
void _edited_type_selected();
260
void _edited_type_edited();
261
void _edited_type_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
262
263
void _update_edit_item_tree(String p_item_type);
264
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
265
266
void _add_theme_type();
267
void _add_theme_item(Theme::DataType p_data_type, const String &p_item_name, const String &p_item_type);
268
void _remove_theme_type(const String &p_theme_type);
269
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
270
void _remove_class_items();
271
void _remove_custom_items();
272
void _remove_all_items();
273
274
void _open_add_theme_item_dialog(int p_data_type);
275
void _open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name);
276
void _confirm_edit_theme_item();
277
void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event);
278
279
void _open_select_another_theme();
280
void _select_another_theme_cbk(const String &p_path);
281
282
protected:
283
void _notification(int p_what);
284
static void _bind_methods();
285
286
public:
287
void set_edited_theme(const Ref<Theme> &p_theme);
288
289
ThemeItemEditorDialog(ThemeTypeEditor *p_theme_editor);
290
};
291
292
class ThemeTypeDialog : public ConfirmationDialog {
293
GDCLASS(ThemeTypeDialog, ConfirmationDialog);
294
295
Ref<Theme> edited_theme;
296
bool include_own_types = false;
297
298
String pre_submitted_value;
299
300
FilterLineEdit *add_type_filter = nullptr;
301
ItemList *add_type_options = nullptr;
302
ConfirmationDialog *add_type_confirmation = nullptr;
303
304
void _dialog_about_to_show();
305
void ok_pressed() override;
306
307
void _update_add_type_options(const String &p_filter = "");
308
309
void _add_type_filter_cbk(const String &p_value);
310
void _add_type_options_cbk(int p_index);
311
void _add_type_dialog_entered(const String &p_value);
312
void _add_type_dialog_activated(int p_index);
313
314
void _add_type_selected(const String &p_type_name);
315
void _add_type_confirmed();
316
317
protected:
318
void _notification(int p_what);
319
static void _bind_methods();
320
321
public:
322
void set_edited_theme(const Ref<Theme> &p_theme);
323
void set_include_own_types(bool p_enable);
324
325
ThemeTypeDialog();
326
};
327
328
// Custom `Label` needed to use `EditorHelpBit` to display theme item documentation.
329
class ThemeItemLabel : public Label {
330
virtual Control *make_custom_tooltip(const String &p_text) const;
331
};
332
333
class ThemeTypeEditor : public MarginContainer {
334
GDCLASS(ThemeTypeEditor, MarginContainer);
335
336
Ref<Theme> edited_theme;
337
String edited_type;
338
bool updating = false;
339
340
struct LeadingStylebox {
341
bool pinned = false;
342
StringName item_name;
343
Ref<StyleBox> stylebox;
344
Ref<StyleBox> ref_stylebox;
345
};
346
347
LeadingStylebox leading_stylebox;
348
349
OptionButton *theme_type_list = nullptr;
350
Button *add_type_button = nullptr;
351
Button *rename_type_button = nullptr;
352
ConfirmationDialog *theme_type_rename_dialog = nullptr;
353
LineEdit *theme_type_rename_line_edit = nullptr;
354
Button *remove_type_button = nullptr;
355
356
CheckButton *show_default_items_button = nullptr;
357
358
TabContainer *data_type_tabs = nullptr;
359
VBoxContainer *color_items_list = nullptr;
360
VBoxContainer *constant_items_list = nullptr;
361
VBoxContainer *font_items_list = nullptr;
362
VBoxContainer *font_size_items_list = nullptr;
363
VBoxContainer *icon_items_list = nullptr;
364
VBoxContainer *stylebox_items_list = nullptr;
365
366
LineEdit *type_variation_edit = nullptr;
367
Button *type_variation_button = nullptr;
368
Label *type_variation_locked = nullptr;
369
370
enum TypeDialogMode {
371
ADD_THEME_TYPE,
372
ADD_VARIATION_BASE,
373
};
374
375
TypeDialogMode add_type_mode = ADD_THEME_TYPE;
376
ThemeTypeDialog *add_type_dialog = nullptr;
377
378
Vector<Control *> focusables;
379
Timer *update_debounce_timer = nullptr;
380
381
VBoxContainer *_create_item_list(Theme::DataType p_data_type);
382
void _update_type_list();
383
void _update_type_list_debounced();
384
HashMap<StringName, bool> _get_type_items(String p_type_name, Theme::DataType p_type, bool p_include_default);
385
HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
386
void _add_focusable(Control *p_control);
387
void _update_type_items();
388
389
void _list_type_selected(int p_index);
390
void _add_type_button_cbk();
391
void _rename_type_button_cbk();
392
void _theme_type_rename_dialog_confirmed();
393
void _remove_type_button_cbk();
394
void _add_default_type_items();
395
396
void _update_add_button(const String &p_text, LineEdit *p_for_edit);
397
void _item_add_cbk(int p_data_type, Control *p_control);
398
void _item_add_lineedit_cbk(String p_value, int p_data_type, Control *p_control);
399
void _item_override_cbk(int p_data_type, String p_item_name);
400
void _item_remove_cbk(int p_data_type, String p_item_name);
401
void _item_rename_cbk(int p_data_type, String p_item_name, Control *p_control);
402
void _item_rename_confirmed(int p_data_type, String p_item_name, Control *p_control);
403
void _item_rename_entered(String p_value, int p_data_type, String p_item_name, Control *p_control);
404
void _item_rename_canceled(int p_data_type, String p_item_name, Control *p_control);
405
406
void _color_item_changed(Color p_value, String p_item_name);
407
void _constant_item_changed(float p_value, String p_item_name);
408
void _font_size_item_changed(float p_value, String p_item_name);
409
void _edit_resource_item(Ref<Resource> p_resource, bool p_edit);
410
void _font_item_changed(Ref<Font> p_value, String p_item_name);
411
void _icon_item_changed(Ref<Texture2D> p_value, String p_item_name);
412
void _stylebox_item_changed(Ref<StyleBox> p_value, String p_item_name);
413
void _change_pinned_stylebox();
414
void _on_pin_leader_button_pressed(Control *p_editor, String p_item_name);
415
void _pin_leading_stylebox(String p_item_name, Ref<StyleBox> p_stylebox);
416
void _on_unpin_leader_button_pressed();
417
void _unpin_leading_stylebox();
418
void _update_stylebox_from_leading();
419
420
void _type_variation_changed(const String p_value);
421
void _add_type_variation_cbk();
422
423
void _add_type_dialog_selected(const String p_type_name);
424
425
protected:
426
void _notification(int p_what);
427
static void _bind_methods();
428
429
public:
430
void set_edited_theme(const Ref<Theme> &p_theme);
431
void select_type(String p_type_name);
432
bool is_stylebox_pinned(Ref<StyleBox> p_stylebox);
433
434
ThemeTypeEditor();
435
};
436
437
class ThemeEditor : public EditorDock {
438
GDCLASS(ThemeEditor, EditorDock);
439
440
friend class ThemeEditorPlugin;
441
ThemeEditorPlugin *plugin = nullptr;
442
443
Ref<Theme> theme;
444
445
Button *theme_edit_button = nullptr;
446
Button *theme_close_button = nullptr;
447
448
TabBar *preview_tabs = nullptr;
449
PanelContainer *preview_tabs_content = nullptr;
450
Control *add_preview_button_ph = nullptr;
451
Button *add_preview_button = nullptr;
452
EditorFileDialog *preview_scene_dialog = nullptr;
453
454
ThemeTypeEditor *theme_type_editor = nullptr;
455
456
Label *theme_name = nullptr;
457
ThemeItemEditorDialog *theme_edit_dialog = nullptr;
458
HSplitContainer *main_hs = nullptr;
459
460
void _theme_save_button_cbk(bool p_save_as);
461
void _theme_edit_button_cbk();
462
void _theme_close_button_cbk();
463
void _dock_closed_cbk();
464
void _scene_closed(const String &p_path);
465
void _resource_saved(const Ref<Resource> &p_resource);
466
void _files_moved(const String &p_old_path, const String &p_new_path);
467
void _update_theme_name(const String &p_name);
468
469
void _add_preview_button_cbk();
470
void _preview_scene_dialog_cbk(const String &p_path);
471
void _add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon);
472
void _change_preview_tab(int p_tab);
473
void _remove_preview_tab(int p_tab);
474
void _remove_preview_tab_invalid(Node *p_tab_control);
475
void _update_preview_tab(Node *p_tab_control);
476
void _preview_control_picked(String p_class_name);
477
void _preview_tabs_resized();
478
479
protected:
480
void _notification(int p_what);
481
482
virtual void save_layout_to_config(Ref<ConfigFile> &p_layout, const String &p_section) const override;
483
virtual void load_layout_from_config(const Ref<ConfigFile> &p_layout, const String &p_section) override;
484
485
public:
486
void edit(const Ref<Theme> &p_theme);
487
Ref<Theme> get_edited_theme();
488
489
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
490
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
491
492
ThemeEditor();
493
};
494
495
class ThemeEditorPlugin : public EditorPlugin {
496
GDCLASS(ThemeEditorPlugin, EditorPlugin);
497
498
ThemeEditor *theme_editor = nullptr;
499
500
public:
501
virtual String get_plugin_name() const override { return "Theme"; }
502
bool has_main_screen() const override { return false; }
503
virtual void edit(Object *p_object) override;
504
virtual bool handles(Object *p_object) const override;
505
virtual void make_visible(bool p_visible) override;
506
virtual bool can_auto_hide() const override;
507
508
ThemeEditorPlugin();
509
};
510
511