2016-06-08 07:25:08 +02:00
|
|
|
/**
|
2020-02-14 17:03:25 +01:00
|
|
|
* @file lv_label.c
|
2018-06-19 09:49:58 +02:00
|
|
|
*
|
2016-06-08 07:25:08 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
* INCLUDES
|
|
|
|
*********************/
|
2018-07-07 11:53:22 +02:00
|
|
|
#include "lv_label.h"
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_LABEL != 0
|
2016-06-08 07:25:08 +02:00
|
|
|
|
2017-11-30 11:35:33 +01:00
|
|
|
#include "../lv_core/lv_obj.h"
|
2019-09-24 16:30:38 +02:00
|
|
|
#include "../lv_core/lv_debug.h"
|
2017-11-30 11:35:33 +01:00
|
|
|
#include "../lv_core/lv_group.h"
|
2019-11-15 07:28:42 +01:00
|
|
|
#include "../lv_draw/lv_draw.h"
|
2017-11-23 20:42:14 +01:00
|
|
|
#include "../lv_misc/lv_color.h"
|
|
|
|
#include "../lv_misc/lv_math.h"
|
2019-10-08 16:26:55 +02:00
|
|
|
#include "../lv_misc/lv_bidi.h"
|
2019-08-06 09:28:50 -04:00
|
|
|
#include "../lv_misc/lv_printf.h"
|
2020-02-14 17:03:25 +01:00
|
|
|
#include "../lv_themes/lv_theme.h"
|
2016-06-08 07:25:08 +02:00
|
|
|
|
|
|
|
/*********************
|
|
|
|
* DEFINES
|
|
|
|
*********************/
|
2019-09-24 23:14:17 +02:00
|
|
|
#define LV_OBJX_NAME "lv_label"
|
2019-09-24 16:30:38 +02:00
|
|
|
|
2017-01-12 09:49:13 +01:00
|
|
|
/*Test configurations*/
|
2019-04-04 16:44:16 +02:00
|
|
|
#ifndef LV_LABEL_DEF_SCROLL_SPEED
|
|
|
|
#define LV_LABEL_DEF_SCROLL_SPEED (25)
|
2017-01-12 09:49:13 +01:00
|
|
|
#endif
|
|
|
|
|
2016-10-16 21:43:28 +02:00
|
|
|
#define LV_LABEL_DOT_END_INV 0xFFFF
|
2019-06-27 07:16:15 +02:00
|
|
|
#define LV_LABEL_HINT_HEIGHT_LIMIT \
|
|
|
|
1024 /*Enable "hint" to buffer info about labels larger than this. (Speed up their drawing)*/
|
2016-06-08 07:25:08 +02:00
|
|
|
|
|
|
|
/**********************
|
|
|
|
* TYPEDEFS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC PROTOTYPES
|
|
|
|
**********************/
|
2017-11-13 16:11:05 +01:00
|
|
|
static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param);
|
2019-09-06 19:53:39 +02:00
|
|
|
static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_area, lv_design_mode_t mode);
|
2016-12-30 21:42:59 +01:00
|
|
|
static void lv_label_refr_text(lv_obj_t * label);
|
2018-06-19 09:49:58 +02:00
|
|
|
static void lv_label_revert_dots(lv_obj_t * label);
|
2017-11-27 17:48:54 +01:00
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_ANIMATION
|
2017-11-23 21:28:36 +01:00
|
|
|
static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x);
|
|
|
|
static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y);
|
2017-11-27 17:48:54 +01:00
|
|
|
#endif
|
2019-04-14 11:18:31 -07:00
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
static bool lv_label_set_dot_tmp(lv_obj_t * label, char * data, uint16_t len);
|
|
|
|
static char * lv_label_get_dot_tmp(lv_obj_t * label);
|
|
|
|
static void lv_label_dot_tmp_free(lv_obj_t * label);
|
2020-02-11 05:47:33 +01:00
|
|
|
static void get_txt_coords(const lv_obj_t * label, lv_area_t * area);
|
2019-04-14 11:18:31 -07:00
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/**********************
|
|
|
|
* STATIC VARIABLES
|
|
|
|
**********************/
|
2019-02-26 09:25:46 +01:00
|
|
|
static lv_signal_cb_t ancestor_signal;
|
2017-11-13 16:11:05 +01:00
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/**********************
|
|
|
|
* MACROS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* GLOBAL FUNCTIONS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a label objects
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param par pointer to an object, it will be the parent of the new label
|
|
|
|
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
2016-06-08 07:25:08 +02:00
|
|
|
* @return pointer to the created button
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
2016-06-08 07:25:08 +02:00
|
|
|
{
|
2018-10-05 17:22:49 +02:00
|
|
|
LV_LOG_TRACE("label create started");
|
2018-07-25 17:57:08 +02:00
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/*Create a basic object*/
|
2016-10-07 11:15:46 +02:00
|
|
|
lv_obj_t * new_label = lv_obj_create(par, copy);
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(new_label);
|
2018-07-25 13:33:53 +02:00
|
|
|
if(new_label == NULL) return NULL;
|
|
|
|
|
2019-04-10 06:40:49 +02:00
|
|
|
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_label);
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/*Extend the basic object to a label object*/
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_allocate_ext_attr(new_label, sizeof(lv_label_ext_t));
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(new_label);
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext);
|
2019-12-03 18:16:14 +01:00
|
|
|
if(ext == NULL) {
|
|
|
|
lv_obj_del(new_label);
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-07-25 13:33:53 +02:00
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->text = NULL;
|
|
|
|
ext->static_txt = 0;
|
|
|
|
ext->recolor = 0;
|
2019-10-08 16:26:55 +02:00
|
|
|
ext->align = LV_LABEL_ALIGN_AUTO;
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot_end = LV_LABEL_DOT_END_INV;
|
|
|
|
ext->long_mode = LV_LABEL_LONG_EXPAND;
|
2019-05-20 09:22:09 -07:00
|
|
|
#if LV_USE_ANIMATION
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->anim_speed = LV_LABEL_DEF_SCROLL_SPEED;
|
2019-05-20 09:22:09 -07:00
|
|
|
#endif
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->offset.x = 0;
|
|
|
|
ext->offset.y = 0;
|
2019-06-14 16:04:15 +02:00
|
|
|
|
2019-07-29 16:00:59 +02:00
|
|
|
#if LV_LABEL_LONG_TXT_HINT
|
2019-06-14 16:04:15 +02:00
|
|
|
ext->hint.line_start = -1;
|
2019-06-27 07:16:15 +02:00
|
|
|
ext->hint.coord_y = 0;
|
|
|
|
ext->hint.y = 0;
|
2019-07-29 16:00:59 +02:00
|
|
|
#endif
|
2019-06-14 16:04:15 +02:00
|
|
|
|
2019-04-18 07:11:43 +02:00
|
|
|
#if LV_LABEL_TEXT_SEL
|
2019-12-19 22:44:18 +01:00
|
|
|
ext->sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
|
|
|
|
ext->sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
|
2019-04-14 09:47:45 -07:00
|
|
|
#endif
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot.tmp_ptr = NULL;
|
2019-04-14 11:18:31 -07:00
|
|
|
ext->dot_tmp_alloc = 0;
|
2019-03-27 16:39:37 -04:00
|
|
|
|
2020-01-05 01:16:13 +01:00
|
|
|
|
2019-02-26 09:25:46 +01:00
|
|
|
lv_obj_set_design_cb(new_label, lv_label_design);
|
|
|
|
lv_obj_set_signal_cb(new_label, lv_label_signal);
|
2016-06-08 07:25:08 +02:00
|
|
|
|
|
|
|
/*Init the new label*/
|
2016-10-07 11:15:46 +02:00
|
|
|
if(copy == NULL) {
|
2020-02-14 17:03:25 +01:00
|
|
|
lv_theme_apply(new_label, LV_THEME_LABEL);
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_obj_set_click(new_label, false);
|
|
|
|
lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND);
|
|
|
|
lv_label_set_text(new_label, "Text");
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
2016-10-07 11:15:46 +02:00
|
|
|
/*Copy 'copy' if not NULL*/
|
2016-06-08 07:25:08 +02:00
|
|
|
else {
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
2017-01-02 14:10:32 +01:00
|
|
|
lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy));
|
2017-02-01 11:39:48 +01:00
|
|
|
lv_label_set_recolor(new_label, lv_label_get_recolor(copy));
|
2017-11-06 16:27:00 +01:00
|
|
|
lv_label_set_align(new_label, lv_label_get_align(copy));
|
2019-04-04 07:15:40 +02:00
|
|
|
if(copy_ext->static_txt == 0)
|
|
|
|
lv_label_set_text(new_label, lv_label_get_text(copy));
|
|
|
|
else
|
|
|
|
lv_label_set_static_text(new_label, lv_label_get_text(copy));
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
/*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/
|
|
|
|
if(copy_ext->long_mode == LV_LABEL_LONG_DOT) {
|
2017-11-24 17:48:47 +01:00
|
|
|
ext->text = lv_mem_realloc(ext->text, lv_mem_get_size(copy_ext->text));
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2018-07-25 14:43:46 +02:00
|
|
|
if(ext->text == NULL) return NULL;
|
2017-11-24 17:48:47 +01:00
|
|
|
memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text));
|
2017-11-13 16:11:05 +01:00
|
|
|
}
|
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
if(copy_ext->dot_tmp_alloc && copy_ext->dot.tmp_ptr) {
|
2019-12-02 12:20:01 +01:00
|
|
|
uint16_t len = (uint16_t )strlen(copy_ext->dot.tmp_ptr);
|
2019-04-20 09:05:36 -04:00
|
|
|
lv_label_set_dot_tmp(new_label, ext->dot.tmp_ptr, len);
|
2019-06-06 06:05:40 +02:00
|
|
|
} else {
|
2019-04-20 09:05:36 -04:00
|
|
|
memcpy(ext->dot.tmp, copy_ext->dot.tmp, sizeof(ext->dot.tmp));
|
2019-04-14 11:18:31 -07:00
|
|
|
}
|
2019-04-14 14:49:42 -07:00
|
|
|
ext->dot_tmp_alloc = copy_ext->dot_tmp_alloc;
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot_end = copy_ext->dot_end;
|
2017-01-02 14:10:32 +01:00
|
|
|
|
2017-01-08 13:06:41 +01:00
|
|
|
/*Refresh the style with new signal function*/
|
2020-02-12 08:54:03 +01:00
|
|
|
lv_obj_refresh_style(new_label);
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
2018-07-25 17:57:08 +02:00
|
|
|
|
2018-10-05 17:22:49 +02:00
|
|
|
LV_LOG_INFO("label created");
|
2018-07-25 17:57:08 +02:00
|
|
|
|
2016-10-07 11:15:46 +02:00
|
|
|
return new_label;
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=====================
|
2018-06-19 09:49:58 +02:00
|
|
|
* Setter functions
|
2016-06-08 07:25:08 +02:00
|
|
|
*====================*/
|
|
|
|
|
|
|
|
/**
|
2016-12-30 21:42:59 +01:00
|
|
|
* Set a new text for a label. Memory will be allocated to store the text by the label.
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2016-12-30 21:42:59 +01:00
|
|
|
* @param text '\0' terminated character string. NULL to refresh with the current text.
|
2016-06-08 07:25:08 +02:00
|
|
|
*/
|
2016-10-07 11:15:46 +02:00
|
|
|
void lv_label_set_text(lv_obj_t * label, const char * text)
|
2016-06-08 07:25:08 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
2019-09-24 16:30:38 +02:00
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_invalidate(label);
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2016-06-08 07:25:08 +02:00
|
|
|
|
2017-10-05 11:29:21 +02:00
|
|
|
/*If text is NULL then refresh */
|
|
|
|
if(text == NULL) {
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_label_refr_text(label);
|
|
|
|
return;
|
|
|
|
}
|
2016-10-04 09:45:39 +02:00
|
|
|
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_STR(text);
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->text == text) {
|
2017-10-05 11:29:21 +02:00
|
|
|
/*If set its own text then reallocate it (maybe its size changed)*/
|
2017-11-23 21:28:36 +01:00
|
|
|
ext->text = lv_mem_realloc(ext->text, strlen(ext->text) + 1);
|
2020-01-10 18:16:20 +01:00
|
|
|
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2018-07-25 14:43:46 +02:00
|
|
|
if(ext->text == NULL) return;
|
2017-10-05 11:29:21 +02:00
|
|
|
} else {
|
|
|
|
/*Allocate space for the new text*/
|
2019-12-02 12:20:01 +01:00
|
|
|
size_t len = strlen(text) + 1;
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->text != NULL && ext->static_txt == 0) {
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_mem_free(ext->text);
|
2017-11-13 16:11:05 +01:00
|
|
|
ext->text = NULL;
|
2017-10-05 11:29:21 +02:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:28:36 +01:00
|
|
|
ext->text = lv_mem_alloc(len);
|
2020-01-10 18:16:20 +01:00
|
|
|
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2018-07-25 13:33:53 +02:00
|
|
|
if(ext->text == NULL) return;
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
strcpy(ext->text, text);
|
2019-10-18 02:13:41 +03:00
|
|
|
|
2019-10-08 16:26:55 +02:00
|
|
|
/*Now the text is dynamically allocated*/
|
|
|
|
ext->static_txt = 0;
|
2016-10-16 21:43:28 +02:00
|
|
|
}
|
2017-10-05 11:29:21 +02:00
|
|
|
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
2019-01-16 09:57:07 +01:00
|
|
|
|
2019-08-06 09:28:50 -04:00
|
|
|
/**
|
|
|
|
* Set a new formatted text for a label. Memory will be allocated to store the text by the label.
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @param fmt `printf`-like format
|
|
|
|
*/
|
|
|
|
void lv_label_set_text_fmt(lv_obj_t * label, const char * fmt, ...)
|
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
LV_ASSERT_STR(fmt);
|
|
|
|
|
2019-08-06 09:28:50 -04:00
|
|
|
lv_obj_invalidate(label);
|
|
|
|
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
|
|
|
|
/*If text is NULL then refresh */
|
|
|
|
if(fmt == NULL) {
|
|
|
|
lv_label_refr_text(label);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ext->text != NULL && ext->static_txt == 0) {
|
|
|
|
lv_mem_free(ext->text);
|
|
|
|
ext->text = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
va_list ap, ap2;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
va_copy(ap2, ap);
|
|
|
|
|
|
|
|
/*Allocate space for the new text by using trick from C99 standard section 7.19.6.12 */
|
|
|
|
uint32_t len = lv_vsnprintf(NULL, 0, fmt, ap);
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
|
|
ext->text = lv_mem_alloc(len+1);
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2019-08-06 09:28:50 -04:00
|
|
|
if(ext->text == NULL) return;
|
|
|
|
ext->text[len-1] = 0; /* Ensure NULL termination */
|
|
|
|
|
2019-08-18 16:00:57 -04:00
|
|
|
lv_vsnprintf(ext->text, len+1, fmt, ap2);
|
2019-08-06 09:28:50 -04:00
|
|
|
|
|
|
|
va_end(ap2);
|
|
|
|
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
|
|
|
|
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
|
|
|
|
2016-12-30 21:42:59 +01:00
|
|
|
/**
|
|
|
|
* Set a new text for a label from a character array. The array don't has to be '\0' terminated.
|
|
|
|
* Memory will be allocated to store the array by the label.
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @param array array of characters or NULL to refresh the label
|
|
|
|
* @param size the size of 'array' in bytes
|
|
|
|
*/
|
2017-11-13 16:11:05 +01:00
|
|
|
void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size)
|
2016-12-30 21:42:59 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_invalidate(label);
|
2016-10-16 21:43:28 +02:00
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2016-12-30 21:42:59 +01:00
|
|
|
|
|
|
|
/*If trying to set its own text or the array is NULL then refresh */
|
2017-11-13 16:11:05 +01:00
|
|
|
if(array == ext->text || array == NULL) {
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_label_refr_text(label);
|
|
|
|
return;
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
2016-12-30 21:42:59 +01:00
|
|
|
|
|
|
|
/*Allocate space for the new text*/
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->text != NULL && ext->static_txt == 0) {
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_mem_free(ext->text);
|
2017-11-13 16:11:05 +01:00
|
|
|
ext->text = NULL;
|
2016-10-16 21:43:28 +02:00
|
|
|
}
|
2017-11-23 21:28:36 +01:00
|
|
|
ext->text = lv_mem_alloc(size + 1);
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2018-07-25 13:33:53 +02:00
|
|
|
if(ext->text == NULL) return;
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
memcpy(ext->text, array, size);
|
|
|
|
ext->text[size] = '\0';
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
2016-12-30 21:42:59 +01:00
|
|
|
|
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a static text. It will not be saved by the label so the 'text' variable
|
|
|
|
* has to be 'alive' while the label exist.
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @param text pointer to a text. NULL to refresh with the current text.
|
|
|
|
*/
|
2017-11-13 16:11:05 +01:00
|
|
|
void lv_label_set_static_text(lv_obj_t * label, const char * text)
|
2016-12-30 21:42:59 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->static_txt == 0 && ext->text != NULL) {
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_mem_free(ext->text);
|
2017-11-13 16:11:05 +01:00
|
|
|
ext->text = NULL;
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
2016-12-30 21:42:59 +01:00
|
|
|
|
|
|
|
if(text != NULL) {
|
|
|
|
ext->static_txt = 1;
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->text = (char *)text;
|
2017-10-05 11:29:21 +02:00
|
|
|
}
|
|
|
|
|
2017-02-06 08:52:59 +01:00
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
|
|
|
|
2016-06-15 10:23:10 +02:00
|
|
|
/**
|
2016-10-16 21:43:28 +02:00
|
|
|
* Set the behavior of the label with longer text then the object size
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2016-10-16 21:43:28 +02:00
|
|
|
* @param long_mode the new mode from 'lv_label_long_mode' enum.
|
2019-04-04 07:15:40 +02:00
|
|
|
* In LV_LONG_BREAK/LONG/ROLL the size of the label should be set AFTER this
|
|
|
|
* function
|
2016-06-15 10:23:10 +02:00
|
|
|
*/
|
2016-10-16 21:43:28 +02:00
|
|
|
void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode)
|
2016-06-15 10:23:10 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2016-10-16 21:43:28 +02:00
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_ANIMATION
|
2017-06-18 18:25:25 +02:00
|
|
|
/*Delete the old animation (if exists)*/
|
2019-06-12 23:10:54 +02:00
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_obj_set_x);
|
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_obj_set_y);
|
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_x);
|
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_y);
|
2017-11-27 17:48:54 +01:00
|
|
|
#endif
|
2017-06-18 18:25:25 +02:00
|
|
|
ext->offset.x = 0;
|
|
|
|
ext->offset.y = 0;
|
|
|
|
|
2019-06-19 00:35:35 +02:00
|
|
|
if(long_mode == LV_LABEL_LONG_SROLL || long_mode == LV_LABEL_LONG_SROLL_CIRC || long_mode == LV_LABEL_LONG_CROP)
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->expand = 1;
|
|
|
|
else
|
|
|
|
ext->expand = 0;
|
2016-10-20 16:35:03 +02:00
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/*Restore the character under the dots*/
|
|
|
|
if(ext->long_mode == LV_LABEL_LONG_DOT && ext->dot_end != LV_LABEL_DOT_END_INV) {
|
|
|
|
lv_label_revert_dots(label);
|
|
|
|
}
|
|
|
|
|
2016-10-16 21:43:28 +02:00
|
|
|
ext->long_mode = long_mode;
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_label_refr_text(label);
|
2016-06-15 10:23:10 +02:00
|
|
|
}
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/**
|
|
|
|
* Set the align of the label (left or center)
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT'
|
|
|
|
*/
|
2018-06-19 09:49:58 +02:00
|
|
|
void lv_label_set_align(lv_obj_t * label, lv_label_align_t align)
|
2017-11-02 09:25:37 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2018-05-16 23:09:30 +02:00
|
|
|
if(ext->align == align) return;
|
2017-11-02 09:25:37 +01:00
|
|
|
|
|
|
|
ext->align = align;
|
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_obj_invalidate(label); /*Enough to invalidate because alignment is only drawing related
|
|
|
|
(lv_refr_label_text() not required)*/
|
2017-11-02 09:25:37 +01:00
|
|
|
}
|
|
|
|
|
2017-02-01 11:39:48 +01:00
|
|
|
/**
|
|
|
|
* Enable the recoloring by in-line commands
|
|
|
|
* @param label pointer to a label object
|
2018-12-22 19:45:55 +01:00
|
|
|
* @param en true: enable recoloring, false: disable
|
2017-02-01 11:39:48 +01:00
|
|
|
*/
|
2018-12-22 19:45:55 +01:00
|
|
|
void lv_label_set_recolor(lv_obj_t * label, bool en)
|
2017-02-01 11:39:48 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2018-12-22 19:45:55 +01:00
|
|
|
if(ext->recolor == en) return;
|
2017-02-01 11:39:48 +01:00
|
|
|
|
2018-12-22 19:45:55 +01:00
|
|
|
ext->recolor = en == false ? 0 : 1;
|
2017-02-01 11:39:48 +01:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_label_refr_text(label); /*Refresh the text because the potential colo codes in text needs to
|
|
|
|
be hided or revealed*/
|
2017-02-01 11:39:48 +01:00
|
|
|
}
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/**
|
2019-06-20 06:20:23 +02:00
|
|
|
* Set the label's animation speed in LV_LABEL_LONG_SROLL/SCROLL_CIRC modes
|
2017-11-13 16:11:05 +01:00
|
|
|
* @param label pointer to a label object
|
|
|
|
* @param anim_speed speed of animation in px/sec unit
|
|
|
|
*/
|
2018-06-19 09:49:58 +02:00
|
|
|
void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed)
|
2017-11-13 16:11:05 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-05-20 09:22:09 -07:00
|
|
|
#if LV_USE_ANIMATION
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2018-05-16 23:09:30 +02:00
|
|
|
if(ext->anim_speed == anim_speed) return;
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
ext->anim_speed = anim_speed;
|
2018-01-31 10:06:39 +01:00
|
|
|
|
2019-06-19 00:35:35 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_SROLL || ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
2018-01-31 10:06:39 +01:00
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
2019-06-20 06:20:23 +02:00
|
|
|
#else
|
2019-06-27 07:16:15 +02:00
|
|
|
(void)label; /*Unused*/
|
|
|
|
(void)anim_speed; /*Unused*/
|
2019-05-20 09:22:09 -07:00
|
|
|
#endif
|
2017-11-13 16:11:05 +01:00
|
|
|
}
|
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
void lv_label_set_text_sel_start(lv_obj_t * label, uint16_t index)
|
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-04-18 07:11:43 +02:00
|
|
|
#if LV_LABEL_TEXT_SEL
|
2019-04-14 09:47:45 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-12-19 22:44:18 +01:00
|
|
|
ext->sel_start = index;
|
2019-04-18 06:45:45 +02:00
|
|
|
lv_obj_invalidate(label);
|
2019-06-30 05:52:35 +02:00
|
|
|
#else
|
|
|
|
(void)label; /*Unused*/
|
|
|
|
(void)index; /*Unused*/
|
2019-04-14 09:47:45 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
void lv_label_set_text_sel_end(lv_obj_t * label, uint16_t index)
|
2019-04-18 06:45:45 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-04-18 07:11:43 +02:00
|
|
|
#if LV_LABEL_TEXT_SEL
|
2019-04-14 09:47:45 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-12-19 22:44:18 +01:00
|
|
|
ext->sel_end = index;
|
2019-04-18 06:45:45 +02:00
|
|
|
lv_obj_invalidate(label);
|
2019-06-30 05:52:35 +02:00
|
|
|
#else
|
|
|
|
(void)label; /*Unused*/
|
|
|
|
(void)index; /*Unused*/
|
2019-04-14 09:47:45 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/*=====================
|
2018-06-19 09:49:58 +02:00
|
|
|
* Getter functions
|
2016-06-08 07:25:08 +02:00
|
|
|
*====================*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the text of a label
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2016-06-08 07:25:08 +02:00
|
|
|
* @return the text of the label
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
char * lv_label_get_text(const lv_obj_t * label)
|
2016-06-08 07:25:08 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
return ext->text;
|
2016-06-15 10:23:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-02-01 11:39:48 +01:00
|
|
|
* Get the long mode of a label
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2017-02-01 11:39:48 +01:00
|
|
|
* @return the long mode
|
2016-06-15 10:23:10 +02:00
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label)
|
2016-06-15 10:23:10 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2016-10-16 21:43:28 +02:00
|
|
|
return ext->long_mode;
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
|
|
|
|
2017-11-02 09:25:37 +01:00
|
|
|
/**
|
|
|
|
* Get the align attribute
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @return LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
lv_label_align_t lv_label_get_align(const lv_obj_t * label)
|
2017-11-02 09:25:37 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-11-02 09:25:37 +01:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-10-08 16:26:55 +02:00
|
|
|
|
|
|
|
lv_label_align_t align = ext->align;
|
|
|
|
|
|
|
|
if(align == LV_LABEL_ALIGN_AUTO) {
|
|
|
|
#if LV_USE_BIDI
|
|
|
|
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
|
|
|
|
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text);
|
|
|
|
|
|
|
|
if(base_dir == LV_BIDI_DIR_LTR) align = LV_LABEL_ALIGN_LEFT;
|
|
|
|
else if (base_dir == LV_BIDI_DIR_RTL) align = LV_LABEL_ALIGN_RIGHT;
|
|
|
|
#else
|
|
|
|
align = LV_LABEL_ALIGN_LEFT;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return align;
|
2017-11-02 09:25:37 +01:00
|
|
|
}
|
|
|
|
|
2017-02-01 11:39:48 +01:00
|
|
|
/**
|
|
|
|
* Get the recoloring attribute
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @return true: recoloring is enabled, false: disable
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
bool lv_label_get_recolor(const lv_obj_t * label)
|
2017-02-01 11:39:48 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2017-02-01 11:39:48 +01:00
|
|
|
return ext->recolor == 0 ? false : true;
|
2017-06-13 14:17:33 +02:00
|
|
|
}
|
2017-02-01 11:39:48 +01:00
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/**
|
|
|
|
* Get the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes
|
|
|
|
* @param label pointer to a label object
|
|
|
|
* @return speed of animation in px/sec unit
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
|
2017-11-13 16:11:05 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-05-20 09:22:09 -07:00
|
|
|
#if LV_USE_ANIMATION
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2017-11-13 16:11:05 +01:00
|
|
|
return ext->anim_speed;
|
2019-05-20 09:22:09 -07:00
|
|
|
#else
|
2019-06-27 07:16:15 +02:00
|
|
|
(void)label; /*Unused*/
|
2019-05-20 09:22:09 -07:00
|
|
|
return 0;
|
|
|
|
#endif
|
2017-11-13 16:11:05 +01:00
|
|
|
}
|
2017-10-30 17:11:56 +01:00
|
|
|
|
2016-09-30 15:29:00 +02:00
|
|
|
/**
|
|
|
|
* Get the relative x and y coordinates of a letter
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2019-04-04 07:15:40 +02:00
|
|
|
* @param index index of the letter [0 ... text length]. Expressed in character index, not byte
|
|
|
|
* index (different in UTF-8)
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
|
2016-09-30 15:29:00 +02:00
|
|
|
*/
|
2019-11-06 05:19:06 +01:00
|
|
|
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_t * pos)
|
2016-09-30 15:29:00 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
LV_ASSERT_NULL(pos);
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_area_t txt_coords;
|
|
|
|
get_txt_coords(label, &txt_coords);
|
|
|
|
|
2019-04-11 19:59:55 +08:00
|
|
|
const char * txt = lv_label_get_text(label);
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
uint32_t line_start = 0;
|
|
|
|
uint32_t new_line_start = 0;
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_coord_t max_w = lv_area_get_width(&txt_coords);
|
2020-02-02 15:58:08 +01:00
|
|
|
const lv_font_t * font = lv_obj_get_style_font(label, LV_LABEL_PART_MAIN);
|
2020-02-12 08:54:03 +01:00
|
|
|
lv_style_int_t line_space = lv_obj_get_style_text_line_space(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_style_int_t letter_space = lv_obj_get_style_text_letter_space(label, LV_LABEL_PART_MAIN);
|
2019-11-17 17:12:35 +01:00
|
|
|
lv_coord_t letter_height = lv_font_get_line_height(font);
|
2019-04-11 19:59:55 +08:00
|
|
|
lv_coord_t y = 0;
|
|
|
|
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
2017-02-01 11:39:48 +01:00
|
|
|
|
2017-11-24 17:48:47 +01:00
|
|
|
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
|
|
|
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
2019-10-11 12:01:58 +02:00
|
|
|
|
|
|
|
lv_label_align_t align = lv_label_get_align(label);
|
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
|
|
|
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
2016-09-30 15:29:00 +02:00
|
|
|
|
2016-10-16 21:43:28 +02:00
|
|
|
/*If the width will be expanded the set the max length to very big */
|
2019-04-02 06:44:50 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
2017-11-23 21:28:36 +01:00
|
|
|
max_w = LV_COORD_MAX;
|
2016-09-30 15:29:00 +02:00
|
|
|
}
|
|
|
|
|
2019-11-06 05:19:06 +01:00
|
|
|
uint16_t byte_id = lv_txt_encoded_get_byte_id(txt, char_id);
|
2017-10-05 11:29:21 +02:00
|
|
|
|
2016-09-30 15:29:00 +02:00
|
|
|
/*Search the line of the index letter */;
|
2018-06-19 09:49:58 +02:00
|
|
|
while(txt[new_line_start] != '\0') {
|
2019-12-19 22:44:18 +01:00
|
|
|
new_line_start += lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag);
|
2019-11-06 05:19:06 +01:00
|
|
|
if(byte_id < new_line_start || txt[new_line_start] == '\0')
|
2019-04-04 07:15:40 +02:00
|
|
|
break; /*The line of 'index' letter begins at 'line_start'*/
|
2016-09-30 15:29:00 +02:00
|
|
|
|
2019-12-19 22:44:18 +01:00
|
|
|
y += letter_height + line_space;
|
2016-09-30 15:29:00 +02:00
|
|
|
line_start = new_line_start;
|
|
|
|
}
|
|
|
|
|
2017-10-05 11:29:21 +02:00
|
|
|
/*If the last character is line break then go to the next line*/
|
2019-11-06 05:19:06 +01:00
|
|
|
if(byte_id > 0) {
|
|
|
|
if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') {
|
2019-12-19 22:44:18 +01:00
|
|
|
y += letter_height + line_space;
|
2019-11-06 05:19:06 +01:00
|
|
|
line_start = byte_id;
|
2019-01-07 07:06:31 +01:00
|
|
|
}
|
2016-12-20 15:02:23 +01:00
|
|
|
}
|
|
|
|
|
2019-11-11 22:43:12 +02:00
|
|
|
const char *bidi_txt;
|
2019-11-11 19:42:10 +01:00
|
|
|
uint16_t visual_byte_pos;
|
2019-11-05 01:03:40 +02:00
|
|
|
#if LV_USE_BIDI
|
2019-11-15 07:28:42 +01:00
|
|
|
char *mutable_bidi_txt = NULL;
|
2019-11-05 01:03:40 +02:00
|
|
|
/*Handle Bidi*/
|
2019-11-11 19:42:10 +01:00
|
|
|
if(new_line_start == byte_id) {
|
|
|
|
visual_byte_pos = byte_id - line_start;
|
|
|
|
bidi_txt = &txt[line_start];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start);
|
2019-11-05 16:00:32 +01:00
|
|
|
|
2019-11-11 19:42:10 +01:00
|
|
|
bool is_rtl;
|
2019-11-11 22:43:12 +02:00
|
|
|
uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &is_rtl);
|
|
|
|
bidi_txt = mutable_bidi_txt;
|
2019-11-11 19:42:10 +01:00
|
|
|
if (is_rtl) visual_char_pos++;
|
2020-01-10 18:16:20 +01:00
|
|
|
|
2019-11-11 19:42:10 +01:00
|
|
|
visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos);
|
|
|
|
}
|
2019-11-05 01:03:40 +02:00
|
|
|
#else
|
|
|
|
bidi_txt = &txt[line_start];
|
2019-11-11 19:42:10 +01:00
|
|
|
visual_byte_pos = byte_id - line_start;
|
2019-11-05 01:03:40 +02:00
|
|
|
#endif
|
|
|
|
|
2019-11-05 16:00:32 +01:00
|
|
|
|
2016-09-30 15:29:00 +02:00
|
|
|
/*Calculate the x coordinate*/
|
2019-12-19 22:44:18 +01:00
|
|
|
lv_coord_t x = lv_txt_get_width(bidi_txt, visual_byte_pos, font, letter_space, flag);
|
|
|
|
if(char_id != line_start) x += letter_space;
|
2019-01-07 07:06:31 +01:00
|
|
|
|
2019-10-11 12:01:58 +02:00
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) {
|
2019-01-07 07:06:31 +01:00
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) / 2 - line_w / 2;
|
2018-07-25 22:57:36 +02:00
|
|
|
|
2019-10-11 12:01:58 +02:00
|
|
|
} else if(align == LV_LABEL_ALIGN_RIGHT) {
|
2019-01-07 07:06:31 +01:00
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag);
|
2016-10-01 00:25:10 +02:00
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) - line_w;
|
2019-01-07 07:06:31 +01:00
|
|
|
}
|
2016-10-07 11:15:46 +02:00
|
|
|
pos->x = x;
|
|
|
|
pos->y = y;
|
2019-11-15 07:28:42 +01:00
|
|
|
|
|
|
|
#if LV_USE_BIDI
|
2019-12-21 20:48:44 +01:00
|
|
|
if(mutable_bidi_txt) lv_mem_buf_release(mutable_bidi_txt);
|
2019-11-15 07:28:42 +01:00
|
|
|
#endif
|
2016-10-01 00:25:10 +02:00
|
|
|
}
|
|
|
|
|
2016-10-04 09:45:39 +02:00
|
|
|
/**
|
|
|
|
* Get the index of letter on a relative point of a label
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to label object
|
|
|
|
* @param pos pointer to point with coordinates on a the label
|
2016-10-04 09:45:39 +02:00
|
|
|
* @return the index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter)
|
2017-11-05 14:12:50 +01:00
|
|
|
* Expressed in character index and not byte index (different in UTF-8)
|
2016-10-04 09:45:39 +02:00
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
2016-10-01 00:25:10 +02:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
LV_ASSERT_NULL(pos);
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_area_t txt_coords;
|
|
|
|
get_txt_coords(label, &txt_coords);
|
2019-04-11 19:59:55 +08:00
|
|
|
const char * txt = lv_label_get_text(label);
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
uint32_t line_start = 0;
|
|
|
|
uint32_t new_line_start = 0;
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_coord_t max_w = lv_area_get_width(&txt_coords);
|
2020-02-02 15:58:08 +01:00
|
|
|
const lv_font_t * font = lv_obj_get_style_font(label, LV_LABEL_PART_MAIN);
|
2020-02-12 08:54:03 +01:00
|
|
|
lv_style_int_t line_space = lv_obj_get_style_text_line_space(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_style_int_t letter_space = lv_obj_get_style_text_letter_space(label, LV_LABEL_PART_MAIN);
|
2019-11-17 17:12:35 +01:00
|
|
|
lv_coord_t letter_height = lv_font_get_line_height(font);
|
2019-04-11 19:59:55 +08:00
|
|
|
lv_coord_t y = 0;
|
|
|
|
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
2019-11-05 01:03:40 +02:00
|
|
|
uint16_t logical_pos;
|
|
|
|
char *bidi_txt;
|
2017-02-01 11:39:48 +01:00
|
|
|
|
2017-11-24 17:48:47 +01:00
|
|
|
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
|
|
|
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
2019-10-11 12:01:58 +02:00
|
|
|
|
|
|
|
lv_label_align_t align = lv_label_get_align(label);
|
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
|
|
|
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
2016-10-01 00:25:10 +02:00
|
|
|
|
2016-10-16 21:43:28 +02:00
|
|
|
/*If the width will be expanded set the max length to very big */
|
2019-04-02 06:44:50 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
2017-11-23 21:28:36 +01:00
|
|
|
max_w = LV_COORD_MAX;
|
2016-10-01 00:25:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*Search the line of the index letter */;
|
2018-06-19 09:49:58 +02:00
|
|
|
while(txt[line_start] != '\0') {
|
2019-12-19 22:44:18 +01:00
|
|
|
new_line_start += lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag);
|
2018-07-25 06:12:05 +02:00
|
|
|
|
2019-11-10 23:16:54 -08:00
|
|
|
if(pos->y <= y + letter_height) {
|
|
|
|
/*The line is found (stored in 'line_start')*/
|
|
|
|
/* Include the NULL terminator in the last line */
|
|
|
|
uint32_t tmp = new_line_start;
|
|
|
|
uint32_t letter;
|
|
|
|
letter = lv_txt_encoded_prev(txt, &tmp);
|
|
|
|
if(letter != '\n' && txt[new_line_start] == '\0' ) new_line_start++;
|
|
|
|
break;
|
|
|
|
}
|
2019-12-19 22:44:18 +01:00
|
|
|
y += letter_height + line_space;
|
2018-07-25 06:12:05 +02:00
|
|
|
|
2016-10-01 00:25:10 +02:00
|
|
|
line_start = new_line_start;
|
2016-09-30 15:29:00 +02:00
|
|
|
}
|
|
|
|
|
2019-11-05 01:03:40 +02:00
|
|
|
#if LV_USE_BIDI
|
2019-11-19 06:25:14 +01:00
|
|
|
bidi_txt = lv_mem_buf_get(new_line_start - line_start + 1);
|
2019-11-11 19:42:10 +01:00
|
|
|
uint16_t txt_len = new_line_start - line_start;
|
2020-01-24 14:55:56 +01:00
|
|
|
if(new_line_start > 0 && txt[new_line_start - 1] == '\0' && txt_len > 0) txt_len--;
|
2019-11-11 19:42:10 +01:00
|
|
|
lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_base_dir(label), NULL, 0);
|
2019-11-05 01:03:40 +02:00
|
|
|
#else
|
2019-11-12 15:26:35 +00:00
|
|
|
bidi_txt = (char*)txt + line_start;
|
2019-11-05 01:03:40 +02:00
|
|
|
#endif
|
|
|
|
|
2016-10-01 00:25:10 +02:00
|
|
|
/*Calculate the x coordinate*/
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_coord_t x = 0;
|
2019-10-11 12:01:58 +02:00
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) {
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) / 2 - line_w / 2;
|
2016-10-01 00:25:10 +02:00
|
|
|
}
|
2019-10-11 12:01:58 +02:00
|
|
|
else if(align == LV_LABEL_ALIGN_RIGHT) {
|
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) - line_w;
|
2019-10-11 12:01:58 +02:00
|
|
|
}
|
2016-10-01 00:25:10 +02:00
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
2019-05-01 16:43:32 +02:00
|
|
|
|
2019-11-05 01:03:40 +02:00
|
|
|
uint32_t i = 0;
|
2019-08-16 13:43:28 +02:00
|
|
|
uint32_t i_act = i;
|
2018-06-19 09:49:58 +02:00
|
|
|
uint32_t letter;
|
2019-05-01 16:43:32 +02:00
|
|
|
uint32_t letter_next;
|
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
if(new_line_start > 0) {
|
2019-11-05 01:03:40 +02:00
|
|
|
while(i + line_start < new_line_start) {
|
2019-08-16 13:43:28 +02:00
|
|
|
/* Get the current letter.*/
|
2019-11-05 01:03:40 +02:00
|
|
|
letter = lv_txt_encoded_next(bidi_txt, &i);
|
2019-06-01 21:46:05 +02:00
|
|
|
|
|
|
|
/*Get the next letter too for kerning*/
|
2019-11-05 01:03:40 +02:00
|
|
|
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
|
2019-06-01 21:46:05 +02:00
|
|
|
|
|
|
|
/*Handle the recolor command*/
|
|
|
|
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
2019-11-05 01:03:40 +02:00
|
|
|
if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
|
2019-06-01 21:46:05 +02:00
|
|
|
continue; /*Skip the letter is it is part of a command*/
|
|
|
|
}
|
2017-02-01 11:39:48 +01:00
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
x += lv_font_get_glyph_width(font, letter, letter_next);
|
2019-08-16 13:43:28 +02:00
|
|
|
|
|
|
|
/*Finish if the x position or the last char of the line is reached*/
|
2020-01-24 14:55:56 +01:00
|
|
|
if(pos->x < x || i + line_start == new_line_start || txt[i + line_start] == '\0') {
|
2019-08-16 13:43:28 +02:00
|
|
|
i = i_act;
|
2019-06-01 21:46:05 +02:00
|
|
|
break;
|
|
|
|
}
|
2019-12-19 22:44:18 +01:00
|
|
|
x += letter_space;
|
2019-08-16 13:43:28 +02:00
|
|
|
i_act = i;
|
2018-06-19 09:49:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-05 01:03:40 +02:00
|
|
|
#if LV_USE_BIDI
|
|
|
|
/*Handle Bidi*/
|
2019-11-09 01:02:51 +02:00
|
|
|
bool is_rtl;
|
2019-11-11 19:42:10 +01:00
|
|
|
logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, txt_len, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i), &is_rtl);
|
2019-11-09 01:02:51 +02:00
|
|
|
if (is_rtl) logical_pos++;
|
2020-01-24 14:55:56 +01:00
|
|
|
lv_mem_buf_release(bidi_txt);
|
2019-11-05 01:03:40 +02:00
|
|
|
#else
|
2019-11-09 01:53:02 +01:00
|
|
|
logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i);
|
2019-11-05 01:03:40 +02:00
|
|
|
#endif
|
|
|
|
|
2019-11-10 10:52:49 +01:00
|
|
|
return logical_pos + lv_txt_encoded_get_char_id(txt, line_start);
|
2016-09-30 15:29:00 +02:00
|
|
|
}
|
|
|
|
|
2019-04-15 22:03:12 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the selection start index.
|
|
|
|
* @param label pointer to a label object.
|
2019-04-18 06:45:45 +02:00
|
|
|
* @return selection start index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected.
|
2019-04-15 22:03:12 -07:00
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
uint16_t lv_label_get_text_sel_start(const lv_obj_t * label)
|
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-04-18 07:11:43 +02:00
|
|
|
#if LV_LABEL_TEXT_SEL
|
2019-04-14 09:47:45 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-12-19 22:44:18 +01:00
|
|
|
return ext->sel_start;
|
2019-04-18 06:45:45 +02:00
|
|
|
|
2019-04-14 09:47:45 -07:00
|
|
|
#else
|
2019-06-30 05:52:35 +02:00
|
|
|
(void)label; /*Unused*/
|
2019-04-18 06:45:45 +02:00
|
|
|
return LV_LABEL_TEXT_SEL_OFF;
|
2019-04-14 09:47:45 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-04-15 22:03:12 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the selection end index.
|
|
|
|
* @param label pointer to a label object.
|
2019-04-18 06:45:45 +02:00
|
|
|
* @return selection end index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected.
|
2019-04-15 22:03:12 -07:00
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
uint16_t lv_label_get_text_sel_end(const lv_obj_t * label)
|
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2019-04-18 07:11:43 +02:00
|
|
|
#if LV_LABEL_TEXT_SEL
|
2019-04-14 09:47:45 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-12-19 22:44:18 +01:00
|
|
|
return ext->sel_end;
|
2019-04-14 09:47:45 -07:00
|
|
|
#else
|
2019-06-06 06:05:40 +02:00
|
|
|
(void)label; /*Unused*/
|
2019-04-18 06:45:45 +02:00
|
|
|
return LV_LABEL_TEXT_SEL_OFF;
|
2019-04-14 09:47:45 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-03-27 19:11:04 -04:00
|
|
|
/**
|
|
|
|
* Check if a character is drawn under a point.
|
|
|
|
* @param label Label object
|
|
|
|
* @param pos Point to check for characte under
|
|
|
|
* @return whether a character is drawn under the point
|
|
|
|
*/
|
2019-04-04 07:15:40 +02:00
|
|
|
bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
LV_ASSERT_NULL(pos);
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_area_t txt_coords;
|
|
|
|
get_txt_coords(label, &txt_coords);
|
2019-04-11 19:59:55 +08:00
|
|
|
const char * txt = lv_label_get_text(label);
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
uint32_t line_start = 0;
|
|
|
|
uint32_t new_line_start = 0;
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_coord_t max_w = lv_area_get_width(&txt_coords);
|
2020-02-02 15:58:08 +01:00
|
|
|
const lv_font_t * font = lv_obj_get_style_font(label, LV_LABEL_PART_MAIN);
|
2020-02-12 08:54:03 +01:00
|
|
|
lv_style_int_t line_space = lv_obj_get_style_text_line_space(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_style_int_t letter_space = lv_obj_get_style_text_letter_space(label, LV_LABEL_PART_MAIN);
|
2019-11-17 17:12:35 +01:00
|
|
|
lv_coord_t letter_height = lv_font_get_line_height(font);
|
2019-04-11 19:59:55 +08:00
|
|
|
lv_coord_t y = 0;
|
|
|
|
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
2019-11-10 11:03:19 +01:00
|
|
|
lv_label_align_t align = lv_label_get_align(label);
|
2019-04-04 07:15:40 +02:00
|
|
|
|
|
|
|
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
|
|
|
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
2019-11-10 11:03:19 +01:00
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
2019-04-04 07:15:40 +02:00
|
|
|
|
|
|
|
/*If the width will be expanded set the max length to very big */
|
|
|
|
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
|
|
|
max_w = LV_COORD_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Search the line of the index letter */;
|
|
|
|
while(txt[line_start] != '\0') {
|
2019-12-19 22:44:18 +01:00
|
|
|
new_line_start += lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag);
|
2019-04-04 07:15:40 +02:00
|
|
|
|
|
|
|
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
|
2019-12-19 22:44:18 +01:00
|
|
|
y += letter_height + line_space;
|
2019-04-04 07:15:40 +02:00
|
|
|
|
|
|
|
line_start = new_line_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Calculate the x coordinate*/
|
|
|
|
lv_coord_t x = 0;
|
|
|
|
lv_coord_t last_x = 0;
|
2019-11-10 11:03:19 +01:00
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) {
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, letter_space, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) / 2 - line_w / 2;
|
2019-04-04 07:15:40 +02:00
|
|
|
}
|
2019-11-10 11:03:19 +01:00
|
|
|
else if(align == LV_LABEL_ALIGN_RIGHT) {
|
|
|
|
lv_coord_t line_w;
|
2019-12-19 22:44:18 +01:00
|
|
|
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, letter_space, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
x += lv_area_get_width(&txt_coords) - line_w;
|
2019-11-10 11:03:19 +01:00
|
|
|
}
|
2019-04-04 07:15:40 +02:00
|
|
|
|
|
|
|
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
2019-05-01 16:43:32 +02:00
|
|
|
|
2019-06-27 07:16:15 +02:00
|
|
|
uint32_t i = line_start;
|
|
|
|
uint32_t i_current = i;
|
|
|
|
uint32_t letter = '\0';
|
2019-06-11 06:33:33 +02:00
|
|
|
uint32_t letter_next = '\0';
|
2019-05-01 16:43:32 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
if(new_line_start > 0) {
|
|
|
|
while(i <= new_line_start - 1) {
|
|
|
|
/* Get the current letter
|
|
|
|
* Be careful 'i' already points to the next character */
|
|
|
|
letter = lv_txt_encoded_next(txt, &i);
|
2019-05-01 16:43:32 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
/*Get the next letter for kerning*/
|
|
|
|
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
2019-05-01 16:43:32 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
/*Handle the recolor command*/
|
|
|
|
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
|
|
|
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
|
|
|
|
continue; /*Skip the letter is it is part of a command*/
|
|
|
|
}
|
2019-04-04 07:15:40 +02:00
|
|
|
}
|
2019-06-01 21:46:05 +02:00
|
|
|
last_x = x;
|
|
|
|
x += lv_font_get_glyph_width(font, letter, letter_next);
|
|
|
|
if(pos->x < x) {
|
|
|
|
i = i_current;
|
|
|
|
break;
|
|
|
|
}
|
2019-12-19 22:44:18 +01:00
|
|
|
x += letter_space;
|
2019-06-01 21:46:05 +02:00
|
|
|
i_current = i;
|
2019-04-04 07:15:40 +02:00
|
|
|
}
|
|
|
|
}
|
2019-03-27 19:11:04 -04:00
|
|
|
|
2019-12-19 22:44:18 +01:00
|
|
|
int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + letter_space + 1;
|
|
|
|
return (pos->x >= (last_x - letter_space) && pos->x <= (last_x + max_diff));
|
2019-04-04 07:15:40 +02:00
|
|
|
}
|
2016-06-08 07:25:08 +02:00
|
|
|
|
2020-01-16 14:26:36 +01:00
|
|
|
lv_style_list_t * lv_label_get_style(lv_obj_t * label, uint8_t type)
|
2019-12-19 22:44:18 +01:00
|
|
|
{
|
2020-01-16 14:26:36 +01:00
|
|
|
lv_style_list_t * style_dsc_p;
|
2019-12-19 22:44:18 +01:00
|
|
|
switch(type) {
|
2019-12-31 06:10:50 +01:00
|
|
|
case LV_LABEL_PART_MAIN:
|
2020-01-16 21:25:11 +01:00
|
|
|
style_dsc_p = &label->style_list;
|
2019-12-19 22:44:18 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
style_dsc_p = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return style_dsc_p;
|
|
|
|
}
|
2017-11-13 16:11:05 +01:00
|
|
|
/*=====================
|
|
|
|
* Other functions
|
|
|
|
*====================*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a text to the label. The label text can not be static.
|
|
|
|
* @param label pointer to a label object
|
2019-04-04 07:15:40 +02:00
|
|
|
* @param pos character index to insert. Expressed in character index and not byte index (Different
|
|
|
|
* in UTF-8) 0: before first char. LV_LABEL_POS_LAST: after last char.
|
2017-11-13 16:11:05 +01:00
|
|
|
* @param txt pointer to the text to insert
|
|
|
|
*/
|
2019-04-04 07:15:40 +02:00
|
|
|
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
2017-11-13 16:11:05 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
LV_ASSERT_STR(txt);
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
|
|
|
|
/*Can not append to static text*/
|
|
|
|
if(ext->static_txt != 0) return;
|
|
|
|
|
|
|
|
lv_obj_invalidate(label);
|
|
|
|
|
|
|
|
/*Allocate space for the new text*/
|
2019-12-02 12:20:01 +01:00
|
|
|
size_t old_len = strlen(ext->text);
|
|
|
|
size_t ins_len = strlen(txt);
|
|
|
|
size_t new_len = ins_len + old_len;
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->text = lv_mem_realloc(ext->text, new_len + 1);
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_MEM(ext->text);
|
2018-07-25 14:43:46 +02:00
|
|
|
if(ext->text == NULL) return;
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
if(pos == LV_LABEL_POS_LAST) {
|
2018-07-26 00:10:20 +02:00
|
|
|
pos = lv_txt_get_encoded_length(ext->text);
|
2017-11-13 16:11:05 +01:00
|
|
|
}
|
|
|
|
|
2019-10-15 14:25:47 +02:00
|
|
|
#if LV_USE_BIDI
|
2019-11-19 06:27:21 +01:00
|
|
|
char * bidi_buf = lv_mem_buf_get(ins_len + 1);
|
2019-10-15 14:25:47 +02:00
|
|
|
LV_ASSERT_MEM(bidi_buf);
|
|
|
|
if(bidi_buf == NULL) return;
|
|
|
|
|
|
|
|
lv_bidi_process(txt, bidi_buf, lv_obj_get_base_dir(label));
|
|
|
|
lv_txt_ins(ext->text, pos, bidi_buf);
|
|
|
|
|
2019-11-19 06:27:21 +01:00
|
|
|
lv_mem_buf_release(bidi_buf);
|
2019-10-15 14:25:47 +02:00
|
|
|
#else
|
2017-11-24 17:48:47 +01:00
|
|
|
lv_txt_ins(ext->text, pos, txt);
|
2019-11-15 07:28:42 +01:00
|
|
|
#endif
|
2019-12-21 20:48:44 +01:00
|
|
|
lv_label_refr_text(label);
|
2017-11-13 16:11:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete characters from a label. The label text can not be static.
|
|
|
|
* @param label pointer to a label object
|
2019-04-04 07:15:40 +02:00
|
|
|
* @param pos character index to insert. Expressed in character index and not byte index (Different
|
|
|
|
* in UTF-8) 0: before first char.
|
2017-11-13 16:11:05 +01:00
|
|
|
* @param cnt number of characters to cut
|
|
|
|
*/
|
2019-04-04 07:15:40 +02:00
|
|
|
void lv_label_cut_text(lv_obj_t * label, uint32_t pos, uint32_t cnt)
|
2017-11-13 16:11:05 +01:00
|
|
|
{
|
2019-09-24 23:14:17 +02:00
|
|
|
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
|
|
|
|
/*Can not append to static text*/
|
|
|
|
if(ext->static_txt != 0) return;
|
|
|
|
|
|
|
|
lv_obj_invalidate(label);
|
|
|
|
|
|
|
|
char * label_txt = lv_label_get_text(label);
|
|
|
|
/*Delete the characters*/
|
2017-11-24 17:48:47 +01:00
|
|
|
lv_txt_cut(label_txt, pos, cnt);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
/*Refresh the label*/
|
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
|
|
|
|
2016-06-08 07:25:08 +02:00
|
|
|
/**********************
|
|
|
|
* STATIC FUNCTIONS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle the drawing related tasks of the labels
|
2016-10-07 11:15:46 +02:00
|
|
|
* @param label pointer to a label object
|
2019-09-06 19:53:39 +02:00
|
|
|
* @param clip_area the object will be drawn only in this area
|
2016-06-08 07:25:08 +02:00
|
|
|
* @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')
|
2016-10-04 09:45:39 +02:00
|
|
|
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
2019-09-06 19:53:39 +02:00
|
|
|
* @param return an element of `lv_design_res_t`
|
2016-06-08 07:25:08 +02:00
|
|
|
*/
|
2019-09-06 19:53:39 +02:00
|
|
|
static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_area, lv_design_mode_t mode)
|
2016-06-08 07:25:08 +02:00
|
|
|
{
|
|
|
|
/* A label never covers an area */
|
2019-04-04 07:15:40 +02:00
|
|
|
if(mode == LV_DESIGN_COVER_CHK)
|
2019-09-06 19:53:39 +02:00
|
|
|
return LV_DESIGN_RES_NOT_COVER;
|
2016-10-04 09:45:39 +02:00
|
|
|
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
2020-01-10 18:16:20 +01:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
|
|
|
|
lv_draw_rect_dsc_t draw_rect_dsc;
|
|
|
|
lv_draw_rect_dsc_init(&draw_rect_dsc);
|
|
|
|
lv_obj_init_draw_rect_dsc(label, LV_LABEL_PART_MAIN, &draw_rect_dsc);
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_draw_rect(&label->coords, clip_area, &draw_rect_dsc);
|
|
|
|
|
|
|
|
lv_area_t txt_coords;
|
|
|
|
get_txt_coords(label, &txt_coords);
|
|
|
|
|
|
|
|
lv_area_t txt_clip;
|
|
|
|
bool is_common = lv_area_intersect(&txt_clip, clip_area, &txt_coords);
|
|
|
|
if(!is_common) return LV_DESIGN_RES_OK;
|
|
|
|
|
2017-09-11 10:15:40 +02:00
|
|
|
|
2019-10-08 16:26:55 +02:00
|
|
|
lv_label_align_t align = lv_label_get_align(label);
|
2016-10-04 09:45:39 +02:00
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
|
|
|
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
2017-11-24 17:48:47 +01:00
|
|
|
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
2019-10-08 16:26:55 +02:00
|
|
|
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
|
|
|
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
2016-10-16 21:43:28 +02:00
|
|
|
|
2019-12-27 15:39:54 +01:00
|
|
|
lv_draw_label_dsc_t label_draw_dsc;
|
|
|
|
lv_draw_label_dsc_init(&label_draw_dsc);
|
|
|
|
|
|
|
|
label_draw_dsc.sel_start = lv_label_get_text_sel_start(label);
|
|
|
|
label_draw_dsc.sel_end = lv_label_get_text_sel_end(label);
|
|
|
|
label_draw_dsc.ofs_x = ext->offset.x;
|
|
|
|
label_draw_dsc.ofs_y = ext->offset.y;
|
|
|
|
label_draw_dsc.flag = flag;
|
2020-01-01 16:01:31 +01:00
|
|
|
lv_obj_init_draw_label_dsc(label, LV_LABEL_PART_MAIN, &label_draw_dsc);
|
2019-12-27 15:39:54 +01:00
|
|
|
|
2018-09-25 16:30:49 +02:00
|
|
|
/* In ROLL mode the CENTER and RIGHT are pointless so remove them.
|
|
|
|
* (In addition they will result mis-alignment is this case)*/
|
2019-06-19 00:35:35 +02:00
|
|
|
if((ext->long_mode == LV_LABEL_LONG_SROLL || ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) &&
|
2019-04-04 07:15:40 +02:00
|
|
|
(ext->align == LV_LABEL_ALIGN_CENTER || ext->align == LV_LABEL_ALIGN_RIGHT)) {
|
2018-10-05 17:22:49 +02:00
|
|
|
lv_point_t size;
|
2019-12-27 15:39:54 +01:00
|
|
|
lv_txt_get_size(&size, ext->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space,
|
2019-06-06 06:05:40 +02:00
|
|
|
LV_COORD_MAX, flag);
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.x > lv_area_get_width(&txt_coords)) {
|
2018-10-05 17:22:49 +02:00
|
|
|
flag &= ~LV_TXT_FLAG_RIGHT;
|
|
|
|
flag &= ~LV_TXT_FLAG_CENTER;
|
|
|
|
}
|
2018-09-25 16:30:49 +02:00
|
|
|
}
|
2019-07-29 16:00:59 +02:00
|
|
|
#if LV_LABEL_LONG_TXT_HINT
|
2019-06-14 16:04:15 +02:00
|
|
|
lv_draw_label_hint_t * hint = &ext->hint;
|
2020-02-11 05:47:33 +01:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC || lv_area_get_height(&txt_coords) < LV_LABEL_HINT_HEIGHT_LIMIT)
|
2019-06-27 07:16:15 +02:00
|
|
|
hint = NULL;
|
2019-06-14 16:04:15 +02:00
|
|
|
|
2019-07-29 16:00:59 +02:00
|
|
|
#else
|
|
|
|
/*Just for compatibility*/
|
|
|
|
lv_draw_label_hint_t * hint = NULL;
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, ext->text, hint);
|
2019-04-02 06:44:50 +02:00
|
|
|
|
2019-06-19 00:35:35 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
2019-04-02 06:44:50 +02:00
|
|
|
lv_point_t size;
|
2019-12-27 15:39:54 +01:00
|
|
|
lv_txt_get_size(&size, ext->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space,
|
2019-06-06 06:05:40 +02:00
|
|
|
LV_COORD_MAX, flag);
|
2019-04-02 06:44:50 +02:00
|
|
|
|
|
|
|
/*Draw the text again next to the original to make an circular effect */
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.x > lv_area_get_width(&txt_coords)) {
|
2019-12-19 22:44:18 +01:00
|
|
|
label_draw_dsc.ofs_x = ext->offset.x + size.x +
|
2019-12-27 15:39:54 +01:00
|
|
|
lv_font_get_glyph_width(label_draw_dsc.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
2019-12-19 22:44:18 +01:00
|
|
|
label_draw_dsc.ofs_y = ext->offset.y;
|
2019-04-14 09:47:45 -07:00
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, ext->text, hint);
|
2019-04-02 06:44:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*Draw the text again below the original to make an circular effect */
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.y > lv_area_get_height(&txt_coords)) {
|
2019-12-19 22:44:18 +01:00
|
|
|
label_draw_dsc.ofs_x = ext->offset.x;
|
2019-12-27 15:39:54 +01:00
|
|
|
label_draw_dsc.ofs_y = ext->offset.y + size.y + lv_font_get_line_height(label_draw_dsc.font);
|
2019-12-19 22:44:18 +01:00
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_draw_label(&txt_coords, &txt_clip, &label_draw_dsc, ext->text, hint);
|
2019-04-02 06:44:50 +02:00
|
|
|
}
|
|
|
|
}
|
2016-10-04 09:45:39 +02:00
|
|
|
}
|
2019-10-30 10:34:39 +01:00
|
|
|
|
2019-09-06 19:53:39 +02:00
|
|
|
return LV_DESIGN_RES_OK;
|
2016-06-08 07:25:08 +02:00
|
|
|
}
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/**
|
|
|
|
* Signal function of the label
|
|
|
|
* @param label pointer to a label 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_label_signal(lv_obj_t * label, lv_signal_t sign, void * param)
|
|
|
|
{
|
|
|
|
lv_res_t res;
|
|
|
|
|
2019-12-19 22:44:18 +01:00
|
|
|
if(sign == LV_SIGNAL_GET_STYLE) {
|
2020-01-07 23:43:57 +01:00
|
|
|
lv_get_style_info_t * info = param;
|
|
|
|
info->result = lv_label_get_style(label, info->part);
|
|
|
|
if(info->result != NULL) return LV_RES_OK;
|
|
|
|
else return ancestor_signal(label, sign, param);
|
2019-12-19 22:44:18 +01:00
|
|
|
}
|
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/* Include the ancient signal function */
|
|
|
|
res = ancestor_signal(label, sign, param);
|
|
|
|
if(res != LV_RES_OK) return res;
|
2019-09-26 12:54:40 +02:00
|
|
|
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-04-04 07:15:40 +02:00
|
|
|
if(sign == LV_SIGNAL_CLEANUP) {
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->static_txt == 0) {
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_mem_free(ext->text);
|
2017-11-13 16:11:05 +01:00
|
|
|
ext->text = NULL;
|
|
|
|
}
|
2019-04-14 11:18:31 -07:00
|
|
|
lv_label_dot_tmp_free(label);
|
2018-06-19 09:49:58 +02:00
|
|
|
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
|
|
|
/*Revert dots for proper refresh*/
|
|
|
|
lv_label_revert_dots(label);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_label_refr_text(label);
|
2020-01-05 01:16:13 +01:00
|
|
|
} else if(sign == LV_SIGNAL_COORD_CHG) {
|
2017-11-28 16:15:13 +01:00
|
|
|
if(lv_area_get_width(&label->coords) != lv_area_get_width(param) ||
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_area_get_height(&label->coords) != lv_area_get_height(param)) {
|
2017-11-13 16:11:05 +01:00
|
|
|
lv_label_revert_dots(label);
|
|
|
|
lv_label_refr_text(label);
|
|
|
|
}
|
2020-02-11 05:47:33 +01:00
|
|
|
} else if(sign == LV_SIGNAL_BASE_DIR_CHG) {
|
2019-10-08 16:54:28 +02:00
|
|
|
#if LV_USE_BIDI
|
2019-10-08 16:26:55 +02:00
|
|
|
if(ext->static_txt == 0) lv_label_set_text(label, NULL);
|
2019-10-08 16:54:28 +02:00
|
|
|
#endif
|
2018-06-19 09:49:58 +02:00
|
|
|
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
2018-02-28 15:37:41 +01:00
|
|
|
lv_obj_type_t * buf = param;
|
|
|
|
uint8_t i;
|
2019-04-04 07:15:40 +02:00
|
|
|
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
2018-02-28 15:37:41 +01:00
|
|
|
if(buf->type[i] == NULL) break;
|
|
|
|
}
|
|
|
|
buf->type[i] = "lv_label";
|
|
|
|
}
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-30 21:42:59 +01:00
|
|
|
/**
|
|
|
|
* Refresh the label with its text stored in its extended data
|
|
|
|
* @param label pointer to a label object
|
|
|
|
*/
|
|
|
|
static void lv_label_refr_text(lv_obj_t * label)
|
|
|
|
{
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2016-12-30 21:42:59 +01:00
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
if(ext->text == NULL) return;
|
2019-07-29 16:00:59 +02:00
|
|
|
#if LV_LABEL_LONG_TXT_HINT
|
2019-06-27 07:16:15 +02:00
|
|
|
ext->hint.line_start = -1; /*The hint is invalid if the text changes*/
|
2019-07-29 16:00:59 +02:00
|
|
|
#endif
|
2019-06-14 16:04:15 +02:00
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
lv_area_t txt_coords;
|
|
|
|
get_txt_coords(label, &txt_coords);
|
|
|
|
lv_coord_t max_w = lv_area_get_width(&txt_coords);
|
2020-02-02 15:58:08 +01:00
|
|
|
const lv_font_t * font = lv_obj_get_style_font(label, LV_LABEL_PART_MAIN);
|
2020-02-12 08:54:03 +01:00
|
|
|
lv_style_int_t line_space = lv_obj_get_style_text_line_space(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_style_int_t letter_space = lv_obj_get_style_text_letter_space(label, LV_LABEL_PART_MAIN);
|
2016-12-30 21:42:59 +01:00
|
|
|
|
|
|
|
/*If the width will be expanded set the max length to very big */
|
2019-04-02 06:44:50 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
2017-11-23 21:28:36 +01:00
|
|
|
max_w = LV_COORD_MAX;
|
2016-12-30 21:42:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*Calc. the height and longest line*/
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_point_t size;
|
2017-11-24 17:48:47 +01:00
|
|
|
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
|
|
|
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
|
|
|
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
2019-12-19 22:44:18 +01:00
|
|
|
lv_txt_get_size(&size, ext->text, font, letter_space, line_space, max_w, flag);
|
2016-12-30 21:42:59 +01:00
|
|
|
|
2017-11-13 16:11:05 +01:00
|
|
|
/*Set the full size in expand mode*/
|
2019-04-02 06:44:50 +02:00
|
|
|
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
2020-02-11 05:47:33 +01:00
|
|
|
size.x += lv_obj_get_style_pad_left(label, LV_LABEL_PART_MAIN) + lv_obj_get_style_pad_right(label, LV_LABEL_PART_MAIN);
|
|
|
|
size.y += lv_obj_get_style_pad_top(label, LV_LABEL_PART_MAIN) + lv_obj_get_style_pad_bottom(label, LV_LABEL_PART_MAIN);
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_obj_set_size(label, size.x, size.y);
|
|
|
|
}
|
2017-06-18 18:25:25 +02:00
|
|
|
/*In roll mode keep the size but start offset animations*/
|
2019-06-19 00:35:35 +02:00
|
|
|
else if(ext->long_mode == LV_LABEL_LONG_SROLL) {
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_ANIMATION
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_anim_t anim;
|
2019-04-04 07:15:40 +02:00
|
|
|
anim.var = label;
|
|
|
|
anim.repeat = 1;
|
2017-06-18 18:25:25 +02:00
|
|
|
anim.playback = 1;
|
2019-04-04 07:15:40 +02:00
|
|
|
anim.start = 0;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.ready_cb = NULL;
|
|
|
|
anim.path_cb = lv_anim_path_linear;
|
|
|
|
anim.playback_pause =
|
2019-12-19 22:44:18 +01:00
|
|
|
(((lv_font_get_glyph_width(font, ' ', ' ') + letter_space) * 1000) /
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->anim_speed) *
|
|
|
|
LV_LABEL_WAIT_CHAR_COUNT;
|
2019-04-04 07:15:40 +02:00
|
|
|
anim.repeat_pause = anim.playback_pause;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.act_time = -anim.playback_pause;
|
2017-06-18 18:25:25 +02:00
|
|
|
|
|
|
|
bool hor_anim = false;
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.x > lv_area_get_width(&txt_coords)) {
|
|
|
|
anim.end = lv_area_get_width(&txt_coords) - size.x;
|
2019-06-12 23:10:54 +02:00
|
|
|
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
2017-11-23 21:28:36 +01:00
|
|
|
lv_anim_create(&anim);
|
2017-06-18 18:25:25 +02:00
|
|
|
hor_anim = true;
|
2017-11-07 14:30:52 +01:00
|
|
|
} else {
|
|
|
|
/*Delete the offset animation if not required*/
|
2019-06-12 23:10:54 +02:00
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_x);
|
2017-11-07 14:30:52 +01:00
|
|
|
ext->offset.x = 0;
|
2017-06-18 18:25:25 +02:00
|
|
|
}
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.y > lv_area_get_height(&txt_coords) && hor_anim == false) {
|
|
|
|
anim.end = lv_area_get_height(&txt_coords) - size.y - (lv_font_get_line_height(font));
|
2019-06-12 23:10:54 +02:00
|
|
|
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y;
|
2019-04-23 15:59:10 +02:00
|
|
|
|
2017-11-23 21:28:36 +01:00
|
|
|
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
|
|
|
lv_anim_create(&anim);
|
2017-11-07 14:30:52 +01:00
|
|
|
} else {
|
|
|
|
/*Delete the offset animation if not required*/
|
2019-06-12 23:10:54 +02:00
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_y);
|
2017-11-07 14:30:52 +01:00
|
|
|
ext->offset.y = 0;
|
2017-06-18 18:25:25 +02:00
|
|
|
}
|
2017-11-27 17:48:54 +01:00
|
|
|
#endif
|
2019-04-02 06:44:50 +02:00
|
|
|
}
|
|
|
|
/*In roll inf. mode keep the size but start offset animations*/
|
2019-06-19 00:35:35 +02:00
|
|
|
else if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
2019-04-04 07:15:40 +02:00
|
|
|
#if LV_USE_ANIMATION
|
2019-10-11 12:01:58 +02:00
|
|
|
lv_label_align_t align = lv_label_get_align(label);
|
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_anim_t anim;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.var = label;
|
|
|
|
anim.repeat = 1;
|
|
|
|
anim.playback = 0;
|
2019-12-19 22:44:18 +01:00
|
|
|
anim.act_time = -(((lv_font_get_glyph_width(font, ' ', ' ') + letter_space) * 1000) /
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->anim_speed) *
|
|
|
|
LV_LABEL_WAIT_CHAR_COUNT;
|
|
|
|
anim.ready_cb = NULL;
|
|
|
|
anim.path_cb = lv_anim_path_linear;
|
2019-04-04 07:15:40 +02:00
|
|
|
anim.playback_pause = 0;
|
|
|
|
anim.repeat_pause = 0;
|
2019-04-02 06:44:50 +02:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
bool hor_anim = false;
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.x > lv_area_get_width(&txt_coords)) {
|
2019-10-11 12:01:58 +02:00
|
|
|
if(align == LV_LABEL_ALIGN_RIGHT) {
|
|
|
|
anim.end = 0;
|
|
|
|
anim.start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
|
|
|
} else {
|
|
|
|
anim.start = 0;
|
|
|
|
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
|
|
|
}
|
|
|
|
|
2019-06-12 23:10:54 +02:00
|
|
|
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_anim_create(&anim);
|
|
|
|
hor_anim = true;
|
|
|
|
} else {
|
|
|
|
/*Delete the offset animation if not required*/
|
2019-06-12 23:10:54 +02:00
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_x);
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->offset.x = 0;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.y > lv_area_get_height(&txt_coords) && hor_anim == false) {
|
2019-10-11 12:01:58 +02:00
|
|
|
if(align == LV_LABEL_ALIGN_RIGHT) {
|
|
|
|
anim.end = 0;
|
|
|
|
anim.start = -size.y - (lv_font_get_line_height(font));
|
|
|
|
} else {
|
|
|
|
anim.start = 0;
|
|
|
|
anim.end = -size.y - (lv_font_get_line_height(font));
|
|
|
|
}
|
|
|
|
|
2019-06-12 23:10:54 +02:00
|
|
|
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y;
|
2019-06-06 06:05:40 +02:00
|
|
|
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_anim_create(&anim);
|
|
|
|
} else {
|
|
|
|
/*Delete the offset animation if not required*/
|
2019-06-12 23:10:54 +02:00
|
|
|
lv_anim_del(label, (lv_anim_exec_xcb_t)lv_label_set_offset_y);
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->offset.y = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2018-06-19 09:49:58 +02:00
|
|
|
} else if(ext->long_mode == LV_LABEL_LONG_DOT) {
|
2020-02-11 05:47:33 +01:00
|
|
|
if(size.y <= lv_area_get_height(&txt_coords)) { /*No dots are required, the text is short enough*/
|
2018-06-19 09:49:58 +02:00
|
|
|
ext->dot_end = LV_LABEL_DOT_END_INV;
|
2019-06-06 06:05:40 +02:00
|
|
|
} else if(lv_txt_get_encoded_length(ext->text) <= LV_LABEL_DOT_NUM) { /*Don't turn to dots all the characters*/
|
2018-06-19 09:49:58 +02:00
|
|
|
ext->dot_end = LV_LABEL_DOT_END_INV;
|
|
|
|
} else {
|
|
|
|
lv_point_t p;
|
2020-02-11 05:47:33 +01:00
|
|
|
p.x = lv_area_get_width(&txt_coords) -
|
2019-12-19 22:44:18 +01:00
|
|
|
(lv_font_get_glyph_width(font, '.', '.') + letter_space) *
|
2019-04-04 07:15:40 +02:00
|
|
|
LV_LABEL_DOT_NUM; /*Shrink with dots*/
|
2020-02-11 05:47:33 +01:00
|
|
|
p.y = lv_area_get_height(&txt_coords);
|
2019-06-06 06:05:40 +02:00
|
|
|
p.y -= p.y %
|
2019-12-19 22:44:18 +01:00
|
|
|
(lv_font_get_line_height(font) + line_space); /*Round down to the last line*/
|
|
|
|
p.y -= line_space; /*Trim the last line space*/
|
2018-06-19 09:49:58 +02:00
|
|
|
uint32_t letter_id = lv_label_get_letter_on(label, &p);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
2020-01-30 14:58:14 +02:00
|
|
|
|
|
|
|
/*Be sure there is space for the dots*/
|
|
|
|
size_t txt_len = strlen(ext->text);
|
2019-04-04 07:15:40 +02:00
|
|
|
uint32_t byte_id = lv_txt_encoded_get_byte_id(ext->text, letter_id);
|
2020-01-30 14:58:14 +02:00
|
|
|
while(byte_id + LV_LABEL_DOT_NUM > txt_len) {
|
|
|
|
byte_id -= lv_txt_encoded_size(&ext->text[byte_id]);
|
|
|
|
letter_id--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Save letters under the dots and replace them with dots*/
|
2018-06-19 09:49:58 +02:00
|
|
|
uint32_t byte_id_ori = byte_id;
|
2020-01-30 14:58:14 +02:00
|
|
|
uint32_t i;
|
2019-04-04 07:15:40 +02:00
|
|
|
uint8_t len = 0;
|
|
|
|
for(i = 0; i <= LV_LABEL_DOT_NUM; i++) {
|
2018-07-26 00:10:20 +02:00
|
|
|
len += lv_txt_encoded_size(&ext->text[byte_id]);
|
|
|
|
lv_txt_encoded_next(ext->text, &byte_id);
|
2018-06-19 09:49:58 +02:00
|
|
|
}
|
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
if(lv_label_set_dot_tmp(label, &ext->text[byte_id_ori], len)) {
|
2019-04-14 11:18:31 -07:00
|
|
|
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
|
|
|
|
ext->text[byte_id_ori + i] = '.';
|
|
|
|
}
|
|
|
|
ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0';
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot_end = letter_id + LV_LABEL_DOT_NUM;
|
2018-06-19 09:49:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-30 21:42:59 +01:00
|
|
|
/*In break mode only the height can change*/
|
2018-06-19 09:49:58 +02:00
|
|
|
else if(ext->long_mode == LV_LABEL_LONG_BREAK) {
|
2020-02-11 05:47:33 +01:00
|
|
|
size.y += lv_obj_get_style_pad_top(label, LV_LABEL_PART_MAIN) + lv_obj_get_style_pad_bottom(label, LV_LABEL_PART_MAIN);
|
2016-12-30 21:42:59 +01:00
|
|
|
lv_obj_set_height(label, size.y);
|
|
|
|
}
|
2018-09-25 16:21:31 +02:00
|
|
|
/*Do not set the size in Clip mode*/
|
|
|
|
else if(ext->long_mode == LV_LABEL_LONG_CROP) {
|
|
|
|
/*Do nothing*/
|
|
|
|
}
|
2017-10-05 11:29:21 +02:00
|
|
|
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_invalidate(label);
|
2016-12-30 21:42:59 +01:00
|
|
|
}
|
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
static void lv_label_revert_dots(lv_obj_t * label)
|
2017-11-13 16:11:05 +01:00
|
|
|
{
|
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
|
|
|
if(ext->long_mode != LV_LABEL_LONG_DOT) return;
|
|
|
|
if(ext->dot_end == LV_LABEL_DOT_END_INV) return;
|
|
|
|
uint32_t letter_i = ext->dot_end - LV_LABEL_DOT_NUM;
|
2019-04-04 07:15:40 +02:00
|
|
|
uint32_t byte_i = lv_txt_encoded_get_byte_id(ext->text, letter_i);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
/*Restore the characters*/
|
2019-06-06 06:05:40 +02:00
|
|
|
uint8_t i = 0;
|
|
|
|
char * dot_tmp = lv_label_get_dot_tmp(label);
|
2019-04-14 11:18:31 -07:00
|
|
|
while(ext->text[byte_i + i] != '\0') {
|
|
|
|
ext->text[byte_i + i] = dot_tmp[i];
|
2017-11-13 16:11:05 +01:00
|
|
|
i++;
|
|
|
|
}
|
2019-04-14 11:18:31 -07:00
|
|
|
ext->text[byte_i + i] = dot_tmp[i];
|
|
|
|
lv_label_dot_tmp_free(label);
|
2017-11-13 16:11:05 +01:00
|
|
|
|
|
|
|
ext->dot_end = LV_LABEL_DOT_END_INV;
|
|
|
|
}
|
2017-06-18 18:25:25 +02:00
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_ANIMATION
|
2017-11-23 21:28:36 +01:00
|
|
|
static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x)
|
2017-06-18 18:25:25 +02:00
|
|
|
{
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->offset.x = x;
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_invalidate(label);
|
2017-06-18 18:25:25 +02:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:28:36 +01:00
|
|
|
static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y)
|
2017-06-18 18:25:25 +02:00
|
|
|
{
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-04-04 07:15:40 +02:00
|
|
|
ext->offset.y = y;
|
2017-10-20 10:17:02 +02:00
|
|
|
lv_obj_invalidate(label);
|
2017-06-18 18:25:25 +02:00
|
|
|
}
|
2016-06-08 07:25:08 +02:00
|
|
|
#endif
|
2019-04-14 11:18:31 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Store `len` characters from `data`. Allocates space if necessary.
|
|
|
|
*
|
|
|
|
* @param label pointer to label object
|
|
|
|
* @param len Number of characters to store.
|
|
|
|
* @return true on success.
|
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
static bool lv_label_set_dot_tmp(lv_obj_t * label, char * data, uint16_t len)
|
|
|
|
{
|
2019-04-14 11:18:31 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_label_dot_tmp_free(label); /* Deallocate any existing space */
|
|
|
|
if(len > sizeof(char *)) {
|
2019-04-14 11:18:31 -07:00
|
|
|
/* Memory needs to be allocated. Allocates an additional byte
|
|
|
|
* for a NULL-terminator so it can be copied. */
|
2019-04-20 09:05:36 -04:00
|
|
|
ext->dot.tmp_ptr = lv_mem_alloc(len + 1);
|
2019-06-06 06:05:40 +02:00
|
|
|
if(ext->dot.tmp_ptr == NULL) {
|
2019-04-14 11:18:31 -07:00
|
|
|
LV_LOG_ERROR("Failed to allocate memory for dot_tmp_ptr");
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-20 09:05:36 -04:00
|
|
|
memcpy(ext->dot.tmp_ptr, data, len);
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot.tmp_ptr[len] = '\0';
|
|
|
|
ext->dot_tmp_alloc = true;
|
|
|
|
} else {
|
2019-04-14 11:18:31 -07:00
|
|
|
/* Characters can be directly stored in object */
|
|
|
|
ext->dot_tmp_alloc = false;
|
2019-04-20 09:05:36 -04:00
|
|
|
memcpy(ext->dot.tmp, data, len);
|
2019-04-14 11:18:31 -07:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the stored dot_tmp characters
|
|
|
|
* @param label pointer to label object
|
|
|
|
* @return char pointer to a stored characters. Is *not* necessarily NULL-terminated.
|
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
static char * lv_label_get_dot_tmp(lv_obj_t * label)
|
|
|
|
{
|
2019-04-14 11:18:31 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-06-06 06:05:40 +02:00
|
|
|
if(ext->dot_tmp_alloc) {
|
2019-04-20 09:05:36 -04:00
|
|
|
return ext->dot.tmp_ptr;
|
2019-06-06 06:05:40 +02:00
|
|
|
} else {
|
2019-04-20 09:05:36 -04:00
|
|
|
return ext->dot.tmp;
|
2019-04-14 11:18:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Free the dot_tmp_ptr field if it was previously allocated.
|
|
|
|
* Always clears the field
|
|
|
|
* @param label pointer to label object.
|
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
static void lv_label_dot_tmp_free(lv_obj_t * label)
|
|
|
|
{
|
2019-04-14 11:18:31 -07:00
|
|
|
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
2019-06-06 06:05:40 +02:00
|
|
|
if(ext->dot_tmp_alloc && ext->dot.tmp_ptr) {
|
2019-04-20 09:05:36 -04:00
|
|
|
lv_mem_free(ext->dot.tmp_ptr);
|
2019-04-14 11:18:31 -07:00
|
|
|
}
|
|
|
|
ext->dot_tmp_alloc = false;
|
2019-06-06 06:05:40 +02:00
|
|
|
ext->dot.tmp_ptr = NULL;
|
2019-04-14 11:18:31 -07:00
|
|
|
}
|
|
|
|
|
2020-02-11 05:47:33 +01:00
|
|
|
static void get_txt_coords(const lv_obj_t * label, lv_area_t * area)
|
|
|
|
{
|
|
|
|
lv_obj_get_coords(label, area);
|
|
|
|
|
|
|
|
lv_coord_t left = lv_obj_get_style_pad_left(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_coord_t right = lv_obj_get_style_pad_right(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_coord_t top = lv_obj_get_style_pad_top(label, LV_LABEL_PART_MAIN);
|
|
|
|
lv_coord_t bottom = lv_obj_get_style_pad_bottom(label, LV_LABEL_PART_MAIN);
|
|
|
|
area->x1 += left;
|
|
|
|
area->x2 -= right;
|
|
|
|
area->y1 += top;
|
|
|
|
area->y2 -= bottom;
|
|
|
|
}
|
|
|
|
|
2017-11-27 17:48:54 +01:00
|
|
|
#endif
|