textarea
This commit is contained in:
64
Scripts/ResizableTextEdit.gd
Normal file
64
Scripts/ResizableTextEdit.gd
Normal file
@@ -0,0 +1,64 @@
|
||||
extends TextEdit
|
||||
|
||||
@onready var resize_handle = TextureRect.new()
|
||||
var is_resizing = false
|
||||
var resize_start_pos = Vector2()
|
||||
var original_size = Vector2()
|
||||
|
||||
var min_size = Vector2(100, 50)
|
||||
|
||||
func _ready():
|
||||
# Create resize handle as TextureRect child of TextEdit
|
||||
resize_handle.texture = load("res://Assets/Icons/resize-handle.svg")
|
||||
resize_handle.size = Vector2(32, 32)
|
||||
resize_handle.mouse_default_cursor_shape = Control.CURSOR_FDIAGSIZE
|
||||
resize_handle.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
add_child(resize_handle)
|
||||
|
||||
# Position handle in bottom-right corner
|
||||
_update_handle_position()
|
||||
|
||||
# Connect signals
|
||||
resize_handle.gui_input.connect(_on_resize_handle_input)
|
||||
resized.connect(_update_handle_position)
|
||||
|
||||
func _gui_input(event):
|
||||
if event is InputEventMouseButton and get_global_rect().has_point(get_viewport().get_mouse_position()):
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||
set_v_scroll(get_v_scroll() - 2)
|
||||
accept_event()
|
||||
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
set_v_scroll(get_v_scroll() + 2)
|
||||
accept_event()
|
||||
|
||||
func _update_handle_position():
|
||||
if resize_handle:
|
||||
resize_handle.position = Vector2(size.x - 32, size.y - 32)
|
||||
|
||||
func _on_resize_handle_input(event):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
is_resizing = true
|
||||
resize_start_pos = event.global_position
|
||||
original_size = size
|
||||
else:
|
||||
is_resizing = false
|
||||
|
||||
elif event is InputEventMouseMotion and is_resizing:
|
||||
var delta = event.global_position - resize_start_pos
|
||||
var new_size = original_size + delta
|
||||
new_size.x = max(new_size.x, min_size.x)
|
||||
new_size.y = max(new_size.y, min_size.y)
|
||||
|
||||
size = new_size
|
||||
|
||||
# Sync parent Control size
|
||||
var parent_control = get_parent() as Control
|
||||
if parent_control:
|
||||
parent_control.size = new_size
|
||||
parent_control.custom_minimum_size = new_size
|
||||
if parent_control:
|
||||
parent_control.size = new_size
|
||||
parent_control.custom_minimum_size = new_size
|
||||
|
||||
1
Scripts/ResizableTextEdit.gd.uid
Normal file
1
Scripts/ResizableTextEdit.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c5xpoyqcg1p8k
|
||||
@@ -35,5 +35,4 @@ func init(element: HTMLParser.HTMLElement) -> void:
|
||||
if selected_index >= 0:
|
||||
option_button.selected = selected_index
|
||||
|
||||
add_child(option_button)
|
||||
custom_minimum_size = option_button.size
|
||||
|
||||
75
Scripts/Tags/textarea.gd
Normal file
75
Scripts/Tags/textarea.gd
Normal file
@@ -0,0 +1,75 @@
|
||||
extends Control
|
||||
|
||||
const BROWSER_TEXT = preload("res://Scenes/Styles/BrowserText.tres")
|
||||
|
||||
func init(element: HTMLParser.HTMLElement) -> void:
|
||||
var text_edit: TextEdit = $TextEdit
|
||||
|
||||
var placeholder = element.get_attribute("placeholder")
|
||||
var value = element.get_attribute("value")
|
||||
var rows = element.get_attribute("rows")
|
||||
var cols = element.get_attribute("cols")
|
||||
var maxlength = element.get_attribute("maxlength")
|
||||
var readonly = element.get_attribute("readonly")
|
||||
var disabled = element.get_attribute("disabled")
|
||||
|
||||
# Set placeholder text
|
||||
text_edit.placeholder_text = placeholder
|
||||
|
||||
# Set initial value
|
||||
if value.length() > 0:
|
||||
text_edit.text = value
|
||||
elif element.text_content.length() > 0:
|
||||
text_edit.text = element.text_content
|
||||
|
||||
# We assume to fit $rows amount of new lines
|
||||
var line_height = text_edit.get_theme_default_font().get_height(text_edit.get_theme_default_font_size())
|
||||
# We assume the biggest letter typed is "M" (77), and optimize to fit $cols amount of "M"
|
||||
var char_width = text_edit.get_theme_default_font().get_char_size(77, text_edit.get_theme_default_font_size()).x
|
||||
|
||||
var min_height = line_height * (rows.to_int() if rows.length() > 0 else 4) + 26 # padding
|
||||
var min_width = char_width * (cols.to_int() if cols.length() > 0 else 50) + 16 # padding
|
||||
|
||||
text_edit.custom_minimum_size = Vector2(min_width, min_height)
|
||||
text_edit.size = Vector2(min_width, min_height)
|
||||
text_edit.min_size = Vector2(min_width, min_height)
|
||||
|
||||
# Sync Control size with TextEdit
|
||||
custom_minimum_size = text_edit.custom_minimum_size
|
||||
size = text_edit.size
|
||||
|
||||
# Set readonly state
|
||||
if readonly.length() > 0:
|
||||
text_edit.editable = false
|
||||
|
||||
# Set disabled state
|
||||
if disabled.length() > 0:
|
||||
text_edit.editable = false
|
||||
var stylebox = StyleBoxFlat.new()
|
||||
stylebox.bg_color = Color(0.8, 0.8, 0.8, 1.0)
|
||||
stylebox.border_color = Color(0, 0, 0, 1.0)
|
||||
stylebox.border_width_bottom = 1
|
||||
stylebox.border_width_top = 1
|
||||
stylebox.border_width_left = 1
|
||||
stylebox.border_width_right = 1
|
||||
stylebox.corner_radius_bottom_left = 3
|
||||
stylebox.corner_radius_bottom_right = 3
|
||||
stylebox.corner_radius_top_left = 3
|
||||
stylebox.corner_radius_top_right = 3
|
||||
text_edit.add_theme_stylebox_override("normal", stylebox)
|
||||
text_edit.add_theme_stylebox_override("focus", stylebox)
|
||||
text_edit.add_theme_stylebox_override("readonly", stylebox)
|
||||
|
||||
# Handle maxlength
|
||||
if maxlength.length() > 0 and maxlength.is_valid_int():
|
||||
var max_len = maxlength.to_int()
|
||||
text_edit.text_changed.connect(_on_text_changed.bind(max_len))
|
||||
|
||||
func _on_text_changed(max_length: int) -> void:
|
||||
var text_edit = $TextEdit as TextEdit
|
||||
if text_edit.text.length() > max_length:
|
||||
var cursor_pos = text_edit.get_caret_column()
|
||||
var line_pos = text_edit.get_caret_line()
|
||||
text_edit.text = text_edit.text.substr(0, max_length)
|
||||
text_edit.set_caret_line(line_pos)
|
||||
text_edit.set_caret_column(min(cursor_pos, text_edit.get_line(line_pos).length()))
|
||||
1
Scripts/Tags/textarea.gd.uid
Normal file
1
Scripts/Tags/textarea.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bmcx7mr4nye6a
|
||||
@@ -25,6 +25,7 @@ const OL = preload("res://Scenes/Tags/ol.tscn")
|
||||
const LI = preload("res://Scenes/Tags/li.tscn")
|
||||
const SELECT = preload("res://Scenes/Tags/select.tscn")
|
||||
const OPTION = preload("res://Scenes/Tags/option.tscn")
|
||||
const TEXTAREA = preload("res://Scenes/Tags/textarea.tscn")
|
||||
|
||||
const MIN_SIZE = Vector2i(750, 200)
|
||||
|
||||
@@ -85,6 +86,14 @@ line breaks
|
||||
<option value=\"test5\">Test 5</option>
|
||||
</select>
|
||||
|
||||
<textarea />
|
||||
<textarea cols=\"30\" />
|
||||
<textarea rows=\"2\" />
|
||||
<textarea maxlength=\"20\" />
|
||||
<textarea readonly=\"true\">le skibidi le toilet</textarea>
|
||||
<textarea disabled=\"true\" value=\"DISABLED\" />
|
||||
<textarea placeholder=\"this is a placeholder...\" />
|
||||
|
||||
<!-- action, method, and type=submit are for when we implement Lua -->
|
||||
<form action=\"/submit\" method=\"POST\">
|
||||
<span>Name:</span>
|
||||
@@ -479,6 +488,9 @@ func create_element_node(element: HTMLParser.HTMLElement) -> Control:
|
||||
"option":
|
||||
node = OPTION.instantiate()
|
||||
node.init(element)
|
||||
"textarea":
|
||||
node = TEXTAREA.instantiate()
|
||||
node.init(element)
|
||||
_:
|
||||
return null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user