diff --git a/README.md b/README.md index adc47a6bf..a7bc9e89f 100644 --- a/README.md +++ b/README.md @@ -133,14 +133,15 @@ lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL); /*Add a button the curre lv_obj_set_pos(btn, 10, 10); /*Set its position*/ lv_obj_set_size(btn, 100, 50); /*Set its size*/ -lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, btn_action);/*Assign a callback to the button*/ +lv_obj_set_event_cb(btn, btn_event_cb); /*Assign a callback to the button*/ lv_obj_t * label = lv_label_create(btn, NULL); /*Add a label to the button*/ lv_label_set_text(label, "Button"); /*Set the labels text*/ -lv_res_t btn_action(lv_obj_t * btn) +void btn_event_cb(lv_obj_t * btn, lv_event_t event) { - printf("Clicked\n"); - return LV_RES_OK; + if(event == LV_EVENT_CLICKED) { + printf("Clicked\n"); + } } ``` ![Simple button with LittelvGL](https://littlevgl.com/github/btn1.gif) diff --git a/lvgl.h b/lvgl.h index 842fd7727..b6e29b61b 100644 --- a/lvgl.h +++ b/lvgl.h @@ -19,6 +19,7 @@ extern "C" { #include "src/lv_misc/lv_log.h" #include "src/lv_misc/lv_task.h" #include "src/lv_misc/lv_math.h" +#include "src/lv_misc/lv_async.h" #include "src/lv_hal/lv_hal.h" diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index b11bbc8d1..1add35770 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -15,6 +15,7 @@ #include "../lv_draw/lv_draw.h" #include "../lv_misc/lv_anim.h" #include "../lv_misc/lv_task.h" +#include "../lv_misc/lv_async.h" #include "../lv_misc/lv_fs.h" #include "../lv_hal/lv_hal.h" #include @@ -49,6 +50,7 @@ static void report_style_mod_core(void * style_p, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); static void delete_children(lv_obj_t * obj); static void lv_event_mark_deleted(lv_obj_t * obj); +static void lv_obj_del_async_cb(void * obj); static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode); static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param); @@ -448,6 +450,17 @@ lv_res_t lv_obj_del(lv_obj_t * obj) return LV_RES_INV; } +/** + * Helper function for asynchronously deleting objects. + * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). + * @param obj object to delete + * @see lv_async_call + */ +void lv_obj_del_async(lv_obj_t * obj) +{ + lv_async_call(lv_obj_del_async_cb, obj); +} + /** * Delete all children of an object * @param obj pointer to an object @@ -2101,6 +2114,11 @@ bool lv_obj_is_focused(const lv_obj_t * obj) * STATIC FUNCTIONS **********************/ +static void lv_obj_del_async_cb(void * obj) +{ + lv_obj_del(obj); +} + /** * Handle the drawing related tasks of the base objects. * @param obj pointer to an object diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index cc5bd3d74..c2062e969 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -285,6 +285,14 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy); */ lv_res_t lv_obj_del(lv_obj_t * obj); +/** + * Helper function for asynchronously deleting objects. + * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). + * @param obj object to delete + * @see lv_async_call + */ +void lv_obj_del_async(struct _lv_obj_t *obj); + /** * Delete all children of an object * @param obj pointer to an object diff --git a/src/lv_draw/lv_draw_basic.c b/src/lv_draw/lv_draw_basic.c index e7be49a9d..afbf481df 100644 --- a/src/lv_draw/lv_draw_basic.c +++ b/src/lv_draw/lv_draw_basic.c @@ -45,7 +45,9 @@ static void sw_mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t len static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa); +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa); +#endif /********************** * STATIC VARIABLES @@ -90,7 +92,7 @@ void lv_draw_px(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width, x, y, color, opa); } else { bool scr_transp = false; -#if LV_COLOR_SCREEN_TRANSP +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP scr_transp = disp->driver.screen_transp; #endif @@ -104,7 +106,7 @@ void lv_draw_px(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t *vdb_px_p = lv_color_mix(color, *vdb_px_p, opa); } } else { -#if LV_COLOR_DEPTH == 32 +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP *vdb_px_p = color_mix_2_alpha(*vdb_px_p, (*vdb_px_p).ch.alpha, color, opa); #endif } @@ -317,7 +319,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ bool scr_transp = false; -#if LV_COLOR_SCREEN_TRANSP +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP scr_transp = disp->driver.screen_transp; #endif @@ -343,7 +345,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv if(scr_transp == false) { *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa); } else { -#if LV_COLOR_DEPTH == 32 +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP *vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa); #endif } @@ -429,7 +431,7 @@ void lv_draw_map(const lv_area_t * cords_p, const lv_area_t * mask_p, const uint lv_coord_t map_useful_w = lv_area_get_width(&masked_a); bool scr_transp = false; -#if LV_COLOR_SCREEN_TRANSP +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP scr_transp = disp->driver.screen_transp; #endif @@ -535,7 +537,7 @@ void lv_draw_map(const lv_area_t * cords_p, const lv_area_t * mask_p, const uint if(scr_transp == false) { vdb_buf_tmp[col] = lv_color_mix(px_color, vdb_buf_tmp[col], opa_result); } else { -#if LV_COLOR_DEPTH == 32 +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP vdb_buf_tmp[col] = color_mix_2_alpha(vdb_buf_tmp[col], vdb_buf_tmp[col].ch.alpha, px_color, opa_result); #endif @@ -620,7 +622,7 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_ /*Calculate with alpha too*/ else { bool scr_transp = false; -#if LV_COLOR_SCREEN_TRANSP +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP scr_transp = disp->driver.screen_transp; #endif @@ -638,7 +640,7 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_ mem[col] = opa_tmp; } else { -#if LV_COLOR_DEPTH == 32 +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP mem[col] = color_mix_2_alpha(mem[col], mem[col].ch.alpha, color, opa); #endif } @@ -649,6 +651,7 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_ } } +#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP /** * Mix two colors. Both color can have alpha value. It requires ARGB888 colors. * @param bg_color background color @@ -659,8 +662,6 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_ */ static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa) { - -#if LV_COLOR_SCREEN_TRANSP /* Pick the foreground if it's fully opaque or the Background is fully transparent*/ if(fg_opa > LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { fg_color.ch.alpha = fg_opa; @@ -702,13 +703,5 @@ static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa, } return c; } -#else - (void)bg_color; /*Unused*/ - (void)fg_color; /*Unused*/ - (void)bg_opa; /*Unused*/ - (void)fg_opa; /*Unused*/ - - return LV_COLOR_BLACK; - -#endif /*LV_COLOR_SCREEN_TRANSP*/ } +#endif diff --git a/src/lv_draw/lv_img_decoder.c b/src/lv_draw/lv_img_decoder.c index c9f5448f6..5133c2a58 100644 --- a/src/lv_draw/lv_img_decoder.c +++ b/src/lv_draw/lv_img_decoder.c @@ -19,6 +19,8 @@ /********************* * DEFINES *********************/ +#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR +#define CF_BUILT_IN_LAST LV_IMG_CF_ALPHA_8BIT /********************** * TYPEDEFS @@ -34,12 +36,6 @@ typedef struct /********************** * STATIC PROTOTYPES **********************/ - -static lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); -static lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); -static lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, - lv_coord_t y, lv_coord_t len, uint8_t * buf); -static void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf); static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, @@ -177,7 +173,9 @@ lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_c */ void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc) { - if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); + if(dsc->decoder) { + if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); + } } /** @@ -246,16 +244,22 @@ void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_clos decoder->close_cb = close_cb; } -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) +/** + * Get info about a built-in image + * @param decoder the decoder where this function belongs + * @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol + * @param header store the image data here + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) { (void)decoder; /*Unused*/ lv_img_src_t src_type = lv_img_src_get_type(src); if(src_type == LV_IMG_SRC_VARIABLE) { + lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf; + if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV; + header->w = ((lv_img_dsc_t *)src)->header.w; header->h = ((lv_img_dsc_t *)src)->header.h; header->cf = ((lv_img_dsc_t *)src)->header.cf; @@ -271,13 +275,9 @@ static lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const v lv_fs_close(&file); } - /*Create a dummy header on fs error*/ - if(res != LV_FS_RES_OK || rn != sizeof(lv_img_header_t)) { - header->w = LV_DPI; - header->h = LV_DPI; - header->cf = LV_IMG_CF_UNKNOWN; - return LV_RES_INV; - } + lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf; + if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV; + } #endif else if(src_type == LV_IMG_SRC_SYMBOL) { @@ -295,7 +295,13 @@ static lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const v return LV_RES_OK; } -static lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +/** + * Open a built in image + * @param decoder the decoder where this function belongs + * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) { /*Open the file if it's a file*/ if(dsc->src_type == LV_IMG_SRC_FILE) { @@ -424,7 +430,18 @@ static lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_ } } -static lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't return with the whole decoded pixel array. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RES_OK: ok; LV_RES_INV: failed + */ +lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) { (void)decoder; /*Unused*/ @@ -453,7 +470,12 @@ static lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv return res; } -static void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) { (void)decoder; /*Unused*/ @@ -473,6 +495,11 @@ static void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_dec } } + +/********************** + * STATIC FUNCTIONS + **********************/ + static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) { diff --git a/src/lv_draw/lv_img_decoder.h b/src/lv_draw/lv_img_decoder.h index 4c6366741..fb7af8324 100644 --- a/src/lv_draw/lv_img_decoder.h +++ b/src/lv_draw/lv_img_decoder.h @@ -93,6 +93,25 @@ enum { LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/ LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/ LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/ + + LV_IMG_CF_RESERVED_15, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_16, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_17, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_18, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_19, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_20, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_21, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_22, /**< Reserved for further use. */ + LV_IMG_CF_RESERVED_23, /**< Reserved for further use. */ + + LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format. */ + LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format. */ }; typedef uint8_t lv_img_cf_t; @@ -287,6 +306,46 @@ void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_ */ void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb); + + +/** + * Get info about a built-in image + * @param decoder the decoder where this function belongs + * @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol + * @param header store the image data here + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); + +/** + * Open a built in image + * @param decoder the decoder where this function belongs + * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); + +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't return with the whole decoded pixel array. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RES_OK: ok; LV_RES_INV: failed + */ +lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, + lv_coord_t y, lv_coord_t len, uint8_t * buf); + +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); + /********************** * MACROS **********************/ diff --git a/src/lv_font/lv_font.mk b/src/lv_font/lv_font.mk index a605da791..836d86a6c 100644 --- a/src/lv_font/lv_font.mk +++ b/src/lv_font/lv_font.mk @@ -4,6 +4,7 @@ CSRCS += lv_font_roboto_12.c CSRCS += lv_font_roboto_16.c CSRCS += lv_font_roboto_22.c CSRCS += lv_font_roboto_28.c +CSRCS += lv_font_unscii_8.c DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_font VPATH += :$(LVGL_DIR)/lvgl/src/lv_font diff --git a/src/lv_misc/lv_async.c b/src/lv_misc/lv_async.c new file mode 100644 index 000000000..2a836432b --- /dev/null +++ b/src/lv_misc/lv_async.c @@ -0,0 +1,75 @@ +/** + * @file lv_async.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_async.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_async_task_cb(lv_task_t *task); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data) +{ + /*Allocate an info structure */ + lv_async_info_t *info = lv_mem_alloc(sizeof(lv_async_info_t)); + + if(info == NULL) + return LV_RES_INV; + + /* Create a new task */ + /* Use highest priority so that it will run before a refresh */ + lv_task_t *task = lv_task_create(lv_async_task_cb, 0, LV_TASK_PRIO_HIGHEST, info); + + if(task == NULL) { + lv_mem_free(info); + return LV_RES_INV; + } + + info->cb = async_xcb; + info->user_data = user_data; + + /* Set the task's user data */ + task->user_data = info; + lv_task_once(task); + return LV_RES_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_async_task_cb(lv_task_t *task) +{ + lv_async_info_t *info = (lv_async_info_t *)task->user_data; + + info->cb(info->user_data); + + lv_mem_free(info); +} diff --git a/src/lv_misc/lv_async.h b/src/lv_misc/lv_async.h new file mode 100644 index 000000000..9423cd8ec --- /dev/null +++ b/src/lv_misc/lv_async.h @@ -0,0 +1,62 @@ +/** + * @file lv_async.h + * + */ + +#ifndef LV_ASYNC_H +#define LV_ASYNC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "lv_task.h" +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Type for async callback. + */ +typedef void (*lv_async_cb_t)(void *); + +typedef struct _lv_async_info_t { + lv_async_cb_t cb; + void *user_data; +} lv_async_info_t; + +struct _lv_obj_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Call an asynchronous function the next time lv_task_handler() is run. This function is likely to return + * **before** the call actually happens! + * @param task_xcb a callback which is the task itself. + * (the 'x' in the argument name indicates that its not a fully generic function because it not follows + * the `func_name(object, callback, ...)` convention) + * @param user_data custom parameter + */ +lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TEMPL_H*/ diff --git a/src/lv_misc/lv_misc.mk b/src/lv_misc/lv_misc.mk index 52ffe8904..41e4720f0 100644 --- a/src/lv_misc/lv_misc.mk +++ b/src/lv_misc/lv_misc.mk @@ -11,6 +11,7 @@ CSRCS += lv_math.c CSRCS += lv_log.c CSRCS += lv_gc.c CSRCS += lv_utils.c +CSRCS += lv_async.c DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_misc VPATH += :$(LVGL_DIR)/lvgl/src/lv_misc diff --git a/src/lv_objx/lv_list.c b/src/lv_objx/lv_list.c index 6fedf950d..7e8308cc5 100644 --- a/src/lv_objx/lv_list.c +++ b/src/lv_objx/lv_list.c @@ -366,6 +366,36 @@ void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t * } } +/** + * Set layout of a list + * @param list pointer to a list object + * @param layout which layout should be used + */ + void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout) + { + /* Update list layout if necessary */ + if (layout == lv_list_get_layout(list)) return; + + /* Get the first button on the list */ + lv_obj_t * btn = lv_list_get_prev_btn(list, NULL); + + /* Visit all buttons on the list and update their layout */ + while(btn != NULL) { + /*If a column layout set the buttons' width to list width*/ + if(layout == LV_LAYOUT_COL_M || layout == LV_LAYOUT_COL_L || layout == LV_LAYOUT_COL_R) { + lv_btn_set_fit2(list, LV_FIT_FLOOD, LV_FIT_TIGHT); + } + /*If a row layout set the buttons' width according to the content*/ + else if (layout == LV_LAYOUT_ROW_M || layout == LV_LAYOUT_ROW_T || layout == LV_LAYOUT_ROW_B) { + lv_btn_set_fit(list, LV_FIT_TIGHT); + } + + btn = lv_list_get_prev_btn(list, btn); + } + + lv_page_set_scrl_layout(list, layout); + } + /*===================== * Getter functions *====================*/ @@ -529,15 +559,24 @@ lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list) lv_list_ext_t * ext = lv_obj_get_ext_attr(list); return ext->selected_btn; } - #endif +/** + * Get layout of a list + * @param list pointer to a list object + * @return layout of the list object + */ +lv_layout_t lv_list_get_layout(lv_obj_t * list) +{ + return lv_page_get_scrl_layout(list); +} + /** * Get a style of a list * @param list pointer to a list object * @param type which style should be get * @return style pointer to a style - * */ + */ const lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type) { const lv_style_t * style = NULL; @@ -558,6 +597,7 @@ const lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type return style; } + /*===================== * Other functions *====================*/ diff --git a/src/lv_objx/lv_list.h b/src/lv_objx/lv_list.h index 7b7927841..9bba6fb89 100644 --- a/src/lv_objx/lv_list.h +++ b/src/lv_objx/lv_list.h @@ -189,6 +189,13 @@ static inline void lv_list_set_anim_time(lv_obj_t * list, uint16_t anim_time) */ void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t * style); +/** + * Set layout of a list + * @param list pointer to a list object + * @param layout which layout should be used + */ +void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout); + /*===================== * Getter functions *====================*/ @@ -259,6 +266,13 @@ uint16_t lv_list_get_size(const lv_obj_t * list); lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list); #endif +/** + * Get layout of a list + * @param list pointer to a list object + * @return layout of the list object + */ +lv_layout_t lv_list_get_layout(lv_obj_t * list); + /** * Get the scroll bar mode of a list * @param list pointer to a list object diff --git a/src/lv_objx/lv_mbox.c b/src/lv_objx/lv_mbox.c index 6101c4aaa..9a5fa1dd7 100644 --- a/src/lv_objx/lv_mbox.c +++ b/src/lv_objx/lv_mbox.c @@ -40,6 +40,7 @@ static void mbox_realign(lv_obj_t * mbox); static void lv_mbox_close_ready_cb(lv_anim_t * a); #endif static void lv_mbox_default_event_cb(lv_obj_t * mbox, lv_event_t event); +static void lv_mbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event); /********************** * STATIC VARIABLES @@ -157,7 +158,7 @@ void lv_mbox_add_btns(lv_obj_t * mbox, const char ** btn_map) lv_btnm_set_map(ext->btnm, btn_map); lv_btnm_set_btn_ctrl_all(ext->btnm, LV_BTNM_CTRL_CLICK_TRIG | LV_BTNM_CTRL_NO_REPEAT); - lv_obj_set_parent_event(ext->btnm, true); + lv_obj_set_event_cb(ext->btnm, lv_mbox_btnm_event_cb); mbox_realign(mbox); } @@ -529,4 +530,18 @@ static void lv_mbox_default_event_cb(lv_obj_t * mbox, lv_event_t event) lv_mbox_start_auto_close(mbox, 0); } +static void lv_mbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event) +{ + lv_obj_t * mbox = lv_obj_get_parent(btnm); + + /*clang-format off*/ + if(event == LV_EVENT_PRESSED || event == LV_EVENT_PRESSING || event == LV_EVENT_PRESS_LOST || + event == LV_EVENT_RELEASED || event == LV_EVENT_SHORT_CLICKED || event == LV_EVENT_CLICKED || + event == LV_EVENT_LONG_PRESSED || event == LV_EVENT_LONG_PRESSED_REPEAT || + event == LV_EVENT_VALUE_CHANGED) { + lv_event_send(mbox, event, lv_event_get_data()); + } + /*clang-format on*/ +} + #endif diff --git a/src/lv_themes/lv_theme_default.c b/src/lv_themes/lv_theme_default.c index d13dfbc95..7a7c23114 100644 --- a/src/lv_themes/lv_theme_default.c +++ b/src/lv_themes/lv_theme_default.c @@ -35,9 +35,6 @@ static lv_style_t plain_bordered; static lv_style_t label_prim; static lv_style_t label_sec; static lv_style_t label_hint; -static lv_style_t slider_bg; -static lv_style_t sw_bg; -static lv_style_t lmeter; /*Saved input parameters*/ static uint16_t _hue; @@ -149,6 +146,7 @@ static void bar_init(void) static void slider_init(void) { #if LV_USE_SLIDER != 0 + static lv_style_t slider_bg; lv_style_copy(&slider_bg, &lv_style_pretty); slider_bg.body.padding.left = LV_DPI / 20; slider_bg.body.padding.right = LV_DPI / 20; @@ -164,6 +162,7 @@ static void slider_init(void) static void sw_init(void) { #if LV_USE_SW != 0 + static lv_style_t sw_bg; lv_style_copy(&sw_bg, &lv_style_pretty); sw_bg.body.padding.left = 3; sw_bg.body.padding.right = 3; @@ -180,7 +179,7 @@ static void sw_init(void) static void lmeter_init(void) { #if LV_USE_LMETER != 0 - + static lv_style_t lmeter; lv_style_copy(&lmeter, &lv_style_pretty_color); lmeter.line.color = lv_color_hex3(0xddd); lmeter.line.width = 2; @@ -195,11 +194,11 @@ static void gauge_init(void) { #if LV_USE_GAUGE != 0 static lv_style_t gauge; - lv_style_copy(&gauge, &lmeter); - gauge.line.color = lmeter.body.grad_color; + lv_style_copy(&gauge, theme.style.lmeter); + gauge.line.color = theme.style.lmeter->body.grad_color; gauge.line.width = 2; gauge.body.main_color = lv_color_hex3(0x888); - gauge.body.grad_color = lmeter.body.main_color; + gauge.body.grad_color = theme.style.lmeter->body.main_color; gauge.text.color = lv_color_hex3(0x888); theme.style.gauge = &gauge; diff --git a/src/lv_themes/lv_theme_night.c b/src/lv_themes/lv_theme_night.c index 46bacdf9e..49c50db7a 100644 --- a/src/lv_themes/lv_theme_night.c +++ b/src/lv_themes/lv_theme_night.c @@ -31,11 +31,6 @@ static lv_style_t def; /*Static style definitions*/ static lv_style_t scr, bg, sb, panel; static lv_style_t prim, sec, hint; -static lv_style_t btn_rel, btn_pr, btn_tgl_rel, btn_tgl_pr, btn_ina; -static lv_style_t bar_bg, bar_indic; -static lv_style_t slider_knob; -static lv_style_t ddlist_bg, ddlist_sel; -static lv_style_t lmeter_bg; /*Saved input parameters*/ static uint16_t _hue; @@ -108,6 +103,7 @@ static void cont_init(void) static void btn_init(void) { #if LV_USE_BTN != 0 + static lv_style_t btn_rel, btn_pr, btn_tgl_rel, btn_tgl_pr, btn_ina; lv_style_copy(&btn_rel, &def); btn_rel.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 40); @@ -215,6 +211,7 @@ static void img_init(void) static void bar_init(void) { #if LV_USE_BAR + static lv_style_t bar_bg, bar_indic; lv_style_copy(&bar_bg, &panel); bar_bg.body.padding.left = LV_DPI / 16; bar_bg.body.padding.right = LV_DPI / 16; @@ -242,12 +239,12 @@ static void bar_init(void) static void slider_init(void) { #if LV_USE_SLIDER != 0 - - lv_style_copy(&slider_knob, &btn_rel); + static lv_style_t slider_knob; + lv_style_copy(&slider_knob, theme.style.btn.rel); slider_knob.body.radius = LV_RADIUS_CIRCLE; - theme.style.slider.bg = &bar_bg; - theme.style.slider.indic = &bar_indic; + theme.style.slider.bg = theme.style.bar.bg; + theme.style.slider.indic = theme.style.bar.indic; theme.style.slider.knob = &slider_knob; #endif } @@ -256,16 +253,17 @@ static void sw_init(void) { #if LV_USE_SW != 0 - theme.style.sw.bg = &bar_bg; - theme.style.sw.indic = &bar_indic; - theme.style.sw.knob_off = &slider_knob; - theme.style.sw.knob_on = &slider_knob; + theme.style.sw.bg = theme.style.bar.bg; + theme.style.sw.indic = theme.style.bar.indic; + theme.style.sw.knob_off = theme.style.slider.knob; + theme.style.sw.knob_on = theme.style.slider.knob; #endif } static void lmeter_init(void) { #if LV_USE_LMETER != 0 + static lv_style_t lmeter_bg; lv_style_copy(&lmeter_bg, &def); lmeter_bg.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 70); lmeter_bg.body.grad_color = lv_color_hsv_to_rgb(_hue, 95, 90); @@ -450,7 +448,7 @@ static void btnm_init(void) #if LV_USE_BTNM static lv_style_t btnm_bg, rel, pr, tgl_rel, tgl_pr, ina; - lv_style_copy(&btnm_bg, &btn_rel); + lv_style_copy(&btnm_bg, theme.style.btn.rel); btnm_bg.body.padding.left = 2; btnm_bg.body.padding.right = 2; btnm_bg.body.padding.top = 2; @@ -458,27 +456,27 @@ static void btnm_init(void) btnm_bg.body.padding.inner = 0; btnm_bg.body.border.width = 1; - lv_style_copy(&rel, &btn_rel); + lv_style_copy(&rel, theme.style.btn.rel); rel.body.border.part = LV_BORDER_FULL | LV_BORDER_INTERNAL; rel.body.border.width = 1; rel.body.radius = 2; - lv_style_copy(&pr, &btn_pr); + lv_style_copy(&pr, theme.style.btn.pr); pr.body.border.part = rel.body.border.part; pr.body.border.width = rel.body.border.width; pr.body.radius = rel.body.radius; - lv_style_copy(&tgl_rel, &btn_tgl_rel); + lv_style_copy(&tgl_rel, theme.style.btn.tgl_rel); tgl_rel.body.border.part = rel.body.border.part; tgl_rel.body.border.width = rel.body.border.width; tgl_rel.body.radius = rel.body.radius; - lv_style_copy(&tgl_pr, &btn_tgl_pr); + lv_style_copy(&tgl_pr, theme.style.btn.pr); tgl_pr.body.border.part = rel.body.border.part; tgl_pr.body.border.width = rel.body.border.width; tgl_pr.body.radius = rel.body.radius; - lv_style_copy(&ina, &btn_ina); + lv_style_copy(&ina, theme.style.btn.ina); ina.body.border.part = rel.body.border.part; ina.body.border.width = rel.body.border.width; ina.body.radius = rel.body.radius; @@ -496,11 +494,11 @@ static void kb_init(void) { #if LV_USE_KB theme.style.kb.bg = &bg; - theme.style.kb.btn.rel = &btn_rel; - theme.style.kb.btn.pr = &btn_pr; - theme.style.kb.btn.tgl_rel = &btn_tgl_rel; - theme.style.kb.btn.tgl_pr = &btn_tgl_pr; - theme.style.kb.btn.ina = &btn_ina; + theme.style.kb.btn.rel = theme.style.btn.rel; + theme.style.kb.btn.pr = theme.style.btn.pr; + theme.style.kb.btn.tgl_rel = theme.style.btn.tgl_rel; + theme.style.kb.btn.tgl_pr = theme.style.btn.tgl_pr; + theme.style.kb.btn.ina = theme.style.btn.ina; #endif } @@ -518,8 +516,8 @@ static void mbox_init(void) mbox_bg.body.radius = LV_DPI / 20; theme.style.mbox.bg = &mbox_bg; theme.style.mbox.btn.bg = &lv_style_transp; - theme.style.mbox.btn.rel = &btn_rel; - theme.style.mbox.btn.pr = &btn_pr; + theme.style.mbox.btn.rel = theme.style.btn.rel; + theme.style.mbox.btn.pr = theme.style.btn.pr; #endif } @@ -585,9 +583,9 @@ static void list_init(void) list_btn_rel.body.padding.left = LV_DPI / 8; list_btn_rel.body.padding.right = LV_DPI / 8; - lv_style_copy(&list_btn_pr, &btn_pr); - list_btn_pr.body.main_color = btn_pr.body.grad_color; - list_btn_pr.body.grad_color = btn_pr.body.main_color; + lv_style_copy(&list_btn_pr, theme.style.btn.pr); + list_btn_pr.body.main_color = theme.style.btn.pr->body.grad_color; + list_btn_pr.body.grad_color = theme.style.btn.pr->body.main_color; list_btn_pr.body.border.color = lv_color_hsv_to_rgb(_hue, 10, 5); list_btn_pr.body.border.width = 0; list_btn_pr.body.padding.top = LV_DPI / 6; @@ -603,8 +601,8 @@ static void list_init(void) list_btn_tgl_rel.body.grad_color = lv_color_hsv_to_rgb(_hue, 10, 8); lv_style_copy(&list_btn_tgl_pr, &list_btn_tgl_rel); - list_btn_tgl_pr.body.main_color = btn_tgl_pr.body.main_color; - list_btn_tgl_pr.body.grad_color = btn_tgl_pr.body.grad_color; + list_btn_tgl_pr.body.main_color = theme.style.btn.tgl_pr->body.main_color; + list_btn_tgl_pr.body.grad_color = theme.style.btn.tgl_pr->body.grad_color; theme.style.list.sb = &sb; theme.style.list.bg = &list_bg; @@ -620,7 +618,8 @@ static void list_init(void) static void ddlist_init(void) { #if LV_USE_DDLIST != 0 - lv_style_copy(&ddlist_bg, &btn_rel); + static lv_style_t ddlist_bg, ddlist_sel; + lv_style_copy(&ddlist_bg, theme.style.btn.rel); ddlist_bg.text.line_space = LV_DPI / 8; ddlist_bg.body.padding.top = LV_DPI / 8; ddlist_bg.body.padding.bottom = LV_DPI / 8; @@ -628,7 +627,7 @@ static void ddlist_init(void) ddlist_bg.body.padding.right = LV_DPI / 8; ddlist_bg.body.radius = LV_DPI / 30; - lv_style_copy(&ddlist_sel, &btn_rel); + lv_style_copy(&ddlist_sel, theme.style.btn.rel); ddlist_sel.body.main_color = lv_color_hsv_to_rgb(_hue, 20, 50); ddlist_sel.body.grad_color = lv_color_hsv_to_rgb(_hue, 20, 50); ddlist_sel.body.radius = 0; @@ -644,14 +643,14 @@ static void roller_init(void) #if LV_USE_ROLLER != 0 static lv_style_t roller_bg; - lv_style_copy(&roller_bg, &ddlist_bg); + lv_style_copy(&roller_bg, theme.style.ddlist.bg); roller_bg.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 20); roller_bg.body.grad_color = lv_color_hsv_to_rgb(_hue, 10, 40); roller_bg.text.color = lv_color_hsv_to_rgb(_hue, 5, 70); roller_bg.text.opa = LV_OPA_60; theme.style.roller.bg = &roller_bg; - theme.style.roller.sel = &ddlist_sel; + theme.style.roller.sel = theme.style.ddlist.sel; #endif } @@ -661,10 +660,10 @@ static void tabview_init(void) theme.style.tabview.bg = &bg; theme.style.tabview.indic = &lv_style_transp; theme.style.tabview.btn.bg = &lv_style_transp; - theme.style.tabview.btn.rel = &btn_rel; - theme.style.tabview.btn.pr = &btn_pr; - theme.style.tabview.btn.tgl_rel = &btn_tgl_rel; - theme.style.tabview.btn.tgl_pr = &btn_tgl_pr; + theme.style.tabview.btn.rel = theme.style.btn.rel; + theme.style.tabview.btn.pr = theme.style.btn.pr; + theme.style.tabview.btn.tgl_rel = theme.style.btn.tgl_rel; + theme.style.tabview.btn.tgl_pr = theme.style.btn.tgl_pr; #endif }