Example #1
0
/**
 * Create a label objects
 * @param par pointer to an object, it will be the parent of the new label
 * @param copy pointer to a button object, if not NULL then the new object will be copied from it
 * @return pointer to the created button
 */
lv_obj_t * lv_label_create(lv_obj_t * par, lv_obj_t * copy)
{
    /*Create a basic object*/
    lv_obj_t * new_label = lv_obj_create(par, copy);
    lv_mem_assert(new_label);
    if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_label);
    
    /*Extend the basic object to a label object*/
    lv_obj_allocate_ext_attr(new_label, sizeof(lv_label_ext_t));
    
    lv_label_ext_t * ext = lv_obj_get_ext_attr(new_label);
    lv_mem_assert(ext);
    ext->text = NULL;
    ext->static_txt = 0;
    ext->recolor = 0;
    ext->no_break = 0;
    ext->body_draw = 0;
    ext->align = LV_LABEL_ALIGN_LEFT;
    ext->dot_end = LV_LABEL_DOT_END_INV;
    ext->long_mode = LV_LABEL_LONG_EXPAND;
    ext->anim_speed = LV_LABEL_SCROLL_SPEED;
    ext->offset.x = 0;
    ext->offset.y = 0;
	lv_obj_set_design_func(new_label, lv_label_design);
	lv_obj_set_signal_func(new_label, lv_label_signal);

    /*Init the new label*/
    if(copy == NULL) {
		lv_obj_set_click(new_label, false);
		lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND);
		lv_label_set_text(new_label, "Text");
        lv_label_set_style(new_label, NULL);        /*Inherit parent's style*/
    }
    /*Copy 'copy' if not NULL*/
    else {
        lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
        lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy));
        lv_label_set_recolor(new_label, lv_label_get_recolor(copy));
        lv_label_set_body_draw(new_label, lv_label_get_body_draw(copy));
        lv_label_set_align(new_label, lv_label_get_align(copy));
        if(copy_ext->static_txt == 0) lv_label_set_text(new_label, lv_label_get_text(copy));
        else lv_label_set_static_text(new_label, lv_label_get_text(copy));

        /*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/
        if(copy_ext->long_mode == LV_LABEL_LONG_DOT) {
            ext->text = lv_mem_realloc(ext->text, lv_mem_get_size(copy_ext->text));
            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));
        ext->dot_end = copy_ext->dot_end;

        /*Refresh the style with new signal function*/
        lv_obj_refresh_style(new_label);
    }
    return new_label;
}
Example #2
0
/**
 * Handle the drawing related tasks of the rollers
 * @param roller pointer to an object
 * @param mask the object will be drawn only in this area
 * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
 *                                  (return 'true' if yes)
 *             LV_DESIGN_DRAW: draw the object (always return 'true')
 *             LV_DESIGN_DRAW_POST: drawing after every children are drawn
 * @param return true/false, depends on 'mode'
 */
static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_design_mode_t mode)
{
    /*Return false if the object is not covers the mask_p area*/
    if(mode == LV_DESIGN_COVER_CHK) {
    	return false;
    }
    /*Draw the object*/
    else if(mode == LV_DESIGN_DRAW_MAIN) {
        draw_bg(roller, mask);

        lv_style_t *style = lv_roller_get_style(roller, LV_ROLLER_STYLE_BG);
        const lv_font_t * font = style->text.font;
        lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
        lv_coord_t font_h = lv_font_get_height_scale(font);
        lv_area_t rect_area;
        rect_area.y1 = roller->coords.y1 + lv_obj_get_height(roller) / 2 - font_h / 2 - style->text.line_space / 2;
        rect_area.y2 = rect_area.y1 + font_h + style->text.line_space;
        rect_area.x1 = roller->coords.x1;
        rect_area.x2 = roller->coords.x2;

        lv_draw_rect(&rect_area, mask, ext->ddlist.sel_style);
    }
    /*Post draw when the children are drawn*/
    else if(mode == LV_DESIGN_DRAW_POST) {
        lv_style_t *style = lv_roller_get_style(roller, LV_ROLLER_STYLE_BG);
        lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
        const lv_font_t * font = style->text.font;
        lv_coord_t font_h = lv_font_get_height_scale(font);

        /*Redraw the text on the selected area with a different color*/
        lv_area_t rect_area;
        rect_area.y1 = roller->coords.y1 + lv_obj_get_height(roller) / 2 - font_h / 2 - style->text.line_space / 2;
        rect_area.y2 = rect_area.y1 + font_h + style->text.line_space;
        rect_area.x1 = roller->coords.x1;
        rect_area.x2 = roller->coords.x2;
        lv_area_t mask_sel;
        bool area_ok;
        area_ok = lv_area_union(&mask_sel, mask, &rect_area);
        if(area_ok) {
            lv_style_t *sel_style = lv_roller_get_style(roller, LV_ROLLER_STYLE_SEL);
            lv_style_t new_style;
            lv_style_copy(&new_style, style);
            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,
                          lv_label_get_text(ext->ddlist.label), LV_TXT_FLAG_CENTER, NULL);
        }
    }

    return true;
}
Example #3
0
/**
 * 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);
}
Example #4
0
/**
 * Get the current selected option as a string
 * @param ddlist pointer to ddlist object
 * @param buf pointer to an array to store the string
 */
void lv_ddlist_get_selected_str(lv_obj_t * ddlist, char * buf)
{
    lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);

    uint16_t i;
    uint16_t line = 0;
    const char * opt_txt = lv_label_get_text(ext->label);
    uint16_t txt_len = strlen(opt_txt);
    
    
    for(i = 0; i < txt_len && line != ext->sel_opt_id; i++) {
        if(opt_txt[i] == '\n') line ++;
    }
    
    uint16_t c;
    for(c = 0; opt_txt[i] != '\n' && i < txt_len; c++, i++) buf[c] = opt_txt[i];
    
    buf[c] = '\0';
}
Example #5
0
/**
 * Called when a drop down list is released to open it or set new option
 * @param ddlist pointer to a drop down list object
 * @return LV_ACTION_RES_INV if the ddlist it deleted in the user callback else LV_ACTION_RES_OK
 */
static lv_res_t lv_ddlist_release_action(lv_obj_t * ddlist)
{
    lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);

    if(ext->opened == 0) { /*Open the list*/
        ext->opened = 1;
        lv_obj_set_drag(lv_page_get_scrl(ddlist), true);
    } else {
        ext->opened = 0;
        lv_obj_set_drag(lv_page_get_scrl(ddlist), false);

        /*Search the clicked option*/
        lv_indev_t *indev = lv_indev_get_act();
        lv_point_t p;
        lv_indev_get_point(indev, &p);
        p.x -= ext->label->coords.x1;
        p.y -= ext->label->coords.y1;
        uint16_t letter_i;
        letter_i = lv_label_get_letter_on(ext->label, &p);

        uint16_t new_opt = 0;
        const char * txt = lv_label_get_text(ext->label);
        uint16_t i;
        for(i = 0; i < letter_i; i++) {
            if(txt[i] == '\n') new_opt ++;
        }

        ext->sel_opt_id = new_opt;

        if(ext->action != NULL) {
            ext->action(ddlist);
        }
    }
    lv_ddlist_refr_size(ddlist, true);

    return LV_RES_OK;

}
Example #6
0
/**
 * Create a drop down list objects
 * @param par pointer to an object, it will be the parent of the new drop down list
 * @param copy pointer to a drop down list object, if not NULL then the new object will be copied from it
 * @return pointer to the created drop down list
 */
lv_obj_t * lv_ddlist_create(lv_obj_t * par, lv_obj_t * copy)
{
    /*Create the ancestor drop down list*/
    lv_obj_t * new_ddlist = lv_page_create(par, copy);
    lv_mem_assert(new_ddlist);
    if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_ddlist);
    if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_func(lv_page_get_scrl(new_ddlist));
    if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_ddlist);
    
    /*Allocate the drop down list type specific extended data*/
    lv_ddlist_ext_t * ext = lv_obj_allocate_ext_attr(new_ddlist, sizeof(lv_ddlist_ext_t));
    lv_mem_assert(ext);

    /*Initialize the allocated 'ext' */
    ext->label = NULL;
    ext->action = NULL;
    ext->opened = 0;
    ext->fix_height = 0;
    ext->sel_opt_id = 0;
    ext->sel_opt_id_ori = 0;
    ext->option_cnt = 0;
    ext->anim_time = LV_DDLIST_ANIM_TIME;
    ext->sel_style = &lv_style_plain_color;

    /*The signal and design functions are not copied so set them here*/
    lv_obj_set_signal_func(new_ddlist, lv_ddlist_signal);
    lv_obj_set_signal_func(lv_page_get_scrl(new_ddlist), lv_ddlist_scrl_signal);
    lv_obj_set_design_func(new_ddlist, lv_ddlist_design);

    /*Init the new drop down list drop down list*/
    if(copy == NULL) {
        lv_obj_t * scrl = lv_page_get_scrl(new_ddlist);
        lv_obj_set_drag(scrl, false);
        lv_page_set_scrl_fit(new_ddlist, true, true);

        ext->label = lv_label_create(new_ddlist, NULL);
        lv_cont_set_fit(new_ddlist, true, false);
        lv_page_set_rel_action(new_ddlist, lv_ddlist_release_action);
        lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_DRAG);
        lv_page_set_style(new_ddlist, LV_PAGE_STYLE_SCRL, &lv_style_transp_tight);

        lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3");

        /*Set the default styles*/
        lv_theme_t *th = lv_theme_get_current();
        if(th) {
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BG, th->ddlist.bg);
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL,th->ddlist.sel);
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, th->ddlist.sb);
        } else {
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BG, &lv_style_pretty);
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, &lv_style_plain_color);
            lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color);
        }
    }
    /*Copy an existing drop down list*/
    else {
    	lv_ddlist_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
        ext->label = lv_label_create(new_ddlist, copy_ext->label);
        lv_label_set_text(ext->label, lv_label_get_text(copy_ext->label));
        ext->sel_opt_id = copy_ext->sel_opt_id;
        ext->fix_height = copy_ext->fix_height;
        ext->action = copy_ext->action;
        ext->option_cnt = copy_ext->option_cnt;
        ext->sel_style = copy_ext->sel_style;
        ext->anim_time = copy_ext->anim_time;

        /*Refresh the style with new signal function*/
        lv_obj_refresh_style(new_ddlist);
    }
    
    return new_ddlist;
}
Example #7
0
/**
 * Handle the drawing related tasks of the drop down lists
 * @param ddlist pointer to an object
 * @param mask the object will be drawn only in this area
 * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
 *                                  (return 'true' if yes)
 *             LV_DESIGN_DRAW: draw the object (always return 'true')
 *             LV_DESIGN_DRAW_POST: drawing after every children are drawn
 * @param return true/false, depends on 'mode'
 */
static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_design_mode_t mode)
{
    /*Return false if the object is not covers the mask_p area*/
    if(mode == LV_DESIGN_COVER_CHK) {
    	return ancestor_design(ddlist, mask, mode);
    }
    /*Draw the object*/
    else if(mode == LV_DESIGN_DRAW_MAIN) {
        ancestor_design(ddlist, mask, mode);

        lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);

        /*If the list is opened draw a rectangle under the selected item*/
        if(ext->opened != 0) {
            lv_style_t *style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
            const lv_font_t * font = style->text.font;
            lv_coord_t font_h = lv_font_get_height(font);

            /*Draw the selected*/
            lv_area_t rect_area;
            rect_area.y1 = ext->label->coords.y1;
            rect_area.y1 += ext->sel_opt_id * (font_h + style->text.line_space);
            rect_area.y1 -= style->text.line_space / 2;

            rect_area.y2 = rect_area.y1 + font_h + style->text.line_space;
            rect_area.x1 = ddlist->coords.x1;
            rect_area.x2 = ddlist->coords.x2;

            lv_draw_rect(&rect_area, mask, ext->sel_style);
        }
    }
    /*Post draw when the children are drawn*/
    else if(mode == LV_DESIGN_DRAW_POST) {
        ancestor_design(ddlist, mask, mode);

        /*Redraw the text on the selected area with a different color*/
        lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);

        /*Redraw only in opened state*/
        if(ext->opened == 0) return true;

        lv_style_t *style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
        const lv_font_t * font = style->text.font;
        lv_coord_t font_h = lv_font_get_height(font);

        lv_area_t area_sel;
        area_sel.y1 = ext->label->coords.y1;
        area_sel.y1 += ext->sel_opt_id * (font_h + style->text.line_space);
        area_sel.y1 -= style->text.line_space / 2;

        area_sel.y2 = area_sel.y1 + font_h + style->text.line_space;
        area_sel.x1 = ddlist->coords.x1;
        area_sel.x2 = ddlist->coords.x2;
        lv_area_t mask_sel;
        bool area_ok;
        area_ok = lv_area_union(&mask_sel, mask, &area_sel);
        if(area_ok) {
            lv_style_t *sel_style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_SEL);
            lv_style_t new_style;
            lv_style_copy(&new_style, style);
            new_style.text.color = sel_style->text.color;
            new_style.text.opa = sel_style->text.opa;
            lv_draw_label(&ext->label->coords, &mask_sel, &new_style,
                          lv_label_get_text(ext->label), LV_TXT_FLAG_NONE, NULL);
        }
    }

    return true;
}
Example #8
0
/**
 * Get the options of a drop down list
 * @param ddlist pointer to drop down list object
 * @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
 */
const char * lv_ddlist_get_options(lv_obj_t * ddlist)
{
    lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
    return lv_label_get_text(ext->label);
}
Example #9
0
/**
 * Get the index of letter on a relative point of a label
 * @param label pointer to label object
 * @param pos pointer to point with coordinates on a the label
 * @return the index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter)
 * Expressed in character index and not byte index (different in UTF-8)
 */
uint16_t lv_label_get_letter_on(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->no_break != 0) flag |= LV_TXT_FLAG_NO_BREAK;
    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;
	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;
	while(i < new_line_start - 1) {
	    letter = lv_txt_utf8_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*/
            }
	    }

	    x += lv_font_get_width(font, letter);
		if(pos->x < x) {
		    i = i_current;
		    break;
		}
		x += style->text.letter_space;
		i_current = i;
	}

	return lv_txt_utf8_get_char_id(txt, i);
}
Example #10
0
/**
 * Get the relative x and y coordinates of a letter
 * @param label pointer to a label object
 * @param index index of the letter [0 ... text length]. Expressed in character index, not byte index (different in UTF-8)
 * @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
 */
void lv_label_get_letter_pos(lv_obj_t * label, uint16_t index, 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->no_break != 0) flag |= LV_TXT_FLAG_NO_BREAK;
    if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;

    /*If the width will be expanded  the 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;
    }

    index = txt_utf8_get_byte_id(txt, index);

    /*Search the line of the index letter */;
    while (txt[new_line_start] != '\0') {
        new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
        if(index < new_line_start || txt[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/

        y += letter_height + style->text.line_space;
        line_start = new_line_start;
    }

    /*If the last character is line break then go to the next line*/
    if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') {
        y += letter_height + style->text.line_space;
        line_start = index;
    }

    /*Calculate the x coordinate*/
    lv_coord_t x = 0;
	uint32_t i = line_start;
    uint32_t cnt = line_start;                      /*Count the letter (in UTF-8 1 letter not 1 byte)*/
	lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
	uint32_t letter;
	while(cnt < index) {
        cnt += lv_txt_utf8_size(txt[i]);
	    letter = lv_txt_utf8_next(txt, &i);
        /*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*/
            }
        }
        x += lv_font_get_width(font, letter) + style->text.letter_space;
	}

	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;
    }

    pos->x = x;
    pos->y = y;

}