176 lines
5.5 KiB
GDScript3
176 lines
5.5 KiB
GDScript3
|
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()
|