1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-21 12:42:21 +01:00

[lvgl] Implement canvas widget (#8504)

This commit is contained in:
Clyde Stubbs
2025-04-09 10:15:39 +10:00
committed by GitHub
parent 8c5adfb33f
commit 1f7a84cc8e
10 changed files with 631 additions and 67 deletions

View File

@@ -87,31 +87,29 @@ ENCODER_SCHEMA = cv.Schema(
}
)
POINT_SCHEMA = cv.Schema(
{
cv.Required(CONF_X): cv.templatable(cv.int_),
cv.Required(CONF_Y): cv.templatable(cv.int_),
}
)
def point_shorthand(value):
def point_schema(value):
"""
A shorthand for a point in the form of x,y
:param value: The value to check
:return: The value as a tuple of x,y
"""
if isinstance(value, str):
try:
x, y = map(int, value.split(","))
return {CONF_X: x, CONF_Y: y}
except ValueError:
pass
raise cv.Invalid("Invalid point format, should be <x_value>, <y_value>")
POINT_SCHEMA = cv.Any(
cv.Schema(
{
cv.Required(CONF_X): cv.templatable(cv.int_),
cv.Required(CONF_Y): cv.templatable(cv.int_),
}
),
point_shorthand,
)
if isinstance(value, dict):
return POINT_SCHEMA(value)
try:
x, y = map(int, value.split(","))
return {CONF_X: x, CONF_Y: y}
except ValueError:
pass
# not raising this in the catch block because pylint doesn't like it
raise cv.Invalid("Invalid point format, should be <x_int>, <y_int>")
# All LVGL styles and their validators
@@ -132,6 +130,7 @@ STYLE_PROPS = {
"bg_image_recolor": lvalid.lv_color,
"bg_image_recolor_opa": lvalid.opacity,
"bg_image_src": lvalid.lv_image,
"bg_image_tiled": lvalid.lv_bool,
"bg_main_stop": lvalid.stop_value,
"bg_opa": lvalid.opacity,
"border_color": lvalid.lv_color,
@@ -146,9 +145,9 @@ STYLE_PROPS = {
"height": lvalid.size,
"image_recolor": lvalid.lv_color,
"image_recolor_opa": lvalid.opacity,
"line_width": cv.positive_int,
"line_dash_width": cv.positive_int,
"line_dash_gap": cv.positive_int,
"line_width": lvalid.lv_positive_int,
"line_dash_width": lvalid.lv_positive_int,
"line_dash_gap": lvalid.lv_positive_int,
"line_rounded": lvalid.lv_bool,
"line_color": lvalid.lv_color,
"opa": lvalid.opacity,
@@ -176,8 +175,8 @@ STYLE_PROPS = {
"LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH"
).several_of,
"text_font": lv_font,
"text_letter_space": cv.positive_int,
"text_line_space": cv.positive_int,
"text_letter_space": lvalid.lv_positive_int,
"text_line_space": lvalid.lv_positive_int,
"text_opa": lvalid.opacity,
"transform_angle": lvalid.lv_angle,
"transform_height": lvalid.pixels_or_percent,
@@ -201,10 +200,15 @@ STYLE_REMAP = {
"bg_image_recolor": "bg_img_recolor",
"bg_image_recolor_opa": "bg_img_recolor_opa",
"bg_image_src": "bg_img_src",
"bg_image_tiled": "bg_img_tiled",
"image_recolor": "img_recolor",
"image_recolor_opa": "img_recolor_opa",
}
cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
# Complete object style schema
STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend(
{
@@ -215,6 +219,16 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex
}
)
# Also allow widget specific properties for use in style definitions
FULL_STYLE_SCHEMA = STYLE_SCHEMA.extend(
{
cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
cv.Optional(df.CONF_PAD_ROW): lvalid.pixels,
cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels,
}
)
# Object states. Top level properties apply to MAIN
STATE_SCHEMA = cv.Schema(
{cv.Optional(state): STYLE_SCHEMA for state in df.STATES}
@@ -346,10 +360,6 @@ grid_spec = cv.Any(
lvalid.size, df.LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_space
)
cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
LAYOUT_SCHEMA = {
cv.Optional(df.CONF_LAYOUT): cv.typed_schema(
{