Skip to content

Custom component/code integration for pages, widgets, etc. #109

@segfly

Description

@segfly

I'd like to use a LVGL designer like EEZ Studio to generate the more complex pages, widgets, etc. and use the yaml syntax for the simpler stuff like simple pages/widgets, event handling, setup, etc.

Do you have any suggestions on how one might inject code within the generated pages and widgets blocks? Lambdas don't appear to be supported right now.

I've gotten pretty far by adding the generated code from EEZ Studio to the esphome includes: yaml. EEZ generates simple methods for each of the screens and child components (e.g. create_screen_main()) that registers a handle to a global objects struct.

Here is an example of an EEZ Studio generated create function:

void create_screen_main() {
    lv_obj_t *obj = lv_obj_create(0);
    objects.main = obj;
    lv_obj_set_pos(obj, 0, 0);
    lv_obj_set_size(obj, 240, 135);
    lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
    {
        lv_obj_t *parent_obj = obj;
        {
            // label_1
            lv_obj_t *obj = lv_label_create(parent_obj);
            objects.label_1 = obj;
            lv_obj_set_pos(obj, 0, 0);
            lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
            lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP);
            lv_label_set_text(obj, "Hello, world!");
            lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
        }
    }
}

Using an empty page/widgets block:

lvgl:
  pages:
    - id: test_page
      widgets:

The LVGL component generates the following:

  test_page = new LvPageType();
  lvgl_component->add_init_lambda([=](lv_disp_t * lv_disp) {
      lvgl_component->add_page(test_page);
      test_page->index = 0;
      test_page->page = lv_obj_create(nullptr);
      test_page->skip = false;
      lvgl_component->set_page_wrap(true);
      
  });

If I could just replace or later reassign test_page->page = lv_obj_create(nullptr); I think I could use most of the generate code from EEZ Studio. The problem, is I can't find a good way to inject the code:

// Needs to be injected after lvgl_component->add_init_lambda
lv_obj_clean(test_page->page);
create_screen_main();
test_page->page = objects.main;

Placing this in a on_boot: lambda injects the code way too early in setup(). And trying to put it in on_loop: seems to be too late to have an effect.

It would be nice if I could do something like this for "external" pages/widgets along with yaml-only delcared pages/widgets:

lvgl:
  style_definitions:
    - id: custom_style
      lambda: |-
        ...
        return style;   
  pages:
    - id: test_page
      lambda: |-
        create_screen_main();
        return objects.main;      
    - id: another_page
      widgets:
      - label:
          align: CENTER
          id: lbl_id
          styles: custom_style          
          recolor: true
          text: "#FF0000 write# #00FF00 colored# #0000FF text#"
      - id: custom_widget
        lambda: |-
          ...
          return widget; 

And so on for the other LVGL types.

But I could be looking at this all the wrong way... Do you have a better idea on how to streamline the UI design process using this esphome component? While it's great to do simple stuff, the yaml->compile->upload->test cycle is very slow - lots trial/error and waiting?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions