|
|
@@ -35,6 +35,7 @@
|
|
|
#include "scene/gui/box_container.h"
|
|
|
#include "scene/gui/label.h"
|
|
|
#include "scene/gui/texture_rect.h"
|
|
|
+#include "scene/main/viewport.h"
|
|
|
|
|
|
Size2 TabBar::get_minimum_size() const {
|
|
|
Size2 ms;
|
|
|
@@ -158,7 +159,13 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (get_viewport()->gui_is_dragging() && can_drop_data(pos, get_viewport()->gui_get_drag_data())) {
|
|
|
+ dragging_valid_tab = true;
|
|
|
+ update();
|
|
|
+ }
|
|
|
+
|
|
|
_update_hover();
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -333,6 +340,13 @@ void TabBar::_notification(int p_what) {
|
|
|
}
|
|
|
} break;
|
|
|
|
|
|
+ case NOTIFICATION_DRAG_END: {
|
|
|
+ if (dragging_valid_tab) {
|
|
|
+ dragging_valid_tab = false;
|
|
|
+ update();
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+
|
|
|
case NOTIFICATION_DRAW: {
|
|
|
if (tabs.is_empty()) {
|
|
|
return;
|
|
|
@@ -346,8 +360,6 @@ void TabBar::_notification(int p_what) {
|
|
|
Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
|
|
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
|
|
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
|
|
- Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
|
|
|
- Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
|
|
|
|
|
|
bool rtl = is_layout_rtl();
|
|
|
Vector2 size = get_size();
|
|
|
@@ -391,7 +403,10 @@ void TabBar::_notification(int p_what) {
|
|
|
}
|
|
|
|
|
|
if (buttons_visible) {
|
|
|
- int vofs = (get_size().height - incr->get_size().height) / 2;
|
|
|
+ Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
|
|
|
+ Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
|
|
|
+
|
|
|
+ int vofs = (size.height - incr->get_size().height) / 2;
|
|
|
|
|
|
if (rtl) {
|
|
|
if (missing_right) {
|
|
|
@@ -419,6 +434,39 @@ void TabBar::_notification(int p_what) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (dragging_valid_tab) {
|
|
|
+ int x;
|
|
|
+
|
|
|
+ int tab_hover = get_hovered_tab();
|
|
|
+ if (tab_hover != -1) {
|
|
|
+ Rect2 tab_rect = get_tab_rect(tab_hover);
|
|
|
+
|
|
|
+ x = tab_rect.position.x;
|
|
|
+ if (get_local_mouse_position().x > x + tab_rect.size.width / 2) {
|
|
|
+ x += tab_rect.size.width;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (rtl ^ (get_local_mouse_position().x < get_tab_rect(0).position.x)) {
|
|
|
+ x = get_tab_rect(0).position.x;
|
|
|
+ if (rtl) {
|
|
|
+ x += get_tab_rect(0).size.width;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Rect2 tab_rect = get_tab_rect(get_tab_count() - 1);
|
|
|
+
|
|
|
+ x = tab_rect.position.x;
|
|
|
+ if (!rtl) {
|
|
|
+ x += tab_rect.size.width;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Ref<Texture2D> drop_mark = get_theme_icon(SNAME("drop_mark"));
|
|
|
+ Color drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
|
|
|
+
|
|
|
+ drop_mark->draw(get_canvas_item(), Point2(x - drop_mark->get_width() / 2, (size.height - drop_mark->get_height()) / 2), drop_mark_color);
|
|
|
+ }
|
|
|
} break;
|
|
|
}
|
|
|
}
|
|
|
@@ -906,6 +954,8 @@ void TabBar::_on_mouse_exited() {
|
|
|
cb_hover = -1;
|
|
|
hover = -1;
|
|
|
highlight_arrow = -1;
|
|
|
+ dragging_valid_tab = false;
|
|
|
+
|
|
|
update();
|
|
|
}
|
|
|
|
|
|
@@ -1057,13 +1107,29 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
|
|
|
NodePath to_path = get_path();
|
|
|
|
|
|
if (from_path == to_path) {
|
|
|
- if (hover_now < 0) {
|
|
|
- hover_now = get_tab_count() - 1;
|
|
|
+ if (tab_from_id == hover_now) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Drop the new tab to the left or right depending on where the target tab is being hovered.
|
|
|
+ if (hover_now != -1) {
|
|
|
+ Rect2 tab_rect = get_tab_rect(hover_now);
|
|
|
+ if (is_layout_rtl() ^ (p_point.x <= tab_rect.position.x + tab_rect.size.width / 2)) {
|
|
|
+ if (hover_now > tab_from_id) {
|
|
|
+ hover_now -= 1;
|
|
|
+ }
|
|
|
+ } else if (tab_from_id > hover_now) {
|
|
|
+ hover_now += 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ hover_now = is_layout_rtl() ^ (p_point.x < get_tab_rect(0).position.x) ? 0 : get_tab_count() - 1;
|
|
|
}
|
|
|
|
|
|
move_tab(tab_from_id, hover_now);
|
|
|
- emit_signal(SNAME("active_tab_rearranged"), hover_now);
|
|
|
- set_current_tab(hover_now);
|
|
|
+ if (!is_tab_disabled(hover_now)) {
|
|
|
+ emit_signal(SNAME("active_tab_rearranged"), hover_now);
|
|
|
+ set_current_tab(hover_now);
|
|
|
+ }
|
|
|
} else if (get_tabs_rearrange_group() != -1) {
|
|
|
// Drag and drop between Tabs.
|
|
|
|
|
|
@@ -1075,11 +1141,17 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- Tab moving_tab = from_tabs->tabs[tab_from_id];
|
|
|
- if (hover_now < 0) {
|
|
|
- hover_now = get_tab_count();
|
|
|
+ // Drop the new tab to the left or right depending on where the target tab is being hovered.
|
|
|
+ if (hover_now != -1) {
|
|
|
+ Rect2 tab_rect = get_tab_rect(hover_now);
|
|
|
+ if (is_layout_rtl() ^ (p_point.x > tab_rect.position.x + tab_rect.size.width / 2)) {
|
|
|
+ hover_now += 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ hover_now = is_layout_rtl() ^ (p_point.x < get_tab_rect(0).position.x) ? 0 : get_tab_count();
|
|
|
}
|
|
|
|
|
|
+ Tab moving_tab = from_tabs->tabs[tab_from_id];
|
|
|
from_tabs->remove_tab(tab_from_id);
|
|
|
tabs.insert(hover_now, moving_tab);
|
|
|
|
|
|
@@ -1092,7 +1164,13 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- set_current_tab(hover_now);
|
|
|
+ if (!is_tab_disabled(hover_now)) {
|
|
|
+ set_current_tab(hover_now);
|
|
|
+ } else {
|
|
|
+ _update_cache();
|
|
|
+ update();
|
|
|
+ }
|
|
|
+
|
|
|
update_minimum_size();
|
|
|
|
|
|
if (tabs.size() == 1) {
|