@@ -509,13 +509,8 @@ void TabBar::_notification(int p_what) {
509509
510510 int limit_minus_buttons = size.width - theme_cache.increment_icon ->get_width () - theme_cache.decrement_icon ->get_width ();
511511
512- int ofs = tabs[offset].ofs_cache ;
513- int tab_separation_offset = 0 ;
514-
515512 // Draw unselected tabs in the back.
516513 for (int i = offset; i <= max_drawn_tab; i++) {
517- tab_separation_offset = (i - offset) * theme_cache.tab_separation ;
518-
519514 if (tabs[i].hidden ) {
520515 continue ;
521516 }
@@ -535,23 +530,15 @@ void TabBar::_notification(int p_what) {
535530 col = theme_cache.font_unselected_color ;
536531 }
537532
538- _draw_tab (sb, col, i, rtl ? (size.width - ofs - tab_separation_offset - tabs[i].size_cache ) : (ofs + tab_separation_offset) , false );
533+ _draw_tab (sb, col, i, rtl ? (size.width - tabs[i]. ofs_cache - tabs[i].size_cache ) : tabs[i]. ofs_cache , false );
539534 }
540-
541- ofs += tabs[i].size_cache ;
542535 }
543536
544537 // Draw selected tab in the front, but only if it's visible.
545538 if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden ) {
546- tab_separation_offset = (current - offset) * theme_cache.tab_separation ;
547- if (tab_alignment == ALIGNMENT_LEFT && (current - offset) > 1 ) {
548- tab_separation_offset = theme_cache.tab_separation ;
549- }
550-
551539 Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style ;
552- float x = rtl ? (size.width - tabs[current].ofs_cache - tab_separation_offset - tabs[current].size_cache ) : (tabs[current].ofs_cache + tab_separation_offset);
553540
554- _draw_tab (sb, theme_cache.font_selected_color , current, x , has_focus ());
541+ _draw_tab (sb, theme_cache.font_selected_color , current, rtl ? (size. width - tabs[current]. ofs_cache - tabs[current]. size_cache ) : tabs[current]. ofs_cache , has_focus ());
555542 }
556543
557544 if (buttons_visible) {
@@ -590,38 +577,20 @@ void TabBar::_notification(int p_what) {
590577 int closest_tab = get_closest_tab_idx_to_point (get_local_mouse_position ());
591578 if (closest_tab != -1 ) {
592579 Rect2 tab_rect = get_tab_rect (closest_tab);
580+ x = tab_rect.position .x ;
581+
582+ // Only add the tab_separation if closest tab is not on the edge.
583+ bool not_leftmost_tab = -1 != (rtl ? get_next_available (closest_tab) : get_previous_available (closest_tab));
584+ bool not_rightmost_tab = -1 != (rtl ? get_previous_available (closest_tab) : get_next_available (closest_tab));
593585
594586 // Calculate midpoint between tabs.
595- if (rtl) {
596- if (get_local_mouse_position ().x > tab_rect.position .x + tab_rect.size .width / 2 ) {
597- if (closest_tab > 0 ) { // On right side of closest_tab and not first tab.
598- Rect2 next_tab_rect = get_tab_rect (closest_tab - 1 );
599- x = (tab_rect.position .x + tab_rect.size .width + next_tab_rect.position .x ) / 2 ;
600- } else { // First tab, will appear on right edge.
601- x = tab_rect.position .x + tab_rect.size .width ;
602- }
603- } else {
604- if (closest_tab < max_drawn_tab) { // On left side of closest_tab and not last tab.
605- Rect2 prev_tab_rect = get_tab_rect (closest_tab + 1 );
606- x = (tab_rect.position .x + prev_tab_rect.position .x + prev_tab_rect.size .width ) / 2 ;
607- } else { // Last tab, will appear on left edge.
608- x = tab_rect.position .x ;
609- }
610- }
611- } else if (get_local_mouse_position ().x > tab_rect.position .x + tab_rect.size .width / 2 ) {
612- if (closest_tab < max_drawn_tab) { // On right side of closest_tab and not last tab.
613- Rect2 next_tab_rect = get_tab_rect (closest_tab + 1 );
614- x = (tab_rect.position .x + tab_rect.size .width + next_tab_rect.position .x ) / 2 ;
615- } else { // Last tab, will appear on right edge.
616- x = tab_rect.position .x + tab_rect.size .width ;
617- }
618- } else {
619- if (closest_tab > 0 ) { // On left side of closest_tab and not first tab.
620- Rect2 prev_tab_rect = get_tab_rect (closest_tab - 1 );
621- x = (tab_rect.position .x + prev_tab_rect.position .x + prev_tab_rect.size .width ) / 2 ;
622- } else { // First tab, will appear on left edge.
623- x = tab_rect.position .x ;
587+ if (get_local_mouse_position ().x > tab_rect.get_center ().x ) {
588+ x += tab_rect.size .x ;
589+ if (not_rightmost_tab) {
590+ x += Math::ceil (0 .5f * theme_cache.tab_separation );
624591 }
592+ } else if (not_leftmost_tab) {
593+ x -= Math::floor (0 .5f * theme_cache.tab_separation );
625594 }
626595 } else {
627596 if (rtl ^ (get_local_mouse_position ().x < get_tab_rect (0 ).position .x )) {
@@ -841,31 +810,49 @@ int TabBar::get_hovered_tab() const {
841810 return hover;
842811}
843812
844- bool TabBar::select_previous_available () {
845- const int offset_end = (get_current_tab () + 1 );
813+ int TabBar::get_previous_available (int p_idx) const {
814+ ERR_FAIL_COND_V (p_idx < -1 || p_idx > get_tab_count (), -1 );
815+ const int idx = p_idx == -1 ? get_current_tab () : p_idx;
816+ const int offset_end = idx + 1 ;
846817 for (int i = 1 ; i < offset_end; i++) {
847- int target_tab = get_current_tab () - i;
818+ int target_tab = idx - i;
848819 if (target_tab < 0 ) {
849820 target_tab += get_tab_count ();
850821 }
851822 if (!is_tab_disabled (target_tab) && !is_tab_hidden (target_tab)) {
852- set_current_tab (target_tab);
853- return true ;
823+ return target_tab;
854824 }
855825 }
856- return false ;
826+ return - 1 ;
857827}
858828
859- bool TabBar::select_next_available () {
860- const int offset_end = (get_tab_count () - get_current_tab ());
829+ int TabBar::get_next_available (int p_idx) const {
830+ ERR_FAIL_COND_V (p_idx < -1 || p_idx > get_tab_count (), -1 );
831+ const int idx = p_idx == -1 ? get_current_tab () : p_idx;
832+ const int offset_end = get_tab_count () - idx;
861833 for (int i = 1 ; i < offset_end; i++) {
862- int target_tab = (get_current_tab () + i) % get_tab_count ();
834+ int target_tab = (idx + i) % get_tab_count ();
863835 if (!is_tab_disabled (target_tab) && !is_tab_hidden (target_tab)) {
864- set_current_tab (target_tab);
865- return true ;
836+ return target_tab;
866837 }
867838 }
868- return false ;
839+ return -1 ;
840+ }
841+
842+ bool TabBar::select_previous_available () {
843+ const int previous_available = get_previous_available ();
844+ if (previous_available != -1 ) {
845+ set_current_tab (previous_available);
846+ }
847+ return previous_available != -1 ;
848+ }
849+
850+ bool TabBar::select_next_available () {
851+ const int next_available = get_next_available ();
852+ if (next_available != -1 ) {
853+ set_current_tab (next_available);
854+ }
855+ return next_available != -1 ;
869856}
870857
871858void TabBar::set_tab_offset (int p_offset) {
@@ -1166,6 +1153,7 @@ void TabBar::_update_cache(bool p_update_hover) {
11661153 tabs.write [i].text_buf ->set_width (-1 );
11671154 tabs.write [i].size_text = Math::ceil (tabs[i].text_buf ->get_size ().x );
11681155 tabs.write [i].size_cache = get_tab_width (i);
1156+ tabs.write [i].accessibility_item_dirty = true ;
11691157
11701158 tabs.write [i].truncated = max_width > 0 && tabs[i].size_cache > max_width;
11711159 if (tabs[i].truncated ) {
@@ -1189,9 +1177,6 @@ void TabBar::_update_cache(bool p_update_hover) {
11891177 }
11901178
11911179 w += tabs[i].size_cache ;
1192- if ((i - offset) > 0 ) {
1193- w += theme_cache.tab_separation ;
1194- }
11951180
11961181 // Check if all tabs would fit inside the area.
11971182 if (clip_tabs && i > offset && (w > limit || (offset > 0 && w > limit_minus_buttons))) {
@@ -1212,9 +1197,10 @@ void TabBar::_update_cache(bool p_update_hover) {
12121197
12131198 max_drawn_tab--;
12141199 }
1200+ } else if (i < tabs.size () - 1 ) {
1201+ // Only add the tab separation if this isn't the last tab drawn.
1202+ w += theme_cache.tab_separation ;
12151203 }
1216-
1217- tabs.write [i].accessibility_item_dirty = true ;
12181204 }
12191205
12201206 missing_right = max_drawn_tab < tabs.size () - 1 ;
@@ -1234,10 +1220,11 @@ void TabBar::_update_cache(bool p_update_hover) {
12341220 }
12351221
12361222 for (int i = offset; i <= max_drawn_tab; i++) {
1237- tabs.write [i].ofs_cache = w;
1238-
12391223 if (!tabs[i].hidden ) {
1224+ tabs.write [i].ofs_cache = w;
1225+
12401226 w += tabs[i].size_cache ;
1227+ w += theme_cache.tab_separation ;
12411228 }
12421229 }
12431230
@@ -1545,10 +1532,14 @@ void TabBar::_move_tab_from(TabBar *p_from_tabbar, int p_from_index, int p_to_in
15451532}
15461533
15471534int TabBar::get_tab_idx_at_point (const Point2 &p_point) const {
1535+ if (tabs.is_empty ()) {
1536+ return -1 ;
1537+ }
1538+
15481539 int hover_now = -1 ;
15491540
1550- if (!tabs. is_empty () ) {
1551- for ( int i = offset; i <= max_drawn_tab; i++ ) {
1541+ for ( int i = offset; i <= max_drawn_tab; i++ ) {
1542+ if (!tabs[i]. hidden ) {
15521543 Rect2 rect = get_tab_rect (i);
15531544 if (rect.has_point (p_point)) {
15541545 hover_now = i;
@@ -1560,16 +1551,23 @@ int TabBar::get_tab_idx_at_point(const Point2 &p_point) const {
15601551}
15611552
15621553int TabBar::get_closest_tab_idx_to_point (const Point2 &p_point) const {
1563- int closest_tab = get_tab_idx_at_point (p_point); // See if we're hovering over a tab first.
1554+ if (tabs.is_empty ()) {
1555+ return -1 ;
1556+ }
1557+
1558+ int closest_tab = get_tab_idx_at_point (p_point);
1559+ float closest_distance = FLT_MAX;
15641560
1565- if (closest_tab == - 1 ) { // Didn't find a tab, so get the closest one .
1566- float closest_distance = FLT_MAX;
1561+ // Search along the x-axis since the TabBar is horizontal .
1562+ if (closest_tab == - 1 ) {
15671563 for (int i = offset; i <= max_drawn_tab; i++) {
1568- Vector2 center = get_tab_rect (i).get_center ();
1569- float distance = center.distance_to (p_point);
1570- if (distance < closest_distance) {
1571- closest_distance = distance;
1572- closest_tab = i;
1564+ if (!tabs[i].hidden ) {
1565+ float center = get_tab_rect (i).get_center ().x ;
1566+ float distance = Math::abs (center - p_point.x );
1567+ if (distance < closest_distance) {
1568+ closest_distance = distance;
1569+ closest_tab = i;
1570+ }
15731571 }
15741572 }
15751573 }
@@ -1829,14 +1827,11 @@ void TabBar::ensure_tab_visible(int p_idx) {
18291827
18301828Rect2 TabBar::get_tab_rect (int p_tab) const {
18311829 ERR_FAIL_INDEX_V (p_tab, tabs.size (), Rect2 ());
1832- int tab_separation_offset = (p_tab - offset) * theme_cache.tab_separation ;
1833- if (tab_alignment == ALIGNMENT_LEFT && (p_tab - offset) > 1 ) {
1834- tab_separation_offset = theme_cache.tab_separation ;
1835- }
1830+
18361831 if (is_layout_rtl ()) {
1837- return Rect2 (get_size ().width - tabs[p_tab].ofs_cache - tab_separation_offset - tabs[p_tab].size_cache , 0 , tabs[p_tab].size_cache , get_size ().height );
1832+ return Rect2 (get_size ().width - tabs[p_tab].ofs_cache - tabs[p_tab].size_cache , 0 , tabs[p_tab].size_cache , get_size ().height );
18381833 } else {
1839- return Rect2 (tabs[p_tab].ofs_cache + tab_separation_offset , 0 , tabs[p_tab].size_cache , get_size ().height );
1834+ return Rect2 (tabs[p_tab].ofs_cache , 0 , tabs[p_tab].size_cache , get_size ().height );
18401835 }
18411836}
18421837
0 commit comments