hekate/bdk/libs/lvgl/lv_objx/lv_imgbtn.c
CTCaer 185526d134 Introducing Bootloader Development Kit (BDK)
BDK will allow developers to use the full collection of drivers,
with limited editing, if any, for making payloads for Nintendo Switch.

Using a single source for everything will also help decoupling
Switch specific code and easily port it to other Tegra X1/X1+ platforms.
And maybe even to lower targets.

Everything is now centrilized into bdk folder.
Every module or project can utilize it by simply including it.

This is just the start and it will continue to improve.
2020-06-14 15:25:21 +03:00

392 lines
12 KiB
C

/**
* @file lv_imgbtn.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_imgbtn.h"
#if USE_LV_IMGBTN != 0
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_design_mode_t mode);
static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param);
static void refr_img(lv_obj_t * imgbtn);
/**********************
* STATIC VARIABLES
**********************/
static lv_signal_func_t ancestor_signal;
static lv_design_func_t ancestor_design;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create a image button object
* @param par pointer to an object, it will be the parent of the new image button
* @param copy pointer to a image button object, if not NULL then the new object will be copied from it
* @return pointer to the created image button
*/
lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
{
LV_LOG_TRACE("image button create started");
/*Create the ancestor of image button*/
lv_obj_t * new_imgbtn = lv_btn_create(par, copy);
lv_mem_assert(new_imgbtn);
if(new_imgbtn == NULL) return NULL;
/*Allocate the image button type specific extended data*/
lv_imgbtn_ext_t * ext = lv_obj_allocate_ext_attr(new_imgbtn, sizeof(lv_imgbtn_ext_t));
lv_mem_assert(ext);
if(ext == NULL) return NULL;
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_imgbtn);
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_imgbtn);
/*Initialize the allocated 'ext' */
#if LV_IMGBTN_TILED == 0
memset(ext->img_src, 0, sizeof(ext->img_src));
#else
memset(ext->img_src_left, 0, sizeof(ext->img_src_left));
memset(ext->img_src_mid, 0, sizeof(ext->img_src_mid));
memset(ext->img_src_right, 0, sizeof(ext->img_src_right));
#endif
ext->act_cf = LV_IMG_CF_UNKOWN;
/*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_func(new_imgbtn, lv_imgbtn_signal);
lv_obj_set_design_func(new_imgbtn, lv_imgbtn_design);
/*Init the new image button image button*/
if(copy == NULL) {
}
/*Copy an existing image button*/
else {
lv_imgbtn_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
#if LV_IMGBTN_TILED == 0
memcpy(ext->img_src, copy_ext->img_src, sizeof(ext->img_src));
#else
memcpy(ext->img_src_left, copy_ext->img_src_left, sizeof(ext->img_src_left));
memcpy(ext->img_src_mid, copy_ext->img_src_mid, sizeof(ext->img_src_mid));
memcpy(ext->img_src_right, copy_ext->img_src_right, sizeof(ext->img_src_right));
#endif
/*Refresh the style with new signal function*/
lv_obj_refresh_style(new_imgbtn);
}
LV_LOG_INFO("image button created");
return new_imgbtn;
}
/*=====================
* Setter functions
*====================*/
#if LV_IMGBTN_TILED == 0
/**
* Set images for a state of the image button
* @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) `
* @param src pointer to an image source (a C array or path to a file)
*/
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
ext->img_src[state] = src;
refr_img(imgbtn);
}
#else
/**
* Set images for a state of the image button
* @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) `
* @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_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid, const void * src_right)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
ext->img_src_left[state] = src_left;
ext->img_src_mid[state] = src_mid;
ext->img_src_right[state] = src_right;
refr_img(imgbtn);
}
#endif
/**
* Set a style of a image button.
* @param imgbtn pointer to image button object
* @param type which style should be set
* @param style pointer to a style
*/
void lv_imgbtn_set_style(lv_obj_t * imgbtn, lv_imgbtn_style_t type, lv_style_t * style)
{
lv_btn_set_style(imgbtn, type, style);
}
/*=====================
* Getter functions
*====================*/
#if LV_IMGBTN_TILED == 0
/**
* Get the images in a given state
* @param imgbtn pointer to an image button object
* @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to an image source (a C array or path to a file)
*/
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
return ext->img_src[state];
}
#else
/**
* Get the left image in a given state
* @param imgbtn pointer to an image button object
* @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file)
*/
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
return ext->img_src_left[state];
}
/**
* Get the middle image in a given state
* @param imgbtn pointer to an image button object
* @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the middle image source (a C array or path to a file)
*/
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
return ext->img_src_mid[state];
}
/**
* Get the right image in a given state
* @param imgbtn pointer to an image button object
* @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file)
*/
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
return ext->img_src_right[state];
}
#endif
/**
* Get style of a image button.
* @param imgbtn pointer to image button object
* @param type which style should be get
* @return style pointer to the style
*/
lv_style_t * lv_imgbtn_get_style(const lv_obj_t * imgbtn, lv_imgbtn_style_t type)
{
return lv_btn_get_style(imgbtn, type);
}
/*=====================
* Other functions
*====================*/
/*
* New object specific "other" functions come here
*/
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the image buttons
* @param imgbtn pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
* @param return true/false, depends on 'mode'
*/
static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_design_mode_t mode)
{
/*Return false if the object is not covers the mask_p area*/
if(mode == LV_DESIGN_COVER_CHK) {
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
bool cover = false;
if(ext->act_cf == LV_IMG_CF_TRUE_COLOR || ext->act_cf == LV_IMG_CF_RAW) {
cover = lv_area_is_in(mask, &imgbtn->coords);
}
return cover;
}
/*Draw the object*/
else if(mode == LV_DESIGN_DRAW_MAIN) {
/*Just draw an image*/
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn);
lv_style_t * style = lv_imgbtn_get_style(imgbtn, state);
lv_opa_t opa_scale = lv_obj_get_opa_scale(imgbtn);
#if LV_IMGBTN_TILED == 0
const void * src = ext->img_src[state];
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
#else
const void * src;
lv_img_header_t header;
lv_area_t coords;
lv_coord_t left_w = 0;
lv_coord_t right_w = 0;
src = ext->img_src_left[state];
if(src) {
lv_img_dsc_get_info(src, &header);
left_w = header.w;
coords.x1 = imgbtn->coords.x1;
coords.y1 = imgbtn->coords.y1;
coords.x2 = coords.x1 + header.w - 1;
coords.y2 = coords.y1 + header.h - 1;
lv_draw_img(&coords, mask, src, style, opa_scale);
}
src = ext->img_src_right[state];
if(src) {
lv_img_dsc_get_info(src, &header);
right_w = header.w;
coords.x1 = imgbtn->coords.x2 - header.w + 1;
coords.y1 = imgbtn->coords.y1;
coords.x2 = imgbtn->coords.x2;
coords.y2 = imgbtn->coords.y1 + header.h - 1;
lv_draw_img(&coords, mask, src, style, opa_scale);
}
src = ext->img_src_mid[state];
if(src) {
lv_coord_t obj_w = lv_obj_get_width(imgbtn);
lv_coord_t i;
lv_img_dsc_get_info(src, &header);
coords.x1 = imgbtn->coords.x1 + left_w ;
coords.y1 = imgbtn->coords.y1;
coords.x2 = coords.x1 + header.w - 1;
coords.y2 = imgbtn->coords.y1 + header.h - 1;
for(i = 0; i < obj_w - right_w - left_w; i += header.w) {
lv_draw_img(&coords, mask, src, style, opa_scale);
coords.x1 = coords.x2 + 1;
coords.x2 += header.w;
}
}
#endif
}
/*Post draw when the children are drawn*/
else if(mode == LV_DESIGN_DRAW_POST) {
}
return true;
}
/**
* Signal function of the image button
* @param imgbtn pointer to a image button object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
*/
static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param)
{
lv_res_t res;
/* Include the ancient signal function */
res = ancestor_signal(imgbtn, sign, param);
if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_STYLE_CHG) {
/* If the style changed then the button was clicked, released etc. so probably the state was changed as well
* Set the new image for the new state.*/
refr_img(imgbtn);
} else if(sign == LV_SIGNAL_CLEANUP) {
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
} else if(sign == LV_SIGNAL_GET_TYPE) {
lv_obj_type_t * buf = param;
uint8_t i;
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
if(buf->type[i] == NULL) break;
}
buf->type[i] = "lv_imgbtn";
}
return res;
}
static void refr_img(lv_obj_t * imgbtn)
{
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn);
lv_img_header_t header;
#if LV_IMGBTN_TILED == 0
const void * src = ext->img_src[state];
#else
const void * src = ext->img_src_mid[state];
#endif
lv_res_t info_res;
info_res = lv_img_dsc_get_info(src, &header);
if(info_res == LV_RES_OK) {
ext->act_cf = header.cf;
#if LV_IMGBTN_TILED == 0
lv_obj_set_size(imgbtn, header.w, header.h);
#else
lv_obj_set_height(imgbtn, header.h);
#endif
} else {
ext->act_cf = LV_IMG_CF_UNKOWN;
}
lv_obj_invalidate(imgbtn);
}
#endif