summaryrefslogtreecommitdiffstats
path: root/editor/editor_dock_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_dock_manager.cpp')
-rw-r--r--editor/editor_dock_manager.cpp150
1 files changed, 115 insertions, 35 deletions
diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp
index b6250671ee..5d98fefa76 100644
--- a/editor/editor_dock_manager.cpp
+++ b/editor/editor_dock_manager.cpp
@@ -33,12 +33,10 @@
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
-#include "scene/gui/popup.h"
#include "scene/gui/split_container.h"
#include "scene/gui/tab_container.h"
#include "scene/main/window.h"
-#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
@@ -47,6 +45,12 @@
#include "editor/themes/editor_scale.h"
#include "editor/window_wrapper.h"
+enum class TabStyle {
+ TEXT_ONLY,
+ ICON_ONLY,
+ TEXT_AND_ICON,
+};
+
EditorDockManager *EditorDockManager::singleton = nullptr;
void DockSplitContainer::_update_visibility() {
@@ -55,12 +59,13 @@ void DockSplitContainer::_update_visibility() {
}
is_updating = true;
bool any_visible = false;
- for (int i = 0; i < 2; i++) {
- Control *split = get_containable_child(i);
- if (split && split->is_visible()) {
- any_visible = true;
- break;
+ for (int i = 0; i < get_child_count(false); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i, false));
+ if (!c || !c->is_visible() || c->is_set_as_top_level()) {
+ continue;
}
+ any_visible = c;
+ break;
}
set_visible(any_visible);
is_updating = false;
@@ -70,10 +75,13 @@ void DockSplitContainer::add_child_notify(Node *p_child) {
SplitContainer::add_child_notify(p_child);
Control *child_control = nullptr;
- for (int i = 0; i < 2; i++) {
- Control *split = get_containable_child(i);
- if (p_child == split) {
- child_control = split;
+ for (int i = 0; i < get_child_count(false); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i, false));
+ if (!c || c->is_set_as_top_level()) {
+ continue;
+ }
+ if (p_child == c) {
+ child_control = c;
break;
}
}
@@ -81,7 +89,7 @@ void DockSplitContainer::add_child_notify(Node *p_child) {
return;
}
- child_control->connect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
+ child_control->connect(SceneStringName(visibility_changed), callable_mp(this, &DockSplitContainer::_update_visibility));
_update_visibility();
}
@@ -89,10 +97,13 @@ void DockSplitContainer::remove_child_notify(Node *p_child) {
SplitContainer::remove_child_notify(p_child);
Control *child_control = nullptr;
- for (int i = 0; i < 2; i++) {
- Control *split = get_containable_child(i);
- if (p_child == split) {
- child_control = split;
+ for (int i = 0; i < get_child_count(false); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i, false));
+ if (!c || c->is_set_as_top_level()) {
+ continue;
+ }
+ if (p_child == c) {
+ child_control = c;
break;
}
}
@@ -100,7 +111,7 @@ void DockSplitContainer::remove_child_notify(Node *p_child) {
return;
}
- child_control->disconnect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
+ child_control->disconnect(SceneStringName(visibility_changed), callable_mp(this, &DockSplitContainer::_update_visibility));
_update_visibility();
}
@@ -147,7 +158,6 @@ void EditorDockManager::_update_layout() {
if (!dock_context_popup->is_inside_tree() || EditorNode::get_singleton()->is_exiting()) {
return;
}
- EditorNode::get_singleton()->edit_current();
dock_context_popup->docks_updated();
_update_docks_menu();
EditorNode::get_singleton()->save_editor_layout_delayed();
@@ -157,7 +167,7 @@ void EditorDockManager::_update_docks_menu() {
docks_menu->clear();
docks_menu->reset_size();
- const Ref<Texture2D> icon = docks_menu->get_editor_theme_icon(SNAME("Window"));
+ const Ref<Texture2D> default_icon = docks_menu->get_editor_theme_icon(SNAME("Window"));
const Color closed_icon_color_mod = Color(1, 1, 1, 0.5);
// Add docks.
@@ -170,7 +180,8 @@ void EditorDockManager::_update_docks_menu() {
} else {
docks_menu->add_item(dock.value.title, id);
}
- docks_menu->set_item_icon(id, icon);
+ const Ref<Texture2D> icon = dock.value.icon_name ? docks_menu->get_editor_theme_icon(dock.value.icon_name) : dock.value.icon;
+ docks_menu->set_item_icon(id, icon.is_valid() ? icon : default_icon);
if (!dock.value.open) {
docks_menu->set_item_icon_modulate(id, closed_icon_color_mod);
}
@@ -181,7 +192,15 @@ void EditorDockManager::_update_docks_menu() {
}
void EditorDockManager::_docks_menu_option(int p_id) {
- focus_dock(docks_menu_docks[p_id]);
+ Control *dock = docks_menu_docks[p_id];
+ ERR_FAIL_NULL(dock);
+ ERR_FAIL_COND_MSG(!all_docks.has(dock), vformat("Menu option for unknown dock '%s'.", dock->get_name()));
+ if (all_docks[dock].enabled && all_docks[dock].open) {
+ PopupMenu *parent_menu = Object::cast_to<PopupMenu>(docks_menu->get_parent());
+ ERR_FAIL_NULL(parent_menu);
+ parent_menu->hide();
+ }
+ focus_dock(dock);
}
void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) {
@@ -268,7 +287,7 @@ void EditorDockManager::_dock_move_to_bottom(Control *p_dock) {
// Force docks moved to the bottom to appear first in the list, and give them their associated shortcut to toggle their bottom panel.
Button *bottom_button = EditorNode::get_bottom_panel()->add_item(all_docks[p_dock].title, p_dock, all_docks[p_dock].shortcut, true);
- bottom_button->connect("gui_input", callable_mp(this, &EditorDockManager::_bottom_dock_button_gui_input).bind(bottom_button).bind(p_dock));
+ bottom_button->connect(SceneStringName(gui_input), callable_mp(this, &EditorDockManager::_bottom_dock_button_gui_input).bind(bottom_button).bind(p_dock));
EditorNode::get_bottom_panel()->make_item_visible(p_dock);
}
@@ -345,7 +364,9 @@ void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab
p_target->set_block_signals(false);
TabContainer *dock_tab_container = Object::cast_to<TabContainer>(p_target);
if (dock_tab_container) {
- dock_tab_container->set_tab_title(dock_tab_container->get_tab_idx_from_control(p_dock), all_docks[p_dock].title);
+ if (dock_tab_container->is_inside_tree()) {
+ _update_tab_style(p_dock);
+ }
if (p_tab_index >= 0) {
_move_dock_tab_index(p_dock, p_tab_index, p_set_current);
}
@@ -353,6 +374,42 @@ void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab
}
}
+void EditorDockManager::_update_tab_style(Control *p_dock) {
+ const DockInfo &dock_info = all_docks[p_dock];
+ if (!dock_info.enabled || !dock_info.open) {
+ return; // Disabled by feature profile or manually closed by user.
+ }
+ if (dock_info.dock_window || dock_info.at_bottom) {
+ return; // Floating or sent to bottom.
+ }
+
+ TabContainer *tab_container = get_dock_tab_container(p_dock);
+ ERR_FAIL_NULL(tab_container);
+ int index = tab_container->get_tab_idx_from_control(p_dock);
+ ERR_FAIL_COND(index == -1);
+
+ const TabStyle style = (TabStyle)EDITOR_GET("interface/editor/dock_tab_style").operator int();
+ switch (style) {
+ case TabStyle::TEXT_ONLY: {
+ tab_container->set_tab_title(index, dock_info.title);
+ tab_container->set_tab_icon(index, Ref<Texture2D>());
+ tab_container->set_tab_tooltip(index, String());
+ } break;
+ case TabStyle::ICON_ONLY: {
+ const Ref<Texture2D> icon = dock_info.icon_name ? tab_container->get_editor_theme_icon(dock_info.icon_name) : dock_info.icon;
+ tab_container->set_tab_title(index, icon.is_valid() ? String() : dock_info.title);
+ tab_container->set_tab_icon(index, icon);
+ tab_container->set_tab_tooltip(index, icon.is_valid() ? dock_info.title : String());
+ } break;
+ case TabStyle::TEXT_AND_ICON: {
+ const Ref<Texture2D> icon = dock_info.icon_name ? tab_container->get_editor_theme_icon(dock_info.icon_name) : dock_info.icon;
+ tab_container->set_tab_title(index, dock_info.title);
+ tab_container->set_tab_icon(index, icon);
+ tab_container->set_tab_tooltip(index, String());
+ } break;
+ }
+}
+
void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
// Save docks by dock slot.
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
@@ -666,14 +723,15 @@ void EditorDockManager::focus_dock(Control *p_dock) {
tab_container->set_current_tab(tab_index);
}
-void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlot p_slot, const Ref<Shortcut> &p_shortcut) {
+void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlot p_slot, const Ref<Shortcut> &p_shortcut, const StringName &p_icon_name) {
ERR_FAIL_NULL(p_dock);
ERR_FAIL_COND_MSG(all_docks.has(p_dock), vformat("Cannot add dock '%s', already added.", p_dock->get_name()));
DockInfo dock_info;
- dock_info.title = !p_title.is_empty() ? p_title : String(p_dock->get_name());
+ dock_info.title = p_title.is_empty() ? String(p_dock->get_name()) : p_title;
dock_info.dock_slot_index = p_slot;
dock_info.shortcut = p_shortcut;
+ dock_info.icon_name = p_icon_name;
all_docks[p_dock] = dock_info;
if (p_slot != DOCK_SLOT_NONE) {
@@ -696,6 +754,14 @@ void EditorDockManager::remove_dock(Control *p_dock) {
_update_layout();
}
+void EditorDockManager::set_dock_tab_icon(Control *p_dock, const Ref<Texture2D> &p_icon) {
+ ERR_FAIL_NULL(p_dock);
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot set tab icon for unknown dock '%s'.", p_dock->get_name()));
+
+ all_docks[p_dock].icon = p_icon;
+ _update_tab_style(p_dock);
+}
+
void EditorDockManager::set_docks_visible(bool p_show) {
if (docks_visible == p_show) {
return;
@@ -711,6 +777,19 @@ bool EditorDockManager::are_docks_visible() const {
return docks_visible;
}
+void EditorDockManager::update_tab_styles() {
+ for (const KeyValue<Control *, DockInfo> &dock : all_docks) {
+ _update_tab_style(dock.key);
+ }
+}
+
+void EditorDockManager::set_tab_icon_max_width(int p_max_width) {
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ TabContainer *tab_container = dock_slot[i];
+ tab_container->add_theme_constant_override(SNAME("icon_max_width"), p_max_width);
+ }
+}
+
void EditorDockManager::add_vsplit(DockSplitContainer *p_split) {
vsplits.push_back(p_split);
p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
@@ -737,7 +816,7 @@ void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p
p_tab_container->connect("active_tab_rearranged", callable_mp(this, &EditorDockManager::_update_layout).unbind(1));
p_tab_container->connect("child_order_changed", callable_mp(this, &EditorDockManager::_dock_container_update_visibility).bind(p_tab_container));
p_tab_container->set_use_hidden_tabs_for_min_size(true);
- p_tab_container->get_tab_bar()->connect("gui_input", callable_mp(this, &EditorDockManager::_dock_container_gui_input).bind(p_tab_container));
+ p_tab_container->get_tab_bar()->connect(SceneStringName(gui_input), callable_mp(this, &EditorDockManager::_dock_container_gui_input).bind(p_tab_container));
p_tab_container->hide();
}
@@ -758,8 +837,9 @@ EditorDockManager::EditorDockManager() {
EditorNode::get_singleton()->get_gui_base()->add_child(dock_context_popup);
docks_menu = memnew(PopupMenu);
+ docks_menu->set_hide_on_item_selection(false);
docks_menu->connect("id_pressed", callable_mp(this, &EditorDockManager::_docks_menu_option));
- EditorNode::get_singleton()->get_gui_base()->connect("theme_changed", callable_mp(this, &EditorDockManager::_update_docks_menu));
+ EditorNode::get_singleton()->get_gui_base()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorDockManager::_update_docks_menu));
}
void DockContextPopup::_notification(int p_what) {
@@ -1000,7 +1080,7 @@ DockContextPopup::DockContextPopup() {
tab_move_left_button = memnew(Button);
tab_move_left_button->set_flat(true);
tab_move_left_button->set_focus_mode(Control::FOCUS_NONE);
- tab_move_left_button->connect("pressed", callable_mp(this, &DockContextPopup::_tab_move_left));
+ tab_move_left_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_tab_move_left));
header_hb->add_child(tab_move_left_button);
Label *position_label = memnew(Label);
@@ -1012,16 +1092,16 @@ DockContextPopup::DockContextPopup() {
tab_move_right_button = memnew(Button);
tab_move_right_button->set_flat(true);
tab_move_right_button->set_focus_mode(Control::FOCUS_NONE);
- tab_move_right_button->connect("pressed", callable_mp(this, &DockContextPopup::_tab_move_right));
+ tab_move_right_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_tab_move_right));
header_hb->add_child(tab_move_right_button);
dock_select_popup_vb->add_child(header_hb);
dock_select = memnew(Control);
dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
- dock_select->connect("gui_input", callable_mp(this, &DockContextPopup::_dock_select_input));
- dock_select->connect("draw", callable_mp(this, &DockContextPopup::_dock_select_draw));
- dock_select->connect("mouse_exited", callable_mp(this, &DockContextPopup::_dock_select_mouse_exited));
+ dock_select->connect(SceneStringName(gui_input), callable_mp(this, &DockContextPopup::_dock_select_input));
+ dock_select->connect(SceneStringName(draw), callable_mp(this, &DockContextPopup::_dock_select_draw));
+ dock_select->connect(SceneStringName(mouse_exited), callable_mp(this, &DockContextPopup::_dock_select_mouse_exited));
dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
dock_select_popup_vb->add_child(dock_select);
@@ -1035,7 +1115,7 @@ DockContextPopup::DockContextPopup() {
}
make_float_button->set_focus_mode(Control::FOCUS_NONE);
make_float_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- make_float_button->connect("pressed", callable_mp(this, &DockContextPopup::_float_dock));
+ make_float_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_float_dock));
dock_select_popup_vb->add_child(make_float_button);
dock_to_bottom_button = memnew(Button);
@@ -1043,7 +1123,7 @@ DockContextPopup::DockContextPopup() {
dock_to_bottom_button->set_tooltip_text(TTR("Move this dock to the bottom panel."));
dock_to_bottom_button->set_focus_mode(Control::FOCUS_NONE);
dock_to_bottom_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- dock_to_bottom_button->connect("pressed", callable_mp(this, &DockContextPopup::_move_dock_to_bottom));
+ dock_to_bottom_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_move_dock_to_bottom));
dock_to_bottom_button->hide();
dock_select_popup_vb->add_child(dock_to_bottom_button);
@@ -1052,6 +1132,6 @@ DockContextPopup::DockContextPopup() {
close_button->set_tooltip_text(TTR("Close this dock."));
close_button->set_focus_mode(Control::FOCUS_NONE);
close_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- close_button->connect("pressed", callable_mp(this, &DockContextPopup::_close_dock));
+ close_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_close_dock));
dock_select_popup_vb->add_child(close_button);
}