summaryrefslogtreecommitdiff
path: root/lib/lvgl/src/widgets/imagebutton
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
committerjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
commit64bd9053a25297f7a442ca831c7da5b44bd33f84 (patch)
treea90c6cad25a12028302ab1a5334510fba0229bae /lib/lvgl/src/widgets/imagebutton
parent611176ed667c4ed7ee9f609e958f9404f4aee91d (diff)
downloadtangara-fw-64bd9053a25297f7a442ca831c7da5b44bd33f84.tar.gz
Update LVGL to v9.1.0
Diffstat (limited to 'lib/lvgl/src/widgets/imagebutton')
-rw-r--r--lib/lvgl/src/widgets/imagebutton/lv_imagebutton.c335
-rw-r--r--lib/lvgl/src/widgets/imagebutton/lv_imagebutton.h134
2 files changed, 469 insertions, 0 deletions
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*/