diff --git a/src/lv_core/lv_disp.c b/src/lv_core/lv_disp.c index 4a8f5c8a0..abb67f04c 100644 --- a/src/lv_core/lv_disp.c +++ b/src/lv_core/lv_disp.c @@ -120,25 +120,6 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) return disp->sys_layer; } -/** - * Assign a screen to a display. - * @param disp pointer to a display where to assign the screen - * @param scr pointer to a screen object to assign - */ -void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr) -{ - if(lv_obj_get_parent(scr) != NULL) { - LV_LOG_WARN("lv_disp_assign_screen: try to assign a non-screen object"); - return; - } - - lv_disp_t * old_disp = lv_obj_get_disp(scr); - - if(old_disp == disp) return; - - _lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr, true); -} - /** * Set the background color of a display * @param disp pointer to a display diff --git a/src/lv_core/lv_disp.h b/src/lv_core/lv_disp.h index e82d4ea22..e8396e9e7 100644 --- a/src/lv_core/lv_disp.h +++ b/src/lv_core/lv_disp.h @@ -78,14 +78,6 @@ lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp); */ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp); -/** - * Assign a screen to a display. - * @param disp pointer to a display where to assign the screen - * @param scr pointer to a screen object to assign - */ -void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr); - - /** * Set the background color of a display * @param disp pointer to a display diff --git a/src/lv_core/lv_flex.c b/src/lv_core/lv_flex.c index c6cd582b7..d558d5107 100644 --- a/src/lv_core/lv_flex.c +++ b/src/lv_core/lv_flex.c @@ -26,14 +26,14 @@ typedef struct { /********************** * STATIC PROTOTYPES **********************/ -//static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coord_t max_size, lv_coord_t * grow_unit, lv_coord_t * track_cross_size, lv_coord_t * track_main_size, uint32_t * item_cnt); -static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coord_t max_main_size, track_t * t); -static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_flex_place_t main_place, track_t * t); +static uint32_t find_track_end(lv_obj_t * cont, uint32_t item_start_id, lv_coord_t max_main_size, track_t * t); +static void children_repos(lv_obj_t * cont, uint32_t item_first_id, uint32_t item_last_id, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_flex_place_t main_place, track_t * t); static void place_content(lv_coord_t place, lv_coord_t max_size, lv_coord_t track_size, lv_coord_t item_cnt, lv_coord_t * start_pos, lv_coord_t * gap); static lv_flex_dir_t get_dir(const lv_obj_t * obj); static bool get_rev(const lv_obj_t * obj); static bool get_wrap(const lv_obj_t * obj); +static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, uint32_t * item_id); /********************** * STATIC VARIABLES @@ -158,7 +158,6 @@ void _lv_flex_refresh(lv_obj_t * cont) lv_flex_place_t cross_place = lv_obj_get_flex_track_place(cont); lv_flex_place_t main_place = cont->spec_attr->flex_cont.main_place; - lv_ll_t * ll = _lv_obj_get_child_ll(cont); lv_coord_t * cross_pos = (row ? &abs_y : &abs_x); if((row && cont->h_set == LV_SIZE_AUTO) || @@ -175,14 +174,14 @@ void _lv_flex_refresh(lv_obj_t * cont) lv_coord_t total_track_cross_size = 0; lv_coord_t gap = 0; uint32_t track_cnt = 0; - lv_obj_t * track_first_item; - lv_obj_t * next_track_first_item; + uint32_t track_first_item; + uint32_t next_track_first_item; bool rev = get_rev(cont); if(cross_place != LV_FLEX_PLACE_START) { - track_first_item = rev ? _lv_ll_get_head(ll) : _lv_ll_get_tail(ll); + track_first_item = rev ? cont->spec_attr->child_cnt - 1 : 0; track_t t; - while(track_first_item) { + while(track_first_item ) { /*Search the first item of the next row */ next_track_first_item = find_track_end(cont, track_first_item, max_main_size, &t); total_track_cross_size += t.track_cross_size; @@ -194,7 +193,7 @@ void _lv_flex_refresh(lv_obj_t * cont) place_content(cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap); } - track_first_item = rev ? _lv_ll_get_head(ll) : _lv_ll_get_tail(ll); + track_first_item = rev ? cont->spec_attr->child_cnt - 1 : 0; if(rtl && !row) { *cross_pos += total_track_cross_size; @@ -224,7 +223,7 @@ void _lv_flex_refresh(lv_obj_t * cont) * STATIC FUNCTIONS **********************/ -static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coord_t max_main_size, track_t * t) +static uint32_t find_track_end(lv_obj_t * cont, uint32_t item_start_id, lv_coord_t max_main_size, track_t * t) { bool wrap = get_wrap(cont); bool rev = get_rev(cont); @@ -232,9 +231,6 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coor bool row = get_dir(cont) == LV_FLEX_DIR_ROW ? true : false; lv_coord_t(*get_main_size)(const lv_obj_t *) = (row ? lv_obj_get_width_margin : lv_obj_get_height_margin); lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!row ? lv_obj_get_width_margin : lv_obj_get_height_margin); - void * (*ll_iter)(const lv_ll_t * , const void *) = rev ? _lv_ll_get_next : _lv_ll_get_prev; - - lv_ll_t * ll = _lv_obj_get_child_ll(cont); lv_coord_t grow_sum = 0; t->track_main_size = 0; @@ -243,12 +239,14 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coor t->grow_unit = 0; t->item_cnt = 0; - lv_obj_t * item = item_start; + uint32_t item_id = item_start_id; + + lv_obj_t * item = get_next_item(cont, rev, &item_id); while(item) { /*Ignore non-flex items*/ lv_coord_t main_set = (row ? item->x_set : item->y_set); if(LV_COORD_IS_FLEX(main_set) == false) { - item = ll_iter(ll, item); + item = get_next_item(cont, rev, &item_id); continue; } @@ -263,7 +261,8 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coor } t->track_cross_size = LV_MATH_MAX(get_cross_size(item), t->track_cross_size); - item = ll_iter(ll, item); + item_id += rev ? -1 : +1; + item = lv_obj_get_child(cont, item_id); t->item_cnt++; } @@ -279,8 +278,8 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coor } /*Have at least one item in a row*/ - if(item && item == item_start) { - item = ll_iter(ll, item); + if(item && item_id == item_start_id) { + item = get_next_item(cont, rev, &item_id); if(item) { t->track_cross_size = get_cross_size(item); t->track_main_size = get_main_size(item); @@ -288,11 +287,11 @@ static lv_obj_t * find_track_end(lv_obj_t * cont, lv_obj_t * item_start, lv_coor } } - return item; + return item_id; } -static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * item_last, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_flex_place_t main_place, track_t * t) +static void children_repos(lv_obj_t * cont, uint32_t item_first_id, uint32_t item_last_id, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t max_main_size, lv_flex_place_t main_place, track_t * t) { bool rev = get_rev(cont); lv_coord_t gap = lv_obj_get_flex_gap(cont); @@ -305,25 +304,23 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it lv_coord_t (*area_get_main_size)(const lv_area_t *) = (!row ? lv_area_get_width : lv_area_get_height); lv_style_int_t (*get_margin_start)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top); lv_style_int_t (*get_margin_end)(const lv_obj_t *, uint8_t part) = (row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); - void * (*ll_iter)(const lv_ll_t * , const void *) = rev ? _lv_ll_get_next : _lv_ll_get_prev; bool rtl = lv_obj_get_base_dir(cont) == LV_BIDI_DIR_RTL ? true : false; if(row && rtl) abs_x += lv_obj_get_width_fit(cont); - lv_ll_t * ll = _lv_obj_get_child_ll(cont); lv_coord_t main_pos = 0; lv_coord_t place_gap = 0; place_content(main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap); - /*Reposition the children*/ - lv_obj_t * item = item_first; /*Just to use a shorter name*/ - while(item != item_last) { + lv_obj_t * item = get_next_item(cont, rev, &item_first_id); + /*Reposition the children*/ + while(item && item_first_id != item_last_id) { /*Ignore non-flex items*/ lv_coord_t main_set = (row ? item->x_set : item->y_set); if(LV_COORD_IS_FLEX(main_set) == false) { - item = ll_iter(ll, item); + item = get_next_item(cont, rev, &item_first_id); continue; } @@ -343,7 +340,7 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it if(lv_area_get_height(&old_coords) != area_get_main_size(&item->coords)) { lv_obj_invalidate(item); - item->signal_cb(item, LV_SIGNAL_COORD_CHG, &old_coords); + lv_signal_send(item, LV_SIGNAL_COORD_CHG, &old_coords); lv_obj_invalidate(item); } } @@ -379,7 +376,7 @@ static void children_repos(lv_obj_t * cont, lv_obj_t * item_first, lv_obj_t * it if(!(row && rtl)) { main_pos += obj_get_main_size(item) + gap + place_gap; } - item = ll_iter(ll, item); + item = get_next_item(cont, rev, &item_first_id); } } @@ -437,3 +434,24 @@ static bool get_wrap(const lv_obj_t * obj) if(obj->spec_attr) return obj->spec_attr->flex_cont.wrap; else return false; } + +static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, uint32_t * item_id) +{ + if(rev) { + if(*item_id > 0) { + (*item_id)--; + return cont->spec_attr->children[*item_id]; + } + else { + return NULL; + } + } else { + if((*item_id) <= cont->spec_attr->child_cnt - 1) { + item_id++; + return cont->spec_attr->children[*item_id]; + } + else { + return NULL; + } + } +} diff --git a/src/lv_core/lv_grid.c b/src/lv_core/lv_grid.c index 0e75be0fa..18d381257 100644 --- a/src/lv_core/lv_grid.c +++ b/src/lv_core/lv_grid.c @@ -115,9 +115,9 @@ void lv_obj_report_grid_change(const lv_grid_t * grid) lv_disp_t * d = lv_disp_get_next(NULL); while(d) { - lv_obj_t * i; - _LV_LL_READ(&d->scr_ll, i) { - report_grid_change_core(grid, i); + uint32_t i; + for(i = 0; i < d->screen_cnt; i++) { + report_grid_change_core(grid, d->screens[i]); } d = lv_disp_get_next(d); } @@ -136,11 +136,10 @@ void _lv_grid_calc(struct _lv_obj_t * cont, _lv_grid_calc_t * calc_out) if(g->col_dsc == NULL || g->row_dsc == NULL) return; if(g->col_dsc_len == 0 || g->row_dsc_len == 0) return; - if(lv_obj_get_child(cont, NULL) == NULL) { + if(lv_obj_get_child(cont, 0) == NULL) { _lv_memset_00(calc_out, sizeof(_lv_grid_calc_t)); return; } -// printf("calc: %d, %d\n", obj->grid->col_dsc_len, obj->grid->row_dsc_len); calc_rows(cont, calc_out); calc_cols(cont, calc_out); @@ -228,12 +227,12 @@ void _lv_grid_full_refresh(lv_obj_t * cont) hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont); hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont); - lv_obj_t * item = lv_obj_get_child_back(cont, NULL); - while(item) { + uint32_t i; + for(i = 0; i < cont->spec_attr->child_cnt; i++) { + lv_obj_t * item = cont->spec_attr->children[i]; if(LV_COORD_IS_GRID(item->x_set) && LV_COORD_IS_GRID(item->y_set)) { item_repos(item, &calc, &hint); } - item = lv_obj_get_child_back(cont, item); } _lv_grid_calc_free(&calc); @@ -430,7 +429,7 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * calc, item_repos_hint_ lv_area_set_width(&item->coords, item_w); lv_area_set_height(&item->coords, item_h); lv_obj_invalidate(item); - item->signal_cb(item, LV_SIGNAL_COORD_CHG, &old_coords); + lv_signal_send(item, LV_SIGNAL_COORD_CHG, &old_coords); } bool moved = true; @@ -530,10 +529,9 @@ static void report_grid_change_core(const lv_grid_t * grid, lv_obj_t * obj) if(obj->spec_attr->grid == grid || (obj->spec_attr->grid && grid == NULL)) _lv_grid_full_refresh(obj); } - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { - report_grid_change_core(grid, child); - child = lv_obj_get_child(obj, child); + uint32_t i; + for(i = 0; i < obj->spec_attr->child_cnt; i++) { + report_grid_change_core(grid, obj->spec_attr->children[i]); } } diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 5f5be58aa..2d9c01e32 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -1050,16 +1050,13 @@ lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) /*If the point is on this object check its children too*/ if(lv_obj_hit_test(obj, point)) { - lv_obj_t * i; - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, i) { - found_p = lv_indev_search_obj(i, point); + int32_t i; + for(i = lv_obj_get_child_cnt(obj) - 1; i >= 0; i--) { + lv_obj_t * child = lv_obj_get_child(obj, i); + found_p = lv_indev_search_obj(child, point); /*If a child was found then break*/ - if(found_p != NULL) { - break; - } + if(found_p != NULL) break; } /*If then the children was not ok, and this obj is clickable @@ -1222,7 +1219,7 @@ void indev_gesture(lv_indev_proc_t * proc) proc->types.pointer.gesture_dir = LV_GESTURE_DIR_TOP; } - gesture_obj->signal_cb(gesture_obj, LV_SIGNAL_GESTURE, indev_act); + lv_signal_send(gesture_obj, LV_SIGNAL_GESTURE, indev_act); if(indev_reset_check(proc)) return; lv_event_send(gesture_obj, LV_EVENT_GESTURE, NULL); if(indev_reset_check(proc)) return; diff --git a/src/lv_core/lv_indev_scroll.c b/src/lv_core/lv_indev_scroll.c index 66fdab1e1..679dddc77 100644 --- a/src/lv_core/lv_indev_scroll.c +++ b/src/lv_core/lv_indev_scroll.c @@ -258,10 +258,11 @@ static lv_obj_t * find_scroll_obj(lv_indev_proc_t * proc) * 5. Use the last candidate. Always the "deepest" parent or the object from point 3 */ lv_obj_t * obj_act = proc->types.pointer.act_obj; while(obj_act) { - /*Halt search on a scroll freeze object*/ - if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_FREEZE)) return NULL; + if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLLABLE) == false) { + /*If this object don't want to chain the scroll ot the parent stop searching*/ + if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN) == false) break; obj_act = lv_obj_get_parent(obj_act); continue; } @@ -330,6 +331,9 @@ static lv_obj_t * find_scroll_obj(lv_indev_proc_t * proc) break; } + /*If this object don't want to chain the scroll ot the parent stop searching*/ + if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN) == false) break; + /*Try the parent */ obj_act = lv_obj_get_parent(obj_act); } @@ -411,8 +415,9 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo lv_coord_t dist = LV_COORD_MAX; - lv_obj_t * child = lv_obj_get_child_back(obj, NULL); - while(child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPABLE)) { lv_coord_t x_child = 0; lv_coord_t x_parent = 0; @@ -436,8 +441,6 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo if(LV_MATH_ABS(x) < LV_MATH_ABS(dist)) dist = x; } } - - child = lv_obj_get_child_back(obj, child); } return dist == LV_COORD_MAX ? 0: -dist; @@ -459,8 +462,9 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo lv_coord_t dist = LV_COORD_MAX; - lv_obj_t * child = lv_obj_get_child_back(obj, NULL); - while(child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPABLE)) { lv_coord_t y_child = 0; lv_coord_t y_parent = 0; @@ -484,8 +488,6 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo if(LV_MATH_ABS(y) < LV_MATH_ABS(dist)) dist = y; } } - - child = lv_obj_get_child_back(obj, child); } return dist == LV_COORD_MAX ? 0 : -dist; diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index ae1fd820a..68444eb08 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -67,6 +67,8 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin static void lv_obj_del_async_cb(void * obj); static void obj_del_core(lv_obj_t * obj); static void base_dir_refr_children(lv_obj_t * obj); +static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy); +static void lv_obj_destructor(void * obj); /********************** * STATIC VARIABLES @@ -74,6 +76,7 @@ static void base_dir_refr_children(lv_obj_t * obj); static bool lv_initialized = false; static lv_event_temp_data_t * event_temp_data_head; static const void * event_act_data; +lv_obj_class_t lv_obj; /********************** * MACROS @@ -117,6 +120,13 @@ void lv_init(void) lv_gpu_stm32_dma2d_init(); #endif + LV_CLASS_INIT(lv_obj, lv_base); + lv_obj.constructor = lv_obj_constructor; + lv_obj.destructor = lv_obj_destructor; + lv_obj.signal_cb = lv_obj_signal; + lv_obj.design_cb = lv_obj_design; + + _lv_obj_style_init(); _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); @@ -185,127 +195,16 @@ void lv_deinit(void) */ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) { - lv_obj_t * new_obj = NULL; - - /*Create a screen*/ - if(parent == NULL) { - LV_LOG_TRACE("Screen create started"); - lv_disp_t * disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_obj_create: not display created to so far. No place to assign the new screen"); - return NULL; - } - - new_obj = _lv_ll_ins_head(&disp->scr_ll); - LV_ASSERT_MEM(new_obj); - if(new_obj == NULL) return NULL; - - _lv_memset_00(new_obj, sizeof(lv_obj_t)); - - /*Set the callbacks*/ - new_obj->signal_cb = lv_obj_signal; - new_obj->design_cb = lv_obj_design; - - /*Set coordinates to full screen size*/ - new_obj->coords.x1 = 0; - new_obj->coords.y1 = 0; - new_obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1; - new_obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1; - } - /*Create a normal object*/ - else { - LV_LOG_TRACE("Object create started"); - LV_ASSERT_OBJ(parent, LV_OBJX_NAME); - if(parent->spec_attr == NULL) { - parent->spec_attr = lv_obj_allocate_spec_attr(parent); - } - new_obj = _lv_ll_ins_head(&parent->spec_attr->child_ll); - LV_ASSERT_MEM(new_obj); - if(new_obj == NULL) return NULL; - - _lv_memset_00(new_obj, sizeof(lv_obj_t)); - - new_obj->parent = parent; - - /*Set the callbacks (signal:cb is required in `lv_obj_get_base_dir` if `LV_USE_ASSERT_OBJ` is enabled)*/ - new_obj->signal_cb = lv_obj_signal; - new_obj->design_cb = lv_obj_design; - - new_obj->coords.y1 = parent->coords.y1; - new_obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT; - if(lv_obj_get_base_dir(new_obj) == LV_BIDI_DIR_RTL) { - new_obj->coords.x2 = parent->coords.x2; - new_obj->coords.x1 = parent->coords.x2 - LV_OBJ_DEF_WIDTH; - } - else { - new_obj->coords.x1 = parent->coords.x1; - new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; - } - new_obj->w_set = lv_area_get_width(&new_obj->coords); - new_obj->h_set = lv_area_get_height(&new_obj->coords); - } - - /*Set attributes*/ - new_obj->flags = LV_OBJ_FLAG_CLICKABLE; - new_obj->flags |= LV_OBJ_FLAG_SNAPABLE; - new_obj->flags |= LV_OBJ_FLAG_PRESS_LOCK; - new_obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE; - new_obj->flags |= LV_OBJ_FLAG_SCROLLABLE; - new_obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC; - new_obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM; - new_obj->flags |= LV_OBJ_FLAG_FOCUS_SCROLL; - if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE; - new_obj->state = LV_STATE_DEFAULT; - - new_obj->ext_attr = NULL; - - lv_style_list_init(&new_obj->style_list); - lv_style_list_init(&new_obj->style_list); + lv_obj_t * obj = lv_class_new(&lv_obj); + lv_obj.constructor(obj, parent, copy); if(copy == NULL) { - if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ); - else lv_theme_apply(new_obj, LV_THEME_SCR); - } - else { - lv_style_list_copy(&new_obj->style_list, ©->style_list); - } - /*Copy the attributes if required*/ - if(copy != NULL) { - lv_area_copy(&new_obj->coords, ©->coords); - - new_obj->flags = copy->flags; - if(copy->spec_attr) { - lv_obj_allocate_spec_attr(new_obj); - _lv_memcpy_small(new_obj->spec_attr, copy->spec_attr, sizeof(lv_obj_spec_attr_t)); - _lv_ll_init(&new_obj->spec_attr->child_ll, sizeof(lv_obj_t)); /*Make the child list empty*/ - } -#if LV_USE_GROUP - /*Add to the same group*/ - if(copy->spec_attr && copy->spec_attr->group_p) { - new_obj->spec_attr->group_p = NULL; /*It was simply copied */ - lv_group_add_obj(copy->spec_attr->group_p, new_obj); - } -#endif - - /*Set the same coordinates for non screen objects*/ - if(lv_obj_get_parent(copy) != NULL && parent != NULL) { - lv_obj_set_pos(new_obj, lv_obj_get_x(copy), lv_obj_get_y(copy)); - lv_obj_set_size(new_obj, lv_obj_get_width(copy), lv_obj_get_height(copy)); - - } - } else { - lv_obj_set_pos(new_obj, 0, 0); - } - /*Send a signal to the parent to notify it about the new child*/ - if(parent != NULL) { - parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, new_obj); - - /*Invalidate the area if not screen created*/ - lv_obj_invalidate(new_obj); - } - - LV_LOG_INFO("Object create ready"); - - return new_obj; + if(parent != NULL) lv_theme_apply(obj, LV_THEME_OBJ); + else lv_theme_apply(obj, LV_THEME_SCR); + } + else { + lv_style_list_copy(&obj->style_list, ©->style_list); + } + return obj; } /** @@ -327,12 +226,11 @@ lv_res_t lv_obj_del(lv_obj_t * obj) if(disp->act_scr == obj) act_scr_del = true; } - obj_del_core(obj); /*Send a signal to the parent to notify it about the child delete*/ if(par) { - par->signal_cb(par, LV_SIGNAL_CHILD_CHG, NULL); + lv_signal_send(par, LV_SIGNAL_CHILD_CHG, NULL); } /*Handle if the active screen was deleted*/ @@ -373,10 +271,10 @@ void lv_obj_del_async(lv_obj_t * obj) void lv_obj_clean(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { - lv_obj_del(child); - child = lv_obj_get_child(obj, NULL); /*Get the new first child*/ + + while(1) { + lv_obj_t * child = lv_obj_get_child(obj, 0); + obj_del_core(child); } } @@ -500,58 +398,59 @@ bool lv_obj_is_visible(const lv_obj_t * obj) */ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - LV_ASSERT_OBJ(parent, LV_OBJX_NAME); - - if(obj->parent == NULL) { - LV_LOG_WARN("Can't set the parent of a screen"); - return; - } - - if(parent == NULL) { - LV_LOG_WARN("Can't set parent == NULL to an object"); - return; - } - - lv_obj_invalidate(obj); - - if(parent->spec_attr == NULL) { - parent->spec_attr = lv_obj_allocate_spec_attr(parent); - } - - lv_obj_t * old_par = obj->parent; - lv_point_t old_pos; - old_pos.y = lv_obj_get_y(obj); - - lv_bidi_dir_t new_base_dir = lv_obj_get_base_dir(parent); - - if(new_base_dir != LV_BIDI_DIR_RTL) { - old_pos.x = lv_obj_get_x(obj); - } - else { - old_pos.x = old_par->coords.x2 - obj->coords.x2; - } - - _lv_ll_chg_list(_lv_obj_get_child_ll(obj->parent), _lv_obj_get_child_ll(parent), obj, true); - obj->parent = parent; - - - if(new_base_dir != LV_BIDI_DIR_RTL) { - lv_obj_set_pos(obj, old_pos.x, old_pos.y); - } - else { - /*Align to the right in case of RTL base dir*/ - lv_coord_t new_x = lv_obj_get_width(parent) - old_pos.x - lv_obj_get_width(obj); - lv_obj_set_pos(obj, new_x, old_pos.y); - } - - /*Notify the original parent because one of its children is lost*/ - old_par->signal_cb(old_par, LV_SIGNAL_CHILD_CHG, obj); - - /*Notify the new parent about the child*/ - parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); - - lv_obj_invalidate(obj); + while(1); +// LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +// LV_ASSERT_OBJ(parent, LV_OBJX_NAME); +// +// if(obj->parent == NULL) { +// LV_LOG_WARN("Can't set the parent of a screen"); +// return; +// } +// +// if(parent == NULL) { +// LV_LOG_WARN("Can't set parent == NULL to an object"); +// return; +// } +// +// lv_obj_invalidate(obj); +// +// if(parent->spec_attr == NULL) { +// parent->spec_attr = lv_obj_allocate_spec_attr(parent); +// } +// +// lv_obj_t * old_par = obj->parent; +// lv_point_t old_pos; +// old_pos.y = lv_obj_get_y(obj); +// +// lv_bidi_dir_t new_base_dir = lv_obj_get_base_dir(parent); +// +// if(new_base_dir != LV_BIDI_DIR_RTL) { +// old_pos.x = lv_obj_get_x(obj); +// } +// else { +// old_pos.x = old_par->coords.x2 - obj->coords.x2; +// } +// +// _lv_ll_chg_list(_lv_obj_get_child_ll(obj->parent), _lv_obj_get_child_ll(parent), obj, true); +// obj->parent = parent; +// +// +// if(new_base_dir != LV_BIDI_DIR_RTL) { +// lv_obj_set_pos(obj, old_pos.x, old_pos.y); +// } +// else { +// /*Align to the right in case of RTL base dir*/ +// lv_coord_t new_x = lv_obj_get_width(parent) - old_pos.x - lv_obj_get_width(obj); +// lv_obj_set_pos(obj, new_x, old_pos.y); +// } +// +// /*Notify the original parent because one of its children is lost*/ +// lv_signal_send(old_par, LV_SIGNAL_CHILD_CHG, obj); +// +// /*Notify the new parent about the child*/ +// lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); +// +// lv_obj_invalidate(obj); } /** @@ -560,22 +459,22 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) */ void lv_obj_move_foreground(lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_t * parent = lv_obj_get_parent(obj); - lv_ll_t * ll = _lv_obj_get_child_ll(parent); - - /*Do nothing of already in the foreground*/ - if(_lv_ll_get_head(ll) == obj) return; - - lv_obj_invalidate(parent); - - _lv_ll_chg_list(ll, ll, obj, true); - - /*Notify the new parent about the child*/ - parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); - - lv_obj_invalidate(parent); +// LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +// +// lv_obj_t * parent = lv_obj_get_parent(obj); +// lv_ll_t * ll = _lv_obj_get_child_ll(parent); +// +// /*Do nothing of already in the foreground*/ +// if(_lv_ll_get_head(ll) == obj) return; +// +// lv_obj_invalidate(parent); +// +// _lv_ll_chg_list(ll, ll, obj, true); +// +// /*Notify the new parent about the child*/ +// lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); +// +// lv_obj_invalidate(parent); } /** @@ -584,22 +483,22 @@ void lv_obj_move_foreground(lv_obj_t * obj) */ void lv_obj_move_background(lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_t * parent = lv_obj_get_parent(obj); - lv_ll_t * ll = _lv_obj_get_child_ll(parent); - - /*Do nothing of already in the background*/ - if(_lv_ll_get_tail(ll) == obj) return; - - lv_obj_invalidate(parent); - - _lv_ll_chg_list(ll, ll, obj, false); - - /*Notify the new parent about the child*/ - parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); - - lv_obj_invalidate(parent); +// LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +// +// lv_obj_t * parent = lv_obj_get_parent(obj); +// lv_ll_t * ll = _lv_obj_get_child_ll(parent); +// +// /*Do nothing of already in the background*/ +// if(_lv_ll_get_tail(ll) == obj) return; +// +// lv_obj_invalidate(parent); +// +// _lv_ll_chg_list(ll, ll, obj, false); +// +// /*Notify the new parent about the child*/ +// lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); +// +// lv_obj_invalidate(parent); } /*-------------------- @@ -855,10 +754,9 @@ void lv_event_send_refresh_recursive(lv_obj_t * obj) /*If no obj specified refresh all screen of all displays */ lv_disp_t * d = lv_disp_get_next(NULL); while(d) { - lv_obj_t * scr = _lv_ll_get_head(&d->scr_ll); - while(scr) { - lv_event_send_refresh_recursive(scr); - scr = _lv_ll_get_next(&d->scr_ll, scr); + uint32_t i; + for(i = 0; i < d->screen_cnt; i++) { + lv_event_send_refresh_recursive(d->screens[i]); } lv_event_send_refresh_recursive(d->top_layer); lv_event_send_refresh_recursive(d->sys_layer); @@ -871,10 +769,9 @@ void lv_event_send_refresh_recursive(lv_obj_t * obj) lv_res_t res = lv_event_send_refresh(obj); if(res != LV_RES_OK) return; /*If invalid returned do not check the children*/ - lv_obj_t * child; - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, child) { - lv_event_send_refresh_recursive(child); + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_event_send_refresh_recursive(lv_obj_get_child(obj, i)); } } } @@ -952,20 +849,6 @@ const void * lv_event_get_data(void) { return event_act_data; } - -/** - * Set the a signal function of an object. Used internally by the library. - * Always call the previous signal function in the new. - * @param obj pointer to an object - * @param cb the new signal function - */ -void lv_obj_set_signal_cb(lv_obj_t * obj, lv_signal_cb_t signal_cb) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->signal_cb = signal_cb; -} - /** * Send an event to the object * @param obj pointer to an object @@ -977,46 +860,15 @@ lv_res_t lv_signal_send(lv_obj_t * obj, lv_signal_t signal, void * param) if(obj == NULL) return LV_RES_OK; lv_res_t res = LV_RES_OK; - if(obj->signal_cb) res = obj->signal_cb(obj, signal, param); + if(obj->class_p->signal_cb) res = obj->class_p->signal_cb(obj, signal, param); return res; } -/** - * Set a new design function for an object - * @param obj pointer to an object - * @param design_cb the new design function - */ -void lv_obj_set_design_cb(lv_obj_t * obj, lv_design_cb_t design_cb) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - obj->design_cb = design_cb; -} - /*---------------- * Other set *--------------*/ -/** - * Allocate a new ext. data for an object - * @param obj pointer to an object - * @param ext_size the size of the new ext. data - * @return pointer to the allocated ext. - * If out of memory NULL is returned and the original ext is preserved - */ -void * lv_obj_allocate_ext_attr(lv_obj_t * obj, uint16_t ext_size) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - void * new_ext = lv_mem_realloc(obj->ext_attr, ext_size); - LV_ASSERT_MEM(new_ext); - if(new_ext == NULL) return NULL; - - obj->ext_attr = new_ext; - return (void *)obj->ext_attr; -} - /** * Allocate a new ext. data for an object * @param obj pointer to an object @@ -1028,7 +880,6 @@ lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - if(obj->spec_attr == NULL) { static uint32_t x = 0; x++; @@ -1037,7 +888,6 @@ lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj) if(obj->spec_attr == NULL) return NULL; _lv_memset_00(obj->spec_attr, sizeof(lv_obj_spec_attr_t)); - _lv_ll_init(&(obj->spec_attr->child_ll), sizeof(lv_obj_t)); obj->spec_attr->scroll_dir = LV_DIR_ALL; obj->spec_attr->base_dir = LV_BIDI_DIR_INHERIT; @@ -1047,8 +897,6 @@ lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj) return obj->spec_attr; } - - /*======================= * Getter functions *======================*/ @@ -1084,20 +932,18 @@ lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) const lv_obj_t * scr; - if(obj->parent == NULL) - scr = obj; /*`obj` is a screen*/ - else - scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/ + if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/ + else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/ lv_disp_t * d; _LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) { - lv_obj_t * s; - _LV_LL_READ(&d->scr_ll, s) { - if(s == scr) return d; + uint32_t i; + for(i = 0; i < d->screen_cnt; i++) { + if(d->screens[i] == scr) return d; } } - LV_LOG_WARN("lv_scr_get_disp: screen not found") + LV_LOG_WARN("No screen found") return NULL; } @@ -1117,55 +963,27 @@ lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) return obj->parent; } -/** - * Iterate through the children of an object (start from the "youngest") - * @param obj pointer to an object - * @param child NULL at first call to get the next children - * and the previous return value later - * @return the child after 'act_child' or NULL if no more child - */ -lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - if (child) return _lv_ll_get_next(ll, child); - else return _lv_ll_get_head(ll); -} - -/** - * Iterate through the children of an object (start from the "oldest") - * @param obj pointer to an object - * @param child NULL at first call to get the next children - * and the previous return value later - * @return the child after 'act_child' or NULL if no more child - */ -lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - if(child) return _lv_ll_get_prev(ll, child); - else return _lv_ll_get_tail(ll); -} - /** * Get the Nth child of an object. 0th is the lastly created. * @param obj pointer to an object whose children should be get * @param id of a child * @return the child or `NULL` if `id` was greater then the `number of children - 1` */ -lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, uint32_t id) +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, uint32_t id) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_t * child = lv_obj_get_child_back(obj, NULL); - uint32_t i; - for(i = 0; i < id; i++) { - child = lv_obj_get_child_back(obj, child); - } + if(obj->spec_attr == NULL) return NULL; - return child; + if(id >= obj->spec_attr->child_cnt) return NULL; + else return obj->spec_attr->children[id]; +} + +uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + if(obj->spec_attr == NULL) return 0; + return obj->spec_attr->child_cnt; } /** @@ -1182,33 +1000,12 @@ uint32_t lv_obj_get_child_id(const lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); if(parent == NULL) return 0; - uint32_t id = 0; - lv_obj_t * child; - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ_BACK(ll, child) { - if(child == obj) return id; - id++; + uint32_t i = 0; + for(i = 0; i < lv_obj_get_child_cnt(parent); i++) { + if(lv_obj_get_child(parent, i) == obj) return i; } - return id; -} -/** - * Count the children of an object (only children directly on 'obj') - * @param obj pointer to an object - * @return children number of 'obj' - */ -uint32_t lv_obj_count_children(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_t * i; - uint16_t cnt = 0; - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, i) cnt++; - - return cnt; + return 0xFFFFFFFF; } /** Recursively count the children of an object @@ -1219,13 +1016,12 @@ uint32_t lv_obj_count_children_recursive(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_t * i; uint16_t cnt = 0; - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, i) { - cnt++; /*Count the child*/ - cnt += lv_obj_count_children_recursive(i); /*recursively count children's children*/ + uint32_t i = 0; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + cnt++; + cnt += lv_obj_count_children_recursive(lv_obj_get_child(obj, i)); } return cnt; @@ -1303,7 +1099,7 @@ bool lv_obj_hit_test(lv_obj_t * obj, lv_point_t * point) lv_hit_test_info_t hit_info; hit_info.point = point; hit_info.result = true; - obj->signal_cb(obj, LV_SIGNAL_HIT_TEST, &hit_info); + lv_signal_send(obj, LV_SIGNAL_HIT_TEST, &hit_info); return hit_info.result; } else { @@ -1357,30 +1153,6 @@ lv_state_t lv_obj_get_state(const lv_obj_t * obj) return ((lv_obj_t *)obj)->state; } -/** - * Get the signal function of an object - * @param obj pointer to an object - * @return the signal function - */ -lv_signal_cb_t lv_obj_get_signal_cb(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->signal_cb; -} - -/** - * Get the design function of an object - * @param obj pointer to an object - * @return the design function - */ -lv_design_cb_t lv_obj_get_design_cb(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->design_cb; -} - /** * Get the event function of an object * @param obj pointer to an object @@ -1398,85 +1170,6 @@ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj) * Other get *-----------------*/ -/** - * Get the ext pointer - * @param obj pointer to an object - * @return the ext pointer but not the dynamic version - * Use it as ext->data1, and NOT da(ext)->data1 - */ -void * lv_obj_get_ext_attr(const lv_obj_t * obj) -{ - return obj->ext_attr; -} - -/** - * Get object's and its ancestors type. Put their name in `type_buf` starting with the current type. - * E.g. buf.type[0]="lv_btn", buf.type[1]="lv_cont", buf.type[2]="lv_obj" - * @param obj pointer to an object which type should be get - * @param buf pointer to an `lv_obj_type_t` buffer to store the types - */ -void lv_obj_get_type(const lv_obj_t * obj, lv_obj_type_t * buf) -{ - LV_ASSERT_NULL(buf); - LV_ASSERT_NULL(obj); - - lv_obj_type_t tmp; - - _lv_memset_00(buf, sizeof(lv_obj_type_t)); - _lv_memset_00(&tmp, sizeof(lv_obj_type_t)); - - obj->signal_cb((lv_obj_t *)obj, LV_SIGNAL_GET_TYPE, &tmp); - - uint8_t cnt; - for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) { - if(tmp.type[cnt] == NULL) break; - } - - /*Swap the order. The real type comes first*/ - uint8_t i; - for(i = 0; i < cnt; i++) { - buf->type[i] = tmp.type[cnt - 1 - i]; - } -} - -#if LV_USE_USER_DATA - -/** - * Get the object's user data - * @param obj pointer to an object - * @return user data - */ -lv_obj_user_data_t lv_obj_get_user_data(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - return obj->user_data; -} - -/** - * Get a pointer to the object's user data - * @param obj pointer to an object - * @return pointer to the user data - */ -lv_obj_user_data_t * lv_obj_get_user_data_ptr(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return &obj->user_data; -} - -/** - * Set the object's user data. The data will be copied. - * @param obj pointer to an object - * @param data user data - */ -void lv_obj_set_user_data(lv_obj_t * obj, lv_obj_user_data_t data) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - _lv_memcpy(&obj->user_data, &data, sizeof(lv_obj_user_data_t)); -} -#endif - /** * Get the group of the object * @param obj pointer to an object @@ -1516,29 +1209,11 @@ bool lv_obj_is_focused(const lv_obj_t * obj) #endif } -/** - * Tell if an object is an instance of a certain widget type or not - * @param obj pointer to an object - * @param type_str the type to check. The name of the widget's type, g.g. "lv_label", "lv_btn", etc - * @return true: `obj` has the given type - * @note Not only the "final" type matters. Therefore every widget has "lv_obj" type and "lv_slider" is an "lv_bar" too. - */ -bool lv_obj_is_instance_of(lv_obj_t * obj, const char * type_str) +lv_obj_t ** lv_obj_get_children(const lv_obj_t * obj) { - lv_obj_type_t type; - lv_obj_get_type(obj, &type); - uint8_t cnt; - for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) { - if(type.type[cnt] == NULL) break; - if(!strcmp(type.type[cnt], type_str)) return true; - } - return false; -} - -lv_ll_t * _lv_obj_get_child_ll(const lv_obj_t * obj) -{ - if(obj->spec_attr) return &obj->spec_attr->child_ll; - else return NULL; + static lv_obj_t * empty[1] = {NULL}; + if(obj->spec_attr) return obj->spec_attr->children; + else return empty; } /*------------------- @@ -1589,18 +1264,7 @@ lv_res_t _lv_obj_handle_get_type_signal(lv_obj_type_t * buf, const char * name) */ bool _lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type) { - if(obj_type[0] == '\0') return true; - - lv_obj_type_t types; - lv_obj_get_type((lv_obj_t *)obj, &types); - - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM; i++) { - if(types.type[i] == NULL) break; - if(strcmp(types.type[i], obj_type) == 0) return true; - } - - return false; + return true; } /** @@ -1613,11 +1277,10 @@ bool _lv_debug_check_obj_valid(const lv_obj_t * obj) { lv_disp_t * disp = lv_disp_get_next(NULL); while(disp) { - lv_obj_t * scr; - _LV_LL_READ(&disp->scr_ll, scr) { - - if(scr == obj) return true; - bool found = obj_valid_child(scr, obj); + uint32_t i; + for(i = 0; i < disp->screen_cnt; i++) { + if(disp->screens[i] == obj) return true; + bool found = obj_valid_child(disp->screens[i], obj); if(found) return true; } @@ -1664,15 +1327,9 @@ static void obj_del_core(lv_obj_t * obj) #endif /*Recursively delete the children*/ - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - lv_obj_t * i; - i = _lv_ll_get_head(ll); - while(i != NULL) { - /*Call the recursive delete to the child too*/ - obj_del_core(i); - - /*Set i to the new head node*/ - i = _lv_ll_get_head(ll); + while(1) { + lv_obj_t * child = lv_obj_get_child(obj, 0); + obj_del_core(child); } lv_event_mark_deleted(obj); @@ -1697,21 +1354,135 @@ static void obj_del_core(lv_obj_t * obj) /* All children deleted. * Now clean up the object specific data*/ - obj->signal_cb(obj, LV_SIGNAL_CLEANUP, NULL); + obj->class_p->destructor(obj); +} - /*Remove the object from parent's children list*/ - lv_obj_t * par = lv_obj_get_parent(obj); - if(par == NULL) { /*It is a screen*/ - lv_disp_t * d = lv_obj_get_disp(obj); - _lv_ll_remove(&d->scr_ll, obj); +static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) +{ + LV_CLASS_CONSTRUCTOR_BEGIN(obj, lv_obj) + lv_obj.base_p->constructor(obj); + + /*Create a screen*/ + if(parent == NULL) { + LV_LOG_TRACE("Screen create started"); + lv_disp_t * disp = lv_disp_get_default(); + if(!disp) { + LV_LOG_WARN("No display created to so far. No place to assign the new screen"); + return; + } + + if(disp->screens == NULL) { + disp->screens = lv_mem_alloc(sizeof(lv_obj_t *)); + disp->screens[0] = obj; + disp->screen_cnt = 1; + } else { + disp->screen_cnt++; + disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt); + disp->screens[disp->screen_cnt - 1] = obj; + } + + /*Set coordinates to full screen size*/ + obj->coords.x1 = 0; + obj->coords.y1 = 0; + obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1; + obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1; } + /*Create a normal object*/ else { - _lv_ll_remove(_lv_obj_get_child_ll(par), obj); + LV_LOG_TRACE("Object create started"); + LV_ASSERT_OBJ(parent, LV_OBJX_NAME); + if(parent->spec_attr == NULL) { + parent->spec_attr = lv_obj_allocate_spec_attr(parent); + } + + if(parent->spec_attr->children == NULL) { + parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *) * 2); + parent->spec_attr->children[0] = obj; + parent->spec_attr->child_cnt = 1; + } else { + parent->spec_attr->child_cnt++; + parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, sizeof(lv_obj_t *) * parent->spec_attr->child_cnt); + parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj; + } + + obj->parent = parent; + + obj->coords.y1 = parent->coords.y1; + obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT; + if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL) { + obj->coords.x2 = parent->coords.x2; + obj->coords.x1 = parent->coords.x2 - LV_OBJ_DEF_WIDTH; + } + else { + obj->coords.x1 = parent->coords.x1; + obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; + } + obj->w_set = lv_area_get_width(&obj->coords); + obj->h_set = lv_area_get_height(&obj->coords); } - /*Delete the base objects*/ - if(obj->ext_attr != NULL) lv_mem_free(obj->ext_attr); - lv_mem_free(obj); /*Free the object itself*/ + /*Set attributes*/ + obj->flags = LV_OBJ_FLAG_CLICKABLE; + obj->flags |= LV_OBJ_FLAG_SNAPABLE; + if(parent) obj->flags |= LV_OBJ_FLAG_PRESS_LOCK; + if(parent) obj->flags |= LV_OBJ_FLAG_SCROLL_CHAIN; + obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE; + obj->flags |= LV_OBJ_FLAG_SCROLLABLE; + obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC; + obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM; + obj->flags |= LV_OBJ_FLAG_FOCUS_SCROLL; + if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE; + obj->state = LV_STATE_DEFAULT; + + lv_style_list_init(&obj->style_list); + + /*Copy the attributes if required*/ + if(copy != NULL) { + lv_area_copy(&obj->coords, ©->coords); + + obj->flags = copy->flags; + if(copy->spec_attr) { + lv_obj_allocate_spec_attr(obj); + _lv_memcpy_small(obj->spec_attr, copy->spec_attr, sizeof(lv_obj_spec_attr_t)); + obj->spec_attr->children = NULL; /*Make the child list empty*/ + } +#if LV_USE_GROUP + /*Add to the same group*/ + if(copy->spec_attr && copy->spec_attr->group_p) { + obj->spec_attr->group_p = NULL; /*It was simply copied */ + lv_group_add_obj(copy->spec_attr->group_p, obj); + } +#endif + + /*Set the same coordinates for non screen objects*/ + if(lv_obj_get_parent(copy) != NULL && parent != NULL) { + lv_obj_set_pos(obj, lv_obj_get_x(copy), lv_obj_get_y(copy)); + lv_obj_set_size(obj, lv_obj_get_width(copy), lv_obj_get_height(copy)); + + } + } else { + lv_obj_set_pos(obj, 0, 0); + } + /*Send a signal to the parent to notify it about the new child*/ + if(parent != NULL) { + lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); + + /*Invalidate the area if not screen created*/ + lv_obj_invalidate(obj); + } + + LV_CLASS_CONSTRUCTOR_END(obj, lv_obj) + + LV_LOG_INFO("Object create ready"); +} + +static void lv_obj_destructor(void * p) +{ + lv_obj_t * obj = p; + _lv_obj_reset_style_list_no_refr(obj, LV_OBJ_PART_MAIN); + if(obj->spec_attr) lv_mem_free(obj->spec_attr); + + lv_class_destroy(obj); } /** @@ -1859,8 +1630,9 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area static void base_dir_refr_children(lv_obj_t * obj) { - lv_obj_t * child; - _LV_LL_READ(_lv_obj_get_child_ll(obj), child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); if(lv_obj_get_base_dir(child) == LV_BIDI_DIR_INHERIT) { lv_signal_send(child, LV_SIGNAL_BASE_DIR_CHG, NULL); base_dir_refr_children(child); @@ -1885,9 +1657,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) else info->result = NULL; return LV_RES_OK; } - else if(sign == LV_SIGNAL_GET_TYPE) { - return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - } else if(sign == LV_SIGNAL_PRESSED) { lv_obj_add_state(obj, LV_STATE_PRESSED); } @@ -1977,11 +1746,11 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } if(w_new || h_new) { - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - lv_obj_t * child; - _LV_LL_READ(ll, child) { + uint32_t i = 0; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); if((LV_COORD_IS_PCT(child->w_set) && w_new) || - (LV_COORD_IS_PCT(child->h_set) && h_new)) + (LV_COORD_IS_PCT(child->h_set) && h_new)) { lv_obj_set_size(child, child->w_set, child->h_set); } @@ -2021,10 +1790,9 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) if(lv_obj_get_flex_dir(obj)) _lv_flex_refresh(obj); /*Reposition non grid objects on by one*/ - lv_obj_t * child; - - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); if(LV_COORD_IS_PX(child->x_set) || LV_COORD_IS_PX(child->y_set)) { lv_obj_set_pos(child, child->x_set, child->y_set); } @@ -2035,10 +1803,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } _lv_obj_refresh_ext_draw_pad(obj); } - else if(sign == LV_SIGNAL_CLEANUP) { - _lv_obj_reset_style_list_no_refr(obj, LV_OBJ_PART_MAIN); - } - return res; } @@ -2056,9 +1820,9 @@ static void lv_event_mark_deleted(lv_obj_t * obj) static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find) { /*Check all children of `parent`*/ - lv_obj_t * child; - lv_ll_t * ll = _lv_obj_get_child_ll(parent); - _LV_LL_READ(ll, child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(parent); i++) { + lv_obj_t * child = lv_obj_get_child(parent, i); if(child == obj_to_find) return true; /*Check the children*/ diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index be8c1badb..c70bc13ac 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -24,6 +24,7 @@ extern "C" { #include "../lv_misc/lv_area.h" #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_debug.h" +#include "../lv_misc/lv_class.h" #include "../lv_hal/lv_hal.h" #include "../lv_draw/lv_draw_rect.h" #include "../lv_draw/lv_draw_label.h" @@ -120,13 +121,11 @@ typedef void (*lv_event_cb_t)(struct _lv_obj_t * obj, lv_event_t event); * on the object. */ enum { /*General signals*/ - LV_SIGNAL_CLEANUP, /**< Object is being deleted */ 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, /**< The base dir has changed*/ LV_SIGNAL_REFR_EXT_DRAW_PAD, /**< Object's extra padding has changed */ - LV_SIGNAL_GET_TYPE, /**< LVGL needs to retrieve the object's type */ LV_SIGNAL_GET_STYLE, /**< Get the style of an object*/ LV_SIGNAL_GET_SELF_SIZE, /**< Get the internal size of a widget*/ @@ -176,7 +175,7 @@ enum { LV_OBJ_FLAG_SCROLL_ELASTIC = (1 << 5), LV_OBJ_FLAG_SCROLL_MOMENTUM = (1 << 6), LV_OBJ_FLAG_SCROLL_STOP = (1 << 7), - LV_OBJ_FLAG_SCROLL_FREEZE = (1 << 8), /** Do not allow scrolling on this object and do not propagate the scroll to parent */ + LV_OBJ_FLAG_SCROLL_CHAIN = (1 << 8), /** Allow propagating the scroll to a parent */ LV_OBJ_FLAG_SNAPABLE = (1 << 9), LV_OBJ_FLAG_PRESS_LOCK = (1 << 10), LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 11), @@ -195,8 +194,8 @@ typedef uint16_t lv_obj_flag_t; typedef struct { - lv_ll_t child_ll; /**< Linked list to store the children objects*/ - + lv_obj_t ** children; /**< Store the pointer of the children.*/ + uint32_t child_cnt; #if LV_USE_GROUP != 0 void * group_p; #endif @@ -223,32 +222,30 @@ typedef struct { }lv_obj_spec_attr_t; -struct _lv_obj_t { - lv_obj_spec_attr_t * spec_attr; - struct _lv_obj_t * parent; /**< Pointer to the parent object*/ +LV_CLASS_DECLARE_START(lv_obj, lv_base) +#define _lv_obj_constructor void (*constructor)(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy) - lv_signal_cb_t signal_cb; /**< Object type specific signal function*/ - lv_design_cb_t design_cb; /**< Object type specific design function*/ +#define _lv_obj_data \ + _lv_base_data \ + struct _lv_obj_t * parent; \ + lv_obj_spec_attr_t * spec_attr; \ + lv_style_list_t style_list; \ + lv_area_t coords; \ + lv_coord_t x_set; \ + lv_coord_t y_set; \ + lv_coord_t w_set; \ + lv_coord_t h_set; \ + lv_obj_flag_t flags; \ + lv_state_t state; - void * ext_attr; /**< Object type specific extended data*/ +#define _lv_obj_class_dsc \ + _lv_base_class_dsc \ + lv_signal_cb_t signal_cb; /**< Object type specific signal function*/ \ + lv_design_cb_t design_cb; /**< Object type specific design function*/ -#if LV_USE_USER_DATA - lv_obj_user_data_t user_data; /**< Custom user data for object. */ -#endif - - lv_style_list_t style_list; - - /*Attributes and states*/ - lv_obj_flag_t flags; - lv_state_t state; - - lv_area_t coords; /**< Coordinates of the object (x1, y1, x2, y2)*/ - lv_coord_t x_set; - lv_coord_t y_set; - lv_coord_t w_set; - lv_coord_t h_set; -}; +LV_CLASS_DECLARE_END(lv_obj, lv_base) +extern lv_obj_class_t lv_obj; enum { LV_OBJ_PART_MAIN, @@ -573,31 +570,15 @@ lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj); */ lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj); -/** - * Iterate through the children of an object (start from the "youngest, lastly created") - * @param obj pointer to an object - * @param child NULL at first call to get the next children - * and the previous return value later - * @return the child after 'act_child' or NULL if no more child - */ -lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child); - -/** - * Iterate through the children of an object (start from the "oldest", firstly created) - * @param obj pointer to an object - * @param child NULL at first call to get the next children - * and the previous return value later - * @return the child after 'act_child' or NULL if no more child - */ -lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child); - /** * Get the Nth child of a an object. 0th is the lastly created. * @param obj pointer to an object whose children should be get * @param id of a child * @return the child or `NULL` if `id` was greater then the `number of children - 1` */ -lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * obj, uint32_t id); +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, uint32_t id); + +uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj); /** * Get the child index of an object. @@ -748,16 +729,7 @@ void * lv_obj_get_group(const lv_obj_t * obj); */ bool lv_obj_is_focused(const lv_obj_t * obj); -/** - * Tell if an object is an instance of a certain widget type or not - * @param obj pointer to an object - * @param type_str the type to check. The name of the widget's type, g.g. "lv_label", "lv_btn", etc - * @return true: `obj` has the given type - * @note Not only the "final" type matters. Therefore every widget has "lv_obj" type and "lv_slider" is an "lv_bar" too. - */ -bool lv_obj_is_instance_of(lv_obj_t * obj, const char * type_str); - -lv_ll_t * _lv_obj_get_child_ll(const lv_obj_t * obj) ; +lv_obj_t ** lv_obj_get_children(const lv_obj_t * obj); /** * Get the really focused object by taking `focus_parent` into account. @@ -770,15 +742,6 @@ lv_obj_t * _lv_obj_get_focused_obj(const lv_obj_t * obj); * OTHER FUNCTIONS *------------------*/ -/** - * Used in the signal callback to handle `LV_SIGNAL_GET_TYPE` signal - * @param buf pointer to `lv_obj_type_t`. (`param` in the signal callback) - * @param name name of the object. E.g. "lv_btn". (Only the pointer is saved) - * @return LV_RES_OK - */ -lv_res_t _lv_obj_handle_get_type_signal(lv_obj_type_t * buf, const char * name); - - /** * Check if any object has a given type * @param obj pointer to an object diff --git a/src/lv_core/lv_obj_draw.c b/src/lv_core/lv_obj_draw.c index b43920889..40fd6dd90 100644 --- a/src/lv_core/lv_obj_draw.c +++ b/src/lv_core/lv_obj_draw.c @@ -386,7 +386,7 @@ void _lv_obj_refresh_ext_draw_pad(lv_obj_t * obj) LV_ASSERT_OBJ(obj, LV_OBJX_NAME); lv_coord_t s = 0; - obj->signal_cb(obj, LV_SIGNAL_REFR_EXT_DRAW_PAD, &s); + lv_signal_send(obj, LV_SIGNAL_REFR_EXT_DRAW_PAD, &s); /*Store the result if the special attrs already allocated*/ if(obj->spec_attr) { diff --git a/src/lv_core/lv_obj_pos.c b/src/lv_core/lv_obj_pos.c index 66599531a..51b89921a 100644 --- a/src/lv_core/lv_obj_pos.c +++ b/src/lv_core/lv_obj_pos.c @@ -660,10 +660,10 @@ void _lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, bool notify_par _lv_obj_move_children_by(obj, diff.x, diff.y); /*Inform the object about its new coordinates*/ - obj->signal_cb(obj, LV_SIGNAL_COORD_CHG, &ori); + lv_signal_send(obj, LV_SIGNAL_COORD_CHG, &ori); /*Send a signal to the parent too*/ - if(parent && notify_parent) parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); + if(parent && notify_parent) lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); /*Invalidate the new area*/ lv_obj_invalidate(obj); @@ -678,15 +678,15 @@ void _lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, bool notify_par */ void _lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff) { - lv_obj_t * i; - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, i) { - i->coords.x1 += x_diff; - i->coords.y1 += y_diff; - i->coords.x2 += x_diff; - i->coords.y2 += y_diff; + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + child->coords.x1 += x_diff; + child->coords.y1 += y_diff; + child->coords.x2 += x_diff; + child->coords.y2 += y_diff; - _lv_obj_move_children_by(i, x_diff, y_diff); + _lv_obj_move_children_by(child, x_diff, y_diff); } } @@ -770,11 +770,11 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) } /*Send a signal to the object with its new coordinates*/ - obj->signal_cb(obj, LV_SIGNAL_COORD_CHG, &ori); + lv_signal_send(obj, LV_SIGNAL_COORD_CHG, &ori); /*Send a signal to the parent too*/ lv_obj_t * par = lv_obj_get_parent(obj); - if(par != NULL) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); + if(par != NULL) lv_signal_send(par, LV_SIGNAL_CHILD_CHG, obj); /*Invalidate the new area*/ lv_obj_invalidate(obj); diff --git a/src/lv_core/lv_obj_scroll.c b/src/lv_core/lv_obj_scroll.c index 1244cb498..f3b7b71f5 100644 --- a/src/lv_core/lv_obj_scroll.c +++ b/src/lv_core/lv_obj_scroll.c @@ -127,19 +127,12 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) LV_ASSERT_OBJ(obj, LV_OBJX_NAME); lv_coord_t child_res = LV_COORD_MIN; - - lv_obj_t * child = lv_obj_get_child(obj, NULL); - 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); - } - - child_res = y2; + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + child_res = LV_MATH_MAX(child_res, child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN)); } - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN); lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); @@ -167,15 +160,17 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN); lv_coord_t child_res = 0; - lv_obj_t * child = lv_obj_get_child(obj, NULL); - if(child) { - lv_coord_t x1 = LV_COORD_MAX; - while(child) { - x1 = LV_MATH_MIN(x1, child->coords.x1 - lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN)); - child = lv_obj_get_child(obj, child); - } - child_res = x1; + uint32_t i; + lv_coord_t x1 = LV_COORD_MAX; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + x1 = LV_MATH_MIN(x1, child->coords.x1 - lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN)); + + } + + if(x1 != LV_COORD_MAX) { + child_res = x1; child_res = (obj->coords.x1 + pad_left) - child_res; } @@ -199,15 +194,10 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) /*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/ lv_coord_t child_res = LV_COORD_MIN; - lv_obj_t * child = lv_obj_get_child(obj, NULL); - 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; - + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + child_res = LV_MATH_MAX(child_res, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN)); } lv_coord_t pad_right = 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 bbe19152c..643c6f1db 100644 --- a/src/lv_core/lv_obj_style.c +++ b/src/lv_core/lv_obj_style.c @@ -190,9 +190,9 @@ void lv_obj_report_style_change(lv_style_t * style) lv_disp_t * d = lv_disp_get_next(NULL); while(d) { - lv_obj_t * i; - _LV_LL_READ(&d->scr_ll, i) { - report_style_change_core(style, i); + uint32_t i; + for(i = 0; i < d->screen_cnt; i++) { + report_style_change_core(style, d->screens[i]); } d = lv_disp_get_next(d); } @@ -318,10 +318,10 @@ void _lv_obj_invalidate_style_cache(lv_obj_t * obj, uint8_t part, lv_style_prope list->valid_cache = 0; } - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); update_style_cache_children(child); - child = lv_obj_get_child(obj, child); } } #endif /*LV_STYLE_CACHE_LEVEL >= 1*/ @@ -871,7 +871,7 @@ void _lv_obj_refresh_style(lv_obj_t * obj, uint8_t part, lv_style_property_t pro if(real_refr) { lv_obj_invalidate(obj); - obj->signal_cb(obj, LV_SIGNAL_STYLE_CHG, NULL); + lv_signal_send(obj, LV_SIGNAL_STYLE_CHG, NULL); switch(prop) { case LV_STYLE_PROP_ALL: @@ -879,7 +879,7 @@ void _lv_obj_refresh_style(lv_obj_t * obj, uint8_t part, lv_style_property_t pro case LV_STYLE_MARGIN_BOTTOM: case LV_STYLE_MARGIN_LEFT: case LV_STYLE_MARGIN_RIGHT: - if(obj->parent) obj->parent->signal_cb(obj->parent, LV_SIGNAL_CHILD_CHG, obj); + if(obj->parent) lv_signal_send(obj->parent, LV_SIGNAL_CHILD_CHG, obj); break; } @@ -1099,12 +1099,11 @@ static void report_style_change_core(void * style, lv_obj_t * obj) } } - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); report_style_change_core(style, child); - child = lv_obj_get_child(obj, child); } - } /** @@ -1114,14 +1113,14 @@ static void report_style_change_core(void * style, lv_obj_t * obj) */ static void refresh_children_style(lv_obj_t * obj) { - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child != NULL) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); lv_obj_invalidate(child); - child->signal_cb(child, LV_SIGNAL_STYLE_CHG, NULL); + lv_signal_send(child, LV_SIGNAL_STYLE_CHG, NULL); lv_obj_invalidate(child); refresh_children_style(child); /*Check children too*/ - child = lv_obj_get_child(obj, child); } } @@ -1514,10 +1513,10 @@ static void update_style_cache_children(lv_obj_t * obj) list->ignore_cache = ignore_cache_ori; } - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); update_style_cache_children(child); - child = lv_obj_get_child(obj, child); } } diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index dc4a3558c..c60256d33 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -594,7 +594,7 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) /*If this object is fully cover the draw area check the children too */ if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) { - lv_design_res_t design_res = obj->design_cb(obj, area_p, LV_DESIGN_COVER_CHK); + lv_design_res_t design_res = obj->class_p->design_cb(obj, area_p, LV_DESIGN_COVER_CHK); if(design_res == LV_DESIGN_RES_MASKED) return NULL; #if LV_USE_OPA_SCALE @@ -603,10 +603,10 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) } #endif - lv_obj_t * i; - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ(ll, i) { - found_p = lv_refr_get_top_obj(area_p, i); + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + found_p = lv_refr_get_top_obj(area_p, child); /*If a children is ok then break*/ if(found_p != NULL) { @@ -649,20 +649,22 @@ static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p) /*Do until not reach the screen*/ while(par != NULL) { - lv_ll_t * ll = _lv_obj_get_child_ll(par); - /*object before border_p has to be redrawn*/ - lv_obj_t * i = _lv_ll_get_prev(ll, border_p); - - while(i != NULL) { - /*Refresh the objects*/ - lv_refr_obj(i, mask_p); - i = _lv_ll_get_prev(ll, i); + bool go = false; + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(par); i++) { + lv_obj_t * child = lv_obj_get_child(par, i); + if(!go) { + if(child == border_p) go = true; + } else { + /*Refresh the objects*/ + lv_refr_obj(child, mask_p); + } } /*Call the post draw design function of the parents of the to object*/ - if(par->design_cb) par->design_cb(par, mask_p, LV_DESIGN_DRAW_POST); + par->class_p->design_cb(par, mask_p, LV_DESIGN_DRAW_POST); - /*The new border will be there last parents, + /*The new border will be the last parents, *so the 'younger' brothers of parent will be refreshed*/ border_p = par; /*Go a level deeper*/ @@ -696,9 +698,8 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) /*Draw the parent and its children only if they ore on 'mask_parent'*/ if(union_ok != false) { - /* Redraw the object */ - if(obj->design_cb) obj->design_cb(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN); + obj->class_p->design_cb(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN); #if MASK_AREA_DEBUG static lv_color_t debug_color = LV_COLOR_RED; @@ -722,12 +723,12 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) union_ok = _lv_area_intersect(&obj_mask, mask_ori_p, &obj_area); if(union_ok != false) { lv_area_t mask_child; /*Mask from obj and its child*/ - lv_obj_t * child_p; lv_area_t child_area; - lv_ll_t * ll = _lv_obj_get_child_ll(obj); - _LV_LL_READ_BACK(ll, child_p) { - lv_obj_get_coords(child_p, &child_area); - ext_size = _lv_obj_get_ext_draw_pad(child_p); + uint32_t i; + for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + lv_obj_get_coords(child, &child_area); + ext_size = _lv_obj_get_ext_draw_pad(child); child_area.x1 -= ext_size; child_area.y1 -= ext_size; child_area.x2 += ext_size; @@ -739,13 +740,13 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) /*If the parent and the child has common area then refresh the child */ if(union_ok) { /*Refresh the next children*/ - lv_refr_obj(child_p, &mask_child); + lv_refr_obj(child, &mask_child); } } } /* If all the children are redrawn make 'post draw' design */ - if(obj->design_cb) obj->design_cb(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST); + obj->class_p->design_cb(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST); } } diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index 9ff730f0a..93e289a09 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -128,7 +128,6 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) _lv_memset_00(disp, sizeof(lv_disp_t)); _lv_memcpy(&disp->driver, driver, sizeof(lv_disp_drv_t)); - _lv_ll_init(&disp->scr_ll, sizeof(lv_obj_t)); disp->last_activity_time = 0; if(disp_def == NULL) disp_def = disp; @@ -187,9 +186,9 @@ void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv) { memcpy(&disp->driver, new_drv, sizeof(lv_disp_drv_t)); - lv_obj_t * scr; - _LV_LL_READ(&disp->scr_ll, scr) { - lv_obj_set_size(scr, lv_disp_get_hor_res(disp), lv_disp_get_ver_res(disp)); + uint32_t i; + for(i = 0; disp->screens[i]; i++) { + lv_obj_set_size(disp->screens[i], lv_disp_get_hor_res(disp), lv_disp_get_ver_res(disp)); } } diff --git a/src/lv_hal/lv_hal_disp.h b/src/lv_hal/lv_hal_disp.h index 12144a972..62854d727 100644 --- a/src/lv_hal/lv_hal_disp.h +++ b/src/lv_hal/lv_hal_disp.h @@ -152,12 +152,12 @@ typedef struct _disp_t { lv_timer_t * refr_task; /** Screens of the display*/ - lv_ll_t scr_ll; + struct _lv_obj_t ** screens; /**< Array of screen objects. `NULL` terminated*/ struct _lv_obj_t * act_scr; /**< Currently active screen on this display */ struct _lv_obj_t * prev_scr; /**< Previous screen. Used during screen animations */ struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top */ struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys */ - + uint32_t screen_cnt; uint8_t del_prev : 1; /**< 1: Automatically delete the previous screen when the screen load animation is ready */ diff --git a/src/lv_misc/lv_class.c b/src/lv_misc/lv_class.c index 0befbefc8..e72d21814 100644 --- a/src/lv_misc/lv_class.c +++ b/src/lv_misc/lv_class.c @@ -20,7 +20,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static void lv_class_base_construct(void * inst); /********************** * STATIC VARIABLES @@ -45,60 +44,43 @@ void _lv_class_init(void * class_p, uint32_t class_size, uint32_t instance_size, if(bc) _lv_memcpy(c, base_p, bc->_class_size); c->base_p = base_p; /*Save the base to allow accessing its methods later*/ - c->constructor_cb = lv_class_base_construct; + c->constructor = NULL; c->_instance_size = instance_size; c->_class_size = class_size; c->_inited = 1; } -void * _lv_class_new(void * class_p) +void * lv_class_new(void * class_p) { lv_base_class_t * base_class_p = class_p; lv_base_t * instance = lv_mem_alloc(base_class_p->_instance_size); _lv_memset_00(instance, base_class_p->_instance_size); instance->class_p = class_p; - - /*Call the constructor of base classes and this class*/ - lv_class_construct(instance, class_p); - instance->_dynamic = 1; +// instance->_dynamic = 1; return instance; } -void * _lv_class_new_static(void * class_p, void * instance) + +void lv_class_destroy(void * instance) { - lv_base_class_t * base_class_p = class_p; - lv_base_t * base_inst = instance; - _lv_memset_00(base_inst, base_class_p->_instance_size); - base_inst->class_p = class_p; - - /*Call the constructor of base classes and this class*/ - lv_class_construct(instance, class_p); - base_inst->_dynamic = 0; - return instance; + lv_mem_free(instance); } -/** - * Recursively call all constructor of base(s). Starting from the the oldest. - * @param inst pointer to an instance - * @param dsc pointer to the class dsc whose constructor should be called - */ -void lv_class_construct(void * inst, lv_base_class_t * dsc) -{ - if(dsc->base_p) lv_class_construct(inst, dsc->base_p); - - if(dsc->constructor_cb) dsc->constructor_cb(inst); -} - - /********************** * STATIC FUNCTIONS **********************/ +//static void desctructor_chain(void * inst) +//{ +// lv_base_t * base_inst = inst; +// if(base->) +//} + /** * Constructor of the base class. Just zero out the instance * @param inst pointer to an instance */ -static void lv_class_base_construct(void * inst) +void lv_class_base_construct(void * inst) { lv_base_t * base_inst = inst; void * class_p = base_inst->class_p; diff --git a/src/lv_misc/lv_class.h b/src/lv_misc/lv_class.h index 3b1d63f3a..b1d874285 100644 --- a/src/lv_misc/lv_class.h +++ b/src/lv_misc/lv_class.h @@ -10,6 +10,32 @@ extern "C" { #endif + +/* EXAMPLE CLASS DECLARATION + +LV_CLASS_DECLARE_START(person, lv_base) + +#define _person_create struct _person_t * (*create)(struct _person_t * father, struct _person_t * mother) +#define _person_create_static struct _person_t * (*create_static)(struct _person_t * p, struct _person_t * father, struct _person_t * mother) + +#define _person_data \ + _lv_base_data \ + bool male; \ + char name[64]; \ + uint32_t age; \ + struct _person_t * mother; \ + struct _person_t * father; \ + +#define _person_class_dsc \ + _lv_base_class_dsc \ + uint32_t max_age; \ + void (*set_name)(struct _person_t * p, const char * name); + +LV_CLASS_DECLARE_END(person, lv_base) + + */ + + /********************* * INCLUDES *********************/ @@ -18,27 +44,22 @@ extern "C" { /********************* * DEFINES *********************/ -#define LV_CLASS_MIXIN_EMPTY - #define _lv_base_class_dsc \ - void(*constructor_cb)(void * inst); \ - void(*descructor_cb)(void * inst); \ + void(*destructor)(void * inst); \ uint32_t _instance_size; \ uint32_t _class_size; \ uint32_t _inited :1; -#define _lv_base_data \ - uint32_t _dynamic :1; +#define _lv_base_data /********************** * TYPEDEFS **********************/ -/*Just to have a type that can be referenced later*/ + typedef struct _lv_base_class_t { struct _lv_base_class_t * base_p; - void * (*create)(void); - void (*create_static)(void *); + void (*constructor)(void *); _lv_base_class_dsc }lv_base_class_t; @@ -65,8 +86,9 @@ void _lv_class_init(void * class_p, uint32_t class_size, uint32_t instance_size, * @param class pointer to a class to create * @return the created instance */ -void * _lv_class_new(void * class_p); - +void * lv_class_new(void * class_p); +void lv_class_base_construct(void * inst); +void lv_class_destroy(void * instance); void lv_class_construct(void * inst, lv_base_class_t * dsc); @@ -89,16 +111,32 @@ struct _##classname##_class_t; \ #define LV_CLASS_DECLARE_END(classname, basename) \ typedef struct _##classname##_class_t { \ basename##_class_t * base_p; \ - _##classname##_create; \ - _##classname##_create_static; \ - _##classname##_class_dsc \ + _##classname##_constructor; \ + _##classname##_class_dsc \ }classname##_class_t; \ \ typedef struct _##classname##_t { \ classname##_class_t * class_p; \ - _##classname##_data \ + _##classname##_data \ } classname##_t; + +/** + * Start the constructor + * Makes the instance look like to instance of the class where the constructor is called. + * It's important because the virtual functions should be called from the level of the constructor. + */ +#define LV_CLASS_CONSTRUCTOR_BEGIN(inst, classname) \ + void * _original_class_p = ((lv_base_t*)inst)->class_p; \ + obj->class_p = (void*)&classname; + +/** + * Finish the constructor. + * It reverts the original base class (changed by LV_CLASS_CONSTRUCTOR_BEGIN). + */ +#define LV_CLASS_CONSTRUCTOR_END(inst, classname) \ + ((lv_base_t*)inst)->class_p = _original_class_p; + /** * Initialize a class. Need to be called only once for every class */ diff --git a/src/lv_misc/lv_mem.c b/src/lv_misc/lv_mem.c index 597b6aebd..0c8666ba0 100644 --- a/src/lv_misc/lv_mem.c +++ b/src/lv_misc/lv_mem.c @@ -161,10 +161,7 @@ void * lv_mem_alloc(size_t size) return &zero_mem; } -// last_ent = NULL; - static uint32_t c = 0; - c++; -// if(c%10 == 0) printf("alloc:%d\n", c); + printf("alloc:%d\n", size); #ifdef LV_ARCH_64 /*Round the size up to 8*/ diff --git a/src/lv_widgets/lv_bar.c b/src/lv_widgets/lv_bar.c index c540e8d6d..04fe72311 100644 --- a/src/lv_widgets/lv_bar.c +++ b/src/lv_widgets/lv_bar.c @@ -38,16 +38,18 @@ /********************** * STATIC PROTOTYPES **********************/ +static void lv_bar_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy); +static void lv_bar_destructor(void * obj); static lv_design_res_t lv_bar_design(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param); -static lv_style_list_t * lv_bar_get_style(lv_obj_t * bar, uint8_t part); +static lv_style_list_t * lv_bar_get_style(lv_bar_t * bar, uint8_t part); static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area); #if LV_USE_ANIMATION -static void lv_bar_set_value_with_anim(lv_obj_t * bar, int16_t new_value, int16_t * value_ptr, +static void lv_bar_set_value_with_anim(lv_bar_t * bar, int16_t new_value, int16_t * value_ptr, lv_bar_anim_t * anim_info, lv_anim_enable_t en); -static void lv_bar_init_anim(lv_obj_t * bar, lv_bar_anim_t * bar_anim); +static void lv_bar_init_anim(lv_bar_t * bar, lv_bar_anim_t * bar_anim); static void lv_bar_anim(lv_bar_anim_t * bar, lv_anim_value_t value); static void lv_bar_anim_ready(lv_anim_t * a); #endif @@ -55,8 +57,7 @@ static void lv_bar_anim_ready(lv_anim_t * a); /********************** * STATIC VARIABLES **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; +lv_bar_class_t lv_bar; /********************** * MACROS @@ -75,65 +76,26 @@ static lv_signal_cb_t ancestor_signal; */ lv_obj_t * lv_bar_create(lv_obj_t * parent, const lv_obj_t * copy) { - LV_LOG_TRACE("lv_bar create started"); - - /*Create the ancestor basic object*/ - lv_obj_t * bar = lv_obj_create(parent, copy); - LV_ASSERT_MEM(bar); - if(bar == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(bar); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(bar); - - /*Allocate the object type specific extended data*/ - lv_bar_ext_t * ext = lv_obj_allocate_ext_attr(bar, sizeof(lv_bar_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(bar); - return NULL; + if(!lv_bar._inited) { + LV_CLASS_INIT(lv_bar, lv_obj); + lv_bar.constructor = lv_bar_constructor; + lv_bar.destructor = lv_bar_destructor; + lv_bar.design_cb = lv_bar_design; + lv_bar.signal_cb = lv_bar_signal; } - ext->min_value = 0; - ext->start_value = 0; - ext->max_value = 100; - ext->cur_value = 0; -#if LV_USE_ANIMATION - ext->anim_time = 200; - lv_bar_init_anim(bar, &ext->cur_value_anim); - lv_bar_init_anim(bar, &ext->start_value_anim); -#endif - ext->type = LV_BAR_TYPE_NORMAL; + lv_obj_t * obj = lv_class_new(&lv_bar); + lv_bar.constructor(obj, parent, copy); - lv_style_list_init(&ext->style_indic); - - lv_obj_set_signal_cb(bar, lv_bar_signal); - lv_obj_set_design_cb(bar, lv_bar_design); - - if(copy == NULL) { - lv_obj_clear_flag(bar, LV_OBJ_FLAG_CHECKABLE); - lv_obj_clear_flag(bar, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_set_size(bar, LV_DPI * 2, LV_DPI / 10); - lv_bar_set_value(bar, ext->cur_value, false); - - lv_theme_apply(bar, LV_THEME_BAR); - } else { - lv_bar_ext_t * ext_copy = lv_obj_get_ext_attr(copy); - ext->min_value = ext_copy->min_value; - ext->start_value = ext_copy->start_value; - ext->max_value = ext_copy->max_value; - ext->cur_value = ext_copy->cur_value; - ext->type = ext_copy->type; - - lv_style_list_copy(&ext->style_indic, &ext_copy->style_indic); - - /*Refresh the style with new signal function*/ - _lv_obj_refresh_style(bar, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - - lv_bar_set_value(bar, ext->cur_value, LV_ANIM_OFF); + lv_bar_t * bar = (lv_bar_t *) obj; + const lv_bar_t * bar_copy = (const lv_bar_t *) copy; + if(!copy) lv_theme_apply(obj, LV_THEME_BAR); + else { + lv_style_list_copy(&bar->style_indic, &bar_copy->style_indic); + _lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); } - LV_LOG_INFO("bar created"); - return bar; + return obj; } /*===================== @@ -146,26 +108,26 @@ lv_obj_t * lv_bar_create(lv_obj_t * parent, const lv_obj_t * copy) * @param value new value * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ -void lv_bar_set_value(lv_obj_t * bar, int16_t value, lv_anim_enable_t anim) +void lv_bar_set_value(lv_obj_t * obj, int16_t value, lv_anim_enable_t anim) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - if(ext->cur_value == value) return; + if(bar->cur_value == value) return; int16_t new_value = value; - new_value = value > ext->max_value ? ext->max_value : new_value; - new_value = new_value < ext->min_value ? ext->min_value : new_value; - new_value = new_value < ext->start_value ? ext->start_value : new_value; + new_value = value > bar->max_value ? bar->max_value : new_value; + new_value = new_value < bar->min_value ? bar->min_value : new_value; + new_value = new_value < bar->start_value ? bar->start_value : new_value; - if(ext->cur_value == new_value) return; + if(bar->cur_value == new_value) return; #if LV_USE_ANIMATION == 0 LV_UNUSED(anim); - ext->cur_value = new_value; + bar->cur_value = new_value; lv_obj_invalidate(bar); #else - lv_bar_set_value_with_anim(bar, new_value, &ext->cur_value, &ext->cur_value_anim, anim); + lv_bar_set_value_with_anim(bar, new_value, &bar->cur_value, &bar->cur_value_anim, anim); #endif } @@ -175,24 +137,23 @@ void lv_bar_set_value(lv_obj_t * bar, int16_t value, lv_anim_enable_t anim) * @param value new start value * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ -void lv_bar_set_start_value(lv_obj_t * bar, int16_t start_value, lv_anim_enable_t anim) +void lv_bar_set_start_value(lv_obj_t * obj, int16_t start_value, lv_anim_enable_t anim) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - if(ext->start_value == start_value) return; + lv_bar_t * bar = (lv_bar_t *)obj; int16_t new_value = start_value; - new_value = new_value > ext->max_value ? ext->max_value : new_value; - new_value = new_value < ext->min_value ? ext->min_value : new_value; - new_value = new_value > ext->cur_value ? ext->cur_value : new_value; + new_value = new_value > bar->max_value ? bar->max_value : new_value; + new_value = new_value < bar->min_value ? bar->min_value : new_value; + new_value = new_value > bar->cur_value ? bar->cur_value : new_value; - if(ext->start_value == new_value) return; + if(bar->start_value == new_value) return; #if LV_USE_ANIMATION == 0 LV_UNUSED(anim); - ext->start_value = new_value; + bar->start_value = new_value; #else - lv_bar_set_value_with_anim(bar, new_value, &ext->start_value, &ext->start_value_anim, anim); + lv_bar_set_value_with_anim(bar, new_value, &bar->start_value, &bar->start_value_anim, anim); #endif } @@ -202,28 +163,28 @@ void lv_bar_set_start_value(lv_obj_t * bar, int16_t start_value, lv_anim_enable_ * @param min minimum value * @param max maximum value */ -void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max) +void lv_bar_set_range(lv_obj_t * obj, int16_t min, int16_t max) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - if(ext->min_value == min && ext->max_value == max) return; + if(bar->min_value == min && bar->max_value == max) return; - ext->max_value = max; - ext->min_value = min; + bar->max_value = max; + bar->min_value = min; - if(lv_bar_get_type(bar) != LV_BAR_TYPE_CUSTOM) - ext->start_value = min; + if(lv_bar_get_type(obj) != LV_BAR_TYPE_CUSTOM) + bar->start_value = min; - if(ext->cur_value > max) { - ext->cur_value = max; - lv_bar_set_value(bar, ext->cur_value, false); + if(bar->cur_value > max) { + bar->cur_value = max; + lv_bar_set_value(obj, bar->cur_value, false); } - if(ext->cur_value < min) { - ext->cur_value = min; - lv_bar_set_value(bar, ext->cur_value, false); + if(bar->cur_value < min) { + bar->cur_value = min; + lv_bar_set_value(obj, bar->cur_value, false); } - lv_obj_invalidate(bar); + lv_obj_invalidate(obj); } /** @@ -231,16 +192,16 @@ void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max) * @param bar pointer to bar object * @param type bar type */ -void lv_bar_set_type(lv_obj_t * bar, lv_bar_type_t type) +void lv_bar_set_type(lv_obj_t * obj, lv_bar_type_t type) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - ext->type = type; - if(ext->type != LV_BAR_TYPE_CUSTOM) - ext->start_value = ext->min_value; + bar->type = type; + if(bar->type != LV_BAR_TYPE_CUSTOM) + bar->start_value = bar->min_value; - lv_obj_invalidate(bar); + lv_obj_invalidate(obj); } /** @@ -248,13 +209,13 @@ void lv_bar_set_type(lv_obj_t * bar, lv_bar_type_t type) * @param bar pointer to a bar object * @param anim_time the animation time in milliseconds. */ -void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time) +void lv_bar_set_anim_time(lv_obj_t * obj, uint16_t anim_time) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); #if LV_USE_ANIMATION - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - ext->anim_time = anim_time; + lv_bar_t * bar = (lv_bar_t *)obj; + bar->anim_time = anim_time; #else (void)bar; /*Unused*/ (void)anim_time; /*Unused*/ @@ -270,12 +231,12 @@ void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time) * @param bar pointer to a bar object * @return the value of the bar */ -int16_t lv_bar_get_value(const lv_obj_t * bar) +int16_t lv_bar_get_value(const lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - return LV_BAR_GET_ANIM_VALUE(ext->cur_value, ext->cur_value_anim); + return LV_BAR_GET_ANIM_VALUE(bar->cur_value, bar->cur_value_anim); } /** @@ -283,15 +244,14 @@ int16_t lv_bar_get_value(const lv_obj_t * bar) * @param bar pointer to a bar object * @return the start value of the bar */ -int16_t lv_bar_get_start_value(const lv_obj_t * bar) +int16_t lv_bar_get_start_value(const lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); + if(bar->type != LV_BAR_TYPE_CUSTOM) return bar->min_value; - if(ext->type != LV_BAR_TYPE_CUSTOM) return ext->min_value; - - return LV_BAR_GET_ANIM_VALUE(ext->start_value, ext->start_value_anim); + return LV_BAR_GET_ANIM_VALUE(bar->start_value, bar->start_value_anim); } /** @@ -299,12 +259,11 @@ int16_t lv_bar_get_start_value(const lv_obj_t * bar) * @param bar pointer to a bar object * @return the minimum value of the bar */ -int16_t lv_bar_get_min_value(const lv_obj_t * bar) +int16_t lv_bar_get_min_value(const lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); - - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - return ext->min_value; + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; + return bar->min_value; } /** @@ -312,12 +271,12 @@ int16_t lv_bar_get_min_value(const lv_obj_t * bar) * @param bar pointer to a bar object * @return the maximum value of the bar */ -int16_t lv_bar_get_max_value(const lv_obj_t * bar) +int16_t lv_bar_get_max_value(const lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - return ext->max_value; + return bar->max_value; } /** @@ -325,12 +284,12 @@ int16_t lv_bar_get_max_value(const lv_obj_t * bar) * @param bar pointer to bar object * @return bar type */ -lv_bar_type_t lv_bar_get_type(lv_obj_t * bar) +lv_bar_type_t lv_bar_get_type(lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - return ext->type; + return bar->type; } /** @@ -338,13 +297,14 @@ lv_bar_type_t lv_bar_get_type(lv_obj_t * bar) * @param bar pointer to a bar object * @return the animation time in milliseconds. */ -uint16_t lv_bar_get_anim_time(const lv_obj_t * bar) +uint16_t lv_bar_get_anim_time(const lv_obj_t * obj) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); #if LV_USE_ANIMATION - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - return ext->anim_time; + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; + return bar->anim_time; #else (void)bar; /*Unused*/ return 0; @@ -356,6 +316,59 @@ uint16_t lv_bar_get_anim_time(const lv_obj_t * bar) * STATIC FUNCTIONS **********************/ +static void lv_bar_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) +{ + LV_LOG_TRACE("lv_bar create started"); + + LV_CLASS_CONSTRUCTOR_BEGIN(obj, lv_bar) + lv_bar.base_p->constructor(obj, parent, copy); + + lv_bar_t * bar = (lv_bar_t *) obj; + bar->min_value = 0; + bar->max_value = 100; + bar->start_value = 0; + bar->cur_value = 0; + bar->type = LV_BAR_TYPE_NORMAL; + lv_style_list_init(&bar->style_indic); + +#if LV_USE_ANIMATION + bar->anim_time = 200; + lv_bar_init_anim(bar, &bar->cur_value_anim); + lv_bar_init_anim(bar, &bar->start_value_anim); +#endif + + if(copy == NULL) { + lv_obj_clear_flag(obj, LV_OBJ_FLAG_CHECKABLE); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_size(obj, LV_DPI * 2, LV_DPI / 10); + lv_bar_set_value(obj, 0, LV_ANIM_OFF); + } else { + lv_bar_t * bar_copy = (lv_bar_t *)copy; + bar->min_value = bar_copy->min_value; + bar->start_value = bar_copy->start_value; + bar->max_value = bar_copy->max_value; + bar->cur_value = bar_copy->cur_value; + bar->type = bar_copy->type; + + lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF); + } + LV_CLASS_CONSTRUCTOR_END(obj, lv_bar) + LV_LOG_INFO("bar created"); +} + +static void lv_bar_destructor(void * obj) +{ + lv_bar_t * bar = obj; + + _lv_obj_reset_style_list_no_refr(obj, LV_BAR_PART_INDIC); +#if LV_USE_ANIMATION + lv_anim_del(&bar->cur_value_anim, NULL); + lv_anim_del(&bar->start_value_anim, NULL); +#endif + + bar->class_p->base_p->destructor(obj); +} + /** * Handle the drawing related tasks of the bars * @param bar pointer to an object @@ -366,16 +379,18 @@ uint16_t lv_bar_get_anim_time(const lv_obj_t * bar) * 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_bar_design(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode) +static lv_design_res_t lv_bar_design(lv_obj_t * obj, const lv_area_t * clip_area, lv_design_mode_t mode) { + lv_bar_t * bar = (lv_bar_t *)obj; + if(mode == LV_DESIGN_COVER_CHK) { /*Return false if the object is not covers the mask area*/ - return ancestor_design(bar, clip_area, mode); + return lv_bar.base_p->design_cb(obj, clip_area, mode); } else if(mode == LV_DESIGN_DRAW_MAIN) { -// draw_bg(bar, clip_area); - ancestor_design(bar, clip_area, mode); - draw_indic(bar, clip_area); + //Draw the background + lv_bar.base_p->design_cb(obj, clip_area, mode); + draw_indic(obj, clip_area); /*Get the value and draw it after the indicator*/ lv_draw_rect_dsc_t draw_dsc; @@ -385,52 +400,53 @@ static lv_design_res_t lv_bar_design(lv_obj_t * bar, const lv_area_t * clip_area draw_dsc.shadow_opa = LV_OPA_TRANSP; draw_dsc.pattern_opa = LV_OPA_TRANSP; draw_dsc.outline_opa = LV_OPA_TRANSP; - lv_obj_init_draw_rect_dsc(bar, LV_BAR_PART_MAIN, &draw_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_BAR_PART_MAIN, &draw_dsc); lv_draw_rect(&bar->coords, clip_area, &draw_dsc); } else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_design(bar, clip_area, mode); + lv_bar.base_p->design_cb(obj, clip_area, mode); } return LV_DESIGN_RES_OK; } -static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) +static void draw_indic(lv_obj_t * obj, const lv_area_t * clip_area) { - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(bar); + lv_bar_t * bar = (lv_bar_t *)obj; - lv_coord_t objw = lv_obj_get_width(bar); - lv_coord_t objh = lv_obj_get_height(bar); - int32_t range = ext->max_value - ext->min_value; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(obj); + + lv_coord_t objw = lv_obj_get_width(obj); + lv_coord_t objh = lv_obj_get_height(obj); + int32_t range = bar->max_value - bar->min_value; bool hor = objw >= objh ? true : false; bool sym = false; - if(ext->type == LV_BAR_TYPE_SYMMETRICAL && ext->min_value < 0 && ext->max_value > 0 && - ext->start_value == ext->min_value) sym = true; + if(bar->type == LV_BAR_TYPE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 && + bar->start_value == bar->min_value) sym = true; /*Calculate the indicator area*/ - lv_style_int_t bg_left = lv_obj_get_style_pad_left(bar, LV_BAR_PART_MAIN); - lv_style_int_t bg_right = lv_obj_get_style_pad_right(bar, LV_BAR_PART_MAIN); - lv_style_int_t bg_top = lv_obj_get_style_pad_top(bar, LV_BAR_PART_MAIN); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(bar, LV_BAR_PART_MAIN); + lv_style_int_t bg_left = lv_obj_get_style_pad_left(obj, LV_BAR_PART_MAIN); + lv_style_int_t bg_right = lv_obj_get_style_pad_right(obj, LV_BAR_PART_MAIN); + lv_style_int_t bg_top = lv_obj_get_style_pad_top(obj, LV_BAR_PART_MAIN); + lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_BAR_PART_MAIN); /*Respect padding and minimum width/height too*/ - lv_area_copy(&ext->indic_area, &bar->coords); - ext->indic_area.x1 += bg_left; - ext->indic_area.x2 -= bg_right; - ext->indic_area.y1 += bg_top; - ext->indic_area.y2 -= bg_bottom; + lv_area_copy(&bar->indic_area, &bar->coords); + bar->indic_area.x1 += bg_left; + bar->indic_area.x2 -= bg_right; + bar->indic_area.y1 += bg_top; + bar->indic_area.y2 -= bg_bottom; - if(hor && lv_area_get_height(&ext->indic_area) < LV_BAR_SIZE_MIN) { - ext->indic_area.y1 = bar->coords.y1 + (objh / 2) - (LV_BAR_SIZE_MIN / 2); - ext->indic_area.y2 = ext->indic_area.y1 + LV_BAR_SIZE_MIN; + if(hor && lv_area_get_height(&bar->indic_area) < LV_BAR_SIZE_MIN) { + bar->indic_area.y1 = bar->coords.y1 + (objh / 2) - (LV_BAR_SIZE_MIN / 2); + bar->indic_area.y2 = bar->indic_area.y1 + LV_BAR_SIZE_MIN; } - else if(!hor && lv_area_get_width(&ext->indic_area) < LV_BAR_SIZE_MIN) { - ext->indic_area.x1 = bar->coords.x1 + (objw / 2) - (LV_BAR_SIZE_MIN / 2); - ext->indic_area.x2 = ext->indic_area.x1 + LV_BAR_SIZE_MIN; + else if(!hor && lv_area_get_width(&bar->indic_area) < LV_BAR_SIZE_MIN) { + bar->indic_area.x1 = bar->coords.x1 + (objw / 2) - (LV_BAR_SIZE_MIN / 2); + bar->indic_area.x2 = bar->indic_area.x1 + LV_BAR_SIZE_MIN; } - lv_coord_t indicw = lv_area_get_width(&ext->indic_area); - lv_coord_t indich = lv_area_get_height(&ext->indic_area); + lv_coord_t indicw = lv_area_get_width(&bar->indic_area); + lv_coord_t indich = lv_area_get_height(&bar->indic_area); /*Calculate the indicator length*/ lv_coord_t anim_length = hor ? indicw : indich; @@ -441,24 +457,24 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) lv_coord_t (*indic_length_calc)(const lv_area_t * area); if(hor) { - axis1 = &ext->indic_area.x1; - axis2 = &ext->indic_area.x2; + axis1 = &bar->indic_area.x1; + axis2 = &bar->indic_area.x2; indic_length_calc = lv_area_get_width; } else { - axis1 = &ext->indic_area.y1; - axis2 = &ext->indic_area.y2; + axis1 = &bar->indic_area.y1; + axis2 = &bar->indic_area.y2; indic_length_calc = lv_area_get_height; } #if LV_USE_ANIMATION - if(LV_BAR_IS_ANIMATING(ext->start_value_anim)) { + if(LV_BAR_IS_ANIMATING(bar->start_value_anim)) { lv_coord_t anim_start_value_start_x = - (int32_t)((int32_t)anim_length * (ext->start_value_anim.anim_start - ext->min_value)) / range; + (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_start - bar->min_value)) / range; lv_coord_t anim_start_value_end_x = - (int32_t)((int32_t)anim_length * (ext->start_value_anim.anim_end - ext->min_value)) / range; + (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_end - bar->min_value)) / range; - anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * ext->start_value_anim.anim_state) / + anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * bar->start_value_anim.anim_state) / LV_BAR_ANIM_STATE_END); anim_start_value_x += anim_start_value_start_x; @@ -466,24 +482,24 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) else #endif { - anim_start_value_x = (int32_t)((int32_t)anim_length * (ext->start_value - ext->min_value)) / range; + anim_start_value_x = (int32_t)((int32_t)anim_length * (bar->start_value - bar->min_value)) / range; } #if LV_USE_ANIMATION - if(LV_BAR_IS_ANIMATING(ext->cur_value_anim)) { + if(LV_BAR_IS_ANIMATING(bar->cur_value_anim)) { lv_coord_t anim_cur_value_start_x = - (int32_t)((int32_t)anim_length * (ext->cur_value_anim.anim_start - ext->min_value)) / range; + (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_start - bar->min_value)) / range; lv_coord_t anim_cur_value_end_x = - (int32_t)((int32_t)anim_length * (ext->cur_value_anim.anim_end - ext->min_value)) / range; + (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_end - bar->min_value)) / range; anim_cur_value_x = anim_cur_value_start_x + (((anim_cur_value_end_x - anim_cur_value_start_x) * - ext->cur_value_anim.anim_state) / + bar->cur_value_anim.anim_state) / LV_BAR_ANIM_STATE_END); } else #endif { - anim_cur_value_x = (int32_t)((int32_t)anim_length * (ext->cur_value - ext->min_value)) / range; + anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range; } if(hor && base_dir == LV_BIDI_DIR_RTL) { @@ -507,7 +523,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) } if(sym) { lv_coord_t zero; - zero = *axis1 + (-ext->min_value * anim_length) / range; + zero = *axis1 + (-bar->min_value * anim_length) / range; if(*axis2 > zero) *axis1 = zero; else { @@ -519,21 +535,21 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) /*Draw the indicator*/ /*Do not draw a zero length indicator*/ - if(!sym && indic_length_calc(&ext->indic_area) <= 1) return; + if(!sym && indic_length_calc(&bar->indic_area) <= 1) return; - uint16_t bg_radius = lv_obj_get_style_radius(bar, LV_BAR_PART_MAIN); + uint16_t bg_radius = lv_obj_get_style_radius(obj, LV_BAR_PART_MAIN); lv_coord_t short_side = LV_MATH_MIN(objw, objh); if(bg_radius > short_side >> 1) bg_radius = short_side >> 1; lv_draw_rect_dsc_t draw_indic_dsc; lv_draw_rect_dsc_init(&draw_indic_dsc); - lv_obj_init_draw_rect_dsc(bar, LV_BAR_PART_INDIC, &draw_indic_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_BAR_PART_INDIC, &draw_indic_dsc); /* Draw only the shadow if the indicator is long enough. * The radius of the bg and the indicator can make a strange shape where * it'd be very difficult to draw shadow. */ - if((hor && lv_area_get_width(&ext->indic_area) > bg_radius * 2) || - (!hor && lv_area_get_height(&ext->indic_area) > bg_radius * 2)) { + if((hor && lv_area_get_width(&bar->indic_area) > bg_radius * 2) || + (!hor && lv_area_get_height(&bar->indic_area) > bg_radius * 2)) { lv_opa_t bg_opa = draw_indic_dsc.bg_opa; lv_opa_t border_opa = draw_indic_dsc.border_opa; lv_opa_t value_opa = draw_indic_dsc.value_opa; @@ -542,7 +558,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) draw_indic_dsc.border_opa = LV_OPA_TRANSP; draw_indic_dsc.value_opa = LV_OPA_TRANSP; draw_indic_dsc.pattern_image = NULL; - lv_draw_rect(&ext->indic_area, clip_area, &draw_indic_dsc); + lv_draw_rect(&bar->indic_area, clip_area, &draw_indic_dsc); draw_indic_dsc.bg_opa = bg_opa; draw_indic_dsc.border_opa = border_opa; draw_indic_dsc.value_opa = value_opa; @@ -580,7 +596,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) /*Create a mask to the current indicator area to see only this part from the whole gradient.*/ lv_draw_mask_radius_param_t mask_indic_param; - lv_draw_mask_radius_init(&mask_indic_param, &ext->indic_area, draw_indic_dsc.radius, false); + lv_draw_mask_radius_init(&mask_indic_param, &bar->indic_area, draw_indic_dsc.radius, false); int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL); lv_draw_rect(&mask_indic_max_area, clip_area, &draw_indic_dsc); @@ -593,7 +609,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) draw_indic_dsc.shadow_opa = LV_OPA_TRANSP; draw_indic_dsc.value_opa = LV_OPA_TRANSP; draw_indic_dsc.pattern_image = NULL; - lv_draw_rect(&ext->indic_area, clip_area, &draw_indic_dsc); + lv_draw_rect(&bar->indic_area, clip_area, &draw_indic_dsc); lv_draw_mask_remove_id(mask_indic_id); lv_draw_mask_remove_id(mask_bg_id); @@ -601,7 +617,7 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) /*When not masks draw the value*/ draw_indic_dsc.value_opa = value_opa; draw_indic_dsc.border_opa = LV_OPA_TRANSP; - lv_draw_rect(&ext->indic_area, clip_area, &draw_indic_dsc); + lv_draw_rect(&bar->indic_area, clip_area, &draw_indic_dsc); } @@ -612,49 +628,37 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) * @param param pointer to a signal specific variable * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted */ -static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param) +static lv_res_t lv_bar_signal(lv_obj_t * obj, lv_signal_t sign, void * param) { + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_bar_t * bar = (lv_bar_t *)obj; + lv_res_t res; /* Include the ancient signal function */ - res = ancestor_signal(bar, sign, param); + res = lv_bar.base_p->signal_cb(obj, 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_bar_get_style(bar, info->part); if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(bar, sign, param); - } - else if(sign == LV_SIGNAL_GET_TYPE) { - return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); + else return lv_bar.base_p->signal_cb(obj, sign, param); } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { lv_coord_t indic_size; - indic_size = _lv_obj_get_draw_rect_ext_pad_size(bar, LV_BAR_PART_INDIC); + indic_size = _lv_obj_get_draw_rect_ext_pad_size(obj, LV_BAR_PART_INDIC); /*Bg size is handled by lv_obj*/ lv_coord_t * s = param; *s = LV_MATH_MAX(*s, indic_size); - - } - if(sign == LV_SIGNAL_CLEANUP) { - _lv_obj_reset_style_list_no_refr(bar, LV_BAR_PART_INDIC); -#if LV_USE_ANIMATION - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - lv_anim_del(&ext->cur_value_anim, NULL); - lv_anim_del(&ext->start_value_anim, NULL); -#endif } return res; } -static lv_style_list_t * lv_bar_get_style(lv_obj_t * bar, uint8_t part) +static lv_style_list_t * lv_bar_get_style(lv_bar_t * bar, uint8_t part) { - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); - - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); lv_style_list_t * list; switch(part) { @@ -662,7 +666,7 @@ static lv_style_list_t * lv_bar_get_style(lv_obj_t * bar, uint8_t part) list = &bar->style_list; break; case LV_BAR_PART_INDIC: - list = &ext->style_indic; + list = &bar->style_indic; break; default: list = NULL; @@ -681,24 +685,25 @@ static void lv_bar_anim(lv_bar_anim_t * var, lv_anim_value_t value) static void lv_bar_anim_ready(lv_anim_t * a) { lv_bar_anim_t * var = a->var; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(var->bar); + lv_bar_t * bar = (lv_bar_t *)var->bar; + var->anim_state = LV_BAR_ANIM_STATE_INV; - if(var == &ext->cur_value_anim) - ext->cur_value = var->anim_end; - else if(var == &ext->start_value_anim) - ext->start_value = var->anim_end; + if(var == &bar->cur_value_anim) + bar->cur_value = var->anim_end; + else if(var == &bar->start_value_anim) + bar->start_value = var->anim_end; lv_obj_invalidate(var->bar); } -static void lv_bar_set_value_with_anim(lv_obj_t * bar, int16_t new_value, int16_t * value_ptr, +static void lv_bar_set_value_with_anim(lv_bar_t * bar, int16_t new_value, int16_t * value_ptr, lv_bar_anim_t * anim_info, lv_anim_enable_t en) { if(en == LV_ANIM_OFF) { *value_ptr = new_value; - lv_obj_invalidate(bar); + lv_obj_invalidate((lv_obj_t*)bar); } else { - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); + /*No animation in progress -> simply set the values*/ if(anim_info->anim_state == LV_BAR_ANIM_STATE_INV) { anim_info->anim_start = *value_ptr; @@ -719,14 +724,14 @@ static void lv_bar_set_value_with_anim(lv_obj_t * bar, int16_t new_value, int16_ lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_bar_anim); lv_anim_set_values(&a, LV_BAR_ANIM_STATE_START, LV_BAR_ANIM_STATE_END); lv_anim_set_ready_cb(&a, lv_bar_anim_ready); - lv_anim_set_time(&a, ext->anim_time); + lv_anim_set_time(&a, bar->anim_time); lv_anim_start(&a); } } -static void lv_bar_init_anim(lv_obj_t * bar, lv_bar_anim_t * bar_anim) +static void lv_bar_init_anim(lv_bar_t * bar, lv_bar_anim_t * bar_anim) { - bar_anim->bar = bar; + bar_anim->bar = (lv_obj_t *)bar; bar_anim->anim_start = 0; bar_anim->anim_end = 0; bar_anim->anim_state = LV_BAR_ANIM_STATE_INV; diff --git a/src/lv_widgets/lv_bar.h b/src/lv_widgets/lv_bar.h index e23de2f03..41708403d 100644 --- a/src/lv_widgets/lv_bar.h +++ b/src/lv_widgets/lv_bar.h @@ -58,24 +58,37 @@ typedef struct { } lv_bar_anim_t; #endif -/** Data of bar*/ -typedef struct { - /*No inherited ext, derived from the base object */ - /*New data for this type */ - int16_t cur_value; /*Current value of the bar*/ - int16_t min_value; /*Minimum value of the bar*/ - int16_t max_value; /*Maximum value of the bar*/ - int16_t start_value; /*Start value of the bar*/ - lv_area_t indic_area; /*Save the indicator area. MIght be used by derived types*/ +LV_CLASS_DECLARE_START(lv_bar, lv_obj); + +#define _lv_bar_constructor void (*constructor)(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy) + #if LV_USE_ANIMATION - lv_anim_value_t anim_time; - lv_bar_anim_t cur_value_anim; +#define _lv_bar_anim_data \ + lv_anim_value_t anim_time; \ + lv_bar_anim_t cur_value_anim; \ lv_bar_anim_t start_value_anim; +#else +#define _lv_bar_anim_data #endif - uint8_t type : 2; /*Type of bar*/ - lv_style_list_t style_indic; /*Style of the indicator*/ -} lv_bar_ext_t; + +#define _lv_bar_data \ + _lv_obj_data \ + int16_t cur_value; /*Current value of the bar*/ \ + int16_t min_value; /*Minimum value of the bar*/ \ + int16_t max_value; /*Maximum value of the bar*/ \ + int16_t start_value; /*Start value of the bar*/ \ + lv_area_t indic_area; /*Save the indicator area. Might be used by derived types*/ \ + _lv_bar_anim_data \ + uint8_t type : 2; /*Type of bar*/ \ + lv_style_list_t style_indic; /*Style of the indicator*/ + +#define _lv_bar_class_dsc \ + _lv_obj_class_dsc \ + +LV_CLASS_DECLARE_END(lv_bar, lv_obj); + +extern lv_bar_class_t lv_bar; /** Bar parts */ enum { diff --git a/src/lv_widgets/lv_slider.c b/src/lv_widgets/lv_slider.c index 4101b5063..9a28aa34e 100644 --- a/src/lv_widgets/lv_slider.c +++ b/src/lv_widgets/lv_slider.c @@ -16,6 +16,7 @@ #include "../lv_draw/lv_draw.h" #include "../lv_themes/lv_theme.h" #include "../lv_misc/lv_math.h" +#include "../lv_core/lv_disp.h" #include "lv_img.h" /********************* @@ -32,17 +33,18 @@ /********************** * STATIC PROTOTYPES **********************/ +static void lv_slider_desctructor(void * obj); +static void lv_slider_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy); static lv_design_res_t lv_slider_design(lv_obj_t * slider, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * param); -static lv_style_list_t * lv_slider_get_style(lv_obj_t * slider, uint8_t part); +static lv_style_list_t * lv_slider_get_style(lv_slider_t * slider, uint8_t part); static void lv_slider_position_knob(lv_obj_t * slider, lv_area_t * knob_area, lv_coord_t knob_size, bool hor); static void lv_slider_draw_knob(lv_obj_t * slider, const lv_area_t * knob_area, const lv_area_t * clip_area); /********************** * STATIC VARIABLES **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; +lv_slider_class_t lv_slider; /********************** * MACROS @@ -63,51 +65,33 @@ lv_obj_t * lv_slider_create(lv_obj_t * parent, const lv_obj_t * copy) { LV_LOG_TRACE("slider create started"); - /*Create the ancestor slider*/ - lv_obj_t * slider = lv_bar_create(parent, copy); - LV_ASSERT_MEM(slider); - if(slider == NULL) return NULL; - - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(slider); - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(slider); - - /*Allocate the slider type specific extended data*/ - lv_slider_ext_t * ext = lv_obj_allocate_ext_attr(slider, sizeof(lv_slider_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(slider); - return NULL; + if(!lv_slider._inited) { + LV_CLASS_INIT(lv_slider, lv_bar); + lv_slider.constructor = lv_slider_constructor; + lv_slider.destructor = lv_slider_desctructor; + lv_slider.signal_cb = lv_slider_signal; + lv_slider.design_cb = lv_slider_design; } - /*Initialize the allocated 'ext' */ - ext->value_to_set = NULL; - ext->dragging = 0; - ext->left_knob_focus = 0; - lv_style_list_init(&ext->style_knob); - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(slider, lv_slider_signal); - lv_obj_set_design_cb(slider, lv_slider_design); + lv_obj_t * obj = lv_class_new(&lv_slider); + lv_slider.constructor(obj, parent, copy); + + lv_slider_t * slider = (lv_slider_t *) obj; /*Init the new slider slider*/ - if(copy == NULL) { - lv_theme_apply(slider, LV_THEME_SLIDER); - lv_obj_add_flag(slider, LV_OBJ_FLAG_SCROLL_FREEZE); - lv_obj_set_ext_click_area(slider, 0, 0, LV_DPI / 10, LV_DPI / 10); - lv_obj_set_height(slider, LV_DPI / 15); - } else { - lv_slider_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - lv_style_list_copy(&ext->style_knob, ©_ext->style_knob); - lv_area_copy(&ext->left_knob_area, ©_ext->left_knob_area); - lv_area_copy(&ext->right_knob_area, ©_ext->right_knob_area); - - _lv_obj_refresh_style(slider, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } + if(copy == NULL) { + lv_theme_apply(obj, LV_THEME_SLIDER); + } else { + lv_slider_t * copy_slider = (lv_slider_t *) copy; + lv_style_list_copy(&slider->style_knob, ©_slider->style_knob); + _lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); + } LV_LOG_INFO("slider created"); - return slider; + return obj; } /*===================== @@ -123,18 +107,55 @@ lv_obj_t * lv_slider_create(lv_obj_t * parent, const lv_obj_t * copy) * @param slider pointer to a slider object * @return true: drag in progress false: not dragged */ -bool lv_slider_is_dragged(const lv_obj_t * slider) +bool lv_slider_is_dragged(const lv_obj_t * obj) { - LV_ASSERT_OBJ(slider, LV_OBJX_NAME); + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_slider_t * slider = (lv_slider_t *) obj; - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); - return ext->dragging ? true : false; + return slider->dragging ? true : false; } /********************** * STATIC FUNCTIONS **********************/ +static void lv_slider_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) +{ + LV_CLASS_CONSTRUCTOR_BEGIN(obj, lv_slider) + lv_slider.base_p->constructor(obj, parent, copy); + + lv_slider_t * slider = (lv_slider_t*) obj; + + /*Initialize the allocated 'slider' */ + slider->value_to_set = NULL; + slider->dragging = 0; + slider->left_knob_focus = 0; + lv_style_list_init(&slider->style_knob); + + /*Init the new slider slider*/ + if(copy == NULL) { + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_ext_click_area(obj, lv_dpx(5), lv_dpx(5), lv_dpx(5), lv_dpx(5)); + lv_obj_set_height(obj, LV_DPI / 15); + } else { + lv_slider_t * copy_slider = (lv_slider_t *) copy; + lv_area_copy(&slider->left_knob_area, ©_slider->left_knob_area); + lv_area_copy(&slider->right_knob_area, ©_slider->right_knob_area); + } + + LV_CLASS_CONSTRUCTOR_END(obj, lv_slider) +} + +static void lv_slider_desctructor(void * obj) +{ + lv_slider_t * slider = obj; + + _lv_obj_reset_style_list_no_refr(obj, LV_SLIDER_PART_KNOB); + + slider->class_p->base_p->destructor(obj); +} + /** * Handle the drawing related tasks of the sliders * @param slider pointer to an object @@ -145,7 +166,7 @@ bool lv_slider_is_dragged(const lv_obj_t * slider) * 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_slider_design(lv_obj_t * slider, const lv_area_t * clip_area, lv_design_mode_t mode) +static lv_design_res_t lv_slider_design(lv_obj_t * obj, const lv_area_t * clip_area, lv_design_mode_t mode) { /*Return false if the object is not covers the mask_p area*/ if(mode == LV_DESIGN_COVER_CHK) { @@ -154,71 +175,71 @@ static lv_design_res_t lv_slider_design(lv_obj_t * slider, const lv_area_t * cli /*Draw the object*/ else if(mode == LV_DESIGN_DRAW_MAIN) { /* The ancestor design function will draw the background and the indicator. - * It also sets ext->bar.indic_area*/ - ancestor_design(slider, clip_area, mode); + * It also sets slider->indic_area*/ + lv_slider.base_p->design_cb(obj, clip_area, mode); - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(slider); + lv_slider_t * slider = (lv_slider_t *)obj; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(obj); - lv_coord_t objw = lv_obj_get_width(slider); - lv_coord_t objh = lv_obj_get_height(slider); + lv_coord_t objw = lv_obj_get_width(obj); + lv_coord_t objh = lv_obj_get_height(obj); bool hor = objw >= objh ? true : false; lv_coord_t knob_size = hor ? objh : objw; bool sym = false; - if(ext->bar.type == LV_BAR_TYPE_SYMMETRICAL && ext->bar.min_value < 0 && ext->bar.max_value > 0) sym = true; + if(slider->type == LV_BAR_TYPE_SYMMETRICAL && slider->min_value < 0 && slider->max_value > 0) sym = true; lv_area_t knob_area; /*Horizontal*/ if(hor) { if(!sym) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BIDI_DIR_RTL, ext->bar.indic_area); + knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BIDI_DIR_RTL, slider->indic_area); } else { - if(ext->bar.cur_value >= 0) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BIDI_DIR_RTL, ext->bar.indic_area); + if(slider->cur_value >= 0) { + knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir == LV_BIDI_DIR_RTL, slider->indic_area); } else { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BIDI_DIR_RTL, ext->bar.indic_area); + knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BIDI_DIR_RTL, slider->indic_area); } } } /*Vertical*/ else { if(!sym) { - knob_area.y1 = ext->bar.indic_area.y1; + knob_area.y1 = slider->indic_area.y1; } else { - if(ext->bar.cur_value >= 0) { - knob_area.y1 = ext->bar.indic_area.y1; + if(slider->cur_value >= 0) { + knob_area.y1 = slider->indic_area.y1; } else { - knob_area.y1 = ext->bar.indic_area.y2; + knob_area.y1 = slider->indic_area.y2; } } } - lv_slider_position_knob(slider, &knob_area, knob_size, hor); + lv_slider_position_knob(obj, &knob_area, knob_size, hor); - lv_area_copy(&ext->right_knob_area, &knob_area); - lv_slider_draw_knob(slider, &knob_area, clip_area); + lv_area_copy(&slider->right_knob_area, &knob_area); + lv_slider_draw_knob(obj, &knob_area, clip_area); - if(lv_slider_get_type(slider) == LV_SLIDER_TYPE_RANGE) { + if(lv_slider_get_type(obj) == LV_SLIDER_TYPE_RANGE) { /* Draw a second knob for the start_value side */ if(hor) { - knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BIDI_DIR_RTL, ext->bar.indic_area); + knob_area.x1 = LV_SLIDER_KNOB_COORD(hor, base_dir != LV_BIDI_DIR_RTL, slider->indic_area); } else { - knob_area.y1 = ext->bar.indic_area.y2; + knob_area.y1 = slider->indic_area.y2; } - lv_slider_position_knob(slider, &knob_area, knob_size, hor); + lv_slider_position_knob(obj, &knob_area, knob_size, hor); - lv_area_copy(&ext->left_knob_area, &knob_area); - lv_slider_draw_knob(slider, &knob_area, clip_area); + lv_area_copy(&slider->left_knob_area, &knob_area); + lv_slider_draw_knob(obj, &knob_area, clip_area); } } /*Post draw when the children are drawn*/ else if(mode == LV_DESIGN_DRAW_POST) { - return ancestor_design(slider, clip_area, mode); + return lv_slider.base_p->design_cb(obj, clip_area, mode); } return LV_DESIGN_RES_OK; @@ -231,107 +252,106 @@ static lv_design_res_t lv_slider_design(lv_obj_t * slider, const lv_area_t * cli * @param param pointer to a signal specific variable * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted */ -static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * param) +static lv_res_t lv_slider_signal(lv_obj_t * obj, lv_signal_t sign, void * param) { lv_res_t res; + lv_slider_t * slider = (lv_slider_t *)obj; if(sign == LV_SIGNAL_GET_STYLE) { lv_get_style_info_t * info = param; info->result = lv_slider_get_style(slider, info->part); if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(slider, sign, param); + else return lv_slider.base_p->signal_cb(obj, sign, param); } /* Include the ancient signal function */ - res = ancestor_signal(slider, sign, param); + res = lv_slider.base_p->signal_cb(obj, 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_slider_type_t type = lv_slider_get_type(slider); - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); + lv_slider_type_t type = lv_slider_get_type(obj); /* Advanced hit testing: react only on dragging the knob(s) */ if(sign == LV_SIGNAL_HIT_TEST) { lv_hit_test_info_t * info = param; /* Ordinary slider: was the knob area hit? */ - info->result = _lv_area_is_point_on(&ext->right_knob_area, info->point, 0); + info->result = _lv_area_is_point_on(&slider->right_knob_area, info->point, 0); /* There's still a change we have a hit, if we have another knob */ if((info->result == false) && (type == LV_SLIDER_TYPE_RANGE)) { - info->result = _lv_area_is_point_on(&ext->left_knob_area, info->point, 0); + info->result = _lv_area_is_point_on(&slider->left_knob_area, info->point, 0); } } lv_point_t p; if(sign == LV_SIGNAL_PRESSED) { - ext->dragging = true; + slider->dragging = true; if(type == LV_SLIDER_TYPE_NORMAL || type == LV_SLIDER_TYPE_SYMMETRICAL) { - ext->value_to_set = &ext->bar.cur_value; + slider->value_to_set = &slider->cur_value; } else if(type == LV_SLIDER_TYPE_RANGE) { lv_indev_get_point(param, &p); - bool hor = lv_obj_get_width(slider) >= lv_obj_get_height(slider); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(slider); + bool hor = lv_obj_get_width(obj) >= lv_obj_get_height(obj); + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(obj); lv_coord_t dist_left, dist_right; if(hor) { - if((base_dir != LV_BIDI_DIR_RTL && p.x > ext->right_knob_area.x2) || (base_dir == LV_BIDI_DIR_RTL && - p.x < ext->right_knob_area.x1)) { - ext->value_to_set = &ext->bar.cur_value; + if((base_dir != LV_BIDI_DIR_RTL && p.x > slider->right_knob_area.x2) || (base_dir == LV_BIDI_DIR_RTL && + p.x < slider->right_knob_area.x1)) { + slider->value_to_set = &slider->cur_value; } - else if((base_dir != LV_BIDI_DIR_RTL && p.x < ext->left_knob_area.x1) || (base_dir == LV_BIDI_DIR_RTL && - p.x > ext->left_knob_area.x2)) { - ext->value_to_set = &ext->bar.start_value; + else if((base_dir != LV_BIDI_DIR_RTL && p.x < slider->left_knob_area.x1) || (base_dir == LV_BIDI_DIR_RTL && + p.x > slider->left_knob_area.x2)) { + slider->value_to_set = &slider->start_value; } else { /* Calculate the distance from each knob */ - dist_left = LV_MATH_ABS((ext->left_knob_area.x1 + (ext->left_knob_area.x2 - ext->left_knob_area.x1) / 2) - p.x); - dist_right = LV_MATH_ABS((ext->right_knob_area.x1 + (ext->right_knob_area.x2 - ext->right_knob_area.x1) / 2) - p.x); + dist_left = LV_MATH_ABS((slider->left_knob_area.x1 + (slider->left_knob_area.x2 - slider->left_knob_area.x1) / 2) - p.x); + dist_right = LV_MATH_ABS((slider->right_knob_area.x1 + (slider->right_knob_area.x2 - slider->right_knob_area.x1) / 2) - p.x); /* Use whichever one is closer */ - if(dist_right < dist_left)ext->value_to_set = &ext->bar.cur_value; - else ext->value_to_set = &ext->bar.start_value; + if(dist_right < dist_left)slider->value_to_set = &slider->cur_value; + else slider->value_to_set = &slider->start_value; } } else { - if(p.y < ext->right_knob_area.y1) { - ext->value_to_set = &ext->bar.cur_value; + if(p.y < slider->right_knob_area.y1) { + slider->value_to_set = &slider->cur_value; } - else if(p.y > ext->left_knob_area.y2) { - ext->value_to_set = &ext->bar.start_value; + else if(p.y > slider->left_knob_area.y2) { + slider->value_to_set = &slider->start_value; } else { /* Calculate the distance from each knob */ - dist_left = LV_MATH_ABS((ext->left_knob_area.y1 + (ext->left_knob_area.y2 - ext->left_knob_area.y1) / 2) - p.y); - dist_right = LV_MATH_ABS((ext->right_knob_area.y1 + (ext->right_knob_area.y2 - ext->right_knob_area.y1) / 2) - p.y); + dist_left = LV_MATH_ABS((slider->left_knob_area.y1 + (slider->left_knob_area.y2 - slider->left_knob_area.y1) / 2) - p.y); + dist_right = LV_MATH_ABS((slider->right_knob_area.y1 + (slider->right_knob_area.y2 - slider->right_knob_area.y1) / 2) - p.y); /* Use whichever one is closer */ - if(dist_right < dist_left)ext->value_to_set = &ext->bar.cur_value; - else ext->value_to_set = &ext->bar.start_value; + if(dist_right < dist_left)slider->value_to_set = &slider->cur_value; + else slider->value_to_set = &slider->start_value; } } } } - else if(sign == LV_SIGNAL_PRESSING && ext->value_to_set != NULL) { + else if(sign == LV_SIGNAL_PRESSING && slider->value_to_set != NULL) { if(lv_indev_get_type(param) != LV_INDEV_TYPE_POINTER) return res; lv_indev_get_point(param, &p); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(slider); + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(obj); - lv_coord_t w = lv_obj_get_width(slider); - lv_coord_t h = lv_obj_get_height(slider); + lv_coord_t w = lv_obj_get_width(obj); + lv_coord_t h = lv_obj_get_height(obj); - lv_style_int_t bg_left = lv_obj_get_style_pad_left(slider, LV_SLIDER_PART_MAIN); - lv_style_int_t bg_right = lv_obj_get_style_pad_right(slider, LV_SLIDER_PART_MAIN); - lv_style_int_t bg_top = lv_obj_get_style_pad_top(slider, LV_SLIDER_PART_MAIN); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(slider, LV_SLIDER_PART_MAIN); + lv_style_int_t bg_left = lv_obj_get_style_pad_left(obj, LV_SLIDER_PART_MAIN); + lv_style_int_t bg_right = lv_obj_get_style_pad_right(obj, LV_SLIDER_PART_MAIN); + lv_style_int_t bg_top = lv_obj_get_style_pad_top(obj, LV_SLIDER_PART_MAIN); + lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_SLIDER_PART_MAIN); - int32_t range = ext->bar.max_value - ext->bar.min_value; + int32_t range = slider->max_value - slider->min_value; int16_t new_value = 0; - int16_t real_max_value = ext->bar.max_value; - int16_t real_min_value = ext->bar.min_value; + int16_t real_max_value = slider->max_value; + int16_t real_min_value = slider->min_value; if(w >= h) { lv_coord_t indic_w = w - bg_left - bg_right; @@ -342,37 +362,37 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par new_value = p.x - (slider->coords.x1 + bg_left); /*Make the point relative to the indicator*/ } new_value = (new_value * range) / indic_w; - new_value += ext->bar.min_value; + new_value += slider->min_value; } else { lv_coord_t indic_h = h - bg_bottom - bg_top; new_value = p.y - (slider->coords.y2 + bg_bottom); /*Make the point relative to the indicator*/ new_value = (-new_value * range) / indic_h; - new_value += ext->bar.min_value; + new_value += slider->min_value; } /* Figure out the min. and max. for this mode */ - if(ext->value_to_set == &ext->bar.start_value) { - real_max_value = ext->bar.cur_value; + if(slider->value_to_set == &slider->start_value) { + real_max_value = slider->cur_value; } else { - real_min_value = ext->bar.start_value; + real_min_value = slider->start_value; } if(new_value < real_min_value) new_value = real_min_value; else if(new_value > real_max_value) new_value = real_max_value; - if(*ext->value_to_set != new_value) { - *ext->value_to_set = new_value; - lv_obj_invalidate(slider); - res = lv_event_send(slider, LV_EVENT_VALUE_CHANGED, NULL); + if(*slider->value_to_set != new_value) { + *slider->value_to_set = new_value; + lv_obj_invalidate(obj); + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } } else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { - ext->dragging = false; - ext->value_to_set = NULL; + slider->dragging = false; + slider->value_to_set = NULL; #if LV_USE_GROUP /*Leave edit mode if released. (No need to wait for LONG_PRESS) */ @@ -382,9 +402,9 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par if(indev_type == LV_INDEV_TYPE_ENCODER) { if(editing) { if(lv_slider_get_type(slider) == LV_SLIDER_TYPE_RANGE) { - if(ext->left_knob_focus == 0) ext->left_knob_focus = 1; + if(slider->left_knob_focus == 0) slider->left_knob_focus = 1; else { - ext->left_knob_focus = 0; + slider->left_knob_focus = 0; lv_group_set_editing(g, false); } } @@ -397,28 +417,28 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par } else if(sign == LV_SIGNAL_FOCUS) { - ext->left_knob_focus = 0; + slider->left_knob_focus = 0; } else if(sign == LV_SIGNAL_COORD_CHG) { /* The knob size depends on slider size. - * During the drawing method the ext. size is used by the knob so refresh the ext. size.*/ - if(lv_obj_get_width(slider) != lv_area_get_width(param) || - lv_obj_get_height(slider) != lv_area_get_height(param)) { - _lv_obj_refresh_ext_draw_pad(slider); + * During the drawing method the obj. size is used by the knob so refresh the obj. size.*/ + if(lv_obj_get_width(obj) != lv_area_get_width(param) || + lv_obj_get_height(obj) != lv_area_get_height(param)) { + _lv_obj_refresh_ext_draw_pad(obj); } } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - lv_style_int_t knob_left = lv_obj_get_style_pad_left(slider, LV_SLIDER_PART_KNOB); - lv_style_int_t knob_right = lv_obj_get_style_pad_right(slider, LV_SLIDER_PART_KNOB); - lv_style_int_t knob_top = lv_obj_get_style_pad_top(slider, LV_SLIDER_PART_KNOB); - lv_style_int_t knob_bottom = lv_obj_get_style_pad_bottom(slider, LV_SLIDER_PART_KNOB); + lv_style_int_t knob_left = lv_obj_get_style_pad_left(obj, LV_SLIDER_PART_KNOB); + lv_style_int_t knob_right = lv_obj_get_style_pad_right(obj,LV_SLIDER_PART_KNOB); + lv_style_int_t knob_top = lv_obj_get_style_pad_top(obj, LV_SLIDER_PART_KNOB); + lv_style_int_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_SLIDER_PART_KNOB); /* The smaller size is the knob diameter*/ - lv_coord_t knob_size = LV_MATH_MIN(lv_obj_get_width(slider), lv_obj_get_height(slider)) >> 1; + lv_coord_t knob_size = LV_MATH_MIN(lv_obj_get_width(obj), lv_obj_get_height(obj)) >> 1; knob_size += LV_MATH_MAX(LV_MATH_MAX(knob_left, knob_right), LV_MATH_MAX(knob_bottom, knob_top)); knob_size += 2; /*For rounding error*/ - knob_size += _lv_obj_get_draw_rect_ext_pad_size(slider, LV_SLIDER_PART_KNOB); + knob_size += _lv_obj_get_draw_rect_ext_pad_size(obj, LV_SLIDER_PART_KNOB); /*Indic. size is handled by bar*/ lv_coord_t * s = param; @@ -430,14 +450,14 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par char c = *((char *)param); if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - if(!ext->left_knob_focus) lv_slider_set_value(slider, lv_slider_get_value(slider) + 1, LV_ANIM_ON); + if(!slider->left_knob_focus) lv_slider_set_value(slider, lv_slider_get_value(slider) + 1, LV_ANIM_ON); else lv_slider_set_left_value(slider, lv_slider_get_left_value(slider) + 1, LV_ANIM_ON); res = lv_event_send(slider, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res; } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - if(!ext->left_knob_focus) lv_slider_set_value(slider, lv_slider_get_value(slider) - 1, LV_ANIM_ON); + if(!slider->left_knob_focus) lv_slider_set_value(slider, lv_slider_get_value(slider) - 1, LV_ANIM_ON); else lv_slider_set_left_value(slider, lv_slider_get_left_value(slider) - 1, LV_ANIM_ON); res = lv_event_send(slider, LV_EVENT_VALUE_CHANGED, NULL); @@ -445,9 +465,6 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par } #endif } - else if(sign == LV_SIGNAL_CLEANUP) { - _lv_obj_reset_style_list_no_refr(slider, LV_SLIDER_PART_KNOB); - } else if(sign == LV_SIGNAL_GET_EDITABLE) { #if LV_USE_GROUP bool * editable = (bool *)param; @@ -459,11 +476,8 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par } -static lv_style_list_t * lv_slider_get_style(lv_obj_t * slider, uint8_t part) +static lv_style_list_t * lv_slider_get_style(lv_slider_t * slider, uint8_t part) { - LV_ASSERT_OBJ(slider, LV_OBJX_NAME); - - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); lv_style_list_t * style_dsc_p; switch(part) { @@ -471,10 +485,10 @@ static lv_style_list_t * lv_slider_get_style(lv_obj_t * slider, uint8_t part) style_dsc_p = &slider->style_list; break; case LV_SLIDER_PART_INDIC: - style_dsc_p = &ext->bar.style_indic; + style_dsc_p = &slider->style_indic; break; case LV_SLIDER_PART_KNOB: - style_dsc_p = &ext->style_knob; + style_dsc_p = &slider->style_knob; break; default: style_dsc_p = NULL; diff --git a/src/lv_widgets/lv_slider.h b/src/lv_widgets/lv_slider.h index 0ae953980..9dbb0ec63 100644 --- a/src/lv_widgets/lv_slider.h +++ b/src/lv_widgets/lv_slider.h @@ -40,17 +40,23 @@ enum { }; typedef uint8_t lv_slider_type_t; -/*Data of slider*/ -typedef struct { - lv_bar_ext_t bar; /*Ext. of ancestor*/ - /*New data for this type */ - lv_style_list_t style_knob; /*Style of the knob*/ - lv_area_t left_knob_area; - lv_area_t right_knob_area; - int16_t * value_to_set; /* Which bar value to set */ - uint8_t dragging : 1; /*1: the slider is being dragged*/ - uint8_t left_knob_focus : 1; /*1: with encoder now the right knob can be adjusted*/ -} lv_slider_ext_t; +LV_CLASS_DECLARE_START(lv_slider, lv_bar) + +#define _lv_slider_constructor void (*constructor)(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy) + +#define _lv_slider_data \ + _lv_bar_data \ + lv_style_list_t style_knob; /*Style of the knob*/ \ + lv_area_t left_knob_area; \ + lv_area_t right_knob_area; \ + int16_t * value_to_set; /* Which bar value to set */ \ + uint8_t dragging : 1; /*1: the slider is being dragged*/ \ + uint8_t left_knob_focus : 1; /*1: with encoder now the right knob can be adjusted*/ + +#define _lv_slider_class_dsc \ + _lv_bar_class_dsc \ + +LV_CLASS_DECLARE_END(lv_slider, lv_bar) /** Built-in styles of slider*/ enum {