From 64bd9053a25297f7a442ca831c7da5b44bd33f84 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 12 Jun 2024 17:54:40 +1000 Subject: Update LVGL to v9.1.0 --- lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c | 335 ++++++++++++++++++++++ lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h | 134 +++++++++ 2 files changed, 469 insertions(+) create mode 100644 lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c create mode 100644 lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h (limited to 'lib/lvgl/src/widgets/imagebutton') diff --git a/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c b/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c new file mode 100644 index 00000000..dcecf953 --- /dev/null +++ b/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c @@ -0,0 +1,335 @@ +/** + * @file lv_imagebutton.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_imagebutton.h" + +#if LV_USE_IMAGEBUTTON != 0 + +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS (&lv_imagebutton_class) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_imagebutton_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void draw_main(lv_event_t * e); +static void lv_imagebutton_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void refr_image(lv_obj_t * imagebutton); +static lv_imagebutton_state_t suggest_state(lv_obj_t * imagebutton, lv_imagebutton_state_t state); +static lv_imagebutton_state_t get_state(const lv_obj_t * imagebutton); +static void update_src_info(lv_imagebutton_src_info_t * info, const void * src); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_imagebutton_class = { + .base_class = &lv_obj_class, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_imagebutton_t), + .constructor_cb = lv_imagebutton_constructor, + .event_cb = lv_imagebutton_event, + .name = "imagebutton", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_imagebutton_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 + *====================*/ + +void lv_imagebutton_set_src(lv_obj_t * obj, lv_imagebutton_state_t state, const void * src_left, const void * src_mid, + const void * src_right) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + update_src_info(&imagebutton->src_left[state], src_left); + update_src_info(&imagebutton->src_mid[state], src_mid); + update_src_info(&imagebutton->src_right[state], src_right); + + refr_image(obj); +} + +void lv_imagebutton_set_state(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_state_t obj_state = LV_STATE_DEFAULT; + if(state == LV_IMAGEBUTTON_STATE_PRESSED || + state == LV_IMAGEBUTTON_STATE_CHECKED_PRESSED) obj_state |= LV_STATE_PRESSED; + if(state == LV_IMAGEBUTTON_STATE_DISABLED || + state == LV_IMAGEBUTTON_STATE_CHECKED_DISABLED) obj_state |= LV_STATE_DISABLED; + if(state == LV_IMAGEBUTTON_STATE_CHECKED_DISABLED || state == LV_IMAGEBUTTON_STATE_CHECKED_PRESSED || + state == LV_IMAGEBUTTON_STATE_CHECKED_RELEASED) { + obj_state |= LV_STATE_CHECKED; + } + + lv_obj_remove_state(obj, LV_STATE_CHECKED | LV_STATE_PRESSED | LV_STATE_DISABLED); + lv_obj_add_state(obj, obj_state); + + refr_image(obj); +} + +/*===================== + * Getter functions + *====================*/ + +const void * lv_imagebutton_get_src_left(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_left[state].img_src; +} + +const void * lv_imagebutton_get_src_middle(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_mid[state].img_src; +} + +const void * lv_imagebutton_get_src_right(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_right[state].img_src; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_imagebutton_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + /*Initialize the allocated 'ext'*/ + + lv_memzero(&imagebutton->src_mid, sizeof(imagebutton->src_mid)); + lv_memzero(&imagebutton->src_left, sizeof(imagebutton->src_left)); + lv_memzero(&imagebutton->src_right, sizeof(imagebutton->src_right)); +} + +static void lv_imagebutton_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_result_t res = lv_obj_event_base(&lv_imagebutton_class, e); + if(res != LV_RESULT_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); + if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { + refr_image(obj); + } + else if(code == LV_EVENT_DRAW_MAIN) { + draw_main(e); + } + else if(code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * info = lv_event_get_param(e); + if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; + } + else if(code == LV_EVENT_GET_SELF_SIZE) { + lv_point_t * p = lv_event_get_self_size_info(e); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + if(imagebutton->src_left[state].img_src == NULL && + imagebutton->src_mid[state].img_src != NULL && + imagebutton->src_right[state].img_src == NULL) { + p->x = LV_MAX(p->x, imagebutton->src_mid[state].header.w); + } + } +} + +static void draw_main(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_current_target(e); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_layer_t * layer = lv_event_get_layer(e); + + /*Just draw_main an image*/ + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + + /*Simply draw the middle src if no tiled*/ + lv_imagebutton_src_info_t * src_info = &imagebutton->src_left[state]; + + int32_t tw = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t th = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + lv_area_increase(&coords, tw, th); + + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &img_dsc); + + lv_area_t coords_part; + int32_t left_w = 0; + int32_t right_w = 0; + + if(src_info->img_src) { + left_w = src_info->header.w; + coords_part.x1 = coords.x1; + coords_part.y1 = coords.y1; + coords_part.x2 = coords.x1 + src_info->header.w - 1; + coords_part.y2 = coords.y1 + src_info->header.h - 1; + img_dsc.src = src_info->img_src; + lv_draw_image(layer, &img_dsc, &coords_part); + } + + src_info = &imagebutton->src_right[state]; + if(src_info->img_src) { + right_w = src_info->header.w; + coords_part.x1 = coords.x2 - src_info->header.w + 1; + coords_part.y1 = coords.y1; + coords_part.x2 = coords.x2; + coords_part.y2 = coords.y1 + src_info->header.h - 1; + img_dsc.src = src_info->img_src; + lv_draw_image(layer, &img_dsc, &coords_part); + } + + src_info = &imagebutton->src_mid[state]; + if(src_info->img_src) { + coords_part.x1 = coords.x1 + left_w; + coords_part.x2 = coords.x2 - right_w; + coords_part.y1 = coords.y1; + coords_part.y2 = coords.y2; + + lv_area_t clip_area_center; + if(_lv_area_intersect(&clip_area_center, &coords_part, &layer->_clip_area)) { + lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area_center; + img_dsc.src = src_info->img_src; + img_dsc.tile = 1; + lv_draw_image(layer, &img_dsc, &coords_part); + layer->_clip_area = clip_area_ori; + } + + } +} + +static void refr_image(lv_obj_t * obj) +{ + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + + const void * src = imagebutton->src_mid[state].img_src; + if(src == NULL) return; + + lv_obj_refresh_self_size(obj); + lv_obj_set_height(obj, imagebutton->src_mid[state].header.h); /*Keep the user defined width*/ + + lv_obj_invalidate(obj); +} + +/** + * If `src` is not defined for the current state try to get a state which is related to the current but has `src`. + * E.g. if the PRESSED src is not set but the RELEASED does, use the RELEASED. + * @param imagebutton pointer to an image button + * @param state the state to convert + * @return the suggested state + */ +static lv_imagebutton_state_t suggest_state(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + if(imagebutton->src_mid[state].img_src == NULL) { + switch(state) { + case LV_IMAGEBUTTON_STATE_PRESSED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_RELEASED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_PRESSED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_CHECKED_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_PRESSED].img_src) return LV_IMAGEBUTTON_STATE_PRESSED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_DISABLED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_DISABLED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_CHECKED_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + default: + break; + } + } + + return state; +} + +static lv_imagebutton_state_t get_state(const lv_obj_t * imagebutton) +{ + LV_ASSERT_OBJ(imagebutton, MY_CLASS); + + lv_state_t obj_state = lv_obj_get_state(imagebutton); + + if(obj_state & LV_STATE_DISABLED) { + if(obj_state & LV_STATE_CHECKED) return LV_IMAGEBUTTON_STATE_CHECKED_DISABLED; + else return LV_IMAGEBUTTON_STATE_DISABLED; + } + + if(obj_state & LV_STATE_CHECKED) { + if(obj_state & LV_STATE_PRESSED) return LV_IMAGEBUTTON_STATE_CHECKED_PRESSED; + else return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + } + else { + if(obj_state & LV_STATE_PRESSED) return LV_IMAGEBUTTON_STATE_PRESSED; + else return LV_IMAGEBUTTON_STATE_RELEASED; + } +} + +static void update_src_info(lv_imagebutton_src_info_t * info, const void * src) +{ + if(!src) { + lv_memzero(info, sizeof(lv_imagebutton_src_info_t)); + return; + } + + lv_result_t res = lv_image_decoder_get_info(src, &info->header); + if(res != LV_RESULT_OK) { + LV_LOG_WARN("can't get info"); + return; + } + + info->img_src = src; +} + +#endif diff --git a/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h b/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h new file mode 100644 index 00000000..1f91eb68 --- /dev/null +++ b/lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h @@ -0,0 +1,134 @@ +/** + * @file lv_imagebutton.h + * + */ + +#ifndef LV_IMAGEBUTTON_H +#define LV_IMAGEBUTTON_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj.h" + +#if LV_USE_IMAGEBUTTON != 0 + +/********************* + * DEFINES + *********************/ +typedef enum { + LV_IMAGEBUTTON_STATE_RELEASED, + LV_IMAGEBUTTON_STATE_PRESSED, + LV_IMAGEBUTTON_STATE_DISABLED, + LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, + LV_IMAGEBUTTON_STATE_CHECKED_PRESSED, + LV_IMAGEBUTTON_STATE_CHECKED_DISABLED, + _LV_IMAGEBUTTON_STATE_NUM, +} lv_imagebutton_state_t; + +typedef struct { + const void * img_src; + lv_image_header_t header; +} lv_imagebutton_src_info_t; + +/********************** + * TYPEDEFS + **********************/ +/*Data of image button*/ +typedef struct { + lv_obj_t obj; + lv_imagebutton_src_info_t src_mid[_LV_IMAGEBUTTON_STATE_NUM]; /*Store center images to each state*/ + lv_imagebutton_src_info_t src_left[_LV_IMAGEBUTTON_STATE_NUM]; /*Store left side images to each state*/ + lv_imagebutton_src_info_t src_right[_LV_IMAGEBUTTON_STATE_NUM]; /*Store right side images to each state*/ +} lv_imagebutton_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_imagebutton_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image button object + * @param parent pointer to an object, it will be the parent of the new image button + * @return pointer to the created image button + */ +lv_obj_t * lv_imagebutton_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set images for a state of the image button + * @param imagebutton pointer to an image button object + * @param state for which state set the new image + * @param src_left pointer to an image source for the left side of the button (a C array or path to + * a file) + * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C + * array or path to a file) + * @param src_right pointer to an image source for the right side of the button (a C array or path + * to a file) + */ +void lv_imagebutton_set_src(lv_obj_t * imagebutton, lv_imagebutton_state_t state, const void * src_left, + const void * src_mid, + const void * src_right); + +/** + * Use this function instead of `lv_obj_add/remove_state` to set a state manually + * @param imagebutton pointer to an image button object + * @param state the new state + */ +void lv_imagebutton_set_state(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the left image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_left(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/** + * Get the middle image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the middle image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_middle(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/** + * Get the right image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_right(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_IMAGEBUTTON*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMAGEBUTTON_H*/ -- cgit v1.2.3