Godot-Simple-TODO/addons/SimpleTODO/TODOItem.gd
Nukiloco 2e4ac956da
Added item and column dragging (#1)
* Added item and column dragging

* Fixed layout saving issues

* Fixed deleting items

* Fixed some of the requested changes
2022-07-19 11:19:37 +02:00

184 lines
6.0 KiB
GDScript

tool
extends HBoxContainer
onready var text_field = $Text
onready var label_hack = $Text/HackLabel
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:
delete_item()
func request_save() -> void:
get_tree().get_nodes_in_group("__todo_plugin__").front().save_data()
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()