#pragma once #include #include "esphome/components/select/select.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/components/lvgl/lvgl_esphome.h" namespace esphome { namespace lvgl { class LVGLSelect : public select::Select, public Component { public: LVGLSelect(LvSelectable *widget, lv_anim_enable_t anim, bool restore) : widget_(widget), anim_(anim), restore_(restore) {} void setup() override { this->set_options_(); if (this->restore_) { size_t index; this->pref_ = this->make_entity_preference(); if (this->pref_.load(&index)) this->widget_->set_selected_index(index, LV_ANIM_OFF); } this->publish(); lv_obj_add_event_cb( this->widget_->obj, [](lv_event_t *e) { auto *it = static_cast(lv_event_get_user_data(e)); it->set_options_(); }, LV_EVENT_REFRESH, this); auto lamb = [](lv_event_t *e) { auto *self = static_cast(lv_event_get_user_data(e)); self->publish(); }; lv_obj_add_event_cb(this->widget_->obj, lamb, LV_EVENT_VALUE_CHANGED, this); lv_obj_add_event_cb(this->widget_->obj, lamb, lv_update_event, this); } void publish() { auto index = this->widget_->get_selected_index(); this->publish_state(index); if (this->restore_) { this->pref_.save(&index); } } protected: void control(size_t index) override { this->widget_->set_selected_index(index, this->anim_); this->publish(); } void set_options_() { // Widget uses std::vector, SelectTraits uses FixedVector // Convert by extracting c_str() pointers const auto &opts = this->widget_->get_options(); FixedVector opt_ptrs; opt_ptrs.init(opts.size()); for (const auto &opt : opts) { opt_ptrs.push_back(opt.c_str()); } this->traits.set_options(opt_ptrs); } LvSelectable *widget_; lv_anim_enable_t anim_; bool restore_; ESPPreferenceObject pref_{}; }; } // namespace lvgl } // namespace esphome