mirror of
https://github.com/esphome/esphome.git
synced 2025-09-06 13:22:19 +01:00
LVGL stage 2 (#7129)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -3,15 +3,9 @@ from esphome.const import CONF_ARGS, CONF_FORMAT, CONF_ID, CONF_STATE, CONF_TYPE
|
||||
from esphome.schema_extractors import SCHEMA_EXTRACT
|
||||
|
||||
from . import defines as df, lv_validation as lvalid, types as ty
|
||||
from .defines import WIDGET_PARTS
|
||||
from .helpers import (
|
||||
REQUIRED_COMPONENTS,
|
||||
add_lv_use,
|
||||
requires_component,
|
||||
validate_printf,
|
||||
)
|
||||
from .helpers import add_lv_use, requires_component, validate_printf
|
||||
from .lv_validation import lv_font
|
||||
from .types import WIDGET_TYPES, get_widget_type
|
||||
from .types import WIDGET_TYPES, WidgetType
|
||||
|
||||
# A schema for text properties
|
||||
TEXT_SCHEMA = cv.Schema(
|
||||
@@ -46,9 +40,9 @@ STYLE_PROPS = {
|
||||
"bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of,
|
||||
"bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of,
|
||||
"bg_grad_stop": lvalid.stop_value,
|
||||
"bg_img_opa": lvalid.opacity,
|
||||
"bg_img_recolor": lvalid.lv_color,
|
||||
"bg_img_recolor_opa": lvalid.opacity,
|
||||
"bg_image_opa": lvalid.opacity,
|
||||
"bg_image_recolor": lvalid.lv_color,
|
||||
"bg_image_recolor_opa": lvalid.opacity,
|
||||
"bg_main_stop": lvalid.stop_value,
|
||||
"bg_opa": lvalid.opacity,
|
||||
"border_color": lvalid.lv_color,
|
||||
@@ -60,8 +54,8 @@ STYLE_PROPS = {
|
||||
"border_width": cv.positive_int,
|
||||
"clip_corner": lvalid.lv_bool,
|
||||
"height": lvalid.size,
|
||||
"img_recolor": lvalid.lv_color,
|
||||
"img_recolor_opa": lvalid.opacity,
|
||||
"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,
|
||||
@@ -108,12 +102,21 @@ STYLE_PROPS = {
|
||||
"max_width": lvalid.pixels_or_percent,
|
||||
"min_height": lvalid.pixels_or_percent,
|
||||
"min_width": lvalid.pixels_or_percent,
|
||||
"radius": cv.Any(lvalid.size, df.LvConstant("LV_RADIUS_", "CIRCLE").one_of),
|
||||
"radius": lvalid.radius,
|
||||
"width": lvalid.size,
|
||||
"x": lvalid.pixels_or_percent,
|
||||
"y": lvalid.pixels_or_percent,
|
||||
}
|
||||
|
||||
STYLE_REMAP = {
|
||||
"bg_image_opa": "bg_img_opa",
|
||||
"bg_image_recolor": "bg_img_recolor",
|
||||
"bg_image_recolor_opa": "bg_img_recolor_opa",
|
||||
"bg_image_src": "bg_img_src",
|
||||
"image_recolor": "img_recolor",
|
||||
"image_recolor_opa": "img_recolor_opa",
|
||||
}
|
||||
|
||||
# Complete object style schema
|
||||
STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend(
|
||||
{
|
||||
@@ -132,25 +135,23 @@ SET_STATE_SCHEMA = cv.Schema(
|
||||
{cv.Optional(state): lvalid.lv_bool for state in df.STATES}
|
||||
)
|
||||
# Setting object flags
|
||||
FLAG_SCHEMA = cv.Schema({cv.Optional(flag): cv.boolean for flag in df.OBJ_FLAGS})
|
||||
FLAG_SCHEMA = cv.Schema({cv.Optional(flag): lvalid.lv_bool for flag in df.OBJ_FLAGS})
|
||||
FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of)
|
||||
|
||||
|
||||
def part_schema(widget_type):
|
||||
def part_schema(widget_type: WidgetType):
|
||||
"""
|
||||
Generate a schema for the various parts (e.g. main:, indicator:) of a widget type
|
||||
:param widget_type: The type of widget to generate for
|
||||
:return:
|
||||
"""
|
||||
parts = WIDGET_PARTS.get(widget_type)
|
||||
if parts is None:
|
||||
parts = (df.CONF_MAIN,)
|
||||
parts = widget_type.parts
|
||||
return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend(
|
||||
STATE_SCHEMA
|
||||
)
|
||||
|
||||
|
||||
def obj_schema(widget_type: str):
|
||||
def obj_schema(widget_type: WidgetType):
|
||||
"""
|
||||
Create a schema for a widget type itself i.e. no allowance for children
|
||||
:param widget_type:
|
||||
@@ -187,13 +188,12 @@ STYLED_TEXT_SCHEMA = cv.maybe_simple_value(
|
||||
STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT
|
||||
)
|
||||
|
||||
|
||||
ALL_STYLES = {
|
||||
**STYLE_PROPS,
|
||||
}
|
||||
|
||||
|
||||
def container_validator(schema, widget_type):
|
||||
def container_validator(schema, widget_type: WidgetType):
|
||||
"""
|
||||
Create a validator for a container given the widget type
|
||||
:param schema: Base schema to extend
|
||||
@@ -203,13 +203,16 @@ def container_validator(schema, widget_type):
|
||||
|
||||
def validator(value):
|
||||
result = schema
|
||||
if w_sch := WIDGET_TYPES[widget_type].schema:
|
||||
if w_sch := widget_type.schema:
|
||||
result = result.extend(w_sch)
|
||||
if value and (layout := value.get(df.CONF_LAYOUT)):
|
||||
if not isinstance(layout, dict):
|
||||
raise cv.Invalid("Layout value must be a dict")
|
||||
ltype = layout.get(CONF_TYPE)
|
||||
add_lv_use(ltype)
|
||||
result = result.extend(
|
||||
{cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())}
|
||||
)
|
||||
if value == SCHEMA_EXTRACT:
|
||||
return result
|
||||
return result(value)
|
||||
@@ -217,7 +220,7 @@ def container_validator(schema, widget_type):
|
||||
return validator
|
||||
|
||||
|
||||
def container_schema(widget_type, extras=None):
|
||||
def container_schema(widget_type: WidgetType, extras=None):
|
||||
"""
|
||||
Create a schema for a container widget of a given type. All obj properties are available, plus
|
||||
the extras passed in, plus any defined for the specific widget being specified.
|
||||
@@ -225,15 +228,16 @@ def container_schema(widget_type, extras=None):
|
||||
:param extras: Additional options to be made available, e.g. layout properties for children
|
||||
:return: The schema for this type of widget.
|
||||
"""
|
||||
lv_type = get_widget_type(widget_type)
|
||||
schema = obj_schema(widget_type).extend({cv.GenerateID(): cv.declare_id(lv_type)})
|
||||
schema = obj_schema(widget_type).extend(
|
||||
{cv.GenerateID(): cv.declare_id(widget_type.w_type)}
|
||||
)
|
||||
if extras:
|
||||
schema = schema.extend(extras)
|
||||
# Delayed evaluation for recursion
|
||||
return container_validator(schema, widget_type)
|
||||
|
||||
|
||||
def widget_schema(widget_type, extras=None):
|
||||
def widget_schema(widget_type: WidgetType, extras=None):
|
||||
"""
|
||||
Create a schema for a given widget type
|
||||
:param widget_type: The name of the widget
|
||||
@@ -241,9 +245,9 @@ def widget_schema(widget_type, extras=None):
|
||||
:return:
|
||||
"""
|
||||
validator = container_schema(widget_type, extras=extras)
|
||||
if required := REQUIRED_COMPONENTS.get(widget_type):
|
||||
if required := widget_type.required_component:
|
||||
validator = cv.All(validator, requires_component(required))
|
||||
return cv.Exclusive(widget_type, df.CONF_WIDGETS), validator
|
||||
return cv.Exclusive(widget_type.name, df.CONF_WIDGETS), validator
|
||||
|
||||
|
||||
# All widget schemas must be defined before this is called.
|
||||
@@ -257,4 +261,4 @@ def any_widget_schema(extras=None):
|
||||
:param extras: Additional schema to be applied to each generated one
|
||||
:return:
|
||||
"""
|
||||
return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_PARTS))
|
||||
return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_TYPES.values()))
|
||||
|
Reference in New Issue
Block a user