瀏覽代碼

Fix TabContainer respecting tabbar_background margins

Logan Detrick 2 月之前
父節點
當前提交
944295ab04
共有 2 個文件被更改,包括 70 次插入63 次删除
  1. 69 63
      scene/gui/tab_container.cpp
  2. 1 0
      scene/gui/tab_container.h

+ 69 - 63
scene/gui/tab_container.cpp

@@ -32,10 +32,20 @@
 
 
 #include "scene/theme/theme_db.h"
 #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 TabContainer::_get_tab_height() const {
 	int height = 0;
 	int height = 0;
 	if (tabs_visible && get_tab_count() > 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;
 	return height;
@@ -50,29 +60,27 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
 
 
 	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 		Point2 pos = mb->get_position();
 		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.
 		// 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;
 			return;
 		}
 		}
 
 
 		// Handle menu button.
 		// Handle menu button.
 		if (popup) {
 		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"));
 				emit_signal(SNAME("pre_popup_pressed"));
 
 
 				Vector2 popup_pos = get_screen_position();
 				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) {
 				if (tabs_position == POSITION_BOTTOM) {
-					popup_pos.y += content_height;
 					popup_pos.y -= popup->get_size().height;
 					popup_pos.y -= popup->get_size().height;
 					popup_pos.y -= theme_cache.menu_icon->get_height() / 2.0;
 					popup_pos.y -= theme_cache.menu_icon->get_height() / 2.0;
 				} else {
 				} else {
@@ -90,17 +98,15 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
 
 
 	if (mm.is_valid()) {
 	if (mm.is_valid()) {
 		Point2 pos = mm->get_position();
 		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.
 		// 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) {
 			if (menu_hovered) {
 				menu_hovered = false;
 				menu_hovered = false;
 				queue_redraw();
 				queue_redraw();
@@ -109,28 +115,15 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
 		}
 		}
 
 
 		if (popup) {
 		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();
 					queue_redraw();
+					return;
 				}
 				}
+			} else if (menu_hovered) {
+				menu_hovered = false;
+				queue_redraw();
 			}
 			}
 
 
 			if (menu_hovered) {
 			if (menu_hovered) {
@@ -201,6 +194,7 @@ void TabContainer::_notification(int p_what) {
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
 			RID canvas = get_canvas_item();
 			RID canvas = get_canvas_item();
 			Size2 size = get_size();
 			Size2 size = get_size();
+			Rect2 tabbar_rect = _get_tab_rect();
 
 
 			// Draw only the tab area if the header is hidden.
 			// Draw only the tab area if the header is hidden.
 			if (!tabs_visible) {
 			if (!tabs_visible) {
@@ -218,12 +212,13 @@ void TabContainer::_notification(int p_what) {
 
 
 			// Draw the popup menu.
 			// Draw the popup menu.
 			if (get_popup()) {
 			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) {
 				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 {
 				} 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;
 		} break;
@@ -307,14 +302,17 @@ void TabContainer::_repaint() {
 	Vector<Control *> controls = _get_tab_controls();
 	Vector<Control *> controls = _get_tab_controls();
 	int current = get_current_tab();
 	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.
 	// 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.
 	// Don't change the left and right offsets since the TabBar will resize and may change tab offset.
 	if (tabs_position == POSITION_BOTTOM) {
 	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 {
 	} 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;
 	updating_visibility = true;
@@ -349,46 +347,52 @@ void TabContainer::_repaint() {
 void TabContainer::_update_margins() {
 void TabContainer::_update_margins() {
 	// Directly check for validity, to avoid errors when quitting.
 	// Directly check for validity, to avoid errors when quitting.
 	bool has_popup = popup_obj_id.is_valid();
 	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) {
 	if (has_popup) {
-		menu_width = theme_cache.menu_icon->get_width();
+		right_margin += theme_cache.menu_icon->get_width();
 	}
 	}
 
 
 	if (get_tab_count() == 0) {
 	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;
 		return;
 	}
 	}
 
 
 	switch (get_tab_alignment()) {
 	switch (get_tab_alignment()) {
 		case TabBar::ALIGNMENT_LEFT: {
 		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;
 		} break;
 
 
 		case TabBar::ALIGNMENT_CENTER: {
 		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;
 		} break;
 
 
 		case TabBar::ALIGNMENT_RIGHT: {
 		case TabBar::ALIGNMENT_RIGHT: {
-			tab_bar->set_offset(SIDE_LEFT, 0);
+			tab_bar->set_offset(SIDE_LEFT, left_margin);
 
 
 			if (has_popup) {
 			if (has_popup) {
-				tab_bar->set_offset(SIDE_RIGHT, -menu_width);
+				tab_bar->set_offset(SIDE_RIGHT, -right_margin);
 				return;
 				return;
 			}
 			}
 
 
 			int first_tab_pos = tab_bar->get_tab_rect(0).position.x;
 			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);
 			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.
 			// 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))) {
 			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 {
 			} else {
-				tab_bar->set_offset(SIDE_RIGHT, -theme_cache.side_margin);
+				tab_bar->set_offset(SIDE_RIGHT, -right_margin - theme_cache.side_margin);
 			}
 			}
 		} break;
 		} break;
 
 
@@ -944,6 +948,8 @@ Size2 TabContainer::get_minimum_size() const {
 
 
 	if (tabs_visible) {
 	if (tabs_visible) {
 		ms = tab_bar->get_minimum_size();
 		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_clip_tabs()) {
 			if (get_popup()) {
 			if (get_popup()) {

+ 1 - 0
scene/gui/tab_container.h

@@ -99,6 +99,7 @@ private:
 
 
 	HashMap<Node *, RID> tab_panels;
 	HashMap<Node *, RID> tab_panels;
 
 
+	Rect2 _get_tab_rect() const;
 	int _get_tab_height() const;
 	int _get_tab_height() const;
 	Vector<Control *> _get_tab_controls() const;
 	Vector<Control *> _get_tab_controls() const;
 	void _on_theme_changed();
 	void _on_theme_changed();