175 lines
4.7 KiB
GDScript
175 lines
4.7 KiB
GDScript
extends Control
|
|
|
|
enum CloseButtonPolicy {
|
|
SHOW_NEVER = 0,
|
|
SHOW_ACTIVE_ONLY = 1,
|
|
SHOW_ALWAYS = 2
|
|
}
|
|
|
|
enum TabAlign {
|
|
ALIGN_LEFT = 0,
|
|
ALIGN_CENTER = 1,
|
|
ALIGN_RIGHT = 2
|
|
}
|
|
|
|
export var current_tab := 0 setget _set_current_tab, _get_current_tab
|
|
export var drag_to_rearrange_enabled := false setget _set_drag_to_rearrange_enabled
|
|
export var drag_out_enabled := false
|
|
export var show_tabs := true setget _set_show_tabs
|
|
export(CloseButtonPolicy) var tab_close_display_policy := CloseButtonPolicy.SHOW_NEVER setget _set_tab_close_display_policy
|
|
export(TabAlign) var tab_align := TabAlign.ALIGN_CENTER setget _set_tab_align
|
|
|
|
var __mouse_was_inside := false
|
|
|
|
#############
|
|
# overrides #
|
|
#############
|
|
func _ready() -> void:
|
|
$tabs.connect("tab_changed", self, "_on_tabs_tab_changed")
|
|
$tabs.connect("tab_close", self, "_on_tabs_tab_close")
|
|
$tabs.connect("reposition_active_tab_request", self, "_on_tabs_reposition_active_tab_request")
|
|
$tabs.connect("gui_input", self, "_on_tabs_gui_input")
|
|
|
|
set_process(false) # only enabled for dragging
|
|
|
|
func _process(delta : float) -> void:
|
|
if !Input.is_mouse_button_pressed(BUTTON_LEFT):
|
|
__stop_tab_dragging()
|
|
return
|
|
var mouse_pos := get_viewport().get_mouse_position()
|
|
var mouse_is_inside : bool = $tabs.get_global_rect().has_point(mouse_pos)
|
|
if mouse_is_inside == __mouse_was_inside:
|
|
return
|
|
__mouse_was_inside = mouse_is_inside
|
|
if mouse_is_inside:
|
|
emit_signal("tab_dragged_in", _get_current_tab(), mouse_pos)
|
|
else:
|
|
emit_signal("tab_dragged_out", _get_current_tab(), mouse_pos)
|
|
|
|
################
|
|
# public stuff #
|
|
################
|
|
func add_tab(title : String, control : Control, icon : Texture = null) -> int:
|
|
$tabs.add_tab(title, icon)
|
|
$container.add_child(control)
|
|
|
|
var tab := control.get_position_in_parent()
|
|
emit_signal("tab_added", tab)
|
|
return tab
|
|
|
|
func move_tab(from : int, to : int) -> void:
|
|
$tabs.move_tab(from, to)
|
|
$container.move_child($container.get_child(from), to)
|
|
|
|
func remove_tab(tab : int) -> void:
|
|
if tab == current_tab && __is_tab_dragging():
|
|
__stop_tab_dragging()
|
|
|
|
$tabs.remove_tab(tab)
|
|
$container.remove_child($container.get_child(tab))
|
|
emit_signal("tab_removed", tab)
|
|
|
|
func find_tab(control : Control) -> int:
|
|
for tab in range(get_tab_count()):
|
|
if get_tab_control(tab) == control:
|
|
return tab
|
|
return -1
|
|
|
|
func remove_all_tabs() -> void:
|
|
while $tabs.get_tab_count() > 0:
|
|
$tabs.remove_tab(0)
|
|
while $container.get_child_count() > 0:
|
|
$container.remove_child($container.get_child(0))
|
|
|
|
func get_tab_control(tab : int) -> Control:
|
|
return $container.get_tab_control(tab)
|
|
|
|
func get_tab_title(tab : int) -> String:
|
|
return $tabs.get_tab_title(tab)
|
|
|
|
func get_tabs() -> Array:
|
|
return $container.get_children()
|
|
|
|
func get_tab_count() -> int:
|
|
return $container.get_child_count()
|
|
|
|
func get_tab_rect(tab : int) -> Rect2:
|
|
var rect : Rect2 = $tabs.get_tab_rect(tab)
|
|
return $tabs.get_transform().xform_inv(rect)
|
|
|
|
#################
|
|
# private stuff #
|
|
#################
|
|
func __handle_tabs_gui_input(event : InputEvent) -> void:
|
|
if drag_out_enabled \
|
|
&& event is InputEventMouseButton \
|
|
&& event.pressed \
|
|
&& event.button_index == BUTTON_LEFT:
|
|
yield(get_tree(), "idle_frame") # wait for the original control to handle the input
|
|
|
|
var tab_rect : Rect2 = $tabs.get_tab_rect(_get_current_tab())
|
|
if tab_rect.has_point(event.position):
|
|
__start_tab_dragging()
|
|
|
|
func __start_tab_dragging() -> void:
|
|
__mouse_was_inside = true
|
|
set_process(true)
|
|
|
|
func __stop_tab_dragging() -> void:
|
|
set_process(false)
|
|
|
|
func __is_tab_dragging() -> bool:
|
|
return is_processing()
|
|
|
|
###########
|
|
# setters #
|
|
###########
|
|
func _set_current_tab(tab : int) -> void:
|
|
current_tab = tab
|
|
$tabs.current_tab = current_tab
|
|
|
|
func _get_current_tab() -> int:
|
|
return $tabs.current_tab
|
|
|
|
func _set_drag_to_rearrange_enabled(enabled : bool) -> void:
|
|
drag_to_rearrange_enabled = enabled
|
|
$tabs.drag_to_rearrange_enabled = enabled
|
|
|
|
func _set_tab_close_display_policy(policy : int) -> void:
|
|
tab_close_display_policy = policy
|
|
$tabs.tab_close_display_policy = policy
|
|
|
|
func _set_tab_align(align : int) -> void:
|
|
tab_align = align
|
|
$tabs.tab_align = align
|
|
|
|
func _set_show_tabs(show : bool) -> void:
|
|
show_tabs = show
|
|
$tabs.visible = show
|
|
|
|
###################
|
|
# signal handlers #
|
|
###################
|
|
func _on_tabs_tab_changed(tab : int) -> void:
|
|
current_tab = tab
|
|
$container.current_tab = tab
|
|
|
|
func _on_tabs_tab_close(tab : int) -> void:
|
|
emit_signal("tab_close", tab)
|
|
|
|
func _on_tabs_reposition_active_tab_request(to : int) -> void:
|
|
$container.move_child($container.get_child(_get_current_tab()), to)
|
|
current_tab = to
|
|
|
|
func _on_tabs_gui_input(event : InputEvent) -> void:
|
|
__handle_tabs_gui_input(event)
|
|
|
|
###########
|
|
# signals #
|
|
###########
|
|
signal tab_added(tab)
|
|
signal tab_removed(tab)
|
|
signal tab_close(tab)
|
|
signal tab_dragged_out(tab, position)
|
|
signal tab_dragged_in(tab, position)
|