mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-29 22:24:26 +00:00 
			
		
		
		
	[lvgl] Use styles instead of object properties for themes (#9116)
This commit is contained in:
		| @@ -3,7 +3,6 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ID | ||||
| from esphome.core import ID | ||||
| from esphome.cpp_generator import MockObj | ||||
|  | ||||
| from .defines import ( | ||||
|     CONF_STYLE_DEFINITIONS, | ||||
| @@ -13,12 +12,13 @@ from .defines import ( | ||||
|     literal, | ||||
| ) | ||||
| 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 .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 ( | ||||
|     Widget, | ||||
|     add_widgets, | ||||
|     collect_parts, | ||||
|     set_obj_properties, | ||||
|     theme_widget_map, | ||||
|     wait_for_widgets, | ||||
| @@ -37,12 +37,18 @@ async def style_set(svar, style): | ||||
|             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): | ||||
|     """Convert styles to C__ code.""" | ||||
|     for style in config.get(CONF_STYLE_DEFINITIONS, ()): | ||||
|         svar = cg.new_Pvariable(style[CONF_ID]) | ||||
|         lv.style_init(svar) | ||||
|         await style_set(svar, style) | ||||
|         await create_style(style, style[CONF_ID].id) | ||||
|  | ||||
|  | ||||
| @automation.register_action( | ||||
| @@ -68,16 +74,18 @@ async def theme_to_code(config): | ||||
|     if theme := config.get(CONF_THEME): | ||||
|         add_lv_use(CONF_THEME) | ||||
|         for w_name, style in theme.items(): | ||||
|             if not isinstance(style, dict): | ||||
|                 continue | ||||
|  | ||||
|             lname = "lv_theme_apply_" + w_name | ||||
|             apply = lv_variable(lv_lambda_t, lname) | ||||
|             theme_widget_map[w_name] = apply | ||||
|             ow = Widget.create("obj", MockObj(ID("obj")), obj_spec) | ||||
|             async with LambdaContext([(lv_obj_t_ptr, "obj")], where=w_name) as context: | ||||
|                 await set_obj_properties(ow, style) | ||||
|             lv_assign(apply, await context.get_lambda()) | ||||
|             # Work around Python 3.10 bug with nested async comprehensions | ||||
|             # With Python 3.11 this could be simplified | ||||
|             styles = {} | ||||
|             for part, states in collect_parts(style).items(): | ||||
|                 styles[part] = { | ||||
|                     state: await create_style( | ||||
|                         props, | ||||
|                         "_lv_theme_style_" + w_name + "_" + part + "_" + state, | ||||
|                     ) | ||||
|                     for state, props in states.items() | ||||
|                 } | ||||
|             theme_widget_map[w_name] = styles | ||||
|  | ||||
|  | ||||
| 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.core import ID, TimePeriod | ||||
| from esphome.coroutine import FakeAwaitable | ||||
| from esphome.cpp_generator import CallExpression, MockObj | ||||
| from esphome.cpp_generator import MockObj | ||||
|  | ||||
| from ..defines import ( | ||||
|     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) | ||||
|     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 add_widgets(w, w_cnfig) | ||||
|     await spec.to_code(w, w_cnfig) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user