From f40ee380c898ef6ed70862ea5d770b44a711e5b2 Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 09:47:45 -0700 Subject: [PATCH 1/8] Optimized bitfields in lv_btn and lv_label. In lv_label, changed selection fields from int to uint16. Because of this change, added getters/setters. Added LV_LABEL_SELECTION_EN option in lv_conf to enable/disable the selection fields --- lv_conf_template.h | 1 + src/lv_objx/lv_btn.h | 2 +- src/lv_objx/lv_label.c | 67 ++++++++++++++++++++++++++++++++++++++---- src/lv_objx/lv_label.h | 45 ++++++++++++++++++++++++---- src/lv_objx/lv_ta.c | 47 +++++++++++++++-------------- 5 files changed, 126 insertions(+), 36 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index d6e450290..dc71340a2 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -346,6 +346,7 @@ typedef void * lv_obj_user_data_t; #if LV_USE_LABEL != 0 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ # define LV_LABEL_DEF_SCROLL_SPEED 25 +# define LV_LABEL_SELECTION_EN 1 #endif /*LED (dependencies: -)*/ diff --git a/src/lv_objx/lv_btn.h b/src/lv_objx/lv_btn.h index 2e0d12101..cd23e24e3 100644 --- a/src/lv_objx/lv_btn.h +++ b/src/lv_objx/lv_btn.h @@ -55,12 +55,12 @@ typedef struct lv_cont_ext_t cont; /*Ext. of ancestor*/ /*New data for this type */ const lv_style_t * styles[LV_BTN_STATE_NUM]; /*Styles in each state*/ - lv_btn_state_t state; /*Current state of the button from 'lv_btn_state_t' enum*/ #if LV_BTN_INK_EFFECT uint16_t ink_in_time; /*[ms] Time of ink fill effect (0: disable ink effect)*/ uint16_t ink_wait_time; /*[ms] Wait before the ink disappears */ uint16_t ink_out_time; /*[ms] Time of ink disappearing*/ #endif + lv_btn_state_t state : 3; /*Current state of the button from 'lv_btn_state_t' enum*/ uint8_t toggle : 1; /*1: Toggle enabled*/ } lv_btn_ext_t; diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index e3c50d164..f9baded8f 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -90,8 +90,11 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->anim_speed = LV_LABEL_DEF_SCROLL_SPEED; ext->offset.x = 0; ext->offset.y = 0; - ext->selection_start = -1; - ext->selection_end = -1; +#if LV_LABEL_SELECTION_EN + ext->selection_start = 0; + ext->selection_end = 0; + ext->selection_en = 0; +#endif lv_obj_set_design_cb(new_label, lv_label_design); lv_obj_set_signal_cb(new_label, lv_label_signal); @@ -339,6 +342,34 @@ void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed) } } +void lv_label_set_selection_start( const lv_obj_t * label, int index ) { +#if LV_LABEL_SELECTION_EN + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( index > 0 ) { + ext->selection_en = 1; + ext->selection_start = index; + } + else { + ext->selection_en = 0; + ext->selection_start = 0; + } +#endif +} + +void lv_label_set_selection_end( const lv_obj_t * label, int index ) { +#if LV_LABEL_SELECTION_EN + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( index > 0 ) { + ext->selection_en = 1; + ext->selection_end = index; + } + else { + ext->selection_en = 0; + ext->selection_end = 0; + } +#endif +} + /*===================== * Getter functions *====================*/ @@ -558,6 +589,31 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) return lv_encoded_get_char_id(txt, i); } +int lv_label_get_selection_start( const lv_obj_t * label ) { +#if LV_LABEL_SELECTION_EN + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->selection_en ) + return ext->selection_start; + else + return -1; +#else + return -1; +#endif +} + +int lv_label_get_selection_end( const lv_obj_t * label ) { +#if LV_LABEL_SELECTION_EN + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->selection_en ) + return ext->selection_end; + else + return -1; +#else + return -1; +#endif +} + + /** * Check if a character is drawn under a point. * @param label Label object @@ -763,7 +819,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ } lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, - ext->selection_start, ext->selection_end); + lv_label_get_selection_start(label), lv_label_get_selection_end(label)); if(ext->long_mode == LV_LABEL_LONG_ROLL_CIRC) { lv_point_t size; @@ -776,8 +832,9 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.x = ext->offset.x + size.x + lv_font_get_width(style->text.font, ' ') * ANIM_WAIT_CHAR_COUNT; ofs.y = ext->offset.y; + lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - ext->selection_start, ext->selection_end); + lv_label_get_selection_start(label), lv_label_get_selection_end(label)); } /*Draw the text again below the original to make an circular effect */ @@ -785,7 +842,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.x = ext->offset.x; ofs.y = ext->offset.y + size.y + lv_font_get_height(style->text.font); lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - ext->selection_start, ext->selection_end); + lv_label_get_selection_start(label), lv_label_get_selection_end(label)); } } } diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 05f4e1ace..87e658373 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -62,20 +62,23 @@ typedef struct /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ char * text; /*Text of the label*/ - lv_label_long_mode_t long_mode; /*Determinate what to do with the long texts*/ - char dot_tmp[LV_LABEL_DOT_NUM * 4 + - 1]; /*Store the character which are replaced by dots (Handled by the library)*/ - + char dot_tmp[LV_LABEL_DOT_NUM * 4 ]; /*Store the character which are replaced by dots (Handled by the library)*/ uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ lv_point_t offset; /*Text draw position offset*/ + +#if LV_LABEL_SELECTION_EN + uint16_t selection_start; /*Left-most selection character*/ + uint16_t selection_end; /*Right-most selection character*/ + uint8_t selection_en : 1; /*True if text is selection */ +#endif + + lv_label_long_mode_t long_mode : 3; /*Determinate what to do with the long texts*/ uint8_t static_txt : 1; /*Flag to indicate the text is static*/ uint8_t align : 2; /*Align type from 'lv_label_align_t'*/ uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_ROLL)*/ uint8_t body_draw : 1; /*Draw background body*/ - int selection_start; /*Left-most selection character*/ - int selection_end; /*Right-most selection character*/ } lv_label_ext_t; /********************** @@ -164,6 +167,21 @@ static inline void lv_label_set_style(lv_obj_t * label, const lv_style_t * style { lv_obj_set_style(label, style); } + +/** + * @brief Set the selection start index. + * @param label pointer to a label object. + * @param index index to set. -1 to select nothing. + */ +void lv_label_set_selection_start( const lv_obj_t * label, int index ); + +/** + * @brief Set the selection end index. + * @param label pointer to a label object. + * @param index index to set. -1 to select nothing. + */ +void lv_label_set_selection_end( const lv_obj_t * label, int index ); + /*===================== * Getter functions *====================*/ @@ -246,6 +264,21 @@ static inline const lv_style_t * lv_label_get_style(const lv_obj_t * label) return lv_obj_get_style(label); } +/** + * @brief Get the selection start index. + * @param label pointer to a label object. + * @return selection start index. -1 if nothing is selected. + */ +int lv_label_get_selection_start( const lv_obj_t * label ); + +/** + * @brief Get the selection end index. + * @param label pointer to a label object. + * @return selection end index. -1 if nothing is selected. + */ +int lv_label_get_selection_end( const lv_obj_t * label ); + + /*===================== * Other functions *====================*/ diff --git a/src/lv_objx/lv_ta.c b/src/lv_objx/lv_ta.c index 7349ebd66..e37f6ad9f 100644 --- a/src/lv_objx/lv_ta.c +++ b/src/lv_objx/lv_ta.c @@ -955,17 +955,15 @@ const lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type) void lv_ta_get_selection(lv_obj_t * ta, int * sel_start, int * sel_end) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); + + *sel_start = lv_label_get_selection_start(ext->label) ; + *sel_end = lv_label_get_selection_end(ext->label) ; /*Force both values to -1 if there is no selection*/ - if(ext_label->selection_start == -1 || ext_label->selection_end == -1) { + if( *sel_start == -1 || *sel_end == -1) { *sel_start = -1; *sel_end = -1; - return; } - - *sel_start = ext_label->selection_start; - *sel_end = ext_label->selection_end; } /** @@ -976,9 +974,7 @@ void lv_ta_get_selection(lv_obj_t * ta, int * sel_start, int * sel_end) bool lv_ta_text_is_selected(const lv_obj_t * ta) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); - - return (ext_label->selection_start == -1 || ext_label->selection_end == -1); + return (lv_label_get_selection_start(ext->label) == -1 || lv_label_get_selection_end(ext->label) == -1); } /** @@ -1004,11 +1000,10 @@ bool lv_ta_get_sel_mode(lv_obj_t * ta) void lv_ta_clear_selection(lv_obj_t * ta) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); - if(ext_label->selection_start != -1 || ext_label->selection_end != -1) { - ext_label->selection_start = -1; - ext_label->selection_end = -1; + if(lv_label_get_selection_start(ext->label) == -1 || lv_label_get_selection_end(ext->label) == -1){ + lv_label_set_selection_start(ext->label, -1); + lv_label_set_selection_end(ext->label, -1); lv_obj_invalidate(ta); } } @@ -1695,24 +1690,28 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, if(ext->selecting) { /*If the selected area has changed then update the real values and*/ /*invalidate the text area.*/ + int sel_start, sel_end; + sel_start = lv_label_get_selection_start(ext->label); + sel_end = lv_label_get_selection_end(ext->label); + if(ext->tmp_sel_start > ext->tmp_sel_end) { - if(ext_label->selection_start != ext->tmp_sel_end || - ext_label->selection_end != ext->tmp_sel_start) { - ext_label->selection_start = ext->tmp_sel_end; - ext_label->selection_end = ext->tmp_sel_start; + if(sel_start != ext->tmp_sel_end || + sel_end != ext->tmp_sel_start) { + sel_start = ext->tmp_sel_end; + sel_end = ext->tmp_sel_start; lv_obj_invalidate(ta); } } else if(ext->tmp_sel_start < ext->tmp_sel_end) { - if(ext_label->selection_start != ext->tmp_sel_start || - ext_label->selection_end != ext->tmp_sel_end) { - ext_label->selection_start = ext->tmp_sel_start; - ext_label->selection_end = ext->tmp_sel_end; + if(sel_start != ext->tmp_sel_start || + sel_end != ext->tmp_sel_end) { + sel_start = ext->tmp_sel_start; + sel_end = ext->tmp_sel_end; lv_obj_invalidate(ta); } } else { - if(ext_label->selection_start != -1 || ext_label->selection_end != -1) { - ext_label->selection_start = -1; - ext_label->selection_end = -1; + if(sel_start != -1 || sel_end != -1) { + sel_start = -1; + sel_end = -1; lv_obj_invalidate(ta); } } From 50edf4e1f8ab651dfc9c16d1b216d4b767836b13 Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 09:50:02 -0700 Subject: [PATCH 2/8] Fixed lv_label selection start/end setters to allow the 0th index. --- src/lv_objx/lv_label.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index f9baded8f..630b6c7c1 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -345,7 +345,7 @@ void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed) void lv_label_set_selection_start( const lv_obj_t * label, int index ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); - if( index > 0 ) { + if( index >= 0 ) { ext->selection_en = 1; ext->selection_start = index; } @@ -359,7 +359,7 @@ void lv_label_set_selection_start( const lv_obj_t * label, int index ) { void lv_label_set_selection_end( const lv_obj_t * label, int index ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); - if( index > 0 ) { + if( index >= 0 ) { ext->selection_en = 1; ext->selection_end = index; } From 3d7713717831ff7f8c30ca24bd64b2a3203dbf0a Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 11:18:31 -0700 Subject: [PATCH 3/8] lv_label: dynamically allocate space for dots if necessary. If the required dots storage space is 4 or less bytes, directly stores them in the extended data object --- src/lv_core/lv_obj.h | 3 +- src/lv_objx/lv_label.c | 97 +++++++++++++++++++++++++++++++++++++----- src/lv_objx/lv_label.h | 6 ++- 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 1fa0bf1df..7845ad7d6 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -208,8 +208,7 @@ typedef struct _lv_obj_t `lv_protect_t`*/ lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/ - lv_coord_t - ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ + lv_coord_t ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ #if LV_OBJ_REALIGN lv_reailgn_t realign; #endif diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 630b6c7c1..d4d02b5ae 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -43,6 +43,11 @@ static void lv_label_revert_dots(lv_obj_t * label); 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); #endif + +static bool lv_label_set_dot_tmp(lv_obj_t *label, char *data, int len); +static char * lv_label_get_dot_tmp(lv_obj_t *label); +static void lv_label_dot_tmp_free(lv_obj_t *label); + /********************** * STATIC VARIABLES **********************/ @@ -95,6 +100,8 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->selection_end = 0; ext->selection_en = 0; #endif + ext->dot_tmp_ptr = NULL; + ext->dot_tmp_alloc = 0; lv_obj_set_design_cb(new_label, lv_label_design); lv_obj_set_signal_cb(new_label, lv_label_signal); @@ -126,7 +133,13 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text)); } - memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); + if(copy_ext->dot_tmp_alloc && copy_ext->dot_tmp_ptr ){ + int len = strlen(copy_ext->dot_tmp_ptr); + lv_label_set_dot_tmp(new_label, ext->dot_tmp_ptr, len); + } + else{ + memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); + } ext->dot_end = copy_ext->dot_end; /*Refresh the style with new signal function*/ @@ -870,6 +883,7 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param lv_mem_free(ext->text); ext->text = NULL; } + lv_label_dot_tmp_free(label); } else if(sign == LV_SIGNAL_STYLE_CHG) { /*Revert dots for proper refresh*/ lv_label_revert_dots(label); @@ -1040,15 +1054,13 @@ static void lv_label_refr_text(lv_obj_t * label) lv_txt_encoded_next(ext->text, &byte_id); } - memcpy(ext->dot_tmp, &ext->text[byte_id_ori], len); - ext->dot_tmp[len] = '\0'; /*Close with a zero*/ - - for(i = 0; i < LV_LABEL_DOT_NUM; i++) { - ext->text[byte_id_ori + i] = '.'; + if( lv_label_set_dot_tmp(label, &ext->text[byte_id_ori], len ) ){ + 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'; + ext->dot_end = letter_id + LV_LABEL_DOT_NUM; } - ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0'; - - ext->dot_end = letter_id + LV_LABEL_DOT_NUM; } } /*In break mode only the height can change*/ @@ -1073,10 +1085,13 @@ static void lv_label_revert_dots(lv_obj_t * label) /*Restore the characters*/ uint8_t i = 0; - while(ext->dot_tmp[i] != '\0') { - ext->text[byte_i + i] = ext->dot_tmp[i]; + char* dot_tmp = lv_label_get_dot_tmp(label); + while(ext->text[byte_i + i] != '\0') { + ext->text[byte_i + i] = dot_tmp[i]; i++; } + ext->text[byte_i + i] = dot_tmp[i]; + lv_label_dot_tmp_free(label); ext->dot_end = LV_LABEL_DOT_END_INV; } @@ -1096,4 +1111,64 @@ static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y) lv_obj_invalidate(label); } #endif + +/** + * 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. + */ +static bool lv_label_set_dot_tmp(lv_obj_t *label, char *data, int len){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + lv_label_dot_tmp_free( label ); /* Deallocate any existing space */ + if( len > 4 ){ + /* Memory needs to be allocated. Allocates an additional byte + * for a NULL-terminator so it can be copied. */ + ext->dot_tmp_ptr = lv_mem_alloc(len + 1); + if( ext->dot_tmp_ptr == NULL ){ + LV_LOG_ERROR("Failed to allocate memory for dot_tmp_ptr"); + return false; + } + memcpy(ext->dot_tmp_ptr, data, len); + ext->dot_tmp_ptr[len]='\0'; + ext->dot_tmp_alloc = true; + } + else { + /* Characters can be directly stored in object */ + ext->dot_tmp_alloc = false; + memcpy(ext->dot_tmp, data, len); + } + 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. + */ +static char * lv_label_get_dot_tmp(lv_obj_t *label){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->dot_tmp_alloc ){ + return ext->dot_tmp_ptr; + } + else{ + return ext->dot_tmp; + } +} + +/** + * Free the dot_tmp_ptr field if it was previously allocated. + * Always clears the field + * @param label pointer to label object. + */ +static void lv_label_dot_tmp_free(lv_obj_t *label){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->dot_tmp_alloc && ext->dot_tmp_ptr ){ + lv_mem_free(ext->dot_tmp_ptr); + } + ext->dot_tmp_alloc = false; + ext->dot_tmp_ptr = NULL; +} + #endif diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 87e658373..98f7297f3 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -62,7 +62,10 @@ typedef struct /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ char * text; /*Text of the label*/ - char dot_tmp[LV_LABEL_DOT_NUM * 4 ]; /*Store the character which are replaced by dots (Handled by the library)*/ + union{ + char * dot_tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled by the library)*/ + char dot_tmp[4]; /* Directly store the characters if <=4 characters */ + }; uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ lv_point_t offset; /*Text draw position offset*/ @@ -79,6 +82,7 @@ typedef struct uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_ROLL)*/ uint8_t body_draw : 1; /*Draw background body*/ + uint8_t dot_tmp_alloc : 1; /*True if dot_tmp has been allocated. False if dot_tmp directly holds up to 4 bytes of characters */ } lv_label_ext_t; /********************** From 30dcf6835150c2c526b897730cf174c0c9d2bbad Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 13:52:54 -0700 Subject: [PATCH 4/8] lv_label: change magic number 4 to sizeof(char *) --- src/lv_objx/lv_label.c | 2 +- src/lv_objx/lv_label.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index d4d02b5ae..42d17e18b 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -1122,7 +1122,7 @@ static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y) static bool lv_label_set_dot_tmp(lv_obj_t *label, char *data, int len){ lv_label_ext_t * ext = lv_obj_get_ext_attr(label); lv_label_dot_tmp_free( label ); /* Deallocate any existing space */ - if( len > 4 ){ + if( len > sizeof(char *) ){ /* Memory needs to be allocated. Allocates an additional byte * for a NULL-terminator so it can be copied. */ ext->dot_tmp_ptr = lv_mem_alloc(len + 1); diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 98f7297f3..7a0428c56 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -64,7 +64,7 @@ typedef struct char * text; /*Text of the label*/ union{ char * dot_tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled by the library)*/ - char dot_tmp[4]; /* Directly store the characters if <=4 characters */ + char dot_tmp[ sizeof(char *) ]; /* Directly store the characters if <=4 characters */ }; uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ From b3f60153cf216eb1194e9b137b8b3d8fabd88fb8 Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 14:49:42 -0700 Subject: [PATCH 5/8] lv_label: fixed missing dot_tmp_alloc copy on create --- src/lv_objx/lv_label.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 42d17e18b..a27dcd50b 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -140,6 +140,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) else{ memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); } + ext->dot_tmp_alloc = copy_ext->dot_tmp_alloc; ext->dot_end = copy_ext->dot_end; /*Refresh the style with new signal function*/ From c40148150902845d2cc8177ef40f6b876d594f35 Mon Sep 17 00:00:00 2001 From: BrianPugh Date: Mon, 15 Apr 2019 21:55:22 -0700 Subject: [PATCH 6/8] lv_obj.h re-added missing #if LV_USE_OBJ_REALIGN in lv_obj_t --- src/lv_core/lv_obj.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 81768d336..6d43c865c 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -223,7 +223,8 @@ typedef struct _lv_obj_t lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/ lv_coord_t ext_draw_pad; /*EXTtend the size in every direction for drawing. */ - + +#if LV_USE_OBJ_REALIGN lv_reailgn_t realign; #endif From d7b193d3fc40531b4536e932dc289bd37a83433a Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Mon, 15 Apr 2019 22:03:12 -0700 Subject: [PATCH 7/8] lv_label: change to . Repeated header documentation in c file. --- src/lv_objx/lv_label.c | 18 ++++++++++++++---- src/lv_objx/lv_label.h | 8 ++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index f66063dc2..d84747397 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -356,7 +356,7 @@ void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed) } } -void lv_label_set_selection_start( const lv_obj_t * label, int index ) { +void lv_label_set_selection_start( lv_obj_t * label, int32_t index ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); if( index >= 0 ) { @@ -370,7 +370,7 @@ void lv_label_set_selection_start( const lv_obj_t * label, int index ) { #endif } -void lv_label_set_selection_end( const lv_obj_t * label, int index ) { +void lv_label_set_selection_end( lv_obj_t * label, int32_t index ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); if( index >= 0 ) { @@ -603,7 +603,12 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) return lv_encoded_get_char_id(txt, i); } -int lv_label_get_selection_start( const lv_obj_t * label ) { +/** + * @brief Get the selection start index. + * @param label pointer to a label object. + * @return selection start index. -1 if nothing is selected. + */ +int32_t lv_label_get_selection_start( const lv_obj_t * label ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); if( ext->selection_en ) @@ -615,7 +620,12 @@ int lv_label_get_selection_start( const lv_obj_t * label ) { #endif } -int lv_label_get_selection_end( const lv_obj_t * label ) { +/** + * @brief Get the selection end index. + * @param label pointer to a label object. + * @return selection end index. -1 if nothing is selected. + */ +int32_t lv_label_get_selection_end( const lv_obj_t * label ) { #if LV_LABEL_SELECTION_EN lv_label_ext_t * ext = lv_obj_get_ext_attr(label); if( ext->selection_en ) diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 7a0428c56..acc9864df 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -177,14 +177,14 @@ static inline void lv_label_set_style(lv_obj_t * label, const lv_style_t * style * @param label pointer to a label object. * @param index index to set. -1 to select nothing. */ -void lv_label_set_selection_start( const lv_obj_t * label, int index ); +void lv_label_set_selection_start( lv_obj_t * label, int32_t index ); /** * @brief Set the selection end index. * @param label pointer to a label object. * @param index index to set. -1 to select nothing. */ -void lv_label_set_selection_end( const lv_obj_t * label, int index ); +void lv_label_set_selection_end( lv_obj_t * label, int32_t index ); /*===================== * Getter functions @@ -273,14 +273,14 @@ static inline const lv_style_t * lv_label_get_style(const lv_obj_t * label) * @param label pointer to a label object. * @return selection start index. -1 if nothing is selected. */ -int lv_label_get_selection_start( const lv_obj_t * label ); +int32_t lv_label_get_selection_start( const lv_obj_t * label ); /** * @brief Get the selection end index. * @param label pointer to a label object. * @return selection end index. -1 if nothing is selected. */ -int lv_label_get_selection_end( const lv_obj_t * label ); +int32_t lv_label_get_selection_end( const lv_obj_t * label ); /*===================== From 41fc80e96bb3f55dd8b4740a563f446db2b23689 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 18 Apr 2019 07:11:43 +0200 Subject: [PATCH 8/8] text_sel: minor fixes and renames --- lv_conf_template.h | 2 +- src/lv_objx/lv_label.c | 21 +++++++------- src/lv_objx/lv_label.h | 6 ++-- src/lv_objx/lv_ta.c | 64 ++++++++++++++++++++++++++++++++++-------- src/lv_objx/lv_ta.h | 30 ++++++++++---------- 5 files changed, 82 insertions(+), 41 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 6fb68df88..fe16371be 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -354,7 +354,7 @@ typedef void * lv_obj_user_data_t; /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ # define LV_LABEL_DEF_SCROLL_SPEED 25 # define LV_LABEL_WAIT_CHAR_COUNT 3 /* Waiting period at beginning/end of animation cycle */ -# define LV_LABEL_TEXT_SELECTION 1 +# define LV_LABEL_TEXT_SEL 1 /*Enable selecting text of the label */ #endif /*LED (dependencies: -)*/ diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index d65cdcd1a..5cdad6147 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -93,7 +93,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->anim_speed = LV_LABEL_DEF_SCROLL_SPEED; ext->offset.x = 0; ext->offset.y = 0; -#if LV_LABEL_TEXT_SELECTION +#if LV_LABEL_TEXT_SEL ext->txt_sel_start = LV_LABEL_TEXT_SEL_OFF; ext->txt_sel_end = LV_LABEL_TEXT_SEL_OFF; #endif @@ -354,7 +354,7 @@ void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed) } void lv_label_set_text_sel_start( lv_obj_t * label, uint16_t index ) { -#if LV_LABEL_TEXT_SELECTION +#if LV_LABEL_TEXT_SEL lv_label_ext_t * ext = lv_obj_get_ext_attr(label); ext->txt_sel_start = index; lv_obj_invalidate(label); @@ -363,7 +363,7 @@ void lv_label_set_text_sel_start( lv_obj_t * label, uint16_t index ) { void lv_label_set_text_sel_end( lv_obj_t * label, uint16_t index ) { -#if LV_LABEL_TEXT_SELECTION +#if LV_LABEL_TEXT_SEL lv_label_ext_t * ext = lv_obj_get_ext_attr(label); ext->txt_sel_end = index; lv_obj_invalidate(label); @@ -594,8 +594,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) * @param label pointer to a label object. * @return selection start index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. */ -int32_t lv_label_get_txt_sel_start( const lv_obj_t * label ) { -#if LV_LABEL_TEXT_SELECTION +uint16_t lv_label_get_text_sel_start( const lv_obj_t * label ) { +#if LV_LABEL_TEXT_SEL lv_label_ext_t * ext = lv_obj_get_ext_attr(label); return ext->txt_sel_start; @@ -609,11 +609,12 @@ int32_t lv_label_get_txt_sel_start( const lv_obj_t * label ) { * @param label pointer to a label object. * @return selection end index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. */ -int32_t lv_label_get_tsxt_sel_end( const lv_obj_t * label ) { -#if LV_LABEL_TEXT_SELECTION +uint16_t lv_label_get_text_sel_end( const lv_obj_t * label ) { +#if LV_LABEL_TEXT_SEL lv_label_ext_t * ext = lv_obj_get_ext_attr(label); return ext->txt_sel_end; #else + (void) label; /*Unused*/ return LV_LABEL_TEXT_SEL_OFF; #endif } @@ -824,7 +825,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ } lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, - lv_label_get_txt_sel_start(label), lv_label_get_tsxt_sel_end(label)); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label)); if(ext->long_mode == LV_LABEL_LONG_ROLL_CIRC) { lv_point_t size; @@ -839,7 +840,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.y = ext->offset.y; lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - lv_label_get_txt_sel_start(label), lv_label_get_tsxt_sel_end(label)); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label)); } /*Draw the text again below the original to make an circular effect */ @@ -847,7 +848,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.x = ext->offset.x; ofs.y = ext->offset.y + size.y + lv_font_get_height(style->text.font); lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - lv_label_get_txt_sel_start(label), lv_label_get_tsxt_sel_end(label)); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label)); } } } diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 285df0f6c..cd2e25a9e 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -71,7 +71,7 @@ typedef struct uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ lv_point_t offset; /*Text draw position offset*/ -#if LV_LABEL_TEXT_SELECTION +#if LV_LABEL_TEXT_SEL uint16_t txt_sel_start; /*Left-most selection character*/ uint16_t txt_sel_end; /*Right-most selection character*/ #endif @@ -273,14 +273,14 @@ static inline const lv_style_t * lv_label_get_style(const lv_obj_t * label) * @param label pointer to a label object. * @return selection start index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. */ -int32_t lv_label_get_text_sel_start( const lv_obj_t * label ); +uint16_t lv_label_get_text_sel_start( const lv_obj_t * label ); /** * @brief Get the selection end index. * @param label pointer to a label object. * @return selection end index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. */ -int32_t lv_label_get_tsxt_sel_end( const lv_obj_t * label ); +uint16_t lv_label_get_text_sel_end( const lv_obj_t * label ); /*===================== diff --git a/src/lv_objx/lv_ta.c b/src/lv_objx/lv_ta.c index 7a9b76213..b6a912ba0 100644 --- a/src/lv_objx/lv_ta.c +++ b/src/lv_objx/lv_ta.c @@ -795,10 +795,16 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, const lv_style_t * style */ void lv_ta_set_text_sel(lv_obj_t * ta, bool en) { +#if LV_LABEL_TEXT_SEL lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + ext->text_sel_en = en; if(!en) lv_ta_clear_selection(ta); +#else + (void) ta; /*Unused*/ + (void) en; /*Unused*/ +#endif } /*===================== @@ -950,8 +956,19 @@ const lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type) */ bool lv_ta_text_is_selected(const lv_obj_t * ta) { - lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - return (lv_label_get_txt_sel_start(ext->label) == LV_LABEL_TEXT_SEL_OFF || lv_label_get_tsxt_sel_end(ext->label) == LV_LABEL_TEXT_SEL_OFF); +#if LV_LABEL_TEXT_SEL + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); + + if((lv_label_get_text_sel_start(ext->label) == LV_LABEL_TEXT_SEL_OFF || + lv_label_get_text_sel_end(ext->label) == LV_LABEL_TEXT_SEL_OFF)){ + return true; + } else { + return false; + } +#else + (void) ta; /*Unused*/ + return false; +#endif } /** @@ -959,11 +976,15 @@ bool lv_ta_text_is_selected(const lv_obj_t * ta) * @param ta pointer to a text area object * @return true: selection mode is enabled, false: disabled */ -bool lv_ta_get_text_sel_mode(lv_obj_t * ta) +bool lv_ta_get_text_sel_en(lv_obj_t * ta) { +#if LV_LABEL_TEXT_SEL lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - return ext->text_sel_en; +#else + (void) ta; /*Unused*/ + return false; +#endif } /*===================== @@ -976,13 +997,17 @@ bool lv_ta_get_text_sel_mode(lv_obj_t * ta) */ void lv_ta_clear_selection(lv_obj_t * ta) { +#if LV_LABEL_TEXT_SEL lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - if(lv_label_get_txt_sel_start(ext->label) != LV_LABEL_TEXT_SEL_OFF || - lv_label_get_tsxt_sel_end(ext->label) != LV_LABEL_TEXT_SEL_OFF){ + if(lv_label_get_text_sel_start(ext->label) != LV_LABEL_TEXT_SEL_OFF || + lv_label_get_text_sel_end(ext->label) != LV_LABEL_TEXT_SEL_OFF){ lv_label_set_text_sel_start(ext->label, LV_LABEL_TEXT_SEL_OFF); lv_label_set_text_sel_end(ext->label, LV_LABEL_TEXT_SEL_OFF); } +#else + (void) ta; /*Unused*/ +#endif } /** @@ -1612,18 +1637,12 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, } lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); lv_area_t label_coords; - bool click_outside_label; - uint16_t index_of_char_at_position; - lv_obj_get_coords(ext->label, &label_coords); lv_point_t point_act, vect_act; - lv_indev_get_point(click_source, &point_act); - lv_indev_get_vect(click_source, &vect_act); if(point_act.x < 0 || point_act.y < 0) return; /*Ignore event from keypad*/ @@ -1633,6 +1652,12 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_coord_t label_width = lv_obj_get_width(ext->label); + uint16_t index_of_char_at_position; + + +#if LV_LABEL_TEXT_SEL + lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); + bool click_outside_label; /*Check if the click happened on the left side of the area outside the label*/ if(relative_position.x < 0) { index_of_char_at_position = 0; @@ -1697,6 +1722,21 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, ext->text_sel_in_prog = 0; } } +#else + /*Check if the click happened on the left side of the area outside the label*/ + if(relative_position.x < 0) { + index_of_char_at_position = 0; + } + /*Check if the click happened on the right side of the area outside the label*/ + else if(relative_position.x >= label_width) { + index_of_char_at_position = LV_TA_CURSOR_LAST; + } else { + index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position); + } + + if(sign == LV_SIGNAL_PRESSED) + lv_ta_set_cursor_pos(ta, index_of_char_at_position); +#endif } #endif diff --git a/src/lv_objx/lv_ta.h b/src/lv_objx/lv_ta.h index 9757ea152..41a5b4579 100644 --- a/src/lv_objx/lv_ta.h +++ b/src/lv_objx/lv_ta.h @@ -59,8 +59,7 @@ typedef struct lv_page_ext_t page; /*Ext. of ancestor*/ /*New data for this type */ lv_obj_t * label; /*Label of the text area*/ - lv_obj_t * placeholder; /*Place holder label of the text area, only visible if text is an empty - string*/ + lv_obj_t * placeholder; /*Place holder label. only visible if text is an empty string*/ char * pwd_tmp; /*Used to store the original text in password mode*/ const char * accapted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint16_t max_length; /*The max. number of characters. 0: no limit*/ @@ -68,21 +67,22 @@ typedef struct uint8_t one_line : 1; /*One line mode (ignore line breaks)*/ struct { - const lv_style_t * style; /*Style of the cursor (NULL to use label's style)*/ - lv_coord_t valid_x; /*Used when stepping up/down in text area when stepping to a shorter - line. (Handled by the library)*/ - uint16_t - pos; /*The current cursor position (0: before 1. letter; 1: before 2. letter etc.)*/ - lv_area_t area; /*Cursor area relative to the Text Area*/ - uint16_t txt_byte_pos; /*Byte index of the letter after (on) the cursor*/ - lv_cursor_type_t type : 4; /*Shape of the cursor*/ - uint8_t - state : 1; /*Indicates that the cursor is visible now or not (Handled by the library)*/ + const lv_style_t * style; /* Style of the cursor (NULL to use label's style)*/ + lv_coord_t valid_x; /* Used when stepping up/down to a shorter line. + * (Used by the library)*/ + uint16_t pos; /* The current cursor position + * (0: before 1st letter; 1: before 2nd letter ...)*/ + lv_area_t area; /* Cursor area relative to the Text Area*/ + uint16_t txt_byte_pos; /* Byte index of the letter after (on) the cursor*/ + lv_cursor_type_t type : 4; /* Shape of the cursor*/ + uint8_t state : 1; /*Cursor is visible now or not (Handled by the library)*/ } cursor; - int tmp_sel_start; /*Temporary value*/ - int tmp_sel_end; /*Temporary value*/ +#if LV_LABEL_TEXT_SEL + uint16_t tmp_sel_start; /*Temporary value*/ + uint16_t tmp_sel_end; /*Temporary value*/ uint8_t text_sel_in_prog : 1; /*User is in process of selecting */ uint8_t text_sel_en : 1; /*Text can be selected on this text area*/ +#endif } lv_ta_ext_t; enum { @@ -388,7 +388,7 @@ bool lv_ta_text_is_selected(const lv_obj_t * ta); * @param ta pointer to a text area object * @return true: selection mode is enabled, false: disabled */ -bool lv_ta_get_text_sel_mode(lv_obj_t * ta); +bool lv_ta_get_text_sel_en(lv_obj_t * ta); /*===================== * Other functions