mirror of
https://github.com/No-Chicken/Power-Pico.git
synced 2026-04-03 13:02:36 +08:00
打包keil_MDK的工程
This commit is contained in:
@@ -1,707 +0,0 @@
|
||||
/**
|
||||
* @file lv_file_explorer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_file_explorer_private.h"
|
||||
#include "../../misc/lv_fs_private.h"
|
||||
#include "../../core/lv_obj_class_private.h"
|
||||
#if LV_USE_FILE_EXPLORER != 0
|
||||
|
||||
#include "../../lvgl.h"
|
||||
#include "../../core/lv_global.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS (&lv_file_explorer_class)
|
||||
|
||||
#define FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH (22)
|
||||
#define FILE_EXPLORER_BROWSER_AREA_WIDTH (100 - FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH)
|
||||
|
||||
#define quick_access_list_button_style (LV_GLOBAL_DEFAULT()->fe_list_button_style)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
|
||||
static void browser_file_event_handler(lv_event_t * e);
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
static void quick_access_event_handler(lv_event_t * e);
|
||||
static void quick_access_area_event_handler(lv_event_t * e);
|
||||
#endif
|
||||
|
||||
static void init_style(lv_obj_t * obj);
|
||||
static void show_dir(lv_obj_t * obj, const char * path);
|
||||
static void strip_ext(char * dir);
|
||||
static void file_explorer_sort(lv_obj_t * obj);
|
||||
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi);
|
||||
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j);
|
||||
static bool is_end_with(const char * str1, const char * str2);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
const lv_obj_class_t lv_file_explorer_class = {
|
||||
.constructor_cb = lv_file_explorer_constructor,
|
||||
.width_def = LV_SIZE_CONTENT,
|
||||
.height_def = LV_SIZE_CONTENT,
|
||||
.instance_size = sizeof(lv_file_explorer_t),
|
||||
.base_class = &lv_obj_class,
|
||||
.name = "file-explorer",
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_obj_t * lv_file_explorer_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
/*If path is unavailable */
|
||||
if((path == NULL) || (lv_strlen(path) <= 0)) return;
|
||||
|
||||
char ** dir_str = NULL;
|
||||
switch(dir) {
|
||||
case LV_EXPLORER_HOME_DIR:
|
||||
dir_str = &(explorer->home_dir);
|
||||
break;
|
||||
case LV_EXPLORER_MUSIC_DIR:
|
||||
dir_str = &(explorer->music_dir);
|
||||
break;
|
||||
case LV_EXPLORER_PICTURES_DIR:
|
||||
dir_str = &(explorer->pictures_dir);
|
||||
break;
|
||||
case LV_EXPLORER_VIDEO_DIR:
|
||||
dir_str = &(explorer->video_dir);
|
||||
break;
|
||||
case LV_EXPLORER_DOCS_DIR:
|
||||
dir_str = &(explorer->docs_dir);
|
||||
break;
|
||||
case LV_EXPLORER_FS_DIR:
|
||||
dir_str = &(explorer->fs_dir);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Free the old text*/
|
||||
if(*dir_str != NULL) {
|
||||
lv_free(*dir_str);
|
||||
*dir_str = NULL;
|
||||
}
|
||||
|
||||
/*Allocate space for the new text*/
|
||||
*dir_str = lv_strdup(path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
explorer->sort = sort;
|
||||
|
||||
file_explorer_sort(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->sel_fn;
|
||||
}
|
||||
|
||||
const char * lv_file_explorer_get_current_path(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->current_path;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->file_table;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->head_area;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->path_label;
|
||||
}
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->quick_access_area;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->list_places;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->list_device;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
return explorer->sort;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
show_dir(obj, dir);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
explorer->home_dir = NULL;
|
||||
explorer->video_dir = NULL;
|
||||
explorer->pictures_dir = NULL;
|
||||
explorer->music_dir = NULL;
|
||||
explorer->docs_dir = NULL;
|
||||
explorer->fs_dir = NULL;
|
||||
#endif
|
||||
|
||||
explorer->sort = LV_EXPLORER_SORT_NONE;
|
||||
|
||||
lv_memzero(explorer->current_path, sizeof(explorer->current_path));
|
||||
|
||||
lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
explorer->cont = lv_obj_create(obj);
|
||||
lv_obj_set_width(explorer->cont, LV_PCT(100));
|
||||
lv_obj_set_flex_grow(explorer->cont, 1);
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/*Quick access bar area on the left*/
|
||||
explorer->quick_access_area = lv_obj_create(explorer->cont);
|
||||
lv_obj_set_size(explorer->quick_access_area, LV_PCT(FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH), LV_PCT(100));
|
||||
lv_obj_set_flex_flow(explorer->quick_access_area, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_add_event_cb(explorer->quick_access_area, quick_access_area_event_handler, LV_EVENT_ALL,
|
||||
explorer);
|
||||
#endif
|
||||
|
||||
/*File table area on the right*/
|
||||
explorer->browser_area = lv_obj_create(explorer->cont);
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100));
|
||||
#else
|
||||
lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100));
|
||||
#endif
|
||||
lv_obj_set_flex_flow(explorer->browser_area, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
/*The area displayed above the file browse list(head)*/
|
||||
explorer->head_area = lv_obj_create(explorer->browser_area);
|
||||
lv_obj_set_size(explorer->head_area, LV_PCT(100), LV_PCT(14));
|
||||
lv_obj_remove_flag(explorer->head_area, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/*Two lists of quick access bar*/
|
||||
lv_obj_t * btn;
|
||||
/*list 1*/
|
||||
explorer->list_device = lv_list_create(explorer->quick_access_area);
|
||||
lv_obj_set_size(explorer->list_device, LV_PCT(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_device, "DEVICE"), lv_palette_main(LV_PALETTE_ORANGE), 0);
|
||||
|
||||
btn = lv_list_add_button(explorer->list_device, NULL, LV_SYMBOL_DRIVE " File System");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
|
||||
/*list 2*/
|
||||
explorer->list_places = lv_list_create(explorer->quick_access_area);
|
||||
lv_obj_set_size(explorer->list_places, LV_PCT(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_places, "PLACES"), lv_palette_main(LV_PALETTE_LIME), 0);
|
||||
|
||||
btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_HOME " HOME");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_VIDEO " Video");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_IMAGE " Pictures");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_AUDIO " Music");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_FILE " Documents");
|
||||
lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj);
|
||||
#endif
|
||||
|
||||
/*Show current path*/
|
||||
explorer->path_label = lv_label_create(explorer->head_area);
|
||||
lv_label_set_text(explorer->path_label, LV_SYMBOL_EYE_OPEN"https://lvgl.io");
|
||||
lv_obj_center(explorer->path_label);
|
||||
|
||||
/*Table showing the contents of the table of contents*/
|
||||
explorer->file_table = lv_table_create(explorer->browser_area);
|
||||
lv_obj_set_size(explorer->file_table, LV_PCT(100), LV_PCT(86));
|
||||
lv_table_set_column_width(explorer->file_table, 0, LV_PCT(100));
|
||||
lv_table_set_column_count(explorer->file_table, 1);
|
||||
lv_obj_add_event_cb(explorer->file_table, browser_file_event_handler, LV_EVENT_ALL, obj);
|
||||
|
||||
/*only scroll up and down*/
|
||||
lv_obj_set_scroll_dir(explorer->file_table, LV_DIR_TOP | LV_DIR_BOTTOM);
|
||||
|
||||
/*Initialize style*/
|
||||
init_style(obj);
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void init_style(lv_obj_t * obj)
|
||||
{
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
/*lv_file_explorer obj style*/
|
||||
lv_obj_set_style_radius(obj, 0, 0);
|
||||
lv_obj_set_style_bg_color(obj, lv_color_hex(0xf2f1f6), 0);
|
||||
|
||||
/*main container style*/
|
||||
lv_obj_set_style_radius(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_bg_opa(explorer->cont, LV_OPA_0, 0);
|
||||
lv_obj_set_style_border_width(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_outline_width(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_pad_column(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_pad_row(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_flex_flow(explorer->cont, LV_FLEX_FLOW_ROW, 0);
|
||||
lv_obj_set_style_pad_all(explorer->cont, 0, 0);
|
||||
lv_obj_set_style_layout(explorer->cont, LV_LAYOUT_FLEX, 0);
|
||||
|
||||
/*head cont style*/
|
||||
lv_obj_set_style_radius(explorer->head_area, 0, 0);
|
||||
lv_obj_set_style_border_width(explorer->head_area, 0, 0);
|
||||
lv_obj_set_style_pad_top(explorer->head_area, 0, 0);
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/*Quick access bar container style*/
|
||||
lv_obj_set_style_pad_all(explorer->quick_access_area, 0, 0);
|
||||
lv_obj_set_style_pad_row(explorer->quick_access_area, 20, 0);
|
||||
lv_obj_set_style_radius(explorer->quick_access_area, 0, 0);
|
||||
lv_obj_set_style_border_width(explorer->quick_access_area, 1, 0);
|
||||
lv_obj_set_style_outline_width(explorer->quick_access_area, 0, 0);
|
||||
lv_obj_set_style_bg_color(explorer->quick_access_area, lv_color_hex(0xf2f1f6), 0);
|
||||
#endif
|
||||
|
||||
/*File browser container style*/
|
||||
lv_obj_set_style_pad_all(explorer->browser_area, 0, 0);
|
||||
lv_obj_set_style_pad_row(explorer->browser_area, 0, 0);
|
||||
lv_obj_set_style_radius(explorer->browser_area, 0, 0);
|
||||
lv_obj_set_style_border_width(explorer->browser_area, 0, 0);
|
||||
lv_obj_set_style_outline_width(explorer->browser_area, 0, 0);
|
||||
lv_obj_set_style_bg_color(explorer->browser_area, lv_color_hex(0xffffff), 0);
|
||||
|
||||
/*Style of the table in the browser container*/
|
||||
lv_obj_set_style_bg_color(explorer->file_table, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_set_style_pad_all(explorer->file_table, 0, 0);
|
||||
lv_obj_set_style_radius(explorer->file_table, 0, 0);
|
||||
lv_obj_set_style_border_width(explorer->file_table, 0, 0);
|
||||
lv_obj_set_style_outline_width(explorer->file_table, 0, 0);
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/*Style of the list in the quick access bar*/
|
||||
lv_obj_set_style_border_width(explorer->list_device, 0, 0);
|
||||
lv_obj_set_style_outline_width(explorer->list_device, 0, 0);
|
||||
lv_obj_set_style_radius(explorer->list_device, 0, 0);
|
||||
lv_obj_set_style_pad_all(explorer->list_device, 0, 0);
|
||||
|
||||
lv_obj_set_style_border_width(explorer->list_places, 0, 0);
|
||||
lv_obj_set_style_outline_width(explorer->list_places, 0, 0);
|
||||
lv_obj_set_style_radius(explorer->list_places, 0, 0);
|
||||
lv_obj_set_style_pad_all(explorer->list_places, 0, 0);
|
||||
|
||||
/*Style of the quick access list btn in the quick access bar*/
|
||||
lv_style_init(&quick_access_list_button_style);
|
||||
lv_style_set_border_width(&quick_access_list_button_style, 0);
|
||||
lv_style_set_bg_color(&quick_access_list_button_style, lv_color_hex(0xf2f1f6));
|
||||
|
||||
uint32_t i, j;
|
||||
for(i = 0; i < lv_obj_get_child_count(explorer->quick_access_area); i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(explorer->quick_access_area, i);
|
||||
if(lv_obj_check_type(child, &lv_list_class)) {
|
||||
for(j = 0; j < lv_obj_get_child_count(child); j++) {
|
||||
lv_obj_t * list_child = lv_obj_get_child(child, j);
|
||||
if(lv_obj_check_type(list_child, &lv_list_button_class)) {
|
||||
lv_obj_add_style(list_child, &quick_access_list_button_style, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
static void quick_access_event_handler(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * btn = lv_event_get_current_target(e);
|
||||
lv_obj_t * obj = lv_event_get_user_data(e);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
if(code == LV_EVENT_CLICKED) {
|
||||
char ** path = NULL;
|
||||
lv_obj_t * label = lv_obj_get_child(btn, -1);
|
||||
char * label_text = lv_label_get_text(label);
|
||||
|
||||
if((lv_strcmp(label_text, LV_SYMBOL_HOME " HOME") == 0)) {
|
||||
path = &(explorer->home_dir);
|
||||
}
|
||||
else if((lv_strcmp(label_text, LV_SYMBOL_VIDEO " Video") == 0)) {
|
||||
path = &(explorer->video_dir);
|
||||
}
|
||||
else if((lv_strcmp(label_text, LV_SYMBOL_IMAGE " Pictures") == 0)) {
|
||||
path = &(explorer->pictures_dir);
|
||||
}
|
||||
else if((lv_strcmp(label_text, LV_SYMBOL_AUDIO " Music") == 0)) {
|
||||
path = &(explorer->music_dir);
|
||||
}
|
||||
else if((lv_strcmp(label_text, LV_SYMBOL_FILE " Documents") == 0)) {
|
||||
path = &(explorer->docs_dir);
|
||||
}
|
||||
else if((lv_strcmp(label_text, LV_SYMBOL_DRIVE " File System") == 0)) {
|
||||
path = &(explorer->fs_dir);
|
||||
}
|
||||
|
||||
if(path != NULL)
|
||||
show_dir(obj, *path);
|
||||
}
|
||||
}
|
||||
|
||||
static void quick_access_area_event_handler(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * area = lv_event_get_current_target(e);
|
||||
lv_obj_t * obj = lv_event_get_user_data(e);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
if(code == LV_EVENT_LAYOUT_CHANGED) {
|
||||
if(lv_obj_has_flag(area, LV_OBJ_FLAG_HIDDEN))
|
||||
lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100));
|
||||
else
|
||||
lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void browser_file_event_handler(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_user_data(e);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
char file_name[LV_FILE_EXPLORER_PATH_MAX_LEN];
|
||||
const char * str_fn = NULL;
|
||||
uint32_t row;
|
||||
uint32_t col;
|
||||
|
||||
lv_memzero(file_name, sizeof(file_name));
|
||||
lv_table_get_selected_cell(explorer->file_table, &row, &col);
|
||||
str_fn = lv_table_get_cell_value(explorer->file_table, row, col);
|
||||
|
||||
str_fn = str_fn + 5;
|
||||
if((lv_strcmp(str_fn, ".") == 0)) return;
|
||||
|
||||
if((lv_strcmp(str_fn, "..") == 0) && (lv_strlen(explorer->current_path) > 3)) {
|
||||
strip_ext(explorer->current_path);
|
||||
/*Remove the last '/' character*/
|
||||
strip_ext(explorer->current_path);
|
||||
lv_snprintf((char *)file_name, sizeof(file_name), "%s", explorer->current_path);
|
||||
}
|
||||
else {
|
||||
if(lv_strcmp(str_fn, "..") != 0) {
|
||||
lv_snprintf((char *)file_name, sizeof(file_name), "%s%s", explorer->current_path, str_fn);
|
||||
}
|
||||
}
|
||||
|
||||
lv_fs_dir_t dir;
|
||||
if(lv_fs_dir_open(&dir, file_name) == LV_FS_RES_OK) {
|
||||
lv_fs_dir_close(&dir);
|
||||
show_dir(obj, (char *)file_name);
|
||||
}
|
||||
else {
|
||||
if(lv_strcmp(str_fn, "..") != 0) {
|
||||
explorer->sel_fn = str_fn;
|
||||
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_SIZE_CHANGED) {
|
||||
lv_table_set_column_width(explorer->file_table, 0, lv_obj_get_width(explorer->file_table));
|
||||
}
|
||||
else if((code == LV_EVENT_CLICKED) || (code == LV_EVENT_RELEASED)) {
|
||||
lv_obj_send_event(obj, LV_EVENT_CLICKED, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_dir(lv_obj_t * obj, const char * path)
|
||||
{
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
char fn[LV_FILE_EXPLORER_PATH_MAX_LEN];
|
||||
uint16_t index = 0;
|
||||
lv_fs_dir_t dir;
|
||||
lv_fs_res_t res;
|
||||
|
||||
res = lv_fs_dir_open(&dir, path);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_USER("Open dir error %d!", res);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", ".");
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", "..");
|
||||
lv_table_set_cell_value(explorer->file_table, 0, 1, "0");
|
||||
lv_table_set_cell_value(explorer->file_table, 1, 1, "0");
|
||||
|
||||
while(1) {
|
||||
res = lv_fs_dir_read(&dir, fn, sizeof(fn));
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_USER("Driver, file or directory is not exists %d!", res);
|
||||
break;
|
||||
}
|
||||
|
||||
/*fn is empty, if not more files to read*/
|
||||
if(lv_strlen(fn) == 0) {
|
||||
LV_LOG_USER("Not more files to read!");
|
||||
break;
|
||||
}
|
||||
|
||||
if((is_end_with(fn, ".png") == true) || (is_end_with(fn, ".PNG") == true) || \
|
||||
(is_end_with(fn, ".jpg") == true) || (is_end_with(fn, ".JPG") == true) || \
|
||||
(is_end_with(fn, ".bmp") == true) || (is_end_with(fn, ".BMP") == true) || \
|
||||
(is_end_with(fn, ".gif") == true) || (is_end_with(fn, ".GIF") == true)) {
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_IMAGE " %s", fn);
|
||||
lv_table_set_cell_value(explorer->file_table, index, 1, "1");
|
||||
}
|
||||
else if((is_end_with(fn, ".mp3") == true) || (is_end_with(fn, ".MP3") == true) || \
|
||||
(is_end_with(fn, ".wav") == true) || (is_end_with(fn, ".WAV") == true)) {
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_AUDIO " %s", fn);
|
||||
lv_table_set_cell_value(explorer->file_table, index, 1, "2");
|
||||
}
|
||||
else if((is_end_with(fn, ".mp4") == true) || (is_end_with(fn, ".MP4") == true)) {
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_VIDEO " %s", fn);
|
||||
lv_table_set_cell_value(explorer->file_table, index, 1, "3");
|
||||
}
|
||||
else if((is_end_with(fn, ".") == true) || (is_end_with(fn, "..") == true)) {
|
||||
/*is dir*/
|
||||
continue;
|
||||
}
|
||||
else if(fn[0] == '/') {/*is dir*/
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_DIRECTORY " %s", fn + 1);
|
||||
lv_table_set_cell_value(explorer->file_table, index, 1, "0");
|
||||
}
|
||||
else {
|
||||
lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_FILE " %s", fn);
|
||||
lv_table_set_cell_value(explorer->file_table, index, 1, "4");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
lv_fs_dir_close(&dir);
|
||||
|
||||
lv_table_set_row_count(explorer->file_table, index);
|
||||
file_explorer_sort(obj);
|
||||
lv_obj_send_event(obj, LV_EVENT_READY, NULL);
|
||||
|
||||
/*Move the table to the top*/
|
||||
lv_obj_scroll_to_y(explorer->file_table, 0, LV_ANIM_OFF);
|
||||
|
||||
lv_strlcpy(explorer->current_path, path, sizeof(explorer->current_path));
|
||||
lv_label_set_text_fmt(explorer->path_label, LV_SYMBOL_EYE_OPEN" %s", path);
|
||||
|
||||
size_t current_path_len = lv_strlen(explorer->current_path);
|
||||
if((*((explorer->current_path) + current_path_len) != '/') && (current_path_len < LV_FILE_EXPLORER_PATH_MAX_LEN)) {
|
||||
*((explorer->current_path) + current_path_len) = '/';
|
||||
}
|
||||
}
|
||||
|
||||
/*Remove the specified suffix*/
|
||||
static void strip_ext(char * dir)
|
||||
{
|
||||
char * end = dir + lv_strlen(dir);
|
||||
|
||||
while(end >= dir && *end != '/') {
|
||||
--end;
|
||||
}
|
||||
|
||||
if(end > dir) {
|
||||
*end = '\0';
|
||||
}
|
||||
else if(end == dir) {
|
||||
*(end + 1) = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j)
|
||||
{
|
||||
const char * tmp;
|
||||
tmp = lv_table_get_cell_value(tb, i, 0);
|
||||
lv_table_set_cell_value(tb, 0, 2, tmp);
|
||||
lv_table_set_cell_value(tb, i, 0, lv_table_get_cell_value(tb, j, 0));
|
||||
lv_table_set_cell_value(tb, j, 0, lv_table_get_cell_value(tb, 0, 2));
|
||||
|
||||
tmp = lv_table_get_cell_value(tb, i, 1);
|
||||
lv_table_set_cell_value(tb, 0, 2, tmp);
|
||||
lv_table_set_cell_value(tb, i, 1, lv_table_get_cell_value(tb, j, 1));
|
||||
lv_table_set_cell_value(tb, j, 1, lv_table_get_cell_value(tb, 0, 2));
|
||||
}
|
||||
|
||||
static void file_explorer_sort(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj;
|
||||
|
||||
uint16_t sum = lv_table_get_row_count(explorer->file_table);
|
||||
|
||||
if(sum > 1) {
|
||||
switch(explorer->sort) {
|
||||
case LV_EXPLORER_SORT_NONE:
|
||||
break;
|
||||
case LV_EXPLORER_SORT_KIND:
|
||||
sort_by_file_kind(explorer->file_table, 0, (sum - 1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Quick sort 3 way*/
|
||||
static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi)
|
||||
{
|
||||
if(lo >= hi) return;
|
||||
|
||||
int16_t lt = lo;
|
||||
int16_t i = lo + 1;
|
||||
int16_t gt = hi;
|
||||
const char * v = lv_table_get_cell_value(tb, lo, 1);
|
||||
while(i <= gt) {
|
||||
if(lv_strcmp(lv_table_get_cell_value(tb, i, 1), v) < 0)
|
||||
exch_table_item(tb, lt++, i++);
|
||||
else if(lv_strcmp(lv_table_get_cell_value(tb, i, 1), v) > 0)
|
||||
exch_table_item(tb, i, gt--);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
sort_by_file_kind(tb, lo, lt - 1);
|
||||
sort_by_file_kind(tb, gt + 1, hi);
|
||||
}
|
||||
|
||||
static bool is_end_with(const char * str1, const char * str2)
|
||||
{
|
||||
if(str1 == NULL || str2 == NULL)
|
||||
return false;
|
||||
|
||||
uint16_t len1 = lv_strlen(str1);
|
||||
uint16_t len2 = lv_strlen(str2);
|
||||
if((len1 < len2) || (len1 == 0 || len2 == 0))
|
||||
return false;
|
||||
|
||||
while(len2 >= 1) {
|
||||
if(str2[len2 - 1] != str1[len1 - 1])
|
||||
return false;
|
||||
|
||||
len2--;
|
||||
len1--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FILE_EXPLORER*/
|
||||
@@ -1,168 +0,0 @@
|
||||
/**
|
||||
* @file lv_file_explorer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FILE_EXPLORER_H
|
||||
#define LV_FILE_EXPLORER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#include "../../core/lv_obj.h"
|
||||
|
||||
#if LV_USE_FILE_EXPLORER != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_EXPLORER_SORT_NONE,
|
||||
LV_EXPLORER_SORT_KIND,
|
||||
} lv_file_explorer_sort_t;
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
typedef enum {
|
||||
LV_EXPLORER_HOME_DIR,
|
||||
LV_EXPLORER_MUSIC_DIR,
|
||||
LV_EXPLORER_PICTURES_DIR,
|
||||
LV_EXPLORER_VIDEO_DIR,
|
||||
LV_EXPLORER_DOCS_DIR,
|
||||
LV_EXPLORER_FS_DIR,
|
||||
} lv_file_explorer_dir_t;
|
||||
#endif
|
||||
|
||||
extern const lv_obj_class_t lv_file_explorer_class;
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
lv_obj_t * lv_file_explorer_create(lv_obj_t * parent);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/**
|
||||
* Set file_explorer
|
||||
* @param obj pointer to a label object
|
||||
* @param dir the dir from 'lv_file_explorer_dir_t' enum.
|
||||
* @param path path
|
||||
|
||||
*/
|
||||
void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set file_explorer sort
|
||||
* @param obj pointer to a file explorer object
|
||||
* @param sort the sort from 'lv_file_explorer_sort_t' enum.
|
||||
*/
|
||||
void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get file explorer Selected file
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer selected file name
|
||||
*/
|
||||
const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get file explorer cur path
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer cur path
|
||||
*/
|
||||
const char * lv_file_explorer_get_current_path(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get file explorer head area obj
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer head area obj(lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get file explorer head area obj
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer quick access area obj(lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get file explorer path obj(label)
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer path obj(lv_label)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj);
|
||||
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
/**
|
||||
* Get file explorer places list obj(lv_list)
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer places list obj(lv_list)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get file explorer device list obj(lv_list)
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer device list obj(lv_list)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get file explorer file list obj(lv_table)
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return pointer to the file explorer file table obj(lv_table)
|
||||
*/
|
||||
lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set file_explorer sort
|
||||
* @param obj pointer to a file explorer object
|
||||
* @return the current mode from 'lv_file_explorer_sort_t'
|
||||
*/
|
||||
lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Open a specified path
|
||||
* @param obj pointer to a file explorer object
|
||||
* @param dir pointer to the path
|
||||
*/
|
||||
void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FILE_EXPLORER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FILE_EXPLORER_H*/
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* @file lv_file_explorer_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FILE_EXPLORER_PRIVATE_H
|
||||
#define LV_FILE_EXPLORER_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../core/lv_obj_private.h"
|
||||
#include "lv_file_explorer.h"
|
||||
|
||||
#if LV_USE_FILE_EXPLORER != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of canvas*/
|
||||
struct lv_file_explorer_t {
|
||||
lv_obj_t obj;
|
||||
lv_obj_t * cont;
|
||||
lv_obj_t * head_area;
|
||||
lv_obj_t * browser_area;
|
||||
lv_obj_t * file_table;
|
||||
lv_obj_t * path_label;
|
||||
#if LV_FILE_EXPLORER_QUICK_ACCESS
|
||||
lv_obj_t * quick_access_area;
|
||||
lv_obj_t * list_device;
|
||||
lv_obj_t * list_places;
|
||||
char * home_dir;
|
||||
char * music_dir;
|
||||
char * pictures_dir;
|
||||
char * video_dir;
|
||||
char * docs_dir;
|
||||
char * fs_dir;
|
||||
#endif
|
||||
const char * sel_fn;
|
||||
char current_path[LV_FILE_EXPLORER_PATH_MAX_LEN];
|
||||
lv_file_explorer_sort_t sort;
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_FILE_EXPLORER != 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FILE_EXPLORER_PRIVATE_H*/
|
||||
@@ -1,155 +0,0 @@
|
||||
/**
|
||||
* @file lv_fragment.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_fragment_private.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void cb_delete_assertion(lv_event_t * event);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args)
|
||||
{
|
||||
LV_ASSERT_NULL(cls);
|
||||
LV_ASSERT_NULL(cls->create_obj_cb);
|
||||
LV_ASSERT(cls->instance_size >= sizeof(lv_fragment_t));
|
||||
lv_fragment_t * instance = lv_malloc_zeroed(cls->instance_size);
|
||||
instance->cls = cls;
|
||||
instance->child_manager = lv_fragment_manager_create(instance);
|
||||
if(cls->constructor_cb) {
|
||||
cls->constructor_cb(instance, args);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void lv_fragment_delete(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
if(fragment->managed) {
|
||||
lv_fragment_manager_remove(fragment->managed->manager, fragment);
|
||||
return;
|
||||
}
|
||||
if(fragment->obj) {
|
||||
lv_fragment_delete_obj(fragment);
|
||||
}
|
||||
/* Objects will leak if this function called before objects deleted */
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
if(cls->destructor_cb) {
|
||||
cls->destructor_cb(fragment);
|
||||
}
|
||||
lv_fragment_manager_delete(fragment->child_manager);
|
||||
lv_free(fragment);
|
||||
}
|
||||
|
||||
lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
return fragment->managed->manager;
|
||||
}
|
||||
|
||||
lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
return fragment->managed->container;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
return lv_fragment_manager_get_parent_fragment(fragment->managed->manager);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container)
|
||||
{
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
if(states) {
|
||||
states->destroying_obj = false;
|
||||
}
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
lv_obj_t * obj = cls->create_obj_cb(fragment, container);
|
||||
LV_ASSERT_NULL(obj);
|
||||
fragment->obj = obj;
|
||||
lv_fragment_manager_create_obj(fragment->child_manager);
|
||||
if(states) {
|
||||
states->obj_created = true;
|
||||
lv_obj_add_event_cb(obj, cb_delete_assertion, LV_EVENT_DELETE, NULL);
|
||||
}
|
||||
if(cls->obj_created_cb) {
|
||||
cls->obj_created_cb(fragment, obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_fragment_delete_obj(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
lv_fragment_manager_delete_obj(fragment->child_manager);
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
if(states) {
|
||||
if(!states->obj_created) return;
|
||||
states->destroying_obj = true;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t event_cnt = lv_obj_get_event_count(fragment->obj);
|
||||
bool cb_removed = false;
|
||||
for(i = 0; i < event_cnt; i++) {
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(fragment->obj, i);
|
||||
if(lv_event_dsc_get_cb(event_dsc) == cb_delete_assertion) {
|
||||
cb_removed = lv_obj_remove_event(fragment->obj, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LV_ASSERT(cb_removed);
|
||||
}
|
||||
LV_ASSERT_NULL(fragment->obj);
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
if(cls->obj_will_delete_cb) {
|
||||
cls->obj_will_delete_cb(fragment, fragment->obj);
|
||||
}
|
||||
lv_obj_delete(fragment->obj);
|
||||
if(cls->obj_deleted_cb) {
|
||||
cls->obj_deleted_cb(fragment, fragment->obj);
|
||||
}
|
||||
if(states) {
|
||||
states->obj_created = false;
|
||||
}
|
||||
fragment->obj = NULL;
|
||||
}
|
||||
|
||||
void lv_fragment_recreate_obj(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
lv_fragment_delete_obj(fragment);
|
||||
lv_fragment_create_obj(fragment, *fragment->managed->container);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void cb_delete_assertion(lv_event_t * event)
|
||||
{
|
||||
LV_UNUSED(event);
|
||||
LV_ASSERT_MSG(0, "Please delete objects with lv_fragment_destroy_obj");
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
||||
@@ -1,297 +0,0 @@
|
||||
/**
|
||||
* Public header for Fragment
|
||||
* @file lv_fragment.h
|
||||
*/
|
||||
|
||||
#ifndef LV_FRAGMENT_H
|
||||
#define LV_FRAGMENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../core/lv_obj.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_fragment_manager_t lv_fragment_manager_t;
|
||||
|
||||
struct lv_fragment_t {
|
||||
/**
|
||||
* Class of this fragment
|
||||
*/
|
||||
const lv_fragment_class_t * cls;
|
||||
/**
|
||||
* Managed fragment states. If not null, then this fragment is managed.
|
||||
*
|
||||
* @warning Don't modify values inside this struct!
|
||||
*/
|
||||
lv_fragment_managed_states_t * managed;
|
||||
/**
|
||||
* Child fragment manager
|
||||
*/
|
||||
lv_fragment_manager_t * child_manager;
|
||||
/**
|
||||
* lv_obj returned by create_obj_cb
|
||||
*/
|
||||
lv_obj_t * obj;
|
||||
|
||||
};
|
||||
|
||||
struct lv_fragment_class_t {
|
||||
/**
|
||||
* Constructor function for fragment class
|
||||
* @param self Fragment instance
|
||||
* @param args Arguments assigned by fragment manager
|
||||
*/
|
||||
void (*constructor_cb)(lv_fragment_t * self, void * args);
|
||||
|
||||
/**
|
||||
* Destructor function for fragment class
|
||||
* @param self Fragment instance, will be freed after this call
|
||||
*/
|
||||
void (*destructor_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Fragment attached to manager
|
||||
* @param self Fragment instance
|
||||
*/
|
||||
void (*attached_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Fragment detached from manager
|
||||
* @param self Fragment instance
|
||||
*/
|
||||
void (*detached_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Create objects
|
||||
* @param self Fragment instance
|
||||
* @param container Container of the objects should be created upon
|
||||
* @return Created object, NULL if multiple objects has been created
|
||||
*/
|
||||
lv_obj_t * (*create_obj_cb)(lv_fragment_t * self, lv_obj_t * container);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param self Fragment instance
|
||||
* @param obj lv_obj returned by create_obj_cb
|
||||
*/
|
||||
void (*obj_created_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Called before objects in the fragment will be deleted.
|
||||
*
|
||||
* @param self Fragment instance
|
||||
* @param obj object with this fragment
|
||||
*/
|
||||
void (*obj_will_delete_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Called when the object created by fragment received `LV_EVENT_DELETE` event
|
||||
* @param self Fragment instance
|
||||
* @param obj object with this fragment
|
||||
*/
|
||||
void (*obj_deleted_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Handle event
|
||||
* @param self Fragment instance
|
||||
* @param which User-defined ID of event
|
||||
* @param data1 User-defined data
|
||||
* @param data2 User-defined data
|
||||
*/
|
||||
bool (*event_cb)(lv_fragment_t * self, int code, void * userdata);
|
||||
|
||||
/**
|
||||
* *REQUIRED*: Allocation size of fragment
|
||||
*/
|
||||
size_t instance_size;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create fragment manager instance
|
||||
* @param parent Parent fragment if this manager is placed inside another fragment, can be null.
|
||||
* @return Fragment manager instance
|
||||
*/
|
||||
lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent);
|
||||
|
||||
/**
|
||||
* Destroy fragment manager instance
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_delete(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Create object of all fragments managed by this manager.
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted.
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_delete_obj(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Attach fragment to manager, and add to container.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Detach and destroy fragment. If fragment is in navigation stack, remove from it.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
*/
|
||||
void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Attach fragment to manager and add to navigation stack.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Remove the top-most fragment for stack
|
||||
* @param manager Fragment manager instance
|
||||
* @return true if there is fragment to pop
|
||||
*/
|
||||
bool lv_fragment_manager_pop(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Replace fragment. Old item in the stack will be removed.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Send event to top-most fragment
|
||||
* @param manager Fragment manager instance
|
||||
* @param code User-defined ID of event
|
||||
* @param userdata User-defined data
|
||||
* @return true if fragment returned true
|
||||
*/
|
||||
bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata);
|
||||
|
||||
/**
|
||||
* Get stack size of this fragment manager
|
||||
* @param manager Fragment manager instance
|
||||
* @return Stack size of this fragment manager
|
||||
*/
|
||||
size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Get top most fragment instance
|
||||
* @param manager Fragment manager instance
|
||||
* @return Top most fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Find first fragment instance in the container
|
||||
* @param manager Fragment manager instance
|
||||
* @param container Container which target fragment added to
|
||||
* @return First fragment instance in the container
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container);
|
||||
|
||||
/**
|
||||
* Get parent fragment
|
||||
* @param manager Fragment manager instance
|
||||
* @return Parent fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Create a fragment instance.
|
||||
*
|
||||
* @param cls Fragment class. This fragment must return non null object.
|
||||
* @param args Arguments assigned by fragment manager
|
||||
* @return Fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args);
|
||||
|
||||
/**
|
||||
* Destroy a fragment.
|
||||
* @param fragment Fragment instance.
|
||||
*/
|
||||
void lv_fragment_delete(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get associated manager of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Fragment manager instance
|
||||
*/
|
||||
lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get container object of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Reference to container object
|
||||
*/
|
||||
lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get parent fragment of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Parent fragment
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Create object by fragment.
|
||||
*
|
||||
* @param fragment Fragment instance.
|
||||
* @param container Container of the objects should be created upon.
|
||||
* @return Created object
|
||||
*/
|
||||
lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container);
|
||||
|
||||
/**
|
||||
* Delete created object of a fragment
|
||||
*
|
||||
* @param fragment Fragment instance.
|
||||
*/
|
||||
void lv_fragment_delete_obj(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Destroy obj in fragment, and recreate them.
|
||||
* @param fragment Fragment instance
|
||||
*/
|
||||
void lv_fragment_recreate_obj(lv_fragment_t * fragment);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FRAGMENT_H*/
|
||||
@@ -1,279 +0,0 @@
|
||||
/**
|
||||
* @file lv_fragment_manager.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_fragment_private.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
#include "../../misc/lv_ll.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct lv_fragment_stack_item_t {
|
||||
lv_fragment_managed_states_t * states;
|
||||
} lv_fragment_stack_item_t;
|
||||
|
||||
struct lv_fragment_manager_t {
|
||||
lv_fragment_t * parent;
|
||||
/**
|
||||
* Linked list to store attached fragments
|
||||
*/
|
||||
lv_ll_t attached;
|
||||
/**
|
||||
* Linked list to store fragments in stack
|
||||
*/
|
||||
lv_ll_t stack;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void item_create_obj(lv_fragment_managed_states_t * item);
|
||||
|
||||
static void item_delete_obj(lv_fragment_managed_states_t * item);
|
||||
|
||||
static void item_delete_fragment(lv_fragment_managed_states_t * item);
|
||||
|
||||
static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent)
|
||||
{
|
||||
lv_fragment_manager_t * instance = lv_malloc_zeroed(sizeof(lv_fragment_manager_t));
|
||||
instance->parent = parent;
|
||||
lv_ll_init(&instance->attached, sizeof(lv_fragment_managed_states_t));
|
||||
lv_ll_init(&instance->stack, sizeof(lv_fragment_stack_item_t));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void lv_fragment_manager_delete(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_managed_states_t * states;
|
||||
LV_LL_READ_BACK(&manager->attached, states) {
|
||||
item_delete_obj(states);
|
||||
item_delete_fragment(states);
|
||||
}
|
||||
lv_ll_clear(&manager->attached);
|
||||
lv_ll_clear(&manager->stack);
|
||||
lv_free(manager);
|
||||
}
|
||||
|
||||
void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_stack_item_t * top = lv_ll_get_tail(&manager->stack);
|
||||
lv_fragment_managed_states_t * states = NULL;
|
||||
LV_LL_READ(&manager->attached, states) {
|
||||
if(states->in_stack && top->states != states) {
|
||||
/*Only create obj for top item in stack*/
|
||||
continue;
|
||||
}
|
||||
item_create_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_delete_obj(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_managed_states_t * states = NULL;
|
||||
LV_LL_READ_BACK(&manager->attached, states) {
|
||||
item_delete_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container);
|
||||
if(!manager->parent || manager->parent->managed->obj_created) {
|
||||
item_create_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
LV_ASSERT(fragment->managed->manager == manager);
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
lv_fragment_managed_states_t * prev = NULL;
|
||||
bool was_top = false;
|
||||
if(states->in_stack) {
|
||||
void * stack_top = lv_ll_get_tail(&manager->stack);
|
||||
lv_fragment_stack_item_t * item = NULL;
|
||||
LV_LL_READ_BACK(&manager->stack, item) {
|
||||
if(item->states == states) {
|
||||
was_top = stack_top == item;
|
||||
void * stack_prev = lv_ll_get_prev(&manager->stack, item);
|
||||
if(!stack_prev) break;
|
||||
prev = ((lv_fragment_stack_item_t *) stack_prev)->states;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(item) {
|
||||
lv_ll_remove(&manager->stack, item);
|
||||
lv_free(item);
|
||||
}
|
||||
}
|
||||
item_delete_obj(states);
|
||||
item_delete_fragment(states);
|
||||
lv_ll_remove(&manager->attached, states);
|
||||
lv_free(states);
|
||||
if(prev && was_top) {
|
||||
item_create_obj(prev);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_stack_item_t * top = lv_ll_get_tail(&manager->stack);
|
||||
if(top != NULL) {
|
||||
item_delete_obj(top->states);
|
||||
}
|
||||
lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container);
|
||||
states->in_stack = true;
|
||||
/*Add fragment to the top of the stack*/
|
||||
lv_fragment_stack_item_t * item = lv_ll_ins_tail(&manager->stack);
|
||||
lv_memzero(item, sizeof(lv_fragment_stack_item_t));
|
||||
item->states = states;
|
||||
item_create_obj(states);
|
||||
}
|
||||
|
||||
bool lv_fragment_manager_pop(lv_fragment_manager_t * manager)
|
||||
{
|
||||
lv_fragment_t * top = lv_fragment_manager_get_top(manager);
|
||||
if(top == NULL) return false;
|
||||
lv_fragment_manager_remove(manager, top);
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_t * top = lv_fragment_manager_find_by_container(manager, *container);
|
||||
if(top != NULL) {
|
||||
lv_fragment_manager_remove(manager, top);
|
||||
}
|
||||
lv_fragment_manager_add(manager, fragment, container);
|
||||
}
|
||||
|
||||
bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_managed_states_t * p = NULL;
|
||||
LV_LL_READ_BACK(&manager->attached, p) {
|
||||
if(!p->obj_created || p->destroying_obj) continue;
|
||||
lv_fragment_t * instance = p->instance;
|
||||
if(!instance) continue;
|
||||
if(lv_fragment_manager_send_event(instance->child_manager, code, userdata)) return true;
|
||||
if(p->cls->event_cb && p->cls->event_cb(instance, code, userdata)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
return lv_ll_get_len(&manager->stack);
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
lv_fragment_stack_item_t * top = lv_ll_get_tail(&manager->stack);
|
||||
if(!top)return NULL;
|
||||
return top->states->instance;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
lv_fragment_managed_states_t * states;
|
||||
LV_LL_READ(&manager->attached, states) {
|
||||
if(*states->container == container) return states->instance;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
return manager->parent;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void item_create_obj(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
LV_ASSERT(item->instance);
|
||||
lv_fragment_create_obj(item->instance, item->container ? *item->container : NULL);
|
||||
}
|
||||
|
||||
static void item_delete_obj(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
lv_fragment_delete_obj(item->instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach, then destroy fragment
|
||||
* @param item fragment states
|
||||
*/
|
||||
static void item_delete_fragment(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
lv_fragment_t * instance = item->instance;
|
||||
if(instance->cls->detached_cb) {
|
||||
instance->cls->detached_cb(instance);
|
||||
}
|
||||
instance->managed = NULL;
|
||||
lv_fragment_delete(instance);
|
||||
item->instance = NULL;
|
||||
}
|
||||
|
||||
static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
LV_ASSERT(fragment);
|
||||
LV_ASSERT(fragment->managed == NULL);
|
||||
lv_fragment_managed_states_t * states = lv_ll_ins_tail(&manager->attached);
|
||||
lv_memzero(states, sizeof(lv_fragment_managed_states_t));
|
||||
states->cls = fragment->cls;
|
||||
states->manager = manager;
|
||||
states->container = container;
|
||||
states->instance = fragment;
|
||||
fragment->managed = states;
|
||||
if(fragment->cls->attached_cb) {
|
||||
fragment->cls->attached_cb(fragment);
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* @file lv_fragment_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FRAGMENT_PRIVATE_H
|
||||
#define LV_FRAGMENT_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_fragment.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Fragment states
|
||||
*/
|
||||
struct lv_fragment_managed_states_t {
|
||||
/**
|
||||
* Class of the fragment
|
||||
*/
|
||||
const lv_fragment_class_t * cls;
|
||||
/**
|
||||
* Manager the fragment attached to
|
||||
*/
|
||||
lv_fragment_manager_t * manager;
|
||||
/**
|
||||
* Container object the fragment adding view to
|
||||
*/
|
||||
lv_obj_t * const * container;
|
||||
/**
|
||||
* Fragment instance
|
||||
*/
|
||||
lv_fragment_t * instance;
|
||||
/**
|
||||
* true between `create_obj_cb` and `obj_deleted_cb`
|
||||
*/
|
||||
bool obj_created;
|
||||
/**
|
||||
* true before `lv_fragment_delete_obj` is called. Don't touch any object if this is true
|
||||
*/
|
||||
bool destroying_obj;
|
||||
/**
|
||||
* true if this fragment is in navigation stack that can be popped
|
||||
*/
|
||||
bool in_stack;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_FRAGMENT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FRAGMENT_PRIVATE_H*/
|
||||
@@ -1,400 +0,0 @@
|
||||
/**
|
||||
* @file lv_gridnav.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_gridnav.h"
|
||||
#if LV_USE_GRIDNAV
|
||||
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
#include "../../core/lv_obj_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_gridnav_ctrl_t ctrl;
|
||||
lv_obj_t * focused_obj;
|
||||
} lv_gridnav_dsc_t;
|
||||
|
||||
typedef enum {
|
||||
FIND_LEFT,
|
||||
FIND_RIGHT,
|
||||
FIND_TOP,
|
||||
FIND_BOTTOM,
|
||||
FIND_NEXT_ROW_FIRST_ITEM,
|
||||
FIND_PREV_ROW_LAST_ITEM,
|
||||
FIND_FIRST_ROW,
|
||||
FIND_LAST_ROW,
|
||||
} find_mode_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void gridnav_event_cb(lv_event_t * e);
|
||||
static lv_obj_t * find_chid(lv_obj_t * obj, lv_obj_t * start_child, find_mode_t mode);
|
||||
static lv_obj_t * find_first_focusable(lv_obj_t * obj);
|
||||
static lv_obj_t * find_last_focusable(lv_obj_t * obj);
|
||||
static bool obj_is_focusable(lv_obj_t * obj);
|
||||
static int32_t get_x_center(lv_obj_t * obj);
|
||||
static int32_t get_y_center(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_gridnav_add(lv_obj_t * obj, lv_gridnav_ctrl_t ctrl)
|
||||
{
|
||||
lv_gridnav_remove(obj); /*Be sure to not add gridnav twice*/
|
||||
|
||||
lv_gridnav_dsc_t * dsc = lv_malloc(sizeof(lv_gridnav_dsc_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
dsc->ctrl = ctrl;
|
||||
dsc->focused_obj = NULL;
|
||||
lv_obj_add_event_cb(obj, gridnav_event_cb, LV_EVENT_ALL, dsc);
|
||||
|
||||
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_WITH_ARROW);
|
||||
}
|
||||
|
||||
void lv_gridnav_remove(lv_obj_t * obj)
|
||||
{
|
||||
lv_event_dsc_t * event_dsc = NULL;
|
||||
uint32_t event_cnt = lv_obj_get_event_count(obj);
|
||||
uint32_t i;
|
||||
for(i = 0; i < event_cnt; i++) {
|
||||
event_dsc = lv_obj_get_event_dsc(obj, i);
|
||||
if(lv_event_dsc_get_cb(event_dsc) == gridnav_event_cb) {
|
||||
lv_free(lv_event_dsc_get_user_data(event_dsc));
|
||||
lv_obj_remove_event(obj, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable_t anim_en)
|
||||
{
|
||||
LV_ASSERT_NULL(to_focus);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t event_cnt = lv_obj_get_event_count(cont);
|
||||
lv_gridnav_dsc_t * dsc = NULL;
|
||||
for(i = 0; i < event_cnt; i++) {
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(cont, i);
|
||||
if(lv_event_dsc_get_cb(event_dsc) == gridnav_event_cb) {
|
||||
dsc = lv_event_dsc_get_user_data(event_dsc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dsc == NULL) {
|
||||
LV_LOG_WARN("`cont` is not a gridnav container");
|
||||
return;
|
||||
}
|
||||
|
||||
if(obj_is_focusable(to_focus) == false) {
|
||||
LV_LOG_WARN("The object to focus is not focusable");
|
||||
return;
|
||||
}
|
||||
|
||||
if(dsc->focused_obj) {
|
||||
lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
}
|
||||
|
||||
lv_obj_add_state(to_focus, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_scroll_to_view(to_focus, anim_en);
|
||||
dsc->focused_obj = to_focus;
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void gridnav_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||
lv_gridnav_dsc_t * dsc = lv_event_get_user_data(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
if(code == LV_EVENT_KEY) {
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
if(child_cnt == 0) return;
|
||||
|
||||
if(dsc->focused_obj == NULL) dsc->focused_obj = find_first_focusable(obj);
|
||||
if(dsc->focused_obj == NULL) return;
|
||||
|
||||
uint32_t key = lv_event_get_key(e);
|
||||
lv_obj_t * guess = NULL;
|
||||
|
||||
if(key == LV_KEY_RIGHT && !(dsc->ctrl & LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY)) {
|
||||
if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) &&
|
||||
lv_obj_get_scroll_right(dsc->focused_obj) > 0) {
|
||||
int32_t d = lv_obj_get_width(dsc->focused_obj) / 4;
|
||||
if(d <= 0) d = 1;
|
||||
lv_obj_scroll_by_bounded(dsc->focused_obj, -d, 0, LV_ANIM_ON);
|
||||
}
|
||||
else {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_RIGHT);
|
||||
if(guess == NULL) {
|
||||
if(dsc->ctrl & LV_GRIDNAV_CTRL_ROLLOVER) {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_NEXT_ROW_FIRST_ITEM);
|
||||
if(guess == NULL) guess = find_first_focusable(obj);
|
||||
}
|
||||
else {
|
||||
lv_group_focus_next(lv_obj_get_group(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(key == LV_KEY_LEFT && !(dsc->ctrl & LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY)) {
|
||||
if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) &&
|
||||
lv_obj_get_scroll_left(dsc->focused_obj) > 0) {
|
||||
int32_t d = lv_obj_get_width(dsc->focused_obj) / 4;
|
||||
if(d <= 0) d = 1;
|
||||
lv_obj_scroll_by_bounded(dsc->focused_obj, d, 0, LV_ANIM_ON);
|
||||
}
|
||||
else {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_LEFT);
|
||||
if(guess == NULL) {
|
||||
if(dsc->ctrl & LV_GRIDNAV_CTRL_ROLLOVER) {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_PREV_ROW_LAST_ITEM);
|
||||
if(guess == NULL) guess = find_last_focusable(obj);
|
||||
}
|
||||
else {
|
||||
lv_group_focus_prev(lv_obj_get_group(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(key == LV_KEY_DOWN && !(dsc->ctrl & LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY)) {
|
||||
if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) &&
|
||||
lv_obj_get_scroll_bottom(dsc->focused_obj) > 0) {
|
||||
int32_t d = lv_obj_get_height(dsc->focused_obj) / 4;
|
||||
if(d <= 0) d = 1;
|
||||
lv_obj_scroll_by_bounded(dsc->focused_obj, 0, -d, LV_ANIM_ON);
|
||||
}
|
||||
else {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_BOTTOM);
|
||||
if(guess == NULL) {
|
||||
if(dsc->ctrl & LV_GRIDNAV_CTRL_ROLLOVER) {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_FIRST_ROW);
|
||||
}
|
||||
else {
|
||||
lv_group_focus_next(lv_obj_get_group(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(key == LV_KEY_UP && !(dsc->ctrl & LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY)) {
|
||||
if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) &&
|
||||
lv_obj_get_scroll_top(dsc->focused_obj) > 0) {
|
||||
int32_t d = lv_obj_get_height(dsc->focused_obj) / 4;
|
||||
if(d <= 0) d = 1;
|
||||
lv_obj_scroll_by_bounded(dsc->focused_obj, 0, d, LV_ANIM_ON);
|
||||
}
|
||||
else {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_TOP);
|
||||
if(guess == NULL) {
|
||||
if(dsc->ctrl & LV_GRIDNAV_CTRL_ROLLOVER) {
|
||||
guess = find_chid(obj, dsc->focused_obj, FIND_LAST_ROW);
|
||||
}
|
||||
else {
|
||||
lv_group_focus_prev(lv_obj_get_group(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(lv_group_get_focused(lv_obj_get_group(obj)) == obj) {
|
||||
lv_obj_send_event(dsc->focused_obj, LV_EVENT_KEY, &key);
|
||||
}
|
||||
}
|
||||
|
||||
if(guess && guess != dsc->focused_obj) {
|
||||
lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_send_event(dsc->focused_obj, LV_EVENT_DEFOCUSED, lv_indev_active());
|
||||
lv_obj_add_state(guess, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_send_event(guess, LV_EVENT_FOCUSED, lv_indev_active());
|
||||
lv_obj_scroll_to_view(guess, LV_ANIM_ON);
|
||||
dsc->focused_obj = guess;
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_FOCUSED) {
|
||||
if(dsc->focused_obj == NULL) dsc->focused_obj = find_first_focusable(obj);
|
||||
if(dsc->focused_obj) {
|
||||
lv_obj_add_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_remove_state(dsc->focused_obj, LV_STATE_PRESSED); /*Be sure the focuses obj is not stuck in pressed state*/
|
||||
lv_obj_scroll_to_view(dsc->focused_obj, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DEFOCUSED) {
|
||||
if(dsc->focused_obj) {
|
||||
lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_CHILD_CREATED) {
|
||||
lv_obj_t * child = lv_event_get_target(e);
|
||||
if(lv_obj_get_parent(child) == obj) {
|
||||
if(dsc->focused_obj == NULL) {
|
||||
dsc->focused_obj = child;
|
||||
if(lv_obj_has_state(obj, LV_STATE_FOCUSED)) {
|
||||
lv_obj_add_state(child, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_scroll_to_view(child, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_CHILD_DELETED) {
|
||||
/*This event bubble, so be sure this object's child was deleted.
|
||||
*As we don't know which object was deleted we can't make the next focused.
|
||||
*So make the first object focused*/
|
||||
lv_obj_t * target = lv_event_get_target(e);
|
||||
if(target == obj) {
|
||||
dsc->focused_obj = find_first_focusable(obj);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DELETE) {
|
||||
lv_gridnav_remove(obj);
|
||||
}
|
||||
else if(code == LV_EVENT_PRESSED || code == LV_EVENT_PRESSING || code == LV_EVENT_PRESS_LOST ||
|
||||
code == LV_EVENT_SHORT_CLICKED || code == LV_EVENT_LONG_PRESSED || code == LV_EVENT_LONG_PRESSED_REPEAT ||
|
||||
code == LV_EVENT_CLICKED || code == LV_EVENT_RELEASED) {
|
||||
if(lv_group_get_focused(lv_obj_get_group(obj)) == obj) {
|
||||
/*Forward press/release related event too*/
|
||||
lv_indev_type_t t = lv_indev_get_type(lv_indev_active());
|
||||
if(t == LV_INDEV_TYPE_ENCODER || t == LV_INDEV_TYPE_KEYPAD) {
|
||||
lv_obj_send_event(dsc->focused_obj, code, lv_indev_active());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static lv_obj_t * find_chid(lv_obj_t * obj, lv_obj_t * start_child, find_mode_t mode)
|
||||
{
|
||||
int32_t x_start = get_x_center(start_child);
|
||||
int32_t y_start = get_y_center(start_child);
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
lv_obj_t * guess = NULL;
|
||||
int32_t x_err_guess = LV_COORD_MAX;
|
||||
int32_t y_err_guess = LV_COORD_MAX;
|
||||
int32_t h_half = lv_obj_get_height(start_child) / 2;
|
||||
int32_t h_max = lv_obj_get_height(obj) + lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj);
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
if(child == start_child) continue;
|
||||
if(obj_is_focusable(child) == false) continue;
|
||||
|
||||
int32_t x_err = 0;
|
||||
int32_t y_err = 0;
|
||||
switch(mode) {
|
||||
case FIND_LEFT:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(x_err >= 0) continue; /*It's on the right*/
|
||||
if(LV_ABS(y_err) > h_half) continue; /*Too far*/
|
||||
break;
|
||||
case FIND_RIGHT:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(x_err <= 0) continue; /*It's on the left*/
|
||||
if(LV_ABS(y_err) > h_half) continue; /*Too far*/
|
||||
break;
|
||||
case FIND_TOP:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(y_err >= 0) continue; /*It's on the bottom*/
|
||||
break;
|
||||
case FIND_BOTTOM:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(y_err <= 0) continue; /*It's on the top*/
|
||||
break;
|
||||
case FIND_NEXT_ROW_FIRST_ITEM:
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(y_err <= 0) continue; /*It's on the top*/
|
||||
x_err = lv_obj_get_x(child);
|
||||
break;
|
||||
case FIND_PREV_ROW_LAST_ITEM:
|
||||
y_err = get_y_center(child) - y_start;
|
||||
if(y_err >= 0) continue; /*It's on the bottom*/
|
||||
x_err = obj->coords.x2 - child->coords.x2;
|
||||
break;
|
||||
case FIND_FIRST_ROW:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = lv_obj_get_y(child);
|
||||
break;
|
||||
case FIND_LAST_ROW:
|
||||
x_err = get_x_center(child) - x_start;
|
||||
y_err = h_max - lv_obj_get_y(child);
|
||||
}
|
||||
|
||||
if(guess == NULL ||
|
||||
(y_err * y_err + x_err * x_err < y_err_guess * y_err_guess + x_err_guess * x_err_guess)) {
|
||||
guess = child;
|
||||
x_err_guess = x_err;
|
||||
y_err_guess = y_err;
|
||||
}
|
||||
}
|
||||
return guess;
|
||||
}
|
||||
|
||||
static lv_obj_t * find_first_focusable(lv_obj_t * obj)
|
||||
{
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
if(obj_is_focusable(child)) return child;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static lv_obj_t * find_last_focusable(lv_obj_t * obj)
|
||||
{
|
||||
uint32_t child_cnt = lv_obj_get_child_count(obj);
|
||||
int32_t i;
|
||||
for(i = child_cnt - 1; i >= 0; i--) {
|
||||
lv_obj_t * child = lv_obj_get_child(obj, i);
|
||||
if(obj_is_focusable(child)) return child;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool obj_is_focusable(lv_obj_t * obj)
|
||||
{
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false;
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_CLICK_FOCUSABLE)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
static int32_t get_x_center(lv_obj_t * obj)
|
||||
{
|
||||
return obj->coords.x1 + lv_area_get_width(&obj->coords) / 2;
|
||||
}
|
||||
|
||||
static int32_t get_y_center(lv_obj_t * obj)
|
||||
{
|
||||
return obj->coords.y1 + lv_area_get_height(&obj->coords) / 2;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_GRIDNAV*/
|
||||
@@ -1,95 +0,0 @@
|
||||
/**
|
||||
* @file lv_gridnav.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GRIDNAV_H
|
||||
#define LV_GRIDNAV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../core/lv_obj.h"
|
||||
|
||||
#if LV_USE_GRIDNAV
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef enum {
|
||||
LV_GRIDNAV_CTRL_NONE = 0x0,
|
||||
|
||||
/**
|
||||
* If there is no next/previous object in a direction,
|
||||
* the focus goes to the object in the next/previous row (on left/right keys)
|
||||
* or first/last row (on up/down keys)
|
||||
*/
|
||||
LV_GRIDNAV_CTRL_ROLLOVER = 0x1,
|
||||
|
||||
/**
|
||||
* If an arrow is pressed and the focused object can be scrolled in that direction
|
||||
* then it will be scrolled instead of going to the next/previous object.
|
||||
* If there is no more room for scrolling the next/previous object will be focused normally */
|
||||
LV_GRIDNAV_CTRL_SCROLL_FIRST = 0x2,
|
||||
|
||||
/**
|
||||
* Only use left/right keys for grid navigation. Up/down key events will be sent to the
|
||||
* focused object.
|
||||
*/
|
||||
LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY = 0x4,
|
||||
|
||||
/**
|
||||
* Only use up/down keys for grid navigation. Left/right key events will be sent to the
|
||||
* focused object.
|
||||
*/
|
||||
LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY = 0x8
|
||||
|
||||
} lv_gridnav_ctrl_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Add grid navigation feature to an object. It expects the children to be arranged
|
||||
* into a grid-like layout. Although it's not required to have pixel perfect alignment.
|
||||
* This feature makes possible to use keys to navigate among the children and focus them.
|
||||
* The keys other than arrows and press/release related events
|
||||
* are forwarded to the focused child.
|
||||
* @param obj pointer to an object on which navigation should be applied.
|
||||
* @param ctrl control flags from `lv_gridnav_ctrl_t`.
|
||||
*/
|
||||
void lv_gridnav_add(lv_obj_t * obj, lv_gridnav_ctrl_t ctrl);
|
||||
|
||||
/**
|
||||
* Remove the grid navigation support from an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_gridnav_remove(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Manually focus an object on gridnav container
|
||||
* @param cont pointer to a gridnav container
|
||||
* @param to_focus pointer to an object to focus
|
||||
* @param anim_en LV_ANIM_ON/OFF
|
||||
*/
|
||||
void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GRIDNAV*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_GRIDNAV_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
/**
|
||||
* @file lv_ime_pinyin.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_IME_PINYIN_H
|
||||
#define LV_IME_PINYIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#include "../../core/lv_obj.h"
|
||||
|
||||
#if LV_USE_IME_PINYIN != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_IME_PINYIN_K9_MAX_INPUT 7
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_IME_PINYIN_MODE_K26,
|
||||
LV_IME_PINYIN_MODE_K9,
|
||||
LV_IME_PINYIN_MODE_K9_NUMBER,
|
||||
} lv_ime_pinyin_mode_t;
|
||||
|
||||
/*Data of pinyin_dict*/
|
||||
typedef struct {
|
||||
const char * const py;
|
||||
const char * const py_mb;
|
||||
} lv_pinyin_dict_t;
|
||||
|
||||
/*Data of 9-key input(k9) mode*/
|
||||
typedef struct {
|
||||
char py_str[7];
|
||||
} ime_pinyin_k9_py_str_t;
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
||||
extern const lv_obj_class_t lv_ime_pinyin_class;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the keyboard of Pinyin input method.
|
||||
* @param obj pointer to a Pinyin input method object
|
||||
* @param kb pointer to a Pinyin input method keyboard
|
||||
*/
|
||||
void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Set the dictionary of Pinyin input method.
|
||||
* @param obj pointer to a Pinyin input method object
|
||||
* @param dict pointer to a Pinyin input method dictionary
|
||||
*/
|
||||
void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict);
|
||||
|
||||
/**
|
||||
* Set mode, 26-key input(k26) or 9-key input(k9).
|
||||
* @param obj pointer to a Pinyin input method object
|
||||
* @param mode the mode from 'lv_ime_pinyin_mode_t'
|
||||
*/
|
||||
void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the dictionary of Pinyin input method.
|
||||
* @param obj pointer to a Pinyin IME object
|
||||
* @return pointer to the Pinyin IME keyboard
|
||||
*/
|
||||
lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the dictionary of Pinyin input method.
|
||||
* @param obj pointer to a Pinyin input method object
|
||||
* @return pointer to the Pinyin input method candidate panel
|
||||
*/
|
||||
lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the dictionary of Pinyin input method.
|
||||
* @param obj pointer to a Pinyin input method object
|
||||
* @return pointer to the Pinyin input method dictionary
|
||||
*/
|
||||
const lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_IME_PINYIN*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_IME_PINYIN*/
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* @file lv_ime_pinyin_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IME_PINYIN_PRIVATE_H
|
||||
#define LV_IME_PINYIN_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../core/lv_obj_private.h"
|
||||
#include "lv_ime_pinyin.h"
|
||||
|
||||
#if LV_USE_IME_PINYIN != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of lv_ime_pinyin*/
|
||||
struct lv_ime_pinyin_t {
|
||||
lv_obj_t obj;
|
||||
lv_obj_t * kb;
|
||||
lv_obj_t * cand_panel;
|
||||
const lv_pinyin_dict_t * dict;
|
||||
lv_ll_t k9_legal_py_ll;
|
||||
char * cand_str; /* Candidate string */
|
||||
char input_char[16]; /* Input box character */
|
||||
#if LV_IME_PINYIN_USE_K9_MODE
|
||||
char k9_input_str[LV_IME_PINYIN_K9_MAX_INPUT + 1]; /* 9-key input(k9) mode input string */
|
||||
uint16_t k9_py_ll_pos; /* Current pinyin map pages(k9) */
|
||||
uint16_t k9_legal_py_count; /* Count of legal Pinyin numbers(k9) */
|
||||
uint16_t k9_input_str_len; /* 9-key input(k9) mode input string max len */
|
||||
#endif
|
||||
uint16_t ta_count; /* The number of characters entered in the text box this time */
|
||||
uint16_t cand_num; /* Number of candidates */
|
||||
uint16_t py_page; /* Current pinyin map pages(k26) */
|
||||
uint16_t py_num[26]; /* Number and length of Pinyin */
|
||||
uint16_t py_pos[26]; /* Pinyin position */
|
||||
lv_ime_pinyin_mode_t mode; /* Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1. */
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_IME_PINYIN != 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IME_PINYIN_PRIVATE_H*/
|
||||
@@ -1,121 +0,0 @@
|
||||
/**
|
||||
* @file lv_imgfont.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lvgl.h"
|
||||
|
||||
#if LV_USE_IMGFONT
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_font_t font;
|
||||
lv_imgfont_get_path_cb_t path_cb;
|
||||
void * user_data;
|
||||
} imgfont_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static const void * imgfont_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf);
|
||||
static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out,
|
||||
uint32_t unicode, uint32_t unicode_next);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
lv_font_t * lv_imgfont_create(uint16_t height, lv_imgfont_get_path_cb_t path_cb, void * user_data)
|
||||
{
|
||||
imgfont_dsc_t * dsc = lv_malloc_zeroed(sizeof(imgfont_dsc_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) return NULL;
|
||||
|
||||
dsc->path_cb = path_cb;
|
||||
dsc->user_data = user_data;
|
||||
|
||||
lv_font_t * font = &dsc->font;
|
||||
font->dsc = dsc;
|
||||
font->get_glyph_dsc = imgfont_get_glyph_dsc;
|
||||
font->get_glyph_bitmap = imgfont_get_glyph_bitmap;
|
||||
font->subpx = LV_FONT_SUBPX_NONE;
|
||||
font->line_height = height;
|
||||
font->base_line = 0;
|
||||
font->underline_position = 0;
|
||||
font->underline_thickness = 0;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void lv_imgfont_destroy(lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc;
|
||||
lv_free(dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static const void * imgfont_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf)
|
||||
{
|
||||
LV_UNUSED(draw_buf);
|
||||
|
||||
const void * img_src = g_dsc->gid.src;
|
||||
return img_src;
|
||||
}
|
||||
|
||||
static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out,
|
||||
uint32_t unicode, uint32_t unicode_next)
|
||||
{
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc;
|
||||
LV_ASSERT_NULL(dsc);
|
||||
if(dsc->path_cb == NULL) return false;
|
||||
|
||||
int32_t offset_y = 0;
|
||||
|
||||
const void * img_src = dsc->path_cb(font, unicode, unicode_next, &offset_y, dsc->user_data);
|
||||
if(img_src == NULL) return false;
|
||||
|
||||
lv_image_header_t header;
|
||||
if(lv_image_decoder_get_info(img_src, &header) != LV_RESULT_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc_out->is_placeholder = 0;
|
||||
dsc_out->adv_w = header.w;
|
||||
dsc_out->box_w = header.w;
|
||||
dsc_out->box_h = header.h;
|
||||
dsc_out->ofs_x = 0;
|
||||
dsc_out->ofs_y = offset_y;
|
||||
dsc_out->format = LV_FONT_GLYPH_FORMAT_IMAGE; /* is image identifier */
|
||||
dsc_out->gid.src = img_src;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_IMGFONT*/
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @file lv_imgfont.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMGFONT_H
|
||||
#define LV_IMGFONT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#include "../../font/lv_font.h"
|
||||
|
||||
#if LV_USE_IMGFONT
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* gets the image path name of this character */
|
||||
typedef const void * (*lv_imgfont_get_path_cb_t)(const lv_font_t * font,
|
||||
uint32_t unicode, uint32_t unicode_next,
|
||||
int32_t * offset_y, void * user_data);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Creates a image font with info parameter specified.
|
||||
* @param height font size
|
||||
* @param path_cb a function to get the image path name of character.
|
||||
* @param user_data pointer to user data
|
||||
* @return pointer to the new imgfont or NULL if create error.
|
||||
*/
|
||||
lv_font_t * lv_imgfont_create(uint16_t height, lv_imgfont_get_path_cb_t path_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Destroy a image font that has been created.
|
||||
* @param font pointer to image font handle.
|
||||
*/
|
||||
void lv_imgfont_destroy(lv_font_t * font);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_IMGFONT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_IMGFONT_H */
|
||||
@@ -1,178 +0,0 @@
|
||||
/**
|
||||
* @file lv_monkey.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_monkey_private.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include "../../display/lv_display.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MONKEY_PERIOD_RANGE_MIN_DEF 100
|
||||
#define MONKEY_PERIOD_RANGE_MAX_DEF 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct lv_monkey_t {
|
||||
lv_monkey_config_t config;
|
||||
lv_indev_data_t indev_data;
|
||||
lv_indev_t * indev;
|
||||
lv_timer_t * timer;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
static const lv_key_t lv_key_map[] = {
|
||||
LV_KEY_UP,
|
||||
LV_KEY_DOWN,
|
||||
LV_KEY_RIGHT,
|
||||
LV_KEY_LEFT,
|
||||
LV_KEY_ESC,
|
||||
LV_KEY_DEL,
|
||||
LV_KEY_BACKSPACE,
|
||||
LV_KEY_ENTER,
|
||||
LV_KEY_NEXT,
|
||||
LV_KEY_PREV,
|
||||
LV_KEY_HOME,
|
||||
LV_KEY_END,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static int32_t lv_monkey_random(int32_t howsmall, int32_t howbig);
|
||||
static void lv_monkey_timer_cb(lv_timer_t * timer);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_monkey_config_init(lv_monkey_config_t * config)
|
||||
{
|
||||
lv_memzero(config, sizeof(lv_monkey_config_t));
|
||||
config->type = LV_INDEV_TYPE_POINTER;
|
||||
config->period_range.min = MONKEY_PERIOD_RANGE_MIN_DEF;
|
||||
config->period_range.max = MONKEY_PERIOD_RANGE_MAX_DEF;
|
||||
}
|
||||
|
||||
lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_malloc_zeroed(sizeof(lv_monkey_t));
|
||||
LV_ASSERT_MALLOC(monkey);
|
||||
|
||||
monkey->config = *config;
|
||||
monkey->timer = lv_timer_create(lv_monkey_timer_cb, monkey->config.period_range.min, monkey);
|
||||
lv_timer_pause(monkey->timer);
|
||||
|
||||
monkey->indev = lv_indev_create();
|
||||
lv_indev_set_type(monkey->indev, config->type);
|
||||
lv_indev_set_read_cb(monkey->indev, lv_monkey_read_cb);
|
||||
lv_indev_set_user_data(monkey->indev, monkey);
|
||||
return monkey;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_monkey_get_indev(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return monkey->indev;
|
||||
}
|
||||
|
||||
void lv_monkey_set_enable(lv_monkey_t * monkey, bool en)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
en ? lv_timer_resume(monkey->timer) : lv_timer_pause(monkey->timer);
|
||||
}
|
||||
|
||||
bool lv_monkey_get_enable(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return !lv_timer_get_paused(monkey->timer);
|
||||
}
|
||||
|
||||
void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
monkey->user_data = user_data;
|
||||
}
|
||||
|
||||
void * lv_monkey_get_user_data(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
return monkey->user_data;
|
||||
}
|
||||
|
||||
void lv_monkey_delete(lv_monkey_t * monkey)
|
||||
{
|
||||
LV_ASSERT_NULL(monkey);
|
||||
|
||||
lv_timer_delete(monkey->timer);
|
||||
lv_indev_delete(monkey->indev);
|
||||
lv_free(monkey);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_indev_get_user_data(indev);
|
||||
|
||||
data->btn_id = monkey->indev_data.btn_id;
|
||||
data->point = monkey->indev_data.point;
|
||||
data->enc_diff = monkey->indev_data.enc_diff;
|
||||
data->state = monkey->indev_data.state;
|
||||
}
|
||||
|
||||
static int32_t lv_monkey_random(int32_t howsmall, int32_t howbig)
|
||||
{
|
||||
if(howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
int32_t diff = howbig - howsmall;
|
||||
return (int32_t)lv_rand(0, diff) + howsmall;
|
||||
}
|
||||
|
||||
static void lv_monkey_timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
lv_monkey_t * monkey = lv_timer_get_user_data(timer);
|
||||
lv_indev_data_t * data = &monkey->indev_data;
|
||||
|
||||
switch(lv_indev_get_type(monkey->indev)) {
|
||||
case LV_INDEV_TYPE_POINTER:
|
||||
data->point.x = (int32_t)lv_monkey_random(0, LV_HOR_RES - 1);
|
||||
data->point.y = (int32_t)lv_monkey_random(0, LV_VER_RES - 1);
|
||||
break;
|
||||
case LV_INDEV_TYPE_ENCODER:
|
||||
data->enc_diff = (int16_t)lv_monkey_random(monkey->config.input_range.min, monkey->config.input_range.max);
|
||||
break;
|
||||
case LV_INDEV_TYPE_BUTTON:
|
||||
data->btn_id = (uint32_t)lv_monkey_random(monkey->config.input_range.min, monkey->config.input_range.max);
|
||||
break;
|
||||
case LV_INDEV_TYPE_KEYPAD: {
|
||||
int32_t index = lv_monkey_random(0, sizeof(lv_key_map) / sizeof(lv_key_map[0]) - 1);
|
||||
data->key = lv_key_map[index];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
data->state = lv_monkey_random(0, 100) < 50 ? LV_INDEV_STATE_RELEASED : LV_INDEV_STATE_PRESSED;
|
||||
|
||||
lv_timer_set_period(monkey->timer, lv_monkey_random(monkey->config.period_range.min, monkey->config.period_range.max));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_MONKEY*/
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* @file lv_monkey.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_MONKEY_H
|
||||
#define LV_MONKEY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#include "../../indev/lv_indev.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_monkey_t lv_monkey_t;
|
||||
|
||||
struct lv_monkey_config_t {
|
||||
/**< Input device type*/
|
||||
lv_indev_type_t type;
|
||||
|
||||
/**< Monkey execution period*/
|
||||
struct {
|
||||
//! @cond Doxygen_Suppress
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
//! @endcond
|
||||
} period_range;
|
||||
|
||||
/**< The range of input value*/
|
||||
struct {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
} input_range;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize a monkey config with default values
|
||||
* @param config pointer to 'lv_monkey_config_t' variable to initialize
|
||||
*/
|
||||
void lv_monkey_config_init(lv_monkey_config_t * config);
|
||||
|
||||
/**
|
||||
* Create monkey for test
|
||||
* @param config pointer to 'lv_monkey_config_t' variable
|
||||
* @return pointer to the created monkey
|
||||
*/
|
||||
lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config);
|
||||
|
||||
/**
|
||||
* Get monkey input device
|
||||
* @param monkey pointer to a monkey
|
||||
* @return pointer to the input device
|
||||
*/
|
||||
lv_indev_t * lv_monkey_get_indev(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Enable monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @param en set to true to enable
|
||||
*/
|
||||
void lv_monkey_set_enable(lv_monkey_t * monkey, bool en);
|
||||
|
||||
/**
|
||||
* Get whether monkey is enabled
|
||||
* @param monkey pointer to a monkey
|
||||
* @return return true if monkey enabled
|
||||
*/
|
||||
bool lv_monkey_get_enable(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Set the user_data field of the monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @param user_data pointer to the new user_data.
|
||||
*/
|
||||
void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data);
|
||||
|
||||
/**
|
||||
* Get the user_data field of the monkey
|
||||
* @param monkey pointer to a monkey
|
||||
* @return the pointer to the user_data of the monkey
|
||||
*/
|
||||
void * lv_monkey_get_user_data(lv_monkey_t * monkey);
|
||||
|
||||
/**
|
||||
* Delete monkey
|
||||
* @param monkey pointer to monkey
|
||||
*/
|
||||
void lv_monkey_delete(lv_monkey_t * monkey);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_MONKEY*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MONKEY_H*/
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* @file lv_monkey_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MONKEY_PRIVATE_H
|
||||
#define LV_MONKEY_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_monkey.h"
|
||||
|
||||
#if LV_USE_MONKEY != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_MONKEY != 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MONKEY_PRIVATE_H*/
|
||||
@@ -1,725 +0,0 @@
|
||||
/**
|
||||
* @file lv_observer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_observer_private.h"
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
#include "../../lvgl.h"
|
||||
#include "../../core/lv_obj_private.h"
|
||||
#include "../../misc/lv_event_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
uint32_t flag;
|
||||
lv_subject_value_t value;
|
||||
uint32_t inv : 1;
|
||||
} flag_and_cond_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void unsubscribe_on_delete_cb(lv_event_t * e);
|
||||
static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag,
|
||||
int32_t ref_value, bool inv);
|
||||
static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void obj_value_changed_event_cb(lv_event_t * e);
|
||||
|
||||
#if LV_USE_LABEL
|
||||
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_ARC
|
||||
static void arc_value_changed_event_cb(lv_event_t * e);
|
||||
static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_SLIDER
|
||||
static void slider_value_changed_event_cb(lv_event_t * e);
|
||||
static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_ROLLER
|
||||
static void roller_value_changed_event_cb(lv_event_t * e);
|
||||
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_DROPDOWN
|
||||
static void dropdown_value_changed_event_cb(lv_event_t * e);
|
||||
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_subject_init_int(lv_subject_t * subject, int32_t value)
|
||||
{
|
||||
lv_memzero(subject, sizeof(lv_subject_t));
|
||||
subject->type = LV_SUBJECT_TYPE_INT;
|
||||
subject->value.num = value;
|
||||
subject->prev_value.num = value;
|
||||
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
|
||||
}
|
||||
|
||||
void lv_subject_set_int(lv_subject_t * subject, int32_t value)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
|
||||
return;
|
||||
}
|
||||
|
||||
subject->prev_value.num = subject->value.num;
|
||||
subject->value.num = value;
|
||||
lv_subject_notify(subject);
|
||||
}
|
||||
|
||||
int32_t lv_subject_get_int(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return subject->value.num;
|
||||
}
|
||||
|
||||
int32_t lv_subject_get_previous_int(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return subject->prev_value.num;
|
||||
}
|
||||
|
||||
void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value)
|
||||
{
|
||||
lv_memzero(subject, sizeof(lv_subject_t));
|
||||
lv_strlcpy(buf, value, size);
|
||||
if(prev_buf) lv_strlcpy(prev_buf, value, size);
|
||||
|
||||
subject->type = LV_SUBJECT_TYPE_STRING;
|
||||
subject->size = size;
|
||||
subject->value.pointer = buf;
|
||||
subject->prev_value.pointer = prev_buf;
|
||||
|
||||
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
|
||||
}
|
||||
|
||||
void lv_subject_copy_string(lv_subject_t * subject, const char * buf)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_STRING) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT");
|
||||
return;
|
||||
}
|
||||
|
||||
if(subject->size < 1) return;
|
||||
if(subject->prev_value.pointer) {
|
||||
lv_strlcpy((char *)subject->prev_value.pointer, subject->value.pointer, subject->size);
|
||||
}
|
||||
|
||||
lv_strlcpy((char *)subject->value.pointer, buf, subject->size);
|
||||
|
||||
lv_subject_notify(subject);
|
||||
|
||||
}
|
||||
|
||||
const char * lv_subject_get_string(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_STRING) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
|
||||
return "";
|
||||
}
|
||||
|
||||
return subject->value.pointer;
|
||||
}
|
||||
|
||||
const char * lv_subject_get_previous_string(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_STRING) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subject->prev_value.pointer;
|
||||
}
|
||||
|
||||
void lv_subject_init_pointer(lv_subject_t * subject, void * value)
|
||||
{
|
||||
lv_memzero(subject, sizeof(lv_subject_t));
|
||||
subject->type = LV_SUBJECT_TYPE_POINTER;
|
||||
subject->value.pointer = value;
|
||||
subject->prev_value.pointer = value;
|
||||
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
|
||||
}
|
||||
|
||||
void lv_subject_set_pointer(lv_subject_t * subject, void * ptr)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_POINTER) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
|
||||
return;
|
||||
}
|
||||
|
||||
subject->prev_value.pointer = subject->value.pointer;
|
||||
subject->value.pointer = ptr;
|
||||
lv_subject_notify(subject);
|
||||
}
|
||||
|
||||
const void * lv_subject_get_pointer(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_POINTER) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subject->value.pointer;
|
||||
}
|
||||
|
||||
const void * lv_subject_get_previous_pointer(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_POINTER) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subject->prev_value.pointer;
|
||||
}
|
||||
|
||||
void lv_subject_init_color(lv_subject_t * subject, lv_color_t color)
|
||||
{
|
||||
lv_memzero(subject, sizeof(lv_subject_t));
|
||||
subject->type = LV_SUBJECT_TYPE_COLOR;
|
||||
subject->value.color = color;
|
||||
subject->prev_value.color = color;
|
||||
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
|
||||
}
|
||||
|
||||
void lv_subject_set_color(lv_subject_t * subject, lv_color_t color)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_COLOR) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
|
||||
return;
|
||||
}
|
||||
|
||||
subject->prev_value.color = subject->value.color;
|
||||
subject->value.color = color;
|
||||
lv_subject_notify(subject);
|
||||
}
|
||||
|
||||
lv_color_t lv_subject_get_color(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_COLOR) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
|
||||
return lv_color_black();
|
||||
}
|
||||
|
||||
return subject->value.color;
|
||||
}
|
||||
|
||||
lv_color_t lv_subject_get_previous_color(lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_COLOR) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR");
|
||||
return lv_color_black();
|
||||
}
|
||||
|
||||
return subject->prev_value.color;
|
||||
}
|
||||
|
||||
void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len)
|
||||
{
|
||||
subject->type = LV_SUBJECT_TYPE_GROUP;
|
||||
subject->size = list_len;
|
||||
lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t));
|
||||
subject->value.pointer = list;
|
||||
|
||||
/* bind all subjects to this subject */
|
||||
uint32_t i;
|
||||
for(i = 0; i < list_len; i++) {
|
||||
/*If a subject in the group changes notify the group itself*/
|
||||
lv_subject_add_observer(list[i], group_notify_cb, subject);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_subject_deinit(lv_subject_t * subject)
|
||||
{
|
||||
lv_observer_t * observer = lv_ll_get_head(&subject->subs_ll);
|
||||
while(observer) {
|
||||
lv_observer_t * observer_next = lv_ll_get_next(&subject->subs_ll, observer);
|
||||
|
||||
if(observer->for_obj) {
|
||||
lv_obj_remove_event_cb(observer->target, unsubscribe_on_delete_cb);
|
||||
lv_obj_remove_event_cb_with_user_data(observer->target, NULL, subject);
|
||||
}
|
||||
|
||||
lv_observer_remove(observer);
|
||||
observer = observer_next;
|
||||
}
|
||||
|
||||
lv_ll_clear(&subject->subs_ll);
|
||||
}
|
||||
|
||||
lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_GROUP) {
|
||||
LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_GROUP");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(index >= subject->size) return NULL;
|
||||
|
||||
return ((lv_subject_t **)(subject->value.pointer))[index];
|
||||
}
|
||||
|
||||
lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t cb, void * user_data)
|
||||
{
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, cb, NULL, user_data);
|
||||
if(observer == NULL) return NULL;
|
||||
|
||||
observer->for_obj = 0;
|
||||
return observer;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t cb, lv_obj_t * obj,
|
||||
void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(subject);
|
||||
if(subject->type == LV_SUBJECT_TYPE_INVALID) {
|
||||
LV_LOG_WARN("Subject not initialized yet");
|
||||
return NULL;
|
||||
}
|
||||
lv_observer_t * observer = lv_ll_ins_tail(&(subject->subs_ll));
|
||||
LV_ASSERT_MALLOC(observer);
|
||||
if(observer == NULL) return NULL;
|
||||
|
||||
lv_memzero(observer, sizeof(*observer));
|
||||
|
||||
observer->subject = subject;
|
||||
observer->cb = cb;
|
||||
observer->user_data = user_data;
|
||||
observer->target = obj;
|
||||
observer->for_obj = 1;
|
||||
/* subscribe to delete event of the object */
|
||||
if(obj != NULL) {
|
||||
lv_obj_add_event_cb(obj, unsubscribe_on_delete_cb, LV_EVENT_DELETE, observer);
|
||||
}
|
||||
|
||||
/* update object immediately */
|
||||
if(observer->cb) observer->cb(observer, subject);
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t cb, void * target,
|
||||
void * user_data)
|
||||
{
|
||||
LV_ASSERT_NULL(subject);
|
||||
if(subject->type == LV_SUBJECT_TYPE_INVALID) {
|
||||
LV_LOG_WARN("Subject not initialized yet");
|
||||
return NULL;
|
||||
}
|
||||
lv_observer_t * observer = lv_ll_ins_tail(&(subject->subs_ll));
|
||||
LV_ASSERT_MALLOC(observer);
|
||||
if(observer == NULL) return NULL;
|
||||
|
||||
lv_memzero(observer, sizeof(*observer));
|
||||
|
||||
observer->subject = subject;
|
||||
observer->cb = cb;
|
||||
observer->user_data = user_data;
|
||||
observer->target = target;
|
||||
|
||||
/* update object immediately */
|
||||
if(observer->cb) observer->cb(observer, subject);
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
|
||||
void lv_observer_remove(lv_observer_t * observer)
|
||||
{
|
||||
LV_ASSERT_NULL(observer);
|
||||
|
||||
observer->subject->notify_restart_query = 1;
|
||||
|
||||
lv_ll_remove(&(observer->subject->subs_ll), observer);
|
||||
|
||||
if(observer->auto_free_user_data) {
|
||||
lv_free(observer->user_data);
|
||||
}
|
||||
lv_free(observer);
|
||||
}
|
||||
|
||||
void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
int32_t i;
|
||||
int32_t event_cnt = (int32_t)(obj->spec_attr ? lv_array_size(&obj->spec_attr->event_list) : 0);
|
||||
for(i = event_cnt - 1; i >= 0; i--) {
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, i);
|
||||
if(event_dsc->cb == unsubscribe_on_delete_cb) {
|
||||
lv_observer_t * observer = event_dsc->user_data;
|
||||
if(subject == NULL || subject == observer->subject) {
|
||||
lv_observer_remove(observer);
|
||||
lv_obj_remove_event(obj, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * lv_observer_get_target(lv_observer_t * observer)
|
||||
{
|
||||
LV_ASSERT_NULL(observer);
|
||||
|
||||
return observer->target;
|
||||
}
|
||||
|
||||
void lv_subject_notify(lv_subject_t * subject)
|
||||
{
|
||||
LV_ASSERT_NULL(subject);
|
||||
|
||||
lv_observer_t * observer;
|
||||
LV_LL_READ(&(subject->subs_ll), observer) {
|
||||
observer->notified = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
subject->notify_restart_query = 0;
|
||||
LV_LL_READ(&(subject->subs_ll), observer) {
|
||||
if(observer->cb && observer->notified == 0) {
|
||||
observer->cb(observer, subject);
|
||||
if(subject->notify_restart_query) break;
|
||||
observer->notified = 1;
|
||||
}
|
||||
}
|
||||
} while(subject->notify_restart_query);
|
||||
}
|
||||
|
||||
lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value)
|
||||
{
|
||||
lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, false);
|
||||
return observable;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag,
|
||||
int32_t ref_value)
|
||||
{
|
||||
lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, true);
|
||||
return observable;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value)
|
||||
{
|
||||
lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, false);
|
||||
return observable;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value)
|
||||
{
|
||||
lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, true);
|
||||
return observable;
|
||||
}
|
||||
|
||||
lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, LV_STATE_CHECKED, 1, false);
|
||||
lv_obj_add_event_cb(obj, obj_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
|
||||
return observable;
|
||||
}
|
||||
|
||||
#if LV_USE_LABEL
|
||||
lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt)
|
||||
{
|
||||
if(fmt == NULL) {
|
||||
if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER &&
|
||||
subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, label_text_observer_cb, obj, (void *)fmt);
|
||||
return observer;
|
||||
}
|
||||
#endif /*LV_USE_LABEL*/
|
||||
|
||||
#if LV_USE_ARC
|
||||
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(obj, arc_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, arc_value_observer_cb, obj, NULL);
|
||||
return observer;
|
||||
}
|
||||
#endif /*LV_USE_ARC*/
|
||||
|
||||
#if LV_USE_SLIDER
|
||||
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(obj, slider_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, slider_value_observer_cb, obj, NULL);
|
||||
return observer;
|
||||
}
|
||||
#endif /*LV_USE_SLIDER*/
|
||||
|
||||
#if LV_USE_ROLLER
|
||||
|
||||
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(obj, roller_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, roller_value_observer_cb, obj, NULL);
|
||||
return observer;
|
||||
|
||||
}
|
||||
#endif /*LV_USE_ROLLER*/
|
||||
|
||||
#if LV_USE_DROPDOWN
|
||||
|
||||
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(obj, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject);
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(subject, dropdown_value_observer_cb, obj, NULL);
|
||||
return observer;
|
||||
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DROPDOWN*/
|
||||
|
||||
lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer)
|
||||
{
|
||||
return (lv_obj_t *)lv_observer_get_target(observer);
|
||||
}
|
||||
|
||||
void * lv_observer_get_user_data(const lv_observer_t * observer)
|
||||
{
|
||||
LV_ASSERT_NULL(observer);
|
||||
|
||||
return observer->user_data;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
LV_UNUSED(subject);
|
||||
lv_subject_t * subject_group = observer->user_data;
|
||||
lv_subject_notify(subject_group);
|
||||
}
|
||||
|
||||
static void unsubscribe_on_delete_cb(lv_event_t * e)
|
||||
{
|
||||
lv_observer_t * observer = lv_event_get_user_data(e);
|
||||
lv_observer_remove(observer);
|
||||
}
|
||||
|
||||
static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag,
|
||||
int32_t ref_value, bool inv)
|
||||
{
|
||||
if(subject->type != LV_SUBJECT_TYPE_INT) {
|
||||
LV_LOG_WARN("Incompatible subject type: %d", subject->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flag_and_cond_t * p = lv_malloc(sizeof(flag_and_cond_t));
|
||||
if(p == NULL) {
|
||||
LV_LOG_WARN("Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->flag = flag;
|
||||
p->value.num = ref_value;
|
||||
p->inv = inv;
|
||||
|
||||
lv_observer_t * observable = lv_subject_add_observer_obj(subject, cb, obj, p);
|
||||
observable->auto_free_user_data = 1;
|
||||
return observable;
|
||||
}
|
||||
|
||||
static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
flag_and_cond_t * p = observer->user_data;
|
||||
|
||||
bool res = subject->value.num == p->value.num;
|
||||
if(p->inv) res = !res;
|
||||
|
||||
if(res) {
|
||||
lv_obj_add_flag(observer->target, p->flag);
|
||||
}
|
||||
else {
|
||||
lv_obj_remove_flag(observer->target, p->flag);
|
||||
}
|
||||
}
|
||||
|
||||
static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
flag_and_cond_t * p = observer->user_data;
|
||||
|
||||
bool res = subject->value.num == p->value.num;
|
||||
if(p->inv) res = !res;
|
||||
|
||||
if(res) {
|
||||
lv_obj_add_state(observer->target, p->flag);
|
||||
}
|
||||
else {
|
||||
lv_obj_remove_state(observer->target, p->flag);
|
||||
}
|
||||
}
|
||||
|
||||
static void obj_value_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||
lv_subject_t * subject = lv_event_get_user_data(e);
|
||||
|
||||
lv_subject_set_int(subject, lv_obj_has_state(obj, LV_STATE_CHECKED));
|
||||
}
|
||||
|
||||
#if LV_USE_LABEL
|
||||
|
||||
static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
const char * fmt = observer->user_data;
|
||||
|
||||
if(fmt == NULL) {
|
||||
lv_label_set_text(observer->target, subject->value.pointer);
|
||||
}
|
||||
else {
|
||||
switch(subject->type) {
|
||||
case LV_SUBJECT_TYPE_INT:
|
||||
lv_label_set_text_fmt(observer->target, fmt, subject->value.num);
|
||||
break;
|
||||
case LV_SUBJECT_TYPE_STRING:
|
||||
case LV_SUBJECT_TYPE_POINTER:
|
||||
lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_LABEL*/
|
||||
|
||||
#if LV_USE_ARC
|
||||
|
||||
static void arc_value_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * arc = lv_event_get_current_target(e);
|
||||
lv_subject_t * subject = lv_event_get_user_data(e);
|
||||
|
||||
lv_subject_set_int(subject, lv_arc_get_value(arc));
|
||||
}
|
||||
|
||||
static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_arc_set_value(observer->target, subject->value.num);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_ARC*/
|
||||
|
||||
#if LV_USE_SLIDER
|
||||
|
||||
static void slider_value_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * slider = lv_event_get_current_target(e);
|
||||
lv_subject_t * subject = lv_event_get_user_data(e);
|
||||
|
||||
lv_subject_set_int(subject, lv_slider_get_value(slider));
|
||||
}
|
||||
|
||||
static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_slider_set_value(observer->target, subject->value.num, LV_ANIM_OFF);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_SLIDER*/
|
||||
|
||||
#if LV_USE_ROLLER
|
||||
|
||||
static void roller_value_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * roller = lv_event_get_current_target(e);
|
||||
lv_subject_t * subject = lv_event_get_user_data(e);
|
||||
|
||||
lv_subject_set_int(subject, lv_roller_get_selected(roller));
|
||||
}
|
||||
|
||||
static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
if((int32_t)lv_roller_get_selected(observer->target) != subject->value.num) {
|
||||
lv_roller_set_selected(observer->target, subject->value.num, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_ROLLER*/
|
||||
|
||||
#if LV_USE_DROPDOWN
|
||||
|
||||
static void dropdown_value_changed_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * dropdown = lv_event_get_current_target(e);
|
||||
lv_subject_t * subject = lv_event_get_user_data(e);
|
||||
|
||||
lv_subject_set_int(subject, lv_dropdown_get_selected(dropdown));
|
||||
}
|
||||
|
||||
static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_dropdown_set_selected(observer->target, subject->value.num);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DROPDOWN*/
|
||||
|
||||
#endif /*LV_USE_OBSERVER*/
|
||||
@@ -1,406 +0,0 @@
|
||||
/**
|
||||
* @file lv_observer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBSERVER_H
|
||||
#define LV_OBSERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../core/lv_obj.h"
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Values for lv_submect_t's `type` field.
|
||||
*/
|
||||
typedef enum {
|
||||
LV_SUBJECT_TYPE_INVALID = 0, /**< indicates subject not initialized yet*/
|
||||
LV_SUBJECT_TYPE_NONE = 1, /**< a null value like None or NILt*/
|
||||
LV_SUBJECT_TYPE_INT = 2, /**< an int32_t*/
|
||||
LV_SUBJECT_TYPE_POINTER = 3, /**< a void pointer*/
|
||||
LV_SUBJECT_TYPE_COLOR = 4, /**< an lv_color_t*/
|
||||
LV_SUBJECT_TYPE_GROUP = 5, /**< an array of subjects*/
|
||||
LV_SUBJECT_TYPE_STRING = 6, /**< a char pointer*/
|
||||
} lv_subject_type_t;
|
||||
|
||||
/**
|
||||
* A common type to handle all the various observable types in the same way
|
||||
*/
|
||||
typedef union {
|
||||
int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers)*/
|
||||
const void * pointer; /**< Constant pointer (string buffer, format string, font, cone text, etc)*/
|
||||
lv_color_t color; /**< Color */
|
||||
} lv_subject_value_t;
|
||||
|
||||
/**
|
||||
* The subject (an observable value)
|
||||
*/
|
||||
typedef struct {
|
||||
lv_ll_t subs_ll; /**< Subscribers*/
|
||||
uint32_t type : 4;
|
||||
uint32_t size : 28; /**< Might be used to store a size related to `type`*/
|
||||
lv_subject_value_t value; /**< Actual value*/
|
||||
lv_subject_value_t prev_value; /**< Previous value*/
|
||||
uint32_t notify_restart_query : 1; /**< If an observer deleted start notifying from the beginning. */
|
||||
void * user_data; /**< Additional parameter, can be used freely by the user*/
|
||||
} lv_subject_t;
|
||||
|
||||
/**
|
||||
* Callback called when the observed value changes
|
||||
* @param observer pointer to the observer of the callback
|
||||
* @param subject pointer to the subject of the observer
|
||||
*/
|
||||
typedef void (*lv_observer_cb_t)(lv_observer_t * observer, lv_subject_t * subject);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize an integer type subject
|
||||
* @param subject pointer to the subject
|
||||
* @param value initial value
|
||||
*/
|
||||
void lv_subject_init_int(lv_subject_t * subject, int32_t value);
|
||||
|
||||
/**
|
||||
* Set the value of an integer subject. It will notify all the observers as well.
|
||||
* @param subject pointer to the subject
|
||||
* @param value the new value
|
||||
*/
|
||||
void lv_subject_set_int(lv_subject_t * subject, int32_t value);
|
||||
|
||||
/**
|
||||
* Get the current value of an integer subject
|
||||
* @param subject pointer to the subject
|
||||
* @return the current value
|
||||
*/
|
||||
int32_t lv_subject_get_int(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get the previous value of an integer subject
|
||||
* @param subject pointer to the subject
|
||||
* @return the current value
|
||||
*/
|
||||
int32_t lv_subject_get_previous_int(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize a string type subject
|
||||
* @param subject pointer to the subject
|
||||
* @param buf pointer to a buffer to store the string
|
||||
* @param prev_buf pointer to a buffer to store the previous string, can be NULL if not used
|
||||
* @param size size of the buffer
|
||||
* @param value initial value as a string, e.g. "hello"
|
||||
* @note the string subject stores the whole string, not only a pointer
|
||||
*/
|
||||
void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value);
|
||||
|
||||
/**
|
||||
* Copy a string to a subject. It will notify all the observers as well.
|
||||
* @param subject pointer to the subject
|
||||
* @param buf the new string
|
||||
*/
|
||||
void lv_subject_copy_string(lv_subject_t * subject, const char * buf);
|
||||
|
||||
/**
|
||||
* Get the current value of an string subject
|
||||
* @param subject pointer to the subject
|
||||
* @return pointer to the buffer containing the current value
|
||||
*/
|
||||
const char * lv_subject_get_string(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get the previous value of an string subject
|
||||
* @param subject pointer to the subject
|
||||
* @return pointer to the buffer containing the current value
|
||||
* @note NULL will be returned if NULL was passed in `lv_subject_init_string()`
|
||||
* as `prev_buf`
|
||||
*/
|
||||
const char * lv_subject_get_previous_string(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize an pointer type subject
|
||||
* @param subject pointer to the subject
|
||||
* @param value initial value
|
||||
*/
|
||||
void lv_subject_init_pointer(lv_subject_t * subject, void * value);
|
||||
|
||||
/**
|
||||
* Set the value of a pointer subject. It will notify all the observers as well.
|
||||
* @param subject pointer to the subject
|
||||
* @param ptr new value
|
||||
*/
|
||||
void lv_subject_set_pointer(lv_subject_t * subject, void * ptr);
|
||||
|
||||
/**
|
||||
* Get the current value of a pointer subject
|
||||
* @param subject pointer to the subject
|
||||
* @return current value
|
||||
*/
|
||||
const void * lv_subject_get_pointer(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get the previous value of a pointer subject
|
||||
* @param subject pointer to the subject
|
||||
* @return current value
|
||||
*/
|
||||
const void * lv_subject_get_previous_pointer(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize an color type subject
|
||||
* @param subject pointer to the subject
|
||||
* @param color initial value
|
||||
*/
|
||||
void lv_subject_init_color(lv_subject_t * subject, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the value of a color subject. It will notify all the observers as well.
|
||||
* @param subject pointer to the subject
|
||||
* @param color new value
|
||||
*/
|
||||
void lv_subject_set_color(lv_subject_t * subject, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Get the current value of a color subject
|
||||
* @param subject pointer to the subject
|
||||
* @return current value
|
||||
*/
|
||||
lv_color_t lv_subject_get_color(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get the previous value of a color subject
|
||||
* @param subject pointer to the subject
|
||||
* @return current value
|
||||
*/
|
||||
lv_color_t lv_subject_get_previous_color(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Initialize a subject group
|
||||
* @param subject pointer to the subject
|
||||
* @param list list of other subject addresses, any of these changes `subject` will be notified
|
||||
* @param list_len number of elements in `list`
|
||||
*/
|
||||
void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len);
|
||||
|
||||
/**
|
||||
* Remove all the observers from a subject and free all allocated memories in it
|
||||
* @param subject pointer to the subject
|
||||
* @note objects added with `lv_subject_add_observer_obj` should be already deleted or
|
||||
* removed manually.
|
||||
*/
|
||||
void lv_subject_deinit(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get an element from the subject group's list
|
||||
* @param subject pointer to the subject
|
||||
* @param index index of the element to get
|
||||
* @return pointer a subject from the list, or NULL if the index is out of bounds
|
||||
*/
|
||||
lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index);
|
||||
|
||||
/**
|
||||
* Add an observer to a subject. When the subject changes `observer_cb` will be called.
|
||||
* @param subject pointer to the subject
|
||||
* @param observer_cb callback to call
|
||||
* @param user_data optional user data
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t observer_cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Add an observer to a subject for an object.
|
||||
* When the object is deleted, it will be removed from the subject automatically.
|
||||
* @param subject pointer to the subject
|
||||
* @param observer_cb callback to call
|
||||
* @param obj pointer to an object
|
||||
* @param user_data optional user data
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t observer_cb, lv_obj_t * obj,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Add an observer to a subject and also save a target.
|
||||
* @param subject pointer to the subject
|
||||
* @param observer_cb callback to call
|
||||
* @param target pointer to any data
|
||||
* @param user_data optional user data
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t observer_cb,
|
||||
void * target, void * user_data);
|
||||
|
||||
/**
|
||||
* Remove an observer from its subject
|
||||
* @param observer pointer to an observer
|
||||
*/
|
||||
void lv_observer_remove(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Remove the observers of an object from a subject or all subjects
|
||||
* @param obj the object whose observers should be removed
|
||||
* @param subject the subject to remove the object from, or `NULL` to remove from all subjects
|
||||
* @note This function can be used e.g. when an object's subject(s) needs to be replaced by other subject(s)
|
||||
*/
|
||||
void lv_obj_remove_from_subject(lv_obj_t * obj, lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Get the target of an observer
|
||||
* @param observer pointer to an observer
|
||||
* @return pointer to the saved target
|
||||
*/
|
||||
void * lv_observer_get_target(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Get the target object of the observer.
|
||||
* It's the same as `lv_observer_get_target` and added only
|
||||
* for semantic reasons
|
||||
* @param observer pointer to an observer
|
||||
* @return pointer to the saved object target
|
||||
*/
|
||||
lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Get the user data of the observer.
|
||||
* @param observer pointer to an observer
|
||||
* @return void pointer to the saved user data
|
||||
*/
|
||||
void * lv_observer_get_user_data(const lv_observer_t * observer);
|
||||
|
||||
/**
|
||||
* Notify all observers of subject
|
||||
* @param subject pointer to a subject
|
||||
*/
|
||||
void lv_subject_notify(lv_subject_t * subject);
|
||||
|
||||
/**
|
||||
* Set an object flag if an integer subject's value is equal to a reference value, clear the flag otherwise
|
||||
* @param obj pointer to an object
|
||||
* @param subject pointer to a subject
|
||||
* @param flag flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare the subject's value with
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set an object flag if an integer subject's value is not equal to a reference value, clear the flag otherwise
|
||||
* @param obj pointer to an object
|
||||
* @param subject pointer to a subject
|
||||
* @param flag flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`)
|
||||
* @param ref_value reference value to compare the subject's value with
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag,
|
||||
int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set an object state if an integer subject's value is equal to a reference value, clear the flag otherwise
|
||||
* @param obj pointer to an object
|
||||
* @param subject pointer to a subject
|
||||
* @param state state to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare the subject's value with
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set an object state if an integer subject's value is not equal to a reference value, clear the flag otherwise
|
||||
* @param obj pointer to an object
|
||||
* @param subject pointer to a subject
|
||||
* @param state state to set or clear (e.g. `LV_STATE_CHECKED`)
|
||||
* @param ref_value reference value to compare the subject's value with
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state,
|
||||
int32_t ref_value);
|
||||
|
||||
/**
|
||||
* Set an integer subject to 1 when an object is checked and set it 0 when unchecked.
|
||||
* @param obj pointer to an object
|
||||
* @param subject pointer to a subject
|
||||
* @return pointer to the created observer
|
||||
* @note Ensure the object's `LV_OBJ_FLAG_CHECKABLE` flag is set
|
||||
*/
|
||||
lv_observer_t * lv_obj_bind_checked(lv_obj_t * obj, lv_subject_t * subject);
|
||||
|
||||
#if LV_USE_LABEL
|
||||
/**
|
||||
* Bind an integer, string, or pointer subject to a label.
|
||||
* @param obj pointer to a label
|
||||
* @param subject pointer to a subject
|
||||
* @param fmt optional format string with 1 format specifier (e.g. "%d °C")
|
||||
* or NULL to bind the value directly.
|
||||
* @return pointer to the created observer
|
||||
* @note fmt == NULL can be used only with string and pointer subjects.
|
||||
* @note if the subject is a pointer must point to a `\0` terminated string.
|
||||
*/
|
||||
lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt);
|
||||
#endif
|
||||
|
||||
#if LV_USE_ARC
|
||||
/**
|
||||
* Bind an integer subject to an arc's value
|
||||
* @param obj pointer to an arc
|
||||
* @param subject pointer to a subject
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_SLIDER
|
||||
/**
|
||||
* Bind an integer subject to a slider's value
|
||||
* @param obj pointer to a slider
|
||||
* @param subject pointer to a subject
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_ROLLER
|
||||
/**
|
||||
* Bind an integer subject to a roller's value
|
||||
* @param obj pointer to a roller
|
||||
* @param subject pointer to a subject
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
#if LV_USE_DROPDOWN
|
||||
/**
|
||||
* Bind an integer subject to a dropdown's value
|
||||
* @param obj pointer to a drop down
|
||||
* @param subject pointer to a subject
|
||||
* @return pointer to the created observer
|
||||
*/
|
||||
lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_OBSERVER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBSERVER_H*/
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* @file lv_observer_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBSERVER_PRIVATE_H
|
||||
#define LV_OBSERVER_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_observer.h"
|
||||
|
||||
#if LV_USE_OBSERVER
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* The observer object: a descriptor returned when subscribing LVGL widgets to subjects
|
||||
*/
|
||||
struct lv_observer_t {
|
||||
lv_subject_t * subject; /**< The observed value */
|
||||
lv_observer_cb_t cb; /**< Callback that should be called when the value changes*/
|
||||
void * target; /**< A target for the observer, e.g. a widget or style*/
|
||||
void * user_data; /**< Additional parameter supplied when subscribing*/
|
||||
uint32_t auto_free_user_data : 1; /**< Automatically free user data when the observer is removed */
|
||||
uint32_t notified : 1; /**< Mark if this observer was already notified*/
|
||||
uint32_t for_obj : 1; /**< `target` is an `lv_obj_t *`*/
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_OBSERVER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBSERVER_PRIVATE_H*/
|
||||
@@ -1,178 +0,0 @@
|
||||
/**
|
||||
* @file lv_snapshot.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../draw/lv_draw_private.h"
|
||||
#include "../../core/lv_obj_draw_private.h"
|
||||
#include "lv_snapshot.h"
|
||||
#if LV_USE_SNAPSHOT
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../../display/lv_display.h"
|
||||
#include "../../core/lv_refr_private.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a draw buffer for object to store the snapshot image.
|
||||
*/
|
||||
lv_draw_buf_t * lv_snapshot_create_draw_buf(lv_obj_t * obj, lv_color_format_t cf)
|
||||
{
|
||||
lv_obj_update_layout(obj);
|
||||
int32_t w = lv_obj_get_width(obj);
|
||||
int32_t h = lv_obj_get_height(obj);
|
||||
int32_t ext_size = lv_obj_get_ext_draw_size(obj);
|
||||
w += ext_size * 2;
|
||||
h += ext_size * 2;
|
||||
if(w == 0 || h == 0) return NULL;
|
||||
|
||||
return lv_draw_buf_create(w, h, cf, LV_STRIDE_AUTO);
|
||||
}
|
||||
|
||||
lv_result_t lv_snapshot_reshape_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf)
|
||||
{
|
||||
lv_obj_update_layout(obj);
|
||||
int32_t w = lv_obj_get_width(obj);
|
||||
int32_t h = lv_obj_get_height(obj);
|
||||
int32_t ext_size = lv_obj_get_ext_draw_size(obj);
|
||||
w += ext_size * 2;
|
||||
h += ext_size * 2;
|
||||
if(w == 0 || h == 0) return LV_RESULT_INVALID;
|
||||
|
||||
draw_buf = lv_draw_buf_reshape(draw_buf, LV_COLOR_FORMAT_UNKNOWN, w, h, LV_STRIDE_AUTO);
|
||||
return draw_buf == NULL ? LV_RESULT_INVALID : LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * obj, lv_color_format_t cf, lv_draw_buf_t * draw_buf)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
LV_ASSERT_NULL(draw_buf);
|
||||
lv_result_t res;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
break;
|
||||
default:
|
||||
LV_LOG_WARN("Not supported color format");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
res = lv_snapshot_reshape_draw_buf(obj, draw_buf);
|
||||
if(res != LV_RESULT_OK) return res;
|
||||
|
||||
/* clear draw buffer*/
|
||||
lv_draw_buf_clear(draw_buf, NULL);
|
||||
|
||||
lv_area_t snapshot_area;
|
||||
int32_t w = draw_buf->header.w;
|
||||
int32_t h = draw_buf->header.h;
|
||||
int32_t ext_size = lv_obj_get_ext_draw_size(obj);
|
||||
lv_obj_get_coords(obj, &snapshot_area);
|
||||
lv_area_increase(&snapshot_area, ext_size, ext_size);
|
||||
|
||||
lv_layer_t layer;
|
||||
lv_memzero(&layer, sizeof(layer));
|
||||
|
||||
layer.draw_buf = draw_buf;
|
||||
layer.buf_area.x1 = snapshot_area.x1;
|
||||
layer.buf_area.y1 = snapshot_area.y1;
|
||||
layer.buf_area.x2 = snapshot_area.x1 + w - 1;
|
||||
layer.buf_area.y2 = snapshot_area.y1 + h - 1;
|
||||
layer.color_format = cf;
|
||||
layer._clip_area = snapshot_area;
|
||||
layer.phy_clip_area = snapshot_area;
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_identity(&layer.matrix);
|
||||
#endif
|
||||
|
||||
lv_display_t * disp_old = lv_refr_get_disp_refreshing();
|
||||
lv_display_t * disp_new = lv_obj_get_display(obj);
|
||||
lv_layer_t * layer_old = disp_new->layer_head;
|
||||
disp_new->layer_head = &layer;
|
||||
|
||||
lv_refr_set_disp_refreshing(disp_new);
|
||||
lv_obj_redraw(&layer, obj);
|
||||
|
||||
while(layer.draw_task_head) {
|
||||
lv_draw_dispatch_wait_for_request();
|
||||
lv_draw_dispatch();
|
||||
}
|
||||
|
||||
disp_new->layer_head = layer_old;
|
||||
lv_refr_set_disp_refreshing(disp_old);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
lv_draw_buf_t * lv_snapshot_take(lv_obj_t * obj, lv_color_format_t cf)
|
||||
{
|
||||
LV_ASSERT_NULL(obj);
|
||||
lv_draw_buf_t * draw_buf = lv_snapshot_create_draw_buf(obj, cf);
|
||||
if(draw_buf == NULL) return NULL;
|
||||
|
||||
if(lv_snapshot_take_to_draw_buf(obj, cf, draw_buf) != LV_RESULT_OK) {
|
||||
lv_draw_buf_destroy(draw_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return draw_buf;
|
||||
}
|
||||
|
||||
void lv_snapshot_free(lv_image_dsc_t * dsc)
|
||||
{
|
||||
LV_LOG_WARN("Deprecated API, use lv_draw_buf_destroy directly.");
|
||||
lv_draw_buf_destroy((lv_draw_buf_t *)dsc);
|
||||
}
|
||||
|
||||
lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc,
|
||||
void * buf,
|
||||
uint32_t buf_size)
|
||||
{
|
||||
lv_draw_buf_t draw_buf;
|
||||
LV_LOG_WARN("Deprecated API, use lv_snapshot_take_to_draw_buf instead.");
|
||||
lv_draw_buf_init(&draw_buf, 1, 1, cf, buf_size, buf, buf_size);
|
||||
lv_result_t res = lv_snapshot_take_to_draw_buf(obj, cf, &draw_buf);
|
||||
if(res == LV_RESULT_OK) {
|
||||
lv_memcpy((void *)dsc, &draw_buf, sizeof(lv_image_dsc_t));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SNAPSHOT*/
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* @file lv_snapshot.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SNAPSHOT_H
|
||||
#define LV_SNAPSHOT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../core/lv_obj.h"
|
||||
|
||||
#if LV_USE_SNAPSHOT
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Take snapshot for object with its children, create the draw buffer as needed.
|
||||
* @param obj the object to generate snapshot.
|
||||
* @param cf color format for generated image.
|
||||
* @return a pointer to an draw buffer containing snapshot image, or NULL if failed.
|
||||
*/
|
||||
lv_draw_buf_t * lv_snapshot_take(lv_obj_t * obj, lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Create a draw buffer to store the snapshot image for object.
|
||||
* @param obj the object to generate snapshot.
|
||||
* @param cf color format for generated image.
|
||||
* @return a pointer to an draw buffer ready for taking snapshot, or NULL if failed.
|
||||
*/
|
||||
lv_draw_buf_t * lv_snapshot_create_draw_buf(lv_obj_t * obj, lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Reshape the draw buffer to prepare for taking snapshot for obj.
|
||||
* This is usually used to check if the existing draw buffer is enough for
|
||||
* obj snapshot. If return LV_RESULT_INVALID, you should create a new one.
|
||||
* @param draw_buf the draw buffer to reshape.
|
||||
* @param obj the object to generate snapshot.
|
||||
*/
|
||||
lv_result_t lv_snapshot_reshape_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf);
|
||||
|
||||
/**
|
||||
* Take snapshot for object with its children, save image info to provided buffer.
|
||||
* @param obj the object to generate snapshot.
|
||||
* @param cf color format for new snapshot image.
|
||||
* It could differ with cf of `draw_buf` as long as the new cf will fit in.
|
||||
* @param draw_buf the draw buffer to store the image result. It's reshaped automatically.
|
||||
* @return LV_RESULT_OK on success, LV_RESULT_INVALID on error.
|
||||
*/
|
||||
lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * obj, lv_color_format_t cf, lv_draw_buf_t * draw_buf);
|
||||
|
||||
/**
|
||||
* @deprecated Use `lv_draw_buf_destroy` instead.
|
||||
*
|
||||
* Free the snapshot image returned by @ref lv_snapshot_take
|
||||
* @param dsc the image descriptor generated by lv_snapshot_take.
|
||||
*/
|
||||
void lv_snapshot_free(lv_image_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Take snapshot for object with its children, save image info to provided buffer.
|
||||
* @param obj the object to generate snapshot.
|
||||
* @param cf color format for generated image.
|
||||
* @param dsc image descriptor to store the image result.
|
||||
* @param buf the buffer to store image data. It must meet align requirement.
|
||||
* @param buf_size provided buffer size in bytes.
|
||||
* @return LV_RESULT_OK on success, LV_RESULT_INVALID on error.
|
||||
* @deprecated Use lv_snapshot_take_to_draw_buf instead.
|
||||
*/
|
||||
lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc,
|
||||
void * buf,
|
||||
uint32_t buf_size);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_SNAPSHOT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,335 +0,0 @@
|
||||
/**
|
||||
* @file lv_sysmon.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_sysmon_private.h"
|
||||
#include "../../misc/lv_timer_private.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
#include "../../core/lv_global.h"
|
||||
#include "../../misc/lv_async.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "../../widgets/label/lv_label.h"
|
||||
#include "../../display/lv_display_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_SYSMON_REFR_PERIOD_DEF
|
||||
#define LV_SYSMON_REFR_PERIOD_DEF 300 /* ms */
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define sysmon_mem LV_GLOBAL_DEFAULT()->sysmon_mem
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
static void perf_update_timer_cb(lv_timer_t * t);
|
||||
static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
static void perf_monitor_disp_event_cb(lv_event_t * e);
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
static void mem_update_timer_cb(lv_timer_t * t);
|
||||
static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_sysmon_builtin_init(void)
|
||||
{
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
static lv_mem_monitor_t mem_info;
|
||||
lv_subject_init_pointer(&sysmon_mem.subject, &mem_info);
|
||||
sysmon_mem.timer = lv_timer_create(mem_update_timer_cb, LV_SYSMON_REFR_PERIOD_DEF, &mem_info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_sysmon_builtin_deinit(void)
|
||||
{
|
||||
#if LV_USE_MEM_MONITOR
|
||||
lv_timer_delete(sysmon_mem.timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_obj_t * lv_sysmon_create(lv_display_t * disp)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_display_get_layer_sys(disp));
|
||||
lv_obj_set_style_bg_opa(label, LV_OPA_50, 0);
|
||||
lv_obj_set_style_bg_color(label, lv_color_black(), 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_white(), 0);
|
||||
lv_obj_set_style_pad_all(label, 3, 0);
|
||||
lv_label_set_text(label, "?");
|
||||
return label;
|
||||
}
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
void lv_sysmon_show_performance(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->perf_label = lv_sysmon_create(disp);
|
||||
if(disp->perf_label == NULL) {
|
||||
LV_LOG_WARN("Couldn't create sysmon");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_subject_init_pointer(&disp->perf_sysmon_backend.subject, &disp->perf_sysmon_info);
|
||||
lv_obj_align(disp->perf_label, LV_USE_PERF_MONITOR_POS, 0, 0);
|
||||
lv_subject_add_observer_obj(&disp->perf_sysmon_backend.subject, perf_observer_cb, disp->perf_label, NULL);
|
||||
disp->perf_sysmon_backend.timer = lv_timer_create(perf_update_timer_cb, LV_SYSMON_REFR_PERIOD_DEF, disp);
|
||||
lv_display_add_event_cb(disp, perf_monitor_disp_event_cb, LV_EVENT_ALL, NULL);
|
||||
|
||||
#if LV_USE_PERF_MONITOR_LOG_MODE
|
||||
lv_obj_add_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
#else
|
||||
lv_obj_remove_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_sysmon_hide_performance(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_add_flag(disp->perf_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
void lv_sysmon_show_memory(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->mem_label = lv_sysmon_create(disp);
|
||||
if(disp->mem_label == NULL) {
|
||||
LV_LOG_WARN("Couldn't create sysmon");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_align(disp->mem_label, LV_USE_MEM_MONITOR_POS, 0, 0);
|
||||
lv_subject_add_observer_obj(&sysmon_mem.subject, mem_observer_cb, disp->mem_label, NULL);
|
||||
|
||||
lv_obj_remove_flag(disp->mem_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void lv_sysmon_hide_memory(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) {
|
||||
LV_LOG_WARN("There is no default display");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_add_flag(disp->mem_label, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
static void perf_monitor_disp_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_display_t * disp = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_sysmon_perf_info_t * info = &disp->perf_sysmon_info;
|
||||
|
||||
switch(code) {
|
||||
case LV_EVENT_REFR_START:
|
||||
info->measured.refr_interval_sum += lv_tick_elaps(info->measured.refr_start);
|
||||
info->measured.refr_start = lv_tick_get();
|
||||
break;
|
||||
case LV_EVENT_REFR_READY:
|
||||
info->measured.refr_elaps_sum += lv_tick_elaps(info->measured.refr_start);
|
||||
info->measured.refr_cnt++;
|
||||
break;
|
||||
case LV_EVENT_RENDER_START:
|
||||
info->measured.render_in_progress = 1;
|
||||
info->measured.render_start = lv_tick_get();
|
||||
break;
|
||||
case LV_EVENT_RENDER_READY:
|
||||
info->measured.render_in_progress = 0;
|
||||
info->measured.render_elaps_sum += lv_tick_elaps(info->measured.render_start);
|
||||
info->measured.render_cnt++;
|
||||
break;
|
||||
case LV_EVENT_FLUSH_START:
|
||||
case LV_EVENT_FLUSH_WAIT_START:
|
||||
if(info->measured.render_in_progress) {
|
||||
info->measured.flush_in_render_start = lv_tick_get();
|
||||
}
|
||||
else {
|
||||
info->measured.flush_not_in_render_start = lv_tick_get();
|
||||
}
|
||||
break;
|
||||
case LV_EVENT_FLUSH_FINISH:
|
||||
case LV_EVENT_FLUSH_WAIT_FINISH:
|
||||
if(info->measured.render_in_progress) {
|
||||
info->measured.flush_in_render_elaps_sum += lv_tick_elaps(info->measured.flush_in_render_start);
|
||||
}
|
||||
else {
|
||||
info->measured.flush_not_in_render_elaps_sum += lv_tick_elaps(info->measured.flush_not_in_render_start);
|
||||
}
|
||||
break;
|
||||
case LV_EVENT_DELETE:
|
||||
lv_timer_delete(disp->perf_sysmon_backend.timer);
|
||||
lv_subject_deinit(&disp->perf_sysmon_backend.subject);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_update_timer_cb(lv_timer_t * t)
|
||||
{
|
||||
lv_display_t * disp = lv_timer_get_user_data(t);
|
||||
|
||||
uint32_t LV_SYSMON_GET_IDLE(void);
|
||||
|
||||
lv_sysmon_perf_info_t * info = &disp->perf_sysmon_info;
|
||||
info->calculated.run_cnt++;
|
||||
|
||||
uint32_t time_since_last_report = lv_tick_elaps(info->measured.last_report_timestamp);
|
||||
lv_timer_t * disp_refr_timer = lv_display_get_refr_timer(NULL);
|
||||
uint32_t disp_refr_period = disp_refr_timer->period;
|
||||
|
||||
info->calculated.fps = info->measured.refr_interval_sum ? (1000 * info->measured.refr_cnt / time_since_last_report) : 0;
|
||||
info->calculated.fps = LV_MIN(info->calculated.fps,
|
||||
1000 / disp_refr_period); /*Limit due to possible off-by-one error*/
|
||||
|
||||
info->calculated.cpu = 100 - LV_SYSMON_GET_IDLE();
|
||||
info->calculated.refr_avg_time = info->measured.refr_cnt ? (info->measured.refr_elaps_sum / info->measured.refr_cnt) :
|
||||
0;
|
||||
|
||||
info->calculated.flush_avg_time = info->measured.render_cnt ?
|
||||
((info->measured.flush_in_render_elaps_sum + info->measured.flush_not_in_render_elaps_sum)
|
||||
/ info->measured.render_cnt) : 0;
|
||||
/*Flush time was measured in rendering time so subtract it*/
|
||||
info->calculated.render_avg_time = info->measured.render_cnt ? ((info->measured.render_elaps_sum -
|
||||
info->measured.flush_in_render_elaps_sum) /
|
||||
info->measured.render_cnt) : 0;
|
||||
|
||||
info->calculated.cpu_avg_total = ((info->calculated.cpu_avg_total * (info->calculated.run_cnt - 1)) +
|
||||
info->calculated.cpu) / info->calculated.run_cnt;
|
||||
info->calculated.fps_avg_total = ((info->calculated.fps_avg_total * (info->calculated.run_cnt - 1)) +
|
||||
info->calculated.fps) / info->calculated.run_cnt;
|
||||
|
||||
lv_subject_set_pointer(&disp->perf_sysmon_backend.subject, info);
|
||||
|
||||
lv_sysmon_perf_info_t prev_info = *info;
|
||||
lv_memzero(info, sizeof(lv_sysmon_perf_info_t));
|
||||
info->measured.refr_start = prev_info.measured.refr_start;
|
||||
info->calculated.cpu_avg_total = prev_info.calculated.cpu_avg_total;
|
||||
info->calculated.fps_avg_total = prev_info.calculated.fps_avg_total;
|
||||
info->calculated.run_cnt = prev_info.calculated.run_cnt;
|
||||
|
||||
info->measured.last_report_timestamp = lv_tick_get();
|
||||
}
|
||||
|
||||
static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
const lv_sysmon_perf_info_t * perf = lv_subject_get_pointer(subject);
|
||||
|
||||
#if LV_USE_PERF_MONITOR_LOG_MODE
|
||||
LV_UNUSED(observer);
|
||||
LV_LOG("sysmon: "
|
||||
"%" LV_PRIu32 " FPS (refr_cnt: %" LV_PRIu32 " | redraw_cnt: %" LV_PRIu32"), "
|
||||
"refr %" LV_PRIu32 "ms (render %" LV_PRIu32 "ms | flush %" LV_PRIu32 "ms), "
|
||||
"CPU %" LV_PRIu32 "%%\n",
|
||||
perf->calculated.fps, perf->measured.refr_cnt, perf->measured.render_cnt,
|
||||
perf->calculated.refr_avg_time, perf->calculated.render_avg_time, perf->calculated.flush_avg_time,
|
||||
perf->calculated.cpu);
|
||||
#else
|
||||
lv_obj_t * label = lv_observer_get_target(observer);
|
||||
lv_label_set_text_fmt(
|
||||
label,
|
||||
"%" LV_PRIu32" FPS, %" LV_PRIu32 "%% CPU\n"
|
||||
"%" LV_PRIu32" ms (%" LV_PRIu32" | %" LV_PRIu32")",
|
||||
perf->calculated.fps, perf->calculated.cpu,
|
||||
perf->calculated.render_avg_time + perf->calculated.flush_avg_time,
|
||||
perf->calculated.render_avg_time, perf->calculated.flush_avg_time
|
||||
);
|
||||
#endif /*LV_USE_PERF_MONITOR_LOG_MODE*/
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
static void mem_update_timer_cb(lv_timer_t * t)
|
||||
{
|
||||
lv_mem_monitor_t * mem_mon = lv_timer_get_user_data(t);
|
||||
lv_mem_monitor(mem_mon);
|
||||
lv_subject_set_pointer(&sysmon_mem.subject, mem_mon);
|
||||
}
|
||||
|
||||
static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_obj_t * label = lv_observer_get_target(observer);
|
||||
const lv_mem_monitor_t * mon = lv_subject_get_pointer(subject);
|
||||
|
||||
size_t used_size = mon->total_size - mon->free_size;;
|
||||
size_t used_kb = used_size / 1024;
|
||||
size_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102;
|
||||
size_t max_used_kb = mon->max_used / 1024;
|
||||
size_t max_used_kb_tenth = (mon->max_used - (max_used_kb * 1024)) / 102;
|
||||
lv_label_set_text_fmt(label,
|
||||
"%zu.%zu kB (%d%%)\n"
|
||||
"%zu.%zu kB max, %d%% frag.",
|
||||
used_kb, used_kb_tenth, mon->used_pct,
|
||||
max_used_kb, max_used_kb_tenth,
|
||||
mon->frag_pct);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* @file lv_sysmon.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SYSMON_H
|
||||
#define LV_SYSMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../misc/lv_timer.h"
|
||||
#include "../../others/observer/lv_observer.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
#if LV_USE_LABEL == 0
|
||||
#error "lv_sysmon: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_OBSERVER == 0
|
||||
#error "lv_observer: lv_observer is required. Enable it in lv_conf.h (LV_USE_OBSERVER 1) "
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new system monitor label
|
||||
* @param disp create the sys. mon. on this display's system layer
|
||||
* @return the create label
|
||||
*/
|
||||
lv_obj_t * lv_sysmon_create(lv_display_t * disp);
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
|
||||
/**
|
||||
* Show system performance monitor: CPU usage and FPS count
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_show_performance(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Hide system performance monitor
|
||||
* @param disp target display, NULL: use the default
|
||||
*/
|
||||
void lv_sysmon_hide_performance(lv_display_t * disp);
|
||||
|
||||
#endif /*LV_USE_PERF_MONITOR*/
|
||||
|
||||
#if LV_USE_MEM_MONITOR
|
||||
|
||||
/**
|
||||
* Show system memory monitor: used memory and the memory fragmentation
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_show_memory(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Hide system memory monitor
|
||||
* @param disp target display, NULL: use the default displays
|
||||
*/
|
||||
void lv_sysmon_hide_memory(lv_display_t * disp);
|
||||
|
||||
#endif /*LV_USE_MEM_MONITOR*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SYSMON_H*/
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* @file lv_sysmon_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SYSMON_PRIVATE_H
|
||||
#define LV_SYSMON_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_sysmon.h"
|
||||
|
||||
#if LV_USE_SYSMON
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct lv_sysmon_backend_data_t {
|
||||
lv_subject_t subject;
|
||||
lv_timer_t * timer;
|
||||
};
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
struct lv_sysmon_perf_info_t {
|
||||
struct {
|
||||
bool inited;
|
||||
uint32_t refr_start;
|
||||
uint32_t refr_interval_sum;
|
||||
uint32_t refr_elaps_sum;
|
||||
uint32_t refr_cnt;
|
||||
uint32_t render_start;
|
||||
uint32_t render_elaps_sum; /*Contains the flush time too*/
|
||||
uint32_t render_cnt;
|
||||
uint32_t flush_in_render_start;
|
||||
uint32_t flush_in_render_elaps_sum;
|
||||
uint32_t flush_not_in_render_start;
|
||||
uint32_t flush_not_in_render_elaps_sum;
|
||||
uint32_t last_report_timestamp;
|
||||
uint32_t render_in_progress : 1;
|
||||
} measured;
|
||||
|
||||
struct {
|
||||
uint32_t fps;
|
||||
uint32_t cpu;
|
||||
uint32_t refr_avg_time;
|
||||
uint32_t render_avg_time; /**< Pure rendering time without flush time*/
|
||||
uint32_t flush_avg_time; /**< Pure flushing time without rendering time*/
|
||||
uint32_t cpu_avg_total;
|
||||
uint32_t fps_avg_total;
|
||||
uint32_t run_cnt;
|
||||
} calculated;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize built-in system monitor, such as performance and memory monitor.
|
||||
*/
|
||||
void lv_sysmon_builtin_init(void);
|
||||
|
||||
/**
|
||||
* DeInitialize built-in system monitor, such as performance and memory monitor.
|
||||
*/
|
||||
void lv_sysmon_builtin_deinit(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_SYSMON */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_SYSMON_PRIVATE_H*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,162 +0,0 @@
|
||||
/**
|
||||
* @file vg_lite_matrix.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define VG_SW_BLIT_PRECISION_OPT 1
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
vg_lite_error_t vg_lite_identity(vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set identify matrix. */
|
||||
matrix->m[0][0] = 1.0f;
|
||||
matrix->m[0][1] = 0.0f;
|
||||
matrix->m[0][2] = 0.0f;
|
||||
matrix->m[1][0] = 0.0f;
|
||||
matrix->m[1][1] = 1.0f;
|
||||
matrix->m[1][2] = 0.0f;
|
||||
matrix->m[2][0] = 0.0f;
|
||||
matrix->m[2][1] = 0.0f;
|
||||
matrix->m[2][2] = 1.0f;
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->scaleX = 1.0f;
|
||||
matrix->scaleY = 1.0f;
|
||||
matrix->angle = 0.0f;
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
|
||||
{
|
||||
vg_lite_matrix_t temp;
|
||||
int row, column;
|
||||
|
||||
/* Process all rows. */
|
||||
for(row = 0; row < 3; row++) {
|
||||
/* Process all columns. */
|
||||
for(column = 0; column < 3; column++) {
|
||||
/* Compute matrix entry. */
|
||||
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
|
||||
+ (matrix->m[row][1] * mult->m[1][column])
|
||||
+ (matrix->m[row][2] * mult->m[2][column]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy temporary matrix into result. */
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
memcpy(matrix, &temp, sizeof(vg_lite_float_t) * 9);
|
||||
#else
|
||||
memcpy(matrix, &temp, sizeof(temp));
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_translate(vg_lite_float_t x, vg_lite_float_t y, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set translation matrix. */
|
||||
vg_lite_matrix_t t = { { {1.0f, 0.0f, x},
|
||||
{0.0f, 1.0f, y},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &t);
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_scale(vg_lite_float_t scale_x, vg_lite_float_t scale_y, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Set scale matrix. */
|
||||
vg_lite_matrix_t s = { { {scale_x, 0.0f, 0.0f},
|
||||
{0.0f, scale_y, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &s);
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->scaleX = matrix->scaleX * scale_x;
|
||||
matrix->scaleY = matrix->scaleY * scale_y;
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_rotate(vg_lite_float_t degrees, vg_lite_matrix_t * matrix)
|
||||
{
|
||||
/* Convert degrees into radians. */
|
||||
vg_lite_float_t angle = (degrees / 180.0f) * 3.141592654f;
|
||||
|
||||
/* Compute cosine and sine values. */
|
||||
vg_lite_float_t cos_angle = cosf(angle);
|
||||
vg_lite_float_t sin_angle = sinf(angle);
|
||||
|
||||
/* Set rotation matrix. */
|
||||
vg_lite_matrix_t r = { { {cos_angle, -sin_angle, 0.0f},
|
||||
{sin_angle, cos_angle, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
},
|
||||
0.0f, 0.0f, 0.0f
|
||||
};
|
||||
|
||||
/* Multiply with current matrix. */
|
||||
multiply(matrix, &r);
|
||||
|
||||
#if VG_SW_BLIT_PRECISION_OPT
|
||||
matrix->angle = matrix->angle + degrees;
|
||||
if(matrix->angle >= 360) {
|
||||
vg_lite_uint32_t count = (vg_lite_uint32_t)matrix->angle / 360;
|
||||
matrix->angle = matrix->angle - count * 360;
|
||||
}
|
||||
#endif /* VG_SW_BLIT_PRECISION_OPT */
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_VG_LITE_THORVG*/
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user