stick-the-quick/ui/EditableHorizontalList.gd

176 lines
5.5 KiB
GDScript

class_name EditableHorizontalList extends HBoxContainer
@onready var item_array: Array[EditableHorizontalListItem] = []
@onready var item_container := (
$'ItemsScrollContainer/Items' as HBoxContainer
)
@onready var button_push_item := (
$'PushItemMargin/PushItem' as Button
)
@onready var button_pop_item := (
$'PopItemMargin/PopItem' as Button
)
@onready var button_clear_list := (
$'ClearListMargin/ClearList' as Button
)
signal new_item_needs_content(item: EditableHorizontalListItem)
func _ready() -> void:
button_push_item.pressed.connect(_on_push_item_clicked)
button_pop_item.pressed.connect(_on_pop_item_clicked)
button_clear_list.pressed.connect(_on_clear_list_clicked)
for descendant in item_container.get_children():
if descendant is EditableHorizontalListItem:
item_array.push_back(descendant)
descendant.insert_before_clicked.connect(_fulfill_insert_before)
descendant.shift_back_clicked.connect(_fulfill_shift_back)
descendant.remove_clicked.connect(_fulfill_remove)
descendant.shift_forward_clicked.connect(_fulfill_shift_forward)
descendant.insert_after_clicked.connect(_fulfill_insert_after)
else:
push_warning((
"Non-EditableHorizontalListItem child of Items container " +
"will be deleted: %s"
) % descendant)
item_container.remove_child(descendant)
descendant.queue_free()
reorganize()
func reorganize() -> void:
for item in item_array:
if item.get_parent() == item_container:
item_container.remove_child(item)
for descendant in item_container.get_children():
push_warning(
"Unexpected child of Items container will be deleted: %s" %
descendant
)
item_container.remove_child(descendant)
descendant.queue_free()
for item in item_array:
item_container.add_child(item)
item.button_shift_back.disabled = false
item.button_shift_forward.disabled = false
if item_array.is_empty():
button_pop_item.disabled = true
button_clear_list.disabled = true
else:
var first := item_array[0]
var last := item_array[item_array.size() - 1]
first.button_shift_back.disabled = true
last.button_shift_forward.disabled = true
button_pop_item.disabled = false
button_clear_list.disabled = false
func insert(index: int = -1) -> EditableHorizontalListItem:
var item := (
preload('res://ui/EditableHorizontalListItem.tscn').instantiate()
) as EditableHorizontalListItem
if index >= 0 and index < item_array.size():
item_array.insert(index, item)
else:
item_array.push_back(item)
item.insert_before_clicked.connect(_fulfill_insert_before)
item.shift_back_clicked.connect(_fulfill_shift_back)
item.remove_clicked.connect(_fulfill_remove)
item.shift_forward_clicked.connect(_fulfill_shift_forward)
item.insert_after_clicked.connect(_fulfill_insert_after)
reorganize()
new_item_needs_content.emit(item)
return item
func remove(index: int = -1) -> bool:
var item: EditableHorizontalListItem = null
if index >= 0 and index < item_array.size():
item = item_array[index]
item_array.remove_at(index)
elif item_array.is_empty():
return false
else:
item = item_array[item_array.size() - 1]
item_array.pop_back()
item.insert_before_clicked.disconnect(_fulfill_insert_before)
item.shift_back_clicked.disconnect(_fulfill_shift_back)
item.remove_clicked.disconnect(_fulfill_remove)
item.shift_forward_clicked.disconnect(_fulfill_shift_forward)
item.insert_after_clicked.disconnect(_fulfill_insert_after)
if item.get_parent() == item_container:
item_container.remove_child(item)
item.queue_free()
reorganize()
return true
func shift_back(index: int) -> bool:
if index > 0 and index < item_array.size():
var a := item_array[index - 1]
var b := item_array[index]
item_array[index] = a
item_array[index - 1] = b
reorganize()
return true
else:
return false
func shift_forward(index: int) -> bool:
if index >= 0 and index < item_array.size() - 1:
var a := item_array[index]
var b := item_array[index + 1]
item_array[index + 1] = a
item_array[index] = b
reorganize()
return true
else:
return false
func clear() -> void:
for item in item_array:
item.insert_before_clicked.disconnect(_fulfill_insert_before)
item.shift_back_clicked.disconnect(_fulfill_shift_back)
item.remove_clicked.disconnect(_fulfill_remove)
item.shift_forward_clicked.disconnect(_fulfill_shift_forward)
item.insert_after_clicked.disconnect(_fulfill_insert_after)
if item.get_parent() == item_container:
item_container.remove_child(item)
item.queue_free()
for descendant in item_container.get_children():
push_warning(
"Unexpected child of Items container will be deleted: %s" %
descendant
)
item_container.remove_child(descendant)
descendant.queue_free()
item_array.clear()
func size() -> int:
return item_array.size()
func _fulfill_insert_before(item: EditableHorizontalListItem) -> void:
var index := item_array.find(item)
if index >= 0: insert(index)
func _fulfill_shift_back(item: EditableHorizontalListItem) -> void:
var index := item_array.find(item)
if index >= 0: shift_back(index)
func _fulfill_remove(item: EditableHorizontalListItem) -> void:
var index := item_array.find(item)
if index >= 0: remove(index)
func _fulfill_shift_forward(item: EditableHorizontalListItem) -> void:
var index := item_array.find(item)
if index >= 0: shift_forward(index)
func _fulfill_insert_after(item: EditableHorizontalListItem) -> void:
var index := item_array.find(item)
if index >= 0: insert(index + 1)
func _on_push_item_clicked() -> void:
insert()
func _on_pop_item_clicked() -> void:
remove()
func _on_clear_list_clicked() -> void:
clear()