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:
commit
e902f0955f
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 ++;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user