mirror of
https://github.com/Relintai/Godot-Simple-TODO.git
synced 2024-12-20 10:16:52 +01:00
Improvements
- Added column filter - Added "marker" functionality (right-click item's drag panel to toggle mark) - Column loading is deferred for better performance
This commit is contained in:
parent
8f0f90c7b7
commit
b35e5d9b8b
BIN
Media/ReadmeFilter.gif
Normal file
BIN
Media/ReadmeFilter.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
BIN
Media/ReadmeMarker.gif
Normal file
BIN
Media/ReadmeMarker.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
14
README.md
14
README.md
@ -4,15 +4,23 @@ This simple plugin that lets you take random notes and organize them in named co
|
||||
|
||||
Just enable it to get a new editor screen called "TODO" where you can create columns, where you can create random labels where you can put any text. Simple as that.
|
||||
|
||||
![](https://github.com/KoBeWi/Godot-Simple-TODO/blob/master/Media/ReadmeShowcase.gif)
|
||||
![](Media/ReadmeShowcase.gif)
|
||||
|
||||
The plugin has full undo support.
|
||||
|
||||
![](https://github.com/KoBeWi/Godot-Simple-TODO/blob/master/Media/ReadmeUndo.gif)
|
||||
![](Media/ReadmeUndo.gif)
|
||||
|
||||
And drag and drop support (contributed by [@Nukiloco](https://github.com/Nukiloco)).
|
||||
|
||||
![](https://github.com/KoBeWi/Godot-Simple-TODO/blob/master/Media/ReadmeDragAndDrop.gif)
|
||||
![](Media/ReadmeDragAndDrop.gif)
|
||||
|
||||
You can filter items.
|
||||
|
||||
![](Media/ReadmeFilter.gif)
|
||||
|
||||
There is also a simple "marker" function. You can right-click the item's drag field to leave a temporary visual marker. The marker is not saved, it's only meant to easier keep track of the item you are currently working on.
|
||||
|
||||
![](Media/ReadmeMarker.gif)
|
||||
|
||||
## Data
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
extends EditorPlugin
|
||||
|
||||
const DATA_FILE = "res://TODO.cfg"
|
||||
var pending_columns: Array[Control]
|
||||
|
||||
var todo_screen: Control
|
||||
var is_loading: bool
|
||||
|
||||
func _get_plugin_name():
|
||||
return "TODO"
|
||||
@ -22,11 +22,19 @@ func _enter_tree():
|
||||
|
||||
get_editor_interface().get_editor_main_screen().add_child(todo_screen)
|
||||
load_data()
|
||||
print("TODO loaded")
|
||||
|
||||
func _ready() -> void:
|
||||
set_process_input(false)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if pending_columns.is_empty():
|
||||
set_process(false)
|
||||
print("TODO loaded")
|
||||
return
|
||||
|
||||
var column = pending_columns.pop_front()
|
||||
todo_screen.column_container.add_child(column)
|
||||
|
||||
func _set_window_layout(configuration: ConfigFile):
|
||||
if configuration.has_section("SimpleTODO"):
|
||||
var minimized_tabs = configuration.get_value("SimpleTODO", "minimized_tabs")
|
||||
@ -68,9 +76,6 @@ func _input(event: InputEvent) -> void:
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
func save_data():
|
||||
if is_loading:
|
||||
return
|
||||
|
||||
var data := ConfigFile.new()
|
||||
for column in todo_screen.column_container.get_children():
|
||||
var section = column.header.name_edit.text
|
||||
@ -87,19 +92,15 @@ func load_data():
|
||||
var data := ConfigFile.new()
|
||||
data.load(DATA_FILE)
|
||||
|
||||
is_loading = true
|
||||
|
||||
for section in data.get_sections():
|
||||
var column = todo_screen.add_column()
|
||||
column.set_name(section)
|
||||
var column = todo_screen.create_column()
|
||||
column.ready.connect(column.set_title.bind(section))
|
||||
pending_columns.append(column)
|
||||
|
||||
for item in data.get_section_keys(section):
|
||||
if item == "__none__":
|
||||
continue
|
||||
|
||||
var column_item = column.add_item()
|
||||
column_item.text_field.text = data.get_value(section, item)
|
||||
column_item.id = item.to_int()
|
||||
|
||||
todo_screen.undo_redo.clear_history()
|
||||
is_loading = false
|
||||
var column_item = column.create_item()
|
||||
column_item.ready.connect(column_item.initialize.bind(data.get_value(section, item), item.to_int()), CONNECT_DEFERRED)
|
||||
column.ready.connect(column_item.add_to_column.bind(column))
|
||||
|
@ -9,11 +9,13 @@ var plugin: EditorPlugin
|
||||
|
||||
var undo_redo: UndoRedo
|
||||
var item_placement_holder: Panel
|
||||
var counter_queued: bool
|
||||
|
||||
func _ready() -> void:
|
||||
undo_redo = UndoRedo.new()
|
||||
item_placement_holder = create_drag_placement_holder()
|
||||
scroll_container.get_v_scroll_bar().value_changed.connect(update_mirror)
|
||||
update_full_counter()
|
||||
|
||||
func update_mirror(v: float):
|
||||
column_mirror.visible = v > column_mirror.get_child(0).size.y
|
||||
@ -29,13 +31,18 @@ func create_drag_placement_holder() -> Panel:
|
||||
|
||||
return new_holder
|
||||
|
||||
func add_column(from_button := false) -> Control:
|
||||
func create_column() -> Control:
|
||||
var column = preload("res://addons/SimpleTODO/TODOColumn.tscn").instantiate()
|
||||
column.main = self
|
||||
column.plugin = plugin
|
||||
column.undo_redo = undo_redo
|
||||
|
||||
column.delete.connect(delete_column.bind(column))
|
||||
column.counter_updated.connect(update_full_counter)
|
||||
return column
|
||||
|
||||
func add_column(from_button := false) -> Control:
|
||||
var column := create_column()
|
||||
|
||||
undo_redo.create_action("Add Column")
|
||||
undo_redo.add_do_method(column_container.add_child.bind(column))
|
||||
@ -67,3 +74,19 @@ func request_save() -> void:
|
||||
func refresh_mirrors():
|
||||
for column in column_container.get_children():
|
||||
column.update_mirror.call_deferred(0)
|
||||
|
||||
func filter_elements(new_text: String) -> void:
|
||||
for column in column_container.get_children():
|
||||
for item in column.item_container.get_children():
|
||||
item.filter(new_text)
|
||||
|
||||
func update_full_counter():
|
||||
if counter_queued:
|
||||
return
|
||||
counter_queued = true
|
||||
|
||||
_update_full_counter.call_deferred()
|
||||
|
||||
func _update_full_counter():
|
||||
%Total.text = str("Total: %d" % column_container.get_children().reduce(func(accum: int, column: Node) -> int: return accum + column.item_container.get_child_count(), 0))
|
||||
counter_queued = false
|
||||
|
@ -1,6 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://yf8y5e74vv4o"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODO.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODO.gd" id="1_wo5wb"]
|
||||
|
||||
[node name="TODO" type="Control"]
|
||||
clip_contents = true
|
||||
@ -12,7 +12,7 @@ grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1")
|
||||
script = ExtResource("1_wo5wb")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
@ -30,11 +30,40 @@ layout_mode = 2
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer"]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/PanelContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 100
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Total" type="Label" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
text = "Total: %d"
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "Add column"
|
||||
|
||||
[node name="MarginContainer3" type="MarginContainer" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/MarginContainer3"]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
placeholder_text = "Search Items"
|
||||
clear_button_enabled = true
|
||||
|
||||
[node name="ColumnMirror" type="Control" parent="VBoxContainer/PanelContainer/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
@ -52,4 +81,5 @@ layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/Button" to="." method="add_column" binds= [true]]
|
||||
[connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/MarginContainer2/Button" to="." method="add_column" binds= [true]]
|
||||
[connection signal="text_changed" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/MarginContainer3/LineEdit" to="." method="filter_elements"]
|
||||
|
@ -23,6 +23,7 @@ var current_drag_item_index := 0
|
||||
var item_margin := 20
|
||||
|
||||
signal delete
|
||||
signal counter_updated
|
||||
|
||||
func set_minimized(val: bool):
|
||||
minimized = val
|
||||
@ -67,7 +68,7 @@ func _ready() -> void:
|
||||
item_container.child_entered_tree.connect(update_counter.unbind(1), CONNECT_DEFERRED)
|
||||
item_container.child_exiting_tree.connect(update_counter.unbind(1), CONNECT_DEFERRED)
|
||||
|
||||
func set_name(column_name):
|
||||
func set_title(column_name):
|
||||
header.name_edit.text = column_name
|
||||
mirror_header.name_edit.text = column_name
|
||||
|
||||
@ -98,12 +99,16 @@ func _process(delta):
|
||||
|
||||
position = mouse_position
|
||||
|
||||
func add_item(from_button := false) -> Control:
|
||||
func create_item() -> Control:
|
||||
var item = preload("res://addons/SimpleTODO/TODOItem.tscn").instantiate()
|
||||
item.parent_column = self
|
||||
item.plugin = plugin
|
||||
item.main = main
|
||||
return item
|
||||
|
||||
func add_item(from_button := false) -> Control:
|
||||
var item := create_item()
|
||||
|
||||
undo_redo.create_action("Add Item")
|
||||
undo_redo.add_do_method(item_container.add_child.bind(item))
|
||||
undo_redo.add_do_reference(item)
|
||||
@ -124,6 +129,7 @@ func delete_column() -> void:
|
||||
func update_counter() -> void:
|
||||
header.counter.text = str(item_container.get_child_count())
|
||||
mirror_header.counter.text = str(item_container.get_child_count())
|
||||
counter_updated.emit()
|
||||
|
||||
func request_save() -> void:
|
||||
plugin.save_data()
|
||||
|
@ -1,7 +1,7 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://bga0tfe37uva2"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODOColumn.gd" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cwcwdmxxpf65e" path="res://addons/SimpleTODO/ColumnHeader.tscn" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODOColumn.gd" id="1_6bfuv"]
|
||||
[ext_resource type="PackedScene" uid="uid://cwcwdmxxpf65e" path="res://addons/SimpleTODO/ColumnHeader.tscn" id="2_0fkhl"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="3"]
|
||||
content_margin_left = 4.0
|
||||
@ -18,12 +18,12 @@ corner_radius_bottom_left = 4
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
size_flags_vertical = 2
|
||||
theme_override_styles/panel = SubResource("3")
|
||||
script = ExtResource("1")
|
||||
script = ExtResource("1_6bfuv")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Header" parent="VBoxContainer" instance=ExtResource("2")]
|
||||
[node name="Header" parent="VBoxContainer" instance=ExtResource("2_0fkhl")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
@tool
|
||||
extends HBoxContainer
|
||||
|
||||
@onready var text_field = $Text
|
||||
@onready var text_field: TextEdit = $Text
|
||||
@onready var button: Button = $Button
|
||||
|
||||
var main: Control
|
||||
@ -19,6 +19,7 @@ var is_dragging := false
|
||||
var item_margin := 20
|
||||
|
||||
var id: int
|
||||
var is_marked: bool
|
||||
|
||||
func _ready() -> void:
|
||||
undo_redo = main.undo_redo
|
||||
@ -99,7 +100,7 @@ func get_column_item_from_mouse_position() -> Dictionary:
|
||||
# Handles left click being pressed on the drag panel.
|
||||
func drag_panel_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed and !is_dragging:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed and not is_dragging:
|
||||
initial_item_index = get_index()
|
||||
get_parent().remove_child(self)
|
||||
main.add_child(self)
|
||||
@ -119,6 +120,13 @@ func drag_panel_input(event: InputEvent):
|
||||
item_placement_holder.visible = true
|
||||
item_placement_holder.custom_minimum_size = custom_minimum_size
|
||||
item_placement_holder.size = size
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
|
||||
if is_marked:
|
||||
$DragPanel.modulate = Color.WHITE
|
||||
is_marked = false
|
||||
else:
|
||||
$DragPanel.modulate = Color.RED
|
||||
is_marked = true
|
||||
|
||||
# Handles left click being released.
|
||||
func _input(event: InputEvent):
|
||||
@ -175,3 +183,16 @@ func delete_item():
|
||||
undo_redo.add_undo_method(parent_column.item_container.move_child.bind(self, get_index()))
|
||||
undo_redo.add_undo_method(parent_column.request_save)
|
||||
undo_redo.commit_action()
|
||||
|
||||
func filter(text: String):
|
||||
if text.is_empty() or text_field.text.contains(text):
|
||||
show()
|
||||
else:
|
||||
hide()
|
||||
|
||||
func initialize(text: String, p_id: int):
|
||||
text_field.text = text
|
||||
id = p_id
|
||||
|
||||
func add_to_column(column: Control):
|
||||
column.item_container.add_child(self)
|
||||
|
@ -1,14 +1,15 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bdesiystlxdb2"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODOItem.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://addons/SimpleTODO/TODOItem.gd" id="1_ecqce"]
|
||||
|
||||
[node name="TODOItem" type="HBoxContainer"]
|
||||
mouse_filter = 2
|
||||
script = ExtResource("1")
|
||||
script = ExtResource("1_ecqce")
|
||||
|
||||
[node name="DragPanel" type="Panel" parent="."]
|
||||
custom_minimum_size = Vector2(20, 0)
|
||||
layout_mode = 2
|
||||
tooltip_text = "Right-click to mark/unmark"
|
||||
mouse_default_cursor_shape = 13
|
||||
|
||||
[node name="Text" type="TextEdit" parent="."]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Simple TODO"
|
||||
description="Organize random notes in tabs."
|
||||
description="Organize random notes in columns."
|
||||
author="KoBeWi"
|
||||
version="1.4"
|
||||
version="1.5"
|
||||
script="SimpleTODO.gd"
|
Loading…
Reference in New Issue
Block a user