diff --git a/lv_draw/lv_draw_rbasic.h b/lv_draw/lv_draw_rbasic.h index 222ad0c07..730f7e349 100644 --- a/lv_draw/lv_draw_rbasic.h +++ b/lv_draw/lv_draw_rbasic.h @@ -10,7 +10,7 @@ * INCLUDES *********************/ #include "misc/others/color.h" -#include "../lv_misc/2d.h" +#include "../lv_misc/area.h" #include "../lv_misc/font.h" /********************* diff --git a/lv_draw/lv_draw_vbasic.h b/lv_draw/lv_draw_vbasic.h index a9a8b0e8a..2ec5a4a7e 100644 --- a/lv_draw/lv_draw_vbasic.h +++ b/lv_draw/lv_draw_vbasic.h @@ -14,7 +14,7 @@ #if LV_VDB_SIZE != 0 #include "misc/others/color.h" -#include "../lv_misc/2d.h" +#include "../lv_misc/area.h" #include "../lv_misc/font.h" /********************* diff --git a/lv_misc/2d.c b/lv_misc/area.c similarity index 92% rename from lv_misc/2d.c rename to lv_misc/area.c index a3402a97f..92482de73 100644 --- a/lv_misc/2d.c +++ b/lv_misc/area.c @@ -6,7 +6,7 @@ /********************* * INCLUDES *********************/ -#include +#include #include "misc/math/math_base.h" /********************* @@ -49,6 +49,26 @@ void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2) area_p->y2 = y2; } +void area_set_width(area_t * area_p, cord_t w) +{ + area_p->x2 = area_p->x1 + w - 1; +} + +void area_set_height(area_t * area_p, cord_t h) +{ + area_p->y2 = area_p->y1 + h - 1; +} + +void area_set_pos(area_t * area_p, cord_t x, cord_t y) +{ + cord_t w = area_get_width(area_p); + cord_t h = area_get_height(area_p); + area_p->x1 = x; + area_p->y1 = y; + area_set_width(area_p, w); + area_set_height(area_p, h); +} + /** * Return with area of an area (x * y) * @param area_p pointer to an area diff --git a/lv_misc/2d.h b/lv_misc/area.h similarity index 89% rename from lv_misc/2d.h rename to lv_misc/area.h index df99b7625..9928f2552 100644 --- a/lv_misc/2d.h +++ b/lv_misc/area.h @@ -1,5 +1,5 @@ /** - * @file 2d.h + * @file area.h * */ @@ -57,6 +57,9 @@ static inline cord_t area_get_height(const area_t * area_p) } void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2); +void area_set_width(area_t * area_p, cord_t w); +void area_set_height(area_t * area_p, cord_t h); +void area_set_pos(area_t * area_p, cord_t x, cord_t y); uint32_t area_get_size(const area_t * area_p); bool area_union(area_t * res_p, const area_t * a1_p, const area_t * a2_p); void area_join(area_t * a_res_p, const area_t * a1_p, const area_t * a2_p); diff --git a/lv_misc/circ.c b/lv_misc/circ.c index e8135f6af..100474f96 100644 --- a/lv_misc/circ.c +++ b/lv_misc/circ.c @@ -8,7 +8,7 @@ /********************* * INCLUDES *********************/ -#include +#include /********************* * DEFINES diff --git a/lv_misc/circ.h b/lv_misc/circ.h index 4feaf5342..1402a576b 100644 --- a/lv_misc/circ.h +++ b/lv_misc/circ.h @@ -10,7 +10,7 @@ * INCLUDES *********************/ -#include +#include #include /********************* diff --git a/lv_misc/text.c b/lv_misc/text.c index 7538ff546..a628e6f72 100644 --- a/lv_misc/text.c +++ b/lv_misc/text.c @@ -72,6 +72,10 @@ uint16_t txt_get_next_line(const char * txt, const font_t * font_p, while(txt[i] == ' ') i++; + /* Do not let to return without doing nothing. + * Find at least one character */ + if(i == 0) i++; + return i; } /*If this char still can fit to this line then check if diff --git a/lv_misc/text.h b/lv_misc/text.h index b13b923d4..4ec8b031d 100644 --- a/lv_misc/text.h +++ b/lv_misc/text.h @@ -10,7 +10,7 @@ * INCLUDES *********************/ -#include +#include #include #include "font.h" diff --git a/lv_obj/lv_obj.c b/lv_obj/lv_obj.c index 32c8f1c34..a3b76746a 100644 --- a/lv_obj/lv_obj.c +++ b/lv_obj/lv_obj.c @@ -394,18 +394,15 @@ void lv_obj_set_parent(lv_obj_t* obj_dp, lv_obj_t* parent_dp) old_pos.y = lv_obj_get_y(obj_dp); ll_chg_list(&obj_dp->par_dp->child_ll, &parent_dp->child_ll, obj_dp); - + obj_dp->par_dp = parent_dp; + lv_obj_set_pos(obj_dp, old_pos.x, old_pos.y); + /*Notify the original parent because one of its children is lost*/ obj_dp->par_dp->signal_f(obj_dp->par_dp, LV_SIGNAL_CHILD_CHG, NULL); - - obj_dp->par_dp = parent_dp; - - lv_obj_set_pos(obj_dp, old_pos.x, old_pos.y); - + /*Notify the new parent about the child*/ parent_dp->signal_f(parent_dp, LV_SIGNAL_CHILD_CHG, obj_dp); - lv_obj_inv(obj_dp); } @@ -1342,20 +1339,19 @@ static bool lv_obj_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mo bool cover; cover = area_is_in(mask_p, &obj_dp->cords); return cover; - } + } else if(mode == LV_DESIGN_DRAW_MAIN) { + lv_objs_t * objs_p = lv_obj_get_style(obj_dp); - lv_objs_t * objs_p = lv_obj_get_style(obj_dp); - - opa_t opa = lv_obj_get_opa(obj_dp); - color_t color = objs_p->color; + opa_t opa = lv_obj_get_opa(obj_dp); + color_t color = objs_p->color; - /*Simply draw a rectangle*/ + /*Simply draw a rectangle*/ #if LV_VDB_SIZE == 0 - lv_rfill(&obj_dp->cords, mask_p, color, opa); + lv_rfill(&obj_dp->cords, mask_p, color, opa); #else - lv_vfill(&obj_dp->cords, mask_p, color, opa); + lv_vfill(&obj_dp->cords, mask_p, color, opa); #endif - + } return true; } diff --git a/lv_obj/lv_obj.h b/lv_obj/lv_obj.h index b48f3fc6e..e20b8c76e 100644 --- a/lv_obj/lv_obj.h +++ b/lv_obj/lv_obj.h @@ -9,7 +9,7 @@ /********************* * INCLUDES *********************/ -#include +#include #include #include #include "misc/mem/dyn_mem.h" @@ -54,7 +54,8 @@ struct __LV_OBJ_T; typedef enum { - LV_DESIGN_DRAW, + LV_DESIGN_DRAW_MAIN, + LV_DESIGN_DRAW_POST, LV_DESIGN_COVER_CHK, }lv_design_mode_t; diff --git a/lv_obj/lv_refr.c b/lv_obj/lv_refr.c index 17639a72b..f21d554b5 100644 --- a/lv_obj/lv_refr.c +++ b/lv_obj/lv_refr.c @@ -399,7 +399,7 @@ static void lv_refr_obj(lv_obj_t* obj_dp, const area_t * mask_ori_p) /* Redraw the object */ if(obj_dp->opa != OPA_TRANSP && LV_SA(obj_dp, lv_objs_t)->transp == 0) { - obj_dp->design_f(obj_dp, &mask_parent, LV_DESIGN_DRAW); + obj_dp->design_f(obj_dp, &mask_parent, LV_DESIGN_DRAW_MAIN); } area_t mask_child; /*Mask from obj_dp and its child*/ @@ -416,5 +416,10 @@ static void lv_refr_obj(lv_obj_t* obj_dp, const area_t * mask_ori_p) lv_refr_obj(child_p, &mask_child); } } + + /* If all the children are redrawn call make 'post draw' design */ + if(obj_dp->opa != OPA_TRANSP && LV_SA(obj_dp, lv_objs_t)->transp == 0) { + obj_dp->design_f(obj_dp, &mask_parent, LV_DESIGN_DRAW_POST); + } } } diff --git a/lv_obj/lv_vdb.h b/lv_obj/lv_vdb.h index 79fbbe79a..06e1b9574 100644 --- a/lv_obj/lv_vdb.h +++ b/lv_obj/lv_vdb.h @@ -14,7 +14,7 @@ #if LV_VDB_SIZE != 0 #include "misc/others/color.h" -#include +#include #include "../lv_misc/font.h" /********************* diff --git a/lv_objx/lv_btn.c b/lv_objx/lv_btn.c index 49c31fca2..171336cc9 100644 --- a/lv_objx/lv_btn.c +++ b/lv_objx/lv_btn.c @@ -368,6 +368,7 @@ lv_btns_t * lv_btns_get(lv_btns_builtin_t style, lv_btns_t * copy_p) * @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_btn_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -392,19 +393,18 @@ static bool lv_btn_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mod if(area_is_in(mask_p, &area_tmp) == true) return true; return false; + } else if(mode == LV_DESIGN_DRAW_MAIN) { + opa_t opa = lv_obj_get_opa(obj_dp); + area_t area; + lv_obj_get_cords(obj_dp, &area); + + lv_rects_t rects_tmp; + + lv_btn_style_load(obj_dp, &rects_tmp); + + /*Draw the rectangle*/ + lv_draw_rect(&area, mask_p, &rects_tmp, opa); } - - opa_t opa = lv_obj_get_opa(obj_dp); - area_t area; - lv_obj_get_cords(obj_dp, &area); - - lv_rects_t rects_tmp; - - lv_btn_style_load(obj_dp, &rects_tmp); - - /*Draw the rectangle*/ - lv_draw_rect(&area, mask_p, &rects_tmp, opa); - return true; } diff --git a/lv_objx/lv_btnm.c b/lv_objx/lv_btnm.c index a234b40b1..e184f3a62 100644 --- a/lv_objx/lv_btnm.c +++ b/lv_objx/lv_btnm.c @@ -319,6 +319,7 @@ lv_btnm_callback_t lv_btnm_get_cb(lv_obj_t * obj_dp) * @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_btnm_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) diff --git a/lv_objx/lv_cb.c b/lv_objx/lv_cb.c index 817d87382..0e0ee3854 100644 --- a/lv_objx/lv_cb.c +++ b/lv_objx/lv_cb.c @@ -263,6 +263,7 @@ lv_cbs_t * lv_cbs_get(lv_cbs_builtin_t style, lv_cbs_t * copy_p) * @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_cb_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) diff --git a/lv_objx/lv_chart.c b/lv_objx/lv_chart.c index bc0058ba8..f3070870c 100644 --- a/lv_objx/lv_chart.c +++ b/lv_objx/lv_chart.c @@ -354,6 +354,7 @@ uint16_t lv_chart_get_pnum(lv_obj_t * obj_dp) * @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_chart_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -361,31 +362,30 @@ static bool lv_chart_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_m if(mode == LV_DESIGN_COVER_CHK) { /*Return false if the object is not covers the mask_p area*/ return ancestor_design_fp(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + /*Draw the rectangle ancient*/ + ancestor_design_fp(obj_dp, mask_p, mode); + + /*Draw the object*/ + + lv_chart_ext_t * ext_dp = lv_obj_get_ext(obj_dp); + + lv_chart_draw_div(obj_dp, mask_p); + + switch(ext_dp->type) { + case LV_CHART_LINE: + lv_chart_draw_lines(obj_dp, mask_p); + break; + case LV_CHART_COL: + lv_chart_draw_cols(obj_dp, mask_p); + break; + case LV_CHART_POINT: + lv_chart_draw_points(obj_dp, mask_p); + break; + default: + break; + } } - - /*Draw the rectangle ancient*/ - ancestor_design_fp(obj_dp, mask_p, mode); - - /*Draw the object*/ - - lv_chart_ext_t * ext_dp = lv_obj_get_ext(obj_dp); - - lv_chart_draw_div(obj_dp, mask_p); - - switch(ext_dp->type) { - case LV_CHART_LINE: - lv_chart_draw_lines(obj_dp, mask_p); - break; - case LV_CHART_COL: - lv_chart_draw_cols(obj_dp, mask_p); - break; - case LV_CHART_POINT: - lv_chart_draw_points(obj_dp, mask_p); - break; - default: - break; - } - return true; } diff --git a/lv_objx/lv_img.c b/lv_objx/lv_img.c index 0bb3f0fdb..bb1bb0249 100644 --- a/lv_objx/lv_img.c +++ b/lv_objx/lv_img.c @@ -256,6 +256,7 @@ bool lv_img_get_auto_size(lv_obj_t* obj_dp) * @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_img_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -270,24 +271,25 @@ static bool lv_img_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mod return cover; } else return false; + } else if(mode == LV_DESIGN_DRAW_MAIN) { + area_t cords; + + lv_obj_get_cords(obj_dp, &cords); + opa_t opa = lv_obj_get_opa(obj_dp); + + area_t cords_tmp; + cords_tmp.y1 = cords.y1; + cords_tmp.y2 = cords.y1 + ext_p->h - 1; + + for(; cords_tmp.y1 < cords.y2; cords_tmp.y1 += ext_p->h, cords_tmp.y2 += ext_p->h) { + cords_tmp.x1 = cords.x1; + cords_tmp.x2 = cords.x1 + ext_p->w - 1; + for(; cords_tmp.x1 < cords.x2; cords_tmp.x1 += ext_p->w, cords_tmp.x2 += ext_p->w) { + lv_draw_img(&cords_tmp, mask_p, imgs_p, opa, ext_p->fn_dp); + } + } } - area_t cords; - - lv_obj_get_cords(obj_dp, &cords); - opa_t opa = lv_obj_get_opa(obj_dp); - - area_t cords_tmp; - cords_tmp.y1 = cords.y1; - cords_tmp.y2 = cords.y1 + ext_p->h - 1; - - for(; cords_tmp.y1 < cords.y2; cords_tmp.y1 += ext_p->h, cords_tmp.y2 += ext_p->h) { - cords_tmp.x1 = cords.x1; - cords_tmp.x2 = cords.x1 + ext_p->w - 1; - for(; cords_tmp.x1 < cords.x2; cords_tmp.x1 += ext_p->w, cords_tmp.x2 += ext_p->w) { - lv_draw_img(&cords_tmp, mask_p, imgs_p, opa, ext_p->fn_dp); - } - } return true; } diff --git a/lv_objx/lv_label.c b/lv_objx/lv_label.c index b378a9ae8..47a51d3ed 100644 --- a/lv_objx/lv_label.c +++ b/lv_objx/lv_label.c @@ -71,10 +71,10 @@ static lv_labels_t lv_labels_txt = { * @param copy_dp 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_dp, lv_obj_t * ori_dp) +lv_obj_t* lv_label_create(lv_obj_t* par_dp, lv_obj_t * copy_dp) { /*Create a basic object*/ - lv_obj_t* new_obj = lv_obj_create(par_dp, ori_dp); + lv_obj_t* new_obj = lv_obj_create(par_dp, copy_dp); dm_assert(new_obj); /*Extend the basic object to a label object*/ @@ -87,7 +87,7 @@ lv_obj_t* lv_label_create(lv_obj_t* par_dp, lv_obj_t * ori_dp) lv_obj_set_signal_f(new_obj, lv_label_signal); /*Init the new label*/ - if(ori_dp == NULL) { + if(copy_dp == NULL) { lv_obj_set_opa(new_obj, OPA_COVER); lv_obj_set_click(new_obj, false); lv_obj_set_style(new_obj, &lv_labels_def); @@ -96,8 +96,8 @@ lv_obj_t* lv_label_create(lv_obj_t* par_dp, lv_obj_t * ori_dp) } /*Copy 'ori_dp' if not NULL*/ else { - lv_label_set_fixw(new_obj, lv_label_get_fixw(ori_dp)); - lv_label_set_text(new_obj, lv_label_get_text(ori_dp)); + lv_label_set_fixw(new_obj, lv_label_get_fixw(copy_dp)); + lv_label_set_text(new_obj, lv_label_get_text(copy_dp)); } return new_obj; } @@ -127,8 +127,9 @@ bool lv_label_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param) label_p->txt_dp = NULL; break; case LV_SIGNAL_STYLE_CHG: - lv_label_set_text(obj_dp, lv_label_get_text(obj_dp)); + lv_label_set_text(obj_dp, NULL); break; + default: break; } @@ -144,23 +145,30 @@ bool lv_label_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param) /** * Set a new text for a label * @param obj_dp pointer to a label object - * @param text '\0' terminated character string + * @param text '\0' terminated character string. If NULL then refresh with the current text. */ void lv_label_set_text(lv_obj_t * obj_dp, const char * text) { - if(text == NULL) return; lv_obj_inv(obj_dp); - lv_label_ext_t * ext_p = lv_obj_get_ext(obj_dp); - uint32_t len = strlen(text) + 1; + lv_label_ext_t * label_ext_dp = lv_obj_get_ext(obj_dp); - if(ext_p->txt_dp != NULL && text != ext_p->txt_dp) { - dm_free(ext_p->txt_dp); + if(text == label_ext_dp->txt_dp) text = NULL; + + if(text != NULL) { + uint32_t len = strlen(text) + 1; + if(label_ext_dp->txt_dp != NULL) { + dm_free(label_ext_dp->txt_dp); + } + label_ext_dp->txt_dp = dm_alloc(len); + strcpy(label_ext_dp->txt_dp, text); + } else { + text = label_ext_dp->txt_dp; } - ext_p->txt_dp = dm_alloc(len); - strcpy(ext_p->txt_dp, text); + /*If 'text" still NULL then nothing to do: return*/ + if(text == NULL) return; uint32_t line_start = 0; uint32_t new_line_start = 0; @@ -173,7 +181,7 @@ void lv_label_set_text(lv_obj_t * obj_dp, const char * text) cord_t act_line_length; /*If the fix width is not enabled the set the max length to very big */ - if(ext_p->fixw == 0) { + if(label_ext_dp->fixw == 0) { max_length = LV_CORD_MAX; } @@ -185,7 +193,7 @@ void lv_label_set_text(lv_obj_t * obj_dp, const char * text) new_height += labels_p->line_space; /*If no fix width then calc. the longest line */ - if(ext_p->fixw == false) { + if(label_ext_dp->fixw == false) { act_line_length = txt_get_width(&text[line_start], new_line_start - line_start, font_p, labels_p->letter_space); if(act_line_length > longest_line) { @@ -199,7 +207,7 @@ void lv_label_set_text(lv_obj_t * obj_dp, const char * text) /*Correction with the last line space*/ new_height -= labels_p->line_space; - if(ext_p->fixw == 0) { + if(label_ext_dp->fixw == 0) { /*Refresh the full size */ lv_obj_set_size(obj_dp, longest_line, new_height); } else { @@ -253,7 +261,7 @@ bool lv_label_get_fixw(lv_obj_t * obj_dp) * Get the relative x and y coordinates of a letter * @param obj_dp pointer to a label object * @param index index of the letter (0 ... text length) - * @param pos_p store the result here + * @param pos_p store the result here (E.g. index = 0 gives 0;0 coordinates) */ void lv_label_get_letter_pos(lv_obj_t * obj_dp, uint16_t index, point_t * pos_p) { @@ -273,9 +281,9 @@ void lv_label_get_letter_pos(lv_obj_t * obj_dp, uint16_t index, point_t * pos_p) } /*Search the line of the index letter */; - while (text[line_start] != '\0') { + while (text[new_line_start] != '\0') { new_line_start += txt_get_next_line(&text[line_start], font_p, labels_p->letter_space, max_length); - if(index < new_line_start) break; /*Lines of index letter begins at 'line_start'*/ + if(index < new_line_start || text[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/ y += letter_height + labels_p->line_space; line_start = new_line_start; @@ -300,6 +308,12 @@ void lv_label_get_letter_pos(lv_obj_t * obj_dp, uint16_t index, point_t * pos_p) } +/** + * Get the index of letter on a relative point of a label + * @param obj_dp pointer to label object + * @param pos_p 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) + */ uint16_t lv_label_get_letter_on(lv_obj_t * obj_dp, point_t * pos_p) { const char * text = lv_label_get_text(obj_dp); @@ -337,7 +351,7 @@ uint16_t lv_label_get_letter_on(lv_obj_t * obj_dp, point_t * pos_p) uint32_t i; for(i = line_start; i < new_line_start-1; i++) { x += font_get_width(font_p, text[i]) + labels_p->letter_space; - if(pos_p->x <= x) break; + if(pos_p->x < x) break; } @@ -392,23 +406,23 @@ lv_labels_t * lv_labels_get(lv_labels_builtin_t style, lv_labels_t * copy_p) * @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_label_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) { /* A label never covers an area */ if(mode == LV_DESIGN_COVER_CHK) return false; - - /*TEST: draw a background for the label*/ - /*lv_vfill(&obj_dp->cords, mask_p, COLOR_LIME, OPA_COVER); */ - - area_t cords; - lv_obj_get_cords(obj_dp, &cords); - opa_t opa= lv_obj_get_opa(obj_dp); - const char * txt = lv_label_get_text(obj_dp); - - lv_draw_label(&cords, mask_p, lv_obj_get_style(obj_dp), opa, txt); + else if(mode == LV_DESIGN_DRAW_MAIN) { + /*TEST: draw a background for the label*/ + /*lv_vfill(&obj_dp->cords, mask_p, COLOR_LIME, OPA_COVER); */ + area_t cords; + lv_obj_get_cords(obj_dp, &cords); + opa_t opa= lv_obj_get_opa(obj_dp); + const char * txt = lv_label_get_text(obj_dp); + lv_draw_label(&cords, mask_p, lv_obj_get_style(obj_dp), opa, txt); + } return true; } diff --git a/lv_objx/lv_led.c b/lv_objx/lv_led.c index 3c5d688d8..d1cd5bc73 100644 --- a/lv_objx/lv_led.c +++ b/lv_objx/lv_led.c @@ -235,6 +235,7 @@ uint8_t lv_led_get_bright(lv_obj_t * obj_dp) * @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_led_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -242,26 +243,23 @@ static bool lv_led_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mod if(mode == LV_DESIGN_COVER_CHK) { /*Return false if the object is not covers the mask_p area*/ return false; + } else if(mode == LV_DESIGN_DRAW_MAIN) { + /*Make darker colors in a temporary style according to the brightness*/ + lv_led_ext_t * led_ext_p = lv_obj_get_ext(obj_dp); + lv_leds_t * leds_p = lv_obj_get_style(obj_dp); + lv_leds_t leds_tmp; + + memcpy(&leds_tmp, leds_p, sizeof(leds_tmp)); + + leds_tmp.rects.objs.color = color_mix(leds_tmp.rects.objs.color, COLOR_BLACK, led_ext_p->bright); + leds_tmp.rects.gcolor = color_mix(leds_tmp.rects.gcolor, COLOR_BLACK, led_ext_p->bright); + + opa_t opa = lv_obj_get_opa(obj_dp); + area_t area; + lv_obj_get_cords(obj_dp, &area); + + lv_draw_rect(&area, mask_p, &leds_tmp.rects, opa); } - - /*Draw the object*/ - - /*Make darker colors in a temporary style according to the brightness*/ - lv_led_ext_t * led_ext_p = lv_obj_get_ext(obj_dp); - lv_leds_t * leds_p = lv_obj_get_style(obj_dp); - lv_leds_t leds_tmp; - - memcpy(&leds_tmp, leds_p, sizeof(leds_tmp)); - - leds_tmp.rects.objs.color = color_mix(leds_tmp.rects.objs.color, COLOR_BLACK, led_ext_p->bright); - leds_tmp.rects.gcolor = color_mix(leds_tmp.rects.gcolor, COLOR_BLACK, led_ext_p->bright); - - opa_t opa = lv_obj_get_opa(obj_dp); - area_t area; - lv_obj_get_cords(obj_dp, &area); - - lv_draw_rect(&area, mask_p, &leds_tmp.rects, opa); - return true; } diff --git a/lv_objx/lv_line.c b/lv_objx/lv_line.c index e0d1b599a..55a5b4189 100644 --- a/lv_objx/lv_line.c +++ b/lv_objx/lv_line.c @@ -13,7 +13,7 @@ #include "../lv_draw/lv_draw_vbasic.h" #include "../lv_draw/lv_draw_rbasic.h" #include "../lv_draw/lv_draw.h" -#include +#include #include #include #include @@ -283,49 +283,50 @@ lv_lines_t * lv_lines_get(lv_lines_builtin_t style, lv_lines_t * copy_p) * @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_line_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) { /*A line never covers an area*/ if(mode == LV_DESIGN_COVER_CHK) return false; - - lv_line_ext_t * ext_p = lv_obj_get_ext(obj_dp); + else if(mode == LV_DESIGN_DRAW_MAIN) { + lv_line_ext_t * ext_p = lv_obj_get_ext(obj_dp); - if(ext_p->point_num == 0 || ext_p->point_p == NULL) return false; + if(ext_p->point_num == 0 || ext_p->point_p == NULL) return false; - lv_lines_t * lines_p = lv_obj_get_style(obj_dp); + lv_lines_t * lines_p = lv_obj_get_style(obj_dp); - opa_t opa = lv_obj_get_opa(obj_dp); - area_t area; - lv_obj_get_cords(obj_dp, &area); - cord_t x_ofs = area.x1; - cord_t y_ofs = area.y1; - point_t p1; - point_t p2; - cord_t h = lv_obj_get_height(obj_dp); - uint16_t i; - uint8_t us = 1; - if(ext_p->upscale != 0) { - us = LV_DOWNSCALE; - } - - /*Read all pints and draw the lines*/ - for (i = 0; i < ext_p->point_num - 1; i++) { - - p1.x = ext_p->point_p[i].x * us + x_ofs; - p2.x = ext_p->point_p[i + 1].x * us + x_ofs; - - if(ext_p->y_inv == 0) { - p1.y = ext_p->point_p[i].y * us + y_ofs; - p2.y = ext_p->point_p[i + 1].y * us + y_ofs; - } else { - p1.y = h - ext_p->point_p[i].y * us + y_ofs; - p2.y = h - ext_p->point_p[i + 1].y * us + y_ofs; + opa_t opa = lv_obj_get_opa(obj_dp); + area_t area; + lv_obj_get_cords(obj_dp, &area); + cord_t x_ofs = area.x1; + cord_t y_ofs = area.y1; + point_t p1; + point_t p2; + cord_t h = lv_obj_get_height(obj_dp); + uint16_t i; + uint8_t us = 1; + if(ext_p->upscale != 0) { + us = LV_DOWNSCALE; } - lv_draw_line(&p1, &p2, mask_p, lines_p, opa); - } - + + /*Read all pints and draw the lines*/ + for (i = 0; i < ext_p->point_num - 1; i++) { + + p1.x = ext_p->point_p[i].x * us + x_ofs; + p2.x = ext_p->point_p[i + 1].x * us + x_ofs; + + if(ext_p->y_inv == 0) { + p1.y = ext_p->point_p[i].y * us + y_ofs; + p2.y = ext_p->point_p[i + 1].y * us + y_ofs; + } else { + p1.y = h - ext_p->point_p[i].y * us + y_ofs; + p2.y = h - ext_p->point_p[i + 1].y * us + y_ofs; + } + lv_draw_line(&p1, &p2, mask_p, lines_p, opa); + } + } return true; } diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index 24a2a7773..d14fb4861 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -35,13 +35,72 @@ static bool lv_list_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mo static lv_lists_t lv_lists_def = { /*Page style*/ - .pages.bg_rects.objs.color = COLOR_MAKE(0x20, 0x50, 0x80), .pages.bg_rects.gcolor = COLOR_SILVER, .pages.bg_rects.bcolor = COLOR_GRAY, - .pages.bg_rects.bopa = 50, .pages.bg_rects.bwidth = 0 * LV_STYLE_MULT, .pages.bg_rects.round = 2 * LV_STYLE_MULT, - .pages.bg_rects.empty = 1, + .pages.bg_rects.objs.color = COLOR_MAKE(0x50, 0x70, 0x90), .pages.bg_rects.gcolor = COLOR_MAKE(0x70, 0xA0, 0xC0), + .pages.bg_rects.bcolor = COLOR_WHITE, .pages.bg_rects.bopa = 50, .pages.bg_rects.bwidth = 2 * LV_STYLE_MULT, + .pages.bg_rects.round = 4 * LV_STYLE_MULT, + .pages.bg_rects.empty = 0, .pages.bg_rects.vpad = 10 * LV_STYLE_MULT, .pages.bg_rects.hpad = 10 * LV_STYLE_MULT, .pages.bg_rects.opad = 5 * LV_STYLE_MULT, + .pages.scrable_rects.objs.color = COLOR_WHITE, + .pages.scrable_rects.gcolor = COLOR_SILVER, + .pages.scrable_rects.bcolor = COLOR_GRAY, + .pages.scrable_rects.bopa = 100, + .pages.scrable_rects.bwidth = 2 * LV_STYLE_MULT, + .pages.scrable_rects.round = 4 * LV_STYLE_MULT, + .pages.scrable_rects.empty = 0, + .pages.scrable_rects.hpad = 10 * LV_STYLE_MULT, + .pages.scrable_rects.vpad = 10 * LV_STYLE_MULT, + .pages.scrable_rects.opad = 10 * LV_STYLE_MULT, + + .pages.sb_rects.objs.color = COLOR_BLACK, .pages.sb_rects.gcolor = COLOR_BLACK, .pages.sb_rects.bcolor = COLOR_WHITE, + .pages.sb_rects.bopa = 50, .pages.sb_rects.bwidth = 1 * LV_STYLE_MULT, .pages.sb_rects.round = 5 * LV_STYLE_MULT, + .pages.sb_rects.empty = 0, .pages.sb_width= 8 * LV_STYLE_MULT, .pages.sb_opa=50, .pages.sb_mode = LV_PAGE_SB_MODE_AUTO, + + /*List element style*/ + .liste_btns.mcolor[LV_BTN_STATE_REL] = COLOR_MAKE(0xa0, 0xa0, 0xa0), .liste_btns.gcolor[LV_BTN_STATE_REL] = COLOR_WHITE, .liste_btns.bcolor[LV_BTN_STATE_REL] = COLOR_WHITE, + .liste_btns.mcolor[LV_BTN_STATE_PR] = COLOR_MAKE(0xa0, 0xa0, 0xa0), .liste_btns.gcolor[LV_BTN_STATE_PR] = COLOR_MAKE(0xa0, 0xc0, 0xe0), .liste_btns.bcolor[LV_BTN_STATE_PR] = COLOR_WHITE, + .liste_btns.mcolor[LV_BTN_STATE_TGL_REL] = COLOR_MAKE(0x60,0x80,0xa0), .liste_btns.gcolor[LV_BTN_STATE_TGL_REL] = COLOR_MAKE(0xc0, 0xd0, 0xf0), .liste_btns.bcolor[LV_BTN_STATE_TGL_REL] = COLOR_WHITE, + .liste_btns.mcolor[LV_BTN_STATE_TGL_PR] = COLOR_MAKE(0x60, 0x80, 0xa0), .liste_btns.gcolor[LV_BTN_STATE_TGL_PR] = COLOR_MAKE(0x80, 0xa0, 0xc0), .liste_btns.bcolor[LV_BTN_STATE_TGL_PR] = COLOR_WHITE, + .liste_btns.mcolor[LV_BTN_STATE_INA] = COLOR_SILVER, .liste_btns.gcolor[LV_BTN_STATE_INA] = COLOR_GRAY, .liste_btns.bcolor[LV_BTN_STATE_INA] = COLOR_WHITE, + .liste_btns.rects.bwidth = 2 * LV_STYLE_MULT, .liste_btns.rects.bopa = 50, + .liste_btns.rects.empty = 0, .liste_btns.rects.round = 4 * LV_STYLE_MULT, + .liste_btns.rects.hpad = 10 * LV_STYLE_MULT, + .liste_btns.rects.vpad = 10 * LV_STYLE_MULT, + .liste_btns.rects.opad = 20 * LV_STYLE_MULT, + + .liste_labels.objs.color = COLOR_MAKE(0x20,0x20,0x20), .liste_labels.font = LV_FONT_DEFAULT, + .liste_labels.letter_space = 2 * LV_STYLE_MULT, .liste_labels.line_space = 2 * LV_STYLE_MULT, + .liste_labels.mid = 0, + + .liste_imgs.recolor_opa = OPA_COVER, + + .liste_layout = LV_RECT_LAYOUT_ROW_M +}; + +static lv_lists_t lv_lists_tight = +{ + /*Page style*/ + .pages.bg_rects.objs.color = COLOR_MAKE(0x50, 0x70, 0x90), .pages.bg_rects.gcolor = COLOR_MAKE(0x70, 0xA0, 0xC0), + .pages.bg_rects.bcolor = COLOR_WHITE, .pages.bg_rects.bopa = 50, .pages.bg_rects.bwidth = 0 * LV_STYLE_MULT, + .pages.bg_rects.round = 4 * LV_STYLE_MULT, + .pages.bg_rects.empty = 1, + .pages.bg_rects.vpad = 0 * LV_STYLE_MULT, + .pages.bg_rects.hpad = 0 * LV_STYLE_MULT, + .pages.bg_rects.opad = 0 * LV_STYLE_MULT, + + .pages.scrable_rects.objs.color = COLOR_WHITE, + .pages.scrable_rects.gcolor = COLOR_SILVER, + .pages.scrable_rects.bcolor = COLOR_GRAY, + .pages.scrable_rects.bopa = 100, + .pages.scrable_rects.bwidth = 0 * LV_STYLE_MULT, + .pages.scrable_rects.round = 0 * LV_STYLE_MULT, + .pages.scrable_rects.empty = 0, + .pages.scrable_rects.hpad = 0 * LV_STYLE_MULT, + .pages.scrable_rects.vpad = 0 * LV_STYLE_MULT, + .pages.scrable_rects.opad = 0 * LV_STYLE_MULT, + .pages.sb_rects.objs.color = COLOR_BLACK, .pages.sb_rects.gcolor = COLOR_BLACK, .pages.sb_rects.bcolor = COLOR_WHITE, .pages.sb_rects.bopa = 50, .pages.sb_rects.bwidth = 1 * LV_STYLE_MULT, .pages.sb_rects.round = 5 * LV_STYLE_MULT, .pages.sb_rects.empty = 0, .pages.sb_width= 8 * LV_STYLE_MULT, .pages.sb_opa=50, .pages.sb_mode = LV_PAGE_SB_MODE_AUTO, @@ -91,13 +150,18 @@ lv_obj_t* lv_list_create(lv_obj_t* par_dp, lv_obj_t * copy_dp) lv_obj_t * new_obj_dp = lv_page_create(par_dp, copy_dp); dm_assert(new_obj_dp); lv_list_ext_t * ext_p= lv_obj_alloc_ext(new_obj_dp, sizeof(lv_list_ext_t)); - + + lv_obj_set_signal_f(new_obj_dp, lv_list_signal); + /*Init the new list object*/ if(copy_dp == NULL) { ext_p->fit = LV_LIST_FIT_LONGEST; - lv_obj_set_signal_f(new_obj_dp, lv_list_signal); + lv_obj_set_size_us(new_obj_dp, 100, 150); lv_obj_set_style(new_obj_dp, &lv_lists_def); - lv_rect_set_layout(new_obj_dp, LV_LIST_LAYOUT_DEF); + lv_rect_set_layout(LV_EA(new_obj_dp, lv_list_ext_t)->page_ext.scrolling_dp, LV_LIST_LAYOUT_DEF); + } else { + lv_list_ext_t * copy_ext_dp = lv_obj_get_ext(copy_dp); + ext_p->fit = copy_ext_dp->fit; } return new_obj_dp; @@ -147,7 +211,7 @@ lv_obj_t * lv_list_add(lv_obj_t * obj_dp, const char * img_fn, const char * txt, lv_obj_set_style(liste, &lists_p->liste_btns); lv_btn_set_rel_action(liste, rel_action); lv_page_glue_obj(liste, true); - lv_rect_set_layout(liste, lv_lists_def.liste_layout); + lv_rect_set_layout(liste, lists_p->liste_layout); lv_rect_set_fit(liste, true, true); /*hor. fit might be disabled later*/ if(img_fn != NULL) { @@ -168,7 +232,7 @@ lv_obj_t * lv_list_add(lv_obj_t * obj_dp, const char * img_fn, const char * txt, if(ext_p->fit == LV_LIST_FIT_HOLDER) { /*Now the width will be adjusted*/ lv_rect_set_fit(liste, false, true); - cord_t w = lv_obj_get_width(lv_obj_get_parent(obj_dp)); + cord_t w = lv_obj_get_width(obj_dp); w -= lists_p->pages.bg_rects.hpad * 2; lv_obj_set_width(liste, w); } else if(ext_p->fit == LV_LIST_FIT_LONGEST) { @@ -178,51 +242,26 @@ lv_obj_t * lv_list_add(lv_obj_t * obj_dp, const char * img_fn, const char * txt, lv_obj_t * e; cord_t w = 0; /*Get the longest list element*/ - e = lv_obj_get_child(obj_dp, NULL); + lv_obj_t * e_par = lv_obj_get_parent(liste); /*The page changes the parent so get it*/ + e = lv_obj_get_child(e_par, NULL); while(e != NULL) { w = max(w, lv_obj_get_width(e)); - e = lv_obj_get_child(obj_dp, e); + e = lv_obj_get_child(e_par, e); } /*Set all list element to the longest width*/ - e = lv_obj_get_child(obj_dp, NULL); + e = lv_obj_get_child(e_par, NULL); while(e != NULL) { if(lv_obj_get_width(e) != w) { lv_obj_set_width(e, w); } - e = lv_obj_get_child(obj_dp, e); + e = lv_obj_get_child(e_par, e); } } return liste; } -/** - * Return with a pointer to a built-in style and/or copy it to a variable - * @param style a style name from lv_lists_builtin_t enum - * @param copy_p copy the style to this variable. (NULL if unused) - * @return pointer to an lv_lists_t style - */ -lv_lists_t * lv_lists_get(lv_lists_builtin_t style, lv_lists_t * copy_p) -{ - lv_lists_t *style_p; - - switch(style) { - case LV_LISTS_DEF: - style_p = &lv_lists_def; - break; - default: - style_p = &lv_lists_def; - } - - if(copy_p != NULL) { - if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_lists_t)); - else memcpy(copy_p, &lv_lists_def, sizeof(lv_lists_t)); - } - - return style_p; -} - /** * Move the list elements up by one * @param obj_dp pointer a to list object @@ -298,6 +337,38 @@ lv_list_fit_t lv_list_get_fit(lv_obj_t * obj_dp) return LV_EA(obj_dp, lv_list_ext_t)->fit; } + +/** + * Return with a pointer to a built-in style and/or copy it to a variable + * @param style a style name from lv_lists_builtin_t enum + * @param copy_p copy the style to this variable. (NULL if unused) + * @return pointer to an lv_lists_t style + */ +lv_lists_t * lv_lists_get(lv_lists_builtin_t style, lv_lists_t * copy_p) +{ + lv_lists_t *style_p; + + switch(style) { + case LV_LISTS_DEF: + case LV_LISTS_GAP: + style_p = &lv_lists_def; + break; + case LV_LISTS_TIGHT: + style_p = &lv_lists_tight; + break; + default: + style_p = &lv_lists_def; + } + + if(copy_p != NULL) { + if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_lists_t)); + else memcpy(copy_p, &lv_lists_def, sizeof(lv_lists_t)); + } + + return style_p; +} + + /********************** * STATIC FUNCTIONS **********************/ @@ -310,6 +381,7 @@ lv_list_fit_t lv_list_get_fit(lv_obj_t * obj_dp) * @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_list_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) diff --git a/lv_objx/lv_list.h b/lv_objx/lv_list.h index 67b9dba34..804d540a3 100644 --- a/lv_objx/lv_list.h +++ b/lv_objx/lv_list.h @@ -40,6 +40,8 @@ typedef struct typedef enum { LV_LISTS_DEF, + LV_LISTS_GAP, + LV_LISTS_TIGHT, }lv_lists_builtin_t; typedef enum diff --git a/lv_objx/lv_objx_templ.c b/lv_objx/lv_objx_templ.c index b70e2102c..596891492 100644 --- a/lv_objx/lv_objx_templ.c +++ b/lv_objx/lv_objx_templ.c @@ -156,6 +156,7 @@ lv_templs_t * lv_templs_get(lv_templs_builtin_t style, lv_templs_t * copy_p) * @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_templ_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index 2fd7fed6e..d30cefddc 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -12,7 +12,8 @@ #include "misc/math/math_base.h" #include "../lv_objx/lv_page.h" #include "../lv_objx/lv_rect.h" - +#include "../lv_draw/lv_draw.h" +#include "../lv_obj/lv_refr.h" /********************* * DEFINES @@ -26,23 +27,38 @@ * STATIC PROTOTYPES **********************/ static void lv_page_sb_refresh(lv_obj_t* main_dp); +static bool lv_page_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode); +static bool lv_scrolling_signal(lv_obj_t* obj_dp, lv_signal_t sign, void* param); /********************** * STATIC VARIABLES **********************/ +static lv_design_f_t ancestor_design_f; + static lv_pages_t lv_pages_def = { - .bg_rects.objs.color = COLOR_WHITE, - .bg_rects.gcolor = COLOR_SILVER, - .bg_rects.bcolor = COLOR_GRAY, + .bg_rects.objs.color = COLOR_MAKE(0x50, 0x70, 0x90), + .bg_rects.gcolor = COLOR_MAKE(0x70, 0xA0, 0xC0), + .bg_rects.bcolor = COLOR_WHITE, .bg_rects.bopa = 50, - .bg_rects.bwidth = 0 * LV_STYLE_MULT, - .bg_rects.round = 2 * LV_STYLE_MULT, + .bg_rects.bwidth = 2 * LV_STYLE_MULT, + .bg_rects.round = 4 * LV_STYLE_MULT, .bg_rects.empty = 0, .bg_rects.hpad = 10 * LV_STYLE_MULT, .bg_rects.vpad = 10 * LV_STYLE_MULT, .bg_rects.opad = 5 * LV_STYLE_MULT, + .scrable_rects.objs.color = COLOR_WHITE, + .scrable_rects.gcolor = COLOR_SILVER, + .scrable_rects.bcolor = COLOR_GRAY, + .scrable_rects.bopa = 50, + .scrable_rects.bwidth = 0 * LV_STYLE_MULT, + .scrable_rects.round = 2 * LV_STYLE_MULT, + .scrable_rects.empty = 0, + .scrable_rects.hpad = 10 * LV_STYLE_MULT, + .scrable_rects.vpad = 10 * LV_STYLE_MULT, + .scrable_rects.opad = 5 * LV_STYLE_MULT, + .sb_rects.objs.color = COLOR_BLACK, .sb_rects.gcolor = COLOR_BLACK, .sb_rects.bcolor = COLOR_WHITE, @@ -56,47 +72,29 @@ static lv_pages_t lv_pages_def = .sb_width= 8 * LV_STYLE_MULT, .sb_opa=50, - .sb_mode = LV_PAGE_SB_MODE_ON, + .sb_mode = LV_PAGE_SB_MODE_AUTO, }; -static lv_pages_t lv_pages_paper = -{ - .bg_rects.objs.color = COLOR_WHITE, - .bg_rects.gcolor = COLOR_WHITE, - .bg_rects.bcolor = COLOR_GRAY, - .bg_rects.bopa = 100, - .bg_rects.bwidth = 2 * LV_STYLE_MULT, - .bg_rects.round = 0 * LV_STYLE_MULT, - .bg_rects.empty = 0, - .bg_rects.hpad = 20 * LV_STYLE_MULT, - .bg_rects.vpad = 20 * LV_STYLE_MULT, - .bg_rects.opad = 10 * LV_STYLE_MULT, - - .sb_rects.objs.color = COLOR_BLACK, - .sb_rects.gcolor = COLOR_BLACK, - .sb_rects.bcolor = COLOR_SILVER, - .sb_rects.bopa = 100, - .sb_rects.bwidth = 1 * LV_STYLE_MULT, - .sb_rects.round = 5 * LV_STYLE_MULT, - .sb_rects.empty = 0, - .sb_rects.hpad = 0, - .sb_rects.vpad = 0, - .sb_rects.opad = 0, - - .sb_width = 10 * LV_STYLE_MULT, - .sb_opa=50, - .sb_mode = LV_PAGE_SB_MODE_ON, -}; - static lv_pages_t lv_pages_transp = { - .bg_rects.objs.transp = 1, - .bg_rects.empty = 1, - .bg_rects.bwidth = 0, + .bg_rects.objs.color = COLOR_MAKE(0x50, 0x70, 0x90), + .bg_rects.gcolor = COLOR_MAKE(0x70, 0xA0, 0xC0), + .bg_rects.bcolor = COLOR_WHITE, + .bg_rects.bopa = 50, + .bg_rects.bwidth = 0 * LV_STYLE_MULT, + .bg_rects.round = 2 * LV_STYLE_MULT, + .bg_rects.empty = 0, .bg_rects.hpad = 10 * LV_STYLE_MULT, .bg_rects.vpad = 10 * LV_STYLE_MULT, - .bg_rects.vpad = 10 * LV_STYLE_MULT, + .bg_rects.opad = 5 * LV_STYLE_MULT, + + .scrable_rects.objs.transp = 1, + .scrable_rects.empty = 1, + .scrable_rects.bwidth = 0, + .scrable_rects.hpad = 10 * LV_STYLE_MULT, + .scrable_rects.vpad = 10 * LV_STYLE_MULT, + .scrable_rects.vpad = 10 * LV_STYLE_MULT, .sb_rects.objs.color = COLOR_BLACK, .sb_rects.gcolor = COLOR_BLACK, @@ -129,57 +127,52 @@ static lv_pages_t lv_pages_transp = /** * Create a page objects * @param par_dp pointer to an object, it will be the parent of the new page + * @param copy_dp pointer to a page object, if not NULL then the new object will be copied from it * @return pointer to the created page */ -lv_obj_t* lv_page_create(lv_obj_t * par_dp, lv_obj_t * ori_dp) +lv_obj_t* lv_page_create(lv_obj_t * par_dp, lv_obj_t * copy_dp) { - lv_obj_t* new_dp = NULL; - - /*Create a basic object. Page elements will be stored here*/ - new_dp = lv_rect_create(par_dp, ori_dp); - - /*Init the new object*/ - lv_page_ext_t * page_p = lv_obj_alloc_ext(new_dp, sizeof(lv_page_ext_t)); + /*Create the ancestor object*/ + lv_obj_t * new_obj_dp = lv_rect_create(par_dp, copy_dp); + dm_assert(new_obj_dp); - /*Init the main rectangle if it is not copied*/ - if(ori_dp == NULL) { - lv_obj_set_drag(new_dp, true); - lv_obj_set_drag_throw(new_dp, true); - lv_obj_set_style(new_dp, &lv_pages_def); - lv_rect_set_fit(new_dp, true, true); - } else { - lv_obj_set_style(new_dp, lv_obj_get_style(ori_dp)); + /*Allocate the object type specific extended data*/ + lv_page_ext_t * ext_dp = lv_obj_alloc_ext(new_obj_dp, sizeof(lv_page_ext_t)); + dm_assert(ext_dp); + + if(ancestor_design_f == NULL) { + ancestor_design_f = lv_obj_get_design_f(new_obj_dp); } - lv_pages_t * pages_p = lv_obj_get_style(new_dp); - - /*Create horizontal scroll bar*/ - page_p->sbh_dp = lv_rect_create(par_dp, NULL); - lv_obj_set_height(page_p->sbh_dp, pages_p->sb_width); - lv_obj_set_style(page_p->sbh_dp, &pages_p->sb_rects); - lv_obj_set_click(page_p->sbh_dp, false); - if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) { - lv_obj_set_opa(page_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100); + /*Init the new page object*/ + if(copy_dp == NULL) { + ext_dp->scrolling_dp = lv_rect_create(new_obj_dp, NULL); + lv_obj_set_signal_f(ext_dp->scrolling_dp, lv_scrolling_signal); + lv_obj_set_drag(ext_dp->scrolling_dp, true); + lv_obj_set_drag_throw(ext_dp->scrolling_dp, true); + lv_rect_set_fit(ext_dp->scrolling_dp, true, true); + lv_obj_set_style(ext_dp->scrolling_dp, &lv_pages_def.scrable_rects); + + /* Add the signal function only if 'scrolling_dp' is created + * because everything has to be ready before any signal is received*/ + lv_obj_set_signal_f(new_obj_dp, lv_page_signal); + lv_obj_set_design_f(new_obj_dp, lv_page_design); + lv_obj_set_style(new_obj_dp, &lv_pages_def); } else { - lv_obj_set_opa(page_p->sbh_dp, OPA_TRANSP); - } + lv_page_ext_t * copy_ext_dp = lv_obj_get_ext(copy_dp); + ext_dp->scrolling_dp = lv_rect_create(new_obj_dp, copy_ext_dp->scrolling_dp); + lv_obj_set_signal_f(ext_dp->scrolling_dp, lv_scrolling_signal); - /*Create vertical scroll bar*/ - page_p->sbv_dp =lv_rect_create(par_dp, NULL); - lv_obj_set_width(page_p->sbv_dp, pages_p->sb_width); - lv_obj_set_style(page_p->sbv_dp, &pages_p->sb_rects); - lv_obj_set_click(page_p->sbv_dp, false); - if(lv_pages_def.sb_mode == LV_PAGE_SB_MODE_ON) { - lv_obj_set_opa(page_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100); - } else { - lv_obj_set_opa(page_p->sbv_dp, OPA_TRANSP); + /* Add the signal function only if 'scrolling_dp' is created + * because everything has to be ready before any signal is received*/ + lv_obj_set_signal_f(new_obj_dp, lv_page_signal); + lv_obj_set_design_f(new_obj_dp, lv_page_design); + lv_obj_set_style(new_obj_dp, lv_obj_get_style(copy_dp)); } - - lv_obj_set_signal_f(new_dp, lv_page_signal); - lv_page_sb_refresh(new_dp); + lv_page_sb_refresh(new_obj_dp); - return new_dp; + return new_obj_dp; } @@ -199,99 +192,42 @@ bool lv_page_signal(lv_obj_t* obj_dp, lv_signal_t sign, void* param) /* The object can be deleted so check its validity and then * make the object specific signal handling */ if(obj_valid != false) { - - cord_t new_x; - cord_t new_y; - bool refr_x = false; - bool refr_y = false; - area_t page_cords; - area_t par_cords; - - lv_obj_t * par_dp = lv_obj_get_parent(obj_dp); lv_page_ext_t * page_ext_p = lv_obj_get_ext(obj_dp); lv_pages_t * pages_p = lv_obj_get_style(obj_dp); - + lv_obj_t * child; switch(sign) { - case LV_SIGNAL_CORD_CHG: - new_x = lv_obj_get_x(obj_dp); - new_y = lv_obj_get_y(obj_dp); - lv_obj_get_cords(par_dp, &par_cords); - lv_obj_get_cords(obj_dp, &page_cords); - - /*page width smaller then parent width? -> align to left*/ - if(area_get_width(&page_cords) <= area_get_width(&par_cords)) { - if(page_cords.x1 != par_cords.x1) { - new_x = 0; - refr_x = true; - } - } else { - if(page_cords.x2 < par_cords.x2) { - new_x = area_get_width(&par_cords) - area_get_width(&page_cords); /* Right align */ - refr_x = true; - } - if (page_cords.x1 > par_cords.x1) { - new_x = 0; /*Left align*/ - refr_x = true; - } - } - /*Wrong in y?*/ - if(area_get_height(&page_cords) <= area_get_height(&par_cords)) { - if(page_cords.y1 != par_cords.y1) { - new_y = 0; - refr_y = true; - } - } else { - if(page_cords.y2 < par_cords.y2) { - new_y = area_get_height(&par_cords) - area_get_height(&page_cords); /* Bottom align */ - refr_y = true; - } - if (page_cords.y1 > par_cords.y1) { - new_y = 0; /*Top align*/ - refr_y = true; - } - } - if(refr_x != false || refr_y != false) { - lv_obj_set_pos(obj_dp, new_x, new_y); - } - - lv_page_sb_refresh(obj_dp); - break; - - case LV_SIGNAL_DRAG_BEGIN: - if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO ) { - if(lv_obj_get_height(page_ext_p->sbv_dp) < lv_obj_get_height(par_dp) - pages_p->sb_width) { - lv_obj_set_opa(page_ext_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100); - } - if(lv_obj_get_width(page_ext_p->sbh_dp) < lv_obj_get_width(par_dp) - pages_p->sb_width) { - lv_obj_set_opa(page_ext_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100); - } - } - break; - - case LV_SIGNAL_DRAG_END: - if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO) { - lv_obj_set_opa(page_ext_p->sbh_dp, OPA_TRANSP); - lv_obj_set_opa(page_ext_p->sbv_dp, OPA_TRANSP); - } - break; + case LV_SIGNAL_CHILD_CHG: /*Be sure, only scrollable object is on the page*/ + child = lv_obj_get_child(obj_dp, NULL); + while(child != NULL) { + if(child != page_ext_p->scrolling_dp) { + lv_obj_t * tmp = child; + child = lv_obj_get_child(obj_dp, child); /*Get the next child before move this*/ + lv_obj_set_parent(tmp, page_ext_p->scrolling_dp); + } else { + child = lv_obj_get_child(obj_dp, child); + } + } + break; case LV_SIGNAL_STYLE_CHG: - lv_obj_set_style(page_ext_p->sbh_dp, &pages_p->sb_rects); - lv_obj_set_style(page_ext_p->sbv_dp, &pages_p->sb_rects); - lv_obj_set_width(page_ext_p->sbv_dp, pages_p->sb_width); - lv_obj_set_height(page_ext_p->sbh_dp, pages_p->sb_width); + area_set_height(&page_ext_p->sbh, pages_p->sb_width); + area_set_width(&page_ext_p->sbv, pages_p->sb_width); + lv_obj_set_style(page_ext_p->scrolling_dp, &pages_p->scrable_rects); if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) { - lv_obj_set_opa(page_ext_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100); - lv_obj_set_opa(page_ext_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100); - } else { - lv_obj_set_opa(page_ext_p->sbv_dp, OPA_TRANSP); - lv_obj_set_opa(page_ext_p->sbh_dp, OPA_TRANSP); - } + page_ext_p->sbh_draw = 1; + page_ext_p->sbv_draw = 1; + } else { + page_ext_p->sbh_draw = 0; + page_ext_p->sbv_draw = 0; + } lv_page_sb_refresh(obj_dp); break; - + + case LV_SIGNAL_CORD_CHG: + lv_page_sb_refresh(obj_dp); + break; default: break; @@ -301,6 +237,114 @@ bool lv_page_signal(lv_obj_t* obj_dp, lv_signal_t sign, void* param) return obj_valid; } +/** + * Signal function of the scrollable part of a page + * @param obj_dp pointer to the scrollable object + * @param sign a signal type from lv_signal_t enum + * @param param pointer to a signal specific variable + */ +static bool lv_scrolling_signal(lv_obj_t* obj_dp, lv_signal_t sign, void* param) +{ + bool obj_valid = true; + + /* Include the ancient signal function */ + obj_valid = lv_rect_signal(obj_dp, sign, param); + + /* The object can be deleted so check its validity and then + * make the object specific signal handling */ + if(obj_valid != false) { + + cord_t new_x; + cord_t new_y; + bool refr_x = false; + bool refr_y = false; + area_t page_cords; + area_t obj_cords; + lv_obj_t * page_p = lv_obj_get_parent(obj_dp); + lv_pages_t * pages_p = lv_obj_get_style(page_p); + lv_page_ext_t * page_ext_dp = lv_obj_get_ext(page_p); + cord_t hpad = pages_p->bg_rects.hpad; + cord_t vpad = pages_p->bg_rects.vpad; + + switch(sign) { + case LV_SIGNAL_CORD_CHG: + new_x = lv_obj_get_x(obj_dp); + new_y = lv_obj_get_y(obj_dp); + lv_obj_get_cords(obj_dp, &obj_cords); + lv_obj_get_cords(page_p, &page_cords); + + /*scrollable width smaller then page width? -> align to left*/ + if(area_get_width(&obj_cords) + 2 * hpad < area_get_width(&page_cords)) { + if(obj_cords.x1 != page_cords.x1 + hpad) { + new_x = hpad; + refr_x = true; + } + } else { + /*The edges of the scrollable can not be in the page (minus hpad) */ + if(obj_cords.x2 < page_cords.x2 - hpad) { + new_x = area_get_width(&page_cords) - area_get_width(&obj_cords) - hpad; /* Right align */ + refr_x = true; + } + if (obj_cords.x1 > page_cords.x1 + hpad) { + new_x = hpad; /*Left align*/ + refr_x = true; + } + } + + /*scrollable height smaller then page height? -> align to left*/ + if(area_get_height(&obj_cords) + 2 * vpad < area_get_height(&page_cords)) { + if(obj_cords.y1 != page_cords.y1 + vpad) { + new_y = vpad; + refr_y = true; + } + } else { + /*The edges of the scrollable can not be in the page (minus vpad) */ + if(obj_cords.y2 < page_cords.y2 - vpad) { + new_y = area_get_height(&page_cords) - area_get_height(&obj_cords) - vpad; /* Bottom align */ + refr_y = true; + } + if (obj_cords.y1 > page_cords.y1 + vpad) { + new_y = vpad; /*Top align*/ + refr_y = true; + } + } + if(refr_x != false || refr_y != false) { + lv_obj_set_pos(obj_dp, new_x, new_y); + } + + lv_page_sb_refresh(page_p); + break; + + case LV_SIGNAL_DRAG_BEGIN: + if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO ) { + if(area_get_height(&page_ext_dp->sbv) < lv_obj_get_height(obj_dp) - pages_p->sb_width) { + page_ext_dp->sbv_draw = 1; + lv_inv_area(&page_ext_dp->sbv); + } + if(area_get_width(&page_ext_dp->sbh) < lv_obj_get_width(obj_dp) - pages_p->sb_width) { + page_ext_dp->sbh_draw = 1; + lv_inv_area(&page_ext_dp->sbh); + } + } + break; + + case LV_SIGNAL_DRAG_END: + if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO) { + page_ext_dp->sbh_draw = 0; + page_ext_dp->sbv_draw = 0; + lv_inv_area(&page_ext_dp->sbh); + lv_inv_area(&page_ext_dp->sbv); + } + break; + default: + break; + + } + } + + return obj_valid; +} + /** * Glue the object to the page. After it the page can be moved (dragged) with this object too. * @param obj_dp pointer to an object on a page @@ -326,9 +370,6 @@ lv_pages_t * lv_pages_get(lv_pages_builtin_t style, lv_pages_t * to_copy) case LV_PAGES_DEF: style_p = &lv_pages_def; break; - case LV_PAGES_PAPER: - style_p = &lv_pages_paper; - break; case LV_PAGES_TRANSP: style_p = &lv_pages_transp; break; @@ -359,6 +400,40 @@ lv_pages_t * lv_pages_get(lv_pages_builtin_t style, lv_pages_t * to_copy) * STATIC FUNCTIONS **********************/ +/** + * Handle the drawing related tasks of the pages + * @param obj_dp 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_page_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) +{ + if(mode == LV_DESIGN_COVER_CHK) { + return ancestor_design_f(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + ancestor_design_f(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_POST) { /*Draw the scroll bars finally*/ + lv_page_ext_t * page_ext_dp = lv_obj_get_ext(obj_dp); + lv_pages_t * pages_p = lv_obj_get_style(obj_dp); + opa_t sb_opa = lv_obj_get_opa(obj_dp) * pages_p->sb_opa /100; + + /*Draw the scrollbars*/ + if(page_ext_dp->sbh_draw != 0) { + lv_draw_rect(&page_ext_dp->sbh, mask_p, &pages_p->sb_rects, sb_opa); + } + + if(page_ext_dp->sbv_draw != 0) { + lv_draw_rect(&page_ext_dp->sbv, mask_p, &pages_p->sb_rects, sb_opa); + } + } + + return true; +} + /** * Handle the drawing related tasks of the pages * @param obj_dp pointer to an object @@ -370,51 +445,59 @@ lv_pages_t * lv_pages_get(lv_pages_builtin_t style, lv_pages_t * to_copy) */ static void lv_page_sb_refresh(lv_obj_t* page_dp) { - lv_page_ext_t * page_p = lv_obj_get_ext(page_dp); + lv_page_ext_t * page_ext_dp = lv_obj_get_ext(page_dp); lv_pages_t * pages_p = lv_obj_get_style(page_dp); - lv_obj_t* par_dp = lv_obj_get_parent(page_dp); + lv_obj_t* scrolling_dp = page_ext_dp->scrolling_dp; cord_t size_tmp; - cord_t page_w = lv_obj_get_width(page_dp); - cord_t page_h = lv_obj_get_height(page_dp); - cord_t par_w = lv_obj_get_width(par_dp); - cord_t par_h = lv_obj_get_height(par_dp); - + cord_t scrolling_w = lv_obj_get_width(scrolling_dp); + cord_t scrolling_h = lv_obj_get_height(scrolling_dp); + cord_t hpad = pages_p->bg_rects.hpad; + cord_t vpad = pages_p->bg_rects.vpad; + cord_t obj_w = lv_obj_get_width(page_dp); + cord_t obj_h = lv_obj_get_height(page_dp); + cord_t page_x0 = page_dp->cords.x1; + cord_t page_y0 = page_dp->cords.y1; + + lv_inv_area(&page_ext_dp->sbh); + lv_inv_area(&page_ext_dp->sbv); + /*Horizontal scrollbar*/ - if(page_w <= par_w) { /*Full sized scroll bar*/ - lv_obj_set_width(page_p->sbh_dp, par_w - pages_p->sb_width); - lv_obj_set_pos(page_p->sbh_dp, 0, par_h - pages_p->sb_width); - lv_obj_set_opa(page_p->sbh_dp, OPA_TRANSP); - } else { + if(scrolling_w <= obj_w) { /*Full sized scroll bar*/ + area_set_width(&page_ext_dp->sbh, obj_w - pages_p->sb_width); + area_set_pos(&page_ext_dp->sbh, page_x0, page_y0 + obj_h - pages_p->sb_width); + } else { if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) { - lv_obj_set_opa(page_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100); + page_ext_dp->sbh_draw = 1; } + size_tmp = (((obj_w - hpad) * (obj_w - pages_p->sb_width)) / scrolling_w); + area_set_width(&page_ext_dp->sbh, size_tmp); - size_tmp = ((par_w * (par_w - pages_p->sb_width)) / page_w); - lv_obj_set_width(page_p->sbh_dp, size_tmp); - - lv_obj_set_pos(page_p->sbh_dp, - ( -(lv_obj_get_x(page_dp)) * (par_w - size_tmp - pages_p->sb_width)) / - (page_w - par_w), - par_h - pages_p->sb_width); + area_set_pos(&page_ext_dp->sbh, page_x0 + + ( -(lv_obj_get_x(scrolling_dp) - hpad) * (obj_w - size_tmp - pages_p->sb_width)) / + (scrolling_w - obj_w + 2 * hpad), + page_y0 + obj_h - pages_p->sb_width); } /*Vertical scrollbar*/ - if(page_h <= par_h) { /*Full sized scroll bar*/ - lv_obj_set_height(page_p->sbv_dp, par_h - pages_p->sb_width); - lv_obj_set_pos(page_p->sbv_dp, par_w - pages_p->sb_width, 0); - lv_obj_set_opa(page_p->sbv_dp, OPA_TRANSP); + if(scrolling_h <= obj_h) { /*Full sized scroll bar*/ + area_set_height(&page_ext_dp->sbv, obj_h - pages_p->sb_width); + area_set_pos(&page_ext_dp->sbv, page_x0 + obj_w - pages_p->sb_width, 0); } else { if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) { - lv_obj_set_opa(page_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100); + page_ext_dp->sbv_draw = 1; } - size_tmp = ((par_h * (par_h - pages_p->sb_width)) / page_h); - lv_obj_set_height(page_p->sbv_dp, size_tmp); + size_tmp = (((obj_h - vpad) * (obj_h - pages_p->sb_width)) / scrolling_h); + area_set_height(&page_ext_dp->sbv, size_tmp); - lv_obj_set_pos(page_p->sbv_dp, - par_w - pages_p->sb_width, - (-(lv_obj_get_y(page_dp)) * (par_h - size_tmp - pages_p->sb_width)) / - (page_h - par_h)); + area_set_pos(&page_ext_dp->sbv, page_x0 + obj_w - pages_p->sb_width, + page_y0 + + (-(lv_obj_get_y(scrolling_dp) - vpad) * (obj_h - size_tmp - pages_p->sb_width)) / + (scrolling_h - obj_h + 2 * vpad)); } + lv_inv_area(&page_ext_dp->sbh); + lv_inv_area(&page_ext_dp->sbv); + + } #endif diff --git a/lv_objx/lv_page.h b/lv_objx/lv_page.h index 7537efde7..51b80611b 100644 --- a/lv_objx/lv_page.h +++ b/lv_objx/lv_page.h @@ -31,7 +31,9 @@ typedef enum typedef struct { - lv_rects_t bg_rects; + lv_rects_t bg_rects; /*Style of ancestor*/ + /*New style element for this type */ + lv_rects_t scrable_rects; lv_rects_t sb_rects; cord_t sb_width; lv_page_sb_mode_t sb_mode; @@ -41,15 +43,18 @@ typedef struct typedef struct { - lv_rect_ext_t rect_ext; - lv_obj_t* sbh_dp; /*Horizontal scrollbar*/ - lv_obj_t* sbv_dp; /*Vertical scrollbar*/ + lv_rect_ext_t rect_ext; /*Ext. of ancestor*/ + /*New data for this type */ + lv_obj_t * scrolling_dp; /*The scrollable object on the background*/ + area_t sbh; /*Horizontal scrollbar*/ + area_t sbv; /*Vertical scrollbar*/ + uint8_t sbh_draw :1; /*1: horizontal scrollbar is visible now*/ + uint8_t sbv_draw :1; /*1: vertical scrollbar is visible now*/ }lv_page_ext_t; typedef enum { LV_PAGES_DEF, - LV_PAGES_PAPER, LV_PAGES_TRANSP, }lv_pages_builtin_t; diff --git a/lv_objx/lv_pb.c b/lv_objx/lv_pb.c index 8f141401d..ca51e690a 100644 --- a/lv_objx/lv_pb.c +++ b/lv_objx/lv_pb.c @@ -252,6 +252,7 @@ lv_pbs_t * lv_pbs_get(lv_pbs_builtin_t style, lv_pbs_t * copy_p) * @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_pb_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -261,23 +262,20 @@ static bool lv_pb_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode if(mode == LV_DESIGN_COVER_CHK) { /*Return false if the object is not covers the mask_p area*/ return ancestor_design_fp(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + ancestor_design_fp(obj_dp, mask_p, mode); + + lv_pb_ext_t * ext_dp = lv_obj_get_ext(obj_dp); + area_t bar_area; + uint32_t tmp; + area_cpy(&bar_area, &obj_dp->cords); + tmp = (uint32_t)ext_dp->act_value * lv_obj_get_width(obj_dp); + tmp = (uint32_t) tmp / (ext_dp->max_value - ext_dp->min_value); + bar_area.x2 = bar_area.x1 + (cord_t) tmp; + + lv_pbs_t * style_p = lv_obj_get_style(obj_dp); + lv_draw_rect(&bar_area, mask_p, &style_p->bar, OPA_COVER); } - - - /*Draw the object*/ - ancestor_design_fp(obj_dp, mask_p, mode); - - lv_pb_ext_t * ext_dp = lv_obj_get_ext(obj_dp); - area_t bar_area; - uint32_t tmp; - area_cpy(&bar_area, &obj_dp->cords); - tmp = (uint32_t)ext_dp->act_value * lv_obj_get_width(obj_dp); - tmp = (uint32_t) tmp / (ext_dp->max_value - ext_dp->min_value); - bar_area.x2 = bar_area.x1 + (cord_t) tmp; - - lv_pbs_t * style_p = lv_obj_get_style(obj_dp); - lv_draw_rect(&bar_area, mask_p, &style_p->bar, OPA_COVER); - return true; } diff --git a/lv_objx/lv_rect.c b/lv_objx/lv_rect.c index 8687a3919..6ae5f5971 100644 --- a/lv_objx/lv_rect.c +++ b/lv_objx/lv_rect.c @@ -7,7 +7,7 @@ * INCLUDES *********************/ -#include +#include #include #include #include @@ -173,8 +173,7 @@ void lv_rect_set_fit(lv_obj_t * obj_dp, bool hor_en, bool ver_en) ext_p->vfit_en = ver_en == false ? 0 : 1; /*Send a signal to run the paddig calculations*/ - lv_obj_t * par_dp = lv_obj_get_parent(obj_dp); - par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, obj_dp); + obj_dp->signal_f(obj_dp, LV_SIGNAL_CORD_CHG, obj_dp); } /*===================== @@ -248,12 +247,13 @@ lv_rects_t * lv_rects_get(lv_rects_builtin_t style, lv_rects_t * copy_p) **********************/ /** - * Handle the drawing related tasks of the labels + * Handle the drawing related tasks of the rectangles * @param obj_dp 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_rect_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -278,15 +278,14 @@ static bool lv_rect_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mo if(area_is_in(mask_p, &area_tmp) == true) return true; return false; - } - - opa_t opa = lv_obj_get_opa(obj_dp); - area_t area; - lv_obj_get_cords(obj_dp, &area); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + opa_t opa = lv_obj_get_opa(obj_dp); + area_t area; + lv_obj_get_cords(obj_dp, &area); - /*Draw the rectangle*/ - lv_draw_rect(&area, mask_p, lv_obj_get_style(obj_dp), opa); - + /*Draw the rectangle*/ + lv_draw_rect(&area, mask_p, lv_obj_get_style(obj_dp), opa); + } return true; } diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index a6b9daf07..2aff3857c 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -11,6 +11,7 @@ #if USE_LV_TA != 0 #include "lv_ta.h" +#include "../lv_draw/lv_draw.h" /********************* * DEFINES @@ -25,14 +26,62 @@ * STATIC PROTOTYPES **********************/ static bool lv_ta_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode); +static bool lv_ta_label_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode); +static void lv_ta_save_valid_cursor_x(lv_obj_t * obj_dp); /********************** * STATIC VARIABLES **********************/ static lv_tas_t lv_tas_def = -{ /*Create a default style*/ }; +{ .pages.bg_rects.objs.color = COLOR_MAKE(0x50, 0x70, 0x90), + .pages.bg_rects.gcolor = COLOR_MAKE(0x70, 0xA0, 0xC0), + .pages.bg_rects.bcolor = COLOR_WHITE, + .pages.bg_rects.bopa = 50, + .pages.bg_rects.bwidth = 2 * LV_STYLE_MULT, + .pages.bg_rects.round = 4 * LV_STYLE_MULT, + .pages.bg_rects.empty = 0, + .pages.bg_rects.hpad = 10 * LV_STYLE_MULT, + .pages.bg_rects.vpad = 10 * LV_STYLE_MULT, + .pages.bg_rects.opad = 5 * LV_STYLE_MULT, + + .pages.scrable_rects.objs.color = COLOR_WHITE, + .pages.scrable_rects.gcolor = COLOR_SILVER, + .pages.scrable_rects.bcolor = COLOR_GRAY, + .pages.scrable_rects.bopa = 50, + .pages.scrable_rects.bwidth = 0 * LV_STYLE_MULT, + .pages.scrable_rects.round = 2 * LV_STYLE_MULT, + .pages.scrable_rects.empty = 0, + .pages.scrable_rects.hpad = 10 * LV_STYLE_MULT, + .pages.scrable_rects.vpad = 10 * LV_STYLE_MULT, + .pages.scrable_rects.opad = 5 * LV_STYLE_MULT, + + .pages.sb_rects.objs.color = COLOR_BLACK, + .pages.sb_rects.gcolor = COLOR_BLACK, + .pages.sb_rects.bcolor = COLOR_WHITE, + .pages.sb_rects.bopa = 50, + .pages.sb_rects.bwidth = 1 * LV_STYLE_MULT, + .pages.sb_rects.round = 5 * LV_STYLE_MULT, + .pages.sb_rects.empty = 0, + .pages.sb_rects.hpad = 0, + .pages.sb_rects.vpad = 0, + .pages.sb_rects.opad = 0, + + .pages.sb_width= 8 * LV_STYLE_MULT, + .pages.sb_opa=50, + .pages.sb_mode = LV_PAGE_SB_MODE_AUTO, + + .labels.font = LV_FONT_DEFAULT, + .labels.objs.color = COLOR_MAKE(0x10, 0x18, 0x20), + .labels.letter_space = 2 * LV_STYLE_MULT, + .labels.line_space = 2 * LV_STYLE_MULT, + .labels.mid = 0, + + .cursor_color = COLOR_MAKE(0x20, 0x20, 0x20), + .cursor_width = 2 * LV_STYLE_MULT, /*>1 px for visible cursor*/ +}; lv_design_f_t ancestor_design_f; +lv_design_f_t label_design_f; /********************** * MACROS @@ -69,17 +118,32 @@ lv_obj_t* lv_ta_create(lv_obj_t* par_dp, lv_obj_t * copy_dp) lv_obj_set_signal_f(new_obj_dp, lv_ta_signal); lv_obj_set_design_f(new_obj_dp, lv_ta_design); + ext_dp->cursor_valid_x = 0; + ext_dp->cursor_pos = 0; + /*Init the new text area object*/ if(copy_dp == NULL) { ext_dp->label_dp = lv_label_create(new_obj_dp, NULL); - lv_label_set_text(ext_dp->label_dp, "0123456789 abcdef\nABCDEF\nG\nHIJKLM\n\nnopqrs"); - //lv_obj_set_style(ext_dp->label_dp, lv_labels_get(LV_LABELS_TXT, NULL)); - // lv_label_set_fixw(ext_dp->label_dp, true); - lv_obj_set_width_us(ext_dp->label_dp, 200); + if(label_design_f == NULL) { + label_design_f = lv_obj_get_design_f(ext_dp->label_dp); + } + lv_obj_set_design_f(ext_dp->label_dp, lv_ta_label_design); + lv_label_set_fixw(ext_dp->label_dp, true); + lv_label_set_text(ext_dp->label_dp, "abc aaaa bbbb ccc\n123\nABC\nxyz\nwww\n007\nalma\n:)\naaaaaa"); + lv_page_glue_obj(ext_dp->label_dp, true); + lv_obj_set_click(ext_dp->label_dp, true); + lv_obj_set_style(new_obj_dp, &lv_tas_def); + } /*Copy an existing object*/ else { + lv_ta_ext_t * copy_ext_dp = lv_obj_get_ext(copy_dp); + ext_dp->label_dp = lv_label_create(new_obj_dp, copy_ext_dp->label_dp); + lv_obj_set_design_f(ext_dp->label_dp, lv_ta_label_design); + lv_page_glue_obj(ext_dp->label_dp, true); + /*Refresh the style when everything is ready*/ + lv_obj_set_style(new_obj_dp, lv_obj_get_style(copy_dp)); } return new_obj_dp; @@ -102,9 +166,23 @@ bool lv_ta_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param) /* The object can be deleted so check its validity and then * make the object specific signal handling */ if(valid != false) { + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(obj_dp); + lv_tas_t * tas_p = lv_obj_get_style(obj_dp); switch(sign) { case LV_SIGNAL_CLEANUP: - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ + lv_obj_del(ta_ext_dp->label_dp); + break; + case LV_SIGNAL_STYLE_CHG: + lv_obj_set_style(ta_ext_dp->label_dp, &tas_p->labels); + lv_obj_set_width(ta_ext_dp->label_dp, lv_obj_get_width(obj_dp) - 2 * + (tas_p->pages.bg_rects.hpad + tas_p->pages.scrable_rects.hpad)); + lv_label_set_text(ta_ext_dp->label_dp, NULL); + break; + /*Set the label width according to the text area width*/ + case LV_SIGNAL_CORD_CHG: + lv_obj_set_width(ta_ext_dp->label_dp, lv_obj_get_width(obj_dp) - 2 * + (tas_p->pages.bg_rects.hpad + tas_p->pages.scrable_rects.hpad)); + lv_label_set_text(ta_ext_dp->label_dp, NULL); break; default: break; @@ -118,10 +196,16 @@ bool lv_ta_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param) * Setter functions *====================*/ +/** + * Insert a character to the current cursor position + * @param obj_dp pointer to a text area object + * @param c a character + */ void lv_ta_add_char(lv_obj_t * obj_dp, char c) { lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); + /*Insert the character*/ char buf[LV_TA_MAX_LENGTH]; const char * label_txt = lv_label_get_text(ta_dp->label_dp); @@ -129,15 +213,26 @@ void lv_ta_add_char(lv_obj_t * obj_dp, char c) buf[ta_dp->cursor_pos] = c; memcpy(buf+ta_dp->cursor_pos+1, label_txt+ta_dp->cursor_pos, strlen(label_txt) - ta_dp->cursor_pos + 1); + /*Refresh the label*/ lv_label_set_text(ta_dp->label_dp, buf); + /*Move the cursor after the new character*/ lv_ta_set_cursor_pos(obj_dp, lv_ta_get_cursor_pos(obj_dp) + 1); + + /*It is a valid x step so save it*/ + lv_ta_save_valid_cursor_x(obj_dp); } +/** + * Insert a text to the current cursor position + * @param obj_dp pointer to a text area object + * @param txt a '\0' terminated string to insert + */ void lv_ta_add_text(lv_obj_t * obj_dp, const char * txt) { lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); + /*Insert the text*/ char buf[LV_TA_MAX_LENGTH]; const char * label_txt = lv_label_get_text(ta_dp->label_dp); uint16_t label_len = strlen(label_txt); @@ -147,11 +242,20 @@ void lv_ta_add_text(lv_obj_t * obj_dp, const char * txt) memcpy(buf+ta_dp->cursor_pos, txt, txt_len); memcpy(buf+ta_dp->cursor_pos + txt_len, label_txt+ta_dp->cursor_pos, label_len - ta_dp->cursor_pos + 1); + /*Refresh the label*/ lv_label_set_text(ta_dp->label_dp, buf); + /*Move the cursor after the new text*/ lv_ta_set_cursor_pos(obj_dp, lv_ta_get_cursor_pos(obj_dp) + txt_len); + + /*It is a valid x step so save it*/ + lv_ta_save_valid_cursor_x(obj_dp); } +/** + * Delete a the left character from the current cursor position + * @param obj_dp pointer to a text area object + */ void lv_ta_del(lv_obj_t * obj_dp) { lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); @@ -159,60 +263,163 @@ void lv_ta_del(lv_obj_t * obj_dp) if(cur_pos == 0) return; + /*Delete a character*/ char buf[LV_TA_MAX_LENGTH]; const char * label_txt = lv_label_get_text(ta_dp->label_dp); uint16_t label_len = strlen(label_txt); memcpy(buf, label_txt, cur_pos - 1); memcpy(buf+cur_pos - 1, label_txt + cur_pos, label_len - cur_pos + 1); + /*Refresh the label*/ lv_label_set_text(ta_dp->label_dp, buf); + /*Move the cursor to the place of the deleted character*/ lv_ta_set_cursor_pos(obj_dp, lv_ta_get_cursor_pos(obj_dp) - 1); + + /*It is a valid x step so save it*/ + lv_ta_save_valid_cursor_x(obj_dp); } +/** + * Set the cursor position + * @param obj_dp pointer to a text area object + * @param pos the new cursor position in character index + */ void lv_ta_set_cursor_pos(lv_obj_t * obj_dp, uint16_t pos) { - lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); - ta_dp->cursor_pos = pos; + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(obj_dp); + uint16_t txt_len = strlen(lv_label_get_text(ta_ext_dp->label_dp)); + + if(pos > txt_len) pos = txt_len; + + ta_ext_dp->cursor_pos = pos; + + /*Position the label to make the cursor visible*/ + lv_obj_t * label_par_dp = lv_obj_get_parent(ta_ext_dp->label_dp); + point_t cur_pos; + lv_tas_t * tas_p = lv_obj_get_style(obj_dp); + const font_t * font_p = font_get(tas_p->labels.font); + lv_label_get_letter_pos(ta_ext_dp->label_dp, pos, &cur_pos); + + /*Check the top*/ + if(lv_obj_get_y(label_par_dp) + cur_pos.y < 0) { + lv_obj_set_y(label_par_dp, - cur_pos.y); + } + + /*Check the bottom*/ + if(lv_obj_get_y(label_par_dp) + cur_pos.y + font_get_height(font_p) > lv_obj_get_height(obj_dp)) { + lv_obj_set_y(label_par_dp, -(cur_pos.y - lv_obj_get_height(obj_dp) + + font_get_height(font_p) + tas_p->pages.scrable_rects.vpad * 2)); + } lv_obj_inv(obj_dp); } -void lv_ta_cursor_down(lv_obj_t * obj_dp) + +/** + * Move the cursor one character right + * @param obj_dp pointer to a text area object + */ +void lv_ta_cursor_right(lv_obj_t * obj_dp) { - lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); - point_t pos; + uint16_t cp = lv_ta_get_cursor_pos(obj_dp); + cp++; + lv_ta_set_cursor_pos(obj_dp, cp); - lv_label_get_letter_pos(ta_dp->label_dp, lv_ta_get_cursor_pos(obj_dp), &pos); - - lv_labels_t * labels_p = lv_obj_get_style(ta_dp->label_dp); - const font_t * font_p = font_get(labels_p->font); - pos.y += font_get_height(font_p) + labels_p->line_space + 1; - - uint16_t new_cur_pos = lv_label_get_letter_on(ta_dp->label_dp, &pos); - - lv_ta_set_cursor_pos(obj_dp, new_cur_pos); + /*It is a valid x step so save it*/ + lv_ta_save_valid_cursor_x(obj_dp); } -void lv_ta_cursor_up(lv_obj_t * obj_dp) +/** + * Move the cursor one character left + * @param obj_dp pointer to a text area object + */ +void lv_ta_cursor_left(lv_obj_t * obj_dp) { - lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); + uint16_t cp = lv_ta_get_cursor_pos(obj_dp); + if(cp > 0) { + cp--; + lv_ta_set_cursor_pos(obj_dp, cp); + + /*It is a valid x step so save it*/ + lv_ta_save_valid_cursor_x(obj_dp); + } +} + +/** + * Move the cursor one line down + * @param obj_dp pointer to a text area object + */ +void lv_ta_cursor_down(lv_obj_t * obj_dp) +{ + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(obj_dp); point_t pos; - lv_label_get_letter_pos(ta_dp->label_dp, lv_ta_get_cursor_pos(obj_dp), &pos); + /*Get the position of the current letter*/ + lv_label_get_letter_pos(ta_ext_dp->label_dp, lv_ta_get_cursor_pos(obj_dp), &pos); - lv_labels_t * labels_p = lv_obj_get_style(ta_dp->label_dp); + /*Increment the y with one line and keep the valid x*/ + lv_labels_t * labels_p = lv_obj_get_style(ta_ext_dp->label_dp); + const font_t * font_p = font_get(labels_p->font); + pos.y += font_get_height(font_p) + labels_p->line_space + 1; + pos.x = ta_ext_dp->cursor_valid_x; + + /*Do not go below he last line*/ + if(pos.y < lv_obj_get_height(ta_ext_dp->label_dp)) { + /*Get the letter index on the new cursor position and set it*/ + uint16_t new_cur_pos = lv_label_get_letter_on(ta_ext_dp->label_dp, &pos); + lv_ta_set_cursor_pos(obj_dp, new_cur_pos); + } +} + +/** + * Move the cursor one line up + * @param obj_dp pointer to a text area object + */ +void lv_ta_cursor_up(lv_obj_t * obj_dp) +{ + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(obj_dp); + point_t pos; + + /*Get the position of the current letter*/ + lv_label_get_letter_pos(ta_ext_dp->label_dp, lv_ta_get_cursor_pos(obj_dp), &pos); + + /*Decrement the y with one line and keep the valid x*/ + lv_labels_t * labels_p = lv_obj_get_style(ta_ext_dp->label_dp); const font_t * font_p = font_get(labels_p->font); pos.y -= font_get_height(font_p) + labels_p->line_space - 1; + pos.x = ta_ext_dp->cursor_valid_x; - uint16_t new_cur_pos = lv_label_get_letter_on(ta_dp->label_dp, &pos); - + /*Get the letter index on the new cursor position and set it*/ + uint16_t new_cur_pos = lv_label_get_letter_on(ta_ext_dp->label_dp, &pos); lv_ta_set_cursor_pos(obj_dp, new_cur_pos); } /*===================== * Getter functions *====================*/ +/** + * Get the text of the i the text area + * @param obj_dp obj_dp pointer to a text area object + * @return pointer to the text + */ +const char * lv_ta_get_text(lv_obj_t * obj_dp) +{ + lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); + return lv_label_get_text(ta_dp->label_dp); +} + +/** + * Get the current cursor position in character index + * @param obj_dp pointer to a text area object + * @return the cursor position + */ +uint16_t lv_ta_get_cursor_pos(lv_obj_t * obj_dp) +{ + lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); + return ta_dp->cursor_pos; +} + /** * Return with a pointer to a built-in style and/or copy it to a variable * @param style a style name from lv_tas_builtin_t enum @@ -238,12 +445,6 @@ lv_tas_t * lv_tas_get(lv_tas_builtin_t style, lv_tas_t * copy_p) return style_p; } - -uint16_t lv_ta_get_cursor_pos(lv_obj_t * obj_dp) -{ - lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); - return ta_dp->cursor_pos; -} /********************** * STATIC FUNCTIONS **********************/ @@ -255,7 +456,8 @@ uint16_t lv_ta_get_cursor_pos(lv_obj_t * obj_dp) * @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_MAIN: 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_ta_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) @@ -263,33 +465,66 @@ static bool lv_ta_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode if(mode == LV_DESIGN_COVER_CHK) { /*Return false if the object is not covers the mask_p area*/ return ancestor_design_f(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + /*Draw the object*/ + ancestor_design_f(obj_dp, mask_p, mode); + + } else if(mode == LV_DESIGN_DRAW_POST) { + ancestor_design_f(obj_dp, mask_p, mode); } - - /*Draw the object*/ - ancestor_design_f(obj_dp, mask_p, mode); - - lv_ta_ext_t * ta_dp = lv_obj_get_ext(obj_dp); - uint16_t cur_pos = lv_ta_get_cursor_pos(obj_dp); - point_t letter_pos; - lv_label_get_letter_pos(ta_dp->label_dp, cur_pos, &letter_pos); - - area_t cur_area; - lv_labels_t * labels_p = lv_obj_get_style(ta_dp->label_dp); - cur_area.x1 = letter_pos.x + ta_dp->label_dp->cords.x1 - 2; - cur_area.y1 = letter_pos.y + ta_dp->label_dp->cords.y1; - cur_area.x2 = letter_pos.x + ta_dp->label_dp->cords.x1 + 2; - cur_area.y2 = letter_pos.y + ta_dp->label_dp->cords.y1 + font_get_height(font_get(labels_p->font)); - - lv_rects_t rects; - lv_rects_get(LV_RECTS_DEF, &rects); - rects.round = 0; - rects.bwidth = 0; - rects.objs.color = COLOR_RED; - rects.gcolor = COLOR_RED; - lv_draw_rect(&cur_area, mask_p, &rects, OPA_COVER); - return true; } +static bool lv_ta_label_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode) +{ + if(mode == LV_DESIGN_COVER_CHK) { + /*Return false if the object is not covers the mask_p area*/ + return label_design_f(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_MAIN) { + /*Draw the object*/ + label_design_f(obj_dp, mask_p, mode); + } else if(mode == LV_DESIGN_DRAW_POST) { + label_design_f(obj_dp, mask_p, mode); + + /*Draw the cursor too*/ + lv_obj_t * ta_dp = lv_obj_get_parent(lv_obj_get_parent(obj_dp)); + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(ta_dp); + lv_tas_t * tas_p = lv_obj_get_style(ta_dp); + uint16_t cur_pos = lv_ta_get_cursor_pos(ta_dp); + point_t letter_pos; + lv_label_get_letter_pos(obj_dp, cur_pos, &letter_pos); + + area_t cur_area; + lv_labels_t * labels_p = lv_obj_get_style(ta_ext_dp->label_dp); + cur_area.x1 = letter_pos.x + obj_dp->cords.x1 - (tas_p->cursor_width >> 1); + cur_area.y1 = letter_pos.y + obj_dp->cords.y1; + cur_area.x2 = letter_pos.x + obj_dp->cords.x1 + (tas_p->cursor_width >> 1); + cur_area.y2 = letter_pos.y + obj_dp->cords.y1 + font_get_height(font_get(labels_p->font)); + + lv_rects_t cur_rects; + lv_rects_get(LV_RECTS_DEF, &cur_rects); + cur_rects.round = 0; + cur_rects.bwidth = 0; + cur_rects.objs.color = tas_p->cursor_color; + cur_rects.gcolor = tas_p->cursor_color; + lv_draw_rect(&cur_area, mask_p, &cur_rects, OPA_COVER); + } + + return true; +} + +/** + * Save the cursor x position as valid. It is important when jumping up/down to a shorter line + * @param obj_dp pointer to a text area object + */ +static void lv_ta_save_valid_cursor_x(lv_obj_t * obj_dp) +{ + lv_ta_ext_t * ta_ext_dp = lv_obj_get_ext(obj_dp); + point_t cur_pos; + lv_label_get_letter_pos(ta_ext_dp->label_dp, ta_ext_dp->cursor_pos, &cur_pos); + ta_ext_dp->cursor_valid_x = cur_pos.x; +} + + #endif diff --git a/lv_objx/lv_ta.h b/lv_objx/lv_ta.h index 0ed49415e..807ebfe2b 100644 --- a/lv_objx/lv_ta.h +++ b/lv_objx/lv_ta.h @@ -30,6 +30,8 @@ typedef struct lv_pages_t pages; /*Style of ancestor*/ /*New style element for this type */ lv_labels_t labels; + color_t cursor_color; + cord_t cursor_width; uint8_t cursor_show :1; }lv_tas_t; @@ -45,6 +47,7 @@ typedef struct lv_page_ext_t page; /*Ext. of ancestor*/ /*New data for this type */ lv_obj_t * label_dp; + cord_t cursor_valid_x; uint16_t cursor_pos; }lv_ta_ext_t; @@ -59,6 +62,8 @@ void lv_ta_add_char(lv_obj_t * obj_dp, char c); void lv_ta_add_text(lv_obj_t * obj_dp, const char * txt); void lv_ta_del(lv_obj_t * obj_dp); void lv_ta_set_cursor_pos(lv_obj_t * obj_dp, uint16_t pos); +void lv_ta_cursor_right (lv_obj_t * obj_dp); +void lv_ta_cursor_left(lv_obj_t * obj_dp); void lv_ta_cursor_down(lv_obj_t * obj_dp); void lv_ta_cursor_up(lv_obj_t * obj_dp);