2025-07-31 16:13:21 +03:00
|
|
|
class_name BackgroundUtils
|
|
|
|
|
extends RefCounted
|
|
|
|
|
|
|
|
|
|
static func create_stylebox_from_styles(styles: Dictionary = {}, container: Control = null) -> StyleBoxFlat:
|
|
|
|
|
var style_box = StyleBoxFlat.new()
|
|
|
|
|
|
|
|
|
|
# Background color
|
|
|
|
|
var bg_color = null
|
|
|
|
|
if styles.has("background-color"):
|
|
|
|
|
bg_color = styles["background-color"]
|
|
|
|
|
elif container and container.has_meta("custom_css_background_color"):
|
|
|
|
|
bg_color = container.get_meta("custom_css_background_color")
|
|
|
|
|
|
|
|
|
|
if bg_color:
|
|
|
|
|
style_box.bg_color = bg_color
|
|
|
|
|
else:
|
|
|
|
|
style_box.bg_color = Color.TRANSPARENT
|
|
|
|
|
|
|
|
|
|
# Border radius
|
|
|
|
|
var border_radius = null
|
|
|
|
|
if styles.has("border-radius"):
|
|
|
|
|
border_radius = styles["border-radius"]
|
|
|
|
|
elif container and container.has_meta("custom_css_border_radius"):
|
|
|
|
|
border_radius = container.get_meta("custom_css_border_radius")
|
|
|
|
|
|
|
|
|
|
if border_radius:
|
|
|
|
|
var radius = StyleManager.parse_radius(border_radius)
|
|
|
|
|
style_box.corner_radius_top_left = radius
|
|
|
|
|
style_box.corner_radius_top_right = radius
|
|
|
|
|
style_box.corner_radius_bottom_left = radius
|
|
|
|
|
style_box.corner_radius_bottom_right = radius
|
|
|
|
|
|
2025-08-01 21:16:48 +03:00
|
|
|
# Border properties
|
|
|
|
|
var has_border = false
|
|
|
|
|
|
|
|
|
|
style_box.border_width_top = 0
|
|
|
|
|
style_box.border_width_right = 0
|
|
|
|
|
style_box.border_width_bottom = 0
|
|
|
|
|
style_box.border_width_left = 0
|
|
|
|
|
|
|
|
|
|
var general_border_width = null
|
|
|
|
|
if styles.has("border-width"):
|
|
|
|
|
general_border_width = styles["border-width"]
|
|
|
|
|
elif container and container.has_meta("custom_css_border_width"):
|
|
|
|
|
general_border_width = container.get_meta("custom_css_border_width")
|
|
|
|
|
|
|
|
|
|
if general_border_width:
|
|
|
|
|
has_border = true
|
|
|
|
|
var parsed_width = StyleManager.parse_size(general_border_width)
|
|
|
|
|
style_box.border_width_top = parsed_width
|
|
|
|
|
style_box.border_width_right = parsed_width
|
|
|
|
|
style_box.border_width_bottom = parsed_width
|
|
|
|
|
style_box.border_width_left = parsed_width
|
|
|
|
|
|
|
|
|
|
var individual_border_keys = [
|
|
|
|
|
["border-top-width", "border_width_top"],
|
|
|
|
|
["border-right-width", "border_width_right"],
|
|
|
|
|
["border-bottom-width", "border_width_bottom"],
|
|
|
|
|
["border-left-width", "border_width_left"]
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for pair in individual_border_keys:
|
|
|
|
|
var style_key = pair[0]
|
|
|
|
|
var property_name = pair[1]
|
|
|
|
|
var width = null
|
|
|
|
|
var meta_key = "custom_css_" + style_key.replace("-", "_")
|
|
|
|
|
|
|
|
|
|
if styles.has(style_key):
|
|
|
|
|
width = styles[style_key]
|
|
|
|
|
elif container and container.has_meta(meta_key):
|
|
|
|
|
width = container.get_meta(meta_key)
|
|
|
|
|
|
|
|
|
|
if width:
|
|
|
|
|
has_border = true
|
|
|
|
|
var parsed_width = StyleManager.parse_size(width)
|
|
|
|
|
style_box.set(property_name, parsed_width)
|
|
|
|
|
|
|
|
|
|
var border_color = Color.BLACK
|
|
|
|
|
if styles.has("border-color"):
|
|
|
|
|
border_color = styles["border-color"]
|
|
|
|
|
elif container and container.has_meta("custom_css_border_color"):
|
|
|
|
|
border_color = container.get_meta("custom_css_border_color")
|
|
|
|
|
|
|
|
|
|
if has_border:
|
|
|
|
|
style_box.border_color = border_color
|
|
|
|
|
|
2025-07-31 16:13:21 +03:00
|
|
|
# Padding as content margins
|
|
|
|
|
var has_padding = false
|
|
|
|
|
if styles.size() > 0:
|
|
|
|
|
has_padding = styles.has("padding") or styles.has("padding-top") or styles.has("padding-right") or styles.has("padding-bottom") or styles.has("padding-left")
|
|
|
|
|
elif container:
|
2025-08-05 18:01:16 +03:00
|
|
|
has_padding = container.has_meta("padding") or container.has_meta("padding_top") or container.has_meta("padding_right") or container.has_meta("padding_bottom") or container.has_meta("padding_left")
|
2025-07-31 16:13:21 +03:00
|
|
|
|
|
|
|
|
if has_padding:
|
|
|
|
|
# General padding
|
|
|
|
|
var padding_val = null
|
|
|
|
|
if styles.has("padding"):
|
|
|
|
|
padding_val = StyleManager.parse_size(styles["padding"])
|
|
|
|
|
elif container and container.has_meta("padding"):
|
|
|
|
|
padding_val = StyleManager.parse_size(container.get_meta("padding"))
|
|
|
|
|
|
|
|
|
|
if padding_val:
|
|
|
|
|
style_box.content_margin_left = padding_val
|
|
|
|
|
style_box.content_margin_right = padding_val
|
|
|
|
|
style_box.content_margin_top = padding_val
|
|
|
|
|
style_box.content_margin_bottom = padding_val
|
|
|
|
|
|
|
|
|
|
# Individual padding values override general padding
|
2025-08-05 18:01:16 +03:00
|
|
|
var padding_mappings = [["padding-left", "content_margin_left"], ["padding-right", "content_margin_right"], ["padding-top", "content_margin_top"], ["padding-bottom", "content_margin_bottom"]]
|
2025-07-31 16:13:21 +03:00
|
|
|
|
2025-08-05 18:01:16 +03:00
|
|
|
for mapping in padding_mappings:
|
|
|
|
|
var style_key = mapping[0]
|
|
|
|
|
var property_key = mapping[1]
|
|
|
|
|
var val = get_style_or_meta_value(styles, container, style_key)
|
2025-07-31 16:13:21 +03:00
|
|
|
|
2025-08-05 18:01:16 +03:00
|
|
|
if val != null:
|
|
|
|
|
style_box.set(property_key, val)
|
2025-07-31 16:13:21 +03:00
|
|
|
|
|
|
|
|
return style_box
|
|
|
|
|
|
|
|
|
|
# for AutoSizingFlexContainer
|
|
|
|
|
static func update_background_panel(container: Control) -> void:
|
|
|
|
|
var needs_background = container.has_meta("custom_css_background_color") or container.has_meta("custom_css_border_radius")
|
2025-08-05 18:01:16 +03:00
|
|
|
var needs_padding = container.has_meta("padding") or container.has_meta("padding_top") or container.has_meta("padding_right") or container.has_meta("padding_bottom") or container.has_meta("padding_left")
|
2025-07-31 16:13:21 +03:00
|
|
|
var background_panel = get_background_panel(container)
|
|
|
|
|
|
|
|
|
|
if needs_background or needs_padding:
|
|
|
|
|
if not background_panel:
|
|
|
|
|
background_panel = Panel.new()
|
|
|
|
|
background_panel.name = "BackgroundPanel"
|
|
|
|
|
background_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
|
background_panel.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
|
|
|
container.add_child(background_panel)
|
|
|
|
|
container.move_child(background_panel, 0) # first child
|
|
|
|
|
|
|
|
|
|
var style_box = create_stylebox_from_styles({}, container)
|
|
|
|
|
background_panel.add_theme_stylebox_override("panel", style_box)
|
|
|
|
|
|
|
|
|
|
elif background_panel:
|
|
|
|
|
background_panel.queue_free()
|
|
|
|
|
|
|
|
|
|
# Helper methods for AutoSizingFlexContainer
|
|
|
|
|
static func get_background_panel(container: Control) -> Panel:
|
|
|
|
|
for child in container.get_children():
|
|
|
|
|
if child.name == "BackgroundPanel" and child is Panel:
|
|
|
|
|
return child
|
|
|
|
|
return null
|
|
|
|
|
|
|
|
|
|
static func is_background_panel(node: Node) -> bool:
|
|
|
|
|
return node.name == "BackgroundPanel" and node is Panel
|
|
|
|
|
|
|
|
|
|
# for any other tag
|
2025-08-03 13:23:02 +03:00
|
|
|
static func create_panel_container_with_background(styles: Dictionary, hover_styles: Dictionary = {}) -> PanelContainer:
|
2025-07-31 16:13:21 +03:00
|
|
|
var panel_container = PanelContainer.new()
|
|
|
|
|
panel_container.name = "Div"
|
|
|
|
|
|
|
|
|
|
var vbox = VBoxContainer.new()
|
|
|
|
|
vbox.name = "VBoxContainer"
|
2025-08-03 13:23:02 +03:00
|
|
|
# Allow mouse events to pass through to the parent PanelContainer
|
|
|
|
|
vbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
2025-07-31 16:13:21 +03:00
|
|
|
panel_container.add_child(vbox)
|
|
|
|
|
|
|
|
|
|
var style_box = create_stylebox_from_styles(styles)
|
|
|
|
|
panel_container.add_theme_stylebox_override("panel", style_box)
|
2025-08-03 13:23:02 +03:00
|
|
|
|
|
|
|
|
# Add hover support if hover styles exist
|
|
|
|
|
if hover_styles.size() > 0:
|
|
|
|
|
setup_panel_hover_support(panel_container, styles, hover_styles)
|
|
|
|
|
|
2025-07-31 16:13:21 +03:00
|
|
|
return panel_container
|
|
|
|
|
|
2025-08-03 13:23:02 +03:00
|
|
|
static func setup_panel_hover_support(panel: PanelContainer, normal_styles: Dictionary, hover_styles: Dictionary):
|
|
|
|
|
var normal_stylebox = create_stylebox_from_styles(normal_styles)
|
|
|
|
|
|
|
|
|
|
# Merge normal styles with hover styles for the hover state
|
|
|
|
|
var merged_hover_styles = normal_styles.duplicate()
|
|
|
|
|
for key in hover_styles:
|
|
|
|
|
merged_hover_styles[key] = hover_styles[key]
|
|
|
|
|
var hover_stylebox = create_stylebox_from_styles(merged_hover_styles)
|
|
|
|
|
|
|
|
|
|
# Store references for the hover handlers
|
|
|
|
|
panel.set_meta("normal_stylebox", normal_stylebox)
|
|
|
|
|
panel.set_meta("hover_stylebox", hover_stylebox)
|
|
|
|
|
|
|
|
|
|
# Connect mouse events
|
|
|
|
|
panel.mouse_entered.connect(_on_panel_mouse_entered.bind(panel))
|
|
|
|
|
panel.mouse_exited.connect(_on_panel_mouse_exited.bind(panel))
|
|
|
|
|
|
|
|
|
|
static func _on_panel_mouse_entered(panel: PanelContainer):
|
|
|
|
|
if panel.has_meta("hover_stylebox"):
|
|
|
|
|
var hover_stylebox = panel.get_meta("hover_stylebox")
|
|
|
|
|
panel.add_theme_stylebox_override("panel", hover_stylebox)
|
|
|
|
|
|
|
|
|
|
static func _on_panel_mouse_exited(panel: PanelContainer):
|
|
|
|
|
if panel.has_meta("normal_stylebox"):
|
|
|
|
|
var normal_stylebox = panel.get_meta("normal_stylebox")
|
|
|
|
|
panel.add_theme_stylebox_override("panel", normal_stylebox)
|
|
|
|
|
|
2025-07-31 16:13:21 +03:00
|
|
|
static func needs_background_wrapper(styles: Dictionary) -> bool:
|
2025-08-01 21:16:48 +03:00
|
|
|
return styles.has("background-color") or styles.has("border-radius") or styles.has("padding") or styles.has("padding-top") or styles.has("padding-right") or styles.has("padding-bottom") or styles.has("padding-left") or styles.has("border-width") or styles.has("border-top-width") or styles.has("border-right-width") or styles.has("border-bottom-width") or styles.has("border-left-width") or styles.has("border-color") or styles.has("border-style") or styles.has("border-top-color") or styles.has("border-right-color") or styles.has("border-bottom-color") or styles.has("border-left-color")
|
2025-08-05 18:01:16 +03:00
|
|
|
|
|
|
|
|
static func get_style_or_meta_value(styles: Dictionary, container: Control, key: String):
|
|
|
|
|
if styles.has(key):
|
|
|
|
|
return StyleManager.parse_size(styles[key])
|
|
|
|
|
elif container and container.has_meta(key):
|
|
|
|
|
return StyleManager.parse_size(container.get_meta(key))
|
|
|
|
|
return null
|