116 lines
2.8 KiB
GDScript

extends VBoxContainer
export(Texture) var icon_shown : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_down.svg")
export(Texture) var icon_hidden : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_right.svg")
var child_visible : bool setget _set_child_visible, _get_child_visible
var label := "" setget _set_label
onready var _header : Control = GDBUtility.find_node_by_name(self, "header")
onready var _tex_arrow : TextureRect = GDBUtility.find_node_by_name(self, "tex_arrow")
var __last_child : Control = null
#############
# overrides #
#############
func _ready() -> void:
__update_child()
_header.label = label
func add_child(child : Node, legible_unique_name := false):
.add_child(child, legible_unique_name)
__update_child()
################
# overridables #
################
func _lazy_load_child() -> Control:
return null
################
# public stuff #
################
func toggle() -> void:
_set_child_visible(!_get_child_visible())
#################
# private stuff #
#################
func _get_child() -> Control:
if get_child_count() < 2:
return null
return get_child(1) as Control
func __update_child() -> void:
var the_child := _get_child()
if the_child == __last_child:
return
if __last_child:
GDBUtility.disconnect_all(__last_child, self)
if the_child:
the_child.connect("visibility_changed", self, "_on_child_visibility_changed")
the_child.connect("tree_exiting", self, "_on_child_tree_exiting")
if the_child.visible != _get_child_visible():
emit_signal("child_visibility_changed")
__last_child = the_child
__update_icon()
func __update_icon() -> void:
if _get_child_visible():
_tex_arrow.texture = icon_shown
else:
_tex_arrow.texture = icon_hidden
#####################
# setters & getters #
#####################
func _set_label(val : String) -> void:
label = val
if _header:
_header.label = val
func _set_child_visible(val : bool) -> void:
var child := _get_child()
if val && !child:
child = yield(GDBCoroutine.await(_lazy_load_child()), "completed")
if child:
emit_signal("child_created", child)
child.visible = true
add_child(child)
return
if child && child.visible != val:
child.visible = val
emit_signal("on_child_visibility_changed")
func _get_child_visible() -> bool:
var child := _get_child()
if child:
return child.visible
return false
############
# handlers #
############
func _on_header_gui_input(event : InputEvent) -> void:
if event is InputEventMouseButton && event.button_index == BUTTON_LEFT && event.pressed:
toggle()
func _on_child_visibility_changed() -> void:
__update_icon()
emit_signal("child_visibility_changed")
func _on_child_tree_exiting() -> void:
var tree := get_tree()
if !tree:
return
yield(tree, "idle_frame")
__update_child()
###########
# signals #
###########
signal child_created(child)
signal child_visibility_changed()