use hbox instead of richtextlabel for nested text tags, complete invite creation
This commit is contained in:
@@ -436,7 +436,9 @@ static func apply_element_bbcode_formatting(element: HTMLElement, styles: Dictio
|
||||
color = "#" + color.to_html(false)
|
||||
else:
|
||||
color = str(color)
|
||||
formatted_content = "[color=%s]%s[/color]" % [color, formatted_content]
|
||||
var color_pattern = "[color=%s]" % color
|
||||
if not formatted_content.contains(color_pattern):
|
||||
formatted_content = "[color=%s]%s[/color]" % [color, formatted_content]
|
||||
|
||||
# Apply tag-specific formatting
|
||||
match element.tag_name:
|
||||
@@ -471,8 +473,8 @@ static func apply_element_bbcode_formatting(element: HTMLElement, styles: Dictio
|
||||
var href = element.get_attribute("href")
|
||||
|
||||
if href.length() > 0:
|
||||
# Pass raw href - URL resolution happens in handle_link_click
|
||||
formatted_content = "[url=%s]%s[/url]" % [href, formatted_content]
|
||||
if not formatted_content.contains("[url="):
|
||||
formatted_content = "[url=%s]%s[/url]" % [href, formatted_content]
|
||||
|
||||
return formatted_content
|
||||
|
||||
|
||||
@@ -489,6 +489,10 @@ func _on_input_focus_lost(subscription: EventSubscription) -> void:
|
||||
current_text = dom_node.get_text()
|
||||
elif "text" in dom_node:
|
||||
current_text = dom_node.text
|
||||
else:
|
||||
var element = dom_parser.find_by_id(subscription.element_id)
|
||||
if element:
|
||||
current_text = element.text_content
|
||||
|
||||
var event_info = {"value": current_text}
|
||||
_execute_lua_callback(subscription, [event_info])
|
||||
@@ -723,10 +727,7 @@ func _handle_text_setting(operation: Dictionary):
|
||||
|
||||
var element = SelectorUtils.find_first_matching(selector, dom_parser.parse_result.all_elements)
|
||||
if element:
|
||||
# Always update the HTML element's text content first
|
||||
element.text_content = text
|
||||
|
||||
# If the element has a DOM node, update it too
|
||||
# If the element has a DOM node, update it directly without updating text_content
|
||||
var element_id = get_or_assign_element_id(element)
|
||||
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||
if dom_node:
|
||||
@@ -734,24 +735,37 @@ func _handle_text_setting(operation: Dictionary):
|
||||
var button_node = dom_node.get_node_or_null("ButtonNode")
|
||||
if button_node and button_node is Button:
|
||||
button_node.text = text
|
||||
element.text_content = text
|
||||
return
|
||||
|
||||
if element.tag_name == "p" and dom_node.has_method("set_text"):
|
||||
dom_node.set_text(text)
|
||||
element.text_content = text
|
||||
return
|
||||
|
||||
element.text_content = text
|
||||
|
||||
if dom_node:
|
||||
var text_node = get_dom_node(dom_node, "text")
|
||||
if text_node:
|
||||
if text_node is RichTextLabel:
|
||||
StyleManager.apply_styles_to_label(text_node, dom_parser.get_element_styles_with_inheritance(element, "", []), element, dom_parser, text)
|
||||
text_node.call_deferred("_auto_resize_to_content")
|
||||
try_apply_auto_resize(text_node)
|
||||
elif text_node.has_method("set_text"):
|
||||
text_node.set_text(text)
|
||||
elif "text" in text_node:
|
||||
text_node.text = text
|
||||
if text_node.has_method("_auto_resize_to_content"):
|
||||
text_node.call_deferred("_auto_resize_to_content")
|
||||
try_apply_auto_resize(text_node)
|
||||
else:
|
||||
var rich_text_label = _find_rich_text_label_recursive(dom_node)
|
||||
if rich_text_label:
|
||||
StyleManager.apply_styles_to_label(rich_text_label, dom_parser.get_element_styles_with_inheritance(element, "", []), element, dom_parser, text)
|
||||
rich_text_label.call_deferred("_auto_resize_to_content")
|
||||
try_apply_auto_resize(rich_text_label)
|
||||
|
||||
func try_apply_auto_resize(text_node: Node) -> void:
|
||||
var parent = text_node.get_parent()
|
||||
if parent and parent.has_method("_apply_auto_resize_to_label"):
|
||||
parent.call_deferred("_apply_auto_resize_to_label", text_node)
|
||||
|
||||
func _find_rich_text_label_recursive(node: Node) -> RichTextLabel:
|
||||
if node is RichTextLabel:
|
||||
|
||||
@@ -464,17 +464,17 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
var new_height = max(active_child.custom_minimum_size.y, active_child.size.y)
|
||||
|
||||
if width:
|
||||
if width == "100%":
|
||||
if typeof(width) == TYPE_STRING and width == "100%":
|
||||
active_child.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
new_width = 0
|
||||
elif SizingUtils.is_percentage(width):
|
||||
elif typeof(width) == TYPE_STRING and SizingUtils.is_percentage(width):
|
||||
new_width = SizingUtils.calculate_percentage_size(width, SizingUtils.DEFAULT_VIEWPORT_WIDTH)
|
||||
else:
|
||||
new_width = width
|
||||
|
||||
if height:
|
||||
if SizingUtils.is_percentage(height):
|
||||
if typeof(height) == TYPE_STRING and SizingUtils.is_percentage(height):
|
||||
new_height = SizingUtils.calculate_percentage_size(height, SizingUtils.DEFAULT_VIEWPORT_HEIGHT)
|
||||
else:
|
||||
new_height = height
|
||||
@@ -483,7 +483,7 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
|
||||
active_child.custom_minimum_size = new_child_size
|
||||
|
||||
if width and width != "100%":
|
||||
if width and not (typeof(width) == TYPE_STRING and width == "100%"):
|
||||
active_child.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
if height:
|
||||
active_child.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
@@ -494,7 +494,7 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
custom_minimum_size = new_child_size
|
||||
|
||||
# Root Control adjusts size flags to match child
|
||||
if width and width != "100%":
|
||||
if width and not (typeof(width) == TYPE_STRING and width == "100%"):
|
||||
size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
else:
|
||||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
|
||||
@@ -1,75 +1,127 @@
|
||||
class_name HTMLP
|
||||
extends RichTextLabel
|
||||
extends HBoxContainer
|
||||
|
||||
var element_styles: Dictionary = {}
|
||||
var _element: HTMLParser.HTMLElement
|
||||
var _parser: HTMLParser
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
|
||||
element_styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
|
||||
text = "[font_size=24]%s[/font_size]" % element.get_bbcode_formatted_text(parser)
|
||||
|
||||
# Allow mouse events to pass through to parent containers for hover effects while keeping text selection
|
||||
mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
|
||||
autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
|
||||
call_deferred("_auto_resize_to_content")
|
||||
|
||||
_element = element
|
||||
_parser = parser
|
||||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
set_anchors_and_offsets_preset(Control.PRESET_TOP_WIDE)
|
||||
size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
|
||||
func _auto_resize_to_content():
|
||||
if not is_inside_tree():
|
||||
await tree_entered
|
||||
if get_child_count() > 0:
|
||||
return
|
||||
|
||||
var content_parts = []
|
||||
var current_text = ""
|
||||
|
||||
var element_text = element.text_content
|
||||
var child_texts = []
|
||||
|
||||
for child in element.children:
|
||||
child_texts.append(child.text_content)
|
||||
|
||||
var parent_only_text = element_text
|
||||
for child_text in child_texts:
|
||||
parent_only_text = parent_only_text.replace(child_text, "")
|
||||
|
||||
if not parent_only_text.strip_edges().is_empty():
|
||||
var parent_label = create_styled_label(parent_only_text.strip_edges(), element, parser)
|
||||
|
||||
for child in element.children:
|
||||
var child_label = create_styled_label(child.get_bbcode_formatted_text(parser), element, parser)
|
||||
|
||||
if contains_hyperlink(child):
|
||||
child_label.meta_clicked.connect(_on_meta_clicked)
|
||||
|
||||
func create_styled_label(text: String, element: HTMLParser.HTMLElement, parser: HTMLParser) -> RichTextLabel:
|
||||
var label = RichTextLabel.new()
|
||||
label.fit_content = true
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
label.bbcode_enabled = true
|
||||
add_child(label)
|
||||
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
StyleManager.apply_styles_to_label(label, styles, element, parser, text)
|
||||
|
||||
call_deferred("_apply_auto_resize_to_label", label)
|
||||
return label
|
||||
|
||||
func _apply_auto_resize_to_label(label: RichTextLabel):
|
||||
if not label.is_inside_tree():
|
||||
await label.tree_entered
|
||||
|
||||
var min_width = 20
|
||||
var max_width = 800
|
||||
var min_height = 30
|
||||
|
||||
fit_content = true
|
||||
label.fit_content = true
|
||||
|
||||
var original_autowrap = autowrap_mode
|
||||
autowrap_mode = TextServer.AUTOWRAP_OFF
|
||||
var original_autowrap = label.autowrap_mode
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_OFF
|
||||
|
||||
await get_tree().process_frame
|
||||
|
||||
var natural_width = size.x
|
||||
|
||||
var font_weight_multiplier = _get_font_weight_multiplier()
|
||||
natural_width *= font_weight_multiplier
|
||||
var natural_width = label.size.x
|
||||
natural_width *= 1.0 # font weight multiplier simplified
|
||||
|
||||
var desired_width = clampf(natural_width, min_width, max_width)
|
||||
|
||||
autowrap_mode = original_autowrap
|
||||
label.autowrap_mode = original_autowrap
|
||||
|
||||
await get_tree().process_frame
|
||||
|
||||
var content_height = get_content_height()
|
||||
var explicit_height = custom_minimum_size.y if custom_minimum_size.y > 0 else 0.0
|
||||
var final_height = explicit_height if explicit_height > 0 else max(content_height, min_height)
|
||||
custom_minimum_size = Vector2(desired_width, final_height)
|
||||
label.custom_minimum_size = Vector2(desired_width, 0)
|
||||
|
||||
queue_redraw()
|
||||
label.queue_redraw()
|
||||
|
||||
func _get_font_weight_multiplier() -> float:
|
||||
#if element_styles.has("font-black"):
|
||||
# return 1.12
|
||||
#elif element_styles.has("font-extrabold"):
|
||||
# return 1.10
|
||||
#elif element_styles.has("font-bold"):
|
||||
# return 1.04
|
||||
#elif element_styles.has("font-semibold"):
|
||||
# return 1.06
|
||||
#elif element_styles.has("font-medium"):
|
||||
# return 1.03
|
||||
#elif element_styles.has("font-light"):
|
||||
# return 0.98
|
||||
#elif element_styles.has("font-extralight") or element_styles.has("font-thin"):
|
||||
# return 0.95
|
||||
func contains_hyperlink(element: HTMLParser.HTMLElement) -> bool:
|
||||
if element.tag_name == "a":
|
||||
return true
|
||||
|
||||
#var text_content = get_parsed_text()
|
||||
for child in element.children:
|
||||
if contains_hyperlink(child):
|
||||
return true
|
||||
|
||||
#if text_content.contains("[b]"):
|
||||
# return 1.08
|
||||
return false
|
||||
|
||||
func _on_meta_clicked(meta: Variant) -> void:
|
||||
var current = get_parent()
|
||||
while current:
|
||||
if current.has_method("handle_link_click"):
|
||||
current.handle_link_click(meta)
|
||||
break
|
||||
current = current.get_parent()
|
||||
|
||||
func get_text() -> String:
|
||||
var text_parts = []
|
||||
for child in get_children():
|
||||
if child is RichTextLabel:
|
||||
text_parts.append(child.get_parsed_text())
|
||||
return " ".join(text_parts)
|
||||
|
||||
func set_text(new_text: String) -> void:
|
||||
# Clear existing children immediately
|
||||
for child in get_children():
|
||||
remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
return 1.0
|
||||
if _element and _parser:
|
||||
var label = create_styled_label(new_text, _element, _parser)
|
||||
else:
|
||||
var label = create_label(new_text)
|
||||
|
||||
func create_label(text: String) -> RichTextLabel:
|
||||
var label = RichTextLabel.new()
|
||||
label.text = text
|
||||
label.fit_content = true
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
label.bbcode_enabled = true
|
||||
add_child(label)
|
||||
call_deferred("_apply_auto_resize_to_label", label)
|
||||
return label
|
||||
|
||||
Reference in New Issue
Block a user