2026-02-27 16:17:32 -06:00
|
|
|
@tool
|
|
|
|
|
extends LineEdit
|
|
|
|
|
class_name LineEditWithButtons
|
|
|
|
|
|
|
|
|
|
signal left_button_pressed()
|
|
|
|
|
signal left_button_toggled()
|
|
|
|
|
signal right_button_pressed()
|
|
|
|
|
signal right_button_toggled()
|
|
|
|
|
|
2026-02-28 02:44:29 -06:00
|
|
|
static var _empty_sb = StyleBoxEmpty.new()
|
|
|
|
|
|
2026-02-27 16:17:32 -06:00
|
|
|
@export_subgroup("Left Icon")
|
|
|
|
|
@export var left: Texture2D:
|
|
|
|
|
set(value):
|
|
|
|
|
left = value
|
|
|
|
|
if not is_node_ready(): return
|
|
|
|
|
|
|
|
|
|
if _left_btn and value == null:
|
|
|
|
|
_left_btn.queue_free()
|
|
|
|
|
return
|
|
|
|
|
if not _left_btn and value:
|
|
|
|
|
_left_btn = _create_button_icon(value)
|
2026-02-28 02:44:29 -06:00
|
|
|
_left_btn.toggle_mode = left_is_toggle
|
2026-02-27 16:17:32 -06:00
|
|
|
_left_btn.pressed.connect(left_button_pressed.emit)
|
|
|
|
|
_left_btn.toggled.connect(left_button_toggled.emit)
|
|
|
|
|
return
|
|
|
|
|
_left_btn.icon = value
|
|
|
|
|
@export var left_is_toggle: bool = false
|
|
|
|
|
@export_subgroup("Right Icon")
|
|
|
|
|
@export var right: Texture2D:
|
|
|
|
|
set(value):
|
|
|
|
|
right = value
|
|
|
|
|
if not is_node_ready(): return
|
|
|
|
|
if _right_btn and value == null:
|
|
|
|
|
_right_btn.queue_free()
|
|
|
|
|
return
|
|
|
|
|
if not _right_btn and value:
|
|
|
|
|
_right_btn = _create_button_icon(value)
|
2026-02-28 02:44:29 -06:00
|
|
|
_right_btn.toggle_mode = right_is_toggle
|
2026-02-27 16:17:32 -06:00
|
|
|
_right_btn.pressed.connect(right_button_pressed.emit)
|
|
|
|
|
_right_btn.toggled.connect(right_button_toggled.emit)
|
|
|
|
|
return
|
2026-02-28 02:44:29 -06:00
|
|
|
_right_btn.icon = value
|
2026-02-27 16:17:32 -06:00
|
|
|
@export var right_is_toggle: bool = false
|
|
|
|
|
|
|
|
|
|
var _left_btn: Button
|
|
|
|
|
var _right_btn: Button
|
|
|
|
|
var _container: HBoxContainer
|
|
|
|
|
var _spacer: Control
|
2026-02-28 02:44:29 -06:00
|
|
|
var _nsb: StyleBox
|
|
|
|
|
var _rosb: StyleBox
|
|
|
|
|
var _fsb: StyleBox
|
|
|
|
|
|
|
|
|
|
var _nsb_orig_left: float
|
|
|
|
|
var _nsb_orig_right: float
|
|
|
|
|
var _rosb_orig_left: float
|
|
|
|
|
var _rosb_orig_right: float
|
|
|
|
|
var _fsb_orig_left: float
|
|
|
|
|
var _fsb_orig_right: float
|
2026-02-27 16:17:32 -06:00
|
|
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
_container = HBoxContainer.new()
|
|
|
|
|
_spacer = Control.new()
|
2026-02-28 02:44:29 -06:00
|
|
|
_spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
2026-02-27 16:17:32 -06:00
|
|
|
_spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
2026-02-28 02:44:29 -06:00
|
|
|
_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
2026-02-27 16:17:32 -06:00
|
|
|
_container.add_child(_spacer)
|
|
|
|
|
add_child(_container)
|
|
|
|
|
if left != null:
|
|
|
|
|
_left_btn = _create_button_icon(left)
|
2026-02-28 02:44:29 -06:00
|
|
|
_left_btn.toggle_mode = left_is_toggle
|
2026-02-27 16:17:32 -06:00
|
|
|
_left_btn.pressed.connect(left_button_pressed.emit)
|
|
|
|
|
_left_btn.toggled.connect(left_button_toggled.emit)
|
|
|
|
|
if right != null:
|
|
|
|
|
_right_btn = _create_button_icon(right, -1)
|
2026-02-28 02:44:29 -06:00
|
|
|
_right_btn.toggle_mode = right_is_toggle
|
2026-02-27 16:17:32 -06:00
|
|
|
_right_btn.pressed.connect(right_button_pressed.emit)
|
|
|
|
|
_right_btn.toggled.connect(right_button_toggled.emit)
|
|
|
|
|
|
2026-02-28 02:44:29 -06:00
|
|
|
_nsb = get_theme_stylebox(&"normal").duplicate(true)
|
|
|
|
|
_rosb = get_theme_stylebox(&"read_only").duplicate(true)
|
|
|
|
|
_fsb = get_theme_stylebox(&"focus").duplicate(true)
|
|
|
|
|
_nsb_orig_left = _nsb.content_margin_left
|
|
|
|
|
_nsb_orig_right = _nsb.content_margin_right
|
|
|
|
|
_rosb_orig_left = _rosb.content_margin_left
|
|
|
|
|
_rosb_orig_right = _rosb.content_margin_right
|
|
|
|
|
_fsb_orig_left = _fsb.content_margin_left
|
|
|
|
|
_fsb_orig_right = _fsb.content_margin_right
|
|
|
|
|
|
|
|
|
|
add_theme_stylebox_override(&"normal", _nsb)
|
|
|
|
|
add_theme_stylebox_override(&"read_only", _rosb)
|
|
|
|
|
add_theme_stylebox_override(&"focus", _fsb)
|
|
|
|
|
|
2026-02-27 16:17:32 -06:00
|
|
|
item_rect_changed.connect(_handle_resize)
|
|
|
|
|
|
2026-02-28 02:44:29 -06:00
|
|
|
func _create_button_icon(icon_texture: Texture2D, pos: int = 0) -> Button:
|
2026-02-27 16:17:32 -06:00
|
|
|
var btn = Button.new()
|
2026-02-28 02:44:29 -06:00
|
|
|
btn.icon = icon_texture
|
2026-02-27 16:17:32 -06:00
|
|
|
btn.flat = true
|
|
|
|
|
btn.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
|
|
|
btn.vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
|
|
|
btn.expand_icon = true
|
2026-02-28 02:44:29 -06:00
|
|
|
btn.custom_minimum_size = Vector2(0, size.y)
|
|
|
|
|
btn.ready.connect(func(): btn.icon = icon_texture)
|
|
|
|
|
btn.add_theme_stylebox_override(&"normal", _empty_sb)
|
|
|
|
|
btn.add_theme_stylebox_override(&"pressed", _empty_sb)
|
|
|
|
|
btn.add_theme_stylebox_override(&"hover", _empty_sb)
|
|
|
|
|
btn.add_theme_stylebox_override(&"disabled", _empty_sb)
|
|
|
|
|
btn.add_theme_stylebox_override(&"focus", _empty_sb)
|
2026-02-27 16:17:32 -06:00
|
|
|
_container.add_child(btn)
|
|
|
|
|
_container.move_child(btn, pos)
|
|
|
|
|
return btn
|
|
|
|
|
|
|
|
|
|
func _handle_resize() -> void:
|
|
|
|
|
_container.size = size
|
2026-02-28 02:44:29 -06:00
|
|
|
if _left_btn:
|
|
|
|
|
_left_btn.custom_minimum_size = Vector2(size.y, size.y)
|
|
|
|
|
_fsb.content_margin_left = _fsb_orig_left + size.y
|
|
|
|
|
_rosb.content_margin_left = _rosb_orig_left + size.y
|
|
|
|
|
_nsb.content_margin_left = _nsb_orig_left + size.y
|
|
|
|
|
if _right_btn:
|
|
|
|
|
_right_btn.custom_minimum_size = Vector2(size.y, size.y)
|
|
|
|
|
_fsb.content_margin_right = _fsb_orig_right + size.y
|
|
|
|
|
_rosb.content_margin_right = _rosb_orig_right + size.y
|
|
|
|
|
_nsb.content_margin_right = _nsb_orig_right + size.y
|