diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml
index 40d6e9f26c9..41e1e255ae1 100644
--- a/doc/classes/TabBar.xml
+++ b/doc/classes/TabBar.xml
@@ -57,6 +57,13 @@
Returns the [Texture2D] for the tab at index [code]tab_idx[/code] or [code]null[/code] if the tab has no [Texture2D].
+
+
+
+
+ Returns the index of the tab at local coordinates [code]point[/code]. Returns [code]-1[/code] if the point is outside the control boundaries or if there's no tab at the queried position.
+
+
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index 39869831553..3f4ec81c953 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -43,20 +43,6 @@
Returns the number of tabs.
-
-
-
-
- Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled.
-
-
-
-
-
-
- Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is hidden.
-
-
@@ -71,6 +57,13 @@
Returns the index of the tab at local coordinates [code]point[/code]. Returns [code]-1[/code] if the point is outside the control boundaries or if there's no tab at the queried position.
+
+
+
+
+ Returns the index of the tab tied to the given [code]control[/code]. The control must be a child of the [TabContainer].
+
+
@@ -84,11 +77,25 @@
Returns the [TabContainer] rearrange group id.
+
+
+
+
+ Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled.
+
+
+
+
+
+
+ Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is hidden.
+
+
- If set on a [Popup] node instance, a popup menu icon appears in the top-right corner of the [TabContainer]. Clicking it will expand the [Popup] node.
+ If set on a [Popup] node instance, a popup menu icon appears in the top-right corner of the [TabContainer] (setting it to [code]null[/code] will make it go away). Clicking it will expand the [Popup] node.
@@ -120,7 +127,7 @@
- Sets a title for the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node.
+ Sets a custom title for the tab at index [code]tab_idx[/code] (tab titles default to the name of the indexed child node). Set it to blank to make it the child's name again.
@@ -135,13 +142,17 @@
If [code]true[/code], all tabs are drawn in front of the panel. If [code]false[/code], inactive tabs are drawn behind the panel.
+
+ If [code]true[/code], tabs overflowing this node's width will be hidden, displaying two navigation buttons instead. Otherwise, this node's minimum size is updated so that all tabs are visible.
+
The current tab index. When set, this index's [Control] node's [code]visible[/code] property is set to [code]true[/code] and all others are set to [code]false[/code].
If [code]true[/code], tabs can be rearranged with mouse drag.
-
+
+ Sets the position at which tabs will be placed. See [enum TabBar.AlignmentMode] for details.
If [code]true[/code], tabs are visible. If [code]false[/code], tabs' content and titles are hidden.
@@ -169,14 +180,6 @@
-
-
-
-
-
-
-
-
Font color of disabled tabs.
@@ -197,7 +200,8 @@
The size of the tab text outline.
- The space at the left and right edges of the tab bar.
+ The space at the left or right edges of the tab bar, accordingly with the current [member tab_alignment].
+ The margin is ignored with [code]ALIGNMENT_RIGHT[/code] if the tabs are clipped (see [member clip_tabs]) or a popup has been set (see [method set_popup]). The margin is always ignored with [code]ALIGNMENT_CENTER[/code].
The font used to draw tab names.
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 3eab4947612..92d53cc0057 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -611,7 +611,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
add_child(main_vbox);
tab_container = memnew(TabContainer);
- tab_container->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ tab_container->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
tab_container->set_use_hidden_tabs_for_min_size(true);
tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tab_container->connect("tab_selected", callable_mp(this, &InputEventConfigurationDialog::_tab_selected));
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 1c75b2dff1a..d5a4f5d1380 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -61,7 +61,7 @@ EditorDebuggerNode::EditorDebuggerNode() {
add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))->get_margin(SIDE_RIGHT));
tabs = memnew(TabContainer);
- tabs->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
tabs->set_tabs_visible(false);
tabs->connect("tab_changed", callable_mp(this, &EditorDebuggerNode::_debugger_changed));
add_child(tabs);
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 645d7608f39..0b9631c8162 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -135,15 +135,15 @@ void ScriptEditorDebugger::debug_continue() {
void ScriptEditorDebugger::update_tabs() {
if (error_count == 0 && warning_count == 0) {
errors_tab->set_name(TTR("Errors"));
- tabs->set_tab_icon(errors_tab->get_index(), Ref());
+ tabs->set_tab_icon(tabs->get_tab_idx_from_control(errors_tab), Ref());
} else {
errors_tab->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")");
if (error_count >= 1 && warning_count >= 1) {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
+ tabs->set_tab_icon(tabs->get_tab_idx_from_control(errors_tab), get_theme_icon(SNAME("ErrorWarning"), SNAME("EditorIcons")));
} else if (error_count >= 1) {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ tabs->set_tab_icon(tabs->get_tab_idx_from_control(errors_tab), get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
} else {
- tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
+ tabs->set_tab_icon(tabs->get_tab_idx_from_control(errors_tab), get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")));
}
}
}
@@ -1658,7 +1658,7 @@ bool ScriptEditorDebugger::has_capture(const StringName &p_name) {
ScriptEditorDebugger::ScriptEditorDebugger() {
tabs = memnew(TabContainer);
- tabs->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("DebuggerPanel"), SNAME("EditorStyles")));
tabs->connect("tab_changed", callable_mp(this, &ScriptEditorDebugger::_tab_changed));
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index cda5e6b5378..ddb9c93f049 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -313,6 +313,7 @@ void EditorNode::disambiguate_filenames(const Vector p_full_paths, Vecto
}
}
+// TODO: This REALLY should be done in a better way than replacing all tabs after almost EVERY action.
void EditorNode::_update_scene_tabs() {
bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button");
@@ -330,6 +331,9 @@ void EditorNode::_update_scene_tabs() {
disambiguate_filenames(full_path_names, disambiguated_scene_names);
+ // Workaround to ignore the tab_changed signal from the first added tab.
+ scene_tabs->disconnect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
+
scene_tabs->clear_tabs();
Ref script_icon = gui_base->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
@@ -388,6 +392,9 @@ void EditorNode::_update_scene_tabs() {
scene_tab_add->set_position(Point2(last_tab.position.x + last_tab.size.width + hsep, last_tab.position.y));
}
}
+
+ // Reconnect after everything is done.
+ scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
}
void EditorNode::_version_control_menu_option(int p_idx) {
@@ -4226,7 +4233,7 @@ void EditorNode::_dock_floating_close_request(Control *p_control) {
p_control->get_parent()->remove_child(p_control);
dock_slot[window_slot]->add_child(p_control);
- dock_slot[window_slot]->move_child(p_control, MIN((int)window->get_meta("dock_index"), dock_slot[window_slot]->get_child_count()));
+ dock_slot[window_slot]->move_child(p_control, MIN((int)window->get_meta("dock_index"), dock_slot[window_slot]->get_tab_count()));
dock_slot[window_slot]->set_current_tab(window->get_meta("dock_index"));
window->queue_delete();
@@ -4466,13 +4473,13 @@ void EditorNode::_dock_select_draw() {
if (i == dock_select_rect_over) {
dock_select->draw_rect(r, used_selected);
- } else if (dock_slot[i]->get_child_count() == 0) {
+ } else if (dock_slot[i]->get_tab_count() == 0) {
dock_select->draw_rect(r, unused);
} else {
dock_select->draw_rect(r, used);
}
- for (int j = 0; j < MIN(3, dock_slot[i]->get_child_count()); j++) {
+ for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) {
int xofs = (r.size.width / 3) * j;
Color c = used;
if (i == dock_popup_selected && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) {
@@ -4584,7 +4591,7 @@ void EditorNode::_update_dock_slots_visibility() {
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
int tabs_visible = 0;
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
- if (!dock_slot[i]->get_tab_hidden(j)) {
+ if (!dock_slot[i]->is_tab_hidden(j)) {
tabs_visible++;
}
}
@@ -5648,11 +5655,11 @@ void EditorNode::_feature_profile_changed() {
TabContainer *node_tabs = cast_to(NodeDock::get_singleton()->get_parent());
TabContainer *fs_tabs = cast_to(FileSystemDock::get_singleton()->get_parent());
if (profile.is_valid()) {
- node_tabs->set_tab_hidden(NodeDock::get_singleton()->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK));
+ node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK));
// The Import dock is useless without the FileSystem dock. Ensure the configuration is valid.
bool fs_dock_disabled = profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK);
- fs_tabs->set_tab_hidden(FileSystemDock::get_singleton()->get_index(), fs_dock_disabled);
- import_tabs->set_tab_hidden(ImportDock::get_singleton()->get_index(), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK));
+ fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), fs_dock_disabled);
+ import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK));
main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
@@ -5665,9 +5672,9 @@ void EditorNode::_feature_profile_changed() {
_editor_select(EDITOR_2D);
}
} else {
- import_tabs->set_tab_hidden(ImportDock::get_singleton()->get_index(), false);
- node_tabs->set_tab_hidden(NodeDock::get_singleton()->get_index(), false);
- fs_tabs->set_tab_hidden(FileSystemDock::get_singleton()->get_index(), false);
+ import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), false);
+ node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), false);
+ fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), false);
ImportDock::get_singleton()->set_visible(true);
NodeDock::get_singleton()->set_visible(true);
FileSystemDock::get_singleton()->set_visible(true);
@@ -6205,7 +6212,7 @@ EditorNode::EditorNode() {
dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
dock_slot[i]->set_popup(dock_select_popup);
dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup), varray(i));
- dock_slot[i]->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ dock_slot[i]->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
dock_slot[i]->set_drag_to_rearrange_enabled(true);
dock_slot[i]->set_tabs_rearrange_group(1);
dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed));
@@ -6714,23 +6721,23 @@ EditorNode::EditorNode() {
// Scene: Top left
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(SceneTreeDock::get_singleton()->get_index(), TTR("Scene"));
+ dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(SceneTreeDock::get_singleton()), TTR("Scene"));
// Import: Top left, behind Scene
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(ImportDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(ImportDock::get_singleton()->get_index(), TTR("Import"));
+ dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(ImportDock::get_singleton()), TTR("Import"));
// FileSystem: Bottom left
dock_slot[DOCK_SLOT_LEFT_BR]->add_child(FileSystemDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(FileSystemDock::get_singleton()->get_index(), TTR("FileSystem"));
+ dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_BR]->get_tab_idx_from_control(FileSystemDock::get_singleton()), TTR("FileSystem"));
// Inspector: Full height right
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(InspectorDock::get_singleton());
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(InspectorDock::get_singleton()->get_index(), TTR("Inspector"));
+ dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(InspectorDock::get_singleton()), TTR("Inspector"));
// Node: Full height right, behind Inspector
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton());
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(NodeDock::get_singleton()->get_index(), TTR("Node"));
+ dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node"));
// Hide unused dock slots and vsplits
dock_slot[DOCK_SLOT_LEFT_UL]->hide();
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 18324f9971c..75bba64e2ea 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -662,7 +662,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
undo_redo = memnew(UndoRedo);
tabs = memnew(TabContainer);
- tabs->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
tabs->connect("tab_changed", callable_mp(this, &EditorSettingsDialog::_tabs_tab_changed));
add_child(tabs);
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index cd9986d5278..a766650cd9a 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -477,7 +477,7 @@ LocalizationEditor::LocalizationEditor() {
localization_changed = "localization_changed";
TabContainer *translations = memnew(TabContainer);
- translations->set_tab_alignment(TabContainer::ALIGNMENT_LEFT);
+ translations->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
translations->set_v_size_flags(Control::SIZE_EXPAND_FILL);
add_child(translations);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 30c2b125192..a4a29190346 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -407,8 +407,8 @@ void ScriptEditor::_breaked(bool p_breaked, bool p_can_debug) {
return;
}
- for (int i = 0; i < tab_container->get_child_count(); i++) {
- ScriptEditorBase *se = Object::cast_to(tab_container->get_child(i));
+ for (int i = 0; i < tab_container->get_tab_count(); i++) {
+ ScriptEditorBase *se = Object::cast_to(tab_container->get_tab_control(i));
if (!se) {
continue;
}
@@ -447,8 +447,8 @@ void ScriptEditor::_goto_script_line(REF p_script, int p_line) {
void ScriptEditor::_set_execution(REF p_script, int p_line) {
Ref