Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LVGL] Separate objects struct by screen #646

Open
AndyEveritt opened this issue Nov 22, 2024 · 2 comments
Open

[LVGL] Separate objects struct by screen #646

AndyEveritt opened this issue Nov 22, 2024 · 2 comments
Assignees

Comments

@AndyEveritt
Copy link

Is your feature request related to a problem? Please describe.
I am relatively new to LVGL so I may misunderstand the workflow, please correct me if this is correct.

Currently all named widgets, or widgets used in a flow, have a pointer saved in the objects variable in screens.c. I think it would be beneficial for more complex UIs to have the widgets separated by the screen they are on

Describe the solution you'd like
This could be a struct per screen containing pointers to all the widgets used in that screen.

So instead of this in screens.h:

typedef struct _objects_t {
    lv_obj_t *main;
    lv_obj_t *sub_page;
    lv_obj_t *obj0;
    lv_obj_t *mywidget1;
    lv_obj_t *my_bar;
    lv_obj_t *my_button;
} objects_t;

extern objects_t objects;

You would have something like this:

typedef struct _objects_t {
    lv_obj_t *screen;
    lv_obj_t *obj0;
    lv_obj_t *mywidget1;
} main_screen_objects_t;

typedef struct _objects_t {
    lv_obj_t *screen;
    lv_obj_t *my_bar;
    lv_obj_t *my_button;
} sub_page_screen_objects_t;

typedef struct _screens_t {
    main_screen_objects_t main_screen;
    sub_page_screen_objects_t sub_page_screen;
} screens_t

extern screens_t screen_objects;

Describe alternatives you've considered
In my opinion this structure provides easier access to the widget pointers while not adding significant additional memory usage. However it does not keep the full parent child structure of widgets which would be even better.

@AndyEveritt
Copy link
Author

TouchGFX has a good way of structuring the parent child hierachy of widgets and screens. I think the auto generated structure supports larger projects better since it directly integrates a model view presenter approach.
https://support.touchgfx.com/docs/development/ui-development/software-architecture/code-structure

Would something similar be doable for this program?

@mvladic
Copy link
Contributor

mvladic commented Nov 24, 2024

I agree that currently generated code where we put all the widgets in the single structure is not ideal not only for the larger projects, but also for the user widgets. For example, here is how user widget create function looks like:

void create_user_widget_my_user_widget(lv_obj_t *parent_obj, void *flowState, int startWidgetIndex) {
    lv_obj_t *obj = parent_obj;
    {
        lv_obj_t *parent_obj = obj;
        {
            // my_label
            lv_obj_t *obj = lv_label_create(parent_obj);
            ((lv_obj_t **)&objects)[startWidgetIndex + 0] = obj;
            // ...
        }
        {
            // my_button
            lv_obj_t *obj = lv_btn_create(parent_obj);
            ((lv_obj_t **)&objects)[startWidgetIndex + 1] = obj;
            // ...
        }
    }
}

If we move each screen and user widget objects to separate structures, we will have this:

typedef struct {
    lv_obj_t *my_label;
    lv_obj_t *my_button;
} my_user_widget_objects_t;

void create_user_widget_my_user_widget(lv_obj_t *parent_obj, void *flowState, my_user_widget_objects_t *objects) {
    lv_obj_t *obj = parent_obj;
    {
        lv_obj_t *parent_obj = obj;
        {
            // my_label
            lv_obj_t *obj = lv_label_create(parent_obj);
            objects->my_label = obj;
            // ..
        }
        {
            // my_button
            lv_obj_t *obj = lv_btn_create(parent_obj);
            objects->my_button = obj;
            // ...
        }
    }
}

So, instead of:

((lv_obj_t **)&objects)[startWidgetIndex + 0] = obj;

we will have more elegant code:

objects->my_label = obj;

There are some technical difficulties:

  • We need to keep backward compatibility for the old projects, created with previous versions of Studio. For that reason, we must add a new build option so you can choose between: (1) use single structure or (2) use separate structure per screen/user widget. Old projects will use former option and newly created projects will use later option by default. Of course, you will be able to choose option (2) for the old projects too, but you then need to update your code where you use objects variable.
  • Some code inside EEZ Flow engine expects that pointers to all screen objects are stored in consecutive order in memory. Also, EEZ Flow engine in some parts gets object pointer by index. So, we must see how to change EEZ Flow engine to work with this new layout also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants