feat(gridnav): add lv_gridnav (#2911)

* add first implememtation

* Update src/extra/others/gridnav/lv_gridnav.c

Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>

* minor fix

* add example and minor fixes

* add more examples

* add more examples

* code formatting

* add LV_GRIDNAC_CTRL_SCROLL_FIRST

* code formatting

* add example for list

* add docs

* Misc:  improvements to gridnav docs (#2994)

Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>
Co-authored-by: Ken Carpenter <62639971+FoundationKen@users.noreply.github.com>
This commit is contained in:
Gabor Kiss-Vamosi
2022-01-20 10:28:49 +01:00
parent 731ef5a75e
commit 62fc7123f1
18 changed files with 948 additions and 53 deletions

View File

@@ -21,6 +21,7 @@ void lv_example_flex_2(void)
for(i = 0; i < 8; i++) {
lv_obj_t * obj = lv_obj_create(cont);
lv_obj_set_size(obj, 70, LV_SIZE_CONTENT);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%"LV_PRIu32, i);

View File

@@ -0,0 +1,18 @@
Basic grid navigation
"""""""""""""""""""""
.. lv_example:: others/monkey/lv_example_gridnav_1
:language: c
Grid navigation on a list
""""""""""""""""""""""""
.. lv_example:: others/monkey/lv_example_gridnav_2
:language: c
Nested grid navigations
"""""""""""""""""""""""
.. lv_example:: others/monkey/lv_example_gridanav_3
:language: c

View File

@@ -0,0 +1,40 @@
/**
* @file lv_example_gridnav.h
*
*/
#ifndef LV_EXAMPLE_GRIDNAV_H
#define LV_EXAMPLE_GRIDNAV_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_example_gridnav_1(void);
void lv_example_gridnav_2(void);
void lv_example_gridnav_3(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EXAMPLE_GRIDNAV_H*/

View File

@@ -0,0 +1,72 @@
#include "../../lv_examples.h"
#if LV_USE_GRIDNAV && LV_USE_FLEX && LV_BUILD_EXAMPLES
/**
* Demonstrate a a basic grid navigation
*/
void lv_example_gridnav_1(void)
{
/*It's assumed that the default group is set and
*there is a keyboard indev*/
lv_obj_t * cont1 = lv_obj_create(lv_scr_act());
lv_gridnav_add(cont1, LV_GRIDNAV_CTRL_NONE);
/*Use flex here, but works with grid or manually placed objects as well*/
lv_obj_set_flex_flow(cont1, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_style_bg_color(cont1, lv_palette_lighten(LV_PALETTE_BLUE, 5), LV_STATE_FOCUSED);
lv_obj_set_size(cont1, lv_pct(50), lv_pct(100));
/*Only the container needs to be in a group*/
lv_group_add_obj(lv_group_get_default(), cont1);
lv_obj_t * label = lv_label_create(cont1);
lv_label_set_text_fmt(label, "No rollover");
uint32_t i;
for(i = 0; i < 10; i++) {
lv_obj_t * obj = lv_btn_create(cont1);
lv_obj_set_size(obj, 70, LV_SIZE_CONTENT);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
lv_group_remove_obj(obj); /*Not needed, we use the gridnav instead*/
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%d", i);
lv_obj_center(label);
}
/* Create a second container with rollover grid nav mode.*/
lv_obj_t * cont2 = lv_obj_create(lv_scr_act());
lv_gridnav_add(cont2, LV_GRIDNAV_CTRL_ROLLOVER);
lv_obj_set_style_bg_color(cont2, lv_palette_lighten(LV_PALETTE_BLUE, 5), LV_STATE_FOCUSED);
lv_obj_set_size(cont2, lv_pct(50), lv_pct(100));
lv_obj_align(cont2, LV_ALIGN_RIGHT_MID, 0, 0);
label = lv_label_create(cont2);
lv_obj_set_width(label, lv_pct(100));
lv_label_set_text_fmt(label, "Rollover\nUse tab to focus the other container");
/*Only the container needs to be in a group*/
lv_group_add_obj(lv_group_get_default(), cont2);
/*Add and place some children manually*/
lv_obj_t * ta = lv_textarea_create(cont2);
lv_obj_set_size(ta, lv_pct(100), 80);
lv_obj_set_pos(ta, 0, 80);
lv_group_remove_obj(ta); /*Not needed, we use the gridnav instead*/
lv_obj_t * cb = lv_checkbox_create(cont2);
lv_obj_set_pos(cb, 0, 170);
lv_group_remove_obj(cb); /*Not needed, we use the gridnav instead*/
lv_obj_t * sw1 = lv_switch_create(cont2);
lv_obj_set_pos(sw1, 0, 200);
lv_group_remove_obj(sw1); /*Not needed, we use the gridnav instead*/
lv_obj_t * sw2 = lv_switch_create(cont2);
lv_obj_set_pos(sw2, lv_pct(50), 200);
lv_group_remove_obj(sw2); /*Not needed, we use the gridnav instead*/
}
#endif

View File

@@ -0,0 +1,44 @@
#include "../../lv_examples.h"
#if LV_USE_GRIDNAV && LV_USE_LIST && LV_BUILD_EXAMPLES
/**
* Grid navigation on a list
*/
void lv_example_gridnav_2(void)
{
/*It's assumed that the default group is set and
*there is a keyboard indev*/
lv_obj_t * list1 = lv_list_create(lv_scr_act());
lv_gridnav_add(list1, LV_GRIDNAV_CTRL_NONE);
lv_obj_set_size(list1, lv_pct(45), lv_pct(80));
lv_obj_align(list1, LV_ALIGN_LEFT_MID, 5, 0);
lv_obj_set_style_bg_color(list1, lv_palette_lighten(LV_PALETTE_BLUE, 5), LV_STATE_FOCUSED);
lv_group_add_obj(lv_group_get_default(), list1);
char buf[32];
uint32_t i;
for(i = 0; i < 15; i++) {
lv_snprintf(buf, sizeof(buf), "File %d", i + 1);
lv_obj_t * item = lv_list_add_btn(list1, LV_SYMBOL_FILE, buf);
lv_obj_set_style_bg_opa(item, 0, 0);
lv_group_remove_obj(item); /*Not needed, we use the gridnav instead*/
}
lv_obj_t * list2 = lv_list_create(lv_scr_act());
lv_gridnav_add(list2, LV_GRIDNAV_CTRL_ROLLOVER);
lv_obj_set_size(list2, lv_pct(45), lv_pct(80));
lv_obj_align(list2, LV_ALIGN_RIGHT_MID, -5, 0);
lv_obj_set_style_bg_color(list2, lv_palette_lighten(LV_PALETTE_BLUE, 5), LV_STATE_FOCUSED);
lv_group_add_obj(lv_group_get_default(), list2);
for(i = 0; i < 15; i++) {
lv_snprintf(buf, sizeof(buf), "Folder %d", i + 1);
lv_obj_t * item = lv_list_add_btn(list2, LV_SYMBOL_DIRECTORY, buf);
lv_obj_set_style_bg_opa(item, 0, 0);
lv_group_remove_obj(item);
}
}
#endif

View File

@@ -0,0 +1,101 @@
#include "../../lv_examples.h"
#if LV_USE_GRIDNAV && LV_USE_FLEX && LV_BUILD_EXAMPLES
static void cont_sub_event_cb(lv_event_t * e)
{
uint32_t k = lv_event_get_key(e);
lv_obj_t * obj = lv_event_get_current_target(e);
if(k == LV_KEY_ENTER) {
lv_group_focus_obj(obj);
}
else if(k == LV_KEY_ESC) {
lv_group_focus_next(lv_obj_get_group(obj));
}
}
/**
* Nested grid navigations
*/
void lv_example_gridnav_3(void)
{
/*It's assumed that the default group is set and
*there is a keyboard indev*/
lv_obj_t * cont_main = lv_obj_create(lv_scr_act());
lv_gridnav_add(cont_main, LV_GRIDNAV_CTRL_ROLLOVER | LV_GRIDNAV_CTRL_SCROLL_FIRST);
/*Only the container needs to be in a group*/
lv_group_add_obj(lv_group_get_default(), cont_main);
/*Use flex here, but works with grid or manually placed objects as well*/
lv_obj_set_flex_flow(cont_main, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_style_bg_color(cont_main, lv_palette_lighten(LV_PALETTE_BLUE, 5), LV_STATE_FOCUSED);
lv_obj_set_size(cont_main, lv_pct(80), LV_SIZE_CONTENT);
lv_obj_t * btn;
lv_obj_t * label;
btn = lv_btn_create(cont_main);
lv_group_remove_obj(btn);
label = lv_label_create(btn);
lv_label_set_text(label, "Button 1");
btn = lv_btn_create(cont_main);
lv_group_remove_obj(btn);
label = lv_label_create(btn);
lv_label_set_text(label, "Button 2");
/*Create an other container with long text to show how LV_GRIDNAV_CTRL_SCROLL_FIRST works*/
lv_obj_t * cont_sub1 = lv_obj_create(cont_main);
lv_obj_set_size(cont_sub1, lv_pct(100), 100);
label = lv_label_create(cont_sub1);
lv_obj_set_style_bg_color(cont_sub1, lv_palette_lighten(LV_PALETTE_RED, 5), LV_STATE_FOCUSED);
lv_obj_set_width(label, lv_pct(100));
lv_label_set_text(label,
"I'm a very long text which is makes my container scrollable. "
"As LV_GRIDNAV_FLAG_SCROLL_FIRST is enabled arrow will scroll me first "
"and a new objects will be focused only when an edge is reached with the scrolling.\n\n"
"This is only some placeholder text to be sure the parent will be scrollable. \n\n"
"Hello world!\n"
"Hello world!\n"
"Hello world!\n"
"Hello world!\n"
"Hello world!\n"
"Hello world!");
/*Create a third container that can be focused with ENTER and contains an other grid nav*/
lv_obj_t * cont_sub2 = lv_obj_create(cont_main);
lv_gridnav_add(cont_sub2, LV_GRIDNAV_CTRL_ROLLOVER);
/*Only the container needs to be in a group*/
lv_group_add_obj(lv_group_get_default(), cont_sub2);
lv_obj_add_event_cb(cont_sub2, cont_sub_event_cb, LV_EVENT_KEY, NULL);
/*Use flex here, but works with grid or manually placed objects as well*/
lv_obj_set_flex_flow(cont_sub2, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_style_bg_color(cont_sub2, lv_palette_lighten(LV_PALETTE_RED, 5), LV_STATE_FOCUSED);
lv_obj_set_size(cont_sub2, lv_pct(100), LV_SIZE_CONTENT);
label = lv_label_create(cont_sub2);
lv_label_set_text(label, "Use ENTER/ESC to focus/defocus this container");
lv_obj_set_width(label, lv_pct(100));
btn = lv_btn_create(cont_sub2);
lv_group_remove_obj(btn);
label = lv_label_create(btn);
lv_label_set_text(label, "Button 3");
btn = lv_btn_create(cont_sub2);
lv_group_remove_obj(btn);
label = lv_label_create(btn);
lv_label_set_text(label, "Button 4");
}
#endif

View File

@@ -0,0 +1,47 @@
#include "../../lv_examples.h"
#if LV_USE_GRIDNAV && LV_USE_FLEX && LV_BUILD_EXAMPLES
static void event_handler(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target(e);
lv_obj_t * list = lv_obj_get_parent(obj);
LV_LOG_USER("Clicked: %s", lv_list_get_btn_text(list, obj));
}
/**
* Simple navigation on a list widget
*/
void lv_example_gridnav_4(void)
{
/*It's assumed that the default group is set and
*there is a keyboard indev*/
lv_obj_t * list = lv_list_create(lv_scr_act());
lv_gridnav_add(list, LV_GRIDNAV_CTRL_ROLLOVER);
lv_obj_align(list, LV_ALIGN_LEFT_MID, 0, 10);
lv_group_add_obj(lv_group_get_default(), list);
uint32_t i;
for(i = 0; i < 20; i++) {
char buf[32];
/*Add some separators too, they are not focusable by gridnav*/
if((i % 5) == 0) {
lv_snprintf(buf, sizeof(buf), "Section %d", i / 5 + 1);
lv_list_add_text(list, buf);
}
lv_snprintf(buf, sizeof(buf), "File %d", i + 1);
lv_obj_t * item = lv_list_add_btn(list, LV_SYMBOL_FILE, buf);
lv_obj_add_event_cb(item, event_handler, LV_EVENT_CLICKED, NULL);
lv_group_remove_obj(item); /*The default group adds it automatically*/
}
lv_obj_t * btn = lv_btn_create(lv_scr_act());
lv_obj_align(btn, LV_ALIGN_RIGHT_MID, 0, -10);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, "Button");
}
#endif

View File

@@ -15,6 +15,7 @@ extern "C" {
*********************/
#include "snapshot/lv_example_snapshot.h"
#include "monkey/lv_example_monkey.h"
#include "gridnav/lv_example_gridnav.h"
/*********************
* DEFINES

View File

@@ -10,6 +10,7 @@ static void event_handler(lv_event_t * e)
LV_LOG_USER("Clicked: %s", lv_list_get_btn_text(list1, obj));
}
}
void lv_example_list_1(void)
{
/*Create a list*/