1
0
mirror of https://github.com/esphome/esphome.git synced 2025-01-18 20:10:55 +00:00

[lvgl] Implement lvgl.page.is_showing: condition (#8055)

This commit is contained in:
Clyde Stubbs 2025-01-13 05:53:26 +11:00 committed by GitHub
parent bd17ee8e33
commit 109d737d5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 10 deletions

View File

@ -4,7 +4,7 @@ from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT
from esphome.cpp_generator import get_variable from esphome.cpp_generator import TemplateArguments, get_variable
from esphome.cpp_types import nullptr from esphome.cpp_types import nullptr
from .defines import ( from .defines import (
@ -23,6 +23,7 @@ from .lvcode import (
UPDATE_EVENT, UPDATE_EVENT,
LambdaContext, LambdaContext,
LocalVariable, LocalVariable,
LvglComponent,
ReturnStatement, ReturnStatement,
add_line_marks, add_line_marks,
lv, lv,
@ -93,7 +94,11 @@ async def lvgl_is_paused(config, condition_id, template_arg, args):
lvgl = config[CONF_LVGL_ID] lvgl = config[CONF_LVGL_ID]
async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context: async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context:
lv_add(ReturnStatement(lvgl_comp.is_paused())) lv_add(ReturnStatement(lvgl_comp.is_paused()))
var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) var = cg.new_Pvariable(
condition_id,
TemplateArguments(LvglComponent, *template_arg),
await context.get_lambda(),
)
await cg.register_parented(var, lvgl) await cg.register_parented(var, lvgl)
return var return var
@ -114,7 +119,11 @@ async def lvgl_is_idle(config, condition_id, template_arg, args):
timeout = await cg.templatable(config[CONF_TIMEOUT], [], cg.uint32) timeout = await cg.templatable(config[CONF_TIMEOUT], [], cg.uint32)
async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context: async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context:
lv_add(ReturnStatement(lvgl_comp.is_idle(timeout))) lv_add(ReturnStatement(lvgl_comp.is_idle(timeout)))
var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda()) var = cg.new_Pvariable(
condition_id,
TemplateArguments(LvglComponent, *template_arg),
await context.get_lambda(),
)
await cg.register_parented(var, lvgl) await cg.register_parented(var, lvgl)
return var return var

View File

@ -119,6 +119,7 @@ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_ev
} }
void LvglComponent::add_page(LvPageType *page) { void LvglComponent::add_page(LvPageType *page) {
this->pages_.push_back(page); this->pages_.push_back(page);
page->set_parent(this);
page->setup(this->pages_.size() - 1); page->setup(this->pages_.size() - 1);
} }
void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) { void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) {
@ -143,6 +144,8 @@ void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) {
} while (this->pages_[this->current_page_]->skip); // skip empty pages() } while (this->pages_[this->current_page_]->skip); // skip empty pages()
this->show_page(this->current_page_, anim, time); this->show_page(this->current_page_, anim, time);
} }
size_t LvglComponent::get_current_page() const { return this->current_page_; }
bool LvPageType::is_showing() const { return this->parent_->get_current_page() == this->index; }
void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) {
auto width = lv_area_get_width(area); auto width = lv_area_get_width(area);
auto height = lv_area_get_height(area); auto height = lv_area_get_height(area);

View File

@ -94,7 +94,9 @@ class LvCompound {
lv_obj_t *obj{}; lv_obj_t *obj{};
}; };
class LvPageType { class LvglComponent;
class LvPageType : public Parented<LvglComponent> {
public: public:
LvPageType(bool skip) : skip(skip) {} LvPageType(bool skip) : skip(skip) {}
@ -102,6 +104,9 @@ class LvPageType {
this->index = index; this->index = index;
this->obj = lv_obj_create(nullptr); this->obj = lv_obj_create(nullptr);
} }
bool is_showing() const;
lv_obj_t *obj{}; lv_obj_t *obj{};
size_t index{}; size_t index{};
bool skip; bool skip;
@ -188,6 +193,7 @@ class LvglComponent : public PollingComponent {
void show_next_page(lv_scr_load_anim_t anim, uint32_t time); void show_next_page(lv_scr_load_anim_t anim, uint32_t time);
void show_prev_page(lv_scr_load_anim_t anim, uint32_t time); void show_prev_page(lv_scr_load_anim_t anim, uint32_t time);
void set_page_wrap(bool wrap) { this->page_wrap_ = wrap; } void set_page_wrap(bool wrap) { this->page_wrap_ = wrap; }
size_t get_current_page() const;
void set_focus_mark(lv_group_t *group) { this->focus_marks_[group] = lv_group_get_focused(group); } void set_focus_mark(lv_group_t *group) { this->focus_marks_[group] = lv_group_get_focused(group); }
void restore_focus_mark(lv_group_t *group) { void restore_focus_mark(lv_group_t *group) {
auto *mark = this->focus_marks_[group]; auto *mark = this->focus_marks_[group];
@ -251,14 +257,13 @@ template<typename... Ts> class LvglAction : public Action<Ts...>, public Parente
std::function<void(LvglComponent *)> action_{}; std::function<void(LvglComponent *)> action_{};
}; };
template<typename... Ts> class LvglCondition : public Condition<Ts...>, public Parented<LvglComponent> { template<typename Tc, typename... Ts> class LvglCondition : public Condition<Ts...>, public Parented<Tc> {
public: public:
LvglCondition(std::function<bool(LvglComponent *)> &&condition_lambda) LvglCondition(std::function<bool(Tc *)> &&condition_lambda) : condition_lambda_(std::move(condition_lambda)) {}
: condition_lambda_(std::move(condition_lambda)) {}
bool check(Ts... x) override { return this->condition_lambda_(this->parent_); } bool check(Ts... x) override { return this->condition_lambda_(this->parent_); }
protected: protected:
std::function<bool(LvglComponent *)> condition_lambda_{}; std::function<bool(Tc *)> condition_lambda_{};
}; };
#ifdef USE_LVGL_TOUCHSCREEN #ifdef USE_LVGL_TOUCHSCREEN

View File

@ -2,6 +2,7 @@ from esphome import automation, codegen as cg
from esphome.automation import Trigger from esphome.automation import Trigger
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME, CONF_TRIGGER_ID from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME, CONF_TRIGGER_ID
from esphome.cpp_generator import MockObj, TemplateArguments
from ..defines import ( from ..defines import (
CONF_ANIMATION, CONF_ANIMATION,
@ -17,18 +18,28 @@ from ..lvcode import (
EVENT_ARG, EVENT_ARG,
LVGL_COMP_ARG, LVGL_COMP_ARG,
LambdaContext, LambdaContext,
ReturnStatement,
add_line_marks, add_line_marks,
lv_add, lv_add,
lvgl_comp, lvgl_comp,
lvgl_static, lvgl_static,
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LvglAction, lv_page_t from ..types import LvglAction, LvglCondition, lv_page_t
from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties from . import (
Widget,
WidgetType,
add_widgets,
get_widgets,
set_obj_properties,
wait_for_widgets,
)
CONF_ON_LOAD = "on_load" CONF_ON_LOAD = "on_load"
CONF_ON_UNLOAD = "on_unload" CONF_ON_UNLOAD = "on_unload"
PAGE_ARG = "_page"
PAGE_SCHEMA = cv.Schema( PAGE_SCHEMA = cv.Schema(
{ {
cv.Optional(CONF_SKIP, default=False): lv_bool, cv.Optional(CONF_SKIP, default=False): lv_bool,
@ -86,6 +97,30 @@ async def page_next_to_code(config, action_id, template_arg, args):
return var return var
@automation.register_condition(
"lvgl.page.is_showing",
LvglCondition,
cv.maybe_simple_value(
cv.Schema({cv.Required(CONF_ID): cv.use_id(lv_page_t)}),
key=CONF_ID,
),
)
async def page_is_showing_to_code(config, condition_id, template_arg, args):
await wait_for_widgets()
page = await cg.get_variable(config[CONF_ID])
async with LambdaContext(
[(lv_page_t.operator("ptr"), PAGE_ARG)], return_type=cg.bool_
) as context:
lv_add(ReturnStatement(MockObj(PAGE_ARG, "->").is_showing()))
var = cg.new_Pvariable(
condition_id,
TemplateArguments(lv_page_t, *template_arg),
await context.get_lambda(),
)
await cg.register_parented(var, page)
return var
@automation.register_action( @automation.register_action(
"lvgl.page.previous", "lvgl.page.previous",
LvglAction, LvglAction,

View File

@ -138,6 +138,11 @@ lvgl:
- logger.log: page loaded - logger.log: page loaded
- lvgl.widget.focus: - lvgl.widget.focus:
action: restore action: restore
- if:
condition:
lvgl.page.is_showing: page1
then:
logger.log: "Yes, page1 showing"
on_unload: on_unload:
- logger.log: page unloaded - logger.log: page unloaded
- lvgl.widget.focus: mark - lvgl.widget.focus: mark