godot-control-tree/ControlTreeItem.gd
Lera Elvoé 08bbf61416
add a few things:
* test case with folders/subfolders
* renaming items by double-clicking them
* naive drag test
2022-10-24 22:20:01 +03:00

114 lines
3.0 KiB
GDScript

extends VBoxContainer
class_name ControlTreeItem
# the margin of the offset on the subitem (if this item is a subitem)
const SUBITEM_MARGIN_SIZE := 32
# if this property is true, the item can be interacted with
# e.g, it can be renamed, its checkmark can be ticked
var editable: bool = true
# proxy property for the CheckBox's `pressed` property
var checked: bool = false setget set_checked, is_checked
# if true, this item can be reordered in the tree
var draggable: bool = true
# an array of this item's subitems
var subitems: Array = []
# if true, this item's subitems will not be visible
var collapsed: bool = false
onready var subitem_margin_container: MarginContainer = $"%SubitemMargin"
onready var collapse_button: Button = $"%CollapseButton"
onready var drag_handle: Panel = $"%DragHandle"
onready var check_box: CheckBox = $"%CheckBox"
onready var item_text_button: Button = $"%ItemTextButton"
onready var subitem_container: VBoxContainer = $"%Subitems"
signal rename_allowed
func _ready() -> void:
# warning-ignore:return_value_discarded
# warning-ignore:return_value_discarded
# warning-ignore:return_value_discarded
# warning-ignore:return_value_discarded
check_box.connect("pressed", self, "set_enabled", [true])
collapse_button.connect("pressed", self, "toggle_collapsed")
item_text_button.connect("rename_request", self, "rename_request")
connect("rename_allowed", item_text_button, "create_lineedit")
func set_checked(v: bool, from_checkbox: bool = false) -> void:
checked = v
if from_checkbox: return
check_box.pressed = v
func is_checked() -> bool:
return checked
func set_text(t: String) -> void:
item_text_button.text = t
func get_text() -> String:
return item_text_button.text
func add_subitem(item: ControlTreeItem) -> void:
subitem_container.add_child(item)
subitems.append(item)
item.subitem_margin_container.visible = true
print('d: ', get_depth(item))
item.subitem_margin_container.rect_min_size.x = SUBITEM_MARGIN_SIZE * get_depth(item)# - (clamp(collapse_button.rect_size.x * subitems.size(), 0, 1))
collapse_button.visible = true
func set_button_group(bg: ButtonGroup) -> void:
item_text_button.group = bg
func get_depth(item: ControlTreeItem) -> int:
var depth := 0
# this is the stupidest hack ever to get around cyclic deps
# basically, you can't check if an object is of the same class
# as self, ie `Object is ControlTreeItem` will error out
# so instead we're making a stupid, idiotic method
# that only this class has and checking for its presence
while item.get_parent().get_parent().has_method("i_am_item"):
depth += 1
item = item.get_parent().get_parent()
return depth
func i_am_item() -> void:
pass
func toggle_collapsed() -> void:
collapsed = !collapsed
collapse_button.text = ">" if collapsed else "v"
for i in subitems:
i.visible = !collapsed
func can_drop_data(_position: Vector2, data) -> bool:
if data is Control && data.has_method("i_am_item"):
return true
return false
func rename_request() -> void:
if editable:
emit_signal("rename_allowed")