[lvgl] Animation updates and debug borders option (#19420)

This commit is contained in:
Clyde Stubbs
2026-09-30 07:20:13 +10:00
committed by GitHub
parent 662c7db222
commit 35d41adf86
15 changed files with 271 additions and 3 deletions
@@ -0,0 +1,36 @@
esphome:
name: test-debug-outline
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
data_rate: 20MHz
model: st7735
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
lvgl:
debug_outline: true
widgets:
- obj:
id: root_obj
widgets:
- label:
id: title_label
text: Title
- button:
id: ok_button
widgets:
- label:
text: OK
@@ -0,0 +1,35 @@
esphome:
name: test-debug-outline
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
data_rate: 20MHz
model: st7735
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
lvgl:
widgets:
- obj:
id: root_obj
widgets:
- label:
id: title_label
text: Title
- button:
id: ok_button
widgets:
- label:
text: OK
@@ -191,6 +191,24 @@ class TestTimingSchema:
result = TIMING_SCHEMA({"type": "ease_in_out", "weight": 0.5})
assert result["weight"] == pytest.approx(0.5)
def test_ease_in_default_weight(self) -> None:
result = TIMING_SCHEMA("ease_in")
assert result["type"] == "ease_in"
assert result["weight"] == pytest.approx(1.0)
def test_ease_in_custom_weight(self) -> None:
result = TIMING_SCHEMA({"type": "ease_in", "weight": 0.5})
assert result["weight"] == pytest.approx(0.5)
def test_ease_out_default_weight(self) -> None:
result = TIMING_SCHEMA("ease_out")
assert result["type"] == "ease_out"
assert result["weight"] == pytest.approx(1.0)
def test_ease_out_custom_weight(self) -> None:
result = TIMING_SCHEMA({"type": "ease_out", "weight": 0.5})
assert result["weight"] == pytest.approx(0.5)
def test_gravity_defaults(self) -> None:
result = TIMING_SCHEMA("gravity")
assert result["type"] == "gravity"
@@ -0,0 +1,33 @@
"""Tests for the LVGL ``debug_outline`` option code generation."""
from __future__ import annotations
import re
_OUTLINE_COLOR_RE = re.compile(
r"lv_obj_set_style_outline_color\(.+?, (lv_color_make\(.+?\)),"
)
_OUTLINE_WIDTH_RE = re.compile(r"lv_obj_set_style_outline_width\(")
_OUTLINE_PAD_RE = re.compile(r"lv_obj_set_style_outline_pad\(.+?, 0,")
class TestDebugOutlineCodeGeneration:
"""Verify that ``debug_outline`` outlines every widget in a distinct colour."""
def test_debug_outline_styles_every_widget(
self, generate_main, component_config_path
):
"""Four widgets are declared, so four outlines with different colours appear."""
main_cpp = generate_main(component_config_path("debug_outline.yaml"))
assert len(_OUTLINE_WIDTH_RE.findall(main_cpp)) == 4
assert len(_OUTLINE_PAD_RE.findall(main_cpp)) == 4
colors = _OUTLINE_COLOR_RE.findall(main_cpp)
assert len(colors) == 4
assert len(set(colors)) == 4
def test_debug_outline_default_emits_nothing(
self, generate_main, component_config_path
):
"""Without ``debug_outline`` no outline styles are generated."""
main_cpp = generate_main(component_config_path("no_debug_outline.yaml"))
assert "lv_obj_set_style_outline_" not in main_cpp
@@ -9,13 +9,16 @@ from esphome.components.lvgl.schemas import theme_schema
from esphome.config_validation import Invalid
def _config(displays: list[str], theme: dict | None = None) -> dict:
def _config(
displays: list[str], theme: dict | None = None, debug_outline: bool = False
) -> dict:
config = {
df.CONF_DISPLAYS: displays,
"log_level": "WARN",
"color_depth": 16,
"byte_order": "big_endian",
df.CONF_TRANSPARENCY_KEY: 0x000400,
df.CONF_DEBUG_OUTLINE: debug_outline,
}
if theme is not None:
config[df.CONF_THEME] = theme
@@ -53,3 +56,20 @@ class TestThemeOnMultipleInstances:
def test_passes_when_no_instance_has_theme(self) -> None:
configs = [_config(["disp_a"]), _config(["disp_b"])]
multi_conf_validate(configs)
class TestDebugOutlineOnMultipleInstances:
def test_raises_when_instances_differ(self) -> None:
configs = [
_config(["disp_a"], debug_outline=True),
_config(["disp_b"], debug_outline=False),
]
with pytest.raises(Invalid, match="'debug_outline' must be the same"):
multi_conf_validate(configs)
def test_passes_when_instances_match(self) -> None:
configs = [
_config(["disp_a"], debug_outline=True),
_config(["disp_b"], debug_outline=True),
]
multi_conf_validate(configs)
@@ -0,0 +1,34 @@
# Kept separate from the main lvgl-package.yaml so that enabling debug_outline
# here doesn't add its extra style calls to the memory-impact baseline that
# every other lvgl test change is measured against.
packages:
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
display:
- platform: mipi_spi
spi_id: spi_bus
model: st7789v
id: debug_outline_display
dimensions:
width: 240
height: 320
data_rate: 80MHz
cs_pin: GPIO22
dc_pin: GPIO21
auto_clear_enabled: false
update_interval: never
lvgl:
debug_outline: true
displays:
- debug_outline_display
widgets:
- obj:
id: debug_outline_root
widgets:
- label:
text: Title
- button:
widgets:
- label:
text: OK
+4
View File
@@ -40,6 +40,10 @@ lvgl:
- round_trip
- type: ease_in_out
weight: 0.5
- type: ease_in
weight: 0.3
- type: ease_out
weight: 0.7
on_start:
- logger.log: anim started
on_stop: