gduibasics/scenes/scripts/line_edit_suggestion_popup.gd
2021-08-21 17:15:07 +02:00

101 lines
2.3 KiB
GDScript

extends Popup
enum Position {
ABOVE,
BELOW
}
var line_edit : LineEdit setget _set_line_edit
export(Position) var position = Position.BELOW
#############
# overrides #
#############
func _ready():
call_deferred("__setup")
#################
# private stuff #
#################
func __setup():
__connect()
func __connect():
if !line_edit:
return
line_edit.connect("focus_entered", self, "_on_line_edit_focus_entered")
line_edit.connect("focus_exited", self, "_on_line_edit_focus_exited")
line_edit.connect("item_rect_changed", self, "_on_line_edit_item_rect_changed")
line_edit.connect("resized", self, "_on_line_edit_resized")
func __disconnect():
if !line_edit:
return
line_edit.disconnect("focus_entered", self, "_on_line_edit_focus_entered")
line_edit.disconnect("focus_exited", self, "_on_line_edit_focus_exited")
line_edit.disconnect("item_rect_changed", self, "_on_line_edit_item_rect_changed")
line_edit.disconnect("resized", self, "_on_line_edit_resized")
func __calc_rect() -> Rect2:
var position_ = position
var pos := line_edit.rect_global_position
var vp_pos = get_viewport_rect().position
var vp_size = get_viewport_rect().size
var size := rect_min_size
var le_size := line_edit.rect_size
var max_height : float
if pos.y + size.y > vp_size.y:
position_ = Position.ABOVE
elif pos.y < vp_pos.y:
position_ = Position.BELOW
if position_ == Position.ABOVE:
max_height = pos.y - vp_pos.y
else:
max_height = (vp_pos.y + vp_size.y) - (pos.y + size.y)
var res_size = Vector2(le_size.x, 100.0)
if position_ == Position.ABOVE:
return Rect2(pos - Vector2(0.0, res_size.y), res_size)
else:
return Rect2(pos + Vector2(0.0, size.y), res_size)
func __update():
var should_be_visible = line_edit.has_focus()
if !should_be_visible:
hide()
else:
var rect := __calc_rect()
if visible:
rect_position = rect.position
rect_size = rect.size
else:
popup(rect)
############
# handlers #
############
func _on_line_edit_focus_entered():
__update()
func _on_line_edit_focus_exited():
hide()
func _on_line_edit_item_rect_changed():
__update()
func _on_line_edit_resized():
__update()
###########
# setters #
###########
func _set_line_edit(value : LineEdit):
if value != line_edit:
__disconnect()
line_edit = value
__connect()