Sandbox application framework

Hi All,
I found that I needed to have a common look and feel as well as page/screen navigation without the need to consistently deal with that on every page or screen that is created.
So I wrote a LittlevGL application framework I have called Sandbox.

It has the following features and characteristics,

  • Home, Previous and Next page navigations,
  • Optionally Settings, Info and Help button callbacks. These can be context specific (IE associated with a specific page) or one which handles the same for the application as a whole or only part thereof.
  • Each page has a title which is displayed in the header.
  • Allocates, clears and deallocates memory required by each page. No global variables needed or required (in fact discouraged) if used as intended.
  • Provides for “Create, Task and Destroy” callbacks.
  • All configuration and parameters can be placed in Read only memory. I am always one to be frugal with RAM … :slight_smile:
  • Does not limit or restrict any LittlevGL functions or features.
  • Effectively self contained within only a few C source and header files.
  • Coding style and naming conventions modeled on that in LittlevGL.
  • Auto prunes the navigation list length so as not to become to long, nested or congested.
  • Navigation uses a different linked list to that of LittlevGL (it just suited my purposes better), but it can easily written to use LittlevGL’s.

The Sandbox provides for “Create, Task and Destroy” callbacks, global variables are not required at all, again if the programming model is used as intended.
A descriptor pointer is passed with parameters to the Sandbox at instantiation,
The API is simple. It looks as follows,

 *      TYPEDEFS

typedef void (*sndbx_pge_create_cb_t)(lv_obj_t *, void *, const void *);
typedef void (*sndbx_pge_task_cb_t)(void *);
typedef void (*sndbx_pge_destroy_cb_t)(void *);

typedef void (*sndbx_pge_help_cb_t)(void *, lv_event_t);
typedef void (*sndbx_pge_settings_cb_t)(void *, lv_event_t);
typedef void (*sndbx_pge_info_cb_t)(void *, lv_event_t);

typedef struct {
    const char *               name;           /**< Name of page, displayed in the toolbar */    
    uint32_t                   mem_size;       /**< How much memory the page needs */
    sndbx_pge_create_cb_t      create_cb;      /**< Called when the page is created */
    sndbx_pge_task_cb_t        task_cb;        /**< Called periodically, set by task_interval */
    sndbx_pge_destroy_cb_t     destroy_cb;     /**< Called when the page is destroyed */
    lv_task_prio_t             task_prio;      /**< Task Priority */
    uint32_t                   task_period;    /**< How often the task should run */
    sndbx_pge_settings_cb_t    settings_cb;    /**< Called on settings button events */
    sndbx_pge_info_cb_t        info_cb;        /**< Called on info button events */
    sndbx_pge_help_cb_t        help_cb;        /**< Called on help button events */
} sndbx_pge_dsc_t;

typedef struct {
    const sndbx_pge_dsc_t * dsc;
    const void * prms;
} sndbx_pge_t;


extern void sndbx_create_app( const sndbx_pge_t * home );
extern void sndbx_create_page( const sndbx_pge_t * page );
extern lv_task_t * sndbx_get_task( void );

I am in the process of converting all of the LittlevGL example repo apps, tutorials and tests so that they can contained within a single application and dispatched via a home page,
So far I have completed “Hello world”, “Demo”, “Benchmark”, “Sysmon” and soon to complete “Theme Test’s 1 & 2” and later the others. I have not had any issues with this so far, it has mainly involved placing all global (to the app/demo/test file that is, more specifically statically or linker allocated memory) variables in a structure which is sized and included in the sandbox page descriptor so that the correct amount of memory can be allocated for the concerned page.

The model relies on the user data members in the lv_x objects to pass memory pointers to the callbacks and assumes that lv_user_data_t, lv_anim_user_data_t etc are defined as void * in lv_config.h.

Please see the screen shots below,

Note the use of the Warning (for Info) and Call (for Help) symbols, I just have not had the time to generate more suitable ones using the online font converter, but that is a mechanical process and easy to do.

I am posting this to see if there is any interest for what I have done so far. If so I will create a GitHub repo (after properly structuring and organizing the file placement for an easy bolt on to LittlevGL and to ensure there are no compiler complaints when correctly placed) and make it available.

If there is absolutely no interest then I will not waste my time :wink: :slight_smile:

1 Like

I advise you to hold off on converting all the examples. They are being replaced.

In general, though, this looks interesting!

I just started converting them as an exercise to see if I have taken care of everything in the API and to make sure there would not be any hickups in using it. So far so good though.

I look forward to the new examples.When will they be ready ?

I really looks amazing. Maybe you have already seen that LittlevGL has Live demo site. It’d be great to add this application there.

The examples used in the documentation are in the rework branch of lv_examples.
The application will be moved to the lv_apps repo. BTW, the new settings app is worth a look.

According to the result of the survey so far, it’s clear that people want more examples and tutorials. So it will have high priority in the near future but I can say an exact date now.

Pleased you think it is worthwhile, I will let you know once I am a bit further with it.
The settings app looks great, will include that as well.
I am also going to add a means of hiding the toolbar so that a dispatched page can use the entire display area. That will mean it will need to signal when it is done so that the toolbar can be displayed and become active again. Would welcome any other ideas you may think it may need.

You can create a new screen when a demo/example is opened, load the new screen and simply call the demo/example create function (by default they create the demo on the active screen). This way the original, unchanged version of the examples could be used.

To leave the demo screen a close button can be created on the top layer which loads the selector screen again and deletes the demo screen.

What do you think?

1 Like

@kisvegabor Thanks, that guidance saved me a lot of time.
It works perfectly :grinning:

The only issue I have regarding that is if the concerned demo/application has started a task (such as is done on the demo app for the task switcher if enabled) is there a way for me to know this so that when I delete the screen I can also delete the task or tasks at the same time ? I would prefer if possible to manage it in an automated way rather than having to make specific calls for particular apps that do such things.

With this method I will be able to complete the set in short order. I will let you know once I have. Should I mail it to you or just upload it here ?

PS, I have been working with 800x480 and 132 DPI. Does the live demo run at the default resolution 480x320 and 100 DPI, I will make sure it looks decent before I send it to you.

The examples (in rework branch) shouldn’t use lv_tasks as they are very simple.
For more advanced demos (will be called “apps” such as demo, benchmark etc.) there should be a close function. It needs some time to rework the apps but I can quickly add a demo_close function.

Great, thank you! :slight_smile:


Attached is a zip file with exe (visual_studio_2017_sdl_x64.exe, SDL2.dll) and associated files (bin files for lv_images tutorial).

I have included just about all the apps, examples and demo’s with some exceptions noted below.
That is all those in the lv_apps, lv_examples, and lv_examples-rework repo’s. (1.0 MB)

I will post the source code for everything tomorrow once I have cleaned things up a bit.

Some notes here in the meantime,
lv_ex_imgbtn_1 has a bug, lv_style_t style_pr; on line 5 should be static lv_style_t style_pr;
lv_ex_guage_1, not included. Gives Compiler error C2099: initializer is not a constant
lv_ex_label_3, not included. It creates a task.

For me this has been an interesting exercise but a good way to become reasonably proficient with the library :smile:

1 Like

Fixed, thank you.

On what line number does that error occur?

1 Like

Awesome! Thank you!
I can try it on Monday.

LV_COLOR_MAKE resolves to inline function. Not surprised it does not compile initialising a static variable. :wink: (46.9 KB)

Code attached,
For visual studio unzip in the project directory, include in the project and compile.

The code assumes the following directories at that level,


to run the application call


I hope you find it useful.

LV_COLOR_MAKE should be define.
lv_color_make is an inline function.

:face_with_hand_over_mouth: My mistake, quite right.

But the compiler does give that error.

#define COLOR_BLUE COLOR_MAKE(0x00, 0x00, 0xFF)
#define COLOR_PURPLE COLOR_MAKE(0x80, 0x00, 0x80)
#define COLOR_ORANGE COLOR_MAKE(0xFF, 0xA5, 0x00)

//#define COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Gives compiler error */
#define COLOR_MAKE(r8, g8, b8) {{b8, g8, r8, 0xff}} /*Compiles fine */

Simple solution,

//static lv_color_t needle_colors[] = {LV_COLOR_BLUE, LV_COLOR_ORANGE, LV_COLOR_PURPLE};
static lv_color_t needle_colors[3];
needle_colors[0] = LV_COLOR_BLUE;
needle_colors[1] = LV_COLOR_ORANGE;
needle_colors[2] = LV_COLOR_PURPLE;

I’ve applied your fix in lv_ex_gauge_1. See 9e96eca

I’ve tested your app in Eclipse on Linux and after some tweaks (include paths, delete apps from lv_example master) it worked. I think we can continue with it when the the examples will be really reworked and lv_examples master won’t be required.

Please check above link, I will post source for the app during the next week once I have reorganised and cleaned things up a little.

I intend on changing a lot of the pages that have settings to use the lv_settings module so that I can test some use cases and perhaps to see if there are any aspects lacking.

With the image tutorial, I have not been able to get emscripten to pick up the bin files.

Any feedback, suggestions comments etc are welcome.

BTW, I used this as a test case to see if linux under windows WSL is actually usable for anything, it turned out for me that it is. Miracles never cease :smile:

You have to build them into the image, since they are separate binaries and not C structures.

@kisvegabor @deonm

I think I found a bug.

Click on “Tests”, then choose “Theme 2”. Click on “Material” on the theme selector, then drag it upwards until “Mono” is in the selection window. Do not release the mouse in the process, otherwise the bug doesn’t seem to occur.

Once Mono is in the selection window, let go of the mouse. Immediately strange graphical glitches begin to occur.

Not sure if this can be reproduced in the pure example or not. I will have to take a look when I get a chance.