From 877b30017d2504d97372d48120deb7f00b63f186 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 14 Sep 2020 20:13:43 +0200 Subject: [PATCH] move some widgets to lv_components repo --- lvgl.h | 14 - src/lv_core/lv_grid.c | 10 + src/lv_core/lv_grid.h | 37 +- src/lv_core/lv_obj.c | 215 +++-- src/lv_core/lv_obj.h | 35 +- src/lv_core/lv_obj_scroll.c | 4 +- src/lv_core/lv_obj_style.c | 9 +- src/lv_hal/lv_hal_disp.c | 6 +- src/lv_themes/lv_theme_material.c | 6 - src/lv_themes/lv_theme_mono.c | 8 +- src/lv_themes/lv_theme_template.c | 6 - src/lv_widgets/lv_btn.c | 224 +---- src/lv_widgets/lv_btn.h | 167 +--- src/lv_widgets/lv_calendar.c | 1087 ----------------------- src/lv_widgets/lv_calendar.h | 199 ----- src/lv_widgets/lv_cont.c | 795 ----------------- src/lv_widgets/lv_cont.h | 223 ----- src/lv_widgets/lv_cpicker.c | 1039 ---------------------- src/lv_widgets/lv_cpicker.h | 229 ----- src/lv_widgets/lv_keyboard.c | 479 ---------- src/lv_widgets/lv_keyboard.h | 180 ---- src/lv_widgets/lv_label.c | 50 +- src/lv_widgets/lv_label.h | 5 +- src/lv_widgets/lv_led.c | 251 ------ src/lv_widgets/lv_led.h | 97 -- src/lv_widgets/lv_linemeter.c | 634 ------------- src/lv_widgets/lv_linemeter.h | 170 ---- src/lv_widgets/lv_list.c | 923 ------------------- src/lv_widgets/lv_list.h | 311 ------- src/lv_widgets/lv_msgbox.c | 606 ------------- src/lv_widgets/lv_msgbox.h | 188 ---- src/lv_widgets/lv_page.c | 1375 ----------------------------- src/lv_widgets/lv_page.h | 427 --------- src/lv_widgets/lv_spinbox.c | 603 ------------- src/lv_widgets/lv_spinbox.h | 176 ---- src/lv_widgets/lv_spinner.c | 326 ------- src/lv_widgets/lv_spinner.h | 180 ---- src/lv_widgets/lv_tabview.c | 1033 ---------------------- src/lv_widgets/lv_tabview.h | 192 ---- src/lv_widgets/lv_tileview.c | 475 ---------- src/lv_widgets/lv_tileview.h | 164 ---- src/lv_widgets/lv_win.c | 807 ----------------- src/lv_widgets/lv_win.h | 300 ------- 43 files changed, 181 insertions(+), 14084 deletions(-) delete mode 100644 src/lv_widgets/lv_calendar.c delete mode 100644 src/lv_widgets/lv_calendar.h delete mode 100644 src/lv_widgets/lv_cont.c delete mode 100644 src/lv_widgets/lv_cont.h delete mode 100644 src/lv_widgets/lv_cpicker.c delete mode 100644 src/lv_widgets/lv_cpicker.h delete mode 100644 src/lv_widgets/lv_keyboard.c delete mode 100644 src/lv_widgets/lv_keyboard.h delete mode 100644 src/lv_widgets/lv_led.c delete mode 100644 src/lv_widgets/lv_led.h delete mode 100644 src/lv_widgets/lv_linemeter.c delete mode 100644 src/lv_widgets/lv_linemeter.h delete mode 100644 src/lv_widgets/lv_list.c delete mode 100644 src/lv_widgets/lv_list.h delete mode 100644 src/lv_widgets/lv_msgbox.c delete mode 100644 src/lv_widgets/lv_msgbox.h delete mode 100644 src/lv_widgets/lv_page.c delete mode 100644 src/lv_widgets/lv_page.h delete mode 100644 src/lv_widgets/lv_spinbox.c delete mode 100644 src/lv_widgets/lv_spinbox.h delete mode 100644 src/lv_widgets/lv_spinner.c delete mode 100644 src/lv_widgets/lv_spinner.h delete mode 100644 src/lv_widgets/lv_tabview.c delete mode 100644 src/lv_widgets/lv_tabview.h delete mode 100644 src/lv_widgets/lv_tileview.c delete mode 100644 src/lv_widgets/lv_tileview.h delete mode 100644 src/lv_widgets/lv_win.c delete mode 100644 src/lv_widgets/lv_win.h diff --git a/lvgl.h b/lvgl.h index 1ab541ea0..c6521df22 100644 --- a/lvgl.h +++ b/lvgl.h @@ -49,34 +49,20 @@ extern "C" { #include "src/lv_widgets/lv_img.h" #include "src/lv_widgets/lv_label.h" #include "src/lv_widgets/lv_line.h" -#include "src/lv_widgets/lv_page.h" -#include "src/lv_widgets/lv_cont.h" -#include "src/lv_widgets/lv_list.h" #include "src/lv_widgets/lv_chart.h" #include "src/lv_widgets/lv_table.h" #include "src/lv_widgets/lv_checkbox.h" -#include "src/lv_widgets/lv_cpicker.h" #include "src/lv_widgets/lv_bar.h" #include "src/lv_widgets/lv_slider.h" -#include "src/lv_widgets/lv_led.h" #include "src/lv_widgets/lv_btnmatrix.h" -#include "src/lv_widgets/lv_keyboard.h" #include "src/lv_widgets/lv_dropdown.h" #include "src/lv_widgets/lv_roller.h" #include "src/lv_widgets/lv_textarea.h" #include "src/lv_widgets/lv_canvas.h" -#include "src/lv_widgets/lv_win.h" -#include "src/lv_widgets/lv_tabview.h" -#include "src/lv_widgets/lv_tileview.h" -#include "src/lv_widgets/lv_msgbox.h" #include "src/lv_widgets/lv_objmask.h" #include "src/lv_widgets/lv_gauge.h" -#include "src/lv_widgets/lv_linemeter.h" #include "src/lv_widgets/lv_switch.h" #include "src/lv_widgets/lv_arc.h" -#include "src/lv_widgets/lv_spinner.h" -#include "src/lv_widgets/lv_calendar.h" -#include "src/lv_widgets/lv_spinbox.h" #include "src/lv_draw/lv_img_cache.h" diff --git a/src/lv_core/lv_grid.c b/src/lv_core/lv_grid.c index 845054be5..b7aadcfce 100644 --- a/src/lv_core/lv_grid.c +++ b/src/lv_core/lv_grid.c @@ -37,6 +37,12 @@ static void report_grid_change_core(const lv_grid_t * grid, lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ +static const lv_coord_t lv_grid_1_dsc[1] = {LV_GRID_FR(1)}; +const lv_grid_t lv_grid_center = { + .col_dsc = lv_grid_1_dsc, + .col_dsc_len = 1, + .col_place = LV_GRID_CENTER, + .row_place = LV_GRID_CENTER}; /********************** * MACROS @@ -99,6 +105,10 @@ void lv_obj_report_grid_change(const lv_grid_t * grid) void _lv_grid_calc(struct _lv_obj_t * cont, _lv_grid_calc_t * calc_out) { if(cont->grid == NULL) return; + if(lv_obj_get_child(cont, NULL) == NULL) { + _lv_memset_00(calc_out, sizeof(_lv_grid_calc_t)); + return; + } // printf("calc: %d, %d\n", obj->grid->col_dsc_len, obj->grid->row_dsc_len); if(cont->grid->col_dsc && cont->grid->row_dsc) { diff --git a/src/lv_core/lv_grid.h b/src/lv_core/lv_grid.h index 14ac908ba..d2cf08c3b 100644 --- a/src/lv_core/lv_grid.h +++ b/src/lv_core/lv_grid.h @@ -77,14 +77,6 @@ extern "C" { struct _lv_obj_t; typedef struct _lv_obj_t lv_obj_t; -/** - * Describe how to flow LV_GRID_POS_AUTO elements - */ -typedef enum { - LV_GRID_FLOW_COLUMN, /**Fill each column and add now columns if required*/ - LV_GRID_FLOW_ROW, /**Fill each row and add now rows if required*/ -}lv_grid_flow_t; - typedef struct { const lv_coord_t * col_dsc; const lv_coord_t * row_dsc; @@ -92,7 +84,6 @@ typedef struct { uint8_t row_dsc_len; lv_coord_t col_gap; lv_coord_t row_gap; - lv_grid_flow_t flow; uint8_t col_place; uint8_t row_place; }lv_grid_t; @@ -118,6 +109,28 @@ void lv_grid_set_template(lv_grid_t * grid, const lv_coord_t * col_dsc, const lv void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_place, uint8_t row_place); +/** + * Set a grid for an object + * @param obj pointer to an object + * @param grid the grid to set + */ +void lv_obj_set_grid(lv_obj_t * obj, const lv_grid_t * grid); + +/** + * Get the grid of an object + * @param obj pointer to an object + * @return the grid, NULL if no grid + */ +const lv_grid_t * lv_obj_get_grid(lv_obj_t * obj, const lv_grid_t * grid); + + +/** + * Notify all object if a style is modified + * @param grid pointer to a grid. Only the objects with this grid will be notified + * (NULL to notify all objects with any grid) + */ +void lv_obj_report_grid_change(const lv_grid_t * grid); + void _lv_grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc); void _lv_grid_calc_free(_lv_grid_calc_t * calc); @@ -132,6 +145,12 @@ void lv_grid_item_refr_pos(lv_obj_t * item); bool _lv_obj_is_grid_item(lv_obj_t * obj); + +/********************** + * GLOBAL VARIABLES + **********************/ +extern const lv_grid_t lv_grid_center; + /********************** * MACROS **********************/ diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index d440179e6..0b0f40944 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -180,10 +180,9 @@ void lv_deinit(void) * 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 */ -lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) +lv_obj_t * lv_obj_create(lv_obj_t * parent) { lv_obj_t * new_obj = NULL; @@ -277,7 +276,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) #if LV_USE_GROUP new_obj->group_p = NULL; - #endif /*Set attributes*/ @@ -292,49 +290,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->ext_attr = NULL; lv_style_list_init(&new_obj->style_list); - if(copy == NULL) { - if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ); - else lv_theme_apply(new_obj, LV_THEME_SCR); - } - else { - lv_style_list_copy(&new_obj->style_list, ©->style_list); - } - /*Copy the attributes if required*/ - if(copy != NULL) { - lv_area_copy(&new_obj->coords, ©->coords); - new_obj->ext_draw_pad = copy->ext_draw_pad; - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - lv_area_copy(&new_obj->ext_click_pad, ©->ext_click_pad); -#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - new_obj->ext_click_pad = copy->ext_click_pad; -#endif - - /*Set user data*/ -#if LV_USE_USER_DATA - _lv_memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t)); -#endif - - /*Only copy the `event_cb`. `signal_cb` and `design_cb` will be copied in the derived - * object type (e.g. `lv_btn`)*/ - new_obj->event_cb = copy->event_cb; - - /*Copy attributes*/ - new_obj->flags = copy->flags; - new_obj->scroll_mode = copy->scroll_mode; - -#if LV_USE_GROUP - /*Add to the same group*/ - if(copy->group_p != NULL) { - lv_group_add_obj(copy->group_p, new_obj); - } -#endif - - /*Set the same coordinates for non screen objects*/ - if(lv_obj_get_parent(copy) != NULL && parent != NULL) { - lv_obj_set_pos(new_obj, lv_obj_get_x(copy), lv_obj_get_y(copy)); - } - } + if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ); + else lv_theme_apply(new_obj, LV_THEME_SCR); lv_obj_set_pos(new_obj, 0, 0); @@ -1298,18 +1255,7 @@ lv_state_t lv_obj_get_state(const lv_obj_t * obj, uint8_t part) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - if(part < _LV_OBJ_PART_REAL_LAST) return ((lv_obj_t *)obj)->state; - - /*If a real part is asked, then use the object's signal to get its state. - * A real object can be in different state then the main part - * and only the object itself knows who to get it's state. */ - lv_get_state_info_t info; - info.part = part; - info.result = LV_STATE_DEFAULT; - lv_signal_send((lv_obj_t *)obj, LV_SIGNAL_GET_STATE_DSC, &info); - - return info.result; - + return ((lv_obj_t *)obj)->state; } /** @@ -1808,75 +1754,59 @@ static void base_dir_refr_children(lv_obj_t * obj) */ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) { + lv_res_t res = LV_RES_OK; + if(sign == LV_SIGNAL_GET_STYLE) { lv_get_style_info_t * info = param; if(info->part == LV_OBJ_PART_MAIN) info->result = &obj->style_list; else info->result = NULL; return LV_RES_OK; } - else if(sign == LV_SIGNAL_GET_TYPE) return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_res_t res = LV_RES_OK; - - if(sign == LV_SIGNAL_COORD_CHG) { - if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) || - (lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj))) - { - _lv_grid_full_refresh(obj); - } - } - else if(sign == LV_SIGNAL_CHILD_CHG) { - if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { - lv_obj_set_size(obj, obj->w_set, obj->h_set); - } - - if(obj->grid) { - lv_obj_t * child = param; - if(child) { - if(_lv_obj_is_grid_item(child)) _lv_grid_full_refresh(obj); - } else { - _lv_grid_full_refresh(obj); - } - } - } - else if(sign == LV_SIGNAL_SCROLL) { - res = lv_event_send(obj, LV_EVENT_SCROLLED, NULL); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_SCROLL_END) { - if(lv_obj_get_scroll_mode(obj) == LV_SCROLL_MODE_ACTIVE) { - lv_obj_invalidate(obj); - } - - } - else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - lv_coord_t d = 0;//_lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); - obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - if(_lv_obj_is_grid_item(obj)) _lv_grid_full_refresh(obj); - - if(obj->grid) _lv_grid_full_refresh(obj); - - /*Reposition non grid objects on by one*/ - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child) { - if(!_GRID_IS_CELL(child->x_set) || !_GRID_IS_CELL(child->y_set)) { - lv_obj_set_pos(child, child->x_set, child->y_set); - } - child = lv_obj_get_child(obj, child); - } - - if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { - lv_obj_set_size(obj, obj->w_set, obj->h_set); - } - _lv_obj_refresh_ext_draw_pad(obj); + else if(sign == LV_SIGNAL_GET_TYPE) { + return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); } else if(sign == LV_SIGNAL_PRESSED) { lv_obj_add_state(obj, LV_STATE_PRESSED); } - else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { + else if(sign == LV_SIGNAL_RELEASED) { lv_obj_clear_state(obj, LV_STATE_PRESSED); + + /*Go the checked state if enabled*/ + if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { + uint32_t toggled = 0; + if(!(lv_obj_get_state(obj, LV_OBJ_PART_MAIN) & LV_STATE_CHECKED)) { + 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; + } + } + else if(sign == LV_SIGNAL_PRESS_LOST) { + lv_obj_clear_state(obj, LV_STATE_PRESSED); + } + else if(sign == LV_SIGNAL_CONTROL) { +#if LV_USE_GROUP + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { + uint32_t state = 0; + char c = *((char *)param); + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { + lv_obj_set_state(obj, LV_STATE_CHECKED); + state = 1; + } + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { + lv_obj_clear_state(obj, LV_STATE_CHECKED); + state = 0; + } + res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &state); + if(res != LV_RES_OK) return res; + } +#endif } else if(sign == LV_SIGNAL_FOCUS) { bool editing = false; @@ -1908,6 +1838,59 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED); } + else if(sign == LV_SIGNAL_COORD_CHG) { + if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) || + (lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj))) + { + _lv_grid_full_refresh(obj); + } + } + else if(sign == LV_SIGNAL_CHILD_CHG) { + if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { + lv_obj_set_size(obj, obj->w_set, obj->h_set); + } + + if(obj->grid) { + lv_obj_t * child = param; + if(child) { + if(_lv_obj_is_grid_item(child)) _lv_grid_full_refresh(obj); + } else { + _lv_grid_full_refresh(obj); + } + } + } + else if(sign == LV_SIGNAL_SCROLL) { + res = lv_event_send(obj, LV_EVENT_SCROLLED, NULL); + if(res != LV_RES_OK) return res; + } + else if(sign == LV_SIGNAL_SCROLL_END) { + if(lv_obj_get_scroll_mode(obj) == LV_SCROLL_MODE_ACTIVE) { + lv_obj_invalidate(obj); + } + } + else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { + lv_coord_t d = _lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); + obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); + } + else if(sign == LV_SIGNAL_STYLE_CHG) { + if(_lv_obj_is_grid_item(obj)) _lv_grid_full_refresh(obj); + + if(obj->grid) _lv_grid_full_refresh(obj); + + /*Reposition non grid objects on by one*/ + lv_obj_t * child = lv_obj_get_child(obj, NULL); + while(child) { + if(!_GRID_IS_CELL(child->x_set) || !_GRID_IS_CELL(child->y_set)) { + lv_obj_set_pos(child, child->x_set, child->y_set); + } + child = lv_obj_get_child(obj, child); + } + + if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) { + lv_obj_set_size(obj, obj->w_set, obj->h_set); + } + _lv_obj_refresh_ext_draw_pad(obj); + } else if(sign == LV_SIGNAL_CLEANUP) { _lv_obj_reset_style_list_no_refr(obj, LV_OBJ_PART_MAIN); } diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index fb655aaa1..3f5477379 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -130,7 +130,6 @@ enum { LV_SIGNAL_REFR_EXT_DRAW_PAD, /**< Object's extra padding has changed */ LV_SIGNAL_GET_TYPE, /**< LVGL needs to retrieve the object's type */ LV_SIGNAL_GET_STYLE, /**coords.y2 + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); + return y2 - (obj->coords.y2 - lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN)); } /** @@ -229,7 +229,7 @@ lv_coord_t lv_obj_get_scroll_right(const lv_obj_t * obj) child = lv_obj_get_child(obj, child); } - return x2 - obj->coords.x2 + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN); + return x2 - (obj->coords.x2 - lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN)); } /********************** diff --git a/src/lv_core/lv_obj_style.c b/src/lv_core/lv_obj_style.c index ae50d2545..bc4d69bff 100644 --- a/src/lv_core/lv_obj_style.c +++ b/src/lv_core/lv_obj_style.c @@ -1058,7 +1058,7 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta static void report_style_change_core(void * style, lv_obj_t * obj) { uint8_t part; - for(part = 0; part != _LV_OBJ_PART_REAL_LAST; part++) { + for(part = 0; part < _LV_OBJ_PART_SPACIAL_START; part++) { lv_style_list_t * list = _lv_obj_get_style_list(obj, part); if(list == NULL) break; @@ -1288,6 +1288,7 @@ static _lv_style_state_cmp_t style_snapshot_compare(style_snapshot_t * shot1, st if(shot1->transform_zoom != shot2->transform_zoom) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->rect.outline_width != shot2->rect.outline_width) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->rect.outline_pad != shot2->rect.outline_pad) return _LV_STYLE_STATE_CMP_DIFF; + if(shot1->rect.outline_opa != shot2->rect.outline_opa) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->rect.value_font != shot2->rect.value_font) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->rect.value_align != shot2->rect.value_align) return _LV_STYLE_STATE_CMP_DIFF; if(shot1->rect.value_font != shot2->rect.value_font) return _LV_STYLE_STATE_CMP_DIFF; @@ -1358,10 +1359,6 @@ static bool style_prop_is_cacheable(lv_style_property_t prop) */ static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop) { - static uint32_t cnt = 0; - cnt++; - printf("update cache: %d\n", cnt); - if(style_prop_is_cacheable(prop) == false) return; lv_style_list_t * list = _lv_obj_get_style_list(obj, part); @@ -1458,7 +1455,7 @@ static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop) static void update_style_cache_children(lv_obj_t * obj) { uint8_t part; - for(part = 0; part != _LV_OBJ_PART_REAL_LAST; part++) { + for(part = 0; part < _LV_OBJ_PART_SPACIAL_START; part++) { lv_style_list_t * list = _lv_obj_get_style_list(obj, part); if(list == NULL) break; diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index 3e7a33c67..fac9f1a0b 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -153,9 +153,9 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) #endif disp->prev_scr = NULL; - 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*/ + disp->act_scr = lv_obj_create(NULL); /*Create a default screen on the display*/ + disp->top_layer = lv_obj_create(NULL); /*Create top layer on the display*/ + disp->sys_layer = lv_obj_create(NULL); /*Create sys layer on the display*/ lv_obj_reset_style_list(disp->top_layer, LV_OBJ_PART_MAIN); lv_obj_reset_style_list(disp->sys_layer, LV_OBJ_PART_MAIN); lv_obj_clear_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE); diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index 5116e85e8..09e4ba037 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -985,12 +985,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); _lv_style_list_add_style(list, &styles->bg); break; -#if LV_USE_CONT - case LV_THEME_CONT: - list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN); - _lv_style_list_add_style(list, &styles->bg); - break; -#endif #if LV_USE_BTN case LV_THEME_BTN: diff --git a/src/lv_themes/lv_theme_mono.c b/src/lv_themes/lv_theme_mono.c index 8a251cc12..42e5b0ed5 100644 --- a/src/lv_themes/lv_theme_mono.c +++ b/src/lv_themes/lv_theme_mono.c @@ -584,14 +584,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); _lv_style_list_add_style(list, &styles->bg); break; -#if LV_USE_CONT - case LV_THEME_CONT: - list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN); - _lv_style_list_add_style(list, &styles->bg); - break; -#endif -#if LV_USE_BTN + #if LV_USE_BTN case LV_THEME_BTN: list = _lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); _lv_style_list_add_style(list, &styles->bg); diff --git a/src/lv_themes/lv_theme_template.c b/src/lv_themes/lv_theme_template.c index 6777d2846..63bccb2c5 100644 --- a/src/lv_themes/lv_theme_template.c +++ b/src/lv_themes/lv_theme_template.c @@ -428,12 +428,6 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); _lv_style_list_add_style(list, &styles->bg); break; -#if LV_USE_CONT - case LV_THEME_CONT: - list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN); - _lv_style_list_add_style(list, &styles->bg); - break; -#endif #if LV_USE_BTN case LV_THEME_BTN: diff --git a/src/lv_widgets/lv_btn.c b/src/lv_widgets/lv_btn.c index 87a467c66..1003d84b1 100644 --- a/src/lv_widgets/lv_btn.c +++ b/src/lv_widgets/lv_btn.c @@ -23,8 +23,6 @@ * DEFINES *********************/ #define LV_OBJX_NAME "lv_btn" -#define LV_BTN_INK_VALUE_MAX 256 -#define LV_BTN_INK_VALUE_MAX_SHIFT 8 /********************** * TYPEDEFS @@ -33,14 +31,12 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_design_res_t lv_btn_design(lv_obj_t * btn, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param); /********************** * STATIC VARIABLES **********************/ static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; /********************** * MACROS @@ -52,56 +48,30 @@ static lv_design_cb_t ancestor_design; /** * Create a button object - * @param par pointer to an object, it will be the parent of the new button - * @param copy pointer to a button object, if not NULL then the new object will be copied from it + * @param parent pointer to an object, it will be the parent of the new button * @return pointer to the created button */ -lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy) +lv_obj_t * lv_btn_create(lv_obj_t * parent) { LV_LOG_TRACE("button create started"); lv_obj_t * btn; - btn = lv_cont_create(par, copy); + btn = lv_obj_create(parent); LV_ASSERT_MEM(btn); if(btn == NULL) return NULL; if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(btn); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(btn); - - /*Allocate the extended data*/ - lv_btn_ext_t * ext = lv_obj_allocate_ext_attr(btn, sizeof(lv_btn_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(btn); - return NULL; - } - - ext->checkable = 0; lv_obj_set_signal_cb(btn, lv_btn_signal); - lv_obj_set_design_cb(btn, lv_btn_design); - /*If no copy do the basic initialization*/ - if(copy == NULL) { - /*Set layout if the button is not a screen*/ - if(par) { - lv_obj_set_size(btn, LV_DPI, LV_DPI / 3); - lv_btn_set_layout(btn, LV_LAYOUT_CENTER); - } - - lv_obj_set_click(btn, true); /*Be sure the button is clickable*/ - - lv_theme_apply(btn, LV_THEME_BTN); + /*Set layout if the button is not a screen*/ + if(parent) { + lv_obj_set_size(btn, LV_DPI, LV_DPI / 3); + lv_obj_set_grid(btn, &lv_grid_center); } - /*Copy 'copy'*/ - else { - lv_btn_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->checkable = copy_ext->checkable; - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(btn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } + lv_theme_apply(btn, LV_THEME_BTN); LV_LOG_INFO("button created"); @@ -112,146 +82,14 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy) * Setter functions *====================*/ -/** - * Enable the toggled states - * @param btn pointer to a button object - * @param tgl true: enable toggled states, false: disable - */ -void lv_btn_set_checkable(lv_obj_t * btn, bool tgl) -{ - LV_ASSERT_OBJ(btn, LV_OBJX_NAME); - - lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn); - - ext->checkable = tgl != false ? 1 : 0; -} - -/** - * Set the state of the button - * @param btn pointer to a button object - * @param state the new state of the button (from lv_btn_state_t enum) - */ -void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state) -{ - LV_ASSERT_OBJ(btn, LV_OBJX_NAME); - - switch(state) { - case LV_BTN_STATE_RELEASED: - lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED | LV_STATE_DISABLED); - break; - case LV_BTN_STATE_PRESSED: - lv_obj_clear_state(btn, LV_STATE_CHECKED | LV_STATE_DISABLED); - lv_obj_add_state(btn, LV_STATE_PRESSED); - break; - case LV_BTN_STATE_CHECKED_RELEASED: - lv_obj_add_state(btn, LV_STATE_CHECKED); - lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_DISABLED); - break; - case LV_BTN_STATE_CHECKED_PRESSED: - lv_obj_add_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED); - lv_obj_clear_state(btn, LV_STATE_DISABLED); - break; - case LV_BTN_STATE_DISABLED: - lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED); - lv_obj_add_state(btn, LV_STATE_DISABLED); - break; - case LV_BTN_STATE_CHECKED_DISABLED: - lv_obj_clear_state(btn, LV_STATE_PRESSED); - lv_obj_add_state(btn, LV_STATE_DISABLED | LV_STATE_CHECKED); - break; - } -} - -/** - * Toggle the state of the button (ON->OFF, OFF->ON) - * @param btn pointer to a button object - */ -void lv_btn_toggle(lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, LV_OBJX_NAME); - - if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) { - lv_obj_clear_state(btn, LV_STATE_CHECKED); - } - else { - lv_obj_add_state(btn, LV_STATE_CHECKED); - } -} - /*===================== * Getter functions *====================*/ -/** - * Get the current state of the button - * @param btn pointer to a button object - * @return the state of the button (from lv_btn_state_t enum). - * If the button is in disabled state `LV_BTN_STATE_DISABLED` will be ORed to the other button states. - */ -lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, LV_OBJX_NAME); - - lv_state_t obj_state = lv_obj_get_state(btn, LV_BTN_PART_MAIN); - - if(obj_state & LV_STATE_DISABLED) { - if(obj_state & LV_STATE_CHECKED) return LV_BTN_STATE_CHECKED_DISABLED; - else return LV_BTN_STATE_DISABLED; - } - - if(obj_state & LV_STATE_CHECKED) { - if(obj_state & LV_STATE_PRESSED) return LV_BTN_STATE_CHECKED_PRESSED; - else return LV_BTN_STATE_CHECKED_RELEASED; - } - else { - if(obj_state & LV_STATE_PRESSED) return LV_BTN_STATE_PRESSED; - else return LV_BTN_STATE_RELEASED; - } -} - -/** - * Get the toggle enable attribute of the button - * @param btn pointer to a button object - * @return true: toggle enabled, false: disabled - */ -bool lv_btn_get_checkable(const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, LV_OBJX_NAME); - - lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn); - - return ext->checkable != 0 ? true : false; -} - /********************** * STATIC FUNCTIONS **********************/ -/** - * Handle the drawing related tasks of the drop down lists - * @param btn pointer to an object - * @param mask the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_btn_design(lv_obj_t * btn, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - if(mode == LV_DESIGN_COVER_CHK) { - return ancestor_design(btn, clip_area, mode); - } - else if(mode == LV_DESIGN_DRAW_MAIN) { - ancestor_design(btn, clip_area, mode); - } - else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_design(btn, clip_area, mode); - } - - return LV_DESIGN_RES_OK; -} - /** * Signal function of the button * @param btn pointer to a button object @@ -266,51 +104,9 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param) /* Include the ancient signal function */ res = ancestor_signal(btn, sign, param); if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - bool tgl = lv_btn_get_checkable(btn); - - if(sign == LV_SIGNAL_RELEASED) { - /*If not dragged and it was not long press action then - *change state and run the action*/ - if(lv_indev_get_scroll_dir(param) == LV_SCROLL_DIR_NONE && tgl) { - uint32_t toggled = 0; - if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) { - lv_btn_set_state(btn, LV_BTN_STATE_RELEASED); - toggled = 0; - } - else { - lv_btn_set_state(btn, LV_BTN_STATE_CHECKED_RELEASED); - toggled = 1; - } - - res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &toggled); - if(res != LV_RES_OK) return res; - } - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - char c = *((char *)param); - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - if(lv_btn_get_checkable(btn)) { - lv_btn_set_state(btn, LV_BTN_STATE_CHECKED_RELEASED); - - uint32_t state = 1; - res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; - } - - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - if(lv_btn_get_checkable(btn)) { - lv_btn_set_state(btn, LV_BTN_STATE_RELEASED); - - uint32_t state = 0; - res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; - } - } -#endif + if(sign == LV_SIGNAL_GET_TYPE) { + return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); } return res; diff --git a/src/lv_widgets/lv_btn.h b/src/lv_widgets/lv_btn.h index 34f72f636..721d2b5a1 100644 --- a/src/lv_widgets/lv_btn.h +++ b/src/lv_widgets/lv_btn.h @@ -17,12 +17,6 @@ extern "C" { #if LV_USE_BTN != 0 -/*Testing of dependencies*/ -#if LV_USE_CONT == 0 -#error "lv_btn: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) " -#endif - -#include "lv_cont.h" #include "../lv_core/lv_indev.h" /********************* @@ -33,33 +27,9 @@ extern "C" { * TYPEDEFS **********************/ -/** Possible states of a button. - * It can be used not only by buttons but other button-like objects too*/ -enum { - LV_BTN_STATE_RELEASED, - LV_BTN_STATE_PRESSED, - LV_BTN_STATE_DISABLED, - LV_BTN_STATE_CHECKED_RELEASED, - LV_BTN_STATE_CHECKED_PRESSED, - LV_BTN_STATE_CHECKED_DISABLED, - _LV_BTN_STATE_LAST, /* Number of states*/ -}; -typedef uint8_t lv_btn_state_t; - -/** Extended data of button*/ -typedef struct { - /** Ext. of ancestor*/ - lv_cont_ext_t cont; - - /** 1: Toggle enabled*/ - uint8_t checkable : 1; -} lv_btn_ext_t; - /**Styles*/ enum { LV_BTN_PART_MAIN = LV_OBJ_PART_MAIN, - _LV_BTN_PART_VIRTUAL_LAST, - _LV_BTN_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST, }; typedef uint8_t lv_btn_part_t; @@ -69,152 +39,19 @@ typedef uint8_t lv_btn_part_t; /** * Create a button object - * @param par pointer to an object, it will be the parent of the new button - * @param copy pointer to a button object, if not NULL then the new object will be copied from it + * @param parent pointer to an object, it will be the parent of the new button * @return pointer to the created button */ -lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy); +lv_obj_t * lv_btn_create(lv_obj_t * parent); /*===================== * Setter functions *====================*/ -/** - * Enable the toggled states. On release the button will change from/to toggled state. - * @param btn pointer to a button object - * @param tgl true: enable toggled states, false: disable - */ -void lv_btn_set_checkable(lv_obj_t * btn, bool tgl); - -/** - * Set the state of the button - * @param btn pointer to a button object - * @param state the new state of the button (from lv_btn_state_t enum) - */ -void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state); - -/** - * Toggle the state of the button (ON->OFF, OFF->ON) - * @param btn pointer to a button object - */ -void lv_btn_toggle(lv_obj_t * btn); - -/** - * Set the layout on a button - * @param btn pointer to a button object - * @param layout a layout from 'lv_cont_layout_t' - */ -static inline void lv_btn_set_layout(lv_obj_t * btn, lv_layout_t layout) -{ - lv_cont_set_layout(btn, layout); -} - -/** - * Set the fit policy in all 4 directions separately. - * It tells how to change the button size automatically. - * @param btn pointer to a button object - * @param left left fit policy from `lv_fit_t` - * @param right right fit policy from `lv_fit_t` - * @param top top fit policy from `lv_fit_t` - * @param bottom bottom fit policy from `lv_fit_t` - */ -static inline void lv_btn_set_fit4(lv_obj_t * btn, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom) -{ - lv_cont_set_fit4(btn, left, right, top, bottom); -} - -/** - * Set the fit policy horizontally and vertically separately. - * It tells how to change the button size automatically. - * @param btn pointer to a button object - * @param hor horizontal fit policy from `lv_fit_t` - * @param ver vertical fit policy from `lv_fit_t` - */ -static inline void lv_btn_set_fit2(lv_obj_t * btn, lv_fit_t hor, lv_fit_t ver) -{ - lv_cont_set_fit2(btn, hor, ver); -} - -/** - * Set the fit policy in all 4 direction at once. - * It tells how to change the button size automatically. - * @param btn pointer to a button object - * @param fit fit policy from `lv_fit_t` - */ -static inline void lv_btn_set_fit(lv_obj_t * btn, lv_fit_t fit) -{ - lv_cont_set_fit(btn, fit); -} - /*===================== * Getter functions *====================*/ -/** - * Get the current state of the button - * @param btn pointer to a button object - * @return the state of the button (from lv_btn_state_t enum) - * If the button is in disabled state `LV_BTN_STATE_DISABLED` will be ORed to the other button states. - */ -lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn); - -/** - * Get the toggle enable attribute of the button - * @param btn pointer to a button object - * @return true: checkable enabled, false: disabled - */ -bool lv_btn_get_checkable(const lv_obj_t * btn); - -/** - * Get the layout of a button - * @param btn pointer to button object - * @return the layout from 'lv_cont_layout_t' - */ -static inline lv_layout_t lv_btn_get_layout(const lv_obj_t * btn) -{ - return lv_cont_get_layout(btn); -} - -/** - * Get the left fit mode - * @param btn pointer to a button object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_btn_get_fit_left(const lv_obj_t * btn) -{ - return lv_cont_get_fit_left(btn); -} - -/** - * Get the right fit mode - * @param btn pointer to a button object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_btn_get_fit_right(const lv_obj_t * btn) -{ - return lv_cont_get_fit_right(btn); -} - -/** - * Get the top fit mode - * @param btn pointer to a button object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_btn_get_fit_top(const lv_obj_t * btn) -{ - return lv_cont_get_fit_top(btn); -} - -/** - * Get the bottom fit mode - * @param btn pointer to a button object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_btn_get_fit_bottom(const lv_obj_t * btn) -{ - return lv_cont_get_fit_bottom(btn); -} - /********************** * MACROS **********************/ diff --git a/src/lv_widgets/lv_calendar.c b/src/lv_widgets/lv_calendar.c deleted file mode 100644 index a95e08c2d..000000000 --- a/src/lv_widgets/lv_calendar.c +++ /dev/null @@ -1,1087 +0,0 @@ -/** - * @file lv_calendar.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_calendar.h" -#if LV_USE_CALENDAR != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_draw/lv_draw.h" -#include "../lv_hal/lv_hal_indev.h" -#include "../lv_misc/lv_utils.h" -#include "../lv_core/lv_indev.h" -#include "../lv_themes/lv_theme.h" -#include - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_calendar" - -/********************** - * TYPEDEFS - **********************/ -enum { - DAY_DRAW_PREV_MONTH, - DAY_DRAW_ACT_MONTH, - DAY_DRAW_NEXT_MONTH, -}; -typedef uint8_t day_draw_state_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_design_res_t lv_calendar_design(lv_obj_t * calendar, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void * param); -static lv_style_list_t * lv_calendar_get_style(lv_obj_t * calendar, uint8_t part); -static bool calculate_touched_day(lv_obj_t * calendar, const lv_point_t * touched_point); -static lv_coord_t get_header_height(lv_obj_t * calendar); -static lv_coord_t get_day_names_height(lv_obj_t * calendar); -static void draw_header(lv_obj_t * calendar, const lv_area_t * mask); -static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask); -static void draw_dates(lv_obj_t * calendar, const lv_area_t * clip_area); -static uint8_t get_day_of_week(uint32_t year, uint32_t month, uint32_t day); -static bool is_highlighted(lv_obj_t * calendar, day_draw_state_t draw_state, int32_t year, int32_t month, int32_t day); -static bool is_pressed(lv_obj_t * calendar, day_draw_state_t draw_state, int32_t year, int32_t month, int32_t day); -static const char * get_day_name(lv_obj_t * calendar, uint8_t day); -static const char * get_month_name(lv_obj_t * calendar, int32_t month); -static uint8_t get_month_length(int32_t year, int32_t month); -static uint8_t is_leap_year(uint32_t year); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; -#if LV_CALENDAR_WEEK_STARTS_MONDAY != 0 -static const char * day_name[7] = {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; -#else -static const char * day_name[7] = {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}; -#endif -static const char * month_name[12] = {"January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" - }; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a calendar object - * @param par pointer to an object, it will be the parent of the new calendar - * @param copy pointer to a calendar object, if not NULL then the new object will be copied from it - * @return pointer to the created calendar - */ -lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("calendar create started"); - - /*Create the ancestor of calendar*/ - lv_obj_t * calendar = lv_obj_create(par, copy); - LV_ASSERT_MEM(calendar); - if(calendar == NULL) return NULL; - - /*Allocate the calendar type specific extended data*/ - lv_calendar_ext_t * ext = lv_obj_allocate_ext_attr(calendar, sizeof(lv_calendar_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(calendar); - return NULL; - } - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(calendar); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(calendar); - - /*Initialize the allocated 'ext' */ - ext->today.year = 2020; - ext->today.month = 1; - ext->today.day = 1; - - ext->showed_date.year = 2020; - ext->showed_date.month = 1; - ext->showed_date.day = 1; - - ext->pressed_date.year = 0; - ext->pressed_date.month = 0; - ext->pressed_date.day = 0; - - ext->highlighted_dates = NULL; - ext->highlighted_dates_num = 0; - ext->day_names = NULL; - ext->month_names = NULL; - - ext->btn_pressing = 0; - - - lv_style_list_init(&ext->style_date_nums); - lv_style_list_init(&ext->style_day_names); - lv_style_list_init(&ext->style_header); - ext->style_date_nums.skip_trans = 1; - ext->style_day_names.skip_trans = 1; - ext->style_header.skip_trans = 1; - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(calendar, lv_calendar_signal); - lv_obj_set_design_cb(calendar, lv_calendar_design); - - /*Init the new calendar calendar*/ - if(copy == NULL) { - lv_theme_apply(calendar, LV_THEME_CALENDAR); - - lv_obj_set_size(calendar, 5 * LV_DPI / 2, 5 * LV_DPI / 2); - - } - /*Copy an existing calendar*/ - else { - lv_calendar_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->today.year = copy_ext->today.year; - ext->today.month = copy_ext->today.month; - ext->today.day = copy_ext->today.day; - - ext->showed_date.year = copy_ext->showed_date.year; - ext->showed_date.month = copy_ext->showed_date.month; - ext->showed_date.day = copy_ext->showed_date.day; - - ext->highlighted_dates = copy_ext->highlighted_dates; - ext->highlighted_dates_num = copy_ext->highlighted_dates_num; - ext->day_names = copy_ext->day_names; - - ext->month_names = copy_ext->month_names; - ext->style_header = copy_ext->style_header; - ext->style_day_names = copy_ext->style_day_names; - /*Refresh the style with new signal function*/ - // lv_obj_refresh_style(new_calendar); - } - - LV_LOG_INFO("calendar created"); - - return calendar; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/* - * New object specific "add" or "remove" functions come here - */ - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the today's date - * @param calendar pointer to a calendar object - * @param today pointer to an `lv_calendar_date_t` variable containing the date of today. The value - * will be saved it can be local variable too. - */ -void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - LV_ASSERT_NULL(today); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->today.year = today->year; - ext->today.month = today->month; - ext->today.day = today->day; - - lv_obj_invalidate(calendar); -} - -/** - * Set the currently showed - * @param calendar pointer to a calendar object - * @param showed pointer to an `lv_calendar_date_t` variable containing the date to show. The value - * will be saved it can be local variable too. - */ -void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showed) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - LV_ASSERT_NULL(showed); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->showed_date.year = showed->year; - ext->showed_date.month = showed->month; - ext->showed_date.day = showed->day; - - lv_obj_invalidate(calendar); -} - -/** - * Set the the highlighted dates - * @param calendar pointer to a calendar object - * @param highlighted pointer to an `lv_calendar_date_t` array containing the dates. ONLY A POINTER - * WILL BE SAVED! CAN'T BE LOCAL ARRAY. - * @param date_num number of dates in the array - */ -void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t highlighted[], uint16_t date_num) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - LV_ASSERT_NULL(highlighted); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->highlighted_dates = highlighted; - ext->highlighted_dates_num = date_num; - - lv_obj_invalidate(calendar); -} - -/** - * Set the name of the days - * @param calendar pointer to a calendar object - * @param day_names pointer to an array with the names. E.g. `const char * days[7] = {"Sun", "Mon", - * ...}` Only the pointer will be saved so this variable can't be local which will be destroyed - * later. - */ -void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - LV_ASSERT_NULL(day_names); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->day_names = day_names; - lv_obj_invalidate(calendar); -} - -/** - * Set the name of the month - * @param calendar pointer to a calendar object - * @param month_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb", - * ...}` Only the pointer will be saved so this variable can't be local which will be destroyed - * later. - */ -void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** month_names) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - LV_ASSERT_NULL(month_names); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->month_names = month_names; - lv_obj_invalidate(calendar); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the today's date - * @param calendar pointer to a calendar object - * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. - */ -lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return &ext->today; -} - -/** - * Get the currently showed - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. - */ -lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return &ext->showed_date; -} - -/** - * Get the the pressed date. - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the pressed date. - * `NULL` if not date pressed (e.g. the header) - */ -lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return ext->pressed_date.year != 0 ? &ext->pressed_date : NULL; -} - -/** - * Get the the highlighted dates - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` array containing the dates. - */ -lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return ext->highlighted_dates; -} - -/** - * Get the number of the highlighted dates - * @param calendar pointer to a calendar object - * @return number of highlighted days - */ -uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return ext->highlighted_dates_num; -} - -/** - * Get the name of the days - * @param calendar pointer to a calendar object - * @return pointer to the array of day names - */ -const char ** lv_calendar_get_day_names(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return ext->day_names; -} - -/** - * Get the name of the month - * @param calendar pointer to a calendar object - * @return pointer to the array of month names - */ -const char ** lv_calendar_get_month_names(const lv_obj_t * calendar) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - return ext->month_names; -} - -/*===================== - * Other functions - *====================*/ - -/* - * New object specific "other" functions come here - */ - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Handle the drawing related tasks of the calendars - * @param calendar pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_calendar_design(lv_obj_t * calendar, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return ancestor_design(calendar, clip_area, mode); - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - ancestor_design(calendar, clip_area, mode); - - draw_header(calendar, clip_area); - draw_day_names(calendar, clip_area); - draw_dates(calendar, clip_area); - - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_design(calendar, clip_area, mode); - } - - return LV_DESIGN_RES_OK; -} - -/** - * Signal function of the calendar - * @param calendar pointer to a calendar object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void * param) -{ - lv_res_t res; - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_calendar_get_style(calendar, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(calendar, sign, param); - return LV_RES_OK; - } - - /* Include the ancient signal function */ - res = ancestor_signal(calendar, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_CLEANUP) { - lv_obj_clean_style_list(calendar, LV_CALENDAR_PART_HEADER); - lv_obj_clean_style_list(calendar, LV_CALENDAR_PART_DAY_NAMES); - lv_obj_clean_style_list(calendar, LV_CALENDAR_PART_DATE); - } - else if(sign == LV_SIGNAL_PRESSING) { - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - lv_area_t header_area; - lv_area_copy(&header_area, &calendar->coords); - header_area.y2 = header_area.y1 + get_header_height(calendar); - - lv_indev_t * indev = lv_indev_get_act(); - lv_point_t p; - lv_indev_get_point(indev, &p); - - /*If the header is pressed mark an arrow as pressed*/ - if(_lv_area_is_point_on(&header_area, &p, 0)) { - if(p.x < header_area.x1 + lv_area_get_width(&header_area) / 2) { - if(ext->btn_pressing != -1) lv_obj_invalidate(calendar); - ext->btn_pressing = -1; - } - else { - if(ext->btn_pressing != 1) lv_obj_invalidate(calendar); - ext->btn_pressing = 1; - } - - ext->pressed_date.year = 0; - ext->pressed_date.month = 0; - ext->pressed_date.day = 0; - } - /*If a day is pressed save it*/ - else if(calculate_touched_day(calendar, &p)) { - ext->btn_pressing = 0; - lv_obj_invalidate(calendar); - } - /*Else set a default state*/ - else { - if(ext->btn_pressing != 0) lv_obj_invalidate(calendar); - ext->btn_pressing = 0; - ext->pressed_date.year = 0; - ext->pressed_date.month = 0; - ext->pressed_date.day = 0; - } - } - else if(sign == LV_SIGNAL_PRESS_LOST) { - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - ext->btn_pressing = 0; - ext->pressed_date.year = 0; - ext->pressed_date.month = 0; - ext->pressed_date.day = 0; - lv_obj_invalidate(calendar); - - } - else if(sign == LV_SIGNAL_RELEASED) { - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - if(ext->btn_pressing < 0) { - if(ext->showed_date.month <= 1) { - ext->showed_date.month = 12; - ext->showed_date.year--; - } - else { - ext->showed_date.month--; - } - } - else if(ext->btn_pressing > 0) { - if(ext->showed_date.month >= 12) { - ext->showed_date.month = 1; - ext->showed_date.year++; - } - else { - ext->showed_date.month++; - } - } - else if(ext->pressed_date.year != 0) { - res = lv_event_send(calendar, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - - } - - ext->btn_pressing = 0; - ext->pressed_date.year = 0; - ext->pressed_date.month = 0; - ext->pressed_date.day = 0; - lv_obj_invalidate(calendar); - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - uint8_t c = *((uint8_t *)param); - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - if(ext->showed_date.month >= 12) { - ext->showed_date.month = 1; - ext->showed_date.year++; - } - else { - ext->showed_date.month++; - } - lv_obj_invalidate(calendar); - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - if(ext->showed_date.month <= 1) { - ext->showed_date.month = 12; - ext->showed_date.year--; - } - else { - ext->showed_date.month--; - } - lv_obj_invalidate(calendar); - } -#endif - } - - return res; -} - -/** - * Get the style descriptor of a part of the object - * @param page pointer the object - * @param part the part from `lv_calendar_part_t`. (LV_CALENDAR_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_calendar_get_style(lv_obj_t * calendar, uint8_t part) -{ - LV_ASSERT_OBJ(calendar, LV_OBJX_NAME); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - lv_style_list_t * style_dsc_p; - - - switch(part) { - case LV_CALENDAR_PART_BG: - style_dsc_p = &calendar->style_list; - break; - case LV_CALENDAR_PART_HEADER: - style_dsc_p = &ext->style_header; - break; - case LV_CALENDAR_PART_DAY_NAMES: - style_dsc_p = &ext->style_day_names; - break; - case LV_CALENDAR_PART_DATE: - style_dsc_p = &ext->style_date_nums; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -/** - * It will check if the days part of calendar is touched - * and if it is, it will calculate the day and put it in pressed_date of calendar object. - * @param calendar pointer to a calendar object - * @param pointer to a point - * @return true: days part of calendar is touched and its related date is put in pressed date - * false: the point is out of days part area. - */ -static bool calculate_touched_day(lv_obj_t * calendar, const lv_point_t * touched_point) -{ - lv_area_t days_area; - lv_area_copy(&days_area, &calendar->coords); - lv_style_int_t left = lv_obj_get_style_pad_left(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t right = lv_obj_get_style_pad_right(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(calendar, LV_CALENDAR_PART_DATE); - - days_area.x1 += left; - days_area.x2 -= right; - days_area.y1 = calendar->coords.y1 + get_header_height(calendar) + get_day_names_height(calendar) + top; - days_area.y2 -= bottom; - - if(_lv_area_is_point_on(&days_area, touched_point, 0)) { - lv_coord_t w = (days_area.x2 - days_area.x1 + 1) / 7; - lv_coord_t h = (days_area.y2 - days_area.y1 + 1) / 6; - uint8_t x_pos = 0; - x_pos = (touched_point->x - days_area.x1) / w; - if(x_pos > 6) x_pos = 6; - uint8_t y_pos = 0; - y_pos = (touched_point->y - days_area.y1) / h; - if(y_pos > 5) y_pos = 5; - - uint8_t i_pos = 0; - i_pos = (y_pos * 7) + x_pos; - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - if(i_pos < get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1)) { - ext->pressed_date.year = ext->showed_date.year - (ext->showed_date.month == 1 ? 1 : 0); - ext->pressed_date.month = ext->showed_date.month == 1 ? 12 : (ext->showed_date.month - 1); - ext->pressed_date.day = get_month_length(ext->pressed_date.year, ext->pressed_date.month) - - get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1) + 1 + i_pos; - } - else if(i_pos < (get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1) + - get_month_length(ext->showed_date.year, ext->showed_date.month))) { - ext->pressed_date.year = ext->showed_date.year; - ext->pressed_date.month = ext->showed_date.month; - ext->pressed_date.day = i_pos + 1 - get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1); - } - else if(i_pos < 42) { - ext->pressed_date.year = ext->showed_date.year + (ext->showed_date.month == 12 ? 1 : 0); - ext->pressed_date.month = ext->showed_date.month == 12 ? 1 : (ext->showed_date.month + 1); - ext->pressed_date.day = i_pos + 1 - get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1) - - get_month_length(ext->showed_date.year, ext->showed_date.month); - } - return true; - } - else { - return false; - } -} - -/** - * Get the height of a calendar's header based on it's style - * @param calendar point to a calendar - * @return the header's height - */ -static lv_coord_t get_header_height(lv_obj_t * calendar) -{ - const lv_font_t * font = lv_obj_get_style_text_font(calendar, LV_CALENDAR_PART_HEADER); - lv_style_int_t top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_HEADER); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(calendar, LV_CALENDAR_PART_HEADER); - - return lv_font_get_line_height(font) + top + bottom; -} - -/** - * Get the height of a calendar's day_names based on it's style - * @param calendar point to a calendar - * @return the day_names's height - */ -static lv_coord_t get_day_names_height(lv_obj_t * calendar) -{ - const lv_font_t * font = lv_obj_get_style_text_font(calendar, LV_CALENDAR_PART_DAY_NAMES); - lv_style_int_t top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_DAY_NAMES); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(calendar, LV_CALENDAR_PART_DAY_NAMES); - - return lv_font_get_line_height(font) + top + bottom; -} - -/** - * Draw the calendar header with month name and arrows - * @param calendar point to a calendar - * @param mask a mask for drawing - */ -static void draw_header(lv_obj_t * calendar, const lv_area_t * mask) -{ - lv_style_int_t header_top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_HEADER); - lv_style_int_t header_left = lv_obj_get_style_pad_left(calendar, LV_CALENDAR_PART_HEADER); - lv_style_int_t header_right = lv_obj_get_style_pad_right(calendar, LV_CALENDAR_PART_HEADER); - const lv_font_t * font = lv_obj_get_style_text_font(calendar, LV_CALENDAR_PART_HEADER); - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - - lv_area_t header_area; - header_area.x1 = calendar->coords.x1; - header_area.x2 = calendar->coords.x2; - header_area.y1 = calendar->coords.y1 + header_top; - header_area.y2 = header_area.y1 + lv_font_get_line_height(font); - - lv_draw_rect_dsc_t header_rect_dsc; - lv_draw_rect_dsc_init(&header_rect_dsc); - lv_obj_init_draw_rect_dsc(calendar, LV_CALENDAR_PART_HEADER, &header_rect_dsc); - lv_draw_rect(&header_area, mask, &header_rect_dsc); - - lv_state_t state_ori = calendar->state; - - /*Add the year + month name*/ - char txt_buf[64]; - _lv_utils_num_to_str(ext->showed_date.year, txt_buf); - txt_buf[4] = ' '; - txt_buf[5] = '\0'; - strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month)); - - calendar->state = LV_STATE_DEFAULT; - _lv_obj_disable_style_caching(calendar, true); - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(calendar, LV_CALENDAR_PART_HEADER, &label_dsc); - label_dsc.flag = LV_TXT_FLAG_CENTER; - lv_draw_label(&header_area, mask, &label_dsc, txt_buf, NULL); - - calendar->state = state_ori; /*Restore the state*/ - - /*Add the left arrow*/ - if(ext->btn_pressing < 0) calendar->state |= LV_STATE_PRESSED; - else calendar->state &= ~(LV_STATE_PRESSED); - - header_area.x1 += header_left; - - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(calendar, LV_CALENDAR_PART_HEADER, &label_dsc); - lv_draw_label(&header_area, mask, &label_dsc, LV_SYMBOL_LEFT, NULL); - - calendar->state = state_ori; /*Restore the state*/ - - /*Add the right arrow*/ - if(ext->btn_pressing > 0) calendar->state |= LV_STATE_PRESSED; - else calendar->state &= ~(LV_STATE_PRESSED); - - header_area.x1 = header_area.x2 - header_right - _lv_txt_get_width(LV_SYMBOL_RIGHT, (uint16_t)strlen(LV_SYMBOL_RIGHT), - font, 0, LV_TXT_FLAG_NONE); - - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(calendar, LV_CALENDAR_PART_HEADER, &label_dsc); - lv_draw_label(&header_area, mask, &label_dsc, LV_SYMBOL_RIGHT, NULL); - - calendar->state = state_ori; /*Restore the state*/ - _lv_obj_disable_style_caching(calendar, false); -} - -/** - * Draw the day's name below the header - * @param calendar point to a calendar - * @param mask a mask for drawing - */ -static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask) -{ - lv_style_int_t date_top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_bottom = lv_obj_get_style_pad_bottom(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_left = lv_obj_get_style_pad_left(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_right = lv_obj_get_style_pad_right(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_inner = lv_obj_get_style_pad_inner(calendar, LV_CALENDAR_PART_DATE); - - lv_coord_t days_w = lv_obj_get_width(calendar) - date_left - date_right; - lv_coord_t box_w = (days_w - date_inner * 6) / 7; - lv_coord_t days_y1 = calendar->coords.y1 + date_top + get_header_height(calendar) + get_day_names_height(calendar); - lv_coord_t days_h = calendar->coords.y2 - days_y1 - date_bottom; - lv_coord_t box_h = (days_h - 5 * date_inner) / 6; - lv_coord_t box_size = LV_MATH_MIN(box_w, box_h); - - lv_style_int_t left = lv_obj_get_style_pad_left(calendar, LV_CALENDAR_PART_DAY_NAMES); - lv_style_int_t right = lv_obj_get_style_pad_right(calendar, LV_CALENDAR_PART_DAY_NAMES); - lv_style_int_t top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_DAY_NAMES); - const lv_font_t * font = lv_obj_get_style_text_font(calendar, LV_CALENDAR_PART_DAY_NAMES); - - lv_coord_t w = lv_obj_get_width(calendar) - left - right; - - lv_coord_t label_w = w / 6; - - lv_area_t label_area; - label_area.y1 = calendar->coords.y1 + get_header_height(calendar) + top; - label_area.y2 = label_area.y1 + lv_font_get_line_height(font); - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(calendar, LV_CALENDAR_PART_DAY_NAMES, &label_dsc); - label_dsc.flag = LV_TXT_FLAG_CENTER; - - uint32_t i; - for(i = 0; i < 7; i++) { - label_area.x1 = calendar->coords.x1 + ((w - box_size) * i) / 6 + box_size / 2 - label_w / 2 + left; - label_area.x2 = label_area.x1 + label_w - 1; - - lv_draw_label(&label_area, mask, &label_dsc, get_day_name(calendar, i), NULL); - } -} - -/** - * Draw the date numbers in a matrix - * @param calendar point to a calendar - * @param mask a mask for drawing - */ -static void draw_dates(lv_obj_t * calendar, const lv_area_t * clip_area) -{ - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - - const lv_font_t * nums_font = lv_obj_get_style_text_font(calendar, LV_CALENDAR_PART_DATE); - - lv_style_int_t date_top = lv_obj_get_style_pad_top(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_bottom = lv_obj_get_style_pad_bottom(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_left = lv_obj_get_style_pad_left(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_right = lv_obj_get_style_pad_right(calendar, LV_CALENDAR_PART_DATE); - lv_style_int_t date_inner = lv_obj_get_style_pad_inner(calendar, LV_CALENDAR_PART_DATE); - - lv_coord_t days_y1 = calendar->coords.y1 + date_top + get_header_height(calendar) + get_day_names_height(calendar); - lv_coord_t days_h = calendar->coords.y2 - days_y1 - date_bottom; - - /*The state changes without re-caching the styles, disable the use of cache*/ - lv_state_t state_ori = calendar->state; - calendar->state = LV_STATE_DEFAULT; - _lv_obj_disable_style_caching(calendar, true); - - lv_state_t month_state = LV_STATE_DISABLED; - - uint8_t day_cnt; - lv_coord_t days_w = lv_obj_get_width(calendar) - date_left - date_right; - lv_coord_t box_w = (days_w - date_inner * 6) / 7; - lv_coord_t box_h = (days_h - 5 * date_inner) / 6; - lv_coord_t box_size = LV_MATH_MIN(box_w, box_h); - - uint8_t month_start_day = get_day_of_week(ext->showed_date.year, ext->showed_date.month, 1); - - day_draw_state_t draw_state; - - /*If starting with the first day of the week then the previous month is not visible*/ - if(month_start_day == 0) { - day_cnt = 1; - draw_state = DAY_DRAW_ACT_MONTH; - month_state = 0; - } - else { - draw_state = DAY_DRAW_PREV_MONTH; - day_cnt = get_month_length(ext->showed_date.year, ext->showed_date.month - 1); /*Length of the previous month*/ - day_cnt -= month_start_day - 1; /*First visible number of the previous month*/ - month_state = LV_STATE_DISABLED; - } - - bool month_of_today_shown = false; - if(ext->showed_date.year == ext->today.year && ext->showed_date.month == ext->today.month) { - month_of_today_shown = true; - } - - char buf[3]; - - /*Draw 6 weeks*/ - lv_draw_rect_dsc_t rect_dsc; - lv_draw_label_dsc_t label_dsc; - lv_state_t prev_state = 0xFF; - uint32_t week; - for(week = 0; week < 6; week++) { - lv_area_t box_area; - - box_area.y1 = days_y1 + ((days_h - box_size) * week) / 5; - box_area.y2 = box_area.y1 + box_size - 1; - - if(box_area.y1 > clip_area->y2) { - calendar->state = state_ori; - _lv_obj_disable_style_caching(calendar, false); - return; - } - - lv_area_t label_area; - label_area.y1 = box_area.y1 + (lv_area_get_height(&box_area) - lv_font_get_line_height(nums_font)) / 2; - label_area.y2 = label_area.y1 + lv_font_get_line_height(nums_font); - - /*Draw the 7 days of a week*/ - uint32_t day; - for(day = 0; day < 7; day++) { - /*The previous month is over*/ - if(draw_state == DAY_DRAW_PREV_MONTH && day == month_start_day) { - draw_state = DAY_DRAW_ACT_MONTH; - day_cnt = 1; - month_state = 0; - } - /*The current month is over*/ - else if(draw_state == DAY_DRAW_ACT_MONTH && - day_cnt > get_month_length(ext->showed_date.year, ext->showed_date.month)) { - draw_state = DAY_DRAW_NEXT_MONTH; - day_cnt = 1; - month_state = LV_STATE_DISABLED; - } - - if(box_area.y2 < clip_area->y1) { - day_cnt++; - continue; - } - - lv_state_t day_state = month_state; - if(is_pressed(calendar, draw_state, ext->showed_date.year, ext->showed_date.month, day_cnt)) { - day_state |= LV_STATE_PRESSED; - } - if(is_highlighted(calendar, draw_state, ext->showed_date.year, ext->showed_date.month, day_cnt)) { - day_state |= LV_STATE_CHECKED; - } - if(month_of_today_shown && day_cnt == ext->today.day && draw_state == DAY_DRAW_ACT_MONTH) { - day_state |= LV_STATE_FOCUSED; - } - - if(prev_state != day_state) { - lv_draw_rect_dsc_init(&rect_dsc); - lv_draw_label_dsc_init(&label_dsc); - label_dsc.flag = LV_TXT_FLAG_CENTER; - - calendar->state = day_state; - lv_obj_init_draw_label_dsc(calendar, LV_CALENDAR_PART_DATE, &label_dsc); - lv_obj_init_draw_rect_dsc(calendar, LV_CALENDAR_PART_DATE, &rect_dsc); - - prev_state = day_state; - } - - label_area.x1 = calendar->coords.x1 + ((days_w - box_size) * day) / 6 + date_left; - label_area.x2 = label_area.x1 + box_size - 1; - - box_area.x1 = label_area.x1; - box_area.x2 = label_area.x2; - - - lv_draw_rect(&box_area, clip_area, &rect_dsc); - - /*Write the day's number*/ - _lv_utils_num_to_str(day_cnt, buf); - lv_draw_label(&label_area, clip_area, &label_dsc, buf, NULL); - - /*Go to the next day*/ - day_cnt++; - } - } - calendar->state = state_ori; - _lv_obj_disable_style_caching(calendar, false); - - -} - -/** - * Check weather a date is highlighted or not - * @param calendar pointer to a calendar object - * @param draw_state which month is drawn (previous, active, next) - * @param year a year - * @param month a month [1..12] - * @param day a day [1..31] - * @return true: highlighted - */ -static bool is_highlighted(lv_obj_t * calendar, day_draw_state_t draw_state, int32_t year, int32_t month, int32_t day) -{ - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - - - if(draw_state == DAY_DRAW_PREV_MONTH) { - year -= month == 1 ? 1 : 0; - month = month == 1 ? 12 : month - 1; - } - else if(draw_state == DAY_DRAW_NEXT_MONTH) { - year += month == 12 ? 1 : 0; - month = month == 12 ? 1 : month + 1; - } - - uint32_t i; - for(i = 0; i < ext->highlighted_dates_num; i++) { - if(ext->highlighted_dates[i].year == year && ext->highlighted_dates[i].month == month && - ext->highlighted_dates[i].day == day) { - return true; - } - } - - return false; -} - -/** - * Check weather a date is highlighted or not - * @param calendar pointer to a calendar object - * @param draw_state which month is drawn (previous, active, next) - * @param year a year - * @param month a month [1..12] - * @param day a day [1..31] - * @return true: highlighted - */ -static bool is_pressed(lv_obj_t * calendar, day_draw_state_t draw_state, int32_t year, int32_t month, int32_t day) -{ - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - - - if(draw_state == DAY_DRAW_PREV_MONTH) { - year -= month == 1 ? 1 : 0; - month = month == 1 ? 12 : month - 1; - } - else if(draw_state == DAY_DRAW_NEXT_MONTH) { - year += month == 12 ? 1 : 0; - month = month == 12 ? 1 : month + 1; - } - - if(year == ext->pressed_date.year && month == ext->pressed_date.month && day == ext->pressed_date.day) return true; - else return false; -} -/** - * Get the day name - * @param calendar pointer to a calendar object - * @param day a day in [0..6] - * @return - */ -static const char * get_day_name(lv_obj_t * calendar, uint8_t day) -{ - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - if(ext->day_names) - return ext->day_names[day]; - else - return day_name[day]; -} - -/** - * Get the month name - * @param calendar pointer to a calendar object - * @param month a month. The range is basically [1..12] but [-11..1] is also supported to handle - * previous year - * @return - */ -static const char * get_month_name(lv_obj_t * calendar, int32_t month) -{ - month--; /*Range of months id [1..12] but range of indexes is [0..11]*/ - if(month < 0) month = 12 + month; - - lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar); - if(ext->month_names) - return ext->month_names[month]; - else - return month_name[month]; -} - -/** - * Get the number of days in a month - * @param year a year - * @param month a month. The range is basically [1..12] but [-11..1] is also supported to handle - * previous year - * @return [28..31] - */ -static uint8_t get_month_length(int32_t year, int32_t month) -{ - month--; /*Range of months id [1..12] but range of indexes is [0..11]*/ - if(month < 0) { - year--; /*Already in the previous year (won't be less then -12 to skip a whole year)*/ - month = 12 + month; /*`month` is negative, the result will be < 12*/ - } - if(month >= 12) { - year++; - month -= 12; - } - - /*month == 1 is february*/ - return (month == 1) ? (28 + is_leap_year(year)) : 31 - month % 7 % 2; -} - -/** - * Tells whether a year is leap year or not - * @param year a year - * @return 0: not leap year; 1: leap year - */ -static uint8_t is_leap_year(uint32_t year) -{ - return (year % 4) || ((year % 100 == 0) && (year % 400)) ? 0 : 1; -} - -/** - * Get the day of the week - * @param year a year - * @param month a month - * @param day a day - * @return [0..6] which means [Sun..Sat] or [Mon..Sun] depending on LV_CALENDAR_WEEK_STARTS_MONDAY - */ -static uint8_t get_day_of_week(uint32_t year, uint32_t month, uint32_t day) -{ - uint32_t a = month < 3 ? 1 : 0; - uint32_t b = year - a; - -#if LV_CALENDAR_WEEK_STARTS_MONDAY - uint32_t day_of_week = (day + (31 * (month - 2 + 12 * a) / 12) + b + (b / 4) - (b / 100) + (b / 400) - 1) % 7; -#else - uint32_t day_of_week = (day + (31 * (month - 2 + 12 * a) / 12) + b + (b / 4) - (b / 100) + (b / 400)) % 7; -#endif - - return day_of_week; -} - -#endif diff --git a/src/lv_widgets/lv_calendar.h b/src/lv_widgets/lv_calendar.h deleted file mode 100644 index 1e0f88cdc..000000000 --- a/src/lv_widgets/lv_calendar.h +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file lv_calendar.h - * - */ - -#ifndef LV_CALENDAR_H -#define LV_CALENDAR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_CALENDAR != 0 - -#include "../lv_core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * Represents a date on the calendar object (platform-agnostic). - */ -typedef struct { - uint16_t year; - int8_t month; - int8_t day; -} lv_calendar_date_t; - -/*Data of calendar*/ -typedef struct { - /*None*/ /*Ext. of ancestor*/ - /*New data for this type */ - lv_calendar_date_t today; /*Date of today*/ - lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/ - lv_calendar_date_t * highlighted_dates; /*Apply different style on these days (pointer to an - array defined by the user)*/ - int8_t btn_pressing; /*-1: prev month pressing, +1 next month pressing on the header*/ - uint16_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/ - lv_calendar_date_t pressed_date; - const char ** day_names; /*Pointer to an array with the name of the days (NULL: use default names)*/ - const char ** month_names; /*Pointer to an array with the name of the month (NULL. use default names)*/ - - /*Styles*/ - lv_style_list_t style_header; - lv_style_list_t style_day_names; - lv_style_list_t style_date_nums; -} lv_calendar_ext_t; - -/** Calendar parts*/ -enum { - LV_CALENDAR_PART_BG, /**< Background and "normal" date numbers style */ - LV_CALENDAR_PART_HEADER, /** Calendar header style */ - LV_CALENDAR_PART_DAY_NAMES, /** Day name style */ - LV_CALENDAR_PART_DATE, /** Day name style */ -}; -typedef uint8_t lv_calendar_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a calendar objects - * @param par pointer to an object, it will be the parent of the new calendar - * @param copy pointer to a calendar object, if not NULL then the new object will be copied from it - * @return pointer to the created calendar - */ -lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy); - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the today's date - * @param calendar pointer to a calendar object - * @param today pointer to an `lv_calendar_date_t` variable containing the date of today. The value - * will be saved it can be local variable too. - */ -void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today); - -/** - * Set the currently showed - * @param calendar pointer to a calendar object - * @param showed pointer to an `lv_calendar_date_t` variable containing the date to show. The value - * will be saved it can be local variable too. - */ -void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showed); - -/** - * Set the the highlighted dates - * @param calendar pointer to a calendar object - * @param highlighted pointer to an `lv_calendar_date_t` array containing the dates. ONLY A POINTER - * WILL BE SAVED! CAN'T BE LOCAL ARRAY. - * @param date_num number of dates in the array - */ -void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t highlighted[], uint16_t date_num); - -/** - * Set the name of the days - * @param calendar pointer to a calendar object - * @param day_names pointer to an array with the names. E.g. `const char * days[7] = {"Sun", "Mon", - * ...}` Only the pointer will be saved so this variable can't be local which will be destroyed - * later. - */ -void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names); - -/** - * Set the name of the month - * @param calendar pointer to a calendar object - * @param month_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb", - * ...}` Only the pointer will be saved so this variable can't be local which will be destroyed - * later. - */ -void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** month_names); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the today's date - * @param calendar pointer to a calendar object - * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. - */ -lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar); - -/** - * Get the currently showed - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. - */ -lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar); - -/** - * Get the the pressed date. - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the pressed date. - * `NULL` if not date pressed (e.g. the header) - */ -lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar); - -/** - * Get the the highlighted dates - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` array containing the dates. - */ -lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar); - -/** - * Get the number of the highlighted dates - * @param calendar pointer to a calendar object - * @return number of highlighted days - */ -uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar); - -/** - * Get the name of the days - * @param calendar pointer to a calendar object - * @return pointer to the array of day names - */ -const char ** lv_calendar_get_day_names(const lv_obj_t * calendar); - -/** - * Get the name of the month - * @param calendar pointer to a calendar object - * @return pointer to the array of month names - */ -const char ** lv_calendar_get_month_names(const lv_obj_t * calendar); - -/*===================== - * Other functions - *====================*/ - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_CALENDAR*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_CALENDAR_H*/ diff --git a/src/lv_widgets/lv_cont.c b/src/lv_widgets/lv_cont.c deleted file mode 100644 index 04a81343e..000000000 --- a/src/lv_widgets/lv_cont.c +++ /dev/null @@ -1,795 +0,0 @@ -/** - * @file lv_cont.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_cont.h" -#if LV_USE_CONT != 0 - -#include -#include -#include - -#include "../lv_misc/lv_debug.h" -#include "../lv_draw/lv_draw.h" -#include "../lv_draw/lv_draw_mask.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_area.h" -#include "../lv_misc/lv_color.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_cont" - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param); -static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type); -static void lv_cont_refr_layout(lv_obj_t * cont); -static void lv_cont_layout_col(lv_obj_t * cont); -static void lv_cont_layout_row(lv_obj_t * cont); -static void lv_cont_layout_center(lv_obj_t * cont); -static void lv_cont_layout_pretty(lv_obj_t * cont); -static void lv_cont_layout_grid(lv_obj_t * cont); -static void lv_cont_refr_autofit(lv_obj_t * cont); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a container objects - * @param par pointer to an object, it will be the parent of the new container - * @param copy pointer to a container object, if not NULL then the new object will be copied from it - * @return pointer to the created container - */ -lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy) -{ - - LV_LOG_TRACE("container create started"); - - /*Create a basic object*/ - lv_obj_t * cont = lv_obj_create(par, copy); - LV_ASSERT_MEM(cont); - if(cont == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cont); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(cont); - - lv_obj_allocate_ext_attr(cont, sizeof(lv_cont_ext_t)); - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - if(ext == NULL) { - lv_obj_del(cont); - return NULL; - } - - LV_ASSERT_MEM(ext); - ext->fit_left = LV_FIT_NONE; - ext->fit_right = LV_FIT_NONE; - ext->fit_top = LV_FIT_NONE; - ext->fit_bottom = LV_FIT_NONE; - ext->layout = LV_LAYOUT_OFF; - - lv_obj_set_signal_cb(cont, lv_cont_signal); - - /*Init the new container*/ - if(copy == NULL) { - /*Set the default styles if it's not screen*/ - if(par != NULL) { - lv_theme_apply(cont, LV_THEME_CONT); - } - - - } - /*Copy an existing object*/ - else { - lv_cont_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->fit_left = copy_ext->fit_left; - ext->fit_right = copy_ext->fit_right; - ext->fit_top = copy_ext->fit_top; - ext->fit_bottom = copy_ext->fit_bottom; - ext->layout = copy_ext->layout; - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(cont, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("container created"); - - return cont; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a layout on a container - * @param cont pointer to a container object - * @param layout a layout from 'lv_cont_layout_t' - */ -void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - if(ext->layout == layout) return; - - ext->layout = layout; - - /*Send a signal to refresh the layout*/ - cont->signal_cb(cont, LV_SIGNAL_CHILD_CHG, NULL); -} - -/** - * Set the fit policy in all 4 directions separately. - * It tell how to change the container's size automatically. - * @param cont pointer to a container object - * @param left left fit policy from `lv_fit_t` - * @param right right fit policy from `lv_fit_t` - * @param top bottom fit policy from `lv_fit_t` - * @param bottom bottom fit policy from `lv_fit_t` - */ -void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_obj_invalidate(cont); - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - if(ext->fit_left == left && ext->fit_right == right && ext->fit_top == top && ext->fit_bottom == bottom) { - return; - } - - ext->fit_left = left; - ext->fit_right = right; - ext->fit_top = top; - ext->fit_bottom = bottom; - - /*Send a signal to refresh the layout*/ - cont->signal_cb(cont, LV_SIGNAL_CHILD_CHG, NULL); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the layout of a container - * @param cont pointer to container object - * @return the layout from 'lv_cont_layout_t' - */ -lv_layout_t lv_cont_get_layout(const lv_obj_t * cont) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->layout; -} - -/** - * Get left fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->fit_left; -} - -/** - * Get right fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->fit_right; -} - -/** - * Get top fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->fit_top; -} - -/** - * Get bottom fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont) -{ - LV_ASSERT_OBJ(cont, LV_OBJX_NAME); - - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - return ext->fit_bottom; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the container - * @param cont pointer to a container object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param) -{ - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_cont_get_style(cont, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(cont, sign, param); - } - - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(cont, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_STYLE_CHG) { /*Recalculate the padding if the style changed*/ - lv_cont_refr_layout(cont); - lv_cont_refr_autofit(cont); - } - else if(sign == LV_SIGNAL_CHILD_CHG) { - lv_cont_refr_layout(cont); - lv_cont_refr_autofit(cont); - } - else if(sign == LV_SIGNAL_COORD_CHG) { - if(lv_obj_get_width(cont) != lv_area_get_width(param) || lv_obj_get_height(cont) != lv_area_get_height(param)) { - lv_cont_refr_layout(cont); - lv_cont_refr_autofit(cont); - } - } - else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) { - /*MAX and EDGE fit needs to be refreshed if the parent's size has changed*/ - lv_cont_refr_autofit(cont); - } - - return res; -} - - -static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type) -{ - lv_style_list_t * style_dsc_p; - switch(type) { - case LV_CONT_PART_MAIN: - style_dsc_p = &cont->style_list; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -/** - * Refresh the layout of a container - * @param cont pointer to an object which layout should be refreshed - */ -static void lv_cont_refr_layout(lv_obj_t * cont) -{ - if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return; - lv_layout_t type = lv_cont_get_layout(cont); - - /*'cont' has to be at least 1 child*/ - if(lv_obj_get_child(cont, NULL) == NULL) return; - - if(type == LV_LAYOUT_OFF) return; - - if(type == LV_LAYOUT_CENTER) { - lv_cont_layout_center(cont); - } - else if(type == LV_LAYOUT_COLUMN_LEFT || type == LV_LAYOUT_COLUMN_MID || type == LV_LAYOUT_COLUMN_RIGHT) { - lv_cont_layout_col(cont); - } - else if(type == LV_LAYOUT_ROW_TOP || type == LV_LAYOUT_ROW_MID || type == LV_LAYOUT_ROW_BOTTOM) { - lv_cont_layout_row(cont); - } - else if(type == LV_LAYOUT_PRETTY_MID || type == LV_LAYOUT_PRETTY_TOP || type == LV_LAYOUT_PRETTY_BOTTOM) { - lv_cont_layout_pretty(cont); - } - else if(type == LV_LAYOUT_GRID) { - lv_cont_layout_grid(cont); - } -} - -/** - * Handle column type layouts - * @param cont pointer to an object which layout should be handled - */ -static void lv_cont_layout_col(lv_obj_t * cont) -{ - lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN); - lv_coord_t right = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN); - lv_coord_t top = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN); - lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN); - - lv_layout_t type = lv_cont_get_layout(cont); - lv_obj_t * child; - - /*Adjust margin and get the alignment type*/ - lv_align_t align; - lv_coord_t hpad_corr; - - switch(type) { - case LV_LAYOUT_COLUMN_LEFT: - hpad_corr = left; - align = LV_ALIGN_IN_TOP_LEFT; - break; - case LV_LAYOUT_COLUMN_MID: - hpad_corr = 0; - align = LV_ALIGN_IN_TOP_MID; - break; - case LV_LAYOUT_COLUMN_RIGHT: - hpad_corr = -right; - align = LV_ALIGN_IN_TOP_RIGHT; - break; - default: - hpad_corr = 0; - align = LV_ALIGN_IN_TOP_LEFT; - break; - } - - /* Disable child change action because the children will be moved a lot - * an unnecessary child change signals could be sent*/ - lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG); - /* Align the children */ - lv_coord_t last_cord = top; - _LV_LL_READ_BACK(cont->child_ll, child) { - if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - lv_style_int_t mtop = lv_obj_get_style_margin_top(child, LV_OBJ_PART_MAIN); - lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN); - lv_style_int_t mleft = lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN); - lv_obj_align(child, cont, align, hpad_corr + mleft, last_cord + mtop); - last_cord += lv_obj_get_height(child) + inner + mtop + mbottom; - } - - lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG); -} - -/** - * Handle row type layouts - * @param cont pointer to an object which layout should be handled - */ -static void lv_cont_layout_row(lv_obj_t * cont) -{ - - lv_layout_t type = lv_cont_get_layout(cont); - lv_obj_t * child; - - /*Adjust margin and get the alignment type*/ - lv_align_t align; - lv_coord_t vpad_corr; - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont); - switch(type) { - case LV_LAYOUT_ROW_TOP: - vpad_corr = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN); - align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT; - break; - case LV_LAYOUT_ROW_MID: - vpad_corr = 0; - align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID : LV_ALIGN_IN_LEFT_MID; - break; - case LV_LAYOUT_ROW_BOTTOM: - vpad_corr = -lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN); - align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT : LV_ALIGN_IN_BOTTOM_LEFT; - break; - default: - vpad_corr = 0; - align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT; - break; - } - - /* Disable child change action because the children will be moved a lot - * an unnecessary child change signals could be sent*/ - lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG); - - /* Align the children */ - lv_coord_t last_cord; - if(base_dir == LV_BIDI_DIR_RTL) last_cord = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN); - else last_cord = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN); - - lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN); - - _LV_LL_READ_BACK(cont->child_ll, child) { - if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - - if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr); - else lv_obj_align(child, cont, align, last_cord, vpad_corr); - - last_cord += lv_obj_get_width(child) + inner; - } - - lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG); -} - -/** - * Handle the center layout - * @param cont pointer to an object which layout should be handled - */ -static void lv_cont_layout_center(lv_obj_t * cont) -{ - lv_obj_t * child; - uint32_t obj_num = 0; - lv_coord_t h_tot = 0; - - lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN); - _LV_LL_READ(cont->child_ll, child) { - if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - h_tot += lv_obj_get_height(child) + inner; - obj_num++; - } - - if(obj_num == 0) return; - - h_tot -= inner; - - /* Disable child change action because the children will be moved a lot - * an unnecessary child change signals could be sent*/ - lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG); - - /* Align the children */ - lv_coord_t last_cord = -(h_tot / 2); - _LV_LL_READ_BACK(cont->child_ll, child) { - if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - - lv_obj_align(child, cont, LV_ALIGN_CENTER, 0, last_cord + lv_obj_get_height(child) / 2); - last_cord += lv_obj_get_height(child) + inner; - } - - lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG); -} - -/** - * Handle the pretty layout. Put as many object as possible in row - * then begin a new row - * @param cont pointer to an object which layout should be handled - */ -static void lv_cont_layout_pretty(lv_obj_t * cont) -{ - lv_layout_t type = lv_cont_get_layout(cont); - - lv_obj_t * child_rs; /* Row starter child */ - lv_obj_t * child_rc; /* Row closer child */ - lv_obj_t * child_tmp; /* Temporary child */ - lv_coord_t w_obj = lv_obj_get_width(cont); - lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN); - /* Disable child change action because the children will be moved a lot - * an unnecessary child change signals could be sent*/ - - child_rs = _lv_ll_get_tail(&cont->child_ll); /*Set the row starter child*/ - if(child_rs == NULL) return; /*Return if no child*/ - - lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG); - lv_coord_t pleft = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN); - lv_coord_t pinner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN); - - child_rc = child_rs; /*Initially the the row starter and closer is the same*/ - while(child_rs != NULL) { - lv_coord_t h_row = 0; - lv_coord_t w_row = pleft + pright; /*The width is at least the left+right pad*/ - uint32_t obj_num = 0; - - /*Find the row closer object and collect some data*/ - do { - if(lv_obj_get_hidden(child_rc) == false && lv_obj_is_protected(child_rc, LV_PROTECT_POS) == false) { - /*If this object is already not fit then break*/ - lv_coord_t w = lv_obj_get_width(child_rc); - w += lv_obj_get_style_margin_left(child_rc, LV_OBJ_PART_MAIN); - w += lv_obj_get_style_margin_right(child_rc, LV_OBJ_PART_MAIN); - if(w_row + w > w_obj) { - /*Step back one child because the last already not fit, so the previous is the - * closer*/ - if(child_rc != NULL && obj_num != 0) { - child_rc = _lv_ll_get_next(&cont->child_ll, child_rc); - } - break; - } - w_row += w + pinner; /*Add the object width + inner padding*/ - - lv_coord_t h = lv_obj_get_height(child_rc); - h += lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN); - h += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN); - h_row = LV_MATH_MAX(h_row, h); /*Search the highest object*/ - obj_num++; - if(lv_obj_is_protected(child_rc, LV_PROTECT_FOLLOW)) - break; /*If can not be followed by an other object then break here*/ - } - child_rc = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Load the next object*/ - if(obj_num == 0) - child_rs = child_rc; /*If the first object was hidden (or too long) then set the - next as first */ - } while(child_rc != NULL); - - /*If the object is too long then align it to the middle*/ - if(obj_num == 0) { - if(child_rc != NULL) { - lv_style_int_t mtop = lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN); - - lv_obj_align(child_rc, cont, LV_ALIGN_IN_TOP_MID, 0, act_y + mtop); - h_row = lv_obj_get_height(child_rc); /*Not set previously because of the early break*/ - h_row += mtop; - h_row += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN); - } - } - /*If there is only one object in the row then align it to the middle*/ - else if(obj_num == 1) { - lv_obj_align(child_rs, cont, LV_ALIGN_IN_TOP_MID, - 0, - act_y + lv_obj_get_style_margin_top(child_rs, LV_OBJ_PART_MAIN)); - } - /* Align the children (from child_rs to child_rc)*/ - else { - w_row -= pinner * obj_num; - lv_coord_t new_pinner = (w_obj - w_row) / (obj_num - 1); - lv_coord_t act_x = pleft; /*x init*/ - child_tmp = child_rs; - while(child_tmp != NULL) { - if(lv_obj_get_hidden(child_tmp) == false && lv_obj_is_protected(child_tmp, LV_PROTECT_POS) == false) { - lv_coord_t mleft = lv_obj_get_style_margin_left(child_tmp, LV_OBJ_PART_MAIN); - lv_coord_t mright = lv_obj_get_style_margin_right(child_tmp, LV_OBJ_PART_MAIN); - switch(type) { - case LV_LAYOUT_PRETTY_TOP: - lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT, - act_x + mleft, - act_y + lv_obj_get_style_margin_top(child_tmp, LV_OBJ_PART_MAIN)); - break; - case LV_LAYOUT_PRETTY_MID: - lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT, - act_x + mleft, - act_y + (h_row - lv_obj_get_height(child_tmp)) / 2); - - break; - case LV_LAYOUT_PRETTY_BOTTOM: - lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT, - act_x + mleft, - act_y + h_row - lv_obj_get_height(child_tmp) - lv_obj_get_style_margin_bottom(child_tmp, LV_OBJ_PART_MAIN)); - break; - default: - break; - } - - act_x += lv_obj_get_width(child_tmp) + new_pinner + mleft + mright; - } - if(child_tmp == child_rc) break; - child_tmp = _lv_ll_get_prev(&cont->child_ll, child_tmp); - } - } - - if(child_rc == NULL) break; - act_y += pinner + h_row; /*y increment*/ - child_rs = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Go to the next object*/ - child_rc = child_rs; - } - lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG); -} - -/** - * Handle the grid layout. Align same-sized objects in a grid - * @param cont pointer to an object which layout should be handled - */ -static void lv_cont_layout_grid(lv_obj_t * cont) -{ - lv_coord_t w_fit = lv_obj_get_width_fit(cont); - lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN); - lv_coord_t y_ofs = inner + lv_obj_get_height(lv_obj_get_child(cont, NULL)); - - /* Disable child change action because the children will be moved a lot - * an unnecessary child change signals could be sent*/ - lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG); - - /* Align the children */ - lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN); - lv_coord_t act_x = left; - lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN); - lv_obj_t * child; - _LV_LL_READ_BACK(cont->child_ll, child) { - if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - lv_coord_t obj_w = lv_obj_get_width(child); - if(act_x + obj_w > w_fit + left) { - act_x = left; - act_y += y_ofs; - } - - lv_obj_set_pos(child, act_x, act_y); - act_x += inner + obj_w; - } - - lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG); -} - -/** - * Handle auto fit. Set the size of the object to involve all children. - * @param cont pointer to an object which size will be modified - */ -static void lv_cont_refr_autofit(lv_obj_t * cont) -{ - if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return; - lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont); - - if(ext->fit_left == LV_FIT_NONE && ext->fit_right == LV_FIT_NONE && ext->fit_top == LV_FIT_NONE && - ext->fit_bottom == LV_FIT_NONE) { - return; - } - - lv_area_t tight_area; - lv_area_t ori; - lv_obj_t * child_i; - - lv_obj_t * par = lv_obj_get_parent(cont); - lv_area_t parent_area; - lv_area_copy(&parent_area, &par->coords); - parent_area.x1 += lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN); - parent_area.x2 -= lv_obj_get_style_pad_right(par, LV_OBJ_PART_MAIN); - parent_area.y1 += lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN); - parent_area.y2 -= lv_obj_get_style_pad_bottom(par, LV_OBJ_PART_MAIN); - - /*Search the side coordinates of the children*/ - lv_obj_get_coords(cont, &ori); - lv_obj_get_coords(cont, &tight_area); - - bool has_children = _lv_ll_is_empty(&cont->child_ll) ? false : true; - - if(has_children) { - tight_area.x1 = LV_COORD_MAX; - tight_area.y1 = LV_COORD_MAX; - tight_area.x2 = LV_COORD_MIN; - tight_area.y2 = LV_COORD_MIN; - - _LV_LL_READ(cont->child_ll, child_i) { - if(lv_obj_get_hidden(child_i) != false) continue; - - if(ext->fit_left != LV_FIT_PARENT) { - lv_style_int_t mleft = lv_obj_get_style_margin_left(child_i, LV_OBJ_PART_MAIN); - tight_area.x1 = LV_MATH_MIN(tight_area.x1, child_i->coords.x1 - mleft); - } - - if(ext->fit_right != LV_FIT_PARENT) { - lv_style_int_t mright = lv_obj_get_style_margin_right(child_i, LV_OBJ_PART_MAIN); - tight_area.x2 = LV_MATH_MAX(tight_area.x2, child_i->coords.x2 + mright); - } - - if(ext->fit_top != LV_FIT_PARENT) { - lv_style_int_t mtop = lv_obj_get_style_margin_top(child_i, LV_OBJ_PART_MAIN); - tight_area.y1 = LV_MATH_MIN(tight_area.y1, child_i->coords.y1 - mtop); - } - - if(ext->fit_bottom != LV_FIT_PARENT) { - lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child_i, LV_OBJ_PART_MAIN); - tight_area.y2 = LV_MATH_MAX(tight_area.y2, child_i->coords.y2 + mbottom); - } - } - - tight_area.x1 -= lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN); - tight_area.x2 += lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN); - tight_area.y1 -= lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN); - tight_area.y2 += lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN); - } - - lv_area_t new_area; - lv_area_copy(&new_area, &ori); - - switch(ext->fit_left) { - case LV_FIT_TIGHT: - new_area.x1 = tight_area.x1; - break; - case LV_FIT_PARENT: - new_area.x1 = parent_area.x1; - break; - case LV_FIT_MAX: - new_area.x1 = has_children ? LV_MATH_MIN(tight_area.x1, parent_area.x1) : parent_area.x1; - break; - default: - break; - } - - switch(ext->fit_right) { - case LV_FIT_TIGHT: - new_area.x2 = tight_area.x2; - break; - case LV_FIT_PARENT: - new_area.x2 = parent_area.x2; - break; - case LV_FIT_MAX: - new_area.x2 = has_children ? LV_MATH_MAX(tight_area.x2, parent_area.x2) : parent_area.x2; - break; - default: - break; - } - - switch(ext->fit_top) { - case LV_FIT_TIGHT: - new_area.y1 = tight_area.y1; - break; - case LV_FIT_PARENT: - new_area.y1 = parent_area.y1; - break; - case LV_FIT_MAX: - new_area.y1 = has_children ? LV_MATH_MIN(tight_area.y1, parent_area.y1) : parent_area.y1; - break; - default: - break; - } - - switch(ext->fit_bottom) { - case LV_FIT_TIGHT: - new_area.y2 = tight_area.y2; - break; - case LV_FIT_PARENT: - new_area.y2 = parent_area.y2; - break; - case LV_FIT_MAX: - new_area.y2 = has_children ? LV_MATH_MAX(tight_area.y2, parent_area.y2) : parent_area.y2; - break; - default: - break; - } - - /*Do nothing if the coordinates are not changed*/ - if(cont->coords.x1 != new_area.x1 || cont->coords.y1 != new_area.y1 || cont->coords.x2 != new_area.x2 || - cont->coords.y2 != new_area.y2) { - - lv_obj_invalidate(cont); - lv_area_copy(&cont->coords, &new_area); - lv_obj_invalidate(cont); - - /*Notify the object about its new coordinates*/ - cont->signal_cb(cont, LV_SIGNAL_COORD_CHG, &ori); - - /*Inform the parent about the new coordinates*/ - par->signal_cb(par, LV_SIGNAL_CHILD_CHG, cont); - - if(lv_obj_get_auto_realign(cont)) { - lv_obj_realign(cont); - } - - /*Tell the children the parent's size has changed*/ - _LV_LL_READ(cont->child_ll, child_i) { - child_i->signal_cb(child_i, LV_SIGNAL_PARENT_SIZE_CHG, &ori); - } - } -} - -#endif diff --git a/src/lv_widgets/lv_cont.h b/src/lv_widgets/lv_cont.h deleted file mode 100644 index 837559a3d..000000000 --- a/src/lv_widgets/lv_cont.h +++ /dev/null @@ -1,223 +0,0 @@ -/** - * @file lv_cont.h - * - */ - -#ifndef LV_CONT_H -#define LV_CONT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_CONT != 0 - -#include "../lv_core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** Container layout options*/ -enum { - LV_LAYOUT_OFF = 0, /**< No layout */ - LV_LAYOUT_CENTER, /**< Center objects */ - - /** - * COULMN: - * - Place the object below each other - * - Keep `pad_top` space on the top - * - Keep `pad_inner` space between the objects - */ - LV_LAYOUT_COLUMN_LEFT, /**< Column left align*/ - LV_LAYOUT_COLUMN_MID, /**< Column middle align*/ - LV_LAYOUT_COLUMN_RIGHT, /**< Column right align*/ - - /** - * ROW: - * - Place the object next to each other - * - Keep `pad_left` space on the left - * - Keep `pad_inner` space between the objects - * - If the object which applies the layout has `base_dir == LV_BIDI_DIR_RTL` - * the row will start from the right applying `pad.right` space - */ - LV_LAYOUT_ROW_TOP, /**< Row top align*/ - LV_LAYOUT_ROW_MID, /**< Row middle align*/ - LV_LAYOUT_ROW_BOTTOM, /**< Row bottom align*/ - - - /** - * PRETTY: - * - Place the object next to each other - * - If there is no more space start a new row - * - Respect `pad_left` and `pad_right` when determining the available space in a row - * - Keep `pad_inner` space between the objects in the same row - * - Keep `pad_inner` space between the objects in rows - * - Divide the remaining horizontal space equally - */ - LV_LAYOUT_PRETTY_TOP, /**< Row top align*/ - LV_LAYOUT_PRETTY_MID, /**< Row middle align*/ - LV_LAYOUT_PRETTY_BOTTOM, /**< Row bottom align*/ - - /** - * GRID - * - Place the object next to each other - * - If there is no more space start a new row - * - Respect `pad_left` and `pad_right` when determining the available space in a row - * - Keep `pad_inner` space between the objects in the same row - * - Keep `pad_inner` space between the objects in rows - * - Unlike `PRETTY`, `GRID` always keep `pad_inner` space horizontally between objects - * so it doesn't divide the remaining horizontal space equally - */ - LV_LAYOUT_GRID, /**< Align same-sized object into a grid*/ - - _LV_LAYOUT_LAST -}; -typedef uint8_t lv_layout_t; - -/** - * How to resize the container around the children. - */ -enum { - LV_FIT_NONE, /**< Do not change the size automatically*/ - LV_FIT_TIGHT, /**< Shrink wrap around the children */ - LV_FIT_PARENT, /**< Align the size to the parent's edge*/ - LV_FIT_MAX, /**< Align the size to the parent's edge first but if there is an object out of it - then get larger */ - _LV_FIT_LAST -}; -typedef uint8_t lv_fit_t; - -typedef struct { - /*Inherited from 'base_obj' so no inherited ext. */ /*Ext. of ancestor*/ - /*New data for this type */ - lv_layout_t layout : 4; /*A layout from 'lv_layout_t' enum*/ - lv_fit_t fit_left : 2; /*A fit type from `lv_fit_t` enum */ - lv_fit_t fit_right : 2; /*A fit type from `lv_fit_t` enum */ - lv_fit_t fit_top : 2; /*A fit type from `lv_fit_t` enum */ - lv_fit_t fit_bottom : 2; /*A fit type from `lv_fit_t` enum */ -} lv_cont_ext_t; - -/*Part of the container*/ -enum { - LV_CONT_PART_MAIN = LV_OBJ_PART_MAIN, - _LV_CONT_PART_VIRTUAL_LAST = _LV_OBJ_PART_VIRTUAL_LAST, - _LV_CONT_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST, -}; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a container objects - * @param par pointer to an object, it will be the parent of the new container - * @param copy pointer to a container object, if not NULL then the new object will be copied from it - * @return pointer to the created container - */ -lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a layout on a container - * @param cont pointer to a container object - * @param layout a layout from 'lv_cont_layout_t' - */ -void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout); - -/** - * Set the fit policy in all 4 directions separately. - * It tell how to change the container's size automatically. - * @param cont pointer to a container object - * @param left left fit policy from `lv_fit_t` - * @param right right fit policy from `lv_fit_t` - * @param top top fit policy from `lv_fit_t` - * @param bottom bottom fit policy from `lv_fit_t` - */ -void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom); - -/** - * Set the fit policy horizontally and vertically separately. - * It tells how to change the container's size automatically. - * @param cont pointer to a container object - * @param hor horizontal fit policy from `lv_fit_t` - * @param ver vertical fit policy from `lv_fit_t` - */ -static inline void lv_cont_set_fit2(lv_obj_t * cont, lv_fit_t hor, lv_fit_t ver) -{ - lv_cont_set_fit4(cont, hor, hor, ver, ver); -} - -/** - * Set the fit policy in all 4 direction at once. - * It tells how to change the container's size automatically. - * @param cont pointer to a container object - * @param fit fit policy from `lv_fit_t` - */ -static inline void lv_cont_set_fit(lv_obj_t * cont, lv_fit_t fit) -{ - lv_cont_set_fit4(cont, fit, fit, fit, fit); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the layout of a container - * @param cont pointer to container object - * @return the layout from 'lv_cont_layout_t' - */ -lv_layout_t lv_cont_get_layout(const lv_obj_t * cont); - -/** - * Get left fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont); - -/** - * Get right fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont); - -/** - * Get top fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont); - -/** - * Get bottom fit mode of a container - * @param cont pointer to a container object - * @return an element of `lv_fit_t` - */ -lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_CONT*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_CONT_H*/ diff --git a/src/lv_widgets/lv_cpicker.c b/src/lv_widgets/lv_cpicker.c deleted file mode 100644 index 9b3a857ae..000000000 --- a/src/lv_widgets/lv_cpicker.c +++ /dev/null @@ -1,1039 +0,0 @@ -/** - * @file lv_cpicker.c - * - * From @AloyseTech and @paulpv. - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_cpicker.h" -#if LV_USE_CPICKER != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_draw/lv_draw_arc.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_core/lv_indev.h" -#include "../lv_core/lv_refr.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_cpicker" - -#ifndef LV_CPICKER_DEF_TYPE - #define LV_CPICKER_DEF_TYPE LV_CPICKER_TYPE_DISC -#endif - -#ifndef LV_CPICKER_DEF_HUE - #define LV_CPICKER_DEF_HUE 0 -#endif - -#ifndef LV_CPICKER_DEF_SATURATION - #define LV_CPICKER_DEF_SATURATION 100 -#endif - -#ifndef LV_CPICKER_DEF_VALUE - #define LV_CPICKER_DEF_VALUE 100 -#endif - -#ifndef LV_CPICKER_DEF_HSV - #define LV_CPICKER_DEF_HSV ((lv_color_hsv_t){LV_CPICKER_DEF_HUE, LV_CPICKER_DEF_SATURATION, LV_CPICKER_DEF_VALUE}) -#endif - -#ifndef LV_CPICKER_DEF_QF /*quantization factor*/ - #define LV_CPICKER_DEF_QF 3 -#endif - -#define TRI_OFFSET 2 - -/* The OUTER_MASK_WIDTH define is required to assist with the placing of a mask over the outer ring of the widget as when the - * multicoloured radial lines are calculated for the outer ring of the widget their lengths are jittering because of the - * integer based arithmetic. From tests the maximum delta was found to be 2 so the current value is set to 3 to achieve - * appropriate masking. - */ -#define OUTER_MASK_WIDTH 3 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_design_res_t lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param); -static lv_style_list_t * lv_cpicker_get_style(lv_obj_t * cpicker, uint8_t part); -static bool lv_cpicker_hit(lv_obj_t * cpicker, const lv_point_t * p); - -static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask); -static void draw_disc_grad(lv_obj_t * cpicker, const lv_area_t * mask); -static void draw_knob(lv_obj_t * cpicker, const lv_area_t * mask); -static void invalidate_knob(lv_obj_t * cpicker); -static lv_area_t get_knob_area(lv_obj_t * cpicker); - -static void next_color_mode(lv_obj_t * cpicker); -static lv_res_t double_click_reset(lv_obj_t * cpicker); -static void refr_knob_pos(lv_obj_t * cpicker); -static lv_color_t angle_to_mode_color(lv_obj_t * cpicker, uint16_t angle); -static uint16_t get_angle(lv_obj_t * cpicker); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a color_picker object - * @param par pointer to an object, it will be the parent of the new color_picker - * @param copy pointer to a color_picker object, if not NULL then the new object will be copied from it - * @return pointer to the created color_picker - */ -lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("color_picker create started"); - - lv_obj_t * cpicker = lv_obj_create(par, copy); - LV_ASSERT_MEM(cpicker); - if(cpicker == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cpicker); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(cpicker); - - /*Allocate the extended data*/ - lv_cpicker_ext_t * ext = lv_obj_allocate_ext_attr(cpicker, sizeof(lv_cpicker_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(cpicker); - return NULL; - } - - /*Initialize the allocated 'ext' */ - ext->type = LV_CPICKER_DEF_TYPE; - ext->hsv = LV_CPICKER_DEF_HSV; - ext->knob.colored = 1; - ext->color_mode = LV_CPICKER_COLOR_MODE_HUE; - ext->color_mode_fixed = 0; - ext->last_click_time = 0; - ext->last_change_time = 0; - - lv_style_list_init(&ext->knob.style_list); - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(cpicker, lv_cpicker_signal); - lv_obj_set_design_cb(cpicker, lv_cpicker_design); - - /*If no copy do the basic initialization*/ - if(copy == NULL) { - lv_obj_set_size(cpicker, LV_DPI * 2, LV_DPI * 2); - lv_obj_add_protect(cpicker, LV_PROTECT_PRESS_LOST); - lv_obj_set_adv_hittest(cpicker, true); - lv_theme_apply(cpicker, LV_THEME_CPICKER); - } - /*Copy 'copy'*/ - else { - lv_cpicker_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->type = copy_ext->type; - ext->color_mode = copy_ext->color_mode; - ext->color_mode_fixed = copy_ext->color_mode_fixed; - ext->hsv = copy_ext->hsv; - ext->knob.colored = copy_ext->knob.colored; - - lv_style_list_copy(&ext->knob.style_list, ©_ext->knob.style_list); - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(cpicker, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - refr_knob_pos(cpicker); - - LV_LOG_INFO("color_picker created"); - - return cpicker; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new type for a cpicker - * @param cpicker pointer to a cpicker object - * @param type new type of the cpicker (from 'lv_cpicker_type_t' enum) - */ -void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - if(ext->type == type) return; - - ext->type = type; - lv_obj_refresh_ext_draw_pad(cpicker); - refr_knob_pos(cpicker); - - lv_obj_invalidate(cpicker); -} - -/** - * Set the current hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param hue current selected hue [0..360] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue) -{ - lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker); - hsv.h = hue; - return lv_cpicker_set_hsv(cpicker, hsv); -} - -/** - * Set the current saturation of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param saturation current selected saturation [0..100] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation) -{ - lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker); - hsv.s = saturation; - return lv_cpicker_set_hsv(cpicker, hsv); -} - -/** - * Set the current value of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param val current selected value [0..100] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val) -{ - lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker); - hsv.v = val; - return lv_cpicker_set_hsv(cpicker, hsv); -} - -/** - * Set the current hsv of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param color current selected hsv - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - if(hsv.h > 360) hsv.h %= 360; - if(hsv.s > 100) hsv.s = 100; - if(hsv.v > 100) hsv.v = 100; - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - if(ext->hsv.h == hsv.h && ext->hsv.s == hsv.s && ext->hsv.v == hsv.v) return false; - - ext->hsv = hsv; - - refr_knob_pos(cpicker); - - lv_obj_invalidate(cpicker); - - return true; -} - -/** - * Set the current color of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param color current selected color - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_color32_t c32; - c32.full = lv_color_to32(color); - - return lv_cpicker_set_hsv(cpicker, - lv_color_rgb_to_hsv(c32.ch.red, c32.ch.green, c32.ch.blue)); -} - -/** - * Set the current color mode. - * @param cpicker pointer to colorpicker object - * @param mode color mode (hue/sat/val) - */ -void lv_cpicker_set_color_mode(lv_obj_t * cpicker, lv_cpicker_color_mode_t mode) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - ext->color_mode = mode; - refr_knob_pos(cpicker); - lv_obj_invalidate(cpicker); -} - -/** - * Set if the color mode is changed on long press on center - * @param cpicker pointer to colorpicker object - * @param fixed color mode cannot be changed on long press - */ -void lv_cpicker_set_color_mode_fixed(lv_obj_t * cpicker, bool fixed) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - ext->color_mode_fixed = fixed; -} - -/** - * Make the knob to be colored to the current color - * @param cpicker pointer to colorpicker object - * @param en true: color the knob; false: not color the knob - */ -void lv_cpicker_set_knob_colored(lv_obj_t * cpicker, bool en) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - ext->knob.colored = en ? 1 : 0; - invalidate_knob(cpicker); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the current color mode. - * @param cpicker pointer to colorpicker object - * @return color mode (hue/sat/val) - */ -lv_cpicker_color_mode_t lv_cpicker_get_color_mode(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->color_mode; -} - -/** - * Get if the color mode is changed on long press on center - * @param cpicker pointer to colorpicker object - * @return mode cannot be changed on long press - */ -bool lv_cpicker_get_color_mode_fixed(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->color_mode_fixed; -} - -/** - * Get the current selected hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return hue current selected hue - */ -uint16_t lv_cpicker_get_hue(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->hsv.h; -} - -/** - * Get the current selected saturation of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected saturation - */ -uint8_t lv_cpicker_get_saturation(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->hsv.s; -} - -/** - * Get the current selected hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected value - */ -uint8_t lv_cpicker_get_value(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->hsv.v; -} - -/** - * Get the current selected hsv of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected hsv - */ -lv_color_hsv_t lv_cpicker_get_hsv(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->hsv; -} - -/** - * Get the current selected color of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return color current selected color - */ -lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return lv_color_hsv_to_rgb(ext->hsv.h, ext->hsv.s, ext->hsv.v); -} - -/** - * Whether the knob is colored to the current color or not - * @param cpicker pointer to color picker object - * @return true: color the knob; false: not color the knob - */ -bool lv_cpicker_get_knob_colored(lv_obj_t * cpicker) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - return ext->knob.colored ? true : false; -} - -/*===================== - * Other functions - *====================*/ - -/********************** - * STATIC FUNCTIONS - **********************/ - - -/** - * Handle the drawing related tasks of the color_picker - * @param cpicker pointer to an object - * @param mask the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @return return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return LV_DESIGN_RES_NOT_COVER; - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - if(ext->type == LV_CPICKER_TYPE_DISC) { - draw_disc_grad(cpicker, clip_area); - } - else if(ext->type == LV_CPICKER_TYPE_RECT) { - draw_rect_grad(cpicker, clip_area); - } - - draw_knob(cpicker, clip_area); - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - } - - return LV_DESIGN_RES_OK; -} - -static void draw_disc_grad(lv_obj_t * cpicker, const lv_area_t * mask) -{ - lv_coord_t w = lv_obj_get_width(cpicker); - lv_coord_t h = lv_obj_get_height(cpicker); - lv_coord_t cx = cpicker->coords.x1 + w / 2; - lv_coord_t cy = cpicker->coords.y1 + h / 2; - lv_coord_t r = w / 2; - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(cpicker, LV_CPICKER_PART_MAIN, &line_dsc); - - line_dsc.width = (r * 628 / (360 / LV_CPICKER_DEF_QF)) / 100; - line_dsc.width += 2; - uint16_t i; - lv_coord_t cir_w = lv_obj_get_style_scale_width(cpicker, LV_CPICKER_PART_MAIN); - - /* Mask outer ring of widget to tidy up ragged edges of lines while drawing outer ring */ - lv_area_t mask_area_out; - lv_area_copy(&mask_area_out, &cpicker->coords); - mask_area_out.x1 += OUTER_MASK_WIDTH; - mask_area_out.x2 -= OUTER_MASK_WIDTH; - mask_area_out.y1 += OUTER_MASK_WIDTH; - mask_area_out.y2 -= OUTER_MASK_WIDTH; - lv_draw_mask_radius_param_t mask_out_param; - lv_draw_mask_radius_init(&mask_out_param, &mask_area_out, LV_RADIUS_CIRCLE, false); - int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0); - - /* The inner line ends will be masked out. - * So make lines a little bit longer because the masking makes a more even result */ - lv_coord_t cir_w_extra = cir_w + line_dsc.width; - - for(i = 0; i <= 360; i += LV_CPICKER_DEF_QF) { - line_dsc.color = angle_to_mode_color(cpicker, i); - - lv_point_t p[2]; - p[0].x = cx + (r * _lv_trigo_sin(i) >> LV_TRIGO_SHIFT); - p[0].y = cy + (r * _lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); - p[1].x = cx + ((r - cir_w_extra) * _lv_trigo_sin(i) >> LV_TRIGO_SHIFT); - p[1].y = cy + ((r - cir_w_extra) * _lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); - - lv_draw_line(&p[0], &p[1], mask, &line_dsc); - } - /* Now remove mask to continue with inner part */ - lv_draw_mask_remove_id(mask_out_id); - - /*Mask out the inner area*/ - lv_draw_rect_dsc_t bg_dsc; - lv_draw_rect_dsc_init(&bg_dsc); - lv_obj_init_draw_rect_dsc(cpicker, LV_CPICKER_PART_MAIN, &bg_dsc); - bg_dsc.radius = LV_RADIUS_CIRCLE; - - lv_area_t area_mid; - lv_area_copy(&area_mid, &cpicker->coords); - area_mid.x1 += cir_w; - area_mid.y1 += cir_w; - area_mid.x2 -= cir_w; - area_mid.y2 -= cir_w; - - lv_draw_rect(&area_mid, mask, &bg_dsc); - - lv_style_int_t inner = lv_obj_get_style_pad_inner(cpicker, LV_CPICKER_PART_MAIN); - lv_color_t color = lv_cpicker_get_color(cpicker); - bg_dsc.bg_color = color; - area_mid.x1 += inner; - area_mid.y1 += inner; - area_mid.x2 -= inner; - area_mid.y2 -= inner; - - lv_draw_rect(&area_mid, mask, &bg_dsc); -} - -static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask) -{ - lv_draw_rect_dsc_t bg_dsc; - lv_draw_rect_dsc_init(&bg_dsc); - lv_obj_init_draw_rect_dsc(cpicker, LV_CPICKER_PART_MAIN, &bg_dsc); - - lv_area_t grad_area; - lv_obj_get_coords(cpicker, &grad_area); - - if(bg_dsc.radius) { - lv_coord_t h = lv_obj_get_height(cpicker); - lv_coord_t r = bg_dsc.radius; - if(r > h / 2) r = h / 2; - /*Make the gradient area smaller with a half circle on both ends*/ - grad_area.x1 += r; - grad_area.x2 -= r; - - /*Draw the left rounded end*/ - lv_area_t rounded_edge_area; - lv_obj_get_coords(cpicker, &rounded_edge_area); - rounded_edge_area.x2 = rounded_edge_area.x1 + 2 * r; - - bg_dsc.bg_color = angle_to_mode_color(cpicker, 0); - - lv_draw_rect(&rounded_edge_area, mask, &bg_dsc); - - /*Draw the right rounded end*/ - lv_obj_get_coords(cpicker, &rounded_edge_area); - rounded_edge_area.x1 = rounded_edge_area.x2 - 2 * r; - - bg_dsc.bg_color = angle_to_mode_color(cpicker, 359); - - lv_draw_rect(&rounded_edge_area, mask, &bg_dsc); - } - - lv_coord_t grad_w = lv_area_get_width(&grad_area); - uint16_t i_step = LV_MATH_MAX(LV_CPICKER_DEF_QF, 360 / grad_w); - bg_dsc.radius = 0; - bg_dsc.border_width = 0; - bg_dsc.shadow_width = 0; - - uint16_t i; - for(i = 0; i < 360; i += i_step) { - bg_dsc.bg_color = angle_to_mode_color(cpicker, i); - - /*the following attribute might need changing between index to add border, shadow, radius etc*/ - lv_area_t rect_area; - - /*scale angle (hue/sat/val) to linear coordinate*/ - lv_coord_t xi = (i * grad_w) / 360; - lv_coord_t xi2 = ((i + i_step) * grad_w) / 360; - - rect_area.x1 = LV_MATH_MIN(grad_area.x1 + xi, grad_area.x1 + grad_w - i_step); - rect_area.y1 = grad_area.y1; - rect_area.x2 = LV_MATH_MIN(grad_area.x1 + xi2, grad_area.x1 + grad_w - i_step); - rect_area.y2 = grad_area.y2; - - lv_draw_rect(&rect_area, mask, &bg_dsc); - } -} - -static void draw_knob(lv_obj_t * cpicker, const lv_area_t * mask) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - lv_draw_rect_dsc_t cir_dsc; - lv_draw_rect_dsc_init(&cir_dsc); - lv_obj_init_draw_rect_dsc(cpicker, LV_CPICKER_PART_KNOB, &cir_dsc); - - cir_dsc.radius = LV_RADIUS_CIRCLE; - - if(ext->knob.colored) { - cir_dsc.bg_color = lv_cpicker_get_color(cpicker); - } - - lv_area_t knob_area = get_knob_area(cpicker); - - lv_draw_rect(&knob_area, mask, &cir_dsc); -} - -static void invalidate_knob(lv_obj_t * cpicker) -{ - lv_area_t knob_area = get_knob_area(cpicker); - - lv_obj_invalidate_area(cpicker, &knob_area); -} - -static lv_area_t get_knob_area(lv_obj_t * cpicker) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - /*Get knob's radius*/ - uint16_t r = 0; - if(ext->type == LV_CPICKER_TYPE_DISC) { - r = lv_obj_get_style_scale_width(cpicker, LV_CPICKER_PART_MAIN) / 2; - } - else if(ext->type == LV_CPICKER_TYPE_RECT) { - lv_coord_t h = lv_obj_get_height(cpicker); - r = h / 2; - } - - lv_style_int_t left = lv_obj_get_style_pad_left(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t right = lv_obj_get_style_pad_right(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t top = lv_obj_get_style_pad_top(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(cpicker, LV_CPICKER_PART_KNOB); - - lv_area_t knob_area; - knob_area.x1 = cpicker->coords.x1 + ext->knob.pos.x - r - left; - knob_area.y1 = cpicker->coords.y1 + ext->knob.pos.y - r - right; - knob_area.x2 = cpicker->coords.x1 + ext->knob.pos.x + r + top; - knob_area.y2 = cpicker->coords.y1 + ext->knob.pos.y + r + bottom; - - return knob_area; -} - -/** - * Signal function of the color_picker - * @param cpicker pointer to a color_picker object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param) -{ - /* Include the ancient signal function */ - lv_res_t res; - - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_cpicker_get_style(cpicker, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(cpicker, sign, param); - } - - res = ancestor_signal(cpicker, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - - if(sign == LV_SIGNAL_CLEANUP) { - lv_obj_clean_style_list(cpicker, LV_CPICKER_PART_KNOB); - } - else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - lv_style_int_t left = lv_obj_get_style_pad_left(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t right = lv_obj_get_style_pad_right(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t top = lv_obj_get_style_pad_top(cpicker, LV_CPICKER_PART_KNOB); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(cpicker, LV_CPICKER_PART_KNOB); - - lv_coord_t knob_pad = LV_MATH_MAX4(left, right, top, bottom) + 2; - - if(ext->type == LV_CPICKER_TYPE_DISC) { - cpicker->ext_draw_pad = LV_MATH_MAX(cpicker->ext_draw_pad, knob_pad); - } - else { - knob_pad += lv_obj_get_height(cpicker) / 2; - cpicker->ext_draw_pad = LV_MATH_MAX(cpicker->ext_draw_pad, knob_pad); - } - } - else if(sign == LV_SIGNAL_COORD_CHG) { - /*Refresh extended draw area to make knob visible*/ - if(lv_obj_get_width(cpicker) != lv_area_get_width(param) || - lv_obj_get_height(cpicker) != lv_area_get_height(param)) { - lv_obj_refresh_ext_draw_pad(cpicker); - refr_knob_pos(cpicker); - lv_obj_invalidate(cpicker); - } - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - /*Refresh extended draw area to make knob visible*/ - lv_obj_refresh_ext_draw_pad(cpicker); - refr_knob_pos(cpicker); - lv_obj_invalidate(cpicker); - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ - - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_color_hsv_t hsv_cur; - hsv_cur = ext->hsv; - - switch(ext->color_mode) { - case LV_CPICKER_COLOR_MODE_HUE: - hsv_cur.h = (ext->hsv.h + 1) % 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - hsv_cur.s = (ext->hsv.s + 1) % 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - hsv_cur.v = (ext->hsv.v + 1) % 100; - break; - } - - if(lv_cpicker_set_hsv(cpicker, hsv_cur)) { - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_color_hsv_t hsv_cur; - hsv_cur = ext->hsv; - - switch(ext->color_mode) { - case LV_CPICKER_COLOR_MODE_HUE: - hsv_cur.h = ext->hsv.h > 0 ? (ext->hsv.h - 1) : 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - hsv_cur.s = ext->hsv.s > 0 ? (ext->hsv.s - 1) : 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - hsv_cur.v = ext->hsv.v > 0 ? (ext->hsv.v - 1) : 100; - break; - } - - if(lv_cpicker_set_hsv(cpicker, hsv_cur)) { - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } -#endif - } - else if(sign == LV_SIGNAL_PRESSED) { - ext->last_change_time = lv_tick_get(); - lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); - res = double_click_reset(cpicker); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return res; - - lv_indev_type_t indev_type = lv_indev_get_type(indev); - lv_point_t p; - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { - p.x = cpicker->coords.x1 + lv_obj_get_width(cpicker) / 2; - p.y = cpicker->coords.y1 + lv_obj_get_height(cpicker) / 2; - } - else { - lv_indev_get_point(indev, &p); - } - - if((LV_MATH_ABS(p.x - ext->last_press_point.x) > indev->driver.scroll_limit / 2) || - (LV_MATH_ABS(p.y - ext->last_press_point.y) > indev->driver.scroll_limit / 2)) { - ext->last_change_time = lv_tick_get(); - ext->last_press_point.x = p.x; - ext->last_press_point.y = p.y; - } - - p.x -= cpicker->coords.x1; - p.y -= cpicker->coords.y1; - - /*Ignore pressing in the inner area*/ - uint16_t w = lv_obj_get_width(cpicker); - - int16_t angle = 0; - - if(ext->type == LV_CPICKER_TYPE_RECT) { - /*If pressed long enough without change go to next color mode*/ - uint32_t diff = lv_tick_elaps(ext->last_change_time); - if(diff > (uint32_t)indev->driver.long_press_time * 2 && !ext->color_mode_fixed) { - next_color_mode(cpicker); - lv_indev_wait_release(lv_indev_get_act()); - return res; - } - - angle = (p.x * 360) / w; - if(angle < 0) angle = 0; - if(angle >= 360) angle = 359; - - } - else if(ext->type == LV_CPICKER_TYPE_DISC) { - lv_style_int_t scale_w = lv_obj_get_style_scale_width(cpicker, LV_CPICKER_PART_MAIN); - - lv_coord_t r_in = w / 2; - p.x -= r_in; - p.y -= r_in; - bool on_ring = true; - r_in -= scale_w; - if(r_in > LV_DPI / 2) { - lv_style_int_t inner = lv_obj_get_style_pad_inner(cpicker, LV_CPICKER_PART_MAIN); - r_in -= inner; - - if(r_in < LV_DPI / 2) r_in = LV_DPI / 2; - } - - if(p.x * p.x + p.y * p.y < r_in * r_in) { - on_ring = false; - } - - /*If the inner area is being pressed, go to the next color mode on long press*/ - uint32_t diff = lv_tick_elaps(ext->last_change_time); - if(!on_ring && diff > indev->driver.long_press_time && !ext->color_mode_fixed) { - next_color_mode(cpicker); - lv_indev_wait_release(lv_indev_get_act()); - return res; - } - - /*Set the angle only if pressed on the ring*/ - if(!on_ring) return res; - - angle = _lv_atan2(p.x, p.y) % 360; - } - - lv_color_hsv_t hsv_cur; - hsv_cur = ext->hsv; - - switch(ext->color_mode) { - case LV_CPICKER_COLOR_MODE_HUE: - hsv_cur.h = angle; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - hsv_cur.s = (angle * 100) / 360; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - hsv_cur.v = (angle * 100) / 360; - break; - } - - if(lv_cpicker_set_hsv(cpicker, hsv_cur)) { - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - else if(sign == LV_SIGNAL_HIT_TEST) { - lv_hit_test_info_t * info = param; - info->result = lv_cpicker_hit(cpicker, info->point); - } - - return res; -} - - -/** - * Get the style_list descriptor of a part of the object - * @param cpicker pointer the object - * @param part the part of the cpicker. (LV_PAGE_CPICKER_...) - * @return pointer to the style_list descriptor of the specified part - */ -static lv_style_list_t * lv_cpicker_get_style(lv_obj_t * cpicker, uint8_t part) -{ - LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_CPICKER_PART_MAIN : - style_dsc_p = &cpicker->style_list; - break; - case LV_CPICKER_PART_KNOB: - style_dsc_p = &ext->knob.style_list; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -static bool lv_cpicker_hit(lv_obj_t * cpicker, const lv_point_t * p) -{ - bool is_point_on_coords = lv_obj_is_point_on_coords(cpicker, p); - if(!is_point_on_coords) - return false; - - lv_cpicker_ext_t * ext = (lv_cpicker_ext_t *)lv_obj_get_ext_attr(cpicker); - if(ext->type == LV_CPICKER_TYPE_RECT) - return true; - - - /*Valid clicks can be only in the circle*/ - if(_lv_area_is_point_on(&cpicker->coords, p, LV_RADIUS_CIRCLE)) return true; - else return false; -} - -static void next_color_mode(lv_obj_t * cpicker) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - ext->color_mode = (ext->color_mode + 1) % 3; - refr_knob_pos(cpicker); - lv_obj_invalidate(cpicker); -} - -static void refr_knob_pos(lv_obj_t * cpicker) -{ - invalidate_knob(cpicker); - - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_coord_t w = lv_obj_get_width(cpicker); - lv_coord_t h = lv_obj_get_height(cpicker); - - if(ext->type == LV_CPICKER_TYPE_RECT) { - lv_coord_t ind_pos = 0; - switch(ext->color_mode) { - case LV_CPICKER_COLOR_MODE_HUE: - ind_pos += (ext->hsv.h * w) / 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ind_pos += (ext->hsv.s * w) / 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ind_pos += (ext->hsv.v * w) / 100; - break; - } - - ext->knob.pos.x = ind_pos; - ext->knob.pos.y = h / 2; - } - else if(ext->type == LV_CPICKER_TYPE_DISC) { - lv_style_int_t scale_w = lv_obj_get_style_scale_width(cpicker, LV_CPICKER_PART_MAIN); - lv_coord_t r = (w - scale_w) / 2; - uint16_t angle = get_angle(cpicker); - ext->knob.pos.x = (((int32_t)r * _lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT); - ext->knob.pos.y = (((int32_t)r * _lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT); - ext->knob.pos.x = ext->knob.pos.x + w / 2; - ext->knob.pos.y = ext->knob.pos.y + h / 2; - } - - invalidate_knob(cpicker); -} - -static lv_res_t double_click_reset(lv_obj_t * cpicker) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_indev_t * indev = lv_indev_get_act(); - /*Double clicked? Use long press time as double click time out*/ - if(lv_tick_elaps(ext->last_click_time) < indev->driver.long_press_time) { - lv_color_hsv_t hsv_cur; - hsv_cur = ext->hsv; - - switch(ext->color_mode) { - case LV_CPICKER_COLOR_MODE_HUE: - hsv_cur.h = LV_CPICKER_DEF_HUE; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - hsv_cur.s = LV_CPICKER_DEF_SATURATION; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - hsv_cur.v = LV_CPICKER_DEF_VALUE; - break; - } - - lv_indev_wait_release(indev); - - if(lv_cpicker_set_hsv(cpicker, hsv_cur)) { - lv_res_t res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - ext->last_click_time = lv_tick_get(); - - return LV_RES_OK; -} - -static lv_color_t angle_to_mode_color(lv_obj_t * cpicker, uint16_t angle) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_color_t color; - switch(ext->color_mode) { - default: - case LV_CPICKER_COLOR_MODE_HUE: - color = lv_color_hsv_to_rgb(angle % 360, ext->hsv.s, ext->hsv.v); - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - color = lv_color_hsv_to_rgb(ext->hsv.h, ((angle % 360) * 100) / 360, ext->hsv.v); - break; - case LV_CPICKER_COLOR_MODE_VALUE: - color = lv_color_hsv_to_rgb(ext->hsv.h, ext->hsv.s, ((angle % 360) * 100) / 360); - break; - } - return color; -} - -static uint16_t get_angle(lv_obj_t * cpicker) -{ - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - uint16_t angle; - switch(ext->color_mode) { - default: - case LV_CPICKER_COLOR_MODE_HUE: - angle = ext->hsv.h; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - angle = (ext->hsv.s * 360) / 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - angle = (ext->hsv.v * 360) / 100 ; - break; - } - return angle; -} - -#endif /* LV_USE_CPICKER != 0 */ diff --git a/src/lv_widgets/lv_cpicker.h b/src/lv_widgets/lv_cpicker.h deleted file mode 100644 index 2aef0d732..000000000 --- a/src/lv_widgets/lv_cpicker.h +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @file lv_cpicker.h - * - */ - -#ifndef LV_CPICKER_H -#define LV_CPICKER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_CPICKER != 0 - -#include "../lv_core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -enum { - LV_CPICKER_TYPE_RECT, - LV_CPICKER_TYPE_DISC, -}; -typedef uint8_t lv_cpicker_type_t; - -enum { - LV_CPICKER_COLOR_MODE_HUE, - LV_CPICKER_COLOR_MODE_SATURATION, - LV_CPICKER_COLOR_MODE_VALUE -}; -typedef uint8_t lv_cpicker_color_mode_t; - - - -/*Data of colorpicker*/ -typedef struct { - lv_color_hsv_t hsv; - struct { - lv_style_list_t style_list; - lv_point_t pos; - uint8_t colored : 1; - - } knob; - uint32_t last_click_time; - uint32_t last_change_time; - lv_point_t last_press_point; - lv_cpicker_color_mode_t color_mode : 2; - uint8_t color_mode_fixed : 1; - lv_cpicker_type_t type : 1; -} lv_cpicker_ext_t; - -/*Parts*/ -enum { - LV_CPICKER_PART_MAIN = LV_OBJ_PART_MAIN, - LV_CPICKER_PART_KNOB = _LV_OBJ_PART_VIRTUAL_LAST, - _LV_CPICKER_PART_VIRTUAL_LAST, - _LV_CPICKER_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST, -}; - - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a colorpicker objects - * @param par pointer to an object, it will be the parent of the new colorpicker - * @param copy pointer to a colorpicker object, if not NULL then the new object will be copied from it - * @return pointer to the created colorpicker - */ -lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new type for a colorpicker - * @param cpicker pointer to a colorpicker object - * @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum) - */ -void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type); - -/** - * Set the current hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param hue current selected hue [0..360] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue); - -/** - * Set the current saturation of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param saturation current selected saturation [0..100] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation); - -/** - * Set the current value of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param val current selected value [0..100] - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val); - -/** - * Set the current hsv of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param hsv current selected hsv - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv); - -/** - * Set the current color of a colorpicker. - * @param cpicker pointer to colorpicker object - * @param color current selected color - * @return true if changed, otherwise false - */ -bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color); - -/** - * Set the current color mode. - * @param cpicker pointer to colorpicker object - * @param mode color mode (hue/sat/val) - */ -void lv_cpicker_set_color_mode(lv_obj_t * cpicker, lv_cpicker_color_mode_t mode); - -/** - * Set if the color mode is changed on long press on center - * @param cpicker pointer to colorpicker object - * @param fixed color mode cannot be changed on long press - */ -void lv_cpicker_set_color_mode_fixed(lv_obj_t * cpicker, bool fixed); - -/** - * Make the knob to be colored to the current color - * @param cpicker pointer to colorpicker object - * @param en true: color the knob; false: not color the knob - */ -void lv_cpicker_set_knob_colored(lv_obj_t * cpicker, bool en); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the current color mode. - * @param cpicker pointer to colorpicker object - * @return color mode (hue/sat/val) - */ -lv_cpicker_color_mode_t lv_cpicker_get_color_mode(lv_obj_t * cpicker); - -/** - * Get if the color mode is changed on long press on center - * @param cpicker pointer to colorpicker object - * @return mode cannot be changed on long press - */ -bool lv_cpicker_get_color_mode_fixed(lv_obj_t * cpicker); - -/** - * Get the current hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected hue - */ -uint16_t lv_cpicker_get_hue(lv_obj_t * cpicker); - -/** - * Get the current saturation of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected saturation - */ -uint8_t lv_cpicker_get_saturation(lv_obj_t * cpicker); - -/** - * Get the current hue of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected value - */ -uint8_t lv_cpicker_get_value(lv_obj_t * cpicker); - -/** - * Get the current selected hsv of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected hsv - */ -lv_color_hsv_t lv_cpicker_get_hsv(lv_obj_t * cpicker); - -/** - * Get the current selected color of a colorpicker. - * @param cpicker pointer to colorpicker object - * @return current selected color - */ -lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker); - -/** - * Whether the knob is colored to the current color or not - * @param cpicker pointer to color picker object - * @return true: color the knob; false: not color the knob - */ -bool lv_cpicker_get_knob_colored(lv_obj_t * cpicker); - -/*===================== - * Other functions - *====================*/ - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_CPICKER*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_CPICKER_H*/ diff --git a/src/lv_widgets/lv_keyboard.c b/src/lv_widgets/lv_keyboard.c deleted file mode 100644 index 9138b171e..000000000 --- a/src/lv_widgets/lv_keyboard.c +++ /dev/null @@ -1,479 +0,0 @@ - -/** - * @file lv_kb.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_keyboard.h" -#if LV_USE_KEYBOARD != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" -#include "lv_textarea.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_keyboard" - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_keyboard_signal(lv_obj_t * kb, lv_signal_t sign, void * param); -static void lv_keyboard_update_map(lv_obj_t * kb); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -/* clang-format off */ -static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n", - "ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n", - "_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n", - LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" - }; - -static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 -}; - -static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n", - "abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n", - "_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n", - LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" - }; - -static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 -}; - -static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n", - "abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n", - "\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n", - LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" - }; - -static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 -}; - -static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_CLOSE, "\n", - "4", "5", "6", LV_SYMBOL_OK, "\n", - "7", "8", "9", LV_SYMBOL_BACKSPACE, "\n", - "+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, "" - }; - -static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = { - 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, - 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, - 1, 1, 1, 2, - 1, 1, 1, 1, 1 -}; -/* clang-format on */ - -static const char * * kb_map[4] = { - (const char * *)default_kb_map_lc, - (const char * *)default_kb_map_uc, - (const char * *)default_kb_map_spec, - (const char * *)default_kb_map_num -}; -static const lv_btnmatrix_ctrl_t * kb_ctrl[4] = { - default_kb_ctrl_lc_map, - default_kb_ctrl_uc_map, - default_kb_ctrl_spec_map, - default_kb_ctrl_num_map -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a keyboard objects - * @param par pointer to an object, it will be the parent of the new keyboard - * @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it - * @return pointer to the created keyboard - */ -lv_obj_t * lv_keyboard_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("keyboard create started"); - - /*Create the ancestor of keyboard*/ - lv_obj_t * kb = lv_btnmatrix_create(par, copy); - LV_ASSERT_MEM(kb); - if(kb == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(kb); - - /*Allocate the keyboard type specific extended data*/ - lv_keyboard_ext_t * ext = lv_obj_allocate_ext_attr(kb, sizeof(lv_keyboard_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(kb); - return NULL; - } - - /*Initialize the allocated 'ext' */ - ext->ta = NULL; - ext->mode = LV_KEYBOARD_MODE_TEXT_LOWER; - ext->cursor_mng = 0; - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(kb, lv_keyboard_signal); - - /*Init the new keyboard keyboard*/ - if(copy == NULL) { - /* Set a size which fits into the parent. - * Don't use `par` directly because if the window is created on a page it is moved to the - * scrollable so the parent has changed */ - lv_obj_set_size(kb, lv_obj_get_width_fit(lv_obj_get_parent(kb)), - lv_obj_get_height_fit(lv_obj_get_parent(kb)) / 2); - lv_obj_align(kb, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - lv_obj_set_event_cb(kb, lv_keyboard_def_event_cb); - lv_obj_set_base_dir(kb, LV_BIDI_DIR_LTR); - lv_obj_add_protect(kb, LV_PROTECT_CLICK_FOCUS); - - lv_btnmatrix_set_map(kb, kb_map[ext->mode]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]); - - lv_theme_apply(kb, LV_THEME_KEYBOARD); - } - /*Copy an existing keyboard*/ - else { - lv_keyboard_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->ta = copy_ext->ta; - ext->mode = copy_ext->mode; - ext->cursor_mng = copy_ext->cursor_mng; - - lv_btnmatrix_set_map(kb, kb_map[ext->mode]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]); - - /*Refresh the style with new signal function*/ - // lv_obj_refresh_style(new_kb); - } - - LV_LOG_INFO("keyboard created"); - - return kb; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @param ta pointer to a Text Area object to write there - */ -void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - if(ta) LV_ASSERT_OBJ(ta, "lv_textarea"); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - - /*Hide the cursor of the old Text area if cursor management is enabled*/ - if(ext->ta && ext->cursor_mng) { - lv_textarea_set_cursor_hidden(ext->ta, true); - } - - ext->ta = ta; - - /*Show the cursor of the new Text area if cursor management is enabled*/ - if(ext->ta && ext->cursor_mng) { - lv_textarea_set_cursor_hidden(ext->ta, false); - } -} - -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @param mode the mode from 'lv_keyboard_mode_t' - */ -void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - if(ext->mode == mode) return; - - ext->mode = mode; - lv_btnmatrix_set_map(kb, kb_map[mode]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[mode]); -} - -/** - * Automatically hide or show the cursor of Text Area - * @param kb pointer to a Keyboard object - * @param en true: show cursor on the current text area, false: hide cursor - */ -void lv_keyboard_set_cursor_manage(lv_obj_t * kb, bool en) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - if(ext->cursor_mng == en) return; - - ext->cursor_mng = en == false ? 0 : 1; - - if(ext->ta) { - - if(ext->cursor_mng) { - lv_textarea_set_cursor_hidden(ext->ta, false); - } - else { - lv_textarea_set_cursor_hidden(ext->ta, true); - } - } -} - -/** - * Set a new map for the keyboard - * @param kb pointer to a Keyboard object - * @param mode keyboard map to alter 'lv_keyboard_mode_t' - * @param map pointer to a string array to describe the map. - * See 'lv_btnmatrix_set_map()' for more info. - */ -void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[]) -{ - kb_map[mode] = map; - lv_keyboard_update_map(kb); -} - -/** - * Set the button control map (hidden, disabled etc.) for the keyboard. The - * control map array will be copied and so may be deallocated after this - * function returns. - * @param kb pointer to a keyboard object - * @param mode keyboard ctrl map to alter 'lv_keyboard_mode_t' - * @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes. - * See: `lv_btnmatrix_set_ctrl_map` for more details. - */ -void lv_keyboard_set_ctrl_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const lv_btnmatrix_ctrl_t ctrl_map[]) -{ - kb_ctrl[mode] = ctrl_map; - lv_keyboard_update_map(kb); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @return pointer to the assigned Text Area object - */ -lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - return ext->ta; -} - -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @return the current mode from 'lv_keyboard_mode_t' - */ -lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - return ext->mode; -} - -/** - * Get the current cursor manage mode. - * @param kb pointer to a Keyboard object - * @return true: show cursor on the current text area, false: hide cursor - */ -bool lv_keyboard_get_cursor_manage(const lv_obj_t * kb) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - return ext->cursor_mng == 0 ? false : true; -} - -/*===================== - * Other functions - *====================*/ - -/** - * Default keyboard event to add characters to the Text area and change the map. - * If a custom `event_cb` is added to the keyboard this function be called from it to handle the - * button clicks - * @param kb pointer to a keyboard - * @param event the triggering event - */ -void lv_keyboard_def_event_cb(lv_obj_t * kb, lv_event_t event) -{ - LV_ASSERT_OBJ(kb, LV_OBJX_NAME); - - if(event != LV_EVENT_VALUE_CHANGED) return; - - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - uint16_t btn_id = lv_btnmatrix_get_active_btn(kb); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return; - if(lv_btnmatrix_get_btn_ctrl(kb, btn_id, LV_BTNMATRIX_CTRL_HIDDEN | LV_BTNMATRIX_CTRL_DISABLED)) return; - if(lv_btnmatrix_get_btn_ctrl(kb, btn_id, LV_BTNMATRIX_CTRL_NO_REPEAT) && event == LV_EVENT_LONG_PRESSED_REPEAT) return; - - const char * txt = lv_btnmatrix_get_active_btn_text(kb); - if(txt == NULL) return; - - /*Do the corresponding action according to the text of the button*/ - if(strcmp(txt, "abc") == 0) { - ext->mode = LV_KEYBOARD_MODE_TEXT_LOWER; - lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_TEXT_LOWER]); - return; - } - else if(strcmp(txt, "ABC") == 0) { - ext->mode = LV_KEYBOARD_MODE_TEXT_UPPER; - lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_TEXT_UPPER]); - return; - } - else if(strcmp(txt, "1#") == 0) { - ext->mode = LV_KEYBOARD_MODE_SPECIAL; - lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_SPECIAL]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_SPECIAL]); - return; - } - else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0) { - if(kb->event_cb != lv_keyboard_def_event_cb) { - lv_res_t res = lv_event_send(kb, LV_EVENT_CANCEL, NULL); - if(res != LV_RES_OK) return; - } - else { - lv_keyboard_set_textarea(kb, NULL); /*De-assign the text area to hide it cursor if needed*/ - lv_obj_del(kb); - return; - } - return; - } - else if(strcmp(txt, LV_SYMBOL_OK) == 0) { - if(kb->event_cb != lv_keyboard_def_event_cb) { - lv_res_t res = lv_event_send(kb, LV_EVENT_APPLY, NULL); - if(res != LV_RES_OK) return; - } - else { - lv_keyboard_set_textarea(kb, NULL); /*De-assign the text area to hide it cursor if needed*/ - } - return; - } - - /*Add the characters to the text area if set*/ - if(ext->ta == NULL) return; - - if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) - lv_textarea_add_char(ext->ta, '\n'); - else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) - lv_textarea_cursor_left(ext->ta); - else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) - lv_textarea_cursor_right(ext->ta); - else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) - lv_textarea_del_char(ext->ta); - else if(strcmp(txt, "+/-") == 0) { - uint16_t cur = lv_textarea_get_cursor_pos(ext->ta); - const char * ta_txt = lv_textarea_get_text(ext->ta); - if(ta_txt[0] == '-') { - lv_textarea_set_cursor_pos(ext->ta, 1); - lv_textarea_del_char(ext->ta); - lv_textarea_add_char(ext->ta, '+'); - lv_textarea_set_cursor_pos(ext->ta, cur); - } - else if(ta_txt[0] == '+') { - lv_textarea_set_cursor_pos(ext->ta, 1); - lv_textarea_del_char(ext->ta); - lv_textarea_add_char(ext->ta, '-'); - lv_textarea_set_cursor_pos(ext->ta, cur); - } - else { - lv_textarea_set_cursor_pos(ext->ta, 0); - lv_textarea_add_char(ext->ta, '-'); - lv_textarea_set_cursor_pos(ext->ta, cur + 1); - } - } - else { - lv_textarea_add_text(ext->ta, txt); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the keyboard - * @param kb pointer to a keyboard object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_keyboard_signal(lv_obj_t * kb, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(kb, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_CLEANUP) { - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } - else if(sign == LV_SIGNAL_FOCUS) { - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - /*Show the cursor of the Text area if cursor management is enabled*/ - if(ext->ta && ext->cursor_mng) { - lv_textarea_set_cursor_hidden(ext->ta, false); - } - } - else if(sign == LV_SIGNAL_DEFOCUS) { - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - /*Show the cursor of the Text area if cursor management is enabled*/ - if(ext->ta && ext->cursor_mng) { - lv_textarea_set_cursor_hidden(ext->ta, true); - } - } - - return res; -} - -/** - * Update the key map for the current mode - * @param kb pointer to a keyboard object - */ -static void lv_keyboard_update_map(lv_obj_t * kb) -{ - lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb); - lv_btnmatrix_set_map(kb, kb_map[ext->mode]); - lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]); -} - -#endif diff --git a/src/lv_widgets/lv_keyboard.h b/src/lv_widgets/lv_keyboard.h deleted file mode 100644 index 3edd344b0..000000000 --- a/src/lv_widgets/lv_keyboard.h +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @file lv_keyboard.h - * - */ - -#ifndef LV_KEYBOARD_H -#define LV_KEYBOARD_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_KEYBOARD != 0 - -/*Testing of dependencies*/ -#if LV_USE_BTNMATRIX == 0 -#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " -#endif - -#if LV_USE_TEXTAREA == 0 -#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "lv_btnmatrix.h" - -/********************* - * DEFINES - *********************/ -#define LV_KEYBOARD_CTRL_BTN_FLAGS (LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CLICK_TRIG) - -/********************** - * TYPEDEFS - **********************/ - -/** Current keyboard mode. */ -enum { - LV_KEYBOARD_MODE_TEXT_LOWER, - LV_KEYBOARD_MODE_TEXT_UPPER, - LV_KEYBOARD_MODE_SPECIAL, - LV_KEYBOARD_MODE_NUM, -}; -typedef uint8_t lv_keyboard_mode_t; - -/*Data of keyboard*/ -typedef struct { - lv_btnmatrix_ext_t btnm; /*Ext. of ancestor*/ - /*New data for this type */ - lv_obj_t * ta; /*Pointer to the assigned text area*/ - lv_keyboard_mode_t mode; /*Key map type*/ - uint8_t cursor_mng : 1; /*1: automatically show/hide cursor when a text area is assigned or left*/ -} lv_keyboard_ext_t; - -enum { - LV_KEYBOARD_PART_BG, - LV_KEYBOARD_PART_BTN, -}; -typedef uint8_t lv_keyboard_style_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a keyboard objects - * @param par pointer to an object, it will be the parent of the new keyboard - * @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it - * @return pointer to the created keyboard - */ -lv_obj_t * lv_keyboard_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @param ta pointer to a Text Area object to write there - */ -void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta); - -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @param mode the mode from 'lv_keyboard_mode_t' - */ -void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode); - -/** - * Automatically hide or show the cursor of the current Text Area - * @param kb pointer to a Keyboard object - * @param en true: show cursor on the current text area, false: hide cursor - */ -void lv_keyboard_set_cursor_manage(lv_obj_t * kb, bool en); - -/** - * Set a new map for the keyboard - * @param kb pointer to a Keyboard object - * @param mode keyboard map to alter 'lv_keyboard_mode_t' - * @param map pointer to a string array to describe the map. - * See 'lv_btnmatrix_set_map()' for more info. - */ -void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[]); - -/** - * Set the button control map (hidden, disabled etc.) for the keyboard. The - * control map array will be copied and so may be deallocated after this - * function returns. - * @param kb pointer to a keyboard object - * @param mode keyboard ctrl map to alter 'lv_keyboard_mode_t' - * @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes. - * See: `lv_btnmatrix_set_ctrl_map` for more details. - */ -void lv_keyboard_set_ctrl_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const lv_btnmatrix_ctrl_t ctrl_map[]); - -/*===================== - * Getter functions - *====================*/ - -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @return pointer to the assigned Text Area object - */ -lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb); - -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @return the current mode from 'lv_keyboard_mode_t' - */ -lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb); - -/** - * Get the current cursor manage mode. - * @param kb pointer to a Keyboard object - * @return true: show cursor on the current text area, false: hide cursor - */ -bool lv_keyboard_get_cursor_manage(const lv_obj_t * kb); - -/** - * Get the current map of a keyboard - * @param kb pointer to a keyboard object - * @return the current map - */ -static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) -{ - return lv_btnmatrix_get_map_array(kb); -} - -/*===================== - * Other functions - *====================*/ - -/** - * Default keyboard event to add characters to the Text area and change the map. - * If a custom `event_cb` is added to the keyboard this function be called from it to handle the - * button clicks - * @param kb pointer to a keyboard - * @param event the triggering event - */ -void lv_keyboard_def_event_cb(lv_obj_t * kb, lv_event_t event); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_KEYBOARD*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_KEYBOARD_H*/ diff --git a/src/lv_widgets/lv_label.c b/src/lv_widgets/lv_label.c index 8dd5d84e8..bef0ec357 100644 --- a/src/lv_widgets/lv_label.c +++ b/src/lv_widgets/lv_label.c @@ -70,16 +70,15 @@ static lv_signal_cb_t ancestor_signal; /** * Create a label objects - * @param par pointer to an object, it will be the parent of the new label - * @param copy pointer to a label object, if not NULL then the new object will be copied from it + * @param parent pointer to an object, it will be the parent of the new label * @return pointer to the created button */ -lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) +lv_obj_t * lv_label_create(lv_obj_t * parent) { LV_LOG_TRACE("label create started"); /*Create a basic object*/ - lv_obj_t * new_label = lv_obj_create(par, copy); + lv_obj_t * new_label = lv_obj_create(parent); LV_ASSERT_MEM(new_label); if(new_label == NULL) return NULL; @@ -120,49 +119,14 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->dot.tmp_ptr = NULL; ext->dot_tmp_alloc = 0; - lv_obj_set_design_cb(new_label, lv_label_design); lv_obj_set_signal_cb(new_label, lv_label_signal); /*Init the new label*/ - if(copy == NULL) { - lv_theme_apply(new_label, LV_THEME_LABEL); - lv_obj_clear_flag(new_label, LV_OBJ_FLAG_CLICKABLE); - lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND); - lv_label_set_text(new_label, "Text"); - } - /*Copy 'copy' if not NULL*/ - else { - lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy)); - lv_label_set_recolor(new_label, lv_label_get_recolor(copy)); - lv_label_set_align(new_label, lv_label_get_align(copy)); - if(copy_ext->static_txt == 0) - lv_label_set_text(new_label, lv_label_get_text(copy)); - else - lv_label_set_text_static(new_label, lv_label_get_text(copy)); - - /*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/ - if(copy_ext->long_mode == LV_LABEL_LONG_DOT) { - ext->text = lv_mem_realloc(ext->text, _lv_mem_get_size(copy_ext->text)); - LV_ASSERT_MEM(ext->text); - if(ext->text == NULL) return NULL; - _lv_memcpy(ext->text, copy_ext->text, _lv_mem_get_size(copy_ext->text)); - } - - if(copy_ext->dot_tmp_alloc && copy_ext->dot.tmp_ptr) { - uint32_t len = (uint32_t)strlen(copy_ext->dot.tmp_ptr); - lv_label_set_dot_tmp(new_label, ext->dot.tmp_ptr, len); - } - else { - _lv_memcpy(ext->dot.tmp, copy_ext->dot.tmp, sizeof(ext->dot.tmp)); - } - ext->dot_tmp_alloc = copy_ext->dot_tmp_alloc; - ext->dot_end = copy_ext->dot_end; - - /*Refresh the style with new signal function*/ - _lv_obj_refresh_style(new_label, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } + lv_theme_apply(new_label, LV_THEME_LABEL); + lv_obj_clear_flag(new_label, LV_OBJ_FLAG_CLICKABLE); + lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND); + lv_label_set_text(new_label, "Text"); LV_LOG_INFO("label created"); diff --git a/src/lv_widgets/lv_label.h b/src/lv_widgets/lv_label.h index 1a32ef74f..99e517e31 100644 --- a/src/lv_widgets/lv_label.h +++ b/src/lv_widgets/lv_label.h @@ -111,11 +111,10 @@ typedef uint8_t lv_label_part_t; /** * Create a label objects - * @param par pointer to an object, it will be the parent of the new label - * @param copy pointer to a button object, if not NULL then the new object will be copied from it + * @param parent pointer to an object, it will be the parent of the new label * @return pointer to the created button */ -lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy); +lv_obj_t * lv_label_create(lv_obj_t * parent); /*===================== * Setter functions diff --git a/src/lv_widgets/lv_led.c b/src/lv_widgets/lv_led.c deleted file mode 100644 index dea778d7d..000000000 --- a/src/lv_widgets/lv_led.c +++ /dev/null @@ -1,251 +0,0 @@ -/** - * @file lv_led.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_led.h" -#if LV_USE_LED != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_draw/lv_draw.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_led" - -#define LV_LED_WIDTH_DEF (LV_DPI / 3) -#define LV_LED_HEIGHT_DEF (LV_DPI / 3) - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a led objects - * @param par pointer to an object, it will be the parent of the new led - * @param copy pointer to a led object, if not NULL then the new object will be copied from it - * @return pointer to the created led - */ -lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("led create started"); - - /*Create the ancestor basic object*/ - lv_obj_t * led = lv_obj_create(par, copy); - LV_ASSERT_MEM(led); - if(led == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(led); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(led); - - /*Allocate the object type specific extended data*/ - lv_led_ext_t * ext = lv_obj_allocate_ext_attr(led, sizeof(lv_led_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(led); - return NULL; - } - - ext->bright = LV_LED_BRIGHT_MAX; - - lv_obj_set_signal_cb(led, lv_led_signal); - lv_obj_set_design_cb(led, lv_led_design); - - /*Init the new led object*/ - if(copy == NULL) { - lv_obj_set_size(led, LV_LED_WIDTH_DEF, LV_LED_HEIGHT_DEF); - - lv_theme_apply(led, LV_THEME_LED); - } - /*Copy an existing object*/ - else { - lv_led_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->bright = copy_ext->bright; - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(led, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("led created"); - - return led; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the brightness of a LED object - * @param led pointer to a LED object - * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) - */ -void lv_led_set_bright(lv_obj_t * led, uint8_t bright) -{ - LV_ASSERT_OBJ(led, LV_OBJX_NAME); - - /*Set the brightness*/ - lv_led_ext_t * ext = lv_obj_get_ext_attr(led); - if(ext->bright == bright) return; - - if(bright <= LV_LED_BRIGHT_MIN) bright = LV_LED_BRIGHT_MIN; - if(bright >= LV_LED_BRIGHT_MAX) bright = LV_LED_BRIGHT_MAX; - - ext->bright = bright; - - /*Invalidate the object there fore it will be redrawn*/ - lv_obj_invalidate(led); -} - -/** - * Light on a LED - * @param led pointer to a LED object - */ -void lv_led_on(lv_obj_t * led) -{ - LV_ASSERT_OBJ(led, LV_OBJX_NAME); - - lv_led_set_bright(led, LV_LED_BRIGHT_MAX); -} - -/** - * Light off a LED - * @param led pointer to a LED object - */ -void lv_led_off(lv_obj_t * led) -{ - LV_ASSERT_OBJ(led, LV_OBJX_NAME); - - lv_led_set_bright(led, LV_LED_BRIGHT_MIN); -} - -/** - * Toggle the state of a LED - * @param led pointer to a LED object - */ -void lv_led_toggle(lv_obj_t * led) -{ - LV_ASSERT_OBJ(led, LV_OBJX_NAME); - - uint8_t bright = lv_led_get_bright(led); - if(bright > (LV_LED_BRIGHT_MIN + LV_LED_BRIGHT_MAX) >> 1) - lv_led_off(led); - else - lv_led_on(led); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the brightness of a LEd object - * @param led pointer to LED object - * @return bright 0 (max. dark) ... 255 (max. light) - */ -uint8_t lv_led_get_bright(const lv_obj_t * led) -{ - LV_ASSERT_OBJ(led, LV_OBJX_NAME); - - lv_led_ext_t * ext = lv_obj_get_ext_attr(led); - return ext->bright; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Handle the drawing related tasks of the leds - * @param led pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - if(mode == LV_DESIGN_COVER_CHK) { - /*Return false if the object is not covers the clip_area area*/ - return ancestor_design(led, clip_area, mode); - } - else if(mode == LV_DESIGN_DRAW_MAIN) { - /*Make darker colors in a temporary style according to the brightness*/ - lv_led_ext_t * ext = lv_obj_get_ext_attr(led); - - lv_draw_rect_dsc_t rect_dsc; - lv_draw_rect_dsc_init(&rect_dsc); - lv_obj_init_draw_rect_dsc(led, LV_LED_PART_MAIN, &rect_dsc); - - /*Mix. the color with black proportionally with brightness*/ - rect_dsc.bg_color = lv_color_mix(rect_dsc.bg_color, LV_COLOR_BLACK, ext->bright); - rect_dsc.bg_grad_color = lv_color_mix(rect_dsc.bg_grad_color, LV_COLOR_BLACK, ext->bright); - rect_dsc.border_color = lv_color_mix(rect_dsc.border_color, LV_COLOR_BLACK, ext->bright); - rect_dsc.shadow_color = lv_color_mix(rect_dsc.shadow_color, LV_COLOR_BLACK, ext->bright); - - /*Set the current shadow width according to brightness proportionally between LV_LED_BRIGHT_OFF - * and LV_LED_BRIGHT_ON*/ - rect_dsc.shadow_width = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_width) / - (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); - rect_dsc.shadow_spread = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) / - (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); - - lv_draw_rect(&led->coords, clip_area, &rect_dsc); - } - return LV_DESIGN_RES_OK; -} - -/** - * Signal function of the led - * @param led pointer to a led object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(led, sign, param); - if(res != LV_RES_OK) return res; - - if(sign == LV_SIGNAL_GET_TYPE) { - lv_obj_type_t * buf = param; - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ - if(buf->type[i] == NULL) break; - } - buf->type[i] = "lv_led"; - } - - return res; -} -#endif diff --git a/src/lv_widgets/lv_led.h b/src/lv_widgets/lv_led.h deleted file mode 100644 index 7ab33cef1..000000000 --- a/src/lv_widgets/lv_led.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file lv_led.h - * - */ - -#ifndef LV_LED_H -#define LV_LED_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_LED != 0 - -#include "../lv_core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/*Data of led*/ -typedef struct { - /*No inherited ext.*/ - /*New data for this type */ - uint8_t bright; /*Current brightness of the LED (0..255)*/ -} lv_led_ext_t; - -/*Parts of LED*/ -enum { - LV_LED_PART_MAIN = LV_OBJ_PART_MAIN, -}; -typedef uint8_t lv_led_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a led objects - * @param par pointer to an object, it will be the parent of the new led - * @param copy pointer to a led object, if not NULL then the new object will be copied from it - * @return pointer to the created led - */ -lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy); - -/** - * Set the brightness of a LED object - * @param led pointer to a LED object - * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) - */ -void lv_led_set_bright(lv_obj_t * led, uint8_t bright); - -/** - * Light on a LED - * @param led pointer to a LED object - */ -void lv_led_on(lv_obj_t * led); - -/** - * Light off a LED - * @param led pointer to a LED object - */ -void lv_led_off(lv_obj_t * led); - -/** - * Toggle the state of a LED - * @param led pointer to a LED object - */ -void lv_led_toggle(lv_obj_t * led); - -/** - * Get the brightness of a LEd object - * @param led pointer to LED object - * @return bright 0 (max. dark) ... 255 (max. light) - */ -uint8_t lv_led_get_bright(const lv_obj_t * led); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_LED*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_LED_H*/ diff --git a/src/lv_widgets/lv_linemeter.c b/src/lv_widgets/lv_linemeter.c deleted file mode 100644 index eac998bb9..000000000 --- a/src/lv_widgets/lv_linemeter.c +++ /dev/null @@ -1,634 +0,0 @@ -/** - * @file lv_linemeter.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_linemeter.h" -#if LV_USE_LINEMETER != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_draw/lv_draw.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_core/lv_group.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_linemeter" - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_design_res_t lv_linemeter_design(lv_obj_t * lmeter, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_linemeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a line meter objects - * @param par pointer to an object, it will be the parent of the new line meter - * @param copy pointer to a line meter object, if not NULL then the new object will be copied from - * it - * @return pointer to the created line meter - */ -lv_obj_t * lv_linemeter_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("line meter create started"); - - /*Create the ancestor of line meter*/ - lv_obj_t * linemeter = lv_obj_create(par, copy); - LV_ASSERT_MEM(linemeter); - if(linemeter == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(linemeter); - - /*Allocate the line meter type specific extended data*/ - lv_linemeter_ext_t * ext = lv_obj_allocate_ext_attr(linemeter, sizeof(lv_linemeter_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(linemeter); - return NULL; - } - - /*Initialize the allocated 'ext' */ - ext->min_value = 0; - ext->max_value = 100; - ext->cur_value = 0; - ext->line_cnt = 18; - ext->scale_angle = 240; - ext->angle_ofs = 0; - ext->mirrored = 0; - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(linemeter, lv_linemeter_signal); - lv_obj_set_design_cb(linemeter, lv_linemeter_design); - - /*Init the new line meter line meter*/ - if(copy == NULL) { - lv_obj_set_size(linemeter, 3 * LV_DPI / 2, 3 * LV_DPI / 2); - lv_theme_apply(linemeter, LV_THEME_LINEMETER); - } - /*Copy an existing line meter*/ - else { - lv_linemeter_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->scale_angle = copy_ext->scale_angle; - ext->line_cnt = copy_ext->line_cnt; - ext->min_value = copy_ext->min_value; - ext->max_value = copy_ext->max_value; - ext->cur_value = copy_ext->cur_value; - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(linemeter, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("line meter created"); - - return linemeter; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new value on the line meter - * @param lmeter pointer to a line meter object - * @param value new value - */ -void lv_linemeter_set_value(lv_obj_t * lmeter, int32_t value) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - if(ext->cur_value == value) return; - - int32_t old_value = ext->cur_value; - - ext->cur_value = value > ext->max_value ? ext->max_value : value; - ext->cur_value = ext->cur_value < ext->min_value ? ext->min_value : ext->cur_value; - - int16_t level_old = - (int32_t)((int32_t)(old_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value); - int16_t level_new = - (int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value); - - if(level_new == level_old) { - return; - } - - lv_style_int_t left = lv_obj_get_style_pad_left(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t right = lv_obj_get_style_pad_right(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t top = lv_obj_get_style_pad_top(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(lmeter, LV_LINEMETER_PART_MAIN); - - lv_coord_t r_out = (lv_obj_get_width(lmeter) - left - right) / 2 ; - lv_coord_t r_in = r_out - lv_obj_get_style_scale_width(lmeter, LV_LINEMETER_PART_MAIN); - if(r_in < 1) r_in = 1; - - lv_coord_t x_ofs = lmeter->coords.x1 + r_out + left; - lv_coord_t y_ofs = lmeter->coords.y1 + r_out + top; - int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2; - - lv_style_int_t line_width = lv_obj_get_style_scale_end_line_width(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t end_line_width = lv_obj_get_style_scale_end_line_width(lmeter, LV_LINEMETER_PART_MAIN); - line_width = LV_MATH_MAX(line_width, end_line_width); - - int32_t angle_old = (level_old * ext->scale_angle) / (ext->line_cnt - 1); - - /*Use smaller clip area only around the visible line*/ - int32_t y_in_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - int32_t x_in_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - - - int32_t y_out_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - int32_t x_out_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - - - - int32_t angle_new = (level_new * ext->scale_angle) / (ext->line_cnt - 1); - - /*Use smaller clip area only around the visible line*/ - int32_t y_in_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - int32_t x_in_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - - - int32_t y_out_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - int32_t x_out_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - - lv_area_t a; - if(x_out_old < 0 && x_out_new < 0) { - a.x1 = lmeter->coords.x1 + left - line_width; - a.y1 = LV_MATH_MIN4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs - line_width; - a.x2 = LV_MATH_MAX(x_in_old, x_in_new) + x_ofs + line_width; - a.y2 = LV_MATH_MAX4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs + line_width; - } - else if(x_out_old > 0 && x_out_new > 0) { - a.x1 = LV_MATH_MIN(x_in_old, x_in_new) + x_ofs - line_width; - a.y1 = LV_MATH_MIN4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs - line_width; - a.x2 = lmeter->coords.x2 - right + line_width; - a.y2 = LV_MATH_MAX4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs + line_width; - } - else if(y_out_old < 0 && y_out_new < 0) { - a.x1 = LV_MATH_MIN4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs - line_width; - a.y1 = lmeter->coords.y1 + top - line_width; - a.x2 = LV_MATH_MAX4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs + line_width; - a.y2 = LV_MATH_MAX(y_in_old, y_in_new) + y_ofs + line_width; - } - else if(y_out_old > 0 && y_out_new > 0) { - a.x1 = LV_MATH_MIN4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs - line_width; - a.y1 = LV_MATH_MIN(y_in_old, y_in_new) + y_ofs - line_width; - a.x2 = LV_MATH_MAX4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs + line_width; - a.y2 = lmeter->coords.y2 - bottom + line_width; - } - else { - a.x1 = lmeter->coords.x1 + left - line_width; - a.y1 = lmeter->coords.y1 + top - line_width; - a.x2 = lmeter->coords.x2 - right + line_width; - a.y2 = lmeter->coords.y2 - bottom + line_width; - } - - lv_obj_invalidate_area(lmeter, &a); - -} - -/** - * Set minimum and the maximum values of a line meter - * @param lmeter pointer to he line meter object - * @param min minimum value - * @param max maximum value - */ -void lv_linemeter_set_range(lv_obj_t * lmeter, int32_t min, int32_t max) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - if(ext->min_value == min && ext->max_value == max) return; - - ext->max_value = max; - ext->min_value = min; - if(ext->cur_value > max) { - ext->cur_value = max; - lv_linemeter_set_value(lmeter, ext->cur_value); - } - if(ext->cur_value < min) { - ext->cur_value = min; - lv_linemeter_set_value(lmeter, ext->cur_value); - } - lv_obj_invalidate(lmeter); -} - -/** - * Set the scale settings of a line meter - * @param lmeter pointer to a line meter object - * @param angle angle of the scale (0..360) - * @param line_cnt number of lines - */ -void lv_linemeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint16_t line_cnt) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - if(ext->scale_angle == angle && ext->line_cnt == line_cnt) return; - - ext->scale_angle = angle; - ext->line_cnt = line_cnt; - - lv_obj_invalidate(lmeter); -} - -/** - * Set the set an offset for the line meter's angles to rotate it. - * @param lmeter pointer to a line meter object - * @param angle angle where the meter will be facing (with its center) - */ -void lv_linemeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle) -{ - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - if(ext->angle_ofs == angle) return; - - ext->angle_ofs = angle; - - lv_obj_invalidate(lmeter); -} - -/** - * Set the orientation of the meter growth, clockwise or counterclockwise (mirrored) - * @param lmeter pointer to a line meter object - * @param mirror mirror setting - */ -void lv_linemeter_set_mirror(lv_obj_t * lmeter, bool mirror) -{ - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - if(ext->mirrored == mirror) return; - - ext->mirrored = mirror; - - lv_obj_invalidate(lmeter); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the value of a line meter - * @param lmeter pointer to a line meter object - * @return the value of the line meter - */ -int32_t lv_linemeter_get_value(const lv_obj_t * lmeter) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - return ext->cur_value; -} - -/** - * Get the minimum value of a line meter - * @param lmeter pointer to a line meter object - * @return the minimum value of the line meter - */ -int32_t lv_linemeter_get_min_value(const lv_obj_t * lmeter) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - return ext->min_value; -} - -/** - * Get the maximum value of a line meter - * @param lmeter pointer to a line meter object - * @return the maximum value of the line meter - */ -int32_t lv_linemeter_get_max_value(const lv_obj_t * lmeter) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - return ext->max_value; -} - -/** - * Get the scale number of a line meter - * @param lmeter pointer to a line meter object - * @return number of the scale units - */ -uint16_t lv_linemeter_get_line_count(const lv_obj_t * lmeter) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - return ext->line_cnt; -} - -/** - * Get the scale angle of a line meter - * @param lmeter pointer to a line meter object - * @return angle_ofs of the scale - */ -uint16_t lv_linemeter_get_scale_angle(const lv_obj_t * lmeter) -{ - LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME); - - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - return ext->scale_angle; -} - -/** - * Get the offset for the line meter. - * @param lmeter pointer to a line meter object - * @return angle offset (0..360) - */ -uint16_t lv_linemeter_get_angle_offset(lv_obj_t * lmeter) -{ - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - - return ext->angle_ofs; -} - -/** - * get the mirror setting for the line meter - * @param lmeter pointer to a line meter object - * @return mirror (true or false) - */ -bool lv_linemeter_get_mirror(lv_obj_t * lmeter) -{ - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - - return ext->mirrored; -} - -void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uint8_t part) -{ - lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); - - lv_style_int_t left = lv_obj_get_style_pad_left(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t right = lv_obj_get_style_pad_right(lmeter, LV_LINEMETER_PART_MAIN); - lv_style_int_t top = lv_obj_get_style_pad_top(lmeter, LV_LINEMETER_PART_MAIN); - - lv_coord_t r_out = (lv_obj_get_width(lmeter) - left - right) / 2 ; - lv_coord_t r_in = r_out - lv_obj_get_style_scale_width(lmeter, part); - if(r_in < 1) r_in = 1; - - lv_coord_t x_ofs = lmeter->coords.x1 + r_out + left; - lv_coord_t y_ofs = lmeter->coords.y1 + r_out + top; - int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2; - int16_t level = ext->mirrored ? - (int32_t)((int32_t)(ext->max_value - ext->cur_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value) : - (int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value); - uint8_t i; - - lv_color_t main_color = lv_obj_get_style_line_color(lmeter, part); - lv_color_t grad_color = lv_obj_get_style_scale_grad_color(lmeter, part); - lv_color_t end_color = lv_obj_get_style_scale_end_color(lmeter, part); - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(lmeter, part, &line_dsc); -#if LV_LINEMETER_PRECISE == 2 - line_dsc.raw_end = 1; -#endif - - lv_style_int_t end_line_width = lv_obj_get_style_scale_end_line_width(lmeter, part); - -#if LV_LINEMETER_PRECISE > 0 - lv_area_t mask_area; - mask_area.x1 = x_ofs - r_in; - mask_area.x2 = x_ofs + r_in - 1; - mask_area.y1 = y_ofs - r_in; - mask_area.y2 = y_ofs + r_in - 1; - - lv_draw_mask_radius_param_t mask_in_param; - lv_draw_mask_radius_init(&mask_in_param, &mask_area, LV_RADIUS_CIRCLE, true); - int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, 0); -#endif - - -#if LV_LINEMETER_PRECISE > 1 - mask_area.x1 = x_ofs - r_out; - mask_area.x2 = x_ofs + r_out - 1; - mask_area.y1 = y_ofs - r_out; - mask_area.y2 = y_ofs + r_out - 1; - lv_draw_mask_radius_param_t mask_out_param; - lv_draw_mask_radius_init(&mask_out_param, &mask_area, LV_RADIUS_CIRCLE, false); - int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0); - /*In calculation use a larger radius to avoid rounding errors */ - lv_coord_t r_out_extra = r_out + LV_DPI; -#else - lv_coord_t r_out_extra = r_out; -#endif - - for(i = 0; i < ext->line_cnt; i++) { - /* `* 256` for extra precision*/ - int32_t angle_upscale = (i * ext->scale_angle * 256) / (ext->line_cnt - 1); - int32_t angle_normal = angle_upscale >> 8; - - int32_t angle_low = (angle_upscale >> 8); - int32_t angle_high = angle_low + 1; - int32_t angle_rem = angle_upscale & 0xFF; - - /*Interpolate sine and cos*/ - int32_t sin_low = _lv_trigo_sin(angle_low + angle_ofs); - int32_t sin_high = _lv_trigo_sin(angle_high + angle_ofs); - int32_t sin_mid = (sin_low * (256 - angle_rem) + sin_high * angle_rem) >> 8; - - int32_t cos_low = _lv_trigo_sin(angle_low + 90 + angle_ofs); - int32_t cos_high = _lv_trigo_sin(angle_high + 90 + angle_ofs); - int32_t cos_mid = (cos_low * (256 - angle_rem) + cos_high * angle_rem) >> 8; - - /*Use the interpolated values to get x and y coordinates*/ - int32_t y_out_extra = (int32_t)((int32_t)sin_mid * r_out_extra) >> (LV_TRIGO_SHIFT - 8); - int32_t x_out_extra = (int32_t)((int32_t)cos_mid * r_out_extra) >> (LV_TRIGO_SHIFT - 8); - - /*Rounding*/ - if(x_out_extra > 0) x_out_extra = (x_out_extra + 127) >> 8; - else x_out_extra = (x_out_extra - 127) >> 8; - - if(y_out_extra > 0) y_out_extra = (y_out_extra + 127) >> 8; - else y_out_extra = (y_out_extra - 127) >> 8; - - x_out_extra += x_ofs; - y_out_extra += y_ofs; - - /*With no extra precision use the coordinates on the inner radius*/ -#if LV_LINEMETER_PRECISE == 0 - /*Use the interpolated values to get x and y coordinates*/ - int32_t y_in_extra = (int32_t)((int32_t)sin_mid * r_in) >> (LV_TRIGO_SHIFT - 8); - int32_t x_in_extra = (int32_t)((int32_t)cos_mid * r_in) >> (LV_TRIGO_SHIFT - 8); - - /*Rounding*/ - if(x_in_extra > 0) x_in_extra = (x_in_extra + 127) >> 8; - else x_in_extra = (x_in_extra - 127) >> 8; - - if(y_in_extra > 0) y_in_extra = (y_in_extra + 127) >> 8; - else y_in_extra = (y_in_extra - 127) >> 8; - - x_in_extra += x_ofs; - y_in_extra += y_ofs; -#else - int32_t x_in_extra = x_ofs; - int32_t y_in_extra = y_ofs; -#endif - - /*Use smaller clip area only around the visible line*/ - int32_t y_in = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - int32_t x_in = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; - - x_in += x_ofs; - y_in += y_ofs; - - int32_t y_out = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - int32_t x_out = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT; - - x_out += x_ofs; - y_out += y_ofs; - - lv_area_t clip_sub; - clip_sub.x1 = LV_MATH_MIN(x_in, x_out) - line_dsc.width; - clip_sub.x2 = LV_MATH_MAX(x_in, x_out) + line_dsc.width; - clip_sub.y1 = LV_MATH_MIN(y_in, y_out) - line_dsc.width; - clip_sub.y2 = LV_MATH_MAX(y_in, y_out) + line_dsc.width; - - if(_lv_area_intersect(&clip_sub, &clip_sub, clip_area) == false) continue; - - lv_point_t p1; - lv_point_t p2; - - p2.x = x_in_extra; - p2.y = y_in_extra; - - p1.x = x_out_extra; - p1.y = y_out_extra; - - /* Set the color of the lines */ -<<<<<<< HEAD - uint16_t index = ext->mirrored ? ext->line_cnt - i : i; -======= ->>>>>>> master - if((!ext->mirrored && i >= level) || (ext->mirrored && i <= level)) { - line_dsc.color = end_color; - line_dsc.width = end_line_width; - } else { - line_dsc.color = lv_color_mix(grad_color, main_color, (255 * i) / ext->line_cnt); - } - - lv_draw_line(&p1, &p2, &clip_sub, &line_dsc); - } - -#if LV_LINEMETER_PRECISE > 0 - lv_draw_mask_remove_id(mask_in_id); -#endif - -#if LV_LINEMETER_PRECISE > 1 - lv_draw_mask_remove_id(mask_out_id); -#endif - - if(part == LV_LINEMETER_PART_MAIN && level + 1 < ext->line_cnt - 1) { - lv_style_int_t border_width = lv_obj_get_style_scale_border_width(lmeter, part); - lv_style_int_t end_border_width = lv_obj_get_style_scale_end_border_width(lmeter, part); - - if(border_width || end_border_width) { - int16_t end_angle = ((level + 1) * ext->scale_angle) / (ext->line_cnt - 1) + angle_ofs; - lv_draw_line_dsc_t arc_dsc; - lv_draw_line_dsc_init(&arc_dsc); - lv_obj_init_draw_line_dsc(lmeter, part, &arc_dsc); - - if(border_width) { - arc_dsc.width = border_width; - arc_dsc.color = main_color; - lv_draw_arc(x_ofs, y_ofs, r_out, angle_ofs, end_angle, clip_area, &arc_dsc); - } - - if(end_border_width) { - arc_dsc.width = end_border_width; - arc_dsc.color = end_color; - lv_draw_arc(x_ofs, y_ofs, r_out, end_angle, (angle_ofs + ext->scale_angle) % 360, clip_area, &arc_dsc); - } - } - } - - -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Handle the drawing related tasks of the line meters - * @param lmeter pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_linemeter_design(lv_obj_t * lmeter, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return LV_DESIGN_RES_NOT_COVER; - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - lv_draw_rect_dsc_t bg_dsc; - lv_draw_rect_dsc_init(&bg_dsc); - lv_obj_init_draw_rect_dsc(lmeter, LV_LINEMETER_PART_MAIN, &bg_dsc); - lv_draw_rect(&lmeter->coords, clip_area, &bg_dsc); - lv_linemeter_draw_scale(lmeter, clip_area, LV_LINEMETER_PART_MAIN); - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - } - - return LV_DESIGN_RES_OK; -} - -/** - * Signal function of the line meter - * @param lmeter pointer to a line meter object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_linemeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(lmeter, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_CLEANUP) { - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - lv_obj_refresh_ext_draw_pad(lmeter); - lv_obj_invalidate(lmeter); - } - - return res; -} -#endif diff --git a/src/lv_widgets/lv_linemeter.h b/src/lv_widgets/lv_linemeter.h deleted file mode 100644 index c33bffb27..000000000 --- a/src/lv_widgets/lv_linemeter.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file lv_linemeter.h - * - */ - -#ifndef LV_LINEMETER_H -#define LV_LINEMETER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_LINEMETER != 0 - -#include "../lv_core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -/*Data of line meter*/ -typedef struct { - /*No inherited ext.*/ /*Ext. of ancestor*/ - /*New data for this type */ - uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/ - uint16_t angle_ofs; - uint16_t line_cnt; /*Count of lines */ - int32_t cur_value; - int32_t min_value; - int32_t max_value; - uint8_t mirrored : 1; -} lv_linemeter_ext_t; - -/*Styles*/ -enum { - LV_LINEMETER_PART_MAIN, - _LV_LINEMETER_PART_VIRTUAL_LAST, - _LV_LINEMETER_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST, -}; -typedef uint8_t lv_linemeter_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a line meter objects - * @param par pointer to an object, it will be the parent of the new line meter - * @param copy pointer to a line meter object, if not NULL then the new object will be copied from - * it - * @return pointer to the created line meter - */ -lv_obj_t * lv_linemeter_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new value on the line meter - * @param lmeter pointer to a line meter object - * @param value new value - */ -void lv_linemeter_set_value(lv_obj_t * lmeter, int32_t value); - -/** - * Set minimum and the maximum values of a line meter - * @param lmeter pointer to he line meter object - * @param min minimum value - * @param max maximum value - */ -void lv_linemeter_set_range(lv_obj_t * lmeter, int32_t min, int32_t max); - -/** - * Set the scale settings of a line meter - * @param lmeter pointer to a line meter object - * @param angle angle of the scale (0..360) - * @param line_cnt number of lines - */ -void lv_linemeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint16_t line_cnt); - -/** - * Set the set an offset for the line meter's angles to rotate it. - * @param lmeter pointer to a line meter object - * @param angle angle offset (0..360), rotates clockwise - */ -void lv_linemeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle); - -/** - * Set the orientation of the meter growth, clockwise or counterclockwise (mirrored) - * @param lmeter pointer to a line meter object - * @param mirror mirror setting - */ -void lv_linemeter_set_mirror(lv_obj_t * lmeter, bool mirror); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the value of a line meter - * @param lmeter pointer to a line meter object - * @return the value of the line meter - */ -int32_t lv_linemeter_get_value(const lv_obj_t * lmeter); - -/** - * Get the minimum value of a line meter - * @param lmeter pointer to a line meter object - * @return the minimum value of the line meter - */ -int32_t lv_linemeter_get_min_value(const lv_obj_t * lmeter); - -/** - * Get the maximum value of a line meter - * @param lmeter pointer to a line meter object - * @return the maximum value of the line meter - */ -int32_t lv_linemeter_get_max_value(const lv_obj_t * lmeter); - -/** - * Get the scale number of a line meter - * @param lmeter pointer to a line meter object - * @return number of the scale units - */ -uint16_t lv_linemeter_get_line_count(const lv_obj_t * lmeter); - -/** - * Get the scale angle of a line meter - * @param lmeter pointer to a line meter object - * @return angle of the scale - */ -uint16_t lv_linemeter_get_scale_angle(const lv_obj_t * lmeter); - -/** - * Get the offset for the line meter. - * @param lmeter pointer to a line meter object - * @return angle offset (0..360) - */ -uint16_t lv_linemeter_get_angle_offset(lv_obj_t * lmeter); - - -void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uint8_t part); - -/** - * get the mirror setting for the line meter - * @param lmeter pointer to a line meter object - * @return mirror (true or false) - */ -bool lv_linemeter_get_mirror(lv_obj_t * lmeter); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_LINEMETER*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_LINEMETER_H*/ diff --git a/src/lv_widgets/lv_list.c b/src/lv_widgets/lv_list.c deleted file mode 100644 index fd8d5a41a..000000000 --- a/src/lv_widgets/lv_list.c +++ /dev/null @@ -1,923 +0,0 @@ -/** - * @file lv_list.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_list.h" -#if LV_USE_LIST != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_core/lv_group.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_anim.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_list" - -#define LV_LIST_LAYOUT_DEF LV_LAYOUT_COLUMN_MID - -#if LV_USE_ANIMATION == 0 - #undef LV_LIST_DEF_ANIM_TIME - #define LV_LIST_DEF_ANIM_TIME 0 -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param); -static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param); -static lv_style_list_t * lv_list_get_style(lv_obj_t * list, uint8_t part); -static bool lv_list_is_list_btn(lv_obj_t * list_btn); -static bool lv_list_is_list_img(lv_obj_t * list_btn); -static bool lv_list_is_list_label(lv_obj_t * list_btn); - -/********************** - * STATIC VARIABLES - **********************/ -#if LV_USE_IMG - static lv_signal_cb_t img_signal; -#endif -static lv_signal_cb_t label_signal; -static lv_signal_cb_t ancestor_page_signal; -static lv_signal_cb_t ancestor_btn_signal; - - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a list objects - * @param par pointer to an object, it will be the parent of the new list - * @param copy pointer to a list object, if not NULL then the new object will be copied from it - * @return pointer to the created list - */ -lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("list create started"); - - /*Create the ancestor basic object*/ - lv_obj_t * list = lv_page_create(par, copy); - LV_ASSERT_MEM(list); - if(list == NULL) return NULL; - - if(ancestor_page_signal == NULL) ancestor_page_signal = lv_obj_get_signal_cb(list); - - lv_list_ext_t * ext = lv_obj_allocate_ext_attr(list, sizeof(lv_list_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(list); - return NULL; - } - -#if LV_USE_GROUP - ext->last_sel_btn = NULL; -#endif - ext->act_sel_btn = NULL; - - lv_obj_set_signal_cb(list, lv_list_signal); - - /*Init the new list object*/ - if(copy == NULL) { - lv_page_set_anim_time(list, LV_LIST_DEF_ANIM_TIME); - lv_page_set_scrollable_fit2(list, LV_FIT_PARENT, LV_FIT_TIGHT); - lv_obj_set_size(list, 2 * LV_DPI, 3 * LV_DPI); - lv_page_set_scrl_layout(list, LV_LIST_LAYOUT_DEF); - lv_list_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_DRAG); - - lv_theme_apply(list, LV_THEME_LIST); - - } - else { - lv_obj_t * copy_btn = lv_list_get_next_btn(copy, NULL); - while(copy_btn) { - const void * img_src = NULL; -#if LV_USE_IMG - lv_obj_t * copy_img = lv_list_get_btn_img(copy_btn); - if(copy_img) img_src = lv_img_get_src(copy_img); -#endif - lv_list_add_btn(list, img_src, lv_list_get_btn_text(copy_btn)); - copy_btn = lv_list_get_next_btn(copy, copy_btn); - } - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(list, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("list created"); - - return list; -} - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param list pointer to an object - */ -void lv_list_clean(lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - lv_obj_t * scrl = lv_page_get_scrollable(list); - lv_obj_clean(scrl); -} - -/*====================== - * Add/remove functions - *=====================*/ -/** - * Add a list element to the list - * @param list pointer to list object - * @param img_fn file name of an image before the text (NULL if unused) - * @param txt text of the list element (NULL if unused) - * @return pointer to the new list element which can be customized (a button) - */ -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * txt) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - lv_obj_t * last_btn = lv_list_get_prev_btn(list, NULL); - - /*The coordinates may changed due to autofit so revert them at the end*/ - lv_coord_t pos_x_ori = lv_obj_get_x(list); - lv_coord_t pos_y_ori = lv_obj_get_y(list); - - lv_obj_t * scrl = lv_page_get_scrollable(list); - lv_obj_add_protect(scrl, LV_PROTECT_CHILD_CHG); - - /*Create a list element with the image an the text*/ - lv_obj_t * btn; - btn = lv_btn_create(list, NULL); - - lv_obj_add_protect(btn, LV_PROTECT_CHILD_CHG); - - /*Save the original signal function because it will be required in `lv_list_btn_signal`*/ - if(ancestor_btn_signal == NULL) ancestor_btn_signal = lv_obj_get_signal_cb(btn); - - /*Set the default styles*/ - lv_theme_apply(btn, LV_THEME_LIST_BTN); - - lv_page_glue_obj(list, btn, true); - lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID); - - lv_layout_t list_layout = lv_list_get_layout(list); - bool layout_ver = false; - if(list_layout == LV_LAYOUT_COLUMN_MID || list_layout == LV_LAYOUT_COLUMN_LEFT || - list_layout == LV_LAYOUT_COLUMN_RIGHT) { - layout_ver = true; - } - - if(layout_ver) { - lv_btn_set_fit2(btn, LV_FIT_PARENT, LV_FIT_TIGHT); - } - else { - lv_coord_t w = last_btn ? lv_obj_get_width(last_btn) : (LV_DPI * 3) / 2; - lv_btn_set_fit2(btn, LV_FIT_NONE, LV_FIT_TIGHT); - lv_obj_set_width(btn, w); - } - - - lv_obj_add_protect(btn, LV_PROTECT_PRESS_LOST); - lv_obj_set_signal_cb(btn, lv_list_btn_signal); - - -#if LV_USE_IMG != 0 - lv_obj_t * img = NULL; - if(img_src) { - img = lv_img_create(btn, NULL); - lv_img_set_src(img, img_src); - lv_obj_set_click(img, false); - if(img_signal == NULL) img_signal = lv_obj_get_signal_cb(img); - } -#endif - if(txt != NULL) { - lv_obj_t * label = lv_label_create(btn, NULL); - lv_label_set_text(label, txt); - lv_obj_set_click(label, false); - lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC); - if(lv_obj_get_base_dir(btn) == LV_BIDI_DIR_RTL) { - lv_coord_t pad = lv_obj_get_style_pad_left(btn, LV_BTN_PART_MAIN); - lv_obj_set_width(label, label->coords.x2 - btn->coords.x1 - pad); - } - else { - lv_coord_t pad = lv_obj_get_style_pad_right(btn, LV_BTN_PART_MAIN); - lv_obj_set_width(label, btn->coords.x2 - label->coords.x1 - pad); - } - if(label_signal == NULL) label_signal = lv_obj_get_signal_cb(label); - } - -#if LV_USE_GROUP - /* If this is the first item to be added to the list and the list is - * focused, select it */ - { - lv_group_t * g = lv_obj_get_group(list); - if(lv_list_get_next_btn(list, NULL) == btn && lv_group_get_focused(g) == list) { - lv_list_focus_btn(list, btn); - } - } -#endif - - lv_obj_clear_protect(scrl, LV_PROTECT_CHILD_CHG); - lv_obj_clear_protect(btn, LV_PROTECT_CHILD_CHG); - btn->signal_cb(btn, LV_SIGNAL_CHILD_CHG, NULL); - - lv_obj_set_pos(list, pos_x_ori, pos_y_ori); - - return btn; -} - -/** - * Remove the index of the button in the list - * @param list pointer to a list object - * @param index pointer to a the button's index in the list, index must be 0 <= index < - * lv_list_ext_t.size - * @return true: successfully deleted - */ -bool lv_list_remove(const lv_obj_t * list, uint16_t index) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - uint16_t count = 0; - lv_obj_t * e = lv_list_get_next_btn(list, NULL); - while(e != NULL) { - if(count == index) { - lv_obj_del(e); - return true; - } - e = lv_list_get_next_btn(list, e); - count++; - } - return false; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Make a button selected - * @param list pointer to a list object - * @param btn pointer to a button to select - * NULL to not select any buttons - */ -void lv_list_focus_btn(lv_obj_t * list, lv_obj_t * btn) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - if(btn) LV_ASSERT_OBJ(btn, "lv_btn"); - - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - - /*Defocus the current button*/ - if(ext->act_sel_btn) lv_obj_clear_state(ext->act_sel_btn, LV_STATE_FOCUSED); - -#if LV_USE_GROUP - /*Don't forget which button was selected. - * It will be restored when the list is focused again.*/ - if(btn) ext->last_sel_btn = btn; -#endif - - /*Focus the new button*/ - ext->act_sel_btn = btn; - - if(ext->act_sel_btn) { - lv_obj_add_state(ext->act_sel_btn, LV_STATE_FOCUSED); - lv_page_focus(list, ext->act_sel_btn, LV_ANIM_ON); - } -} - -/** - * Set layout of a list - * @param list pointer to a list object - * @param layout which layout should be used - */ -void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - /* Update list layout if necessary */ - if(layout == lv_list_get_layout(list)) return; - - /* Get the first button on the list */ - lv_obj_t * btn = lv_list_get_prev_btn(list, NULL); - - /* Visit all buttons on the list and update their layout */ - while(btn != NULL) { - /*If a column layout set the buttons' width to list width*/ - if(layout == LV_LAYOUT_COLUMN_MID || layout == LV_LAYOUT_COLUMN_LEFT || layout == LV_LAYOUT_COLUMN_RIGHT) { - lv_btn_set_fit2(btn, LV_FIT_PARENT, LV_FIT_TIGHT); - } - /*If a row layout set the buttons' width according to the content*/ - else if(layout == LV_LAYOUT_ROW_MID || layout == LV_LAYOUT_ROW_TOP || layout == LV_LAYOUT_ROW_BOTTOM) { - lv_btn_set_fit(btn, LV_FIT_TIGHT); - } - - btn = lv_list_get_prev_btn(list, btn); - } - - if(layout == LV_LAYOUT_COLUMN_MID || layout == LV_LAYOUT_COLUMN_LEFT || layout == LV_LAYOUT_COLUMN_RIGHT) { - lv_page_set_scrollable_fit2(list, LV_FIT_PARENT, LV_FIT_TIGHT); - } - else if(layout == LV_LAYOUT_ROW_MID || layout == LV_LAYOUT_ROW_TOP || layout == LV_LAYOUT_ROW_BOTTOM) { - lv_page_set_scrollable_fit2(list, LV_FIT_TIGHT, LV_FIT_TIGHT); - lv_cont_set_fit2(list, LV_FIT_NONE, LV_FIT_TIGHT); - } - - lv_page_set_scrl_layout(list, layout); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the text of a list element - * @param btn pointer to list element - * @return pointer to the text - */ -const char * lv_list_get_btn_text(const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, "lv_btn"); - - lv_obj_t * label = lv_list_get_btn_label(btn); - if(label == NULL) return ""; - return lv_label_get_text(label); -} - -/** - * Get the label object from a list element - * @param btn pointer to a list element (button) - * @return pointer to the label from the list element or NULL if not found - */ -lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, "lv_btn"); - - lv_obj_t * label = lv_obj_get_child_back(btn, NULL); - if(label == NULL) return NULL; - - while(lv_list_is_list_label(label) == false) { - label = lv_obj_get_child_back(btn, label); - if(label == NULL) break; - } - - return label; -} - -/** - * Get the image object from a list element - * @param btn pointer to a list element (button) - * @return pointer to the image from the list element or NULL if not found - */ -lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, "lv_btn"); - -#if LV_USE_IMG != 0 - lv_obj_t * img = lv_obj_get_child_back(btn, NULL); - if(img == NULL) return NULL; - - while(lv_list_is_list_img(img) == false) { - img = lv_obj_get_child_back(btn, img); - if(img == NULL) break; - } - - return img; -#else - return NULL; -#endif -} - -/** - * Get the previous button from list. (Starts from the bottom button) - * @param list pointer to a list object - * @param prev_btn pointer to button. Search the previous before it. - * @return pointer to the previous button or NULL when no more buttons - */ -lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - /* Not a good practice but user can add/create objects to the lists manually. - * When getting the next button try to be sure that it is at least a button */ - - lv_obj_t * btn; - lv_obj_t * scrl = lv_page_get_scrollable(list); - - btn = lv_obj_get_child(scrl, prev_btn); - if(btn == NULL) return NULL; - - while(lv_list_is_list_btn(btn) == false) { - btn = lv_obj_get_child(scrl, btn); - if(btn == NULL) break; - } - - return btn; -} - -/** - * Get the next button from list. (Starts from the top button) - * @param list pointer to a list object - * @param prev_btn pointer to button. Search the next after it. - * @return pointer to the next button or NULL when no more buttons - */ -lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - /* Not a good practice but user can add/create objects to the lists manually. - * When getting the next button try to be sure that it is at least a button */ - - lv_obj_t * btn; - lv_obj_t * scrl = lv_page_get_scrollable(list); - - btn = lv_obj_get_child_back(scrl, prev_btn); - if(btn == NULL) return NULL; - - while(lv_list_is_list_btn(btn) == false) { - btn = lv_obj_get_child_back(scrl, btn); - if(btn == NULL) break; - } - - return btn; -} - -/** - * Get the index of the button in the list - * @param list pointer to a list object. If NULL, assumes btn is part of a list. - * @param btn pointer to a list element (button) - * @return the index of the button in the list, or -1 of the button not in this list - */ -int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn) -{ - LV_ASSERT_OBJ(btn, "lv_btn"); - - int index = 0; - if(list == NULL) { - /* no list provided, assuming btn is part of a list */ - list = lv_obj_get_parent(lv_obj_get_parent(btn)); - } - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - lv_obj_t * e = lv_list_get_next_btn(list, NULL); - while(e != NULL) { - if(e == btn) { - return index; - } - index++; - e = lv_list_get_next_btn(list, e); - } - return -1; -} - -/** - * Get the number of buttons in the list - * @param list pointer to a list object - * @return the number of buttons in the list - */ -uint16_t lv_list_get_size(const lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - uint16_t size = 0; - lv_obj_t * btn = lv_list_get_next_btn(list, NULL); - while(btn) { - size++; - btn = lv_list_get_next_btn(list, btn); - } - return size; -} - -#if LV_USE_GROUP -/** - * Get the currently selected button - * @param list pointer to a list object - * @return pointer to the selected button - */ -lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - return ext->act_sel_btn; -} -#endif - -/** - * Get layout of a list - * @param list pointer to a list object - * @return layout of the list object - */ -lv_layout_t lv_list_get_layout(lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - return lv_page_get_scrl_layout(list); -} - -/*===================== - * Other functions - *====================*/ - -/** - * Move the list elements up by one - * @param list pointer a to list object - */ -void lv_list_up(const lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - /*Search the first list element which 'y' coordinate is below the parent - * and position the list to show this element on the bottom*/ - lv_obj_t * scrl = lv_page_get_scrollable(list); - lv_obj_t * e; - lv_obj_t * e_prev = NULL; - - e = lv_list_get_prev_btn(list, NULL); - while(e != NULL) { - if(e->coords.y2 <= list->coords.y2) { - if(e_prev != NULL) { - lv_coord_t new_y = lv_obj_get_height(list) - (lv_obj_get_y(e_prev) + lv_obj_get_height(e_prev)); - if(lv_list_get_anim_time(list) == 0) { - lv_obj_set_y(scrl, new_y); - } - else { -#if LV_USE_ANIMATION - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, lv_obj_get_y(scrl), new_y); - lv_anim_set_time(&a, LV_LIST_DEF_ANIM_TIME); - lv_anim_start(&a); -#endif - } - } - break; - } - e_prev = e; - e = lv_list_get_prev_btn(list, e); - } -} - -/** - * Move the list elements down by one - * @param list pointer to a list object - */ -void lv_list_down(const lv_obj_t * list) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - /*Search the first list element which 'y' coordinate is above the parent - * and position the list to show this element on the top*/ - lv_obj_t * scrl = lv_page_get_scrollable(list); - lv_obj_t * e; - e = lv_list_get_prev_btn(list, NULL); - while(e != NULL) { - if(e->coords.y1 < list->coords.y1) { - lv_coord_t new_y = -lv_obj_get_y(e); - if(lv_list_get_anim_time(list) == 0) { - lv_obj_set_y(scrl, new_y); - } - else { -#if LV_USE_ANIMATION - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, lv_obj_get_y(scrl), new_y); - lv_anim_set_time(&a, LV_LIST_DEF_ANIM_TIME); - lv_anim_start(&a); -#endif - } - break; - } - e = lv_list_get_prev_btn(list, e); - } -} - -/** - * Focus on a list button. It ensures that the button will be visible on the list. - * @param btn pointer to a list button to focus - * @param anim_en LV_ANIM_ON: scroll with animation, LV_ANOM_OFF: without animation - */ -void lv_list_focus(const lv_obj_t * btn, lv_anim_enable_t anim) -{ - LV_ASSERT_OBJ(btn, ""); - -#if LV_USE_ANIMATION == 0 - anim = false; -#endif - - lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn)); - - lv_page_focus(list, btn, anim == LV_ANIM_OFF ? 0 : lv_list_get_anim_time(list)); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the list - * @param list pointer to a list object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param) -{ - lv_res_t res; - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_list_get_style(list, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_page_signal(list, sign, param); - } - - /* Include the ancient signal function */ - res = ancestor_page_signal(list, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESSING || - sign == LV_SIGNAL_LONG_PRESS || sign == LV_SIGNAL_LONG_PRESS_REP) { -#if LV_USE_GROUP - /*If pressed/released etc by a KEYPAD or ENCODER delegate signal and events to the button*/ - lv_indev_t * indev = lv_indev_get_act(); - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type == LV_INDEV_TYPE_KEYPAD || - (indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(lv_obj_get_group(list)))) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - - /*The page receives the key presses so the events should be propagated to the selected - * button*/ - if(ext->act_sel_btn) { - res = lv_signal_send(ext->act_sel_btn, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_PRESSED) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_PRESSED, NULL); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_PRESSING) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_PRESSING, NULL); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_LONG_PRESS) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_LONG_PRESSED, NULL); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_LONG_PRESS_REP) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_LONG_PRESSED_REPEAT, NULL); - if(res != LV_RES_OK) return res; - } - else if(sign == LV_SIGNAL_RELEASED) { - if(indev->proc.long_pr_sent == 0) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_SHORT_CLICKED, NULL); - if(res != LV_RES_OK) return res; - } - if(lv_indev_is_scrolling(indev) == false) { - res = lv_event_send(ext->act_sel_btn, LV_EVENT_CLICKED, NULL); - if(res != LV_RES_OK) return res; - } - - res = lv_event_send(ext->act_sel_btn, LV_EVENT_RELEASED, NULL); - if(res != LV_RES_OK) return res; - } - } - } -#endif - } - else if(sign == LV_SIGNAL_FOCUS) { - -#if LV_USE_GROUP - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - /*With ENCODER focus the button only in edit mode*/ - lv_group_t * g = lv_obj_get_group(list); - if((indev_type == LV_INDEV_TYPE_KEYPAD) || - (indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(g))) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - /* Select the last used button, or use the first no last button */ - if(ext->last_sel_btn) lv_list_focus_btn(list, ext->last_sel_btn); - else lv_list_focus_btn(list, lv_list_get_next_btn(list, NULL)); - } - if(indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(g) == false) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - if(ext->act_sel_btn) lv_obj_clear_state(ext->act_sel_btn, LV_STATE_PRESSED); - if(ext->last_sel_btn) lv_obj_clear_state(ext->last_sel_btn, LV_STATE_PRESSED); - } -#endif - } - else if(sign == LV_SIGNAL_DEFOCUS) { - -#if LV_USE_GROUP - /*De-select the selected btn*/ - lv_list_focus_btn(list, NULL); - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - ext->act_sel_btn = NULL; -#endif - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } - else if(sign == LV_SIGNAL_CONTROL) { - -#if LV_USE_GROUP - char c = *((char *)param); - if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - /*If there is a valid selected button the make the previous selected*/ - if(ext->act_sel_btn) { - lv_obj_t * btn_prev = lv_list_get_next_btn(list, ext->act_sel_btn); - if(btn_prev) lv_list_focus_btn(list, btn_prev); - } - /*If there is no selected button the make the first selected*/ - else { - lv_obj_t * btn = lv_list_get_next_btn(list, NULL); - if(btn) - lv_list_focus_btn(list, - btn); /*If there are no buttons on the list then there is no first button*/ - } - } - else if(c == LV_KEY_LEFT || c == LV_KEY_UP) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - /*If there is a valid selected button the make the next selected*/ - if(ext->act_sel_btn != NULL) { - lv_obj_t * btn_next = lv_list_get_prev_btn(list, ext->act_sel_btn); - if(btn_next) lv_list_focus_btn(list, btn_next); - } - /*If there is no selected button the make the first selected*/ - else { - lv_obj_t * btn = lv_list_get_next_btn(list, NULL); - if(btn) lv_list_focus_btn(list, btn); - } - } - else if(c == LV_KEY_ESC) { - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - /* Handle ESC/Cancel event */ - res = lv_event_send(ext->act_sel_btn, LV_EVENT_CANCEL, NULL); - } -#endif - } - return res; -} - -/** - * Signal function of the list buttons - * @param btn pointer to a button on the list - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_btn_signal(btn, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, ""); - - if((sign == LV_SIGNAL_COORD_CHG && (lv_obj_get_width(btn) != lv_area_get_width(param) || - lv_obj_get_height(btn) != lv_area_get_height(param))) || - sign == LV_SIGNAL_STYLE_CHG) { - lv_obj_t * label = lv_list_get_btn_label(btn); - if(label) { - const lv_font_t * font = lv_obj_get_style_text_font(label, LV_LABEL_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - if(lv_obj_get_base_dir(btn) == LV_BIDI_DIR_RTL) { - lv_coord_t pad = lv_obj_get_style_pad_left(btn, LV_BTN_PART_MAIN); - lv_obj_set_size(label, label->coords.x2 - btn->coords.x1 - pad, font_h); - } - else { - lv_coord_t pad = lv_obj_get_style_pad_right(btn, LV_BTN_PART_MAIN); - lv_obj_set_size(label, btn->coords.x2 - label->coords.x1 - pad + 1, font_h); - } - } - } - else if(sign == LV_SIGNAL_RELEASED) { - if(lv_indev_is_scrolling(lv_indev_get_act()) == false) { - lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn)); - lv_list_focus_btn(list, btn); -#if LV_USE_GROUP - if(lv_obj_get_group(list)) { - lv_group_focus_obj(list); - } -#endif - } - } - else if(sign == LV_SIGNAL_CLEANUP) { -#if LV_USE_GROUP - lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn)); - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - lv_obj_t * sel = lv_list_get_btn_selected(list); - if(sel == btn) lv_list_focus_btn(list, lv_list_get_next_btn(list, btn)); - if(ext->last_sel_btn == btn) ext->last_sel_btn = NULL; -#endif - } - - return res; -} - -/** - * Get the style descriptor of a part of the object - * @param list pointer the object - * @param part the part from `lv_page_list_t`. (LV_LIST_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_list_get_style(lv_obj_t * list, uint8_t part) -{ - LV_ASSERT_OBJ(list, LV_OBJX_NAME); - - lv_list_ext_t * ext = lv_obj_get_ext_attr(list); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_LIST_PART_BG: - style_dsc_p = &list->style_list; - break; - case LV_LIST_PART_SCROLLABLE: - style_dsc_p = &ext->page.scrl->style_list; - break; - case LV_LIST_PART_SCROLLBAR: - style_dsc_p = &ext->page.scrlbar.style; - break; -#if LV_USE_ANIMATION - case LV_LIST_PART_EDGE_FLASH: - style_dsc_p = &ext->page.edge_flash.style; - break; -#endif - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -/** - * Check if this is really a list button or another object. - * @param list_btn List button - */ -static bool lv_list_is_list_btn(lv_obj_t * list_btn) -{ - lv_obj_type_t type; - - lv_obj_get_type(list_btn, &type); - uint8_t cnt; - for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) { - if(type.type[cnt] == NULL) break; - if(!strcmp(type.type[cnt], "lv_btn")) return true; - } - return false; -} - -/** - * Check if this is really a list label or another object. - * @param list_label List label - */ -static bool lv_list_is_list_label(lv_obj_t * list_label) -{ - lv_obj_type_t type; - - lv_obj_get_type(list_label, &type); - uint8_t cnt; - for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) { - if(type.type[cnt] == NULL) break; - if(!strcmp(type.type[cnt], "lv_label")) return true; - } - return false; -} - -/** - * Check if this is really a list image or another object. - * @param list_image List image - */ -static bool lv_list_is_list_img(lv_obj_t * list_img) -{ - lv_obj_type_t type; - - lv_obj_get_type(list_img, &type); - uint8_t cnt; - for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) { - if(type.type[cnt] == NULL) break; - if(!strcmp(type.type[cnt], "lv_img")) return true; - } - return false; -} - -#endif diff --git a/src/lv_widgets/lv_list.h b/src/lv_widgets/lv_list.h deleted file mode 100644 index 92e521a14..000000000 --- a/src/lv_widgets/lv_list.h +++ /dev/null @@ -1,311 +0,0 @@ -/** - * @file lv_list.h - * - */ - -#ifndef LV_LIST_H -#define LV_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_LIST != 0 - -/*Testing of dependencies*/ -#if LV_USE_PAGE == 0 -#error "lv_list: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) " -#endif - -#if LV_USE_BTN == 0 -#error "lv_list: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) " -#endif - -#if LV_USE_LABEL == 0 -#error "lv_list: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "lv_page.h" -#include "lv_btn.h" -#include "lv_label.h" -#include "lv_img.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -/*Data of list*/ -typedef struct { - lv_page_ext_t page; /*Ext. of ancestor*/ - /*New data for this type */ - -#if LV_USE_GROUP - lv_obj_t * last_sel_btn; /* The last selected button. It will be reverted when the list is focused again */ -#endif - lv_obj_t * act_sel_btn; /* The button is currently being selected*/ -} lv_list_ext_t; - -/** List styles. */ -enum { - LV_LIST_PART_BG = LV_PAGE_PART_BG, /**< List background style */ - LV_LIST_PART_SCROLLBAR = LV_PAGE_PART_SCROLLBAR, /**< List scrollbar style. */ - LV_LIST_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH, /**< List edge flash style. */ - _LV_LIST_PART_VIRTUAL_LAST = _LV_PAGE_PART_VIRTUAL_LAST, - LV_LIST_PART_SCROLLABLE = LV_PAGE_PART_SCROLLABLE, /**< List scrollable area style. */ - _LV_LIST_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST, -}; -typedef uint8_t lv_list_style_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a list objects - * @param par pointer to an object, it will be the parent of the new list - * @param copy pointer to a list object, if not NULL then the new object will be copied from it - * @return pointer to the created list - */ -lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy); - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param list pointer to an object - */ -void lv_list_clean(lv_obj_t * list); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add a list element to the list - * @param list pointer to list object - * @param img_fn file name of an image before the text (NULL if unused) - * @param txt text of the list element (NULL if unused) - * @return pointer to the new list element which can be customized (a button) - */ -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * txt); - -/** - * Remove the index of the button in the list - * @param list pointer to a list object - * @param index pointer to a the button's index in the list, index must be 0 <= index < - * lv_list_ext_t.size - * @return true: successfully deleted - */ -bool lv_list_remove(const lv_obj_t * list, uint16_t index); - -/*===================== - * Setter functions - *====================*/ - -/** - * Make a button selected - * @param list pointer to a list object - * @param btn pointer to a button to select - * NULL to not select any buttons - */ -void lv_list_focus_btn(lv_obj_t * list, lv_obj_t * btn); - -/** - * Set the scroll bar mode of a list - * @param list pointer to a list object - * @param sb_mode the new mode from 'lv_page_sb_mode_t' enum - */ -static inline void lv_list_set_scrollbar_mode(lv_obj_t * list, lv_scrollbar_mode_t mode) -{ - lv_page_set_scrollbar_mode(list, mode); -} - -/** - * Enable the scroll propagation feature. If enabled then the List will move its parent if there is - * no more space to scroll. - * @param list pointer to a List - * @param en true or false to enable/disable scroll propagation - */ -static inline void lv_list_set_scroll_propagation(lv_obj_t * list, bool en) -{ - lv_page_set_scroll_propagation(list, en); -} - -/** - * Enable the edge flash effect. (Show an arc when the an edge is reached) - * @param list pointer to a List - * @param en true or false to enable/disable end flash - */ -static inline void lv_list_set_edge_flash(lv_obj_t * list, bool en) -{ - lv_page_set_edge_flash(list, en); -} - -/** - * Set scroll animation duration on 'list_up()' 'list_down()' 'list_focus()' - * @param list pointer to a list object - * @param anim_time duration of animation [ms] - */ -static inline void lv_list_set_anim_time(lv_obj_t * list, uint16_t anim_time) -{ - lv_page_set_anim_time(list, anim_time); -} - -/** - * Set layout of a list - * @param list pointer to a list object - * @param layout which layout should be used - */ -void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the text of a list element - * @param btn pointer to list element - * @return pointer to the text - */ -const char * lv_list_get_btn_text(const lv_obj_t * btn); -/** - * Get the label object from a list element - * @param btn pointer to a list element (button) - * @return pointer to the label from the list element or NULL if not found - */ -lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn); - -/** - * Get the image object from a list element - * @param btn pointer to a list element (button) - * @return pointer to the image from the list element or NULL if not found - */ -lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn); - -/** - * Get the next button from list. (Starts from the bottom button) - * @param list pointer to a list object - * @param prev_btn pointer to button. Search the next after it. - * @return pointer to the next button or NULL when no more buttons - */ -lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn); - -/** - * Get the previous button from list. (Starts from the top button) - * @param list pointer to a list object - * @param prev_btn pointer to button. Search the previous before it. - * @return pointer to the previous button or NULL when no more buttons - */ -lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn); - -/** - * Get the index of the button in the list - * @param list pointer to a list object. If NULL, assumes btn is part of a list. - * @param btn pointer to a list element (button) - * @return the index of the button in the list, or -1 of the button not in this list - */ -int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn); - -/** - * Get the number of buttons in the list - * @param list pointer to a list object - * @return the number of buttons in the list - */ -uint16_t lv_list_get_size(const lv_obj_t * list); - -#if LV_USE_GROUP -/** - * Get the currently selected button. Can be used while navigating in the list with a keypad. - * @param list pointer to a list object - * @return pointer to the selected button - */ -lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list); -#endif - -/** - * Get layout of a list - * @param list pointer to a list object - * @return layout of the list object - */ -lv_layout_t lv_list_get_layout(lv_obj_t * list); - -/** - * Get the scroll bar mode of a list - * @param list pointer to a list object - * @return scrollbar mode from 'lv_scrollbar_mode_t' enum - */ -static inline lv_scrollbar_mode_t lv_list_get_scrollbar_mode(const lv_obj_t * list) -{ - return lv_page_get_scrollbar_mode(list); -} - -/** - * Get the scroll propagation property - * @param list pointer to a List - * @return true or false - */ -static inline bool lv_list_get_scroll_propagation(lv_obj_t * list) -{ - return lv_page_get_scroll_propagation(list); -} - -/** - * Get the scroll propagation property - * @param list pointer to a List - * @return true or false - */ -static inline bool lv_list_get_edge_flash(lv_obj_t * list) -{ - return lv_page_get_edge_flash(list); -} - -/** - * Get scroll animation duration - * @param list pointer to a list object - * @return duration of animation [ms] - */ -static inline uint16_t lv_list_get_anim_time(const lv_obj_t * list) -{ - return lv_page_get_anim_time(list); -} - -/*===================== - * Other functions - *====================*/ - -/** - * Move the list elements up by one - * @param list pointer a to list object - */ -void lv_list_up(const lv_obj_t * list); -/** - * Move the list elements down by one - * @param list pointer to a list object - */ -void lv_list_down(const lv_obj_t * list); - -/** - * Focus on a list button. It ensures that the button will be visible on the list. - * @param btn pointer to a list button to focus - * @param anim LV_ANOM_ON: scroll with animation, LV_ANIM_OFF: without animation - */ -void lv_list_focus(const lv_obj_t * btn, lv_anim_enable_t anim); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_LIST*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_LIST_H*/ diff --git a/src/lv_widgets/lv_msgbox.c b/src/lv_widgets/lv_msgbox.c deleted file mode 100644 index 9448bec58..000000000 --- a/src/lv_widgets/lv_msgbox.c +++ /dev/null @@ -1,606 +0,0 @@ -/** - * @file lv_msgbox.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_msgbox.h" -#if LV_USE_MSGBOX != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_core/lv_group.h" -#include "../lv_core/lv_disp.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_anim.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_msgbox" - -#if LV_USE_ANIMATION - #ifndef LV_MSGBOX_CLOSE_ANIM_TIME - #define LV_MSGBOX_CLOSE_ANIM_TIME 200 /*List close animation time) */ - #endif -#else - #undef LV_MSGBOX_CLOSE_ANIM_TIME - #define LV_MSGBOX_CLOSE_ANIM_TIME 0 /*No animations*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_msgbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param); -static void mbox_realign(lv_obj_t * mbox); -static lv_style_list_t * lv_msgbox_get_style(lv_obj_t * mbox, uint8_t part); -#if LV_USE_ANIMATION - static void lv_msgbox_close_ready_cb(lv_anim_t * a); -#endif -static void lv_msgbox_default_event_cb(lv_obj_t * mbox, lv_event_t event); -static void lv_msgbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a message box objects - * @param par pointer to an object, it will be the parent of the new message box - * @param copy pointer to a message box object, if not NULL then the new object will be copied from - * it - * @return pointer to the created message box - */ -lv_obj_t * lv_msgbox_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("message box create started"); - - /*Create the ancestor message box*/ - lv_obj_t * mbox = lv_cont_create(par, copy); - LV_ASSERT_MEM(mbox); - if(mbox == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(mbox); - - /*Allocate the message box type specific extended data*/ - lv_msgbox_ext_t * ext = lv_obj_allocate_ext_attr(mbox, sizeof(lv_msgbox_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(mbox); - return NULL; - } - - ext->text = NULL; - ext->btnm = NULL; -#if LV_USE_ANIMATION - ext->anim_time = LV_MSGBOX_CLOSE_ANIM_TIME; -#endif - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(mbox, lv_msgbox_signal); - - /*Init the new message box message box*/ - if(copy == NULL) { - ext->text = lv_label_create(mbox, NULL); - lv_label_set_align(ext->text, LV_LABEL_ALIGN_CENTER); - lv_label_set_long_mode(ext->text, LV_LABEL_LONG_BREAK); - lv_label_set_text(ext->text, "Message"); - - lv_cont_set_layout(mbox, LV_LAYOUT_COLUMN_MID); - lv_cont_set_fit2(mbox, LV_FIT_NONE, LV_FIT_TIGHT); - lv_coord_t fit_w = lv_obj_get_width_fit(par); - if(lv_disp_get_size_category(NULL) <= LV_DISP_SIZE_SMALL) { - lv_obj_set_width(mbox, fit_w); - } - else { - lv_obj_set_width(mbox, LV_MATH_MIN(fit_w, LV_DPX(400))); - } - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_event_cb(mbox, lv_msgbox_default_event_cb); - - /*Set the default styles*/ - lv_theme_apply(mbox, LV_THEME_MSGBOX); - - } - /*Copy an existing message box*/ - else { - lv_msgbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - - ext->text = lv_label_create(mbox, copy_ext->text); - - /*Copy the buttons and the label on them*/ - if(copy_ext->btnm) ext->btnm = lv_btnmatrix_create(mbox, copy_ext->btnm); - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(mbox, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("message box created"); - - return mbox; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add button to the message box - * @param mbox pointer to message box object - * @param btn_map button descriptor (button matrix map). - * E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable) - */ -void lv_msgbox_add_btns(lv_obj_t * mbox, const char * btn_map[]) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - LV_ASSERT_NULL(btn_map); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - - /*Create a button matrix if not exists yet*/ - if(ext->btnm == NULL) { - ext->btnm = lv_btnmatrix_create(mbox, NULL); - - lv_theme_apply(mbox, LV_THEME_MSGBOX_BTNS); - } - - lv_btnmatrix_set_map(ext->btnm, btn_map); - lv_btnmatrix_set_btn_ctrl_all(ext->btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); - lv_obj_set_event_cb(ext->btnm, lv_msgbox_btnm_event_cb); - - if(lv_obj_is_focused(mbox)) { - lv_state_t state = lv_obj_get_state(mbox, LV_MSGBOX_PART_BG); - if(state & LV_STATE_EDITED) { - lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED | LV_STATE_EDITED); - } - else { - lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED); - } - - lv_btnmatrix_set_focused_btn(ext->btnm, 0); - } - - mbox_realign(mbox); -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the text of the message box - * @param mbox pointer to a message box - * @param txt a '\0' terminated character string which will be the message box text - */ -void lv_msgbox_set_text(lv_obj_t * mbox, const char * txt) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - LV_ASSERT_STR(txt); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - lv_label_set_text(ext->text, txt); - - mbox_realign(mbox); -} - -/** - * Set animation duration - * @param mbox pointer to a message box object - * @param anim_time animation length in milliseconds (0: no animation) - */ -void lv_msgbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - anim_time = 0; - ext->anim_time = anim_time; -#else - (void)mbox; - (void)anim_time; -#endif -} - -/** - * Automatically delete the message box after a given time - * @param mbox pointer to a message box object - * @param delay a time (in milliseconds) to wait before delete the message box - */ -void lv_msgbox_start_auto_close(lv_obj_t * mbox, uint16_t delay) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - if(lv_msgbox_get_anim_time(mbox) != 0) { - /*Add shrinking animations*/ - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, mbox); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_height); - lv_anim_set_values(&a, lv_obj_get_height(mbox), 0); - lv_anim_set_time(&a, lv_msgbox_get_anim_time(mbox)); - lv_anim_set_delay(&a, delay); - lv_anim_start(&a); - - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_width); - lv_anim_set_values(&a, lv_obj_get_width(mbox), 0); - lv_anim_set_ready_cb(&a, lv_msgbox_close_ready_cb); - lv_anim_start(&a); - - /*Disable fit to let shrinking work*/ - lv_cont_set_fit(mbox, LV_FIT_NONE); - } - else { - /*Create an animation to delete the mbox `delay` ms later*/ - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, mbox); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)NULL); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_ready_cb(&a, lv_msgbox_close_ready_cb); - lv_anim_set_time(&a, lv_msgbox_get_anim_time(mbox)); - lv_anim_set_delay(&a, delay); - lv_anim_start(&a); - } -#else - (void)delay; /*Unused*/ - lv_obj_del(mbox); -#endif -} - -/** - * Stop the auto. closing of message box - * @param mbox pointer to a message box object - */ -void lv_msgbox_stop_auto_close(lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_anim_del(mbox, NULL); -#else - (void)mbox; /*Unused*/ -#endif -} - -/** - * Set whether recoloring is enabled - * @param mbox pointer to message box object - * @param en whether recoloring is enabled - */ -void lv_msgbox_set_recolor(lv_obj_t * mbox, bool en) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - - if(ext->btnm) lv_btnmatrix_set_recolor(ext->btnm, en); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the text of the message box - * @param mbox pointer to a message box object - * @return pointer to the text of the message box - */ -const char * lv_msgbox_get_text(const lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - - return lv_label_get_text(ext->text); -} - -/** - * Get the index of the lastly "activated" button by the user (pressed, released etc) - * Useful in the the `event_cb`. - * @param mbox pointer to message box object - * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) - */ -uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - if(ext->btnm == NULL) return LV_BTNMATRIX_BTN_NONE; - - uint16_t id = lv_btnmatrix_get_active_btn(ext->btnm); - if(id == LV_BTNMATRIX_BTN_NONE) { - id = lv_btnmatrix_get_focused_btn(ext->btnm); - } - - return id; -} - -/** - * Get the text of the lastly "activated" button by the user (pressed, released etc) - * Useful in the the `event_cb`. - * @param mbox pointer to message box object - * @return text of the last released button (NULL: if unset) - */ -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - if(ext->btnm) - return lv_btnmatrix_get_active_btn_text(ext->btnm); - else - return NULL; -} - -/** - * Get the animation duration (close animation time) - * @param mbox pointer to a message box object - * @return animation length in milliseconds (0: no animation) - */ -uint16_t lv_msgbox_get_anim_time(const lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - return ext->anim_time; -#else - (void)mbox; - return 0; -#endif -} - -/** - * Get whether recoloring is enabled - * @param mbox pointer to a message box object - * @return whether recoloring is enabled - */ -bool lv_msgbox_get_recolor(const lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - - if(!ext->btnm) return false; - - return lv_btnmatrix_get_recolor(ext->btnm); -} - -/** - * Get message box button matrix - * @param mbox pointer to a message box object - * @return pointer to button matrix object - * @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called - */ -lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - return ext->btnm; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the message box - * @param mbox pointer to a message box object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_msgbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param) -{ - lv_res_t res; - -#if LV_USE_GROUP - /*Translate LV_KEY_UP/DOWN to LV_KEY_LEFT/RIGHT */ - char c_trans = 0; - if(sign == LV_SIGNAL_CONTROL) { - c_trans = *((char *)param); - if(c_trans == LV_KEY_DOWN) c_trans = LV_KEY_LEFT; - if(c_trans == LV_KEY_UP) c_trans = LV_KEY_RIGHT; - - param = &c_trans; - } -#endif - - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_msgbox_get_style(mbox, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(mbox, sign, param); - } - else if(sign == LV_SIGNAL_GET_STATE_DSC) { - lv_get_state_info_t * info = param; - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - if(ext->btnm && info->part == LV_MSGBOX_PART_BTN_BG) { - info->result = lv_obj_get_state(ext->btnm, LV_BTNMATRIX_PART_BG); - } - else if(ext->btnm && info->part == LV_MSGBOX_PART_BTN) { - info->result = lv_obj_get_state(ext->btnm, LV_BTNMATRIX_PART_BTN); - } - return LV_RES_OK; - } - - /* Include the ancient signal function */ - res = ancestor_signal(mbox, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - if(sign == LV_SIGNAL_COORD_CHG) { - if(lv_obj_get_width(mbox) != lv_area_get_width(param)) { - mbox_realign(mbox); - } - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - mbox_realign(mbox); - } - else if(sign == LV_SIGNAL_RELEASED) { - if(ext->btnm) { - uint32_t btn_id = lv_btnmatrix_get_focused_btn(ext->btnm); - if(btn_id != LV_BTNMATRIX_BTN_NONE) lv_event_send(mbox, LV_EVENT_VALUE_CHANGED, &btn_id); - } - } - else if( -#if LV_USE_GROUP - sign == LV_SIGNAL_CONTROL || sign == LV_SIGNAL_GET_EDITABLE || -#endif - sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) { - if(ext->btnm) { - ext->btnm->signal_cb(ext->btnm, sign, param); - } - - /* The button matrix with ENCODER input supposes it's in a group but in this case it isn't - * (Only the message box's container) So so some actions here instead*/ -#if LV_USE_GROUP - if(sign == LV_SIGNAL_FOCUS) { - lv_indev_t * indev = lv_indev_get_act(); - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type == LV_INDEV_TYPE_ENCODER) { - /*In navigation mode don't select any button but in edit mode select the fist*/ - if(lv_group_get_editing(lv_obj_get_group(mbox))) lv_btnmatrix_set_focused_btn(ext->btnm, 0); - else lv_btnmatrix_set_focused_btn(ext->btnm, LV_BTNMATRIX_BTN_NONE); - } - } - - if(ext->btnm && (sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS)) { - lv_state_t state = lv_obj_get_state(mbox, LV_MSGBOX_PART_BG); - if(state & LV_STATE_FOCUSED) { - lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED); - } - else { - lv_obj_clear_state(ext->btnm, LV_STATE_FOCUSED); - - } - if(state & LV_STATE_EDITED) { - lv_obj_set_state(ext->btnm, LV_STATE_EDITED); - } - else { - lv_obj_clear_state(ext->btnm, LV_STATE_EDITED); - - } - } -#endif - } - - return res; -} - -/** - * Get the style descriptor of a part of the object - * @param mbox pointer the object - * @param part the part from `lv_msgbox_part_t`. (LV_MSGBOX_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_msgbox_get_style(lv_obj_t * mbox, uint8_t part) -{ - LV_ASSERT_OBJ(mbox, LV_OBJX_NAME); - - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_MSGBOX_PART_BG: - style_dsc_p = &mbox->style_list; - break; - case LV_MSGBOX_PART_BTN_BG: - style_dsc_p = ext->btnm ? lv_obj_get_style_list(ext->btnm, LV_BTNMATRIX_PART_BG) : NULL; - break; - case LV_MSGBOX_PART_BTN: - style_dsc_p = ext->btnm ? lv_obj_get_style_list(ext->btnm, LV_BTNMATRIX_PART_BTN) : NULL; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -/** - * Resize the button holder to fit - * @param mbox pointer to message box object - */ -static void mbox_realign(lv_obj_t * mbox) -{ - lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox); - - lv_coord_t w = lv_obj_get_width_fit(mbox); - - if(ext->text) { - lv_obj_set_width(ext->text, w); - } - - if(ext->btnm) { - lv_style_int_t bg_top = lv_obj_get_style_pad_top(mbox, LV_MSGBOX_PART_BTN_BG); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(mbox, LV_MSGBOX_PART_BTN_BG); - lv_style_int_t bg_inner = lv_obj_get_style_pad_inner(mbox, LV_MSGBOX_PART_BTN_BG); - lv_style_int_t btn_top = lv_obj_get_style_pad_top(mbox, LV_MSGBOX_PART_BTN); - lv_style_int_t btn_bottom = lv_obj_get_style_pad_bottom(mbox, LV_MSGBOX_PART_BTN); - const lv_font_t * font = lv_obj_get_style_text_font(mbox, LV_MSGBOX_PART_BTN); - - uint16_t btnm_lines = 1; - const char ** btnm_map = lv_btnmatrix_get_map_array(ext->btnm); - uint16_t i; - for(i = 0; btnm_map[i][0] != '\0'; i++) { - if(btnm_map[i][0] == '\n') btnm_lines++; - } - - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t btn_h = font_h + btn_top + btn_bottom; - lv_obj_set_size(ext->btnm, w, btn_h * btnm_lines + bg_inner * (btnm_lines - 1) + bg_top + bg_bottom); - } -} - -#if LV_USE_ANIMATION -static void lv_msgbox_close_ready_cb(lv_anim_t * a) -{ - lv_obj_del(a->var); -} -#endif - -static void lv_msgbox_default_event_cb(lv_obj_t * mbox, lv_event_t event) -{ - if(event != LV_EVENT_VALUE_CHANGED) return; - - uint32_t btn_id = lv_msgbox_get_active_btn(mbox); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return; - - lv_msgbox_start_auto_close(mbox, 0); -} - -static void lv_msgbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event) -{ - lv_obj_t * mbox = lv_obj_get_parent(btnm); - - /*clang-format off*/ - if(event == LV_EVENT_PRESSED || event == LV_EVENT_PRESSING || event == LV_EVENT_PRESS_LOST || - event == LV_EVENT_RELEASED || event == LV_EVENT_SHORT_CLICKED || event == LV_EVENT_CLICKED || - event == LV_EVENT_LONG_PRESSED || event == LV_EVENT_LONG_PRESSED_REPEAT || - event == LV_EVENT_VALUE_CHANGED) { - lv_event_send(mbox, event, lv_event_get_data()); - } - /*clang-format on*/ -} - -#endif diff --git a/src/lv_widgets/lv_msgbox.h b/src/lv_widgets/lv_msgbox.h deleted file mode 100644 index b9fde8a87..000000000 --- a/src/lv_widgets/lv_msgbox.h +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @file lv_mbox.h - * - */ - -#ifndef LV_MSGBOX_H -#define LV_MSGBOX_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_MSGBOX != 0 - -/*Testing of dependencies*/ -#if LV_USE_CONT == 0 -#error "lv_mbox: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) " -#endif - -#if LV_USE_BTNMATRIX == 0 -#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " -#endif - -#if LV_USE_LABEL == 0 -#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "lv_cont.h" -#include "lv_btnmatrix.h" -#include "lv_label.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/*Data of message box*/ -typedef struct { - lv_cont_ext_t bg; /*Ext. of ancestor*/ - /*New data for this type */ - lv_obj_t * text; /*Text of the message box*/ - lv_obj_t * btnm; /*Button matrix for the buttons*/ -#if LV_USE_ANIMATION - uint16_t anim_time; /*Duration of close animation [ms] (0: no animation)*/ -#endif -} lv_msgbox_ext_t; - -/** Message box styles. */ -enum { - LV_MSGBOX_PART_BG = LV_CONT_PART_MAIN, - - LV_MSGBOX_PART_BTN_BG = _LV_CONT_PART_REAL_LAST, - LV_MSGBOX_PART_BTN, -}; -typedef uint8_t lv_msgbox_style_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a message box objects - * @param par pointer to an object, it will be the parent of the new message box - * @param copy pointer to a message box object, if not NULL then the new object will be copied from - * it - * @return pointer to the created message box - */ -lv_obj_t * lv_msgbox_create(lv_obj_t * par, const lv_obj_t * copy); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add button to the message box - * @param mbox pointer to message box object - * @param btn_map button descriptor (button matrix map). - * E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable) - */ -void lv_msgbox_add_btns(lv_obj_t * mbox, const char * btn_mapaction[]); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the text of the message box - * @param mbox pointer to a message box - * @param txt a '\0' terminated character string which will be the message box text - */ -void lv_msgbox_set_text(lv_obj_t * mbox, const char * txt); - -/** - * Set animation duration - * @param mbox pointer to a message box object - * @param anim_time animation length in milliseconds (0: no animation) - */ -void lv_msgbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time); - -/** - * Automatically delete the message box after a given time - * @param mbox pointer to a message box object - * @param delay a time (in milliseconds) to wait before delete the message box - */ -void lv_msgbox_start_auto_close(lv_obj_t * mbox, uint16_t delay); - -/** - * Stop the auto. closing of message box - * @param mbox pointer to a message box object - */ -void lv_msgbox_stop_auto_close(lv_obj_t * mbox); - -/** - * Set whether recoloring is enabled. Must be called after `lv_msgbox_add_btns`. - * @param mbox pointer to message box object - * @param en whether recoloring is enabled - */ -void lv_msgbox_set_recolor(lv_obj_t * mbox, bool en); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the text of the message box - * @param mbox pointer to a message box object - * @return pointer to the text of the message box - */ -const char * lv_msgbox_get_text(const lv_obj_t * mbox); - -/** - * Get the index of the lastly "activated" button by the user (pressed, released etc) - * Useful in the the `event_cb`. - * @param mbox pointer to message box object - * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) - */ -uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox); - -/** - * Get the text of the lastly "activated" button by the user (pressed, released etc) - * Useful in the the `event_cb`. - * @param mbox pointer to message box object - * @return text of the last released button (NULL: if unset) - */ -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox); - -/** - * Get the animation duration (close animation time) - * @param mbox pointer to a message box object - * @return animation length in milliseconds (0: no animation) - */ -uint16_t lv_msgbox_get_anim_time(const lv_obj_t * mbox); - -/** - * Get whether recoloring is enabled - * @param mbox pointer to a message box object - * @return whether recoloring is enabled - */ -bool lv_msgbox_get_recolor(const lv_obj_t * mbox); - -/** - * Get message box button matrix - * @param mbox pointer to a message box object - * @return pointer to button matrix object - * @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called - */ -lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_MSGBOX*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_MSGBOX_H*/ diff --git a/src/lv_widgets/lv_page.c b/src/lv_widgets/lv_page.c deleted file mode 100644 index 8d6ea7a09..000000000 --- a/src/lv_widgets/lv_page.c +++ /dev/null @@ -1,1375 +0,0 @@ -/** - * @file lv_page.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../lv_widgets/lv_page.h" -#if LV_USE_PAGE != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_core/lv_group.h" -#include "../lv_draw/lv_draw.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_core/lv_refr.h" -#include "../lv_misc/lv_anim.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_page" - -#define LV_PAGE_SB_MIN_SIZE (LV_DPI / 8) - -/*[ms] Scroll anim time on `lv_page_scroll_up/down/left/rigth`*/ -#define LV_PAGE_SCROLL_ANIM_TIME 200 - -#define LV_PAGE_END_FLASH_SIZE (LV_DPI / 4) -#define LV_PAGE_END_ANIM_TIME 300 -#define LV_PAGE_END_ANIM_WAIT_TIME 300 - -#if LV_USE_ANIMATION == 0 - #undef LV_PAGE_DEF_ANIM_TIME - #define LV_PAGE_DEF_ANIM_TIME 0 /*No animation*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void scrlbar_refresh(lv_obj_t * page); -static void scrl_reposition(lv_obj_t * page); -static lv_design_res_t lv_page_design(lv_obj_t * page, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param); -static lv_style_list_t * lv_page_get_style(lv_obj_t * page, uint8_t part); -static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void * param); -static void scrl_def_event_cb(lv_obj_t * scrl, lv_event_t event); -static void refr_ext_draw_pad(lv_obj_t * page); -#if LV_USE_ANIMATION - static void edge_flash_anim(void * page, lv_anim_value_t v); - static void edge_flash_anim_end(lv_anim_t * a); - static void get_edge_flash_area(lv_obj_t * page, lv_area_t * area, lv_coord_t state); -#endif - -/********************** - * STATIC VARIABLES - **********************/ -static lv_design_cb_t ancestor_design; -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a page objects - * @param par pointer to an object, it will be the parent of the new page - * @param copy pointer to a page object, if not NULL then the new object will be copied from it - * @return pointer to the created page - */ -lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("page create started"); - - /*Create the ancestor object*/ - lv_obj_t * page = lv_cont_create(par, copy); - LV_ASSERT_MEM(page); - if(page == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(page); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(page); - - /*Allocate the object type specific extended data*/ - lv_page_ext_t * ext = lv_obj_allocate_ext_attr(page, sizeof(lv_page_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(page); - return NULL; - } - - ext->scrl = NULL; - lv_style_list_init(&ext->scrlbar.style); - ext->scrlbar.hor_draw = 0; - ext->scrlbar.ver_draw = 0; - ext->scrlbar.mode = LV_SCROLLBAR_MODE_AUTO; -#if LV_USE_ANIMATION - lv_style_list_init(&ext->edge_flash.style); - ext->edge_flash.enabled = 0; - ext->edge_flash.bottom_ip = 0; - ext->edge_flash.top_ip = 0; - ext->edge_flash.left_ip = 0; - ext->edge_flash.right_ip = 0; - ext->edge_flash.state = 0; - ext->anim_time = LV_PAGE_DEF_ANIM_TIME; -#endif - ext->scroll_prop = 0; - ext->scroll_prop_obj = NULL; - - /*Init the new page object*/ - if(copy == NULL) { - ext->scrl = lv_cont_create(page, NULL); - lv_obj_set_focus_parent(ext->scrl, true); - lv_obj_set_drag(ext->scrl, true); - lv_obj_set_drag_throw(ext->scrl, true); - lv_obj_add_protect(ext->scrl, LV_PROTECT_PARENT | LV_PROTECT_PRESS_LOST); - lv_cont_set_fit(ext->scrl, LV_FIT_MAX); - lv_obj_set_event_cb(ext->scrl, scrl_def_event_cb); /*Propagate some event to the background - object by default for convenience */ - lv_obj_set_signal_cb(ext->scrl, lv_page_scrollable_signal); - - /* Add the signal function only if 'scrolling' is created - + * because everything has to be ready before any signal is received*/ - lv_obj_set_signal_cb(page, lv_page_signal); - lv_obj_set_design_cb(page, lv_page_design); - - - lv_page_set_scrollbar_mode(page, ext->scrlbar.mode); - - lv_theme_apply(page, LV_THEME_PAGE); - - } - else { - lv_page_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->scrl = lv_cont_create(page, copy_ext->scrl); - lv_obj_set_signal_cb(ext->scrl, lv_page_scrollable_signal); - - lv_style_list_copy(&ext->scrlbar.style, ©_ext->scrlbar.style); -#if LV_USE_ANIMATION - lv_style_list_copy(&ext->edge_flash.style, ©_ext->edge_flash.style); -#endif - - /* Add the signal function only if 'scrolling' is created - * because everything has to be ready before any signal is received*/ - lv_obj_set_signal_cb(page, lv_page_signal); - lv_obj_set_design_cb(page, lv_page_design); - - lv_page_set_scrollbar_mode(page, copy_ext->scrlbar.mode); - } - - - scrlbar_refresh(page); - - LV_LOG_INFO("page created"); - - return page; -} - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param page pointer to an object - */ -void lv_page_clean(lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_obj_t * scrl = lv_page_get_scrollable(page); - lv_obj_clean(scrl); -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the scroll bar mode on a page - * @param page pointer to a page object - * @param sb_mode the new mode from 'lv_page_sb.mode_t' enum - */ -void lv_page_set_scrollbar_mode(lv_obj_t * page, lv_scrollbar_mode_t sb_mode) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - if(ext->scrlbar.mode == sb_mode) return; - - if(sb_mode == LV_SCROLLBAR_MODE_HIDE) - ext->scrlbar.mode |= LV_SCROLLBAR_MODE_HIDE; /*Set the hidden flag*/ - else if(sb_mode == LV_SCROLLBAR_MODE_UNHIDE) - ext->scrlbar.mode &= (~LV_SCROLLBAR_MODE_HIDE); /*Clear the hidden flag*/ - else { - if(ext->scrlbar.mode & LV_SCROLLBAR_MODE_HIDE) sb_mode |= LV_SCROLLBAR_MODE_HIDE; - ext->scrlbar.mode = sb_mode; - } - - ext->scrlbar.hor_draw = 0; - ext->scrlbar.ver_draw = 0; - - scrlbar_refresh(page); - lv_obj_invalidate(page); -} - -/** - * Set the animation time for the page - * @param page pointer to a page object - * @param anim_time animation time in milliseconds - */ -void lv_page_set_anim_time(lv_obj_t * page, uint16_t anim_time) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - ext->anim_time = anim_time; -#else - (void)page; /*Unused*/ - (void)anim_time; /*Unused*/ -#endif -} - -/** - * Enable the scroll propagation feature. If enabled then the page will move its parent if there is - * no more space to scroll. - * The page needs to have a page-like parent (e.g. `lv_page`, `lv_tabview` tab, `lv_win` content area etc) - * If enabled drag direction will be changed `LV_DRAG_DIR_ONE` automatically to allow scrolling only in one direction at one time. - * @param page pointer to a Page - * @param en true or false to enable/disable scroll propagation - */ -void lv_page_set_scroll_propagation(lv_obj_t * page, bool en) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - if(en) lv_obj_set_drag_dir(ext->scrl, LV_DRAG_DIR_ONE); - else lv_obj_set_drag_dir(ext->scrl, LV_DRAG_DIR_BOTH); - - ext->scroll_prop = en ? 1 : 0; -} - -/** - * Enable the edge flash effect. (Show an arc when the an edge is reached) - * @param page pointer to a Page - * @param en true or false to enable/disable end flash - */ -void lv_page_set_edge_flash(lv_obj_t * page, bool en) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - ext->edge_flash.enabled = en ? 1 : 0; -#else - (void)page; - (void)en; -#endif -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the scrollable object of a page - * @param page pointer to a page object - * @return pointer to a container which is the scrollable part of the page - */ -lv_obj_t * lv_page_get_scrollable(const lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - - return ext->scrl; -} - -/** - * Get the animation time - * @param page pointer to a page object - * @return the animation time in milliseconds - */ -uint16_t lv_page_get_anim_time(const lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - return ext->anim_time; -#else - (void)page; /*Unused*/ - return 0; -#endif -} - -/** - * Set the scroll bar mode on a page - * @param page pointer to a page object - * @return the mode from 'lv_page_sb.mode_t' enum - */ -lv_scrollbar_mode_t lv_page_get_scrollbar_mode(const lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - return ext->scrlbar.mode; -} - -/** - * Get the scroll propagation property - * @param page pointer to a Page - * @return true or false - */ -bool lv_page_get_scroll_propagation(lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - return ext->scroll_prop ? true : false; -} - -/** - * Get the edge flash effect property. - * @param page pointer to a Page - * return true or false - */ -bool lv_page_get_edge_flash(lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - return ext->edge_flash.enabled == 0 ? false : true; -#else - (void)page; - return false; -#endif -} - -/** - * Get that width which can be set to the children to still not cause overflow (show scrollbars) - * @param page pointer to a page object - * @return the width which still fits into the page - */ -lv_coord_t lv_page_get_width_fit(lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - lv_style_int_t bg_left = lv_obj_get_style_pad_left(page, LV_PAGE_PART_BG); - lv_style_int_t bg_right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_BG); - lv_style_int_t scrl_left = lv_obj_get_style_pad_left(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_right = lv_obj_get_style_pad_right(ext->scrl, LV_CONT_PART_MAIN); - - return lv_obj_get_width(page) - bg_left - bg_right - scrl_left - scrl_right; -} - -/** - * Get that height which can be set to the children to still not cause overflow (show scrollbars) - * @param page pointer to a page object - * @return the height which still fits into the page - */ -lv_coord_t lv_page_get_height_fit(lv_obj_t * page) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - - lv_style_int_t bg_top = lv_obj_get_style_pad_top(page, LV_PAGE_PART_BG); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_BG); - lv_style_int_t scrl_top = lv_obj_get_style_pad_top(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_bottom = lv_obj_get_style_pad_bottom(ext->scrl, LV_CONT_PART_MAIN); - - return lv_obj_get_height(page) - bg_top - bg_bottom - scrl_top - scrl_bottom; -} - -/** - * Divide the width of the object and get the width of a given number of columns. - * Take into account the paddings of the background and scrollable too. - * @param page pointer to an object - * @param div indicates how many columns are assumed. - * If 1 the width will be set the the parent's width - * If 2 only half parent width - inner padding of the parent - * If 3 only third parent width - 2 * inner padding of the parent - * @param span how many columns are combined - * @return the width according to the given parameters - */ -lv_coord_t lv_page_get_width_grid(lv_obj_t * page, uint8_t div, uint8_t span) -{ - - lv_coord_t obj_w = lv_page_get_width_fit(page); - lv_style_int_t pinner = lv_obj_get_style_pad_inner(page, LV_PAGE_PART_SCROLLABLE); - - lv_coord_t r = (obj_w - (div - 1) * pinner) / div; - - r = r * span + (span - 1) * pinner; - return r; -} - -/** - * Divide the height of the object and get the height of a given number of rows. - * Take into account the paddings of the background and scrollable too. - * @param obj pointer to an object - * @param div indicates how many rows are assumed. - * If 1 the height will be set the the parent's height - * If 2 only half parent height - inner padding of the parent - * If 3 only third parent height - 2 * inner padding of the parent - * @param span how many rows are combined - * @return the height according to the given parameters - */ -lv_coord_t lv_page_get_height_grid(lv_obj_t * page, uint8_t div, uint8_t span) -{ - lv_coord_t obj_h = lv_page_get_height_fit(page); - lv_style_int_t pinner = lv_obj_get_style_pad_inner(page, LV_PAGE_PART_SCROLLABLE); - - lv_coord_t r = (obj_h - (div - 1) * pinner) / div; - - r = r * span + (span - 1) * pinner; - return r; -} - -/*===================== - * Other functions - *====================*/ - -/** - * Find whether the page has been scrolled to a certain edge. - * @param page Page object - * @param edge Edge to check - * @return true if the page is on the specified edge - */ -bool lv_page_on_edge(lv_obj_t * page, lv_page_edge_t edge) -{ - lv_obj_t * scrl = lv_page_get_scrollable(page); - lv_area_t page_coords; - lv_area_t scrl_coords; - - lv_obj_get_coords(scrl, &scrl_coords); - lv_obj_get_coords(page, &page_coords); - - lv_style_int_t left = lv_obj_get_style_pad_left(page, LV_PAGE_PART_BG); - lv_style_int_t right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_BG); - lv_style_int_t top = lv_obj_get_style_pad_top(page, LV_PAGE_PART_BG); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_BG); - - if((edge & LV_PAGE_EDGE_TOP) && scrl_coords.y1 == page_coords.y1 + top) return true; - if((edge & LV_PAGE_EDGE_BOTTOM) && scrl_coords.y2 == page_coords.y2 - bottom) return true; - if((edge & LV_PAGE_EDGE_LEFT) && scrl_coords.x1 == page_coords.x1 + left) return true; - if((edge & LV_PAGE_EDGE_RIGHT) && scrl_coords.x2 == page_coords.x2 - right) return true; - - return false; -} - -/** - * Glue the object to the page. After it the page can be moved (dragged) with this object too. - * @param page pointer to a page object - * @param obj pointer to an object on a page - * @param glue true: enable glue, false: disable glue - */ -void lv_page_glue_obj(lv_obj_t * page, lv_obj_t * obj, bool glue) -{ - lv_obj_set_drag_parent(obj, glue); - lv_obj_set_drag(obj, glue); -} - -/** - * Focus on an object. It ensures that the object will be visible on the page. - * @param page pointer to a page object - * @param obj pointer to an object to focus (must be on the page) - * @param anim_en LV_ANIM_ON to focus with animation; LV_ANIM_OFF to focus without animation - */ -void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, lv_anim_enable_t anim_en) -{ - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - -#if LV_USE_ANIMATION - /* Be sure there is no position changing animation in progress - * because it can override the current changes*/ - lv_anim_del(page, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_del(page, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_del(ext->scrl, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_del(ext->scrl, (lv_anim_exec_xcb_t)lv_obj_set_y); -#endif - - /*if using focus mode, change target to parent*/ - obj = lv_obj_get_focused_obj(obj); - - - /*If obj is higher then the page focus where the "error" is smaller*/ - lv_coord_t obj_y = obj->coords.y1 - ext->scrl->coords.y1; - lv_coord_t obj_h = lv_obj_get_height(obj); - lv_coord_t scrlable_y = lv_obj_get_y(ext->scrl); - lv_coord_t page_h = lv_obj_get_height(page); - - lv_style_int_t bg_top = lv_obj_get_style_pad_top(page, LV_PAGE_PART_BG); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_BG); - lv_style_int_t scrl_top = lv_obj_get_style_pad_top(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_bottom = lv_obj_get_style_pad_bottom(ext->scrl, LV_CONT_PART_MAIN); - - lv_coord_t top_err = -((scrlable_y + obj_y) - bg_top); - lv_coord_t bot_err = scrlable_y + obj_y + obj_h - (page_h - bg_bottom); - - /*Out of the page on the top*/ - if((obj_h <= page_h && top_err > 0) || (obj_h > page_h && top_err < bot_err)) { - /*Calculate a new position and let some space above*/ - scrlable_y = -(obj_y - scrl_top - bg_top); - scrlable_y += scrl_top; - } - /*Out of the page on the bottom*/ - else if((obj_h <= page_h && bot_err > 0) || (obj_h > page_h && top_err >= bot_err)) { - /*Calculate a new position and let some space below*/ - scrlable_y = -(obj_y + scrl_bottom + bg_bottom); - scrlable_y -= scrl_bottom; - scrlable_y += page_h - obj_h; - } - - - /*If obj is wider then the page focus where the "error" is smaller*/ - lv_coord_t obj_x = obj->coords.x1 - ext->scrl->coords.x1; - lv_coord_t obj_w = lv_obj_get_width(obj); - lv_coord_t scrlable_x = lv_obj_get_x(ext->scrl); - lv_coord_t page_w = lv_obj_get_width(page); - - lv_style_int_t bg_left = lv_obj_get_style_pad_left(page, LV_PAGE_PART_BG); - lv_style_int_t bg_right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_BG); - lv_style_int_t scrl_left = lv_obj_get_style_pad_top(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_right = lv_obj_get_style_pad_bottom(ext->scrl, LV_CONT_PART_MAIN); - - lv_coord_t left_err = -((scrlable_x + obj_x) - bg_left); - lv_coord_t right_err = scrlable_x + obj_x + obj_w - (page_w - bg_right); - - /*Out of the page on the left*/ - if((obj_w <= page_w && left_err > 0) || (obj_w > page_w && left_err < right_err)) { - /*Calculate a new position and let some space on the side*/ - scrlable_x = -(obj_x - scrl_left - bg_left); - scrlable_x += scrl_left; - } - /*Out of the page on the rigth*/ - else if((obj_w <= page_w && right_err > 0) || (obj_w > page_w && left_err >= right_err)) { - /*Calculate a new position and let some space on the side*/ - scrlable_x = -(obj_x + scrl_right + bg_right); - scrlable_x -= scrl_right; - scrlable_x += page_w - obj_w; - } - - if(anim_en == LV_ANIM_OFF || lv_page_get_anim_time(page) == 0) { - lv_obj_set_y(ext->scrl, scrlable_y); - lv_obj_set_x(ext->scrl, scrlable_x); - } - else { -#if LV_USE_ANIMATION - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ext->scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, lv_obj_get_y(ext->scrl), scrlable_y); - lv_anim_set_time(&a, lv_page_get_anim_time(page)); - lv_anim_start(&a); - - lv_anim_set_values(&a, lv_obj_get_x(ext->scrl), scrlable_x); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_start(&a); -#endif - } -} - -/** - * Scroll the page horizontally - * @param page pointer to a page object - * @param dist the distance to scroll (< 0: scroll right; > 0 scroll left) - */ -void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist) -{ - lv_obj_t * scrl = lv_page_get_scrollable(page); - -#if LV_USE_ANIMATION - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_set_values(&a, lv_obj_get_x(scrl), lv_obj_get_x(scrl) + dist); - lv_anim_set_time(&a, lv_page_get_anim_time(page)); - lv_anim_start(&a); -#else - lv_obj_set_x(scrl, lv_obj_get_x(scrl) + dist); -#endif -} - -/** - * Scroll the page vertically - * @param page pointer to a page object - * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) - */ -void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist) -{ - lv_obj_t * scrl = lv_page_get_scrollable(page); - -#if LV_USE_ANIMATION - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, lv_obj_get_y(scrl), lv_obj_get_y(scrl) + dist); - lv_anim_set_time(&a, lv_page_get_anim_time(page)); - lv_anim_start(&a); -#else - lv_obj_set_y(scrl, lv_obj_get_y(scrl) + dist); -#endif -} - -/** - * Not intended to use directly by the user but by other object types internally. - * Start an edge flash animation. - * @param page - * @param edge the edge to flash. Can be `LV_PAGE_EDGE_LEFT/RIGHT/TOP/BOTTOM` - */ -void lv_page_start_edge_flash(lv_obj_t * page, lv_page_edge_t edge) -{ -#if LV_USE_ANIMATION - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - if(ext->edge_flash.enabled == 0) return; - - if(ext->edge_flash.left_ip || - ext->edge_flash.right_ip || - ext->edge_flash.top_ip || - ext->edge_flash.bottom_ip) { - return; - } - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, page); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)edge_flash_anim); - lv_anim_set_values(&a, 0, LV_PAGE_END_FLASH_SIZE); - lv_anim_set_time(&a, lv_page_get_anim_time(page)); - lv_anim_set_playback_time(&a, lv_page_get_anim_time(page)); - lv_anim_set_playback_delay(&a, LV_PAGE_END_ANIM_WAIT_TIME); - lv_anim_set_ready_cb(&a, edge_flash_anim_end); - lv_anim_start(&a); - - switch(edge) { - case LV_PAGE_EDGE_BOTTOM: - ext->edge_flash.bottom_ip = 1; - break; - case LV_PAGE_EDGE_TOP: - ext->edge_flash.top_ip = 1; - break; - case LV_PAGE_EDGE_LEFT: - ext->edge_flash.left_ip = 1; - break; - case LV_PAGE_EDGE_RIGHT: - ext->edge_flash.right_ip = 1; - break; - } - -#else - LV_UNUSED(page); - LV_UNUSED(edge); -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Handle the drawing related tasks of the pages - * @param page pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_page_design(lv_obj_t * page, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - if(mode == LV_DESIGN_COVER_CHK) { - return ancestor_design(page, clip_area, mode); - } - - if(mode == LV_DESIGN_DRAW_MAIN) { - return ancestor_design(page, clip_area, mode); - } - else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_design(page, clip_area, mode); - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - - lv_area_t sb_hor_area; - lv_area_t sb_ver_area; - /*Convert the relative coordinates to absolute*/ - lv_area_copy(&sb_hor_area, &ext->scrlbar.hor_area); - sb_hor_area.x1 += page->coords.x1; - sb_hor_area.y1 += page->coords.y1; - sb_hor_area.x2 += page->coords.x1; - sb_hor_area.y2 += page->coords.y1; - - /*Convert the relative coordinates to absolute*/ - lv_area_copy(&sb_ver_area, &ext->scrlbar.ver_area); - sb_ver_area.x1 += page->coords.x1; - sb_ver_area.y1 += page->coords.y1; - sb_ver_area.x2 += page->coords.x1; - sb_ver_area.y2 += page->coords.y1; - - if((ext->scrlbar.hor_draw && _lv_area_is_on(&sb_hor_area, clip_area)) || - (ext->scrlbar.ver_draw && _lv_area_is_on(&sb_ver_area, clip_area))) { - /*Draw the scrollbars*/ - lv_draw_rect_dsc_t rect_dsc; - lv_draw_rect_dsc_init(&rect_dsc); - lv_obj_init_draw_rect_dsc(page, LV_PAGE_PART_SCROLLBAR, &rect_dsc); - if(ext->scrlbar.hor_draw && (ext->scrlbar.mode & LV_SCROLLBAR_MODE_HIDE) == 0) { - lv_draw_rect(&sb_hor_area, clip_area, &rect_dsc); - } - - if(ext->scrlbar.ver_draw && (ext->scrlbar.mode & LV_SCROLLBAR_MODE_HIDE) == 0) { - lv_draw_rect(&sb_ver_area, clip_area, &rect_dsc); - } - } - -#if LV_USE_ANIMATION - { - - - if(ext->edge_flash.left_ip || ext->edge_flash.right_ip || ext->edge_flash.top_ip || - ext->edge_flash.bottom_ip) { - lv_area_t flash_area; - get_edge_flash_area(page, &flash_area, ext->edge_flash.state); - - lv_draw_rect_dsc_t edge_draw_dsc; - lv_draw_rect_dsc_init(&edge_draw_dsc); - lv_obj_init_draw_rect_dsc(page, LV_PAGE_PART_EDGE_FLASH, &edge_draw_dsc); - edge_draw_dsc.radius = LV_RADIUS_CIRCLE; - uint32_t opa = (edge_draw_dsc.bg_opa * ext->edge_flash.state) / LV_PAGE_END_FLASH_SIZE; - edge_draw_dsc.bg_opa = opa; - lv_draw_rect(&flash_area, clip_area, &edge_draw_dsc); - } - } -#endif - } - - return LV_DESIGN_RES_OK; -} - -/** - * Signal function of the page - * @param page pointer to a page object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) -{ - lv_res_t res; - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_page_get_style(page, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(page, sign, param); - } - else if(sign == LV_SIGNAL_GET_STATE_DSC) { - lv_get_state_info_t * info = param; - if(info->part == LV_PAGE_PART_SCROLLABLE) info->result = lv_obj_get_state(lv_page_get_scrollable(page), - LV_CONT_PART_MAIN); - else info->result = lv_obj_get_state(page, info->part); - return LV_RES_OK; - } - - /* Include the ancient signal function */ - res = ancestor_signal(page, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - if(sign == LV_SIGNAL_CLEANUP) { - /*Check whether the object being deleted is propagating scroll to the parent */ - if(ext->scroll_prop) { - lv_obj_t * parent_page = lv_obj_get_parent(lv_obj_get_parent(page)); - lv_page_ext_t * parent_ext = lv_obj_get_ext_attr(parent_page); - if(parent_ext->scroll_prop_obj == page) { - parent_ext->scroll_prop_obj = NULL; - } - } - - lv_obj_clean_style_list(page, LV_PAGE_PART_SCROLLBAR); -#if LV_USE_ANIMATION - lv_obj_clean_style_list(page, LV_PAGE_PART_EDGE_FLASH); -#endif - } - /*Automatically move children to the scrollable object*/ - else if(sign == LV_SIGNAL_CHILD_CHG) { - lv_obj_t * child; - if(ext->scrl == NULL) return LV_RES_OK; - - lv_fit_t fit_left = lv_page_get_scrl_fit_left(page); - lv_fit_t fit_right = lv_page_get_scrl_fit_right(page); - lv_fit_t fit_top = lv_page_get_scrl_fit_top(page); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(page); - - lv_style_int_t scrl_left = lv_obj_get_style_pad_left(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_right = lv_obj_get_style_pad_right(ext->scrl, LV_CONT_PART_MAIN); - lv_style_int_t scrl_top = lv_obj_get_style_pad_top(ext->scrl, LV_CONT_PART_MAIN); - - child = lv_obj_get_child(page, NULL); - while(child != NULL) { - if(lv_obj_is_protected(child, LV_PROTECT_PARENT) == false) { - lv_obj_t * tmp = child; - child = lv_obj_get_child(page, child); /*Get the next child before move this*/ - - /* Reposition the child to take padding into account - * It's required to keep new the object on the same coordinate if FIT is enabled.*/ - if((tmp->coords.x1 == page->coords.x1) && - (fit_left == LV_FIT_TIGHT || fit_left == LV_FIT_MAX) && - base_dir != LV_BIDI_DIR_RTL) { - tmp->coords.x1 += scrl_left; - tmp->coords.x2 += scrl_left; - } - else if((tmp->coords.x2 == page->coords.x2) && - (fit_right == LV_FIT_TIGHT || fit_right == LV_FIT_MAX) - && base_dir == LV_BIDI_DIR_RTL) { - tmp->coords.x1 -= scrl_right; - tmp->coords.x2 -= scrl_right; - } - if((tmp->coords.y1 == page->coords.y1) && (fit_top == LV_FIT_TIGHT || fit_top == LV_FIT_MAX)) { - tmp->coords.y1 += scrl_top; - tmp->coords.y2 += scrl_top; - } - lv_obj_set_parent(tmp, ext->scrl); - } - else { - child = lv_obj_get_child(page, child); - } - } - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - lv_style_int_t sb_width = lv_obj_get_style_size(page, LV_PAGE_PART_SCROLLBAR); - lv_area_set_height(&ext->scrlbar.hor_area, sb_width); - lv_area_set_width(&ext->scrlbar.ver_area, sb_width); - - /*The scrollbars are important only if they are visible now*/ - if(ext->scrlbar.hor_draw || ext->scrlbar.ver_draw) scrlbar_refresh(page); - - /*Refresh the ext. size because the scrollbars might be positioned out of the page*/ - refr_ext_draw_pad(page); - } - else if(sign == LV_SIGNAL_COORD_CHG) { - /*Refresh the scrollbar and notify the scrl if the size is changed*/ - if(ext->scrl != NULL && (lv_obj_get_width(page) != lv_area_get_width(param) || - lv_obj_get_height(page) != lv_area_get_height(param))) { - ext->scrl->signal_cb(ext->scrl, LV_SIGNAL_COORD_CHG, &ext->scrl->coords); - - /*The scrollbars are important only if they are visible now*/ - if(ext->scrlbar.hor_draw || ext->scrlbar.ver_draw) scrlbar_refresh(page); - } - } - else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - refr_ext_draw_pad(page); - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - uint32_t c = *((uint32_t *)param); - - if(c == LV_KEY_DOWN) { - lv_page_scroll_ver(page, -lv_obj_get_height(page) / 4); - } - else if(c == LV_KEY_UP) { - lv_page_scroll_ver(page, lv_obj_get_height(page) / 4); - } - else if(c == LV_KEY_RIGHT) { - /*If the page can't be scrolled horizontally because it's not wide enough then scroll it - * vertically*/ - if(lv_page_get_scrl_width(page) <= lv_obj_get_width(page)) - lv_page_scroll_ver(page, -lv_obj_get_height(page) / 4); - else - lv_page_scroll_hor(page, -lv_obj_get_width(page) / 4); - } - else if(c == LV_KEY_LEFT) { - /*If the page can't be scrolled horizontally because it's not wide enough then scroll it - * vertically*/ - if(lv_page_get_scrl_width(page) <= lv_obj_get_width(page)) - lv_page_scroll_ver(page, lv_obj_get_height(page) / 4); - else - lv_page_scroll_hor(page, lv_obj_get_width(page) / 4); - } -#endif - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } - - return res; -} - -/** - * Signal function of the scrollable part of a page - * @param scrl pointer to the scrollable object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void * param) -{ - - if(sign == LV_SIGNAL_GET_STYLE) { - return ancestor_signal(scrl, sign, param); - } - - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(scrl, sign, param); - - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, ""); - - lv_obj_t * page = lv_obj_get_parent(scrl); - lv_page_ext_t * page_ext = lv_obj_get_ext_attr(page); - - if(sign == LV_SIGNAL_COORD_CHG) { - lv_obj_t * page_parent = lv_obj_get_parent(page); - - /*Handle scroll propagation*/ - lv_indev_t * indev = lv_indev_get_act(); - if(page_ext->scroll_prop && indev) { - lv_point_t * drag_sum = &indev->proc.types.pointer.drag_sum; - lv_page_ext_t * parent_ext = lv_obj_get_ext_attr(lv_obj_get_parent(page_parent)); - if(parent_ext->scroll_prop_obj == NULL) { - /*If the dragging just started or scroll is already propagated to this object - * enable the scroll propagation if the conditions are met*/ - if((lv_indev_is_scrolling(indev) == false || page_ext->scroll_prop_obj) && (drag_sum->y || drag_sum->x)) { - /*Propagate vertically?*/ - if((drag_sum->y > 0 && lv_page_on_edge(page, LV_PAGE_EDGE_TOP)) || - (drag_sum->y < 0 && lv_page_on_edge(page, LV_PAGE_EDGE_BOTTOM))) { - lv_obj_set_drag_parent(page, true); - lv_obj_set_drag_parent(scrl, true); - parent_ext->scroll_prop_obj = page; - } - /*Propagate horizontally?*/ - if((drag_sum->x > 0 && lv_page_on_edge(page, LV_PAGE_EDGE_LEFT)) || - (drag_sum->x < 0 && lv_page_on_edge(page, LV_PAGE_EDGE_RIGHT))) { - lv_obj_set_drag_parent(page, true); - lv_obj_set_drag_parent(scrl, true); - parent_ext->scroll_prop_obj = page; - } - } - } - } - - scrl_reposition(page); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - - /*The scrollbars are important only if they are visible now or the scrollable's size has changed*/ - if((ext->scrlbar.hor_draw || ext->scrlbar.ver_draw) || - (lv_obj_get_width(scrl) != lv_area_get_width(param) || lv_obj_get_height(scrl) != lv_area_get_height(param))) { - scrlbar_refresh(page); - } - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - scrl_reposition(page); - scrlbar_refresh(page); - } - else if(sign == LV_SIGNAL_DRAG_BEGIN) { - if(page_ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) { - scrlbar_refresh(page); - } - } - else if(sign == LV_SIGNAL_DRAG_END) { - /*Scroll propagation is finished on drag end*/ - if(page_ext->scroll_prop_obj) { - lv_obj_t * scroller_page = page_ext->scroll_prop_obj; - lv_page_ext_t * scroller_page_ext = lv_obj_get_ext_attr(scroller_page); - page_ext->scroll_prop_obj = NULL; - lv_obj_set_drag_parent(scroller_page, false); - lv_obj_set_drag_parent(lv_page_get_scrollable(scroller_page), false); - - /*Hide scrollbars if required*/ - if(scroller_page_ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) { - lv_area_t sb_area_tmp; - if(scroller_page_ext->scrlbar.hor_draw) { - lv_area_copy(&sb_area_tmp, &scroller_page_ext->scrlbar.hor_area); - sb_area_tmp.x1 += scroller_page->coords.x1; - sb_area_tmp.y1 += scroller_page->coords.y1; - sb_area_tmp.x2 += scroller_page->coords.x1; - sb_area_tmp.y2 += scroller_page->coords.y1; - lv_obj_invalidate_area(scroller_page, &sb_area_tmp); - scroller_page_ext->scrlbar.hor_draw = 0; - } - if(scroller_page_ext->scrlbar.ver_draw) { - lv_area_copy(&sb_area_tmp, &scroller_page_ext->scrlbar.ver_area); - sb_area_tmp.x1 += scroller_page->coords.x1; - sb_area_tmp.y1 += scroller_page->coords.y1; - sb_area_tmp.x2 += scroller_page->coords.x1; - sb_area_tmp.y2 += scroller_page->coords.y1; - lv_obj_invalidate_area(scroller_page, &sb_area_tmp); - scroller_page_ext->scrlbar.ver_draw = 0; - } - } - - /*The scrolling can be chained so stop all of them*/ - lv_page_ext_t * scroller_ext = lv_obj_get_ext_attr(scroller_page); - while(scroller_ext->scroll_prop_obj) { - scroller_page = scroller_ext->scroll_prop_obj; - scroller_ext->scroll_prop_obj = NULL; - lv_obj_set_drag_parent(scroller_page, false); - lv_obj_set_drag_parent(lv_page_get_scrollable(scroller_page), false); - - /*Hide scrollbars if required*/ - if(scroller_page_ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) { - scroller_page_ext->scrlbar.hor_draw = 0; - scroller_page_ext->scrlbar.ver_draw = 0; - lv_obj_invalidate(scroller_page); - } - scroller_ext = lv_obj_get_ext_attr(scroller_page); - } - } - - /*Hide scrollbars if required*/ - if(page_ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) { - lv_area_t sb_area_tmp; - if(page_ext->scrlbar.hor_draw) { - lv_area_copy(&sb_area_tmp, &page_ext->scrlbar.hor_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - page_ext->scrlbar.hor_draw = 0; - } - if(page_ext->scrlbar.ver_draw) { - lv_area_copy(&sb_area_tmp, &page_ext->scrlbar.ver_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - page_ext->scrlbar.ver_draw = 0; - } - } - } - else if(sign == LV_SIGNAL_CLEANUP) { - page_ext->scrl = NULL; - - } - return res; -} - -/** - * Propagate the input device related event of the scrollable to the parent page background - * It is used by default if the scrollable's event is not specified - * @param scrl pointer to the page's scrollable object - * @param event type of the event - * @param data data of the event - */ -static void scrl_def_event_cb(lv_obj_t * scrl, lv_event_t event) -{ - lv_obj_t * page = lv_obj_get_parent(scrl); - - /*clang-format off*/ - if(event == LV_EVENT_PRESSED || event == LV_EVENT_PRESSING || event == LV_EVENT_PRESS_LOST || - event == LV_EVENT_RELEASED || event == LV_EVENT_SHORT_CLICKED || event == LV_EVENT_CLICKED || - event == LV_EVENT_LONG_PRESSED || event == LV_EVENT_LONG_PRESSED_REPEAT || - event == LV_EVENT_DRAG_BEGIN || event == LV_EVENT_DRAG_END || event == LV_EVENT_DRAG_THROW_BEGIN) { - lv_event_send(page, event, lv_event_get_data()); - } - /*clang-format on*/ -} - -/** - * Get the style descriptor of a part of the object - * @param page pointer the object - * @param part the part of the page. (LV_PAGE_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_page_get_style(lv_obj_t * page, uint8_t part) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_PAGE_PART_BG: - style_dsc_p = &page->style_list; - break; - case LV_PAGE_PART_SCROLLABLE: - style_dsc_p = lv_obj_get_style_list(ext->scrl, LV_CONT_PART_MAIN); - break; - case LV_PAGE_PART_SCROLLBAR: - style_dsc_p = &ext->scrlbar.style; - break; -#if LV_USE_ANIMATION - case LV_PAGE_PART_EDGE_FLASH: - style_dsc_p = &ext->edge_flash.style; - break; -#endif - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - -static void scrl_reposition(lv_obj_t * page) -{ - /*Limit the position of the scrollable object to be always visible - * (Do not let its edge inner then its parent respective edge)*/ - lv_obj_t * scrl = lv_page_get_scrollable(page); - lv_coord_t new_x = lv_obj_get_x(scrl); - lv_coord_t new_y = lv_obj_get_y(scrl); - bool refr_x = false; - bool refr_y = false; - lv_area_t page_coords; - lv_area_t scrl_coords; - lv_obj_get_coords(scrl, &scrl_coords); - lv_obj_get_coords(page, &page_coords); - - lv_style_int_t left = lv_obj_get_style_pad_left(page, LV_PAGE_PART_BG); - lv_style_int_t right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_BG); - lv_style_int_t top = lv_obj_get_style_pad_top(page, LV_PAGE_PART_BG); - lv_style_int_t bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_BG); - - /*scrollable width smaller then page width? -> align to left*/ - if(lv_area_get_width(&scrl_coords) + left + right <= lv_area_get_width(&page_coords)) { - if(scrl_coords.x1 != page_coords.x1 + left) { - new_x = left; - refr_x = true; - } - } - else { - /*The edges of the scrollable can not be in the page (minus hpad) */ - if(scrl_coords.x2 < page_coords.x2 - right) { - new_x = lv_area_get_width(&page_coords) - lv_area_get_width(&scrl_coords) - right; /* Right align */ - refr_x = true; - lv_page_start_edge_flash(page, LV_PAGE_EDGE_RIGHT); - } - else if(scrl_coords.x1 > page_coords.x1 + left) { - new_x = left; /*Left align*/ - refr_x = true; - lv_page_start_edge_flash(page, LV_PAGE_EDGE_LEFT); - } - } - - /*scrollable height smaller then page height? -> align to top*/ - if(lv_area_get_height(&scrl_coords) + top + bottom <= lv_area_get_height(&page_coords)) { - if(scrl_coords.y1 != page_coords.y1 + top) { - new_y = top; - refr_y = true; - } - } - else { - /*The edges of the scrollable can not be in the page (minus vpad) */ - if(scrl_coords.y2 < page_coords.y2 - bottom) { - new_y = lv_area_get_height(&page_coords) - lv_area_get_height(&scrl_coords) - bottom; /* Bottom align */ - refr_y = true; - lv_page_start_edge_flash(page, LV_PAGE_EDGE_BOTTOM); - } - else if(scrl_coords.y1 > page_coords.y1 + top) { - new_y = top; /*Top align*/ - refr_y = true; - lv_page_start_edge_flash(page, LV_PAGE_EDGE_TOP); - } - } - - if(refr_x || refr_y) { - lv_obj_set_pos(scrl, new_x, new_y); - } -} - -/** - * Refresh the position and size of the scroll bars. - * @param page pointer to a page object - */ -static void scrlbar_refresh(lv_obj_t * page) -{ - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - lv_obj_t * scrl = ext->scrl; - lv_coord_t size_tmp; - lv_coord_t scrl_w = lv_obj_get_width(scrl); - lv_coord_t scrl_h = lv_obj_get_height(scrl); - lv_coord_t obj_w = lv_obj_get_width(page); - lv_coord_t obj_h = lv_obj_get_height(page); - - lv_style_int_t sb_width = lv_obj_get_style_size(page, LV_PAGE_PART_SCROLLBAR); - lv_style_int_t sb_right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_SCROLLBAR); - lv_style_int_t sb_bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_SCROLLBAR); - - lv_style_int_t bg_left = lv_obj_get_style_pad_left(page, LV_PAGE_PART_BG); - lv_style_int_t bg_right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_BG); - lv_style_int_t bg_top = lv_obj_get_style_pad_top(page, LV_PAGE_PART_BG); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_BG); - - /*Always let 'scrollbar width' padding above, under, left and right to the scrollbars - * else: - * - horizontal and vertical scrollbars can overlap on the corners - * - if the page has radius the scrollbar can be out of the radius */ - lv_coord_t sb_hor_pad = LV_MATH_MAX(sb_width, sb_right); - lv_coord_t sb_ver_pad = LV_MATH_MAX(sb_width, sb_bottom); - - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_OFF) return; - - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_ON) { - ext->scrlbar.hor_draw = 1; - ext->scrlbar.ver_draw = 1; - } - - /*Invalidate the current (old) scrollbar areas*/ - lv_area_t sb_area_tmp; - if(ext->scrlbar.hor_draw != 0) { - lv_area_copy(&sb_area_tmp, &ext->scrlbar.hor_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - } - if(ext->scrlbar.ver_draw != 0) { - lv_area_copy(&sb_area_tmp, &ext->scrlbar.ver_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - } - - /*Full sized horizontal scrollbar*/ - if(scrl_w <= obj_w - bg_left - bg_right) { - lv_area_set_width(&ext->scrlbar.hor_area, obj_w - 2 * sb_hor_pad); - _lv_area_set_pos(&ext->scrlbar.hor_area, sb_hor_pad, - obj_h - sb_width - sb_bottom); - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_AUTO || - ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) ext->scrlbar.hor_draw = 0; - } - /*Smaller horizontal scrollbar*/ - else { - size_tmp = - (obj_w * (obj_w - (2 * sb_hor_pad))) / (scrl_w + bg_left + bg_right); - if(size_tmp < LV_PAGE_SB_MIN_SIZE) size_tmp = LV_PAGE_SB_MIN_SIZE; - lv_area_set_width(&ext->scrlbar.hor_area, size_tmp); - - _lv_area_set_pos(&ext->scrlbar.hor_area, - sb_hor_pad + - (-(lv_obj_get_x(scrl) - bg_left) * (obj_w - size_tmp - 2 * sb_hor_pad)) / - (scrl_w + bg_left + bg_right - obj_w), - obj_h - sb_width - sb_bottom); - - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_AUTO || - ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) ext->scrlbar.hor_draw = 1; - } - - /*Full sized vertical scroll bar*/ - if(scrl_h <= obj_h - bg_top - bg_bottom) { - lv_area_set_height(&ext->scrlbar.ver_area, obj_h - 2 * sb_ver_pad); - _lv_area_set_pos(&ext->scrlbar.ver_area, - obj_w - sb_width - sb_right, sb_ver_pad); - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_AUTO || - ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) ext->scrlbar.ver_draw = 0; - } - /*Smaller vertical scroll bar*/ - else { - size_tmp = - (obj_h * (obj_h - (2 * sb_ver_pad))) / (scrl_h + bg_top + bg_bottom); - if(size_tmp < LV_PAGE_SB_MIN_SIZE) size_tmp = LV_PAGE_SB_MIN_SIZE; - lv_area_set_height(&ext->scrlbar.ver_area, size_tmp); - - _lv_area_set_pos(&ext->scrlbar.ver_area, - obj_w - sb_width - sb_right, - sb_ver_pad + (-(lv_obj_get_y(scrl) - bg_left) * - (obj_h - size_tmp - 2 * sb_ver_pad)) / - (scrl_h + bg_top + bg_bottom - obj_h)); - - if(ext->scrlbar.mode == LV_SCROLLBAR_MODE_AUTO || - ext->scrlbar.mode == LV_SCROLLBAR_MODE_DRAG) ext->scrlbar.ver_draw = 1; - } - - /*Invalidate the new scrollbar areas*/ - if(ext->scrlbar.hor_draw != 0) { - lv_area_copy(&sb_area_tmp, &ext->scrlbar.hor_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - } - if(ext->scrlbar.ver_draw != 0) { - lv_area_copy(&sb_area_tmp, &ext->scrlbar.ver_area); - sb_area_tmp.x1 += page->coords.x1; - sb_area_tmp.y1 += page->coords.y1; - sb_area_tmp.x2 += page->coords.x1; - sb_area_tmp.y2 += page->coords.y1; - lv_obj_invalidate_area(page, &sb_area_tmp); - } -} - -static void refr_ext_draw_pad(lv_obj_t * page) -{ - lv_style_int_t sb_bottom = lv_obj_get_style_pad_bottom(page, LV_PAGE_PART_SCROLLBAR); - lv_style_int_t sb_right = lv_obj_get_style_pad_right(page, LV_PAGE_PART_SCROLLBAR); - - /*Ensure ext. size for the scrollbars if they are out of the page*/ - if(page->ext_draw_pad < (-sb_right)) page->ext_draw_pad = -sb_right; - if(page->ext_draw_pad < (-sb_bottom)) page->ext_draw_pad = -sb_bottom; -} - -#if LV_USE_ANIMATION -static void edge_flash_anim(void * page, lv_anim_value_t v) -{ - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - ext->edge_flash.state = v; - - lv_area_t flash_area; - get_edge_flash_area(page, &flash_area, LV_PAGE_END_FLASH_SIZE); - lv_obj_invalidate_area(page, &flash_area); -} - -static void edge_flash_anim_end(lv_anim_t * a) -{ - lv_area_t flash_area; - get_edge_flash_area(a->var, &flash_area, LV_PAGE_END_FLASH_SIZE); - lv_obj_invalidate_area(a->var, &flash_area); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(a->var); - ext->edge_flash.top_ip = 0; - ext->edge_flash.bottom_ip = 0; - ext->edge_flash.left_ip = 0; - ext->edge_flash.right_ip = 0; - -} - -static void get_edge_flash_area(lv_obj_t * page, lv_area_t * flash_area, lv_coord_t state) -{ - lv_coord_t page_w = lv_obj_get_width(page); - lv_coord_t page_h = lv_obj_get_height(page); - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - - if(ext->edge_flash.top_ip) { - flash_area->x1 = page->coords.x1 - page_w; - flash_area->x2 = page->coords.x2 + page_w; - flash_area->y1 = page->coords.y1 - 3 * page_w + state; - flash_area->y2 = page->coords.y1 + state; - } - else if(ext->edge_flash.bottom_ip) { - flash_area->x1 = page->coords.x1 - page_w; - flash_area->x2 = page->coords.x2 + page_w; - flash_area->y1 = page->coords.y2 - state; - flash_area->y2 = page->coords.y2 + 3 * page_w - state; - } - else if(ext->edge_flash.right_ip) { - flash_area->x1 = page->coords.x2 - state; - flash_area->x2 = page->coords.x2 + 3 * page_h - state; - flash_area->y1 = page->coords.y1 - page_h; - flash_area->y2 = page->coords.y2 + page_h; - } - else if(ext->edge_flash.left_ip) { - flash_area->x1 = page->coords.x1 - 3 * page_h + state; - flash_area->x2 = page->coords.x1 + state; - flash_area->y1 = page->coords.y1 - page_h; - flash_area->y2 = page->coords.y2 + page_h; - } - else { - lv_area_set(flash_area, 0, 0, -1, -1); - } -} - -#endif - -#endif diff --git a/src/lv_widgets/lv_page.h b/src/lv_widgets/lv_page.h deleted file mode 100644 index 387afc6e7..000000000 --- a/src/lv_widgets/lv_page.h +++ /dev/null @@ -1,427 +0,0 @@ -/** - * @file lv_page.h - * - */ - -#ifndef LV_PAGE_H -#define LV_PAGE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_PAGE != 0 - -/*Testing of dependencies*/ -#if LV_USE_CONT == 0 -#error "lv_page: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) " -#endif - -#include "lv_cont.h" -#include "../lv_core/lv_indev.h" -#include "../lv_misc/lv_anim.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** Scrollbar modes: shows when should the scrollbars be visible*/ -enum { - LV_SCROLLBAR_MODE_OFF = 0x0, /**< Never show scroll bars*/ - LV_SCROLLBAR_MODE_ON = 0x1, /**< Always show scroll bars*/ - LV_SCROLLBAR_MODE_DRAG = 0x2, /**< Show scroll bars when page is being dragged*/ - LV_SCROLLBAR_MODE_AUTO = 0x3, /**< Show scroll bars when the scrollable container is large enough to be scrolled*/ - LV_SCROLLBAR_MODE_HIDE = 0x4, /**< Hide the scroll bar temporally*/ - LV_SCROLLBAR_MODE_UNHIDE = 0x8, /**< Unhide the previously hidden scroll bar. Recover original mode too*/ -}; -typedef uint8_t lv_scrollbar_mode_t; - -/** Edges: describes the four edges of the page*/ -enum { LV_PAGE_EDGE_LEFT = 0x1, LV_PAGE_EDGE_TOP = 0x2, LV_PAGE_EDGE_RIGHT = 0x4, LV_PAGE_EDGE_BOTTOM = 0x8 }; -typedef uint8_t lv_page_edge_t; - -/*Data of page*/ -typedef struct { - lv_cont_ext_t bg; /*Ext. of ancestor*/ - /*New data for this type */ - lv_obj_t * scrl; /*The scrollable object on the background*/ - struct { - lv_style_list_t style; /*Style of scrollbars*/ - lv_area_t hor_area; /*Horizontal scrollbar area relative to the page. (Handled by the library) */ - lv_area_t ver_area; /*Vertical scrollbar area relative to the page (Handled by the library)*/ - uint8_t hor_draw : 1; /*1: horizontal scrollbar is visible now (Handled by the library)*/ - uint8_t ver_draw : 1; /*1: vertical scrollbar is visible now (Handled by the library)*/ - lv_scrollbar_mode_t mode : 3; /*Scrollbar visibility from 'lv_scrollbar_mode_t'*/ - } scrlbar; -#if LV_USE_ANIMATION - struct { - lv_anim_value_t state; /*Store the current size of the edge flash effect*/ - lv_style_list_t style; /*Style of edge flash effect (usually homogeneous circle)*/ - uint8_t enabled : 1; /*1: Show a flash animation on the edge*/ - uint8_t top_ip : 1; /*Used internally to show that top most position is reached (flash is In - Progress)*/ - uint8_t bottom_ip : 1; /*Used internally to show that bottom most position is reached (flash - is In Progress)*/ - uint8_t right_ip : 1; /*Used internally to show that right most position is reached (flash - is In Progress)*/ - uint8_t left_ip : 1; /*Used internally to show that left most position is reached (flash is - In Progress)*/ - } edge_flash; - - uint16_t anim_time; /*Scroll animation time*/ -#endif - lv_obj_t * scroll_prop_obj; /*Pointer to child page from where the scroll is being propagated */ - uint8_t scroll_prop : 1; /*The direction of the scroll propagation*/ -} lv_page_ext_t; - -enum { - LV_PAGE_PART_BG = LV_CONT_PART_MAIN, - LV_PAGE_PART_SCROLLBAR = _LV_OBJ_PART_VIRTUAL_LAST, - LV_PAGE_PART_EDGE_FLASH, - _LV_PAGE_PART_VIRTUAL_LAST, - - LV_PAGE_PART_SCROLLABLE = _LV_OBJ_PART_REAL_LAST, - _LV_PAGE_PART_REAL_LAST, -}; -typedef uint8_t lv_part_style_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a page objects - * @param par pointer to an object, it will be the parent of the new page - * @param copy pointer to a page object, if not NULL then the new object will be copied from it - * @return pointer to the created page - */ -lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy); - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param page pointer to an object - */ -void lv_page_clean(lv_obj_t * page); - -/** - * Get the scrollable object of a page - * @param page pointer to a page object - * @return pointer to a container which is the scrollable part of the page - */ -lv_obj_t * lv_page_get_scrollable(const lv_obj_t * page); - -/** - * Get the animation time - * @param page pointer to a page object - * @return the animation time in milliseconds - */ -uint16_t lv_page_get_anim_time(const lv_obj_t * page); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the scroll bar mode on a page - * @param page pointer to a page object - * @param sb_mode the new mode from 'lv_page_sb.mode_t' enum - */ -void lv_page_set_scrollbar_mode(lv_obj_t * page, lv_scrollbar_mode_t sb_mode); - -/** - * Set the animation time for the page - * @param page pointer to a page object - * @param anim_time animation time in milliseconds - */ -void lv_page_set_anim_time(lv_obj_t * page, uint16_t anim_time); - -/** - * Enable the scroll propagation feature. If enabled then the page will move its parent if there is - * no more space to scroll. - * The page needs to have a page-like parent (e.g. `lv_page`, `lv_tabview` tab, `lv_win` content area etc) - * If enabled drag direction will be changed `LV_DRAG_DIR_ONE` automatically to allow scrolling only in one direction at one time. - * @param page pointer to a Page - * @param en true or false to enable/disable scroll propagation - */ -void lv_page_set_scroll_propagation(lv_obj_t * page, bool en); - -/** - * Enable the edge flash effect. (Show an arc when the an edge is reached) - * @param page pointer to a Page - * @param en true or false to enable/disable end flash - */ -void lv_page_set_edge_flash(lv_obj_t * page, bool en); - -/** - * Set the fit policy in all 4 directions separately. - * It tell how to change the page size automatically. - * @param page pointer to a page object - * @param left left fit policy from `lv_fit_t` - * @param right right fit policy from `lv_fit_t` - * @param top bottom fit policy from `lv_fit_t` - * @param bottom bottom fit policy from `lv_fit_t` - */ -static inline void lv_page_set_scrollable_fit4(lv_obj_t * page, lv_fit_t left, lv_fit_t right, lv_fit_t top, - lv_fit_t bottom) -{ - lv_cont_set_fit4(lv_page_get_scrollable(page), left, right, top, bottom); -} - -/** - * Set the fit policy horizontally and vertically separately. - * It tell how to change the page size automatically. - * @param page pointer to a page object - * @param hot horizontal fit policy from `lv_fit_t` - * @param ver vertical fit policy from `lv_fit_t` - */ -static inline void lv_page_set_scrollable_fit2(lv_obj_t * page, lv_fit_t hor, lv_fit_t ver) -{ - lv_cont_set_fit2(lv_page_get_scrollable(page), hor, ver); -} - -/** - * Set the fit policy in all 4 direction at once. - * It tell how to change the page size automatically. - * @param page pointer to a button object - * @param fit fit policy from `lv_fit_t` - */ -static inline void lv_page_set_scrollable_fit(lv_obj_t * page, lv_fit_t fit) -{ - lv_cont_set_fit(lv_page_get_scrollable(page), fit); -} - -/** - * Set width of the scrollable part of a page - * @param page pointer to a page object - * @param w the new width of the scrollable (it ha no effect is horizontal fit is enabled) - */ -static inline void lv_page_set_scrl_width(lv_obj_t * page, lv_coord_t w) -{ - lv_obj_set_width(lv_page_get_scrollable(page), w); -} - -/** - * Set height of the scrollable part of a page - * @param page pointer to a page object - * @param h the new height of the scrollable (it ha no effect is vertical fit is enabled) - */ -static inline void lv_page_set_scrl_height(lv_obj_t * page, lv_coord_t h) -{ - lv_obj_set_height(lv_page_get_scrollable(page), h); -} - -/** - * Set the layout of the scrollable part of the page - * @param page pointer to a page object - * @param layout a layout from 'lv_cont_layout_t' - */ -static inline void lv_page_set_scrl_layout(lv_obj_t * page, lv_layout_t layout) -{ - lv_cont_set_layout(lv_page_get_scrollable(page), layout); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Set the scroll bar mode on a page - * @param page pointer to a page object - * @return the mode from 'lv_page_sb.mode_t' enum - */ -lv_scrollbar_mode_t lv_page_get_scrollbar_mode(const lv_obj_t * page); - -/** - * Get the scroll propagation property - * @param page pointer to a Page - * @return true or false - */ -bool lv_page_get_scroll_propagation(lv_obj_t * page); - -/** - * Get the edge flash effect property. - * @param page pointer to a Page - * return true or false - */ -bool lv_page_get_edge_flash(lv_obj_t * page); - -/** - * Get that width which can be set to the children to still not cause overflow (show scrollbars) - * @param page pointer to a page object - * @return the width which still fits into the page - */ -lv_coord_t lv_page_get_width_fit(lv_obj_t * page); - -/** - * Get that height which can be set to the children to still not cause overflow (show scrollbars) - * @param page pointer to a page object - * @return the height which still fits into the page - */ -lv_coord_t lv_page_get_height_fit(lv_obj_t * page); - -/** - * Divide the width of the object and get the width of a given number of columns. - * Take into account the paddings of the background and scrollable too. - * @param page pointer to an object - * @param div indicates how many columns are assumed. - * If 1 the width will be set the the parent's width - * If 2 only half parent width - inner padding of the parent - * If 3 only third parent width - 2 * inner padding of the parent - * @param span how many columns are combined - * @return the width according to the given parameters - */ -lv_coord_t lv_page_get_width_grid(lv_obj_t * page, uint8_t div, uint8_t span); - -/** - * Divide the height of the object and get the width of a given number of columns. - * Take into account the paddings of the background and scrollable too. - * @param page pointer to an object - * @param div indicates how many rows are assumed. - * If 1 the height will be set the the parent's height - * If 2 only half parent height - inner padding of the parent - * If 3 only third parent height - 2 * inner padding of the parent - * @param span how many rows are combined - * @return the height according to the given parameters - */ -lv_coord_t lv_page_get_height_grid(lv_obj_t * page, uint8_t div, uint8_t span); - -/** - * Get width of the scrollable part of a page - * @param page pointer to a page object - * @return the width of the scrollable - */ -static inline lv_coord_t lv_page_get_scrl_width(const lv_obj_t * page) -{ - return lv_obj_get_width(lv_page_get_scrollable(page)); -} - -/** - * Get height of the scrollable part of a page - * @param page pointer to a page object - * @return the height of the scrollable - */ -static inline lv_coord_t lv_page_get_scrl_height(const lv_obj_t * page) -{ - return lv_obj_get_height(lv_page_get_scrollable(page)); -} - -/** - * Get the layout of the scrollable part of a page - * @param page pointer to page object - * @return the layout from 'lv_cont_layout_t' - */ -static inline lv_layout_t lv_page_get_scrl_layout(const lv_obj_t * page) -{ - return lv_cont_get_layout(lv_page_get_scrollable(page)); -} - -/** - * Get the left fit mode - * @param page pointer to a page object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_page_get_scrl_fit_left(const lv_obj_t * page) -{ - return lv_cont_get_fit_left(lv_page_get_scrollable(page)); -} - -/** - * Get the right fit mode - * @param page pointer to a page object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_page_get_scrl_fit_right(const lv_obj_t * page) -{ - return lv_cont_get_fit_right(lv_page_get_scrollable(page)); -} - -/** - * Get the top fit mode - * @param page pointer to a page object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_page_get_scrl_fit_top(const lv_obj_t * page) -{ - return lv_cont_get_fit_top(lv_page_get_scrollable(page)); -} - -/** - * Get the bottom fit mode - * @param page pointer to a page object - * @return an element of `lv_fit_t` - */ -static inline lv_fit_t lv_page_get_scrl_fit_bottom(const lv_obj_t * page) -{ - return lv_cont_get_fit_bottom(lv_page_get_scrollable(page)); -} - -/*===================== - * Other functions - *====================*/ - -/** - * Find whether the page has been scrolled to a certain edge. - * @param page Page object - * @param edge Edge to check - * @return true if the page is on the specified edge - */ -bool lv_page_on_edge(lv_obj_t * page, lv_page_edge_t edge); - -/** - * Glue the object to the page. After it the page can be moved (dragged) with this object too. - * @param page pointer to a page object - * @param obj pointer to an object on a page - * @param glue true: enable glue, false: disable glue - */ -void lv_page_glue_obj(lv_obj_t * page, lv_obj_t * obj, bool glue); - -/** - * Focus on an object. It ensures that the object will be visible on the page. - * @param page pointer to a page object - * @param obj pointer to an object to focus (must be on the page) - * @param anim_en LV_ANIM_ON to focus with animation; LV_ANIM_OFF to focus without animation - */ -void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, lv_anim_enable_t anim_en); - -/** - * Scroll the page horizontally - * @param page pointer to a page object - * @param dist the distance to scroll (< 0: scroll left; > 0 scroll right) - */ -void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist); - -/** - * Scroll the page vertically - * @param page pointer to a page object - * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) - */ -void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist); - -/** - * Not intended to use directly by the user but by other object types internally. - * Start an edge flash animation. - * @param page - * @param edge the edge to flash. Can be `LV_PAGE_EDGE_LEFT/RIGHT/TOP/BOTTOM` - */ -void lv_page_start_edge_flash(lv_obj_t * page, lv_page_edge_t edge); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_PAGE*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_PAGE_H*/ diff --git a/src/lv_widgets/lv_spinbox.c b/src/lv_widgets/lv_spinbox.c deleted file mode 100644 index 28f2de153..000000000 --- a/src/lv_widgets/lv_spinbox.c +++ /dev/null @@ -1,603 +0,0 @@ -/** - * @file lv_spinbox.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_spinbox.h" - -#if LV_USE_SPINBOX != 0 -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_math.h" -#include "../lv_misc/lv_utils.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_spinbox" - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param); -static lv_style_list_t * lv_spinbox_get_style(lv_obj_t * ta, uint8_t part); -static void lv_spinbox_updatevalue(lv_obj_t * spinbox); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a spinbox object - * @param par pointer to an object, it will be the parent of the new spinbox - * @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it - * @return pointer to the created spinbox - */ -lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("spinbox create started"); - - /*Create the ancestor of spinbox*/ - lv_obj_t * spinbox = lv_textarea_create(par, copy); - LV_ASSERT_MEM(spinbox); - if(spinbox == NULL) return NULL; - - /*Allocate the spinbox type specific extended data*/ - lv_spinbox_ext_t * ext = lv_obj_allocate_ext_attr(spinbox, sizeof(lv_spinbox_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(spinbox); - return NULL; - } - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(spinbox); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(spinbox); - - /*Initialize the allocated 'ext'*/ - ext->value = 0; - ext->dec_point_pos = 0; - ext->digit_count = 5; - ext->digit_padding_left = 0; - ext->step = 1; - ext->range_max = 99999; - ext->range_min = -99999; - ext->rollover = false; - - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(spinbox, lv_spinbox_signal); - lv_obj_set_design_cb(spinbox, ancestor_design); /*Leave the Text area's design function*/ - - /*Init the new spinbox*/ - if(copy == NULL) { - /* No scrolling will happen here so make the scrollable non-clickable - * It allows to handle input events in the bg object only.*/ - lv_obj_set_click(lv_page_get_scrollable(spinbox), false); - lv_textarea_set_one_line(spinbox, true); - lv_textarea_set_cursor_click_pos(spinbox, true); - lv_obj_set_width(spinbox, LV_DPI); - lv_theme_apply(spinbox, LV_THEME_SPINBOX); - } - /*Copy an existing spinbox*/ - else { - lv_spinbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - - lv_spinbox_set_value(spinbox, copy_ext->value); - lv_spinbox_set_digit_format(spinbox, (uint8_t)copy_ext->digit_count, (uint8_t)copy_ext->dec_point_pos); - lv_spinbox_set_range(spinbox, copy_ext->range_min, copy_ext->range_max); - lv_spinbox_set_step(spinbox, copy_ext->step); - lv_spinbox_set_rollover(spinbox, copy_ext->rollover); - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(spinbox, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - lv_spinbox_updatevalue(spinbox); - - LV_LOG_INFO("spinbox created"); - - return spinbox; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set spinbox rollover function - * @param spinbox pointer to spinbox - * @param b true or false to enable or disable (default) - */ -void lv_spinbox_set_rollover(lv_obj_t * spinbox, bool b) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - ext->rollover = b; -} - -/** - * Set spinbox value - * @param spinbox pointer to spinbox - * @param i value to be set - */ -void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - if(ext == NULL) return; - - if(i > ext->range_max) i = ext->range_max; - if(i < ext->range_min) i = ext->range_min; - - ext->value = i; - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Set spinbox digit format (digit count and decimal format) - * @param spinbox pointer to spinbox - * @param digit_count number of digit excluding the decimal separator and the sign - * @param separator_position number of digit before the decimal point. If 0, decimal point is not - * shown - */ -void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - if(ext == NULL) return; - - if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT) digit_count = LV_SPINBOX_MAX_DIGIT_COUNT; - - if(separator_position >= digit_count) separator_position = 0; - if(separator_position > LV_SPINBOX_MAX_DIGIT_COUNT) separator_position = LV_SPINBOX_MAX_DIGIT_COUNT; - - if(digit_count < LV_SPINBOX_MAX_DIGIT_COUNT) { - int64_t max_val = _lv_pow(10, digit_count); - if(ext->range_max > max_val - 1) ext->range_max = max_val - 1; - if(ext->range_min < - max_val + 1) ext->range_min = - max_val + 1; - } - - ext->digit_count = digit_count; - ext->dec_point_pos = separator_position; - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Set spinbox step - * @param spinbox pointer to spinbox - * @param step steps on increment/decrement - */ -void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - if(ext == NULL) return; - - ext->step = step; -} - -/** - * Set spinbox value range - * @param spinbox pointer to spinbox - * @param range_min maximum value, inclusive - * @param range_max minimum value, inclusive - */ -void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - if(ext == NULL) return; - - ext->range_max = range_max; - ext->range_min = range_min; - - if(ext->value > ext->range_max) { - ext->value = ext->range_max; - lv_obj_invalidate(spinbox); - } - if(ext->value < ext->range_min) { - ext->value = ext->range_min; - lv_obj_invalidate(spinbox); - } - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Set spinbox left padding in digits count (added between sign and first digit) - * @param spinbox pointer to spinbox - * @param cb Callback function called on value change event - */ -void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - ext->digit_padding_left = padding; - lv_spinbox_updatevalue(spinbox); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get spinbox rollover function status - * @param spinbox pointer to spinbox - */ -bool lv_spinbox_get_rollover(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - return ext->rollover; -} - -/** - * Get the spinbox numeral value (user has to convert to float according to its digit format) - * @param spinbox pointer to spinbox - * @return value integer value of the spinbox - */ -int32_t lv_spinbox_get_value(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - return ext->value; -} - -/*===================== - * Other functions - *====================*/ - -/** - * Select next lower digit for edition - * @param spinbox pointer to spinbox - */ -void lv_spinbox_step_next(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - int32_t new_step = ext->step / 10; - if((new_step) > 0) - ext->step = new_step; - else - ext->step = 1; - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Select next higher digit for edition - * @param spinbox pointer to spinbox - */ -void lv_spinbox_step_prev(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - int32_t step_limit; - step_limit = LV_MATH_MAX(ext->range_max, (ext->range_min < 0 ? (-ext->range_min) : ext->range_min)); - int32_t new_step = ext->step * 10; - if(new_step <= step_limit) ext->step = new_step; - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Increment spinbox value by one step - * @param spinbox pointer to spinbox - */ -void lv_spinbox_increment(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - if(ext->value + ext->step <= ext->range_max) { - /*Special mode when zero crossing*/ - if((ext->value + ext->step) > 0 && ext->value < 0) ext->value = -ext->value; - ext->value += ext->step; - - } - else { - // Rollover? - if((ext->rollover) && (ext->value == ext->range_max)) - ext->value = ext->range_min; - else - ext->value = ext->range_max; - } - - lv_spinbox_updatevalue(spinbox); -} - -/** - * Decrement spinbox value by one step - * @param spinbox pointer to spinbox - */ -void lv_spinbox_decrement(lv_obj_t * spinbox) -{ - LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - if(ext->value - ext->step >= ext->range_min) { - /*Special mode when zero crossing*/ - if((ext->value - ext->step) < 0 && ext->value > 0) ext->value = -ext->value; - ext->value -= ext->step; - } - else { - // Rollover? - if((ext->rollover) && (ext->value == ext->range_min)) - ext->value = ext->range_max; - else - ext->value = ext->range_min; - } - - lv_spinbox_updatevalue(spinbox); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the spinbox - * @param spinbox pointer to a spinbox object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param) -{ - - lv_res_t res = LV_RES_OK; - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_spinbox_get_style(spinbox, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(spinbox, sign, param); - } - - /* Include the ancient signal function */ - if(sign != LV_SIGNAL_CONTROL) { - res = ancestor_signal(spinbox, sign, param); - if(res != LV_RES_OK) return res; - } - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - - if(sign == LV_SIGNAL_CLEANUP) { - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } - else if(sign == LV_SIGNAL_GET_TYPE) { - lv_obj_type_t * buf = param; - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ - if(buf->type[i] == NULL) break; - } - buf->type[i] = "lv_spinbox"; - } - else if(sign == LV_SIGNAL_RELEASED) { - /*If released with an ENCODER then move to the next digit*/ - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - lv_indev_t * indev = lv_indev_get_act(); - if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) { -#if LV_USE_GROUP - if(lv_group_get_editing(lv_obj_get_group(spinbox))) { - if(ext->step > 1) { - lv_spinbox_step_next(spinbox); - } - else { - /*Restart from the MSB*/ - ext->step = 1; - uint32_t i; - for(i = 0; i < ext->digit_count; i++) { - int32_t new_step = ext->step * 10; - if(new_step >= ext->range_max) break; - ext->step = new_step; - } - lv_spinbox_step_prev(spinbox); - } - } -#endif - } - else { - /*The cursor has been positioned to a digit. - * Set `step` accordingly*/ - const char * txt = lv_textarea_get_text(spinbox); - size_t txt_len = strlen(txt); - - if(txt[ext->ta.cursor.pos] == '.') { - lv_textarea_cursor_left(spinbox); - } - else if(ext->ta.cursor.pos == (uint32_t)txt_len) { - lv_textarea_set_cursor_pos(spinbox, txt_len - 1); - } - else if(ext->ta.cursor.pos == 0 && ext->range_min < 0) { - lv_textarea_set_cursor_pos(spinbox, 1); - } - - size_t len = ext->digit_count - 1; - uint16_t cp = ext->ta.cursor.pos; - - if(ext->ta.cursor.pos > ext->dec_point_pos && ext->dec_point_pos != 0) cp--; - uint32_t pos = len - cp; - - if(ext->range_min < 0) pos++; - - ext->step = 1; - uint16_t i; - for(i = 0; i < pos; i++) ext->step *= 10; - - - - } - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - - uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ - if(c == LV_KEY_RIGHT) { - if(indev_type == LV_INDEV_TYPE_ENCODER) - lv_spinbox_increment(spinbox); - else - lv_spinbox_step_next(spinbox); - } - else if(c == LV_KEY_LEFT) { - if(indev_type == LV_INDEV_TYPE_ENCODER) - lv_spinbox_decrement(spinbox); - else - lv_spinbox_step_prev(spinbox); - } - else if(c == LV_KEY_UP) { - lv_spinbox_increment(spinbox); - } - else if(c == LV_KEY_DOWN) { - lv_spinbox_decrement(spinbox); - } - else { - lv_textarea_add_char(spinbox, c); - } -#endif - } - - return res; -} - -/** - * Get the style descriptor of a part of the object - * @param page pointer the object - * @param part the part from `lv_spinbox_part_t`. (LV_SPINBOX_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_spinbox_get_style(lv_obj_t * ta, uint8_t part) -{ - LV_ASSERT_OBJ(ta, LV_OBJX_NAME); - - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_SPINBOX_PART_BG: - style_dsc_p = &ta->style_list; - break; - case LV_SPINBOX_PART_CURSOR: - style_dsc_p = &ext->ta.cursor.style; - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} -static void lv_spinbox_updatevalue(lv_obj_t * spinbox) -{ - lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox); - - char buf[LV_SPINBOX_MAX_DIGIT_COUNT + 8]; - _lv_memset_00(buf, sizeof(buf)); - char * buf_p = buf; - uint8_t cur_shift_left = 0; - - if(ext->range_min < 0) { // hide sign if there are only positive values - /*Add the sign*/ - (*buf_p) = ext->value >= 0 ? '+' : '-'; - buf_p++; - } - else { - /*Cursor need shift to left*/ - cur_shift_left++; - } - - int32_t i; - /*padding left*/ - for(i = 0; i < ext->digit_padding_left; i++) { - (*buf_p) = ' '; - buf_p++; - } - - char digits[64]; - /*Convert the numbers to string (the sign is already handled so always covert positive number)*/ - _lv_utils_num_to_str(ext->value < 0 ? -ext->value : ext->value, digits); - - /*Add leading zeros*/ - int lz_cnt = ext->digit_count - (int)strlen(digits); - if(lz_cnt > 0) { - for(i = (uint16_t)strlen(digits); i >= 0; i--) { - digits[i + lz_cnt] = digits[i]; - } - for(i = 0; i < lz_cnt; i++) { - digits[i] = '0'; - } - } - - int32_t intDigits; - intDigits = (ext->dec_point_pos == 0) ? ext->digit_count : ext->dec_point_pos; - - /*Add the decimal part*/ - for(i = 0; i < intDigits && digits[i] != '\0'; i++) { - (*buf_p) = digits[i]; - buf_p++; - } - - if(ext->dec_point_pos != 0) { - /*Insert the decimal point*/ - (*buf_p) = '.'; - buf_p++; - - for(/*Leave i*/; i < ext->digit_count && digits[i] != '\0'; i++) { - (*buf_p) = digits[i]; - buf_p++; - } - } - - /*Refresh the text*/ - lv_textarea_set_text(spinbox, (char *)buf); - - /*Set the cursor position*/ - int32_t step = ext->step; - uint8_t cur_pos = (uint8_t)ext->digit_count; - while(step >= 10) { - step /= 10; - cur_pos--; - } - - if(cur_pos > intDigits) cur_pos++; /*Skip the decimal point*/ - - cur_pos += (ext->digit_padding_left - cur_shift_left); - - lv_textarea_set_cursor_pos(spinbox, cur_pos); -} - -#endif diff --git a/src/lv_widgets/lv_spinbox.h b/src/lv_widgets/lv_spinbox.h deleted file mode 100644 index 83c057f58..000000000 --- a/src/lv_widgets/lv_spinbox.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file lv_spinbox.h - * - */ - -#ifndef LV_SPINBOX_H -#define LV_SPINBOX_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_SPINBOX != 0 - -/*Testing of dependencies*/ -#if LV_USE_TEXTAREA == 0 -#error "lv_spinbox: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "../lv_widgets/lv_textarea.h" - -/********************* - * DEFINES - *********************/ -#define LV_SPINBOX_MAX_DIGIT_COUNT 10 - -/********************** - * TYPEDEFS - **********************/ - -/*Data of spinbox*/ -typedef struct { - lv_textarea_ext_t ta; /*Ext. of ancestor*/ - /*New data for this type */ - int32_t value; - int32_t range_max; - int32_t range_min; - int32_t step; - uint8_t rollover : 1; // Set to true for rollover functionality - uint16_t digit_count : 4; - uint16_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/ - uint16_t digit_padding_left : 4; -} lv_spinbox_ext_t; - -/*Styles*/ -enum { - LV_SPINBOX_PART_BG = LV_TEXTAREA_PART_BG, - LV_SPINBOX_PART_CURSOR = LV_TEXTAREA_PART_CURSOR, - _LV_SPINBOX_PART_VIRTUAL_LAST = _LV_TEXTAREA_PART_VIRTUAL_LAST, - _LV_SPINBOX_PART_REAL_LAST = _LV_TEXTAREA_PART_REAL_LAST, -}; -typedef uint8_t lv_spinbox_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a spinbox objects - * @param par pointer to an object, it will be the parent of the new spinbox - * @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it - * @return pointer to the created spinbox - */ -lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set spinbox rollover function - * @param spinbox pointer to spinbox - * @param b true or false to enable or disable (default) - */ -void lv_spinbox_set_rollover(lv_obj_t * spinbox, bool b); - -/** - * Set spinbox value - * @param spinbox pointer to spinbox - * @param i value to be set - */ -void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i); - -/** - * Set spinbox digit format (digit count and decimal format) - * @param spinbox pointer to spinbox - * @param digit_count number of digit excluding the decimal separator and the sign - * @param separator_position number of digit before the decimal point. If 0, decimal point is not - * shown - */ -void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position); - -/** - * Set spinbox step - * @param spinbox pointer to spinbox - * @param step steps on increment/decrement - */ -void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step); - -/** - * Set spinbox value range - * @param spinbox pointer to spinbox - * @param range_min maximum value, inclusive - * @param range_max minimum value, inclusive - */ -void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max); - -/** - * Set spinbox left padding in digits count (added between sign and first digit) - * @param spinbox pointer to spinbox - * @param cb Callback function called on value change event - */ -void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get spinbox rollover function status - * @param spinbox pointer to spinbox - */ -bool lv_spinbox_get_rollover(lv_obj_t * spinbox); - -/** - * Get the spinbox numeral value (user has to convert to float according to its digit format) - * @param spinbox pointer to spinbox - * @return value integer value of the spinbox - */ -int32_t lv_spinbox_get_value(lv_obj_t * spinbox); - -/*===================== - * Other functions - *====================*/ - -/** - * Select next lower digit for edition by dividing the step by 10 - * @param spinbox pointer to spinbox - */ -void lv_spinbox_step_next(lv_obj_t * spinbox); - -/** - * Select next higher digit for edition by multiplying the step by 10 - * @param spinbox pointer to spinbox - */ -void lv_spinbox_step_prev(lv_obj_t * spinbox); - -/** - * Increment spinbox value by one step - * @param spinbox pointer to spinbox - */ -void lv_spinbox_increment(lv_obj_t * spinbox); - -/** - * Decrement spinbox value by one step - * @param spinbox pointer to spinbox - */ -void lv_spinbox_decrement(lv_obj_t * spinbox); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_SPINBOX*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_SPINBOX_H*/ diff --git a/src/lv_widgets/lv_spinner.c b/src/lv_widgets/lv_spinner.c deleted file mode 100644 index 8e0e2dcd0..000000000 --- a/src/lv_widgets/lv_spinner.c +++ /dev/null @@ -1,326 +0,0 @@ -/** - * @file lv_spinner.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_spinner.h" -#if LV_USE_SPINNER != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_misc/lv_math.h" -#include "../lv_draw/lv_draw_rect.h" -#include "../lv_draw/lv_draw_arc.h" -#include "../lv_themes/lv_theme.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_spinner" - -#ifndef LV_SPINNER_DEF_ARC_LENGTH - #define LV_SPINNER_DEF_ARC_LENGTH 60 /*[deg]*/ -#endif - -#ifndef LV_SPINNER_DEF_SPIN_TIME - #define LV_SPINNER_DEF_SPIN_TIME 1000 /*[ms]*/ -#endif - -#ifndef LV_SPINNER_DEF_ANIM - #define LV_SPINNER_DEF_ANIM LV_SPINNER_TYPE_SPINNING_ARC /*animation type*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_spinner_signal(lv_obj_t * spinner, lv_signal_t sign, void * param); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a spinner object - * @param par pointer to an object, it will be the parent of the new spinner - * @param copy pointer to a spinner object, if not NULL then the new object will be copied from - * it - * @return pointer to the created spinner - */ -lv_obj_t * lv_spinner_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("spinner create started"); - - /*Create the ancestor of spinner*/ - lv_obj_t * spinner = lv_arc_create(par, copy); - LV_ASSERT_MEM(spinner); - if(spinner == NULL) return NULL; - - /*Allocate the spinner type specific extended data*/ - lv_spinner_ext_t * ext = lv_obj_allocate_ext_attr(spinner, sizeof(lv_spinner_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(spinner); - return NULL; - } - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(spinner); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(spinner); - - /*Initialize the allocated 'ext' */ - ext->arc_length = LV_SPINNER_DEF_ARC_LENGTH; - ext->anim_type = LV_SPINNER_DEF_ANIM; - ext->anim_dir = LV_SPINNER_DIR_FORWARD; - ext->time = LV_SPINNER_DEF_SPIN_TIME; - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(spinner, lv_spinner_signal); - - /*Init the new spinner spinner*/ - if(copy == NULL) { - ext->arc.bg_angle_start = 0; - ext->arc.bg_angle_end = 360; - lv_obj_set_size(spinner, LV_DPI, LV_DPI); - lv_theme_apply(spinner, LV_THEME_SPINNER); - - } - /*Copy an existing spinner*/ - else { - lv_spinner_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->arc_length = copy_ext->arc_length; - ext->time = copy_ext->time; - ext->anim_dir = copy_ext->anim_dir; - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(spinner, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - lv_spinner_set_type(spinner, ext->anim_type); - - LV_LOG_INFO("spinner created"); - - return spinner; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Set the length of the spinning arc in degrees - * @param spinner pointer to a spinner object - * @param deg length of the arc - */ -void lv_spinner_set_arc_length(lv_obj_t * spinner, lv_anim_value_t deg) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - - ext->arc_length = deg; -} - -/** - * Set the spin time of the arc - * @param spinner pointer to a spinner object - * @param time time of one round in milliseconds - */ -void lv_spinner_set_spin_time(lv_obj_t * spinner, uint16_t time) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - - ext->time = time; - lv_spinner_set_type(spinner, ext->anim_type); -} -/*===================== - * Setter functions - *====================*/ - -/** - * Set the animation type of a spinner. - * @param spinner pointer to spinner object - * @param type animation type of the spinner - * */ -void lv_spinner_set_type(lv_obj_t * spinner, lv_spinner_type_t type) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - - /*delete previous animation*/ - lv_anim_del(spinner, NULL); - switch(type) { - case LV_SPINNER_TYPE_FILLSPIN_ARC: { - ext->anim_type = LV_SPINNER_TYPE_FILLSPIN_ARC; - lv_anim_path_t path; - lv_anim_path_init(&path); - lv_anim_path_set_cb(&path, lv_anim_path_ease_in_out); - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, spinner); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_anim_cb); - lv_anim_set_path(&a, &path); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); - lv_anim_set_time(&a, ext->time); - if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, 0, 360); - else lv_anim_set_values(&a, 360, 0); - lv_anim_start(&a); - - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_set_arc_length); - if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, ext->arc_length, 360 - ext->arc_length); - else lv_anim_set_values(&a, 360 - ext->arc_length, ext->arc_length); - - lv_anim_set_playback_time(&a, ext->time); - lv_anim_start(&a); - break; - } - case LV_SPINNER_TYPE_CONSTANT_ARC: - case LV_SPINNER_TYPE_SPINNING_ARC: - default: { - ext->anim_type = type; - - lv_anim_path_t path; - lv_anim_path_init(&path); - lv_anim_path_set_cb(&path, (LV_SPINNER_TYPE_CONSTANT_ARC == type ? lv_anim_path_linear : lv_anim_path_ease_in_out)); - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, spinner); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_anim_cb); - lv_anim_set_time(&a, ext->time); - lv_anim_set_path(&a, &path); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); - if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, 0, 360); - else lv_anim_set_values(&a, 360, 0); - lv_anim_start(&a); - break; - } - } -} - -void lv_spinner_set_dir(lv_obj_t * spinner, lv_spinner_dir_t dir) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - - ext->anim_dir = dir; - lv_spinner_set_type(spinner, ext->anim_type); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the arc length [degree] of the a spinner - * @param spinner pointer to a spinner object - */ -lv_anim_value_t lv_spinner_get_arc_length(const lv_obj_t * spinner) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - return ext->arc_length; -} - -/** - * Get the spin time of the arc - * @param spinner pointer to a spinner object [milliseconds] - */ -uint16_t lv_spinner_get_spin_time(const lv_obj_t * spinner) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - return ext->time; -} - -/** - * Get the animation type of a spinner. - * @param spinner pointer to spinner object - * @return animation type - * */ -lv_spinner_type_t lv_spinner_get_type(lv_obj_t * spinner) -{ - LV_ASSERT_OBJ(spinner, LV_OBJX_NAME); - - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - return ext->anim_type; -} - -lv_spinner_dir_t lv_spinner_get_dir(lv_obj_t * spinner) -{ - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - return ext->anim_dir; -} - -/*===================== - * Other functions - *====================*/ - -/** - * Animator function (exec_cb) to rotate the arc of spinner. - * @param ptr pointer to spinner - * @param val the current desired value [0..360] - */ -void lv_spinner_anim_cb(void * ptr, lv_anim_value_t val) -{ - lv_obj_t * spinner = ptr; - lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner); - - int16_t angle_start = val - ext->arc_length / 2 - 90; - if(angle_start < 0) angle_start += 360; - int16_t angle_end = angle_start + ext->arc_length; - - angle_start = angle_start % 360; - angle_end = angle_end % 360; - - lv_arc_set_angles(spinner, angle_start, angle_end); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the spinner - * @param spinner pointer to a spinner object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_spinner_signal(lv_obj_t * spinner, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(spinner, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_CLEANUP) { - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } - - return res; -} - -#endif diff --git a/src/lv_widgets/lv_spinner.h b/src/lv_widgets/lv_spinner.h deleted file mode 100644 index 6649202e4..000000000 --- a/src/lv_widgets/lv_spinner.h +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @file lv_spinner.h - * - */ - -#ifndef LV_SPINNER_H -#define LV_SPINNER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_SPINNER != 0 - -/*Testing of dependencies*/ -#if LV_USE_ARC == 0 -#error "lv_spinner: lv_arc is required. Enable it in lv_conf.h (LV_USE_ARC 1) " -#endif - -#if LV_USE_ANIMATION == 0 -#error "lv_spinner: animations are required. Enable it in lv_conf.h (LV_USE_ANIMATION 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "../lv_misc/lv_anim.h" -#include "lv_arc.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * Type of spinner. - */ -enum { - LV_SPINNER_TYPE_SPINNING_ARC, - LV_SPINNER_TYPE_FILLSPIN_ARC, - LV_SPINNER_TYPE_CONSTANT_ARC, -}; -typedef uint8_t lv_spinner_type_t; - -/** - * Direction the spinner should spin. - */ -enum { - LV_SPINNER_DIR_FORWARD, - LV_SPINNER_DIR_BACKWARD, -}; -typedef uint8_t lv_spinner_dir_t; - -/*Data of spinner*/ -typedef struct { - lv_arc_ext_t arc; /*Ext. of ancestor*/ - /*New data for this type */ - lv_anim_value_t arc_length; /*Length of the spinning indicator in degree*/ - uint16_t time; /*Time of one round*/ - lv_spinner_type_t anim_type : 2; /*Type of the arc animation*/ - lv_spinner_dir_t anim_dir : 1; /*Animation Direction*/ -} lv_spinner_ext_t; - -/*Parts of the spinner*/ -enum { - LV_SPINNER_PART_BG = LV_ARC_PART_BG, - LV_SPINNER_PART_INDIC = LV_ARC_PART_INDIC, - _LV_SPINNER_PART_VIRTUAL_LAST, - - _LV_SPINNER_PART_REAL_LAST = _LV_ARC_PART_REAL_LAST, -}; -typedef uint8_t lv_spinner_style_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a spinner object - * @param par pointer to an object, it will be the parent of the new spinner - * @param copy pointer to a spinner object, if not NULL then the new object will be copied from - * it - * @return pointer to the created spinner - */ -lv_obj_t * lv_spinner_create(lv_obj_t * par, const lv_obj_t * copy); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Set the length of the spinning arc in degrees - * @param spinner pointer to a spinner object - * @param deg length of the arc - */ -void lv_spinner_set_arc_length(lv_obj_t * spinner, lv_anim_value_t deg); - -/** - * Set the spin time of the arc - * @param spinner pointer to a spinner object - * @param time time of one round in milliseconds - */ -void lv_spinner_set_spin_time(lv_obj_t * spinner, uint16_t time); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the animation type of a spinner. - * @param spinner pointer to spinner object - * @param type animation type of the spinner - * */ -void lv_spinner_set_type(lv_obj_t * spinner, lv_spinner_type_t type); - -/** - * Set the animation direction of a spinner - * @param spinner pointer to spinner object - * @param direction animation direction of the spinner - */ -void lv_spinner_set_dir(lv_obj_t * spinner, lv_spinner_dir_t dir); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the arc length [degree] of the a spinner - * @param spinner pointer to a spinner object - */ -lv_anim_value_t lv_spinner_get_arc_length(const lv_obj_t * spinner); - -/** - * Get the spin time of the arc - * @param spinner pointer to a spinner object [milliseconds] - */ -uint16_t lv_spinner_get_spin_time(const lv_obj_t * spinner); - -/** - * Get the animation type of a spinner. - * @param spinner pointer to spinner object - * @return animation type - * */ -lv_spinner_type_t lv_spinner_get_type(lv_obj_t * spinner); - -/** - * Get the animation direction of a spinner - * @param spinner pointer to spinner object - * @return animation direction - */ -lv_spinner_dir_t lv_spinner_get_dir(lv_obj_t * spinner); - -/*===================== - * Other functions - *====================*/ - -/** - * Animator function (exec_cb) to rotate the arc of spinner. - * @param ptr pointer to spinner - * @param val the current desired value [0..360] - */ -void lv_spinner_anim_cb(void * ptr, lv_anim_value_t val); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_SPINNER*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_SPINNER_H*/ diff --git a/src/lv_widgets/lv_tabview.c b/src/lv_widgets/lv_tabview.c deleted file mode 100644 index 5cc773444..000000000 --- a/src/lv_widgets/lv_tabview.c +++ /dev/null @@ -1,1033 +0,0 @@ -/** - * @file lv_tab.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_tabview.h" -#if LV_USE_TABVIEW != 0 - -#include "lv_btnmatrix.h" -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_misc/lv_anim.h" -#include "../lv_core/lv_disp.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_tabview" - -#if LV_USE_ANIMATION - #ifndef LV_TABVIEW_DEF_ANIM_TIME - #define LV_TABVIEW_DEF_ANIM_TIME 300 /*Animation time of focusing to the a list element [ms] (0: no animation) */ - #endif -#else - #undef LV_TABVIEW_DEF_ANIM_TIME - #define LV_TABVIEW_DEF_ANIM_TIME 0 /*No animations*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * param); -static lv_res_t tabview_scrl_signal(lv_obj_t * tabview_scrl, lv_signal_t sign, void * param); -static lv_style_list_t * lv_tabview_get_style(lv_obj_t * tabview, uint8_t part); - -static void tab_btnm_event_cb(lv_obj_t * tab_btnm, lv_event_t event); -static void tabview_realign(lv_obj_t * tabview); -static void refr_indic_size(lv_obj_t * tabview); -static void refr_btns_size(lv_obj_t * tabview); -static void refr_content_size(lv_obj_t * tabview); -static void refr_align(lv_obj_t * tabview); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_signal_cb_t ancestor_scrl_signal; -static lv_signal_cb_t page_signal; -static const char * tab_def[] = {""}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a Tab view object - * @param par pointer to an object, it will be the parent of the new tab - * @param copy pointer to a tab object, if not NULL then the new object will be copied from it - * @return pointer to the created tab - */ -lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("tab view create started"); - - /*Create the ancestor of tab*/ - lv_obj_t * tabview = lv_obj_create(par, copy); - LV_ASSERT_MEM(tabview); - if(tabview == NULL) return NULL; - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(tabview); - - /*Allocate the tab type specific extended data*/ - lv_tabview_ext_t * ext = lv_obj_allocate_ext_attr(tabview, sizeof(lv_tabview_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(tabview); - return NULL; - } - - /*Initialize the allocated 'ext' */ - ext->tab_cur = 0; - ext->tab_cnt = 0; - ext->point_last.x = 0; - ext->point_last.y = 0; - ext->content = NULL; - ext->indic = NULL; - ext->btns = NULL; - ext->btns_pos = LV_TABVIEW_TAB_POS_TOP; -#if LV_USE_ANIMATION - ext->anim_time = LV_TABVIEW_DEF_ANIM_TIME; -#endif - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(tabview, lv_tabview_signal); - /*Init the new tab tab*/ - if(copy == NULL) { - ext->tab_name_ptr = lv_mem_alloc(sizeof(char *)); - LV_ASSERT_MEM(ext->tab_name_ptr); - if(ext->tab_name_ptr == NULL) return NULL; - ext->tab_name_ptr[0] = ""; - - /* Set a size which fits into the parent. - * Don't use `par` directly because if the tabview is created on a page it is moved to the - * scrollable so the parent has changed */ - lv_coord_t w; - lv_coord_t h; - if(par) { - w = lv_obj_get_width_fit(lv_obj_get_parent(tabview)); - h = lv_obj_get_height_fit(lv_obj_get_parent(tabview)); - } - else { - w = lv_disp_get_hor_res(NULL); - h = lv_disp_get_ver_res(NULL); - } - - lv_obj_set_size(tabview, w, h); - - ext->content = lv_page_create(tabview, NULL); - ext->btns = lv_btnmatrix_create(tabview, NULL); - ext->indic = lv_obj_create(ext->btns, NULL); - - if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(ext->content)); - lv_obj_set_signal_cb(lv_page_get_scrollable(ext->content), tabview_scrl_signal); - - lv_btnmatrix_set_map(ext->btns, tab_def); - lv_obj_set_event_cb(ext->btns, tab_btnm_event_cb); - - lv_obj_set_click(ext->indic, false); - lv_obj_set_drag_dir(lv_page_get_scrollable(ext->content), LV_DRAG_DIR_ONE); - - lv_page_set_scrollable_fit2(ext->content, LV_FIT_TIGHT, LV_FIT_PARENT); - lv_page_set_scrl_layout(ext->content, LV_LAYOUT_ROW_TOP); - lv_page_set_scrollbar_mode(ext->content, LV_SCROLLBAR_MODE_OFF); - - lv_obj_clean_style_list(ext->content, LV_PAGE_PART_BG); - - lv_theme_apply(tabview, LV_THEME_TABVIEW); - - } - /*Copy an existing tab view*/ - else { - lv_tabview_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->point_last.x = 0; - ext->point_last.y = 0; - ext->btns = lv_btnmatrix_create(tabview, copy_ext->btns); - ext->indic = lv_obj_create(ext->btns, copy_ext->indic); - ext->content = lv_page_create(tabview, copy_ext->content); -#if LV_USE_ANIMATION - ext->anim_time = copy_ext->anim_time; -#endif - - ext->tab_name_ptr = lv_mem_alloc(sizeof(char *)); - LV_ASSERT_MEM(ext->tab_name_ptr); - if(ext->tab_name_ptr == NULL) return NULL; - ext->tab_name_ptr[0] = ""; - lv_btnmatrix_set_map(ext->btns, ext->tab_name_ptr); - - lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_BG_SCRLLABLE), lv_obj_get_style_list(copy, - LV_TABVIEW_PART_BG_SCRLLABLE)); - lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_TAB_BG), lv_obj_get_style_list(copy, - LV_TABVIEW_PART_TAB_BG)); - lv_style_list_copy(lv_obj_get_style_list(tabview, LV_TABVIEW_PART_TAB_BTN), lv_obj_get_style_list(copy, - LV_TABVIEW_PART_TAB_BTN)); - - uint16_t i; - for(i = 0; i < copy_ext->tab_cnt; i++) { - lv_obj_t * new_tab = lv_tabview_add_tab(tabview, copy_ext->tab_name_ptr[i]); - lv_obj_t * copy_tab = lv_tabview_get_tab(copy, i); - lv_style_list_copy(lv_obj_get_style_list(new_tab, LV_PAGE_PART_SCROLLABLE), lv_obj_get_style_list(copy_tab, - LV_PAGE_PART_SCROLLABLE)); - lv_style_list_copy(lv_obj_get_style_list(new_tab, LV_PAGE_PART_SCROLLBAR), lv_obj_get_style_list(copy_tab, - LV_PAGE_PART_SCROLLBAR)); - lv_obj_refresh_style(new_tab, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(tabview, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - tabview_realign(tabview); - - LV_LOG_INFO("tab view created"); - - return tabview; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add a new tab with the given name - * @param tabview pointer to Tab view object where to ass the new tab - * @param name the text on the tab button - * @return pointer to the created page object (lv_page). You can create your content here - */ -lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - LV_ASSERT_STR(name); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - /*Create the container page*/ - lv_obj_t * h = lv_page_create(ext->content, NULL); - lv_obj_set_size(h, lv_obj_get_width(tabview), lv_obj_get_height(ext->content)); - lv_page_set_scrollbar_mode(h, LV_SCROLLBAR_MODE_AUTO); - lv_page_set_scroll_propagation(h, true); - lv_page_set_scrollable_fit4(h, LV_FIT_NONE, LV_FIT_MAX, LV_FIT_NONE, LV_FIT_MAX); - lv_theme_apply(h, LV_THEME_TABVIEW_PAGE); - - if(page_signal == NULL) page_signal = lv_obj_get_signal_cb(h); - - /*Extend the button matrix map with the new name*/ - char * name_dm; - name_dm = lv_mem_alloc(strlen(name) + 1); /*+1 for the the closing '\0' */ - LV_ASSERT_MEM(name_dm); - if(name_dm == NULL) return NULL; - strcpy(name_dm, name); - - ext->tab_cnt++; - - /* FIXME: It is not possible yet to switch tab button position from/to top/bottom from/to left/right at runtime. - * Method: clean extra \n when switch from LV_TABVIEW_BTNS_POS_LEFT or LV_TABVIEW_BTNS_POS_RIGHT - * to LV_TABVIEW_BTNS_POS_TOP or LV_TABVIEW_BTNS_POS_BOTTOM. - */ - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - ext->tab_name_ptr = lv_mem_realloc(ext->tab_name_ptr, sizeof(char *) * (ext->tab_cnt + 1)); - - LV_ASSERT_MEM(ext->tab_name_ptr); - if(ext->tab_name_ptr == NULL) return NULL; - - ext->tab_name_ptr[ext->tab_cnt - 1] = name_dm; - ext->tab_name_ptr[ext->tab_cnt] = ""; - - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - ext->tab_name_ptr = lv_mem_realloc(ext->tab_name_ptr, sizeof(char *) * (ext->tab_cnt * 2)); - - LV_ASSERT_MEM(ext->tab_name_ptr); - if(ext->tab_name_ptr == NULL) return NULL; - - if(ext->tab_cnt == 1) { - ext->tab_name_ptr[0] = name_dm; - ext->tab_name_ptr[1] = ""; - } - else { - ext->tab_name_ptr[ext->tab_cnt * 2 - 3] = "\n"; - ext->tab_name_ptr[ext->tab_cnt * 2 - 2] = name_dm; - ext->tab_name_ptr[ext->tab_cnt * 2 - 1] = ""; - } - break; - } - - /* The button matrix's map still points to the old `tab_name_ptr` which might be freed by - * `lv_mem_realloc`. So make its current map invalid*/ - lv_btnmatrix_ext_t * btnm_ext = lv_obj_get_ext_attr(ext->btns); - btnm_ext->map_p = NULL; - - lv_btnmatrix_set_map(ext->btns, ext->tab_name_ptr); - lv_btnmatrix_set_btn_ctrl(ext->btns, ext->tab_cur, LV_BTNMATRIX_CTRL_NO_REPEAT); - - /*Set the first btn as active*/ - if(ext->tab_cnt == 1) ext->tab_cur = 0; - - tabview_realign(tabview); /*Set the size of the pages, tab buttons and indicator*/ - - lv_tabview_set_tab_act(tabview, ext->tab_cur, false); - - return h; -} - -/** - * Delete all children of a tab created by `lv_tabview_add_tab`. - * @param tab pointer to a tab - */ -void lv_tabview_clean_tab(lv_obj_t * tab) -{ - LV_ASSERT_OBJ(tab, "lv_page"); - - lv_obj_t * scrl = lv_page_get_scrollable(tab); - lv_obj_clean(scrl); -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new tab - * @param tabview pointer to Tab view object - * @param id index of a tab to load - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t anim) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - -#if LV_USE_ANIMATION == 0 - anim = LV_ANIM_OFF; -#endif - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - if(id >= ext->tab_cnt) id = ext->tab_cnt - 1; - - lv_btnmatrix_clear_btn_ctrl(ext->btns, ext->tab_cur, LV_BTNMATRIX_CTRL_CHECK_STATE); - - ext->tab_cur = id; - - if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) { - id = (ext->tab_cnt - (id + 1)); - } - - lv_coord_t cont_x; - lv_style_int_t scrl_inner = lv_obj_get_style_pad_inner(ext->content, LV_PAGE_PART_SCROLLABLE); - lv_style_int_t scrl_left = lv_obj_get_style_pad_left(ext->content, LV_PAGE_PART_SCROLLABLE); - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - cont_x = -(lv_obj_get_width(tabview) * id + scrl_inner * id + scrl_left); - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - cont_x = -((lv_obj_get_width(tabview) - lv_obj_get_width(ext->btns)) * id + scrl_inner * id + scrl_left); - break; - } - - if(anim == LV_ANIM_OFF || lv_tabview_get_anim_time(tabview) == 0) { - lv_obj_set_x(lv_page_get_scrollable(ext->content), cont_x); - } -#if LV_USE_ANIMATION - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, lv_page_get_scrollable(ext->content)); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_set_values(&a, lv_obj_get_x(lv_page_get_scrollable(ext->content)), cont_x); - lv_anim_set_time(&a, ext->anim_time); - lv_anim_start(&a); - } -#endif - - /*Move the indicator*/ - lv_coord_t indic_size; - lv_coord_t indic_pos = 0; /*silence uninitialized variable warning*/; - - lv_style_int_t btns_bg_inner = 0; - lv_style_int_t btns_bg_left = 0; - lv_style_int_t btns_bg_top = 0; - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - btns_bg_inner = lv_obj_get_style_pad_inner(tabview, LV_TABVIEW_PART_TAB_BG); - btns_bg_left = lv_obj_get_style_pad_left(tabview, LV_TABVIEW_PART_TAB_BG); - indic_size = lv_obj_get_width(ext->indic); - indic_pos = indic_size * id + btns_bg_inner * id + btns_bg_left; - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - btns_bg_inner = lv_obj_get_style_pad_inner(tabview, LV_TABVIEW_PART_TAB_BG); - btns_bg_top = lv_obj_get_style_pad_top(tabview, LV_TABVIEW_PART_TAB_BG); - indic_size = lv_obj_get_height(ext->indic); - indic_pos = btns_bg_top + id * (indic_size + btns_bg_inner); - break; - } - -#if LV_USE_ANIMATION - if(anim == LV_ANIM_OFF || ext->anim_time == 0) -#endif - { - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - lv_obj_set_x(ext->indic, indic_pos); - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - lv_obj_set_y(ext->indic, indic_pos); - break; - } - } -#if LV_USE_ANIMATION - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ext->indic); - lv_anim_set_time(&a, ext->anim_time); - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_set_values(&a, lv_obj_get_x(ext->indic), indic_pos); - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, lv_obj_get_y(ext->indic), indic_pos); - break; - } - - lv_anim_start(&a); - } -#endif - - lv_btnmatrix_set_btn_ctrl(ext->btns, ext->tab_cur, LV_BTNMATRIX_CTRL_CHECK_STATE); -} - -/** - * Set the name of a tab. - * @param tabview pointer to Tab view object - * @param id index of the tab the name should be set - * @param name new tab name - */ -void lv_tabview_set_tab_name(lv_obj_t * tabview, uint16_t id, char * name) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - /* get tabview's ext pointer which contains the tab name pointer list */ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - /* check for valid tab index */ - if(ext->tab_cnt > id) { - /* reallocate memory for new tab name (use reallocate due to mostly the size didn't change much) */ - char * str = lv_mem_realloc((void *)ext->tab_name_ptr[id], strlen(name) + 1); - LV_ASSERT_MEM(str); - - /* store new tab name at allocated memory */ - strcpy(str, name); - /* update pointer */ - ext->tab_name_ptr[id] = str; - - /* force redrawing of the tab headers */ - lv_obj_invalidate(ext->btns); - } -} - -/** - * Set the animation time of tab view when a new tab is loaded - * @param tabview pointer to Tab view object - * @param anim_time_ms time of animation in milliseconds - */ -void lv_tabview_set_anim_time(lv_obj_t * tabview, uint16_t anim_time) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - ext->anim_time = anim_time; -#else - (void)tabview; - (void)anim_time; -#endif -} - -/** - * Set the position of tab select buttons - * @param tabview pointer to a tan view object - * @param btns_pos which button position - */ -void lv_tabview_set_btns_pos(lv_obj_t * tabview, lv_tabview_btns_pos_t btns_pos) -{ - if(btns_pos != LV_TABVIEW_TAB_POS_NONE && - btns_pos != LV_TABVIEW_TAB_POS_TOP && - btns_pos != LV_TABVIEW_TAB_POS_BOTTOM && - btns_pos != LV_TABVIEW_TAB_POS_LEFT && - btns_pos != LV_TABVIEW_TAB_POS_RIGHT) { - LV_LOG_WARN("lv_tabview_set_btns_pos: unexpected button position"); - return; - } - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - ext->btns_pos = btns_pos; - tabview_realign(tabview); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the index of the currently active tab - * @param tabview pointer to Tab view object - * @return the active btn index - */ -uint16_t lv_tabview_get_tab_act(const lv_obj_t * tabview) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - return ext->tab_cur; -} - -/** - * Get the number of tabs - * @param tabview pointer to Tab view object - * @return btn count - */ -uint16_t lv_tabview_get_tab_count(const lv_obj_t * tabview) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - return ext->tab_cnt; -} - -/** - * Get the page (content area) of a tab - * @param tabview pointer to Tab view object - * @param id index of the btn (>= 0) - * @return pointer to page (lv_page) object - */ -lv_obj_t * lv_tabview_get_tab(const lv_obj_t * tabview, uint16_t id) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - lv_obj_t * content_scrl = lv_page_get_scrollable(ext->content); - uint16_t i = 0; - lv_obj_t * page = lv_obj_get_child_back(content_scrl, NULL); - - while(page != NULL && i != id) { - if(lv_obj_get_signal_cb(page) == page_signal) i++; - page = lv_obj_get_child_back(content_scrl, page); - } - - if(i == id) return page; - - return NULL; -} - -/** - * Get the animation time of tab view when a new tab is loaded - * @param tabview pointer to Tab view object - * @return time of animation in milliseconds - */ -uint16_t lv_tabview_get_anim_time(const lv_obj_t * tabview) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - -#if LV_USE_ANIMATION - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - return ext->anim_time; -#else - (void)tabview; - return 0; -#endif -} - -/** - * Get position of tab select buttons - * @param tabview pointer to a ab view object - */ -lv_tabview_btns_pos_t lv_tabview_get_btns_pos(const lv_obj_t * tabview) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - return ext->btns_pos; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the Tab view - * @param tabview pointer to a Tab view object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * param) -{ - lv_res_t res; - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_tabview_get_style(tabview, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(tabview, sign, param); - } - else if(sign == LV_SIGNAL_GET_STATE_DSC) { - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - lv_get_state_info_t * info = param; - if(info->part == LV_TABVIEW_PART_TAB_BG) info->result = lv_obj_get_state(ext->btns, LV_BTNMATRIX_PART_BG); - else if(info->part == LV_TABVIEW_PART_TAB_BTN) info->result = lv_obj_get_state(ext->btns, LV_BTNMATRIX_PART_BTN); - else if(info->part == LV_TABVIEW_PART_INDIC) info->result = lv_obj_get_state(ext->indic, LV_OBJ_PART_MAIN); - else if(info->part == LV_TABVIEW_PART_BG_SCRLLABLE) info->result = lv_obj_get_state(ext->content, - LV_PAGE_PART_SCROLLABLE); - return LV_RES_OK; - } - - /* Include the ancient signal function */ - res = ancestor_signal(tabview, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - if(sign == LV_SIGNAL_CLEANUP) { - uint8_t i; - for(i = 0; ext->tab_name_ptr[i][0] != '\0' && ext->tab_name_ptr[i][0] != '\n'; i++) lv_mem_free(ext->tab_name_ptr[i]); - - lv_mem_free(ext->tab_name_ptr); - ext->tab_name_ptr = NULL; - ext->btns = NULL; /*These objects were children so they are already invalid*/ - ext->content = NULL; - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - /*Be sure the buttons are updated because correct button size is required in `tabview_realign`*/ - lv_signal_send(ext->btns, LV_SIGNAL_STYLE_CHG, NULL); - - tabview_realign(tabview); - } - else if(sign == LV_SIGNAL_COORD_CHG) { - if(ext->content != NULL && (lv_obj_get_width(tabview) != lv_area_get_width(param) || - lv_obj_get_height(tabview) != lv_area_get_height(param))) { - tabview_realign(tabview); - } - } - else if(sign == LV_SIGNAL_RELEASED) { -#if LV_USE_GROUP - /*If released by a KEYPAD or ENCODER then really the tab buttons should be released. - * So simulate a CLICK on the tab buttons*/ - lv_indev_t * indev = lv_indev_get_act(); - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type == LV_INDEV_TYPE_KEYPAD || - (indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(lv_obj_get_group(tabview)))) { - lv_event_send(ext->btns, LV_EVENT_CLICKED, lv_event_get_data()); - } -#endif - } - else if(sign == LV_SIGNAL_GET_EDITABLE) { -#if LV_USE_GROUP - bool * editable = (bool *)param; - *editable = true; -#endif - } - - if(sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS || -#if LV_USE_GROUP - sign == LV_SIGNAL_CONTROL || -#endif - sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_RELEASED) { - - /* The button matrix is not in a group (the tab view is in it) but it should handle the - * group signals. So propagate the related signals to the button matrix manually*/ - ext->btns->signal_cb(ext->btns, sign, param); - - /*Make the active tab's button focused*/ - if(sign == LV_SIGNAL_FOCUS) { - lv_btnmatrix_set_focused_btn(ext->btns, ext->tab_cur); - } - - if(sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) { - lv_state_t state = lv_obj_get_state(tabview, LV_TABVIEW_PART_BG); - if(state & LV_STATE_FOCUSED) { - lv_obj_set_state(ext->btns, LV_STATE_FOCUSED); - lv_obj_set_state(ext->indic, LV_STATE_FOCUSED); - } - else { - lv_obj_clear_state(ext->btns, LV_STATE_FOCUSED); - lv_obj_clear_state(ext->indic, LV_STATE_FOCUSED); - - } - if(state & LV_STATE_EDITED) { - lv_obj_set_state(ext->btns, LV_STATE_EDITED); - lv_obj_set_state(ext->indic, LV_STATE_EDITED); - } - else { - lv_obj_clear_state(ext->btns, LV_STATE_EDITED); - lv_obj_clear_state(ext->indic, LV_STATE_EDITED); - - } - } - } - - return res; -} - -/** - * Signal function of a tab views main scrollable area - * @param tab pointer to a tab page object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t tabview_scrl_signal(lv_obj_t * tabview_scrl, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_scrl_signal(tabview_scrl, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, ""); - - lv_obj_t * cont = lv_obj_get_parent(tabview_scrl); - lv_obj_t * tabview = lv_obj_get_parent(cont); - - if(sign == LV_SIGNAL_DRAG_THROW_BEGIN) { - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - lv_indev_t * indev = lv_indev_get_act(); - lv_point_t point_act; - lv_indev_get_point(indev, &point_act); - lv_point_t vect; - lv_indev_get_vect(indev, &vect); - lv_coord_t x_predict = 0; - - while(vect.x != 0) { - x_predict += vect.x; - vect.x = vect.x * (100 - LV_INDEV_DEF_DRAG_THROW) / 100; - } - - res = lv_indev_finish_drag(indev); - if(res != LV_RES_OK) return res; - lv_obj_t * tab_page = lv_tabview_get_tab(tabview, ext->tab_cur); - if(tab_page == NULL) return LV_RES_OK; - lv_coord_t page_x1 = tab_page->coords.x1 - tabview->coords.x1 + x_predict; - lv_coord_t page_x2 = page_x1 + lv_obj_get_width(tabview); - lv_coord_t treshold = lv_obj_get_width(tabview) / 2; - - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(tabview); - int16_t tab_cur = ext->tab_cur; - if(page_x1 > treshold) { - if(base_dir != LV_BIDI_DIR_RTL) tab_cur--; - else tab_cur ++; - } - else if(page_x2 < treshold) { - if(base_dir != LV_BIDI_DIR_RTL) tab_cur++; - else tab_cur --; - } - - if(tab_cur > ext->tab_cnt - 1) tab_cur = ext->tab_cnt - 1; - if(tab_cur < 0) tab_cur = 0; - - uint32_t id_prev = lv_tabview_get_tab_act(tabview); - lv_tabview_set_tab_act(tabview, tab_cur, LV_ANIM_ON); - uint32_t id_new = lv_tabview_get_tab_act(tabview); - - if(id_prev != id_new) res = lv_event_send(tabview, LV_EVENT_VALUE_CHANGED, &id_prev); - if(res != LV_RES_OK) return res; - - } - return res; -} - -/** - * Get the style descriptor of a part of the object - * @param page pointer the object - * @param part the part from `lv_tabview_part_t`. (LV_TABVIEW_PART_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_tabview_get_style(lv_obj_t * tabview, uint8_t part) -{ - LV_ASSERT_OBJ(tabview, LV_OBJX_NAME); - - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_TABVIEW_PART_BG: - style_dsc_p = &tabview->style_list; - break; - case LV_TABVIEW_PART_BG_SCRLLABLE: - style_dsc_p = lv_obj_get_style_list(ext->content, LV_PAGE_PART_SCROLLABLE); - break; - case LV_TABVIEW_PART_TAB_BG: - style_dsc_p = lv_obj_get_style_list(ext->btns, LV_BTNMATRIX_PART_BG); - break; - case LV_TABVIEW_PART_TAB_BTN: - style_dsc_p = lv_obj_get_style_list(ext->btns, LV_BTNMATRIX_PART_BTN); - break; - case LV_TABVIEW_PART_INDIC: - style_dsc_p = lv_obj_get_style_list(ext->indic, LV_OBJ_PART_MAIN); - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - - -/** - * Called when a tab button is clicked - * @param tab_btnm pointer to the tab's button matrix object - * @param event type of the event - */ -static void tab_btnm_event_cb(lv_obj_t * tab_btnm, lv_event_t event) -{ - if(event != LV_EVENT_CLICKED) return; - - uint16_t btn_id = lv_btnmatrix_get_active_btn(tab_btnm); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return; - - if(lv_btnmatrix_get_btn_ctrl(tab_btnm, btn_id, LV_BTNMATRIX_CTRL_DISABLED)) return; - - lv_btnmatrix_clear_btn_ctrl_all(tab_btnm, LV_BTNMATRIX_CTRL_CHECK_STATE); - lv_btnmatrix_set_btn_ctrl(tab_btnm, btn_id, LV_BTNMATRIX_CTRL_CHECK_STATE); - - lv_obj_t * tabview = lv_obj_get_parent(tab_btnm); - - uint32_t id_prev = lv_tabview_get_tab_act(tabview); - lv_tabview_set_tab_act(tabview, btn_id, LV_ANIM_ON); - uint32_t id_new = lv_tabview_get_tab_act(tabview); - - lv_res_t res = LV_RES_OK; - if(id_prev != id_new) res = lv_event_send(tabview, LV_EVENT_VALUE_CHANGED, &id_new); - -#if LV_USE_GROUP - if(lv_indev_get_type(lv_indev_get_act()) == LV_INDEV_TYPE_ENCODER) { - lv_group_set_editing(lv_obj_get_group(tabview), false); - } -#endif - - if(res != LV_RES_OK) return; -} - -/** - * Realign and resize the elements of Tab view - * @param tabview pointer to a Tab view object - */ -static void tabview_realign(lv_obj_t * tabview) -{ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - refr_btns_size(tabview); - refr_content_size(tabview); - refr_indic_size(tabview); - - refr_align(tabview); - - lv_tabview_set_tab_act(tabview, ext->tab_cur, LV_ANIM_OFF); -} - -static void refr_indic_size(lv_obj_t * tabview) -{ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - lv_btnmatrix_ext_t * btnm_ext = lv_obj_get_ext_attr(ext->btns); - - lv_coord_t indic_size = lv_obj_get_style_size(tabview, LV_TABVIEW_PART_INDIC); - - /*Set the indicator width/height*/ - lv_coord_t indic_w; - lv_coord_t indic_h; - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - lv_obj_set_hidden(ext->indic, true); - indic_w = 0; - indic_h = 0; - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - lv_obj_set_hidden(ext->indic, false); - if(ext->tab_cnt) { - indic_h = indic_size; - indic_w = lv_area_get_width(&btnm_ext->button_areas[0]); - } - else { - indic_w = 0; - indic_h = 0; - } - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - lv_obj_set_hidden(ext->indic, false); - if(ext->tab_cnt) { - indic_w = indic_size; - indic_h = lv_area_get_height(&btnm_ext->button_areas[0]); - } - else { - indic_w = 0; - indic_h = 0; - } - break; - } - - lv_obj_set_width(ext->indic, indic_w); - lv_obj_set_height(ext->indic, indic_h); -} - - -static void refr_btns_size(lv_obj_t * tabview) -{ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - lv_style_int_t tab_bg_left = lv_obj_get_style_pad_left(tabview, LV_TABVIEW_PART_TAB_BG); - lv_style_int_t tab_bg_right = lv_obj_get_style_pad_right(tabview, LV_TABVIEW_PART_TAB_BG); - lv_style_int_t tab_bg_top = lv_obj_get_style_pad_top(tabview, LV_TABVIEW_PART_TAB_BG); - lv_style_int_t tab_bg_bottom = lv_obj_get_style_pad_bottom(tabview, LV_TABVIEW_PART_TAB_BG); - - lv_style_int_t tab_left = lv_obj_get_style_pad_left(tabview, LV_TABVIEW_PART_TAB_BTN); - lv_style_int_t tab_right = lv_obj_get_style_pad_right(tabview, LV_TABVIEW_PART_TAB_BTN); - lv_style_int_t tab_top = lv_obj_get_style_pad_top(tabview, LV_TABVIEW_PART_TAB_BTN); - lv_style_int_t tab_bottom = lv_obj_get_style_pad_bottom(tabview, LV_TABVIEW_PART_TAB_BTN); - - const lv_font_t * font = lv_obj_get_style_text_font(tabview, LV_TABVIEW_PART_TAB_BTN); - - /*Set the tabs height/width*/ - lv_coord_t btns_w; - lv_coord_t btns_h; - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - btns_w = 0; - btns_h = 0; - lv_obj_set_hidden(ext->btns, true); - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - lv_obj_set_hidden(ext->btns, false); - btns_h = lv_font_get_line_height(font) + tab_top + tab_bottom + tab_bg_top + tab_bg_bottom; - btns_w = lv_obj_get_width(tabview); - - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - lv_obj_set_hidden(ext->btns, false); - btns_w = lv_font_get_glyph_width(font, 'A', '\0') + - tab_left + tab_right + tab_bg_left + tab_bg_right; - btns_h = lv_obj_get_height(tabview); - break; - } - - lv_obj_set_size(ext->btns, btns_w, btns_h); -} - -static void refr_content_size(lv_obj_t * tabview) -{ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - lv_coord_t cont_w; - lv_coord_t cont_h; - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - cont_w = lv_obj_get_width(tabview); - cont_h = lv_obj_get_height(tabview); - break; - case LV_TABVIEW_TAB_POS_TOP: - case LV_TABVIEW_TAB_POS_BOTTOM: - cont_w = lv_obj_get_width(tabview); - cont_h = lv_obj_get_height(tabview) - lv_obj_get_height(ext->btns); - break; - case LV_TABVIEW_TAB_POS_LEFT: - case LV_TABVIEW_TAB_POS_RIGHT: - cont_w = lv_obj_get_width(tabview) - lv_obj_get_width(ext->btns); - cont_h = lv_obj_get_height(tabview); - break; - } - - lv_obj_set_size(ext->content, cont_w, cont_h); - - /*Refresh the size of the tab pages too. `ext->content` has a layout to align the pages*/ - lv_style_int_t bg_top = lv_obj_get_style_pad_top(tabview, LV_TABVIEW_PART_BG_SCRLLABLE); - lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(tabview, LV_TABVIEW_PART_BG_SCRLLABLE); - cont_h -= bg_top + bg_bottom; - lv_obj_t * content_scrl = lv_page_get_scrollable(ext->content); - lv_obj_t * pages = lv_obj_get_child(content_scrl, NULL); - while(pages != NULL) { - /*Be sure adjust only the pages (user can other things)*/ - if(lv_obj_get_signal_cb(pages) == page_signal) { - lv_obj_set_size(pages, cont_w, cont_h); - } - pages = lv_obj_get_child(content_scrl, pages); - } -} - -static void refr_align(lv_obj_t * tabview) -{ - lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview); - - switch(ext->btns_pos) { - default: /*default case is prevented in lv_tabview_set_btns_pos(), but here for safety*/ - case LV_TABVIEW_TAB_POS_NONE: - lv_obj_align(ext->content, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); - break; - case LV_TABVIEW_TAB_POS_TOP: - lv_obj_align(ext->btns, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_align(ext->content, ext->btns, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); - lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - break; - case LV_TABVIEW_TAB_POS_BOTTOM: - lv_obj_align(ext->content, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_align(ext->btns, ext->content, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); - lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_TOP_LEFT, 0, 0); - break; - case LV_TABVIEW_TAB_POS_LEFT: - lv_obj_align(ext->btns, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_align(ext->content, tabview, LV_ALIGN_IN_TOP_LEFT, lv_obj_get_width(ext->btns), 0); - lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - break; - case LV_TABVIEW_TAB_POS_RIGHT: - lv_obj_align(ext->btns, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - lv_obj_align(ext->content, tabview, LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_TOP_LEFT, 0, 0); - break; - } -} -#endif diff --git a/src/lv_widgets/lv_tabview.h b/src/lv_widgets/lv_tabview.h deleted file mode 100644 index eca985e62..000000000 --- a/src/lv_widgets/lv_tabview.h +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @file lv_tabview.h - * - */ - -#ifndef LV_TABVIEW_H -#define LV_TABVIEW_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_TABVIEW != 0 - -/*Testing of dependencies*/ -#if LV_USE_BTNMATRIX == 0 -#error "lv_tabview: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " -#endif - -#if LV_USE_PAGE == 0 -#error "lv_tabview: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "../lv_widgets/lv_win.h" -#include "../lv_widgets/lv_page.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** Position of tabview buttons. */ -enum { - LV_TABVIEW_TAB_POS_NONE, - LV_TABVIEW_TAB_POS_TOP, - LV_TABVIEW_TAB_POS_BOTTOM, - LV_TABVIEW_TAB_POS_LEFT, - LV_TABVIEW_TAB_POS_RIGHT -}; -typedef uint8_t lv_tabview_btns_pos_t; - -/*Data of tab*/ -typedef struct { - /*Ext. of ancestor*/ - /*New data for this type */ - lv_obj_t * btns; - lv_obj_t * indic; - lv_obj_t * content; /*A background page which holds tab's pages*/ - const char ** tab_name_ptr; - lv_point_t point_last; - uint16_t tab_cur; - uint16_t tab_cnt; -#if LV_USE_ANIMATION - uint16_t anim_time; -#endif - lv_tabview_btns_pos_t btns_pos : 3; -} lv_tabview_ext_t; - -enum { - LV_TABVIEW_PART_BG = LV_OBJ_PART_MAIN, - _LV_TABVIEW_PART_VIRTUAL_LAST = _LV_OBJ_PART_VIRTUAL_LAST, - - LV_TABVIEW_PART_BG_SCRLLABLE = _LV_OBJ_PART_REAL_LAST, - LV_TABVIEW_PART_TAB_BG, - LV_TABVIEW_PART_TAB_BTN, - LV_TABVIEW_PART_INDIC, - _LV_TABVIEW_PART_REAL_LAST, -}; -typedef uint8_t lv_tabview_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a Tab view object - * @param par pointer to an object, it will be the parent of the new tab - * @param copy pointer to a tab object, if not NULL then the new object will be copied from it - * @return pointer to the created tab - */ -lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add a new tab with the given name - * @param tabview pointer to Tab view object where to ass the new tab - * @param name the text on the tab button - * @return pointer to the created page object (lv_page). You can create your content here - */ -lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name); - -/** - * Delete all children of a tab created by `lv_tabview_add_tab`. - * @param tab pointer to a tab - */ -void lv_tabview_clean_tab(lv_obj_t * tab); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new tab - * @param tabview pointer to Tab view object - * @param id index of a tab to load - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t anim); - -/** - * Set the name of a tab. - * @param tabview pointer to Tab view object - * @param id index of the tab the name should be set - * @param name new tab name - */ -void lv_tabview_set_tab_name(lv_obj_t * tabview, uint16_t id, char * name); - -/** - * Set the animation time of tab view when a new tab is loaded - * @param tabview pointer to Tab view object - * @param anim_time time of animation in milliseconds - */ -void lv_tabview_set_anim_time(lv_obj_t * tabview, uint16_t anim_time); - -/** - * Set the position of tab select buttons - * @param tabview pointer to a tab view object - * @param btns_pos which button position - */ -void lv_tabview_set_btns_pos(lv_obj_t * tabview, lv_tabview_btns_pos_t btns_pos); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the index of the currently active tab - * @param tabview pointer to Tab view object - * @return the active tab index - */ -uint16_t lv_tabview_get_tab_act(const lv_obj_t * tabview); - -/** - * Get the number of tabs - * @param tabview pointer to Tab view object - * @return tab count - */ -uint16_t lv_tabview_get_tab_count(const lv_obj_t * tabview); -/** - * Get the page (content area) of a tab - * @param tabview pointer to Tab view object - * @param id index of the tab (>= 0) - * @return pointer to page (lv_page) object - */ -lv_obj_t * lv_tabview_get_tab(const lv_obj_t * tabview, uint16_t id); - -/** - * Get the animation time of tab view when a new tab is loaded - * @param tabview pointer to Tab view object - * @return time of animation in milliseconds - */ -uint16_t lv_tabview_get_anim_time(const lv_obj_t * tabview); - -/** - * Get position of tab select buttons - * @param tabview pointer to a ab view object - */ -lv_tabview_btns_pos_t lv_tabview_get_btns_pos(const lv_obj_t * tabview); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_TABVIEW*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_TABVIEW_H*/ diff --git a/src/lv_widgets/lv_tileview.c b/src/lv_widgets/lv_tileview.c deleted file mode 100644 index 73014a7f5..000000000 --- a/src/lv_widgets/lv_tileview.c +++ /dev/null @@ -1,475 +0,0 @@ -/** - * @file lv_tileview.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_tileview.h" -#if LV_USE_TILEVIEW != 0 - -#include -#include "lv_cont.h" -#include "../lv_misc/lv_math.h" -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_tileview" - -#if LV_USE_ANIMATION - #ifndef LV_TILEVIEW_DEF_ANIM_TIME - #define LV_TILEVIEW_DEF_ANIM_TIME 300 /*Animation time loading a tile [ms] (0: no animation) */ - #endif -#else - #undef LV_TILEVIEW_DEF_ANIM_TIME - #define LV_TILEVIEW_DEF_ANIM_TIME 0 /*No animations*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param); -static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param); -static void drag_end_handler(lv_obj_t * tileview); -static bool set_valid_drag_dirs(lv_obj_t * tileview); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_signal_cb_t ancestor_signal; -static lv_signal_cb_t ancestor_scrl_signal; -static lv_design_cb_t ancestor_design; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a tileview object - * @param par pointer to an object, it will be the parent of the new tileview - * @param copy pointer to a tileview object, if not NULL then the new object will be copied from it - * @return pointer to the created tileview - */ -lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("tileview create started"); - - /*Create the ancestor of tileview*/ - lv_obj_t * new_tileview = lv_page_create(par, copy); - LV_ASSERT_MEM(new_tileview); - if(new_tileview == NULL) return NULL; - - /*Allocate the tileview type specific extended data*/ - lv_tileview_ext_t * ext = lv_obj_allocate_ext_attr(new_tileview, sizeof(lv_tileview_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(new_tileview); - return NULL; - } - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_tileview); - if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(new_tileview)); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_tileview); - - /*Initialize the allocated 'ext' */ -#if LV_USE_ANIMATION - ext->anim_time = LV_TILEVIEW_DEF_ANIM_TIME; -#endif - ext->act_id.x = 0; - ext->act_id.y = 0; - ext->valid_pos = NULL; - ext->valid_pos_cnt = 0; - - /*The signal and design functions are not copied so set them here*/ - lv_obj_set_signal_cb(new_tileview, lv_tileview_signal); - lv_obj_set_signal_cb(lv_page_get_scrollable(new_tileview), lv_tileview_scrl_signal); - - /*Init the new tileview*/ - if(copy == NULL) { - /* Set a size which fits into the parent. - * Don't use `par` directly because if the tileview is created on a page it is moved to the - * scrollable so the parent has changed */ - lv_coord_t w; - lv_coord_t h; - if(par) { - w = lv_obj_get_width_fit(lv_obj_get_parent(new_tileview)); - h = lv_obj_get_height_fit(lv_obj_get_parent(new_tileview)); - } - else { - w = lv_disp_get_hor_res(NULL); - h = lv_disp_get_ver_res(NULL); - } - - lv_obj_set_size(new_tileview, w, h); - lv_obj_set_drag_throw(lv_page_get_scrollable(new_tileview), true); - lv_obj_set_drag_dir(lv_page_get_scrollable(new_tileview), LV_DRAG_DIR_ONE); - - lv_page_set_scrollable_fit(new_tileview, LV_FIT_MAX); - - lv_obj_reset_style_list(new_tileview, LV_PAGE_PART_SCROLLABLE); - lv_theme_apply(new_tileview, LV_THEME_TILEVIEW); - } - /*Copy an existing tileview*/ - else { - lv_tileview_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->act_id.x = copy_ext->act_id.x; - ext->act_id.y = copy_ext->act_id.y; - ext->valid_pos = copy_ext->valid_pos; - ext->valid_pos_cnt = copy_ext->valid_pos_cnt; -#if LV_USE_ANIMATION - ext->anim_time = copy_ext->anim_time; -#endif - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(new_tileview, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - } - - LV_LOG_INFO("tileview created"); - - return new_tileview; -} - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Register an object on the tileview. The register object will able to slide the tileview - * @param tileview pointer to a Tileview object - * @param element pointer to an object - */ -void lv_tileview_add_element(lv_obj_t * tileview, lv_obj_t * element) -{ - LV_UNUSED(tileview); - LV_ASSERT_OBJ(tileview, LV_OBJX_NAME); - LV_ASSERT_NULL(tileview); - - lv_page_glue_obj(tileview, element, true); -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the valid position's indices. The scrolling will be possible only to these positions. - * @param tileview pointer to a Tileview object - * @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}`. - * Only the pointer is saved so can't be a local variable. - * @param valid_pos_cnt number of elements in `valid_pos` array - */ -void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t valid_pos[], uint16_t valid_pos_cnt) -{ - LV_ASSERT_OBJ(tileview, LV_OBJX_NAME); - LV_ASSERT_NULL(valid_pos); - - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - ext->valid_pos = valid_pos; - ext->valid_pos_cnt = valid_pos_cnt; - - set_valid_drag_dirs(tileview); - - /*If valid pos. is selected do nothing*/ - uint16_t i; - for(i = 0; i < valid_pos_cnt; i++) { - if(valid_pos[i].x == ext->act_id.x && valid_pos[i].y == ext->act_id.y) { - return; - } - } - - /*Set a valid position if now an invalid is selected*/ - if(valid_pos_cnt > 0) { - lv_tileview_set_tile_act(tileview, valid_pos[0].x, valid_pos[0].y, LV_ANIM_OFF); - } -} - -/** - * Set the tile to be shown - * @param tileview pointer to a tileview object - * @param x column id (0, 1, 2...) - * @param y line id (0, 1, 2...) - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim) -{ - LV_ASSERT_OBJ(tileview, LV_OBJX_NAME); - -#if LV_USE_ANIMATION == 0 - anim = LV_ANIM_OFF; -#endif - - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - - uint32_t tile_id; - bool valid = false; - for(tile_id = 0; tile_id < ext->valid_pos_cnt; tile_id++) { - if(ext->valid_pos[tile_id].x == x && ext->valid_pos[tile_id].y == y) { - valid = true; - break; - } - } - - if(valid == false) return; /*Don't load not valid tiles*/ - - ext->act_id.x = x; - ext->act_id.y = y; - - lv_coord_t x_coord = -x * lv_obj_get_width(tileview); - lv_coord_t y_coord = -y * lv_obj_get_height(tileview); - lv_obj_t * scrl = lv_page_get_scrollable(tileview); - if(anim) { -#if LV_USE_ANIMATION - lv_coord_t x_act = lv_obj_get_x(scrl); - lv_coord_t y_act = lv_obj_get_y(scrl); - - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, scrl); - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x); - lv_anim_set_time(&a, ext->anim_time); - - - if(x_coord != x_act) { - lv_anim_set_values(&a, x_act, x_coord); - lv_anim_start(&a); - } - - if(y_coord != y_act) { - lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); - lv_anim_set_values(&a, y_act, y_coord); - lv_anim_start(&a); - } -#endif - } - else { - lv_obj_set_pos(scrl, x_coord, y_coord); - } - - lv_res_t res; - res = lv_event_send(tileview, LV_EVENT_VALUE_CHANGED, &tile_id); - if(res != LV_RES_OK) return; /*Prevent the tile loading*/ - - set_valid_drag_dirs(tileview); -} - -/*===================== - * Getter functions - *====================*/ - -/* - * New object specific "get" functions come here - */ -/** -* Get the tile to be shown -* @param tileview pointer to a tileview object -* @param x column id (0, 1, 2...) -* @param y line id (0, 1, 2...) -*/ -void lv_tileview_get_tile_act(lv_obj_t * tileview, lv_coord_t * x, lv_coord_t * y) -{ - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - - *x = ext->act_id.x; - *y = ext->act_id.y; -} - -/*===================== - * Other functions - *====================*/ - -/* - * New object specific "other" functions come here - */ - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Signal function of the tileview - * @param tileview pointer to a tileview object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param) -{ - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_signal(tileview, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - if(sign == LV_SIGNAL_CLEANUP) { - /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } - - return res; -} - -/** - * Signal function of the tileview scrollable - * @param tileview pointer to the scrollable part of the tileview object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param) -{ - - lv_res_t res; - - /* Include the ancient signal function */ - res = ancestor_scrl_signal(scrl, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, ""); - - lv_obj_t * tileview = lv_obj_get_parent(scrl); - - if(sign == LV_SIGNAL_DRAG_BEGIN) { - set_valid_drag_dirs(tileview); - } - else if(sign == LV_SIGNAL_DRAG_THROW_BEGIN) { - drag_end_handler(tileview); - - res = lv_indev_finish_drag(lv_indev_get_act()); - if(res != LV_RES_OK) return res; - } - /*Apply constraint on moving of the tileview*/ - else if(sign == LV_SIGNAL_COORD_CHG) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev) { - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - - lv_coord_t x = lv_obj_get_x(scrl); - lv_coord_t y = lv_obj_get_y(scrl); - lv_coord_t h = lv_obj_get_height(tileview); - lv_coord_t w = lv_obj_get_width(tileview); - lv_coord_t top = lv_obj_get_style_pad_top(tileview, LV_TILEVIEW_PART_BG); - lv_coord_t left = lv_obj_get_style_pad_left(tileview, LV_TILEVIEW_PART_BG); - if(!ext->drag_top_en && y > -(ext->act_id.y * h) && indev->proc.types.pointer.vect.y > 0) { - lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_TOP); - lv_obj_set_y(scrl, -ext->act_id.y * h + top); - } - if(!ext->drag_bottom_en && indev->proc.types.pointer.vect.y < 0 && y < -(ext->act_id.y * h)) { - lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_BOTTOM); - lv_obj_set_y(scrl, -ext->act_id.y * h + top); - } - - if(!ext->drag_left_en && x > -(ext->act_id.x * w) && indev->proc.types.pointer.vect.x > 0) { - lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_LEFT); - lv_obj_set_x(scrl, -ext->act_id.x * w + left); - } - - if(!ext->drag_right_en && indev->proc.types.pointer.vect.x < 0 && x < -(ext->act_id.x * w)) { - lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_RIGHT); - lv_obj_set_x(scrl, -ext->act_id.x * w + left); - } - - /*Apply the drag constraints*/ - lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir; - if(drag_dir == LV_DRAG_DIR_HOR) - lv_obj_set_y(scrl, -ext->act_id.y * lv_obj_get_height(tileview) + top); - else if(drag_dir == LV_DRAG_DIR_VER) - lv_obj_set_x(scrl, -ext->act_id.x * lv_obj_get_width(tileview) + left); - } - } - return res; -} - -/** - * Called when the user releases an element of the tileview after dragging it. - * @param tileview pointer to a tileview object - */ -static void drag_end_handler(lv_obj_t * tileview) -{ - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - lv_indev_t * indev = lv_indev_get_act(); - lv_point_t point_act; - lv_indev_get_point(indev, &point_act); - lv_obj_t * scrl = lv_page_get_scrollable(tileview); - lv_point_t p; - - p.x = -(lv_obj_get_x(scrl) - lv_obj_get_width(tileview) / 2); - p.y = -(lv_obj_get_y(scrl) - lv_obj_get_height(tileview) / 2); - - lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir; - /*From the drag vector (drag throw) predict the end position*/ - if(drag_dir & LV_DRAG_DIR_HOR) { - lv_point_t vect; - lv_indev_get_vect(indev, &vect); - lv_coord_t predict = 0; - - while(vect.x != 0) { - predict += vect.x; - vect.x = vect.x * (100 - LV_INDEV_DEF_DRAG_THROW) / 100; - } - - p.x -= predict; - - } - else if(drag_dir & LV_DRAG_DIR_VER) { - lv_point_t vect; - lv_indev_get_vect(indev, &vect); - lv_coord_t predict = 0; - - while(vect.y != 0) { - predict += vect.y; - vect.y = vect.y * (100 - LV_INDEV_DEF_DRAG_THROW) / 100; - } - - p.y -= predict; - } - - /*Get the index of the tile*/ - p.x = p.x / lv_obj_get_width(tileview); - p.y = p.y / lv_obj_get_height(tileview); - - /*Max +- move*/ - lv_coord_t x_move = p.x - ext->act_id.x; - lv_coord_t y_move = p.y - ext->act_id.y; - if(x_move < -1) x_move = -1; - if(x_move > 1) x_move = 1; - if(y_move < -1) y_move = -1; - if(y_move > 1) y_move = 1; - - /*Set the new tile*/ - lv_tileview_set_tile_act(tileview, ext->act_id.x + x_move, ext->act_id.y + y_move, true); -} - -static bool set_valid_drag_dirs(lv_obj_t * tileview) -{ - - lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview); - if(ext->valid_pos == NULL) return false; - - ext->drag_bottom_en = 0; - ext->drag_top_en = 0; - ext->drag_left_en = 0; - ext->drag_right_en = 0; - - uint16_t i; - for(i = 0; i < ext->valid_pos_cnt; i++) { - if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y - 1) ext->drag_top_en = 1; - if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y + 1) ext->drag_bottom_en = 1; - if(ext->valid_pos[i].x == ext->act_id.x - 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_left_en = 1; - if(ext->valid_pos[i].x == ext->act_id.x + 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_right_en = 1; - } - - return true; -} - -#endif diff --git a/src/lv_widgets/lv_tileview.h b/src/lv_widgets/lv_tileview.h deleted file mode 100644 index 984fc3950..000000000 --- a/src/lv_widgets/lv_tileview.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file lv_tileview.h - * - */ - -#ifndef LV_TILEVIEW_H -#define LV_TILEVIEW_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_TILEVIEW != 0 - -#include "../lv_widgets/lv_page.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/*Data of tileview*/ -typedef struct { - lv_page_ext_t page; - /*New data for this type */ - const lv_point_t * valid_pos; - uint16_t valid_pos_cnt; -#if LV_USE_ANIMATION - uint16_t anim_time; -#endif - lv_point_t act_id; - uint8_t drag_top_en : 1; - uint8_t drag_bottom_en : 1; - uint8_t drag_left_en : 1; - uint8_t drag_right_en : 1; -} lv_tileview_ext_t; - -/*Parts of the Tileview*/ -enum { - LV_TILEVIEW_PART_BG = LV_PAGE_PART_BG, - LV_TILEVIEW_PART_SCROLLBAR = LV_PAGE_PART_SCROLLBAR, - LV_TILEVIEW_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH, - _LV_TILEVIEW_PART_VIRTUAL_LAST = _LV_PAGE_PART_VIRTUAL_LAST, - _LV_TILEVIEW_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST -}; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a tileview objects - * @param par pointer to an object, it will be the parent of the new tileview - * @param copy pointer to a tileview object, if not NULL then the new object will be copied from it - * @return pointer to the created tileview - */ -lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Register an object on the tileview. The register object will able to slide the tileview - * @param tileview pointer to a Tileview object - * @param element pointer to an object - */ -void lv_tileview_add_element(lv_obj_t * tileview, lv_obj_t * element); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the valid position's indices. The scrolling will be possible only to these positions. - * @param tileview pointer to a Tileview object - * @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}`. - * Only the pointer is saved so can't be a local variable. - * @param valid_pos_cnt number of elements in `valid_pos` array - */ -void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t valid_pos[], uint16_t valid_pos_cnt); - -/** - * Set the tile to be shown - * @param tileview pointer to a tileview object - * @param x column id (0, 1, 2...) - * @param y line id (0, 1, 2...) - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately - */ -void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim); - -/** - * Enable the edge flash effect. (Show an arc when the an edge is reached) - * @param tileview pointer to a Tileview - * @param en true or false to enable/disable end flash - */ -static inline void lv_tileview_set_edge_flash(lv_obj_t * tileview, bool en) -{ - lv_page_set_edge_flash(tileview, en); -} - -/** - * Set the animation time for the Tile view - * @param tileview pointer to a page object - * @param anim_time animation time in milliseconds - */ -static inline void lv_tileview_set_anim_time(lv_obj_t * tileview, uint16_t anim_time) -{ - lv_page_set_anim_time(tileview, anim_time); -} - -/*===================== - * Getter functions - *====================*/ -/** -* Get the tile to be shown -* @param tileview pointer to a tileview object -* @param x column id (0, 1, 2...) -* @param y line id (0, 1, 2...) -*/ -void lv_tileview_get_tile_act(lv_obj_t * tileview, lv_coord_t * x, lv_coord_t * y); -/** - * Get the scroll propagation property - * @param tileview pointer to a Tileview - * @return true or false - */ -static inline bool lv_tileview_get_edge_flash(lv_obj_t * tileview) -{ - return lv_page_get_edge_flash(tileview); -} - -/** - * Get the animation time for the Tile view - * @param tileview pointer to a page object - * @return animation time in milliseconds - */ -static inline uint16_t lv_tileview_get_anim_time(lv_obj_t * tileview) -{ - return lv_page_get_anim_time(tileview); -} - -/*===================== - * Other functions - *====================*/ - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_TILEVIEW*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_TILEVIEW_H*/ diff --git a/src/lv_widgets/lv_win.c b/src/lv_widgets/lv_win.c deleted file mode 100644 index 0e122976d..000000000 --- a/src/lv_widgets/lv_win.c +++ /dev/null @@ -1,807 +0,0 @@ -/** - * @file lv_win.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_win.h" -#if LV_USE_WIN != 0 - -#include "../lv_misc/lv_debug.h" -#include "../lv_themes/lv_theme.h" -#include "../lv_core/lv_disp.h" - -/********************* - * DEFINES - *********************/ -#define LV_OBJX_NAME "lv_win" -#define DEF_TITLE "Window" - -/********************** - * TYPEDEFS - **********************/ - -/** Extended data of win_btn*/ -typedef struct { - /** Ext. of ancestor*/ - lv_btn_ext_t btn; - - /** Which side of the header should the button be aligned to. - * 0: Align to right (default), 1: Align to left */ - uint8_t alignment_in_header : 1; -} lv_win_btn_ext_t; - -enum { - LV_WIN_BTN_ALIGN_RIGHT = 0, /**< Align button to right of the header */ - LV_WIN_BTN_ALIGN_LEFT /**< Align button to left of the header */ -}; -typedef uint8_t lv_win_btn_align_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param); -static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_style_list_t * lv_win_get_style(lv_obj_t * win, uint8_t part); -static void lv_win_realign(lv_obj_t * win); -static lv_obj_t * lv_win_btn_create(lv_obj_t * par, const void * img_src); -static void lv_win_btn_set_alignment(lv_obj_t * par, const lv_win_btn_align_t alignment); -static lv_win_btn_align_t lv_win_btn_get_alignment(const lv_obj_t * par); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_design_cb_t ancestor_header_design; -static lv_signal_cb_t ancestor_signal; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a window objects - * @param par pointer to an object, it will be the parent of the new window - * @param copy pointer to a window object, if not NULL then the new object will be copied from it - * @return pointer to the created window - */ -lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy) -{ - LV_LOG_TRACE("window create started"); - - /*Create the ancestor object*/ - lv_obj_t * new_win = lv_obj_create(par, copy); - LV_ASSERT_MEM(new_win); - if(new_win == NULL) return NULL; - - if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_win); - - /*Allocate the object type specific extended data*/ - lv_win_ext_t * ext = lv_obj_allocate_ext_attr(new_win, sizeof(lv_win_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(new_win); - return NULL; - } - - ext->page = NULL; - ext->header = NULL; - ext->title_txt = lv_mem_alloc(strlen(DEF_TITLE) + 1); - strcpy(ext->title_txt, DEF_TITLE); - - /*Init the new window object*/ - if(copy == NULL) { - /* Set a size which fits into the parent. - * Don't use `par` directly because if the window is created on a page it is moved to the - * scrollable so the parent has changed */ - lv_coord_t w; - lv_coord_t h; - if(par) { - w = lv_obj_get_width_fit(lv_obj_get_parent(new_win)); - h = lv_obj_get_height_fit(lv_obj_get_parent(new_win)); - } - else { - w = lv_disp_get_hor_res(NULL); - h = lv_disp_get_ver_res(NULL); - } - - lv_obj_set_size(new_win, w, h); - - ext->btn_w = LV_DPX(65); - - ext->page = lv_page_create(new_win, NULL); - lv_obj_add_protect(ext->page, LV_PROTECT_PARENT); - lv_page_set_scrollbar_mode(ext->page, LV_SCROLLBAR_MODE_AUTO); - lv_obj_clean_style_list(ext->page, LV_PAGE_PART_BG); - - /*Create a holder for the header*/ - ext->header = lv_obj_create(new_win, NULL); - /*Move back to window background because it's automatically moved to the content page*/ - lv_obj_add_protect(ext->header, LV_PROTECT_PARENT); - lv_obj_set_parent(ext->header, new_win); - if(ancestor_header_design == NULL) ancestor_header_design = lv_obj_get_design_cb(ext->header); - lv_obj_set_height(ext->header, LV_DPX(65)); - - lv_obj_set_design_cb(ext->header, lv_win_header_design); - lv_obj_set_signal_cb(new_win, lv_win_signal); - - lv_theme_apply(new_win, LV_THEME_WIN); - } - /*Copy an existing object*/ - else { - lv_win_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - /*Create the objects*/ - ext->header = lv_obj_create(new_win, copy_ext->header); - ext->title_txt = lv_mem_alloc(strlen(copy_ext->title_txt) + 1); - strcpy(ext->title_txt, copy_ext->title_txt); - ext->page = lv_page_create(new_win, copy_ext->page); - ext->btn_w = copy_ext->btn_w; - - /*Copy the buttons*/ - lv_obj_t * child; - child = lv_obj_get_child_back(copy_ext->header, NULL); - child = lv_obj_get_child_back(copy_ext->header, child); /*Sip the title*/ - while(child != NULL) { - lv_obj_t * btn = lv_btn_create(ext->header, child); - lv_img_create(btn, lv_obj_get_child(child, NULL)); - child = lv_obj_get_child_back(copy_ext->header, child); - } - - lv_obj_set_signal_cb(new_win, lv_win_signal); - } - - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(new_win, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); - - lv_win_realign(new_win); - - LV_LOG_INFO("window created"); - - return new_win; -} - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param win pointer to an object - */ -void lv_win_clean(lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_obj_t * scrl = lv_page_get_scrollable(win); - lv_obj_clean(scrl); -} - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add control button to the header of the window - * @param win pointer to a window object - * @param img_src an image source ('lv_img_t' variable, path to file or a symbol) - * @param alignment button alignment on the header - * @return pointer to the created button object - */ -lv_obj_t * lv_win_add_btn_right(lv_obj_t * win, const void * img_src) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - LV_ASSERT_NULL(img_src); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - lv_obj_t * btn = lv_win_btn_create(ext->header, img_src); - lv_win_btn_set_alignment(btn, LV_WIN_BTN_ALIGN_RIGHT); - - lv_win_realign(win); - - return btn; -} - -/** - * Add control button on the left side of the window header - * @param win pointer to a window object - * @param img_src an image source ('lv_img_t' variable, path to file or a symbol) - * @return pointer to the created button object - */ -lv_obj_t * lv_win_add_btn_left(lv_obj_t * win, const void * img_src) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - LV_ASSERT_NULL(img_src); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - lv_obj_t * btn = lv_win_btn_create(ext->header, img_src); - lv_win_btn_set_alignment(btn, LV_WIN_BTN_ALIGN_LEFT); - - lv_win_realign(win); - - return btn; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Can be assigned to a window control button to close the window - * @param btn pointer to the control button on the widows header - * @param evet the event type - */ -void lv_win_close_event_cb(lv_obj_t * btn, lv_event_t event) -{ - LV_ASSERT_OBJ(btn, "lv_btn"); - - if(event == LV_EVENT_RELEASED) { - lv_obj_t * win = lv_win_get_from_btn(btn); - - lv_obj_del(win); - } -} - -/** - * Set the title of a window - * @param win pointer to a window object - * @param title string of the new title - */ -void lv_win_set_title(lv_obj_t * win, const char * title) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - LV_ASSERT_STR(title); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - ext->title_txt = lv_mem_realloc(ext->title_txt, strlen(title) + 1); - LV_ASSERT_MEM(ext->title_txt); - if(ext->title_txt == NULL) return; - - strcpy(ext->title_txt, title); - lv_obj_invalidate(ext->header); -} - -/** - * Set the height of the header - * @param win pointer to a window object - * @param height height of the header - */ -void lv_win_set_header_height(lv_obj_t * win, lv_coord_t height) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - lv_obj_set_height(ext->header, height); - lv_win_realign(win); -} - -/** - * Set the width of the control buttons on the header - * @param win pointer to a window object - * @param width width of the control button. 0: to make them square automatically. - */ -void lv_win_set_btn_width(lv_obj_t * win, lv_coord_t width) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - ext->btn_w = width; - lv_win_realign(win); -} - -/** - * Set the size of the content area. - * It's the effective area where object can be placed. - * @param win pointer to a window object - * @param w width - * @param h height (the window will be higher with the height of the header) - */ -void lv_win_set_content_size(lv_obj_t * win, lv_coord_t w, lv_coord_t h) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - h += lv_obj_get_height(ext->header); - - lv_obj_set_size(win, w, h); -} - -/** - * Set the layout of the window - * @param win pointer to a window object - * @param layout the layout from 'lv_layout_t' - */ -void lv_win_set_layout(lv_obj_t * win, lv_layout_t layout) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_page_set_scrl_layout(ext->page, layout); -} - -/** - * Set the scroll bar mode of a window - * @param win pointer to a window object - * @param sb_mode the new scroll bar mode from 'lv_sb_mode_t' - */ -void lv_win_set_scrollbar_mode(lv_obj_t * win, lv_scrollbar_mode_t sb_mode) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_page_set_scrollbar_mode(ext->page, sb_mode); -} -/** - * Set focus animation duration on `lv_win_focus()` - * @param win pointer to a window object - * @param anim_time duration of animation [ms] - */ -void lv_win_set_anim_time(lv_obj_t * win, uint16_t anim_time) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_page_set_anim_time(lv_win_get_content(win), anim_time); -} - -/** - * Set drag status of a window. If set to 'true' window can be dragged like on a PC. - * @param win pointer to a window object - * @param en whether dragging is enabled - */ -void lv_win_set_drag(lv_obj_t * win, bool en) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_obj_t * win_header = ext->header; - lv_obj_set_drag_parent(win_header, en); - lv_obj_set_drag(win, en); -} - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the title of a window - * @param win pointer to a window object - * @return title string of the window - */ -const char * lv_win_get_title(const lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return ext->title_txt; -} - -/** - * Get the content holder object of window (`lv_page`) to allow additional customization - * @param win pointer to a window object - * @return the Page object where the window's content is - */ -lv_obj_t * lv_win_get_content(const lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return ext->page; -} - -/** - * Get the header height - * @param win pointer to a window object - * @return header height - */ -lv_coord_t lv_win_get_header_height(const lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return lv_obj_get_height(ext->header); -} - -/** - * Get the width of the control buttons on the header - * @param win pointer to a window object - * @return width of the control button. 0: square. - */ -lv_coord_t lv_win_get_btn_width(lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return ext->btn_w; - -} - -/** - * Get the pointer of a widow from one of its control button. - * It is useful in the action of the control buttons where only button is known. - * @param ctrl_btn pointer to a control button of a window - * @return pointer to the window of 'ctrl_btn' - */ -lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn) -{ - LV_ASSERT_OBJ(ctrl_btn, "lv_btn"); - - lv_obj_t * header = lv_obj_get_parent(ctrl_btn); - lv_obj_t * win = lv_obj_get_parent(header); - - return win; -} - -/** - * Get the layout of a window - * @param win pointer to a window object - * @return the layout of the window (from 'lv_layout_t') - */ -lv_layout_t lv_win_get_layout(lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return lv_page_get_scrl_layout(ext->page); -} - -/** - * Get the scroll bar mode of a window - * @param win pointer to a window object - * @return the scroll bar mode of the window (from 'lv_sb_mode_t') - */ -lv_scrollbar_mode_t lv_win_get_sb_mode(lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - return lv_page_get_scrollbar_mode(ext->page); -} - -/** - * Get focus animation duration - * @param win pointer to a window object - * @return duration of animation [ms] - */ -uint16_t lv_win_get_anim_time(const lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - return lv_page_get_anim_time(lv_win_get_content(win)); -} - -/** - * Get width of the content area (page scrollable) of the window - * @param win pointer to a window object - * @return the width of the content_bg area - */ -lv_coord_t lv_win_get_width(lv_obj_t * win) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_obj_t * scrl = lv_page_get_scrollable(ext->page); - lv_coord_t left = lv_obj_get_style_pad_left(win, LV_WIN_PART_BG); - lv_coord_t right = lv_obj_get_style_pad_left(win, LV_WIN_PART_BG); - - return lv_obj_get_width_fit(scrl) - left - right; -} - -/*===================== - * Other functions - *====================*/ - -/** - * Focus on an object. It ensures that the object will be visible in the window. - * @param win pointer to a window object - * @param obj pointer to an object to focus (must be in the window) - * @param anim_en LV_ANIM_ON focus with an animation; LV_ANIM_OFF focus without animation - */ -void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, lv_anim_enable_t anim_en) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - LV_ASSERT_OBJ(obj, ""); - - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_page_focus(ext->page, obj, anim_en); -} - -/********************** - * STATIC FUNCTIONS - **********************/ -/** - * Handle the drawing related tasks of the window header - * @param header pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return ancestor_header_design(header, clip_area, mode); - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - ancestor_header_design(header, clip_area, mode); - - lv_obj_t * win = lv_obj_get_parent(header); - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - lv_style_int_t header_left = lv_obj_get_style_pad_left(win, LV_WIN_PART_HEADER); - lv_style_int_t header_inner = lv_obj_get_style_pad_inner(win, LV_WIN_PART_HEADER); - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(header, LV_OBJ_PART_MAIN, &label_dsc); - - lv_area_t txt_area; - lv_point_t txt_size; - - _lv_txt_get_size(&txt_size, ext->title_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - label_dsc.flag); - - lv_obj_t * btn = NULL; - - lv_coord_t btn_h = lv_obj_get_height_fit(header); - lv_coord_t btn_w = ext->btn_w != 0 ? ext->btn_w : btn_h; - - /*Get x position of the title (should be on the right of the buttons on the left)*/ - - lv_coord_t left_btn_offset = 0; - btn = lv_obj_get_child_back(ext->header, NULL); - while(btn != NULL) { - if(LV_WIN_BTN_ALIGN_LEFT == lv_win_btn_get_alignment(btn)) { - left_btn_offset += btn_w + header_inner; - } - - btn = lv_obj_get_child_back(header, btn); - } - - txt_area.x1 = header->coords.x1 + header_left + left_btn_offset; - txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2; - txt_area.x2 = txt_area.x1 + txt_size.x + left_btn_offset; - txt_area.y2 = txt_area.y1 + txt_size.y; - - lv_draw_label(&txt_area, clip_area, &label_dsc, ext->title_txt, NULL); - } - else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_header_design(header, clip_area, mode); - } - - return LV_DESIGN_RES_OK; -} -/** - * Signal function of the window - * @param win pointer to a window object - * @param sign a signal type from lv_signal_t enum - * @param param pointer to a signal specific variable - * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted - */ -static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param) -{ - lv_res_t res; - - if(sign == LV_SIGNAL_GET_STYLE) { - lv_get_style_info_t * info = param; - info->result = lv_win_get_style(win, info->part); - if(info->result != NULL) return LV_RES_OK; - else return ancestor_signal(win, sign, param); - } - else if(sign == LV_SIGNAL_GET_STATE_DSC) { - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_get_state_info_t * info = param; - if(info->part == LV_WIN_PART_CONTENT_SCROLLABLE) info->result = lv_obj_get_state(lv_page_get_scrollable(ext->page), - LV_CONT_PART_MAIN); - else if(info->part == LV_WIN_PART_SCROLLBAR) info->result = lv_obj_get_state(ext->page, LV_PAGE_PART_SCROLLBAR); - else if(info->part == LV_WIN_PART_HEADER) info->result = lv_obj_get_state(ext->header, LV_OBJ_PART_MAIN); - return LV_RES_OK; - } - - /* Include the ancient signal function */ - res = ancestor_signal(win, sign, param); - if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - if(sign == LV_SIGNAL_CHILD_CHG) { /*Move children to the page*/ - lv_obj_t * page = ext->page; - if(page != NULL) { - lv_obj_t * child; - child = lv_obj_get_child(win, NULL); - while(child != NULL) { - if(lv_obj_is_protected(child, LV_PROTECT_PARENT) == false) { - lv_obj_t * tmp = child; - child = lv_obj_get_child(win, child); /*Get the next child before move this*/ - lv_obj_set_parent(tmp, page); - } - else { - child = lv_obj_get_child(win, child); - } - } - } - } - else if(sign == LV_SIGNAL_STYLE_CHG) { - lv_win_realign(win); - } - else if(sign == LV_SIGNAL_COORD_CHG) { - /*If the size is changed refresh the window*/ - if(lv_area_get_width(param) != lv_obj_get_width(win) || lv_area_get_height(param) != lv_obj_get_height(win)) { - lv_win_realign(win); - } - } - else if(sign == LV_SIGNAL_CLEANUP) { - ext->header = NULL; /*These objects were children so they are already invalid*/ - ext->page = NULL; - lv_mem_free(ext->title_txt); - ext->title_txt = NULL; - } - else if(sign == LV_SIGNAL_CONTROL) { -#if LV_USE_GROUP - /*Forward all the control signals to the page*/ - ext->page->signal_cb(ext->page, sign, param); -#endif - } - - return res; -} -/** - * Get the style descriptor of a part of the object - * @param win pointer the object - * @param part the part of the win. (LV_PAGE_WIN_...) - * @return pointer to the style descriptor of the specified part - */ -static lv_style_list_t * lv_win_get_style(lv_obj_t * win, uint8_t part) -{ - LV_ASSERT_OBJ(win, LV_OBJX_NAME); - - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_style_list_t * style_dsc_p; - - switch(part) { - case LV_WIN_PART_BG: - style_dsc_p = &win->style_list; - break; - case LV_WIN_PART_HEADER: - style_dsc_p = lv_obj_get_style_list(ext->header, LV_OBJ_PART_MAIN); - break; - case LV_WIN_PART_SCROLLBAR: - style_dsc_p = lv_obj_get_style_list(ext->page, LV_PAGE_PART_SCROLLBAR); - break; - case LV_WIN_PART_CONTENT_SCROLLABLE: - style_dsc_p = lv_obj_get_style_list(ext->page, LV_PAGE_PART_SCROLLABLE); - break; - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} -/** - * Realign the building elements of a window - * @param win pointer to a window object - */ -static void lv_win_realign(lv_obj_t * win) -{ - lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - - if(ext->page == NULL || ext->header == NULL) return; - - lv_obj_set_width(ext->header, lv_obj_get_width(win)); - - lv_obj_t * btn; - lv_obj_t * btn_prev_at_left = NULL; - lv_obj_t * btn_prev_at_right = NULL; - - bool is_header_right_side_empty = true; - bool is_header_left_side_empty = true; - - lv_coord_t btn_h = lv_obj_get_height_fit(ext->header); - lv_coord_t btn_w = ext->btn_w != 0 ? ext->btn_w : btn_h; - lv_style_int_t header_inner = lv_obj_get_style_pad_inner(win, LV_WIN_PART_HEADER); - lv_style_int_t header_right = lv_obj_get_style_pad_right(win, LV_WIN_PART_HEADER); - lv_style_int_t header_left = lv_obj_get_style_pad_left(win, LV_WIN_PART_HEADER); - - /*Refresh the size of all control buttons*/ - btn = lv_obj_get_child_back(ext->header, NULL); - while(btn != NULL) { - lv_obj_set_size(btn, btn_w, btn_h); - uint8_t btn_alignment = lv_win_btn_get_alignment(btn); - - if(LV_WIN_BTN_ALIGN_RIGHT == btn_alignment) { - if(is_header_right_side_empty) { - /* Align the button to the right of the header */ - lv_obj_align(btn, ext->header, LV_ALIGN_IN_RIGHT_MID, -header_right, 0); - - is_header_right_side_empty = false; - } - else { - /* Align the button to the left of the previous button */ - lv_obj_align(btn, btn_prev_at_right, LV_ALIGN_OUT_LEFT_MID, -header_inner, 0); - } - - btn_prev_at_right = btn; - } - else if(LV_WIN_BTN_ALIGN_LEFT == btn_alignment) { - if(is_header_left_side_empty) { - /* Align the button to the right of the header */ - lv_obj_align(btn, ext->header, LV_ALIGN_IN_LEFT_MID, header_left, 0); - - is_header_left_side_empty = false; - } - else { - /* Align the button to the right of the previous button */ - lv_obj_align(btn, btn_prev_at_left, LV_ALIGN_OUT_RIGHT_MID, header_inner, 0); - } - - btn_prev_at_left = btn; - } - - btn = lv_obj_get_child_back(ext->header, btn); - } - - lv_obj_set_pos(ext->header, 0, 0); - - lv_obj_set_size(ext->page, lv_obj_get_width(win), lv_obj_get_height(win) - lv_obj_get_height(ext->header)); - lv_obj_align(ext->page, ext->header, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); -} - -static lv_obj_t * lv_win_btn_create(lv_obj_t * par, const void * img_src) -{ - LV_LOG_TRACE("win btn create started"); - - lv_obj_t * win_btn; - - win_btn = lv_btn_create(par, NULL); - LV_ASSERT_MEM(win_btn); - if(win_btn == NULL) return NULL; - - /*Allocate the extended data*/ - lv_win_btn_ext_t * ext = lv_obj_allocate_ext_attr(win_btn, sizeof(lv_win_btn_ext_t)); - LV_ASSERT_MEM(ext); - if(ext == NULL) { - lv_obj_del(win_btn); - return NULL; - } - - ext->alignment_in_header = LV_WIN_BTN_ALIGN_RIGHT; - - lv_obj_set_click(win_btn, true); - lv_win_btn_set_alignment(win_btn, LV_WIN_BTN_ALIGN_RIGHT); - - lv_theme_apply(win_btn, LV_THEME_WIN_BTN); - lv_coord_t btn_size = lv_obj_get_height_fit(par); - lv_obj_set_size(win_btn, btn_size, btn_size); - - lv_obj_t * img = lv_img_create(win_btn, NULL); - lv_obj_set_click(img, false); - lv_img_set_src(img, img_src); - - LV_LOG_INFO("win btn created"); - - return win_btn; -} - -static void lv_win_btn_set_alignment(lv_obj_t * win_btn, const uint8_t alignment) -{ - lv_win_btn_ext_t * ext = lv_obj_get_ext_attr(win_btn); - - ext->alignment_in_header = alignment; -} - -static uint8_t lv_win_btn_get_alignment(const lv_obj_t * win_btn) -{ - lv_win_btn_ext_t * ext = lv_obj_get_ext_attr(win_btn); - - return ext->alignment_in_header; -} - -#endif diff --git a/src/lv_widgets/lv_win.h b/src/lv_widgets/lv_win.h deleted file mode 100644 index c3efb3d63..000000000 --- a/src/lv_widgets/lv_win.h +++ /dev/null @@ -1,300 +0,0 @@ -/** - * @file lv_win.h - * - */ - -#ifndef LV_WIN_H -#define LV_WIN_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_WIN != 0 - -/*Testing of dependencies*/ -#if LV_USE_BTN == 0 -#error "lv_win: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) " -#endif - -#if LV_USE_LABEL == 0 -#error "lv_win: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " -#endif - -#if LV_USE_IMG == 0 -#error "lv_win: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1) " -#endif - -#if LV_USE_PAGE == 0 -#error "lv_win: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) " -#endif - -#include "../lv_core/lv_obj.h" -#include "lv_cont.h" -#include "lv_btn.h" -#include "lv_label.h" -#include "lv_img.h" -#include "lv_page.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/*Data of window*/ -typedef struct { - /*Ext. of ancestor*/ - /*New data for this type */ - lv_obj_t * page; /*Pointer to a page which holds the content*/ - lv_obj_t * header; /*Pointer to the header container of the window*/ - char * title_txt; /*Pointer to the title label of the window*/ - lv_coord_t btn_w; /*Width of the control buttons*/ -} lv_win_ext_t; - -/** Window parts. */ -enum { - LV_WIN_PART_BG = LV_OBJ_PART_MAIN, /**< Window object background style. */ - _LV_WIN_PART_VIRTUAL_LAST, - LV_WIN_PART_HEADER = _LV_OBJ_PART_REAL_LAST, /**< Window titlebar background style. */ - LV_WIN_PART_CONTENT_SCROLLABLE, /**< Window content style. */ - LV_WIN_PART_SCROLLBAR, /**< Window scrollbar style. */ - _LV_WIN_PART_REAL_LAST -}; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a window objects - * @param par pointer to an object, it will be the parent of the new window - * @param copy pointer to a window object, if not NULL then the new object will be copied from it - * @return pointer to the created window - */ -lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy); - -/** - * Delete all children of the scrl object, without deleting scrl child. - * @param win pointer to an object - */ -void lv_win_clean(lv_obj_t * win); - -/*====================== - * Add/remove functions - *=====================*/ - -/** - * Add control button on the right side of the window header - * @param win pointer to a window object - * @param img_src an image source ('lv_img_t' variable, path to file or a symbol) - * @return pointer to the created button object - */ -lv_obj_t * lv_win_add_btn_right(lv_obj_t * win, const void * img_src); - -/** - * Add control button on the left side of the window header - * @param win pointer to a window object - * @param img_src an image source ('lv_img_t' variable, path to file or a symbol) - * @return pointer to the created button object - */ -lv_obj_t * lv_win_add_btn_left(lv_obj_t * win, const void * img_src); - -/*===================== - * Setter functions - *====================*/ - -/** - * Can be assigned to a window control button to close the window - * @param btn pointer to the control button on the widows header - * @param evet the event type - */ -void lv_win_close_event_cb(lv_obj_t * btn, lv_event_t event); - -/** - * Set the title of a window - * @param win pointer to a window object - * @param title string of the new title - */ -void lv_win_set_title(lv_obj_t * win, const char * title); - -/** - * Set the control button size of a window - * @param win pointer to a window object - * @return control button size - */ -void lv_win_set_header_height(lv_obj_t * win, lv_coord_t size); - -/** - * Set the width of the control buttons on the header - * @param win pointer to a window object - * @param width width of the control button. 0: to make them square automatically. - */ -void lv_win_set_btn_width(lv_obj_t * win, lv_coord_t width); - -/** - * Set the size of the content area. - * @param win pointer to a window object - * @param w width - * @param h height (the window will be higher with the height of the header) - */ -void lv_win_set_content_size(lv_obj_t * win, lv_coord_t w, lv_coord_t h); - -/** - * Set the layout of the window - * @param win pointer to a window object - * @param layout the layout from 'lv_layout_t' - */ -void lv_win_set_layout(lv_obj_t * win, lv_layout_t layout); - -/** - * Set the scroll bar mode of a window - * @param win pointer to a window object - * @param sb_mode the new scroll bar mode from 'lv_scrollbar_mode_t' - */ -void lv_win_set_scrollbar_mode(lv_obj_t * win, lv_scrollbar_mode_t sb_mode); - -/** - * Set focus animation duration on `lv_win_focus()` - * @param win pointer to a window object - * @param anim_time duration of animation [ms] - */ -void lv_win_set_anim_time(lv_obj_t * win, uint16_t anim_time); - -/** - * Set drag status of a window. If set to 'true' window can be dragged like on a PC. - * @param win pointer to a window object - * @param en whether dragging is enabled - */ -void lv_win_set_drag(lv_obj_t * win, bool en); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the title of a window - * @param win pointer to a window object - * @return title string of the window - */ -const char * lv_win_get_title(const lv_obj_t * win); - -/** - * Get the content holder object of window (`lv_page`) to allow additional customization - * @param win pointer to a window object - * @return the Page object where the window's content is - */ -lv_obj_t * lv_win_get_content(const lv_obj_t * win); - -/** - * Get the header height - * @param win pointer to a window object - * @return header height - */ -lv_coord_t lv_win_get_header_height(const lv_obj_t * win); - - -/** - * Get the width of the control buttons on the header - * @param win pointer to a window object - * @return width of the control button. 0: square. - */ -lv_coord_t lv_win_get_btn_width(lv_obj_t * win); - -/** - * Get the pointer of a widow from one of its control button. - * It is useful in the action of the control buttons where only button is known. - * @param ctrl_btn pointer to a control button of a window - * @return pointer to the window of 'ctrl_btn' - */ -lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn); - -/** - * Get the layout of a window - * @param win pointer to a window object - * @return the layout of the window (from 'lv_layout_t') - */ -lv_layout_t lv_win_get_layout(lv_obj_t * win); - -/** - * Get the scroll bar mode of a window - * @param win pointer to a window object - * @return the scroll bar mode of the window (from 'lv_sb_mode_t') - */ -lv_scrollbar_mode_t lv_win_get_sb_mode(lv_obj_t * win); - -/** - * Get focus animation duration - * @param win pointer to a window object - * @return duration of animation [ms] - */ -uint16_t lv_win_get_anim_time(const lv_obj_t * win); - -/** - * Get width of the content area (page scrollable) of the window - * @param win pointer to a window object - * @return the width of the content area - */ -lv_coord_t lv_win_get_width(lv_obj_t * win); - -/** - * Get drag status of a window. If set to 'true' window can be dragged like on a PC. - * @param win pointer to a window object - * @return whether window is draggable - */ -static inline bool lv_win_get_drag(const lv_obj_t * win) -{ - return lv_obj_get_drag(win); -} - -/*===================== - * Other functions - *====================*/ - -/** - * Focus on an object. It ensures that the object will be visible in the window. - * @param win pointer to a window object - * @param obj pointer to an object to focus (must be in the window) - * @param anim_en LV_ANIM_ON focus with an animation; LV_ANIM_OFF focus without animation - */ -void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, lv_anim_enable_t anim_en); - -/** - * Scroll the window horizontally - * @param win pointer to a window object - * @param dist the distance to scroll (< 0: scroll right; > 0 scroll left) - */ -static inline void lv_win_scroll_hor(lv_obj_t * win, lv_coord_t dist) -{ - lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win); - lv_page_scroll_hor(ext->page, dist); -} -/** - * Scroll the window vertically - * @param win pointer to a window object - * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) - */ -static inline void lv_win_scroll_ver(lv_obj_t * win, lv_coord_t dist) -{ - lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win); - lv_page_scroll_ver(ext->page, dist); -} - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_WIN*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_WIN_H*/