mirror of
https://github.com/esphome/esphome.git
synced 2025-07-29 06:36:45 +00:00
[lvgl] Use styles instead of object properties for themes (#9116)
This commit is contained in:
parent
78ec9856fb
commit
41c7852128
@ -3,7 +3,6 @@ import esphome.codegen as cg
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
from esphome.core import ID
|
from esphome.core import ID
|
||||||
from esphome.cpp_generator import MockObj
|
|
||||||
|
|
||||||
from .defines import (
|
from .defines import (
|
||||||
CONF_STYLE_DEFINITIONS,
|
CONF_STYLE_DEFINITIONS,
|
||||||
@ -13,12 +12,13 @@ from .defines import (
|
|||||||
literal,
|
literal,
|
||||||
)
|
)
|
||||||
from .helpers import add_lv_use
|
from .helpers import add_lv_use
|
||||||
from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable
|
from .lvcode import LambdaContext, LocalVariable, lv
|
||||||
from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, STYLE_REMAP
|
from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, STYLE_REMAP
|
||||||
from .types import ObjUpdateAction, lv_lambda_t, lv_obj_t, lv_obj_t_ptr, lv_style_t
|
from .types import ObjUpdateAction, lv_obj_t, lv_style_t
|
||||||
from .widgets import (
|
from .widgets import (
|
||||||
Widget,
|
Widget,
|
||||||
add_widgets,
|
add_widgets,
|
||||||
|
collect_parts,
|
||||||
set_obj_properties,
|
set_obj_properties,
|
||||||
theme_widget_map,
|
theme_widget_map,
|
||||||
wait_for_widgets,
|
wait_for_widgets,
|
||||||
@ -37,12 +37,18 @@ async def style_set(svar, style):
|
|||||||
lv.call(f"style_set_{remapped_prop}", svar, literal(value))
|
lv.call(f"style_set_{remapped_prop}", svar, literal(value))
|
||||||
|
|
||||||
|
|
||||||
|
async def create_style(style, id_name):
|
||||||
|
style_id = ID(id_name, True, lv_style_t)
|
||||||
|
svar = cg.new_Pvariable(style_id)
|
||||||
|
lv.style_init(svar)
|
||||||
|
await style_set(svar, style)
|
||||||
|
return svar
|
||||||
|
|
||||||
|
|
||||||
async def styles_to_code(config):
|
async def styles_to_code(config):
|
||||||
"""Convert styles to C__ code."""
|
"""Convert styles to C__ code."""
|
||||||
for style in config.get(CONF_STYLE_DEFINITIONS, ()):
|
for style in config.get(CONF_STYLE_DEFINITIONS, ()):
|
||||||
svar = cg.new_Pvariable(style[CONF_ID])
|
await create_style(style, style[CONF_ID].id)
|
||||||
lv.style_init(svar)
|
|
||||||
await style_set(svar, style)
|
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
@ -68,16 +74,18 @@ async def theme_to_code(config):
|
|||||||
if theme := config.get(CONF_THEME):
|
if theme := config.get(CONF_THEME):
|
||||||
add_lv_use(CONF_THEME)
|
add_lv_use(CONF_THEME)
|
||||||
for w_name, style in theme.items():
|
for w_name, style in theme.items():
|
||||||
if not isinstance(style, dict):
|
# Work around Python 3.10 bug with nested async comprehensions
|
||||||
continue
|
# With Python 3.11 this could be simplified
|
||||||
|
styles = {}
|
||||||
lname = "lv_theme_apply_" + w_name
|
for part, states in collect_parts(style).items():
|
||||||
apply = lv_variable(lv_lambda_t, lname)
|
styles[part] = {
|
||||||
theme_widget_map[w_name] = apply
|
state: await create_style(
|
||||||
ow = Widget.create("obj", MockObj(ID("obj")), obj_spec)
|
props,
|
||||||
async with LambdaContext([(lv_obj_t_ptr, "obj")], where=w_name) as context:
|
"_lv_theme_style_" + w_name + "_" + part + "_" + state,
|
||||||
await set_obj_properties(ow, style)
|
)
|
||||||
lv_assign(apply, await context.get_lambda())
|
for state, props in states.items()
|
||||||
|
}
|
||||||
|
theme_widget_map[w_name] = styles
|
||||||
|
|
||||||
|
|
||||||
async def add_top_layer(lv_component, config):
|
async def add_top_layer(lv_component, config):
|
||||||
|
@ -6,7 +6,7 @@ from esphome.config_validation import Invalid
|
|||||||
from esphome.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
from esphome.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
||||||
from esphome.core import ID, TimePeriod
|
from esphome.core import ID, TimePeriod
|
||||||
from esphome.coroutine import FakeAwaitable
|
from esphome.coroutine import FakeAwaitable
|
||||||
from esphome.cpp_generator import CallExpression, MockObj
|
from esphome.cpp_generator import MockObj
|
||||||
|
|
||||||
from ..defines import (
|
from ..defines import (
|
||||||
CONF_FLEX_ALIGN_CROSS,
|
CONF_FLEX_ALIGN_CROSS,
|
||||||
@ -453,7 +453,17 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent):
|
|||||||
|
|
||||||
w = Widget.create(wid, var, spec, w_cnfig)
|
w = Widget.create(wid, var, spec, w_cnfig)
|
||||||
if theme := theme_widget_map.get(w_type):
|
if theme := theme_widget_map.get(w_type):
|
||||||
lv_add(CallExpression(theme, w.obj))
|
for part, states in theme.items():
|
||||||
|
part = "LV_PART_" + part.upper()
|
||||||
|
for state, style in states.items():
|
||||||
|
state = "LV_STATE_" + state.upper()
|
||||||
|
if state == "LV_STATE_DEFAULT":
|
||||||
|
lv_state = literal(part)
|
||||||
|
elif part == "LV_PART_MAIN":
|
||||||
|
lv_state = literal(state)
|
||||||
|
else:
|
||||||
|
lv_state = join_enums((state, part))
|
||||||
|
lv.obj_add_style(w.obj, style, lv_state)
|
||||||
await set_obj_properties(w, w_cnfig)
|
await set_obj_properties(w, w_cnfig)
|
||||||
await add_widgets(w, w_cnfig)
|
await add_widgets(w, w_cnfig)
|
||||||
await spec.to_code(w, w_cnfig)
|
await spec.to_code(w, w_cnfig)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user