1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00
lvgl/lv_app/lv_app_util/lv_app_fsel.c

382 lines
12 KiB
C
Raw Normal View History

/**
* @file lv_app_fsel.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_app_fsel.h"
#if LV_APP_ENABLE != 0
#include <stdio.h>
#include "lv_app_notice.h"
/*********************
* DEFINES
*********************/
#define LV_APP_FSEL_FN_MAX_LEN 128
#define LV_APP_FSEL_PATH_MAX_LEN 256
#define LV_APP_FSEL_PAGE_SIZE 8
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void fsel_refr(void);
static lv_action_res_t fsel_close_action(lv_obj_t * close, lv_dispi_t * dispi);
static lv_action_res_t fsel_up_action(lv_obj_t * up, lv_dispi_t * dispi);
static lv_action_res_t fsel_next_action(lv_obj_t * next, lv_dispi_t * dispi);
static lv_action_res_t fsel_prev_action(lv_obj_t * prev, lv_dispi_t * dispi);
static lv_action_res_t fsel_drv_action(lv_obj_t * drv, lv_dispi_t * dispi);
static lv_action_res_t fsel_drv_lpr_action(lv_obj_t * drv, lv_dispi_t * dispi);
static lv_action_res_t fsel_folder_action(lv_obj_t * folder, lv_dispi_t * dispi);
static lv_action_res_t fsel_folder_lpr_action(lv_obj_t * folder, lv_dispi_t * dispi);
static lv_action_res_t fsel_file_action(lv_obj_t * file, lv_dispi_t * dispi);
/**********************
* STATIC VARIABLES
**********************/
static const char * fsel_filter;
static char fsel_path[LV_APP_FSEL_PATH_MAX_LEN];
static uint16_t fsel_file_cnt;
static lv_obj_t * fsel_win;
static lv_obj_t * fsel_list;
static lv_lists_t fsel_lists;
static void * fsel_param;
static void (*fsel_ok_action)(void *, const char *);
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the File selector utility
*/
void lv_app_fsel_init(void)
{
lv_lists_get(LV_LISTS_TRANSP, &fsel_lists);
}
/**
* Open the File selector
* @param path start path
* @param filter show only files with a specific extension, e.g. "wav".
* "/" means filter to folders.
* @param param a free parameter which will be added to 'ok_action'
* @param ok_action an action to call when a file or folder is chosen
*/
void lv_app_fsel_open(const char * path, const char * filter, void * param, void (*ok_action)(void *, const char *))
{
2017-01-03 14:24:26 +01:00
/*Save the parameters*/
strcpy(fsel_path, path);
fsel_filter = filter;
fsel_file_cnt = 0;
fsel_param = param;
fsel_ok_action = ok_action;
2017-01-03 14:24:26 +01:00
/*Trim the extra '\' or '/' from the end of path*/
uint16_t i;
for(i = strlen(fsel_path) -1 ; fsel_path[i] == '/' || fsel_path[i] == '\\'; i--) {
fsel_path[i] = '\0';
}
/*Check filter: NULL and "" mean no filtering*/
if(fsel_filter == NULL) fsel_filter = "";
/*Create a window for the File selector*/
lv_app_style_t * app_style = lv_app_style_get();
fsel_win = lv_win_create(lv_scr_act(), NULL);
lv_obj_set_size(fsel_win, LV_HOR_RES, LV_VER_RES);
lv_obj_set_style(fsel_win, &app_style->win_style);
lv_win_add_ctrl_btn(fsel_win, "U:/icon_close", fsel_close_action);
fsel_refr(); /*Refresh the list*/
/*Show instruction when first open with folder filter*/
static bool first_folder_call = false;
if(first_folder_call == false && fsel_filter[0] == '/') {
lv_app_notice_add("Press a folder long\nto choose it!");
first_folder_call = true;
}
}
/**
* Close the File selector
*/
void lv_app_fsel_close(void)
{
if(fsel_win != NULL) {
lv_obj_del(fsel_win);
}
fsel_win = NULL;
fsel_list = NULL;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Refresh the file list according to the current path and filter
*/
static void fsel_refr(void)
{
/*Delete the previous list*/
if(fsel_list != NULL) {
lv_obj_del(fsel_list);
}
lv_win_set_title(fsel_win, fsel_path);
/*Create a new list*/
lv_app_style_t * app_style = lv_app_style_get();
fsel_list = lv_list_create(fsel_win, NULL);
lv_obj_set_width(fsel_list, app_style->win_useful_w);
lv_obj_set_style(fsel_list, lv_lists_get(LV_LISTS_TRANSP, NULL));
lv_obj_set_drag_parent(fsel_list, true);
lv_obj_set_drag_parent(lv_page_get_scrl(fsel_list), true);
lv_rect_set_fit(fsel_list, false, true);
fs_res_t res = FS_RES_OK;
/*At empty path show the drivers */
if(fsel_path[0] == '\0') {
char drv[16];
char buf[2];
lv_obj_t * liste;
fs_get_letters(drv);
uint8_t i;
for(i = 0; drv[i] != '\0'; i++) {
buf[0] = drv[i];
buf[1] = '\0';
liste = lv_list_add(fsel_list, "U:/icon_driver", buf, fsel_drv_action);
/*Add long press action to choose the driver as a folder*/
if(fsel_filter[0] == '/') lv_btn_set_lpr_action(liste, fsel_drv_lpr_action);
}
}
2017-01-03 14:24:26 +01:00
/*List the files/folders with fs interface*/
else {
lv_list_add(fsel_list, "U:/icon_up", "Up", fsel_up_action);
fs_readdir_t rd;
res = fs_readdir_init(&rd, fsel_path);
if(res != FS_RES_OK) {
lv_app_notice_add("Can not read the path\nin File selector");
return;
}
/*At not first page add prev. page button */
if(fsel_file_cnt != 0) {
lv_list_add(fsel_list, "U:/icon_left", "Previous page", fsel_prev_action);
}
char fn[LV_APP_FSEL_FN_MAX_LEN];
/*Read the files from the previous pages*/
uint16_t file_cnt = 0;
while(file_cnt <= fsel_file_cnt) {
res = fs_readdir(&rd, fn);
if(res != FS_RES_OK || fn[0] == '\0'){
lv_app_notice_add("Can not read the path\nin File selector");
return;
}
file_cnt ++;
}
/*Add list elements from the files and folders*/
while(res == FS_RES_OK && fn[0] != '\0') {
if(fn[0] == '/') { /*Add a folder*/
lv_obj_t * liste;
2017-01-03 14:24:26 +01:00
liste = lv_list_add(fsel_list, "U:/icon_folder", &fn[1], fsel_folder_action);
/*Add long press action to choose a folder*/
if(fsel_filter[0] == '/') lv_btn_set_lpr_action(liste, fsel_folder_lpr_action);
fsel_file_cnt ++;
file_cnt ++;
2017-01-03 14:24:26 +01:00
}
/*Add a file if it is not filtered*/
else if(fsel_filter[0] == '\0' || /*No filtering or ...*/
(strcmp(fs_get_ext(fn), fsel_filter) == 0 && /*.. the filter matches*/
fsel_filter[0] != '/')) {
lv_list_add(fsel_list, "U:/icon_file", fn, fsel_file_action);
fsel_file_cnt ++;
file_cnt ++;
}
/*Get the next element*/
res = fs_readdir(&rd, fn);
/*Show only LV_APP_FSEL_MAX_FILE elements and add a Next page button*/
if(fsel_file_cnt != 0 && fsel_file_cnt % LV_APP_FSEL_PAGE_SIZE == 0) {
lv_list_add(fsel_list, "U:/icon_right", "Next page", fsel_next_action);
break;
}
}
/*Close the read directory*/
fs_readdir_close(&rd);
}
if(res != FS_RES_OK) {
lv_app_notice_add("Can not read the path\nin File selector");
}
2017-01-03 14:24:26 +01:00
/*Focus to the top of the list*/
lv_obj_set_y(lv_page_get_scrl(fsel_list), 0);
}
/**
* Called when the File selector window close button is released
* @param close pointer to the close button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the window is deleted in the function
*/
static lv_action_res_t fsel_close_action(lv_obj_t * close, lv_dispi_t * dispi)
{
lv_app_fsel_close();
return LV_ACTION_RES_INV;
}
/**
* Called when the Up list element is released to step one level
* @param up pointer to the Up button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_up_action(lv_obj_t * up, lv_dispi_t * dispi)
{
fs_up(fsel_path);
2017-01-03 14:24:26 +01:00
fsel_file_cnt = 0;
fsel_refr();
return LV_ACTION_RES_INV;
}
/**
* Called when the Next list element is released to go to the next page
* @param next pointer to the Next button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_next_action(lv_obj_t * next, lv_dispi_t * dispi)
{
fsel_refr();
return LV_ACTION_RES_INV;
}
/**
* Called when the Prev list element is released to previous page
* @param prev pointer to the Prev button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_prev_action(lv_obj_t * prev, lv_dispi_t * dispi)
{
if(fsel_file_cnt <= 2 * LV_APP_FSEL_PAGE_SIZE) fsel_file_cnt = 0;
else if(fsel_file_cnt % LV_APP_FSEL_PAGE_SIZE == 0) {
fsel_file_cnt -= 2 * LV_APP_FSEL_PAGE_SIZE;
} else {
fsel_file_cnt = ((fsel_file_cnt / LV_APP_FSEL_PAGE_SIZE) - 1) * LV_APP_FSEL_PAGE_SIZE;
}
fsel_refr();
return LV_ACTION_RES_INV;
}
/**
* Called when the Driver list element is released to step into a driver
* @param drv pointer to the Driver button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_drv_action(lv_obj_t * drv, lv_dispi_t * dispi)
{
sprintf(fsel_path, "%s:", lv_list_element_get_txt(drv));
2017-01-03 14:24:26 +01:00
fsel_file_cnt = 0;
fsel_refr();
return LV_ACTION_RES_INV;
}
/**
* Called when the Driver list element is long pressed to choose it
* @param drv pointer to the Driver button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_drv_lpr_action(lv_obj_t * drv, lv_dispi_t * dispi)
{
sprintf(fsel_path, "%s:", lv_list_element_get_txt(drv));
if(fsel_ok_action != NULL) {
fsel_ok_action(fsel_param, fsel_path);
}
lv_app_fsel_close();
return LV_ACTION_RES_INV;
}
/**
* Called when a folder list element is released to enter into it
* @param folder pointer to a folder button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_folder_action(lv_obj_t * folder, lv_dispi_t * dispi)
{
sprintf(fsel_path, "%s/%s", fsel_path, lv_list_element_get_txt(folder));
2017-01-03 14:24:26 +01:00
fsel_file_cnt = 0;
fsel_refr();
return LV_ACTION_RES_INV;
}
/**
* Called when a folder list element is long pressed to choose it
* @param folder pointer to a folder button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_folder_lpr_action(lv_obj_t * folder, lv_dispi_t * dispi)
{
sprintf(fsel_path, "%s/%s", fsel_path, lv_list_element_get_txt(folder));
if(fsel_ok_action != NULL) {
fsel_ok_action(fsel_param, fsel_path);
}
lv_app_fsel_close();
return LV_ACTION_RES_INV;
}
/**
* Called when a file list element is released to choose it
* @param file pointer to a file button
* @param dispi pointer to the caller display input
* @return LV_ACTION_RES_INV because the list is deleted in the function
*/
static lv_action_res_t fsel_file_action(lv_obj_t * file, lv_dispi_t * dispi)
{
sprintf(fsel_path, "%s/%s", fsel_path, lv_list_element_get_txt(file));
if(fsel_ok_action != NULL) {
fsel_ok_action(fsel_param, fsel_path);
}
lv_app_fsel_close();
return LV_ACTION_RES_INV;
}
#endif /*LV_APP_ENABLE != 0*/