diff --git a/Scenes/Tags/button.tscn b/Scenes/Tags/button.tscn
index bc1656d..008c96f 100644
--- a/Scenes/Tags/button.tscn
+++ b/Scenes/Tags/button.tscn
@@ -11,8 +11,9 @@ script = ExtResource("1_button")
[node name="ButtonNode" type="Button" parent="."]
layout_mode = 1
-offset_right = 100.0
-offset_bottom = 30.0
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_default_cursor_shape = 2
diff --git a/Scenes/Tags/input.tscn b/Scenes/Tags/input.tscn
index f8bdbd1..8e9f4ba 100644
--- a/Scenes/Tags/input.tscn
+++ b/Scenes/Tags/input.tscn
@@ -71,10 +71,8 @@ layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
-offset_left = -102.0
-offset_top = -24.0
-offset_right = -1893.0
-offset_bottom = -1020.0
+offset_right = -1791.0
+offset_bottom = -996.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
@@ -84,7 +82,7 @@ script = ExtResource("1_input")
[node name="LineEdit" type="LineEdit" parent="."]
visible = false
layout_mode = 1
-offset_right = 400.0
+offset_right = 200.0
offset_bottom = 35.0
theme = ExtResource("2_theme")
text = "test"
@@ -110,7 +108,6 @@ button_group = SubResource("ButtonGroup_06us3")
flat = true
[node name="ColorPickerButton" type="ColorPickerButton" parent="."]
-visible = false
layout_mode = 0
offset_right = 83.0
offset_bottom = 35.0
@@ -121,6 +118,7 @@ visible = false
layout_mode = 0
[node name="HSlider" type="HSlider" parent="."]
+visible = false
layout_mode = 0
offset_right = 200.0
offset_bottom = 35.0
diff --git a/Scripts/B9/HTMLParser.gd b/Scripts/B9/HTMLParser.gd
index c6a0889..b744ecb 100644
--- a/Scripts/B9/HTMLParser.gd
+++ b/Scripts/B9/HTMLParser.gd
@@ -123,18 +123,50 @@ func process_styles() -> void:
for child: CSSParser.CSSRule in parse_result.css_parser.stylesheet.rules:
print("INFO: for selector \"%s\" we have props: %s" % [child.selector, child.properties])
-func get_element_styles(element: HTMLElement, event: String = "") -> Dictionary:
+func get_element_styles_with_inheritance(element: HTMLElement, event: String = "", visited_elements: Array = []) -> Dictionary:
+ # Prevent infinite recursion
+ if element in visited_elements:
+ return {}
+
+ visited_elements.append(element)
+
+ var styles = {}
+
+ styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event))
+
+ # 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)
+ for property in inline_parsed:
+ styles[property] = inline_parsed[property]
+
+ # Inherit certain properties from parent elements
+ var inheritable_properties = ["width", "height", "font-size", "color", "font-family"]
+ var parent_element = element.parent
+ while parent_element and parent_element.tag_name != "body":
+ var parent_styles = get_element_styles_internal(parent_element, event)
+ for property in inheritable_properties:
+ # Only inherit if child doesn't already have this property
+ if not styles.has(property) and parent_styles.has(property):
+ styles[property] = parent_styles[property]
+ parent_element = parent_element.parent
+
+ return styles
+
+func get_element_styles_internal(element: HTMLElement, event: String = "") -> Dictionary:
var styles = {}
# Apply CSS rules
if parse_result.css_parser:
styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event))
- # Apply inline styles (higher priority)
+ # 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)
- styles.merge(inline_parsed)
+ for property in inline_parsed:
+ styles[property] = inline_parsed[property] # Force override
return styles
@@ -241,7 +273,7 @@ func get_all_stylesheets() -> Array[String]:
return get_attribute_values("style", "src")
func apply_element_styles(node: Control, element: HTMLElement, parser: HTMLParser) -> void:
- var styles = parser.get_element_styles(element)
+ var styles = parser.get_element_styles_with_inheritance(element, "", [])
if node.get("rich_text_label"):
var label = node.rich_text_label
var text = HTMLParser.get_bbcode_with_styles(element, styles, parser)
@@ -255,7 +287,7 @@ static func get_bbcode_with_styles(element: HTMLElement, styles: Dictionary, par
for child in element.children:
var child_styles = styles
if parser != null:
- child_styles = parser.get_element_styles(child)
+ child_styles = parser.get_element_styles_with_inheritance(child, "", [])
var child_content = HTMLParser.get_bbcode_with_styles(child, child_styles, parser)
match child.tag_name:
"b":
diff --git a/Scripts/Constants.gd b/Scripts/Constants.gd
index 73bc4eb..13f4660 100644
--- a/Scripts/Constants.gd
+++ b/Scripts/Constants.gd
@@ -21,7 +21,7 @@ a { text-[#1a0dab] }
pre { text-xl font-mono }
"""
-var HTML_CONTENT = "
+var HTML_CONTENT2 = "
My cool web
@@ -230,3 +230,68 @@ So
Stretch
".to_utf8_buffer()
+
+var HTML_CONTENT = """
+ Task Manager
+
+
+
+
+
+
+
+
+
+
+ 📝 My Task Manager
+ Keep track of your to-do list
+
+
+
+
+ ✅ Finish homework
+
+
+
+ ✍️ Write blog post
+
+
+
+ 💪 Gym workout
+
+
+
+
+
+
+
+ Add a New Task
+
+
+
+
+
+ Task Categories
+
+ 📚 Study
+ 💼 Work
+ 🏋️ Health
+
+
+""".to_utf8_buffer()
diff --git a/Scripts/StyleManager.gd b/Scripts/StyleManager.gd
index 7518e38..392ade3 100644
--- a/Scripts/StyleManager.gd
+++ b/Scripts/StyleManager.gd
@@ -12,10 +12,12 @@ static func parse_size(val):
if val.ends_with("%"):
# Not supported directly, skip
return null
+ if val == "full":
+ return null
return float(val)
static func apply_element_styles(node: Control, element: HTMLParser.HTMLElement, parser: HTMLParser) -> Control:
- var styles = parser.get_element_styles(element)
+ var styles = parser.get_element_styles_with_inheritance(element, "", [])
var label = null
if not (node is FlexContainer):
@@ -47,7 +49,6 @@ static func apply_element_styles(node: Control, element: HTMLParser.HTMLElement,
if styles.has("background-color"):
var target_node_for_bg = node if node is FlexContainer else label
if target_node_for_bg:
- print("SETTING BACKGROUND FOR ", target_node_for_bg, " TO COLOR: ", styles)
target_node_for_bg.set_meta("custom_css_background_color", styles["background-color"])
if target_node_for_bg.has_method("add_background_rect"):
target_node_for_bg.call_deferred("add_background_rect")
diff --git a/Scripts/Tags/button.gd b/Scripts/Tags/button.gd
index f3e22b3..fca494c 100644
--- a/Scripts/Tags/button.gd
+++ b/Scripts/Tags/button.gd
@@ -16,3 +16,40 @@ func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
-1,
button_node.get_theme_default_font_size()
) + Vector2(20, 10) # Add padding
+
+ apply_button_styles(element, parser)
+
+func apply_button_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
+ if not element or not parser:
+ return
+
+ StyleManager.apply_element_styles(self, element, parser)
+
+ var styles = parser.get_element_styles_with_inheritance(element, "", [])
+
+ var width = null
+ var height = null
+
+ if styles.has("width"):
+ width = StyleManager.parse_size(styles["width"])
+ if styles.has("height"):
+ height = StyleManager.parse_size(styles["height"])
+
+ var button_node = $ButtonNode
+
+ apply_size_and_flags(self, width, height)
+ apply_size_and_flags(button_node, width, height, false)
+
+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(
+ width if width != null else ctrl.custom_minimum_size.x,
+ height if height != null else ctrl.custom_minimum_size.y
+ )
+ if width != null:
+ ctrl.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
+ if height != null:
+ ctrl.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
+ if reset_layout:
+ ctrl.position = Vector2.ZERO
+ ctrl.anchors_preset = Control.PRESET_FULL_RECT
diff --git a/Scripts/Tags/input.gd b/Scripts/Tags/input.gd
index c854daa..fbc30ae 100644
--- a/Scripts/Tags/input.gd
+++ b/Scripts/Tags/input.gd
@@ -7,7 +7,7 @@ var custom_hex_input: LineEdit
var _file_text_content: String = ""
var _file_binary_content: PackedByteArray = PackedByteArray()
-func init(element: HTMLParser.HTMLElement) -> void:
+func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
var color_picker_button: ColorPickerButton = $ColorPickerButton
var picker: ColorPicker = color_picker_button.get_picker()
@@ -74,7 +74,6 @@ func init(element: HTMLParser.HTMLElement) -> void:
var active_child = get_node(active_child_name)
active_child.visible = true
- custom_minimum_size = active_child.size
match input_type:
"checkbox":
@@ -127,11 +126,16 @@ func init(element: HTMLParser.HTMLElement) -> void:
var line_edit = active_child as LineEdit
line_edit.secret = false
setup_text_input(line_edit, placeholder, value, minlength, maxlength, pattern)
+
+ apply_input_styles(element, parser)
func remove_unused_children(keep_child_name: String) -> void:
for child in get_children():
if child.name != keep_child_name:
+ child.visible = false
child.queue_free()
+ else:
+ child.visible = true
func setup_text_input(line_edit: LineEdit, placeholder: String, value: String, minlength: String, maxlength: String, pattern: String) -> void:
if placeholder: line_edit.placeholder_text = placeholder
@@ -289,3 +293,54 @@ func _on_file_selected(path: String) -> void:
file.close()
# TODO: when adding Lua, make these actually usable
+
+func apply_input_styles(element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
+ if not element or not parser:
+ return
+
+ StyleManager.apply_element_styles(self, element, parser)
+
+ var styles = parser.get_element_styles_with_inheritance(element, "", [])
+
+ var width = null
+ var height = null
+
+ if styles.has("width"):
+ if styles["width"] == "full":
+ 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:
+ width = parent_width
+ else:
+ width = StyleManager.parse_size(styles["width"])
+ if styles.has("height"):
+ height = StyleManager.parse_size(styles["height"])
+
+ var active_child = null
+ for child in get_children():
+ if child.visible:
+ 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.name == "DateButton":
+ active_child.anchors_preset = Control.PRESET_TOP_LEFT
+ active_child.position = Vector2.ZERO
diff --git a/Scripts/main.gd b/Scripts/main.gd
index 0183b5d..7acd8e2 100644
--- a/Scripts/main.gd
+++ b/Scripts/main.gd
@@ -120,7 +120,7 @@ func contains_hyperlink(element: HTMLParser.HTMLElement) -> bool:
return false
func create_element_node(element: HTMLParser.HTMLElement, parser: HTMLParser) -> Control:
- var styles = parser.get_element_styles(element)
+ var styles = parser.get_element_styles_with_inheritance(element, "", [])
var is_flex_container = styles.has("display") and ("flex" in styles["display"])
var final_node: Control
@@ -214,10 +214,10 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
safe_add_child(node, child_node)
"input":
node = INPUT.instantiate()
- node.init(element)
+ node.init(element, parser)
"button":
node = BUTTON.instantiate()
- node.init(element)
+ node.init(element, parser)
"span", "b", "i", "u", "small", "mark", "code", "a":
node = SPAN.instantiate()
node.init(element)