diff --git a/src/lv_core/lv_disp.c b/src/lv_core/lv_disp.c index 9cf2fa41a..b9d9df5d4 100644 --- a/src/lv_core/lv_disp.c +++ b/src/lv_core/lv_disp.c @@ -201,7 +201,7 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t lv_disp_load_scr(d->scr_to_load); lv_anim_del(d->scr_to_load, NULL); lv_obj_set_pos(d->scr_to_load, 0, 0); - lv_style_remove_prop(lv_obj_get_local_style(d->scr_to_load, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); +// lv_style_remove_prop(lv_obj_get_local_style(d->scr_to_load, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); act_scr = d->scr_to_load; } @@ -222,8 +222,8 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t /*Be sure both screens are in a normal position*/ lv_obj_set_pos(new_scr, 0, 0); lv_obj_set_pos(lv_scr_act(), 0, 0); - lv_style_remove_prop(lv_obj_get_local_style(new_scr, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); - lv_style_remove_prop(lv_obj_get_local_style(lv_scr_act(), LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); +// lv_style_remove_prop(lv_obj_get_local_style(new_scr, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); +// lv_style_remove_prop(lv_obj_get_local_style(lv_scr_act(), LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); lv_anim_t a_new; lv_anim_init(&a_new); @@ -396,6 +396,6 @@ static void scr_anim_ready(lv_anim_t * a) if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr); d->prev_scr = NULL; d->scr_to_load = NULL; - lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); +// lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_PART_MAIN, LV_STATE_DEFAULT), LV_STYLE_OPA); } #endif diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 96abc3542..6afdd1303 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -226,7 +226,7 @@ uint32_t lv_indev_get_key(const lv_indev_t * indev) return indev->proc.types.keypad.last_key; } -lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) +lv_indev_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) { if(indev == NULL) return false; if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return false; @@ -815,7 +815,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->long_pr_sent = 0; proc->types.pointer.scroll_sum.x = 0; proc->types.pointer.scroll_sum.y = 0; - proc->types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; + proc->types.pointer.scroll_dir = LV_INDEV_SCROLL_DIR_NONE; proc->types.pointer.gesture_sent = 0; proc->types.pointer.gesture_sum.x = 0; proc->types.pointer.gesture_sum.y = 0; @@ -963,7 +963,7 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) indev->proc.longpr_rep_timestamp = 0; indev->proc.types.pointer.scroll_sum.x = 0; indev->proc.types.pointer.scroll_sum.y = 0; - indev->proc.types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; + indev->proc.types.pointer.scroll_dir = LV_INDEV_SCROLL_DIR_NONE; indev->proc.types.pointer.scroll_throw_vect.x = 0; indev->proc.types.pointer.scroll_throw_vect.y = 0; indev->proc.types.pointer.gesture_sum.x = 0; @@ -980,7 +980,7 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) static void indev_click_focus(lv_indev_proc_t * proc) { /*Handle click focus*/ - lv_obj_t * obj_to_focus = _lv_obj_get_focused_obj(indev_obj_act); + lv_obj_t * obj_to_focus = lv_obj_get_focused_obj(indev_obj_act); if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) && proc->types.pointer.last_pressed != obj_to_focus) { #if LV_USE_GROUP diff --git a/src/lv_core/lv_indev.h b/src/lv_core/lv_indev.h index 1708daf1e..2a038eb0d 100644 --- a/src/lv_core/lv_indev.h +++ b/src/lv_core/lv_indev.h @@ -121,7 +121,7 @@ uint32_t lv_indev_get_key(const lv_indev_t * indev); * @return LV_SCROLL_DIR_NONE: no scrolling now * LV_SCROLL_DIR_HOR/VER */ -lv_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); +lv_indev_scroll_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); /** * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and diff --git a/src/lv_core/lv_indev_scroll.c b/src/lv_core/lv_indev_scroll.c index f2da7cc98..4f0a30b08 100644 --- a/src/lv_core/lv_indev_scroll.c +++ b/src/lv_core/lv_indev_scroll.c @@ -71,7 +71,7 @@ void lv_indev_scroll_handler(lv_indev_proc_t * proc) lv_coord_t diff_x = 0; lv_coord_t diff_y = 0; - if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_HOR) { + if(proc->types.pointer.scroll_dir == LV_INDEV_SCROLL_DIR_HOR) { lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr); @@ -105,7 +105,7 @@ void lv_indev_scroll_throw_handler(lv_indev_proc_t * proc) { lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; if(scroll_obj == NULL) return; - if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_NONE) return; + if(proc->types.pointer.scroll_dir == LV_INDEV_SCROLL_DIR_NONE) return; lv_indev_t * indev_act = lv_indev_get_act(); @@ -119,7 +119,7 @@ void lv_indev_scroll_throw_handler(lv_indev_proc_t * proc) lv_snap_align_t align_x = lv_obj_get_snap_align_x(scroll_obj); lv_snap_align_t align_y = lv_obj_get_snap_align_y(scroll_obj); - if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_VER) { + if(proc->types.pointer.scroll_dir == LV_INDEV_SCROLL_DIR_VER) { proc->types.pointer.scroll_throw_vect.x = 0; /*If no snapping "throw"*/ if(align_y == LV_SCROLL_SNAP_ALIGN_NONE) { @@ -142,7 +142,7 @@ void lv_indev_scroll_throw_handler(lv_indev_proc_t * proc) lv_obj_scroll_by(scroll_obj, 0, diff_y + y, LV_ANIM_ON); } } - else if(proc->types.pointer.scroll_dir == LV_SCROLL_DIR_HOR) { + else if(proc->types.pointer.scroll_dir == LV_INDEV_SCROLL_DIR_HOR) { proc->types.pointer.scroll_throw_vect.y = 0; /*If no snapping "throw"*/ if(align_x == LV_SCROLL_SNAP_ALIGN_NONE) { @@ -202,7 +202,7 @@ void lv_indev_scroll_throw_handler(lv_indev_proc_t * proc) lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act); if(proc->reset_query) return; - proc->types.pointer.scroll_dir = LV_SCROLL_DIR_NONE; + proc->types.pointer.scroll_dir = LV_INDEV_SCROLL_DIR_NONE; proc->types.pointer.scroll_obj = NULL; } } @@ -303,7 +303,7 @@ static lv_obj_t * find_scroll_obj(lv_indev_proc_t * proc) (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) { obj_candidate = obj_act; - dir_candidate = LV_SCROLL_DIR_VER; + dir_candidate = LV_INDEV_SCROLL_DIR_VER; } if((sl > 0 || sr > 0) && @@ -311,7 +311,7 @@ static lv_obj_t * find_scroll_obj(lv_indev_proc_t * proc) (right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) { obj_candidate = obj_act; - dir_candidate = LV_SCROLL_DIR_HOR; + dir_candidate = LV_INDEV_SCROLL_DIR_HOR; } if(st <= 0) up_en = false; @@ -325,7 +325,7 @@ static lv_obj_t * find_scroll_obj(lv_indev_proc_t * proc) (up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) || (down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) { - proc->types.pointer.scroll_dir = hor_en ? LV_SCROLL_DIR_HOR : LV_SCROLL_DIR_VER; + proc->types.pointer.scroll_dir = hor_en ? LV_INDEV_SCROLL_DIR_HOR : LV_INDEV_SCROLL_DIR_VER; break; } @@ -351,7 +351,7 @@ static void init_scroll_limits(lv_indev_proc_t * proc) { lv_obj_t * obj = proc->types.pointer.scroll_obj; /*If there no STOP allow scrolling anywhere*/ - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_STOP) == false) { + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ONE) == false) { lv_area_set(&proc->types.pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX); } /*With STOP limit the scrolling to the perv and next snap point*/ diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 1b42d780e..02b52f48f 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -25,15 +25,6 @@ #include #include -#if defined(LV_GC_INCLUDE) - #include LV_GC_INCLUDE -#endif /* LV_ENABLE_GC */ - - -#if defined(LV_USER_DATA_FREE_INCLUDE) - #include LV_USER_DATA_FREE_INCLUDE -#endif /* LV_USE_USER_DATA_FREE */ - #include LV_THEME_DEFAULT_INCLUDE #if LV_USE_GPU_STM32_DMA2D @@ -69,6 +60,13 @@ typedef struct { const lv_anim_path_t * path; }trans_set_t; +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_obj_style_create_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8_t part, lv_state_t prev_state, + lv_state_t new_state, uint32_t time, uint32_t delay, const lv_anim_path_t * path); +_lv_style_state_cmp_t lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2); + /********************** * STATIC PROTOTYPES **********************/ @@ -76,10 +74,7 @@ static lv_draw_res_t lv_obj_draw(lv_obj_t * obj, const lv_area_t * clip_area, lv static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param); static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area); static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); -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); -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(lv_obj_t * obj); @@ -89,7 +84,7 @@ static void lv_obj_destructor(lv_obj_t * obj); **********************/ static bool lv_initialized = false; static lv_event_temp_data_t * event_temp_data_head; -static void * event_act_data; +static const void * event_act_data; const lv_obj_class_t lv_obj = { .constructor = lv_obj_constructor, .destructor = lv_obj_destructor, @@ -107,9 +102,6 @@ const lv_obj_class_t lv_obj = { * GLOBAL FUNCTIONS **********************/ -/** - * Init. the 'lv' library. - */ void lv_init(void) { /* Do nothing if already initialized */ @@ -143,23 +135,13 @@ void lv_init(void) #endif _lv_obj_style_init(); - _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); _lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); - lv_mem_monitor_t mon; - lv_mem_monitor(&mon); - printf("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d\n", - (int)mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct, - (int)mon.free_biggest_size); + lv_theme_t * th = LV_THEME_DEFAULT_INIT(LV_THEME_DEFAULT_COLOR_PRIMARY, LV_THEME_DEFAULT_COLOR_SECONDARY, LV_THEME_DEFAULT_FLAG, LV_THEME_DEFAULT_FONT_SMALL, LV_THEME_DEFAULT_FONT_NORMAL, LV_THEME_DEFAULT_FONT_SUBTITLE, LV_THEME_DEFAULT_FONT_TITLE); - lv_mem_monitor(&mon); - printf("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d\n", - (int)mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct, - (int)mon.free_biggest_size); - lv_theme_set_act(th); /*Initialize the screen refresh system*/ @@ -183,10 +165,6 @@ void lv_init(void) #if LV_ENABLE_GC || !LV_MEM_CUSTOM -/** - * Deinit the 'lv' library - * Currently only implemented when not using custom allocators, or GC is enabled. - */ void lv_deinit(void) { _lv_gc_clear_roots(); @@ -203,435 +181,110 @@ void lv_deinit(void) } #endif -/*-------------------- - * Create and delete - *-------------------*/ - -/** - * Create a basic object - * @param parent pointer to a parent object. - * If NULL then a screen will be created - * - * @param copy DEPRECATED, will be removed in v9. - * Pointer to an other base object to copy. - * @return pointer to the new object - */ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) { return lv_obj_create_from_class(&lv_obj, parent, copy); } -lv_obj_t * lv_obj_create_from_class(const lv_obj_class_t * class, lv_obj_t * parent, const lv_obj_t * copy) +/*--------------------- + * Event/Signal sending + *---------------------*/ + +lv_res_t lv_event_send(lv_obj_t * obj, lv_event_t event, const void * data) { - lv_obj_t * obj = lv_mem_alloc(class->instance_size); - lv_memset_00(obj, class->instance_size); - obj->class_p = class; + if(obj == NULL) return LV_RES_OK; - class->constructor(obj, parent, copy); - - if(!copy) lv_theme_apply(obj); -// else lv_style_list_copy(&checkbox->style_indic, &checkbox_copy->style_indic); - - return obj; -} - - -void lv_obj_construct_base(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) -{ - const lv_obj_class_t * original_class_p = obj->class_p; - - /*Don't let the descendant methods to run during constructing the ancestor type*/ - obj->class_p = obj->class_p->base_class; - - obj->class_p->constructor(obj, parent, copy); - - /*Restore the original class*/ - obj->class_p = original_class_p; - -} -/** - * Delete 'obj' and all of its children - * @param obj pointer to an object to delete - * @return LV_RES_INV because the object is deleted - */ -lv_res_t lv_obj_del(lv_obj_t * obj) -{ LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_obj_invalidate(obj); - lv_disp_t * disp = NULL; - bool act_scr_del = false; - lv_obj_t * par = lv_obj_get_parent(obj); - if(par == NULL) { - disp = lv_obj_get_disp(obj); - if(!disp) return LV_RES_INV; /*Shouldn't happen*/ - if(disp->act_scr == obj) act_scr_del = true; + /*Nothing to do if no event function and not bubbled*/ + lv_event_cb_t event_cb = lv_obj_get_event_cb(obj); + if(event_cb == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) == false) { + return LV_RES_OK; } - obj_del_core(obj); + /* Build a simple linked list from the objects used in the events + * It's important to know if an this object was deleted by a nested event + * called from this `event_cb`. */ + lv_event_temp_data_t event_temp_data; + event_temp_data.obj = obj; + event_temp_data.deleted = false; + event_temp_data.prev = NULL; - /*Send a signal to the parent to notify it about the child delete*/ - if(par) { - lv_signal_send(par, LV_SIGNAL_CHILD_CHG, NULL); + if(event_temp_data_head) { + event_temp_data.prev = event_temp_data_head; + } + event_temp_data_head = &event_temp_data; + + const void * event_act_data_save = event_act_data; + event_act_data = data; + + /*Call the input device's feedback callback if set*/ + lv_indev_t * indev_act = lv_indev_get_act(); + if(indev_act) { + if(indev_act->driver.feedback_cb) indev_act->driver.feedback_cb(&indev_act->driver, event); } - /*Handle if the active screen was deleted*/ - if(act_scr_del) { - disp->act_scr = NULL; - } + /*Call the event callback*/ + if(event_cb) event_cb(obj, event); - return LV_RES_INV; -} + /*Restore the event data*/ + event_act_data = event_act_data_save; -#if LV_USE_ANIMATION -/** - * A function to be easily used in animation ready callback to delete an object when the animation is ready - * @param a pointer to the animation - */ -void lv_obj_del_anim_ready_cb(lv_anim_t * a) -{ - lv_obj_del(a->var); -} -#endif + /*Remove this element from the list*/ + event_temp_data_head = event_temp_data_head->prev; -/** - * Helper function for asynchronously deleting objects. - * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). - * @param obj object to delete - * @see lv_async_call - */ -void lv_obj_del_async(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_async_call(lv_obj_del_async_cb, obj); -} + if(event_temp_data.deleted) return LV_RES_INV; -/** - * Delete all children of an object - * @param obj pointer to an object - */ -void lv_obj_clean(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + if(obj) { + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) && obj->parent) { - while(1) { - lv_obj_t * child = lv_obj_get_child(obj, 0); - obj_del_core(child); - } -} - -/** - * Mark an area of an object as invalid. - * This area will be redrawn by 'lv_refr_task' - * @param obj pointer to an object - * @param area the area to redraw - */ -void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_area_t area_tmp; - lv_area_copy(&area_tmp, area); - bool visible = lv_obj_area_is_visible(obj, &area_tmp); - - if(visible) _lv_inv_area(lv_obj_get_disp(obj), &area_tmp); -} - -/** - * Mark the object as invalid therefore its current position will be redrawn by 'lv_refr_task' - * @param obj pointer to an object - */ -void lv_obj_invalidate(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - /*Truncate the area to the object*/ - lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_pad(obj); - lv_area_copy(&obj_coords, &obj->coords); - obj_coords.x1 -= ext_size; - obj_coords.y1 -= ext_size; - obj_coords.x2 += ext_size; - obj_coords.y2 += ext_size; - - lv_obj_invalidate_area(obj, &obj_coords); - -} - -/** - * Tell whether an area of an object is visible (even partially) now or not - * @param obj pointer to an object - * @param area the are to check. The visible part of the area will be written back here. - * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) - */ -bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) -{ - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false; - - /*Invalidate the object only if it belongs to the current or previous'*/ - lv_obj_t * obj_scr = lv_obj_get_screen(obj); - lv_disp_t * disp = lv_obj_get_disp(obj_scr); - if(obj_scr == lv_disp_get_scr_act(disp) || - obj_scr == lv_disp_get_scr_prev(disp) || - obj_scr == lv_disp_get_layer_top(disp) || - obj_scr == lv_disp_get_layer_sys(disp)) { - - /*Truncate the area to the object*/ - lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_pad(obj); - lv_area_copy(&obj_coords, &obj->coords); - obj_coords.x1 -= ext_size; - obj_coords.y1 -= ext_size; - obj_coords.x2 += ext_size; - obj_coords.y2 += ext_size; - - bool is_common; - - is_common = _lv_area_intersect(area, area, &obj_coords); - if(is_common == false) return false; /*The area is not on the object*/ - - /*Truncate recursively to the parents*/ - lv_obj_t * par = lv_obj_get_parent(obj); - while(par != NULL) { - is_common = _lv_area_intersect(area, area, &par->coords); - if(is_common == false) return false; /*If no common parts with parent break;*/ - if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; /*If the parent is hidden then the child is hidden and won't be drawn*/ - - par = lv_obj_get_parent(par); + lv_res_t res = lv_event_send(obj->parent, event, data); + if(res != LV_RES_OK) return LV_RES_INV; } } - return true; + return LV_RES_OK; +} + + +void * lv_event_get_data(void) +{ + return event_act_data; } /** - * Tell whether an object is visible (even partially) now or not - * @param obj pointer to an object - * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) + * Nested events can be called and one of them might belong to an object that is being deleted. + * Mark this object's `event_temp_data` deleted to know that it's `lv_event_send` should return `LV_RES_INV` + * @param obj pointer to an obejct to mark as deleted */ -bool lv_obj_is_visible(const lv_obj_t * obj) +void lv_event_mark_deleted(lv_obj_t * obj) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_event_temp_data_t * t = event_temp_data_head; - lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_pad(obj); - lv_area_copy(&obj_coords, &obj->coords); - obj_coords.x1 -= ext_size; - obj_coords.y1 -= ext_size; - obj_coords.x2 += ext_size; - obj_coords.y2 += ext_size; + while(t) { + if(t->obj == obj) t->deleted = true; + t = t->prev; + } +} - return lv_obj_area_is_visible(obj, &obj_coords); +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->class_p->signal_cb) res = obj->class_p->signal_cb(obj, signal, param); + + return res; } /*===================== * Setter functions *====================*/ -/*-------------------- - * Parent/children set - *--------------------*/ - -/** - * Set a new parent for an object. Its relative position will be the same. - * @param obj pointer to an object. Can't be a screen. - * @param parent pointer to the new parent object. (Can't be NULL) - */ -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_parent = 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_parent->coords.x2 - obj->coords.x2; - - /*Remove the object from the old parent's child list*/ - int32_t i; - for(i = lv_obj_get_child_id(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) { - old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i+1]; - } - old_parent->spec_attr->child_cnt--; - if(old_parent->spec_attr->child_cnt) { - old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children, old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); - } else { - lv_mem_free(old_parent->spec_attr->children); - old_parent->spec_attr->children = NULL; - } - - /*Add the child to the new parent as the last (newest child)*/ - parent->spec_attr->child_cnt++; - parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); - parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj; - - 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_parent, 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); -} - -/** - * Move and object to the foreground - * @param obj pointer to an object - */ -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_obj_invalidate(parent); - - uint32_t i; - for(i = lv_obj_get_child_id(obj) - 1; i > 0; i--) { - parent->spec_attr->children[i] = parent->spec_attr->children[i-1]; - } - parent->spec_attr->children[0] = obj; - - /*Notify the new parent about the child*/ - lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); - - lv_obj_invalidate(parent); -} - -/** - * Move and object to the background - * @param obj pointer to an object - */ -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_obj_invalidate(parent); - - uint32_t i; - for(i = lv_obj_get_child_id(obj); i < lv_obj_get_child_cnt(parent) - 2; i++) { - parent->spec_attr->children[i] = parent->spec_attr->children[i + 1]; - } - parent->spec_attr->children[ lv_obj_get_child_cnt(parent) - 1] = obj; - - /*Notify the new parent about the child*/ - lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); - - lv_obj_invalidate(parent); -} - -/*-------------------- - * Coordinate set - * ------------------*/ - -/** - * Set the size of an extended clickable area - * If TINY mode is used, only the largest of the horizontal and vertical padding - * values are considered. - * @param obj pointer to an object - * @param left extended clickable are on the left [px] - * @param right extended clickable are on the right [px] - * @param top extended clickable are on the top [px] - * @param bottom extended clickable are on the bottom [px] - */ -void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right, lv_coord_t top, lv_coord_t bottom) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj); - obj->spec_attr->ext_click_pad.x1 = left; - obj->spec_attr->ext_click_pad.x2 = right; - obj->spec_attr->ext_click_pad.y1 = top; - obj->spec_attr->ext_click_pad.y2 = bottom; -#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj); - obj->spec_attr->ext_click_pad = LV_MAX4(left, right, top, bottom); -#else - LV_UNUSED(obj); - LV_UNUSED(left); - LV_UNUSED(right); - LV_UNUSED(top); - LV_UNUSED(bottom); -#endif -} - -/** - * Get the extended draw area of an object. - * @param obj pointer to an object - * @return the size extended draw area around the real coordinates - */ -lv_coord_t _lv_obj_get_ext_draw_pad(const lv_obj_t * obj) -{ - if(obj->spec_attr) return obj->spec_attr->ext_draw_size; - else return 0; -} -/*--------------------- - * Appearance set - *--------------------*/ - /*----------------- * Attribute set *----------------*/ -/** - * Set the base direction of the object - * @param obj pointer to an object - * @param dir the new base direction. `LV_BIDI_DIR_LTR/RTL/AUTO/INHERIT` - */ -void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) -{ - if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL && - dir != LV_BIDI_DIR_AUTO && dir != LV_BIDI_DIR_INHERIT) { - - LV_LOG_WARN("lv_obj_set_base_dir: invalid base dir"); - return; - } - - lv_obj_allocate_spec_attr(obj); - obj->spec_attr->base_dir = dir; - lv_signal_send(obj, LV_SIGNAL_BASE_DIR_CHG, NULL); - - /* Notify the children about the parent base dir has changed. - * (The children might have `LV_BIDI_DIR_INHERIT`)*/ - base_dir_refr_children(obj); -} - - void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -644,8 +297,6 @@ void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) } - - void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -656,15 +307,6 @@ void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) if(f & LV_OBJ_FLAG_LAYOUTABLE) lv_signal_send(lv_obj_get_parent(obj), LV_SIGNAL_CHILD_CHG, obj); } - - -/** - * Set the state (fully overwrite) of an object. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the new state - */ void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) { if(obj->state == new_state) return; @@ -673,12 +315,12 @@ void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) #if LV_USE_ANIMATION == 0 obj->state = new_state; - _lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); + lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); #else lv_state_t prev_state = obj->state; obj->state = new_state; - _lv_style_state_cmp_t cmp_res = _lv_obj_style_state_compare(obj, prev_state, new_state); + _lv_style_state_cmp_t cmp_res = lv_obj_style_state_compare(obj, prev_state, new_state); /*If there is no difference in styles there is nothing else to do*/ if(cmp_res == _LV_STYLE_STATE_CMP_SAME) return; @@ -718,26 +360,18 @@ void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) } for(i = 0;i < tsi; i++) { - _lv_obj_create_style_transition(obj, ts[i].prop, ts[i].part, prev_state, new_state, ts[i].time, ts[i].delay, ts[i].path); + lv_obj_style_create_transition(obj, ts[i].prop, ts[i].part, prev_state, new_state, ts[i].time, ts[i].delay, ts[i].path); } lv_mem_buf_release(ts); - if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); + if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD) lv_obj_refresh_ext_draw_size(obj); else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_REDRAW) lv_obj_invalidate(obj); #endif } - -/** - * Add a given state or states to the object. The other state bits will remain unchanged. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the state bits to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` - */ void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -748,13 +382,6 @@ void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) } } -/** - * Remove a given state or states to the object. The other state bits will remain unchanged. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the state bits to remove. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` - */ void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -765,418 +392,37 @@ void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) } } - -/** - * Set a an event handler function for an object. - * Used by the user to react on event which happens with the object. - * @param obj pointer to an object - * @param event_cb the new event function - */ void lv_obj_set_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - if(obj->spec_attr == NULL) obj->spec_attr = lv_obj_allocate_spec_attr(obj); + lv_obj_allocate_spec_attr(obj); obj->spec_attr->event_cb = event_cb; } -/** - * Send an event to the object - * @param obj pointer to an object - * @param event the type of the event from `lv_event_t` - * @param data arbitrary data depending on the object type and the event. (Usually `NULL`) - * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event - */ -lv_res_t lv_event_send(lv_obj_t * obj, lv_event_t event, const void * data) +void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) { - if(obj == NULL) return LV_RES_OK; + if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL && + dir != LV_BIDI_DIR_AUTO && dir != LV_BIDI_DIR_INHERIT) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - /*Nothing to do if no event function and not bubbled*/ - if(lv_obj_get_event_cb(obj) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) == false) { - return LV_RES_OK; - } - lv_res_t res; - res = lv_event_send_func(lv_obj_get_event_cb(obj), obj, event, data); - return res; -} - -/** - * Send LV_EVENT_REFRESH event to an object - * @param obj point to an obejct. (Can NOT be NULL) - * @return LV_RES_OK: success, LV_RES_INV: to object become invalid (e.g. deleted) due to this event. - */ -lv_res_t lv_event_send_refresh(lv_obj_t * obj) -{ - return lv_event_send(obj, LV_EVENT_REFRESH, NULL); -} - -/** - * Send LV_EVENT_REFRESH event to an object and all of its children. - * @param obj pointer to an object or NULL to refresh all objects of all displays - */ -void lv_event_send_refresh_recursive(lv_obj_t * obj) -{ - if(obj == NULL) { - /*If no obj specified refresh all screen of all displays */ - lv_disp_t * d = lv_disp_get_next(NULL); - while(d) { - 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); - - d = lv_disp_get_next(d); - } - } - else { - - lv_res_t res = lv_event_send_refresh(obj); - if(res != LV_RES_OK) return; /*If invalid returned do not check the children*/ - - 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)); - } - } -} - - -/** - * Call an event function with an object, event, and data. - * @param event_xcb an event callback function. If `NULL` `LV_RES_OK` will return without any actions. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows - * the `func_name(object, callback, ...)` convention) - * @param obj pointer to an object to associate with the event (can be `NULL` to simply call the `event_cb`) - * @param event an event - * @param data pointer to a custom data - * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event - */ -lv_res_t lv_event_send_func(lv_event_cb_t event_xcb, lv_obj_t * obj, lv_event_t event, const void * data) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - /* Build a simple linked list from the objects used in the events - * It's important to know if an this object was deleted by a nested event - * called from this `event_cb`. */ - lv_event_temp_data_t event_temp_data; - event_temp_data.obj = obj; - event_temp_data.deleted = false; - event_temp_data.prev = NULL; - - if(event_temp_data_head) { - event_temp_data.prev = event_temp_data_head; - } - event_temp_data_head = &event_temp_data; - - const void * event_act_data_save = event_act_data; - event_act_data = data; - - /*Call the input device's feedback callback if set*/ - lv_indev_t * indev_act = lv_indev_get_act(); - if(indev_act) { - if(indev_act->driver.feedback_cb) indev_act->driver.feedback_cb(&indev_act->driver, event); + LV_LOG_WARN("lv_obj_set_base_dir: invalid base direction: %d", dir); + return; } - /*Call the event callback itself*/ - if(event_xcb) event_xcb(obj, event); + lv_obj_allocate_spec_attr(obj); + obj->spec_attr->base_dir = dir; + lv_signal_send(obj, LV_SIGNAL_BASE_DIR_CHG, NULL); - /*Restore the event data*/ - event_act_data = event_act_data_save; - - /*Remove this element from the list*/ - event_temp_data_head = event_temp_data_head->prev; - - if(event_temp_data.deleted) return LV_RES_INV; - - if(obj) { - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) && obj->parent) { - - lv_res_t res = lv_event_send(obj->parent, event, data); - if(res != LV_RES_OK) return LV_RES_INV; - } - } - - return LV_RES_OK; + /* Notify the children about the parent base dir has changed. + * (The children might have `LV_BIDI_DIR_INHERIT`)*/ + base_dir_refr_children(obj); } -/** - * Get the `data` parameter of the current event - * @return the `data` parameter - */ -void * lv_event_get_data(void) -{ - return event_act_data; -} -/** - * Send an event to the object - * @param obj pointer to an object - * @param event the type of the event from `lv_event_t`. - * @return LV_RES_OK or LV_RES_INV - */ -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->class_p->signal_cb) res = obj->class_p->signal_cb(obj, signal, param); - - return res; -} - -/*---------------- - * 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 - */ -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++; - obj->spec_attr = lv_mem_alloc(sizeof(lv_obj_spec_attr_t)); - LV_ASSERT_MEM(obj->spec_attr); - if(obj->spec_attr == NULL) return NULL; - - lv_memset_00(obj->spec_attr, sizeof(lv_obj_spec_attr_t)); - - obj->spec_attr->scroll_dir = LV_DIR_ALL; - obj->spec_attr->base_dir = LV_BIDI_DIR_INHERIT; - obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO; - - } - return obj->spec_attr; -} /*======================= * Getter functions *======================*/ -/** - * Return with the screen of an object - * @param obj pointer to an object - * @return pointer to a screen - */ -lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - const lv_obj_t * par = obj; - const lv_obj_t * act_p; - - do { - act_p = par; - par = lv_obj_get_parent(act_p); - } while(par != NULL); - - return (lv_obj_t *)act_p; -} - -/** - * Get the display of an object - * @param scr pointer to an object - * @return pointer the object's display - */ -lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - 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`*/ - - lv_disp_t * d; - _LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) { - uint32_t i; - for(i = 0; i < d->screen_cnt; i++) { - if(d->screens[i] == scr) return d; - } - } - - LV_LOG_WARN("No screen found") - return NULL; -} - -/*--------------------- - * Parent/children get - *--------------------*/ - -/** - * Returns with the parent of an object - * @param obj pointer to an object - * @return pointer to the parent of 'obj' - */ -lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->parent; -} - -/** - * 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(const lv_obj_t * obj, uint32_t id) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - if(obj->spec_attr == NULL) return NULL; - - 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; -} - -/** - * Get the child index of an object. - * If this object is the firstly created child of its parent 0 will be return. - * If its the second child return 1, etc. - * @param obj pointer to an object whose index should be get - * @return the child index of the object. - */ -uint32_t lv_obj_get_child_id(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_t * parent = lv_obj_get_parent(obj); - if(parent == NULL) return 0; - - 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 0xFFFFFFFF; -} - -/** Recursively count the children of an object - * @param obj pointer to an object - * @return children number of 'obj' - */ -uint32_t lv_obj_count_children_recursive(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - uint16_t cnt = 0; - - 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; -} - -/*--------------------- - * Coordinate get - *--------------------*/ - -/** - * Get the extended extended clickable area in a direction - * @param obj pointer to an object - * @param dir in which direction get the extended area (`LV_DIR_LEFT/RIGHT/TOP`) - * @return the extended left padding - */ -lv_coord_t lv_obj_get_ext_click_area(const lv_obj_t * obj, lv_dir_t dir) -{ - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_OFF - LV_UNUSED(obj); - LV_UNUSED(dir); - return 0; -#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - LV_UNUSED(dir); - if(obj->spec_attr) return obj->spec_attr->ext_click_pad; - else return 0; -#else - switch(dir) { - case LV_DIR_LEFT: - return obj->spec_attr->ext_click_pad.x1; - case LV_DIR_RIGHT: - return obj->spec_attr->ext_click_pad.x2; - case LV_DIR_TOP: - return obj->spec_attr->ext_click_pad.y1; - case LV_DIR_BOTTOM: - return obj->spec_attr->ext_click_pad.y2; - default: - return 0; - } -#endif -} - - -/** - * Check if a given screen-space point is on an object's coordinates. - * This method is intended to be used mainly by advanced hit testing algorithms to check - * whether the point is even within the object (as an optimization). - * @param obj object to check - * @param point screen-space point - */ -bool _lv_obj_is_click_point_on(lv_obj_t * obj, const lv_point_t * point) -{ -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_OFF - return _lv_area_is_point_on(&obj->coords, point, 0); -#else - lv_area_t ext_area; - ext_area.x1 = obj->coords.x1 - lv_obj_get_ext_click_area(obj, LV_DIR_LEFT); - ext_area.x2 = obj->coords.x2 + lv_obj_get_ext_click_area(obj, LV_DIR_RIGHT); - ext_area.y1 = obj->coords.y1 - lv_obj_get_ext_click_area(obj, LV_DIR_TOP); - ext_area.y2 = obj->coords.y2 + lv_obj_get_ext_click_area(obj, LV_DIR_BOTTOM); - - return _lv_area_is_point_on(&ext_area, point, 0); -#endif -} - -/** - * Hit-test an object given a particular point in screen space. - * @param obj object to hit-test - * @param point screen-space point - * @return true if the object is considered under the point - */ -bool lv_obj_hit_test(lv_obj_t * obj, lv_point_t * point) -{ - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_ADV_HITTEST)) { - lv_hit_test_info_t hit_info; - hit_info.point = point; - hit_info.result = true; - lv_signal_send(obj, LV_SIGNAL_HIT_TEST, &hit_info); - return hit_info.result; - } - else { - return _lv_obj_is_click_point_on(obj, point); - } -} -/*----------------- - * Appearance get - *---------------*/ - - -/*----------------- - * Attribute get - *----------------*/ - bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -1215,11 +461,6 @@ lv_state_t lv_obj_get_state(const lv_obj_t * obj) return ((lv_obj_t *)obj)->state; } -/** - * Get the event function of an object - * @param obj pointer to an object - * @return the event function - */ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -1228,15 +469,6 @@ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj) else return NULL; } -/*------------------ - * Other get - *-----------------*/ - -/** - * Get the group of the object - * @param obj pointer to an object - * @return the pointer to group of the object - */ void * lv_obj_get_group(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -1250,45 +482,31 @@ void * lv_obj_get_group(const lv_obj_t * obj) #endif } -/** - * Tell whether the object is the focused object of a group or not. - * @param obj pointer to an object - * @return true: the object is focused, false: the object is not focused or not in a group - */ -bool lv_obj_is_focused(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - -#if LV_USE_GROUP - lv_group_t * g = lv_obj_get_group(obj); - if(g) { - if(lv_group_get_focused(g) == obj) return true; - } - return false; -#else - LV_UNUSED(obj); - return false; -#endif -} - -lv_obj_t ** lv_obj_get_children(const lv_obj_t * obj) -{ - static lv_obj_t * empty[1] = {NULL}; - if(obj->spec_attr) return obj->spec_attr->children; - else return empty; -} - /*------------------- * OTHER FUNCTIONS *------------------*/ +void lv_obj_allocate_spec_attr(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); -/** - * Get the really focused object by taking `focus_parent` into account. - * @param obj the start object - * @return the object to really focus - */ -lv_obj_t * _lv_obj_get_focused_obj(const lv_obj_t * obj) + if(obj->spec_attr == NULL) { + static uint32_t x = 0; + x++; + obj->spec_attr = lv_mem_alloc(sizeof(lv_obj_spec_attr_t)); + LV_ASSERT_MEM(obj->spec_attr); + if(obj->spec_attr == NULL) return; + + lv_memset_00(obj->spec_attr, sizeof(lv_obj_spec_attr_t)); + + obj->spec_attr->scroll_dir = LV_DIR_ALL; + obj->spec_attr->base_dir = LV_BIDI_DIR_INHERIT; + obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO; + + } +} + +lv_obj_t * lv_obj_get_focused_obj(const lv_obj_t * obj) { if(obj == NULL) return NULL; const lv_obj_t * focus_obj = obj; @@ -1299,33 +517,16 @@ lv_obj_t * _lv_obj_get_focused_obj(const lv_obj_t * obj) return (lv_obj_t *)focus_obj; } -/** - * 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 - */ bool lv_obj_check_type(const lv_obj_t * obj, const void * class_p) { return obj->class_p == class_p ? true : false; } -/** - * Check if any object has a given type - * @param obj pointer to an object - * @param obj_type type of the object. (e.g. "lv_btn") - * @return true: valid - */ + bool _lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type) { return true; } -/** - * Check if any object is still "alive", and part of the hierarchy - * @param obj pointer to an object - * @param obj_type type of the object. (e.g. "lv_btn") - * @return true: valid - */ bool _lv_debug_check_obj_valid(const lv_obj_t * obj) { lv_disp_t * disp = lv_disp_get_next(NULL); @@ -1347,69 +548,6 @@ bool _lv_debug_check_obj_valid(const lv_obj_t * obj) * STATIC FUNCTIONS **********************/ -static void lv_obj_del_async_cb(void * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_del(obj); -} - -static void obj_del_core(lv_obj_t * obj) -{ - /*Let the user free the resources used in `LV_EVENT_DELETE`*/ - lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL); - if(res == LV_RES_INV) return; - - /*Delete from the group*/ -#if LV_USE_GROUP - lv_group_t * group = lv_obj_get_group(obj); - if(group) lv_group_remove_obj(obj); -#endif - - /*Remove the animations from this object*/ -#if LV_USE_ANIMATION - lv_anim_del(obj, NULL); - _lv_obj_remove_style_trans(obj); -#endif - - /*Delete the user data*/ -#if LV_USE_USER_DATA -#if LV_USE_USER_DATA_FREE - LV_USER_DATA_FREE(obj); -#endif -#endif - - /*Recursively delete the children*/ - while(1) { - lv_obj_t * child = lv_obj_get_child(obj, 0); - obj_del_core(child); - } - - lv_event_mark_deleted(obj); - - /* Reset all input devices if the object to delete is used*/ - lv_indev_t * indev = lv_indev_get_next(NULL); - while(indev) { - if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { - lv_indev_reset(indev, obj); - } - if(indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; - } - -#if LV_USE_GROUP - if(indev->group == group && obj == lv_indev_get_obj_act()) { - lv_indev_reset(indev, obj); - } -#endif - indev = lv_indev_get_next(indev); - } - - /* All children deleted. - * Now clean up the object specific data*/ - obj->class_p->destructor(obj); -} - static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) { /*Create a screen*/ @@ -1442,7 +580,7 @@ static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t 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); + lv_obj_allocate_spec_attr(parent); } if(parent->spec_attr->children == NULL) { @@ -1513,8 +651,10 @@ static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t } else { lv_obj_set_pos(obj, 0, 0); } - /*Send a signal to the parent to notify it about the new child*/ - if(parent != NULL) { + + if(parent) { + /* Send a signal to the parent to notify it about the new child. + * Also triggers layout update*/ lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); /*Invalidate the area if not screen created*/ @@ -1527,20 +667,11 @@ static void lv_obj_constructor(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t static void lv_obj_destructor(lv_obj_t * p) { lv_obj_t * obj = p; - lv_obj_remove_all_styles(obj); +// lv_obj_remove_all_styles(obj); if(obj->spec_attr) lv_mem_free(obj->spec_attr); } -/** - * Handle the drawing related tasks of the base objects. - * @param obj pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DRAW_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DRAW_DRAW: draw the object (always return 'true') - * @param return an element of `lv_draw_res_t` - */ static lv_draw_res_t lv_obj_draw(lv_obj_t * obj, const lv_area_t * clip_area, lv_draw_mode_t mode) { if(mode == LV_DRAW_MODE_COVER_CHECK) { @@ -1626,49 +757,6 @@ static lv_draw_res_t lv_obj_draw(lv_obj_t * obj, const lv_area_t * clip_area, lv coords.y2 += h; lv_draw_rect(&coords, clip_area, &draw_dsc); } - -#if GRID_DEBUG - /*Draw the grid cells*/ - if(lv_obj_get_grid(obj)) { - _lv_grid_calc_t calc; - _lv_grid_calc(obj, &calc); - - /*Create a color unique to this object. */ - uint32_t cx = ((lv_uintptr_t) obj) & 0xFFFFFF; - cx = (cx & 0xff) ^ ((cx >> 8) & 0xff) ^ ((cx >> 16) & 0xff) ^ ((cx >> 24) & 0xff); - lv_color_t c = lv_color_hsv_to_rgb(cx & 0xff, 100, 100); - - lv_draw_rect_dsc_t grid_rect_dsc; - lv_draw_rect_dsc_init(&grid_rect_dsc); - grid_rect_dsc.bg_color = c; - grid_rect_dsc.bg_opa = LV_OPA_10; - grid_rect_dsc.border_width = 2; - grid_rect_dsc.border_color = c; - grid_rect_dsc.border_opa = LV_OPA_30; - - lv_point_t grid_abs; - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN); - grid_abs.x = pad_left + obj->coords.x1 - lv_obj_get_scroll_x(obj); - grid_abs.y = pad_top + obj->coords.y1 - lv_obj_get_scroll_y(obj); - - uint32_t row; - uint32_t col; - for(row = 0; row < calc.row_num; row ++) { - for(col = 0; col < calc.col_num; col ++) { - lv_area_t a; - a.x1 = grid_abs.x + calc.x[col]; - a.x2 = a.x1 + calc.w[col]; - a.y1 = grid_abs.y + calc.y[row]; - a.y2 = a.y1 + calc.h[row]; - lv_draw_rect(&a, clip_area, &grid_rect_dsc); - } - } - - - _lv_grid_calc_free(&calc); - } -#endif } return LV_DRAW_RES_OK; @@ -1678,7 +766,7 @@ static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) == false) return; - lv_scroll_dir_t sm = lv_obj_get_scrollbar_mode(obj); + lv_indev_scroll_dir_t sm = lv_obj_get_scrollbar_mode(obj); if(sm == LV_SCROLLBAR_MODE_OFF) return; /*If there is no indev scrolling this object but `mode==active` return*/ @@ -1696,13 +784,13 @@ static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area) lv_coord_t sl = lv_obj_get_scroll_left(obj); lv_coord_t sr = lv_obj_get_scroll_right(obj); - lv_scroll_dir_t dir = lv_obj_get_scroll_dir(obj); + lv_indev_scroll_dir_t dir = lv_obj_get_scroll_dir(obj); bool ver_draw = false; if((dir & LV_DIR_VER) && ((sm == LV_SCROLLBAR_MODE_ON) || (sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) || - (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_VER))) { + (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_INDEV_SCROLL_DIR_VER))) { ver_draw = true; } @@ -1711,7 +799,7 @@ static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area) if((dir & LV_DIR_HOR) && ((sm == LV_SCROLLBAR_MODE_ON) || (sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) || - (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_SCROLL_DIR_HOR))) { + (sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_INDEV_SCROLL_DIR_HOR))) { hor_draw = true; } @@ -1846,25 +934,6 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc } -static void base_dir_refr_children(lv_obj_t * obj) -{ - 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); - } - } -} - -/** - * Signal function of the basic object - * @param obj pointer to an object - * @param sign signal type - * @param param parameter for the signal (depends on signal type) - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) { lv_res_t res = LV_RES_OK; @@ -1877,18 +946,8 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) /*Go the checked state if enabled*/ if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { - uint32_t toggled = 0; - if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) { - lv_obj_add_state(obj, LV_STATE_CHECKED); - toggled = 0; - } - else { - lv_obj_clear_state(obj, LV_STATE_CHECKED); - toggled = 1; - } - - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &toggled); - if(res != LV_RES_OK) return res; + if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) lv_obj_add_state(obj, LV_STATE_CHECKED); + else lv_obj_clear_state(obj, LV_STATE_CHECKED); } } else if(sign == LV_SIGNAL_PRESS_LOST) { @@ -1926,18 +985,17 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) editing = lv_group_get_editing(lv_obj_get_group(obj)); #endif if(editing) { - uint8_t state = LV_STATE_FOCUSED; + lv_state_t state = LV_STATE_FOCUSED; state |= LV_STATE_EDITED; /*if using focus mode, change target to parent*/ - obj = _lv_obj_get_focused_obj(obj); + obj = lv_obj_get_focused_obj(obj); lv_obj_add_state(obj, state); } else { - /*if using focus mode, change target to parent*/ - obj = _lv_obj_get_focused_obj(obj); + obj = lv_obj_get_focused_obj(obj); lv_obj_add_state(obj, LV_STATE_FOCUSED); lv_obj_clear_state(obj, LV_STATE_EDITED); @@ -1951,7 +1009,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_DEFOCUS) { /*if using focus mode, change target to parent*/ - obj = _lv_obj_get_focused_obj(obj); + obj = lv_obj_get_focused_obj(obj); lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED); } @@ -1983,6 +1041,11 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_obj_set_size(obj, obj->w_set, obj->h_set); } } + else if(sign == LV_SIGNAL_BASE_DIR_CHG) { + /* The layout might depend on the base dir. + * E.g. the first is element is on the left or right*/ + lv_obj_update_layout(obj, NULL); + } else if(sign == LV_SIGNAL_SCROLL) { res = lv_event_send(obj, LV_EVENT_SCROLL, NULL); if(res != LV_RES_OK) return res; @@ -2018,17 +1081,19 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) return res; } - -static void lv_event_mark_deleted(lv_obj_t * obj) +static void base_dir_refr_children(lv_obj_t * obj) { - lv_event_temp_data_t * t = event_temp_data_head; - - while(t) { - if(t->obj == obj) t->deleted = true; - t = t->prev; + 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); + } } } + static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find) { /*Check all children of `parent`*/ diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 3c4ca6a2d..206e5bfe0 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -22,12 +22,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" -#include "../lv_draw/lv_draw_line.h" -#include "../lv_draw/lv_draw_img.h" /********************* * DEFINES @@ -42,12 +37,13 @@ extern "C" { #error "LVGL: LV_ANTIALIAS can be only 0 or 1" #endif -#define LV_MAX_ANCESTOR_NUM 8 -#define _LV_OBJ_PART_MAX 32 - -#define LV_EXT_CLICK_AREA_OFF 0 -#define LV_EXT_CLICK_AREA_TINY 1 -#define LV_EXT_CLICK_AREA_FULL 2 +/** + * Options for extra click area behavior. + * These values can be selected in `lv_conf.h` + */ +#define LV_EXT_CLICK_AREA_OFF 0 /*Disable the usage of extra click area*/ +#define LV_EXT_CLICK_AREA_TINY 1 /*Use the same value in all 4 directions*/ +#define LV_EXT_CLICK_AREA_FULL 2 /*Allow setting different values in every 4 directions*/ /********************** * TYPEDEFS @@ -55,8 +51,14 @@ extern "C" { struct _lv_obj_t; +/*--------------------- + * EVENTS + *---------------------*/ -enum { +/** + * Type of event being sent to the object. + */ +typedef enum { LV_EVENT_PRESSED, /**< The object has been pressed*/ LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ LV_EVENT_PRESS_LOST, /**< User is still pressing but slid cursor/finger off of the object */ @@ -77,8 +79,6 @@ enum { LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved) */ LV_EVENT_INSERT, LV_EVENT_REFRESH, - LV_EVENT_APPLY, /**< "Ok", "Apply" or similar specific button has clicked*/ - LV_EVENT_CANCEL, /**< "Close", "Cancel" or similar specific button has clicked*/ LV_EVENT_DELETE, /**< Object is being deleted */ LV_EVENT_COVER_CHECK, /**< Check if the object fully covers the 'mask_p' area */ @@ -91,9 +91,8 @@ enum { LV_EVENT_DRAW_PART_BEGIN, LV_EVENT_DRAW_PART_END, - _LV_EVENT_LAST /** Number of events*/ -}; -typedef uint8_t lv_event_t; /**< Type of event being sent to the object. */ + _LV_EVENT_LAST /** Number of default events*/ +}lv_event_t; /** * @brief Event callback. @@ -102,17 +101,24 @@ typedef uint8_t lv_event_t; /**< Type of event being sent to the object. */ */ typedef void (*lv_event_cb_t)(struct _lv_obj_t * obj, lv_event_t event); + +/*--------------------- + * EVENTS + *---------------------*/ + + /** Signals are for use by the object itself or to extend the object's functionality. - * Applications should use ::lv_obj_set_event_cb to be notified of events that occur - * on the object. */ -enum { + * They determine a widget with a given type should behave. + * Applications should use ::lv_obj_set_event_cb to be notified of events that occur + * on the object. */ +typedef enum { /*General signals*/ - 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_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_SIZE, /**< Object's extra padding has changed */ - LV_SIGNAL_GET_SELF_SIZE, /**< Get the internal size of a widget*/ + LV_SIGNAL_GET_SELF_SIZE, /**< Get the internal size of a widget*/ /*Input device related*/ LV_SIGNAL_HIT_TEST, /**< Advanced hit-testing */ @@ -125,56 +131,95 @@ enum { LV_SIGNAL_SCROLL_BEGIN, /**< The scrolling has just begun */ LV_SIGNAL_SCROLL, /**< The object has been scrolled */ LV_SIGNAL_SCROLL_END, /**< The scrolling has ended */ - LV_SIGNAL_GESTURE, /**< The object has been gesture*/ - LV_SIGNAL_LEAVE, /**< Another object is clicked or chosen via an input device */ - - /*Group related*/ - LV_SIGNAL_FOCUS, - LV_SIGNAL_DEFOCUS, - LV_SIGNAL_CONTROL, - LV_SIGNAL_GET_EDITABLE, -}; -typedef uint8_t lv_signal_t; + LV_SIGNAL_GESTURE, /**< The object has been gesture*/ + LV_SIGNAL_LEAVE, /**< Another object is clicked or chosen via an input device */ + LV_SIGNAL_FOCUS, /**< The object was focused */ + LV_SIGNAL_DEFOCUS, /**< The object was de-focused */ + LV_SIGNAL_CONTROL, /**< Send a (control) character to the widget */ +} lv_signal_t; +/** + * @brief Signal callback. + * Signals are used to notify the widget of the action related to the object. + * For details, see ::lv_signal_t. + */ typedef lv_res_t (*lv_signal_cb_t)(struct _lv_obj_t * obj, lv_signal_t sign, void * param); - +/** + * Possible states of a widget. + * OR-ed values are possible + */ enum { - LV_STATE_DEFAULT = 0x00, - LV_STATE_CHECKED = 0x01, - LV_STATE_FOCUSED = 0x02, - LV_STATE_EDITED = 0x04, - LV_STATE_HOVERED = 0x08, - LV_STATE_PRESSED = 0x10, - LV_STATE_SCROLLED = 0x20, - LV_STATE_DISABLED = 0x40, - LV_STATE_USER = 0x80, /** Free to use by the user */ + LV_STATE_DEFAULT = 0x00, + LV_STATE_CHECKED = 0x01, + LV_STATE_FOCUSED = 0x02, + LV_STATE_KEY_FOCUSED = 0x04, + LV_STATE_EDITED = 0x08, + LV_STATE_HOVERED = 0x10, + LV_STATE_PRESSED = 0x20, + LV_STATE_SCROLLED = 0x40, + LV_STATE_DISABLED = 0x80, + + LV_STATE_ANY = 0x1FF, /**< Special value can be used in some functions to target all states */ }; -typedef uint8_t lv_state_t; +typedef uint16_t lv_state_t; +/** + * The possible parts of widgets. + * The parts can be considered as the internal building block of the widgets. + * E.g. slider = background + indicator + knob + * Note every part is used by every widget + */ enum { - LV_OBJ_FLAG_HIDDEN = (1 << 0), - LV_OBJ_FLAG_CLICKABLE = (1 << 1), - LV_OBJ_FLAG_CLICK_FOCUSABLE = (1 << 2), - LV_OBJ_FLAG_CHECKABLE = (1 << 3), - LV_OBJ_FLAG_SCROLLABLE = (1 << 4), - 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_CHAIN = (1 << 8), /** Allow propagating the scroll to a parent */ - LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1 << 9), /** Automatically scroll the focused object's ancestors to make the focused object visible*/ - LV_OBJ_FLAG_SNAPABLE = (1 << 10), - LV_OBJ_FLAG_PRESS_LOCK = (1 << 11), - LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 12), - LV_OBJ_FLAG_GESTURE_BUBBLE = (1 << 13), - LV_OBJ_FLAG_FOCUS_BUBBLE = (1 << 14), - LV_OBJ_FLAG_ADV_HITTEST = (1 << 15), - LV_OBJ_FLAG_LAYOUTABLE = (1 << 16), + LV_PART_MAIN, /**< A background like rectangle*/ + LV_PART_SCROLLBAR, /**< The scrollbar(s)*/ + LV_PART_INDICATOR, /**< Indicator, e.g. for slider, bar, switch, */ + LV_PART_KNOB, /**< Like handle to grab to adjust the value */ + LV_PART_SELECTED, /**< Indicate the currently selected option or section*/ + LV_PART_PLACEHOLDER, /**< A text other element used when the widget is empty*/ + LV_PART_ITEMS, /**< Used if the widget has multiple similar elements (e.g. tabel cells)*/ + LV_PART_MARKER, /**< Tick box of a check box, cursor of a text area or anything used to mark something*/ + + LV_PART_CUSTOM_1, /**< Extension point for custom widgets*/ + LV_PART_CUSTOM_2, /**< Extension point for custom widgets*/ + LV_PART_CUSTOM_3, /**< Extension point for custom widgets*/ + LV_PART_CUSTOM_4, /**< Extension point for custom widgets*/ + + LV_PART_ANY = 0xFF, /**< Special value can be used in some functions to target all parts */ +}; + +typedef uint16_t lv_part_t; + +/** + * On/Off features controlling the object's behavior. + * OR-ed values are possible + */ +enum { + LV_OBJ_FLAG_HIDDEN = (1 << 0), /**< Make the object hidden. (Like it wasn't there at all) */ + LV_OBJ_FLAG_CLICKABLE = (1 << 1), /**< Make the object clickable by the input devices */ + LV_OBJ_FLAG_CLICK_FOCUSABLE = (1 << 2), /**< Add focused state to the object when clicked */ + LV_OBJ_FLAG_CHECKABLE = (1 << 3), /**< Toggle checked state when the object is clicked */ + LV_OBJ_FLAG_SCROLLABLE = (1 << 4), /**< Make the object scrollable*/ + LV_OBJ_FLAG_SCROLL_ELASTIC = (1 << 5), /**< Allow scrolling inside but with slower speed*/ + LV_OBJ_FLAG_SCROLL_MOMENTUM = (1 << 6), /**< Make the object scroll further when "thrown"*/ + LV_OBJ_FLAG_SCROLL_ONE = (1 << 7), /**< Allow scrolling only one snappable children*/ + LV_OBJ_FLAG_SCROLL_CHAIN = (1 << 8), /**< Allow propagating the scroll to a parent */ + LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1 << 9), /**< Automatically scroll object to make it visible when focused*/ + LV_OBJ_FLAG_SNAPABLE = (1 << 10), /**< If scroll snap is enabled it can snap to this object*/ + LV_OBJ_FLAG_PRESS_LOCK = (1 << 11), /**< Keep the object pressed even if the press slid from the object */ + LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 12), /**< Propagate the events to the parent too */ + LV_OBJ_FLAG_GESTURE_BUBBLE = (1 << 13), /**< Propagate the gestures to the parent */ + LV_OBJ_FLAG_FOCUS_BUBBLE = (1 << 14), /**< Propagate the focus to the parent */ + LV_OBJ_FLAG_ADV_HITTEST = (1 << 15), /**< Allow performing more accurate hit (click) test. E.g. on rounded corners. */ + LV_OBJ_FLAG_LAYOUTABLE = (1 << 16), /**< MAke the object position-able by the layouts */ + LV_OBJ_FLAG_LAYOUT_1 = (1 << 24), /** Custom flag, free to use by layouts*/ LV_OBJ_FLAG_LAYOUT_2 = (1 << 25), /** Custom flag, free to use by layouts*/ + LV_OBJ_FLAG_WIDGET_1 = (1 << 26), /** Custom flag, free to use by widget*/ LV_OBJ_FLAG_WIDGET_2 = (1 << 27), /** Custom flag, free to use by widget*/ + LV_OBJ_FLAG_USER_1 = (1 << 28), /** Custom flag, free to use by user*/ LV_OBJ_FLAG_USER_2 = (1 << 29), /** Custom flag, free to use by user*/ LV_OBJ_FLAG_USER_3 = (1 << 30), /** Custom flag, free to use by user*/ @@ -182,6 +227,7 @@ enum { }; typedef uint32_t lv_obj_flag_t; +#include "lv_obj_tree.h" #include "lv_obj_pos.h" #include "lv_obj_scroll.h" #include "lv_obj_style.h" @@ -189,45 +235,55 @@ typedef uint32_t lv_obj_flag_t; #include "lv_grid.h" #include "lv_flex.h" +/** + * Describe the common methods of every object. + * Similar to a C++ class. + */ +typedef struct _lv_obj_class_t{ + const struct _lv_obj_class_t * base_class; + void (*constructor)(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy); + void (*destructor)(struct _lv_obj_t * obj); + lv_signal_cb_t signal_cb; /**< Object type specific signal function*/ + lv_draw_cb_t draw_cb; /**< Object type specific draw function*/ + uint32_t editable :1; + uint32_t instance_size :20; +}lv_obj_class_t; + +/** + * Make the base object's class publicly available. + */ +extern const lv_obj_class_t lv_obj; + +/** + * Special, rarely used attributes. + * They are allocated automatically if any elements is set. + */ typedef struct { - struct _lv_obj_t ** children; /**< Store the pointer of the children.*/ - uint32_t child_cnt; + struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/ + uint32_t child_cnt; /**< Number of children */ #if LV_USE_GROUP != 0 void * group_p; #endif - const lv_layout_dsc_t * layout_dsc; + const lv_layout_dsc_t * layout_dsc; /**< Pointer to the layout descriptor*/ - lv_event_cb_t event_cb; /**< Event callback function */ - - lv_point_t scroll; /**< The current X/Y scroll offset*/ - lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing. */ + lv_event_cb_t event_cb; /**< Event callback function */ + lv_point_t scroll; /**< The current X/Y scroll offset*/ #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - uint8_t ext_click_pad; /**< Extra click padding in all direction */ + uint8_t ext_click_pad; /**< Extra click padding in all direction */ #elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL lv_area_t ext_click_pad; /**< Extra click padding area. */ #endif + lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing. */ lv_scrollbar_mode_t scrollbar_mode :2; /**< How to display scrollbars*/ - lv_snap_align_t snap_align_x : 2; - lv_snap_align_t snap_align_y : 2; - lv_scroll_dir_t scroll_dir :4; + lv_snap_align_t snap_align_x : 2; /**< Where to align the snapable children horizontally*/ + lv_snap_align_t snap_align_y : 2; /**< Where to align the snapable children horizontally*/ + lv_dir_t scroll_dir :4; /**< The allowed scroll direction(s)*/ lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */ }lv_obj_spec_attr_t; - -#define _lv_obj_constructor - -typedef struct lv_obj_class{ - const struct lv_obj_class * base_class; - void (*constructor)(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy); - void (*destructor)(struct _lv_obj_t * obj); - lv_signal_cb_t signal_cb; /**< Object type specific signal function*/ - lv_draw_cb_t draw_cb; /**< Object type specific draw function*/ - uint32_t instance_size; -}lv_obj_class_t; - typedef struct _lv_obj_t{ const lv_obj_class_t * class_p; struct _lv_obj_t * parent; @@ -242,24 +298,9 @@ typedef struct _lv_obj_t{ lv_state_t state; }lv_obj_t; -extern const lv_obj_class_t lv_obj; - -enum { - LV_PART_MAIN, - LV_PART_SCROLLBAR, - LV_PART_INDICATOR, - LV_PART_KNOB, - LV_PART_HIGHLIGHT, //selected? - LV_PART_PLACEHOLDER, - LV_PART_ITEMS, - LV_PART_MARKER, - LV_PART_CURSOR, //combine with marker? -}; - -typedef uint8_t lv_part_t; typedef struct { - lv_point_t * point; + const lv_point_t * point; bool result; } lv_hit_test_info_t; @@ -268,234 +309,44 @@ typedef struct { **********************/ /** - * Init. the 'lv' library. + * Initialize LVGL library. + * Should be called before any other LVGL related function. */ void lv_init(void); +#if LV_ENABLE_GC || !LV_MEM_CUSTOM /** * Deinit the 'lv' library * Currently only implemented when not using custom allocators, or GC is enabled. */ -#if LV_ENABLE_GC || !LV_MEM_CUSTOM void lv_deinit(void); + #endif -/*-------------------- - * Create and delete - *-------------------*/ - /** - * Create a basic object - * @param parent pointer to a parent object. - * If NULL then a screen will be created - * - * @param copy DEPRECATED, will be removed in v9. - * Pointer to an other base object to copy. + * Create a base object (a rectangle) + * @param parent: pointer to a parent object. If NULL then a screen will be created. + * @param copy: DEPRECATED, will be removed in v9. + * Pointer to an other base object to copy. * @return pointer to the new object */ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy); -lv_obj_t * lv_obj_create_from_class(const lv_obj_class_t * class, lv_obj_t * parent, const lv_obj_t * copy); - -void lv_obj_construct_base(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy); -/** - * Delete 'obj' and all of its children - * @param obj pointer to an object to delete - * @return LV_RES_INV because the object is deleted - */ -lv_res_t lv_obj_del(lv_obj_t * obj); - -#if LV_USE_ANIMATION -/** - * A function to be easily used in animation ready callback to delete an object when the animation is ready - * @param a pointer to the animation - */ -void lv_obj_del_anim_ready_cb(lv_anim_t * a); -#endif - -/** - * Helper function for asynchronously deleting objects. - * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). - * @param obj object to delete - * @see lv_async_call - */ -void lv_obj_del_async(struct _lv_obj_t * obj); - -/** - * Delete all children of an object - * @param obj pointer to an object - */ -void lv_obj_clean(lv_obj_t * obj); - -/** - * Mark an area of an object as invalid. - * This area will be redrawn by 'lv_refr_task' - * @param obj pointer to an object - * @param area the area to redraw - */ -void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area); - -/** - * Mark the object as invalid therefore its current position will be redrawn by 'lv_refr_task' - * @param obj pointer to an object - */ -void lv_obj_invalidate(const lv_obj_t * obj); - - -/** - * Tell whether an area of an object is visible (even partially) now or not - * @param obj pointer to an object - * @param area the are to check. The visible part of the area will be written back here. - * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) - */ -bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area); - -/** - * Tell whether an object is visible (even partially) now or not - * @param obj pointer to an object - * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) - */ -bool lv_obj_is_visible(const lv_obj_t * obj); - -/*===================== - * Setter functions - *====================*/ - -/*-------------------- - * Parent/children set - *--------------------*/ - -/** - * Set a new parent for an object. Its relative position will be the same. - * @param obj pointer to an object. Can't be a screen. - * @param parent pointer to the new parent object. (Can't be NULL) - */ -void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent); - -/** - * Move and object to the foreground - * @param obj pointer to an object - */ -void lv_obj_move_foreground(lv_obj_t * obj); - -/** - * Move and object to the background - * @param obj pointer to an object - */ -void lv_obj_move_background(lv_obj_t * obj); - -/*-------------------- - * Coordinate set - * ------------------*/ - -/** - * Set the size of an extended clickable area - * @param obj pointer to an object - * @param left extended clickable are on the left [px] - * @param right extended clickable are on the right [px] - * @param top extended clickable are on the top [px] - * @param bottom extended clickable are on the bottom [px] - */ -void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right, lv_coord_t top, lv_coord_t bottom); - -/** - * Get the extended draw area of an object. - * @param obj pointer to an object - * @return the size extended draw area around the real coordinates - */ -lv_coord_t _lv_obj_get_ext_draw_pad(const lv_obj_t * obj); /*--------------------- - * Appearance set - *--------------------*/ - -/*----------------- - * Attribute set - *----------------*/ - -/** - * Set the base direction of the object - * @param obj pointer to an object - * @param dir the new base direction. `LV_BIDI_DIR_LTR/RTL/AUTO/INHERIT` - */ -void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir); - -void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f); - -void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f); - -/** - * Set the state (fully overwrite) of an object. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the new state - */ -void lv_obj_set_state(lv_obj_t * obj, lv_state_t state); - -/** - * Add a given state or states to the object. The other state bits will remain unchanged. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the state bits to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` - */ -void lv_obj_add_state(lv_obj_t * obj, lv_state_t state); - -/** - * Remove a given state or states to the object. The other state bits will remain unchanged. - * If specified in the styles a transition animation will be started - * from the previous state to the current - * @param obj pointer to an object - * @param state the state bits to remove. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` - */ -void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state); - - -/** - * Set a an event handler function for an object. - * Used by the user to react on event which happens with the object. - * @param obj pointer to an object - * @param event_cb the new event function - */ -void lv_obj_set_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb); + * Event/Signal sending + *---------------------*/ /** * Send an event to the object * @param obj pointer to an object - * @param event the type of the event from `lv_event_t`. + * @param event the type of the event from `lv_event_t` * @param data arbitrary data depending on the object type and the event. (Usually `NULL`) * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event */ lv_res_t lv_event_send(lv_obj_t * obj, lv_event_t event, const void * data); - -/** - * Send LV_EVENT_REFRESH event to an object - * @param obj point to an object. (Can NOT be NULL) - * @return LV_RES_OK: success, LV_RES_INV: to object become invalid (e.g. deleted) due to this event. - */ -lv_res_t lv_event_send_refresh(lv_obj_t * obj); - -/** - * Send LV_EVENT_REFRESH event to an object and all of its children - * @param obj pointer to an object or NULL to refresh all objects of all displays - */ -void lv_event_send_refresh_recursive(lv_obj_t * obj); - -/** - * Call an event function with an object, event, and data. - * @param event_xcb an event callback function. If `NULL` `LV_RES_OK` will return without any actions. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows - * the `func_name(object, callback, ...)` convention) - * @param obj pointer to an object to associate with the event (can be `NULL` to simply call the `event_cb`) - * @param event an event - * @param data pointer to a custom data - * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event - */ -lv_res_t lv_event_send_func(lv_event_cb_t event_xcb, lv_obj_t * obj, lv_event_t event, const void * data); - /** * Get the `data` parameter of the current event * @return the `data` parameter @@ -510,133 +361,92 @@ void * lv_event_get_data(void); */ lv_res_t lv_signal_send(lv_obj_t * obj, lv_signal_t signal, void * param); -/*---------------- - * Other set - *--------------*/ +/*===================== + * Setter functions + *====================*/ + /** - * 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 + * Set one or more flags + * @param obj: pointer to an object + * @param f: OR-ed values from `lv_obj_flag_t` to set. */ -void * lv_obj_allocate_ext_attr(lv_obj_t * obj, uint16_t ext_size); +void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f); + +/** + * Clear one or more flags + * @param obj: pointer to an object + * @param f: OR-ed values from `lv_obj_flag_t` to set. + */ +void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f); + +/** + * Set the state (fully overwrite) of an object. + * If specified in the styles, transition animations will be started from the previous state to the current. + * @param obj: pointer to an object + * @param state: the new state + */ +void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state); + + +/** + * Add one or more states to the object. The other state bits will remain unchanged. + * If specified in the styles, transition animation will be started from the previous state to the current. + * @param obj: pointer to an object + * @param state: the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + */ +void lv_obj_add_state(lv_obj_t * obj, lv_state_t state); + +/** + * Remove one or more states to the object. The other state bits will remain unchanged. + * If specified in the styles, transition animation will be started from the previous state to the current. + * @param obj: pointer to an object + * @param state: the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + */ +void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state); + +/** + * Set a an event handler function for an object. + * Used by the user to react on event which happens with the object. + * @param obj pointer to an object + * @param event_cb the new event function + */ +void lv_obj_set_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb); + +/** + * Set the base direction of the object + * @param obj pointer to an object + * @param dir the new base direction. `LV_BIDI_DIR_LTR/RTL/AUTO/INHERIT` + */ +void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir); + -lv_obj_spec_attr_t * lv_obj_allocate_spec_attr(lv_obj_t * obj); /*======================= * Getter functions *======================*/ /** - * Return with the screen of an object + * Check if a given flag or flags are set on an object. * @param obj pointer to an object - * @return pointer to a screen + * @param f the flag(s) to check (OR-ed values can be used) + * @return true: all flags are set; false: not all flags are set */ -lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj); - -/** - * Get the display of an object - * @return pointer the object's display - */ -lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj); - -/*--------------------- - * Parent/children get - *--------------------*/ - -/** - * Returns with the parent of an object - * @param obj pointer to an object - * @return pointer to the parent of 'obj' - */ -lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj); - -/** - * 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(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. - * If this object is the firstly created child of its parent 0 will be return. - * If its the second child return 1, etc. - * @param obj pointer to an object whose index should be get - * @return the child index of the object. - */ -uint32_t lv_obj_get_child_id(const lv_obj_t * obj); - -/** - * 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); - -/** Recursively count the children of an object - * @param obj pointer to an object - * @return children number of 'obj' - */ -uint32_t lv_obj_count_children_recursive(const lv_obj_t * obj); - -/*--------------------- - * Coordinate get - *--------------------*/ - -/** - * Get the extended extended clickable area in a direction - * @param obj pointer to an object - * @param dir in which direction get the extended area (`LV_DIR_LEFT/RIGHT/TOP`) - * @return the extended left padding - */ -lv_coord_t lv_obj_get_ext_click_area(const lv_obj_t * obj, lv_dir_t dir); - - -/** - * Check if a given screen-space point is on an object's coordinates. - * This method is intended to be used mainly by advanced hit testing algorithms to check - * whether the point is even within the object (as an optimization). - * @param obj object to check - * @param point screen-space point - */ -bool _lv_obj_is_click_point_on(lv_obj_t * obj, const lv_point_t * point); - -/** - * Hit-test an object given a particular point in screen space. - * @param obj object to hit-test - * @param point screen-space point - * @return true if the object is considered under the point - */ -bool lv_obj_hit_test(lv_obj_t * obj, lv_point_t * point); - -/*----------------- - * Attribute get - *----------------*/ - bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f); +/** + * Get the base direction of the object + * @param obj pointer to an object + * @return the base direction. `LV_BIDI_DIR_LTR/RTL/AUTO/INHERIT` + */ lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj); +/** + * Get the state of an object + * @param obj pointer to an object + * @return the state (OR-ed values from `lv_state_t`) + */ lv_state_t lv_obj_get_state(const lv_obj_t * obj); -/** - * 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); - -/** - * Get the draw function of an object - * @param obj pointer to an object - * @return the draw function - */ -lv_draw_cb_t lv_obj_get_draw_cb(const lv_obj_t * obj); - /** * Get the event function of an object * @param obj pointer to an object @@ -644,52 +454,6 @@ lv_draw_cb_t lv_obj_get_draw_cb(const lv_obj_t * obj); */ lv_event_cb_t lv_obj_get_event_cb(const lv_obj_t * obj); -/*------------------ - * Other get - *-----------------*/ - -/** - * Hit-test an object given a particular point in screen space. - * @param obj object to hit-test - * @param point screen-space point - * @return true if the object is considered under the point - */ -bool lv_obj_hit_test(lv_obj_t * obj, lv_point_t * point); - -/** - * 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); - -bool lv_obj_check_type(const lv_obj_t * obj, const void * class_p); - -#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); - -/** - * 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); - -/** - * 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); - -#endif - /** * Get the group of the object * @param obj pointer to an object @@ -697,25 +461,30 @@ void lv_obj_set_user_data(lv_obj_t * obj, lv_obj_user_data_t data); */ void * lv_obj_get_group(const lv_obj_t * obj); +/*======================= + * Other functions + *======================*/ + /** - * Tell whether the object is the focused object of a group or not. + * Allocate special data for an object if not allocated yet. * @param obj pointer to an object - * @return true: the object is focused, false: the object is not focused or not in a group */ -bool lv_obj_is_focused(const lv_obj_t * obj); - -lv_obj_t ** lv_obj_get_children(const lv_obj_t * obj); +void lv_obj_allocate_spec_attr(lv_obj_t * obj); /** - * Get the really focused object by taking `focus_parent` into account. + * Get the focused object by taking `LV_OBJ_FLAG_FOCUS_BUBBLE` into account. * @param obj the start object - * @return the object to really focus + * @return the object to to really focus */ -lv_obj_t * _lv_obj_get_focused_obj(const lv_obj_t * obj); +lv_obj_t * lv_obj_get_focused_obj(const lv_obj_t * obj); -/*------------------- - * OTHER FUNCTIONS - *------------------*/ +/** + * 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 + */ +bool lv_obj_check_type(const lv_obj_t * obj, const void * class_p); /** * Check if any object has a given type @@ -737,23 +506,6 @@ bool _lv_debug_check_obj_valid(const lv_obj_t * obj); * MACROS **********************/ -/** - * Helps to quickly declare an event callback function. - * Will be expanded to: `static void (lv_obj_t * obj, lv_event_t e)` - * - * Examples: - * LV_EVENT_CB_DECLARE(my_event1); //Prototype declaration - * - * LV_EVENT_CB_DECLARE(my_event1) - * { - * if(e == LV_EVENT_CLICKED) { - * lv_obj_set_hidden(obj ,true); - * } - * } - */ -#define LV_EVENT_CB_DECLARE(name) static void name(lv_obj_t * obj, lv_event_t e) - - #if LV_USE_DEBUG # ifndef LV_DEBUG_IS_OBJ diff --git a/src/lv_core/lv_obj_draw.c b/src/lv_core/lv_obj_draw.c index 0eaae4bf1..c9e056876 100644 --- a/src/lv_core/lv_obj_draw.c +++ b/src/lv_core/lv_obj_draw.c @@ -344,41 +344,41 @@ lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint8_t part) return s; } -/** - * Initialize a draw hook. - * @param hook_dsc: pointer to a raw hook. Later it should be passed as parameter to an `LV_EEVNT_DRAW_PART_BEGIN/END` event. - * @param clip_area: the current clip area of the drawing - */ void lv_obj_draw_hook_dsc_init(lv_obj_draw_hook_dsc_t * hook_dsc, const lv_area_t * clip_area) { lv_memset_00(hook_dsc, sizeof(lv_obj_draw_hook_dsc_t)); hook_dsc->clip_area = clip_area; } -/** - * Send a 'LV_SIGNAL_REFR_EXT_DRAW_SIZE' signal to the object to refresh the value of the extended draw size. - * The result will be saved in `obj`. - * @param obj: pointer to an object - */ void lv_obj_refresh_ext_draw_size(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - lv_coord_t s = 0; - lv_signal_send(obj, LV_SIGNAL_REFR_EXT_DRAW_SIZE, &s); + lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj); + lv_coord_t s_new = 0; + lv_signal_send(obj, LV_SIGNAL_REFR_EXT_DRAW_SIZE, &s_new); + + if(s_new != s_old) lv_obj_invalidate(obj); /*Store the result if the special attrs already allocated*/ if(obj->spec_attr) { - obj->spec_attr->ext_draw_size = s; + obj->spec_attr->ext_draw_size = s_new; } /* Allocate spec. attrs. only if the result is not zero. * Zero is the default value if the spec. attr. are not defined. */ - else if(s != 0) { + else if(s_new != 0) { lv_obj_allocate_spec_attr(obj); - obj->spec_attr->ext_draw_size = s; + obj->spec_attr->ext_draw_size = s_new; } + + if(s_new != s_old) lv_obj_invalidate(obj); } +lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj) +{ + if(obj->spec_attr) return obj->spec_attr->ext_draw_size; + else return 0; +} /********************** * STATIC FUNCTIONS diff --git a/src/lv_core/lv_obj_draw.h b/src/lv_core/lv_obj_draw.h index 55a65b87a..dd7a579f7 100644 --- a/src/lv_core/lv_obj_draw.h +++ b/src/lv_core/lv_obj_draw.h @@ -141,6 +141,13 @@ void lv_obj_draw_hook_dsc_init(lv_obj_draw_hook_dsc_t * hook_dsc, const lv_area_ */ void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj); +/** + * Get the extended draw area of an object. + * @param obj pointer to an object + * @return the size extended draw area around the real coordinates + */ +lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/src/lv_core/lv_obj_pos.c b/src/lv_core/lv_obj_pos.c index d15907414..3e25bdc44 100644 --- a/src/lv_core/lv_obj_pos.c +++ b/src/lv_core/lv_obj_pos.c @@ -593,6 +593,150 @@ void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_dif } } + +void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_area_t area_tmp; + lv_area_copy(&area_tmp, area); + bool visible = lv_obj_area_is_visible(obj, &area_tmp); + + if(visible) _lv_inv_area(lv_obj_get_disp(obj), &area_tmp); +} + +void lv_obj_invalidate(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + /*Truncate the area to the object*/ + lv_area_t obj_coords; + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + lv_area_copy(&obj_coords, &obj->coords); + obj_coords.x1 -= ext_size; + obj_coords.y1 -= ext_size; + obj_coords.x2 += ext_size; + obj_coords.y2 += ext_size; + + lv_obj_invalidate_area(obj, &obj_coords); + +} + +bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) +{ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false; + + /*Invalidate the object only if it belongs to the current or previous'*/ + lv_obj_t * obj_scr = lv_obj_get_screen(obj); + lv_disp_t * disp = lv_obj_get_disp(obj_scr); + if(obj_scr == lv_disp_get_scr_act(disp) || + obj_scr == lv_disp_get_scr_prev(disp) || + obj_scr == lv_disp_get_layer_top(disp) || + obj_scr == lv_disp_get_layer_sys(disp)) { + + /*Truncate the area to the object*/ + lv_area_t obj_coords; + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + lv_area_copy(&obj_coords, &obj->coords); + obj_coords.x1 -= ext_size; + obj_coords.y1 -= ext_size; + obj_coords.x2 += ext_size; + obj_coords.y2 += ext_size; + + bool is_common; + + is_common = _lv_area_intersect(area, area, &obj_coords); + if(is_common == false) return false; /*The area is not on the object*/ + + /*Truncate recursively to the parents*/ + lv_obj_t * par = lv_obj_get_parent(obj); + while(par != NULL) { + is_common = _lv_area_intersect(area, area, &par->coords); + if(is_common == false) return false; /*If no common parts with parent break;*/ + if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; /*If the parent is hidden then the child is hidden and won't be drawn*/ + + par = lv_obj_get_parent(par); + } + } + + return true; +} + +bool lv_obj_is_visible(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_area_t obj_coords; + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + lv_area_copy(&obj_coords, &obj->coords); + obj_coords.x1 -= ext_size; + obj_coords.y1 -= ext_size; + obj_coords.x2 += ext_size; + obj_coords.y2 += ext_size; + + return lv_obj_area_is_visible(obj, &obj_coords); + +} + +void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right, lv_coord_t top, lv_coord_t bottom) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + +#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL + lv_obj_allocate_spec_attr(obj); + obj->spec_attr->ext_click_pad.x1 = left; + obj->spec_attr->ext_click_pad.x2 = right; + obj->spec_attr->ext_click_pad.y1 = top; + obj->spec_attr->ext_click_pad.y2 = bottom; +#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY + lv_obj_allocate_spec_attr(obj); + obj->spec_attr->ext_click_pad = LV_MAX4(left, right, top, bottom); +#else + LV_UNUSED(obj); + LV_UNUSED(left); + LV_UNUSED(right); + LV_UNUSED(top); + LV_UNUSED(bottom); +#endif +} + +void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area) +{ + lv_area_copy(area, &obj->coords); +#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY + if(obj->spec_attr) { + area->x1 -= obj->spec_attr->ext_click_pad; + area->x2 += obj->spec_attr->ext_click_pad; + area->y1 -= obj->spec_attr->ext_click_pad; + area->y2 += obj->spec_attr->ext_click_pad; + } +#else + if(obj->spec_attr) { + area->x1 -= obj->spec_attr->ext_click_pad.x1; + area->x2 += obj->spec_attr->ext_click_pad.x2; + area->y1 -= obj->spec_attr->ext_click_pad.y1; + area->y2 += obj->spec_attr->ext_click_pad.y2; + } +#endif +} + +bool lv_obj_hit_test(const lv_obj_t * obj, const lv_point_t * point) +{ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_ADV_HITTEST)) { + lv_hit_test_info_t hit_info; + hit_info.point = point; + hit_info.result = true; + lv_signal_send(obj, LV_SIGNAL_HIT_TEST, &hit_info); + return hit_info.result; + } + else { + lv_area_t a; + lv_obj_get_click_area(obj, &a); + return _lv_area_is_point_on(&a, point, 0); + } +} + + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_core/lv_obj_pos.h b/src/lv_core/lv_obj_pos.h index aaadf1f81..99d138141 100644 --- a/src/lv_core/lv_obj_pos.h +++ b/src/lv_core/lv_obj_pos.h @@ -211,6 +211,64 @@ lv_coord_t lv_obj_get_self_height(struct _lv_obj_t * obj); */ bool lv_obj_handle_self_size_chg(struct _lv_obj_t * obj); + +/** + * Mark an area of an object as invalid. + * The area will be truncated to the object's area and marked for redraw. + * @param obj: pointer to an object + * @param area: the area to redraw + */ +void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area); + +/** + * Mark the object as invalid to redrawn its area + * @param obj: pointer to an object + */ +void lv_obj_invalidate(const struct _lv_obj_t * obj); + +/** + * Tell whether an area of an object is visible (even partially) now or not + * @param obj: pointer to an object + * @param area: the are to check. The visible part of the area will be written back here. + * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) + */ +bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area); + +/** + * Tell whether an object is visible (even partially) now or not + * @param obj pointer to an object + * @return true: visible; false: not visible (hidden, out of parent, on other screen, etc) + */ +bool lv_obj_is_visible(const struct _lv_obj_t * obj); + +/** + * Set the size of an extended clickable area + * If `LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY` in `lv_conf.h`, + * only the graetes value will be used. + * @param obj pointer to an object + * @param left extended clickable are on the left [px] + * @param right extended clickable are on the right [px] + * @param top extended clickable are on the top [px] + * @param bottom extended clickable are on the bottom [px] + */ +void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t left, lv_coord_t right, lv_coord_t top, lv_coord_t bottom); + +/** + * Get the an area where to object can be clicked. + * It's the object's normal area plus the extended click area. + * @param obj: pointer to an object + * @param area: store the result area here + */ +void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area); + +/** + * Hit-test an object given a particular point in screen space. + * @param obj object to hit-test + * @param point screen-space point (absolute coordinate) + * @return true: if the object is considered under the point + */ +bool lv_obj_hit_test(const struct _lv_obj_t * obj, const lv_point_t * point); + /********************** * MACROS **********************/ diff --git a/src/lv_core/lv_obj_scroll.c b/src/lv_core/lv_obj_scroll.c index 58fcab061..cc27c7980 100644 --- a/src/lv_core/lv_obj_scroll.c +++ b/src/lv_core/lv_obj_scroll.c @@ -240,9 +240,8 @@ void _lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) { if(x == 0 && y == 0) return; - if(obj->spec_attr == NULL) { - obj->spec_attr = lv_obj_allocate_spec_attr(obj); - } + lv_obj_allocate_spec_attr(obj); + obj->spec_attr->scroll.x += x; obj->spec_attr->scroll.y += y; diff --git a/src/lv_core/lv_obj_scroll.h b/src/lv_core/lv_obj_scroll.h index 1f3706b46..f574cae25 100644 --- a/src/lv_core/lv_obj_scroll.h +++ b/src/lv_core/lv_obj_scroll.h @@ -29,10 +29,10 @@ struct _lv_obj_t; /** Scrollbar modes: shows when should the scrollbars be visible*/ enum { - LV_SCROLLBAR_MODE_OFF = 0x0, /**< Never show scrollbars*/ - LV_SCROLLBAR_MODE_ON = 0x1, /**< Always show scrollbars*/ - LV_SCROLLBAR_MODE_ACTIVE = 0x2, /**< Show scroll bars when object is being scrolled*/ - LV_SCROLLBAR_MODE_AUTO = 0x3, /**< Show scroll bars when the content is large enough to be scrolled*/ + LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/ + LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/ + LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when object is being scrolled*/ + LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/ }; typedef uint8_t lv_scrollbar_mode_t; diff --git a/src/lv_core/lv_obj_style.c b/src/lv_core/lv_obj_style.c index acfcf7589..92a56bcc7 100644 --- a/src/lv_core/lv_obj_style.c +++ b/src/lv_core/lv_obj_style.c @@ -30,7 +30,7 @@ typedef struct { uint8_t part; lv_style_value_t start_value; lv_style_value_t end_value; -} lv_style_trans_t; +} trans_t; typedef enum { CACHE_ZERO = 0, @@ -43,18 +43,20 @@ typedef enum { /********************** * STATIC PROTOTYPES **********************/ +static lv_style_t * get_local_style(lv_obj_t * obj, uint32_t part, uint32_t state); +static lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part); +static bool get_prop_core(const lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_style_value_t * v); +static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v); +static void update_cache(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); +static cache_t read_cache(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); static void report_style_change_core(void * style, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); -#if LV_USE_ANIMATION -static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_style_trans_t * tr_limit); -static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v); +static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, trans_t * tr_limit); +static void trans_anim_cb(trans_t * tr, lv_anim_value_t v); static void trans_anim_start_cb(lv_anim_t * a); static void trans_anim_ready_cb(lv_anim_t * a); static void fade_anim_cb(lv_obj_t * obj, lv_anim_value_t v); static void fade_in_anim_ready(lv_anim_t * a); -#endif -static cache_t read_cache(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); -static void update_cache(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); /********************** * STATIC VARIABLES @@ -74,13 +76,19 @@ static void update_cache(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); */ void _lv_obj_style_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(lv_style_trans_t)); + _lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(trans_t)); } -void lv_obj_add_style_no_refresh(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style) +/** + * Add a style to an object. + * @param obj: pointer to an object + * @param part: a part of the object to which the style should be added E.g. `LV_PART_MAIN` or `LV_PART_KNOB` + * @param state: a state or combination of states to which the style should be assigned + * @param style: pointer to a style to add + * @example lv_obj_add_style_no_refresh(slider, LV_PART_KNOB, LV_STATE_PRESSED, &style1); + */ +void lv_obj_add_style(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style) { - if(style == NULL) return; - #if LV_USE_ANIMATION trans_del(obj, part, 0xFF, NULL); #endif @@ -109,89 +117,57 @@ void lv_obj_add_style_no_refresh(struct _lv_obj_t * obj, uint32_t part, uint32_t obj->style_list.styles[i].part = part; obj->style_list.styles[i].state = state; + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); } /** - * Add a new style to the style list of an object. - * @param obj pointer to an object - * @param part the part of the object which style property should be set. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param style pointer to a style to add (Only its pointer will be saved) - */ -void lv_obj_add_style(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style) -{ - lv_obj_add_style_no_refresh(obj, part, state, style); - _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); -} - -/** - * Remove a style from the style list of an object. - * @param obj pointer to an object - * @param part the part of the object which style property should be set. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param style pointer to a style to remove + * Add a style to an object. + * @param obj: pointer to an object + * @param part: a part of the object from which the style should be removed E.g. `LV_PART_MAIN` or `LV_PART_KNOB` + * @param state: a state or combination of states from which the style should be removed + * @param style: pointer to a style to remove */ void lv_obj_remove_style(lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style) { - if(style == NULL) return; - - uint32_t i; - /*Find the style*/ - for(i = 0; i < obj->style_list.style_cnt; i++) { - if(obj->style_list.styles[i].state == state && - obj->style_list.styles[i].part == part) { - break; + uint32_t i = 0; + bool deleted = false; + while(i < obj->style_list.style_cnt) { + if((state != LV_STATE_ANY && obj->style_list.styles[i].state != state) || + (part != LV_PART_ANY && obj->style_list.styles[i].part != part) || + (style != NULL && style != obj->style_list.styles[i].style)) + { + i++; + continue; } + + if(obj->style_list.styles[i].is_local || obj->style_list.styles[i].is_trans) { + lv_style_reset(obj->style_list.styles[i].style); + lv_mem_free(obj->style_list.styles[i].style); + obj->style_list.styles[i].style = NULL; + } + + /*Shift the styles after `i` by one*/ + uint32_t j; + for(j = i; j < obj->style_list.style_cnt - 1 ; j++) { + obj->style_list.styles[j] = obj->style_list.styles[j + 1]; + } + + obj->style_list.style_cnt--; + obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); + + deleted = true; + /* The style from the current `i` index is removed, so `i` points to the next style. + * Therefore it doesn't needs to be incremented*/ } - /*The style is not found*/ - if(i == obj->style_list.style_cnt) return; - - /*Shift the styles after `i` by one*/ - uint32_t j; - for(j = i; j < obj->style_list.style_cnt - 1 ; j++) { - obj->style_list.styles[j] = obj->style_list.styles[j + 1]; + if(deleted) { + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); } - - - obj->style_list.style_cnt--; - obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); - - -#if LV_USE_ANIMATION - trans_del(obj, part, 0xFF, NULL); -#endif - _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); -} - -void lv_obj_remove_all_styles_no_refresh(lv_obj_t * obj) -{ -#if LV_USE_ANIMATION - trans_del(obj, 0xFF, 0xFF, NULL); -#endif - - lv_mem_free(obj->style_list.styles); - obj->style_list.styles = NULL; - obj->style_list.style_cnt = 0; -} - -/** - * Reset a style to the default (empty) state. - * Release all used memories and cancel pending related transitions. - * Also notifies the object about the style change. - * @param obj pointer to an object - * @param part the part of the object which style list should be reseted. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - */ -void lv_obj_remove_all_styles(lv_obj_t * obj) -{ - lv_obj_remove_all_styles_no_refresh(obj); - _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); } /** * Notify all object if a style is modified - * @param style pointer to a style. Only the objects with this style will be notified + * @param style: pointer to a style. Only the objects with this style will be notified * (NULL to notify all objects) */ void lv_obj_report_style_change(lv_style_t * style) @@ -208,168 +184,42 @@ void lv_obj_report_style_change(lv_style_t * style) } /** - * Remove a local style property from a part of an object with a given state. - * @param obj pointer to an object - * @param part the part of the object which style property should be removed. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param prop a style property ORed with a state. - * E.g. `LV_STYLE_TEXT_FONT | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` - * @return true: the property was found and removed; false: the property was not found + * Notify an object and its children about its style is modified. + * @param obj: pointer to an object + * @param prop: `LV_STYLE_PROP_ALL` or an `LV_STYLE_...` property. + * It is used to optimize what needs to be refreshed. */ -bool lv_obj_remove_style_prop(lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop) +void lv_obj_refresh_style(lv_obj_t * obj,lv_style_prop_t prop) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - uint32_t i; - /*Find the style*/ - for(i = 0; i < obj->style_list.style_cnt; i++) { - if(obj->style_list.styles[i].is_local && - obj->style_list.styles[i].state == state && - obj->style_list.styles[i].part == part) { - break; - } + update_cache(obj, LV_PART_MAIN, prop); + + lv_obj_invalidate(obj); + if(prop == LV_STYLE_PROP_ALL || (prop & LV_STYLE_PROP_LAYOUT_REFR)) { + lv_signal_send(obj, LV_SIGNAL_STYLE_CHG, NULL); + lv_obj_invalidate(obj); + } else if(prop & LV_STYLE_PROP_EXT_DRAW) { + lv_obj_refresh_ext_draw_size(obj); + lv_obj_invalidate(obj); } - /*The style is not found*/ - if(i == obj->style_list.style_cnt) return false; - - return lv_style_remove_prop(obj->style_list.styles[i].style, prop); -} - - -#if LV_USE_ANIMATION -/** - * Fade in (from transparent to fully cover) an object and all its children using an `opa_scale` animation. - * @param obj the object to fade in - * @param time duration of the animation [ms] - * @param delay wait before the animation starts [ms] - */ -void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay) -{ - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, obj); - lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)fade_anim_cb); - lv_anim_set_ready_cb(&a, fade_in_anim_ready); - lv_anim_set_time(&a, time); - lv_anim_set_delay(&a, delay); - lv_anim_start(&a); + if(prop == LV_STYLE_PROP_ALL || + ((prop & LV_STYLE_PROP_INHERIT) && (prop & LV_STYLE_PROP_EXT_DRAW) && (prop & LV_STYLE_PROP_LAYOUT_REFR))) + { + refresh_children_style(obj); + } } /** - * Fade out (from fully cover to transparent) an object and all its children using an `opa_scale` animation. - * @param obj the object to fade in - * @param time duration of the animation [ms] - * @param delay wait before the animation starts [ms] - */ -void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay) -{ - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, obj); - lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_TRANSP); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)fade_anim_cb); - lv_anim_set_time(&a, time); - lv_anim_set_delay(&a, delay); - lv_anim_start(&a); -} -#endif - -static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v) -{ - if(obj == NULL) return v; - lv_color_filter_cb_t f = lv_obj_get_style_color_filter_cb(obj, part); - if(f) { - lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part); - if(f_opa != 0) v.color = f(v.color, f_opa); - } - return v; -} -static bool get_prop_core(const lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_style_value_t * v) -{ - cache_t cache_res = read_cache(obj, part, prop); - switch(cache_res) { - case CACHE_ZERO: - v->ptr = 0; - return true; - case CACHE_TRUE: - v->num = 1; - return true; - case CACHE_255: - v->num = 255; - return true; - case CACHE_UNSET: - return false; - case CACHE_NEED_CHECK: - break; - - } - - int32_t weight = -1; - lv_state_t state = obj->state; - lv_state_t state_inv = ~state; - lv_style_value_t value_tmp; - bool skip_trans = obj->style_list.skip_trans; - uint32_t i; - bool found; - for(i = 0; i < obj->style_list.style_cnt; i++) { - lv_obj_style_t * obj_style = &obj->style_list.styles[i]; - if(obj_style->is_trans == false) break; - if(skip_trans) continue; - if(obj_style->part != part) continue; - found = lv_style_get_prop(obj_style->style, prop, &value_tmp); - if(found) { - *v = value_tmp; - return true; - } - } - - for(; i < obj->style_list.style_cnt; i++) { - lv_obj_style_t * obj_style = &obj->style_list.styles[i]; - if(obj_style->part != part) continue; - - /* Be sure the style not specifies other state than the requested. - * E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/ - if((obj_style->state & state_inv)) continue; - - /*Check only better candidates*/ - if(obj_style->state <= weight) continue; - - found = lv_style_get_prop(obj_style->style, prop, &value_tmp); - - if(found) { - if(obj_style->state == state) { - *v = value_tmp; - return true; - } - if(weight < obj_style->state) { - weight = obj_style->state; - *v = value_tmp; - } - } - } - - if(weight >= 0) { - *v = value_tmp; - return true; - } - else return false; -} - -/** - * Get a style property of a part of an object in the object's current state. - * If there is a running transitions it is taken into account - * @param obj pointer to an object - * @param part the part of the object which style property should be get. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param prop the property to get. E.g. `LV_STYLE_BORDER_OPA`. - * The state of the object will be added internally - * @return the value of the property of the given part in the current state. - * If the property is not found a default value will be returned. - * @note shouldn't be used directly. Use the specific property get functions instead. - * For example: `lv_obj_style_get_border_opa()` - * @note for performance reasons it's not checked if the property really has opacity type + * Get the value of a style property. The current state of the object will be considered. + * Inherited properties will be inherited. + * If a property is not set a default value will be returned. + * @param obj: pointer to an object + * @param part: a part from which the property should be get + * @param prop: the property to get + * @return the value of the property. + * Should be read from the correct field of the `lv_style_value_t` according to the type of the property. */ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, uint8_t part, lv_style_prop_t prop) { @@ -400,113 +250,49 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, uint8_t part, lv_st return value_act; } + /** - * Notify an object and its children about its style is modified - * @param obj pointer to an object - * @param part the part of the object which style property should be refreshed. - * @param prop `LV_STYLE_PROP_ALL` or an `LV_STYLE_...` property. It is used to optimize what needs to be refreshed. + * Set local style property on an object's part and state. + * @param obj: pointer to an object + * @param part: a part to which the property should be added + * @param state: a state to which the property should be added + * @param prop: the property + * @param value: value of the property. The correct element should be set according to the type of the property */ -void _lv_obj_refresh_style(lv_obj_t * obj,lv_style_prop_t prop) +void lv_obj_set_local_style_prop(lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop, lv_style_value_t value) +{ + lv_style_t * style = get_local_style(obj, part, state); + lv_style_set_prop(style, prop, value); + lv_obj_refresh_style(obj, prop); + +} + +/** + * Remove a local style property from a part of an object with a given state. + * @param obj: pointer to an object + * @param part: the part of the object which style property should be removed. + * @param state: the state from which the property should be removed. + * @param prop: a style property to remove. + * @return true: the property was found and removed; false: the property was not found + */ +bool lv_obj_remove_local_style_prop(lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - update_cache(obj, LV_PART_MAIN, prop); - - lv_obj_invalidate(obj); - if(prop == LV_STYLE_PROP_ALL || (prop & LV_STYLE_PROP_LAYOUT_REFR)) { - lv_signal_send(obj, LV_SIGNAL_STYLE_CHG, NULL); - lv_obj_invalidate(obj); - } else if(prop & LV_STYLE_PROP_EXT_DRAW) { - lv_obj_refresh_ext_draw_size(obj); - lv_obj_invalidate(obj); - } - - if(prop == LV_STYLE_PROP_ALL || - ((prop & LV_STYLE_PROP_INHERIT) && (prop & LV_STYLE_PROP_EXT_DRAW) && (prop & LV_STYLE_PROP_LAYOUT_REFR))) - { - refresh_children_style(obj); - } -} - -/** - * Remove all transitions from an object - * @param obj pointer to an object - */ -void _lv_obj_remove_style_trans(lv_obj_t * obj) -{ -#if LV_USE_ANIMATION - trans_del(obj, 0xFF, 0xFF, NULL); -#else - LV_UNUSED(obj); -#endif -} - -#if LV_USE_ANIMATION - -lv_obj_style_t * _get_trans_style(lv_obj_t * obj, uint32_t part) -{ - uint32_t i; - for(i = 0; i < obj->style_list.style_cnt; i++) { - if(obj->style_list.styles[i].is_trans && obj->style_list.styles[i].part == part) break; - } - - /*Already have a transition style for it*/ - if(i != obj->style_list.style_cnt) return &obj->style_list.styles[i]; - - obj->style_list.style_cnt++; - obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); - - for(i = obj->style_list.style_cnt - 1; i > 0 ; i--) { - obj->style_list.styles[i] = obj->style_list.styles[i - 1]; - } - - lv_memset_00(&obj->style_list.styles[0], sizeof(lv_obj_style_t)); - obj->style_list.styles[0].style = lv_mem_alloc(sizeof(lv_style_t)); - lv_style_init(obj->style_list.styles[0].style); - obj->style_list.styles[0].is_trans = 1; - obj->style_list.styles[0].part = part; - return &obj->style_list.styles[0]; -} - - -lv_style_t * lv_obj_get_local_style(lv_obj_t * obj, uint32_t part, uint32_t state) -{ uint32_t i; + /*Find the style*/ for(i = 0; i < obj->style_list.style_cnt; i++) { if(obj->style_list.styles[i].is_local && - obj->style_list.styles[i].part == part && - obj->style_list.styles[i].state == state) - { - return obj->style_list.styles[i].style; + obj->style_list.styles[i].state == state && + obj->style_list.styles[i].part == part) { + break; } } - obj->style_list.style_cnt++; - obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); - - for(i = obj->style_list.style_cnt - 1; i > 0 ; i--) { - /* Copy only normal styles (not local and transition). - * The new local style will be added as the last local style*/ - if(obj->style_list.styles[i - 1].is_local || obj->style_list.styles[i - 1].is_trans) break; - obj->style_list.styles[i] = obj->style_list.styles[i - 1]; - } - - lv_memset_00(&obj->style_list.styles[i], sizeof(lv_obj_style_t)); - obj->style_list.styles[i].style = lv_mem_alloc(sizeof(lv_style_t)); - lv_style_init(obj->style_list.styles[i].style); - obj->style_list.styles[i].is_local = 1; - obj->style_list.styles[i].part = part; - obj->style_list.styles[i].state = state; - return obj->style_list.styles[i].style; -} - - -void lv_obj_set_style_prop(lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop, lv_style_value_t value) -{ - lv_style_t * style = lv_obj_get_local_style(obj, part, state); - lv_style_set_prop(style, prop, value); - _lv_obj_refresh_style(obj, prop); + /*The style is not found*/ + if(i == obj->style_list.style_cnt) return false; + return lv_style_remove_prop(obj->style_list.styles[i].style, prop); } /** @@ -522,11 +308,10 @@ void lv_obj_set_style_prop(lv_obj_t * obj, uint32_t part, uint32_t state, lv_sty * @param path the path of the transition * @return pointer to the allocated `the transaction` variable or `NULL` if no transition created */ -void _lv_obj_create_style_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8_t part, lv_state_t prev_state, +void lv_obj_style_create_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8_t part, lv_state_t prev_state, lv_state_t new_state, uint32_t time, uint32_t delay, const lv_anim_path_t * path) { - lv_style_trans_t * tr; - lv_obj_style_t * style_trans = _get_trans_style(obj, part); + trans_t * tr; /*Get the previous and current values*/ obj->style_list.skip_trans = 1; @@ -540,6 +325,8 @@ void _lv_obj_create_style_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8 obj->state = prev_state; v1 = lv_obj_get_style_prop(obj, part, prop); obj->state = new_state; + + lv_obj_style_t * style_trans = get_trans_style(obj, part); lv_style_set_prop(style_trans->style, prop, v1); /*Be sure `trans_style` has a valid value */ if(prop == LV_STYLE_RADIUS) { @@ -577,8 +364,6 @@ void _lv_obj_create_style_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8 } } -#endif - /** * Compare the style properties of an object in 2 different states * @param obj pointer to an object @@ -586,7 +371,7 @@ void _lv_obj_create_style_transition(lv_obj_t * obj, lv_style_prop_t prop, uint8 * @param state2 an other state * @return an element of `_lv_style_state_cmp_t` */ -_lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2) +_lv_style_state_cmp_t lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2) { lv_obj_style_list_t * list = &obj->style_list; _lv_style_state_cmp_t res = _LV_STYLE_STATE_CMP_SAME; @@ -649,10 +434,203 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta return res; } + +#if LV_USE_ANIMATION +/** + * Fade in (from transparent to fully cover) an object and all its children using an `opa_scale` animation. + * @param obj the object to fade in + * @param time duration of the animation [ms] + * @param delay wait before the animation starts [ms] + */ +void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay) +{ + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)fade_anim_cb); + lv_anim_set_ready_cb(&a, fade_in_anim_ready); + lv_anim_set_time(&a, time); + lv_anim_set_delay(&a, delay); + lv_anim_start(&a); +} + +/** + * Fade out (from fully cover to transparent) an object and all its children using an `opa_scale` animation. + * @param obj the object to fade in + * @param time duration of the animation [ms] + * @param delay wait before the animation starts [ms] + */ +void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay) +{ + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_TRANSP); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)fade_anim_cb); + lv_anim_set_time(&a, time); + lv_anim_set_delay(&a, delay); + lv_anim_start(&a); +} +#endif /********************** * STATIC FUNCTIONS **********************/ +/** + * Get the local style of an object for a given part and for a given state. + * If the local style for the part-state pair doesn't exist allocate and return it. + * @param obj: pointer to an object + * @param part: the part in whose local style to get + * @param state: the state in whose local style to get + * @return pointer to the local style + */ +static lv_style_t * get_local_style(lv_obj_t * obj, uint32_t part, uint32_t state) +{ + uint32_t i; + for(i = 0; i < obj->style_list.style_cnt; i++) { + if(obj->style_list.styles[i].is_local && + obj->style_list.styles[i].part == part && + obj->style_list.styles[i].state == state) + { + return obj->style_list.styles[i].style; + } + } + + obj->style_list.style_cnt++; + obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); + + for(i = obj->style_list.style_cnt - 1; i > 0 ; i--) { + /* Copy only normal styles (not local and transition). + * The new local style will be added as the last local style*/ + if(obj->style_list.styles[i - 1].is_local || obj->style_list.styles[i - 1].is_trans) break; + obj->style_list.styles[i] = obj->style_list.styles[i - 1]; + } + + lv_memset_00(&obj->style_list.styles[i], sizeof(lv_obj_style_t)); + obj->style_list.styles[i].style = lv_mem_alloc(sizeof(lv_style_t)); + lv_style_init(obj->style_list.styles[i].style); + obj->style_list.styles[i].is_local = 1; + obj->style_list.styles[i].part = part; + obj->style_list.styles[i].state = state; + return obj->style_list.styles[i].style; +} + +/** + * Get the transition style of an object for a given part and for a given state. + * If the transition style for the part-state pair doesn't exist allocate and return it. + * @param obj: pointer to an object + * @param part: the part in whose local style to get + * @param state: the state in whose local style to get + * @return pointer to the transition style + */ +static lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part) +{ + uint32_t i; + for(i = 0; i < obj->style_list.style_cnt; i++) { + if(obj->style_list.styles[i].is_trans && obj->style_list.styles[i].part == part) break; + } + + /*Already have a transition style for it*/ + if(i != obj->style_list.style_cnt) return &obj->style_list.styles[i]; + + obj->style_list.style_cnt++; + obj->style_list.styles = lv_mem_realloc(obj->style_list.styles, obj->style_list.style_cnt * sizeof(lv_obj_style_t)); + + for(i = obj->style_list.style_cnt - 1; i > 0 ; i--) { + obj->style_list.styles[i] = obj->style_list.styles[i - 1]; + } + + lv_memset_00(&obj->style_list.styles[0], sizeof(lv_obj_style_t)); + obj->style_list.styles[0].style = lv_mem_alloc(sizeof(lv_style_t)); + lv_style_init(obj->style_list.styles[0].style); + obj->style_list.styles[0].is_trans = 1; + obj->style_list.styles[0].part = part; + return &obj->style_list.styles[0]; +} + + +static bool get_prop_core(const lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_style_value_t * v) +{ + cache_t cache_res = read_cache(obj, part, prop); + switch(cache_res) { + case CACHE_ZERO: + v->ptr = 0; + return true; + case CACHE_TRUE: + v->num = 1; + return true; + case CACHE_255: + v->num = 255; + return true; + case CACHE_UNSET: + return false; + case CACHE_NEED_CHECK: + break; + } + + int32_t weight = -1; + lv_state_t state = obj->state; + lv_state_t state_inv = ~state; + lv_style_value_t value_tmp; + bool skip_trans = obj->style_list.skip_trans; + uint32_t i; + bool found; + for(i = 0; i < obj->style_list.style_cnt; i++) { + lv_obj_style_t * obj_style = &obj->style_list.styles[i]; + if(obj_style->is_trans == false) break; + if(skip_trans) continue; + if(obj_style->part != part) continue; + found = lv_style_get_prop(obj_style->style, prop, &value_tmp); + if(found) { + *v = value_tmp; + return true; + } + } + + for(; i < obj->style_list.style_cnt; i++) { + lv_obj_style_t * obj_style = &obj->style_list.styles[i]; + if(obj_style->part != part) continue; + + /* Be sure the style not specifies other state than the requested. + * E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/ + if((obj_style->state & state_inv)) continue; + + /*Check only better candidates*/ + if(obj_style->state <= weight) continue; + + found = lv_style_get_prop(obj_style->style, prop, &value_tmp); + + if(found) { + if(obj_style->state == state) { + *v = value_tmp; + return true; + } + if(weight < obj_style->state) { + weight = obj_style->state; + *v = value_tmp; + } + } + } + + if(weight >= 0) { + *v = value_tmp; + return true; + } + else return false; +} + +static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v) +{ + if(obj == NULL) return v; + lv_color_filter_cb_t f = lv_obj_get_style_color_filter_cb(obj, part); + if(f) { + lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part); + if(f_opa != 0) v.color = f(v.color, f_opa); + } + return v; +} + static void update_cache(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) { lv_obj_style_list_t * list = &obj->style_list; @@ -880,7 +858,7 @@ static void report_style_change_core(void * style, lv_obj_t * obj) uint32_t i; for(i = 0; i < list->style_cnt; i++) { if(style == NULL || list->styles[i].style == style) { - _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); break; } } @@ -908,7 +886,6 @@ static void refresh_children_style(lv_obj_t * obj) } } -#if LV_USE_ANIMATION /** * Remove the transition from object's part's property. * - Remove the transition from `_lv_obj_style_trans_ll` and free it @@ -916,12 +893,12 @@ static void refresh_children_style(lv_obj_t * obj) * @param obj pointer to an object which transition(s) should be removed * @param part a part of object or 0xFF to remove from all parts * @param prop a property or 0xFF to remove all properties - * @param tr_limit delete transitions only "older" then this. `NULL` is not used + * @param tr_limit delete transitions only "older" than this. `NULL` if not used */ -static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_style_trans_t * tr_limit) +static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, trans_t * tr_limit) { - lv_style_trans_t * tr; - lv_style_trans_t * tr_prev; + trans_t * tr; + trans_t * tr_prev; bool removed = false; tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll)); while(tr != NULL) { @@ -930,7 +907,7 @@ static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_sty /*'tr' might be deleted, so get the next object while 'tr' is valid*/ tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); - if(tr->obj == obj && (part == tr->part || part == 0xFF) && (prop == tr->prop || prop == 0xFF)) { + if(tr->obj == obj && (part == tr->part || part == LV_PART_ANY) && (prop == tr->prop || prop == 0xFF)) { /* Remove the transitioned property from trans. style * to allow changing it by normal styles*/ uint32_t i; @@ -950,7 +927,7 @@ static bool trans_del(lv_obj_t * obj, uint8_t part, lv_style_prop_t prop, lv_sty return removed; } -static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v) +static void trans_anim_cb(trans_t * tr, lv_anim_value_t v) { lv_obj_style_list_t * list = &tr->obj->style_list; @@ -1004,7 +981,7 @@ static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v) } } lv_style_set_prop(list->styles[i].style, tr->prop, value_final); - if (refr) _lv_obj_refresh_style(tr->obj, tr->prop); + if (refr) lv_obj_refresh_style(tr->obj, tr->prop); break; } @@ -1013,7 +990,7 @@ static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v) static void trans_anim_start_cb(lv_anim_t * a) { - lv_style_trans_t * tr = a->var; + trans_t * tr = a->var; tr->start_value = lv_obj_get_style_prop(tr->obj, tr->part, tr->prop); @@ -1026,14 +1003,14 @@ static void trans_anim_start_cb(lv_anim_t * a) tr->prop = prop_tmp; - lv_obj_style_t * style_trans = _get_trans_style(tr->obj, tr->part); + lv_obj_style_t * style_trans = get_trans_style(tr->obj, tr->part); lv_style_set_prop(style_trans->style, tr->prop, tr->start_value); /*Be sure `trans_style` has a valid value */ } static void trans_anim_ready_cb(lv_anim_t * a) { - lv_style_trans_t * tr = a->var; + trans_t * tr = a->var; lv_obj_t * obj = tr->obj; lv_style_prop_t prop = tr->prop; @@ -1041,7 +1018,7 @@ static void trans_anim_ready_cb(lv_anim_t * a) * if there no more transitions for this property * It allows changing it by normal styles*/ bool running = false; - lv_style_trans_t * tr_i; + trans_t * tr_i; _LV_LL_READ(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) { if(tr_i != tr && tr_i->obj == tr->obj && tr_i->part == tr->part && tr_i->prop == tr->prop) { running = true; @@ -1060,10 +1037,9 @@ static void trans_anim_ready_cb(lv_anim_t * a) lv_style_remove_prop(obj_style->style, prop); if(lv_style_is_empty(obj->style_list.styles[i].style)) { - lv_style_t * style = obj_style->style; lv_obj_remove_style(obj, obj_style->part, obj_style->state, obj_style->style); - lv_style_reset(style); - lv_mem_free(style); + //trans_del(obj, obj_style->part, prop, NULL); + } break; } @@ -1073,7 +1049,7 @@ static void trans_anim_ready_cb(lv_anim_t * a) static void fade_anim_cb(lv_obj_t * obj, lv_anim_value_t v) { -// lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v); +// lv_obj_style_set_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v); } static void fade_in_anim_ready(lv_anim_t * a) @@ -1081,5 +1057,4 @@ static void fade_in_anim_ready(lv_anim_t * a) // lv_style_remove_prop(_lv_obj_get_local_style(a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); } -#endif diff --git a/src/lv_core/lv_obj_style.h b/src/lv_core/lv_obj_style.h index 0feb9827e..cd9be00d7 100644 --- a/src/lv_core/lv_obj_style.h +++ b/src/lv_core/lv_obj_style.h @@ -15,12 +15,11 @@ extern "C" { *********************/ #include #include -#include "../lv_misc/lv_style.h" /********************* * DEFINES *********************/ -#define LV_OBJ_STYLE_CACHE_STATE_INVALID 0x1ff +#define LV_OBJ_STYLE_CACHE_STATE_INVALID LV_STATE_ANY /********************** * TYPEDEFS @@ -46,8 +45,8 @@ typedef struct { typedef struct { lv_obj_style_t * styles; uint32_t skip_trans :1; - uint32_t style_cnt :6; - uint32_t cache_state :9; + uint32_t style_cnt :5; + uint32_t cache_state :10; uint32_t cache_opa_set :1; uint32_t cache_radius_zero:1; @@ -82,107 +81,70 @@ typedef struct { void _lv_obj_style_init(void); /** - * Add a new style to the style list of an object. - * @param obj pointer to an object - * @param part the part of the object which style property should be set. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param style pointer to a style to add (Only its pointer will be saved) + * Add a style to an object. + * @param obj: pointer to an object + * @param part: a part of the object to which the style should be added E.g. `LV_PART_MAIN` or `LV_PART_KNOB` + * @param state: a state or combination of states to which the style should be assigned + * @param style: pointer to a style to add + * @example lv_obj_add_style_no_refresh(slider, LV_PART_KNOB, LV_STATE_PRESSED, &style1); */ void lv_obj_add_style(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style); /** - * Remove a style from the style list of an object. - * @param obj pointer to an object - * @param part the part of the object which style property should be set. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - * @param style pointer to a style to remove + * Add a style to an object. + * @param obj: pointer to an object + * @param part: a part of the object from which the style should be removed E.g. `LV_PART_MAIN` or `LV_PART_KNOB` + * @param state: a state or combination of states from which the style should be removed + * @param style: pointer to a style to remove */ -void lv_obj_remove_style(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_t * style); - -/** - * Reset a style to the default (empty) state. - * Release all used memories and cancel pending related transitions. - * Also notifies the object about the style change. - * @param obj pointer to an object - * @param part the part of the object which style list should be reseted. - * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` - */ -void lv_obj_remove_all_styles(struct _lv_obj_t * obj); +void lv_obj_remove_style(struct _lv_obj_t * objj, uint32_t part, uint32_t state, lv_style_t * style); /** * Notify all object if a style is modified - * @param style pointer to a style. Only the objects with this style will be notified + * @param style: pointer to a style. Only the objects with this style will be notified * (NULL to notify all objects) */ void lv_obj_report_style_change(lv_style_t * style); -#if LV_USE_ANIMATION +/** + * Notify an object and its children about its style is modified. + * @param obj: pointer to an object + * @param prop: `LV_STYLE_PROP_ALL` or an `LV_STYLE_...` property. + * It is used to optimize what needs to be refreshed. + */ +void lv_obj_refresh_style(struct _lv_obj_t * obj,lv_style_prop_t prop); /** - * Fade in (from transparent to fully cover) an object and all its children using an `opa_scale` animation. - * @param obj the object to fade in - * @param time duration of the animation [ms] - * @param delay wait before the animation starts [ms] + * Get the value of a style property. The current state of the object will be considered. + * Inherited properties will be inherited. + * If a property is not set a default value will be returned. + * @param obj: pointer to an object + * @param part: a part from which the property should be get + * @param prop: the property to get + * @return the value of the property. + * Should be read from the correct field of the `lv_style_value_t` according to the type of the property. */ -void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); - -/** - * Fade out (from fully cover to transparent) an object and all its children using an `opa_scale` animation. - * @param obj the object to fade in - * @param time duration of the animation [ms] - * @param delay wait before the animation starts [ms] - */ -void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); - -#endif - lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, uint8_t part, lv_style_prop_t prop); /** - * Notify an object and its children about its style is modified - * @param obj pointer to an object - * @param part the part of the object which style property should be refreshed. - * @param prop `LV_STYLE_PROP_ALL` or an `LV_STYLE_...` property. It is used to optimize what needs to be refreshed. + * Set local style property on an object's part and state. + * @param obj: pointer to an object + * @param part: a part to which the property should be added + * @param state: a state to which the property should be added + * @param prop: the property + * @param value: value of the property. The correct element should be set according to the type of the property */ -void _lv_obj_refresh_style(struct _lv_obj_t * obj, lv_style_prop_t prop); - -lv_style_t * lv_obj_get_local_style(struct _lv_obj_t * obj, uint32_t part, uint32_t state); -/** - * Remove all transitions from an object - * @param obj pointer to an object - */ -void _lv_obj_remove_style_trans(struct _lv_obj_t * obj); -void lv_obj_set_style_prop(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop, lv_style_value_t value); - -#if LV_USE_ANIMATION +void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop, lv_style_value_t value); /** - * Allocate and initialize a transition for a property of an object if the properties value is different in the new state. - * It allocates `lv_style_trans_t` in `_lv_obj_style_trans_ll` and set only `start/end_values`. No animation will be created here. - * @param obj and object to add the transition - * @param prop the property to apply the transaction - * @param part the part of the object to apply the transaction - * @param prev_state the previous state of the objects - * @param new_state the new state of the object - * @param time duration of transition in [ms] - * @param delay delay before starting the transition in [ms] - * @param path the path of the transition - * @return pointer to the allocated `the transaction` variable or `NULL` if no transition created + * Remove a local style property from a part of an object with a given state. + * @param obj: pointer to an object + * @param part: the part of the object which style property should be removed. + * @param state: the state from which the property should be removed. + * @param prop: a style property to remove. + * @return true: the property was found and removed; false: the property was not found */ -void _lv_obj_create_style_transition(struct _lv_obj_t * obj, lv_style_prop_t prop, uint8_t part, lv_state_t prev_state, - lv_state_t new_state, uint32_t time, uint32_t delay, const lv_anim_path_t * path); - -#endif - -/** - * Compare the style properties of an object in 2 different states - * @param obj pointer to an object - * @param state1 a state - * @param state2 an other state - * @return an element of `_lv_style_state_cmp_t` - */ -_lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2); - +bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, uint32_t part, uint32_t state, lv_style_prop_t prop); /********************* * OBJ STYLE GET diff --git a/src/lv_core/lv_obj_tree.c b/src/lv_core/lv_obj_tree.c new file mode 100644 index 000000000..5d7a0a4a1 --- /dev/null +++ b/src/lv_core/lv_obj_tree.c @@ -0,0 +1,379 @@ +/** + * @file lv_obj_tree.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include "lv_indev.h" +#include "../lv_themes/lv_theme.h" +#include "../lv_misc/lv_anim.h" +#include "../lv_misc/lv_gc.h" +#include "../lv_misc/lv_async.h" + +/********************* + * DEFINES + *********************/ +#define LV_OBJX_NAME "lv_obj" + +#if defined(LV_USER_DATA_FREE_INCLUDE) + #include LV_USER_DATA_FREE_INCLUDE +#endif /* LV_USE_USER_DATA_FREE */ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_event_mark_deleted(lv_obj_t * obj); + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_obj_del_async_cb(void * obj); +static void obj_del_core(lv_obj_t * obj); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_obj_create_from_class(const lv_obj_class_t * class, lv_obj_t * parent, const lv_obj_t * copy) +{ + lv_obj_t * obj = lv_mem_alloc(class->instance_size); + lv_memset_00(obj, class->instance_size); + obj->class_p = class; + + class->constructor(obj, parent, copy); + + if(!copy) lv_theme_apply(obj); +// else lv_style_list_copy(&checkbox->style_indic, &checkbox_copy->style_indic); + + return obj; +} + +void lv_obj_construct_base(lv_obj_t * obj, lv_obj_t * parent, const lv_obj_t * copy) +{ + const lv_obj_class_t * original_class_p = obj->class_p; + + /*Don't let the descendant methods to run during constructing the ancestor type*/ + obj->class_p = obj->class_p->base_class; + + obj->class_p->constructor(obj, parent, copy); + + /*Restore the original class*/ + obj->class_p = original_class_p; + +} + +void lv_obj_del(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_obj_invalidate(obj); + + lv_disp_t * disp = NULL; + bool act_scr_del = false; + lv_obj_t * par = lv_obj_get_parent(obj); + if(par == NULL) { + disp = lv_obj_get_disp(obj); + if(!disp) return; /*Shouldn't happen*/ + 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) { + lv_signal_send(par, LV_SIGNAL_CHILD_CHG, NULL); + } + + /*Handle if the active screen was deleted*/ + if(act_scr_del) { + disp->act_scr = NULL; + } +} + +void lv_obj_clean(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + while(1) { + lv_obj_t * child = lv_obj_get_child(obj, 0); + obj_del_core(child); + } +} + +void lv_obj_del_anim_ready_cb(lv_anim_t * a) +{ + lv_obj_del(a->var); +} + +void lv_obj_del_async(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_async_call(lv_obj_del_async_cb, 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); + + lv_obj_allocate_spec_attr(parent); + + lv_obj_t * old_parent = 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_parent->coords.x2 - obj->coords.x2; + + /*Remove the object from the old parent's child list*/ + int32_t i; + for(i = lv_obj_get_child_id(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) { + old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i+1]; + } + old_parent->spec_attr->child_cnt--; + if(old_parent->spec_attr->child_cnt) { + old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children, old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + } else { + lv_mem_free(old_parent->spec_attr->children); + old_parent->spec_attr->children = NULL; + } + + /*Add the child to the new parent as the last (newest child)*/ + parent->spec_attr->child_cnt++; + parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj; + + 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_parent, 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); +} + +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_obj_invalidate(parent); + + uint32_t i; + for(i = lv_obj_get_child_id(obj) - 1; i > 0; i--) { + parent->spec_attr->children[i] = parent->spec_attr->children[i-1]; + } + parent->spec_attr->children[0] = obj; + + /*Notify the new parent about the child*/ + lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); + + lv_obj_invalidate(parent); +} + +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_obj_invalidate(parent); + + uint32_t i; + for(i = lv_obj_get_child_id(obj); i < lv_obj_get_child_cnt(parent) - 2; i++) { + parent->spec_attr->children[i] = parent->spec_attr->children[i + 1]; + } + parent->spec_attr->children[ lv_obj_get_child_cnt(parent) - 1] = obj; + + /*Notify the new parent about the child*/ + lv_signal_send(parent, LV_SIGNAL_CHILD_CHG, obj); + + lv_obj_invalidate(parent); +} + +lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + const lv_obj_t * par = obj; + const lv_obj_t * act_par; + + do { + act_par = par; + par = lv_obj_get_parent(act_par); + } while(par != NULL); + + return (lv_obj_t*)act_par; +} + +lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + 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`*/ + + lv_disp_t * d; + _LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) { + uint32_t i; + for(i = 0; i < d->screen_cnt; i++) { + if(d->screens[i] == scr) return d; + } + } + + LV_LOG_WARN("No screen found") + return NULL; +} + +lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + return obj->parent; +} + +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t id) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + if(obj->spec_attr == NULL) return NULL; + + if(id < 0) { + id = obj->spec_attr->child_cnt + id; + if(id < 0) return NULL; + } + + 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; +} + +uint32_t lv_obj_get_child_id(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_obj_t * parent = lv_obj_get_parent(obj); + if(parent == NULL) return 0; + + 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 0xFFFFFFFF; /*Shouldn't happen*/ +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_obj_del_async_cb(void * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_obj_del(obj); +} + +static void obj_del_core(lv_obj_t * obj) +{ + /*Let the user free the resources used in `LV_EVENT_DELETE`*/ + lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL); + if(res == LV_RES_INV) return; + + /*Delete from the group*/ +#if LV_USE_GROUP + lv_group_t * group = lv_obj_get_group(obj); + if(group) lv_group_remove_obj(obj); +#endif + + /*Remove the animations from this object*/ +#if LV_USE_ANIMATION + lv_anim_del(obj, NULL); +// _lv_obj_remove_style_trans(obj); +#endif + + /*Delete the user data*/ +#if LV_USE_USER_DATA +#if LV_USE_USER_DATA_FREE + LV_USER_DATA_FREE(obj); +#endif +#endif + + /*Recursively delete the children*/ + while(1) { + lv_obj_t * child = lv_obj_get_child(obj, 0); + obj_del_core(child); + } + + lv_event_mark_deleted(obj); + + /* Reset all input devices if the object to delete is used*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { + if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { + lv_indev_reset(indev, obj); + } + if(indev->proc.types.pointer.last_pressed == obj) { + indev->proc.types.pointer.last_pressed = NULL; + } + +#if LV_USE_GROUP + if(indev->group == group && obj == lv_indev_get_obj_act()) { + lv_indev_reset(indev, obj); + } +#endif + indev = lv_indev_get_next(indev); + } + + /* All children deleted. + * Now clean up the object specific data*/ + obj->class_p->destructor(obj); +} diff --git a/src/lv_core/lv_obj_tree.h b/src/lv_core/lv_obj_tree.h new file mode 100644 index 000000000..7f4a541a3 --- /dev/null +++ b/src/lv_core/lv_obj_tree.h @@ -0,0 +1,164 @@ +/** + * @file struct _lv_obj_tree.h + * + */ + +#ifndef LV_OBJ_TREE_H +#define LV_OBJ_TREE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_obj_class_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an object form a class descriptor + * @param class pointer to a class + * @param parent pointer to an object where the new object should be created + * @param copy pointer to an other object with the same type to copy (DEPRECATED will be removed in v9) + * @return pointer to the created object + */ +struct _lv_obj_t * lv_obj_create_from_class(const struct _lv_obj_class_t * class, struct _lv_obj_t * parent, const struct _lv_obj_t * copy); + +/** + * Used internally in widget's constructor to construct the base type + * @param obj pointer to the object being constructed + * @param parent pointer to the parent + * @param copy pointer to the object to copy (DEPRECATED will be removed in v9) + */ +void lv_obj_construct_base(struct _lv_obj_t * obj, struct _lv_obj_t * parent, const struct _lv_obj_t * copy); + +/** + * Create a basic object + * @param parent pointer to a parent object. + * If NULL then a screen will be created + * @param copy pointer to a base object, if not NULL then the new object will be copied from it + * @return pointer to the new object + */ +void lv_obj_del(struct _lv_obj_t * obj); + +/** + * Delete 'obj' and all of its children + * @param obj pointer to an object to delete + * @return LV_RES_INV because the object is deleted + */ +void lv_obj_clean(struct _lv_obj_t * obj); + +/** + * A function to be easily used in animation ready callback to delete an object when the animation is ready + * @param a pointer to the animation + */ +void lv_obj_del_anim_ready_cb(lv_anim_t * a); + +/** + * Helper function for asynchronously deleting objects. + * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). + * @param obj object to delete + * @see lv_async_call + */ +void lv_obj_del_async(struct _lv_obj_t * obj); + +/** + * Move the parent of an object. The relative coordinates will be kept. + * + * @param obj: pointer to an object whose parent needs to be changed + * @param parent: pointer to the new parent + */ +void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent); + +/** + * Move the object to the foreground. + * It will look like if it was created as the last child of its parent. + * It also means it can cover any of the siblings. + * @param obj:pointer to an object + */ +void lv_obj_move_foreground(struct _lv_obj_t * obj); + +/** + * Move the object to the background. + * It will look like if it was created as the first child of its parent. + * It also means any of the siblings can cover the object. + * @param obj:pointer to an object + */ +void lv_obj_move_background(struct _lv_obj_t * obj); + +/** + * Get the screen of an object + * @param obj: pointer to an object + * @return pointer to the obejct's screen + */ +struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj); + +/** + * Get the display of the object + * @param obj: pointer to an object + * @return pointer to the obejct's display + */ +lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj); + +/** + * Get the parent of an object + * @param obj: pointer to an object + * @return the parent of the object. (NULL if `obj` was a screen) + */ +struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj); + +/** + * Get the child of an object by the child's index. + * @param obj: pointer to an object whose child should be get + * @param id: the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return pointer to the child or NULL if the index was invalid + */ +struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id); + +/** + * Get the number of children + * @param obj: pointer to an object + * @return the number of children + */ +uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj); + +/** + * Get the index of a child. + * @param obj: pointer to an obejct + * @return the child index of the object. + * E.g. 0: the oldest (firstly created child) + */ +uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_OBJ_TREE_H*/ diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index aad9cb6c5..271dd1198 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -685,7 +685,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) lv_area_t obj_mask; lv_area_t obj_ext_mask; lv_area_t obj_area; - lv_coord_t ext_size = _lv_obj_get_ext_draw_pad(obj); + lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_obj_get_coords(obj, &obj_area); obj_area.x1 -= ext_size; obj_area.y1 -= ext_size; @@ -727,7 +727,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) 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); + ext_size = _lv_obj_get_ext_draw_size(child); child_area.x1 -= ext_size; child_area.y1 -= ext_size; child_area.x2 += ext_size; diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index cc875526e..98f2b314a 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -151,8 +151,8 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) disp->act_scr = lv_obj_create(NULL, NULL); /*Create a default screen on the display*/ disp->top_layer = lv_obj_create(NULL, NULL); /*Create top layer on the display*/ disp->sys_layer = lv_obj_create(NULL, NULL); /*Create sys layer on the display*/ - lv_obj_remove_all_styles(disp->top_layer); - lv_obj_remove_all_styles(disp->sys_layer); + lv_obj_remove_style(disp->top_layer, LV_PART_ANY, LV_STATE_ANY, NULL); + lv_obj_remove_style(disp->sys_layer, LV_PART_ANY, LV_STATE_ANY, NULL); lv_obj_clear_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE); lv_obj_clear_flag(disp->sys_layer, LV_OBJ_FLAG_CLICKABLE); diff --git a/src/lv_hal/lv_hal_indev.h b/src/lv_hal/lv_hal_indev.h index 8b1ca27e0..226a26bbb 100644 --- a/src/lv_hal/lv_hal_indev.h +++ b/src/lv_hal/lv_hal_indev.h @@ -51,12 +51,12 @@ enum { LV_INDEV_STATE_REL = 0, LV_INDEV_STATE_PR }; typedef uint8_t lv_indev_state_t; enum { - LV_SCROLL_DIR_NONE, - LV_SCROLL_DIR_HOR, - LV_SCROLL_DIR_VER, + LV_INDEV_SCROLL_DIR_NONE, + LV_INDEV_SCROLL_DIR_HOR, + LV_INDEV_SCROLL_DIR_VER, }; -typedef uint8_t lv_scroll_dir_t; +typedef uint8_t lv_indev_scroll_dir_t; enum { LV_GESTURE_DIR_TOP, /**< Gesture dir up. */ @@ -144,7 +144,7 @@ typedef struct _lv_indev_proc_t { lv_gesture_dir_t gesture_dir; lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ /*Flags*/ - lv_scroll_dir_t scroll_dir : 2; + lv_indev_scroll_dir_t scroll_dir : 2; uint8_t gesture_sent : 1; } pointer; struct { diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index 6bd895f35..ef9c82f58 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -59,7 +59,7 @@ void _lv_anim_core_init(void) last_task_run = lv_tick_get(); _lv_anim_tmr = lv_timer_create(anim_task, LV_DISP_DEF_REFR_PERIOD, NULL); anim_mark_list_change(); /*Turn off the animation task*/ - anim_list_changed = false; /*The list has not actually changed*/ + anim_list_changed = false; } /** diff --git a/src/lv_misc/lv_class.c b/src/lv_misc/lv_class.c deleted file mode 100644 index c086afdb4..000000000 --- a/src/lv_misc/lv_class.c +++ /dev/null @@ -1,89 +0,0 @@ -///** -// * @file lv_class.c -// * -// */ -// -///********************* -// * INCLUDES -// *********************/ -//#include "lv_class.h" -//#include "lv_mem.h" -// -///********************* -// * DEFINES -// *********************/ -// -///********************** -// * TYPEDEFS -// **********************/ -// -///********************** -// * STATIC PROTOTYPES -// **********************/ -// -///********************** -// * STATIC VARIABLES -// **********************/ -//lv_base_class_t lv_base; -// -///********************** -// * MACROS -// **********************/ -// -///********************** -// * GLOBAL FUNCTIONS -// **********************/ -// -//void _lv_class_init(void * class_p, uint32_t class_size, uint32_t instance_size, void * base_p) -//{ -// lv_base_class_t * c = class_p; -// const lv_base_class_t * bc = base_p; -// lv_memset_00(c, class_size); -// -// /*By default use the same methods as the base*/ -// 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->init = NULL; -// c->constructor = NULL; -// c->_instance_size = instance_size; -// c->_class_size = class_size; -// c->_inited = 1; -//} -// -//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; -// return instance; -//} -// -// -//void lv_class_destroy(void * instance) -//{ -// lv_mem_free(instance); -//} -// -///********************** -// * 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 -// */ -//void lv_class_base_construct(void * inst) -//{ -// lv_base_t * base_inst = inst; -// void * class_p = base_inst->class_p; -// lv_memset_00(inst, base_inst->class_p->_instance_size); -// base_inst->class_p = class_p; /*Restore class dsc pointer*/ -//} diff --git a/src/lv_misc/lv_class.h b/src/lv_misc/lv_class.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lv_misc/lv_mem.c b/src/lv_misc/lv_mem.c index b389c52d6..af5d93def 100644 --- a/src/lv_misc/lv_mem.c +++ b/src/lv_misc/lv_mem.c @@ -153,13 +153,17 @@ void lv_mem_deinit(void) */ void * lv_mem_alloc(size_t size) { + + if(size == 0) { + printf("alloc: 0\n"); return &zero_mem; } /*Round the size up to ALIGN_MASK*/ size = (size + ALIGN_MASK) & (~ALIGN_MASK); void * alloc = NULL; + printf("alloc: %d\n", size); #if LV_MEM_CUSTOM == 0 alloc = alloc_core(size); @@ -217,12 +221,17 @@ void * lv_mem_alloc(size_t size) */ void lv_mem_free(const void * data) { - if(data == &zero_mem) return; + if(data == &zero_mem) { + printf("free: %d\n", 0); + return; + } if(data == NULL) return; + #if LV_ENABLE_GC == 0 /*e points to the header*/ lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data - sizeof(lv_mem_header_t)); + printf("free: %d\n", e->header.s.d_size); # if LV_MEM_ADD_JUNK lv_memset((void *)data, 0xbb, lv_mem_get_size(data)); # endif @@ -291,9 +300,8 @@ void * lv_mem_realloc(void * data_p, size_t new_size) if(data_p != NULL) { /*Copy the old data to the new. Use the smaller size*/ - if(old_size != 0) { + if(old_size != 0 && new_size != 0) { lv_memcpy(new_p, data_p, LV_MIN(new_size, old_size)); - lv_mem_free(data_p); } lv_mem_free(data_p); } diff --git a/src/lv_misc/lv_style.c b/src/lv_misc/lv_style.c index 1efb1cc26..a20630e9e 100644 --- a/src/lv_misc/lv_style.c +++ b/src/lv_misc/lv_style.c @@ -70,6 +70,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) if(!style->allocated) { if(style->prop1 == prop) { style->prop1 = LV_STYLE_PROP_INV; + style->prop_cnt = 0; return true; } return false; diff --git a/src/lv_themes/lv_theme.c b/src/lv_themes/lv_theme.c index 832b2ff04..74e927898 100644 --- a/src/lv_themes/lv_theme.c +++ b/src/lv_themes/lv_theme.c @@ -60,12 +60,12 @@ lv_theme_t * lv_theme_get_act(void) */ void lv_theme_apply(lv_obj_t * obj) { - lv_obj_remove_all_styles_no_refresh(obj); + lv_obj_remove_style(obj, LV_PART_ANY, LV_STATE_ANY, NULL); /*Apply the theme including the base theme(s)*/ apply_theme(act_theme, obj); - _lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); } /** diff --git a/src/lv_themes/lv_theme_default.c b/src/lv_themes/lv_theme_default.c index 760b48b0c..de637b088 100644 --- a/src/lv_themes/lv_theme_default.c +++ b/src/lv_themes/lv_theme_default.c @@ -300,7 +300,7 @@ static void basic_init(void) style_init_reset(&styles->grow); lv_style_set_transform_width(&styles->grow, LV_DPX(3)); - lv_style_set_transform_angle(&styles->grow, LV_DPX(3)); + lv_style_set_transform_height(&styles->grow, LV_DPX(3)); style_init_reset(&styles->knob); lv_style_set_bg_color(&styles->knob, IS_LIGHT ? theme.color_primary : LV_COLOR_WHITE); @@ -479,158 +479,158 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) LV_UNUSED(th); if(lv_obj_get_parent(obj) == NULL) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->scr); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->scr); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); return; } if(lv_obj_check_type(obj, &lv_obj)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); } #if LV_USE_BTN else if(lv_obj_check_type(obj, &lv_btn)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->btn); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_delayed); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->pressed); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->transition_normal); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->grow); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_CHECKED, &styles->bg_color_secondary); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->btn); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_delayed); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->pressed); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->grow); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_CHECKED, &styles->bg_color_secondary); } #endif #if LV_USE_BTNMATRIX else if(lv_obj_check_type(obj, &lv_btnmatrix)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_gap); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->btn); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->pressed); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->grow); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->transition_delayed); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_gap); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->btn); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->pressed); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->grow); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->transition_delayed); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_PRESSED, &styles->transition_normal); } #endif #if LV_USE_BAR else if(lv_obj_check_type(obj, &lv_bar)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); } #endif #if LV_USE_SLIDER else if(lv_obj_check_type(obj, &lv_slider)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_delayed); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->transition_normal); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_PRESSED, &styles->grow); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->transition_delayed); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_PRESSED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_delayed); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_PRESSED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_PRESSED, &styles->grow); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->transition_delayed); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_PRESSED, &styles->transition_normal); } #endif #if LV_USE_TABLE else if(lv_obj_check_type(obj, &lv_table)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_SCROLLED, &styles->transition_normal); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->bg_color_white); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->table_cell); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->pad_small); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_SCROLLED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->bg_color_white); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->table_cell); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->pad_small); } #endif #if LV_USE_CHECKBOX else if(lv_obj_check_type(obj, &lv_checkbox)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_gap); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->cb_marker); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_CHECKED, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_CHECKED, &styles->cb_marker_checked); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->pressed); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->grow); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->transition_normal); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->transition_delayed); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_gap); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->cb_marker); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_CHECKED, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_CHECKED, &styles->cb_marker_checked); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->pressed); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->grow); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_PRESSED, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->transition_delayed); } #endif #if LV_USE_SWITCH else if(lv_obj_check_type(obj, &lv_switch)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->bg_color_white); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->pad_small_negative); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->bg_color_gray); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->circle); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->bg_color_white); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->pad_small_negative); } #endif #if LV_USE_CHART else if(lv_obj_check_type(obj, &lv_chart)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->line_dashed); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_zero); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); - lv_obj_add_style_no_refresh(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->chart_series); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->pad_small); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->chart_ticks); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->line_dashed); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->pad_zero); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); + lv_obj_add_style(obj, LV_PART_ITEMS, LV_STATE_DEFAULT, &styles->chart_series); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->pad_small); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->chart_ticks); } #endif #if LV_USE_ROLLER else if(lv_obj_check_type(obj, &lv_roller)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->anim); - lv_obj_add_style_no_refresh(obj, LV_PART_HIGHLIGHT, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->anim); + lv_obj_add_style(obj, LV_PART_SELECTED, LV_STATE_DEFAULT, &styles->bg_color_primary); } #endif #if LV_USE_DROPDOWN else if(lv_obj_check_type(obj, &lv_dropdown)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_CHECKED, &styles->ddlist_flip); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_normal); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_CHECKED, &styles->ddlist_flip); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->transition_normal); } else if(lv_obj_check_type(obj, &lv_dropdown_list)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_HIGHLIGHT, LV_STATE_DEFAULT, &styles->bg_color_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_HIGHLIGHT, LV_STATE_PRESSED, &styles->bg_color_gray); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_SELECTED, LV_STATE_DEFAULT, &styles->bg_color_primary); + lv_obj_add_style(obj, LV_PART_SELECTED, LV_STATE_PRESSED, &styles->bg_color_gray); } #endif #if LV_USE_ARC else if(lv_obj_check_type(obj, &lv_arc)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->arc_indic); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->arc_indic); - lv_obj_add_style_no_refresh(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->arc_indic_primary); - lv_obj_add_style_no_refresh(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->arc_indic); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->arc_indic); + lv_obj_add_style(obj, LV_PART_INDICATOR, LV_STATE_DEFAULT, &styles->arc_indic_primary); + lv_obj_add_style(obj, LV_PART_KNOB, LV_STATE_DEFAULT, &styles->knob); } #endif #if LV_USE_METER else if(lv_obj_check_type(obj, &lv_meter)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->meter_marker); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->meter_marker); } #endif #if LV_USE_TEXTAREA else if(lv_obj_check_type(obj, &lv_textarea)) { - lv_obj_add_style_no_refresh(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); - lv_obj_add_style_no_refresh(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); - lv_obj_add_style_no_refresh(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->ta_cursor); + lv_obj_add_style(obj, LV_PART_MAIN, LV_STATE_DEFAULT, &styles->card); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_DEFAULT, &styles->scrollbar); + lv_obj_add_style(obj, LV_PART_SCROLLBAR, LV_STATE_SCROLLED, &styles->scrollbar_scrolled); + lv_obj_add_style(obj, LV_PART_MARKER, LV_STATE_DEFAULT, &styles->ta_cursor); } #endif diff --git a/src/lv_widgets/lv_arc.c b/src/lv_widgets/lv_arc.c index d659894e3..1b22846d1 100644 --- a/src/lv_widgets/lv_arc.c +++ b/src/lv_widgets/lv_arc.c @@ -47,6 +47,7 @@ const lv_obj_class_t lv_arc = { .signal_cb = lv_arc_signal, .draw_cb = lv_arc_draw, .instance_size = sizeof(lv_arc_t), + .editable = 1, .base_class = &lv_obj }; @@ -708,12 +709,6 @@ static lv_res_t lv_arc_signal(lv_obj_t * obj, lv_signal_t sign, void * param) if(res != LV_RES_OK) return res; } } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } return res; } diff --git a/src/lv_widgets/lv_btnmatrix.c b/src/lv_widgets/lv_btnmatrix.c index b7f08e376..8cb1f51a4 100644 --- a/src/lv_widgets/lv_btnmatrix.c +++ b/src/lv_widgets/lv_btnmatrix.c @@ -59,6 +59,7 @@ const lv_obj_class_t lv_btnmatrix = { .signal_cb = lv_btnmatrix_signal, .draw_cb = lv_btnmatrix_draw, .instance_size = sizeof(lv_btnmatrix_t), + .editable = 1, .base_class = &lv_obj }; @@ -993,12 +994,6 @@ static lv_res_t lv_btnmatrix_signal(lv_obj_t * obj, lv_signal_t sign, void * par btnm->btn_id_act = btnm->btn_id_focused; lv_obj_invalidate(obj); } -#endif - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; #endif } return res; diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index 9c8070650..ecc3c0ba0 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -1133,14 +1133,14 @@ static void draw_cursors(lv_obj_t * obj, const lv_area_t * clip_area) lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_CURSOR, &line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MARKER, &line_dsc); lv_draw_rect_dsc_t point_dsc; lv_draw_rect_dsc_init(&point_dsc); point_dsc.bg_opa = line_dsc.opa; point_dsc.radius = LV_RADIUS_CIRCLE; - lv_coord_t point_radius = lv_obj_get_style_size(chart, LV_PART_CURSOR); + lv_coord_t point_radius = lv_obj_get_style_size(chart, LV_PART_MARKER); /*Do not bother with line ending is the point will over it*/ if(point_radius > line_dsc.width / 2) line_dsc.raw_end = 1; @@ -1461,7 +1461,7 @@ static void invalidate_point(lv_obj_t * obj, uint16_t i) _lv_inv_area(lv_obj_get_disp(obj), &col_a); } else { - lv_obj_invalidate(chart); + lv_obj_invalidate(obj); } } diff --git a/src/lv_widgets/lv_checkbox.c b/src/lv_widgets/lv_checkbox.c index ffcd1514a..103cfdd00 100644 --- a/src/lv_widgets/lv_checkbox.c +++ b/src/lv_widgets/lv_checkbox.c @@ -290,6 +290,13 @@ static lv_res_t lv_checkbox_signal(lv_obj_t * obj, lv_signal_t sign, void * para lv_coord_t m = lv_obj_calculate_ext_draw_size(obj, LV_PART_MARKER); *s = LV_MAX(*s, m); } + else if(sign == LV_SIGNAL_RELEASED) { + uint32_t v = lv_obj_get_state(obj) & LV_STATE_CHECKED ? 1 : 0; + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &v); + if(res != LV_RES_OK) return res; + + lv_obj_invalidate(obj); + } return res; } diff --git a/src/lv_widgets/lv_dropdown.c b/src/lv_widgets/lv_dropdown.c index 5a5611206..e14f3eb97 100644 --- a/src/lv_widgets/lv_dropdown.c +++ b/src/lv_widgets/lv_dropdown.c @@ -66,6 +66,7 @@ const lv_obj_class_t lv_dropdown = { .signal_cb = lv_dropdown_signal, .draw_cb = lv_dropdown_draw, .instance_size = sizeof(lv_dropdown_t), + .editable = 1, .base_class = &lv_obj }; @@ -983,12 +984,6 @@ static lv_res_t lv_dropdown_signal(lv_obj_t * obj, lv_signal_t sign, void * para } #endif } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } return res; } @@ -1037,8 +1032,8 @@ static void draw_box(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, uint1 } /*Draw a rectangle under the selected item*/ - const lv_font_t * font = lv_obj_get_style_text_font(list_obj, LV_PART_HIGHLIGHT); - lv_coord_t line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_HIGHLIGHT); + const lv_font_t * font = lv_obj_get_style_text_font(list_obj, LV_PART_SELECTED); + lv_coord_t line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_SELECTED); lv_coord_t font_h = lv_font_get_line_height(font); /*Draw the selected*/ @@ -1054,7 +1049,7 @@ static void draw_box(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, uint1 lv_draw_rect_dsc_t sel_rect; lv_draw_rect_dsc_init(&sel_rect); - lv_obj_init_draw_rect_dsc(list_obj, LV_PART_HIGHLIGHT, &sel_rect); + lv_obj_init_draw_rect_dsc(list_obj, LV_PART_SELECTED, &sel_rect); lv_draw_rect(&rect_area, clip_area, &sel_rect); list_obj->state = state_orig; @@ -1072,9 +1067,9 @@ static void draw_box_label(lv_obj_t * dropdown_obj, const lv_area_t * clip_area, lv_draw_label_dsc_t label_dsc; lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(list_obj, LV_PART_HIGHLIGHT, &label_dsc); + lv_obj_init_draw_label_dsc(list_obj, LV_PART_SELECTED, &label_dsc); - label_dsc.line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_HIGHLIGHT); /*Line space should come from the list*/ + label_dsc.line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_SELECTED); /*Line space should come from the list*/ lv_obj_t * label = get_label(dropdown_obj); if(label == NULL) return; @@ -1183,7 +1178,6 @@ static uint16_t get_id_on_point(lv_obj_t * dropdown_obj, lv_coord_t y) static void position_to_selected(lv_obj_t * dropdown_obj) { lv_dropdown_t * dropdown = (lv_dropdown_t *) dropdown_obj; - lv_obj_t * list_obj = dropdown->list; lv_obj_t * label = get_label(dropdown_obj); if(label == NULL) return; diff --git a/src/lv_widgets/lv_img.c b/src/lv_widgets/lv_img.c index 926155493..00b0cb945 100644 --- a/src/lv_widgets/lv_img.c +++ b/src/lv_widgets/lv_img.c @@ -740,8 +740,11 @@ static lv_res_t lv_img_signal(lv_obj_t * obj, lv_signal_t sign, void * param) info->result = _lv_area_is_point_on(&coords, info->point, 0); } - else - info->result = _lv_obj_is_click_point_on(obj, info->point); + else { + lv_area_t a; + lv_obj_get_click_area(obj, &a); + info->result = _lv_area_is_point_on(&a, info->point, 0); + } } else if(sign == LV_SIGNAL_GET_SELF_SIZE) { lv_point_t * p = param; diff --git a/src/lv_widgets/lv_imgbtn.c b/src/lv_widgets/lv_imgbtn.c index d7e787b24..853d713db 100644 --- a/src/lv_widgets/lv_imgbtn.c +++ b/src/lv_widgets/lv_imgbtn.c @@ -101,7 +101,7 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy) #endif ext->tiled = copy_ext->tiled; /*Refresh the style with new signal function*/ - _lv_obj_refresh_style(imgbtn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); + lv_obj_refresh_style(imgbtn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); } LV_LOG_INFO("image button created"); diff --git a/src/lv_widgets/lv_label.c b/src/lv_widgets/lv_label.c index 5769ddce6..277d3161e 100644 --- a/src/lv_widgets/lv_label.c +++ b/src/lv_widgets/lv_label.c @@ -1132,8 +1132,8 @@ static lv_draw_res_t lv_label_draw(lv_obj_t * obj, const lv_area_t * clip_area, label_draw_dsc.sel_start = lv_label_get_text_sel_start(obj); label_draw_dsc.sel_end = lv_label_get_text_sel_end(obj); if(label_draw_dsc.sel_start != LV_DRAW_LABEL_NO_TXT_SEL && label_draw_dsc.sel_end != LV_DRAW_LABEL_NO_TXT_SEL) { - label_draw_dsc.sel_color = lv_obj_get_style_text_color_filtered(obj, LV_PART_HIGHLIGHT); - label_draw_dsc.sel_bg_color = lv_obj_get_style_bg_color(obj, LV_PART_HIGHLIGHT); + label_draw_dsc.sel_color = lv_obj_get_style_text_color_filtered(obj, LV_PART_SELECTED); + label_draw_dsc.sel_bg_color = lv_obj_get_style_bg_color(obj, LV_PART_SELECTED); } /* In SROLL and SROLL_CIRC mode the CENTER and RIGHT are pointless so remove them. diff --git a/src/lv_widgets/lv_roller.c b/src/lv_widgets/lv_roller.c index 82bfda0f9..42ea20321 100644 --- a/src/lv_widgets/lv_roller.c +++ b/src/lv_widgets/lv_roller.c @@ -389,14 +389,14 @@ static lv_draw_res_t lv_roller_draw(lv_obj_t * obj, const lv_area_t * clip_area, lv_draw_rect_dsc_t sel_dsc; lv_draw_rect_dsc_init(&sel_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_HIGHLIGHT, &sel_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_SELECTED, &sel_dsc); lv_draw_rect(&rect_area, clip_area, &sel_dsc); } /*Post draw when the children are drawn*/ else if(mode == LV_DRAW_MODE_POST_DRAW) { lv_draw_label_dsc_t label_dsc; lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_HIGHLIGHT, &label_dsc); + lv_obj_init_draw_label_dsc(obj, LV_PART_SELECTED, &label_dsc); lv_coord_t bg_font_h = lv_font_get_line_height(lv_obj_get_style_text_font(obj, LV_PART_MAIN)); @@ -844,8 +844,8 @@ static lv_coord_t get_selected_label_width(const lv_obj_t * obj) lv_obj_t * label = get_label(obj); if(label == NULL) return 0; - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_HIGHLIGHT); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_HIGHLIGHT); + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_SELECTED); + lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_SELECTED); const char * txt = lv_label_get_text(label); lv_point_t size; _lv_txt_get_size(&size, txt, font, letter_space, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); diff --git a/src/lv_widgets/lv_slider.c b/src/lv_widgets/lv_slider.c index c62881807..1186382e0 100644 --- a/src/lv_widgets/lv_slider.c +++ b/src/lv_widgets/lv_slider.c @@ -48,6 +48,7 @@ const lv_obj_class_t lv_slider = { .destructor = lv_slider_destructor, .signal_cb = lv_slider_signal, .draw_cb = lv_slider_draw, + .editable = 1, .instance_size = sizeof(lv_slider_t), .base_class = &lv_bar }; @@ -379,12 +380,6 @@ static lv_res_t lv_slider_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } #endif } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } return res; } diff --git a/src/lv_widgets/lv_switch.c b/src/lv_widgets/lv_switch.c index f00ff98b1..f52a25db3 100644 --- a/src/lv_widgets/lv_switch.c +++ b/src/lv_widgets/lv_switch.c @@ -224,14 +224,12 @@ static lv_res_t lv_switch_signal(lv_obj_t * obj, lv_signal_t sign, void * param) *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); } else if(sign == LV_SIGNAL_RELEASED) { + uint32_t v = lv_obj_get_state(obj) & LV_STATE_CHECKED ? 1 : 0; + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &v); + if(res != LV_RES_OK) return res; + lv_obj_invalidate(obj); } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = false; /*The ancestor slider is editable the switch is not*/ -#endif - } return res; } diff --git a/src/lv_widgets/lv_textarea.c b/src/lv_widgets/lv_textarea.c index d7a06a0c1..b5364e47e 100644 --- a/src/lv_widgets/lv_textarea.c +++ b/src/lv_widgets/lv_textarea.c @@ -72,6 +72,7 @@ const lv_obj_class_t lv_textarea = { .destructor = lv_textarea_destructor, .signal_cb = lv_textarea_signal, .draw_cb = lv_textarea_draw, + .editable = 1, .instance_size = sizeof(lv_textarea_t), .base_class = &lv_obj }; @@ -1152,12 +1153,6 @@ static lv_res_t lv_textarea_signal(lv_obj_t * obj, lv_signal_t sign, void * para else { lv_textarea_add_char(obj, c); } -#endif - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; #endif } else if(sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESSING || sign == LV_SIGNAL_PRESS_LOST ||