From 25691a4d941645f2331c1a89854c1221a7257af6 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 15 Sep 2020 15:38:18 +0200 Subject: [PATCH] rework checkbox now it has no real parts, the bullet and text are drawn on the fly --- src/lv_core/lv_grid.h | 2 - src/lv_core/lv_indev.c | 2 +- src/lv_core/lv_obj.c | 15 ++- src/lv_core/lv_obj.h | 9 +- src/lv_core/lv_obj_draw.c | 20 +-- src/lv_core/lv_obj_pos.c | 24 +++- src/lv_core/lv_obj_pos.h | 9 ++ src/lv_core/lv_obj_scroll.c | 46 +++++-- src/lv_core/lv_obj_style.c | 10 +- src/lv_themes/lv_theme.c | 2 +- src/lv_themes/lv_theme_material.c | 3 +- src/lv_themes/lv_theme_mono.c | 2 +- src/lv_themes/lv_theme_template.c | 2 +- src/lv_widgets/lv_checkbox.c | 195 ++++++++++++++++++++++-------- src/lv_widgets/lv_checkbox.h | 46 +++---- 15 files changed, 253 insertions(+), 134 deletions(-) diff --git a/src/lv_core/lv_grid.h b/src/lv_core/lv_grid.h index d2cf08c3b..4f3dfc907 100644 --- a/src/lv_core/lv_grid.h +++ b/src/lv_core/lv_grid.h @@ -143,8 +143,6 @@ void _lv_grid_full_refresh(lv_obj_t * cont); void lv_grid_item_refr_pos(lv_obj_t * item); -bool _lv_obj_is_grid_item(lv_obj_t * obj); - /********************** * GLOBAL VARIABLES diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 119fea2c2..788a3dda3 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -848,7 +848,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) } /*Do not use disabled objects*/ - if(indev_obj_act && (lv_obj_get_state(indev_obj_act, LV_OBJ_PART_MAIN) & LV_STATE_DISABLED)) { + if(indev_obj_act && (lv_obj_get_state(indev_obj_act) & LV_STATE_DISABLED)) { indev_obj_act = proc->types.pointer.act_obj; } diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 4496d0d0b..92a4f181c 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -185,7 +185,7 @@ void lv_deinit(void) * Pointer to an other base object to copy. * @return pointer to the new object */ -lv_obj_t * lv_obj_create(lv_obj_t * parent, lv_obj_t * copy) +lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) { lv_obj_t * new_obj = NULL; @@ -775,10 +775,9 @@ void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) } } - if(cmp_res == _LV_STYLE_STATE_CMP_DIFF) _lv_obj_refresh_style(obj, part, LV_STYLE_PROP_ALL); } - - if(cmp_res == _LV_STYLE_STATE_CMP_VISUAL_DIFF) lv_obj_invalidate(obj); + if(cmp_res == _LV_STYLE_STATE_CMP_DIFF) _lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); + else if(cmp_res == _LV_STYLE_STATE_CMP_VISUAL_DIFF) lv_obj_invalidate(obj); #endif @@ -1292,7 +1291,7 @@ lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) #endif } -lv_state_t lv_obj_get_state(const lv_obj_t * obj, uint8_t part) +lv_state_t lv_obj_get_state(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -1815,7 +1814,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) /*Go the checked state if enabled*/ if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { uint32_t toggled = 0; - if(!(lv_obj_get_state(obj, LV_OBJ_PART_MAIN) & LV_STATE_CHECKED)) { + if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) { lv_obj_add_state(obj, LV_STATE_CHECKED); toggled = 0; } @@ -1880,8 +1879,8 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED); } else if(sign == LV_SIGNAL_COORD_CHG) { - if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) || - (lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj))) + if(param && ((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) || + (lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj)))) { _lv_grid_full_refresh(obj); } diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index c663a0b3a..d9467ba1d 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -126,10 +126,11 @@ enum { LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ LV_SIGNAL_COORD_CHG, /**< Object coordinates/size have changed */ LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ - LV_SIGNAL_BASE_DIR_CHG, /**x = 0; + p->y = 0; + lv_signal_send(obj, LV_SIGNAL_GET_SELF_SIZE, p); +} /********************** * STATIC FUNCTIONS @@ -613,7 +626,8 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_area_t ori; lv_obj_get_coords(obj, &ori); - /*Set the length and height*/ + /* Set the length and height + * Be sure the content is not scrolled in an invalid position on the new size*/ obj->coords.y2 = obj->coords.y1 + h - 1; if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL) { obj->coords.x1 = obj->coords.x2 - w + 1; diff --git a/src/lv_core/lv_obj_pos.h b/src/lv_core/lv_obj_pos.h index 8dd4d94d2..d508c8154 100644 --- a/src/lv_core/lv_obj_pos.h +++ b/src/lv_core/lv_obj_pos.h @@ -230,6 +230,15 @@ void _lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coor * @return true: grid item; false: not grid item */ bool _lv_obj_is_grid_item(struct _lv_obj_t * obj); + +/** + * Get the size of the virtual content on an object + * (E.g. some texts which are "just drawn" and there is not real object behind them) + * @param obj pointer to an object + * @param p store the result size here + */ +void _lv_obj_get_self_size(lv_obj_t * obj, lv_point_t * p); + /********************** * MACROS **********************/ diff --git a/src/lv_core/lv_obj_scroll.c b/src/lv_core/lv_obj_scroll.c index db1b1df7b..17206b166 100644 --- a/src/lv_core/lv_obj_scroll.c +++ b/src/lv_core/lv_obj_scroll.c @@ -183,17 +183,26 @@ lv_coord_t lv_obj_get_scroll_bottom(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_coord_t y2 = LV_COORD_MIN; + lv_coord_t child_res = LV_COORD_MIN; lv_obj_t * child = lv_obj_get_child(obj, NULL); - if(child == NULL) return 0; + if(child) { + lv_coord_t y2 = LV_COORD_MIN; + while(child) { + y2 = LV_MATH_MAX(y2, child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN)); + child = lv_obj_get_child(obj, child); + } - while(child) { - y2 = LV_MATH_MAX(y2, child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN)); - child = lv_obj_get_child(obj, child); + child_res = y2; } - return y2 - (obj->coords.y2 - lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN)); + lv_point_t self_size; + _lv_obj_get_self_size(obj, &self_size); + self_size.y += obj->coords.y1 + lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN) + obj->scroll.y; + + lv_coord_t y_max = LV_MATH_MAX(child_res, self_size.y) - obj->coords.y2; + + return y_max + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); } /** @@ -217,19 +226,30 @@ lv_coord_t lv_obj_get_scroll_left(const lv_obj_t * obj) */ lv_coord_t lv_obj_get_scroll_right(const lv_obj_t * obj) { + static uint32_t cnt = 0; + printf("scrl right: %d\n", cnt); + cnt++; LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_coord_t x2 = LV_COORD_MIN; - + lv_coord_t child_res = LV_COORD_MIN; lv_obj_t * child = lv_obj_get_child(obj, NULL); - if(child == NULL) return 0; + if(child) { + lv_coord_t x2 = LV_COORD_MIN; + while(child) { + x2 = LV_MATH_MAX(x2, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN)); + child = lv_obj_get_child(obj, child); + } + child_res = x2; - while(child) { - x2 = LV_MATH_MAX(x2, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN)); - child = lv_obj_get_child(obj, child); } - return x2 - (obj->coords.x2 - lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN)); + lv_point_t self_size; + _lv_obj_get_self_size(obj, &self_size); + self_size.x += obj->coords.x1 + lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN) + obj->scroll.x; + + lv_coord_t x_max = LV_MATH_MAX(child_res, self_size.x) - obj->coords.x2; + + return x_max + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN); } /********************** diff --git a/src/lv_core/lv_obj_style.c b/src/lv_core/lv_obj_style.c index bc4d69bff..c3c7799b8 100644 --- a/src/lv_core/lv_obj_style.c +++ b/src/lv_core/lv_obj_style.c @@ -409,7 +409,7 @@ lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_styl } #endif - lv_state_t state = lv_obj_get_state(parent, part); + lv_state_t state = lv_obj_get_state(parent); prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); res = _lv_style_list_get_int(list, prop, &value_act); @@ -474,7 +474,7 @@ lv_color_t _lv_obj_get_style_color(const lv_obj_t * obj, uint8_t part, lv_style_ while(parent) { lv_style_list_t * list = _lv_obj_get_style_list(parent, part); - lv_state_t state = lv_obj_get_state(parent, part); + lv_state_t state = lv_obj_get_state(parent); prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); res = _lv_style_list_get_color(list, prop, &value_act); @@ -552,7 +552,7 @@ lv_opa_t _lv_obj_get_style_opa(const lv_obj_t * obj, uint8_t part, lv_style_prop } #endif - lv_state_t state = lv_obj_get_state(parent, part); + lv_state_t state = lv_obj_get_state(parent); prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); res = _lv_style_list_get_opa(list, prop, &value_act); @@ -629,7 +629,7 @@ const void * _lv_obj_get_style_ptr(const lv_obj_t * obj, uint8_t part, lv_style_ } } #endif - lv_state_t state = lv_obj_get_state(parent, part); + lv_state_t state = lv_obj_get_state(parent); prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); res = _lv_style_list_get_ptr(list, prop, &value_act); @@ -1279,7 +1279,7 @@ static _lv_style_state_cmp_t style_snapshot_compare(style_snapshot_t * shot1, st if(shot1->pad_inner != shot2->pad_inner) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->margin_top != shot2->margin_top) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->margin_bottom != shot2->margin_bottom) return _LV_STYLE_STATE_CMP_DIFF; - if(shot1->margin_left != shot2->margin_right) return _LV_STYLE_STATE_CMP_DIFF; + if(shot1->margin_left != shot2->margin_left) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->margin_right != shot2->margin_right) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->margin_top != shot2->margin_top) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->transform_width != shot2->transform_width) return _LV_STYLE_STATE_CMP_DIFF; diff --git a/src/lv_themes/lv_theme.c b/src/lv_themes/lv_theme.c index 08b7fc8d8..66a626bac 100644 --- a/src/lv_themes/lv_theme.c +++ b/src/lv_themes/lv_theme.c @@ -306,7 +306,7 @@ static void clear_styles(lv_obj_t * obj, lv_theme_style_t name) #if LV_USE_CHECKBOX case LV_THEME_CHECKBOX: - _lv_obj_reset_style_list_no_refr(obj, LV_CHECKBOX_PART_BG); + _lv_obj_reset_style_list_no_refr(obj, LV_CHECKBOX_PART_MAIN); _lv_obj_reset_style_list_no_refr(obj, LV_CHECKBOX_PART_BULLET); break; #endif diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index ca6b3e460..4c73697df 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -645,6 +645,7 @@ static void checkbox_init(void) lv_style_set_pad_right(&styles->cb_bullet, LV_STATE_DEFAULT, LV_DPX(3)); lv_style_set_pad_top(&styles->cb_bullet, LV_STATE_DEFAULT, LV_DPX(3)); lv_style_set_pad_bottom(&styles->cb_bullet, LV_STATE_DEFAULT, LV_DPX(3)); + lv_style_set_margin_right(&styles->cb_bullet, LV_STATE_DEFAULT, LV_DPX(6)); #endif } @@ -1107,7 +1108,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) #if LV_USE_CHECKBOX case LV_THEME_CHECKBOX: - list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); + list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_MAIN); _lv_style_list_add_style(list, &styles->cb_bg); list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BULLET); diff --git a/src/lv_themes/lv_theme_mono.c b/src/lv_themes/lv_theme_mono.c index bf934c9f1..77c6f554e 100644 --- a/src/lv_themes/lv_theme_mono.c +++ b/src/lv_themes/lv_theme_mono.c @@ -717,7 +717,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) #if LV_USE_CHECKBOX case LV_THEME_CHECKBOX: - list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); + list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_MAIN); _lv_style_list_add_style(list, &styles->pad_small); list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BULLET); diff --git a/src/lv_themes/lv_theme_template.c b/src/lv_themes/lv_theme_template.c index 8d3e87508..ff220e120 100644 --- a/src/lv_themes/lv_theme_template.c +++ b/src/lv_themes/lv_theme_template.c @@ -563,7 +563,7 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) #if LV_USE_CHECKBOX case LV_THEME_CHECKBOX: - list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); + list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_MAIN); list = _lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BULLET); _lv_style_list_add_style(list, &styles->bg); diff --git a/src/lv_widgets/lv_checkbox.c b/src/lv_widgets/lv_checkbox.c index 3f8ac3dc7..f800c6322 100644 --- a/src/lv_widgets/lv_checkbox.c +++ b/src/lv_widgets/lv_checkbox.c @@ -25,6 +25,7 @@ /********************** * STATIC PROTOTYPES **********************/ +static lv_design_res_t lv_checkbox_design(lv_obj_t * cb, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_checkbox_signal(lv_obj_t * cb, lv_signal_t sign, void * param); static lv_style_list_t * lv_checkbox_get_style(lv_obj_t * cb, uint8_t type); @@ -32,6 +33,7 @@ static lv_style_list_t * lv_checkbox_get_style(lv_obj_t * cb, uint8_t type); * STATIC VARIABLES **********************/ static lv_signal_cb_t ancestor_signal; +static lv_design_cb_t ancestor_design; /********************** * MACROS @@ -52,11 +54,12 @@ lv_obj_t * lv_checkbox_create(lv_obj_t * par, const lv_obj_t * copy) LV_LOG_TRACE("check box create started"); /*Create the ancestor basic object*/ - lv_obj_t * cb = lv_btn_create(par, copy); + lv_obj_t * cb = lv_obj_create(par, copy); LV_ASSERT_MEM(cb); if(cb == NULL) return NULL; if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cb); + if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(cb); lv_checkbox_ext_t * ext = lv_obj_allocate_ext_attr(cb, sizeof(lv_checkbox_ext_t)); LV_ASSERT_MEM(ext); @@ -65,34 +68,33 @@ lv_obj_t * lv_checkbox_create(lv_obj_t * par, const lv_obj_t * copy) return NULL; } - ext->bullet = NULL; - ext->label = NULL; + ext->static_txt = 1; + ext->text = "Check box"; + lv_style_list_init(&ext->style_bullet); lv_obj_set_signal_cb(cb, lv_checkbox_signal); + lv_obj_set_design_cb(cb, lv_checkbox_design); /*Init the new checkbox object*/ if(copy == NULL) { - ext->bullet = lv_obj_create(cb, NULL); - lv_obj_set_click(ext->bullet, false); - - ext->label = lv_label_create(cb, NULL); - - lv_checkbox_set_text(cb, "Check box"); - lv_btn_set_layout(cb, LV_LAYOUT_ROW_MID); - lv_btn_set_fit(cb, LV_FIT_TIGHT); - lv_btn_set_checkable(cb, true); - lv_obj_add_protect(cb, LV_PROTECT_PRESS_LOST); - lv_theme_apply(cb, LV_THEME_CHECKBOX); + lv_obj_add_flag(cb, LV_OBJ_FLAG_CLICKABLE); + lv_obj_set_size(cb, LV_SIZE_AUTO, LV_SIZE_AUTO); } else { - lv_checkbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->bullet = lv_obj_create(cb, copy_ext->bullet); - ext->label = lv_label_create(cb, copy_ext->label); + lv_checkbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy); + lv_style_list_copy(&ext->style_bullet, ©_ext->style_bullet); + + ext->static_txt = copy_ext->static_txt; + if(copy_ext->static_txt) ext->text = copy_ext->text; + else { + ext->text = lv_mem_alloc(strlen(copy_ext->text) + 1); + strcpy(ext->text, copy_ext->text); + } /*Refresh the style with new signal function*/ - // lv_obj_refresh_style(cb); + _lv_obj_refresh_style(cb, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); } LV_LOG_INFO("check box created"); @@ -115,7 +117,16 @@ void lv_checkbox_set_text(lv_obj_t * cb, const char * txt) LV_ASSERT_OBJ(cb, LV_OBJX_NAME); lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); - lv_label_set_text(ext->label, txt); + if(ext->static_txt) { + ext->static_txt = 0; + ext->text = NULL; + } + + ext->text = lv_mem_realloc(ext->text, strlen(txt) + 1); + strcpy(ext->text, txt); + + lv_signal_send(cb, LV_SIGNAL_CHILD_CHG, NULL); + } /** @@ -129,7 +140,13 @@ void lv_checkbox_set_text_static(lv_obj_t * cb, const char * txt) LV_ASSERT_OBJ(cb, LV_OBJX_NAME); lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); - lv_label_set_text_static(ext->label, txt); + if(ext->static_txt == 0) { + ext->static_txt = 1; + lv_mem_free(ext->text); + ext->text = NULL; + } + + ext->text = txt; } /*===================== @@ -146,13 +163,85 @@ const char * lv_checkbox_get_text(const lv_obj_t * cb) LV_ASSERT_OBJ(cb, LV_OBJX_NAME); lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); - return lv_label_get_text(ext->label); + return ext->text; } /********************** * STATIC FUNCTIONS **********************/ +/** + * Handle the drawing related tasks of the check box + * @param cb pointer to a check box object + * @param clip_area 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 an element of `lv_design_res_t` + */ +static lv_design_res_t lv_checkbox_design(lv_obj_t * cb, const lv_area_t * clip_area, lv_design_mode_t mode) +{ + /* A label never covers an area */ + if(mode == LV_DESIGN_COVER_CHK) + return LV_DESIGN_RES_NOT_COVER; + else if(mode == LV_DESIGN_DRAW_MAIN) { + /*Draw the background*/ + ancestor_design(cb, clip_area, mode); + + lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); + + const lv_font_t * font = lv_obj_get_style_text_font(cb, LV_CHECKBOX_PART_MAIN); + lv_style_int_t letter_sp = lv_obj_get_style_text_letter_space(cb, LV_CHECKBOX_PART_MAIN); + lv_style_int_t line_sp = lv_obj_get_style_text_line_space(cb, LV_CHECKBOX_PART_MAIN); + lv_coord_t line_height = lv_font_get_line_height(font); + + lv_coord_t bg_leftp = lv_obj_get_style_pad_left(cb, LV_CHECKBOX_PART_MAIN); + lv_coord_t bg_rightp = lv_obj_get_style_pad_right(cb, LV_CHECKBOX_PART_MAIN); + lv_coord_t bg_topp = lv_obj_get_style_pad_top(cb, LV_CHECKBOX_PART_MAIN); + lv_coord_t bg_bottomp = lv_obj_get_style_pad_bottom(cb, LV_CHECKBOX_PART_MAIN); + + lv_coord_t bullet_leftm = lv_obj_get_style_margin_left(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_rightm = lv_obj_get_style_margin_right(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_topm = lv_obj_get_style_margin_top(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_bottomm = lv_obj_get_style_margin_bottom(cb, LV_CHECKBOX_PART_BULLET); + + lv_coord_t bullet_leftp = lv_obj_get_style_pad_left(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_rightp = lv_obj_get_style_pad_right(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_topp = lv_obj_get_style_pad_top(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_bottomp = lv_obj_get_style_pad_bottom(cb, LV_CHECKBOX_PART_BULLET); + + lv_draw_rect_dsc_t bullet_dsc; + lv_draw_rect_dsc_init(&bullet_dsc); + lv_obj_init_draw_rect_dsc(cb, LV_CHECKBOX_PART_BULLET, &bullet_dsc); + lv_area_t bullet_area; + bullet_area.x1 = cb->coords.x1 + bg_leftp + bullet_leftm; + bullet_area.x2 = bullet_area.x1 + line_height + bullet_leftp + bullet_rightp; + bullet_area.y1 = cb->coords.y1 + bg_topp + bullet_topm; + bullet_area.y2 = bullet_area.y1 + line_height + bullet_topp + bullet_bottomp; + + lv_draw_rect(&bullet_area, clip_area, &bullet_dsc); + + lv_point_t text_size; + _lv_txt_get_size(&text_size, ext->text, font, letter_sp, line_sp, LV_COORD_MAX, LV_TXT_FLAG_RECOLOR); + + lv_coord_t y_ofs = (lv_area_get_height(&bullet_area) - line_height) / 2; /*Align the text to the bullet's center line*/ + lv_area_t text_area; + text_area.x1 = bullet_area.x2 + bullet_rightm; + text_area.x2 = text_area.x1 + text_size.x; + text_area.y1 = bullet_area.y1 + bg_topp + y_ofs; + text_area.y2 = text_area.y1 + text_size.y; + + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + lv_obj_init_draw_label_dsc(cb, LV_CHECKBOX_PART_MAIN, &label_dsc); + lv_draw_label(&text_area, clip_area, &label_dsc, ext->text, NULL); + } else { + ancestor_design(cb, clip_area, mode); + } + + return LV_DESIGN_RES_OK; +} /** * Signal function of the check box * @param cb pointer to a check box object @@ -162,44 +251,48 @@ const char * lv_checkbox_get_text(const lv_obj_t * cb) */ static lv_res_t lv_checkbox_signal(lv_obj_t * cb, lv_signal_t sign, void * param) { + lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); + lv_res_t res; + /* Include the ancient signal function */ + res = ancestor_signal(cb, sign, param); + if(res != LV_RES_OK) return res; + if(sign == LV_SIGNAL_GET_STYLE) { lv_get_style_info_t * info = param; info->result = lv_checkbox_get_style(cb, info->part); if(info->result != NULL) return LV_RES_OK; else return ancestor_signal(cb, sign, param); } + else if (sign == LV_SIGNAL_GET_TYPE) { + return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); + } + else if (sign == LV_SIGNAL_GET_SELF_SIZE) { + const lv_font_t * font = lv_obj_get_style_text_font(cb, LV_CHECKBOX_PART_MAIN); + lv_style_int_t letter_sp = lv_obj_get_style_text_letter_space(cb, LV_CHECKBOX_PART_MAIN); + lv_style_int_t line_sp = lv_obj_get_style_text_line_space(cb, LV_CHECKBOX_PART_MAIN); + lv_point_t text_size; + _lv_txt_get_size(&text_size, ext->text, font, letter_sp, line_sp, LV_COORD_MAX, LV_TXT_FLAG_RECOLOR); - /* Include the ancient signal function */ - res = ancestor_signal(cb, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); - - if(sign == LV_SIGNAL_STYLE_CHG) { - const lv_font_t * font = lv_obj_get_style_text_font(ext->label, LV_LABEL_PART_MAIN); lv_coord_t line_height = lv_font_get_line_height(font); - lv_coord_t leftp = lv_obj_get_style_pad_left(cb, LV_CHECKBOX_PART_BULLET); - lv_coord_t rightp = lv_obj_get_style_pad_right(cb, LV_CHECKBOX_PART_BULLET); - lv_coord_t topp = lv_obj_get_style_pad_top(cb, LV_CHECKBOX_PART_BULLET); - lv_coord_t bottomp = lv_obj_get_style_pad_bottom(cb, LV_CHECKBOX_PART_BULLET); - lv_obj_set_size(ext->bullet, line_height + leftp + rightp, line_height + topp + bottomp); - lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG)); - } - else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST || - sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) { - lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG)); - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - char c = *((char *)param); - if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN || c == LV_KEY_LEFT || c == LV_KEY_UP) { - /*Follow the backgrounds state with the bullet*/ - lv_obj_set_state(ext->bullet, lv_obj_get_state(cb, LV_CHECKBOX_PART_BG)); - } -#endif + lv_coord_t bullet_leftm = lv_obj_get_style_margin_left(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_rightm = lv_obj_get_style_margin_right(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_topm = lv_obj_get_style_margin_top(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_bottomm = lv_obj_get_style_margin_bottom(cb, LV_CHECKBOX_PART_BULLET); + + lv_coord_t bullet_leftp = lv_obj_get_style_pad_left(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_rightp = lv_obj_get_style_pad_right(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_topp = lv_obj_get_style_pad_top(cb, LV_CHECKBOX_PART_BULLET); + lv_coord_t bullet_bottomp = lv_obj_get_style_pad_bottom(cb, LV_CHECKBOX_PART_BULLET); + + lv_point_t bullet_size; + bullet_size.x = line_height + bullet_leftm + bullet_rightm + bullet_leftp + bullet_rightp; + bullet_size.y = line_height + bullet_topm + bullet_bottomm + bullet_topp + bullet_bottomp; + + lv_point_t * size_res = param; + size_res->x = bullet_size.x + text_size.x; + size_res->y = LV_MATH_MAX(bullet_size.y, text_size.y); } return res; @@ -212,11 +305,11 @@ static lv_style_list_t * lv_checkbox_get_style(lv_obj_t * cb, uint8_t type) lv_checkbox_ext_t * ext = lv_obj_get_ext_attr(cb); switch(type) { - case LV_CHECKBOX_PART_BG: + case LV_CHECKBOX_PART_MAIN: style_dsc_p = &cb->style_list; break; case LV_CHECKBOX_PART_BULLET: - style_dsc_p = lv_obj_get_style_list(ext->bullet, LV_BTN_PART_MAIN); + style_dsc_p = &ext->style_bullet; break; default: style_dsc_p = NULL; diff --git a/src/lv_widgets/lv_checkbox.h b/src/lv_widgets/lv_checkbox.h index 7576a76d9..c1b24aa74 100644 --- a/src/lv_widgets/lv_checkbox.h +++ b/src/lv_widgets/lv_checkbox.h @@ -27,8 +27,6 @@ extern "C" { #endif #include "../lv_core/lv_obj.h" -#include "lv_btn.h" -#include "lv_label.h" /********************* * DEFINES @@ -43,13 +41,15 @@ typedef struct { /*No inherited ext, derived from the base object */ /*New data for this widget */ - lv_obj_t * text; /*Pointer to button*/ - lv_obj_t * label; /*Pointer to label*/ + lv_style_list_t style_bullet; + char * text; /*Pointer to button*/ + uint32_t static_txt :1; } lv_checkbox_ext_t; /** Checkbox styles. */ enum { LV_CHECKBOX_PART_MAIN = LV_OBJ_PART_MAIN, /**< Style of object background. */ + LV_CHECKBOX_PART_BULLET, /**< Style of the bullet */ _LV_CHECKBOX_PART_VIRTUAL_LAST, }; typedef uint8_t lv_checkbox_style_t; @@ -74,7 +74,7 @@ lv_obj_t * lv_checkbox_create(lv_obj_t * par, const lv_obj_t * copy); * Set the text of a check box. `txt` will be copied and may be deallocated * after this function returns. * @param cb pointer to a check box - * @param txt the text of the check box. NULL to refresh with the current text. + * @param txt the text of the check box. */ void lv_checkbox_set_text(lv_obj_t * cb, const char * txt); @@ -82,7 +82,7 @@ void lv_checkbox_set_text(lv_obj_t * cb, const char * txt); * Set the text of a check box. `txt` must not be deallocated during the life * of this checkbox. * @param cb pointer to a check box - * @param txt the text of the check box. NULL to refresh with the current text. + * @param txt the text of the check box. */ void lv_checkbox_set_text_static(lv_obj_t * cb, const char * txt); @@ -93,27 +93,21 @@ void lv_checkbox_set_text_static(lv_obj_t * cb, const char * txt); */ static inline void lv_checkbox_set_checked(lv_obj_t * cb, bool checked) { - lv_btn_set_state(cb, checked ? LV_BTN_STATE_CHECKED_RELEASED : LV_BTN_STATE_RELEASED); + if(checked) lv_obj_set_state(cb, LV_STATE_CHECKED); + else lv_obj_clear_state(cb, LV_STATE_CHECKED); } /** * Make the check box inactive (disabled) * @param cb pointer to a check box object + * @param dis true; make the checkbox disabled; false: make the chackbox active */ -static inline void lv_checkbox_set_disabled(lv_obj_t * cb) +static inline void lv_checkbox_set_disabled(lv_obj_t * cb, bool dis) { - lv_btn_set_state(cb, LV_BTN_STATE_DISABLED); + if(dis) lv_obj_set_state(cb, LV_STATE_DISABLED); + else lv_obj_clear_state(cb, LV_STATE_DISABLED); } -/** - * Set the state of a check box - * @param cb pointer to a check box object - * @param state the new state of the check box (from lv_btn_state_t enum) - */ -static inline void lv_checkbox_set_state(lv_obj_t * cb, lv_btn_state_t state) -{ - lv_btn_set_state(cb, state); -} /*===================== * Getter functions *====================*/ @@ -132,7 +126,7 @@ const char * lv_checkbox_get_text(const lv_obj_t * cb); */ static inline bool lv_checkbox_is_checked(const lv_obj_t * cb) { - return lv_btn_get_state(cb) == LV_BTN_STATE_RELEASED ? false : true; + return lv_obj_get_state(cb) & LV_STATE_CHECKED ? true : false; } /** @@ -140,19 +134,9 @@ static inline bool lv_checkbox_is_checked(const lv_obj_t * cb) * @param cb pointer to a check box object * @return true: inactive; false: not inactive */ -static inline bool lv_checkbox_is_inactive(const lv_obj_t * cb) +static inline bool lv_checkbox_is_disabled(const lv_obj_t * cb) { - return lv_btn_get_state(cb) == LV_BTN_STATE_DISABLED ? true : false; -} - -/** - * Get the current state of a check box - * @param cb pointer to a check box object - * @return the state of the check box (from lv_btn_state_t enum) - */ -static inline lv_btn_state_t lv_checkbox_get_state(const lv_obj_t * cb) -{ - return lv_btn_get_state(cb); + return lv_obj_get_state(cb) & LV_STATE_DISABLED ? true : false; } /**********************