1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

Merge branch 'ta_selection' into dev-6.0

This commit is contained in:
Gabor Kiss-Vamosi 2019-03-29 05:33:54 +01:00
commit e902f0955f
17 changed files with 326 additions and 31 deletions

View File

@ -95,6 +95,7 @@ void lv_style_init(void)
lv_style_scr.text.opa = LV_OPA_COVER;
lv_style_scr.text.color = lv_color_make(0x30, 0x30, 0x30);
lv_style_scr.text.sel_color = lv_color_make(0x55, 0x96, 0xd8);
lv_style_scr.text.font = LV_FONT_DEFAULT;
lv_style_scr.text.letter_space = 2;
lv_style_scr.text.line_space = 2;

View File

@ -84,6 +84,7 @@ typedef struct
struct {
lv_color_t color;
lv_color_t sel_color;
const lv_font_t * font;
lv_coord_t letter_space;
lv_coord_t line_space;

View File

@ -71,7 +71,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask,
if(src == NULL) {
LV_LOG_WARN("Image draw: src is NULL");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1);
return;
}
@ -81,7 +81,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask,
if(res == LV_RES_INV) {
LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1);
return;
}
}

View File

@ -51,10 +51,11 @@ 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)
*/
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)
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, int sel_start, int sel_end)
{
const lv_font_t * font = style->text.font;
lv_coord_t w;
@ -121,6 +122,9 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
uint16_t par_start = 0;
lv_color_t recolor;
lv_coord_t letter_w;
lv_style_t sel_style;
lv_style_copy(&sel_style, &lv_style_plain_color);
sel_style.body.main_color = sel_style.body.grad_color = style->text.sel_color;
/*Write out all lines*/
while(txt[line_start] != '\0') {
@ -175,9 +179,23 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
if(cmd_state == CMD_STATE_IN) color = recolor;
lv_draw_letter(&pos, mask, font, letter, color, opa);
letter_w = lv_font_get_width(font, letter);
if(sel_start != -1 && sel_end != -1) {
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) {
lv_area_t sel_coords;
sel_coords.x1 = pos.x;
sel_coords.y1 = pos.y;
sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
sel_coords.y2 = pos.y + line_height - 1;
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
}
}
lv_draw_letter(&pos, mask, font, letter, color, opa);
if(letter_w > 0){
pos.x += letter_w + style->text.letter_space;
}

View File

@ -36,10 +36,11 @@ 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)
*/
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);
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, int sel_start, int sel_end);
/**********************
* MACROS

View File

@ -683,7 +683,7 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
area_tmp.x2 = area_tmp.x1 + txt_size.x;
area_tmp.y2 = area_tmp.y1 + txt_size.y;
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL);
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1);
}
}
return true;

View File

@ -686,19 +686,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
txt_buf[5] = '\0';
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
header_area.y1 += ext->style_header->body.padding.top;
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL);
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, -1, -1);
/*Add the left arrow*/
lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header;
header_area.x1 += ext->style_header->body.padding.left;
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, -1, -1);
/*Add the right arrow*/
arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header;
header_area.x1 = header_area.x2 - ext->style_header->body.padding.right -
lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font,
arrow_style->text.line_space, LV_TXT_FLAG_NONE);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, -1, -1);
}
@ -722,7 +722,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
for(i = 0; i < 7; i++) {
label_area.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad;
label_area.x2 = label_area.x1 + box_w;
lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER, NULL);
lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER, NULL, -1, -1);
}
}
@ -852,7 +852,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
/*Write the day's number*/
lv_utils_num_to_str(day_cnt, buf);
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL);
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1);
/*Go to the next day*/
day_cnt ++;

View File

@ -1069,7 +1069,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask)
/* set the area at some distance of the major tick len left of the tick */
lv_area_t a = {(p2.x - size.x - LV_CHART_AXIS_TO_LABEL_DISTANCE) , (p2.y - size.y/2), (p2.x - LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.y + size.y/2) };
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL);
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1);
}
}
}
@ -1183,7 +1183,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
/* set the area at some distance of the major tick len under of the tick */
lv_area_t a = { (p2.x - size.x/2) , (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x/2), (p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE) };
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL);
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1);
}
}
}

View File

@ -574,7 +574,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
new_style.text.opa = sel_style->text.opa;
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale,
lv_label_get_text(ext->label), flag, NULL);
lv_label_get_text(ext->label), flag, NULL, -1, -1);
}
}
@ -606,7 +606,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
if (area_ok)
{
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale,
LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE, NULL); /*Use a down arrow in ddlist, you can replace it with your custom symbol*/
LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE, NULL, -1, -1); /*Use a down arrow in ddlist, you can replace it with your custom symbol*/
}
}
}

View File

@ -385,7 +385,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask)
label_cord.x2 = label_cord.x1 + label_size.x;
label_cord.y2 = label_cord.y1 + label_size.y;
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL);
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, -1, -1);
}
}
/**

View File

@ -388,7 +388,7 @@ static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode
lv_style_t style_mod;
lv_style_copy(&style_mod, style);
style_mod.text.color = style->image.color;
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL);
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, -1, -1);
} else {
/*Trigger the error handler of image drawer*/
LV_LOG_WARN("lv_img_design: image source type is unknown");

View File

@ -90,6 +90,9 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
ext->anim_speed = LV_LABEL_SCROLL_SPEED;
ext->offset.x = 0;
ext->offset.y = 0;
ext->selection_start = -1;
ext->selection_end = -1;
lv_obj_set_design_cb(new_label, lv_label_design);
lv_obj_set_signal_cb(new_label, lv_label_signal);
@ -543,6 +546,79 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
return lv_encoded_get_char_id(txt, i);
}
/**
* 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
*/
bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos) {
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;
lv_coord_t max_w = lv_obj_get_width(label);
lv_style_t * style = lv_obj_get_style(label);
const lv_font_t * font = style->text.font;
uint8_t letter_height = lv_font_get_height(font);
lv_coord_t y = 0;
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;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
/*If the width will be expanded set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND || ext->long_mode == LV_LABEL_LONG_SCROLL) {
max_w = LV_COORD_MAX;
}
/*Search the line of the index letter */;
while(txt[line_start] != '\0') {
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
y += letter_height + style->text.line_space;
line_start = new_line_start;
}
/*Calculate the x coordinate*/
lv_coord_t x = 0;
lv_coord_t last_x = 0;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start,
font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2;
}
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
uint32_t i = line_start;
uint32_t i_current = i;
uint32_t letter = 0;
while(i <= new_line_start - 1) {
letter = lv_txt_encoded_next(txt, &i); /*Be careful 'i' already points to the next character*/
/*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*/
}
}
last_x = x;
x += lv_font_get_width(font, letter);
if(pos->x < x) {
i = i_current;
break;
}
x += style->text.letter_space;
i_current = i;
}
int max_diff = lv_font_get_width(font, letter) + style->text.letter_space + 1;
return (pos->x >= (last_x - style->text.letter_space) && pos->x <= (last_x + max_diff));
}
/*=====================
* Other functions
@ -671,7 +747,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_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, ext->selection_start, ext->selection_end);
}
return true;
}

View File

@ -73,6 +73,8 @@ 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*/
int selection_start; /*Left-most selection character*/
int selection_end; /*Right-most selection character*/
} lv_label_ext_t;
/**********************
@ -224,6 +226,14 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
*/
uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos);
/**
* 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
*/
bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos);
/**
* Get the style of an label object
* @param label pointer to an label object

View File

@ -373,7 +373,7 @@ static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_desig
new_style.text.color = sel_style->text.color;
new_style.text.opa = sel_style->text.opa;
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale,
lv_label_get_text(ext->ddlist.label), txt_align, NULL);
lv_label_get_text(ext->ddlist.label), txt_align, NULL, -1, -1);
}
}

View File

@ -54,7 +54,7 @@ static bool char_is_accepted(lv_obj_t * ta, uint32_t c);
static void get_cursor_style(lv_obj_t * ta, lv_style_t * style_res);
static void refr_cursor_area(lv_obj_t * ta);
static void placeholder_update(lv_obj_t * ta);
static void update_cursor_position_on_click(lv_obj_t * ta, lv_indev_t * click_source);
static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source);
/**********************
* STATIC VARIABLES
@ -231,6 +231,7 @@ void lv_ta_add_char(lv_obj_t * ta, uint32_t c)
if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/
lv_label_ins_text(ext->label, ext->cursor.pos, (const char *)letter_buf); /*Insert the character*/
lv_ta_clear_selection(ta); /*Clear selection*/
if(ext->pwd_mode != 0) {
@ -311,6 +312,7 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt)
/*Insert the text*/
lv_label_ins_text(ext->label, ext->cursor.pos, txt);
lv_ta_clear_selection(ta);
if(ext->pwd_mode != 0) {
ext->pwd_tmp = lv_mem_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + strlen(txt) + 1);
@ -380,6 +382,7 @@ void lv_ta_del_char(lv_obj_t * ta)
lv_txt_cut(label_txt, ext->cursor.pos - 1, 1);
/*Refresh the label*/
lv_label_set_text(ext->label, label_txt);
lv_ta_clear_selection(ta);
/*Don't let 'width == 0' because cursor will not be visible*/
if(lv_obj_get_width(ext->label) == 0) {
@ -415,6 +418,7 @@ void lv_ta_del_char_forward(lv_obj_t * ta)
if(cp != lv_ta_get_cursor_pos(ta)) lv_ta_del_char(ta);
}
/*=====================
* Setter functions
*====================*/
@ -428,6 +432,9 @@ void lv_ta_set_text(lv_obj_t * ta, const char * txt)
{
lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta);
/*Clear the existing selection*/
lv_ta_clear_selection(ta);
/*Add the character one-by-one if not all characters are accepted or there is character limit.*/
if(lv_ta_get_accepted_chars(ta) || lv_ta_get_max_length(ta)) {
lv_label_set_text(ext->label, "");
@ -623,10 +630,13 @@ void lv_ta_set_pwd_mode(lv_obj_t * ta, bool en)
}
txt[i] = '\0';
lv_ta_clear_selection(ta);
lv_label_set_text(ext->label, NULL);
}
/*Pwd mode is now disabled*/
else if(ext->pwd_mode == 1 && en == false) {
lv_ta_clear_selection(ta);
lv_label_set_text(ext->label, ext->pwd_tmp);
lv_mem_free(ext->pwd_tmp);
ext->pwd_tmp = NULL;
@ -778,6 +788,18 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, lv_style_t * style)
}
}
/**
* Enable/disable selection mode.
* @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) {
lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta);
ext->sel_mode = en;
if(!en)
lv_ta_clear_selection(ta);
}
/*=====================
* Getter functions
*====================*/
@ -931,10 +953,73 @@ 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
* @return whether text is selected or not
*/
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);
}
/**
* Find whether selection mode is enabled.
* @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 en) {
lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta);
return ext->sel_mode;
}
/*=====================
* Other functions
*====================*/
/**
* Clear the selection on the text area.
* @param ta Text area object
*/
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;
lv_obj_invalidate(ta);
}
}
/**
* Move the cursor one character right
* @param ta pointer to a text area object
@ -1103,7 +1188,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);
lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, 0, -1, -1);
} else if(ext->cursor.type == LV_CURSOR_OUTLINE) {
cur_style.body.opa = LV_OPA_TRANSP;
@ -1234,8 +1319,9 @@ static lv_res_t lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param)
}
#endif
}
else if(sign == LV_SIGNAL_PRESSED) {
update_cursor_position_on_click(ta, (lv_indev_t *) param);
else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESSING
|| sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) {
update_cursor_position_on_click(ta, sign, (lv_indev_t *) param);
}
return res;
}
@ -1279,8 +1365,9 @@ static lv_res_t lv_ta_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void
}
}
}
else if(sign == LV_SIGNAL_PRESSED) {
update_cursor_position_on_click(ta, (lv_indev_t *)param);
else if(sign == LV_SIGNAL_PRESSING || sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESS_LOST ||
sign == LV_SIGNAL_RELEASED) {
update_cursor_position_on_click(ta, sign, (lv_indev_t *)param);
}
return res;
@ -1535,7 +1622,7 @@ static void placeholder_update(lv_obj_t * ta)
}
}
static void update_cursor_position_on_click(lv_obj_t * ta, lv_indev_t * click_source)
static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source)
{
if(click_source == NULL) return;
@ -1547,14 +1634,20 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_indev_t * click_so
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;
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*/
lv_point_t relative_position;
relative_position.x = point_act.x - label_coords.x1;
@ -1562,19 +1655,71 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_indev_t * click_so
lv_coord_t label_width = lv_obj_get_width(ext->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;
click_outside_label = true;
}
/*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;
click_outside_label = true;
}
else {
index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position);
click_outside_label = !lv_label_is_char_under_pos(ext->label, &relative_position);
}
lv_ta_set_cursor_pos(ta, index_of_char_at_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->selecting || sign == LV_SIGNAL_PRESSED)
lv_ta_set_cursor_pos(ta, index_of_char_at_position);
if(ext->selecting) {
/*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;
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;
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;
lv_obj_invalidate(ta);
}
}
/*Finish selection if necessary */
if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) {
ext->selecting = 0;
}
}
}
#endif

View File

@ -74,6 +74,10 @@ typedef struct
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)*/
} 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*/
} lv_ta_ext_t;
enum {
@ -248,6 +252,13 @@ static inline void lv_ta_set_edge_flash(lv_obj_t * ta, bool en)
*/
void lv_ta_set_style(lv_obj_t *ta, lv_ta_style_t type, lv_style_t *style);
/**
* Enable/disable selection mode.
* @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);
/*=====================
* Getter functions
*====================*/
@ -360,10 +371,42 @@ static inline bool lv_ta_get_edge_flash(lv_obj_t * ta)
*/
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
* @return whether text is selected or not
*/
bool lv_ta_text_is_selected(const lv_obj_t *ta);
/**
* Find whether selection mode is enabled.
* @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 en);
/*=====================
* Other functions
*====================*/
/**
* Clear the selection on the text area.
* @param ta Text area object
*/
void lv_ta_clear_selection(lv_obj_t * ta);
/**
* Move the cursor one character right
* @param ta pointer to a text area object

View File

@ -701,7 +701,7 @@ static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_
bool label_mask_ok;
label_mask_ok = lv_area_intersect(&label_mask, mask, &cell_area);
if(label_mask_ok) {
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1, txt_flags, NULL);
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1, txt_flags, NULL, -1, -1);
}
/*Draw lines after '\n's*/
lv_point_t p1;