Drag to rearrange Tabs and TabContainer
This commit is contained in:
parent
b67bfa3328
commit
9ac3c474b8
6 changed files with 347 additions and 4 deletions
|
@ -3892,6 +3892,53 @@ void EditorNode::_update_dock_slots_visibility() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorNode::_dock_tab_changed(int p_tab) {
|
||||||
|
|
||||||
|
// update visibility but dont set current tab
|
||||||
|
VSplitContainer *splits[DOCK_SLOT_MAX / 2] = {
|
||||||
|
left_l_vsplit,
|
||||||
|
left_r_vsplit,
|
||||||
|
right_l_vsplit,
|
||||||
|
right_r_vsplit,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!docks_visible) {
|
||||||
|
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
dock_slot[i]->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
|
||||||
|
splits[i]->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
right_hsplit->hide();
|
||||||
|
bottom_panel->hide();
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
|
||||||
|
if (dock_slot[i]->get_tab_count())
|
||||||
|
dock_slot[i]->show();
|
||||||
|
else
|
||||||
|
dock_slot[i]->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) {
|
||||||
|
bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
|
||||||
|
if (in_use)
|
||||||
|
splits[i]->show();
|
||||||
|
else
|
||||||
|
splits[i]->hide();
|
||||||
|
}
|
||||||
|
bottom_panel->show();
|
||||||
|
|
||||||
|
if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
|
||||||
|
right_hsplit->show();
|
||||||
|
else
|
||||||
|
right_hsplit->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
|
void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
|
||||||
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
@ -4762,6 +4809,7 @@ void EditorNode::_bind_methods() {
|
||||||
ClassDB::bind_method("_dock_popup_exit", &EditorNode::_dock_popup_exit);
|
ClassDB::bind_method("_dock_popup_exit", &EditorNode::_dock_popup_exit);
|
||||||
ClassDB::bind_method("_dock_move_left", &EditorNode::_dock_move_left);
|
ClassDB::bind_method("_dock_move_left", &EditorNode::_dock_move_left);
|
||||||
ClassDB::bind_method("_dock_move_right", &EditorNode::_dock_move_right);
|
ClassDB::bind_method("_dock_move_right", &EditorNode::_dock_move_right);
|
||||||
|
ClassDB::bind_method("_dock_tab_changed", &EditorNode::_dock_tab_changed);
|
||||||
|
|
||||||
ClassDB::bind_method("_layout_menu_option", &EditorNode::_layout_menu_option);
|
ClassDB::bind_method("_layout_menu_option", &EditorNode::_layout_menu_option);
|
||||||
|
|
||||||
|
@ -5121,6 +5169,9 @@ EditorNode::EditorNode() {
|
||||||
dock_slot[i]->set_popup(dock_select_popup);
|
dock_slot[i]->set_popup(dock_select_popup);
|
||||||
dock_slot[i]->connect("pre_popup_pressed", this, "_dock_pre_popup", varray(i));
|
dock_slot[i]->connect("pre_popup_pressed", this, "_dock_pre_popup", varray(i));
|
||||||
dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT);
|
dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT);
|
||||||
|
dock_slot[i]->set_drag_to_rearrange_enabled(true);
|
||||||
|
dock_slot[i]->set_tabs_rearrange_group(1);
|
||||||
|
dock_slot[i]->connect("tab_changed", this, "_dock_tab_changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
dock_drag_timer = memnew(Timer);
|
dock_drag_timer = memnew(Timer);
|
||||||
|
@ -5158,6 +5209,7 @@ EditorNode::EditorNode() {
|
||||||
scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
|
scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
|
||||||
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
|
scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
|
||||||
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
|
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
|
||||||
|
scene_tabs->set_drag_to_rearrange_enabled(true);
|
||||||
scene_tabs->connect("tab_changed", this, "_scene_tab_changed");
|
scene_tabs->connect("tab_changed", this, "_scene_tab_changed");
|
||||||
scene_tabs->connect("right_button_pressed", this, "_scene_tab_script_edited");
|
scene_tabs->connect("right_button_pressed", this, "_scene_tab_script_edited");
|
||||||
scene_tabs->connect("tab_close", this, "_scene_tab_closed");
|
scene_tabs->connect("tab_close", this, "_scene_tab_closed");
|
||||||
|
|
|
@ -569,6 +569,7 @@ private:
|
||||||
void _save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section);
|
void _save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section);
|
||||||
void _load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
|
void _load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
|
||||||
void _update_dock_slots_visibility();
|
void _update_dock_slots_visibility();
|
||||||
|
void _dock_tab_changed(int p_tab);
|
||||||
|
|
||||||
bool restoring_scenes;
|
bool restoring_scenes;
|
||||||
void _save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section);
|
void _save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section);
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include "tab_container.h"
|
#include "tab_container.h"
|
||||||
|
|
||||||
#include "message_queue.h"
|
#include "message_queue.h"
|
||||||
|
#include "scene/gui/box_container.h"
|
||||||
|
#include "scene/gui/label.h"
|
||||||
|
#include "scene/gui/texture_rect.h"
|
||||||
|
|
||||||
int TabContainer::_get_top_margin() const {
|
int TabContainer::_get_top_margin() const {
|
||||||
|
|
||||||
|
@ -492,6 +495,141 @@ void TabContainer::_update_current_tab() {
|
||||||
set_current_tab(current);
|
set_current_tab(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant TabContainer::get_drag_data(const Point2 &p_point) {
|
||||||
|
|
||||||
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
int tab_over = get_tab_idx_at_point(p_point);
|
||||||
|
|
||||||
|
if (tab_over < 0)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
HBoxContainer *drag_preview = memnew(HBoxContainer);
|
||||||
|
|
||||||
|
Ref<Texture> icon = get_tab_icon(tab_over);
|
||||||
|
if (!icon.is_null()) {
|
||||||
|
TextureRect *tf = memnew(TextureRect);
|
||||||
|
tf->set_texture(icon);
|
||||||
|
drag_preview->add_child(tf);
|
||||||
|
}
|
||||||
|
Label *label = memnew(Label(get_tab_title(tab_over)));
|
||||||
|
drag_preview->add_child(label);
|
||||||
|
set_drag_preview(drag_preview);
|
||||||
|
|
||||||
|
Dictionary drag_data;
|
||||||
|
drag_data["type"] = "tabc_element";
|
||||||
|
drag_data["tabc_element"] = tab_over;
|
||||||
|
drag_data["from_path"] = get_path();
|
||||||
|
return drag_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TabContainer::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
|
||||||
|
|
||||||
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Dictionary d = p_data;
|
||||||
|
if (!d.has("type"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (String(d["type"]) == "tabc_element") {
|
||||||
|
|
||||||
|
NodePath from_path = d["from_path"];
|
||||||
|
NodePath to_path = get_path();
|
||||||
|
if (from_path == to_path) {
|
||||||
|
return true;
|
||||||
|
} else if (get_tabs_rearrange_group() != -1) {
|
||||||
|
// drag and drop between other TabContainers
|
||||||
|
Node *from_node = get_node(from_path);
|
||||||
|
TabContainer *from_tabc = Object::cast_to<TabContainer>(from_node);
|
||||||
|
if (from_tabc && from_tabc->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabContainer::drop_data(const Point2 &p_point, const Variant &p_data) {
|
||||||
|
|
||||||
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int hover_now = get_tab_idx_at_point(p_point);
|
||||||
|
|
||||||
|
Dictionary d = p_data;
|
||||||
|
if (!d.has("type"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (String(d["type"]) == "tabc_element") {
|
||||||
|
|
||||||
|
int tab_from_id = d["tabc_element"];
|
||||||
|
NodePath from_path = d["from_path"];
|
||||||
|
NodePath to_path = get_path();
|
||||||
|
if (from_path == to_path) {
|
||||||
|
if (hover_now < 0)
|
||||||
|
hover_now = get_tab_count() - 1;
|
||||||
|
move_child(get_tab_control(tab_from_id), hover_now);
|
||||||
|
set_current_tab(hover_now);
|
||||||
|
} else if (get_tabs_rearrange_group() != -1) {
|
||||||
|
// drag and drop between TabContainers
|
||||||
|
Node *from_node = get_node(from_path);
|
||||||
|
TabContainer *from_tabc = Object::cast_to<TabContainer>(from_node);
|
||||||
|
if (from_tabc && from_tabc->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
|
||||||
|
Control *moving_tabc = from_tabc->get_tab_control(tab_from_id);
|
||||||
|
from_tabc->remove_child(moving_tabc);
|
||||||
|
add_child(moving_tabc);
|
||||||
|
if (hover_now < 0)
|
||||||
|
hover_now = get_tab_count() - 1;
|
||||||
|
move_child(moving_tabc, hover_now);
|
||||||
|
set_current_tab(hover_now);
|
||||||
|
emit_signal("tab_changed", hover_now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TabContainer::get_tab_idx_at_point(const Point2 &p_point) const {
|
||||||
|
|
||||||
|
if (get_tab_count() == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// must be on tabs in the tab header area.
|
||||||
|
if (p_point.x < tabs_ofs_cache || p_point.y > _get_top_margin())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Size2 size = get_size();
|
||||||
|
int right_ofs = 0;
|
||||||
|
|
||||||
|
if (popup) {
|
||||||
|
Ref<Texture> menu = get_icon("menu");
|
||||||
|
right_ofs += menu->get_width();
|
||||||
|
}
|
||||||
|
if (buttons_visible_cache) {
|
||||||
|
Ref<Texture> increment = get_icon("increment");
|
||||||
|
Ref<Texture> decrement = get_icon("decrement");
|
||||||
|
right_ofs += increment->get_width() + decrement->get_width();
|
||||||
|
}
|
||||||
|
if (p_point.x > size.width - right_ofs) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the tab at the point
|
||||||
|
Vector<Control *> tabs = _get_tabs();
|
||||||
|
int px = p_point.x;
|
||||||
|
px -= tabs_ofs_cache;
|
||||||
|
for (int i = first_tab_cache; i <= last_tab_cache; i++) {
|
||||||
|
int tab_width = _get_tab_width(i);
|
||||||
|
if (px < tab_width) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
px -= tab_width;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void TabContainer::set_tab_align(TabAlign p_align) {
|
void TabContainer::set_tab_align(TabAlign p_align) {
|
||||||
|
|
||||||
ERR_FAIL_INDEX(p_align, 3);
|
ERR_FAIL_INDEX(p_align, 3);
|
||||||
|
@ -500,6 +638,7 @@ void TabContainer::set_tab_align(TabAlign p_align) {
|
||||||
|
|
||||||
_change_notify("tab_align");
|
_change_notify("tab_align");
|
||||||
}
|
}
|
||||||
|
|
||||||
TabContainer::TabAlign TabContainer::get_tab_align() const {
|
TabContainer::TabAlign TabContainer::get_tab_align() const {
|
||||||
|
|
||||||
return align;
|
return align;
|
||||||
|
@ -643,6 +782,21 @@ Popup *TabContainer::get_popup() const {
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabContainer::set_drag_to_rearrange_enabled(bool p_enabled) {
|
||||||
|
drag_to_rearrange_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TabContainer::get_drag_to_rearrange_enabled() const {
|
||||||
|
return drag_to_rearrange_enabled;
|
||||||
|
}
|
||||||
|
void TabContainer::set_tabs_rearrange_group(int p_group_id) {
|
||||||
|
tabs_rearrange_group = p_group_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TabContainer::get_tabs_rearrange_group() const {
|
||||||
|
return tabs_rearrange_group;
|
||||||
|
}
|
||||||
|
|
||||||
void TabContainer::_bind_methods() {
|
void TabContainer::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_gui_input"), &TabContainer::_gui_input);
|
ClassDB::bind_method(D_METHOD("_gui_input"), &TabContainer::_gui_input);
|
||||||
|
@ -664,6 +818,10 @@ void TabContainer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled);
|
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled);
|
||||||
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
|
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
|
||||||
ClassDB::bind_method(D_METHOD("get_popup"), &TabContainer::get_popup);
|
ClassDB::bind_method(D_METHOD("get_popup"), &TabContainer::get_popup);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabContainer::set_drag_to_rearrange_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &TabContainer::get_drag_to_rearrange_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &TabContainer::set_tabs_rearrange_group);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabContainer::get_tabs_rearrange_group);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback);
|
ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback);
|
||||||
ClassDB::bind_method(D_METHOD("_on_theme_changed"), &TabContainer::_on_theme_changed);
|
ClassDB::bind_method(D_METHOD("_on_theme_changed"), &TabContainer::_on_theme_changed);
|
||||||
|
@ -676,6 +834,7 @@ void TabContainer::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
||||||
BIND_ENUM_CONSTANT(ALIGN_CENTER);
|
BIND_ENUM_CONSTANT(ALIGN_CENTER);
|
||||||
|
@ -694,4 +853,6 @@ TabContainer::TabContainer() {
|
||||||
align = ALIGN_CENTER;
|
align = ALIGN_CENTER;
|
||||||
tabs_visible = true;
|
tabs_visible = true;
|
||||||
popup = NULL;
|
popup = NULL;
|
||||||
|
drag_to_rearrange_enabled = false;
|
||||||
|
tabs_rearrange_group = -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ private:
|
||||||
Control *_get_tab(int p_idx) const;
|
Control *_get_tab(int p_idx) const;
|
||||||
int _get_top_margin() const;
|
int _get_top_margin() const;
|
||||||
Popup *popup;
|
Popup *popup;
|
||||||
|
bool drag_to_rearrange_enabled;
|
||||||
|
int tabs_rearrange_group;
|
||||||
|
|
||||||
Vector<Control *> _get_tabs() const;
|
Vector<Control *> _get_tabs() const;
|
||||||
int _get_tab_width(int p_index) const;
|
int _get_tab_width(int p_index) const;
|
||||||
|
@ -71,6 +73,11 @@ protected:
|
||||||
virtual void add_child_notify(Node *p_child);
|
virtual void add_child_notify(Node *p_child);
|
||||||
virtual void remove_child_notify(Node *p_child);
|
virtual void remove_child_notify(Node *p_child);
|
||||||
|
|
||||||
|
Variant get_drag_data(const Point2 &p_point);
|
||||||
|
bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
|
||||||
|
void drop_data(const Point2 &p_point, const Variant &p_data);
|
||||||
|
int get_tab_idx_at_point(const Point2 &p_point) const;
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -104,6 +111,11 @@ public:
|
||||||
void set_popup(Node *p_popup);
|
void set_popup(Node *p_popup);
|
||||||
Popup *get_popup() const;
|
Popup *get_popup() const;
|
||||||
|
|
||||||
|
void set_drag_to_rearrange_enabled(bool p_enabled);
|
||||||
|
bool get_drag_to_rearrange_enabled() const;
|
||||||
|
void set_tabs_rearrange_group(int p_group_id);
|
||||||
|
int get_tabs_rearrange_group() const;
|
||||||
|
|
||||||
TabContainer();
|
TabContainer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include "tabs.h"
|
#include "tabs.h"
|
||||||
|
|
||||||
#include "message_queue.h"
|
#include "message_queue.h"
|
||||||
|
#include "scene/gui/box_container.h"
|
||||||
|
#include "scene/gui/label.h"
|
||||||
|
#include "scene/gui/texture_rect.h"
|
||||||
|
|
||||||
Size2 Tabs::get_minimum_size() const {
|
Size2 Tabs::get_minimum_size() const {
|
||||||
|
|
||||||
|
@ -624,20 +627,105 @@ void Tabs::remove_tab(int p_idx) {
|
||||||
|
|
||||||
Variant Tabs::get_drag_data(const Point2 &p_point) {
|
Variant Tabs::get_drag_data(const Point2 &p_point) {
|
||||||
|
|
||||||
return get_tab_idx_at_point(p_point);
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
int tab_over = get_tab_idx_at_point(p_point);
|
||||||
|
|
||||||
|
if (tab_over < 0)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
HBoxContainer *drag_preview = memnew(HBoxContainer);
|
||||||
|
|
||||||
|
if (!tabs[tab_over].icon.is_null()) {
|
||||||
|
TextureRect *tf = memnew(TextureRect);
|
||||||
|
tf->set_texture(tabs[tab_over].icon);
|
||||||
|
drag_preview->add_child(tf);
|
||||||
|
}
|
||||||
|
Label *label = memnew(Label(tabs[tab_over].text));
|
||||||
|
drag_preview->add_child(label);
|
||||||
|
if (!tabs[tab_over].right_button.is_null()) {
|
||||||
|
TextureRect *tf = memnew(TextureRect);
|
||||||
|
tf->set_texture(tabs[tab_over].right_button);
|
||||||
|
drag_preview->add_child(tf);
|
||||||
|
}
|
||||||
|
set_drag_preview(drag_preview);
|
||||||
|
|
||||||
|
Dictionary drag_data;
|
||||||
|
drag_data["type"] = "tab_element";
|
||||||
|
drag_data["tab_element"] = tab_over;
|
||||||
|
drag_data["from_path"] = get_path();
|
||||||
|
return drag_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
|
bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
|
||||||
|
|
||||||
return get_tab_idx_at_point(p_point) > -1;
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Dictionary d = p_data;
|
||||||
|
if (!d.has("type"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (String(d["type"]) == "tab_element") {
|
||||||
|
|
||||||
|
NodePath from_path = d["from_path"];
|
||||||
|
NodePath to_path = get_path();
|
||||||
|
if (from_path == to_path) {
|
||||||
|
return true;
|
||||||
|
} else if (get_tabs_rearrange_group() != -1) {
|
||||||
|
// drag and drop between other Tabs
|
||||||
|
Node *from_node = get_node(from_path);
|
||||||
|
Tabs *from_tabs = Object::cast_to<Tabs>(from_node);
|
||||||
|
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
|
void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
|
||||||
|
|
||||||
|
if (!drag_to_rearrange_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
int hover_now = get_tab_idx_at_point(p_point);
|
int hover_now = get_tab_idx_at_point(p_point);
|
||||||
|
|
||||||
ERR_FAIL_INDEX(hover_now, tabs.size());
|
Dictionary d = p_data;
|
||||||
|
if (!d.has("type"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (String(d["type"]) == "tab_element") {
|
||||||
|
|
||||||
|
int tab_from_id = d["tab_element"];
|
||||||
|
NodePath from_path = d["from_path"];
|
||||||
|
NodePath to_path = get_path();
|
||||||
|
if (from_path == to_path) {
|
||||||
|
if (hover_now < 0)
|
||||||
|
hover_now = get_tab_count() - 1;
|
||||||
|
move_tab(tab_from_id, hover_now);
|
||||||
emit_signal("reposition_active_tab_request", hover_now);
|
emit_signal("reposition_active_tab_request", hover_now);
|
||||||
|
set_current_tab(hover_now);
|
||||||
|
} else if (get_tabs_rearrange_group() != -1) {
|
||||||
|
// drag and drop between Tabs
|
||||||
|
Node *from_node = get_node(from_path);
|
||||||
|
Tabs *from_tabs = Object::cast_to<Tabs>(from_node);
|
||||||
|
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
|
||||||
|
if (tab_from_id >= from_tabs->get_tab_count())
|
||||||
|
return;
|
||||||
|
Tab moving_tab = from_tabs->tabs[tab_from_id];
|
||||||
|
if (hover_now < 0)
|
||||||
|
hover_now = get_tab_count();
|
||||||
|
tabs.insert(hover_now, moving_tab);
|
||||||
|
from_tabs->remove_tab(tab_from_id);
|
||||||
|
set_current_tab(hover_now);
|
||||||
|
emit_signal("tab_changed", hover_now);
|
||||||
|
_update_cache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Tabs::get_tab_idx_at_point(const Point2 &p_point) const {
|
int Tabs::get_tab_idx_at_point(const Point2 &p_point) const {
|
||||||
|
@ -817,6 +905,21 @@ bool Tabs::get_scrolling_enabled() const {
|
||||||
return scrolling_enabled;
|
return scrolling_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tabs::set_drag_to_rearrange_enabled(bool p_enabled) {
|
||||||
|
drag_to_rearrange_enabled = p_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tabs::get_drag_to_rearrange_enabled() const {
|
||||||
|
return drag_to_rearrange_enabled;
|
||||||
|
}
|
||||||
|
void Tabs::set_tabs_rearrange_group(int p_group_id) {
|
||||||
|
tabs_rearrange_group = p_group_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Tabs::get_tabs_rearrange_group() const {
|
||||||
|
return tabs_rearrange_group;
|
||||||
|
}
|
||||||
|
|
||||||
void Tabs::_bind_methods() {
|
void Tabs::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input);
|
ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input);
|
||||||
|
@ -842,6 +945,10 @@ void Tabs::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy);
|
ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy);
|
||||||
ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled);
|
ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled);
|
||||||
ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled);
|
ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &Tabs::set_drag_to_rearrange_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &Tabs::get_drag_to_rearrange_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &Tabs::set_tabs_rearrange_group);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &Tabs::get_tabs_rearrange_group);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
|
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
|
||||||
ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
|
ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
|
||||||
|
@ -854,6 +961,7 @@ void Tabs::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
|
||||||
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
|
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
BIND_ENUM_CONSTANT(ALIGN_LEFT);
|
||||||
BIND_ENUM_CONSTANT(ALIGN_CENTER);
|
BIND_ENUM_CONSTANT(ALIGN_CENTER);
|
||||||
|
@ -884,4 +992,6 @@ Tabs::Tabs() {
|
||||||
scrolling_enabled = true;
|
scrolling_enabled = true;
|
||||||
buttons_visible = false;
|
buttons_visible = false;
|
||||||
hover = -1;
|
hover = -1;
|
||||||
|
drag_to_rearrange_enabled = false;
|
||||||
|
tabs_rearrange_group = -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ private:
|
||||||
int hover; // hovered tab
|
int hover; // hovered tab
|
||||||
int min_width;
|
int min_width;
|
||||||
bool scrolling_enabled;
|
bool scrolling_enabled;
|
||||||
|
bool drag_to_rearrange_enabled;
|
||||||
|
int tabs_rearrange_group;
|
||||||
|
|
||||||
int get_tab_width(int p_idx) const;
|
int get_tab_width(int p_idx) const;
|
||||||
void _ensure_no_over_offset();
|
void _ensure_no_over_offset();
|
||||||
|
@ -143,6 +145,11 @@ public:
|
||||||
void set_scrolling_enabled(bool p_enabled);
|
void set_scrolling_enabled(bool p_enabled);
|
||||||
bool get_scrolling_enabled() const;
|
bool get_scrolling_enabled() const;
|
||||||
|
|
||||||
|
void set_drag_to_rearrange_enabled(bool p_enabled);
|
||||||
|
bool get_drag_to_rearrange_enabled() const;
|
||||||
|
void set_tabs_rearrange_group(int p_group_id);
|
||||||
|
int get_tabs_rearrange_group() const;
|
||||||
|
|
||||||
void ensure_tab_visible(int p_idx);
|
void ensure_tab_visible(int p_idx);
|
||||||
void set_min_width(int p_width);
|
void set_min_width(int p_width);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue