diff --git a/lv_conf_template.h b/lv_conf_template.h index a591eb9fd..fe16371be 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -354,6 +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_SEL 1 /*Enable selecting text of the label */ #endif /*LED (dependencies: -)*/ diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 014ded5e6..d505f137f 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -224,6 +224,7 @@ 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 diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 332324c6f..bb0f2c4d2 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -50,12 +50,12 @@ static uint8_t hex_char_to_num(char hex); * @param txt 0 terminated text to write * @param flag settings for the text from 'txt_flag_t' enum * @param offset text offset in x and y direction (NULL if unused) - * @param sel_start start index of selected area (-1 if none) - * @param sel_end end index of selected area (-1 if none) + * @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none) + * @param sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none) */ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, const char * txt, lv_txt_flag_t flag, lv_point_t * offset, - int sel_start, int sel_end) + uint16_t sel_start, uint16_t sel_end) { const lv_font_t * font = style->text.font; lv_coord_t w; @@ -183,7 +183,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st letter_w = lv_font_get_width(font, letter); - if(sel_start != -1 && sel_end != -1) { + if(sel_start != 0xFFFF && sel_end != 0xFFFF) { int char_ind = lv_encoded_get_char_id(txt, i); /*Do not draw the rectangle on the character at `sel_start`.*/ if(char_ind > sel_start && char_ind <= sel_end) { diff --git a/src/lv_draw/lv_draw_label.h b/src/lv_draw/lv_draw_label.h index b51961d94..11b0c8235 100644 --- a/src/lv_draw/lv_draw_label.h +++ b/src/lv_draw/lv_draw_label.h @@ -36,12 +36,12 @@ extern "C" { * @param txt 0 terminated text to write * @param flag settings for the text from 'txt_flag_t' enum * @param offset text offset in x and y direction (NULL if unused) - * @param sel_start start index of selected area (-1 if none) - * @param sel_end end index of selected area (-1 if none) + * @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none) + * @param sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none) */ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, const char * txt, lv_txt_flag_t flag, lv_point_t * offset, - int sel_start, int sel_end); + uint16_t sel_start, uint16_t sel_end); /********************** * MACROS 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 70ff1507c..5cdad6147 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -41,6 +41,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, 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); + /********************** * STATIC VARIABLES **********************/ @@ -88,8 +93,12 @@ 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_TEXT_SEL + ext->txt_sel_start = LV_LABEL_TEXT_SEL_OFF; + ext->txt_sel_end = LV_LABEL_TEXT_SEL_OFF; +#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); @@ -121,7 +130,14 @@ 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_tmp_alloc = copy_ext->dot_tmp_alloc; ext->dot_end = copy_ext->dot_end; /*Refresh the style with new signal function*/ @@ -337,6 +353,23 @@ 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_SEL + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + ext->txt_sel_start = index; + lv_obj_invalidate(label); +#endif +} + +void lv_label_set_text_sel_end( lv_obj_t * label, uint16_t index ) +{ +#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); +#endif +} + /*===================== * Getter functions *====================*/ @@ -556,6 +589,37 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) return lv_encoded_get_char_id(txt, i); } +/** + * @brief Get the selection start index. + * @param label pointer to a label object. + * @return selection start index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. + */ +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; + +#else + return LV_LABEL_TEXT_SEL_OFF; +#endif +} + +/** + * @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. + */ +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 +} + + /** * Check if a character is drawn under a point. * @param label Label object @@ -761,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, - ext->selection_start, ext->selection_end); + 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; @@ -774,8 +838,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, ' ') * LV_LABEL_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_text_sel_start(label), lv_label_get_text_sel_end(label)); } /*Draw the text again below the original to make an circular effect */ @@ -783,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, - ext->selection_start, ext->selection_end); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label)); } } } @@ -811,6 +876,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); @@ -982,15 +1048,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*/ @@ -1015,10 +1079,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; } @@ -1038,4 +1105,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, uint16_t len){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + lv_label_dot_tmp_free( label ); /* Deallocate any existing space */ + 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); + 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 05f4e1ace..cd2e25a9e 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -29,8 +29,9 @@ extern "C" { /********************* * DEFINES *********************/ -#define LV_LABEL_DOT_NUM 3 -#define LV_LABEL_POS_LAST 0xFFFF +#define LV_LABEL_DOT_NUM 3 +#define LV_LABEL_POS_LAST 0xFFFF +#define LV_LABEL_TEXT_SEL_OFF 0xFFFF /********************** * TYPEDEFS @@ -62,20 +63,26 @@ 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)*/ - + 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[ 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*/ lv_point_t offset; /*Text draw position offset*/ + +#if LV_LABEL_TEXT_SEL + uint16_t txt_sel_start; /*Left-most selection character*/ + uint16_t txt_sel_end; /*Right-most selection character*/ +#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*/ + 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; /********************** @@ -164,6 +171,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. `LV_LABEL_TXT_SEL_OFF` to select nothing. + */ +void lv_label_set_text_sel_start( lv_obj_t * label, uint16_t index ); + +/** + * @brief Set the selection end index. + * @param label pointer to a label object. + * @param index index to set. `LV_LABEL_TXT_SEL_OFF` to select nothing. + */ +void lv_label_set_text_sel_end( lv_obj_t * label, uint16_t index ); + /*===================== * Getter functions *====================*/ @@ -246,6 +268,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. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. + */ +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. + */ +uint16_t lv_label_get_text_sel_end( const lv_obj_t * label ); + + /*===================== * Other functions *====================*/ diff --git a/src/lv_objx/lv_page.c b/src/lv_objx/lv_page.c index 1e23a969a..6b8141bb0 100644 --- a/src/lv_objx/lv_page.c +++ b/src/lv_objx/lv_page.c @@ -1044,13 +1044,23 @@ static void scrl_def_event_cb(lv_obj_t * scrl, lv_event_t event) { lv_obj_t * page = lv_obj_get_parent(scrl); - if(event == LV_EVENT_PRESSED || event == LV_EVENT_PRESSING || event == LV_EVENT_PRESS_LOST || - event == LV_EVENT_RELEASED || event == LV_EVENT_SHORT_CLICKED || - event == LV_EVENT_LONG_PRESSED || event == LV_EVENT_LONG_PRESSED_REPEAT || - event == LV_EVENT_LONG_HOVER_IN || event == LV_EVENT_LONG_HOVER_OUT || - event == LV_EVENT_FOCUSED || event == LV_EVENT_DEFOCUSED) { + /*clang-format off*/ + if(event == LV_EVENT_PRESSED || + event == LV_EVENT_PRESSING || + event == LV_EVENT_PRESS_LOST || + event == LV_EVENT_RELEASED || + event == LV_EVENT_SHORT_CLICKED || + event == LV_EVENT_CLICKED || + event == LV_EVENT_LONG_PRESSED || + event == LV_EVENT_LONG_PRESSED_REPEAT || + event == LV_EVENT_LONG_HOVER_IN || + event == LV_EVENT_LONG_HOVER_OUT || + event == LV_EVENT_FOCUSED || + event == LV_EVENT_DEFOCUSED) + { lv_event_send(page, event, lv_event_get_data()); } + /*clang-format on*/ } /** diff --git a/src/lv_objx/lv_ta.c b/src/lv_objx/lv_ta.c index c84fa10a9..b6a912ba0 100644 --- a/src/lv_objx/lv_ta.c +++ b/src/lv_objx/lv_ta.c @@ -793,11 +793,18 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, const lv_style_t * style * @param ta pointer to a text area object * @param en true or false to enable/disable selection mode */ -void lv_ta_set_sel_mode(lv_obj_t * ta, bool en) +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->sel_mode = en; + + ext->text_sel_en = en; + if(!en) lv_ta_clear_selection(ta); +#else + (void) ta; /*Unused*/ + (void) en; /*Unused*/ +#endif } /*===================== @@ -942,32 +949,6 @@ const lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type) return style; } -/** - * Get the selection index of the text area. - * - * The last character is exclusive (i.e. if the API says that the selection - * ranges from 6 to 7, only character 6 is selected). - * @param ta Text area object - * @param sel_start pointer to int used to hold first selected character - * @param sel_end pointer to int used to hold last selected character - */ - -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); - - /*Force both values to -1 if there is no selection*/ - if(ext_label->selection_start == -1 || ext_label->selection_end == -1) { - *sel_start = -1; - *sel_end = -1; - return; - } - - *sel_start = ext_label->selection_start; - *sel_end = ext_label->selection_end; -} - /** * Find whether text is selected or not. * @param ta Text area object @@ -975,10 +956,19 @@ 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); +#if LV_LABEL_TEXT_SEL + lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - return (ext_label->selection_start == -1 || ext_label->selection_end == -1); + 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 } /** @@ -986,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_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->sel_mode; + return ext->text_sel_en; +#else + (void) ta; /*Unused*/ + return false; +#endif } /*===================== @@ -1003,14 +997,17 @@ bool lv_ta_get_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); - 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; - lv_obj_invalidate(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){ + 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 } /** @@ -1182,7 +1179,7 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ cur_area.x1 += cur_style.body.padding.left; cur_area.y1 += cur_style.body.padding.top; lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, 0, - -1, -1); + LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF); } else if(ext->cursor.type == LV_CURSOR_OUTLINE) { cur_style.body.opa = LV_OPA_TRANSP; @@ -1640,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*/ @@ -1661,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; @@ -1675,52 +1672,71 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, click_outside_label = !lv_label_is_char_under_pos(ext->label, &relative_position); } - if(ext->sel_mode && !ext->selecting && !click_outside_label && sign == LV_SIGNAL_PRESSED) { - /*Input device just went down. Store the selection start position*/ - ext->tmp_sel_start = index_of_char_at_position; - ext->tmp_sel_end = -1; - ext->selecting = 1; - lv_obj_set_drag(lv_page_get_scrl(ta), false); - } else if(ext->selecting && sign == LV_SIGNAL_PRESSING) { - /*Input device may be moving. Store the end position */ - ext->tmp_sel_end = index_of_char_at_position; - } else if(ext->selecting && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) { - /*Input device is released. Check if anything was selected.*/ - lv_obj_set_drag(lv_page_get_scrl(ta), true); + if(ext->text_sel_en) { + if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) { + /*Input device just went down. Store the selection start position*/ + ext->tmp_sel_start = index_of_char_at_position; + ext->tmp_sel_end = LV_LABEL_TEXT_SEL_OFF; + ext->text_sel_in_prog = 1; + lv_obj_set_drag(lv_page_get_scrl(ta), false); + } else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) { + /*Input device may be moving. Store the end position */ + ext->tmp_sel_end = index_of_char_at_position; + } else if(ext->text_sel_in_prog && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) { + /*Input device is released. Check if anything was selected.*/ + lv_obj_set_drag(lv_page_get_scrl(ta), true); + } } - if(ext->selecting || sign == LV_SIGNAL_PRESSED) + if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position); - if(ext->selecting) { + if(ext->text_sel_in_prog) { /*If the selected area has changed then update the real values and*/ /*invalidate the text area.*/ + 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(ext_label->txt_sel_start != ext->tmp_sel_end || + ext_label->txt_sel_end != ext->tmp_sel_start) { + ext_label->txt_sel_start = ext->tmp_sel_end; + ext_label->txt_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(ext_label->txt_sel_start != ext->tmp_sel_start || + ext_label->txt_sel_end != ext->tmp_sel_end) { + ext_label->txt_sel_start = ext->tmp_sel_start; + ext_label->txt_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(ext_label->txt_sel_start != LV_LABEL_TEXT_SEL_OFF || + ext_label->txt_sel_end != LV_LABEL_TEXT_SEL_OFF) { + ext_label->txt_sel_start = LV_LABEL_TEXT_SEL_OFF; + ext_label->txt_sel_end = LV_LABEL_TEXT_SEL_OFF; lv_obj_invalidate(ta); } } /*Finish selection if necessary */ if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) { - ext->selecting = 0; + 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 eba2d6832..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*/ - uint8_t selecting : 1; /*User is in process of selecting */ - uint8_t sel_mode : 1; /*Text can be selected on this text area*/ +#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 { @@ -262,7 +262,7 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, const lv_style_t * style * @param ta pointer to a text area object * @param en true or false to enable/disable selection mode */ -void lv_ta_set_sel_mode(lv_obj_t * ta, bool en); +void lv_ta_set_text_sel(lv_obj_t * ta, bool en); /*===================== * Getter functions @@ -376,18 +376,6 @@ static inline bool lv_ta_get_edge_flash(lv_obj_t * ta) */ const lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type); -/** - * Get the selection index of the text area. - * - * The last character is exclusive (i.e. if the API says that the selection - * ranges from 6 to 7, only character 6 is selected). - * @param ta Text area object - * @param sel_start pointer to int used to hold first selected character - * @param sel_end pointer to int used to hold last selected character - */ - -void lv_ta_get_selection(lv_obj_t * ta, int * sel_start, int * sel_end); - /** * Find whether text is selected or not. * @param ta Text area object @@ -400,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_sel_mode(lv_obj_t * ta); +bool lv_ta_get_text_sel_en(lv_obj_t * ta); /*===================== * Other functions