Lera Elvoé
08bbf61416
* test case with folders/subfolders * renaming items by double-clicking them * naive drag test
114 lines
3.0 KiB
GDScript
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")
|