diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 7db6e1f045..168fc03cb7 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -15,6 +15,7 @@ from .defines import ( CONF_FREEZE, CONF_LVGL_ID, CONF_SHOW_SNOW, + PARTS, literal, ) from .lv_validation import lv_bool, lv_color, lv_image, opacity @@ -33,7 +34,7 @@ from .lvcode import ( lvgl_comp, static_cast, ) -from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA +from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA, base_update_schema from .types import ( LV_STATE, LvglAction, @@ -41,6 +42,7 @@ from .types import ( ObjUpdateAction, lv_disp_t, lv_group_t, + lv_obj_base_t, lv_obj_t, lv_pseudo_button_t, ) @@ -336,3 +338,14 @@ async def widget_focus(config, action_id, template_arg, args): lv.group_focus_freeze(group, True) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) return var + + +@automation.register_action( + "lvgl.widget.update", ObjUpdateAction, base_update_schema(lv_obj_base_t, PARTS) +) +async def obj_update_to_code(config, action_id, template_arg, args): + async def do_update(widget: Widget): + await set_obj_properties(widget, config) + + widgets = await get_widgets(config[CONF_ID]) + return await action_to_code(widgets, do_update, action_id, template_arg, args) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 271dbea19f..f0318dd17a 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -199,13 +199,12 @@ FLAG_SCHEMA = cv.Schema({cv.Optional(flag): lvalid.lv_bool for flag in df.OBJ_FL FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of) -def part_schema(widget_type: WidgetType): +def part_schema(parts): """ 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: + :param parts: The parts to include in the schema + :return: The schema """ - parts = widget_type.parts return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend( STATE_SCHEMA ) @@ -228,9 +227,15 @@ def automation_schema(typ: LvType): } -def create_modify_schema(widget_type): +def base_update_schema(widget_type, parts): + """ + Create a schema for updating a widgets style properties, states and flags + :param widget_type: The type of the ID + :param parts: The allowable parts to specify + :return: + """ return ( - part_schema(widget_type) + part_schema(parts) .extend( { cv.Required(CONF_ID): cv.ensure_list( @@ -245,7 +250,12 @@ def create_modify_schema(widget_type): } ) .extend(FLAG_SCHEMA) - .extend(widget_type.modify_schema) + ) + + +def create_modify_schema(widget_type): + return base_update_schema(widget_type.w_type, widget_type.parts).extend( + widget_type.modify_schema ) @@ -256,7 +266,7 @@ def obj_schema(widget_type: WidgetType): :return: """ return ( - part_schema(widget_type) + part_schema(widget_type.parts) .extend(FLAG_SCHEMA) .extend(LAYOUT_SCHEMA) .extend(ALIGN_TO_SCHEMA) @@ -341,7 +351,6 @@ FLEX_OBJ_SCHEMA = { cv.Optional(df.CONF_FLEX_GROW): cv.int_, } - DISP_BG_SCHEMA = cv.Schema( { cv.Optional(df.CONF_DISP_BG_IMAGE): cv.Any( diff --git a/esphome/components/lvgl/widgets/dropdown.py b/esphome/components/lvgl/widgets/dropdown.py index a6bfc6bb88..b32b5a2b2e 100644 --- a/esphome/components/lvgl/widgets/dropdown.py +++ b/esphome/components/lvgl/widgets/dropdown.py @@ -37,7 +37,7 @@ DROPDOWN_BASE_SCHEMA = cv.Schema( cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int, cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text, cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of, - cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec), + cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec.parts), } ) diff --git a/esphome/components/lvgl/widgets/keyboard.py b/esphome/components/lvgl/widgets/keyboard.py index ba7edb302e..d4a71078d0 100644 --- a/esphome/components/lvgl/widgets/keyboard.py +++ b/esphome/components/lvgl/widgets/keyboard.py @@ -16,6 +16,11 @@ KEYBOARD_SCHEMA = { cv.Optional(CONF_TEXTAREA): cv.use_id(lv_textarea_t), } +KEYBOARD_MODIFY_SCHEMA = { + cv.Optional(CONF_MODE): KEYBOARD_MODES.one_of, + cv.Optional(CONF_TEXTAREA): cv.use_id(lv_textarea_t), +} + lv_keyboard_t = LvType( "LvKeyboardType", parents=(KeyProvider, LvCompound), @@ -32,6 +37,7 @@ class KeyboardType(WidgetType): lv_keyboard_t, (CONF_MAIN, CONF_ITEMS), KEYBOARD_SCHEMA, + modify_schema=KEYBOARD_MODIFY_SCHEMA, ) def get_uses(self): @@ -41,7 +47,8 @@ class KeyboardType(WidgetType): lvgl_components_required.add("KEY_LISTENER") lvgl_components_required.add(CONF_KEYBOARD) add_lv_use("btnmatrix") - await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(config[CONF_MODE])) + if mode := config.get(CONF_MODE): + await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(mode)) if ta := await get_widgets(config, CONF_TEXTAREA): await w.set_property(CONF_TEXTAREA, ta[0].obj) diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index c3393940b6..82b2442378 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -51,7 +51,7 @@ MSGBOX_SCHEMA = container_schema( cv.Required(CONF_TITLE): STYLED_TEXT_SCHEMA, cv.Optional(CONF_BODY, default=""): STYLED_TEXT_SCHEMA, cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA), - cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec), + cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec.parts), cv.Optional(CONF_CLOSE_BUTTON, default=True): lv_bool, cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), } diff --git a/esphome/components/lvgl/widgets/obj.py b/esphome/components/lvgl/widgets/obj.py index afb4c97f33..ab22a5ce86 100644 --- a/esphome/components/lvgl/widgets/obj.py +++ b/esphome/components/lvgl/widgets/obj.py @@ -1,9 +1,5 @@ -from esphome import automation - -from ..automation import update_to_code from ..defines import CONF_MAIN, CONF_OBJ, CONF_SCROLLBAR -from ..schemas import create_modify_schema -from ..types import ObjUpdateAction, WidgetType, lv_obj_t +from ..types import WidgetType, lv_obj_t class ObjType(WidgetType): @@ -21,10 +17,3 @@ class ObjType(WidgetType): obj_spec = ObjType() - - -@automation.register_action( - "lvgl.widget.update", ObjUpdateAction, create_modify_schema(obj_spec) -) -async def obj_update_to_code(config, action_id, template_arg, args): - return await update_to_code(config, action_id, template_arg, args) diff --git a/esphome/components/lvgl/widgets/tabview.py b/esphome/components/lvgl/widgets/tabview.py index 226fc3f286..1d18ddd259 100644 --- a/esphome/components/lvgl/widgets/tabview.py +++ b/esphome/components/lvgl/widgets/tabview.py @@ -38,7 +38,7 @@ TABVIEW_SCHEMA = cv.Schema( }, ) ), - cv.Optional(CONF_TAB_STYLE): part_schema(buttonmatrix_spec), + cv.Optional(CONF_TAB_STYLE): part_schema(buttonmatrix_spec.parts), cv.Optional(CONF_POSITION, default="top"): DIRECTIONS.one_of, cv.Optional(CONF_SIZE, default="10%"): size, } diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 7c59cfa171..b3227bb96e 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -805,9 +805,24 @@ lvgl: - logger.log: format: "keyboard value %s" args: [text.c_str()] + - lvgl.keyboard.update: + id: lv_keyboard + hidden: true + on_ready: + - lvgl.widget.update: + id: lv_keyboard + - lvgl.keyboard.update: + id: lv_keyboard + hidden: true + - keyboard: id: lv_keyboard1 mode: special + on_ready: + lvgl.keyboard.update: + id: lv_keyboard1 + hidden: true + mode: text_lower font: - file: "gfonts://Roboto"