add button color, corner radius & hover/active states + fix input sizing
This commit is contained in:
@@ -148,7 +148,9 @@ func parse_rule(rule_data: Dictionary) -> CSSRule:
|
||||
|
||||
return rule
|
||||
|
||||
func parse_utility_class(rule: CSSRule, utility_name: String) -> void:
|
||||
# Parses a utility class (e.g. "text-red-500") and adds properties to the rule (e.g. "color: red")
|
||||
# Used as a translation layer for Tailwind-like utility classes, as it becomes easier to manage these programmatically
|
||||
static func parse_utility_class(rule: CSSRule, utility_name: String) -> void:
|
||||
# Handle color classes like text-[#ff0000]
|
||||
if utility_name.begins_with("text-[") and utility_name.ends_with("]"):
|
||||
var color_value = extract_bracket_content(utility_name, 5) # after 'text-'
|
||||
@@ -348,10 +350,45 @@ func parse_utility_class(rule: CSSRule, utility_name: String) -> void:
|
||||
rule.properties["order"] = val.to_int()
|
||||
return
|
||||
|
||||
# Handle border radius classes like rounded, rounded-lg, rounded-[12px]
|
||||
if utility_name == "rounded":
|
||||
rule.properties["border-radius"] = "4px"
|
||||
return
|
||||
if utility_name == "rounded-none":
|
||||
rule.properties["border-radius"] = "0px"
|
||||
return
|
||||
if utility_name == "rounded-sm":
|
||||
rule.properties["border-radius"] = "2px"
|
||||
return
|
||||
if utility_name == "rounded-md":
|
||||
rule.properties["border-radius"] = "6px"
|
||||
return
|
||||
if utility_name == "rounded-lg":
|
||||
rule.properties["border-radius"] = "8px"
|
||||
return
|
||||
if utility_name == "rounded-xl":
|
||||
rule.properties["border-radius"] = "12px"
|
||||
return
|
||||
if utility_name == "rounded-2xl":
|
||||
rule.properties["border-radius"] = "16px"
|
||||
return
|
||||
if utility_name == "rounded-3xl":
|
||||
rule.properties["border-radius"] = "24px"
|
||||
return
|
||||
if utility_name == "rounded-full":
|
||||
rule.properties["border-radius"] = "9999px"
|
||||
return
|
||||
|
||||
# Handle custom border radius like rounded-[12px]
|
||||
if utility_name.begins_with("rounded-[") and utility_name.ends_with("]"):
|
||||
var radius_value = extract_bracket_content(utility_name, 8) # after 'rounded-'
|
||||
rule.properties["border-radius"] = radius_value
|
||||
return
|
||||
|
||||
# Handle more utility classes as needed
|
||||
# Add more cases here for other utilities
|
||||
|
||||
func parse_size(val: String) -> String:
|
||||
static func parse_size(val: String) -> String:
|
||||
var named = {
|
||||
"0": "0px", "1": "4px", "2": "8px", "3": "12px", "4": "16px", "5": "20px", "6": "24px", "8": "32px", "10": "40px",
|
||||
"12": "48px", "16": "64px", "20": "80px", "24": "96px", "28": "112px", "32": "128px", "36": "144px", "40": "160px",
|
||||
@@ -372,7 +409,7 @@ func parse_size(val: String) -> String:
|
||||
return val
|
||||
|
||||
# Helper to extract content inside first matching brackets after a given index
|
||||
func extract_bracket_content(string: String, start_idx: int) -> String:
|
||||
static func extract_bracket_content(string: String, start_idx: int) -> String:
|
||||
var open_idx = string.find("[", start_idx)
|
||||
if open_idx == -1:
|
||||
return ""
|
||||
@@ -381,7 +418,7 @@ func extract_bracket_content(string: String, start_idx: int) -> String:
|
||||
return ""
|
||||
return string.substr(open_idx + 1, close_idx - open_idx - 1)
|
||||
|
||||
func parse_color(color_string: String) -> Color:
|
||||
static func parse_color(color_string: String) -> Color:
|
||||
color_string = color_string.strip_edges()
|
||||
|
||||
# Handle hex colors
|
||||
|
||||
@@ -164,12 +164,40 @@ func get_element_styles_internal(element: HTMLElement, event: String = "") -> Di
|
||||
# Apply inline styles (higher priority) - force override CSS rules
|
||||
var inline_style = element.get_attribute("style")
|
||||
if inline_style.length() > 0:
|
||||
var inline_parsed = CSSParser.parse_inline_style(inline_style)
|
||||
var inline_parsed = parse_inline_style_with_event(inline_style, event)
|
||||
for property in inline_parsed:
|
||||
styles[property] = inline_parsed[property] # Force override
|
||||
|
||||
return styles
|
||||
|
||||
func parse_inline_style_with_event(style_string: String, event: String = "") -> Dictionary:
|
||||
var properties = {}
|
||||
|
||||
# Split style string into individual utility classes
|
||||
var utility_classes = style_string.split(" ") # e.g. ["bg-red-500, "text-lg", "hover:bg-blue-500"]
|
||||
|
||||
for utility_name in utility_classes:
|
||||
utility_name = utility_name.strip_edges() # e.g. "bg-red-500"
|
||||
if utility_name.is_empty():
|
||||
continue
|
||||
|
||||
# Check if this utility is for the requested event
|
||||
if event.length() > 0:
|
||||
if utility_name.begins_with(event + ":"): # e.g. "hover:bg-blue-500"
|
||||
var actual_utility = utility_name.substr(event.length() + 1) # bg-blue-500
|
||||
var rule = CSSParser.CSSRule.new()
|
||||
CSSParser.parse_utility_class(rule, actual_utility)
|
||||
for property in rule.properties:
|
||||
properties[property] = rule.properties[property]
|
||||
else:
|
||||
if not utility_name.contains(":"):
|
||||
var rule = CSSParser.CSSRule.new()
|
||||
CSSParser.parse_utility_class(rule, utility_name)
|
||||
for property in rule.properties:
|
||||
properties[property] = rule.properties[property]
|
||||
|
||||
return properties
|
||||
|
||||
# Creates element from CURRENT xml parser node
|
||||
func create_element() -> HTMLElement:
|
||||
var element = HTMLElement.new(xml_parser.get_node_name())
|
||||
|
||||
@@ -31,6 +31,7 @@ var HTML_CONTENT2 = "<head>
|
||||
<style>
|
||||
h1 { text-[#ff0000] font-italic hover:text-[#00ff00] }
|
||||
p { text-[#333333] text-2xl }
|
||||
button { hover:bg-[#FF6B35] hover:text-[#FFFFFF] active:bg-[#CC5429] active:text-[#F0F0F0] }
|
||||
</style>
|
||||
<style src=\"styles.css\">
|
||||
<script src=\"script.lua\" />
|
||||
@@ -116,10 +117,6 @@ So
|
||||
<h2>File Upload</h2>
|
||||
<input type=\"file\" accept=\".txt,.pdf,image/*\" />
|
||||
|
||||
<input type=\"password\" placeholder=\"your password...\" />
|
||||
<button type=\"submit\">Submit</button>
|
||||
</form>
|
||||
|
||||
<separator direction=\"horizontal\" />
|
||||
# Ordered list
|
||||
<ol>
|
||||
@@ -241,7 +238,6 @@ var HTML_CONTENT = """<head>
|
||||
<style>
|
||||
h1 { text-[#4ade80] text-3xl font-bold }
|
||||
p { text-[#94a3b8] text-lg }
|
||||
button { bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e] }
|
||||
input { border border-[#cbd5e1] px-2 py-1 rounded }
|
||||
</style>
|
||||
|
||||
@@ -256,15 +252,15 @@ var HTML_CONTENT = """<head>
|
||||
<div style="flex flex-col gap-2 w-80 mx-auto bg-[#f8fafc] p-4 rounded">
|
||||
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
|
||||
<span>✅ Finish homework</span>
|
||||
<button>Delete</button>
|
||||
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
|
||||
</span>
|
||||
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
|
||||
<span>✍️ Write blog post</span>
|
||||
<button>Delete</button>
|
||||
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
|
||||
</span>
|
||||
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
|
||||
<span>💪 Gym workout</span>
|
||||
<button>Delete</button>
|
||||
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -275,7 +271,7 @@ var HTML_CONTENT = """<head>
|
||||
<form action="/add-task" method="POST" style="flex flex-col gap-2 w-80 mx-auto">
|
||||
<input type="text" placeholder="Enter task..." minlength="3" required="true" />
|
||||
<input type="date" />
|
||||
<button type="submit">Add Task</button>
|
||||
<button type="submit" style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Add Task</button>
|
||||
</form>
|
||||
|
||||
<separator direction="horizontal" />
|
||||
@@ -286,5 +282,70 @@ var HTML_CONTENT = """<head>
|
||||
<span style="bg-[#d1fae5] px-4 py-2 rounded">💼 Work</span>
|
||||
<span style="bg-[#e0e7ff] px-4 py-2 rounded">🏋️ Health</span>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<input type=\"password\" placeholder=\"your password...\" />
|
||||
<button type=\"submit\" style=\"bg-[#4CAF50] rounded-lg text-[#FFFFFF]\">Submit</button>
|
||||
<button style=\"bg-[#2196F3] rounded-xl text-[#FFFFFF]\">Blue Button</button>
|
||||
<button style=\"bg-[#FF5722] rounded-full text-[#FFFFFF]\">Orange Pill</button>
|
||||
<button style=\"bg-[#9C27B0] rounded-[20px] text-[#FFFFFF]\">Purple Custom</button>
|
||||
<button style=\"bg-[#FFD700] rounded text-[#000000] hover:bg-[#FFA500] hover:text-[#FFFFFF]\">Hover Test</button>
|
||||
</form>
|
||||
|
||||
<h2>Button Style Tests</h2>
|
||||
|
||||
<button>Normal, no-styling button.</button>
|
||||
|
||||
<h3>Corner Radius Variants</h3>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-none\">No Radius</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-sm\">Small (2px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded\">Default (4px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-md\">Medium (6px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-lg\">Large (8px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl\">Extra Large (12px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-2xl\">2XL (16px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-3xl\">3XL (24px)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-full\">Full (Pill)</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-[30px]\">Custom 30px</button>
|
||||
|
||||
<h3>Color Combinations</h3>
|
||||
<button style=\"bg-[#FF6B6B] text-[#FFFFFF] rounded-lg\">Red Background</button>
|
||||
<button style=\"bg-[#4ECDC4] text-[#2C3E50] rounded-lg\">Teal & Dark Text</button>
|
||||
<button style=\"bg-[#45B7D1] text-[#FFFFFF] rounded-lg\">Sky Blue</button>
|
||||
<button style=\"bg-[#96CEB4] text-[#2C3E50] rounded-lg\">Mint Green</button>
|
||||
<button style=\"bg-[#FFEAA7] text-[#2D3436] rounded-lg\">Yellow Cream</button>
|
||||
<button style=\"bg-[#DDA0DD] text-[#FFFFFF] rounded-lg\">Plum Purple</button>
|
||||
<button style=\"bg-[#98D8C8] text-[#2C3E50] rounded-lg\">Seafoam</button>
|
||||
|
||||
<h3>Hover Effects</h3>
|
||||
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] hover:text-[#F8F9FA]\">Blue Hover</button>
|
||||
<button style=\"bg-[#E67E22] text-[#FFFFFF] rounded-xl hover:bg-[#D35400] hover:text-[#ECF0F1]\">Orange Hover</button>
|
||||
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-full hover:bg-[#8E44AD] hover:text-[#F4F4F4]\">Purple Pill Hover</button>
|
||||
<button style=\"bg-[#1ABC9C] text-[#FFFFFF] rounded-2xl hover:bg-[#16A085]\">Turquoise Hover</button>
|
||||
|
||||
<h3>Advanced Hover Combinations</h3>
|
||||
<button style=\"bg-[#34495E] text-[#ECF0F1] rounded hover:bg-[#E74C3C] hover:text-[#FFFFFF]\">Dark to Red</button>
|
||||
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded-lg hover:bg-[#27AE60] hover:text-[#FFFFFF]\">Gold to Green</button>
|
||||
<button style=\"bg-[#FFFFFF] text-[#2C3E50] rounded-xl hover:bg-[#2C3E50] hover:text-[#FFFFFF]\">Light to Dark</button>
|
||||
|
||||
<h3>Text Color Focus</h3>
|
||||
<button style=\"text-[#E74C3C] rounded-lg\">Red Text Only</button>
|
||||
<button style=\"text-[#27AE60] rounded-lg\">Green Text Only</button>
|
||||
<button style=\"text-[#3498DB] rounded-lg\">Blue Text Only</button>
|
||||
<button style=\"text-[#9B59B6] rounded-full\">Purple Text Pill</button>
|
||||
|
||||
<h3>Mixed Styles</h3>
|
||||
<button style=\"bg-[#FF7675] text-[#FFFFFF] rounded-[15px] hover:bg-[#FD79A8] hover:text-[#2D3436]\">Custom Mix 1</button>
|
||||
<button style=\"bg-[#6C5CE7] text-[#DDD] rounded-3xl hover:bg-[#A29BFE] hover:text-[#2D3436]\">Custom Mix 2</button>
|
||||
<button style=\"bg-[#00B894] text-[#FFFFFF] rounded-[25px] hover:bg-[#00CEC9] hover:text-[#2D3436]\">Custom Mix 3</button>
|
||||
<button style=\"bg-[#0000ff] text-[#FFFFFF] rounded-[25px] hover:bg-[#ff0000] hover:text-[#2D3436]\">Blue normal, red hover</button>
|
||||
|
||||
<h3>Active State Tests</h3>
|
||||
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] active:bg-[#1F618D] active:text-[#F8F9FA]\">Blue with Active</button>
|
||||
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl hover:bg-[#C0392B] active:bg-[#A93226] active:text-[#ECF0F1]\">Red with Active</button>
|
||||
<button style=\"bg-[#27AE60] text-[#FFFFFF] rounded-full hover:bg-[#229954] active:bg-[#1E8449] active:text-[#D5DBDB]\">Green Pill Active</button>
|
||||
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded hover:bg-[#E67E22] hover:text-[#FFFFFF] active:bg-[#D35400] active:text-[#F7F9FC]\">Gold Multi-State</button>
|
||||
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-2xl active:bg-[#7D3C98] active:text-[#E8DAEF]\">Purple Active Only</button>
|
||||
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
|
||||
@@ -272,3 +272,13 @@ static func should_skip_sizing(node: Control, element: HTMLParser.HTMLElement, p
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
static func parse_radius(radius_str: String) -> int:
|
||||
if radius_str.ends_with("px"):
|
||||
return int(radius_str.replace("px", ""))
|
||||
elif radius_str.ends_with("rem"):
|
||||
return int(radius_str.replace("rem", "")) * 16
|
||||
elif radius_str.is_valid_float():
|
||||
return int(radius_str)
|
||||
else:
|
||||
return 0
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
extends Control
|
||||
|
||||
var current_element: HTMLParser.HTMLElement
|
||||
var current_parser: HTMLParser
|
||||
|
||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||
current_element = element
|
||||
current_parser = parser
|
||||
var button_node: Button = $ButtonNode
|
||||
|
||||
var button_text = element.text_content.strip_edges()
|
||||
@@ -34,9 +39,30 @@ func apply_button_styles(element: HTMLParser.HTMLElement, parser: HTMLParser, na
|
||||
return
|
||||
|
||||
var styles = parser.get_element_styles_internal(element, "")
|
||||
var hover_styles = parser.get_element_styles_internal(element, "hover")
|
||||
var active_styles = parser.get_element_styles_internal(element, "active")
|
||||
var button_node = $ButtonNode
|
||||
|
||||
# Apply text color with state-dependent colors
|
||||
apply_button_text_color(button_node, styles, hover_styles, active_styles)
|
||||
|
||||
# Apply background color (hover: + active:)
|
||||
if styles.has("background-color"):
|
||||
set_meta("custom_css_background_color", styles["background-color"])
|
||||
var normal_color = styles["background-color"] as Color
|
||||
var hover_color: Color = Color()
|
||||
var active_color: Color = Color()
|
||||
|
||||
if hover_styles.has("background-color"):
|
||||
hover_color = hover_styles["background-color"] as Color
|
||||
if active_styles.has("background-color"):
|
||||
active_color = active_styles["background-color"] as Color
|
||||
|
||||
apply_button_color_with_states(button_node, normal_color, hover_color, active_color)
|
||||
|
||||
# Apply corner radius
|
||||
if styles.has("border-radius"):
|
||||
var radius = StyleManager.parse_radius(styles["border-radius"])
|
||||
apply_button_radius(button_node, radius)
|
||||
|
||||
var width = null
|
||||
var height = null
|
||||
@@ -46,8 +72,6 @@ func apply_button_styles(element: HTMLParser.HTMLElement, parser: HTMLParser, na
|
||||
if styles.has("height"):
|
||||
height = StyleManager.parse_size(styles["height"])
|
||||
|
||||
var button_node = $ButtonNode
|
||||
|
||||
# Only apply size flags if there's explicit sizing
|
||||
if width != null or height != null:
|
||||
apply_size_and_flags(self, width, height)
|
||||
@@ -59,6 +83,65 @@ func apply_button_styles(element: HTMLParser.HTMLElement, parser: HTMLParser, na
|
||||
button_node.custom_minimum_size = Vector2.ZERO
|
||||
button_node.anchors_preset = Control.PRESET_FULL_RECT
|
||||
|
||||
func apply_button_text_color(button: Button, normal_styles: Dictionary, hover_styles: Dictionary, active_styles: Dictionary) -> void:
|
||||
var normal_color = normal_styles.get("color", Color.WHITE)
|
||||
var hover_color = hover_styles.get("color", normal_color)
|
||||
var active_color = active_styles.get("color", hover_color)
|
||||
|
||||
button.add_theme_color_override("font_color", normal_color)
|
||||
button.add_theme_color_override("font_hover_color", hover_color)
|
||||
button.add_theme_color_override("font_pressed_color", active_color)
|
||||
button.add_theme_color_override("font_focus_color", normal_color)
|
||||
|
||||
func apply_button_color_with_states(button: Button, normal_color: Color, hover_color: Color, active_color: Color) -> void:
|
||||
var existing_normal: StyleBoxFlat = button.get_theme_stylebox("normal") if button.has_theme_stylebox_override("normal") else null
|
||||
|
||||
var style_normal = StyleBoxFlat.new()
|
||||
var style_hover = StyleBoxFlat.new()
|
||||
var style_pressed = StyleBoxFlat.new()
|
||||
|
||||
var radius: int = existing_normal.corner_radius_top_left if existing_normal else 0
|
||||
|
||||
style_normal.set_corner_radius_all(radius)
|
||||
style_hover.set_corner_radius_all(radius)
|
||||
style_pressed.set_corner_radius_all(radius)
|
||||
|
||||
# Set normal color
|
||||
style_normal.bg_color = normal_color
|
||||
|
||||
# Set hover: color
|
||||
# If hover isn't default, use it
|
||||
if hover_color != Color():
|
||||
style_hover.bg_color = hover_color
|
||||
else:
|
||||
# If no hover, fallback to normal color
|
||||
style_hover.bg_color = normal_color
|
||||
|
||||
# Set active: color
|
||||
if active_color != Color():
|
||||
style_pressed.bg_color = active_color
|
||||
elif hover_color != Color():
|
||||
style_pressed.bg_color = hover_color # Fallback to hover if defined
|
||||
else:
|
||||
style_pressed.bg_color = normal_color # Final fallback to normal
|
||||
|
||||
button.add_theme_stylebox_override("normal", style_normal)
|
||||
button.add_theme_stylebox_override("hover", style_hover)
|
||||
button.add_theme_stylebox_override("pressed", style_pressed)
|
||||
|
||||
func apply_button_radius(button: Button, radius: int) -> void:
|
||||
var style_normal = button.get_theme_stylebox("normal")
|
||||
var style_hover = button.get_theme_stylebox("hover")
|
||||
var style_pressed = button.get_theme_stylebox("pressed")
|
||||
|
||||
style_normal.set_corner_radius_all(radius)
|
||||
style_hover.set_corner_radius_all(radius)
|
||||
style_pressed.set_corner_radius_all(radius)
|
||||
|
||||
button.add_theme_stylebox_override("normal", style_normal)
|
||||
button.add_theme_stylebox_override("hover", style_hover)
|
||||
button.add_theme_stylebox_override("pressed", style_pressed)
|
||||
|
||||
func apply_size_and_flags(ctrl: Control, width: Variant, height: Variant, reset_layout := false) -> void:
|
||||
if width != null or height != null:
|
||||
ctrl.custom_minimum_size = Vector2(
|
||||
|
||||
@@ -310,7 +310,7 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
var parent_styles = parser.get_element_styles_with_inheritance(element.parent, "", []) if element.parent else {}
|
||||
if parent_styles.has("width"):
|
||||
var parent_width = StyleManager.parse_size(parent_styles["width"])
|
||||
if parent_width != null:
|
||||
if parent_width:
|
||||
width = parent_width
|
||||
else:
|
||||
width = StyleManager.parse_size(styles["width"])
|
||||
@@ -323,23 +323,44 @@ func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
active_child = child
|
||||
break
|
||||
|
||||
if active_child and (width != null or height != null):
|
||||
var new_child_size = Vector2(
|
||||
width if width != null else active_child.custom_minimum_size.x,
|
||||
height if height != null else max(active_child.custom_minimum_size.y, active_child.size.y)
|
||||
)
|
||||
|
||||
active_child.custom_minimum_size = new_child_size
|
||||
|
||||
if width != null:
|
||||
active_child.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
if height != null:
|
||||
active_child.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
|
||||
if active_child.size.x < new_child_size.x or (new_child_size.y > 0 and active_child.size.y < new_child_size.y):
|
||||
active_child.size = new_child_size
|
||||
|
||||
custom_minimum_size = new_child_size
|
||||
if active_child:
|
||||
if width or height:
|
||||
# Explicit sizing from CSS
|
||||
var new_child_size = Vector2(
|
||||
width if width else active_child.custom_minimum_size.x,
|
||||
height if height else max(active_child.custom_minimum_size.y, active_child.size.y)
|
||||
)
|
||||
|
||||
active_child.custom_minimum_size = new_child_size
|
||||
|
||||
if width:
|
||||
active_child.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
if height:
|
||||
active_child.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
|
||||
if active_child.size.x < new_child_size.x or (new_child_size.y > 0 and active_child.size.y < new_child_size.y):
|
||||
active_child.size = new_child_size
|
||||
|
||||
custom_minimum_size = new_child_size
|
||||
|
||||
# Root Control adjusts size flags to match child
|
||||
if width:
|
||||
size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
else:
|
||||
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
if height:
|
||||
size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||
else:
|
||||
size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
else:
|
||||
# No explicit CSS sizing - sync root Control with child's natural size
|
||||
var child_natural_size = active_child.get_combined_minimum_size()
|
||||
if child_natural_size == Vector2.ZERO:
|
||||
child_natural_size = active_child.size
|
||||
|
||||
custom_minimum_size = child_natural_size
|
||||
size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
|
||||
if active_child.name == "DateButton":
|
||||
active_child.anchors_preset = Control.PRESET_TOP_LEFT
|
||||
|
||||
@@ -164,8 +164,15 @@ func create_element_node(element: HTMLParser.HTMLElement, parser: HTMLParser) ->
|
||||
# Apply flex ITEM properties
|
||||
StyleManager.apply_flex_item_properties(final_node, styles)
|
||||
|
||||
# Add child elements (but NOT for ul/ol which handle their own children)
|
||||
if element.tag_name != "ul" and element.tag_name != "ol":
|
||||
# Skip ul/ol and non-flex forms, they handle their own children
|
||||
var skip_general_processing = false
|
||||
|
||||
if element.tag_name == "ul" or element.tag_name == "ol":
|
||||
skip_general_processing = true
|
||||
elif element.tag_name == "form":
|
||||
skip_general_processing = not is_flex_container
|
||||
|
||||
if not skip_general_processing:
|
||||
for child_element in element.children:
|
||||
# Only add child nodes if the child is NOT an inline element
|
||||
# UNLESS the parent is a flex container (inline elements become flex items)
|
||||
@@ -205,13 +212,21 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
||||
node = SEPARATOR.instantiate()
|
||||
node.init(element)
|
||||
"form":
|
||||
node = FORM.instantiate()
|
||||
node.init(element)
|
||||
var form_styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
var is_flex_form = form_styles.has("display") and ("flex" in form_styles["display"])
|
||||
|
||||
# Forms need to manually process their children
|
||||
for child_element in element.children:
|
||||
var child_node = await create_element_node(child_element, parser)
|
||||
safe_add_child(node, child_node)
|
||||
if is_flex_form:
|
||||
# Don't create a form node here - return null so general processing takes over
|
||||
return null
|
||||
else:
|
||||
node = FORM.instantiate()
|
||||
node.init(element)
|
||||
|
||||
# Manually process children for non-flex forms
|
||||
for child_element in element.children:
|
||||
var child_node = await create_element_node(child_element, parser)
|
||||
if child_node:
|
||||
safe_add_child(node, child_node)
|
||||
"input":
|
||||
node = INPUT.instantiate()
|
||||
node.init(element, parser)
|
||||
|
||||
Reference in New Issue
Block a user