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