Files
Kalulu/sources/language_tool/lesson_container.gd
T
2025-09-05 15:55:48 +02:00

105 lines
3.5 KiB
GDScript

class_name LessonContainer
extends MarginContainer
signal lesson_dropped(before: bool, number: int, dropped_number: int)
var gp_label_scene: PackedScene = preload("res://sources/language_tool/lesson_gp_label.tscn")
var number: int = 0:
set = set_number
@onready var gp_container: HBoxContainer = $%GPContainer
@onready var number_label: Label = $%NumberLabel
func set_number(p_number: int) -> void:
number = p_number
if number_label:
number_label.text = str(number)
func add_gp(new_gp: Dictionary) -> void:
var gp_label: LessonGPLabel = gp_label_scene.instantiate()
gp_label.grapheme = new_gp.grapheme
gp_label.phoneme = new_gp.phoneme
gp_label.gp_id = new_gp.gp_id
gp_container.add_child(gp_label)
gp_label.gp_dropped.connect(_on_gp_dropped.bind(gp_label))
func _on_gp_dropped(before: bool, data: Dictionary, gp_label: Control) -> void:
var new_gp_label: LessonGPLabel = gp_label_scene.instantiate()
new_gp_label.grapheme = data.grapheme
new_gp_label.phoneme = data.phoneme
new_gp_label.gp_id = data.gp_id
new_gp_label.gp_dropped.connect(_on_gp_dropped.bind(new_gp_label))
gp_container.add_child(new_gp_label)
var children: Array[Node] = gp_container.get_children()
for index: int in range(children.size()):
var child: Node = children[index]
if child == gp_label:
if before:
gp_container.move_child(new_gp_label, index)
else:
gp_container.move_child(new_gp_label, index + 1)
func _can_drop_in_gp_container(_at_position: Vector2, data: Variant) -> bool:
if data is Dictionary:
return (data as Dictionary).has("gp_id")
else:
Logger.error("LessonContainer: Can not drop data (that is not of type Dictionary) in GP Container")
return false
func _drop_data_in_gp_container(_at_position: Vector2, data: Variant) -> void:
if not data is Dictionary:
Logger.error("LessonContainer: Cancel drop data in GP container because data is not of type Dictionary")
return
if not (data as Dictionary).has("gp_id"):
Logger.trace("LessonContainer: Cancel drop data in GP container because data has no key gp_id")
return
var new_gp_label: LessonGPLabel = gp_label_scene.instantiate()
new_gp_label.grapheme = data.grapheme
new_gp_label.phoneme = data.phoneme
new_gp_label.gp_id = data.gp_id
new_gp_label.gp_dropped.connect(_on_gp_dropped.bind(new_gp_label))
gp_container.add_child(new_gp_label)
gp_container.move_child(new_gp_label, 0)
func _ready() -> void:
gp_container.set_drag_forwarding(Callable(), _can_drop_in_gp_container, _drop_data_in_gp_container)
func _get_drag_data(_at_position: Vector2) -> Variant:
set_drag_preview(self.duplicate() as Control)
return { number = number }
func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
if data is Dictionary:
return ((data as Dictionary).has("number") and number != (data as Dictionary).number) or _can_drop_in_gp_container(at_position, data)
else:
Logger.error("LessonContainer: Can not drop data that is not of type Dictionary")
return false
func _drop_data(at_position: Vector2, data: Variant) -> void:
if not data is Dictionary:
Logger.error("LessonContainer: drop data failed because data is not of type Dictionary")
return
if not (data as Dictionary).has("number") or (data as Dictionary).has("gp_id"):
return
if (data as Dictionary).has("number"):
var before: bool = at_position.y < size.y
lesson_dropped.emit(before, number, data.number)
else:
_drop_data_in_gp_container(at_position, data)
func get_gp_ids() -> Array[int]:
var res: Array[int] = []
for gp: LessonGPLabel in gp_container.get_children():
res.append(gp.gp_id)
return res