Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/docks/editor_dock.cpp
20888 views
1
/**************************************************************************/
2
/* editor_dock.cpp */
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
#include "editor_dock.h"
32
33
#include "core/input/shortcut.h"
34
#include "core/io/config_file.h"
35
#include "editor/docks/dock_tab_container.h"
36
#include "editor/docks/editor_dock_manager.h"
37
38
void EditorDock::_set_default_slot_bind(DockSlot p_slot) {
39
ERR_FAIL_COND(p_slot < DOCK_SLOT_NONE || p_slot >= DOCK_SLOT_MAX);
40
default_slot = p_slot;
41
}
42
43
void EditorDock::_emit_changed() {
44
emit_signal(SNAME("_tab_style_changed"));
45
}
46
47
void EditorDock::_notification(int p_what) {
48
switch (p_what) {
49
case NOTIFICATION_READY: {
50
set_accessibility_region(true);
51
set_accessibility_name(get_display_title());
52
} break;
53
54
case NOTIFICATION_PARENTED: {
55
parent_dock_container = Object::cast_to<DockTabContainer>(get_parent());
56
} break;
57
58
case NOTIFICATION_UNPARENTED: {
59
parent_dock_container = nullptr;
60
} break;
61
}
62
}
63
64
void EditorDock::_bind_methods() {
65
ClassDB::bind_method(D_METHOD("open"), &EditorDock::open);
66
ClassDB::bind_method(D_METHOD("make_visible"), &EditorDock::make_visible);
67
ClassDB::bind_method(D_METHOD("close"), &EditorDock::close);
68
69
ClassDB::bind_method(D_METHOD("set_title", "title"), &EditorDock::set_title);
70
ClassDB::bind_method(D_METHOD("get_title"), &EditorDock::get_title);
71
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
72
73
ClassDB::bind_method(D_METHOD("set_layout_key", "layout_key"), &EditorDock::set_layout_key);
74
ClassDB::bind_method(D_METHOD("get_layout_key"), &EditorDock::get_layout_key);
75
ADD_PROPERTY(PropertyInfo(Variant::STRING, "layout_key"), "set_layout_key", "get_layout_key");
76
77
ClassDB::bind_method(D_METHOD("set_global", "global"), &EditorDock::set_global);
78
ClassDB::bind_method(D_METHOD("is_global"), &EditorDock::is_global);
79
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "global"), "set_global", "is_global");
80
81
ClassDB::bind_method(D_METHOD("set_transient", "transient"), &EditorDock::set_transient);
82
ClassDB::bind_method(D_METHOD("is_transient"), &EditorDock::is_transient);
83
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient");
84
85
ClassDB::bind_method(D_METHOD("set_closable", "closable"), &EditorDock::set_closable);
86
ClassDB::bind_method(D_METHOD("is_closable"), &EditorDock::is_closable);
87
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closable"), "set_closable", "is_closable");
88
89
ClassDB::bind_method(D_METHOD("set_icon_name", "icon_name"), &EditorDock::set_icon_name);
90
ClassDB::bind_method(D_METHOD("get_icon_name"), &EditorDock::get_icon_name);
91
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "icon_name"), "set_icon_name", "get_icon_name");
92
93
ClassDB::bind_method(D_METHOD("set_dock_icon", "icon"), &EditorDock::set_dock_icon);
94
ClassDB::bind_method(D_METHOD("get_dock_icon"), &EditorDock::get_dock_icon);
95
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "dock_icon", PROPERTY_HINT_RESOURCE_TYPE, Texture2D::get_class_static()), "set_dock_icon", "get_dock_icon");
96
97
ClassDB::bind_method(D_METHOD("set_force_show_icon", "force"), &EditorDock::set_force_show_icon);
98
ClassDB::bind_method(D_METHOD("get_force_show_icon"), &EditorDock::get_force_show_icon);
99
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_show_icon"), "set_force_show_icon", "get_force_show_icon");
100
101
ClassDB::bind_method(D_METHOD("set_title_color", "color"), &EditorDock::set_title_color);
102
ClassDB::bind_method(D_METHOD("get_title_color"), &EditorDock::get_title_color);
103
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "title_color"), "set_title_color", "get_title_color");
104
105
ClassDB::bind_method(D_METHOD("set_dock_shortcut", "shortcut"), &EditorDock::set_dock_shortcut);
106
ClassDB::bind_method(D_METHOD("get_dock_shortcut"), &EditorDock::get_dock_shortcut);
107
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "dock_shortcut", PROPERTY_HINT_RESOURCE_TYPE, Shortcut::get_class_static()), "set_dock_shortcut", "get_dock_shortcut");
108
109
ClassDB::bind_method(D_METHOD("set_default_slot", "slot"), &EditorDock::_set_default_slot_bind);
110
ClassDB::bind_method(D_METHOD("get_default_slot"), &EditorDock::_get_default_slot_bind);
111
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_slot", PROPERTY_HINT_ENUM, "None:-1,Left Side Upper-Left,Left Side Bottom-Left,Left Side Upper-Right,Left Side Bottom-Right,Right Side Upper-Left,Right Side Bottom-Left,Right Side Upper-Right,Right Side Bottom-Right,Bottom"), "set_default_slot", "get_default_slot");
112
113
ClassDB::bind_method(D_METHOD("set_available_layouts", "layouts"), &EditorDock::set_available_layouts);
114
ClassDB::bind_method(D_METHOD("get_available_layouts"), &EditorDock::get_available_layouts);
115
ADD_PROPERTY(PropertyInfo(Variant::INT, "available_layouts", PROPERTY_HINT_FLAGS, "Vertical:1,Horizontal:2,Floating:4"), "set_available_layouts", "get_available_layouts");
116
117
ADD_SIGNAL(MethodInfo("opened"));
118
ADD_SIGNAL(MethodInfo("closed"));
119
ADD_SIGNAL(MethodInfo("_tab_style_changed"));
120
121
BIND_BITFIELD_FLAG(DOCK_LAYOUT_VERTICAL);
122
BIND_BITFIELD_FLAG(DOCK_LAYOUT_HORIZONTAL);
123
BIND_BITFIELD_FLAG(DOCK_LAYOUT_FLOATING);
124
BIND_BITFIELD_FLAG(DOCK_LAYOUT_ALL);
125
126
BIND_ENUM_CONSTANT(DOCK_SLOT_NONE);
127
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UL);
128
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_BL);
129
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UR);
130
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_BR);
131
BIND_ENUM_CONSTANT(DOCK_SLOT_RIGHT_UL);
132
BIND_ENUM_CONSTANT(DOCK_SLOT_RIGHT_BL);
133
BIND_ENUM_CONSTANT(DOCK_SLOT_RIGHT_UR);
134
BIND_ENUM_CONSTANT(DOCK_SLOT_RIGHT_BR);
135
BIND_ENUM_CONSTANT(DOCK_SLOT_BOTTOM);
136
BIND_ENUM_CONSTANT(DOCK_SLOT_MAX);
137
138
GDVIRTUAL_BIND(_update_layout, "layout");
139
GDVIRTUAL_BIND(_save_layout_to_config, "config", "section");
140
GDVIRTUAL_BIND(_load_layout_from_config, "config", "section");
141
}
142
143
void EditorDock::open() {
144
if (!is_open) {
145
EditorDockManager::get_singleton()->open_dock(this, false);
146
}
147
}
148
149
void EditorDock::make_visible() {
150
EditorDockManager::get_singleton()->open_dock(this, true);
151
}
152
153
void EditorDock::make_floating() {
154
EditorDockManager::get_singleton()->make_dock_floating(this);
155
}
156
157
void EditorDock::close() {
158
if (is_open) {
159
EditorDockManager::get_singleton()->close_dock(this);
160
}
161
}
162
163
void EditorDock::set_title(const String &p_title) {
164
if (title == p_title) {
165
return;
166
}
167
title = p_title;
168
set_accessibility_name(get_display_title());
169
_emit_changed();
170
}
171
172
void EditorDock::set_global(bool p_global) {
173
if (global == p_global) {
174
return;
175
}
176
global = p_global;
177
if (is_inside_tree()) {
178
EditorDockManager::get_singleton()->update_docks_menu();
179
}
180
}
181
182
void EditorDock::set_icon_name(const StringName &p_name) {
183
if (icon_name == p_name) {
184
return;
185
}
186
icon_name = p_name;
187
_emit_changed();
188
}
189
190
void EditorDock::set_dock_icon(const Ref<Texture2D> &p_icon) {
191
if (dock_icon == p_icon) {
192
return;
193
}
194
dock_icon = p_icon;
195
_emit_changed();
196
}
197
198
void EditorDock::set_force_show_icon(bool p_force) {
199
if (force_show_icon == p_force) {
200
return;
201
}
202
force_show_icon = p_force;
203
_emit_changed();
204
}
205
206
void EditorDock::set_title_color(const Color &p_color) {
207
if (title_color == p_color) {
208
return;
209
}
210
title_color = p_color;
211
_emit_changed();
212
}
213
214
void EditorDock::set_dock_shortcut(const Ref<Shortcut> &p_shortcut) {
215
if (shortcut == p_shortcut) {
216
return;
217
}
218
219
const Callable changed_callback = callable_mp(this, &EditorDock::_emit_changed);
220
if (shortcut.is_valid()) {
221
shortcut->disconnect_changed(changed_callback);
222
}
223
shortcut = p_shortcut;
224
if (shortcut.is_valid()) {
225
shortcut->connect_changed(changed_callback);
226
}
227
_emit_changed();
228
}
229
230
Ref<Shortcut> EditorDock::get_dock_shortcut() const {
231
return shortcut;
232
}
233
234
void EditorDock::set_default_slot(DockSlot p_slot) {
235
ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
236
default_slot = p_slot;
237
}
238
239
String EditorDock::get_display_title() const {
240
if (!title.is_empty()) {
241
return title;
242
}
243
244
const String sname = get_name();
245
if (sname.contains_char('@')) {
246
// Auto-generated name, try to use something better.
247
const Node *child = get_child_count() > 0 ? get_child(0) : nullptr;
248
if (child) {
249
// In user plugins, the child will usually be dock's content and have a proper name.
250
return child->get_name();
251
}
252
}
253
return sname;
254
}
255
256
String EditorDock::get_effective_layout_key() const {
257
return layout_key.is_empty() ? get_display_title() : layout_key;
258
}
259
260
void EditorDock::set_tab_index(int p_index, bool p_set_current) {
261
parent_dock_container->move_dock_index(this, p_index, p_set_current);
262
previous_tab_index = parent_dock_container->get_tab_idx_from_control(this);
263
}
264
265
void EditorDock::update_tab_style() {
266
if (!enabled || !is_open) {
267
return; // Disabled by feature profile or manually closed by user.
268
}
269
if (dock_window) {
270
return; // Floating.
271
}
272
273
ERR_FAIL_NULL(parent_dock_container);
274
275
int index = parent_dock_container->get_tab_idx_from_control(this);
276
ERR_FAIL_COND(index == -1);
277
278
parent_dock_container->get_tab_bar()->set_font_color_override_all(index, title_color);
279
280
const Ref<Texture2D> icon = get_effective_icon(callable_mp((Control *)this, &Control::get_editor_theme_icon));
281
bool assign_icon = force_show_icon;
282
String tooltip;
283
switch (parent_dock_container->get_tab_style()) {
284
case DockTabContainer::TabStyle::TEXT_ONLY: {
285
parent_dock_container->set_tab_title(index, get_display_title());
286
} break;
287
case DockTabContainer::TabStyle::ICON_ONLY: {
288
parent_dock_container->set_tab_title(index, icon.is_valid() ? String() : get_display_title());
289
tooltip = TTR(get_display_title());
290
assign_icon = true;
291
} break;
292
case DockTabContainer::TabStyle::TEXT_AND_ICON: {
293
parent_dock_container->set_tab_title(index, get_display_title());
294
parent_dock_container->set_tab_tooltip(index, String());
295
assign_icon = true;
296
} break;
297
}
298
299
if (shortcut.is_valid() && shortcut->has_valid_event()) {
300
tooltip += (tooltip.is_empty() ? "" : "\n") + TTR(shortcut->get_name()) + " (" + shortcut->get_as_text() + ")";
301
}
302
parent_dock_container->set_tab_tooltip(index, tooltip);
303
304
if (assign_icon) {
305
parent_dock_container->set_tab_icon(index, icon);
306
} else {
307
parent_dock_container->set_tab_icon(index, Ref<Texture2D>());
308
}
309
}
310
311
Ref<Texture2D> EditorDock::get_effective_icon(const Callable &p_icon_fetch) {
312
Ref<Texture2D> icon = dock_icon;
313
if (icon.is_null() && !icon_name.is_empty()) {
314
icon = p_icon_fetch.call(icon_name);
315
}
316
return icon;
317
}
318
319