gduibasics/scenes/scripts/flexview_window.gd
2021-08-21 17:15:07 +02:00

142 lines
3.7 KiB
GDScript

extends WindowDialog
const FlexView = preload("res://addons/de.mewin.gduibasics/scenes/scripts/flexview.gd")
var flex_view : FlexView setget _set_flex_view, _get_flex_view
var __drop_target : FlexView = null
var __is_dragging := false
#############
# overrides #
#############
func _ready() -> void:
set_process(false) # only used to stop dropping when mouse button is lifted
__update_title()
func _process(delta : float) -> void:
if !Input.is_mouse_button_pressed(BUTTON_LEFT):
__drop()
func _input(event : InputEvent) -> void:
if event is InputEventKey && event.scancode == KEY_SHIFT && __is_dragging:
__update_dragging()
#################
# private stuff #
#################
func __update_view_count() -> void:
var child := __get_flex_child()
if !(child is FlexView):
return
var count : int = child.get_view_count()
if count == 0:
self.queue_free()
return
else:
# child.show_tabs = (count > 1)
pass
func __update_dragging() -> void:
var child := __get_flex_child()
if !(child is FlexView) || child.get_view_count() > 1:
set_process(false)
__is_dragging = false
return
__is_dragging = true
set_process(true)
# dragging with shift disables dropping
if Input.is_key_pressed(KEY_SHIFT):
__set_drop_target(null)
return
var mouse_pos := get_viewport().get_mouse_position()
var flex_views := get_tree().get_nodes_in_group(FlexView.GROUP_NAME)
var views_under_cursor := []
for view in flex_views:
if !self.is_a_parent_of(view) && view.visible && view.get_global_rect().has_point(mouse_pos):
views_under_cursor.append(view)
if views_under_cursor.empty():
__set_drop_target(null)
return
# find first in tree
var target : FlexView = views_under_cursor[0]
for i in range(1, views_under_cursor.size()):
var node : FlexView = views_under_cursor[i]
if GDBUtility.control_is_in_front_of(node, target):
target = node
__set_drop_target(target)
func __set_drop_target(target : FlexView) -> void:
if target == __drop_target:
return
set_process(is_instance_valid(__drop_target)) # process to check if mouse button is lifted
if is_instance_valid(__drop_target):
__drop_target._stop_dropping()
__drop_target = target
if is_instance_valid(__drop_target):
__drop_target._start_dropping()
func __drop() -> void:
var child := __get_flex_child()
set_process(false)
__is_dragging = false
if !is_instance_valid(__drop_target) || !(child is FlexView) || child.get_view_count() != 1:
return
var control : Control = child.get_view_control(0)
child.remove_view(0)
__drop_target._drop(control)
self.queue_free()
func __update_title() -> void:
var child := __get_flex_child()
if !(child is FlexView):
window_title = ""
elif child.get_view_count() > 0:
window_title = child.get_view_title(child.current_view)
func __get_flex_child() -> Control:
return get_child(1) as Control # TODO: something better (and safer) than a fixed index
func __close_requested() -> void:
for flex_view in GDBUtility.find_nodes_by_type(self, FlexView):
flex_view.close_all_views()
#####################
# setters & getters #
#####################
func _set_flex_view(val) -> void:
assert(0, "Cannot set this.")
func _get_flex_view() -> FlexView:
return $flex_view as FlexView
###################
# signal handlers #
###################
func _on_flex_view_view_added(view : int, flex_view : FlexView) -> void:
__update_view_count()
func _on_flex_view_view_removed(view : int, flex_view : FlexView) -> void:
__update_view_count()
func _on_flexview_window_item_rect_changed() -> void:
__update_dragging()
func _on_flex_view_current_view_changed(flex_view : FlexView):
__update_title()
func _on_flexview_window_visibility_changed():
if !visible:
__close_requested()
visible = true