diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c93420ee408..b92dce1f5a7 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -32,10 +32,20 @@ #include "scene/theme/theme_db.h" +Rect2 TabContainer::_get_tab_rect() const { + Rect2 rect; + if (tabs_visible && get_tab_count() > 0) { + rect = Rect2(theme_cache.tabbar_style->get_offset(), tab_bar->get_size()); + rect.position.x += is_layout_rtl() ? theme_cache.menu_icon->get_width() : theme_cache.side_margin; + } + + return rect; +} + int TabContainer::_get_tab_height() const { int height = 0; if (tabs_visible && get_tab_count() > 0) { - height = tab_bar->get_minimum_size().height; + height = tab_bar->get_minimum_size().height + theme_cache.tabbar_style->get_margin(SIDE_TOP) + theme_cache.tabbar_style->get_margin(SIDE_BOTTOM); } return height; @@ -50,29 +60,27 @@ void TabContainer::gui_input(const Ref &p_event) { if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Point2 pos = mb->get_position(); - Size2 size = get_size(); - real_t content_height = size.height - _get_tab_height(); + real_t content_height = get_size().height - _get_tab_height(); + + Rect2 popup_rect = _get_tab_rect(); + popup_rect.position.x += is_layout_rtl() ? -theme_cache.menu_icon->get_width() : popup_rect.size.x; + popup_rect.position.y += tabs_position == POSITION_BOTTOM ? content_height : 0; + popup_rect.size.x = theme_cache.menu_icon->get_width(); // Click must be on tabs in the tab header area. - if (tabs_position == POSITION_TOP && pos.y > _get_tab_height()) { - return; - } - if (tabs_position == POSITION_BOTTOM && pos.y < content_height) { + if (!tabs_visible || pos.y < popup_rect.position.y || pos.y >= popup_rect.position.y + popup_rect.size.y) { return; } // Handle menu button. if (popup) { - if (is_layout_rtl() ? pos.x < theme_cache.menu_icon->get_width() : pos.x > size.width - theme_cache.menu_icon->get_width()) { + if (popup_rect.has_point(pos)) { emit_signal(SNAME("pre_popup_pressed")); Vector2 popup_pos = get_screen_position(); - if (!is_layout_rtl()) { - popup_pos.x += size.width - popup->get_size().width; - } - popup_pos.y += _get_tab_height() / 2.0; + popup_pos.x += popup_rect.position.x + (is_layout_rtl() ? 0 : popup_rect.size.x - popup->get_size().width); + popup_pos.y += popup_rect.position.y + popup_rect.size.y / 2.0; if (tabs_position == POSITION_BOTTOM) { - popup_pos.y += content_height; popup_pos.y -= popup->get_size().height; popup_pos.y -= theme_cache.menu_icon->get_height() / 2.0; } else { @@ -90,17 +98,15 @@ void TabContainer::gui_input(const Ref &p_event) { if (mm.is_valid()) { Point2 pos = mm->get_position(); - Size2 size = get_size(); + real_t content_height = get_size().height - _get_tab_height(); + + Rect2 popup_rect = _get_tab_rect(); + popup_rect.position.x += is_layout_rtl() ? -theme_cache.menu_icon->get_width() : popup_rect.size.x; + popup_rect.position.y += tabs_position == POSITION_BOTTOM ? content_height : 0; + popup_rect.size.x = theme_cache.menu_icon->get_width(); // Mouse must be on tabs in the tab header area. - if (tabs_position == POSITION_TOP && pos.y > _get_tab_height()) { - if (menu_hovered) { - menu_hovered = false; - queue_redraw(); - } - return; - } - if (tabs_position == POSITION_BOTTOM && pos.y < size.height - _get_tab_height()) { + if (!tabs_visible || pos.y < popup_rect.position.y || pos.y >= popup_rect.position.y + popup_rect.size.y) { if (menu_hovered) { menu_hovered = false; queue_redraw(); @@ -109,28 +115,15 @@ void TabContainer::gui_input(const Ref &p_event) { } if (popup) { - if (is_layout_rtl()) { - if (pos.x <= theme_cache.menu_icon->get_width()) { - if (!menu_hovered) { - menu_hovered = true; - queue_redraw(); - return; - } - } else if (menu_hovered) { - menu_hovered = false; - queue_redraw(); - } - } else { - if (pos.x >= size.width - theme_cache.menu_icon->get_width()) { - if (!menu_hovered) { - menu_hovered = true; - queue_redraw(); - return; - } - } else if (menu_hovered) { - menu_hovered = false; + if (popup_rect.has_point(pos)) { + if (!menu_hovered) { + menu_hovered = true; queue_redraw(); + return; } + } else if (menu_hovered) { + menu_hovered = false; + queue_redraw(); } if (menu_hovered) { @@ -201,6 +194,7 @@ void TabContainer::_notification(int p_what) { case NOTIFICATION_DRAW: { RID canvas = get_canvas_item(); Size2 size = get_size(); + Rect2 tabbar_rect = _get_tab_rect(); // Draw only the tab area if the header is hidden. if (!tabs_visible) { @@ -218,12 +212,13 @@ void TabContainer::_notification(int p_what) { // Draw the popup menu. if (get_popup()) { - int x = is_layout_rtl() ? 0 : get_size().width - theme_cache.menu_icon->get_width(); + int x = is_layout_rtl() ? tabbar_rect.position.x - theme_cache.menu_icon->get_width() : tabbar_rect.position.x + tabbar_rect.size.x; + header_voffset += tabbar_rect.position.y; if (menu_hovered) { - theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, header_voffset + (header_height - theme_cache.menu_hl_icon->get_height()) / 2)); + theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, header_voffset + (tabbar_rect.size.y - theme_cache.menu_hl_icon->get_height()) / 2)); } else { - theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, header_voffset + (header_height - theme_cache.menu_icon->get_height()) / 2)); + theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, header_voffset + (tabbar_rect.size.y - theme_cache.menu_icon->get_height()) / 2)); } } } break; @@ -307,14 +302,17 @@ void TabContainer::_repaint() { Vector controls = _get_tab_controls(); int current = get_current_tab(); + float top_margin = theme_cache.tabbar_style->get_margin(SIDE_TOP); + float bottom_margin = theme_cache.tabbar_style->get_margin(SIDE_BOTTOM); + // Move the TabBar to the top or bottom. // Don't change the left and right offsets since the TabBar will resize and may change tab offset. if (tabs_position == POSITION_BOTTOM) { - tab_bar->set_anchor_and_offset(SIDE_BOTTOM, 1.0, 0.0); - tab_bar->set_anchor_and_offset(SIDE_TOP, 1.0, -_get_tab_height()); + tab_bar->set_anchor_and_offset(SIDE_BOTTOM, 1.0, -bottom_margin); + tab_bar->set_anchor_and_offset(SIDE_TOP, 1.0, top_margin - _get_tab_height()); } else { - tab_bar->set_anchor_and_offset(SIDE_BOTTOM, 0.0, _get_tab_height()); - tab_bar->set_anchor_and_offset(SIDE_TOP, 0.0, 0.0); + tab_bar->set_anchor_and_offset(SIDE_TOP, 0.0, top_margin); + tab_bar->set_anchor_and_offset(SIDE_BOTTOM, 0.0, _get_tab_height() - bottom_margin); } updating_visibility = true; @@ -349,46 +347,52 @@ void TabContainer::_repaint() { void TabContainer::_update_margins() { // Directly check for validity, to avoid errors when quitting. bool has_popup = popup_obj_id.is_valid(); - int menu_width = 0; + + int left_margin = theme_cache.tabbar_style->get_margin(SIDE_LEFT); + int right_margin = theme_cache.tabbar_style->get_margin(SIDE_RIGHT); + + if (is_layout_rtl()) { + SWAP(left_margin, right_margin); + } + if (has_popup) { - menu_width = theme_cache.menu_icon->get_width(); + right_margin += theme_cache.menu_icon->get_width(); } if (get_tab_count() == 0) { - tab_bar->set_offset(SIDE_LEFT, 0); - tab_bar->set_offset(SIDE_RIGHT, -menu_width); - + tab_bar->set_offset(SIDE_LEFT, left_margin); + tab_bar->set_offset(SIDE_RIGHT, -right_margin); return; } switch (get_tab_alignment()) { case TabBar::ALIGNMENT_LEFT: { - tab_bar->set_offset(SIDE_LEFT, theme_cache.side_margin); - tab_bar->set_offset(SIDE_RIGHT, -menu_width); + tab_bar->set_offset(SIDE_LEFT, left_margin + theme_cache.side_margin); + tab_bar->set_offset(SIDE_RIGHT, -right_margin); } break; case TabBar::ALIGNMENT_CENTER: { - tab_bar->set_offset(SIDE_LEFT, 0); - tab_bar->set_offset(SIDE_RIGHT, -menu_width); + tab_bar->set_offset(SIDE_LEFT, left_margin); + tab_bar->set_offset(SIDE_RIGHT, -right_margin); } break; case TabBar::ALIGNMENT_RIGHT: { - tab_bar->set_offset(SIDE_LEFT, 0); + tab_bar->set_offset(SIDE_LEFT, left_margin); if (has_popup) { - tab_bar->set_offset(SIDE_RIGHT, -menu_width); + tab_bar->set_offset(SIDE_RIGHT, -right_margin); return; } int first_tab_pos = tab_bar->get_tab_rect(0).position.x; Rect2 last_tab_rect = tab_bar->get_tab_rect(get_tab_count() - 1); - int total_tabs_width = last_tab_rect.position.x - first_tab_pos + last_tab_rect.size.width; + int total_tabs_width = left_margin + right_margin + last_tab_rect.position.x - first_tab_pos + last_tab_rect.size.width; // Calculate if all the tabs would still fit if the margin was present. if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + theme_cache.side_margin) > get_size().width))) { - tab_bar->set_offset(SIDE_RIGHT, -menu_width); + tab_bar->set_offset(SIDE_RIGHT, -right_margin); } else { - tab_bar->set_offset(SIDE_RIGHT, -theme_cache.side_margin); + tab_bar->set_offset(SIDE_RIGHT, -right_margin - theme_cache.side_margin); } } break; @@ -944,6 +948,8 @@ Size2 TabContainer::get_minimum_size() const { if (tabs_visible) { ms = tab_bar->get_minimum_size(); + ms.x += theme_cache.tabbar_style->get_margin(SIDE_LEFT) + theme_cache.tabbar_style->get_margin(SIDE_RIGHT); + ms.y += theme_cache.tabbar_style->get_margin(SIDE_TOP) + theme_cache.tabbar_style->get_margin(SIDE_BOTTOM); if (!get_clip_tabs()) { if (get_popup()) { diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 7a392cb6384..46952faa021 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -99,6 +99,7 @@ private: HashMap tab_panels; + Rect2 _get_tab_rect() const; int _get_tab_height() const; Vector _get_tab_controls() const; void _on_theme_changed();