diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index c64ffcb5f2..07f5d94543 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -61,7 +61,14 @@ from .types import ( lv_style_t, lvgl_ns, ) -from .widgets import Widget, add_widgets, get_scr_act, set_obj_properties, styles_used +from .widgets import ( + LvScrActType, + Widget, + add_widgets, + get_scr_act, + set_obj_properties, + styles_used, +) from .widgets.animimg import animimg_spec from .widgets.arc import arc_spec from .widgets.button import button_spec @@ -318,7 +325,7 @@ async def to_code(configs): config[df.CONF_RESUME_ON_INPUT], ) await cg.register_component(lv_component, config) - Widget.create(config[CONF_ID], lv_component, obj_spec, config) + Widget.create(config[CONF_ID], lv_component, LvScrActType(), config) lv_scr_act = get_scr_act(lv_component) async with LvContext(): @@ -391,7 +398,7 @@ FINAL_VALIDATE_SCHEMA = final_validation LVGL_SCHEMA = ( cv.polling_component_schema("1s") - .extend(obj_schema(obj_spec)) + .extend(obj_schema(LvScrActType())) .extend( { cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 733a6bc180..119a358e1d 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -146,6 +146,8 @@ TYPE_FLEX = "flex" TYPE_GRID = "grid" TYPE_NONE = "none" +DIRECTIONS = LvConstant("LV_DIR_", "LEFT", "RIGHT", "BOTTOM", "TOP") + LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [ "dejavu_16_persian_hebrew", "simsun_16_cjk", @@ -169,9 +171,13 @@ LV_EVENT_MAP = { "CANCEL": "CANCEL", "ALL_EVENTS": "ALL", "CHANGE": "VALUE_CHANGED", + "GESTURE": "GESTURE", } LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP) +SWIPE_TRIGGERS = tuple( + f"on_swipe_{x.lower()}" for x in DIRECTIONS.choices + ("up", "down") +) LV_ANIM = LvConstant( @@ -250,7 +256,6 @@ KEYBOARD_MODES = LvConstant( "NUMBER", ) ROLLER_MODES = LvConstant("LV_ROLLER_MODE_", "NORMAL", "INFINITE") -DIRECTIONS = LvConstant("LV_DIR_", "LEFT", "RIGHT", "BOTTOM", "TOP") TILE_DIRECTIONS = DIRECTIONS.extend("HOR", "VER", "ALL") CHILD_ALIGNMENTS = LvConstant( "LV_ALIGN_", diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index f0318dd17a..ae50d5b2e1 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -211,10 +211,9 @@ def part_schema(parts): def automation_schema(typ: LvType): + events = df.LV_EVENT_TRIGGERS + df.SWIPE_TRIGGERS if typ.has_on_value: - events = df.LV_EVENT_TRIGGERS + (CONF_ON_VALUE,) - else: - events = df.LV_EVENT_TRIGGERS + events = events + (CONF_ON_VALUE,) args = typ.get_arg_type() if isinstance(typ, LvType) else [] args.append(lv_event_t_ptr) return { diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index fb856df04e..b76f90fecd 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -7,8 +7,10 @@ from .defines import ( CONF_ALIGN_TO, CONF_X, CONF_Y, + DIRECTIONS, LV_EVENT_MAP, LV_EVENT_TRIGGERS, + SWIPE_TRIGGERS, literal, ) from .lvcode import ( @@ -23,7 +25,7 @@ from .lvcode import ( lvgl_static, ) from .types import LV_EVENT -from .widgets import widget_map +from .widgets import LvScrActType, get_scr_act, widget_map async def generate_triggers(): @@ -33,6 +35,9 @@ async def generate_triggers(): """ for w in widget_map.values(): + if isinstance(w.type, LvScrActType): + w = get_scr_act(w.var) + if w.config: for event, conf in { event: conf @@ -43,6 +48,24 @@ async def generate_triggers(): w.add_flag("LV_OBJ_FLAG_CLICKABLE") event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()]) await add_trigger(conf, w, event) + + for event, conf in { + event: conf + for event, conf in w.config.items() + if event in SWIPE_TRIGGERS + }.items(): + conf = conf[0] + dir = event[9:].upper() + dir = {"UP": "TOP", "DOWN": "BOTTOM"}.get(dir, dir) + dir = DIRECTIONS.mapper(dir) + w.clear_flag("LV_OBJ_FLAG_SCROLLABLE") + selected = literal( + f"lv_indev_get_gesture_dir(lv_indev_get_act()) == {dir}" + ) + await add_trigger( + conf, w, literal("LV_EVENT_GESTURE"), is_selected=selected + ) + for conf in w.config.get(CONF_ON_VALUE, ()): await add_trigger( conf, @@ -61,13 +84,14 @@ async def generate_triggers(): lv.obj_align_to(w.obj, target, align, x, y) -async def add_trigger(conf, w, *events): +async def add_trigger(conf, w, *events, is_selected=None): + is_selected = is_selected or w.is_selected() tid = conf[CONF_TRIGGER_ID] trigger = cg.new_Pvariable(tid) args = w.get_args() + [(lv_event_t_ptr, "event")] value = w.get_values() await automation.build_automation(trigger, args, conf) async with LambdaContext(EVENT_ARG, where=tid) as context: - with LvConditional(w.is_selected()): + with LvConditional(is_selected): lv_add(trigger.trigger(*value, literal("event"))) lv_add(lvgl_static.add_event_cb(w.obj, await context.get_lambda(), *events)) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index c51a3d03e7..c527f51b1e 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -133,6 +133,18 @@ lvgl: pages: - id: page1 + on_swipe_top: + logger.log: "swiped up" + on_swipe_bottom: + logger.log: "swiped down" + on_swipe_up: + logger.log: "swiped up" + on_swipe_down: + logger.log: "swiped down" + on_swipe_left: + logger.log: "swiped left" + on_swipe_right: + logger.log: "swiped right" bg_image_src: cat_image on_load: - logger.log: page loaded