From 2e4ac956da179f26afb31d688ee9ae5edd7fb4a5 Mon Sep 17 00:00:00 2001 From: Nukiloco Date: Tue, 19 Jul 2022 02:19:37 -0700 Subject: [PATCH] Added item and column dragging (#1) * Added item and column dragging * Fixed layout saving issues * Fixed deleting items * Fixed some of the requested changes --- addons/SimpleTODO/ItemPlacementHolder.tscn | 18 +++ addons/SimpleTODO/SimpleTODO.gd | 23 ++- addons/SimpleTODO/TODO.gd | 22 ++- addons/SimpleTODO/TODO.tscn | 23 ++- addons/SimpleTODO/TODOColumn.gd | 154 ++++++++++++++++--- addons/SimpleTODO/TODOColumn.tscn | 73 +++++---- addons/SimpleTODO/TODOItem.gd | 168 ++++++++++++++++++++- addons/SimpleTODO/TODOItem.tscn | 26 ++-- 8 files changed, 430 insertions(+), 77 deletions(-) create mode 100644 addons/SimpleTODO/ItemPlacementHolder.tscn diff --git a/addons/SimpleTODO/ItemPlacementHolder.tscn b/addons/SimpleTODO/ItemPlacementHolder.tscn new file mode 100644 index 0000000..506650a --- /dev/null +++ b/addons/SimpleTODO/ItemPlacementHolder.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=2] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0.529412, 0.529412, 0.529412, 0.529412 ) +border_width_left = 4 +border_width_top = 4 +border_width_right = 4 +border_width_bottom = 4 +border_color = Color( 0, 0.741176, 1, 1 ) +corner_radius_top_left = 16 +corner_radius_top_right = 16 +corner_radius_bottom_right = 16 +corner_radius_bottom_left = 16 + +[node name="ItemPlacementHolder" type="Panel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +custom_styles/panel = SubResource( 1 ) diff --git a/addons/SimpleTODO/SimpleTODO.gd b/addons/SimpleTODO/SimpleTODO.gd index f4c9bf0..c872071 100644 --- a/addons/SimpleTODO/SimpleTODO.gd +++ b/addons/SimpleTODO/SimpleTODO.gd @@ -22,10 +22,30 @@ func _enter_tree(): get_editor_interface().get_editor_viewport().add_child(todo_screen) load_data() + print("TODO loaded") func _ready() -> void: set_process_input(false) +func set_window_layout(configuration: ConfigFile): + if configuration.has_section("SimpleTODO"): + var minimized_tabs = configuration.get_value("SimpleTODO", "minimized_tabs") + + if minimized_tabs.size() <= 0: + return + + for i in todo_screen.column_container.get_child_count(): + var column = todo_screen.column_container.get_children()[i] + column.minimized = minimized_tabs[i] + +func get_window_layout(configuration: ConfigFile): + var new_minimized_tabs = [] + + for column in todo_screen.column_container.get_children(): + new_minimized_tabs.append(column.minimized) + + configuration.set_value("SimpleTODO", "minimized_tabs", new_minimized_tabs) + func _exit_tree(): todo_screen.queue_free() @@ -70,7 +90,7 @@ func load_data(): for section in data.get_sections(): var column = todo_screen.add_column() column.name_edit.text = section - + for item in data.get_section_keys(section): if item == "__none__": continue @@ -81,4 +101,3 @@ func load_data(): todo_screen.undo_redo.clear_history() is_loading = false - print("TODO loaded") diff --git a/addons/SimpleTODO/TODO.gd b/addons/SimpleTODO/TODO.gd index 23d474d..3c45998 100644 --- a/addons/SimpleTODO/TODO.gd +++ b/addons/SimpleTODO/TODO.gd @@ -1,16 +1,28 @@ tool -extends VBoxContainer - -onready var column_container = $ScrollContainer/Columns +extends Control +onready var column_container = $VBoxContainer/ScrollContainer/Columns +onready var vbox_container = $VBoxContainer +var item_placement_holder: Panel var undo_redo: UndoRedo func _ready() -> void: + item_placement_holder = create_drag_placement_holder() + undo_redo = UndoRedo.new() +func create_drag_placement_holder() -> Panel: + var new_holder = preload("res://addons/SimpleTODO/ItemPlacementHolder.tscn").instance() + new_holder.visible = false + add_child(new_holder) + + return new_holder + func add_column(from_button := false) -> Control: var column = preload("res://addons/SimpleTODO/TODOColumn.tscn").instance() + column.main = self column.undo_redo = undo_redo + column.connect("delete", self, "delete_column", [column]) undo_redo.create_action("Add Column") @@ -22,8 +34,8 @@ func add_column(from_button := false) -> Control: undo_redo.commit_action() if from_button: - column.get_node("VBoxContainer/HBoxContainer2/Name").call_deferred("grab_focus") - column.get_node("VBoxContainer/HBoxContainer2/Name").call_deferred("select_all") + column.name_edit.call_deferred("grab_focus") + column.name_edit.call_deferred("select_all") return column diff --git a/addons/SimpleTODO/TODO.tscn b/addons/SimpleTODO/TODO.tscn index a4df0d4..1e61c18 100644 --- a/addons/SimpleTODO/TODO.tscn +++ b/addons/SimpleTODO/TODO.tscn @@ -2,21 +2,28 @@ [ext_resource path="res://addons/SimpleTODO/TODO.gd" type="Script" id=1] -[node name="TODO" type="VBoxContainer"] +[node name="TODO" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_clip_content = true +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource( 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 size_flags_horizontal = 3 size_flags_vertical = 3 -script = ExtResource( 1 ) __meta__ = { -"_edit_use_anchors_": false +"_editor_description_": "" } -[node name="PanelContainer" type="PanelContainer" parent="."] +[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"] margin_right = 1024.0 margin_bottom = 34.0 -[node name="Button" type="Button" parent="PanelContainer"] +[node name="Button" type="Button" parent="VBoxContainer/PanelContainer"] margin_left = 467.0 margin_top = 7.0 margin_right = 556.0 @@ -24,16 +31,16 @@ margin_bottom = 27.0 size_flags_horizontal = 4 text = "Add column" -[node name="ScrollContainer" type="ScrollContainer" parent="."] +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] margin_top = 38.0 margin_right = 1024.0 margin_bottom = 600.0 size_flags_vertical = 3 -[node name="Columns" type="HBoxContainer" parent="ScrollContainer"] +[node name="Columns" type="HBoxContainer" parent="VBoxContainer/ScrollContainer"] margin_right = 1024.0 margin_bottom = 562.0 size_flags_horizontal = 3 size_flags_vertical = 3 -[connection signal="pressed" from="PanelContainer/Button" to="." method="add_column" binds= [ true ]] +[connection signal="pressed" from="VBoxContainer/PanelContainer/Button" to="." method="add_column" binds= [ true ]] diff --git a/addons/SimpleTODO/TODOColumn.gd b/addons/SimpleTODO/TODOColumn.gd index 920b282..694efa9 100644 --- a/addons/SimpleTODO/TODOColumn.gd +++ b/addons/SimpleTODO/TODOColumn.gd @@ -1,27 +1,76 @@ tool extends PanelContainer -onready var name_edit = $VBoxContainer/HBoxContainer2/Name +onready var head = $VBoxContainer/Head +onready var top_separator = $VBoxContainer/TopSeparator +onready var bottom_separator = $VBoxContainer/BottomSeparator +onready var scroll_container = $VBoxContainer/ScrollContainer +onready var actions = $VBoxContainer/Actions +onready var minimize_button = $VBoxContainer/Head/Minimize +onready var name_edit = $VBoxContainer/Head/Name onready var item_container = $VBoxContainer/ScrollContainer/Items -onready var counter = $VBoxContainer/HBoxContainer2/Counter -onready var delete_button = $VBoxContainer/HBoxContainer/DeleteColumn +onready var counter = $VBoxContainer/Head/Counter +onready var delete_button = $VBoxContainer/Actions/DeleteColumn onready var timer = $Timer - var undo_redo: UndoRedo +var minimized = false setget set_minimized +var main: Control +var item_placement_holder: Panel +var is_dragging = false +var initial_item_index = 0 +var current_drag_item_index = 0 +var item_margin = 20 + +func set_minimized(val): + minimized = val + + var new_text = "V" + + if !val: + new_text = "^" + + minimize_button.text = new_text + + top_separator.visible = !val + scroll_container.visible = !val + bottom_separator.visible = !val + actions.visible = !val signal delete func _ready() -> void: + set_process(false) + item_placement_holder = main.item_placement_holder delete_button.icon = get_icon("Remove", "EditorIcons") counter.rect_min_size.x = delete_button.get_minimum_size().x + set_minimized(false) + +func _process(_delta): + if is_dragging: + var mouse_position = main.get_local_mouse_position() + + var item_under_mouse = main.column_container.get_column_from_mouse_position() + if item_under_mouse: + if item_under_mouse: + var item_index = item_under_mouse.get_index() + + if main.column_container != item_placement_holder.get_parent(): + item_placement_holder.get_parent().remove_child(item_placement_holder) + main.column_container.add_child(item_placement_holder) + + item_placement_holder.get_parent().move_child(item_placement_holder, item_index) + + current_drag_item_index = item_index + + rect_position = mouse_position func add_item(from_button := false) -> Control: var item = preload("res://addons/SimpleTODO/TODOItem.tscn").instance() - item.connect("delete", self, "delete_item", [item]) - + item.parent_column = self + item.main = main + undo_redo.create_action("Add Item") undo_redo.add_do_method(item_container, "add_child", item) - undo_redo.add_do_method(item, "add_child", item) undo_redo.add_do_reference(item) undo_redo.add_do_method(self, "request_save") undo_redo.add_undo_method(item_container, "remove_child", item) @@ -34,21 +83,90 @@ func add_item(from_button := false) -> Control: return item -func delete_item(item): - undo_redo.create_action("Delete Item") - undo_redo.add_do_method(item_container, "remove_child", item) - undo_redo.add_do_method(self, "request_save") - undo_redo.add_undo_method(item_container, "add_child", item) - undo_redo.add_undo_reference(item) - undo_redo.add_undo_method(self, "request_save") - undo_redo.commit_action() - func delete_column() -> void: emit_signal("delete") -func request_save() -> void: +func update_counter() -> void: counter.text = str(item_container.get_child_count()) + +func request_save() -> void: get_tree().get_nodes_in_group("__todo_plugin__").front().save_data() -func name_changed(new_text: String) -> void: +func name_changed(_new_text: String) -> void: timer.start() + +func _on_Minimize_pressed(): + set_minimized(!minimized) + +# Handles left click being pressed on the drag panel +func _on_DragPanel_gui_input(event): + if event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT and event.pressed and !is_dragging: + initial_item_index = get_index() + + get_parent().remove_child(self) + + # Set the size vertical flags to none so that it doesn't stretch + # when being dragged + size_flags_vertical = SIZE_FILL + + main.add_child(self) + + set_process(true) + + # Set dragging to true to tell _process to now handle dragging + is_dragging = true + + item_placement_holder.get_parent().remove_child(item_placement_holder) + + main.column_container.add_child(item_placement_holder) + + item_placement_holder.size_flags_vertical = 0 + item_placement_holder.visible = true + item_placement_holder.rect_min_size = rect_size + item_placement_holder.rect_size = rect_size + +# Handles left click being released +func _input(event): + if event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT and !event.pressed and is_dragging: + set_process(false) + + is_dragging = false + + get_parent().remove_child(self) + + size_flags_vertical = SIZE_EXPAND + + rect_size = Vector2.ZERO + + if item_placement_holder: + item_placement_holder.size_flags_vertical = SIZE_FILL + item_placement_holder.visible = false + item_placement_holder.get_parent().remove_child(item_placement_holder) + main.add_child(item_placement_holder) + + main.column_container.add_child(self) + + move_column(current_drag_item_index) + + current_drag_item_index = 0 + initial_item_index = 0 + +func move_column(index): + undo_redo.create_action("Move Column") + + var current_index = initial_item_index + + undo_redo.add_do_method(main.column_container, "move_child", self, index) + undo_redo.add_do_method(self, "request_save") + undo_redo.add_undo_method(main.column_container, "move_child", self, current_index) + undo_redo.add_undo_method(self, "request_save") + + undo_redo.commit_action() + +func _on_Items_child_entered_tree(node): + update_counter() + +func _on_Items_child_exited_tree(node): + update_counter() diff --git a/addons/SimpleTODO/TODOColumn.tscn b/addons/SimpleTODO/TODOColumn.tscn index 6e0e137..7185966 100644 --- a/addons/SimpleTODO/TODOColumn.tscn +++ b/addons/SimpleTODO/TODOColumn.tscn @@ -13,7 +13,7 @@ corner_radius_top_right = 4 corner_radius_bottom_right = 4 corner_radius_bottom_left = 4 -[sub_resource type="Image" id=4] +[sub_resource type="Image" id=6] data = { "data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), "format": "LumAlpha8", @@ -22,50 +22,60 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id=2] +[sub_resource type="ImageTexture" id=5] flags = 4 flags = 4 -image = SubResource( 4 ) +image = SubResource( 6 ) size = Vector2( 16, 16 ) [node name="TODOColumn" type="PanelContainer"] margin_right = 400.0 -margin_bottom = 480.0 +margin_bottom = 78.0 rect_min_size = Vector2( 400, 0 ) -size_flags_vertical = 0 +size_flags_vertical = 2 custom_styles/panel = SubResource( 3 ) script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="VBoxContainer" type="VBoxContainer" parent="."] margin_left = 4.0 margin_top = 4.0 margin_right = 396.0 -margin_bottom = 476.0 +margin_bottom = 74.0 rect_min_size = Vector2( 200, 0 ) -[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"] +[node name="Head" type="HBoxContainer" parent="VBoxContainer"] margin_right = 392.0 margin_bottom = 24.0 -[node name="Name" type="LineEdit" parent="VBoxContainer/HBoxContainer2"] -margin_right = 360.0 +[node name="DragPanel" type="Panel" parent="VBoxContainer/Head"] +margin_right = 20.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 20, 0 ) +mouse_default_cursor_shape = 13 + +[node name="Name" type="LineEdit" parent="VBoxContainer/Head"] +margin_left = 24.0 +margin_right = 337.0 margin_bottom = 24.0 size_flags_horizontal = 3 text = "Column name" -[node name="Counter" type="Label" parent="VBoxContainer/HBoxContainer2"] -margin_left = 364.0 +[node name="Counter" type="Label" parent="VBoxContainer/Head"] +margin_left = 341.0 margin_top = 5.0 -margin_right = 392.0 +margin_right = 369.0 margin_bottom = 19.0 rect_min_size = Vector2( 28, 0 ) text = "0" align = 1 -[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +[node name="Minimize" type="Button" parent="VBoxContainer/Head"] +margin_left = 373.0 +margin_right = 392.0 +margin_bottom = 24.0 +text = "^" + +[node name="TopSeparator" type="HSeparator" parent="VBoxContainer"] margin_top = 28.0 margin_right = 392.0 margin_bottom = 32.0 @@ -73,46 +83,49 @@ margin_bottom = 32.0 [node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] margin_top = 36.0 margin_right = 392.0 -margin_bottom = 438.0 +margin_bottom = 36.0 size_flags_vertical = 3 scroll_horizontal_enabled = false scroll_vertical_enabled = false [node name="Items" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"] margin_right = 392.0 -margin_bottom = 402.0 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"] -margin_top = 442.0 +[node name="BottomSeparator" type="HSeparator" parent="VBoxContainer"] +margin_top = 40.0 margin_right = 392.0 -margin_bottom = 446.0 +margin_bottom = 44.0 -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -margin_top = 450.0 +[node name="Actions" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 48.0 margin_right = 392.0 -margin_bottom = 472.0 +margin_bottom = 70.0 -[node name="AddItem" type="Button" parent="VBoxContainer/HBoxContainer"] +[node name="AddItem" type="Button" parent="VBoxContainer/Actions"] margin_right = 360.0 margin_bottom = 22.0 hint_tooltip = "Add item" size_flags_horizontal = 3 text = "+" -[node name="DeleteColumn" type="Button" parent="VBoxContainer/HBoxContainer"] +[node name="DeleteColumn" type="Button" parent="VBoxContainer/Actions"] margin_left = 364.0 margin_right = 392.0 margin_bottom = 22.0 hint_tooltip = "Delete column" -icon = SubResource( 2 ) +icon = SubResource( 5 ) [node name="Timer" type="Timer" parent="."] wait_time = 0.5 one_shot = true -[connection signal="text_changed" from="VBoxContainer/HBoxContainer2/Name" to="." method="name_changed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/AddItem" to="." method="add_item" binds= [ true ]] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/DeleteColumn" to="." method="delete_column"] +[connection signal="gui_input" from="VBoxContainer/Head/DragPanel" to="." method="_on_DragPanel_gui_input"] +[connection signal="text_changed" from="VBoxContainer/Head/Name" to="." method="name_changed"] +[connection signal="pressed" from="VBoxContainer/Head/Minimize" to="." method="_on_Minimize_pressed"] +[connection signal="child_entered_tree" from="VBoxContainer/ScrollContainer/Items" to="." method="_on_Items_child_entered_tree"] +[connection signal="child_exited_tree" from="VBoxContainer/ScrollContainer/Items" to="." method="_on_Items_child_exited_tree"] +[connection signal="pressed" from="VBoxContainer/Actions/AddItem" to="." method="add_item" binds= [ true ]] +[connection signal="pressed" from="VBoxContainer/Actions/DeleteColumn" to="." method="delete_column"] [connection signal="timeout" from="Timer" to="." method="request_save"] diff --git a/addons/SimpleTODO/TODOItem.gd b/addons/SimpleTODO/TODOItem.gd index 7b39ee0..c1a61bf 100644 --- a/addons/SimpleTODO/TODOItem.gd +++ b/addons/SimpleTODO/TODOItem.gd @@ -3,15 +3,28 @@ extends HBoxContainer onready var text_field = $Text onready var label_hack = $Text/HackLabel - -signal delete +var item_placement_holder: Panel +var main: Control +var undo_redo: UndoRedo +var initial_item_index = 0 +# The main TODO scene column container node +var main_column_container: HBoxContainer +var parent_column: PanelContainer +var next_parent_column: PanelContainer +var current_drag_item_index = 0 +var is_dragging = false +var item_margin = 20 func _ready() -> void: + undo_redo = main.undo_redo + item_placement_holder = main.item_placement_holder + next_parent_column = parent_column + get_node("Button").icon = get_icon("Remove", "EditorIcons") call_deferred("text_changed") func delete_pressed() -> void: - emit_signal("delete") + delete_item() func request_save() -> void: get_tree().get_nodes_in_group("__todo_plugin__").front().save_data() @@ -19,3 +32,152 @@ func request_save() -> void: func text_changed() -> void: label_hack.text = text_field.text text_field.rect_min_size.y = label_hack.get_minimum_size().y + 8 + +func _process(_delta): + if is_dragging: + var mouse_position = main.get_local_mouse_position() + + var item_under_mouse = get_column_item_from_mouse_position() + if item_under_mouse: + var column = item_under_mouse.column + var column_items = column.item_container + var item = item_under_mouse.item + next_parent_column = column + + if column_items != item_placement_holder.get_parent(): + item_placement_holder.get_parent().remove_child(item_placement_holder) + column_items.add_child(item_placement_holder) + + if item: + var item_index = item.get_index() + item_placement_holder.get_parent().move_child(item_placement_holder, item_index) + current_drag_item_index = item_index + elif column_items.get_child_count() <= 0: + item_placement_holder.get_parent().move_child(item_placement_holder, 0) + current_drag_item_index = 0 + + rect_position = mouse_position + +func get_column_from_mouse_position() -> PanelContainer: + var mouse_position = main.column_container.get_local_mouse_position() + + for i in main.column_container.get_child_count(): + var child = main.column_container.get_child(i) + var rect: Rect2 = child.get_rect() + + if rect.has_point(Vector2(mouse_position.x, 0)): + return child + return null + +func get_column_item_from_mouse_position(): + var column_under_mouse = get_column_from_mouse_position() + if column_under_mouse: + var column_items = column_under_mouse.item_container + var mouse_position = column_items.get_local_mouse_position() + + for i in column_items.get_child_count(): + var child: Control = column_items.get_child(i) + + var rect: Rect2 = child.get_rect() + var top_rect: Rect2 = Rect2(rect.position - Vector2(0, item_margin), Vector2(rect.size.x, item_margin)) + var bottom_rect: Rect2 = Rect2(rect.position + Vector2(0, item_margin), Vector2(rect.size.x, item_margin)) + + if top_rect.has_point(mouse_position) and i <= 0: + return {"item": child, "column": column_under_mouse} + + if bottom_rect.has_point(mouse_position): + return {"item": child, "column": column_under_mouse} + + # Likely we are dragging into a column with no items + return {"item": null, "column": column_under_mouse} + else: + return null + +# Handles left click being pressed on the drag panel +func _on_DragPanel_gui_input(event): + if event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT and event.pressed and !is_dragging: + initial_item_index = get_index() + + get_parent().remove_child(self) + + parent_column.update_counter() + + rect_min_size = rect_size + + # Set the size vertical flags to none so that it doesn't stretch + # when being dragged + size_flags_vertical = 0 + + main.add_child(self) + + set_process(true) + + # Set dragging to true to tell _process to now handle dragging + is_dragging = true + + item_placement_holder.get_parent().remove_child(item_placement_holder) + parent_column.item_container.add_child(item_placement_holder) + item_placement_holder.get_parent().move_child(item_placement_holder, initial_item_index) + + item_placement_holder.visible = true + item_placement_holder.rect_min_size = rect_min_size + item_placement_holder.rect_size = rect_size + +# Handles left click being released +func _input(event): + if event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT and !event.pressed and is_dragging: + set_process(false) + + is_dragging = false + + get_parent().remove_child(self) + + size_flags_vertical = SIZE_FILL + + rect_min_size = Vector2.ZERO + + if item_placement_holder: + item_placement_holder.visible = false + item_placement_holder.get_parent().remove_child(item_placement_holder) + main.add_child(item_placement_holder) + + move_item(current_drag_item_index) + + current_drag_item_index = 0 + initial_item_index = 0 + +# Used for undo redo, if we can't remove this item then don't error out +func remove_self_safe(): + var parent = get_parent() + if parent: + parent.remove_child(self) + +func move_item(index): + undo_redo.create_action("Move Item") + + var current_index = initial_item_index + + undo_redo.add_do_method(self, "remove_self_safe") + undo_redo.add_do_method(next_parent_column.item_container, "add_child", self) + undo_redo.add_do_method(next_parent_column.item_container, "move_child", self, index) + undo_redo.add_do_method(next_parent_column, "request_save") + undo_redo.add_do_property(self, "parent_column", next_parent_column) + undo_redo.add_do_property(self, "next_parent_column", parent_column) + + undo_redo.add_undo_method(self, "remove_self_safe") + undo_redo.add_undo_method(parent_column.item_container, "add_child", self) + undo_redo.add_undo_method(parent_column.item_container, "move_child", self, current_index) + undo_redo.add_undo_method(parent_column, "request_save") + undo_redo.add_undo_property(self, "parent_column", parent_column) + + undo_redo.commit_action() + +func delete_item(): + undo_redo.create_action("Delete Item") + undo_redo.add_do_method(parent_column.item_container, "remove_child", self) + undo_redo.add_do_method(parent_column, "request_save") + undo_redo.add_undo_method(parent_column.item_container, "add_child", self) + undo_redo.add_undo_method(parent_column, "request_save") + undo_redo.commit_action() diff --git a/addons/SimpleTODO/TODOItem.tscn b/addons/SimpleTODO/TODOItem.tscn index eb5e179..6cedc48 100644 --- a/addons/SimpleTODO/TODOItem.tscn +++ b/addons/SimpleTODO/TODOItem.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://addons/SimpleTODO/TODOItem.gd" type="Script" id=1] -[sub_resource type="Image" id=3] +[sub_resource type="Image" id=6] data = { "data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), "format": "LumAlpha8", @@ -11,25 +11,31 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id=2] +[sub_resource type="ImageTexture" id=5] flags = 4 flags = 4 -image = SubResource( 3 ) +image = SubResource( 6 ) size = Vector2( 16, 16 ) [node name="TODOItem" type="HBoxContainer"] margin_right = 480.0 margin_bottom = 36.0 +mouse_filter = 2 script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} + +[node name="DragPanel" type="Panel" parent="."] +margin_right = 20.0 +margin_bottom = 36.0 +rect_min_size = Vector2( 20, 0 ) +mouse_default_cursor_shape = 13 [node name="Text" type="TextEdit" parent="."] +margin_left = 24.0 margin_right = 448.0 margin_bottom = 36.0 rect_min_size = Vector2( 0, 22 ) size_flags_horizontal = 3 +size_flags_vertical = 3 text = "TODO" wrap_enabled = true @@ -40,25 +46,23 @@ anchor_right = 0.5 anchor_bottom = 0.5 margin_left = -224.0 margin_top = 80.0 -margin_right = 122.0 +margin_right = 200.0 margin_bottom = 160.0 text = "TODO" autowrap = true -__meta__ = { -"_edit_use_anchors_": false -} [node name="Button" type="Button" parent="."] margin_left = 452.0 margin_right = 480.0 margin_bottom = 36.0 hint_tooltip = "Delete item" -icon = SubResource( 2 ) +icon = SubResource( 5 ) [node name="Timer" type="Timer" parent="."] wait_time = 0.5 one_shot = true +[connection signal="gui_input" from="DragPanel" to="." method="_on_DragPanel_gui_input"] [connection signal="text_changed" from="Text" to="." method="text_changed"] [connection signal="text_changed" from="Text" to="Timer" method="start"] [connection signal="pressed" from="Button" to="." method="delete_pressed"]