1 /*************************************************************************/
2 /* theme_editor_plugin.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
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 #include "theme_editor_plugin.h"
31 #include "os/file_access.h"
32 #include "version.h"
33
edit(const Ref<Theme> & p_theme)34 void ThemeEditor::edit(const Ref<Theme> &p_theme) {
35
36 theme = p_theme;
37 main_vb->set_theme(p_theme);
38 }
39
_propagate_redraw(Control * p_at)40 void ThemeEditor::_propagate_redraw(Control *p_at) {
41
42 p_at->notification(NOTIFICATION_THEME_CHANGED);
43 p_at->minimum_size_changed();
44 p_at->update();
45 for (int i = 0; i < p_at->get_child_count(); i++) {
46 Control *a = p_at->get_child(i)->cast_to<Control>();
47 if (a)
48 _propagate_redraw(a);
49 }
50 }
51
_refresh_interval()52 void ThemeEditor::_refresh_interval() {
53
54 _propagate_redraw(main_vb);
55 }
56
_type_menu_cbk(int p_option)57 void ThemeEditor::_type_menu_cbk(int p_option) {
58
59 type_edit->set_text(type_menu->get_popup()->get_item_text(p_option));
60 }
61
_name_menu_about_to_show()62 void ThemeEditor::_name_menu_about_to_show() {
63
64 String fromtype = type_edit->get_text();
65 List<StringName> names;
66
67 if (popup_mode == POPUP_ADD) {
68
69 switch (type_select->get_selected()) {
70
71 case 0: Theme::get_default()->get_icon_list(fromtype, &names); break;
72 case 1: Theme::get_default()->get_stylebox_list(fromtype, &names); break;
73 case 2: Theme::get_default()->get_font_list(fromtype, &names); break;
74 case 3: Theme::get_default()->get_color_list(fromtype, &names); break;
75 case 4: Theme::get_default()->get_constant_list(fromtype, &names); break;
76 }
77 } else if (popup_mode == POPUP_REMOVE) {
78
79 theme->get_icon_list(fromtype, &names);
80 theme->get_stylebox_list(fromtype, &names);
81 theme->get_font_list(fromtype, &names);
82 theme->get_color_list(fromtype, &names);
83 theme->get_constant_list(fromtype, &names);
84 }
85
86 name_menu->get_popup()->clear();
87
88 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
89
90 name_menu->get_popup()->add_item(E->get());
91 }
92 }
93
_name_menu_cbk(int p_option)94 void ThemeEditor::_name_menu_cbk(int p_option) {
95
96 name_edit->set_text(name_menu->get_popup()->get_item_text(p_option));
97 }
98
99 struct _TECategory {
100
101 template <class T>
102 struct RefItem {
103
104 Ref<T> item;
105 StringName name;
operator <_TECategory::RefItem106 bool operator<(const RefItem<T> &p) const { return item->get_instance_ID() < p.item->get_instance_ID(); }
107 };
108
109 template <class T>
110 struct Item {
111
112 T item;
113 String name;
operator <_TECategory::Item114 bool operator<(const Item<T> &p) const { return name < p.name; }
115 };
116
117 Set<RefItem<StyleBox> > stylebox_items;
118 Set<RefItem<Font> > font_items;
119 Set<RefItem<Texture> > icon_items;
120
121 Set<Item<Color> > color_items;
122 Set<Item<int> > constant_items;
123 };
124
_save_template_cbk(String fname)125 void ThemeEditor::_save_template_cbk(String fname) {
126
127 String filename = file_dialog->get_current_path();
128
129 Map<String, _TECategory> categories;
130
131 //fill types
132 List<StringName> type_list;
133 Theme::get_default()->get_type_list(&type_list);
134 for (List<StringName>::Element *E = type_list.front(); E; E = E->next()) {
135 categories.insert(E->get(), _TECategory());
136 }
137
138 //fill default theme
139 for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
140
141 _TECategory &tc = E->get();
142
143 List<StringName> stylebox_list;
144 Theme::get_default()->get_stylebox_list(E->key(), &stylebox_list);
145 for (List<StringName>::Element *F = stylebox_list.front(); F; F = F->next()) {
146 _TECategory::RefItem<StyleBox> it;
147 it.name = F->get();
148 it.item = Theme::get_default()->get_stylebox(F->get(), E->key());
149 tc.stylebox_items.insert(it);
150 }
151
152 List<StringName> font_list;
153 Theme::get_default()->get_font_list(E->key(), &font_list);
154 for (List<StringName>::Element *F = font_list.front(); F; F = F->next()) {
155 _TECategory::RefItem<Font> it;
156 it.name = F->get();
157 it.item = Theme::get_default()->get_font(F->get(), E->key());
158 tc.font_items.insert(it);
159 }
160
161 List<StringName> icon_list;
162 Theme::get_default()->get_icon_list(E->key(), &icon_list);
163 for (List<StringName>::Element *F = icon_list.front(); F; F = F->next()) {
164 _TECategory::RefItem<Texture> it;
165 it.name = F->get();
166 it.item = Theme::get_default()->get_icon(F->get(), E->key());
167 tc.icon_items.insert(it);
168 }
169
170 List<StringName> color_list;
171 Theme::get_default()->get_color_list(E->key(), &color_list);
172 for (List<StringName>::Element *F = color_list.front(); F; F = F->next()) {
173 _TECategory::Item<Color> it;
174 it.name = F->get();
175 it.item = Theme::get_default()->get_color(F->get(), E->key());
176 tc.color_items.insert(it);
177 }
178
179 List<StringName> constant_list;
180 Theme::get_default()->get_constant_list(E->key(), &constant_list);
181 for (List<StringName>::Element *F = constant_list.front(); F; F = F->next()) {
182 _TECategory::Item<int> it;
183 it.name = F->get();
184 it.item = Theme::get_default()->get_constant(F->get(), E->key());
185 tc.constant_items.insert(it);
186 }
187 }
188
189 FileAccess *file = FileAccess::open(filename, FileAccess::WRITE);
190 if (!file) {
191
192 ERR_EXPLAIN(TTR("Can't save theme to file:") + " " + filename);
193 return;
194 }
195 file->store_line("; ******************* ");
196 file->store_line("; Template Theme File ");
197 file->store_line("; ******************* ");
198 file->store_line("; ");
199 file->store_line("; Theme Syntax: ");
200 file->store_line("; ------------- ");
201 file->store_line("; ");
202 file->store_line("; Must be placed in section [theme]");
203 file->store_line("; ");
204 file->store_line("; Type.item = [value] ");
205 file->store_line("; ");
206 file->store_line("; [value] examples:");
207 file->store_line("; ");
208 file->store_line("; Type.item = 6 ; numeric constant. ");
209 file->store_line("; Type.item = #FF00FF ; HTML color ");
210 file->store_line("; Type.item = #55FF00FF ; HTML color with alpha 55.");
211 file->store_line("; Type.item = icon(image.png) ; icon in a png file (relative to theme file).");
212 file->store_line("; Type.item = font(font.xres) ; font in a resource (relative to theme file).");
213 file->store_line("; Type.item = sbox(stylebox.xres) ; stylebox in a resource (relative to theme file).");
214 file->store_line("; Type.item = sboxf(2,#FF00FF) ; flat stylebox with margin 2.");
215 file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF) ; flat stylebox with margin 2 and border.");
216 file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF,#000000) ; flat stylebox with margin 2, light & dark borders.");
217 file->store_line("; Type.item = sboxt(base.png,2,2,2,2) ; textured stylebox with 3x3 stretch and stretch margins.");
218 file->store_line("; -Additionally, 4 extra integers can be added to sboxf and sboxt to specify custom padding of contents:");
219 file->store_line("; Type.item = sboxt(base.png,2,2,2,2,5,4,2,4) ;");
220 file->store_line("; -Order for all is always left, top, right, bottom.");
221 file->store_line("; ");
222 file->store_line("; Special values:");
223 file->store_line("; Type.item = default ; use the value in the default theme (must exist there).");
224 file->store_line("; Type.item = @somebutton_color ; reference to a library value previously defined.");
225 file->store_line("; ");
226 file->store_line("; Library Syntax: ");
227 file->store_line("; --------------- ");
228 file->store_line("; ");
229 file->store_line("; Must be placed in section [library], but usage is optional.");
230 file->store_line("; ");
231 file->store_line("; item = [value] ; same as Theme, but assign to library.");
232 file->store_line("; ");
233 file->store_line("; examples:");
234 file->store_line("; ");
235 file->store_line("; [library]");
236 file->store_line("; ");
237 file->store_line("; default_button_color = #FF00FF");
238 file->store_line("; ");
239 file->store_line("; [theme]");
240 file->store_line("; ");
241 file->store_line("; Button.color = @default_button_color ; used reference.");
242 file->store_line("; ");
243 file->store_line("; ******************* ");
244 file->store_line("; ");
245 file->store_line("; Template Generated Using: " + String(VERSION_MKSTRING));
246 file->store_line("; ");
247 file->store_line("; ");
248 file->store_line("");
249 file->store_line("[library]");
250 file->store_line("");
251 file->store_line("; place library stuff here");
252 file->store_line("");
253 file->store_line("[theme]");
254 file->store_line("");
255 file->store_line("");
256
257 //write default theme
258 for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) {
259
260 _TECategory &tc = E->get();
261
262 String underline = "; ";
263 for (int i = 0; i < E->key().length(); i++)
264 underline += "*";
265
266 file->store_line("");
267 file->store_line(underline);
268 file->store_line("; " + E->key());
269 file->store_line(underline);
270
271 if (tc.stylebox_items.size())
272 file->store_line("\n; StyleBox Items:\n");
273
274 for (Set<_TECategory::RefItem<StyleBox> >::Element *F = tc.stylebox_items.front(); F; F = F->next()) {
275
276 file->store_line(E->key() + "." + F->get().name + " = default");
277 }
278
279 if (tc.font_items.size())
280 file->store_line("\n; Font Items:\n");
281
282 for (Set<_TECategory::RefItem<Font> >::Element *F = tc.font_items.front(); F; F = F->next()) {
283
284 file->store_line(E->key() + "." + F->get().name + " = default");
285 }
286
287 if (tc.icon_items.size())
288 file->store_line("\n; Icon Items:\n");
289
290 for (Set<_TECategory::RefItem<Texture> >::Element *F = tc.icon_items.front(); F; F = F->next()) {
291
292 file->store_line(E->key() + "." + F->get().name + " = default");
293 }
294
295 if (tc.color_items.size())
296 file->store_line("\n; Color Items:\n");
297
298 for (Set<_TECategory::Item<Color> >::Element *F = tc.color_items.front(); F; F = F->next()) {
299
300 file->store_line(E->key() + "." + F->get().name + " = default");
301 }
302
303 if (tc.constant_items.size())
304 file->store_line("\n; Constant Items:\n");
305
306 for (Set<_TECategory::Item<int> >::Element *F = tc.constant_items.front(); F; F = F->next()) {
307
308 file->store_line(E->key() + "." + F->get().name + " = default");
309 }
310 }
311
312 file->close();
313 memdelete(file);
314 }
315
_dialog_cbk()316 void ThemeEditor::_dialog_cbk() {
317
318 switch (popup_mode) {
319 case POPUP_ADD: {
320
321 switch (type_select->get_selected()) {
322
323 case 0: theme->set_icon(name_edit->get_text(), type_edit->get_text(), Ref<Texture>()); break;
324 case 1: theme->set_stylebox(name_edit->get_text(), type_edit->get_text(), Ref<StyleBox>()); break;
325 case 2: theme->set_font(name_edit->get_text(), type_edit->get_text(), Ref<Font>()); break;
326 case 3: theme->set_color(name_edit->get_text(), type_edit->get_text(), Color()); break;
327 case 4: theme->set_constant(name_edit->get_text(), type_edit->get_text(), 0); break;
328 }
329
330 } break;
331 case POPUP_CLASS_ADD: {
332
333 StringName fromtype = type_edit->get_text();
334 List<StringName> names;
335
336 {
337 names.clear();
338 Theme::get_default()->get_icon_list(fromtype, &names);
339 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
340 theme->set_icon(E->get(), fromtype, Ref<Texture>());
341 }
342 }
343 {
344 names.clear();
345 Theme::get_default()->get_stylebox_list(fromtype, &names);
346 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
347 theme->set_stylebox(E->get(), fromtype, Ref<StyleBox>());
348 }
349 }
350 {
351 names.clear();
352 Theme::get_default()->get_font_list(fromtype, &names);
353 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
354 theme->set_font(E->get(), fromtype, Ref<Font>());
355 }
356 }
357 {
358 names.clear();
359 Theme::get_default()->get_color_list(fromtype, &names);
360 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
361 theme->set_color(E->get(), fromtype, Theme::get_default()->get_color(E->get(), fromtype));
362 }
363 }
364 {
365 names.clear();
366 Theme::get_default()->get_constant_list(fromtype, &names);
367 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
368 theme->set_constant(E->get(), fromtype, Theme::get_default()->get_constant(E->get(), fromtype));
369 }
370 }
371 } break;
372 case POPUP_REMOVE: {
373 switch (type_select->get_selected()) {
374
375 case 0: theme->clear_icon(name_edit->get_text(), type_edit->get_text()); break;
376 case 1: theme->clear_stylebox(name_edit->get_text(), type_edit->get_text()); break;
377 case 2: theme->clear_font(name_edit->get_text(), type_edit->get_text()); break;
378 case 3: theme->clear_color(name_edit->get_text(), type_edit->get_text()); break;
379 case 4: theme->clear_constant(name_edit->get_text(), type_edit->get_text()); break;
380 }
381
382 } break;
383 case POPUP_CLASS_REMOVE: {
384 StringName fromtype = type_edit->get_text();
385 List<StringName> names;
386
387 {
388 names.clear();
389 Theme::get_default()->get_icon_list(fromtype, &names);
390 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
391 theme->clear_icon(E->get(), fromtype);
392 }
393 }
394 {
395 names.clear();
396 Theme::get_default()->get_stylebox_list(fromtype, &names);
397 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
398 theme->clear_stylebox(E->get(), fromtype);
399 }
400 }
401 {
402 names.clear();
403 Theme::get_default()->get_font_list(fromtype, &names);
404 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
405 theme->clear_font(E->get(), fromtype);
406 }
407 }
408 {
409 names.clear();
410 Theme::get_default()->get_color_list(fromtype, &names);
411 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
412 theme->clear_color(E->get(), fromtype);
413 }
414 }
415 {
416 names.clear();
417 Theme::get_default()->get_constant_list(fromtype, &names);
418 for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
419 theme->clear_constant(E->get(), fromtype);
420 }
421 }
422
423 } break;
424 }
425 }
426
_theme_menu_cbk(int p_option)427 void ThemeEditor::_theme_menu_cbk(int p_option) {
428
429 if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY) {
430
431 Ref<Theme> base_theme;
432
433 if (p_option == POPUP_CREATE_EMPTY) {
434 base_theme = Theme::get_default();
435 } else {
436 base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme();
437 }
438
439 {
440
441 List<StringName> types;
442 base_theme->get_type_list(&types);
443
444 for (List<StringName>::Element *T = types.front(); T; T = T->next()) {
445 StringName type = T->get();
446
447 List<StringName> icons;
448 base_theme->get_icon_list(type, &icons);
449
450 for (List<StringName>::Element *E = icons.front(); E; E = E->next()) {
451 theme->set_icon(E->get(), type, Ref<Texture>());
452 }
453
454 List<StringName> shaders;
455 base_theme->get_shader_list(type, &shaders);
456
457 for (List<StringName>::Element *E = shaders.front(); E; E = E->next()) {
458 theme->set_shader(E->get(), type, Ref<Shader>());
459 }
460
461 List<StringName> styleboxs;
462 base_theme->get_stylebox_list(type, &styleboxs);
463
464 for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) {
465 theme->set_stylebox(E->get(), type, Ref<StyleBox>());
466 }
467
468 List<StringName> fonts;
469 base_theme->get_font_list(type, &fonts);
470
471 for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) {
472 theme->set_font(E->get(), type, Ref<Font>());
473 }
474
475 List<StringName> colors;
476 base_theme->get_color_list(type, &colors);
477
478 for (List<StringName>::Element *E = colors.front(); E; E = E->next()) {
479 theme->set_color(E->get(), type, Color());
480 }
481
482 List<StringName> constants;
483 base_theme->get_constant_list(type, &constants);
484
485 for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
486 theme->set_constant(E->get(), type, base_theme->get_constant(type, E->get()));
487 }
488 }
489 }
490 return;
491 }
492
493 Ref<Theme> base_theme;
494
495 type_select->show();
496 type_select_label->show();
497 name_select_label->show();
498 name_edit->show();
499 name_menu->show();
500
501 if (p_option == POPUP_ADD) { //add
502
503 add_del_dialog->set_title(TTR("Add Item"));
504 add_del_dialog->get_ok()->set_text(TTR("Add"));
505 add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE);
506
507 base_theme = Theme::get_default();
508
509 } else if (p_option == POPUP_CLASS_ADD) { //add
510
511 add_del_dialog->set_title(TTR("Add All Items"));
512 add_del_dialog->get_ok()->set_text(TTR("Add All"));
513 add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE);
514
515 base_theme = Theme::get_default();
516
517 type_select->hide();
518 name_select_label->hide();
519 type_select_label->hide();
520 name_edit->hide();
521 name_menu->hide();
522
523 } else if (p_option == POPUP_REMOVE) {
524
525 add_del_dialog->set_title(TTR("Remove Item"));
526 add_del_dialog->get_ok()->set_text(TTR("Remove"));
527 add_del_dialog->popup_centered(Size2(490, 85) * EDSCALE);
528
529 base_theme = theme;
530
531 } else if (p_option == POPUP_CLASS_REMOVE) {
532
533 add_del_dialog->set_title("Remove All Items");
534 add_del_dialog->get_ok()->set_text("Remove All");
535 add_del_dialog->popup_centered(Size2(240, 85) * EDSCALE);
536
537 base_theme = Theme::get_default();
538
539 type_select->hide();
540 name_select_label->hide();
541 type_select_label->hide();
542 name_edit->hide();
543 name_menu->hide();
544 }
545 popup_mode = p_option;
546
547 ERR_FAIL_COND(theme.is_null());
548
549 List<StringName> types;
550 base_theme->get_type_list(&types);
551
552 type_menu->get_popup()->clear();
553
554 if (p_option == 0 || p_option == 1) { //add
555
556 List<StringName> new_types;
557 theme->get_type_list(&new_types);
558
559 //uh kind of sucks
560 for (List<StringName>::Element *F = new_types.front(); F; F = F->next()) {
561
562 bool found = false;
563 for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
564
565 if (E->get() == F->get()) {
566 found = true;
567 break;
568 }
569 }
570
571 if (!found)
572 types.push_back(F->get());
573 }
574 }
575
576 //types.sort();
577 types.sort_custom<StringName::AlphCompare>();
578 for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
579
580 type_menu->get_popup()->add_item(E->get());
581 }
582 }
583
_notification(int p_what)584 void ThemeEditor::_notification(int p_what) {
585
586 if (p_what == NOTIFICATION_PROCESS) {
587
588 time_left -= get_process_delta_time();
589 if (time_left < 0) {
590 time_left = 1.5;
591 _refresh_interval();
592 }
593 }
594 }
595
_bind_methods()596 void ThemeEditor::_bind_methods() {
597
598 ObjectTypeDB::bind_method("_type_menu_cbk", &ThemeEditor::_type_menu_cbk);
599 ObjectTypeDB::bind_method("_name_menu_about_to_show", &ThemeEditor::_name_menu_about_to_show);
600 ObjectTypeDB::bind_method("_name_menu_cbk", &ThemeEditor::_name_menu_cbk);
601 ObjectTypeDB::bind_method("_theme_menu_cbk", &ThemeEditor::_theme_menu_cbk);
602 ObjectTypeDB::bind_method("_dialog_cbk", &ThemeEditor::_dialog_cbk);
603 ObjectTypeDB::bind_method("_save_template_cbk", &ThemeEditor::_save_template_cbk);
604 }
605
ThemeEditor()606 ThemeEditor::ThemeEditor() {
607
608 time_left = 0;
609
610 scroll = memnew(ScrollContainer);
611 add_child(scroll);
612 scroll->set_area_as_parent_rect(3);
613 scroll->set_margin(MARGIN_TOP, 30 * EDSCALE);
614 //scroll->set_enable_h_scroll(true);
615 scroll->set_enable_v_scroll(true);
616 scroll->set_enable_h_scroll(false);
617
618 Panel *panel = memnew(Panel);
619 scroll->add_child(panel);
620 panel->set_custom_minimum_size(Size2(500, 800) * EDSCALE);
621 panel->set_theme(Theme::get_default());
622 panel->set_h_size_flags(SIZE_EXPAND_FILL);
623
624 main_vb = memnew(VBoxContainer);
625 panel->add_child(main_vb);
626 main_vb->set_area_as_parent_rect(4 * EDSCALE);
627
628 HBoxContainer *hb_menu = memnew(HBoxContainer);
629 main_vb->add_child(hb_menu);
630
631 theme_menu = memnew(MenuButton);
632 theme_menu->set_text("Theme");
633 theme_menu->get_popup()->add_item(TTR("Add Item"), POPUP_ADD);
634 theme_menu->get_popup()->add_item(TTR("Add Class Items"), POPUP_CLASS_ADD);
635 theme_menu->get_popup()->add_item(TTR("Remove Item"), POPUP_REMOVE);
636 theme_menu->get_popup()->add_item(TTR("Remove Class Items"), POPUP_CLASS_REMOVE);
637 theme_menu->get_popup()->add_separator();
638 theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY);
639 theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
640
641 add_child(theme_menu);
642 theme_menu->set_pos(Vector2(3, 3) * EDSCALE);
643 theme_menu->get_popup()->connect("item_pressed", this, "_theme_menu_cbk");
644
645 HBoxContainer *main_hb = memnew(HBoxContainer);
646 main_vb->add_child(main_hb);
647
648 VBoxContainer *first_vb = memnew(VBoxContainer);
649 first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
650 main_hb->add_child(first_vb);
651
652 // main_panel->add_child(panel);
653 // panel->set_area_as_parent_rect();
654 // panel->set_margin( MARGIN_TOP,20 );
655
656 first_vb->add_child(memnew(Label("Label")));
657
658 first_vb->add_child(memnew(Button("Button")));
659 ToolButton *tb = memnew(ToolButton);
660 tb->set_text("ToolButton");
661 first_vb->add_child(tb);
662 CheckButton *cb = memnew(CheckButton);
663 cb->set_text("CheckButton");
664 first_vb->add_child(cb);
665 CheckBox *cbx = memnew(CheckBox);
666 cbx->set_text("CheckBox");
667 first_vb->add_child(cbx);
668
669 ButtonGroup *bg = memnew(ButtonGroup);
670 bg->set_v_size_flags(SIZE_EXPAND_FILL);
671 VBoxContainer *gbvb = memnew(VBoxContainer);
672 gbvb->set_v_size_flags(SIZE_EXPAND_FILL);
673 CheckBox *rbx1 = memnew(CheckBox);
674 rbx1->set_text(TTR("CheckBox Radio1"));
675 rbx1->set_pressed(true);
676 gbvb->add_child(rbx1);
677 CheckBox *rbx2 = memnew(CheckBox);
678 rbx2->set_text(TTR("CheckBox Radio2"));
679 gbvb->add_child(rbx2);
680 bg->add_child(gbvb);
681 first_vb->add_child(bg);
682
683 MenuButton *test_menu_button = memnew(MenuButton);
684 test_menu_button->set_text("MenuButton");
685 test_menu_button->get_popup()->add_item(TTR("Item"));
686 test_menu_button->get_popup()->add_separator();
687 test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
688 test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
689 test_menu_button->get_popup()->set_item_checked(2, true);
690 first_vb->add_child(test_menu_button);
691
692 OptionButton *test_option_button = memnew(OptionButton);
693 test_option_button->add_item("OptionButton");
694 test_option_button->add_separator();
695 test_option_button->add_item(TTR("Has"));
696 test_option_button->add_item(TTR("Many"));
697 test_option_button->add_item(TTR("Options"));
698 first_vb->add_child(test_option_button);
699
700 ColorPickerButton *cpb = memnew(ColorPickerButton);
701 first_vb->add_child(cpb);
702
703 first_vb->add_child(memnew(HSeparator));
704 first_vb->add_child(memnew(HSlider));
705 first_vb->add_child(memnew(HScrollBar));
706 first_vb->add_child(memnew(SpinBox));
707 ProgressBar *pb = memnew(ProgressBar);
708 pb->set_val(50);
709 first_vb->add_child(pb);
710 Panel *pn = memnew(Panel);
711 pn->set_custom_minimum_size(Size2(40, 40) * EDSCALE);
712 first_vb->add_child(pn);
713 first_vb->add_constant_override("separation", 10 * EDSCALE);
714
715 VBoxContainer *second_vb = memnew(VBoxContainer);
716 second_vb->set_h_size_flags(SIZE_EXPAND_FILL);
717 main_hb->add_child(second_vb);
718 second_vb->add_constant_override("separation", 10 * EDSCALE);
719 LineEdit *le = memnew(LineEdit);
720 le->set_text("LineEdit");
721 second_vb->add_child(le);
722 TextEdit *te = memnew(TextEdit);
723 te->set_text("TextEdit");
724 //te->set_v_size_flags(SIZE_EXPAND_FILL);
725 te->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
726 second_vb->add_child(te);
727
728 Tree *test_tree = memnew(Tree);
729 second_vb->add_child(test_tree);
730 test_tree->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
731
732 TreeItem *item = test_tree->create_item();
733 item->set_editable(0, true);
734 item->set_text(0, "Tree");
735 item = test_tree->create_item(test_tree->get_root());
736 item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
737 item->set_editable(0, true);
738 item->set_text(0, "check");
739 item = test_tree->create_item(test_tree->get_root());
740 item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
741 item->set_editable(0, true);
742 item->set_range_config(0, 0, 20, 0.1);
743 item->set_range(0, 2);
744 item = test_tree->create_item(test_tree->get_root());
745 item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
746 item->set_editable(0, true);
747 item->set_text(0, TTR("Have,Many,Several,Options!"));
748 item->set_range(0, 2);
749
750 VBoxContainer *third_vb = memnew(VBoxContainer);
751 third_vb->set_h_size_flags(SIZE_EXPAND_FILL);
752 third_vb->add_constant_override("separation", 10);
753
754 main_hb->add_child(third_vb);
755
756 HBoxContainer *vhb = memnew(HBoxContainer);
757 vhb->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
758 vhb->add_child(memnew(VSeparator));
759 vhb->add_child(memnew(VSlider));
760 vhb->add_child(memnew(VScrollBar));
761 third_vb->add_child(vhb);
762
763 TabContainer *tc = memnew(TabContainer);
764 third_vb->add_child(tc);
765 tc->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
766 Control *tcc = memnew(Control);
767 tcc->set_name(TTR("Tab 1"));
768 tc->add_child(tcc);
769 tcc = memnew(Control);
770 tcc->set_name(TTR("Tab 2"));
771 tc->add_child(tcc);
772 tcc = memnew(Control);
773 tcc->set_name(TTR("Tab 3"));
774 tc->add_child(tcc);
775
776 main_hb->add_constant_override("separation", 20 * EDSCALE);
777
778 /*
779 test_h_scroll = memnew( HScrollBar );
780 test_h_scroll->set_pos( Point2( 25, 225 ) );
781 test_h_scroll->set_size( Point2( 150, 5 ) );
782 panel->add_child(test_h_scroll);
783
784 line_edit = memnew( LineEdit );
785 line_edit->set_pos( Point2( 25, 275 ) );
786 line_edit->set_size( Point2( 150, 5 ) );
787 line_edit->set_text("Line Edit");
788 panel->add_child(line_edit);
789
790 test_v_scroll = memnew( VScrollBar );
791 test_v_scroll->set_pos( Point2( 200, 25 ) );
792 test_v_scroll->set_size( Point2( 5, 150 ) );
793 panel->add_child(test_v_scroll);
794
795 test_tree = memnew(Tree);
796 test_tree->set_pos( Point2( 300, 25 ) );
797 test_tree->set_size( Point2( 200, 200 ) );
798 panel->add_child(test_tree);
799
800
801 TreeItem *item = test_tree->create_item();
802 item->set_editable(0,true);
803 item->set_text(0,"root");
804 item = test_tree->create_item( test_tree->get_root() );
805 item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
806 item->set_editable(0,true);
807 item->set_text(0,"check");
808 item = test_tree->create_item( test_tree->get_root() );
809 item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
810 item->set_editable(0,true);
811 item->set_range_config(0,0,20,0.1);
812 item->set_range(0,2);
813 item = test_tree->create_item( test_tree->get_root() );
814 item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
815 item->set_editable(0,true);
816 item->set_text(0,"Have,Many,Several,Options!"));
817 item->set_range(0,2);
818
819 Button *fd_button= memnew( Button );
820 fd_button->set_pos(Point2(300,275));
821 fd_button->set_text("Open File Dialog");
822 panel->add_child(fd_button);
823
824 test_file_dialog = memnew( EditorFileDialog );
825 panel->add_child(test_file_dialog);
826
827 fd_button->connect("pressed", this,"_open_file_dialog");
828 */
829
830 add_del_dialog = memnew(ConfirmationDialog);
831 add_del_dialog->hide();
832 add_child(add_del_dialog);
833
834 Label *l = memnew(Label);
835 l->set_pos(Point2(5, 5) * EDSCALE);
836 l->set_text(TTR("Type:"));
837 add_del_dialog->add_child(l);
838 dtype_select_label = l;
839
840 type_edit = memnew(LineEdit);
841 type_edit->set_pos(Point2(5, 25) * EDSCALE);
842 type_edit->set_size(Point2(150, 5) * EDSCALE);
843 add_del_dialog->add_child(type_edit);
844 type_menu = memnew(MenuButton);
845 type_menu->set_pos(Point2(160, 25) * EDSCALE);
846 type_menu->set_size(Point2(30, 5) * EDSCALE);
847 type_menu->set_text("..");
848 add_del_dialog->add_child(type_menu);
849
850 type_menu->get_popup()->connect("item_pressed", this, "_type_menu_cbk");
851
852 l = memnew(Label);
853 l->set_pos(Point2(200, 5) * EDSCALE);
854 l->set_text(TTR("Name:"));
855 add_del_dialog->add_child(l);
856 name_select_label = l;
857
858 name_edit = memnew(LineEdit);
859 name_edit->set_pos(Point2(200, 25) * EDSCALE);
860 name_edit->set_size(Point2(150, 5) * EDSCALE);
861 add_del_dialog->add_child(name_edit);
862 name_menu = memnew(MenuButton);
863 name_menu->set_pos(Point2(360, 25) * EDSCALE);
864 name_menu->set_size(Point2(30, 5) * EDSCALE);
865 name_menu->set_text("..");
866
867 add_del_dialog->add_child(name_menu);
868
869 name_menu->get_popup()->connect("about_to_show", this, "_name_menu_about_to_show");
870 name_menu->get_popup()->connect("item_pressed", this, "_name_menu_cbk");
871
872 type_select_label = memnew(Label);
873 type_select_label->set_pos(Point2(400, 5) * EDSCALE);
874 type_select_label->set_text(TTR("Data Type:"));
875 add_del_dialog->add_child(type_select_label);
876
877 type_select = memnew(OptionButton);
878 type_select->add_item(TTR("Icon"));
879 type_select->add_item(TTR("Style"));
880 type_select->add_item(TTR("Font"));
881 type_select->add_item(TTR("Color"));
882 type_select->add_item(TTR("Constant"));
883 type_select->set_pos(Point2(400, 25) * EDSCALE);
884 type_select->set_size(Point2(80, 5) * EDSCALE);
885
886 add_del_dialog->add_child(type_select);
887
888 add_del_dialog->get_ok()->connect("pressed", this, "_dialog_cbk");
889
890 file_dialog = memnew(EditorFileDialog);
891 file_dialog->add_filter("*.theme ; Theme File");
892 add_child(file_dialog);
893 file_dialog->connect("file_selected", this, "_save_template_cbk");
894
895 //MenuButton *name_menu;
896 //LineEdit *name_edit;
897 }
898
edit(Object * p_node)899 void ThemeEditorPlugin::edit(Object *p_node) {
900
901 if (p_node && p_node->cast_to<Theme>()) {
902 theme_editor->show();
903 theme_editor->edit(p_node->cast_to<Theme>());
904 } else {
905 theme_editor->edit(Ref<Theme>());
906 theme_editor->hide();
907 }
908 }
909
handles(Object * p_node) const910 bool ThemeEditorPlugin::handles(Object *p_node) const {
911
912 return p_node->is_type("Theme");
913 }
914
make_visible(bool p_visible)915 void ThemeEditorPlugin::make_visible(bool p_visible) {
916
917 if (p_visible) {
918 theme_editor->set_process(true);
919 button->show();
920 editor->make_bottom_panel_item_visible(theme_editor);
921
922 } else {
923 theme_editor->set_process(false);
924 if (theme_editor->is_visible())
925 editor->hide_bottom_panel();
926 button->hide();
927 }
928 }
929
ThemeEditorPlugin(EditorNode * p_node)930 ThemeEditorPlugin::ThemeEditorPlugin(EditorNode *p_node) {
931
932 editor = p_node;
933 theme_editor = memnew(ThemeEditor);
934 theme_editor->set_custom_minimum_size(Size2(0, 200));
935
936 // p_node->get_viewport()->add_child(theme_editor);
937 button = editor->add_bottom_panel_item("Theme", theme_editor);
938 button->hide();
939 }
940