Created
July 6, 2020 12:03
-
-
Save embeddedt/be0adf541e65a2fbbf3c5e2e4efd85e1 to your computer and use it in GitHub Desktop.
Incomplete file browser implementation for LVGL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <lvgl/lvgl.h> | |
#define BROWSE_DRV_LETTER "C" | |
/********************* | |
* DEFINES | |
*********************/ | |
/********************** | |
* TYPEDEFS | |
**********************/ | |
/********************** | |
* STATIC PROTOTYPES | |
**********************/ | |
static void file_list_button_event(lv_obj_t * list_btn, lv_event_t event); | |
static void populate_list(void); | |
static void go_up(lv_obj_t * up_btn, lv_event_t event); | |
static void stop_selecting(lv_obj_t * btn, lv_event_t event); | |
static void set_selecting_mode(bool mode); | |
/********************** | |
* STATIC VARIABLES | |
**********************/ | |
static bool selecting_mode; | |
static lv_obj_t * main_list, * win; | |
static lv_obj_t * select_stop_btn = NULL; | |
static char current_dir[LV_FS_MAX_PATH_LENGTH] = BROWSE_DRV_LETTER ":"; | |
/********************** | |
* MACROS | |
**********************/ | |
/********************** | |
* GLOBAL FUNCTIONS | |
**********************/ | |
void lv_file_browser(void) | |
{ | |
static lv_style_t header_style, page_style; | |
/* Create a window to use as the action bar */ | |
win = lv_win_create(lv_scr_act(), NULL); | |
lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES); | |
/* Override some properties of the style */ | |
lv_style_copy(&header_style, lv_win_get_style(win, LV_WIN_STYLE_HEADER)); | |
lv_style_copy(&page_style, &lv_style_transp); | |
header_style.body.shadow.color = lv_color_hex3(0xaaa); | |
header_style.body.shadow.width = 4; | |
header_style.body.shadow.type = LV_SHADOW_BOTTOM; | |
page_style.body.padding.left = page_style.body.padding.right = 0; | |
page_style.body.padding.top = page_style.body.padding.bottom = 0; | |
page_style.body.padding.inner = 0; | |
lv_win_set_style(win, LV_WIN_STYLE_HEADER, &header_style); | |
lv_win_set_style(win, LV_WIN_STYLE_CONTENT, &page_style); | |
lv_win_set_title(win, "File Manager"); | |
lv_obj_t * up_btn = lv_win_add_btn(win, LV_SYMBOL_UP); | |
lv_obj_set_event_cb(up_btn, go_up); | |
lv_win_add_btn(win, LV_SYMBOL_HOME); | |
lv_win_add_btn(win, LV_SYMBOL_TRASH); | |
lv_obj_t * win_content = lv_win_get_content(win); | |
lv_cont_set_fit(lv_page_get_scrl(win_content), LV_FIT_FLOOD); | |
/* Create the list */ | |
main_list = lv_list_create(win, NULL); | |
lv_list_set_style(main_list, LV_LIST_STYLE_BG, &page_style); | |
/* Fit the list inside the page, taking into account any borders. */ | |
lv_area_t page_area; | |
lv_obj_get_coords(win_content, &page_area); | |
lv_obj_get_inner_coords(win_content, &page_area); | |
lv_obj_set_size(main_list, lv_area_get_width(&page_area), lv_area_get_height(&page_area)); | |
populate_list(); | |
} | |
/********************** | |
* STATIC FUNCTIONS | |
**********************/ | |
static void stop_selecting(lv_obj_t * btn, lv_event_t event) | |
{ | |
if(event == LV_EVENT_CLICKED) { | |
set_selecting_mode(false); | |
} | |
} | |
static void set_selecting_mode(bool mode) | |
{ | |
if(selecting_mode != mode) { | |
if(mode) { | |
select_stop_btn = lv_win_add_btn(win, LV_SYMBOL_OK); | |
lv_obj_set_event_cb(select_stop_btn, stop_selecting); | |
} else { | |
if(select_stop_btn) { | |
lv_obj_del(select_stop_btn); | |
select_stop_btn = NULL; | |
} | |
lv_obj_t * btn = NULL; | |
do { | |
btn = lv_list_get_next_btn(main_list, btn); | |
if(btn != NULL) { | |
lv_btn_set_state(btn, LV_BTN_STATE_REL); | |
} | |
} while(btn != NULL); | |
} | |
} | |
selecting_mode = mode; | |
} | |
static void go_up(lv_obj_t * up_btn, lv_event_t event) | |
{ | |
if(event == LV_EVENT_CLICKED) { | |
if(strlen(current_dir) == 2) { /* drive letter plus : */ | |
/* We cannot go up further */ | |
return; | |
} | |
printf("Current directory: %s\n", current_dir); | |
char *last_slash = strrchr(current_dir, '/'); | |
assert(last_slash != NULL); | |
*last_slash = 0; | |
populate_list(); | |
} | |
} | |
static void file_list_button_event(lv_obj_t * list_btn, lv_event_t event) | |
{ | |
if(event == LV_EVENT_SHORT_CLICKED) { | |
if(selecting_mode) { | |
if(lv_btn_get_state(list_btn) == LV_BTN_STATE_TGL_REL) { | |
lv_btn_set_state(list_btn, LV_BTN_STATE_REL); | |
} else | |
lv_btn_set_state(list_btn, LV_BTN_STATE_TGL_REL); | |
return; | |
} | |
/* Get some basic information about the file */ | |
char *filename = lv_list_get_btn_text(list_btn); | |
lv_obj_t * img = lv_list_get_btn_img(list_btn); | |
/* This assumes that the button's image is always a symbol */ | |
bool is_dir = (!strcmp(lv_img_get_src(img), LV_SYMBOL_DIRECTORY)); | |
/* Only change to new directories */ | |
if(!is_dir) | |
return; | |
uint32_t len = strnlen(current_dir, LV_FS_MAX_PATH_LENGTH); | |
strncat(current_dir, "/", LV_FS_MAX_PATH_LENGTH - len - 1); | |
len++; | |
strncat(current_dir, filename, LV_FS_MAX_PATH_LENGTH - len - 1); | |
populate_list(); | |
/* The list button is deleted now */ | |
} else if(event == LV_EVENT_LONG_PRESSED) { | |
set_selecting_mode(true); | |
lv_btn_set_state(list_btn, LV_BTN_STATE_TGL_PR); | |
} | |
} | |
static void populate_list(void) | |
{ | |
static char fn[LV_FS_MAX_FN_LENGTH]; | |
lv_fs_res_t err; | |
lv_fs_dir_t dir; | |
bool is_dir; | |
err = lv_fs_dir_open(&dir, current_dir); | |
if(err != LV_FS_RES_OK) { | |
printf("Error: %d\n", err); | |
return; | |
} | |
/* Once the list changes we are no longer selecting */ | |
set_selecting_mode(false); | |
lv_list_clean(main_list); | |
fn[0] = 0; | |
do { | |
lv_fs_dir_read(&dir, fn); | |
if(fn[0] != 0) { | |
is_dir = (fn[0] == '/'); | |
lv_obj_t * list_btn = lv_list_add_btn(main_list, (is_dir ? LV_SYMBOL_DIRECTORY : LV_SYMBOL_FILE), &fn[is_dir]); | |
lv_obj_set_event_cb(list_btn, file_list_button_event); | |
} else | |
break; | |
} while(1); | |
lv_fs_dir_close(&dir); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment