Merge branch 'master' of https://github.com/littlevgl/lvgl
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## v7.9.0
|
||||
|
||||
### New features
|
||||
- feat(chart) add lv_chart_remove_series and lv_chart_hide_series
|
||||
- feat(img_cahce) allow disabling image cacheing
|
||||
|
||||
### Bugfixes
|
||||
|
||||
## v7.8.1 (Plannad at 15.12.2020)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
@@ -240,7 +240,7 @@ typedef void * lv_fs_drv_user_data_t;
|
||||
* (I.e. no new image decoder is added)
|
||||
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
* However the opened images might consume additional RAM.
|
||||
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */
|
||||
* Set it to 0 to disable caching */
|
||||
#define LV_IMG_CACHE_DEF_SIZE 1
|
||||
|
||||
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
|
||||
|
||||
4
lvgl.h
4
lvgl.h
@@ -15,8 +15,8 @@ extern "C" {
|
||||
* CURRENT VERSION OF LVGL
|
||||
***************************/
|
||||
#define LVGL_VERSION_MAJOR 7
|
||||
#define LVGL_VERSION_MINOR 8
|
||||
#define LVGL_VERSION_PATCH 1
|
||||
#define LVGL_VERSION_MINOR 9
|
||||
#define LVGL_VERSION_PATCH 0
|
||||
#define LVGL_VERSION_INFO "dev"
|
||||
|
||||
/*********************
|
||||
|
||||
@@ -188,7 +188,7 @@ static inline lv_obj_t * lv_page_get_scrl(lv_obj_t * page)
|
||||
#if LV_USE_API_EXTENSION_V7
|
||||
|
||||
#if LV_USE_ROLLER
|
||||
#define LV_ROLLER_MODE_INIFINITE LV_ROLLER_MODE_INFINITE
|
||||
#define LV_ROLLER_MODE_INIFINITE LV_ROLLER_MODE_INFINITE
|
||||
#endif
|
||||
|
||||
#if LV_USE_WIN
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Complier prefix for a big array declaration */
|
||||
/* Compiler prefix for a big array declaration */
|
||||
#ifndef LV_MEM_ATTR
|
||||
# ifdef CONFIG_LV_MEM_ATTR
|
||||
# define LV_MEM_ATTR CONFIG_LV_MEM_ATTR
|
||||
@@ -330,7 +330,7 @@
|
||||
#endif
|
||||
|
||||
/* Long press time in milliseconds.
|
||||
* Time to send `LV_EVENT_LONG_PRESSSED`) */
|
||||
* Time to send `LV_EVENT_LONG_PRESSED`) */
|
||||
#ifndef LV_INDEV_DEF_LONG_PRESS_TIME
|
||||
# ifdef CONFIG_LV_INDEV_DEF_LONG_PRESS_TIME
|
||||
# define LV_INDEV_DEF_LONG_PRESS_TIME CONFIG_LV_INDEV_DEF_LONG_PRESS_TIME
|
||||
@@ -1322,7 +1322,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */
|
||||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
* The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#ifndef LV_USE_BIDI
|
||||
# ifdef CONFIG_LV_USE_BIDI
|
||||
|
||||
@@ -221,8 +221,9 @@ void lv_init(void)
|
||||
_lv_indev_init();
|
||||
|
||||
_lv_img_decoder_init();
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
|
||||
|
||||
#endif
|
||||
/*Test if the IDE has UTF-8 encoding*/
|
||||
char * txt = "Á";
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const
|
||||
bool chroma_key, bool alpha_byte);
|
||||
|
||||
static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg);
|
||||
static void draw_cleanup(lv_img_cache_entry_t * cache);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -267,9 +268,10 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, clip_area, &map_area_rot);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn
|
||||
successfully.*/
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, draw_dsc, chroma_keyed, alpha_byte);
|
||||
@@ -279,9 +281,10 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, clip_area, coords);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn
|
||||
successfully.*/
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
int32_t width = lv_area_get_width(&mask_com);
|
||||
@@ -306,6 +309,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
|
||||
lv_img_decoder_close(&cdsc->dec_dsc);
|
||||
LV_LOG_WARN("Image draw can't read the line");
|
||||
_lv_mem_buf_release(buf);
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
@@ -318,6 +322,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords,
|
||||
_lv_mem_buf_release(buf);
|
||||
}
|
||||
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
@@ -649,3 +654,13 @@ static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, co
|
||||
lv_draw_label(coords, clip_area, &label_dsc, msg, NULL);
|
||||
}
|
||||
|
||||
static void draw_cleanup(lv_img_cache_entry_t * cache)
|
||||
{
|
||||
/*Automatically close images with no caching*/
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(&cache->dec_dsc);
|
||||
#else
|
||||
LV_UNUSED(cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value in every open*/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
@@ -29,10 +29,6 @@
|
||||
* "die" from very high values */
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE < 1
|
||||
#error "LV_IMG_CACHE_DEF_SIZE must be >= 1. See lv_conf.h"
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -40,11 +36,16 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
static lv_img_cache_entry_t cache_temp;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -64,6 +65,10 @@ static uint16_t entry_cnt;
|
||||
*/
|
||||
lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
|
||||
return NULL;
|
||||
@@ -79,8 +84,6 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
|
||||
}
|
||||
}
|
||||
|
||||
/*Is the image cached?*/
|
||||
lv_img_cache_entry_t * cached_src = NULL;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
bool match = false;
|
||||
lv_img_src_t src_type = lv_img_src_get_type(cache[i].dec_dsc.src);
|
||||
@@ -104,48 +107,51 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
if(cached_src == NULL) {
|
||||
/*Find an entry to reuse. Select the entry with the least life*/
|
||||
cached_src = &cache[0];
|
||||
for(i = 1; i < entry_cnt; i++) {
|
||||
if(cache[i].life < cached_src->life) {
|
||||
cached_src = &cache[i];
|
||||
}
|
||||
}
|
||||
if(cached_src) return cached_src;
|
||||
|
||||
/*Close the decoder to reuse if it was opened (has a valid source)*/
|
||||
if(cached_src->dec_dsc.src) {
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
|
||||
/*Find an entry to reuse. Select the entry with the least life*/
|
||||
cached_src = &cache[0];
|
||||
for(i = 1; i < entry_cnt; i++) {
|
||||
if(cache[i].life < cached_src->life) {
|
||||
cached_src = &cache[i];
|
||||
}
|
||||
else {
|
||||
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
|
||||
}
|
||||
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start;
|
||||
t_start = lv_tick_get();
|
||||
cached_src->dec_dsc.time_to_open = 0;
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
_lv_memset_00(&cached_src->dec_dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
_lv_memset_00(cached_src, sizeof(lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cached_src->life = 0;
|
||||
|
||||
/*If `time_to_open` was not set in the open function set it here*/
|
||||
if(cached_src->dec_dsc.time_to_open == 0) {
|
||||
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
|
||||
}
|
||||
|
||||
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
|
||||
}
|
||||
|
||||
/*Close the decoder to reuse if it was opened (has a valid source)*/
|
||||
if(cached_src->dec_dsc.src) {
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
|
||||
}
|
||||
else {
|
||||
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
|
||||
}
|
||||
|
||||
#else
|
||||
cached_src = &cache_temp;
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start;
|
||||
t_start = lv_tick_get();
|
||||
cached_src->dec_dsc.time_to_open = 0;
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
_lv_memset_00(&cached_src->dec_dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
_lv_memset_00(cached_src, sizeof(lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cached_src->life = 0;
|
||||
|
||||
/*If `time_to_open` was not set in the open function set it here*/
|
||||
if(cached_src->dec_dsc.time_to_open == 0) {
|
||||
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
|
||||
}
|
||||
|
||||
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
|
||||
|
||||
return cached_src;
|
||||
}
|
||||
|
||||
@@ -157,6 +163,10 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color)
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
{
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
LV_UNUSED(new_entry_cnt);
|
||||
LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0");
|
||||
#else
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
@@ -178,6 +188,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
_lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i].dec_dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
_lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i], sizeof(lv_img_cache_entry_t));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +198,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src)
|
||||
{
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
@@ -201,6 +212,7 @@ void lv_img_cache_invalidate_src(const void * src)
|
||||
_lv_memset_00(&cache[i], sizeof(lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
||||
@@ -195,6 +195,7 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
|
||||
ser->start_point = 0;
|
||||
ser->ext_buf_assigned = false;
|
||||
ser->hidden = 0;
|
||||
ser->y_axis = LV_CHART_AXIS_PRIMARY_Y;
|
||||
|
||||
uint16_t i;
|
||||
@@ -207,6 +208,33 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
return ser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate and remove a data series from a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param series pointer to a data series on 'chart'
|
||||
*/
|
||||
void lv_chart_remove_series(lv_obj_t * chart, lv_chart_series_t * series)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(series);
|
||||
|
||||
if(chart == NULL || series == NULL) return;
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(!series->ext_buf_assigned && series->points) lv_mem_free(series->points);
|
||||
|
||||
_lv_ll_remove(&ext->series_ll, series);
|
||||
lv_mem_free(series);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cursor with a given color
|
||||
* @param chart pointer to chart object
|
||||
* @param color color of the cursor
|
||||
* @param dir direction of the cursor. `LV_CHART_CURSOR_RIGHT/LEFT/TOP/DOWN`. OR-ed values are possible
|
||||
* @return pointer to the created cursor
|
||||
*/
|
||||
lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * chart, lv_color_t color, lv_cursor_direction_t axes)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
@@ -246,6 +274,22 @@ void lv_chart_clear_series(lv_obj_t * chart, lv_chart_series_t * series)
|
||||
series->start_point = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide/Unhide a single series of a chart.
|
||||
* @param chart pointer to a chart object.
|
||||
* @param series pointer to a series object
|
||||
* @param hide true: hide the series
|
||||
*/
|
||||
void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(series);
|
||||
|
||||
series->hidden = hide ? 1 : 0;
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
@@ -666,6 +710,7 @@ void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -1135,6 +1180,7 @@ static void draw_series_line(lv_obj_t * chart, const lv_area_t * series_area, co
|
||||
|
||||
/*Go through all data lines*/
|
||||
_LV_LL_READ_BACK(ext->series_ll, ser) {
|
||||
if (ser->hidden) continue;
|
||||
line_dsc.color = ser->color;
|
||||
point_dsc.bg_color = ser->color;
|
||||
area_dsc.bg_color = ser->color;
|
||||
@@ -1271,6 +1317,7 @@ static void draw_series_column(lv_obj_t * chart, const lv_area_t * series_area,
|
||||
|
||||
/*Draw the current point of all data line*/
|
||||
_LV_LL_READ_BACK(ext->series_ll, ser) {
|
||||
if (ser->hidden) continue;
|
||||
lv_coord_t start_point = ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0;
|
||||
|
||||
col_a.x1 = x_act;
|
||||
|
||||
@@ -74,6 +74,7 @@ typedef struct {
|
||||
lv_color_t color;
|
||||
uint16_t start_point;
|
||||
uint8_t ext_buf_assigned : 1;
|
||||
uint8_t hidden : 1;
|
||||
lv_chart_axis_t y_axis : 1;
|
||||
} lv_chart_series_t;
|
||||
|
||||
@@ -153,6 +154,13 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
*/
|
||||
lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Deallocate and remove a data series from a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param series pointer to a data series on 'chart'
|
||||
*/
|
||||
void lv_chart_remove_series(lv_obj_t * chart, lv_chart_series_t * series);
|
||||
|
||||
/**
|
||||
* Add a cursor with a given color
|
||||
* @param chart pointer to chart object
|
||||
@@ -169,6 +177,15 @@ lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * chart, lv_color_t color, lv_c
|
||||
*/
|
||||
void lv_chart_clear_series(lv_obj_t * chart, lv_chart_series_t * series);
|
||||
|
||||
/**
|
||||
* Hide/Unhide a single series of a chart.
|
||||
* @param chart pointer to a chart object.
|
||||
* @param series pointer to a series object
|
||||
* @param hide true: hide the series
|
||||
*/
|
||||
void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide);
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
@@ -356,7 +356,7 @@ void lv_dropdown_set_selected(lv_obj_t * ddlist, uint16_t sel_opt)
|
||||
|
||||
ext->sel_opt_id = sel_opt < ext->option_cnt ? sel_opt : ext->option_cnt - 1;
|
||||
ext->sel_opt_id_orig = ext->sel_opt_id;
|
||||
|
||||
|
||||
lv_obj_invalidate(ddlist);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_btnmatrix_set_map(ext->btns, ext->tab_name_ptr);
|
||||
|
||||
lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_BG_SCROLLABLE), lv_obj_get_style_list(copy,
|
||||
LV_TABVIEW_PART_BG_SCROLLABLE));
|
||||
LV_TABVIEW_PART_BG_SCROLLABLE));
|
||||
lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_TAB_BG), lv_obj_get_style_list(copy,
|
||||
LV_TABVIEW_PART_TAB_BG));
|
||||
lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_TAB_BTN), lv_obj_get_style_list(copy,
|
||||
@@ -616,7 +616,7 @@ static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * p
|
||||
else if(info->part == LV_TABVIEW_PART_TAB_BTN) info->result = lv_obj_get_state(ext->btns, LV_BTNMATRIX_PART_BTN);
|
||||
else if(info->part == LV_TABVIEW_PART_INDIC) info->result = lv_obj_get_state(ext->indic, LV_OBJ_PART_MAIN);
|
||||
else if(info->part == LV_TABVIEW_PART_BG_SCROLLABLE) info->result = lv_obj_get_state(ext->content,
|
||||
LV_PAGE_PART_SCROLLABLE);
|
||||
LV_PAGE_PART_SCROLLABLE);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->page = NULL;
|
||||
ext->header = NULL;
|
||||
ext->title_txt = lv_mem_alloc(strlen(DEF_TITLE) + 1);
|
||||
ext->title_txt_align = LV_TXT_FLAG_NONE;
|
||||
strcpy(ext->title_txt, DEF_TITLE);
|
||||
|
||||
/*Init the new window object*/
|
||||
@@ -363,6 +364,14 @@ void lv_win_set_drag(lv_obj_t * win, bool en)
|
||||
lv_obj_set_drag(win, en);
|
||||
}
|
||||
|
||||
void lv_win_title_set_alignment(lv_obj_t * win, uint8_t alignment)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
ext->title_txt_align = alignment;
|
||||
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -491,6 +500,14 @@ lv_coord_t lv_win_get_width(lv_obj_t * win)
|
||||
return lv_obj_get_width_fit(scrl) - left - right;
|
||||
}
|
||||
|
||||
uint8_t lv_win_title_get_alignment(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
return ext->title_txt_align;
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
@@ -538,11 +555,13 @@ static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t *
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_style_int_t header_left = lv_obj_get_style_pad_left(win, LV_WIN_PART_HEADER);
|
||||
lv_style_int_t header_right = lv_obj_get_style_pad_right(win, LV_WIN_PART_HEADER);
|
||||
lv_style_int_t header_inner = lv_obj_get_style_pad_inner(win, LV_WIN_PART_HEADER);
|
||||
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_obj_init_draw_label_dsc(header, LV_OBJ_PART_MAIN, &label_dsc);
|
||||
label_dsc.flag = ext->title_txt_align;
|
||||
|
||||
lv_area_t txt_area;
|
||||
lv_point_t txt_size;
|
||||
@@ -557,21 +576,41 @@ static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t *
|
||||
|
||||
/*Get x position of the title (should be on the right of the buttons on the left)*/
|
||||
|
||||
lv_coord_t left_btn_offset = 0;
|
||||
lv_coord_t btn_offset = 0;
|
||||
btn = lv_obj_get_child_back(ext->header, NULL);
|
||||
while(btn != NULL) {
|
||||
if(LV_WIN_BTN_ALIGN_LEFT == lv_win_btn_get_alignment(btn)) {
|
||||
left_btn_offset += btn_w + header_inner;
|
||||
btn_offset += btn_w + header_inner;
|
||||
}
|
||||
|
||||
btn = lv_obj_get_child_back(header, btn);
|
||||
}
|
||||
|
||||
txt_area.x1 = header->coords.x1 + header_left + left_btn_offset;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.x2 = txt_area.x1 + txt_size.x + left_btn_offset;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
|
||||
switch(label_dsc.flag) {
|
||||
case LV_TXT_FLAG_CENTER:
|
||||
txt_area.x1 = header->coords.x1 + header_left + btn_offset;
|
||||
txt_area.x2 = header->coords.x2 - header_right - btn_offset;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
break;
|
||||
case LV_TXT_FLAG_RIGHT:
|
||||
txt_area.x1 = header->coords.x1;
|
||||
txt_area.x2 = header->coords.x2 - header_right - btn_offset;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
break;
|
||||
case LV_TXT_FLAG_FIT || LV_TXT_FLAG_EXPAND:
|
||||
txt_area.x1 = header->coords.x1;
|
||||
txt_area.x2 = header->coords.x2;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
break;
|
||||
default:
|
||||
txt_area.x1 = header->coords.x1 + header_left + btn_offset;
|
||||
txt_area.x2 = txt_area.x1 + txt_size.x + btn_offset;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
break;
|
||||
}
|
||||
lv_draw_label(&txt_area, clip_area, &label_dsc, ext->title_txt, NULL);
|
||||
}
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct {
|
||||
lv_obj_t * header; /*Pointer to the header container of the window*/
|
||||
char * title_txt; /*Pointer to the title label of the window*/
|
||||
lv_coord_t btn_w; /*Width of the control buttons*/
|
||||
uint8_t title_txt_align; /*Control the alignment of the header text*/
|
||||
} lv_win_ext_t;
|
||||
|
||||
/** Window parts. */
|
||||
@@ -175,6 +176,13 @@ void lv_win_set_anim_time(lv_obj_t * win, uint16_t anim_time);
|
||||
*/
|
||||
void lv_win_set_drag(lv_obj_t * win, bool en);
|
||||
|
||||
/**
|
||||
* Set alignment of title text in window header.
|
||||
* @param win pointer to a window object
|
||||
* @param alignment set the type of alignment with LV_TXT_FLAGS
|
||||
*/
|
||||
void lv_win_title_set_alignment(lv_obj_t * win, uint8_t alignment);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -254,6 +262,12 @@ static inline bool lv_win_get_drag(const lv_obj_t * win)
|
||||
return lv_obj_get_drag(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current alignment of title text in window header.
|
||||
* @param win pointer to a window object
|
||||
*/
|
||||
uint8_t lv_win_title_get_alignment(lv_obj_t * win);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
Reference in New Issue
Block a user