diff --git a/Kconfig b/Kconfig index 11447f631..9eaf97a4a 100644 --- a/Kconfig +++ b/Kconfig @@ -856,7 +856,7 @@ menu "LVGL configuration" bool "Support bidirectional texts" help Allows mixing Left-to-Right and Right-to-Left texts. - The direction will be processed according to the Unicode Bidirectioanl Algorithm: + The direction will be processed according to the Unicode Bidirectional Algorithm: https://www.w3.org/International/articles/inline-bidi-markup/uba-basics choice diff --git a/examples/porting/lv_port_fs_template.c b/examples/porting/lv_port_fs_template.c index 6aead148e..27c1ca903 100644 --- a/examples/porting/lv_port_fs_template.c +++ b/examples/porting/lv_port_fs_template.c @@ -325,9 +325,9 @@ static lv_fs_res_t fs_free (lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * fr } /** - * Initialize a 'fs_read_dir_t' variable for directory reading + * Initialize a 'lv_fs_dir_t' variable for directory reading * @param drv pointer to a driver where this function belongs - * @param rddir_p pointer to a 'fs_read_dir_t' variable + * @param rddir_p pointer to a 'lv_fs_dir_t' variable * @param path path to a directory * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -344,7 +344,7 @@ static lv_fs_res_t fs_dir_open (lv_fs_drv_t * drv, void * rddir_p, const char *p * Read the next filename form a directory. * The name of the directories will begin with '/' * @param drv pointer to a driver where this function belongs - * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable + * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable * @param fn pointer to a buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -360,7 +360,7 @@ static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * rddir_p, char *fn) /** * Close the directory reading * @param drv pointer to a driver where this function belongs - * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable + * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * rddir_p) diff --git a/library.json b/library.json index cadc395d8..3aec465fc 100644 --- a/library.json +++ b/library.json @@ -1,10 +1,6 @@ { "name": "lvgl", -<<<<<<< HEAD "version": "8.0.0", -======= - "version": "7.8.1", ->>>>>>> master "keywords": "graphics, gui, embedded, tft, lvgl", "description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.", "repository": { diff --git a/library.properties b/library.properties index ffb786645..25144d43b 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,5 @@ name=lvgl -<<<<<<< HEAD version=8.0.0 -======= -version=7.8.1 ->>>>>>> master author=kisvegabor maintainer=kisvegabor,embeddedt,pete-pjb sentence=Full-featured Graphics Library for Embedded Systems diff --git a/lv_conf_template.h b/lv_conf_template.h index 152a7d15c..0c65b9216 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -86,7 +86,7 @@ typedef int16_t lv_coord_t; /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ # define LV_MEM_SIZE (32U * 1024U) -/* Complier prefix for a big array declaration */ +/* Compiler prefix for a big array declaration */ # define LV_MEM_ATTR /* Set an address for the memory pool instead of allocating it as an array. @@ -131,7 +131,7 @@ typedef int16_t lv_coord_t; #define LV_INDEV_DEF_DRAG_THROW 10 /* Long press time in milliseconds. - * Time to send `LV_EVENT_LONG_PRESSSED`) */ + * Time to send `LV_EVENT_LONG_PRESSED`) */ #define LV_INDEV_DEF_LONG_PRESS_TIME 400 /* Repeated trigger period in long press [ms] @@ -514,7 +514,7 @@ typedef void * lv_font_user_data_t; /* Support bidirectional texts. * Allows mixing Left-to-Right and Right-to-Left texts. - * The direction will be processed according to the Unicode Bidirectioanl Algorithm: + * The direction will be processed according to the Unicode Bidirectional Algorithm: * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ #define LV_USE_BIDI 0 #if LV_USE_BIDI diff --git a/lvgl.h b/lvgl.h index 649e0002f..fa007e42b 100644 --- a/lvgl.h +++ b/lvgl.h @@ -24,7 +24,7 @@ extern "C" { *********************/ #include "src/lv_misc/lv_log.h" -#include +#include "src/lv_misc/lv_timer.h" #include "src/lv_misc/lv_math.h" #include "src/lv_misc/lv_async.h" diff --git a/src/lv_api_map.h b/src/lv_api_map.h index c3d8f5062..2cce6f37a 100644 --- a/src/lv_api_map.h +++ b/src/lv_api_map.h @@ -27,6 +27,7 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ + static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) { return lv_timer_handler(); diff --git a/src/lv_core/lv_disp.h b/src/lv_core/lv_disp.h index f144a2060..e82d4ea22 100644 --- a/src/lv_core/lv_disp.h +++ b/src/lv_core/lv_disp.h @@ -225,4 +225,4 @@ static inline lv_coord_t lv_dpx(lv_coord_t n) } /* extern "C" */ #endif -#endif /*LV_TEMPL_H*/ +#endif /*LV_DISP_H*/ diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index ca3076e79..5f5be58aa 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -522,7 +522,7 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) lv_group_focus_prev(g); if(indev_reset_check(&i->proc)) return; } - /*Just send other keys again to the object (e.g. 'A' or `LV_GORUP_KEY_RIGHT)*/ + /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/ else { lv_group_send_data(g, data->key); if(indev_reset_check(&i->proc)) return; @@ -815,7 +815,7 @@ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) } /** - * Process the pressed state of LV_INDEV_TYPE_POINER input devices + * Process the pressed state of LV_INDEV_TYPE_POINTER input devices * @param indev pointer to an input device 'proc' * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required */ @@ -961,7 +961,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) } /** - * Process the released state of LV_INDEV_TYPE_POINER input devices + * Process the released state of LV_INDEV_TYPE_POINTER input devices * @param proc pointer to an input device 'proc' */ static void indev_proc_release(lv_indev_proc_t * proc) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 9210b8542..ae1fd820a 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -428,7 +428,7 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return false; - /*Invalidate the object only if it belongs to the curent or previous'*/ + /*Invalidate the object only if it belongs to the current or previous'*/ lv_obj_t * obj_scr = lv_obj_get_screen(obj); lv_disp_t * disp = lv_obj_get_disp(obj_scr); if(obj_scr == lv_disp_get_scr_act(disp) || diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index 7149418fe..6e78c3ed2 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -44,7 +44,7 @@ static inline size_t get_prop_size(uint8_t prop_id); static inline size_t get_next_prop_index(uint8_t prop_id, size_t id); /********************** - * GLOABAL VARIABLES + * GLOBAL VARIABLES **********************/ /********************** @@ -340,7 +340,7 @@ uint16_t _lv_style_get_mem_size(const lv_style_t * style) size_t i = 0; uint8_t prop_id; - while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSEING_PROP) { + while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSING_PROP) { i = get_next_prop_index(prop_id, i); } @@ -378,7 +378,7 @@ void _lv_style_set_int(lv_style_t * style, lv_style_property_t prop, lv_style_in /*Add new property if not exists yet*/ uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_style_int_t)); - lv_style_property_t end_mark = _LV_STYLE_CLOSEING_PROP; + lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); @@ -424,7 +424,7 @@ void _lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_ /*Add new property if not exists yet*/ uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_color_t)); - lv_style_property_t end_mark = _LV_STYLE_CLOSEING_PROP; + lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); @@ -471,7 +471,7 @@ void _lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t op /*Add new property if not exists yet*/ uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_opa_t)); - lv_style_property_t end_mark = _LV_STYLE_CLOSEING_PROP; + lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); @@ -518,7 +518,7 @@ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void /*Add new property if not exists yet*/ uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(const void *)); - lv_style_property_t end_mark = _LV_STYLE_CLOSEING_PROP; + lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); @@ -1076,7 +1076,7 @@ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t } uint8_t prop_id; - while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSEING_PROP) { + while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSING_PROP) { if(prop_id == id_to_find) { lv_style_attr_t attr_i; attr_i = get_style_prop_attr(style, i); diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 04cbfd42f..0fdfb515b 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -39,7 +39,7 @@ LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE); #define LV_STYLE_ATTR_NONE 0 #define LV_STYLE_ATTR_INHERIT (1 << 7) -#define _LV_STYLE_CLOSEING_PROP 0xFF +#define _LV_STYLE_CLOSING_PROP 0xFF #define LV_STYLE_TRANS_NUM_MAX 6 diff --git a/src/lv_draw/lv_draw_arc.c b/src/lv_draw/lv_draw_arc.c index ed1dd5335..ef7918750 100644 --- a/src/lv_draw/lv_draw_arc.c +++ b/src/lv_draw/lv_draw_arc.c @@ -42,7 +42,7 @@ static void draw_quarter_0(quarter_draw_dsc_t * q); static void draw_quarter_1(quarter_draw_dsc_t * q); static void draw_quarter_2(quarter_draw_dsc_t * q); static void draw_quarter_3(quarter_draw_dsc_t * q); -static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t tickness, lv_area_t * res_area); +static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area); /********************** @@ -386,13 +386,13 @@ static void draw_quarter_3(quarter_draw_dsc_t * q) } -static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t tickness, lv_area_t * res_area) +static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area) { const uint8_t ps = 8; const uint8_t pa = 127; - int32_t thick_half = tickness / 2; - uint8_t thick_corr = (tickness & 0x01) ? 0 : 1; + int32_t thick_half = thickness / 2; + uint8_t thick_corr = (thickness & 0x01) ? 0 : 1; int32_t cir_x; int32_t cir_y; diff --git a/src/lv_draw/lv_draw_img.h b/src/lv_draw/lv_draw_img.h index e4531d725..168b7fffc 100644 --- a/src/lv_draw/lv_draw_img.h +++ b/src/lv_draw/lv_draw_img.h @@ -93,4 +93,4 @@ bool lv_img_cf_has_alpha(lv_img_cf_t cf); } /* extern "C" */ #endif -#endif /*LV_TEMPL_H*/ +#endif /*LV_DRAW_IMG_H*/ diff --git a/src/lv_draw/lv_draw_rect.c b/src/lv_draw/lv_draw_rect.c index 2710db162..11be44f32 100644 --- a/src/lv_draw/lv_draw_rect.c +++ b/src/lv_draw/lv_draw_rect.c @@ -17,7 +17,7 @@ /********************* * DEFINES *********************/ -#define SHADOW_UPSACALE_SHIFT 6 +#define SHADOW_UPSCALE_SHIFT 6 #define SHADOW_ENHANCE 1 #define SPLIT_LIMIT 50 @@ -1029,10 +1029,10 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord } else { int32_t i; - sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSACALE_SHIFT) / sw; + sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSCALE_SHIFT) / sw; for(i = 1; i < size; i++) { if(mask_line[i] == mask_line[i - 1]) sh_ups_tmp_buf[i] = sh_ups_tmp_buf[i - 1]; - else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSACALE_SHIFT) / sw; + else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSCALE_SHIFT) / sw; } } @@ -1044,7 +1044,7 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord int32_t i; lv_opa_t * res_buf = (lv_opa_t *)sh_buf; for(i = 0; i < size * size; i++) { - res_buf[i] = (sh_buf[i] >> SHADOW_UPSACALE_SHIFT); + res_buf[i] = (sh_buf[i] >> SHADOW_UPSCALE_SHIFT); } return; } @@ -1062,10 +1062,10 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord sw += sw_ori & 1; if(sw > 1) { uint32_t i; - sh_buf[0] = (sh_buf[0] << SHADOW_UPSACALE_SHIFT) / sw; + sh_buf[0] = (sh_buf[0] << SHADOW_UPSCALE_SHIFT) / sw; for(i = 1; i < (uint32_t) size * size; i++) { if(sh_buf[i] == sh_buf[i - 1]) sh_buf[i] = sh_buf[i - 1]; - else sh_buf[i] = (sh_buf[i] << SHADOW_UPSACALE_SHIFT) / sw; + else sh_buf[i] = (sh_buf[i] << SHADOW_UPSCALE_SHIFT) / sw; } shadow_blur_corner(size, sw, sh_buf); @@ -1125,7 +1125,7 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(lv_coord_t size, lv_coord_t sh_ups_tmp_buf = &sh_ups_buf[x]; int32_t v = sh_ups_tmp_buf[0] * sw; for(y = 0; y < size ; y++, sh_ups_tmp_buf += size) { - sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSACALE_SHIFT); + sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSCALE_SHIFT); /*Forget the top pixel*/ uint32_t top_val; diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index cc4d1cb0f..f18a6fd6c 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -423,14 +423,14 @@ void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc) dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256; int32_t angle_low = dsc->cfg.angle / 10; - int32_t angle_hight = angle_low + 1; + int32_t angle_high = angle_low + 1; int32_t angle_rem = dsc->cfg.angle - (angle_low * 10); int32_t s1 = _lv_trigo_sin(-angle_low); - int32_t s2 = _lv_trigo_sin(-angle_hight); + int32_t s2 = _lv_trigo_sin(-angle_high); int32_t c1 = _lv_trigo_sin(-angle_low + 90); - int32_t c2 = _lv_trigo_sin(-angle_hight + 90); + int32_t c2 = _lv_trigo_sin(-angle_high + 90); dsc->tmp.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; dsc->tmp.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; @@ -500,14 +500,14 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t } int32_t angle_low = angle / 10; - int32_t angle_hight = angle_low + 1; + int32_t angle_high = angle_low + 1; int32_t angle_rem = angle - (angle_low * 10); int32_t s1 = _lv_trigo_sin(angle_low); - int32_t s2 = _lv_trigo_sin(angle_hight); + int32_t s2 = _lv_trigo_sin(angle_high); int32_t c1 = _lv_trigo_sin(angle_low + 90); - int32_t c2 = _lv_trigo_sin(angle_hight + 90); + int32_t c2 = _lv_trigo_sin(angle_high + 90); int32_t sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; int32_t cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; diff --git a/src/lv_draw/lv_img_decoder.h b/src/lv_draw/lv_img_decoder.h index 8e3cf2662..5ea93ae5e 100644 --- a/src/lv_draw/lv_img_decoder.h +++ b/src/lv_draw/lv_img_decoder.h @@ -3,8 +3,8 @@ * */ -#ifndef LV_IMG_DEOCER_H -#define LV_IMG_DEOCER_H +#ifndef LV_IMG_DECODER_H +#define LV_IMG_DECODER_H #ifdef __cplusplus extern "C" { @@ -267,4 +267,4 @@ void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_ds } /* extern "C" */ #endif -#endif /*LV_TEMPL_H*/ +#endif /*LV_IMG_DECODER_H*/ diff --git a/src/lv_gpu/lv_gpu_nxp_vglite.h b/src/lv_gpu/lv_gpu_nxp_vglite.h index a92259620..bdadfd695 100644 --- a/src/lv_gpu/lv_gpu_nxp_vglite.h +++ b/src/lv_gpu/lv_gpu_nxp_vglite.h @@ -67,7 +67,7 @@ extern "C" { #endif #ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS -/** Enable logging of VG-Lite erors (\see LV_LOG_ERROR) */ +/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR) */ #define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1 #endif diff --git a/src/lv_hal/lv_hal_indev.c b/src/lv_hal/lv_hal_indev.c index 2df2e4aea..915416ec4 100644 --- a/src/lv_hal/lv_hal_indev.c +++ b/src/lv_hal/lv_hal_indev.c @@ -150,9 +150,9 @@ bool _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data) } if(indev->driver.read_cb) { - LV_LOG_TRACE("idnev read started"); + LV_LOG_TRACE("indev read started"); cont = indev->driver.read_cb(&indev->driver, data); - LV_LOG_TRACE("idnev read finished"); + LV_LOG_TRACE("indev read finished"); } else { LV_LOG_WARN("indev function registered"); diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index 183c125d3..d36d7008e 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -13,7 +13,7 @@ #include #include "../lv_misc/lv_debug.h" #include "../lv_hal/lv_hal_tick.h" -#include +#include "lv_timer.h" #include "lv_math.h" #include "lv_gc.h" diff --git a/src/lv_misc/lv_async.h b/src/lv_misc/lv_async.h index 8e462c2ab..7d8c2625f 100644 --- a/src/lv_misc/lv_async.h +++ b/src/lv_misc/lv_async.h @@ -14,7 +14,7 @@ extern "C" { * INCLUDES *********************/ -#include +#include "lv_timer.h" #include "lv_types.h" /********************* @@ -59,4 +59,4 @@ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); } /* extern "C" */ #endif -#endif /*LV_TEMPL_H*/ +#endif /*LV_ASYNC_H*/ diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 8f9c53236..fd98009e5 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -1,5 +1,5 @@ /** - * @file lv_bifi.h + * @file lv_bidi.h * */ diff --git a/src/lv_misc/lv_fs.c b/src/lv_misc/lv_fs.c index fbf6e7de0..3b5843378 100644 --- a/src/lv_misc/lv_fs.c +++ b/src/lv_misc/lv_fs.c @@ -346,8 +346,8 @@ lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname) } /** - * Initialize a 'fs_read_dir_t' variable for directory reading - * @param rddir_p pointer to a 'fs_read_dir_t' variable + * Initialize a 'lv_fs_dir_t' variable for directory reading + * @param rddir_p pointer to a 'lv_fs_dir_t' variable * @param path path to a directory * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -385,7 +385,7 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path) /** * Read the next filename form a directory. * The name of the directories will begin with '/' - * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable + * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable * @param fn pointer to a buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -407,7 +407,7 @@ lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn) /** * Close the directory reading - * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable + * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p) diff --git a/src/lv_misc/lv_fs.h b/src/lv_misc/lv_fs.h index 00eebadc1..bbf797c78 100644 --- a/src/lv_misc/lv_fs.h +++ b/src/lv_misc/lv_fs.h @@ -231,7 +231,7 @@ lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname); /** * Initialize a 'fs_dir_t' variable for directory reading - * @param rddir_p pointer to a 'fs_read_dir_t' variable + * @param rddir_p pointer to a 'lv_fs_dir_t' variable * @param path path to a directory * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -240,7 +240,7 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path); /** * Read the next filename form a directory. * The name of the directories will begin with '/' - * @param rddir_p pointer to an initialized 'fs_rdir_t' variable + * @param rddir_p pointer to an initialized 'fs_dir_t' variable * @param fn pointer to a buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ diff --git a/src/lv_misc/lv_gc.h b/src/lv_misc/lv_gc.h index 029477bf7..73861e37c 100644 --- a/src/lv_misc/lv_gc.h +++ b/src/lv_misc/lv_gc.h @@ -17,7 +17,7 @@ extern "C" { #include #include "lv_mem.h" #include "lv_ll.h" -#include +#include "lv_timer.h" #include "../lv_draw/lv_img_cache.h" #include "../lv_draw/lv_draw_mask.h" diff --git a/src/lv_misc/lv_timer.c b/src/lv_misc/lv_timer.c index 115ee7480..8eca3be99 100644 --- a/src/lv_misc/lv_timer.c +++ b/src/lv_misc/lv_timer.c @@ -5,7 +5,7 @@ /********************* * INCLUDES *********************/ -#include +#include "lv_timer.h" #include #include "../lv_misc/lv_debug.h" #include "../lv_hal/lv_hal_tick.h" diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index e429dffaf..5d05c714e 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -391,7 +391,7 @@ lv_coord_t _lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t /** * Check next character in a string and decide if the character is part of the command or not * @param state pointer to a txt_cmd_state_t variable which stores the current state of command - * processing (Initied. to TXT_CMD_STATE_WAIT ) + * processing (Inited to TXT_CMD_STATE_WAIT ) * @param c the current character * @return true: the character is part of a command and should not be written, * false: the character should be written @@ -525,7 +525,7 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) #if LV_TXT_ENC == LV_TXT_ENC_UTF8 /******************************* - * UTF-8 ENCODER/DECOER + * UTF-8 ENCODER/DECODER ******************************/ /** diff --git a/src/lv_misc/lv_txt.h b/src/lv_misc/lv_txt.h index 52df561ce..a5e78d9da 100644 --- a/src/lv_misc/lv_txt.h +++ b/src/lv_misc/lv_txt.h @@ -136,7 +136,7 @@ void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len); char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap); /*************************************************************** - * GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE + * GLOBAL FUNCTION POINTERS FOR CHARACTER ENCODING INTERFACE ***************************************************************/ /** diff --git a/src/lv_themes/lv_theme_template.c b/src/lv_themes/lv_theme_template.c new file mode 100644 index 000000000..18a47a1ca --- /dev/null +++ b/src/lv_themes/lv_theme_template.c @@ -0,0 +1,868 @@ +/** + * @file lv_theme_template.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lvgl.h" /*To see all the widgets*/ + +#if LV_USE_THEME_TEMPLATE + +#include "../lv_misc/lv_gc.h" + +#if defined(LV_GC_INCLUDE) + #include LV_GC_INCLUDE +#endif /* LV_ENABLE_GC */ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_style_t bg; + lv_style_t btn; + lv_style_t round; + lv_style_t color; + lv_style_t gray; + lv_style_t tick_line; + lv_style_t tight; +} theme_styles_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name); + +/********************** + * STATIC VARIABLES + **********************/ + +static lv_theme_t theme; +static theme_styles_t * styles; + +static bool inited; + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ +static void style_init_reset(lv_style_t * style); + + +static void basic_init(void) +{ + style_init_reset(&styles->bg); + lv_style_set_bg_opa(&styles->bg, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_style_set_border_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_border_width(&styles->bg, LV_STATE_FOCUSED, 2); + lv_style_set_border_color(&styles->bg, LV_STATE_FOCUSED, theme.color_secondary); + lv_style_set_border_color(&styles->bg, LV_STATE_EDITED, lv_color_darken(theme.color_secondary, LV_OPA_30)); + lv_style_set_line_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_scale_end_line_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_scale_end_color(&styles->bg, LV_STATE_DEFAULT, theme.color_primary); + lv_style_set_text_color(&styles->bg, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_style_set_pad_left(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_right(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_top(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_bottom(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_inner(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + + style_init_reset(&styles->btn); + lv_style_set_bg_color(&styles->btn, LV_STATE_PRESSED, lv_color_hex3(0xccc)); + lv_style_set_bg_color(&styles->btn, LV_STATE_CHECKED, theme.color_primary); + lv_style_set_bg_color(&styles->btn, LV_STATE_CHECKED | LV_STATE_PRESSED, lv_color_darken(theme.color_primary, + LV_OPA_30)); + lv_style_set_bg_color(&styles->btn, LV_STATE_DISABLED, LV_COLOR_SILVER); + lv_style_set_text_color(&styles->btn, LV_STATE_DISABLED, LV_COLOR_GRAY); + lv_style_set_image_recolor(&styles->btn, LV_STATE_DISABLED, LV_COLOR_GRAY); + + style_init_reset(&styles->round); + lv_style_set_radius(&styles->round, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + + style_init_reset(&styles->color); + lv_style_set_bg_color(&styles->color, LV_STATE_DEFAULT, theme.color_primary); + lv_style_set_line_color(&styles->color, LV_STATE_DEFAULT, theme.color_primary); + + style_init_reset(&styles->gray); + lv_style_set_bg_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_SILVER); + lv_style_set_line_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_SILVER); + lv_style_set_text_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + style_init_reset(&styles->tick_line); + lv_style_set_line_width(&styles->tick_line, LV_STATE_DEFAULT, 5); + lv_style_set_scale_end_line_width(&styles->tick_line, LV_STATE_DEFAULT, 5); + lv_style_set_scale_end_color(&styles->tick_line, LV_STATE_DEFAULT, theme.color_primary); + + style_init_reset(&styles->tight); + lv_style_set_pad_left(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_right(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_top(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_bottom(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_inner(&styles->tight, LV_STATE_DEFAULT, 0); +} + +static void arc_init(void) +{ +#if LV_USE_ARC != 0 + +#endif +} + +static void bar_init(void) +{ +#if LV_USE_BAR + +#endif +} + +static void btn_init(void) +{ +#if LV_USE_BTN != 0 + +#endif +} + + +static void btnmatrix_init(void) +{ +#if LV_USE_BTNMATRIX + +#endif +} + + +static void calendar_init(void) +{ +#if LV_USE_CALENDAR + +#endif +} + +static void chart_init(void) +{ +#if LV_USE_CHART + +#endif +} + + +static void cpicker_init(void) +{ +#if LV_USE_CPICKER + +#endif +} + +static void checkbox_init(void) +{ +#if LV_USE_CHECKBOX != 0 + +#endif +} + + +static void cont_init(void) +{ +#if LV_USE_CONT != 0 + +#endif +} + + +static void gauge_init(void) +{ +#if LV_USE_GAUGE != 0 + +#endif +} + +static void img_init(void) +{ +#if LV_USE_IMG != 0 + +#endif +} + +static void label_init(void) +{ +#if LV_USE_LABEL != 0 + +#endif +} + + +static void linemeter_init(void) +{ +#if LV_USE_LINEMETER != 0 + +#endif +} + +static void line_init(void) +{ +#if LV_USE_LINE != 0 + +#endif +} + +static void led_init(void) +{ +#if LV_USE_LED != 0 + +#endif +} + +static void page_init(void) +{ +#if LV_USE_PAGE + +#endif +} + +static void slider_init(void) +{ +#if LV_USE_SLIDER != 0 + +#endif +} + +static void switch_init(void) +{ +#if LV_USE_SWITCH != 0 + +#endif +} + + +static void spinbox_init(void) +{ +#if LV_USE_SPINBOX + +#endif +} + + +static void spinner_init(void) +{ +#if LV_USE_SPINNER != 0 + +#endif +} + +static void keyboard_init(void) +{ +#if LV_USE_KEYBOARD + +#endif +} + +static void msgbox_init(void) +{ +#if LV_USE_MSGBOX + +#endif +} + +static void textarea_init(void) +{ +#if LV_USE_TEXTAREA + +#endif +} + +static void list_init(void) +{ +#if LV_USE_LIST != 0 + +#endif +} + +static void ddlist_init(void) +{ +#if LV_USE_DROPDOWN != 0 + +#endif +} + +static void roller_init(void) +{ +#if LV_USE_ROLLER != 0 + +#endif +} + +static void tabview_init(void) +{ +#if LV_USE_TABVIEW != 0 + +#endif +} + +static void tileview_init(void) +{ +#if LV_USE_TILEVIEW != 0 +#endif +} + +static void table_init(void) +{ +#if LV_USE_TABLE != 0 + +#endif +} + +static void win_init(void) +{ +#if LV_USE_WIN != 0 + +#endif +} + + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Initialize the default + * @param color_primary the primary color of the theme + * @param color_secondary the secondary color for the theme + * @param flags ORed flags starting with `LV_THEME_DEF_FLAG_...` + * @param font_small pointer to a small font + * @param font_normal pointer to a normal font + * @param font_subtitle pointer to a large font + * @param font_title pointer to a extra large font + * @return a pointer to reference this theme later + */ +lv_theme_t * lv_theme_template_init(lv_color_t color_primary, lv_color_t color_secondary, uint32_t flags, + const lv_font_t * font_small, const lv_font_t * font_normal, const lv_font_t * font_subtitle, + const lv_font_t * font_title) +{ + + /* This trick is required only to avoid the garbage collection of + * styles' data if LVGL is used in a binding (e.g. Micropython) + * In a general case styles could be simple `static lv_style_t my style` variables or allocated directly into `styles`*/ + if(!inited) { +#if defined(LV_GC_INCLUDE) + LV_GC_ROOT(_lv_theme_template_styles) = lv_mem_alloc(sizeof(theme_styles_t)); + styles = (theme_styles_t *)LV_GC_ROOT(_lv_theme_template_styles); +#else + styles = lv_mem_alloc(sizeof(theme_styles_t)); +#endif + + } + + theme.color_primary = color_primary; + theme.color_secondary = color_secondary; + theme.font_small = font_small; + theme.font_normal = font_normal; + theme.font_subtitle = font_subtitle; + theme.font_title = font_title; + theme.flags = flags; + + basic_init(); + cont_init(); + btn_init(); + label_init(); + bar_init(); + img_init(); + line_init(); + led_init(); + slider_init(); + switch_init(); + linemeter_init(); + gauge_init(); + arc_init(); + spinner_init(); + chart_init(); + calendar_init(); + cpicker_init(); + checkbox_init(); + btnmatrix_init(); + keyboard_init(); + msgbox_init(); + page_init(); + textarea_init(); + spinbox_init(); + list_init(); + ddlist_init(); + roller_init(); + tabview_init(); + tileview_init(); + table_init(); + win_init(); + + theme.apply_xcb = NULL; + theme.apply_cb = theme_apply; + + return &theme; +} + + +void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) +{ + LV_UNUSED(th); + + lv_style_list_t * list; + + switch(name) { + case LV_THEME_NONE: + break; + + case LV_THEME_SCR: + list = lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; + case LV_THEME_OBJ: + 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: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_BTNMATRIX + case LV_THEME_BTNMATRIX: + list = lv_obj_get_style_list(obj, LV_BTNMATRIX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_BTNMATRIX_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_KEYBOARD + case LV_THEME_KEYBOARD: + list = lv_obj_get_style_list(obj, LV_KEYBOARD_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_KEYBOARD_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_BAR + case LV_THEME_BAR: + list = lv_obj_get_style_list(obj, LV_BAR_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_BAR_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + +#if LV_USE_SWITCH + case LV_THEME_SWITCH: + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_CANVAS + case LV_THEME_CANVAS: + list = lv_obj_get_style_list(obj, LV_CANVAS_PART_MAIN); + break; +#endif + +#if LV_USE_IMG + case LV_THEME_IMAGE: + list = lv_obj_get_style_list(obj, LV_IMG_PART_MAIN); + break; +#endif + +#if LV_USE_IMGBTN + case LV_THEME_IMGBTN: + list = lv_obj_get_style_list(obj, LV_IMG_PART_MAIN); + break; +#endif + +#if LV_USE_LABEL + case LV_THEME_LABEL: + list = lv_obj_get_style_list(obj, LV_LABEL_PART_MAIN); + break; +#endif + +#if LV_USE_LINE + case LV_THEME_LINE: + list = lv_obj_get_style_list(obj, LV_LABEL_PART_MAIN); + break; +#endif + +#if LV_USE_ARC + case LV_THEME_ARC: + list = lv_obj_get_style_list(obj, LV_ARC_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tick_line); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_ARC_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->tick_line); + break; +#endif + +#if LV_USE_SPINNER + case LV_THEME_SPINNER: + list = lv_obj_get_style_list(obj, LV_SPINNER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tick_line); + + list = lv_obj_get_style_list(obj, LV_SPINNER_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->tick_line); + break; +#endif + +#if LV_USE_SLIDER + case LV_THEME_SLIDER: + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_CHECKBOX + case LV_THEME_CHECKBOX: + list = lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); + + list = lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BULLET); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_MSGBOX + case LV_THEME_MSGBOX: + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_MSGBOX_BTNS: + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BTN_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; + +#endif +#if LV_USE_LED + case LV_THEME_LED: + list = lv_obj_get_style_list(obj, LV_LED_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->round); + break; +#endif +#if LV_USE_PAGE + case LV_THEME_PAGE: + list = lv_obj_get_style_list(obj, LV_PAGE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif +#if LV_USE_TABVIEW + case LV_THEME_TABVIEW: + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_BG_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_TAB_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_TAB_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; + + case LV_THEME_TABVIEW_PAGE: + list = lv_obj_get_style_list(obj, LV_PAGE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + break; +#endif + +#if LV_USE_TILEVIEW + case LV_THEME_TILEVIEW: + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_EDGE_FLASH); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + + +#if LV_USE_ROLLER + case LV_THEME_ROLLER: + list = lv_obj_get_style_list(obj, LV_ROLLER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_ROLLER_PART_SELECTED); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + + +#if LV_USE_OBJMASK + case LV_THEME_OBJMASK: + list = lv_obj_get_style_list(obj, LV_OBJMASK_PART_MAIN); + break; +#endif + +#if LV_USE_LIST + case LV_THEME_LIST: + list = lv_obj_get_style_list(obj, LV_LIST_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_LIST_PART_SCROLLABLE); + + list = lv_obj_get_style_list(obj, LV_LIST_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_LIST_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_DROPDOWN + case LV_THEME_DROPDOWN: + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_LIST); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_SELECTED); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + +#if LV_USE_CHART + case LV_THEME_CHART: + list = lv_obj_get_style_list(obj, LV_CHART_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; +#endif +#if LV_USE_TABLE + case LV_THEME_TABLE: { + list = lv_obj_get_style_list(obj, LV_TABLE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + int idx = 1; /* start value should be 1, not zero, since cell styles + start at 1 due to presence of LV_TABLE_PART_BG=0 + in the enum (lv_table.h) */ + /* declaring idx outside loop to work with older compilers */ + for(; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++) { + list = lv_obj_get_style_list(obj, idx); + _lv_style_list_add_style(list, &styles->bg); + } + break; + } +#endif + +#if LV_USE_WIN + case LV_THEME_WIN: + list = lv_obj_get_style_list(obj, LV_WIN_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_CONTENT_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_HEADER); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_WIN_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_TEXTAREA + case LV_THEME_TEXTAREA: + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_PLACEHOLDER); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + + +#if LV_USE_SPINBOX + case LV_THEME_SPINBOX: + list = lv_obj_get_style_list(obj, LV_SPINBOX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_SPINBOX_PART_CURSOR); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_SPINBOX_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_CALENDAR + case LV_THEME_CALENDAR: + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_DATE); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_HEADER); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_DAY_NAMES); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; +#endif +#if LV_USE_CPICKER + case LV_THEME_CPICKER: + list = lv_obj_get_style_list(obj, LV_CPICKER_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CPICKER_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_LINEMETER + case LV_THEME_LINEMETER: + list = lv_obj_get_style_list(obj, LV_LINEMETER_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif +#if LV_USE_GAUGE + case LV_THEME_GAUGE: + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_MAJOR); + _lv_style_list_add_style(list, &styles->tick_line); + + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_NEEDLE); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + default: + break; + } + + lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init_reset(lv_style_t * style) +{ + if(inited) lv_style_reset(style); + else lv_style_init(style); +} + +#endif diff --git a/src/lv_widgets/lv_chart.h b/src/lv_widgets/lv_chart.h index 1468dd50d..48f69bd97 100644 --- a/src/lv_widgets/lv_chart.h +++ b/src/lv_widgets/lv_chart.h @@ -157,7 +157,7 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color); * Add a cursor with a given color * @param chart pointer to chart object * @param color color of the cursor - * @param dir direction of the cursor. `LV_CHART_CURSOR_RIGHT/LEFT/TOP/DOWN`. OR-ed vaƩues are possible + * @param dir direction of the cursor. `LV_CHART_CURSOR_RIGHT/LEFT/TOP/DOWN`. OR-ed values are possible * @return pointer to the created cursor */ lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * chart, lv_color_t color, lv_cursor_direction_t dir); diff --git a/src/lv_widgets/lv_cont.h b/src/lv_widgets/lv_cont.h new file mode 100644 index 000000000..6fc6a2a52 --- /dev/null +++ b/src/lv_widgets/lv_cont.h @@ -0,0 +1,223 @@ +/** + * @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 */ + + /** + * COLUMN: + * - 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_img.c b/src/lv_widgets/lv_img.c index 866dbb8f5..e3767a62d 100644 --- a/src/lv_widgets/lv_img.c +++ b/src/lv_widgets/lv_img.c @@ -627,16 +627,16 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area if(zoomed_src_w <= 0) return LV_DESIGN_RES_OK; lv_coord_t zoomed_src_h = (int32_t)((int32_t)ext->h * zoom_final) >> 8; if(zoomed_src_h <= 0) return LV_DESIGN_RES_OK; - lv_area_t zommed_coords; - lv_obj_get_coords(img, &zommed_coords); + lv_area_t zoomed_coords; + lv_obj_get_coords(img, &zoomed_coords); - zommed_coords.x1 += (int32_t)((int32_t)ext->offset.x * zoom_final) >> 8; - zommed_coords.y1 += (int32_t)((int32_t)ext->offset.y * zoom_final) >> 8; - zommed_coords.x2 = zommed_coords.x1 + ((int32_t)((int32_t)(obj_w - 1) * zoom_final) >> 8); - zommed_coords.y2 = zommed_coords.y1 + ((int32_t)((int32_t)(obj_h - 1) * zoom_final) >> 8); + zoomed_coords.x1 += (int32_t)((int32_t)ext->offset.x * zoom_final) >> 8; + zoomed_coords.y1 += (int32_t)((int32_t)ext->offset.y * zoom_final) >> 8; + zoomed_coords.x2 = zoomed_coords.x1 + ((int32_t)((int32_t)(obj_w - 1) * zoom_final) >> 8); + zoomed_coords.y2 = zoomed_coords.y1 + ((int32_t)((int32_t)(obj_h - 1) * zoom_final) >> 8); - if(zommed_coords.x1 > img->coords.x1) zommed_coords.x1 -= ext->w; - if(zommed_coords.y1 > img->coords.y1) zommed_coords.y1 -= ext->h; + if(zoomed_coords.x1 > img->coords.x1) zoomed_coords.x1 -= ext->w; + if(zoomed_coords.y1 > img->coords.y1) zoomed_coords.y1 -= ext->h; lv_area_t clip_real; _lv_img_buf_get_transformed_area(&clip_real, lv_obj_get_width(img), lv_obj_get_height(img), angle_final, zoom_final, @@ -649,13 +649,13 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area if(_lv_area_intersect(&clip_real, &clip_real, clip_area) == false) return LV_DESIGN_RES_OK; lv_area_t coords_tmp; - coords_tmp.y1 = zommed_coords.y1; - coords_tmp.y2 = zommed_coords.y1 + ext->h - 1; + coords_tmp.y1 = zoomed_coords.y1; + coords_tmp.y2 = zoomed_coords.y1 + ext->h - 1; - for(; coords_tmp.y1 < zommed_coords.y2; coords_tmp.y1 += zoomed_src_h, coords_tmp.y2 += zoomed_src_h) { - coords_tmp.x1 = zommed_coords.x1; - coords_tmp.x2 = zommed_coords.x1 + ext->w - 1; - for(; coords_tmp.x1 < zommed_coords.x2; coords_tmp.x1 += zoomed_src_w, coords_tmp.x2 += zoomed_src_w) { + for(; coords_tmp.y1 < zoomed_coords.y2; coords_tmp.y1 += zoomed_src_h, coords_tmp.y2 += zoomed_src_h) { + coords_tmp.x1 = zoomed_coords.x1; + coords_tmp.x2 = zoomed_coords.x1 + ext->w - 1; + for(; coords_tmp.x1 < zoomed_coords.x2; coords_tmp.x1 += zoomed_src_w, coords_tmp.x2 += zoomed_src_w) { lv_draw_img(&coords_tmp, &clip_real, ext->src, &img_dsc); } } diff --git a/src/lv_widgets/lv_imgbtn.c b/src/lv_widgets/lv_imgbtn.c index b9dc78485..6c678bdb1 100644 --- a/src/lv_widgets/lv_imgbtn.c +++ b/src/lv_widgets/lv_imgbtn.c @@ -515,7 +515,7 @@ static void refr_img(lv_obj_t * imgbtn) } /** - * If `src` is not defined for the current state try to get a state which is related to the curent but has `src`. + * If `src` is not defined for the current state try to get a state which is related to the current but has `src`. * E.g. if the PRESSED src is not set but the RELEASED does, use the RELEASED. * @param imgbtn pointer to an image button * @param state the state to convert diff --git a/src/lv_widgets/lv_label.c b/src/lv_widgets/lv_label.c index 7756e211f..a4f961cf5 100644 --- a/src/lv_widgets/lv_label.c +++ b/src/lv_widgets/lv_label.c @@ -336,11 +336,11 @@ void lv_label_set_recolor(lv_obj_t * label, bool en) ext->recolor = en == false ? 0 : 1; lv_label_refr_text(label); /*Refresh the text because the potential color codes in text needs to - be hided or revealed*/ + be hidden or revealed*/ } /** - * Set the label's animation speed in LV_LABEL_LONG_SROLL/SCROLL_CIRC modes + * Set the label's animation speed in LV_LABEL_LONG_SROLL/SROLL_CIRC modes * @param label pointer to a label object * @param anim_speed speed of animation in px/sec unit */ @@ -1252,7 +1252,7 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_ label_draw_dsc.flag = flag; lv_obj_init_draw_label_dsc(label, LV_LABEL_PART_MAIN, &label_draw_dsc); - /* In SCROLL and SCROLL_CIRC mode the CENTER and RIGHT are pointless so remove them. + /* In SROLL and SROLL_CIRC mode the CENTER and RIGHT are pointless so remove them. * (In addition they will result misalignment is this case)*/ if((ext->long_mode == LV_LABEL_LONG_SROLL || ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) && (ext->align == LV_LABEL_ALIGN_CENTER || ext->align == LV_LABEL_ALIGN_RIGHT)) { diff --git a/src/lv_widgets/lv_label.h b/src/lv_widgets/lv_label.h index 67b19f58e..097846c5c 100644 --- a/src/lv_widgets/lv_label.h +++ b/src/lv_widgets/lv_label.h @@ -168,7 +168,7 @@ void lv_label_set_align(lv_obj_t * label, lv_label_align_t align); void lv_label_set_recolor(lv_obj_t * label, bool en); /** - * Set the label's animation speed in LV_LABEL_LONG_SROLL/SCROLL_CIRC modes + * Set the label's animation speed in LV_LABEL_LONG_SROLL/SROLL_CIRC modes * @param label pointer to a label object * @param anim_speed speed of animation in px/sec unit */ diff --git a/src/lv_widgets/lv_list.h b/src/lv_widgets/lv_list.h new file mode 100644 index 000000000..f78cd3cf9 --- /dev/null +++ b/src/lv_widgets/lv_list.h @@ -0,0 +1,311 @@ +/** + * @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_ANIM_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_roller.h b/src/lv_widgets/lv_roller.h index b3e595477..9db187dff 100644 --- a/src/lv_widgets/lv_roller.h +++ b/src/lv_widgets/lv_roller.h @@ -94,7 +94,7 @@ void lv_roller_set_align(lv_obj_t * roller, lv_label_align_t align); * Set the selected option * @param roller pointer to a roller object * @param sel_opt id of the selected option (0 ... number of option - 1); - * @param anim LV_ANOM_ON: set with animation; LV_ANIM_OFF set immediately + * @param anim LV_ANIM_ON: set with animation; LV_ANIM_OFF set immediately */ void lv_roller_set_selected(lv_obj_t * roller, uint16_t sel_opt, lv_anim_enable_t anim); diff --git a/src/lv_widgets/lv_switch.c b/src/lv_widgets/lv_switch.c index 36fcb8772..43eeca456 100644 --- a/src/lv_widgets/lv_switch.c +++ b/src/lv_widgets/lv_switch.c @@ -37,7 +37,6 @@ static lv_res_t lv_switch_signal(lv_obj_t * sw, lv_signal_t sign, void * param); static lv_design_res_t lv_switch_design(lv_obj_t * sw, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_style_list_t * lv_switch_get_style(lv_obj_t * sw, uint8_t part); -static lv_style_list_t * lv_switch_get_style(lv_obj_t * sw, uint8_t part); /********************** * STATIC VARIABLES @@ -114,7 +113,7 @@ lv_obj_t * lv_switch_create(lv_obj_t * parent, const lv_obj_t * copy) /** * Turn ON the switch * @param sw pointer to a switch object - * @param anim LV_ANOM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ void lv_switch_on(lv_obj_t * sw, lv_anim_enable_t anim) { diff --git a/src/lv_widgets/lv_tabview.c b/src/lv_widgets/lv_tabview.c new file mode 100644 index 000000000..2cb2b6bc0 --- /dev/null +++ b/src/lv_widgets/lv_tabview.c @@ -0,0 +1,1033 @@ +/** + * @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_SCROLLABLE), lv_obj_get_style_list(copy, + LV_TABVIEW_PART_BG_SCROLLABLE)); + 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_SCROLLABLE) 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_SCROLLABLE: + 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_SCROLLABLE); + lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(tabview, LV_TABVIEW_PART_BG_SCROLLABLE); + 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 new file mode 100644 index 000000000..6970d8e18 --- /dev/null +++ b/src/lv_widgets/lv_tabview.h @@ -0,0 +1,192 @@ +/** + * @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_SCROLLABLE = _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_textarea.c b/src/lv_widgets/lv_textarea.c index 9a16c4b97..1b1b3b0cd 100644 --- a/src/lv_widgets/lv_textarea.c +++ b/src/lv_widgets/lv_textarea.c @@ -106,7 +106,7 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy) ext->pwd_mode = 0; ext->pwd_tmp = NULL; ext->pwd_show_time = LV_TEXTAREA_DEF_PWD_SHOW_TIME; - ext->accapted_chars = NULL; + ext->accepted_chars = NULL; ext->max_length = 0; ext->cursor.state = 1; ext->cursor.hidden = 0; @@ -146,7 +146,7 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy) lv_textarea_ext_t * copy_ext = lv_obj_get_ext_attr(copy); ext->label = lv_label_create(ta, copy_ext->label); ext->pwd_mode = copy_ext->pwd_mode; - ext->accapted_chars = copy_ext->accapted_chars; + ext->accepted_chars = copy_ext->accepted_chars; ext->max_length = copy_ext->max_length; ext->cursor.pos = copy_ext->cursor.pos; ext->cursor.valid_x = copy_ext->cursor.valid_x; @@ -764,7 +764,7 @@ void lv_textarea_set_accepted_chars(lv_obj_t * ta, const char * list) lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); - ext->accapted_chars = list; + ext->accepted_chars = list; } /** @@ -1006,7 +1006,7 @@ const char * lv_textarea_get_accepted_chars(lv_obj_t * ta) lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); - return ext->accapted_chars; + return ext->accepted_chars; } /** @@ -1472,7 +1472,7 @@ static bool char_is_accepted(lv_obj_t * ta, uint32_t c) lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); /*If no restriction accept it*/ - if(ext->accapted_chars == NULL && ext->max_length == 0) return true; + if(ext->accepted_chars == NULL && ext->max_length == 0) return true; /*Too many characters?*/ if(ext->max_length > 0 && _lv_txt_get_encoded_length(lv_textarea_get_text(ta)) >= ext->max_length) { @@ -1480,11 +1480,11 @@ static bool char_is_accepted(lv_obj_t * ta, uint32_t c) } /*Accepted character?*/ - if(ext->accapted_chars) { + if(ext->accepted_chars) { uint32_t i = 0; - while(ext->accapted_chars[i] != '\0') { - uint32_t a = _lv_txt_encoded_next(ext->accapted_chars, &i); + while(ext->accepted_chars[i] != '\0') { + uint32_t a = _lv_txt_encoded_next(ext->accepted_chars, &i); if(a == c) return true; /*Accepted*/ } diff --git a/src/lv_widgets/lv_textarea.h b/src/lv_widgets/lv_textarea.h index 0141d85e8..e7f17457b 100644 --- a/src/lv_widgets/lv_textarea.h +++ b/src/lv_widgets/lv_textarea.h @@ -43,7 +43,7 @@ typedef struct { char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ lv_style_list_t style_placeholder; char * pwd_tmp; /*Used to store the original text in password mode*/ - const char * accapted_chars; /*Only these characters will be accepted. NULL: accept all*/ + const char * accepted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint32_t max_length; /*The max. number of characters. 0: no limit*/ uint16_t pwd_show_time; /*Time to show characters in password mode before change them to '*' */ struct { diff --git a/src/lv_widgets/lv_win.c b/src/lv_widgets/lv_win.c new file mode 100644 index 000000000..b0f123ee8 --- /dev/null +++ b/src/lv_widgets/lv_win.c @@ -0,0 +1,808 @@ +/** + * @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 * win_btn, 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_win_ext_t * ext = lv_obj_get_ext_attr(win); + + lv_obj_t * scrl = lv_page_get_scrollable(ext->page); + 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 event 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 new file mode 100644 index 000000000..06e67132d --- /dev/null +++ b/src/lv_widgets/lv_win.h @@ -0,0 +1,300 @@ +/** + * @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 event 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*/