/** * Set a new text for a label. Memory will be allocated to store the text by the label. * @param label pointer to a label object * @param text '\0' terminated character string. NULL to refresh with the current text. */ void lv_label_set_text(lv_obj_t * label, const char * text) { lv_obj_invalidate(label); lv_label_ext_t * ext = lv_obj_get_ext_attr(label); /*If text is NULL then refresh */ if(text == NULL) { lv_label_refr_text(label); return; } if(ext->text == text) { /*If set its own text then reallocate it (maybe its size changed)*/ ext->text = lv_mem_realloc(ext->text, strlen(ext->text) + 1); } else { /*Allocate space for the new text*/ uint32_t len = strlen(text) + 1; if(ext->text != NULL && ext->static_txt == 0) { lv_mem_free(ext->text); ext->text = NULL; } ext->text = lv_mem_alloc(len); strcpy(ext->text, text); ext->static_txt = 0; /*Now the text is dynamically allocated*/ } lv_label_refr_text(label); }
/** * Insert a text to the label. The label text can not be static. * @param label pointer to a label object * @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8) * 0: before first char. * LV_LABEL_POS_LAST: after last char. * @param txt pointer to the text to insert */ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); /*Can not append to static text*/ if(ext->static_txt != 0) return; lv_obj_invalidate(label); /*Allocate space for the new text*/ uint32_t old_len = strlen(ext->text); uint32_t ins_len = strlen(txt); uint32_t new_len = ins_len + old_len; ext->text = lv_mem_realloc(ext->text, new_len + 1); if(pos == LV_LABEL_POS_LAST) { #if LV_TXT_UTF8 == 0 pos = old_len; #else pos = lv_txt_get_length(ext->text); #endif } lv_txt_ins(ext->text, pos, txt); lv_label_refr_text(label); }
/** * Set the scale settings of a gauge * @param gauge pointer to a gauge object * @param angle angle of the scale (0..360) * @param line_cnt count of scale lines * @param label_cnt count of scale labels */ void lv_gauge_set_scale(lv_obj_t * gauge, uint16_t angle, uint8_t line_cnt, uint8_t label_cnt) { lv_lmeter_set_scale(gauge, angle, line_cnt); lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge); ext->label_count = label_cnt; lv_obj_invalidate(gauge); }
/** * Set the brightness of a LED object * @param led pointer to a LED object * @param bright 0 (max. dark) ... 255 (max. light) */ void lv_led_set_bright(lv_obj_t * led, uint8_t bright) { /*Set the brightness*/ lv_led_ext_t * ext = lv_obj_get_ext_attr(led); ext->bright = bright; /*Invalidate the object there fore it will be redrawn*/ lv_obj_invalidate(led); }
/** * Set the align of the label (left or center) * @param label pointer to a label object * @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT' */ void lv_label_set_align(lv_obj_t *label, lv_label_align_t align) { lv_label_ext_t *ext = lv_obj_get_ext_attr(label); ext->align = align; lv_obj_invalidate(label); /*Enough to invalidate because alignment is only drawing related (lv_refr_label_text() not required)*/ }
/** * Set the scroll bar mode on a page * @param page pointer to a page object * @param sb.mode the new mode from 'lv_page_sb.mode_t' enum */ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode) { lv_page_ext_t * ext = lv_obj_get_ext_attr(page); ext->sb.mode = sb_mode; ext->sb.hor_draw = 0; ext->sb.ver_draw = 0; lv_page_sb_refresh(page); lv_obj_invalidate(page); }
/** * Set the label to draw (or not draw) background specified in its style's body * @param label pointer to a label object * @param body_en true: draw body; false: don't draw body */ void lv_label_set_body_draw(lv_obj_t *label, bool body_en) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); ext->body_draw = body_en == false ? 0 : 1; lv_obj_refresh_ext_size(label); lv_obj_invalidate(label); }
/** * Set the selected option * @param ddlist pointer to drop down list object * @param sel_opt id of the selected option (0 ... number of option - 1); */ void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt) { lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); if(ext->sel_opt_id == sel_opt) return; ext->sel_opt_id = sel_opt < ext->option_cnt ? sel_opt : ext->option_cnt - 1; /*Move the list to show the current option*/ if(ext->opened == 0) { lv_ddlist_pos_current_option(ddlist); } else { lv_obj_invalidate(ddlist); } }
/** * Delete characters from a label. The label text can not be static. * @param label pointer to a label object * @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8) * 0: before first char. * @param cnt number of characters to cut */ void lv_label_cut_text(lv_obj_t * label, uint32_t pos, uint32_t cnt) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); /*Can not append to static text*/ if(ext->static_txt != 0) return; lv_obj_invalidate(label); char * label_txt = lv_label_get_text(label); /*Delete the characters*/ lv_txt_cut(label_txt, pos, cnt); /*Refresh the label*/ lv_label_refr_text(label); }
/** * Set the value of a needle * @param gauge pointer to a gauge * @param needle_id the id of the needle * @param value the new value */ void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int16_t value) { lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge); if(needle_id >= ext->needle_count) return; int16_t min = lv_gauge_get_min_value(gauge); int16_t max = lv_gauge_get_max_value(gauge); if(value > max) value = max; else if(value < min) value = min; ext->values[needle_id] = value; lv_obj_invalidate(gauge); }
/** * Set the number of needles * @param gauge pointer to gauge object * @param needle_cnt new count of needles * @param colors an array of colors for needles (with 'num' elements) */ void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_color_t * colors) { lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge); if(ext->values != NULL) { lv_mem_free(ext->values); ext->values = NULL; } ext->values = lv_mem_realloc(ext->values, needle_cnt * sizeof(int16_t)); int16_t min = lv_gauge_get_min_value(gauge); uint8_t n; for(n = ext->needle_count; n < needle_cnt; n++) { ext->values[n] = min; } ext->needle_count = needle_cnt; ext->needle_colors = colors; lv_obj_invalidate(gauge); }
/** * Set a style of a page * @param page pointer to a page object * @param type which style should be set * @param style pointer to a style * */ void lv_page_set_style(lv_obj_t *page, lv_page_style_t type, lv_style_t *style) { lv_page_ext_t * ext = lv_obj_get_ext_attr(page); switch (type) { case LV_PAGE_STYLE_BG: lv_obj_set_style(page, style); break; case LV_PAGE_STYLE_SCRL: lv_obj_set_style(ext->scrl, style); break; case LV_PAGE_STYLE_SB: ext->sb.style = style; lv_area_set_height(&ext->sb.hor_area, ext->sb.style->body.padding.inner); lv_area_set_width(&ext->sb.ver_area, ext->sb.style->body.padding.inner); lv_page_sb_refresh(page); lv_obj_refresh_ext_size(page); lv_obj_invalidate(page); break; } }
/** * Set a new text for a label from a character array. The array don't has to be '\0' terminated. * Memory will be allocated to store the array by the label. * @param label pointer to a label object * @param array array of characters or NULL to refresh the label * @param size the size of 'array' in bytes */ void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size) { lv_obj_invalidate(label); lv_label_ext_t * ext = lv_obj_get_ext_attr(label); /*If trying to set its own text or the array is NULL then refresh */ if(array == ext->text || array == NULL) { lv_label_refr_text(label); return; } /*Allocate space for the new text*/ if(ext->text != NULL && ext->static_txt == 0) { lv_mem_free(ext->text); ext->text = NULL; } ext->text = lv_mem_alloc(size + 1); memcpy(ext->text, array, size); ext->text[size] = '\0'; ext->static_txt = 0; /*Now the text is dynamically allocated*/ lv_label_refr_text(label); }
/** * Signal function of the drop down list * @param ddlist pointer to a drop down list object * @param sign a signal type from lv_signal_t enum * @param param pointer to a signal specific variable * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted */ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * param) { lv_res_t res; /* Include the ancient signal function */ res = ancestor_signal(ddlist, sign, param); if(res != LV_RES_OK) return res; lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); if(sign == LV_SIGNAL_STYLE_CHG) { lv_ddlist_refr_size(ddlist, 0); } else if(sign == LV_SIGNAL_CLEANUP) { ext->label = NULL; } else if(sign == LV_SIGNAL_FOCUS) { if(ext->opened == false) { ext->opened = true; lv_ddlist_refr_size(ddlist, true); ext->sel_opt_id_ori = ext->sel_opt_id; } } else if(sign == LV_SIGNAL_DEFOCUS) { if(ext->opened != false) { ext->opened = false; ext->sel_opt_id = ext->sel_opt_id_ori; lv_ddlist_refr_size(ddlist, true); } } else if(sign == LV_SIGNAL_CONTROLL) { char c = *((char*)param); if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN) { if(!ext->opened) { ext->opened = 1; lv_ddlist_refr_size(ddlist, true); } if(ext->sel_opt_id + 1 < ext->option_cnt) { ext->sel_opt_id ++; lv_ddlist_pos_current_option(ddlist); lv_obj_invalidate(ddlist); } } else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) { if(!ext->opened) { ext->opened = 1; lv_ddlist_refr_size(ddlist, true); } if(ext->sel_opt_id > 0) { ext->sel_opt_id --; lv_ddlist_pos_current_option(ddlist); lv_obj_invalidate(ddlist); } } else if(c == LV_GROUP_KEY_ENTER || c == LV_GROUP_KEY_ENTER_LONG) { if(ext->opened) { ext->sel_opt_id_ori = ext->sel_opt_id; ext->opened = 0; if(ext->action) ext->action(ddlist); } else { ext->opened = 1; } lv_ddlist_refr_size(ddlist, true); } else if(c == LV_GROUP_KEY_ESC) { if(ext->opened) { ext->opened = 0; lv_ddlist_refr_size(ddlist, true); } } } else if(sign == LV_SIGNAL_GET_TYPE) { lv_obj_type_t * buf = param; uint8_t i; for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ if(buf->type[i] == NULL) break; } buf->type[i] = "lv_ddlist"; } return res; }
static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); ext->offset.y = y; lv_obj_invalidate(label); }
/** * Refresh the label with its text stored in its extended data * @param label pointer to a label object */ static void lv_label_refr_text(lv_obj_t * label) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); if(ext->text == NULL) return; 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; /*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; } /*Calc. the height and longest line*/ lv_point_t size; 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->no_break != 0) flag |= LV_TXT_FLAG_NO_BREAK; lv_txt_get_size(&size, ext->text, font, style->text.letter_space, style->text.line_space, max_w, flag); /*Set the full size in expand mode*/ if(ext->long_mode == LV_LABEL_LONG_EXPAND || ext->long_mode == LV_LABEL_LONG_SCROLL) { lv_obj_set_size(label, size.x, size.y); /*Start scrolling if the label is greater then its parent*/ if(ext->long_mode == LV_LABEL_LONG_SCROLL) { #if USE_LV_ANIMATION lv_obj_t * parent = lv_obj_get_parent(label); /*Delete the potential previous scroller animations*/ lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_x); lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_y); lv_anim_t anim; anim.var = label; anim.repeat = 1; anim.playback = 1; anim.start = lv_font_get_width(font, ' '); anim.act_time = 0; anim.end_cb = NULL; anim.path = lv_anim_path_linear; anim.playback_pause = (((lv_font_get_width(style->text.font, ' ') + style->text.letter_space) * 1000) / ext->anim_speed) * ANIM_WAIT_CHAR_COUNT; anim.repeat_pause = anim.playback_pause; if(lv_obj_get_width(label) > lv_obj_get_width(parent)) { anim.end = lv_obj_get_width(parent) - lv_obj_get_width(label) - lv_font_get_width(font, ' '); anim.fp = (lv_anim_fp_t) lv_obj_set_x; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); } else if(lv_obj_get_height(label) > lv_obj_get_height(parent)) { anim.end = lv_obj_get_height(parent) - lv_obj_get_height(label) - lv_font_get_height(font); anim.fp = (lv_anim_fp_t)lv_obj_set_y; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); } #endif } } /*In roll mode keep the size but start offset animations*/ else if(ext->long_mode == LV_LABEL_LONG_ROLL) { #if USE_LV_ANIMATION lv_anim_t anim; anim.var = label; anim.repeat = 1; anim.playback = 1; anim.start = lv_font_get_width(font, ' '); anim.act_time = 0; anim.end_cb = NULL; anim.path = lv_anim_path_linear; anim.playback_pause = (((lv_font_get_width(style->text.font, ' ') + style->text.letter_space) * 1000) / ext->anim_speed) * ANIM_WAIT_CHAR_COUNT;; anim.repeat_pause = anim.playback_pause; bool hor_anim = false; if(size.x > lv_obj_get_width(label)) { anim.end = lv_obj_get_width(label) - size.x - lv_font_get_width(font, ' '); anim.fp = (lv_anim_fp_t) lv_label_set_offset_x; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); hor_anim = true; } else { /*Delete the offset animation if not required*/ lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_x); ext->offset.x = 0; } if(size.y > lv_obj_get_height(label) && hor_anim == false) { anim.end = lv_obj_get_height(label) - size.y - (lv_font_get_height(font)); anim.fp = (lv_anim_fp_t)lv_label_set_offset_y; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); } else { /*Delete the offset animation if not required*/ lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_y); ext->offset.y = 0; } #endif } else if(ext->long_mode == LV_LABEL_LONG_DOT) { if(size.y <= lv_obj_get_height(label)) { /*No dots are required, the text is short enough*/ ext->dot_end = LV_LABEL_DOT_END_INV; } else if(lv_txt_get_length(ext->text) <= LV_LABEL_DOT_NUM) { /*Don't turn to dots all the characters*/ ext->dot_end = LV_LABEL_DOT_END_INV; } else { lv_point_t p; p.x = lv_obj_get_width(label) - (lv_font_get_width(style->text.font, '.') + style->text.letter_space) * LV_LABEL_DOT_NUM; /*Shrink with dots*/ p.y = lv_obj_get_height(label); p.y -= p.y % (lv_font_get_height(style->text.font) + style->text.line_space); /*Round down to the last line*/ p.y -= style->text.line_space; /*Trim the last line space*/ uint32_t letter_id = lv_label_get_letter_on(label, &p); #if LV_TXT_UTF8 == 0 /*Save letters under the dots and replace them with dots*/ uint8_t i; for(i = 0; i < LV_LABEL_DOT_NUM; i++) { ext->dot_tmp[i] = ext->text[letter_id + i]; ext->text[letter_id + i] = '.'; } ext->dot_tmp[LV_LABEL_DOT_NUM] = ext->text[letter_id + LV_LABEL_DOT_NUM]; ext->text[letter_id + LV_LABEL_DOT_NUM] = '\0'; ext->dot_end = letter_id + LV_LABEL_DOT_NUM; #else /*Save letters under the dots and replace them with dots*/ uint32_t i; uint32_t byte_id = txt_utf8_get_byte_id(ext->text, letter_id); uint32_t byte_id_ori = byte_id; uint8_t len = 0; for(i = 0; i <= LV_LABEL_DOT_NUM; i++) { len += lv_txt_utf8_size(ext->text[byte_id]); lv_txt_utf8_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] = '.'; } ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0'; ext->dot_end = letter_id + LV_LABEL_DOT_NUM; #endif } } /*In break mode only the height can change*/ else if (ext->long_mode == LV_LABEL_LONG_BREAK) { lv_obj_set_height(label, size.y); } lv_obj_invalidate(label); }
/** * Set the 'knob in' attribute of a slider * @param slider pointer to slider object * @param in true: the knob is drawn always in the slider; * false: the knob can be out on the edges */ void lv_slider_set_knob_in(lv_obj_t * slider, bool in) { lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); ext->knob_in = in == false ? 0 : 1; lv_obj_invalidate(slider); }