diff --git a/examples/ESP32_TFT_eSPI/ESP32_TFT_eSPI.ino b/examples/ESP32_TFT_eSPI/ESP32_TFT_eSPI.ino index 5e94cfa..1f16516 100644 --- a/examples/ESP32_TFT_eSPI/ESP32_TFT_eSPI.ino +++ b/examples/ESP32_TFT_eSPI/ESP32_TFT_eSPI.ino @@ -78,7 +78,7 @@ void setup() /* Create simple label */ lv_obj_t *label = lv_label_create(lv_scr_act(), NULL); - lv_label_set_text(label, "Hello Arduino! (V6.1.1)"); + lv_label_set_text(label, "Hello Arduino! (V7.0.X)"); lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0); } diff --git a/library.json b/library.json index 9842370..d13f837 100644 --- a/library.json +++ b/library.json @@ -10,9 +10,9 @@ "repository": { "type": "git", - "url": "https://github.com/littlevgl/arduino" + "url": "https://github.com/lvgl/lv_arduino" }, - "version": "2.1.5", + "version": "3.0.0", "license": "MIT", "frameworks": "arduino", "build": { diff --git a/library.properties b/library.properties index 9508bc1..b901fbe 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=lv_arduino -version=2.1.5 +version=3.0.0 author=Gabor Kiss-Vamosi maintainer=Pavel Brychta sentence=Full-featured Graphics Library for embedded systems paragraph=Littlev Graphics Library provides everything you need to create a Graphical User Interface (GUI) on embedded systems with easy-to-use graphical elements, beautiful visual effects and low memory footprint. category=Display -url=https://littlevgl.com +url=https://lvgl.io architectures=* includes=lvgl.h diff --git a/lv_conf.h b/lv_conf.h index 0f13971..fa70a45 100644 --- a/lv_conf.h +++ b/lv_conf.h @@ -20,8 +20,8 @@ *====================*/ /* Maximal horizontal and vertical resolution to support by the library.*/ -#define LV_HOR_RES_MAX (320) -#define LV_VER_RES_MAX (240) +#define LV_HOR_RES_MAX (480) +#define LV_VER_RES_MAX (320) /* Color depth: * - 1: 1 byte per pixel @@ -43,9 +43,6 @@ /*Images pixels with this color will not be drawn (with chroma keying)*/ #define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ -/* Enable chroma keying for indexed images. */ -#define LV_INDEXED_CHROMA 1 - /* Enable anti-aliasing (lines, and radiuses will be smoothed) */ #define LV_ANTIALIAS 1 @@ -56,7 +53,18 @@ /* Dot Per Inch: used to initialize default sizes. * E.g. a button with width = LV_DPI / 2 -> half inch wide * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI 100 /*[px]*/ +#define LV_DPI 130 /*[px]*/ + +/* The the real width of the display changes some default values: + * default object sizes, layout of examples, etc. + * According to the width of the display (hor. res. / dpi) + * the displays fall in 4 categories. + * The 4th is extra large which has no upper limit so not listed here + * The upper limit of the categories are set below in 0.1 inch unit. + */ +#define LV_DISP_SMALL_LIMIT 30 +#define LV_DISP_MEDIUM_LIMIT 50 +#define LV_DISP_LARGE_LIMIT 70 /* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ typedef int16_t lv_coord_t; @@ -112,7 +120,7 @@ typedef int16_t lv_coord_t; #define LV_INDEV_DEF_DRAG_LIMIT 10 /* Drag throw slow-down in [%]. Greater value -> faster slow-down */ -#define LV_INDEV_DEF_DRAG_THROW 20 +#define LV_INDEV_DEF_DRAG_THROW 10 /* Long press time in milliseconds. * Time to send `LV_EVENT_LONG_PRESSSED`) */ @@ -122,6 +130,13 @@ typedef int16_t lv_coord_t; * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ #define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 + +/* Gesture threshold in pixels */ +#define LV_INDEV_DEF_GESTURE_LIMIT 50 + +/* Gesture min velocity at release before swipe (pixels)*/ +#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 + /*================== * Feature usage *==================*/ @@ -137,6 +152,22 @@ typedef void * lv_anim_user_data_t; /* 1: Enable shadow drawing*/ #define LV_USE_SHADOW 1 +#if LV_USE_SHADOW +/* Allow buffering some shadow calculation + * LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, + * where shadow size is `shadow_width + radius` + * Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ +#define LV_SHADOW_CACHE_SIZE 0 +#endif + +/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/ +#define LV_USE_BLEND_MODES 1 + +/* 1: Use the `opa_scale` style property to set the opacity of an object and its children at once*/ +#define LV_USE_OPA_SCALE 1 + +/* 1: Use image zoom and rotation*/ +#define LV_USE_IMG_TRANSFORM 1 /* 1: Enable object groups (for keyboard/encoder navigation) */ #define LV_USE_GROUP 1 @@ -145,7 +176,8 @@ typedef void * lv_group_user_data_t; #endif /*LV_USE_GROUP*/ /* 1: Enable GPU interface*/ -#define LV_USE_GPU 1 +#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ +#define LV_USE_GPU_STM32_DMA2D 0 /* 1: Enable file system (might be required for images */ #define LV_USE_FILESYSTEM 1 @@ -155,7 +187,13 @@ typedef void * lv_fs_drv_user_data_t; #endif /*1: Add a `user_data` to drivers and objects*/ -#define LV_USE_USER_DATA 1 +#define LV_USE_USER_DATA 0 + +/*1: Show CPU usage and FPS count in the right bottom corner*/ +#define LV_USE_PERF_MONITOR 0 + +/*1: Use the functions and types from the older API if possible */ +#define LV_USE_API_EXTENSION_V6 1 /*======================== * Image decoder and cache @@ -187,6 +225,9 @@ typedef void * lv_img_decoder_user_data_t; /* Define a custom attribute to `lv_task_handler` function */ #define LV_ATTRIBUTE_TASK_HANDLER +/* Define a custom attribute to `lv_disp_flush_ready` function */ +#define LV_ATTRIBUTE_FLUSH_READY + /* With size optimization (-Os) the compiler might not align data to * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. * E.g. __attribute__((aligned(4))) */ @@ -196,6 +237,10 @@ typedef void * lv_img_decoder_user_data_t; * font's bitmaps */ #define LV_ATTRIBUTE_LARGE_CONST +/* Prefix performance critical functions to place them into a faster memory (e.g RAM) + * Uses 15-20 kB extra memory */ +#define LV_ATTRIBUTE_FAST_MEM + /* Export integer constant to binding. * This macro is used with constants in the form of LV_ that * should also appear on lvgl binding API such as Micropython @@ -262,6 +307,9 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i /*Checks is the memory is successfully allocated or no. (Quite fast)*/ #define LV_USE_ASSERT_MEM 1 +/*Check the integrity of `lv_mem` after critical operations. (Slow)*/ +#define LV_USE_ASSERT_MEM_INTEGRITY 0 + /* Check the strings. * Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow) * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ @@ -272,44 +320,47 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i #define LV_USE_ASSERT_OBJ 0 /*Check if the styles are properly initialized. (Fast)*/ -#define LV_USE_ASSERT_STYLE 1 +#define LV_USE_ASSERT_STYLE 0 #endif /*LV_USE_DEBUG*/ -/*================ - * THEME USAGE - *================*/ -#define LV_THEME_LIVE_UPDATE 0 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ - -#define LV_USE_THEME_TEMPL 0 /*Just for test*/ -#define LV_USE_THEME_DEFAULT 0 /*Built mainly from the built-in styles. Consumes very few RAM*/ -#define LV_USE_THEME_ALIEN 0 /*Dark futuristic theme*/ -#define LV_USE_THEME_NIGHT 0 /*Dark elegant theme*/ -#define LV_USE_THEME_MONO 0 /*Mono color theme for monochrome displays*/ -#define LV_USE_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/ -#define LV_USE_THEME_ZEN 0 /*Peaceful, mainly light theme */ -#define LV_USE_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/ - /*================== * FONT USAGE *===================*/ /* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel. * The symbols are available via `LV_SYMBOL_...` defines - * More info about fonts: https://docs.littlevgl.com/#Fonts - * To create a new font go to: https://littlevgl.com/ttf-font-to-c-array + * More info about fonts: https://docs.lvgl.com/#Fonts + * To create a new font go to: https://lvgl.com/ttf-font-to-c-array */ -/* Robot fonts with bpp = 4 - * https://fonts.google.com/specimen/Roboto */ -#define LV_FONT_ROBOTO_12 0 -#define LV_FONT_ROBOTO_16 1 -#define LV_FONT_ROBOTO_22 0 -#define LV_FONT_ROBOTO_28 0 +/* Montserrat fonts with bpp = 4 + * https://fonts.google.com/specimen/Montserrat */ +#define LV_FONT_MONTSERRAT_12 0 +#define LV_FONT_MONTSERRAT_14 0 +#define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_18 0 +#define LV_FONT_MONTSERRAT_20 0 +#define LV_FONT_MONTSERRAT_22 0 +#define LV_FONT_MONTSERRAT_24 0 +#define LV_FONT_MONTSERRAT_26 0 +#define LV_FONT_MONTSERRAT_28 0 +#define LV_FONT_MONTSERRAT_30 0 +#define LV_FONT_MONTSERRAT_32 0 +#define LV_FONT_MONTSERRAT_34 0 +#define LV_FONT_MONTSERRAT_36 0 +#define LV_FONT_MONTSERRAT_38 0 +#define LV_FONT_MONTSERRAT_40 0 +#define LV_FONT_MONTSERRAT_42 0 +#define LV_FONT_MONTSERRAT_44 0 +#define LV_FONT_MONTSERRAT_46 0 +#define LV_FONT_MONTSERRAT_48 0 /* Demonstrate special features */ -#define LV_FONT_ROBOTO_12_SUBPX 1 -#define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/ +#define LV_FONT_MONTSERRAT_12_SUBPX 0 +#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ +#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, PErisan letters and all their forms*/ +#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ /*Pixel perfect monospace font * http://pelulamu.net/unscii/ */ @@ -323,9 +374,6 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i */ #define LV_FONT_CUSTOM_DECLARE -/*Always set a default font from the built-in fonts*/ -#define LV_FONT_DEFAULT &lv_font_roboto_16 - /* Enable it if you have fonts with a lot of characters. * The limit depends on the font size, font face and bpp * but with > 10,000 characters if you see issues probably you need to enable it.*/ @@ -340,6 +388,43 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i /*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_font_user_data_t; +/*================ + * THEME USAGE + *================*/ + +/*Always enable at least on theme*/ + +/* No theme, you can apply your styles as you need + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_EMPTY 1 + +/*Simple to the create your theme based on it + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_TEMPLATE 1 + +/* A fast and impressive theme. + * Flags: + * LV_THEME_MATERIAL_FLAG_LIGHT: light theme + * LV_THEME_MATERIAL_FLAG_DARK: dark theme*/ + #define LV_USE_THEME_MATERIAL 1 + +/* Mono-color theme for monochrome displays. + * If LV_THEME_DEFAULT_COLOR_PRIMARY is LV_COLOR_BLACK the + * texts and borders will be black and the background will be + * white. Else the colors are inverted. + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_MONO 1 + +#define LV_THEME_DEFAULT_INCLUDE /*Include a header for the init. function*/ +#define LV_THEME_DEFAULT_INIT lv_theme_material_init +#define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED +#define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE +#define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT +#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_16 + /*================= * Text settings *=================*/ @@ -356,7 +441,7 @@ typedef void * lv_font_user_data_t; /* If a word is at least this long, will break wherever "prettiest" * To disable, set to a value <= 0 */ -#define LV_TXT_LINE_BREAK_LONG_LEN 12 +#define LV_TXT_LINE_BREAK_LONG_LEN 0 /* Minimum number of characters in a long word to put on a line before a break. * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ @@ -382,6 +467,11 @@ typedef void * lv_font_user_data_t; #define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO #endif +/* Enable Arabic/Persian processing + * In these languages characters should be replaced with + * an other form based on their position in the text */ +#define LV_USE_ARABIC_PERSIAN_CHARS 0 + /*Change the built in (v)snprintf functions*/ #define LV_SPRINTF_CUSTOM 0 #if LV_SPRINTF_CUSTOM @@ -394,8 +484,17 @@ typedef void * lv_font_user_data_t; * LV_OBJ SETTINGS *==================*/ +#if LV_USE_USER_DATA /*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_obj_user_data_t; +/*Provide a function to free user data*/ +#define LV_USE_USER_DATA_FREE 0 +#if LV_USE_USER_DATA_FREE +# define LV_USER_DATA_FREE_INCLUDE "something.h" /*Header for user data free function*/ +/* Function prototype : void user_data_free(lv_obj_t * obj); */ +# define LV_USER_DATA_FREE (user_data_free) /*Invoking for user data free function*/ +#endif +#endif /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ #define LV_USE_OBJ_REALIGN 1 @@ -405,13 +504,13 @@ typedef void * lv_obj_user_data_t; * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) */ -#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_OFF +#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_TINY /*================== * LV OBJ X USAGE *================*/ /* - * Documentation of the object types: https://docs.littlevgl.com/#Object-types + * Documentation of the object types: https://docs.lvgl.com/#Object-types */ /*Arc (dependencies: -)*/ @@ -422,13 +521,9 @@ typedef void * lv_obj_user_data_t; /*Button (dependencies: lv_cont*/ #define LV_USE_BTN 1 -#if LV_USE_BTN != 0 -/*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/ -# define LV_BTN_INK_EFFECT 1 -#endif /*Button matrix (dependencies: -)*/ -#define LV_USE_BTNM 1 +#define LV_USE_BTNMATRIX 1 /*Calendar (dependencies: -)*/ #define LV_USE_CALENDAR 1 @@ -437,12 +532,12 @@ typedef void * lv_obj_user_data_t; #define LV_USE_CANVAS 1 /*Check box (dependencies: lv_btn, lv_label)*/ -#define LV_USE_CB 1 +#define LV_USE_CHECKBOX 1 /*Chart (dependencies: -)*/ #define LV_USE_CHART 1 #if LV_USE_CHART -# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20 +# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 256 #endif /*Container (dependencies: -*/ @@ -452,13 +547,13 @@ typedef void * lv_obj_user_data_t; #define LV_USE_CPICKER 1 /*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ -#define LV_USE_DDLIST 1 -#if LV_USE_DDLIST != 0 +#define LV_USE_DROPDOWN 1 +#if LV_USE_DROPDOWN != 0 /*Open and close default animation time [ms] (0: no animation)*/ -# define LV_DDLIST_DEF_ANIM_TIME 200 +# define LV_DROPDOWN_DEF_ANIM_TIME 200 #endif -/*Gauge (dependencies:lv_bar, lv_lmeter)*/ +/*Gauge (dependencies:lv_bar, lv_linemeter)*/ #define LV_USE_GAUGE 1 /*Image (dependencies: lv_label*/ @@ -472,7 +567,7 @@ typedef void * lv_obj_user_data_t; #endif /*Keyboard (dependencies: lv_btnm)*/ -#define LV_USE_KB 1 +#define LV_USE_KEYBOARD 1 /*Label (dependencies: -*/ #define LV_USE_LABEL 1 @@ -492,6 +587,10 @@ typedef void * lv_obj_user_data_t; /*LED (dependencies: -)*/ #define LV_USE_LED 1 +#if LV_USE_LED +# define LV_LED_BRIGHT_MIN 120 /*Minimal brightness*/ +# define LV_LED_BRIGHT_MAX 255 /*Maximal brightness*/ +#endif /*Line (dependencies: -*/ #define LV_USE_LINE 1 @@ -504,10 +603,22 @@ typedef void * lv_obj_user_data_t; #endif /*Line meter (dependencies: *;)*/ -#define LV_USE_LMETER 1 +#define LV_USE_LINEMETER 1 +#if LV_USE_LINEMETER +/* Draw line more precisely at cost of performance. + * Useful if there are lot of lines any minor are visible + * 0: No extra precision + * 1: Some extra precision + * 2: Best precision + */ +# define LV_LINEMETER_PRECISE 0 +#endif + +/*Mask (dependencies: -)*/ +#define LV_USE_OBJMASK 1 /*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ -#define LV_USE_MBOX 1 +#define LV_USE_MSGBOX 1 /*Page (dependencies: lv_cont)*/ #define LV_USE_PAGE 1 @@ -517,11 +628,11 @@ typedef void * lv_obj_user_data_t; #endif /*Preload (dependencies: lv_arc, lv_anim)*/ -#define LV_USE_PRELOAD 1 -#if LV_USE_PRELOAD != 0 -# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ -# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ -# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC +#define LV_USE_SPINNER 1 +#if LV_USE_SPINNER != 0 +# define LV_SPINNER_DEF_ARC_LENGTH 60 /*[deg]*/ +# define LV_SPINNER_DEF_SPIN_TIME 1000 /*[ms]*/ +# define LV_SPINNER_DEF_ANIM LV_SPINNER_TYPE_SPINNING_ARC #endif /*Roller (dependencies: lv_ddlist)*/ @@ -541,13 +652,13 @@ typedef void * lv_obj_user_data_t; #define LV_USE_SPINBOX 1 /*Switch (dependencies: lv_slider)*/ -#define LV_USE_SW 1 +#define LV_USE_SWITCH 1 /*Text area (dependencies: lv_label, lv_page)*/ -#define LV_USE_TA 1 -#if LV_USE_TA != 0 -# define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ -# define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#define LV_USE_TEXTAREA 1 +#if LV_USE_TEXTAREA != 0 +# define LV_TEXTAREA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ +# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ #endif /*Table (dependencies: lv_label)*/ @@ -583,9 +694,6 @@ typedef void * lv_obj_user_data_t; /*--END OF LV_CONF_H--*/ -/*Be sure every define has a default value*/ -#include "src/lv_conf_checker.h" - #endif /*LV_CONF_H*/ #endif /*End of "Content enable"*/ diff --git a/src/src/lv_conf_checker.h b/lv_conf.h_ similarity index 77% rename from src/src/lv_conf_checker.h rename to lv_conf.h_ index 4b0d9a6..0f13971 100644 --- a/src/src/lv_conf_checker.h +++ b/lv_conf.h_ @@ -1,11 +1,16 @@ /** - * GENERATED FILE, DO NOT EDIT IT! - * @file lv_conf_checker.h - * Make sure all the defines of lv_conf.h have a default value -**/ + * @file lv_conf.h + * + */ + +/* + * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER + */ -#ifndef LV_CONF_CHECKER_H -#define LV_CONF_CHECKER_H +#if 1 /*Set it to "1" to enable content*/ + +#ifndef LV_CONF_H +#define LV_CONF_H /* clang-format off */ #include @@ -15,12 +20,8 @@ *====================*/ /* Maximal horizontal and vertical resolution to support by the library.*/ -#ifndef LV_HOR_RES_MAX -#define LV_HOR_RES_MAX (480) -#endif -#ifndef LV_VER_RES_MAX -#define LV_VER_RES_MAX (320) -#endif +#define LV_HOR_RES_MAX (320) +#define LV_VER_RES_MAX (240) /* Color depth: * - 1: 1 byte per pixel @@ -28,52 +29,37 @@ * - 16: RGB565 * - 32: ARGB8888 */ -#ifndef LV_COLOR_DEPTH #define LV_COLOR_DEPTH 16 -#endif /* Swap the 2 bytes of RGB565 color. * Useful if the display has a 8 bit interface (e.g. SPI)*/ -#ifndef LV_COLOR_16_SWAP #define LV_COLOR_16_SWAP 0 -#endif /* 1: Enable screen transparency. * Useful for OSD or other overlapping GUIs. * Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/ -#ifndef LV_COLOR_SCREEN_TRANSP #define LV_COLOR_SCREEN_TRANSP 0 -#endif /*Images pixels with this color will not be drawn (with chroma keying)*/ -#ifndef LV_COLOR_TRANSP #define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ -#endif /* Enable chroma keying for indexed images. */ -#ifndef LV_INDEXED_CHROMA #define LV_INDEXED_CHROMA 1 -#endif /* Enable anti-aliasing (lines, and radiuses will be smoothed) */ -#ifndef LV_ANTIALIAS #define LV_ANTIALIAS 1 -#endif /* Default display refresh period. * Can be changed in the display driver (`lv_disp_drv_t`).*/ -#ifndef LV_DISP_DEF_REFR_PERIOD #define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ -#endif /* Dot Per Inch: used to initialize default sizes. * E.g. a button with width = LV_DPI / 2 -> half inch wide * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#ifndef LV_DPI #define LV_DPI 100 /*[px]*/ -#endif /* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ +typedef int16_t lv_coord_t; /*========================= Memory manager settings @@ -83,57 +69,33 @@ * The graphical objects and other related data are stored here. */ /* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ -#ifndef LV_MEM_CUSTOM #define LV_MEM_CUSTOM 0 -#endif #if LV_MEM_CUSTOM == 0 /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ -#ifndef LV_MEM_SIZE # define LV_MEM_SIZE (32U * 1024U) -#endif /* Complier prefix for a big array declaration */ -#ifndef LV_MEM_ATTR # define LV_MEM_ATTR -#endif /* Set an address for the memory pool instead of allocating it as an array. * Can be in external SRAM too. */ -#ifndef LV_MEM_ADR # define LV_MEM_ADR 0 -#endif /* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ -#ifndef LV_MEM_AUTO_DEFRAG # define LV_MEM_AUTO_DEFRAG 1 -#endif #else /*LV_MEM_CUSTOM*/ -#ifndef LV_MEM_CUSTOM_INCLUDE # define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -#endif -#ifndef LV_MEM_CUSTOM_ALLOC # define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ -#endif -#ifndef LV_MEM_CUSTOM_FREE # define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ -#endif #endif /*LV_MEM_CUSTOM*/ /* Garbage Collector settings * Used if lvgl is binded to higher level language and the memory is managed by that language */ -#ifndef LV_ENABLE_GC #define LV_ENABLE_GC 0 -#endif #if LV_ENABLE_GC != 0 -#ifndef LV_GC_INCLUDE # define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -#endif -#ifndef LV_MEM_CUSTOM_REALLOC # define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/ -#endif -#ifndef LV_MEM_CUSTOM_GET_SIZE # define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/ -#endif #endif /* LV_ENABLE_GC */ /*======================= @@ -144,89 +106,66 @@ * Can be changed in the Input device driver (`lv_indev_drv_t`)*/ /* Input device read period in milliseconds */ -#ifndef LV_INDEV_DEF_READ_PERIOD #define LV_INDEV_DEF_READ_PERIOD 30 -#endif /* Drag threshold in pixels */ -#ifndef LV_INDEV_DEF_DRAG_LIMIT #define LV_INDEV_DEF_DRAG_LIMIT 10 -#endif /* Drag throw slow-down in [%]. Greater value -> faster slow-down */ -#ifndef LV_INDEV_DEF_DRAG_THROW #define LV_INDEV_DEF_DRAG_THROW 20 -#endif /* Long press time in milliseconds. * Time to send `LV_EVENT_LONG_PRESSSED`) */ -#ifndef LV_INDEV_DEF_LONG_PRESS_TIME #define LV_INDEV_DEF_LONG_PRESS_TIME 400 -#endif /* Repeated trigger period in long press [ms] * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ -#ifndef LV_INDEV_DEF_LONG_PRESS_REP_TIME #define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 -#endif /*================== * Feature usage *==================*/ /*1: Enable the Animations */ -#ifndef LV_USE_ANIMATION #define LV_USE_ANIMATION 1 -#endif #if LV_USE_ANIMATION /*Declare the type of the user data of animations (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_anim_user_data_t; #endif /* 1: Enable shadow drawing*/ -#ifndef LV_USE_SHADOW #define LV_USE_SHADOW 1 -#endif /* 1: Enable object groups (for keyboard/encoder navigation) */ -#ifndef LV_USE_GROUP #define LV_USE_GROUP 1 -#endif #if LV_USE_GROUP +typedef void * lv_group_user_data_t; #endif /*LV_USE_GROUP*/ /* 1: Enable GPU interface*/ -#ifndef LV_USE_GPU #define LV_USE_GPU 1 -#endif /* 1: Enable file system (might be required for images */ -#ifndef LV_USE_FILESYSTEM #define LV_USE_FILESYSTEM 1 -#endif #if LV_USE_FILESYSTEM /*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_fs_drv_user_data_t; #endif /*1: Add a `user_data` to drivers and objects*/ -#ifndef LV_USE_USER_DATA -#define LV_USE_USER_DATA 0 -#endif +#define LV_USE_USER_DATA 1 /*======================== * Image decoder and cache *========================*/ /* 1: Enable indexed (palette) images */ -#ifndef LV_IMG_CF_INDEXED #define LV_IMG_CF_INDEXED 1 -#endif /* 1: Enable alpha indexed images */ -#ifndef LV_IMG_CF_ALPHA #define LV_IMG_CF_ALPHA 1 -#endif /* Default image cache size. Image caching keeps the images opened. * If only the built-in image formats are used there is no real advantage of caching. @@ -234,37 +173,28 @@ * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. * However the opened images might consume additional RAM. * LV_IMG_CACHE_DEF_SIZE must be >= 1 */ -#ifndef LV_IMG_CACHE_DEF_SIZE #define LV_IMG_CACHE_DEF_SIZE 1 -#endif /*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_img_decoder_user_data_t; /*===================== * Compiler settings *====================*/ /* Define a custom attribute to `lv_tick_inc` function */ -#ifndef LV_ATTRIBUTE_TICK_INC #define LV_ATTRIBUTE_TICK_INC -#endif /* Define a custom attribute to `lv_task_handler` function */ -#ifndef LV_ATTRIBUTE_TASK_HANDLER #define LV_ATTRIBUTE_TASK_HANDLER -#endif /* With size optimization (-Os) the compiler might not align data to * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. * E.g. __attribute__((aligned(4))) */ -#ifndef LV_ATTRIBUTE_MEM_ALIGN #define LV_ATTRIBUTE_MEM_ALIGN -#endif /* Attribute to mark large constant arrays for example * font's bitmaps */ -#ifndef LV_ATTRIBUTE_LARGE_CONST #define LV_ATTRIBUTE_LARGE_CONST -#endif /* Export integer constant to binding. * This macro is used with constants in the form of LV_ that @@ -272,9 +202,7 @@ * * The default value just prevents a GCC warning. */ -#ifndef LV_EXPORT_CONST_INT #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning -#endif /*=================== * HAL settings @@ -282,27 +210,21 @@ /* 1: use a custom tick source. * It removes the need to manually update the tick with `lv_tick_inc`) */ -#ifndef LV_TICK_CUSTOM -#define LV_TICK_CUSTOM 0 -#endif +#define LV_TICK_CUSTOM 1 #if LV_TICK_CUSTOM == 1 -#ifndef LV_TICK_CUSTOM_INCLUDE -#define LV_TICK_CUSTOM_INCLUDE "something.h" /*Header for the sys time function*/ -#endif -#ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR +#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the sys time function*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current systime in ms*/ -#endif #endif /*LV_TICK_CUSTOM*/ +typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/ +typedef void * lv_indev_drv_user_data_t; /*Type of user data in the input device driver*/ /*================ * Log settings *===============*/ /*1: Enable the log module*/ -#ifndef LV_USE_LOG #define LV_USE_LOG 0 -#endif #if LV_USE_LOG /* How important log should be added: * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information @@ -311,15 +233,11 @@ * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail * LV_LOG_LEVEL_NONE Do not log anything */ -#ifndef LV_LOG_LEVEL # define LV_LOG_LEVEL LV_LOG_LEVEL_WARN -#endif /* 1: Print the log with 'printf'; * 0: user need to register a callback with `lv_log_register_print_cb`*/ -#ifndef LV_LOG_PRINTF # define LV_LOG_PRINTF 0 -#endif #endif /*LV_USE_LOG*/ /*================= @@ -335,72 +253,42 @@ * The behavior of asserts can be overwritten by redefining them here. * E.g. #define LV_ASSERT_MEM(p) */ -#ifndef LV_USE_DEBUG #define LV_USE_DEBUG 1 -#endif #if LV_USE_DEBUG /*Check if the parameter is NULL. (Quite fast) */ -#ifndef LV_USE_ASSERT_NULL #define LV_USE_ASSERT_NULL 1 -#endif /*Checks is the memory is successfully allocated or no. (Quite fast)*/ -#ifndef LV_USE_ASSERT_MEM #define LV_USE_ASSERT_MEM 1 -#endif /* Check the strings. * Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow) * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ -#ifndef LV_USE_ASSERT_STR #define LV_USE_ASSERT_STR 0 -#endif /* Check NULL, the object's type and existence (e.g. not deleted). (Quite slow) * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ -#ifndef LV_USE_ASSERT_OBJ #define LV_USE_ASSERT_OBJ 0 -#endif /*Check if the styles are properly initialized. (Fast)*/ -#ifndef LV_USE_ASSERT_STYLE #define LV_USE_ASSERT_STYLE 1 -#endif #endif /*LV_USE_DEBUG*/ /*================ * THEME USAGE *================*/ -#ifndef LV_THEME_LIVE_UPDATE #define LV_THEME_LIVE_UPDATE 0 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ -#endif -#ifndef LV_USE_THEME_TEMPL #define LV_USE_THEME_TEMPL 0 /*Just for test*/ -#endif -#ifndef LV_USE_THEME_DEFAULT #define LV_USE_THEME_DEFAULT 0 /*Built mainly from the built-in styles. Consumes very few RAM*/ -#endif -#ifndef LV_USE_THEME_ALIEN #define LV_USE_THEME_ALIEN 0 /*Dark futuristic theme*/ -#endif -#ifndef LV_USE_THEME_NIGHT #define LV_USE_THEME_NIGHT 0 /*Dark elegant theme*/ -#endif -#ifndef LV_USE_THEME_MONO #define LV_USE_THEME_MONO 0 /*Mono color theme for monochrome displays*/ -#endif -#ifndef LV_USE_THEME_MATERIAL #define LV_USE_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/ -#endif -#ifndef LV_USE_THEME_ZEN #define LV_USE_THEME_ZEN 0 /*Peaceful, mainly light theme */ -#endif -#ifndef LV_USE_THEME_NEMO #define LV_USE_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/ -#endif /*================== * FONT USAGE @@ -414,32 +302,18 @@ /* Robot fonts with bpp = 4 * https://fonts.google.com/specimen/Roboto */ -#ifndef LV_FONT_ROBOTO_12 #define LV_FONT_ROBOTO_12 0 -#endif -#ifndef LV_FONT_ROBOTO_16 #define LV_FONT_ROBOTO_16 1 -#endif -#ifndef LV_FONT_ROBOTO_22 #define LV_FONT_ROBOTO_22 0 -#endif -#ifndef LV_FONT_ROBOTO_28 #define LV_FONT_ROBOTO_28 0 -#endif /* Demonstrate special features */ -#ifndef LV_FONT_ROBOTO_12_SUBPX #define LV_FONT_ROBOTO_12_SUBPX 1 -#endif -#ifndef LV_FONT_ROBOTO_28_COMPRESSED #define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/ -#endif /*Pixel perfect monospace font * http://pelulamu.net/unscii/ */ -#ifndef LV_FONT_UNSCII_8 #define LV_FONT_UNSCII_8 0 -#endif /* Optionally declare your custom fonts here. * You can use these fonts as default font too @@ -447,31 +321,24 @@ * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \ * LV_FONT_DECLARE(my_font_2) */ -#ifndef LV_FONT_CUSTOM_DECLARE #define LV_FONT_CUSTOM_DECLARE -#endif /*Always set a default font from the built-in fonts*/ -#ifndef LV_FONT_DEFAULT #define LV_FONT_DEFAULT &lv_font_roboto_16 -#endif /* Enable it if you have fonts with a lot of characters. * The limit depends on the font size, font face and bpp * but with > 10,000 characters if you see issues probably you need to enable it.*/ -#ifndef LV_FONT_FMT_TXT_LARGE #define LV_FONT_FMT_TXT_LARGE 0 -#endif /* Set the pixel order of the display. * Important only if "subpx fonts" are used. * With "normal" font it doesn't matter. */ -#ifndef LV_FONT_SUBPX_BGR #define LV_FONT_SUBPX_BGR 0 -#endif /*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_font_user_data_t; /*================= * Text settings @@ -482,69 +349,45 @@ * - LV_TXT_ENC_UTF8 * - LV_TXT_ENC_ASCII * */ -#ifndef LV_TXT_ENC #define LV_TXT_ENC LV_TXT_ENC_UTF8 -#endif /*Can break (wrap) texts on these chars*/ -#ifndef LV_TXT_BREAK_CHARS #define LV_TXT_BREAK_CHARS " ,.;:-_" -#endif /* If a word is at least this long, will break wherever "prettiest" * To disable, set to a value <= 0 */ -#ifndef LV_TXT_LINE_BREAK_LONG_LEN #define LV_TXT_LINE_BREAK_LONG_LEN 12 -#endif /* Minimum number of characters in a long word to put on a line before a break. * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ -#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 -#endif /* Minimum number of characters in a long word to put on a line after a break. * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ -#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 -#endif /* The control character to use for signalling text recoloring. */ -#ifndef LV_TXT_COLOR_CMD #define LV_TXT_COLOR_CMD "#" -#endif /* Support bidirectional texts. * Allows mixing Left-to-Right and Right-to-Left texts. * The direction will be processed according to the Unicode Bidirectioanl Algorithm: * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ -#ifndef LV_USE_BIDI #define LV_USE_BIDI 0 -#endif #if LV_USE_BIDI /* Set the default direction. Supported values: * `LV_BIDI_DIR_LTR` Left-to-Right * `LV_BIDI_DIR_RTL` Right-to-Left * `LV_BIDI_DIR_AUTO` detect texts base direction */ -#ifndef LV_BIDI_BASE_DIR_DEF #define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO #endif -#endif /*Change the built in (v)snprintf functions*/ -#ifndef LV_SPRINTF_CUSTOM #define LV_SPRINTF_CUSTOM 0 -#endif #if LV_SPRINTF_CUSTOM -#ifndef LV_SPRINTF_INCLUDE # define LV_SPRINTF_INCLUDE -#endif -#ifndef lv_snprintf # define lv_snprintf snprintf -#endif -#ifndef lv_vsnprintf # define lv_vsnprintf vsnprintf -#endif #endif /*LV_SPRINTF_CUSTOM*/ /*=================== @@ -552,20 +395,17 @@ *==================*/ /*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_obj_user_data_t; /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ -#ifndef LV_USE_OBJ_REALIGN #define LV_USE_OBJ_REALIGN 1 -#endif /* Enable to make the object clickable on a larger area. * LV_EXT_CLICK_AREA_OFF or 0: Disable this feature * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) */ -#ifndef LV_USE_EXT_CLICK_AREA #define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_OFF -#endif /*================== * LV OBJ X USAGE @@ -575,277 +415,177 @@ */ /*Arc (dependencies: -)*/ -#ifndef LV_USE_ARC #define LV_USE_ARC 1 -#endif /*Bar (dependencies: -)*/ -#ifndef LV_USE_BAR #define LV_USE_BAR 1 -#endif /*Button (dependencies: lv_cont*/ -#ifndef LV_USE_BTN #define LV_USE_BTN 1 -#endif #if LV_USE_BTN != 0 /*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/ -#ifndef LV_BTN_INK_EFFECT -# define LV_BTN_INK_EFFECT 0 -#endif +# define LV_BTN_INK_EFFECT 1 #endif /*Button matrix (dependencies: -)*/ -#ifndef LV_USE_BTNM #define LV_USE_BTNM 1 -#endif /*Calendar (dependencies: -)*/ -#ifndef LV_USE_CALENDAR #define LV_USE_CALENDAR 1 -#endif /*Canvas (dependencies: lv_img)*/ -#ifndef LV_USE_CANVAS #define LV_USE_CANVAS 1 -#endif /*Check box (dependencies: lv_btn, lv_label)*/ -#ifndef LV_USE_CB #define LV_USE_CB 1 -#endif /*Chart (dependencies: -)*/ -#ifndef LV_USE_CHART #define LV_USE_CHART 1 -#endif #if LV_USE_CHART -#ifndef LV_CHART_AXIS_TICK_LABEL_MAX_LEN # define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20 #endif -#endif /*Container (dependencies: -*/ -#ifndef LV_USE_CONT #define LV_USE_CONT 1 -#endif /*Color picker (dependencies: -*/ -#ifndef LV_USE_CPICKER #define LV_USE_CPICKER 1 -#endif /*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ -#ifndef LV_USE_DDLIST #define LV_USE_DDLIST 1 -#endif #if LV_USE_DDLIST != 0 /*Open and close default animation time [ms] (0: no animation)*/ -#ifndef LV_DDLIST_DEF_ANIM_TIME # define LV_DDLIST_DEF_ANIM_TIME 200 #endif -#endif /*Gauge (dependencies:lv_bar, lv_lmeter)*/ -#ifndef LV_USE_GAUGE #define LV_USE_GAUGE 1 -#endif /*Image (dependencies: lv_label*/ -#ifndef LV_USE_IMG #define LV_USE_IMG 1 -#endif /*Image Button (dependencies: lv_btn*/ -#ifndef LV_USE_IMGBTN #define LV_USE_IMGBTN 1 -#endif #if LV_USE_IMGBTN /*1: The imgbtn requires left, mid and right parts and the width can be set freely*/ -#ifndef LV_IMGBTN_TILED # define LV_IMGBTN_TILED 0 #endif -#endif /*Keyboard (dependencies: lv_btnm)*/ -#ifndef LV_USE_KB #define LV_USE_KB 1 -#endif /*Label (dependencies: -*/ -#ifndef LV_USE_LABEL #define LV_USE_LABEL 1 -#endif #if LV_USE_LABEL != 0 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ -#ifndef LV_LABEL_DEF_SCROLL_SPEED # define LV_LABEL_DEF_SCROLL_SPEED 25 -#endif /* Waiting period at beginning/end of animation cycle */ -#ifndef LV_LABEL_WAIT_CHAR_COUNT # define LV_LABEL_WAIT_CHAR_COUNT 3 -#endif /*Enable selecting text of the label */ -#ifndef LV_LABEL_TEXT_SEL # define LV_LABEL_TEXT_SEL 0 -#endif /*Store extra some info in labels (12 bytes) to speed up drawing of very long texts*/ -#ifndef LV_LABEL_LONG_TXT_HINT # define LV_LABEL_LONG_TXT_HINT 0 #endif -#endif /*LED (dependencies: -)*/ -#ifndef LV_USE_LED #define LV_USE_LED 1 -#endif /*Line (dependencies: -*/ -#ifndef LV_USE_LINE #define LV_USE_LINE 1 -#endif /*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/ -#ifndef LV_USE_LIST #define LV_USE_LIST 1 -#endif #if LV_USE_LIST != 0 /*Default animation time of focusing to a list element [ms] (0: no animation) */ -#ifndef LV_LIST_DEF_ANIM_TIME # define LV_LIST_DEF_ANIM_TIME 100 #endif -#endif /*Line meter (dependencies: *;)*/ -#ifndef LV_USE_LMETER #define LV_USE_LMETER 1 -#endif /*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ -#ifndef LV_USE_MBOX #define LV_USE_MBOX 1 -#endif /*Page (dependencies: lv_cont)*/ -#ifndef LV_USE_PAGE #define LV_USE_PAGE 1 -#endif #if LV_USE_PAGE != 0 /*Focus default animation time [ms] (0: no animation)*/ -#ifndef LV_PAGE_DEF_ANIM_TIME # define LV_PAGE_DEF_ANIM_TIME 400 #endif -#endif /*Preload (dependencies: lv_arc, lv_anim)*/ -#ifndef LV_USE_PRELOAD #define LV_USE_PRELOAD 1 -#endif #if LV_USE_PRELOAD != 0 -#ifndef LV_PRELOAD_DEF_ARC_LENGTH # define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ -#endif -#ifndef LV_PRELOAD_DEF_SPIN_TIME # define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ -#endif -#ifndef LV_PRELOAD_DEF_ANIM # define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC #endif -#endif /*Roller (dependencies: lv_ddlist)*/ -#ifndef LV_USE_ROLLER #define LV_USE_ROLLER 1 -#endif #if LV_USE_ROLLER != 0 /*Focus animation time [ms] (0: no animation)*/ -#ifndef LV_ROLLER_DEF_ANIM_TIME # define LV_ROLLER_DEF_ANIM_TIME 200 -#endif /*Number of extra "pages" when the roller is infinite*/ -#ifndef LV_ROLLER_INF_PAGES # define LV_ROLLER_INF_PAGES 7 #endif -#endif /*Slider (dependencies: lv_bar)*/ -#ifndef LV_USE_SLIDER #define LV_USE_SLIDER 1 -#endif /*Spinbox (dependencies: lv_ta)*/ -#ifndef LV_USE_SPINBOX #define LV_USE_SPINBOX 1 -#endif /*Switch (dependencies: lv_slider)*/ -#ifndef LV_USE_SW #define LV_USE_SW 1 -#endif /*Text area (dependencies: lv_label, lv_page)*/ -#ifndef LV_USE_TA #define LV_USE_TA 1 -#endif #if LV_USE_TA != 0 -#ifndef LV_TA_DEF_CURSOR_BLINK_TIME # define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ -#endif -#ifndef LV_TA_DEF_PWD_SHOW_TIME # define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/ #endif -#endif /*Table (dependencies: lv_label)*/ -#ifndef LV_USE_TABLE #define LV_USE_TABLE 1 -#endif #if LV_USE_TABLE -#ifndef LV_TABLE_COL_MAX # define LV_TABLE_COL_MAX 12 #endif -#endif /*Tab (dependencies: lv_page, lv_btnm)*/ -#ifndef LV_USE_TABVIEW #define LV_USE_TABVIEW 1 -#endif # if LV_USE_TABVIEW != 0 /*Time of slide animation [ms] (0: no animation)*/ -#ifndef LV_TABVIEW_DEF_ANIM_TIME # define LV_TABVIEW_DEF_ANIM_TIME 300 #endif -#endif /*Tileview (dependencies: lv_page) */ -#ifndef LV_USE_TILEVIEW #define LV_USE_TILEVIEW 1 -#endif #if LV_USE_TILEVIEW /*Time of slide animation [ms] (0: no animation)*/ -#ifndef LV_TILEVIEW_DEF_ANIM_TIME # define LV_TILEVIEW_DEF_ANIM_TIME 300 #endif -#endif /*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ -#ifndef LV_USE_WIN #define LV_USE_WIN 1 -#endif /*================== * Non-user section *==================*/ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/ -#ifndef _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS #endif -#endif +/*--END OF LV_CONF_H--*/ + +/*Be sure every define has a default value*/ +#include "src/lv_conf_checker.h" + +#endif /*LV_CONF_H*/ -#endif /*LV_CONF_CHECKER_H*/ +#endif /*End of "Content enable"*/ diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md new file mode 100644 index 0000000..4e78c7b --- /dev/null +++ b/src/CHANGELOG.md @@ -0,0 +1,124 @@ +# Changelog + +## v7.0.1 (under development) +*Available in the `master` branch* + +### Bugfixes +- Make the Microptyhon working by adding the required variables as GC_ROOT +- Fix built-in SimSun CJK font +- Fix UTF-8 encoding when `LV_USE_ARABIC_PERSIAN_CHARS` is enabled +- Fix DMA2D usage when 32 bit images directly blended +- Fix lv_roller in infinite mode when used with encoder +- Add `lv_theme_get_color_secondary()` +- Add `LV_COLOR_MIX_ROUND_OFS` to adjust color mixing to make it compatible with the GPU +- Improve DMA2D blending +- Remove memcpy from `lv_ll` (caused issues with some optimization settings) +- `lv_chart` fix X tick drawing +- fix vertical dashed line drawing +- some additonal minor fixes and formattings + +## v7.0.0 (18.05.2020) + +### Documentation +The docs for v7 is available at https://docs.littlevgl.com/v7/en/html/index.html + +### Legal changes + +The name of the project is changed to LVGL and the new website is on https://lvgl.io + +LVGL remains free under the same conditions (MIT license) and a company is created to manage LVGL and offer services. + + +### New drawing system +Complete rework of LVGL's draw engine to use "masks" for more advanced and higher quality graphical effects. +A possible use-case of this system is to remove the overflowing content from the rounded edges. +It also allows drawing perfectly anti-aliased circles, lines, and arcs. +Internally, the drawings happen by defining masks (such as rounded rectangle, line, angle). +When something is drawn the currently active masks can make some pixels transparent. +For example, rectangle borders are drawn by using 2 rectangle masks: one mask removes the inner part and another the outer part. + +The API in this regard remained the same but some new functions were added: +- `lv_img_set_zoom`: set image object's zoom factor +- `lv_img_set_angle`: set image object's angle without using canvas +- `lv_img_set_pivot`: set the pivot point of rotation + + +The new drawing engine brought new drawing features too. They are highlighted in the "style" section. + +### New style system +The old style system is replaced with a new more flexible and lightweighted one. +It uses an approach similar to CSS: support cascading styles, inheriting properties and local style properties per object. +As part of these updates, a lot of objects were reworked and the APIs have been changed. + +- more shadows options: *offset* and *spread* +- gradient stop position to shift the gradient area and horizontal gradient +- `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE` blending modes +- *clip corner*: crop the content on the rounded corners +- *text underline* and *strikethrough* +- dashed vertical and horizontal lines (*dash gap*, *dash_width*) +- *outline*: a border-like part drawn out of the background. Can have spacing to the background. +- *pattern*: display and image in the middle of the background or repeat it +- *value* display a text which is stored in the style. It can be used e.g. as a lighweighted text on buttons too. +- *margin*: similar to *padding* but used to keep space outside of the object + +Read the [Style](https://docs.littlevgl.com/v7/en/html/overview/style.html) section of the documentation to learn how the new styles system works. + +### GPU integration +To better utilize GPUs, from this version GPU usage can be integrated into LVGL. In `lv_conf.h` any supported GPUs can be enabled with a single configuration option. + +Right now, only ST's DMA2D (Chrom-ART) is integrated. More will in the upcoming releases. + +### Renames +The following object types are renamed: +- sw -> switch +- ta -> textarea +- cb -> checkbox +- lmeter -> linemeter +- mbox -> msgbox +- ddlist -> dropdown +- btnm -> btnmatrix +- kb -> keyboard +- preload -> spinner +- lv_objx folder -> lv_widgets +- LV_FIT_FILL -> LV_FIT_PARENT +- LV_FIT_FLOOD -> LV_FLOOD_MAX +- LV_LAYOUT_COL_L/M/R -> LV_LAYOUT_COLUMN_LEFT/MID/RIGHT +- LV_LAYOUT_ROW_T/M/B -> LV_LAYOUT_ROW_TOP/MID/BOTTOM + +### Reworked and improved object +- `dropdown`: Completely reworked. Now creates a separate list when opened and can be dropped to down/up/left/right. +- `label`: `body_draw` is removed, instead, if its style has a visible background/border/shadow etc it will be drawn. Padding really makes the object larger (not just virtually as before) +- `arc`: can draw bacground too. +- `btn`: doesn't store styles for each state because it's done naturally in the new style system. +- `calendar`: highlight the pressed datum. The used styles are changed: use `LV_CALENDAR_PART_DATE` normal for normal dates, checked for highlighted, focused for today, pressed for the being pressed. (checked+pressed, focused+pressed also work) +- `chart`: only has `LINE` and `COLUMN` types because with new styles all the others can be described. LV_CHART_PART_SERIES sets the style of the series. bg_opa > 0 draws an area in LINE mode. `LV_CHART_PART_SERIES_BG` also added to set a different style for the series area. Padding in `LV_CHART_PART_BG` makes the series area smaller, and it ensures space for axis labels/numbers. +- `linemeter`, `gauge`: can have background if the related style properties are set. Padding makes the scale/lines smaller. scale_border_width and scale_end_border_width allow to draw an arc on the outer part of the scale lines. +- `gauge`: `lv_gauge_set_needle_img` allows use image as needle +- `canvas`: allow drawing to true color alpha and alpha only canvas, add `lv_canvas_blur_hor/ver` and rename `lv_canvas_rotate` to `lv_canvas_transform` +- `textarea`: If available in the font use bullet (`U+2022`) character in text area password + +### New object types +- `lv_objmask`: masks can be added to it. The children will be masked accordingly. + +### Others +- Change the built-in fonts to [Montserrat](https://fonts.google.com/specimen/Montserrat) and add built-in fonts from 12 px to 48 px for every 2nd size. +- Add example CJK and Arabic/Persian/Hebrew built-in font +- Add ° and "bullet" to the built-in fonts +- Add Arabic/Persian script support: change the character according to its position in the text. +- Add `playback_time` to animations. +- Add `repeat_count` to animations instead of the current "repeat forever". +- Replace `LV_LAYOUT_PRETTY` with `LV_LAYOUT_PRETTY_TOP/MID/BOTTOM` + +### Demos +- [lv_examples](https://github.com/littlevgl/lv_examples) was reworked and new examples and demos were added + +### New release policy +- Maintain this Changelog for every release +- Save old major version in new branches. E.g. `release/v6` +- Merge new features and fixes directly into `master` and release a patch or minor releases every 2 weeks. + +### Migrating from v6 to v7 +- First and foremost, create a new `lv_conf.h` based on `lv_conf_templ.h`. +- To try the new version it suggested using a simulator project and see the examples. +- If you have a running project, the most difficult part of the migration is updating to the new style system. Unfortunately, there is no better way than manually updating to the new format. +- The other parts are mainly minor renames and refactoring as described above. diff --git a/src/LICENCE.txt b/src/LICENCE.txt index beaef1d..a6f7f80 100644 --- a/src/LICENCE.txt +++ b/src/LICENCE.txt @@ -1,5 +1,5 @@ MIT licence -Copyright (c) 2016 Gábor Kiss-Vámosi +Copyright (c) 2020 LVGL LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/README.md b/src/README.md index 9d17088..bee23cb 100644 --- a/src/README.md +++ b/src/README.md @@ -1,24 +1,23 @@ -

LittlevGL - Open-source Embedded GUI Library

+

LVGL - Little and Versatile Graphics Library

- - + +

- +

-LittlevGL provides everything you need to create a Graphical User Interface (GUI) on embedded systems with easy-to-use graphical elements, beautiful visual effects and low memory footprint. +LVGL provides everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint.

-Website · -Live demo · -Simulator · -Forum · -Docs · -Blog +Website · +Live demo · +Docs · +Forum · +Blog

--- @@ -26,11 +25,10 @@ LittlevGL provides everything you need to create a Graphical User Interface (GUI - [Features](#features) - [Supported devices](#supported-devices) - [Quick start in a simulator](#quick-start-in-a-simulator) -- [Add LittlevGL to your project](#add-littlevgl-to-your-project) +- [Add LVGL to your project](#add-lvgl-to-your-project) - [Learn the basics](#learn-the-basics) - [Examples](#examples) - [Contributing](#contributing) -- [Donate](#donate) ## Features @@ -38,66 +36,66 @@ LittlevGL provides everything you need to create a Graphical User Interface (GUI * **Advanced graphics** with animations, anti-aliasing, opacity, smooth scrolling * **Simultaneously use various input devices** touchscreen, mouse, keyboard, encoder, buttons, etc. * **Simultaneously use multiple displays** i.e. monochrome and color display -* **Multi-language support** with UTF-8 encoding +* **Multi-language support** with UTF-8 encoding, Bidirectional support, and Arabic text handling * **Fully customizable** graphical elements * **Hardware independent** to use with any microcontroller or display * **Scalable** to operate with little memory (64 kB Flash, 10 kB RAM) * **OS, External memory and GPU** supported but not required * **Single frame buffer** operation even with advances graphical effects -* **Written in C** for maximal compatibility -* **Micropython Binding** exposes [LittlevGL API in Micropython](https://blog.littlevgl.com/2019-02-20/micropython-bindings) +* **Written in C** for maximal compatibility (C++ compatible) +* **Micropython Binding** exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) * **Simulator** to develop on PC without embedded hardware * **Tutorials, examples, themes** for rapid development * **Documentation** and API references ## Supported devices -Basically, every modern controller - which is able to drive a display - is suitable to run LittlevGL. The minimal requirements: +Basically, every modern controller (which is able to drive a display( is suitable to run LVGL. The minimal requirements are: - 16, 32 or 64 bit microcontroller or processor - > 16 MHz clock speed is recommended - Flash/ROM: > 64 kB for the very essential components (> 180 kB is recommended) - RAM: - - Static RAM usage: ~8..16 kB depending on the used features and objects types - - Stack: > 2kB (> 4 kB is recommended) - - Dynamic data (heap): > 4 KB (> 16 kB is recommended if using several objects). + - Static RAM usage: ~2 kB depending on the used features and objects types + - Stack: > 2kB (> 8 kB is recommended) + - Dynamic data (heap): > 2 KB (> 16 kB is recommended if using several objects). Set by `LV_MEM_SIZE` in *lv_conf.h*. - Display buffer: > *"Horizontal resolution"* pixels (> 10 × *"Horizontal resolution"* is recommended) -- C99 or newer compiler +- C99 or newer compiler *Note that the memory usage might vary depending on the architecture, compiler and build options.* Just to mention some **platforms**: -- STM32F1, STM32F3, [STM32F4](https://blog.littlevgl.com/2017-07-15/stm32f429_disco_port), [STM32F7](https://github.com/littlevgl/stm32f746_disco_no_os_sw4stm32) +- STM32F1, STM32F3, [STM32F4](https://blog.lvgl.io/2017-07-15/stm32f429_disco_port), [STM32F7](https://github.com/lvgl/lv_port_stm32f746_disco_sw4stm32) - Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ - NXP Kinetis, LPC, iMX -- [Linux frame buffer](https://blog.littlevgl.com/2018-01-03/linux_fb) (/dev/fb) +- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) - [Raspberry PI](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) -- [Espressif ESP32](https://github.com/littlevgl/esp32_ili9431) +- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) - Nordic nrf52 - Quectell M66 ## Quick start in a simulator -The easiest way to get started with LittlevGL is to run it in a simulator on your PC without any embedded hardware. +The easiest way to get started with LVGL is to run it in a simulator on your PC without any embedded hardware. Choose a project with your favourite IDE: | Eclipse | CodeBlocks | Visual Studio | PlatformIO | Qt Creator | |-------------|-------------|---------------|-----------|------------| -| [![Eclipse](https://littlevgl.com/logo/ide/eclipse.jpg)](https://github.com/littlevgl/pc_simulator_sdl_eclipse) | [![CodeBlocks](https://littlevgl.com/logo/ide/codeblocks.jpg)](https://github.com/littlevgl/pc_simulator_win_codeblocks) | [![VisualStudio](https://littlevgl.com/logo/ide/visualstudio.jpg)](https://github.com/littlevgl/visual_studio_2017_sdl_x64) | [![PlatformIO](https://littlevgl.com/logo/ide/platformio.jpg)](https://github.com/littlevgl/pc_simulator_sdl_platformio) | [![QtCreator](https://littlevgl.com/logo/ide/qtcreator.jpg)](https://blog.littlevgl.com/2019-01-03/qt-creator) | +| [![Eclipse](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//eclipse.jpg)](https://github.com/lvgl/lv_sim_eclipse_sdl) | [![CodeBlocks](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//codeblocks.jpg)](https://github.com/lvgl/lv_sim_codeblocks_win) | [![VisualStudio](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//visualstudio.jpg)](https://github.com/lvgl/lv_sim_visual_studio_sdl) | [![PlatformIO](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//platformio.jpg)](https://github.com/lvgl/lv_platformio) | [![QtCreator](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//qtcreator.jpg)](https://blog.lvgl.io/2019-01-03/qt-creator) | | Cross-platform
with SDL
(Recommended on
Linux and Mac) | Native Windows | Windows
with SDL | Cross-platform
with SDL | Cross-platform
with SDL | -## Add LittlevGL to your project +## Add LVGL to your project -The steps below show how to setup LittlevGL on an embedded system with a display and a touchpad. -You can use the [Simulators](https://docs.littlevgl.com/en/html/get-started/pc-simulator) to get ready to use projects which can be run on your PC. +The steps below show how to setup LVGL on an embedded system with a display and a touchpad. +You can use the [Simulators](https://docs.lvgl.io/v7/en/html/get-started/pc-simulator) to get ready to use projects which can be run on your PC. -1. [Download](https://littlevgl.com/download) or [Clone](https://github.com/littlevgl/lvgl) the library +1. [Download](https://lvgl.com/developers) or [Clone](https://github.com/lvgl/lvgl) the library 2. Copy the `lvgl` folder into your project -3. Copy `lvgl/lv_conf_template.h` as `lv_conf.h` next to the `lvgl` folder and set at least `LV_HOR_RES_MAX`, `LV_VER_RES_MAX` and `LV_COLOR_DEPTH`. -4. Include `lvgl/lvgl.h` where you need to use LittlevGL related functions. -5. Call `lv_tick_inc(x)` every `x` milliseconds **in a Timer or Task** (`x` should be between 1 and 10). It is required for the internal timing of LittlevGL. +3. Copy `lvgl/lv_conf_template.h` as `lv_conf.h` next to the `lvgl` folder and set at least `LV_HOR_RES_MAX`, `LV_VER_RES_MAX` and `LV_COLOR_DEPTH`. Don't forget to **change the `#if 0` statement near the top of the file to `#if 1`**, otherwise you will get compilation errors. +4. Include `lvgl/lvgl.h` where you need to use LVGL related functions. +5. Call `lv_tick_inc(x)` every `x` milliseconds **in a Timer or Task** (`x` should be between 1 and 10). It is required for the internal timing of LVGL. 6. Call `lv_init()` -7. Create a display buffer for LittlevGL +7. Create a display buffer for LVGL ```c static lv_disp_buf_t disp_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; /*Declare a buffer for 10 lines*/ @@ -154,16 +152,18 @@ It will redraw the screen if required, handle input devices etc. ## Learn the basics -### Objects (Widgets) +In this section you can ready the very basics. For a more detailed guide check the [Quick overview](https://docs.lvgl.io/v7/en/html/get-started/quick-overview.html#learn-the-basics) in the documentation. -The graphical elements like Buttons, Labels, Sliders, Charts etc are called objects in LittelvGL. Go to [Object types](https://docs.littlevgl.com/en/html/object-types/index) to see the full list of available types. +### Widgets (Objects) + +The graphical elements like Buttons, Labels, Sliders, Charts etc are called objects in LittelvGL. Go to [Object types](https://docs.lvgl.io/v7/en/html/widgets/index) to see the full list of available types. Every object has a parent object. The child object moves with the parent and if you delete the parent the children will be deleted too. Children can be visible only on their parent. The *screen* are the "root" parents. To get the current screen call `lv_scr_act()`. You can create a new object with `lv__create(parent, obj_to_copy)`. It will return an `lv_obj_t *` variable which should be used as a reference to the object to set its parameters. -The first parameter is the desired *parent*, te second parameters can be an object to copy (`NULL` is unused). +The first parameter is the desired *parent*, the second parameters can be an object to copy (`NULL` if unused). For example: ```c lv_obj_t * slider1 = lv_slider_create(lv_scr_act(), NULL); @@ -184,30 +184,27 @@ lv_slider_set_value(slider1, 70, LV_ANIM_ON); To see the full API visit the documentation of the object types or the related header file (e.g. `lvgl/src/lv_objx/lv_slider.h`). ### Styles -Styles can be assigned to the objects to changed their appearance. A style describes the appearance of rectangle-like objects (like a button or slider), texts, images and lines at once. - -You can create a new style like this: +Widgets are created with a default appearance but it can be changed by adding new styles to the object. A new style can be created like this: ```c -static lv_style_t style1; /*Declare a new style. Should be `static`*/ -lv_style_copy(&style1, &lv_style_plain); /*Copy a built-in style*/ -style1.body.main_color = LV_COLOR_RED; /*Main color*/ -style1.body.grad_color = lv_color_hex(0xffd83c) /*Gradient color (orange)*/ -style1.body.radius = 3; -style1.text.color = lv_color_hex3(0x0F0) /*Label color (green)*/ -style1.text.font = &lv_font_dejavu_22; /*Change font*/ -... +static lv_style_t style1; /*Should be static, global or dynamically allocated*/ +lv_style_init(&style1); +lv_style_set_bg_color(&style1, LV_STATE_DEFAULT, LV_COLOR_RED); /*Default background color*/ +lv_style_set_bg_color(&style1, LV_STATE_PRESSED, LV_COLOR_BLUE); /*Pressed background color*/ ``` -To set a new style for an object use the `lv_set_style(obj, LV__STYLE_, &my_style)` functions. For example: -```c -lv_slider_set_style(slider1, LV_SLIDER_STYLE_BG, &slider_bg_style); -lv_slider_set_style(slider1, LV_SLIDER_STYLE_INDIC, &slider_indic_style); -lv_slider_set_style(slider1, LV_SLIDER_STYLE_KNOB, &slider_knob_style); +The wigedt have *parts* which can be referenced via `LV__PART_`. E.g. `LV_BRN_PART_MAIN` or `LV_SLIDER_PART_KNOB`. See the documentation of the widgets to see the exisitng parts. + +To add the style to a button: +``` +lv_obj_add_style(btn1, LV_BTN_PART_MAIN, &style1); ``` -If an object's style is `NULL` then it will inherit its parent's style. For example, the labels' style are `NULL` by default. If you place them on a button then they will use the `style.text` properties from the button's style. +To remove all styles from an object use: +```c +lv_obj_reset_style_list(obj, LV_OBJ_PART_MAIN); +``` -Learn more in [Style overview](https://docs.littlevgl.com/en/html/overview/style) section. +Learn more in [Style overview](https://docs.lvgl.io/v7/en/html/overview/style) section. ### Events Events are used to inform the user if something has happened with an object. You can assign a callback to an object which will be called if the object is clicked, released, dragged, being deleted etc. It should look like this: @@ -225,7 +222,7 @@ void btn_event_cb(lv_obj_t * btn, lv_event_t event) } ``` -Learn more about the events in the [Event overview](https://docs.littlevgl.com/en/html/overview/event) section. +Learn more about the events in the [Event overview](https://docs.lvgl.io/v7/en/html/overview/event) section. ## Examples @@ -249,121 +246,10 @@ void btn_event_cb(lv_obj_t * btn, lv_event_t event) } } ``` -![LittlevGL button with label example](https://docs.littlevgl.com/en/misc/simple_button_example.gif) - -### Button with styles -Add styles to the previously button from the previous example -```c -static lv_style_t style_btn_rel; /*A variable to store the released style*/ -lv_style_copy(&style_btn_rel, &lv_style_plain); /*Initialize from a built-in style*/ -style_btn_rel.body.border.color = lv_color_hex3(0x269); -style_btn_rel.body.border.width = 1; -style_btn_rel.body.main_color = lv_color_hex3(0xADF); -style_btn_rel.body.grad_color = lv_color_hex3(0x46B); -style_btn_rel.body.shadow.width = 4; -style_btn_rel.body.shadow.type = LV_SHADOW_BOTTOM; -style_btn_rel.body.radius = LV_RADIUS_CIRCLE; -style_btn_rel.text.color = lv_color_hex3(0xDEF); - -static lv_style_t style_btn_pr; /*A variable to store the pressed style*/ -lv_style_copy(&style_btn_pr, &style_btn_rel); /*Initialize from the released style*/ -style_btn_pr.body.border.color = lv_color_hex3(0x46B); -style_btn_pr.body.main_color = lv_color_hex3(0x8BD); -style_btn_pr.body.grad_color = lv_color_hex3(0x24A); -style_btn_pr.body.shadow.width = 2; -style_btn_pr.text.color = lv_color_hex3(0xBCD); - -lv_btn_set_style(btn, LV_BTN_STYLE_REL, &style_btn_rel); /*Set the button's released style*/ -lv_btn_set_style(btn, LV_BTN_STYLE_PR, &style_btn_pr); /*Set the button's pressed style*/ -``` +![LVGL button with label example](https://docs.lvgl.io/v7/en/misc/simple_button_example.gif) -![Stylsd button is LittelvGL](https://docs.littlevgl.com/en/misc/button_style_example.gif) - -### Slider and object alignment -```c -lv_obj_t * label; - -... - -/* Create a slider in the center of the display */ -lv_obj_t * slider = lv_slider_create(lv_scr_act(), NULL); -lv_obj_set_width(slider, 200); /*Set the width*/ -lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 0); /*Align to the center of the parent (screen)*/ -lv_obj_set_event_cb(slider, slider_event_cb); /*Assign an event function*/ - -/* Create a label below the slider */ -label = lv_label_create(lv_scr_act(), NULL); -lv_label_set_text(label, "0"); -lv_obj_set_auto_realign(slider, true); -lv_obj_align(label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); - -... - -void slider_event_cb(lv_obj_t * slider, lv_event_t event) -{ - if(event == LV_EVENT_VALUE_CHANGED) { - static char buf[4]; /* max 3 bytes for number plus 1 null terminating byte */ - snprintf(buf, 4, "%u", lv_slider_get_value(slider)); - lv_label_set_text(slider_label, buf); /*Refresh the text*/ - } -} -``` - -![Slider example with LittlevGL](https://docs.littlevgl.com/en/misc/slider_example.gif) - -### List and themes -```c -/*Texts of the list elements*/ -const char * txts[] = {"First", "Second", "Third", "Forth", "Fifth", "Sixth", NULL}; - -/* Initialize and set a theme. `LV_THEME_NIGHT` needs to enabled in lv_conf.h. */ -lv_theme_t * th = lv_theme_night_init(20, NULL); -lv_theme_set_current(th); - -/*Create a list*/ -lv_obj_t* list = lv_list_create(lv_scr_act(), NULL); -lv_obj_set_size(list, 120, 180); -lv_obj_set_pos(list, 10, 10); - -/*Add buttons*/ -uint8_t i; -for(i = 0; txts[i]; i++) { - lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, txts[i]); - lv_obj_set_event_cb(btn, list_event); /*Assign event function*/ - lv_btn_set_toggle(btn, true); /*Enable on/off states*/ -} - -/* Initialize and set an other theme. `LV_THEME_MATERIAL` needs to enabled in lv_conf.h. - * If `LV_TEHE_LIVE_UPDATE 1` then the previous list's style will be updated too.*/ -th = lv_theme_material_init(210, NULL); -lv_theme_set_current(th); - -/*Create an other list*/ -list = lv_list_create(lv_scr_act(), NULL); -lv_obj_set_size(list, 120, 180); -lv_obj_set_pos(list, 150, 10); - -/*Add buttons with the same texts*/ -for(i = 0; txts[i]; i++) { - lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, txts[i]); - lv_obj_set_event_cb(btn, list_event); - lv_btn_set_toggle(btn, true); -} - -... - -static void list_event(lv_obj_t * btn, lv_event_t e) -{ - if(e == LV_EVENT_CLICKED) { - printf("%s\n", lv_list_get_btn_text(btn)); - } - -} -``` -![List and theme example with LittlevGL](https://docs.littlevgl.com/en/misc/list_theme_example.gif) - -### Use LittlevGL from Micropython -Learn more about [Micropython](https://docs.littlevgl.com/en/html/get-started/micropython). +### Use LVGL from Micropython +Learn more about [Micropython](https://docs.lvgl.io/en/html/get-started/micropython). ```python # Create a Button and a Label scr = lv.obj() @@ -377,22 +263,17 @@ lv.scr_load(scr) ``` ## Contributing -To ask questions please use the [Forum](https://forum.littlevgl.com). -For development-related things (bug reports, feature suggestions) use [GitHub's Issue tracker](https://github.com/littlevgl/lvgl/issues). - -If you are interested in contributing to LittlevGL you can -- **Help others** in the [Forum](https://forum.littlevgl.com). -- **Inspire people** by speaking about your project in [My project](https://forum.littlevgl.com/c/my-projects) category in the Forum or add it to the [References](https://blog.littlevgl.com/2018-12-26/references) post -- **Improve and/or translate the documentation.** Go to the [Documentation](https://github.com/littlevgl/docs) repository to learn more -- **Write a blog post** about your experiences. See how to do it in the [Blog](https://github.com/littlevgl/blog) repository -- **Report and/or fix bugs** in [GitHub's issue tracker](https://github.com/littlevgl/lvgl/issues) -- **Help in the developement**. Check the [Open issues](https://github.com/littlevgl/lvgl/issues) especially the ones with [Help wanted](https://github.com/littlevgl/lvgl/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label and tell your ideas about a topic or implement a feature. - -It should be useful to read the -- [Contributing guide](https://blog.littlevgl.com/2018-12-06/contributing) -- [Coding style guide](https://github.com/littlevgl/lvgl/blob/master/docs/CODING_STYLE.md) - -## Donate -If you are pleased with the library, found it useful, or you are happy with the support you got, please help its further development: - -[![Donate](https://littlevgl.com/donate_dir/donate_btn.png)](https://littlevgl.com/donate) +To ask questions please use the [Forum](https://forum.lvgl.io). +For development-related things (bug reports, feature suggestions) use [GitHub's Issue tracker](https://github.com/lvgl/lvgl/issues). + +If you are interested in contributing to LVGL you can +- **Help others** in the [Forum](https://forum.lvgl.io). +- **Inspire people** by speaking about your project in [My project](https://forum.lvgl.io/c/my-projects) category in the Forum. +- **Improve and/or translate the documentation.** Go to the [Documentation](https://github.com/lvgl/docs) repository to learn more +- **Write a blog post** about your experiences. See how to do it in the [Blog](https://github.com/lvgl/blog) repository +- **Report and/or fix bugs** in [GitHub's issue tracker](https://github.com/lvgl/lvgl/issues) +- **Help in the developement**. Check the [Open issues](https://github.com/lvgl/lvgl/issues) especially the ones with [Help wanted](https://github.com/lvgl/lvgl/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label and tell your ideas about a topic or implement a feature. + +Before sending Pull requests, please read the following guides: +- [Contributing guide](https://github.com/lvgl/lvgl/blob/master/docs/CONTRIBUTING.md) +- [Coding style guide](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) diff --git a/src/docs/CODING_STYLE.md b/src/docs/CODING_STYLE.md index 31071e9..1f7b590 100644 --- a/src/docs/CODING_STYLE.md +++ b/src/docs/CODING_STYLE.md @@ -1,6 +1,7 @@ +# Coding style ## File format -Use [lv_misc/lv_templ.c](https://github.com/littlevgl/lvgl/blob/master/src/lv_misc/lv_templ.c) and [lv_misc/lv_templ.h](https://github.com/littlevgl/lvgl/blob/master/src/lv_misc/lv_templ.h) +Use [lv_misc/lv_templ.c](https://github.com/lvgl/lvgl/blob/master/src/lv_misc/lv_templ.c) and [lv_misc/lv_templ.h](https://github.com/lvgl/lvgl/blob/master/src/lv_misc/lv_templ.h) ## Naming conventions * Words are separated by '_' @@ -15,17 +16,18 @@ Use [lv_misc/lv_templ.c](https://github.com/littlevgl/lvgl/blob/master/src/lv_mi * prefer `typedef struct` and `typedef enum` instead of `struct name` and `enum name` * always end `typedef struct` and `typedef enum` type names with `_t` * Abbreviations: - * Use abbreviations on public names only if they become longer than 32 characters - * Use only very straightforward (e.g. pos: position) or well-established (e.g. pr: press) abbreviations + * Only words longer or equal than 6 characters can be abbreviated. + * Abbreviate only if it makes the word at least half as long + * Use only very straightforward and well-known abbreviations (e.g. pos: position, def: default, btn: button) ## Coding guide * Functions: * Try to write function shorter than is 50 lines - * Always shorter than 100 lines (except very straightforwards) + * Always shorter than 200 lines (except very straightforwards) * Variables: * One line, one declaration (BAD: char x, y;) * Use `` (*uint8_t*, *int32_t* etc) - * Declare variables when needed (not all at function start) + * Declare variables where needed (not all at function start) * Use the smallest required scope * Variables in a file (outside functions) are always *static* * Do not use global variables (use functions to set/get static variables) @@ -84,11 +86,4 @@ void lv_label_set_text(lv_obj_t * label, const char * text) Use 4 spaces indentation instead of tab. -You can use **astyle** to format the code. The required config flies are: `docs/astyle_c` and `docs/astyle_h`. -To format the source files: - `$ find . -type f -name "*.c" | xargs astyle --options=docs/astyle_c` - -To format the header files: - `$ find . -type f -name "*.h" | xargs astyle --options=docs/astyle_h` - -Append `-n` to the end to skip creation of backup file OR use `$ find . -type f -name "*.bak" -delete` (for source file's backups) and `find . -type f -name "*.orig" -delete` (for header file's backups) +You can use **astyle** to format the code. Run `code-formatter.sh` from the `scrips` folder. diff --git a/src/docs/CONTRIBUTING.md b/src/docs/CONTRIBUTING.md index aa31870..2fdfca3 100644 --- a/src/docs/CONTRIBUTING.md +++ b/src/docs/CONTRIBUTING.md @@ -1,111 +1,117 @@ -# Contributing to Littlev Graphics Library +# Contributing to LVGL **Do you have some free time to spend with programming? -Are you working on an Embedded GUI project with LittlevGL? -See how can you help to improve the graphics library!** +Are you working on an embedded GUI project with LVGL? +See how can you help to improve the graphics library and help others!** -There are many ways to join the community. If you have some time to work with us I'm sure you will find something that fits you! You can: -- help others in the [Forum](https://forum.littlevgl.com/) -- improve and/or translate the documentation -- write a blog post about your experiences -- report and/or fix bugs -- suggest and/or implement new features -But first, start with the most Frequently Asked Questions. +- [Overview](#overview) +- [How to send a pull request?](#how-to-send-a-pull-request) +- [Help others in the Forum](help-others-in-the-forum) +- [Improve or translate the documentation](#improve-or-translate-the-documentation) +- [Write a blog post](#write-a-blog-post) +- [Report or fix bugs](#report-or-fix-bugs) +- [Suggest or implement new features](#suggest-or-implement-new-features) +- [Summary](#summary) -# FAQ about contributing -## Where can I write my question and remarks? +## Overview -We use the [Forum](https://forum.littlevgl.com/) to ask and answer questions and [GitHub's issue tracker](https://github.com/littlevgl/lvgl/issues) for development-related discussion. +There are many ways to join the community. If you have some time to work with us you will surely find something that fits you! You can: +- **Help others** in the [Forum](https://forum.lvgl.io). +- **Inspire people** by speaking about your project in [My project](https://forum.lvgl.io/c/my-projects) category in the Forum. +- **Improve and/or translate the documentation.** Go to the [Documentation](https://github.com/lvgl/docs) repository to learn more +- **Write a blog post** about your experiences. See how to do it in the [Blog](https://github.com/lvgl/blog) repository +- **Report and/or fix bugs** in [GitHub's issue tracker](https://github.com/lvgl/lvgl/issues) +- **Help the development**. Check the [Open issues](https://github.com/lvgl/lvgl/issues) especially the ones with [Help wanted](https://github.com/lvgl/lvgl/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label and tell your ideas about a topic or implement a feature. -But there are some simple rules: +We have some simple rules: - Be kind and friendly. - Speak about one thing in one issue/topic. - Give feedback and close the issue or mark the topic as solved if your question is answered. - Tell what you experience or expect. _"The button is not working"_ is not enough info to get help. -- If possible send an absolute minimal code example in order to reproduce the issue - Use [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) to format your post. +- We use the [Forum](https://forum.lvgl.io/) to ask and answer questions and [GitHub's issue tracker](https://github.com/lvgl/lvgl/issues) for development-related discussion. +- If possible send an absolute minimal code example in order to reproduce the issue -## How can I send fixes and improvements? -Merging new code happens via Pull Requests. If you are still not familiar with the Pull Requests (PR for short) here is a quick guide: -1. **Fork** the [lvgl repository](https://github.com/littlevgl/lvgl). To do this click the "Fork" button in the top right corner. It will "copy" the `lvgl` repository to your GitHub account (`https://github.com/your_name?tab=repositories`) +## How to send a pull request? + +Merging new code into LVGL, documentation, blog, and examples happens via *Pull requests*. If you are still not familiar with Pull Requests (PR for short) here is a short guide. It's about the `lvgl` repository but it works the same way for other repositories too. +1. **Fork** the [lvgl repository](https://github.com/lvgl/lvgl). To do this click the "Fork" button in the top right corner. It will "copy" the `lvgl` repository to your GitHub account (`https://github.com/your_name?tab=repositories`) 2. **Clone** the forked repository and add your changes 3. **Create a PR** on GitHub from the page of your `lvgl` repository (`https://github.com/your_name/lvgl`) by hitting the "New pull request" button -4. **Set the base branch**. It means where you want to merge your update. Fixes go to `master`, new features to the actual `dev-x.y` branch. +4. **Set the base branch**. It means where you want to merge your update. Fixes go to `master`, new features to feature branch. 5. **Describe** what is in the update. An example code is welcome if applicable. +6. **Update** your `lvgl` branch with new commits. They will appear in the PR too. Some advice: -- If you are not sure about your fix or feature it's better to open an issue first and discuss the details there. +- For non-trivial fixes and features it's better open an issue first to discuss the details. - Maybe your fix or update won't be perfect at first. Don't be afraid, just improve it and push the new commits. The PR will be updated accordingly. - If your update needs some extra work it's okay to say: _"I'm busy now and I will improve it soon"_ or _"Sorry, I don't have time to improve it, I hope it helps in this form too"_. So it's better to say don't have time to continue than saying nothing. -- Please read and follow this [guide about the coding style](https://github.com/littlevgl/lvgl/blob/master/docs/CODING_STYLE.md) - - -## Where is the documentation? - -You can read the documentation here: -You can edit the documentation here: - -## Where is the blog? - -You can read the blog here: -You can edit the blog here: - -# So how and where can you contribute? +- Please read and follow this [guide about the coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) ## Help others in the Forum It's a great way to contribute to the library if you already use it. -Just go to [https://forum.littlevgl.com/](https://forum.littlevgl.com/) a register (Google and GitHub login also works). +Just go to [https://forum.lvgl.io/](https://forum.lvgl.io/) a register (Google and GitHub login also works). Log in, read the titles and if you are already familiar with a topic, don't be shy, and write your suggestion. -## Improving and/or translating the documentation +## Improve or translate the documentation -If you would like to contribute to LittlevGL the documentation is the best place to start. +If you would like to contribute to LVGL the documentation is the best place to start. ### Fix typos, add missing parts -If you find a typo, an obscure sentence or something which is not explained well enough in the [English documentation](https://docs.littlevgl.com/en/html/index.html) +If you find a typo, an obscure sentence or something which is not explained well enough in the [English documentation](https://docs.lvgl.io/en/html/index.html) click the *"Edit on GitHub"* button in the top right corner and fix the issue by sending a Pull Request. ### Translate the documentation -If you have time and interest you can translate the documentation to your native language or any language you speak. +If you have time and interest you can translate the documentation to your native language or any language you speak well. You can join others to work on an already existing language or you can start a new one. To translate the documentation we use [Zanata](https://zanata.org) which is an online translation platform. -You will find the LittlevGL project here: [LittlevGL on Zanata](https://translate.zanata.org/iteration/view/littlevgl-docs/v6.0-doc1?dswid=3430) +You will find the LVGL project here: [LVGL on Zanata](https://translate.zanata.org/iteration/view/littlevgl-docs/v6.0-doc1?dswid=3430) To get started you need to: - register at [Zanata](https://zanata.org) which is an online translation platform. -- comment to [this post](https://forum.littlevgl.com/t/translate-the-documentation/238?u=kisvegabor) +- comment to [this post](https://forum.lvgl.io/t/translate-the-documentation/238?u=kisvegabor) - tell your username at *Zanata* and your selected language(s) to get permission the edit the translations -Note that a translation will be added to the documentation only if at least the [Porting section](https://docs.littlevgl.com/en/html/porting/index.html) is translated. - +Note that a translation will be added to the documentation only if the following parts are translated: +- [Home page](https://docs.lvgl.io/en/v7/) +- [Porting section](https://docs.lvgl.io/en/v7/html/porting/index.html) +- [Quick overview](https://docs.lvgl.io/v7/en/html/get-started/quick-overview.html) -## Writing a blog post about your experiences +## Write a blog post -Have you ported LittlevGL to a new platform? Have you created a fancy GUI? Do you know a great trick? -You can share your knowledge on LittlevGL's blog! It's super easy to add your own post: -- Fork and clone the [blog repository](https://github.com/littlevgl/blog) +Have you ported LVGL to a new platform or created a fancy GUI? Do you know a great trick? +You can share your knowledge on LVGL's blog! It's super easy to add your own post: +- Fork and clone the [blog repository](https://github.com/lvgl/blog) - Add your post in Markdown to the `_posts` folder. - Store the images and other resources in a dedicated folder in `assets` - Create a Pull Request The blog uses [Jekyll](https://jekyllrb.com/) to convert the `.md` files to a webpage. You can easily [run Jekyll offline](https://jekyllrb.com/docs/) to check your post before creating the Pull request -## Reporting and/or fixing bugs -For simple bugfixes (typos, missing error handling, fixing a warning) is fine to send a Pull request directly. However, for more complex bugs it's better to open an issue first. In the issue, you should describe how to reproduce the bug and even add the minimal code snippet. +## Report or fix bugs +For simple bugfixes (typos, missing error handling, fixing a warning) it's fine to send a Pull request directly. However, for more complex bugs it's better to open an issue first. In the issue, you should describe how to reproduce the bug and add the minimal code snippet. + +## Suggest or implement new features +If you have a good idea don't hesitate to share with us. It's even better if you have time to deal with its implementation. Don't be afraid if you still don't know LVGL well enough. We will help you to get started. + +To share your ideas use [Feature request](https://forum.lvgl.io/c/feature-request/9) category of the forum. + +If you are ready to get involved into the development of this faetures feel free to pen a [new issue](https://github.com/lvgl/lvgl/issues) for it on GitHub. -## Suggesting and/or implementing new features -If you have a good idea don't hesitate to share with us. It's even better if you have time to deal with its implementation. Don't be afraid if you still don't know LittlevGL well enough. We will help you to get started. +During the implementation don't forget the [Code style guide](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md). -During the implementation don't forget the [Code style guide](https://github.com/littlevgl/lvgl/blob/master/docs/CODING_STYLE.md). +If you implemented a new feature it's important to record it in the documentation and if applicable create an example for it: +- Go to the [docs](https://github.com/lvgl/docs/tree/master/v7/en) repository and update the relevant part of the English documentation. +- Go to the [examples](https://github.com/lvgl/lv_examples) repository and add a new file about the new feature in the related directory. -# Summary +## Summary -I hope you have taken a liking to contribute to LittlevGL. A helpful and friendly community is waiting for you! :) +I hope you have taken a liking to contribute to LVGL. A helpful and friendly community is waiting for you! :) diff --git a/src/library.json b/src/library.json index 23ecc3f..388130f 100644 --- a/src/library.json +++ b/src/library.json @@ -1,12 +1,12 @@ { "name": "lvgl", - "version": "6.1.1", + "version": "v7.0.1", "keywords": "graphics, gui, embedded, littlevgl", "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": { "type": "git", - "url": "https://github.com/littlevgl/lvgl.git" + "url": "https://github.com/lvgl/lvgl.git" }, "build": { "includeDir": "." diff --git a/src/lv_conf_template.h b/src/lv_conf_template.h index 77b97b1..415a33d 100644 --- a/src/lv_conf_template.h +++ b/src/lv_conf_template.h @@ -25,7 +25,7 @@ /* Color depth: * - 1: 1 byte per pixel - * - 8: RGB233 + * - 8: RGB332 * - 16: RGB565 * - 32: ARGB8888 */ @@ -43,9 +43,6 @@ /*Images pixels with this color will not be drawn (with chroma keying)*/ #define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ -/* Enable chroma keying for indexed images. */ -#define LV_INDEXED_CHROMA 1 - /* Enable anti-aliasing (lines, and radiuses will be smoothed) */ #define LV_ANTIALIAS 1 @@ -56,7 +53,18 @@ /* Dot Per Inch: used to initialize default sizes. * E.g. a button with width = LV_DPI / 2 -> half inch wide * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI 100 /*[px]*/ +#define LV_DPI 130 /*[px]*/ + +/* The the real width of the display changes some default values: + * default object sizes, layout of examples, etc. + * According to the width of the display (hor. res. / dpi) + * the displays fall in 4 categories. + * The 4th is extra large which has no upper limit so not listed here + * The upper limit of the categories are set below in 0.1 inch unit. + */ +#define LV_DISP_SMALL_LIMIT 30 +#define LV_DISP_MEDIUM_LIMIT 50 +#define LV_DISP_LARGE_LIMIT 70 /* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ typedef int16_t lv_coord_t; @@ -112,7 +120,7 @@ typedef int16_t lv_coord_t; #define LV_INDEV_DEF_DRAG_LIMIT 10 /* Drag throw slow-down in [%]. Greater value -> faster slow-down */ -#define LV_INDEV_DEF_DRAG_THROW 20 +#define LV_INDEV_DEF_DRAG_THROW 10 /* Long press time in milliseconds. * Time to send `LV_EVENT_LONG_PRESSSED`) */ @@ -122,6 +130,13 @@ typedef int16_t lv_coord_t; * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ #define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 + +/* Gesture threshold in pixels */ +#define LV_INDEV_DEF_GESTURE_LIMIT 50 + +/* Gesture min velocity at release before swipe (pixels)*/ +#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 + /*================== * Feature usage *==================*/ @@ -137,6 +152,22 @@ typedef void * lv_anim_user_data_t; /* 1: Enable shadow drawing*/ #define LV_USE_SHADOW 1 +#if LV_USE_SHADOW +/* Allow buffering some shadow calculation + * LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, + * where shadow size is `shadow_width + radius` + * Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ +#define LV_SHADOW_CACHE_SIZE 0 +#endif + +/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/ +#define LV_USE_BLEND_MODES 1 + +/* 1: Use the `opa_scale` style property to set the opacity of an object and its children at once*/ +#define LV_USE_OPA_SCALE 1 + +/* 1: Use image zoom and rotation*/ +#define LV_USE_IMG_TRANSFORM 1 /* 1: Enable object groups (for keyboard/encoder navigation) */ #define LV_USE_GROUP 1 @@ -145,7 +176,8 @@ typedef void * lv_group_user_data_t; #endif /*LV_USE_GROUP*/ /* 1: Enable GPU interface*/ -#define LV_USE_GPU 1 +#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ +#define LV_USE_GPU_STM32_DMA2D 0 /* 1: Enable file system (might be required for images */ #define LV_USE_FILESYSTEM 1 @@ -157,6 +189,12 @@ typedef void * lv_fs_drv_user_data_t; /*1: Add a `user_data` to drivers and objects*/ #define LV_USE_USER_DATA 0 +/*1: Show CPU usage and FPS count in the right bottom corner*/ +#define LV_USE_PERF_MONITOR 0 + +/*1: Use the functions and types from the older API if possible */ +#define LV_USE_API_EXTENSION_V6 1 + /*======================== * Image decoder and cache *========================*/ @@ -187,6 +225,9 @@ typedef void * lv_img_decoder_user_data_t; /* Define a custom attribute to `lv_task_handler` function */ #define LV_ATTRIBUTE_TASK_HANDLER +/* Define a custom attribute to `lv_disp_flush_ready` function */ +#define LV_ATTRIBUTE_FLUSH_READY + /* With size optimization (-Os) the compiler might not align data to * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. * E.g. __attribute__((aligned(4))) */ @@ -196,6 +237,10 @@ typedef void * lv_img_decoder_user_data_t; * font's bitmaps */ #define LV_ATTRIBUTE_LARGE_CONST +/* Prefix performance critical functions to place them into a faster memory (e.g RAM) + * Uses 15-20 kB extra memory */ +#define LV_ATTRIBUTE_FAST_MEM + /* Export integer constant to binding. * This macro is used with constants in the form of LV_ that * should also appear on lvgl binding API such as Micropython @@ -262,6 +307,9 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i /*Checks is the memory is successfully allocated or no. (Quite fast)*/ #define LV_USE_ASSERT_MEM 1 +/*Check the integrity of `lv_mem` after critical operations. (Slow)*/ +#define LV_USE_ASSERT_MEM_INTEGRITY 0 + /* Check the strings. * Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow) * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ @@ -272,44 +320,47 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i #define LV_USE_ASSERT_OBJ 0 /*Check if the styles are properly initialized. (Fast)*/ -#define LV_USE_ASSERT_STYLE 1 +#define LV_USE_ASSERT_STYLE 0 #endif /*LV_USE_DEBUG*/ -/*================ - * THEME USAGE - *================*/ -#define LV_THEME_LIVE_UPDATE 0 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ - -#define LV_USE_THEME_TEMPL 0 /*Just for test*/ -#define LV_USE_THEME_DEFAULT 0 /*Built mainly from the built-in styles. Consumes very few RAM*/ -#define LV_USE_THEME_ALIEN 0 /*Dark futuristic theme*/ -#define LV_USE_THEME_NIGHT 0 /*Dark elegant theme*/ -#define LV_USE_THEME_MONO 0 /*Mono color theme for monochrome displays*/ -#define LV_USE_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/ -#define LV_USE_THEME_ZEN 0 /*Peaceful, mainly light theme */ -#define LV_USE_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/ - /*================== * FONT USAGE *===================*/ /* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel. * The symbols are available via `LV_SYMBOL_...` defines - * More info about fonts: https://docs.littlevgl.com/#Fonts - * To create a new font go to: https://littlevgl.com/ttf-font-to-c-array + * More info about fonts: https://docs.lvgl.com/#Fonts + * To create a new font go to: https://lvgl.com/ttf-font-to-c-array */ -/* Robot fonts with bpp = 4 - * https://fonts.google.com/specimen/Roboto */ -#define LV_FONT_ROBOTO_12 0 -#define LV_FONT_ROBOTO_16 1 -#define LV_FONT_ROBOTO_22 0 -#define LV_FONT_ROBOTO_28 0 +/* Montserrat fonts with bpp = 4 + * https://fonts.google.com/specimen/Montserrat */ +#define LV_FONT_MONTSERRAT_12 0 +#define LV_FONT_MONTSERRAT_14 0 +#define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_18 0 +#define LV_FONT_MONTSERRAT_20 0 +#define LV_FONT_MONTSERRAT_22 0 +#define LV_FONT_MONTSERRAT_24 0 +#define LV_FONT_MONTSERRAT_26 0 +#define LV_FONT_MONTSERRAT_28 0 +#define LV_FONT_MONTSERRAT_30 0 +#define LV_FONT_MONTSERRAT_32 0 +#define LV_FONT_MONTSERRAT_34 0 +#define LV_FONT_MONTSERRAT_36 0 +#define LV_FONT_MONTSERRAT_38 0 +#define LV_FONT_MONTSERRAT_40 0 +#define LV_FONT_MONTSERRAT_42 0 +#define LV_FONT_MONTSERRAT_44 0 +#define LV_FONT_MONTSERRAT_46 0 +#define LV_FONT_MONTSERRAT_48 0 /* Demonstrate special features */ -#define LV_FONT_ROBOTO_12_SUBPX 1 -#define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/ +#define LV_FONT_MONTSERRAT_12_SUBPX 0 +#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ +#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, PErisan letters and all their forms*/ +#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ /*Pixel perfect monospace font * http://pelulamu.net/unscii/ */ @@ -323,9 +374,6 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i */ #define LV_FONT_CUSTOM_DECLARE -/*Always set a default font from the built-in fonts*/ -#define LV_FONT_DEFAULT &lv_font_roboto_16 - /* Enable it if you have fonts with a lot of characters. * The limit depends on the font size, font face and bpp * but with > 10,000 characters if you see issues probably you need to enable it.*/ @@ -340,6 +388,43 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i /*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_font_user_data_t; +/*================ + * THEME USAGE + *================*/ + +/*Always enable at least on theme*/ + +/* No theme, you can apply your styles as you need + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_EMPTY 1 + +/*Simple to the create your theme based on it + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_TEMPLATE 1 + +/* A fast and impressive theme. + * Flags: + * LV_THEME_MATERIAL_FLAG_LIGHT: light theme + * LV_THEME_MATERIAL_FLAG_DARK: dark theme*/ + #define LV_USE_THEME_MATERIAL 1 + +/* Mono-color theme for monochrome displays. + * If LV_THEME_DEFAULT_COLOR_PRIMARY is LV_COLOR_BLACK the + * texts and borders will be black and the background will be + * white. Else the colors are inverted. + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ + #define LV_USE_THEME_MONO 1 + +#define LV_THEME_DEFAULT_INCLUDE /*Include a header for the init. function*/ +#define LV_THEME_DEFAULT_INIT lv_theme_material_init +#define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED +#define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE +#define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT +#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_16 +#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_16 + /*================= * Text settings *=================*/ @@ -356,7 +441,7 @@ typedef void * lv_font_user_data_t; /* If a word is at least this long, will break wherever "prettiest" * To disable, set to a value <= 0 */ -#define LV_TXT_LINE_BREAK_LONG_LEN 12 +#define LV_TXT_LINE_BREAK_LONG_LEN 0 /* Minimum number of characters in a long word to put on a line before a break. * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ @@ -382,20 +467,36 @@ typedef void * lv_font_user_data_t; #define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO #endif +/* Enable Arabic/Persian processing + * In these languages characters should be replaced with + * an other form based on their position in the text */ +#define LV_USE_ARABIC_PERSIAN_CHARS 0 + /*Change the built in (v)snprintf functions*/ #define LV_SPRINTF_CUSTOM 0 #if LV_SPRINTF_CUSTOM # define LV_SPRINTF_INCLUDE # define lv_snprintf snprintf # define lv_vsnprintf vsnprintf +#else /*!LV_SPRINTF_CUSTOM*/ +# define LV_SPRINTF_DISABLE_FLOAT 1 #endif /*LV_SPRINTF_CUSTOM*/ /*=================== * LV_OBJ SETTINGS *==================*/ +#if LV_USE_USER_DATA /*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_obj_user_data_t; +/*Provide a function to free user data*/ +#define LV_USE_USER_DATA_FREE 0 +#if LV_USE_USER_DATA_FREE +# define LV_USER_DATA_FREE_INCLUDE "something.h" /*Header for user data free function*/ +/* Function prototype : void user_data_free(lv_obj_t * obj); */ +# define LV_USER_DATA_FREE (user_data_free) /*Invoking for user data free function*/ +#endif +#endif /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ #define LV_USE_OBJ_REALIGN 1 @@ -405,13 +506,13 @@ typedef void * lv_obj_user_data_t; * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) */ -#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_OFF +#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_TINY /*================== * LV OBJ X USAGE *================*/ /* - * Documentation of the object types: https://docs.littlevgl.com/#Object-types + * Documentation of the object types: https://docs.lvgl.com/#Object-types */ /*Arc (dependencies: -)*/ @@ -422,13 +523,9 @@ typedef void * lv_obj_user_data_t; /*Button (dependencies: lv_cont*/ #define LV_USE_BTN 1 -#if LV_USE_BTN != 0 -/*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/ -# define LV_BTN_INK_EFFECT 0 -#endif /*Button matrix (dependencies: -)*/ -#define LV_USE_BTNM 1 +#define LV_USE_BTNMATRIX 1 /*Calendar (dependencies: -)*/ #define LV_USE_CALENDAR 1 @@ -437,12 +534,12 @@ typedef void * lv_obj_user_data_t; #define LV_USE_CANVAS 1 /*Check box (dependencies: lv_btn, lv_label)*/ -#define LV_USE_CB 1 +#define LV_USE_CHECKBOX 1 /*Chart (dependencies: -)*/ #define LV_USE_CHART 1 #if LV_USE_CHART -# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20 +# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 256 #endif /*Container (dependencies: -*/ @@ -452,13 +549,13 @@ typedef void * lv_obj_user_data_t; #define LV_USE_CPICKER 1 /*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ -#define LV_USE_DDLIST 1 -#if LV_USE_DDLIST != 0 +#define LV_USE_DROPDOWN 1 +#if LV_USE_DROPDOWN != 0 /*Open and close default animation time [ms] (0: no animation)*/ -# define LV_DDLIST_DEF_ANIM_TIME 200 +# define LV_DROPDOWN_DEF_ANIM_TIME 200 #endif -/*Gauge (dependencies:lv_bar, lv_lmeter)*/ +/*Gauge (dependencies:lv_bar, lv_linemeter)*/ #define LV_USE_GAUGE 1 /*Image (dependencies: lv_label*/ @@ -472,7 +569,7 @@ typedef void * lv_obj_user_data_t; #endif /*Keyboard (dependencies: lv_btnm)*/ -#define LV_USE_KB 1 +#define LV_USE_KEYBOARD 1 /*Label (dependencies: -*/ #define LV_USE_LABEL 1 @@ -492,6 +589,10 @@ typedef void * lv_obj_user_data_t; /*LED (dependencies: -)*/ #define LV_USE_LED 1 +#if LV_USE_LED +# define LV_LED_BRIGHT_MIN 120 /*Minimal brightness*/ +# define LV_LED_BRIGHT_MAX 255 /*Maximal brightness*/ +#endif /*Line (dependencies: -*/ #define LV_USE_LINE 1 @@ -504,10 +605,22 @@ typedef void * lv_obj_user_data_t; #endif /*Line meter (dependencies: *;)*/ -#define LV_USE_LMETER 1 +#define LV_USE_LINEMETER 1 +#if LV_USE_LINEMETER +/* Draw line more precisely at cost of performance. + * Useful if there are lot of lines any minor are visible + * 0: No extra precision + * 1: Some extra precision + * 2: Best precision + */ +# define LV_LINEMETER_PRECISE 0 +#endif + +/*Mask (dependencies: -)*/ +#define LV_USE_OBJMASK 1 /*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ -#define LV_USE_MBOX 1 +#define LV_USE_MSGBOX 1 /*Page (dependencies: lv_cont)*/ #define LV_USE_PAGE 1 @@ -517,11 +630,11 @@ typedef void * lv_obj_user_data_t; #endif /*Preload (dependencies: lv_arc, lv_anim)*/ -#define LV_USE_PRELOAD 1 -#if LV_USE_PRELOAD != 0 -# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ -# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ -# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC +#define LV_USE_SPINNER 1 +#if LV_USE_SPINNER != 0 +# define LV_SPINNER_DEF_ARC_LENGTH 60 /*[deg]*/ +# define LV_SPINNER_DEF_SPIN_TIME 1000 /*[ms]*/ +# define LV_SPINNER_DEF_ANIM LV_SPINNER_TYPE_SPINNING_ARC #endif /*Roller (dependencies: lv_ddlist)*/ @@ -541,13 +654,13 @@ typedef void * lv_obj_user_data_t; #define LV_USE_SPINBOX 1 /*Switch (dependencies: lv_slider)*/ -#define LV_USE_SW 1 +#define LV_USE_SWITCH 1 /*Text area (dependencies: lv_label, lv_page)*/ -#define LV_USE_TA 1 -#if LV_USE_TA != 0 -# define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ -# define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#define LV_USE_TEXTAREA 1 +#if LV_USE_TEXTAREA != 0 +# define LV_TEXTAREA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ +# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ #endif /*Table (dependencies: lv_label)*/ @@ -583,9 +696,6 @@ typedef void * lv_obj_user_data_t; /*--END OF LV_CONF_H--*/ -/*Be sure every define has a default value*/ -#include "lvgl/src/lv_conf_checker.h" - #endif /*LV_CONF_H*/ #endif /*End of "Content enable"*/ diff --git a/src/lvgl.h b/src/lvgl.h index 418ffd2..20878c1 100644 --- a/src/lvgl.h +++ b/src/lvgl.h @@ -14,8 +14,6 @@ extern "C" { * INCLUDES *********************/ -#include "src/lv_version.h" - #include "src/lv_misc/lv_log.h" #include "src/lv_misc/lv_task.h" #include "src/lv_misc/lv_math.h" @@ -29,54 +27,59 @@ extern "C" { #include "src/lv_core/lv_refr.h" #include "src/lv_core/lv_disp.h" -#include "src/lv_core/lv_debug.h" #include "src/lv_themes/lv_theme.h" #include "src/lv_font/lv_font.h" #include "src/lv_font/lv_font_fmt_txt.h" -#include "src/lv_misc/lv_bidi.h" #include "src/lv_misc/lv_printf.h" -#include "src/lv_objx/lv_btn.h" -#include "src/lv_objx/lv_imgbtn.h" -#include "src/lv_objx/lv_img.h" -#include "src/lv_objx/lv_label.h" -#include "src/lv_objx/lv_line.h" -#include "src/lv_objx/lv_page.h" -#include "src/lv_objx/lv_cont.h" -#include "src/lv_objx/lv_list.h" -#include "src/lv_objx/lv_chart.h" -#include "src/lv_objx/lv_table.h" -#include "src/lv_objx/lv_cb.h" -#include "src/lv_objx/lv_cpicker.h" -#include "src/lv_objx/lv_bar.h" -#include "src/lv_objx/lv_slider.h" -#include "src/lv_objx/lv_led.h" -#include "src/lv_objx/lv_btnm.h" -#include "src/lv_objx/lv_kb.h" -#include "src/lv_objx/lv_ddlist.h" -#include "src/lv_objx/lv_roller.h" -#include "src/lv_objx/lv_ta.h" -#include "src/lv_objx/lv_canvas.h" -#include "src/lv_objx/lv_win.h" -#include "src/lv_objx/lv_tabview.h" -#include "src/lv_objx/lv_tileview.h" -#include "src/lv_objx/lv_mbox.h" -#include "src/lv_objx/lv_gauge.h" -#include "src/lv_objx/lv_lmeter.h" -#include "src/lv_objx/lv_sw.h" -#include "src/lv_objx/lv_kb.h" -#include "src/lv_objx/lv_arc.h" -#include "src/lv_objx/lv_preload.h" -#include "src/lv_objx/lv_calendar.h" -#include "src/lv_objx/lv_spinbox.h" +#include "src/lv_widgets/lv_btn.h" +#include "src/lv_widgets/lv_imgbtn.h" +#include "src/lv_widgets/lv_img.h" +#include "src/lv_widgets/lv_label.h" +#include "src/lv_widgets/lv_line.h" +#include "src/lv_widgets/lv_page.h" +#include "src/lv_widgets/lv_cont.h" +#include "src/lv_widgets/lv_list.h" +#include "src/lv_widgets/lv_chart.h" +#include "src/lv_widgets/lv_table.h" +#include "src/lv_widgets/lv_checkbox.h" +#include "src/lv_widgets/lv_cpicker.h" +#include "src/lv_widgets/lv_bar.h" +#include "src/lv_widgets/lv_slider.h" +#include "src/lv_widgets/lv_led.h" +#include "src/lv_widgets/lv_btnmatrix.h" +#include "src/lv_widgets/lv_keyboard.h" +#include "src/lv_widgets/lv_dropdown.h" +#include "src/lv_widgets/lv_roller.h" +#include "src/lv_widgets/lv_textarea.h" +#include "src/lv_widgets/lv_canvas.h" +#include "src/lv_widgets/lv_win.h" +#include "src/lv_widgets/lv_tabview.h" +#include "src/lv_widgets/lv_tileview.h" +#include "src/lv_widgets/lv_msgbox.h" +#include "src/lv_widgets/lv_objmask.h" +#include "src/lv_widgets/lv_gauge.h" +#include "src/lv_widgets/lv_linemeter.h" +#include "src/lv_widgets/lv_switch.h" +#include "src/lv_widgets/lv_arc.h" +#include "src/lv_widgets/lv_spinner.h" +#include "src/lv_widgets/lv_calendar.h" +#include "src/lv_widgets/lv_spinbox.h" #include "src/lv_draw/lv_img_cache.h" +#include "src/lv_api_map.h" + /********************* * DEFINES *********************/ +/*Current version of LVGL*/ +#define LVGL_VERSION_MAJOR 7 +#define LVGL_VERSION_MINOR 0 +#define LVGL_VERSION_PATCH 1 +#define LVGL_VERSION_INFO "dev" /********************** * TYPEDEFS @@ -90,6 +93,30 @@ extern "C" { * MACROS **********************/ +/** Gives 1 if the x.y.z version is supported in the current version + * Usage: + * + * - Require v6 + * #if LV_VERSION_CHECK(6,0,0) + * new_func_in_v6(); + * #endif + * + * + * - Require at least v5.3 + * #if LV_VERSION_CHECK(5,3,0) + * new_feature_from_v5_3(); + * #endif + * + * + * - Require v5.3.2 bugfixes + * #if LV_VERSION_CHECK(5,3,2) + * bugfix_in_v5_3_2(); + * #endif + * + * */ +#define LV_VERSION_CHECK(x,y,z) (x == LVGL_VERSION_MAJOR && (y < LVGL_VERSION_MINOR || (y == LVGL_VERSION_MINOR && z <= LVGL_VERSION_PATCH))) + + #ifdef __cplusplus } #endif diff --git a/src/lvgl.mk b/src/lvgl.mk index 830fe11..bbea98d 100644 --- a/src/lvgl.mk +++ b/src/lvgl.mk @@ -1,8 +1,10 @@ -include $(LVGL_DIR)/lvgl/src/lv_core/lv_core.mk -include $(LVGL_DIR)/lvgl/src/lv_hal/lv_hal.mk -include $(LVGL_DIR)/lvgl/src/lv_objx/lv_objx.mk -include $(LVGL_DIR)/lvgl/src/lv_font/lv_font.mk -include $(LVGL_DIR)/lvgl/src/lv_misc/lv_misc.mk -include $(LVGL_DIR)/lvgl/src/lv_themes/lv_themes.mk -include $(LVGL_DIR)/lvgl/src/lv_draw/lv_draw.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_core/lv_core.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_hal/lv_hal.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_widgets/lv_widgets.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_font/lv_font.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc/lv_misc.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_themes/lv_themes.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_draw/lv_draw.mk +include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_gpu/lv_gpu.mk + diff --git a/src/porting/lv_port_disp_template.c b/src/porting/lv_port_disp_template.c index 295dbe1..b26c34e 100644 --- a/src/porting/lv_port_disp_template.c +++ b/src/porting/lv_port_disp_template.c @@ -9,7 +9,7 @@ /********************* * INCLUDES *********************/ -#include "lv_port_disp_templ.h" +#include "lv_port_disp_template.h" /********************* * DEFINES @@ -26,8 +26,9 @@ static void disp_init(void); static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); #if LV_USE_GPU -static void gpu_blend(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); -static void gpu_fill(lv_color_t * dest, uint32_t length, lv_color_t color); +static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); +static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, + const lv_area_t * fill_area, lv_color_t color); #endif /********************** @@ -53,20 +54,20 @@ void lv_port_disp_init(void) * Create a buffer for drawing *----------------------------*/ - /* LittlevGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row + /* LVGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row * * There are three buffering configurations: * 1. Create ONE buffer with some rows: - * LittlevGL will draw the display's content here and writes it to your display + * LVGL will draw the display's content here and writes it to your display * * 2. Create TWO buffer with some rows: - * LittlevGL will draw the display's content to a buffer and writes it your display. + * LVGL will draw the display's content to a buffer and writes it your display. * You should use DMA to write the buffer's content to the display. - * It will enable LittlevGL to draw the next part of the screen to the other buffer while + * It will enable LVGL to draw the next part of the screen to the other buffer while * the data is being sent form the first buffer. It makes rendering and flushing parallel. * * 3. Create TWO screen-sized buffer: - * Similar to 2) but the buffer have to be screen sized. When LittlevGL is ready it will give the + * Similar to 2) but the buffer have to be screen sized. When LVGL is ready it will give the * whole frame to display. This way you only need to change the frame buffer's address instead of * copying the pixels. * */ @@ -90,7 +91,7 @@ void lv_port_disp_init(void) /*----------------------------------- - * Register the display in LittlevGL + * Register the display in LVGL *----------------------------------*/ lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ @@ -112,10 +113,10 @@ void lv_port_disp_init(void) /*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/ /*Blend two color array using opacity*/ - disp_drv.gpu_blend = gpu_blend; + disp_drv.gpu_blend_cb = gpu_blend; /*Fill a memory array with a color*/ - disp_drv.gpu_fill = gpu_fill; + disp_drv.gpu_fill_cb = gpu_fill; #endif /*Finally register the driver*/ @@ -151,7 +152,7 @@ static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_colo /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ - lv_disp_flush_ready(disp); + lv_disp_flush_ready(disp_drv); } @@ -171,15 +172,15 @@ static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_colo /* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/ -static void gpu_fill_cb(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, - const lv_area_t * fill_area, lv_color_t color); +static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, + const lv_area_t * fill_area, lv_color_t color) { /*It's an example code which should be done by your GPU*/ - uint32_t x, y; + int32_t x, y; dest_buf += dest_width * fill_area->y1; /*Go to the first line*/ - for(y = fill_area->y1; y < fill_area->y2; y++) { - for(x = fill_area->x1; x < fill_area->x2; x++) { + for(y = fill_area->y1; y <= fill_area->y2; y++) { + for(x = fill_area->x1; x <= fill_area->x2; x++) { dest_buf[x] = color; } dest_buf+=dest_width; /*Go to the next line*/ diff --git a/src/porting/lv_port_fs_template.c b/src/porting/lv_port_fs_template.c index dab9460..6aead14 100644 --- a/src/porting/lv_port_fs_template.c +++ b/src/porting/lv_port_fs_template.c @@ -9,7 +9,7 @@ /********************* * INCLUDES *********************/ -#include "lv_port_fs_templ.h" +#include "lv_port_fs_template.h" /********************* * DEFINES @@ -81,34 +81,34 @@ void lv_port_fs_init(void) fs_init(); /*--------------------------------------------------- - * Register the file system interface in LittlevGL + * Register the file system interface in LVGL *--------------------------------------------------*/ /* Add a simple drive to open images */ - lv_fs_drv_t fs_drv; /*A driver descriptor*/ - memset(&fs_drv, 0, sizeof(lv_fs_drv_t)); /*Initialization*/ + lv_fs_drv_t fs_drv; + lv_fs_drv_init(&fs_drv); /*Set up fields...*/ fs_drv.file_size = sizeof(file_t); fs_drv.letter = 'P'; - fs_drv.open = fs_open; - fs_drv.close = fs_close; - fs_drv.read = fs_read; - fs_drv.write = fs_write; - fs_drv.seek = fs_seek; - fs_drv.tell = fs_tell; - fs_drv.free = fs_free; - fs_drv.size = fs_size; - fs_drv.remove = fs_remove; - fs_drv.rename = fs_rename; - fs_drv.trunc = fs_trunc; + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = fs_write; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + fs_drv.free_space_cb = fs_free; + fs_drv.size_cb = fs_size; + fs_drv.remove_cb = fs_remove; + fs_drv.rename_cb = fs_rename; + fs_drv.trunc_cb = fs_trunc; fs_drv.rddir_size = sizeof(dir_t); - fs_drv.dir_close = fs_dir_close; - fs_drv.dir_open = fs_dir_open; - fs_drv.dir_read = fs_dir_read; + fs_drv.dir_close_cb = fs_dir_close; + fs_drv.dir_open_cb = fs_dir_open; + fs_drv.dir_read_cb = fs_dir_read; - lv_fs_add_drv(&fs_drv); + lv_fs_drv_register(&fs_drv); } /********************** @@ -315,7 +315,7 @@ static lv_fs_res_t fs_rename (lv_fs_drv_t * drv, const char * oldname, const cha * @param free_p pointer to store the free size [kB] * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -static lv_fs_res_t fs_free (uint32_t * total_p, uint32_t * free_p) +static lv_fs_res_t fs_free (lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p) { lv_fs_res_t res = LV_FS_RES_NOT_IMP; diff --git a/src/porting/lv_port_indev_template.c b/src/porting/lv_port_indev_template.c index 7666023..1910b74 100644 --- a/src/porting/lv_port_indev_template.c +++ b/src/porting/lv_port_indev_template.c @@ -9,7 +9,7 @@ /********************* * INCLUDES *********************/ -#include "lv_port_indev_templ.h" +#include "lv_port_indev_template.h" /********************* * DEFINES @@ -140,14 +140,14 @@ void lv_port_indev_init(void) /*Register a encoder input device*/ lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_KEYPAD; + indev_drv.type = LV_INDEV_TYPE_ENCODER; indev_drv.read_cb = encoder_read; indev_encoder = lv_indev_drv_register(&indev_drv); /* Later you should create group(s) with `lv_group_t * group = lv_group_create()`, * add objects to the group with `lv_group_add_obj(group, obj)` * and assign this input device to group to navigate in it: - * `lv_indev_set_group(indev_keypad, group);` */ + * `lv_indev_set_group(indev_encoder, group);` */ /*------------------ * Button @@ -293,7 +293,7 @@ static bool keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) if(act_key != 0) { data->state = LV_INDEV_STATE_PR; - /*Translate the keys to LittlevGL control characters according to your key definitions*/ + /*Translate the keys to LVGL control characters according to your key definitions*/ switch(act_key) { case 1: act_key = LV_KEY_NEXT; diff --git a/src/scripts/Doxyfile b/src/scripts/Doxyfile index 2f93286..7120f5d 100644 --- a/src/scripts/Doxyfile +++ b/src/scripts/Doxyfile @@ -724,7 +724,7 @@ CITE_BIB_FILES = # messages are off. # The default value is: NO. -QUIET = NO +QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES @@ -733,14 +733,14 @@ QUIET = NO # Tip: Turn warnings on while writing the documentation. # The default value is: YES. -WARNINGS = YES +WARNINGS = NO # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. -WARN_IF_UNDOCUMENTED = YES +WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters @@ -748,7 +748,7 @@ WARN_IF_UNDOCUMENTED = YES # markup commands wrongly. # The default value is: YES. -WARN_IF_DOC_ERROR = YES +WARN_IF_DOC_ERROR = NO # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return diff --git a/src/scripts/built_in_font/DejaVuSans.ttf b/src/scripts/built_in_font/DejaVuSans.ttf new file mode 100644 index 0000000..5267218 Binary files /dev/null and b/src/scripts/built_in_font/DejaVuSans.ttf differ diff --git a/src/scripts/built_in_font/FontAwesome.ttf b/src/scripts/built_in_font/FontAwesome.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/src/scripts/built_in_font/FontAwesome.ttf and /dev/null differ diff --git a/src/scripts/built_in_font/Montserrat-Medium.ttf b/src/scripts/built_in_font/Montserrat-Medium.ttf new file mode 100644 index 0000000..6e079f6 Binary files /dev/null and b/src/scripts/built_in_font/Montserrat-Medium.ttf differ diff --git a/src/scripts/built_in_font/Roboto-Regular.woff b/src/scripts/built_in_font/Roboto-Regular.woff deleted file mode 100644 index f823258..0000000 Binary files a/src/scripts/built_in_font/Roboto-Regular.woff and /dev/null differ diff --git a/src/scripts/built_in_font/SimSun.woff b/src/scripts/built_in_font/SimSun.woff new file mode 100644 index 0000000..8d08174 Binary files /dev/null and b/src/scripts/built_in_font/SimSun.woff differ diff --git a/src/scripts/built_in_font/built_in_font_gen.py b/src/scripts/built_in_font/built_in_font_gen.py old mode 100644 new mode 100755 index db8e88c..b320650 --- a/src/scripts/built_in_font/built_in_font_gen.py +++ b/src/scripts/built_in_font/built_in_font_gen.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3.6 + import argparse from argparse import RawTextHelpFormatter import os @@ -18,12 +20,17 @@ parser.add_argument('-r', '--range', nargs='+', metavar = 'start-end', - default='0x20-0x7F', + default=['0x20-0x7F,0xB0,0x2022'], help='Ranges and/or characters to include. Default is 0x20-7F (ASCII). E.g. -r 0x20-0x7F, 0x200, 324') +parser.add_argument('--symbols', + nargs='+', + metavar = 'sym', + default=[''], + help=u'Symbols to include. E.g. -s ÁÉŐ'.encode('utf-8')) parser.add_argument('--font', metavar = 'file', nargs='?', - default='Roboto-Regular.woff', + default='Montserrat-Medium.ttf', help='A TTF or WOFF file') parser.add_argument('-o', '--output', nargs='?', @@ -31,6 +38,8 @@ help='Output file name. E.g. my_font_20.c') parser.add_argument('--compressed', action='store_true', help='Compress the bitmaps') +parser.add_argument('--subpx', action='store_true', + help='3 times wider letters for sub pixel rendering') args = parser.parse_args() @@ -39,9 +48,12 @@ else: compr = "" +if len(args.symbols[0]) != 0: + args.symbols[0] = "--symbols " + args.symbols[0] + #Built in symbols syms = "61441,61448,61451,61452,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650" -#Run the command -cmd = "lv_font_conv {} --bpp {} --size {} --font Roboto-Regular.woff -r {} --font FontAwesome5-Solid+Brands+Regular.woff -r {} --format lvgl -o {} --force-fast-kern-format".format(compr, args.bpp, args.size, args.range[0], syms, args.output) +#Run the command (Add degree and bbullet symbol) +cmd = "lv_font_conv {} --bpp {} --size {} --font {} -r {} {} --font FontAwesome5-Solid+Brands+Regular.woff -r {} --format lvgl -o {} --force-fast-kern-format".format(compr, args.bpp, args.size, args.font, args.range[0], args.symbols[0], syms, args.output) os.system(cmd) diff --git a/src/scripts/built_in_font/generate_all.py b/src/scripts/built_in_font/generate_all.py new file mode 100755 index 0000000..2242fde --- /dev/null +++ b/src/scripts/built_in_font/generate_all.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3.6 + +import os + +print("\nGenerating 16 px CJK") +os.system(u"./built_in_font_gen.py --size 16 -o lv_font_simsun_16_cjk.c --bpp 4 --font SimSun.woff -r 0x20-0x7f --symbols 一在有個我不這了他也就人都說而我們你了要會對及和與以很種的大能著她那上但年還可以最自己為來所他們兩各可為或好等又將因為於由從更被才已者每次把三什麼問題其讓此做再所以只與則台灣卻並位想去呢學生表示到公司將如果社會看小天因此新但是它中使工作全覺得使用這些裡並由於時候知道這樣一認為時間事過向可能中國美國到和幾系統政府大家國家許多生活跟已經大學研究因本二活動該世界應四希望方式內項啊下環境一些必須文化高孩子沒有不能如開始元不同仍網路日本用中心來對雖然重要地方進行關係市場太老師提供學校應該指出經濟其他家發展教育成為多非常便方面很多吃然後未發現電腦一樣而且心不過無法企業正服務較不會臺灣曾嗎空間看到五如何國內們無對於以及之後可是當人員比先產品資訊資料比較先生地除了大陸需要像在給歲請月些名另若亦地區技術至特別其實國際不要發生參加一定其中問台北包括講造成看像常即喜歡去沒出現政治話走單位一直吧是否當然整處理歷史了解那怎麼機會家聽所有只要朋友令甚至用真六呀情況還是錢方法點任何經驗藝術你們十主要媽媽增加提出為什麼以您計畫作利用東西在條設計找之間成長能夠決定學習誰見半時代完成帶相當同學件能力別人生命下來場會議容易開發民眾事情書事實有關自組織言多愛建立相關均產生多業者解決完全的話接受知約一般推動過程管理功能手打水要求小朋友教授難我國告訴內容結果調查家庭成立選擇經營然而父母寫人類至於買尤其配合進入例如得討論依作品情形資源原因啦妳運動觀念給軟體品質經過如此嗯精神影響之過好像成參與以後於是部分另外公園透過訓練努力研究具有共同所謂下行為合作經合作目標起來考慮長意見辦法音樂連受廠商隻受到一切或是中央某女性教學極獲得真的路來快國小部份工程女人舉行句只是段根據現象人民土地面對注意這裡新聞繼續相信政策變成計劃強調學人士前前存在制度意義代表課程該沒至需求人生那些成功爸爸產業負責民間雖影響直接幾乎分實際團體價值使得類形成科技這麼當七不但往本身標準似乎應用或者動物電話態度建設事業老那麼常常字坐舉辦自我有的具目的塊條件即使好十分多少放又電影科學執行邊委員會溝通開一起張針對員工引起自然那麼安全總統此外擁有並且事件設計研究所語言嚴重故事學術片設備之外車基本實在久套達到改善死結構住皆改變拿小組支持座醫院既僅值得學者八交通階段就是申請主管申請同感覺電視母親嘛香港記者壓力快樂喝敢院也許人們談生產怕就身體規定程度積極知識作為機構而是鼓勵角色狀況專家據清楚不僅比賽玩效果越保護共開放附近上父親專業經費曾經工作願意分別重視不少歡迎小孩小時中國人顯示中共出男人避免屬於實施聲音主義行動不可只有校園興趣山表現得回來主任裡面經常不再電子受思想頭終於謝謝協助除當地正式真正低性份因素推出上價格去認識方向責任說明工業大量做逐漸心理一點供須簡單運用觀察往往規劃減少重新業務報導仍然感到開放領域有效女要從事發揮人才反而行政銀行公共媒體提高代自然社區力量啊教育部愈超過維持家長結合校長通常缺乏委員特色結果有時教師之前遠控制本否則法少原則要臉通過建議工具作業達節目智慧來自而變化同樣形式站以為健康擔任人口規劃剛特殊原來道分傳統總是前往投資加強不斷對象追求加上比思考製作台北市取得出來加入台安排兒童國中範圍老人雙方牠北京年輕結束教程式婦女找到彼此全球成本回到部而已之下等變期間非小姐整體採用根本叫歐洲正在加以充滿系列隨著早等等頗不足總分析深報告不錯在於旁笑故消費者意識公尺民族為主大眾到底願度大概對方官員發表進一步自由正確豐富國民黨戰爭怎麼樣只好明顯改革表達肯定強高興哪樹適合茶別國外關心蘇聯成績人物聽到創造不必不論尚居民不管美麗伊拉克帶來有般永遠感情兒子這樣子起全部".encode('utf-8')) +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_simsun_16_cjk.c') + +exit() + +print("Generating 12 px") +os.system("./built_in_font_gen.py --size 12 -o lv_font_montserrat_12.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_12.c') + +print("\nGenerating 14 px") +os.system("./built_in_font_gen.py --size 14 -o lv_font_montserrat_14.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_14.c') + +print("\nGenerating 16 px") +os.system("./built_in_font_gen.py --size 16 -o lv_font_montserrat_16.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_16.c') + +print("\nGenerating 18 px") +os.system("./built_in_font_gen.py --size 18 -o lv_font_montserrat_18.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_18.c') + +print("\nGenerating 20 px") +os.system("./built_in_font_gen.py --size 20 -o lv_font_montserrat_20.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_20.c') + +print("\nGenerating 22 px") +os.system("./built_in_font_gen.py --size 22 -o lv_font_montserrat_22.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_22.c') + +print("\nGenerating 24 px") +os.system("./built_in_font_gen.py --size 24 -o lv_font_montserrat_24.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_24.c') + +print("\nGenerating 26 px") +os.system("./built_in_font_gen.py --size 26 -o lv_font_montserrat_26.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_26.c') + +print("\nGenerating 28 px") +os.system("./built_in_font_gen.py --size 28 -o lv_font_montserrat_28.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_28.c') + +print("\nGenerating 30 px") +os.system("./built_in_font_gen.py --size 30 -o lv_font_montserrat_30.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_30.c') + +print("\nGenerating 32 px") +os.system("./built_in_font_gen.py --size 32 -o lv_font_montserrat_32.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_32.c') + +print("\nGenerating 34 px") +os.system("./built_in_font_gen.py --size 34 -o lv_font_montserrat_34.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_34.c') + +print("\nGenerating 36 px") +os.system("./built_in_font_gen.py --size 36 -o lv_font_montserrat_36.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_36.c') + +print("\nGenerating 38 px") +os.system("./built_in_font_gen.py --size 38 -o lv_font_montserrat_38.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_38.c') + +print("\nGenerating 40 px") +os.system("./built_in_font_gen.py --size 40 -o lv_font_montserrat_40.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_40.c') + +print("\nGenerating 42 px") +os.system("./built_in_font_gen.py --size 42 -o lv_font_montserrat_42.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_42.c') + +print("\nGenerating 44 px") +os.system("./built_in_font_gen.py --size 44 -o lv_font_montserrat_44.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_44.c') + +print("\nGenerating 46 px") +os.system("./built_in_font_gen.py --size 46 -o lv_font_montserrat_46.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_46.c') + +print("\nGenerating 48 px") +os.system("./built_in_font_gen.py --size 48 -o lv_font_montserrat_48.c --bpp 4") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_48.c') + +print("\nGenerating 12 px subpx") +os.system("./built_in_font_gen.py --size 12 -o lv_font_montserrat_12_subpx.c --bpp 4 --subpx") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_12_subpx.c') + +print("\nGenerating 28 px compressed") +os.system("./built_in_font_gen.py --size 28 -o lv_font_montserrat_28_compressed.c --bpp 4 --compressed") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_montserrat_28_compressed.c') + +print("\nGenerating 16 px CJK") +os.system(u"./built_in_font_gen.py --size 16 -o lv_font_simsun_16_cjk.c --bpp 4 --font SimSun.woff -r 0x20-0x7f --symbols 一在有個我不這了他也就人都說而我們你了要會對及和與以很種的大能著她那上但年還可以最自己為來所他們兩各可為或好等又將因為於由從更被才已者每次把三什麼問題其讓此做再所以只與則台灣卻並位想去呢學生表示到公司將如果社會看小天因此新但是它中使工作全覺得使用這些裡並由於時候知道這樣一認為時間事過向可能中國美國到和幾系統政府大家國家許多生活跟已經大學研究因本二活動該世界應四希望方式內項啊下環境一些必須文化高孩子沒有不能如開始元不同仍網路日本用中心來對雖然重要地方進行關係市場太老師提供學校應該指出經濟其他家發展教育成為多非常便方面很多吃然後未發現電腦一樣而且心不過無法企業正服務較不會臺灣曾嗎空間看到五如何國內們無對於以及之後可是當人員比先產品資訊資料比較先生地除了大陸需要像在給歲請月些名另若亦地區技術至特別其實國際不要發生參加一定其中問台北包括講造成看像常即喜歡去沒出現政治話走單位一直吧是否當然整處理歷史了解那怎麼機會家聽所有只要朋友令甚至用真六呀情況還是錢方法點任何經驗藝術你們十主要媽媽增加提出為什麼以您計畫作利用東西在條設計找之間成長能夠決定學習誰見半時代完成帶相當同學件能力別人生命下來場會議容易開發民眾事情書事實有關自組織言多愛建立相關均產生多業者解決完全的話接受知約一般推動過程管理功能手打水要求小朋友教授難我國告訴內容結果調查家庭成立選擇經營然而父母寫人類至於買尤其配合進入例如得討論依作品情形資源原因啦妳運動觀念給軟體品質經過如此嗯精神影響之過好像成參與以後於是部分另外公園透過訓練努力研究具有共同所謂下行為合作經合作目標起來考慮長意見辦法音樂連受廠商隻受到一切或是中央某女性教學極獲得真的路來快國小部份工程女人舉行句只是段根據現象人民土地面對注意這裡新聞繼續相信政策變成計劃強調學人士前前存在制度意義代表課程該沒至需求人生那些成功爸爸產業負責民間雖影響直接幾乎分實際團體價值使得類形成科技這麼當七不但往本身標準似乎應用或者動物電話態度建設事業老那麼常常字坐舉辦自我有的具目的塊條件即使好十分多少放又電影科學執行邊委員會溝通開一起張針對員工引起自然那麼安全總統此外擁有並且事件設計研究所語言嚴重故事學術片設備之外車基本實在久套達到改善死結構住皆改變拿小組支持座醫院既僅值得學者八交通階段就是申請主管申請同感覺電視母親嘛香港記者壓力快樂喝敢院也許人們談生產怕就身體規定程度積極知識作為機構而是鼓勵角色狀況專家據清楚不僅比賽玩效果越保護共開放附近上父親專業經費曾經工作願意分別重視不少歡迎小孩小時中國人顯示中共出男人避免屬於實施聲音主義行動不可只有校園興趣山表現得回來主任裡面經常不再電子受思想頭終於謝謝協助除當地正式真正低性份因素推出上價格去認識方向責任說明工業大量做逐漸心理一點供須簡單運用觀察往往規劃減少重新業務報導仍然感到開放領域有效女要從事發揮人才反而行政銀行公共媒體提高代自然社區力量啊教育部愈超過維持家長結合校長通常缺乏委員特色結果有時教師之前遠控制本否則法少原則要臉通過建議工具作業達節目智慧來自而變化同樣形式站以為健康擔任人口規劃剛特殊原來道分傳統總是前往投資加強不斷對象追求加上比思考製作台北市取得出來加入台安排兒童國中範圍老人雙方牠北京年輕結束教程式婦女找到彼此全球成本回到部而已之下等變期間非小姐整體採用根本叫歐洲正在加以充滿系列隨著早等等頗不足總分析深報告不錯在於旁笑故消費者意識公尺民族為主大眾到底願度大概對方官員發表進一步自由正確豐富國民黨戰爭怎麼樣只好明顯改革表達肯定強高興哪樹適合茶別國外關心蘇聯成績人物聽到創造不必不論尚居民不管美麗伊拉克帶來有般永遠感情兒子這樣子起全部".encode('utf-8')) +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_simsun_16_cjk.c') + +print("Generating 16 px Hebrew, Persian") +os.system("./built_in_font_gen.py --size 16 -o lv_font_dejavu_16_persian_hebrew.c --bpp 4 --font DejaVuSans.ttf -r 0x20-0x7f,0x5d0-0x5ea,0x600-0x6FF,0xFB50-0xFDFF,0xFE70-0xFEFF") +os.system('sed -i \'s|#include "lvgl/lvgl.h"|#include "../../lvgl.h"|\' lv_font_dejavu_16_persian_hebrew.c') + + diff --git a/src/scripts/clang-formatter.sh b/src/scripts/clang-formatter.sh deleted file mode 100755 index d831917..0000000 --- a/src/scripts/clang-formatter.sh +++ /dev/null @@ -1,13 +0,0 @@ -clang-format-7 -style=file ../src/lv_core/*.c -i -clang-format-7 -style=file ../src/lv_draw/*.c -i -clang-format-7 -style=file ../src/lv_hal/*.c -i -clang-format-7 -style=file ../src/lv_misc/*.c -i -clang-format-7 -style=file ../src/lv_objx/*.c -i -clang-format-7 -style=file ../src/lv_themes/*.c -i - -clang-format-7 -style=file ../src/lv_core/*.h -i -clang-format-7 -style=file ../src/lv_draw/*.h -i -clang-format-7 -style=file ../src/lv_hal/*.h -i -clang-format-7 -style=file ../src/lv_misc/*.h -i -clang-format-7 -style=file ../src/lv_objx/*.h -i -clang-format-7 -style=file ../src/lv_themes/*.h -i diff --git a/src/scripts/code-format.cfg b/src/scripts/code-format.cfg new file mode 100644 index 0000000..9b0a35e --- /dev/null +++ b/src/scripts/code-format.cfg @@ -0,0 +1,50 @@ +--style=kr +--indent=spaces=4 +--indent-classes +--indent-switches +--indent-cases +--indent-preproc-block +--indent-preproc-define +--indent-col1-comments +--pad-oper +--unpad-paren +--align-pointer=middle +--align-reference=middle +--convert-tabs +--max-code-length=120 +--break-after-logical +--break-closing-braces +--attach-closing-while +--min-conditional-indent=0 +--max-continuation-indent=120 +--mode=c +--lineend=linux +--recursive +--suffix=none +--preserve-date +--formatted +--exclude=lv_conf_internal.h +--exclude=../src/lv_font/lv_font_montserrat_12.c +--exclude=../src/lv_font/lv_font_montserrat_14.c +--exclude=../src/lv_font/lv_font_montserrat_16.c +--exclude=../src/lv_font/lv_font_montserrat_18.c +--exclude=../src/lv_font/lv_font_montserrat_20.c +--exclude=../src/lv_font/lv_font_montserrat_22.c +--exclude=../src/lv_font/lv_font_montserrat_24.c +--exclude=../src/lv_font/lv_font_montserrat_26.c +--exclude=../src/lv_font/lv_font_montserrat_28.c +--exclude=../src/lv_font/lv_font_montserrat_30.c +--exclude=../src/lv_font/lv_font_montserrat_32.c +--exclude=../src/lv_font/lv_font_montserrat_34.c +--exclude=../src/lv_font/lv_font_montserrat_36.c +--exclude=../src/lv_font/lv_font_montserrat_38.c +--exclude=../src/lv_font/lv_font_montserrat_40.c +--exclude=../src/lv_font/lv_font_montserrat_42.c +--exclude=../src/lv_font/lv_font_montserrat_44.c +--exclude=../src/lv_font/lv_font_montserrat_46.c +--exclude=../src/lv_font/lv_font_montserrat_48.c +--exclude=../src/lv_font/lv_font_montserrat_12_subpx.c +--exclude=../src/lv_font/lv_font_montserrat_28_compressed.c +--exclude=../src/lv_font/lv_font_simsun_16_cjk.c +--exclude=../src/lv_font/lv_font_dejavu_16_persian_hebrew.c + diff --git a/src/scripts/code-format.sh b/src/scripts/code-format.sh new file mode 100755 index 0000000..561f433 --- /dev/null +++ b/src/scripts/code-format.sh @@ -0,0 +1 @@ +astyle --options=code-format.cfg "../src/*.c,*.h" diff --git a/src/scripts/cppcheck_run.sh b/src/scripts/cppcheck_run.sh index 1db16fc..98e594c 100755 --- a/src/scripts/cppcheck_run.sh +++ b/src/scripts/cppcheck_run.sh @@ -1,2 +1,2 @@ -cppcheck --template="{severity}\t{file}:{line}\t{id}: {message}" --enable=all ../src/ --output-file=cppcheck_res.txt --suppress=unusedFunction --suppress=preprocessorErrorDirective --force +cppcheck -j8 --template="{severity}\t{file}:{line}\t{id}: {message}" --enable=all ../src/ --output-file=cppcheck_res.txt --suppress=unusedFunction --suppress=preprocessorErrorDirective --force diff --git a/src/scripts/infer_run.sh b/src/scripts/infer_run.sh new file mode 100755 index 0000000..2d33d5b --- /dev/null +++ b/src/scripts/infer_run.sh @@ -0,0 +1,10 @@ +# https://github.com/facebook/infer +# +# Install: +# VERSION=0.17.0; \ +# curl -sSL "https://github.com/facebook/infer/releases/download/v$VERSION/infer-linux64-v$VERSION.tar.xz" \ +# | sudo tar -C /opt -xJ && \ +# sudoln -s "/opt/infer-linux64-v$VERSION/bin/infer" /usr/local/bin/infer + + +infer run -- make -j8 diff --git a/src/scripts/lv_conf_checker.py b/src/scripts/lv_conf_checker.py index c2171ff..709d681 100755 --- a/src/scripts/lv_conf_checker.py +++ b/src/scripts/lv_conf_checker.py @@ -8,18 +8,34 @@ import re fin = open("../lv_conf_template.h", "r") -fout = open("../src/lv_conf_checker.h", "w") +fout = open("../src/lv_conf_internal.h", "w") fout.write( '''/** * GENERATED FILE, DO NOT EDIT IT! - * @file lv_conf_checker.h + * @file lv_conf_internal.h * Make sure all the defines of lv_conf.h have a default value **/ -#ifndef LV_CONF_CHECKER_H -#define LV_CONF_CHECKER_H +#ifndef LV_CONF_INTERNAL_H +#define LV_CONF_INTERNAL_H +/* clang-format off */ + +#include + +#if defined(LV_CONF_PATH) +#define __LV_TO_STR_AUX(x) #x +#define __LV_TO_STR(x) __LV_TO_STR_AUX(x) +#include __LV_TO_STR(LV_CONF_PATH) +#undef __LV_TO_STR_AUX +#undef __LV_TO_STR +#elif defined(LV_CONF_INCLUDE_SIMPLE) +#include "lv_conf.h" +#else +#include "../../lv_conf.h" +#endif + ''' ) diff --git a/src/scripts/release_patch.py b/src/scripts/release_patch.py new file mode 100644 index 0000000..861b76e --- /dev/null +++ b/src/scripts/release_patch.py @@ -0,0 +1,189 @@ +import re +import os +lastNum = re.compile(r'(?:[^\d]*(\d+)[^\d]*)+') + + +def title(t): + print("\n---------------------------------") + print(t) + print("---------------------------------") + + +def cmd(c): + print("\n" + c) + os.system(c) + + +def increment(s): + """ look for the last sequence of number(s) in a string and increment """ + m = lastNum.search(s) + if m: + next = str(int(m.group(1))+1) + start, end = m.span(1) + s = s[:max(end-len(next), start)] + next + s[end:] + return s, str(next) + + +def lvgl_clone(): + title("lvgl: Clone") + cmd("git clone https://github.com/lvgl/lvgl.git") + os.chdir("./lvgl") + cmd("git co master") + +def lvgl_update_version(): + title("lvgl: Update version number") + + f = open("./src/lv_version.h", "r") + + outbuf = "" + major_ver = -1 + minor_ver = -1 + patch_ver = -1 + + for i in f.read().splitlines(): + r = re.search(r'^#define LVGL_VERSION_MAJOR ', i) + if r: + m = lastNum.search(i) + if m: major_ver = m.group(1) + + r = re.search(r'^#define LVGL_VERSION_MINOR ', i) + if r: + m = lastNum.search(i) + if m: minor_ver = m.group(1) + + r = re.search(r'^#define LVGL_VERSION_PATCH ', i) + if r: + m = lastNum.search(i) + if m: patch_ver = m.group(1) + + + r = re.search(r'^#define LVGL_VERSION_INFO ', i) + if r: + i = "#define LVGL_VERSION_INFO \"\"" + + outbuf += i + '\n' + + f.close() + + f = open("./src/lv_version.h", "w") + + f.write(outbuf) + f.close() + + s = "v" + str(major_ver) + "." + str(minor_ver) + "." + str(patch_ver) + print("New version:" + s) + return s + + + +def lvgl_update_library_json(v): + title("lvgl: Update version number in library.json") + + f = open("./library.json", "r") + + outbuf = "" + + for i in f.read().splitlines(): + r = re.search(r'"version": ', i) + if r: + i = ' "version": "' + v + '",' + + outbuf += i + '\n' + + f.close() + + f = open("./library.json", "w") + + f.write(outbuf) + f.close() + +def lvgl_commit_push(v): + title("lvgl: commit and push release") + + cmd('git ci -am "Release ' + v + '"') + cmd('git tag -a ' + v + ' -m "Release ' + v +'"') + cmd('git push origin master') + cmd('git push origin ' + v) + +def lvgl_update_api_docs(): + title("lvgl: Update API with Doxygen") + + cmd("cd scripts; doxygen"); + + +def docs_clone(): + title("docs: Clone") + os.chdir("../") + cmd("git clone --recursive https://github.com/lvgl/docs.git") + os.chdir("./docs/v7") + cmd("git co master") + +def docs_get_api(): + title("docs: Get API files") + + cmd("rm -rf xml"); + cmd("cp -r ../lvgl/docs/api_doc/xml ."); + + +def docs_update_version(v): + title("docs: Update version number") + + f = open("./conf.py", "r") + + outbuf = "" + + for i in f.read().splitlines(): + r = re.search(r'^version = ', i) + if r: + i = "version = '" + v + "'" + + r = re.search(r'^release = ', i) + if r: + i = "version = '" + v + "'" + + outbuf += i + '\n' + + f.close() + + f = open("./conf.py", "w") + + f.write(outbuf) + f.close() + +def docs_update_trans(): + title("docs: Update translations") + cmd("cd en && ./trans_push.py && ./trans_pull.py") + +def docs_build(): + title("docs: Build") + cmd("./build.py clean") + + +def docs_commit_push(v): + title("docs: Commit release") + + cmd('git add .') + cmd('git ci -am "Release ' + v + '"') + cmd('git tag -a ' + v + ' -m "Release ' + v +'"') + cmd('git push origin master') + cmd('git push origin ' + v) + +def clean_up(): + title("Clean up repos") + os.chdir("..") + cmd("rm -rf lvgl docs") + +lvgl_clone() +lvgl_update_api_docs() +ver_str = lvgl_update_version() +lvgl_update_library_json(ver_str) +lvgl_commit_push(ver_str) + +docs_clone() +docs_get_api() +docs_update_version(ver_str) +#docs_update_trans() # Zanata is not working now +docs_build() +docs_commit_push(ver_str) + +clean_up() diff --git a/src/src/lv_api_map.h b/src/src/lv_api_map.h new file mode 100644 index 0000000..f194a58 --- /dev/null +++ b/src/src/lv_api_map.h @@ -0,0 +1,189 @@ +/** + * @file lv_api_map.h + * + */ + +#ifndef LV_API_MAP_H +#define LV_API_MAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*--------------------- + * V6.0 COMPATIBILITY + *--------------------*/ +#if LV_USE_API_EXTENSION_V6 + +static inline void lv_task_once(lv_task_t * task) +{ + lv_task_set_repeat_count(task, 1); +} + +#if LV_USE_CHECKBOX + +#define lv_checkbox_set_static_text lv_checkbox_set_text_static + +#endif + +#if LV_USE_CHART + +#define lv_chart_get_point_cnt lv_chart_get_point_count + +#endif + + +#if LV_USE_DROPDOWN + +static inline void lv_dropdown_set_draw_arrow(lv_obj_t * ddlist, bool en) +{ + if(en) lv_dropdown_set_symbol(ddlist, LV_SYMBOL_DOWN); + else lv_dropdown_set_symbol(ddlist, NULL); +} + +static inline bool lv_dropdown_get_draw_arrow(lv_obj_t * ddlist) +{ + if(lv_dropdown_get_symbol(ddlist)) return true; + else return false; +} + +#define lv_dropdown_set_static_options lv_dropdown_set_options_static + +#endif + +#if LV_USE_BAR + +/** + * Make the bar symmetric to zero. The indicator will grow from zero instead of the minimum + * position. + * @param bar pointer to a bar object + * @param en true: enable disable symmetric behavior; false: disable + * @deprecated As of v7.0, you should use `lv_bar_set_type` instead. + */ +static inline void lv_bar_set_sym(lv_obj_t * bar, bool en) +{ + if(en) + lv_bar_set_type(bar, LV_BAR_TYPE_SYMMETRICAL); + else + lv_bar_set_type(bar, LV_BAR_TYPE_NORMAL); +} + +/** + * Get whether the bar is symmetric or not. + * @param bar pointer to a bar object + * @return true: symmetric is enabled; false: disable + * @deprecated As of v7.0, you should use `lv_bar_get_type` instead. + */ +static inline bool lv_bar_get_sym(lv_obj_t * bar) +{ + return lv_bar_get_type(bar) == LV_BAR_TYPE_SYMMETRICAL; +} + +#endif + +#if LV_USE_LABEL + +#define lv_label_set_static_text lv_label_set_text_static + +#endif + +#if LV_USE_SLIDER + +/** + * Make the slider symmetric to zero. The indicator will grow from zero instead of the minimum + * position. + * @param slider pointer to a bar object + * @param en true: enable disable symmetric behavior; false: disable + * @deprecated As of v7.0, you should use `lv_slider_set_type` instead. + */ +static inline void lv_slider_set_sym(lv_obj_t * slider, bool en) +{ + lv_bar_set_sym(slider, en); +} + +/** + * Get whether the slider is symmetric or not. + * @param slider pointer to a slider object + * @return true: symmetric is enabled; false: disable + * @deprecated As of v7.0, you should use `lv_slider_get_type` instead. + */ +static inline bool lv_slider_get_sym(lv_obj_t * slider) +{ + return lv_bar_get_sym(slider); +} + +#endif + +#if LV_USE_ROLLER + +/** + * Set a fixed width for the roller. + * @param roller pointer to a roller object + * @param w width + * @deprecated As of v7.0, you should use `lv_roller_set_auto_fit` and set the width normally instead. + */ +static inline void lv_roller_set_fix_width(lv_obj_t * roller, lv_coord_t w) +{ + lv_roller_set_auto_fit(roller, false); + lv_obj_set_width(roller, w); +} + + +#endif + + +#if LV_USE_PAGE +#define lv_scrlbar_mode_t lv_scrollbar_mode_t + +#define LV_SCRLBAR_MODE_OFF LV_SCROLLBAR_MODE_OFF +#define LV_SCRLBAR_MODE_ON LV_SCRILLBAR_MODE_ON +#define LV_SCRLBAR_MODE_DRAG LV_SCROLLBAR_MODE_DRAG +#define LV_SCRLBAR_MODE_AUTO LV_SCROLLBAR_MODE_AUTO +#define LV_SCRLBAR_MODE_HIDE LV_SCROLLBAR_MODE_HIDE +#define LV_SCRLBAR_MODE_UNHIDE LV_SCROLLBAR_MODE_UNHIDE + + +static inline void lv_page_set_scrlbar_mode(lv_obj_t * page, lv_scrlbar_mode_t sb_mode) +{ + lv_page_set_scrollbar_mode(page, sb_mode); +} +static inline lv_scrollbar_mode_t lv_page_get_scrlbar_mode(lv_obj_t * page) +{ + return lv_page_get_scrollbar_mode(page); +} + + +static inline lv_obj_t * lv_page_get_scrl(lv_obj_t * page) +{ + return lv_page_get_scrllable(page); +} +#endif + +#endif /*LV_USE_API_EXTENSION_V6*/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_API_MAP_H*/ diff --git a/src/src/lv_conf_internal.h b/src/src/lv_conf_internal.h new file mode 100644 index 0000000..42cf547 --- /dev/null +++ b/src/src/lv_conf_internal.h @@ -0,0 +1,1064 @@ +/** + * GENERATED FILE, DO NOT EDIT IT! + * @file lv_conf_internal.h + * Make sure all the defines of lv_conf.h have a default value +**/ + +#ifndef LV_CONF_INTERNAL_H +#define LV_CONF_INTERNAL_H +/* clang-format off */ + +#include + +#if defined(LV_CONF_PATH) +#define __LV_TO_STR_AUX(x) #x +#define __LV_TO_STR(x) __LV_TO_STR_AUX(x) +#include __LV_TO_STR(LV_CONF_PATH) +#undef __LV_TO_STR_AUX +#undef __LV_TO_STR +#elif defined(LV_CONF_INCLUDE_SIMPLE) +#include "lv_conf.h" +#else +#include "../../lv_conf.h" +#endif + +/* clang-format off */ + +#include + +/*==================== + Graphical settings + *====================*/ + +/* Maximal horizontal and vertical resolution to support by the library.*/ +#ifndef LV_HOR_RES_MAX +#define LV_HOR_RES_MAX (480) +#endif +#ifndef LV_VER_RES_MAX +#define LV_VER_RES_MAX (320) +#endif + +/* Color depth: + * - 1: 1 byte per pixel + * - 8: RGB332 + * - 16: RGB565 + * - 32: ARGB8888 + */ +#ifndef LV_COLOR_DEPTH +#define LV_COLOR_DEPTH 16 +#endif + +/* Swap the 2 bytes of RGB565 color. + * Useful if the display has a 8 bit interface (e.g. SPI)*/ +#ifndef LV_COLOR_16_SWAP +#define LV_COLOR_16_SWAP 0 +#endif + +/* 1: Enable screen transparency. + * Useful for OSD or other overlapping GUIs. + * Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/ +#ifndef LV_COLOR_SCREEN_TRANSP +#define LV_COLOR_SCREEN_TRANSP 0 +#endif + +/*Images pixels with this color will not be drawn (with chroma keying)*/ +#ifndef LV_COLOR_TRANSP +#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ +#endif + +/* Enable anti-aliasing (lines, and radiuses will be smoothed) */ +#ifndef LV_ANTIALIAS +#define LV_ANTIALIAS 1 +#endif + +/* Default display refresh period. + * Can be changed in the display driver (`lv_disp_drv_t`).*/ +#ifndef LV_DISP_DEF_REFR_PERIOD +#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ +#endif + +/* Dot Per Inch: used to initialize default sizes. + * E.g. a button with width = LV_DPI / 2 -> half inch wide + * (Not so important, you can adjust it to modify default sizes and spaces)*/ +#ifndef LV_DPI +#define LV_DPI 130 /*[px]*/ +#endif + +/* The the real width of the display changes some default values: + * default object sizes, layout of examples, etc. + * According to the width of the display (hor. res. / dpi) + * the displays fall in 4 categories. + * The 4th is extra large which has no upper limit so not listed here + * The upper limit of the categories are set below in 0.1 inch unit. + */ +#ifndef LV_DISP_SMALL_LIMIT +#define LV_DISP_SMALL_LIMIT 30 +#endif +#ifndef LV_DISP_MEDIUM_LIMIT +#define LV_DISP_MEDIUM_LIMIT 50 +#endif +#ifndef LV_DISP_LARGE_LIMIT +#define LV_DISP_LARGE_LIMIT 70 +#endif + +/* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ + +/*========================= + Memory manager settings + *=========================*/ + +/* LittelvGL's internal memory manager's settings. + * The graphical objects and other related data are stored here. */ + +/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ +#ifndef LV_MEM_CUSTOM +#define LV_MEM_CUSTOM 0 +#endif +#if LV_MEM_CUSTOM == 0 +/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ +#ifndef LV_MEM_SIZE +# define LV_MEM_SIZE (32U * 1024U) +#endif + +/* Complier prefix for a big array declaration */ +#ifndef LV_MEM_ATTR +# define LV_MEM_ATTR +#endif + +/* Set an address for the memory pool instead of allocating it as an array. + * Can be in external SRAM too. */ +#ifndef LV_MEM_ADR +# define LV_MEM_ADR 0 +#endif + +/* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ +#ifndef LV_MEM_AUTO_DEFRAG +# define LV_MEM_AUTO_DEFRAG 1 +#endif +#else /*LV_MEM_CUSTOM*/ +#ifndef LV_MEM_CUSTOM_INCLUDE +# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ +#endif +#ifndef LV_MEM_CUSTOM_ALLOC +# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ +#endif +#ifndef LV_MEM_CUSTOM_FREE +# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ +#endif +#endif /*LV_MEM_CUSTOM*/ + +/* Garbage Collector settings + * Used if lvgl is binded to higher level language and the memory is managed by that language */ +#ifndef LV_ENABLE_GC +#define LV_ENABLE_GC 0 +#endif +#if LV_ENABLE_GC != 0 +#ifndef LV_GC_INCLUDE +# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ +#endif +#ifndef LV_MEM_CUSTOM_REALLOC +# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/ +#endif +#ifndef LV_MEM_CUSTOM_GET_SIZE +# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/ +#endif +#endif /* LV_ENABLE_GC */ + +/*======================= + Input device settings + *=======================*/ + +/* Input device default settings. + * Can be changed in the Input device driver (`lv_indev_drv_t`)*/ + +/* Input device read period in milliseconds */ +#ifndef LV_INDEV_DEF_READ_PERIOD +#define LV_INDEV_DEF_READ_PERIOD 30 +#endif + +/* Drag threshold in pixels */ +#ifndef LV_INDEV_DEF_DRAG_LIMIT +#define LV_INDEV_DEF_DRAG_LIMIT 10 +#endif + +/* Drag throw slow-down in [%]. Greater value -> faster slow-down */ +#ifndef LV_INDEV_DEF_DRAG_THROW +#define LV_INDEV_DEF_DRAG_THROW 10 +#endif + +/* Long press time in milliseconds. + * Time to send `LV_EVENT_LONG_PRESSSED`) */ +#ifndef LV_INDEV_DEF_LONG_PRESS_TIME +#define LV_INDEV_DEF_LONG_PRESS_TIME 400 +#endif + +/* Repeated trigger period in long press [ms] + * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ +#ifndef LV_INDEV_DEF_LONG_PRESS_REP_TIME +#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 +#endif + + +/* Gesture threshold in pixels */ +#ifndef LV_INDEV_DEF_GESTURE_LIMIT +#define LV_INDEV_DEF_GESTURE_LIMIT 50 +#endif + +/* Gesture min velocity at release before swipe (pixels)*/ +#ifndef LV_INDEV_DEF_GESTURE_MIN_VELOCITY +#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 +#endif + +/*================== + * Feature usage + *==================*/ + +/*1: Enable the Animations */ +#ifndef LV_USE_ANIMATION +#define LV_USE_ANIMATION 1 +#endif +#if LV_USE_ANIMATION + +/*Declare the type of the user data of animations (can be e.g. `void *`, `int`, `struct`)*/ + +#endif + +/* 1: Enable shadow drawing*/ +#ifndef LV_USE_SHADOW +#define LV_USE_SHADOW 1 +#endif +#if LV_USE_SHADOW +/* Allow buffering some shadow calculation + * LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, + * where shadow size is `shadow_width + radius` + * Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ +#ifndef LV_SHADOW_CACHE_SIZE +#define LV_SHADOW_CACHE_SIZE 0 +#endif +#endif + +/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/ +#ifndef LV_USE_BLEND_MODES +#define LV_USE_BLEND_MODES 1 +#endif + +/* 1: Use the `opa_scale` style property to set the opacity of an object and its children at once*/ +#ifndef LV_USE_OPA_SCALE +#define LV_USE_OPA_SCALE 1 +#endif + +/* 1: Use image zoom and rotation*/ +#ifndef LV_USE_IMG_TRANSFORM +#define LV_USE_IMG_TRANSFORM 1 +#endif + +/* 1: Enable object groups (for keyboard/encoder navigation) */ +#ifndef LV_USE_GROUP +#define LV_USE_GROUP 1 +#endif +#if LV_USE_GROUP +#endif /*LV_USE_GROUP*/ + +/* 1: Enable GPU interface*/ +#ifndef LV_USE_GPU +#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ +#endif +#ifndef LV_USE_GPU_STM32_DMA2D +#define LV_USE_GPU_STM32_DMA2D 0 +#endif + +/* 1: Enable file system (might be required for images */ +#ifndef LV_USE_FILESYSTEM +#define LV_USE_FILESYSTEM 1 +#endif +#if LV_USE_FILESYSTEM +/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ +#endif + +/*1: Add a `user_data` to drivers and objects*/ +#ifndef LV_USE_USER_DATA +#define LV_USE_USER_DATA 0 +#endif + +/*1: Show CPU usage and FPS count in the right bottom corner*/ +#ifndef LV_USE_PERF_MONITOR +#define LV_USE_PERF_MONITOR 0 +#endif + +/*1: Use the functions and types from the older API if possible */ +#ifndef LV_USE_API_EXTENSION_V6 +#define LV_USE_API_EXTENSION_V6 1 +#endif + +/*======================== + * Image decoder and cache + *========================*/ + +/* 1: Enable indexed (palette) images */ +#ifndef LV_IMG_CF_INDEXED +#define LV_IMG_CF_INDEXED 1 +#endif + +/* 1: Enable alpha indexed images */ +#ifndef LV_IMG_CF_ALPHA +#define LV_IMG_CF_ALPHA 1 +#endif + +/* Default image cache size. Image caching keeps the images opened. + * If only the built-in image formats are used there is no real advantage of caching. + * (I.e. no new image decoder is added) + * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. + * However the opened images might consume additional RAM. + * LV_IMG_CACHE_DEF_SIZE must be >= 1 */ +#ifndef LV_IMG_CACHE_DEF_SIZE +#define LV_IMG_CACHE_DEF_SIZE 1 +#endif + +/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ + +/*===================== + * Compiler settings + *====================*/ +/* Define a custom attribute to `lv_tick_inc` function */ +#ifndef LV_ATTRIBUTE_TICK_INC +#define LV_ATTRIBUTE_TICK_INC +#endif + +/* Define a custom attribute to `lv_task_handler` function */ +#ifndef LV_ATTRIBUTE_TASK_HANDLER +#define LV_ATTRIBUTE_TASK_HANDLER +#endif + +/* Define a custom attribute to `lv_disp_flush_ready` function */ +#ifndef LV_ATTRIBUTE_FLUSH_READY +#define LV_ATTRIBUTE_FLUSH_READY +#endif + +/* With size optimization (-Os) the compiler might not align data to + * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. + * E.g. __attribute__((aligned(4))) */ +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +/* Attribute to mark large constant arrays for example + * font's bitmaps */ +#ifndef LV_ATTRIBUTE_LARGE_CONST +#define LV_ATTRIBUTE_LARGE_CONST +#endif + +/* Prefix performance critical functions to place them into a faster memory (e.g RAM) + * Uses 15-20 kB extra memory */ +#ifndef LV_ATTRIBUTE_FAST_MEM +#define LV_ATTRIBUTE_FAST_MEM +#endif + +/* Export integer constant to binding. + * This macro is used with constants in the form of LV_ that + * should also appear on lvgl binding API such as Micropython + * + * The default value just prevents a GCC warning. + */ +#ifndef LV_EXPORT_CONST_INT +#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning +#endif + +/*=================== + * HAL settings + *==================*/ + +/* 1: use a custom tick source. + * It removes the need to manually update the tick with `lv_tick_inc`) */ +#ifndef LV_TICK_CUSTOM +#define LV_TICK_CUSTOM 0 +#endif +#if LV_TICK_CUSTOM == 1 +#ifndef LV_TICK_CUSTOM_INCLUDE +#define LV_TICK_CUSTOM_INCLUDE "something.h" /*Header for the sys time function*/ +#endif +#ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR +#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current systime in ms*/ +#endif +#endif /*LV_TICK_CUSTOM*/ + + +/*================ + * Log settings + *===============*/ + +/*1: Enable the log module*/ +#ifndef LV_USE_LOG +#define LV_USE_LOG 0 +#endif +#if LV_USE_LOG +/* How important log should be added: + * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information + * LV_LOG_LEVEL_INFO Log important events + * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem + * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail + * LV_LOG_LEVEL_NONE Do not log anything + */ +#ifndef LV_LOG_LEVEL +# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN +#endif + +/* 1: Print the log with 'printf'; + * 0: user need to register a callback with `lv_log_register_print_cb`*/ +#ifndef LV_LOG_PRINTF +# define LV_LOG_PRINTF 0 +#endif +#endif /*LV_USE_LOG*/ + +/*================= + * Debug settings + *================*/ + +/* If Debug is enabled LittelvGL validates the parameters of the functions. + * If an invalid parameter is found an error log message is printed and + * the MCU halts at the error. (`LV_USE_LOG` should be enabled) + * If you are debugging the MCU you can pause + * the debugger to see exactly where the issue is. + * + * The behavior of asserts can be overwritten by redefining them here. + * E.g. #define LV_ASSERT_MEM(p) + */ +#ifndef LV_USE_DEBUG +#define LV_USE_DEBUG 1 +#endif +#if LV_USE_DEBUG + +/*Check if the parameter is NULL. (Quite fast) */ +#ifndef LV_USE_ASSERT_NULL +#define LV_USE_ASSERT_NULL 1 +#endif + +/*Checks is the memory is successfully allocated or no. (Quite fast)*/ +#ifndef LV_USE_ASSERT_MEM +#define LV_USE_ASSERT_MEM 1 +#endif + +/*Check the integrity of `lv_mem` after critical operations. (Slow)*/ +#ifndef LV_USE_ASSERT_MEM_INTEGRITY +#define LV_USE_ASSERT_MEM_INTEGRITY 0 +#endif + +/* Check the strings. + * Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow) + * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ +#ifndef LV_USE_ASSERT_STR +#define LV_USE_ASSERT_STR 0 +#endif + +/* Check NULL, the object's type and existence (e.g. not deleted). (Quite slow) + * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ +#ifndef LV_USE_ASSERT_OBJ +#define LV_USE_ASSERT_OBJ 0 +#endif + +/*Check if the styles are properly initialized. (Fast)*/ +#ifndef LV_USE_ASSERT_STYLE +#define LV_USE_ASSERT_STYLE 0 +#endif + +#endif /*LV_USE_DEBUG*/ + +/*================== + * FONT USAGE + *===================*/ + +/* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel. + * The symbols are available via `LV_SYMBOL_...` defines + * More info about fonts: https://docs.lvgl.com/#Fonts + * To create a new font go to: https://lvgl.com/ttf-font-to-c-array + */ + +/* Montserrat fonts with bpp = 4 + * https://fonts.google.com/specimen/Montserrat */ +#ifndef LV_FONT_MONTSERRAT_12 +#define LV_FONT_MONTSERRAT_12 0 +#endif +#ifndef LV_FONT_MONTSERRAT_14 +#define LV_FONT_MONTSERRAT_14 0 +#endif +#ifndef LV_FONT_MONTSERRAT_16 +#define LV_FONT_MONTSERRAT_16 1 +#endif +#ifndef LV_FONT_MONTSERRAT_18 +#define LV_FONT_MONTSERRAT_18 0 +#endif +#ifndef LV_FONT_MONTSERRAT_20 +#define LV_FONT_MONTSERRAT_20 0 +#endif +#ifndef LV_FONT_MONTSERRAT_22 +#define LV_FONT_MONTSERRAT_22 0 +#endif +#ifndef LV_FONT_MONTSERRAT_24 +#define LV_FONT_MONTSERRAT_24 0 +#endif +#ifndef LV_FONT_MONTSERRAT_26 +#define LV_FONT_MONTSERRAT_26 0 +#endif +#ifndef LV_FONT_MONTSERRAT_28 +#define LV_FONT_MONTSERRAT_28 0 +#endif +#ifndef LV_FONT_MONTSERRAT_30 +#define LV_FONT_MONTSERRAT_30 0 +#endif +#ifndef LV_FONT_MONTSERRAT_32 +#define LV_FONT_MONTSERRAT_32 0 +#endif +#ifndef LV_FONT_MONTSERRAT_34 +#define LV_FONT_MONTSERRAT_34 0 +#endif +#ifndef LV_FONT_MONTSERRAT_36 +#define LV_FONT_MONTSERRAT_36 0 +#endif +#ifndef LV_FONT_MONTSERRAT_38 +#define LV_FONT_MONTSERRAT_38 0 +#endif +#ifndef LV_FONT_MONTSERRAT_40 +#define LV_FONT_MONTSERRAT_40 0 +#endif +#ifndef LV_FONT_MONTSERRAT_42 +#define LV_FONT_MONTSERRAT_42 0 +#endif +#ifndef LV_FONT_MONTSERRAT_44 +#define LV_FONT_MONTSERRAT_44 0 +#endif +#ifndef LV_FONT_MONTSERRAT_46 +#define LV_FONT_MONTSERRAT_46 0 +#endif +#ifndef LV_FONT_MONTSERRAT_48 +#define LV_FONT_MONTSERRAT_48 0 +#endif + +/* Demonstrate special features */ +#ifndef LV_FONT_MONTSERRAT_12_SUBPX +#define LV_FONT_MONTSERRAT_12_SUBPX 0 +#endif +#ifndef LV_FONT_MONTSERRAT_28_COMPRESSED +#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ +#endif +#ifndef LV_FONT_DEJAVU_16_PERSIAN_HEBREW +#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, PErisan letters and all their forms*/ +#endif +#ifndef LV_FONT_SIMSUN_16_CJK +#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ +#endif + +/*Pixel perfect monospace font + * http://pelulamu.net/unscii/ */ +#ifndef LV_FONT_UNSCII_8 +#define LV_FONT_UNSCII_8 0 +#endif + +/* Optionally declare your custom fonts here. + * You can use these fonts as default font too + * and they will be available globally. E.g. + * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \ + * LV_FONT_DECLARE(my_font_2) + */ +#ifndef LV_FONT_CUSTOM_DECLARE +#define LV_FONT_CUSTOM_DECLARE +#endif + +/* Enable it if you have fonts with a lot of characters. + * The limit depends on the font size, font face and bpp + * but with > 10,000 characters if you see issues probably you need to enable it.*/ +#ifndef LV_FONT_FMT_TXT_LARGE +#define LV_FONT_FMT_TXT_LARGE 0 +#endif + +/* Set the pixel order of the display. + * Important only if "subpx fonts" are used. + * With "normal" font it doesn't matter. + */ +#ifndef LV_FONT_SUBPX_BGR +#define LV_FONT_SUBPX_BGR 0 +#endif + +/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ + +/*================ + * THEME USAGE + *================*/ + +/*Always enable at least on theme*/ + +/* No theme, you can apply your styles as you need + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ +#ifndef LV_USE_THEME_EMPTY + #define LV_USE_THEME_EMPTY 1 +#endif + +/*Simple to the create your theme based on it + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ +#ifndef LV_USE_THEME_TEMPLATE + #define LV_USE_THEME_TEMPLATE 1 +#endif + +/* A fast and impressive theme. + * Flags: + * LV_THEME_MATERIAL_FLAG_LIGHT: light theme + * LV_THEME_MATERIAL_FLAG_DARK: dark theme*/ +#ifndef LV_USE_THEME_MATERIAL + #define LV_USE_THEME_MATERIAL 1 +#endif + +/* Mono-color theme for monochrome displays. + * If LV_THEME_DEFAULT_COLOR_PRIMARY is LV_COLOR_BLACK the + * texts and borders will be black and the background will be + * white. Else the colors are inverted. + * No flags. Set LV_THEME_DEFAULT_FLAG 0 */ +#ifndef LV_USE_THEME_MONO + #define LV_USE_THEME_MONO 1 +#endif + +#ifndef LV_THEME_DEFAULT_INCLUDE +#define LV_THEME_DEFAULT_INCLUDE /*Include a header for the init. function*/ +#endif +#ifndef LV_THEME_DEFAULT_INIT +#define LV_THEME_DEFAULT_INIT lv_theme_material_init +#endif +#ifndef LV_THEME_DEFAULT_COLOR_PRIMARY +#define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED +#endif +#ifndef LV_THEME_DEFAULT_COLOR_SECONDARY +#define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE +#endif +#ifndef LV_THEME_DEFAULT_FLAG +#define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT +#endif +#ifndef LV_THEME_DEFAULT_FONT_SMALL +#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_16 +#endif +#ifndef LV_THEME_DEFAULT_FONT_NORMAL +#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_16 +#endif +#ifndef LV_THEME_DEFAULT_FONT_SUBTITLE +#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_16 +#endif +#ifndef LV_THEME_DEFAULT_FONT_TITLE +#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_16 +#endif + +/*================= + * Text settings + *=================*/ + +/* Select a character encoding for strings. + * Your IDE or editor should have the same character encoding + * - LV_TXT_ENC_UTF8 + * - LV_TXT_ENC_ASCII + * */ +#ifndef LV_TXT_ENC +#define LV_TXT_ENC LV_TXT_ENC_UTF8 +#endif + + /*Can break (wrap) texts on these chars*/ +#ifndef LV_TXT_BREAK_CHARS +#define LV_TXT_BREAK_CHARS " ,.;:-_" +#endif + +/* If a word is at least this long, will break wherever "prettiest" + * To disable, set to a value <= 0 */ +#ifndef LV_TXT_LINE_BREAK_LONG_LEN +#define LV_TXT_LINE_BREAK_LONG_LEN 0 +#endif + +/* Minimum number of characters in a long word to put on a line before a break. + * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ +#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN +#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 +#endif + +/* Minimum number of characters in a long word to put on a line after a break. + * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ +#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN +#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 +#endif + +/* The control character to use for signalling text recoloring. */ +#ifndef LV_TXT_COLOR_CMD +#define LV_TXT_COLOR_CMD "#" +#endif + +/* Support bidirectional texts. + * Allows mixing Left-to-Right and Right-to-Left texts. + * The direction will be processed according to the Unicode Bidirectioanl Algorithm: + * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#ifndef LV_USE_BIDI +#define LV_USE_BIDI 0 +#endif +#if LV_USE_BIDI +/* Set the default direction. Supported values: + * `LV_BIDI_DIR_LTR` Left-to-Right + * `LV_BIDI_DIR_RTL` Right-to-Left + * `LV_BIDI_DIR_AUTO` detect texts base direction */ +#ifndef LV_BIDI_BASE_DIR_DEF +#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO +#endif +#endif + +/* Enable Arabic/Persian processing + * In these languages characters should be replaced with + * an other form based on their position in the text */ +#ifndef LV_USE_ARABIC_PERSIAN_CHARS +#define LV_USE_ARABIC_PERSIAN_CHARS 0 +#endif + +/*Change the built in (v)snprintf functions*/ +#ifndef LV_SPRINTF_CUSTOM +#define LV_SPRINTF_CUSTOM 0 +#endif +#if LV_SPRINTF_CUSTOM +#ifndef LV_SPRINTF_INCLUDE +# define LV_SPRINTF_INCLUDE +#endif +#ifndef lv_snprintf +# define lv_snprintf snprintf +#endif +#ifndef lv_vsnprintf +# define lv_vsnprintf vsnprintf +#endif +#else /*!LV_SPRINTF_CUSTOM*/ +#ifndef LV_SPRINTF_DISABLE_FLOAT +# define LV_SPRINTF_DISABLE_FLOAT 1 +#endif +#endif /*LV_SPRINTF_CUSTOM*/ + +/*=================== + * LV_OBJ SETTINGS + *==================*/ + +#if LV_USE_USER_DATA +/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ +/*Provide a function to free user data*/ +#ifndef LV_USE_USER_DATA_FREE +#define LV_USE_USER_DATA_FREE 0 +#endif +#if LV_USE_USER_DATA_FREE +#ifndef LV_USER_DATA_FREE_INCLUDE +# define LV_USER_DATA_FREE_INCLUDE "something.h" /*Header for user data free function*/ +#endif +/* Function prototype : void user_data_free(lv_obj_t * obj); */ +#ifndef LV_USER_DATA_FREE +# define LV_USER_DATA_FREE (user_data_free) /*Invoking for user data free function*/ +#endif +#endif +#endif + +/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ +#ifndef LV_USE_OBJ_REALIGN +#define LV_USE_OBJ_REALIGN 1 +#endif + +/* Enable to make the object clickable on a larger area. + * LV_EXT_CLICK_AREA_OFF or 0: Disable this feature + * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) + * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) + */ +#ifndef LV_USE_EXT_CLICK_AREA +#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_TINY +#endif + +/*================== + * LV OBJ X USAGE + *================*/ +/* + * Documentation of the object types: https://docs.lvgl.com/#Object-types + */ + +/*Arc (dependencies: -)*/ +#ifndef LV_USE_ARC +#define LV_USE_ARC 1 +#endif + +/*Bar (dependencies: -)*/ +#ifndef LV_USE_BAR +#define LV_USE_BAR 1 +#endif + +/*Button (dependencies: lv_cont*/ +#ifndef LV_USE_BTN +#define LV_USE_BTN 1 +#endif + +/*Button matrix (dependencies: -)*/ +#ifndef LV_USE_BTNMATRIX +#define LV_USE_BTNMATRIX 1 +#endif + +/*Calendar (dependencies: -)*/ +#ifndef LV_USE_CALENDAR +#define LV_USE_CALENDAR 1 +#endif + +/*Canvas (dependencies: lv_img)*/ +#ifndef LV_USE_CANVAS +#define LV_USE_CANVAS 1 +#endif + +/*Check box (dependencies: lv_btn, lv_label)*/ +#ifndef LV_USE_CHECKBOX +#define LV_USE_CHECKBOX 1 +#endif + +/*Chart (dependencies: -)*/ +#ifndef LV_USE_CHART +#define LV_USE_CHART 1 +#endif +#if LV_USE_CHART +#ifndef LV_CHART_AXIS_TICK_LABEL_MAX_LEN +# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 256 +#endif +#endif + +/*Container (dependencies: -*/ +#ifndef LV_USE_CONT +#define LV_USE_CONT 1 +#endif + +/*Color picker (dependencies: -*/ +#ifndef LV_USE_CPICKER +#define LV_USE_CPICKER 1 +#endif + +/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ +#ifndef LV_USE_DROPDOWN +#define LV_USE_DROPDOWN 1 +#endif +#if LV_USE_DROPDOWN != 0 +/*Open and close default animation time [ms] (0: no animation)*/ +#ifndef LV_DROPDOWN_DEF_ANIM_TIME +# define LV_DROPDOWN_DEF_ANIM_TIME 200 +#endif +#endif + +/*Gauge (dependencies:lv_bar, lv_linemeter)*/ +#ifndef LV_USE_GAUGE +#define LV_USE_GAUGE 1 +#endif + +/*Image (dependencies: lv_label*/ +#ifndef LV_USE_IMG +#define LV_USE_IMG 1 +#endif + +/*Image Button (dependencies: lv_btn*/ +#ifndef LV_USE_IMGBTN +#define LV_USE_IMGBTN 1 +#endif +#if LV_USE_IMGBTN +/*1: The imgbtn requires left, mid and right parts and the width can be set freely*/ +#ifndef LV_IMGBTN_TILED +# define LV_IMGBTN_TILED 0 +#endif +#endif + +/*Keyboard (dependencies: lv_btnm)*/ +#ifndef LV_USE_KEYBOARD +#define LV_USE_KEYBOARD 1 +#endif + +/*Label (dependencies: -*/ +#ifndef LV_USE_LABEL +#define LV_USE_LABEL 1 +#endif +#if LV_USE_LABEL != 0 +/*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ +#ifndef LV_LABEL_DEF_SCROLL_SPEED +# define LV_LABEL_DEF_SCROLL_SPEED 25 +#endif + +/* Waiting period at beginning/end of animation cycle */ +#ifndef LV_LABEL_WAIT_CHAR_COUNT +# define LV_LABEL_WAIT_CHAR_COUNT 3 +#endif + +/*Enable selecting text of the label */ +#ifndef LV_LABEL_TEXT_SEL +# define LV_LABEL_TEXT_SEL 0 +#endif + +/*Store extra some info in labels (12 bytes) to speed up drawing of very long texts*/ +#ifndef LV_LABEL_LONG_TXT_HINT +# define LV_LABEL_LONG_TXT_HINT 0 +#endif +#endif + +/*LED (dependencies: -)*/ +#ifndef LV_USE_LED +#define LV_USE_LED 1 +#endif +#if LV_USE_LED +#ifndef LV_LED_BRIGHT_MIN +# define LV_LED_BRIGHT_MIN 120 /*Minimal brightness*/ +#endif +#ifndef LV_LED_BRIGHT_MAX +# define LV_LED_BRIGHT_MAX 255 /*Maximal brightness*/ +#endif +#endif + +/*Line (dependencies: -*/ +#ifndef LV_USE_LINE +#define LV_USE_LINE 1 +#endif + +/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/ +#ifndef LV_USE_LIST +#define LV_USE_LIST 1 +#endif +#if LV_USE_LIST != 0 +/*Default animation time of focusing to a list element [ms] (0: no animation) */ +#ifndef LV_LIST_DEF_ANIM_TIME +# define LV_LIST_DEF_ANIM_TIME 100 +#endif +#endif + +/*Line meter (dependencies: *;)*/ +#ifndef LV_USE_LINEMETER +#define LV_USE_LINEMETER 1 +#endif +#if LV_USE_LINEMETER +/* Draw line more precisely at cost of performance. + * Useful if there are lot of lines any minor are visible + * 0: No extra precision + * 1: Some extra precision + * 2: Best precision + */ +#ifndef LV_LINEMETER_PRECISE +# define LV_LINEMETER_PRECISE 0 +#endif +#endif + +/*Mask (dependencies: -)*/ +#ifndef LV_USE_OBJMASK +#define LV_USE_OBJMASK 1 +#endif + +/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ +#ifndef LV_USE_MSGBOX +#define LV_USE_MSGBOX 1 +#endif + +/*Page (dependencies: lv_cont)*/ +#ifndef LV_USE_PAGE +#define LV_USE_PAGE 1 +#endif +#if LV_USE_PAGE != 0 +/*Focus default animation time [ms] (0: no animation)*/ +#ifndef LV_PAGE_DEF_ANIM_TIME +# define LV_PAGE_DEF_ANIM_TIME 400 +#endif +#endif + +/*Preload (dependencies: lv_arc, lv_anim)*/ +#ifndef LV_USE_SPINNER +#define LV_USE_SPINNER 1 +#endif +#if LV_USE_SPINNER != 0 +#ifndef LV_SPINNER_DEF_ARC_LENGTH +# define LV_SPINNER_DEF_ARC_LENGTH 60 /*[deg]*/ +#endif +#ifndef LV_SPINNER_DEF_SPIN_TIME +# define LV_SPINNER_DEF_SPIN_TIME 1000 /*[ms]*/ +#endif +#ifndef LV_SPINNER_DEF_ANIM +# define LV_SPINNER_DEF_ANIM LV_SPINNER_TYPE_SPINNING_ARC +#endif +#endif + +/*Roller (dependencies: lv_ddlist)*/ +#ifndef LV_USE_ROLLER +#define LV_USE_ROLLER 1 +#endif +#if LV_USE_ROLLER != 0 +/*Focus animation time [ms] (0: no animation)*/ +#ifndef LV_ROLLER_DEF_ANIM_TIME +# define LV_ROLLER_DEF_ANIM_TIME 200 +#endif + +/*Number of extra "pages" when the roller is infinite*/ +#ifndef LV_ROLLER_INF_PAGES +# define LV_ROLLER_INF_PAGES 7 +#endif +#endif + +/*Slider (dependencies: lv_bar)*/ +#ifndef LV_USE_SLIDER +#define LV_USE_SLIDER 1 +#endif + +/*Spinbox (dependencies: lv_ta)*/ +#ifndef LV_USE_SPINBOX +#define LV_USE_SPINBOX 1 +#endif + +/*Switch (dependencies: lv_slider)*/ +#ifndef LV_USE_SWITCH +#define LV_USE_SWITCH 1 +#endif + +/*Text area (dependencies: lv_label, lv_page)*/ +#ifndef LV_USE_TEXTAREA +#define LV_USE_TEXTAREA 1 +#endif +#if LV_USE_TEXTAREA != 0 +#ifndef LV_TEXTAREA_DEF_CURSOR_BLINK_TIME +# define LV_TEXTAREA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ +#endif +#ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME +# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#endif +#endif + +/*Table (dependencies: lv_label)*/ +#ifndef LV_USE_TABLE +#define LV_USE_TABLE 1 +#endif +#if LV_USE_TABLE +#ifndef LV_TABLE_COL_MAX +# define LV_TABLE_COL_MAX 12 +#endif +#endif + +/*Tab (dependencies: lv_page, lv_btnm)*/ +#ifndef LV_USE_TABVIEW +#define LV_USE_TABVIEW 1 +#endif +# if LV_USE_TABVIEW != 0 +/*Time of slide animation [ms] (0: no animation)*/ +#ifndef LV_TABVIEW_DEF_ANIM_TIME +# define LV_TABVIEW_DEF_ANIM_TIME 300 +#endif +#endif + +/*Tileview (dependencies: lv_page) */ +#ifndef LV_USE_TILEVIEW +#define LV_USE_TILEVIEW 1 +#endif +#if LV_USE_TILEVIEW +/*Time of slide animation [ms] (0: no animation)*/ +#ifndef LV_TILEVIEW_DEF_ANIM_TIME +# define LV_TILEVIEW_DEF_ANIM_TIME 300 +#endif +#endif + +/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ +#ifndef LV_USE_WIN +#define LV_USE_WIN 1 +#endif + +/*================== + * Non-user section + *==================*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/ +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif +#endif + + +#endif /*LV_CONF_CHECKER_H*/ diff --git a/src/src/lv_core/lv_core.mk b/src/src/lv_core/lv_core.mk index eb1c5e0..d7f0924 100644 --- a/src/src/lv_core/lv_core.mk +++ b/src/src/lv_core/lv_core.mk @@ -6,7 +6,7 @@ CSRCS += lv_refr.c CSRCS += lv_style.c CSRCS += lv_debug.c -DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_core -VPATH += :$(LVGL_DIR)/lvgl/src/lv_core +DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_core +VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_core -CFLAGS += "-I$(LVGL_DIR)/lvgl/src/lv_core" +CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_core" diff --git a/src/src/lv_core/lv_debug.c b/src/src/lv_core/lv_debug.c index 83071af..571b2f3 100644 --- a/src/src/lv_core/lv_debug.c +++ b/src/src/lv_core/lv_debug.c @@ -15,11 +15,11 @@ * DEFINES *********************/ #ifndef LV_DEBUG_STR_MAX_LENGTH -#define LV_DEBUG_STR_MAX_LENGTH (1024 * 8) + #define LV_DEBUG_STR_MAX_LENGTH (1024 * 8) #endif #ifndef LV_DEBUG_STR_MAX_REPEAT -#define LV_DEBUG_STR_MAX_REPEAT 8 + #define LV_DEBUG_STR_MAX_REPEAT 8 #endif /********************** * TYPEDEFS @@ -49,6 +49,11 @@ bool lv_debug_check_null(const void * p) return false; } +bool lv_debug_check_mem_integrity(void) +{ + return lv_mem_test() == LV_RES_OK ? true : false; +} + bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type) { if(obj_type[0] == '\0') return true; @@ -58,6 +63,7 @@ bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type) uint8_t i; for(i = 0; i < LV_MAX_ANCESTOR_NUM; i++) { + if(types.type[i] == NULL) break; if(strcmp(types.type[i], obj_type) == 0) return true; } @@ -69,7 +75,7 @@ bool lv_debug_check_obj_valid(const lv_obj_t * obj) lv_disp_t * disp = lv_disp_get_next(NULL); while(disp) { lv_obj_t * scr; - LV_LL_READ(disp->scr_ll, scr) { + _LV_LL_READ(disp->scr_ll, scr) { if(scr == obj) return true; bool found = obj_valid_child(scr, obj); @@ -87,7 +93,21 @@ bool lv_debug_check_style(const lv_style_t * style) if(style == NULL) return true; /*NULL style is still valid*/ #if LV_USE_ASSERT_STYLE - if(style->debug_sentinel != LV_STYLE_DEGUG_SENTINEL_VALUE) { + if(style->sentinel != LV_DEBUG_STYLE_SENTINEL_VALUE) { + LV_LOG_WARN("Invalid style (local variable or not initialized?)"); + return false; + } +#endif + + return true; +} + +bool lv_debug_check_style_list(const lv_style_list_t * list) +{ + if(list == NULL) return true; /*NULL list is still valid*/ + +#if LV_USE_ASSERT_STYLE + if(list->sentinel != LV_DEBUG_STYLE_LIST_SENTINEL_VALUE) { LV_LOG_WARN("Invalid style (local variable or not initialized?)"); return false; } @@ -103,11 +123,12 @@ bool lv_debug_check_str(const void * str) uint32_t rep = 0; uint32_t i; - for(i = 0; s[i] != '\0' && i < LV_DEBUG_STR_MAX_LENGTH; i++) { + for(i = 0; i < LV_DEBUG_STR_MAX_LENGTH && s[i] != '\0'; i++) { if(s[i] != last_byte) { last_byte = s[i]; rep = 1; - } else if(s[i] > 0x7F){ + } + else if(s[i] > 0x7F) { rep++; if(rep > LV_DEBUG_STR_MAX_REPEAT) { LV_LOG_WARN("lv_debug_check_str: a non-ASCII char has repeated more than LV_DEBUG_STR_MAX_REPEAT times)"); @@ -139,7 +160,7 @@ void lv_debug_log_error(const char * msg, uint64_t value) char * bufp = buf; /*Add the function name*/ - memcpy(bufp, msg, msg_len); + _lv_memcpy(bufp, msg, msg_len); bufp += msg_len; /*Add value in hey*/ @@ -165,7 +186,8 @@ void lv_debug_log_error(const char * msg, uint64_t value) *bufp = '\0'; LV_LOG_ERROR(buf); - } else { + } + else { LV_LOG_ERROR(msg); } } @@ -178,7 +200,7 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin { /*Check all children of `parent`*/ lv_obj_t * child; - LV_LL_READ(parent->child_ll, child) { + _LV_LL_READ(parent->child_ll, child) { if(child == obj_to_find) return true; /*Check the children*/ diff --git a/src/src/lv_core/lv_debug.h b/src/src/lv_core/lv_debug.h index 72eb336..3b47f7d 100644 --- a/src/src/lv_core/lv_debug.h +++ b/src/src/lv_core/lv_debug.h @@ -30,12 +30,16 @@ extern "C" { **********************/ bool lv_debug_check_null(const void * p); +bool lv_debug_check_mem_integrity(void); + bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type); bool lv_debug_check_obj_valid(const lv_obj_t * obj); bool lv_debug_check_style(const lv_style_t * style); +bool lv_debug_check_style_list(const lv_style_list_t * list); + bool lv_debug_check_str(const void * str); void lv_debug_log_error(const char * msg, uint64_t value); @@ -46,13 +50,13 @@ void lv_debug_log_error(const char * msg, uint64_t value); #ifndef LV_DEBUG_ASSERT #define LV_DEBUG_ASSERT(expr, msg, value) \ -{ \ - if(!(expr)) { \ - LV_LOG_ERROR(__func__); \ - lv_debug_log_error(msg, (uint64_t)value); \ - while(1); \ - } \ -} + do { \ + if(!(expr)) { \ + LV_LOG_ERROR(__func__); \ + lv_debug_log_error(msg, (uint64_t)((uintptr_t)value)); \ + while(1); \ + } \ + } while(0) #endif /*---------------- @@ -63,6 +67,11 @@ void lv_debug_log_error(const char * msg, uint64_t value); #define LV_DEBUG_IS_NULL(p) (lv_debug_check_null(p)) #endif + +#ifndef LV_DEBUG_CHECK_MEM_INTEGRITY +#define LV_DEBUG_CHECK_MEM_INTEGRITY() (lv_debug_check_mem_integrity()) +#endif + #ifndef LV_DEBUG_IS_STR #define LV_DEBUG_IS_STR(str) (lv_debug_check_null(str) && \ lv_debug_check_str(str)) @@ -78,6 +87,10 @@ void lv_debug_log_error(const char * msg, uint64_t value); #define LV_DEBUG_IS_STYLE(style_p) (lv_debug_check_style(style_p)) #endif +#ifndef LV_DEBUG_IS_STYLE_LIST +#define LV_DEBUG_IS_STYLE_LIST(list_p) (lv_debug_check_style_list(list_p)) +#endif + /*----------------- * ASSERTS *-----------------*/ @@ -100,6 +113,14 @@ void lv_debug_log_error(const char * msg, uint64_t value); # define LV_ASSERT_MEM(p) true #endif +#if LV_USE_ASSERT_MEM_INTEGRITY +# ifndef LV_ASSERT_MEM_INTEGRITY +# define LV_ASSERT_MEM_INTEGRITY() LV_DEBUG_ASSERT(LV_DEBUG_CHECK_MEM_INTEGRITY(), "Memory integrity error", 0); +# endif +#else +# define LV_ASSERT_MEM_INTEGRITY() true +#endif + #if LV_USE_ASSERT_STR # ifndef LV_ASSERT_STR # define LV_ASSERT_STR(str) LV_DEBUG_ASSERT(LV_DEBUG_IS_STR(str), "Strange or invalid string", str); @@ -112,7 +133,6 @@ void lv_debug_log_error(const char * msg, uint64_t value); # endif #endif - #if LV_USE_ASSERT_OBJ # ifndef LV_ASSERT_OBJ # define LV_ASSERT_OBJ(obj_p, obj_type) LV_DEBUG_ASSERT(LV_DEBUG_IS_OBJ(obj_p, obj_type), "Invalid object", obj_p); @@ -130,8 +150,12 @@ void lv_debug_log_error(const char * msg, uint64_t value); # ifndef LV_ASSERT_STYLE # define LV_ASSERT_STYLE(style_p) LV_DEBUG_ASSERT(LV_DEBUG_IS_STYLE(style_p), "Invalid style", style_p); # endif +# ifndef LV_ASSERT_STYLE_LIST +# define LV_ASSERT_STYLE_LIST(list_p) LV_DEBUG_ASSERT(LV_DEBUG_IS_STYLE_LIST(list_p), "Invalid style list", list_p); +# endif #else -# define LV_ASSERT_STYLE(style) true +# define LV_ASSERT_STYLE(style_p) true +# define LV_ASSERT_STYLE_LIST(list_p) true #endif #else /* LV_USE_DEBUG == 0 */ @@ -140,9 +164,11 @@ void lv_debug_log_error(const char * msg, uint64_t value); #define LV_ASSERT_NULL(p) true #define LV_ASSERT_MEM(p) true +#define LV_ASSERT_MEM_INTEGRITY() true #define LV_ASSERT_STR(p) true #define LV_ASSERT_OBJ(obj, obj_type) true #define LV_ASSERT_STYLE(p) true +#define LV_ASSERT_STYLE_LIST(p) true #endif /* LV_USE_DEBUG */ /*clang-format on*/ diff --git a/src/src/lv_core/lv_disp.c b/src/src/lv_core/lv_disp.c index bcb7382..37206b3 100644 --- a/src/src/lv_core/lv_disp.c +++ b/src/src/lv_core/lv_disp.c @@ -43,7 +43,7 @@ lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp) { if(!disp) disp = lv_disp_get_default(); if(!disp) { - LV_LOG_WARN("lv_scr_act: no display registered to get its top layer"); + LV_LOG_WARN("lv_scr_act: no display registered to get its act. screen"); return NULL; } @@ -57,7 +57,7 @@ lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp) void lv_disp_load_scr(lv_obj_t * scr) { lv_disp_t * d = lv_obj_get_disp(scr); - + if(!d) return; /*Shouldn't happen, just to be sure*/ d->act_scr = scr; lv_obj_invalidate(scr); @@ -89,7 +89,7 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) { if(!disp) disp = lv_disp_get_default(); if(!disp) { - LV_LOG_WARN("lv_layer_sys: no display registered to get its top layer"); + LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer"); return NULL; } @@ -112,24 +112,7 @@ void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr) if(old_disp == disp) return; - lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr, true); -} - -/** - * Get a pointer to the screen refresher task to - * modify its parameters with `lv_task_...` functions. - * @param disp pointer to a display - * @return pointer to the display refresher task. (NULL on error) - */ -lv_task_t * lv_disp_get_refr_task(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_disp_get_refr_task: no display registered"); - return NULL; - } - - return disp->refr_task; + _lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr, true); } /** @@ -151,7 +134,8 @@ uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) uint32_t t = UINT32_MAX; d = lv_disp_get_next(NULL); while(d) { - t = LV_MATH_MIN(t, lv_tick_elaps(d->last_activity_time)); + uint32_t elaps = lv_tick_elaps(d->last_activity_time); + t = LV_MATH_MIN(t, elaps); d = lv_disp_get_next(d); } @@ -173,6 +157,24 @@ void lv_disp_trig_activity(lv_disp_t * disp) disp->last_activity_time = lv_tick_get(); } + +/** + * Get a pointer to the screen refresher task to + * modify its parameters with `lv_task_...` functions. + * @param disp pointer to a display + * @return pointer to the display refresher task. (NULL on error) + */ +lv_task_t * _lv_disp_get_refr_task(lv_disp_t * disp) +{ + if(!disp) disp = lv_disp_get_default(); + if(!disp) { + LV_LOG_WARN("lv_disp_get_refr_task: no display registered"); + return NULL; + } + + return disp->refr_task; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/src/lv_core/lv_disp.h b/src/src/lv_core/lv_disp.h index 3047154..58ce214 100644 --- a/src/src/lv_core/lv_disp.h +++ b/src/src/lv_core/lv_disp.h @@ -64,14 +64,6 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp); */ void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr); -/** - * Get a pointer to the screen refresher task to - * modify its parameters with `lv_task_...` functions. - * @param disp pointer to a display - * @return pointer to the display refresher task. (NULL on error) - */ -lv_task_t * lv_disp_get_refr_task(lv_disp_t * disp); - /** * Get elapsed time since last user activity on a display (e.g. click) * @param disp pointer to an display (NULL to get the overall smallest inactivity) @@ -85,6 +77,14 @@ uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp); */ void lv_disp_trig_activity(lv_disp_t * disp); +/** + * Get a pointer to the screen refresher task to + * modify its parameters with `lv_task_...` functions. + * @param disp pointer to a display + * @return pointer to the display refresher task. (NULL on error) + */ +lv_task_t * _lv_disp_get_refr_task(lv_disp_t * disp); + /*------------------------------------------------ * To improve backward compatibility * Recommended only if you have one display @@ -145,6 +145,15 @@ static inline void lv_scr_load(lv_obj_t * scr) #define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default()) #endif + +/** + * Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP) + * 1 dip is 1 px on a 160 DPI screen + * 1 dip is 2 px on a 320 DPI screen + * https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp + */ +#define LV_DPX(n) LV_MATH_MAX((( lv_disp_get_dpi(NULL) * (n) + 80) / 160), 1) /*+80 for rounding*/ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/src/lv_core/lv_group.c b/src/src/lv_core/lv_group.c index b26de56..057c78e 100644 --- a/src/src/lv_core/lv_group.c +++ b/src/src/lv_core/lv_group.c @@ -14,7 +14,7 @@ #include "../lv_misc/lv_gc.h" #if defined(LV_GC_INCLUDE) -#include LV_GC_INCLUDE + #include LV_GC_INCLUDE #endif /* LV_ENABLE_GC */ /********************* @@ -28,9 +28,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static void style_mod_def(lv_group_t * group, lv_style_t * style); -static void style_mod_edit_def(lv_group_t * group, lv_style_t * style); -static void refresh_theme(lv_group_t * g, lv_theme_t * th); static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), void * (*move)(const lv_ll_t *, const void *)); static void lv_group_refocus(lv_group_t * g); @@ -51,9 +48,9 @@ static void obj_to_foreground(lv_obj_t * obj); /** * Init. the group module */ -void lv_group_init(void) +void _lv_group_init(void) { - lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t)); + _lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t)); } /** @@ -62,10 +59,10 @@ void lv_group_init(void) */ lv_group_t * lv_group_create(void) { - lv_group_t * group = lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll)); + lv_group_t * group = _lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll)); LV_ASSERT_MEM(group); if(group == NULL) return NULL; - lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *)); + _lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *)); group->obj_focus = NULL; group->frozen = 0; @@ -76,12 +73,9 @@ lv_group_t * lv_group_create(void) group->wrap = 1; #if LV_USE_USER_DATA - memset(&group->user_data, 0, sizeof(lv_group_user_data_t)); + _lv_memset_00(&group->user_data, sizeof(lv_group_user_data_t)); #endif - /*Initialize style modification callbacks from current theme*/ - refresh_theme(group, lv_theme_get_current()); - return group; } @@ -99,13 +93,12 @@ void lv_group_del(lv_group_t * group) /*Remove the objects from the group*/ lv_obj_t ** obj; - LV_LL_READ(group->obj_ll, obj) - { + _LV_LL_READ(group->obj_ll, obj) { (*obj)->group_p = NULL; } - lv_ll_clear(&(group->obj_ll)); - lv_ll_rem(&LV_GC_ROOT(_lv_group_ll), group); + _lv_ll_clear(&(group->obj_ll)); + _lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group); lv_mem_free(group); } @@ -117,11 +110,9 @@ void lv_group_del(lv_group_t * group) void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj) { if(group == NULL) return; - /*Do not add the object twice*/ lv_obj_t ** obj_i; - LV_LL_READ(group->obj_ll, obj_i) - { + _LV_LL_READ(group->obj_ll, obj_i) { if((*obj_i) == obj) { LV_LOG_INFO("lv_group_add_obj: the object is already added to this group"); return; @@ -138,14 +129,14 @@ void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj) } obj->group_p = group; - lv_obj_t ** next = lv_ll_ins_tail(&group->obj_ll); + lv_obj_t ** next = _lv_ll_ins_tail(&group->obj_ll); LV_ASSERT_MEM(next); if(next == NULL) return; *next = obj; /* If the head and the tail is equal then there is only one object in the linked list. * In this case automatically activate it*/ - if(lv_ll_get_head(&group->obj_ll) == next) { + if(_lv_ll_get_head(&group->obj_ll) == next) { lv_group_refocus(group); } } @@ -162,8 +153,10 @@ void lv_group_remove_obj(lv_obj_t * obj) /*Focus on the next object*/ if(*g->obj_focus == obj) { + if(g->frozen) g->frozen = 0; + /*If this is the only object in the group then focus to nothing.*/ - if(lv_ll_get_head(&g->obj_ll) == g->obj_focus && lv_ll_get_tail(&g->obj_ll) == g->obj_focus) { + if(_lv_ll_get_head(&g->obj_ll) == g->obj_focus && _lv_ll_get_tail(&g->obj_ll) == g->obj_focus) { (*g->obj_focus)->signal_cb(*g->obj_focus, LV_SIGNAL_DEFOCUS, NULL); } /*If there more objects in the group then focus to the next/prev object*/ @@ -181,10 +174,9 @@ void lv_group_remove_obj(lv_obj_t * obj) /*Search the object and remove it from its group */ lv_obj_t ** i; - LV_LL_READ(g->obj_ll, i) - { + _LV_LL_READ(g->obj_ll, i) { if(*i == obj) { - lv_ll_rem(&g->obj_ll, i); + _lv_ll_remove(&g->obj_ll, i); lv_mem_free(i); obj->group_p = NULL; break; @@ -207,12 +199,11 @@ void lv_group_remove_all_objs(lv_group_t * group) /*Remove the objects from the group*/ lv_obj_t ** obj; - LV_LL_READ(group->obj_ll, obj) - { + _LV_LL_READ(group->obj_ll, obj) { (*obj)->group_p = NULL; } - lv_ll_clear(&(group->obj_ll)); + _lv_ll_clear(&(group->obj_ll)); } /** @@ -227,12 +218,13 @@ void lv_group_focus_obj(lv_obj_t * obj) if(g->frozen != 0) return; + if(obj == *g->obj_focus) return; + /*On defocus edit mode must be leaved*/ lv_group_set_editing(g, false); lv_obj_t ** i; - LV_LL_READ(g->obj_ll, i) - { + _LV_LL_READ(g->obj_ll, i) { if(*i == obj) { if(g->obj_focus != NULL) { (*g->obj_focus)->signal_cb(*g->obj_focus, LV_SIGNAL_DEFOCUS, NULL); @@ -264,7 +256,7 @@ void lv_group_focus_obj(lv_obj_t * obj) */ void lv_group_focus_next(lv_group_t * group) { - focus_next_core(group, lv_ll_get_head, lv_ll_get_next); + focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next); } /** @@ -273,7 +265,7 @@ void lv_group_focus_next(lv_group_t * group) */ void lv_group_focus_prev(lv_group_t * group) { - focus_next_core(group, lv_ll_get_tail, lv_ll_get_prev); + focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev); } /** @@ -311,28 +303,6 @@ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) return res; } -/** - * Set a function for a group which will modify the object's style if it is in focus - * @param group pointer to a group - * @param style_mod_cb the style modifier function pointer - */ -void lv_group_set_style_mod_cb(lv_group_t * group, lv_group_style_mod_cb_t style_mod_cb) -{ - group->style_mod_cb = style_mod_cb; - if(group->obj_focus != NULL) lv_obj_invalidate(*group->obj_focus); -} - -/** - * Set a function for a group which will modify the object's style if it is in focus in edit mode - * @param group pointer to a group - * @param style_mod_func the style modifier function pointer - */ -void lv_group_set_style_mod_edit_cb(lv_group_t * group, lv_group_style_mod_cb_t style_mod_edit_cb) -{ - group->style_mod_edit_cb = style_mod_edit_cb; - if(group->obj_focus != NULL) lv_obj_invalidate(*group->obj_focus); -} - /** * Set a function for a group which will be called when a new object is focused * @param group pointer to a group @@ -350,6 +320,7 @@ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) */ void lv_group_set_editing(lv_group_t * group, bool edit) { + if(group == NULL) return; uint8_t en_val = edit ? 1 : 0; if(en_val == group->editing) return; /*Do not set the same mode again*/ @@ -391,25 +362,6 @@ void lv_group_set_wrap(lv_group_t * group, bool en) group->wrap = en ? 1 : 0; } -/** - * Modify a style with the set 'style_mod' function. The input style remains unchanged. - * @param group pointer to group - * @param style pointer to a style to modify - * @return a copy of the input style but modified with the 'style_mod' function - */ -lv_style_t * lv_group_mod_style(lv_group_t * group, const lv_style_t * style) -{ - /*Load the current style. It will be modified by the callback*/ - lv_style_copy(&group->style_tmp, style); - - if(group->editing) { - if(group->style_mod_edit_cb) group->style_mod_edit_cb(group, &group->style_tmp); - } else { - if(group->style_mod_cb) group->style_mod_cb(group, &group->style_tmp); - } - return &group->style_tmp; -} - /** * Get the focused object or NULL if there isn't one * @param group pointer to a group @@ -435,28 +387,6 @@ lv_group_user_data_t * lv_group_get_user_data(lv_group_t * group) } #endif -/** - * Get a the style modifier function of a group - * @param group pointer to a group - * @return pointer to the style modifier function - */ -lv_group_style_mod_cb_t lv_group_get_style_mod_cb(const lv_group_t * group) -{ - if(!group) return false; - return group->style_mod_cb; -} - -/** - * Get a the style modifier function of a group in edit mode - * @param group pointer to a group - * @return pointer to the style modifier function - */ -lv_group_style_mod_cb_t lv_group_get_style_mod_edit_cb(const lv_group_t * group) -{ - if(!group) return false; - return group->style_mod_edit_cb; -} - /** * Get the focus callback function of a group * @param group pointer to a group @@ -464,7 +394,7 @@ lv_group_style_mod_cb_t lv_group_get_style_mod_edit_cb(const lv_group_t * group) */ lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group) { - if(!group) return false; + if(!group) return NULL; return group->focus_cb; } @@ -501,27 +431,6 @@ bool lv_group_get_wrap(lv_group_t * group) return group->wrap ? true : false; } -/** - * Notify the group that current theme changed and style modification callbacks need to be - * refreshed. - * @param group pointer to group. If NULL then all groups are notified. - */ -void lv_group_report_style_mod(lv_group_t * group) -{ - lv_theme_t * th = lv_theme_get_current(); - - if(group != NULL) { - refresh_theme(group, th); - return; - } - - lv_group_t * i; - LV_LL_READ(LV_GC_ROOT(_lv_group_ll), i) - { - refresh_theme(i, th); - } -} - /********************** * STATIC FUNCTIONS **********************/ @@ -540,89 +449,6 @@ static void lv_group_refocus(lv_group_t * g) g->wrap = temp_wrap; } -/** - * Default style modifier function - * @param group pointer to the caller group - * @param style pointer to a style to modify. (Typically group.style_tmp) It will be OVERWRITTEN. - */ -static void style_mod_def(lv_group_t * group, lv_style_t * style) -{ - (void)group; /*Unused*/ -#if LV_COLOR_DEPTH != 1 - - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_ORANGE; - - /*If not transparent or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_ORANGE, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_ORANGE, LV_OPA_70); - - /*Add some recolor to the images*/ - if(style->image.intense < LV_OPA_MIN) { - style->image.color = LV_COLOR_ORANGE; - style->image.intense = LV_OPA_40; - } -#else - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_BLACK; - style->body.border.width = 2; - -#endif -} - -/** - * Default style modifier function - * @param group pointer to the caller group - * @param style pointer to a style to modify. (Typically group.style_tmp) It will be OVERWRITTEN. - */ -static void style_mod_edit_def(lv_group_t * group, lv_style_t * style) -{ - (void)group; /*Unused*/ -#if LV_COLOR_DEPTH != 1 - - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_GREEN; - - /*If not empty or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_GREEN, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_GREEN, LV_OPA_70); - - /*Add some recolor to the images*/ - if(style->image.intense < LV_OPA_MIN) { - style->image.color = LV_COLOR_GREEN; - style->image.intense = LV_OPA_40; - } - -#else - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_BLACK; - style->body.border.width = 3; - -#endif -} - -static void refresh_theme(lv_group_t * g, lv_theme_t * th) -{ - g->style_mod_cb = style_mod_def; - g->style_mod_edit_cb = style_mod_edit_def; - if(th) { - if(th->group.style_mod_xcb) g->style_mod_cb = th->group.style_mod_xcb; - if(th->group.style_mod_edit_xcb) g->style_mod_edit_cb = th->group.style_mod_edit_xcb; - } -} - static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *), void * (*move)(const lv_ll_t *, const void *)) { @@ -640,7 +466,8 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) obj_next = begin(&group->obj_ll); can_move = false; can_begin = false; - } else { + } + else { /*Currently focused object is the last/first in the group, keep it that way*/ return; } diff --git a/src/src/lv_core/lv_group.h b/src/src/lv_core/lv_group.h index c27f769..ef165ee 100644 --- a/src/src/lv_core/lv_group.h +++ b/src/src/lv_core/lv_group.h @@ -13,11 +13,6 @@ extern "C" { /********************* * INCLUDES *********************/ -#ifdef LV_CONF_INCLUDE_SIMPLE -#include "lv_conf.h" -#else -#include "../../../lv_conf.h" -#endif #include "lv_obj.h" @@ -56,15 +51,11 @@ typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); * Groups can be used to logically hold objects so that they can be individually focused. * They are NOT for laying out objects on a screen (try `lv_cont` for that). */ -typedef struct _lv_group_t -{ +typedef struct _lv_group_t { lv_ll_t obj_ll; /**< Linked list to store the objects in the group */ lv_obj_t ** obj_focus; /**< The object in focus*/ - lv_group_style_mod_cb_t style_mod_cb; /**< A function to modifies the style of the focused object*/ - lv_group_style_mod_cb_t style_mod_edit_cb; /**< A function which modifies the style of the edited object*/ lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/ - lv_style_t style_tmp; /**< Stores the modified style of the focused object */ #if LV_USE_USER_DATA lv_group_user_data_t user_data; #endif @@ -90,7 +81,7 @@ typedef uint8_t lv_group_refocus_policy_t; * Init. the group module * @remarks Internal function, do not call directly. */ -void lv_group_init(void); +void _lv_group_init(void); /** * Create a new object group @@ -156,20 +147,6 @@ void lv_group_focus_freeze(lv_group_t * group, bool en); */ lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c); -/** - * Set a function for a group which will modify the object's style if it is in focus - * @param group pointer to a group - * @param style_mod_cb the style modifier function pointer - */ -void lv_group_set_style_mod_cb(lv_group_t * group, lv_group_style_mod_cb_t style_mod_cb); - -/** - * Set a function for a group which will modify the object's style if it is in focus in edit mode - * @param group pointer to a group - * @param style_mod_edit_cb the style modifier function pointer - */ -void lv_group_set_style_mod_edit_cb(lv_group_t * group, lv_group_style_mod_cb_t style_mod_edit_cb); - /** * Set a function for a group which will be called when a new object is focused * @param group pointer to a group @@ -206,14 +183,6 @@ void lv_group_set_click_focus(lv_group_t * group, bool en); */ void lv_group_set_wrap(lv_group_t * group, bool en); -/** - * Modify a style with the set 'style_mod' function. The input style remains unchanged. - * @param group pointer to group - * @param style pointer to a style to modify - * @return a copy of the input style but modified with the 'style_mod' function - */ -lv_style_t * lv_group_mod_style(lv_group_t * group, const lv_style_t * style); - /** * Get the focused object or NULL if there isn't one * @param group pointer to a group @@ -231,20 +200,6 @@ lv_group_user_data_t * lv_group_get_user_data(lv_group_t * group); #endif -/** - * Get a the style modifier function of a group - * @param group pointer to a group - * @return pointer to the style modifier function - */ -lv_group_style_mod_cb_t lv_group_get_style_mod_cb(const lv_group_t * group); - -/** - * Get a the style modifier function of a group in edit mode - * @param group pointer to a group - * @return pointer to the style modifier function - */ -lv_group_style_mod_cb_t lv_group_get_style_mod_edit_cb(const lv_group_t * group); - /** * Get the focus callback function of a group * @param group pointer to a group @@ -273,13 +228,6 @@ bool lv_group_get_click_focus(const lv_group_t * group); */ bool lv_group_get_wrap(lv_group_t * group); -/** - * Notify the group that current theme changed and style modification callbacks need to be - * refreshed. - * @param group pointer to group. If NULL then all groups are notified. - */ -void lv_group_report_style_mod(lv_group_t * group); - /********************** * MACROS **********************/ diff --git a/src/src/lv_core/lv_indev.c b/src/src/lv_core/lv_indev.c index 6ec59bd..6b0e23a 100644 --- a/src/src/lv_core/lv_indev.c +++ b/src/src/lv_core/lv_indev.c @@ -21,7 +21,7 @@ *********************/ #if LV_INDEV_DEF_DRAG_THROW <= 0 -#warning "LV_INDEV_DRAG_THROW must be greater than 0" + #warning "LV_INDEV_DRAG_THROW must be greater than 0" #endif /********************** @@ -39,9 +39,11 @@ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_proc_press(lv_indev_proc_t * proc); static void indev_proc_release(lv_indev_proc_t * proc); static void indev_proc_reset_query_handler(lv_indev_t * indev); -static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj); -static void indev_drag(lv_indev_proc_t * state); +static void indev_click_focus(lv_indev_proc_t * proc); +static void indev_drag(lv_indev_proc_t * proc); static void indev_drag_throw(lv_indev_proc_t * proc); +static lv_obj_t * get_dragged_obj(lv_obj_t * obj); +static void indev_gesture(lv_indev_proc_t * proc); static bool indev_reset_check(lv_indev_proc_t * proc); /********************** @@ -61,16 +63,16 @@ static lv_obj_t * indev_obj_act = NULL; /** * Initialize the display input device subsystem */ -void lv_indev_init(void) +void _lv_indev_init(void) { - lv_indev_reset(NULL); /*Reset all input devices*/ + lv_indev_reset(NULL, NULL); /*Reset all input devices*/ } /** * Called periodically to read the input devices * @param param pointer to and input device to read */ -void lv_indev_read_task(lv_task_t * task) +void _lv_indev_read_task(lv_task_t * task) { LV_LOG_TRACE("indev read task started"); @@ -88,7 +90,7 @@ void lv_indev_read_task(lv_task_t * task) bool more_to_read; do { /*Read the data*/ - more_to_read = lv_indev_read(indev_act, &data); + more_to_read = _lv_indev_read(indev_act, &data); /*The active object might deleted even in the read function*/ indev_proc_reset_query_handler(indev_act); @@ -99,17 +101,21 @@ void lv_indev_read_task(lv_task_t * task) /*Save the last activity time*/ if(indev_act->proc.state == LV_INDEV_STATE_PR) { indev_act->driver.disp->last_activity_time = lv_tick_get(); - } else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER && data.enc_diff) { + } + else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER && data.enc_diff) { indev_act->driver.disp->last_activity_time = lv_tick_get(); } if(indev_act->driver.type == LV_INDEV_TYPE_POINTER) { indev_pointer_proc(indev_act, &data); - } else if(indev_act->driver.type == LV_INDEV_TYPE_KEYPAD) { + } + else if(indev_act->driver.type == LV_INDEV_TYPE_KEYPAD) { indev_keypad_proc(indev_act, &data); - } else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER) { + } + else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER) { indev_encoder_proc(indev_act, &data); - } else if(indev_act->driver.type == LV_INDEV_TYPE_BUTTON) { + } + else if(indev_act->driver.type == LV_INDEV_TYPE_BUTTON) { indev_button_proc(indev_act, &data); } /*Handle reset query if it happened in during processing*/ @@ -144,19 +150,29 @@ lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev) return indev->driver.type; } + /** * Reset one or all input devices * @param indev pointer to an input device to reset or NULL to reset all of them + * @param obj pointer to an object which triggers the reset. */ -void lv_indev_reset(lv_indev_t * indev) +void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) { - if(indev) + if(indev) { indev->proc.reset_query = 1; + if(indev_act == indev) indev_obj_act = NULL; + if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) { + indev->proc.types.pointer.last_pressed = NULL; + } + } else { lv_indev_t * i = lv_indev_get_next(NULL); while(i) { i->proc.reset_query = 1; - + if(indev_act == i) indev_obj_act = NULL; + if(obj == NULL || i->proc.types.pointer.last_pressed == obj) { + i->proc.types.pointer.last_pressed = NULL; + } i = lv_indev_get_next(i); } } @@ -219,7 +235,7 @@ void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group) * @param indev pointer to an input device * @param group point to a group */ -void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t * points) +void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]) { if(indev->driver.type == LV_INDEV_TYPE_BUTTON) { indev->btn_points = points; @@ -233,15 +249,31 @@ void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t * points) */ void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point) { + if(indev == NULL) { + point->x = 0; + point->y = 0; + return; + } if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) { point->x = -1; point->y = -1; - } else { + } + else { point->x = indev->proc.types.pointer.act_point.x; point->y = indev->proc.types.pointer.act_point.y; } } +/** +* Get the current gesture direct +* @param indev pointer to an input device +* @return current gesture direct +*/ +lv_gesture_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev) +{ + return indev->proc.types.pointer.gesture_dir; +} + /** * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD) * @param indev pointer to an input device @@ -285,21 +317,62 @@ void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) { point->x = 0; point->y = 0; - } else { + } + else { point->x = indev->proc.types.pointer.vect.x; point->y = indev->proc.types.pointer.vect.y; } } +/** + * Manually finish dragging. + * `LV_SIGNAL_DRAG_END` and `LV_EVENT_DRAG_END` will be sent. + * @param indev pointer to an input device + * @return `LV_RES_INV` if the object being dragged was deleted. Else `LV_RES_OK`. + */ +lv_res_t lv_indev_finish_drag(lv_indev_t * indev) +{ + if(indev == NULL) return LV_RES_OK; + if(indev->driver.type != LV_INDEV_TYPE_POINTER) return LV_RES_OK; + if(indev->proc.types.pointer.drag_in_prog == 0) return LV_RES_OK; + + indev->proc.types.pointer.drag_in_prog = 0; + indev->proc.types.pointer.drag_throw_vect.x = 0; + indev->proc.types.pointer.drag_throw_vect.y = 0; + + lv_obj_t * drag_obj; + drag_obj = get_dragged_obj(indev->proc.types.pointer.act_obj); + if(drag_obj == NULL) return LV_RES_OK; + + lv_res_t res; + res = drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, NULL); + if(res != LV_RES_OK) return res; + + res = lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); + if(res != LV_RES_OK) return res; + + return res; +} + /** * Do nothing until the next release * @param indev pointer to an input device */ void lv_indev_wait_release(lv_indev_t * indev) { + if(indev == NULL)return; indev->proc.wait_until_release = 1; } +/** + * Gets a pointer to the currently active object in the currently processed input device. + * @return pointer to currently active object or NULL if no active object + */ +lv_obj_t * lv_indev_get_obj_act(void) +{ + return indev_obj_act; +} + /** * Get a pointer to the indev read task to * modify its parameters with `lv_task_...` functions. @@ -316,15 +389,6 @@ lv_task_t * lv_indev_get_read_task(lv_disp_t * indev) return indev->refr_task; } -/** - * Gets a pointer to the currently active object in the currently processed input device. - * @return pointer to currently active object or NULL if no active object - */ -lv_obj_t * lv_indev_get_obj_act(void) -{ - return indev_obj_act; -} - /********************** * STATIC FUNCTIONS **********************/ @@ -347,7 +411,8 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) if(i->proc.state == LV_INDEV_STATE_PR) { indev_proc_press(&i->proc); - } else { + } + else { indev_proc_release(&i->proc); } @@ -404,7 +469,8 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) if(indev_reset_check(&i->proc)) return; lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL); if(indev_reset_check(&i->proc)) return; - } else if(data->key == LV_KEY_ESC) { + } + else if(data->key == LV_KEY_ESC) { /*Send the ESC as a normal KEY*/ lv_group_send_data(g, LV_KEY_ESC); @@ -430,6 +496,14 @@ static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) } /*Pressing*/ else if(data->state == LV_INDEV_STATE_PR && prev_state == LV_INDEV_STATE_PR) { + + if(data->key == LV_KEY_ENTER) { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSING, NULL); + if(indev_reset_check(&i->proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL); + if(indev_reset_check(&i->proc)) return; + } + /*Long press time has elapsed?*/ if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver.long_press_time) { i->proc.long_pr_sent = 1; @@ -540,7 +614,8 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) int32_t s; if(data->enc_diff < 0) { for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(g, LV_KEY_LEFT); - } else if(data->enc_diff > 0) { + } + else if(data->enc_diff > 0) { for(s = 0; s < data->enc_diff; s++) lv_group_send_data(g, LV_KEY_RIGHT); } } @@ -549,7 +624,8 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) int32_t s; if(data->enc_diff < 0) { for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(g); - } else if(data->enc_diff > 0) { + } + else if(data->enc_diff > 0) { for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(g); } } @@ -582,7 +658,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) /*On enter long press toggle edit mode.*/ if(editable) { /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ - if(lv_ll_is_empty(&g->obj_ll) == false) { + if(_lv_ll_is_empty(&g->obj_ll) == false) { lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ } } @@ -619,7 +695,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) /*An object is being edited and the button is released. */ else if(g->editing) { /*Ignore long pressed enter release because it comes from mode switch*/ - if(!i->proc.long_pr_sent || lv_ll_is_empty(&g->obj_ll)) { + if(!i->proc.long_pr_sent || _lv_ll_is_empty(&g->obj_ll)) { indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL); if(indev_reset_check(&i->proc)) return; @@ -659,6 +735,12 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) */ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) { + /* Die gracefully if i->btn_points is NULL */ + if(i->btn_points == NULL) { + LV_LOG_WARN("indev_button_proc: btn_points was NULL"); + return; + } + i->proc.types.pointer.act_point.x = i->btn_points[data->btn_id].x; i->proc.types.pointer.act_point.y = i->btn_points[data->btn_id].y; @@ -666,7 +748,8 @@ static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) if(i->proc.types.pointer.last_point.x == i->proc.types.pointer.act_point.x && i->proc.types.pointer.last_point.y == i->proc.types.pointer.act_point.y && data->state == LV_INDEV_STATE_PR) { indev_proc_press(&i->proc); - } else { + } + else { /*If a new point comes always make a release*/ indev_proc_release(&i->proc); } @@ -691,17 +774,21 @@ static void indev_proc_press(lv_indev_proc_t * proc) /*If there is no last object then search*/ if(indev_obj_act == NULL) { - indev_obj_act = indev_search_obj(proc, lv_disp_get_layer_sys(disp)); - if(indev_obj_act == NULL) indev_obj_act = indev_search_obj(proc, lv_disp_get_layer_top(disp)); - if(indev_obj_act == NULL) indev_obj_act = indev_search_obj(proc, lv_disp_get_scr_act(disp)); + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); new_obj_searched = true; } /*If there is last object but it is not dragged and not protected also search*/ else if(proc->types.pointer.drag_in_prog == 0 && lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST) == false) { - indev_obj_act = indev_search_obj(proc, lv_disp_get_layer_sys(disp)); - if(indev_obj_act == NULL) indev_obj_act = indev_search_obj(proc, lv_disp_get_layer_top(disp)); - if(indev_obj_act == NULL) indev_obj_act = indev_search_obj(proc, lv_disp_get_scr_act(disp)); + indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), + &proc->types.pointer.act_point); + if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), + &proc->types.pointer.act_point); new_obj_searched = true; } /*If a dragable or a protected object was the last then keep it*/ @@ -715,6 +802,11 @@ static void indev_proc_press(lv_indev_proc_t * proc) indev_drag_throw(proc); } + /*Do not use disabled objects*/ + if(indev_obj_act && (lv_obj_get_state(indev_obj_act, LV_OBJ_PART_MAIN) & LV_STATE_DISABLED)) { + indev_obj_act = proc->types.pointer.act_obj; + } + /*If a new object was found reset some variables and send a pressed signal*/ if(indev_obj_act != proc->types.pointer.act_obj) { proc->types.pointer.last_point.x = proc->types.pointer.act_point.x; @@ -736,14 +828,17 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->types.pointer.last_obj = indev_obj_act; if(indev_obj_act != NULL) { - /* Save the time when the obj pressed. - * It is necessary to count the long press time.*/ + /* Save the time when the obj pressed to count long press time.*/ proc->pr_timestamp = lv_tick_get(); proc->long_pr_sent = 0; proc->types.pointer.drag_limit_out = 0; proc->types.pointer.drag_in_prog = 0; proc->types.pointer.drag_sum.x = 0; proc->types.pointer.drag_sum.y = 0; + proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH; + proc->types.pointer.gesture_sent = 0; + proc->types.pointer.gesture_sum.x = 0; + proc->types.pointer.gesture_sum.y = 0; proc->types.pointer.vect.x = 0; proc->types.pointer.vect.y = 0; @@ -766,6 +861,13 @@ static void indev_proc_press(lv_indev_proc_t * proc) lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL); if(indev_reset_check(proc)) return; + + if(indev_act->proc.wait_until_release) return; + + /*Handle focus*/ + indev_click_focus(&indev_act->proc); + if(indev_reset_check(proc)) return; + } } @@ -795,8 +897,10 @@ static void indev_proc_press(lv_indev_proc_t * proc) if(indev_reset_check(proc)) return; lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL); if(indev_reset_check(proc)) return; + if(indev_act->proc.wait_until_release) return; indev_drag(proc); + indev_gesture(proc); if(indev_reset_check(proc)) return; /*If there is no drag then check for long press time*/ @@ -846,6 +950,7 @@ static void indev_proc_release(lv_indev_proc_t * proc) /*Forget the act obj and send a released signal */ if(indev_obj_act) { + /* If the object was protected against press lost then it possible that * the object is already not pressed but still it is the `act_obj`. * In this case send the `LV_SIGNAL_RELEASED/CLICKED` instead of `LV_SIGNAL_PRESS_LOST` if @@ -887,64 +992,14 @@ static void indev_proc_release(lv_indev_proc_t * proc) if(indev_reset_check(proc)) return; } - if(indev_reset_check(proc)) return; - - /*Handle click focus*/ - bool click_focus_sent = false; -#if LV_USE_GROUP - lv_group_t * g = lv_obj_get_group(indev_obj_act); - - /*Check, if the parent is in a group and focus on it.*/ - /*Respect the click focus protection*/ - if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false) { - lv_obj_t * parent = indev_obj_act; - - while(g == NULL) { - parent = lv_obj_get_parent(parent); - if(parent == NULL) break; - - /*Ignore is the protected against click focus*/ - if(lv_obj_is_protected(parent, LV_PROTECT_CLICK_FOCUS)) { - parent = NULL; - break; - } - g = lv_obj_get_group(parent); - } - - /* If a parent is in a group make it focused. - * `LV_EVENT_FOCUSED/DEFOCUSED` will be sent by `lv_group_focus_obj`*/ - if(g && parent) { - if(lv_group_get_click_focus(g)) { - click_focus_sent = true; - lv_group_focus_obj(parent); - } - } - } -#endif - - /* Send defocus to the lastly "active" object and foucus to the new one. - * DO not sent the events if they was sent by the click focus*/ - if(proc->types.pointer.last_pressed != indev_obj_act && click_focus_sent == false) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL); - if(indev_reset_check(proc)) return; - - lv_event_send(proc->types.pointer.act_obj, LV_EVENT_FOCUSED, NULL); - if(indev_reset_check(proc)) return; - - proc->types.pointer.last_pressed = indev_obj_act; - } - - if(indev_reset_check(proc)) return; - /*Send LV_EVENT_DRAG_THROW_BEGIN if required */ /*If drag parent is active check recursively the drag_parent attribute*/ - lv_obj_t * drag_obj = indev_obj_act; - while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { - drag_obj = lv_obj_get_parent(drag_obj); - } - + lv_obj_t * drag_obj = get_dragged_obj(indev_obj_act); if(drag_obj) { if(lv_obj_get_drag_throw(drag_obj) && proc->types.pointer.drag_in_prog) { + if(drag_obj->signal_cb) drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_THROW_BEGIN, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(drag_obj, LV_EVENT_DRAG_THROW_BEGIN, NULL); if(indev_reset_check(proc)) return; } @@ -975,7 +1030,6 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) if(indev->proc.reset_query) { indev->proc.types.pointer.act_obj = NULL; indev->proc.types.pointer.last_obj = NULL; - indev->proc.types.pointer.last_pressed = NULL; indev->proc.types.pointer.drag_limit_out = 0; indev->proc.types.pointer.drag_in_prog = 0; indev->proc.long_pr_sent = 0; @@ -983,47 +1037,31 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) indev->proc.longpr_rep_timestamp = 0; indev->proc.types.pointer.drag_sum.x = 0; indev->proc.types.pointer.drag_sum.y = 0; + indev->proc.types.pointer.drag_dir = LV_DRAG_DIR_BOTH; indev->proc.types.pointer.drag_throw_vect.x = 0; indev->proc.types.pointer.drag_throw_vect.y = 0; + indev->proc.types.pointer.gesture_sum.x = 0; + indev->proc.types.pointer.gesture_sum.y = 0; indev->proc.reset_query = 0; indev_obj_act = NULL; } } /** - * Search the most top, clickable object on the last point of an input device - * @param proc pointer to the `lv_indev_proc_t` part of the input device + * Search the most top, clickable object by a point * @param obj pointer to a start object, typically the screen + * @param point pointer to a point for searhing the most top child * @return pointer to the found object or NULL if there was no suitable object */ -static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj) +lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) { lv_obj_t * found_p = NULL; /*If the point is on this object check its children too*/ -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - lv_area_t ext_area; - ext_area.x1 = obj->coords.x1 - obj->ext_click_pad_hor; - ext_area.x2 = obj->coords.x2 + obj->ext_click_pad_hor; - ext_area.y1 = obj->coords.y1 - obj->ext_click_pad_ver; - ext_area.y2 = obj->coords.y2 + obj->ext_click_pad_ver; - - if(lv_area_is_point_on(&ext_area, &proc->types.pointer.act_point)) { -#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - lv_area_t ext_area; - ext_area.x1 = obj->coords.x1 - obj->ext_click_pad.x1; - ext_area.x2 = obj->coords.x2 + obj->ext_click_pad.x2; - ext_area.y1 = obj->coords.y1 - obj->ext_click_pad.y1; - ext_area.y2 = obj->coords.y2 + obj->ext_click_pad.y2; - - if(lv_area_is_point_on(&ext_area, &proc->types.pointer.act_point)) { -#else - if(lv_area_is_point_on(&obj->coords, &proc->types.pointer.act_point)) { -#endif + if(lv_obj_hittest(obj, point)) { lv_obj_t * i; - LV_LL_READ(obj->child_ll, i) - { - found_p = indev_search_obj(proc, i); + _LV_LL_READ(obj->child_ll, i) { + found_p = lv_indev_search_obj(i, point); /*If a child was found then break*/ if(found_p != NULL) { @@ -1047,49 +1085,151 @@ static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj) return found_p; } +/** + * Handle focus/defocus on click for POINTER inpt devices + * @param proc pointer to the state of the indev + */ +static void indev_click_focus(lv_indev_proc_t * proc) +{ + /*Handle click focus*/ + if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false && + proc->types.pointer.last_pressed != indev_obj_act) { +#if LV_USE_GROUP + lv_group_t * g_act = lv_obj_get_group(indev_obj_act); + lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL; + + /*If both the last and act. obj. are in the same group (or no group but it's also the same) */ + if(g_act == g_prev) { + /*The objects are in a group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(proc)) return; + } + /*The object are not in group*/ + else { + if(proc->types.pointer.last_pressed) { + lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + + lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + } + /*The object are not in the same group (in different group or one in not a group)*/ + else { + /*Focus to the act. its group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(proc)) return; + } + /*If the prev. obj. is not in a group then defocus it.*/ + if(g_prev == NULL && proc->types.pointer.last_pressed) { + lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + /*Focus on a non-group object*/ + else { + if(proc->types.pointer.last_pressed) { + /*If the prev. object also wasn't in a group defocus it*/ + if(g_prev == NULL) { + lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ + else { + lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_LEAVE, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, NULL); + if(indev_reset_check(proc)) return; + } + } + + lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + } +#else + if(proc->types.pointer.last_pressed) { + lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL); + if(indev_reset_check(proc)) return; + } + + lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL); + if(indev_reset_check(proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL); + if(indev_reset_check(proc)) return; +#endif + proc->types.pointer.last_pressed = indev_obj_act; + } + +} + /** * Handle the dragging of indev_proc_p->types.pointer.act_obj * @param indev pointer to a input device state */ -static void indev_drag(lv_indev_proc_t * state) +static void indev_drag(lv_indev_proc_t * proc) { - lv_obj_t * drag_obj = state->types.pointer.act_obj; + lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.act_obj); bool drag_just_started = false; - /*If drag parent is active check recursively the drag_parent attribute*/ - while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { - drag_obj = lv_obj_get_parent(drag_obj); - } - if(drag_obj == NULL) return; if(lv_obj_get_drag(drag_obj) == false) return; + lv_drag_dir_t allowed_dirs = lv_obj_get_drag_dir(drag_obj); /*Count the movement by drag*/ - state->types.pointer.drag_sum.x += state->types.pointer.vect.x; - state->types.pointer.drag_sum.y += state->types.pointer.vect.y; + if(proc->types.pointer.drag_limit_out == 0) { + proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x; + proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y; + + /*Enough move?*/ + bool hor_en = false; + bool ver_en = false; + if(allowed_dirs == LV_DRAG_DIR_HOR || allowed_dirs == LV_DRAG_DIR_BOTH) { + hor_en = true; + } + + if(allowed_dirs == LV_DRAG_DIR_VER || allowed_dirs == LV_DRAG_DIR_BOTH) { + ver_en = true; + } + + if(allowed_dirs == LV_DRAG_DIR_ONE) { + if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { + hor_en = true; + } + else { + ver_en = true; + } + } - /*Enough move?*/ - if(state->types.pointer.drag_limit_out == 0) { /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ - if(((allowed_dirs & LV_DRAG_DIR_HOR) && - LV_MATH_ABS(state->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || - ((allowed_dirs & LV_DRAG_DIR_VER) && - LV_MATH_ABS(state->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { - state->types.pointer.drag_limit_out = 1; + if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) || + (ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) { + proc->types.pointer.drag_limit_out = 1; drag_just_started = true; } } /*If the drag limit is exceeded handle the dragging*/ - if(state->types.pointer.drag_limit_out != 0) { + if(proc->types.pointer.drag_limit_out != 0) { /*Set new position if the vector is not zero*/ - if(state->types.pointer.vect.x != 0 || state->types.pointer.vect.y != 0) { - - uint16_t inv_buf_size = - lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/ + if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) { lv_coord_t prev_x = drag_obj->coords.x1; lv_coord_t prev_y = drag_obj->coords.y1; @@ -1100,27 +1240,64 @@ static void indev_drag(lv_indev_proc_t * state) lv_coord_t act_x = lv_obj_get_x(drag_obj); lv_coord_t act_y = lv_obj_get_y(drag_obj); - if(allowed_dirs == LV_DRAG_DIR_ALL) { + if(allowed_dirs == LV_DRAG_DIR_BOTH) { if(drag_just_started) { - act_x += state->types.pointer.drag_sum.x; - act_y += state->types.pointer.drag_sum.y; + proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH; + act_x += proc->types.pointer.drag_sum.x; + act_y += proc->types.pointer.drag_sum.y; } - lv_obj_set_pos(drag_obj, act_x + state->types.pointer.vect.x, act_y + state->types.pointer.vect.y); - } else if(allowed_dirs & LV_DRAG_DIR_HOR) { + } + else if(allowed_dirs == LV_DRAG_DIR_HOR) { + if(drag_just_started) { + proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR; + proc->types.pointer.drag_sum.y = 0; + act_x += proc->types.pointer.drag_sum.x; + } + } + else if(allowed_dirs == LV_DRAG_DIR_VER) { if(drag_just_started) { - act_x += state->types.pointer.drag_sum.x; + proc->types.pointer.drag_dir = LV_DRAG_DIR_VER; + proc->types.pointer.drag_sum.x = 0; + act_y += proc->types.pointer.drag_sum.y; } - lv_obj_set_x(drag_obj, act_x + state->types.pointer.vect.x); - } else if(allowed_dirs & LV_DRAG_DIR_VER) { + } + else if(allowed_dirs == LV_DRAG_DIR_ONE) { if(drag_just_started) { - act_y += state->types.pointer.drag_sum.y; + if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) { + proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR; + proc->types.pointer.drag_sum.y = 0; + act_x += proc->types.pointer.drag_sum.x; + } + else { + proc->types.pointer.drag_dir = LV_DRAG_DIR_VER; + proc->types.pointer.drag_sum.x = 0; + act_y += proc->types.pointer.drag_sum.y; + } } - lv_obj_set_y(drag_obj, act_y + state->types.pointer.vect.y); } + /*Move the object*/ + if(allowed_dirs == LV_DRAG_DIR_HOR || + allowed_dirs == LV_DRAG_DIR_BOTH || + (allowed_dirs == LV_DRAG_DIR_ONE && + LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y))) { + act_x += proc->types.pointer.vect.x; + } + if(allowed_dirs == LV_DRAG_DIR_VER || + allowed_dirs == LV_DRAG_DIR_BOTH || + (allowed_dirs == LV_DRAG_DIR_ONE && + LV_MATH_ABS(proc->types.pointer.drag_sum.x) < LV_MATH_ABS(proc->types.pointer.drag_sum.y))) { + act_y += proc->types.pointer.vect.y; + } + + uint16_t inv_buf_size = + lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/ + + lv_obj_set_pos(drag_obj, act_x, act_y); + proc->types.pointer.drag_in_prog = 1; + /*If the object didn't moved then clear the invalidated areas*/ if(drag_obj->coords.x1 == prev_x && drag_obj->coords.y1 == prev_y) { -// state->types.pointer.drag_in_prog = 0; /*In a special case if the object is moved on a page and * the scrollable has fit == true and the object is dragged of the page then * while its coordinate is not changing only the parent's size is reduced */ @@ -1128,19 +1305,20 @@ static void indev_drag(lv_indev_proc_t * state) lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj)); if(act_par_w == prev_par_w && act_par_h == prev_par_h) { uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); - lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size); - } - } else { - state->types.pointer.drag_in_prog = 1; - /*Set the drag in progress flag*/ - /*Send the drag begin signal on first move*/ - if(drag_just_started) { - drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_BEGIN, indev_act); - if(indev_reset_check(state)) return; - lv_event_send(drag_obj, LV_EVENT_DRAG_BEGIN, NULL); - if(indev_reset_check(state)) return; + _lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size); } } + + /*Set the drag in progress flag*/ + /*Send the drag begin signal on first move*/ + if(drag_just_started) { + drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_BEGIN, indev_act); + if(indev_reset_check(proc)) return; + + lv_event_send(drag_obj, LV_EVENT_DRAG_BEGIN, NULL); + if(indev_reset_check(proc)) return; + } + } } } @@ -1153,22 +1331,14 @@ static void indev_drag_throw(lv_indev_proc_t * proc) { if(proc->types.pointer.drag_in_prog == 0) return; - lv_obj_t * drag_obj = proc->types.pointer.last_obj; - - /*If drag parent is active check recursively the drag_parent attribute*/ - while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { - drag_obj = lv_obj_get_parent(drag_obj); - } + lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.last_obj); - if(drag_obj == NULL) { - return; - } + if(drag_obj == NULL) return; /*Return if the drag throw is not enabled*/ if(lv_obj_get_drag_throw(drag_obj) == false) { proc->types.pointer.drag_in_prog = 0; drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act); - lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); if(indev_reset_check(proc)) return; lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); @@ -1190,13 +1360,13 @@ static void indev_drag_throw(lv_indev_proc_t * proc) lv_coord_t act_x = lv_obj_get_x(drag_obj) + proc->types.pointer.drag_throw_vect.x; lv_coord_t act_y = lv_obj_get_y(drag_obj) + proc->types.pointer.drag_throw_vect.y; - if(allowed_dirs == LV_DRAG_DIR_ALL) - lv_obj_set_pos(drag_obj, act_x, act_y); - else if(allowed_dirs & LV_DRAG_DIR_HOR) - lv_obj_set_x(drag_obj, act_x); - else if(allowed_dirs & LV_DRAG_DIR_VER) - lv_obj_set_y(drag_obj, act_y); - + if(allowed_dirs == LV_DRAG_DIR_BOTH) lv_obj_set_pos(drag_obj, act_x, act_y); + else if(allowed_dirs == LV_DRAG_DIR_HOR) lv_obj_set_x(drag_obj, act_x); + else if(allowed_dirs == LV_DRAG_DIR_VER) lv_obj_set_y(drag_obj, act_y); + else if(allowed_dirs == LV_DRAG_DIR_ONE) { + if(proc->types.pointer.drag_sum.x) lv_obj_set_x(drag_obj, act_x); + else lv_obj_set_y(drag_obj, act_y); + } lv_area_t coord_new; lv_obj_get_coords(drag_obj, &coord_new); @@ -1210,6 +1380,7 @@ static void indev_drag_throw(lv_indev_proc_t * proc) proc->types.pointer.drag_throw_vect.y = 0; drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act); if(indev_reset_check(proc)) return; + lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL); if(indev_reset_check(proc)) return; } @@ -1225,10 +1396,83 @@ static void indev_drag_throw(lv_indev_proc_t * proc) } } + +/** + * Get the really dragged object by taking `drag_parent` into account. + * @param obj the start obejct + * @return the object to really drag + */ +static lv_obj_t * get_dragged_obj(lv_obj_t * obj) +{ + if(obj == NULL) return NULL; + lv_obj_t * drag_obj = obj; + while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) { + drag_obj = lv_obj_get_parent(drag_obj); + } + + return drag_obj; +} + + +/** +* Handle the gesture of indev_proc_p->types.pointer.act_obj +* @param indev pointer to a input device state +*/ +static void indev_gesture(lv_indev_proc_t * proc) +{ + + if(proc->types.pointer.drag_in_prog) return; + if(proc->types.pointer.gesture_sent) return; + + lv_obj_t * gesture_obj = proc->types.pointer.act_obj; + + /*If gesture parent is active check recursively the drag_parent attribute*/ + while(gesture_obj && lv_obj_get_gesture_parent(gesture_obj)) { + gesture_obj = lv_obj_get_parent(gesture_obj); + } + + if(gesture_obj == NULL) return; + + if((LV_MATH_ABS(proc->types.pointer.vect.x) < indev_act->driver.gesture_min_velocity) && + (LV_MATH_ABS(proc->types.pointer.vect.y) < indev_act->driver.gesture_min_velocity)) { + proc->types.pointer.gesture_sum.x = 0; + proc->types.pointer.gesture_sum.y = 0; + } + + /*Count the movement by gesture*/ + proc->types.pointer.gesture_sum.x += proc->types.pointer.vect.x; + proc->types.pointer.gesture_sum.y += proc->types.pointer.vect.y; + + if((LV_MATH_ABS(proc->types.pointer.gesture_sum.x) > indev_act->driver.gesture_limit) || + (LV_MATH_ABS(proc->types.pointer.gesture_sum.y) > indev_act->driver.gesture_limit)) { + + proc->types.pointer.gesture_sent = 1; + + if(LV_MATH_ABS(proc->types.pointer.gesture_sum.x) > LV_MATH_ABS(proc->types.pointer.gesture_sum.y)) { + if(proc->types.pointer.gesture_sum.x > 0) + proc->types.pointer.gesture_dir = LV_GESTURE_DIR_RIGHT; + else + proc->types.pointer.gesture_dir = LV_GESTURE_DIR_LEFT; + } + else { + if(proc->types.pointer.gesture_sum.y > 0) + proc->types.pointer.gesture_dir = LV_GESTURE_DIR_BOTTOM; + else + proc->types.pointer.gesture_dir = LV_GESTURE_DIR_TOP; + } + + gesture_obj->signal_cb(gesture_obj, LV_SIGNAL_GESTURE, indev_act); + if(indev_reset_check(proc)) return; + lv_event_send(gesture_obj, LV_EVENT_GESTURE, NULL); + if(indev_reset_check(proc)) return; + } +} + + /** * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions * @param proc pointer to an input device 'proc' - * return true if indev query should be immediately truncated. + * @return true if indev query should be immediately truncated. */ static bool indev_reset_check(lv_indev_proc_t * proc) { diff --git a/src/src/lv_core/lv_indev.h b/src/src/lv_core/lv_indev.h index 69ab5a4..1e5fe5d 100644 --- a/src/src/lv_core/lv_indev.h +++ b/src/src/lv_core/lv_indev.h @@ -32,13 +32,13 @@ extern "C" { /** * Initialize the display input device subsystem */ -void lv_indev_init(void); +void _lv_indev_init(void); /** * Called periodically to read the input devices * @param task pointer to the task itself */ -void lv_indev_read_task(lv_task_t * task); +void _lv_indev_read_task(lv_task_t * task); /** * Get the currently processed input device. Can be used in action functions too. @@ -57,8 +57,9 @@ lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev); /** * Reset one or all input devices * @param indev pointer to an input device to reset or NULL to reset all of them + * @param obj pointer to an object which triggers the reset. */ -void lv_indev_reset(lv_indev_t * indev); +void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj); /** * Reset the long press state of an input device @@ -95,7 +96,7 @@ void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group); * @param indev pointer to an input device * @param group point to a group */ -void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t * points); +void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]); /** * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) @@ -104,6 +105,13 @@ void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t * points); */ void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point); +/** +* Get the current gesture direct +* @param indev pointer to an input device +* @return current gesture direct +*/ +lv_gesture_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev); + /** * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD) * @param indev pointer to an input device @@ -128,18 +136,19 @@ bool lv_indev_is_dragging(const lv_indev_t * indev); void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point); /** - * Do nothing until the next release + * Manually finish dragging. + * `LV_SIGNAL_DRAG_END` and `LV_EVENT_DRAG_END` will be sent. * @param indev pointer to an input device + * @return `LV_RES_INV` if the object being dragged was deleted. Else `LV_RES_OK`. */ -void lv_indev_wait_release(lv_indev_t * indev); +lv_res_t lv_indev_finish_drag(lv_indev_t * indev); /** - * Get a pointer to the indev read task to - * modify its parameters with `lv_task_...` functions. - * @param indev pointer to an inout device - * @return pointer to the indev read refresher task. (NULL on error) + * Do nothing until the next release + * @param indev pointer to an input device */ -lv_task_t * lv_indev_get_read_task(lv_disp_t * indev); +void lv_indev_wait_release(lv_indev_t * indev); + /** * Gets a pointer to the currently active object in indev proc functions. @@ -148,6 +157,22 @@ lv_task_t * lv_indev_get_read_task(lv_disp_t * indev); */ lv_obj_t * lv_indev_get_obj_act(void); +/** + * Search the most top, clickable object by a point + * @param obj pointer to a start object, typically the screen + * @param point pointer to a point for searhing the most top child + * @return pointer to the found object or NULL if there was no suitable object + */ +lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point); + +/** + * Get a pointer to the indev read task to + * modify its parameters with `lv_task_...` functions. + * @param indev pointer to an inout device + * @return pointer to the indev read refresher task. (NULL on error) + */ +lv_task_t * lv_indev_get_read_task(lv_disp_t * indev); + /********************** * MACROS **********************/ diff --git a/src/src/lv_core/lv_obj.c b/src/src/lv_core/lv_obj.c index 089c5e3..fde490f 100644 --- a/src/src/lv_core/lv_obj.c +++ b/src/src/lv_core/lv_obj.c @@ -1,5 +1,5 @@ /** - * @file lv_base_obj.c + * @file lv_obj.c * */ @@ -18,45 +18,82 @@ #include "../lv_misc/lv_task.h" #include "../lv_misc/lv_async.h" #include "../lv_misc/lv_fs.h" +#include "../lv_misc/lv_gc.h" +#include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_gc.h" +#include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_log.h" #include "../lv_hal/lv_hal.h" #include #include -#include "../lv_misc/lv_gc.h" -#include "../lv_misc/lv_math.h" #if defined(LV_GC_INCLUDE) -#include LV_GC_INCLUDE + #include LV_GC_INCLUDE #endif /* LV_ENABLE_GC */ + +#if defined(LV_USER_DATA_FREE_INCLUDE) + #include LV_USER_DATA_FREE_INCLUDE +#endif /* LV_USE_USER_DATA_FREE */ + +#include LV_THEME_DEFAULT_INCLUDE + /********************* * DEFINES *********************/ #define LV_OBJX_NAME "lv_obj" -#define LV_OBJ_DEF_WIDTH (LV_DPI) -#define LV_OBJ_DEF_HEIGHT (2 * LV_DPI / 3) +#define LV_OBJ_DEF_WIDTH (LV_DPX(100)) +#define LV_OBJ_DEF_HEIGHT (LV_DPX(50)) /********************** * TYPEDEFS **********************/ -typedef struct _lv_event_temp_data -{ +typedef struct _lv_event_temp_data { lv_obj_t * obj; bool deleted; struct _lv_event_temp_data * prev; } lv_event_temp_data_t; +typedef struct { + lv_obj_t * obj; + lv_style_property_t prop; + uint8_t part; + union { + lv_color_t _color; + lv_style_int_t _int; + lv_opa_t _opa; + const void * _ptr; + } start_value; + union { + lv_color_t _color; + lv_style_int_t _int; + lv_opa_t _opa; + const void * _ptr; + } end_value; +} lv_style_trans_t; + /********************** * STATIC PROTOTYPES **********************/ +static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area, lv_design_mode_t mode); +static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param); static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff); static void report_style_mod_core(void * style_p, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); -static void delete_children(lv_obj_t * obj); static void base_dir_refr_children(lv_obj_t * obj); +#if LV_USE_ANIMATION +static lv_style_trans_t * trans_create(lv_obj_t * obj, lv_style_property_t prop, uint8_t part, lv_state_t prev_state, + lv_state_t new_state); +static void trans_del(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, lv_style_trans_t * tr_limit); +static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v); +static void trans_anim_start_cb(lv_anim_t * a); +static void trans_anim_ready_cb(lv_anim_t * a); +static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v); +static void fade_in_anim_ready(lv_anim_t * a); +#endif static void lv_event_mark_deleted(lv_obj_t * obj); static void lv_obj_del_async_cb(void * obj); -static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode); -static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param); +static void obj_del_core(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -87,40 +124,66 @@ void lv_init(void) LV_LOG_TRACE("lv_init started"); /*Initialize the lv_misc modules*/ - lv_mem_init(); - lv_task_core_init(); + _lv_mem_init(); + _lv_task_core_init(); #if LV_USE_FILESYSTEM - lv_fs_init(); + _lv_fs_init(); #endif #if LV_USE_ANIMATION - lv_anim_core_init(); + _lv_anim_core_init(); #endif #if LV_USE_GROUP - lv_group_init(); + _lv_group_init(); #endif - /*Init. the sstyles*/ - lv_style_init(); + _lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(lv_style_trans_t)); + + lv_theme_t * th = LV_THEME_DEFAULT_INIT(LV_THEME_DEFAULT_COLOR_PRIMARY, LV_THEME_DEFAULT_COLOR_SECONDARY, + LV_THEME_DEFAULT_FLAG, + LV_THEME_DEFAULT_FONT_SMALL, LV_THEME_DEFAULT_FONT_NORMAL, LV_THEME_DEFAULT_FONT_SUBTITLE, LV_THEME_DEFAULT_FONT_TITLE); + lv_theme_set_act(th); /*Initialize the screen refresh system*/ - lv_refr_init(); + _lv_refr_init(); - lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); - lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); + _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); + _lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); /*Init the input device handling*/ - lv_indev_init(); + _lv_indev_init(); - lv_img_decoder_init(); + _lv_img_decoder_init(); lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE); lv_initialized = true; LV_LOG_INFO("lv_init ready"); } +#if LV_ENABLE_GC || !LV_MEM_CUSTOM + +/** + * Deinit the 'lv' library + * Currently only implemented when not using custom allocators, or GC is enabled. + */ +void lv_deinit(void) +{ + _lv_gc_clear_roots(); +#if LV_USE_LOG + lv_log_register_print_cb(NULL); +#endif + lv_disp_set_default(NULL); + _lv_mem_deinit(); + lv_initialized = false; +#if LV_USE_LOG + lv_log_register_print_cb(NULL); +#endif + LV_LOG_INFO("lv_deinit done"); +} +#endif + /*-------------------- * Create and delete *-------------------*/ @@ -134,9 +197,9 @@ void lv_init(void) */ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) { - lv_obj_t * new_obj = NULL; - /*Create a screen if the parent is NULL*/ + + /*Create a screen*/ if(parent == NULL) { LV_LOG_TRACE("Screen create started"); lv_disp_t * disp = lv_disp_get_default(); @@ -145,12 +208,17 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) return NULL; } - new_obj = lv_ll_ins_head(&disp->scr_ll); + new_obj = _lv_ll_ins_head(&disp->scr_ll); LV_ASSERT_MEM(new_obj); if(new_obj == NULL) return NULL; - new_obj->par = NULL; /*Screens has no a parent*/ - lv_ll_init(&(new_obj->child_ll), sizeof(lv_obj_t)); + _lv_memset_00(new_obj, sizeof(lv_obj_t)); + +#if LV_USE_BIDI + new_obj->base_dir = LV_BIDI_BASE_DIR_DEF; +#else + new_obj->base_dir = LV_BIDI_DIR_LTR; +#endif /*Set the callbacks*/ new_obj->signal_cb = lv_obj_signal; @@ -162,81 +230,19 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->coords.y1 = 0; new_obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1; new_obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1; - new_obj->ext_draw_pad = 0; - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - memset(&new_obj->ext_click_pad, 0, sizeof(new_obj->ext_click_pad)); -#endif - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - new_obj->ext_click_pad_hor = 0; - new_obj->ext_click_pad_ver = 0; -#endif - - /*Init realign*/ -#if LV_USE_OBJ_REALIGN - new_obj->realign.align = LV_ALIGN_CENTER; - new_obj->realign.xofs = 0; - new_obj->realign.yofs = 0; - new_obj->realign.base = NULL; - new_obj->realign.auto_realign = 0; -#endif - - /*Set the default styles*/ - lv_theme_t * th = lv_theme_get_current(); - if(th) { - new_obj->style_p = th->style.scr; - } else { - new_obj->style_p = &lv_style_scr; - } - - /*Init. user date*/ -#if LV_USE_USER_DATA - memset(&new_obj->user_data, 0, sizeof(lv_obj_user_data_t)); -#endif - -#if LV_USE_GROUP - new_obj->group_p = NULL; -#endif - /*Set attributes*/ - new_obj->click = 0; - new_obj->drag = 0; - new_obj->drag_throw = 0; - new_obj->drag_parent = 0; - new_obj->hidden = 0; - new_obj->top = 0; - new_obj->protect = LV_PROTECT_NONE; - new_obj->opa_scale_en = 0; - new_obj->opa_scale = LV_OPA_COVER; - new_obj->parent_event = 0; -#if LV_USE_BIDI - new_obj->base_dir = LV_BIDI_BASE_DIR_DEF; -#else - new_obj->base_dir = LV_BIDI_DIR_LTR; -#endif - - new_obj->reserved = 0; - - new_obj->ext_attr = NULL; - - LV_LOG_INFO("Screen create ready"); } - /*parent != NULL create normal obj. on a parent*/ + /*Create a normal object*/ else { LV_LOG_TRACE("Object create started"); LV_ASSERT_OBJ(parent, LV_OBJX_NAME); - new_obj = lv_ll_ins_head(&parent->child_ll); + new_obj = _lv_ll_ins_head(&parent->child_ll); LV_ASSERT_MEM(new_obj); if(new_obj == NULL) return NULL; - new_obj->par = parent; /*Set the parent*/ - lv_ll_init(&(new_obj->child_ll), sizeof(lv_obj_t)); + _lv_memset_00(new_obj, sizeof(lv_obj_t)); - /*Set the callbacks*/ - new_obj->signal_cb = lv_obj_signal; - new_obj->design_cb = lv_obj_design; - new_obj->event_cb = NULL; + new_obj->parent = parent; #if LV_USE_BIDI new_obj->base_dir = LV_BIDI_DIR_INHERIT; @@ -244,97 +250,96 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->base_dir = LV_BIDI_DIR_LTR; #endif - /*Set coordinates left top corner of parent*/ + /*Set the callbacks (signal:cb is required in `lv_obj_get_base_dir` if `LV_USE_ASSERT_OBJ` is enabled)*/ + new_obj->signal_cb = lv_obj_signal; + new_obj->design_cb = lv_obj_design; + new_obj->event_cb = NULL; + new_obj->coords.y1 = parent->coords.y1; new_obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT; if(lv_obj_get_base_dir(new_obj) == LV_BIDI_DIR_RTL) { new_obj->coords.x2 = parent->coords.x2; new_obj->coords.x1 = parent->coords.x2 - LV_OBJ_DEF_WIDTH; - } else { + } + else { new_obj->coords.x1 = parent->coords.x1; new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; } - new_obj->ext_draw_pad = 0; + } -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - memset(&new_obj->ext_click_pad, 0, sizeof(new_obj->ext_click_pad)); -#endif -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - new_obj->ext_click_pad_hor = 0; - new_obj->ext_click_pad_ver = 0; -#endif + _lv_ll_init(&(new_obj->child_ll), sizeof(lv_obj_t)); - /*Init realign*/ -#if LV_USE_OBJ_REALIGN - new_obj->realign.align = LV_ALIGN_CENTER; - new_obj->realign.xofs = 0; - new_obj->realign.yofs = 0; - new_obj->realign.base = NULL; - new_obj->realign.auto_realign = 0; -#endif - /*Set appearance*/ - lv_theme_t * th = lv_theme_get_current(); - if(th) { - new_obj->style_p = th->style.panel; - } else { - new_obj->style_p = &lv_style_plain_color; - } + + new_obj->ext_draw_pad = 0; #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL - memset(&new_obj->ext_click_pad, 0, sizeof(new_obj->ext_click_pad)); + _lv_memset_00(&new_obj->ext_click_pad, sizeof(new_obj->ext_click_pad)); +#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY + new_obj->ext_click_pad_hor = 0; + new_obj->ext_click_pad_ver = 0; #endif -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY - new_obj->ext_click_pad_hor = 0; - new_obj->ext_click_pad_ver = 0; + /*Init realign*/ +#if LV_USE_OBJ_REALIGN + new_obj->realign.align = LV_ALIGN_CENTER; + new_obj->realign.xofs = 0; + new_obj->realign.yofs = 0; + new_obj->realign.base = NULL; + new_obj->realign.auto_realign = 0; #endif - /*Init. user date*/ + /*Init. user date*/ #if LV_USE_USER_DATA - memset(&new_obj->user_data, 0, sizeof(lv_obj_user_data_t)); + _lv_memset_00(&new_obj->user_data, sizeof(lv_obj_user_data_t)); #endif + #if LV_USE_GROUP - new_obj->group_p = NULL; + new_obj->group_p = NULL; #endif - /*Set attributes*/ - new_obj->click = 1; - new_obj->drag = 0; - new_obj->drag_dir = LV_DRAG_DIR_ALL; - new_obj->drag_throw = 0; - new_obj->drag_parent = 0; - new_obj->hidden = 0; - new_obj->top = 0; - new_obj->protect = LV_PROTECT_NONE; - new_obj->opa_scale = LV_OPA_COVER; - new_obj->opa_scale_en = 0; - new_obj->parent_event = 0; - new_obj->reserved = 0; - - new_obj->ext_attr = NULL; + /*Set attributes*/ + new_obj->adv_hittest = 0; + new_obj->click = 1; + new_obj->drag = 0; + new_obj->drag_throw = 0; + new_obj->drag_parent = 0; + new_obj->drag_dir = LV_DRAG_DIR_BOTH; + new_obj->hidden = 0; + new_obj->top = 0; + new_obj->protect = LV_PROTECT_NONE; + new_obj->parent_event = 0; + new_obj->gesture_parent = 1; + new_obj->state = LV_STATE_DEFAULT; + + new_obj->ext_attr = NULL; + + lv_style_list_init(&new_obj->style_list); + if(copy == NULL) { + if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ); + else lv_theme_apply(new_obj, LV_THEME_SCR); + } + else { + lv_style_list_copy(&new_obj->style_list, ©->style_list); } - /*Copy the attributes if required*/ if(copy != NULL) { - LV_ASSERT_OBJ(copy, LV_OBJX_NAME); lv_area_copy(&new_obj->coords, ©->coords); new_obj->ext_draw_pad = copy->ext_draw_pad; #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL lv_area_copy(&new_obj->ext_click_pad, ©->ext_click_pad); -#endif - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY +#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY new_obj->ext_click_pad_hor = copy->ext_click_pad_hor; new_obj->ext_click_pad_ver = copy->ext_click_pad_ver; #endif - /*Set free data*/ + /*Set user data*/ #if LV_USE_USER_DATA - memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t)); + _lv_memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t)); #endif + /*Copy realign*/ #if LV_USE_OBJ_REALIGN new_obj->realign.align = copy->realign.align; @@ -349,6 +354,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->event_cb = copy->event_cb; /*Copy attributes*/ + new_obj->adv_hittest = copy->adv_hittest; new_obj->click = copy->click; new_obj->drag = copy->drag; new_obj->drag_dir = copy->drag_dir; @@ -358,11 +364,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->top = copy->top; new_obj->parent_event = copy->parent_event; - new_obj->opa_scale_en = copy->opa_scale_en; new_obj->protect = copy->protect; - new_obj->opa_scale = copy->opa_scale; - - new_obj->style_p = copy->style_p; + new_obj->gesture_parent = copy->gesture_parent; #if LV_USE_GROUP /*Add to the same group*/ @@ -374,11 +377,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Set the same coordinates for non screen objects*/ if(lv_obj_get_parent(copy) != NULL && parent != NULL) { lv_obj_set_pos(new_obj, lv_obj_get_x(copy), lv_obj_get_y(copy)); - } else { - lv_obj_set_pos(new_obj, 0, 0); } - - LV_LOG_INFO("Object create ready"); } /*Send a signal to the parent to notify it about the new child*/ @@ -389,6 +388,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) lv_obj_invalidate(new_obj); } + LV_LOG_INFO("Object create ready"); + return new_obj; } @@ -402,80 +403,42 @@ lv_res_t lv_obj_del(lv_obj_t * obj) LV_ASSERT_OBJ(obj, LV_OBJX_NAME); lv_obj_invalidate(obj); - /*Delete from the group*/ -#if LV_USE_GROUP - lv_group_t * group = lv_obj_get_group(obj); - if(group) lv_group_remove_obj(obj); -#endif - - /*Remove the animations from this object*/ -#if LV_USE_ANIMATION - lv_anim_del(obj, NULL); -#endif - - /*Recursively delete the children*/ - lv_obj_t * i; - lv_obj_t * i_next; - i = lv_ll_get_head(&(obj->child_ll)); - while(i != NULL) { - /*Get the next object before delete this*/ - i_next = lv_ll_get_next(&(obj->child_ll), i); - - /*Call the recursive del to the child too*/ - delete_children(i); - - /*Set i to the next node*/ - i = i_next; - } - - /*Let the user free the resources used in `LV_EVENT_DELETE`*/ - lv_event_send(obj, LV_EVENT_DELETE, NULL); - - lv_event_mark_deleted(obj); - - /* Reset all input devices if the object to delete is used*/ - lv_indev_t * indev = lv_indev_get_next(NULL); - while(indev) { - if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { - lv_indev_reset(indev); - } - if(indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; - } - -#if LV_USE_GROUP - if(indev->group == group && obj == lv_indev_get_obj_act()) { - lv_indev_reset(indev); - } -#endif - indev = lv_indev_get_next(indev); - } - - /* All children deleted. - * Now clean up the object specific data*/ - obj->signal_cb(obj, LV_SIGNAL_CLEANUP, NULL); - - /*Remove the object from parent's children list*/ + lv_disp_t * disp = NULL; + bool act_scr_del = false; lv_obj_t * par = lv_obj_get_parent(obj); - if(par == NULL) { /*It is a screen*/ - lv_disp_t * d = lv_obj_get_disp(obj); - lv_ll_rem(&d->scr_ll, obj); - } else { - lv_ll_rem(&(par->child_ll), obj); + if(par == NULL) { + disp = lv_obj_get_disp(obj); + if(!disp) return LV_RES_INV; /*Shouldn't happen*/ + if(disp->act_scr == obj) act_scr_del = true; } - /*Delete the base objects*/ - if(obj->ext_attr != NULL) lv_mem_free(obj->ext_attr); - lv_mem_free(obj); /*Free the object itself*/ + + obj_del_core(obj); /*Send a signal to the parent to notify it about the child delete*/ - if(par != NULL) { + if(par) { par->signal_cb(par, LV_SIGNAL_CHILD_CHG, NULL); } + /*Handle if the active screen was deleted*/ + if(act_scr_del) { + disp->act_scr = NULL; + } + return LV_RES_INV; } +#if LV_USE_ANIMATION +/** + * A function to be easily used in animation ready callback to delete an object when the animation is ready + * @param a pointer to the animation + */ +void lv_obj_del_anim_ready_cb(lv_anim_t * a) +{ + lv_obj_del(a->var); +} +#endif + /** * Helper function for asynchronously deleting objects. * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). @@ -507,10 +470,12 @@ void lv_obj_clean(lv_obj_t * obj) } /** - * Mark the object as invalid therefore its current position will be redrawn by 'lv_refr_task' + * Mark an area of an object as invalid. + * This area will be redrawn by 'lv_refr_task' * @param obj pointer to an object + * @param area the area to redraw */ -void lv_obj_invalidate(const lv_obj_t * obj) +void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); @@ -521,31 +486,56 @@ void lv_obj_invalidate(const lv_obj_t * obj) lv_disp_t * disp = lv_obj_get_disp(obj_scr); if(obj_scr == lv_disp_get_scr_act(disp) || obj_scr == lv_disp_get_layer_top(disp) || obj_scr == lv_disp_get_layer_sys(disp)) { - /*Truncate recursively to the parents*/ - lv_area_t area_trunc; - lv_obj_t * par = lv_obj_get_parent(obj); - bool union_ok = true; - /*Start with the original coordinates*/ + + /*Truncate the area to the object*/ + lv_area_t obj_coords; lv_coord_t ext_size = obj->ext_draw_pad; - lv_area_copy(&area_trunc, &obj->coords); - area_trunc.x1 -= ext_size; - area_trunc.y1 -= ext_size; - area_trunc.x2 += ext_size; - area_trunc.y2 += ext_size; + lv_area_copy(&obj_coords, &obj->coords); + obj_coords.x1 -= ext_size; + obj_coords.y1 -= ext_size; + obj_coords.x2 += ext_size; + obj_coords.y2 += ext_size; + + bool is_common; + lv_area_t area_trunc; - /*Check through all parents*/ + is_common = _lv_area_intersect(&area_trunc, area, &obj_coords); + if(is_common == false) return; /*The area is not on the object*/ + + /*Truncate recursively to the parents*/ + lv_obj_t * par = lv_obj_get_parent(obj); while(par != NULL) { - union_ok = lv_area_intersect(&area_trunc, &area_trunc, &par->coords); - if(union_ok == false) break; /*If no common parts with parent break;*/ + is_common = _lv_area_intersect(&area_trunc, &area_trunc, &par->coords); + if(is_common == false) break; /*If no common parts with parent break;*/ if(lv_obj_get_hidden(par)) return; /*If the parent is hidden then the child is hidden and won't be drawn*/ par = lv_obj_get_parent(par); } - if(union_ok) lv_inv_area(disp, &area_trunc); + if(is_common) _lv_inv_area(disp, &area_trunc); } } +/** + * Mark the object as invalid therefore its current position will be redrawn by 'lv_refr_task' + * @param obj pointer to an object + */ +void lv_obj_invalidate(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + /*Truncate the area to the object*/ + lv_area_t obj_coords; + lv_coord_t ext_size = obj->ext_draw_pad; + lv_area_copy(&obj_coords, &obj->coords); + obj_coords.x1 -= ext_size; + obj_coords.y1 -= ext_size; + obj_coords.x2 += ext_size; + obj_coords.y2 += ext_size; + + lv_obj_invalidate_area(obj, &obj_coords); + +} /*===================== * Setter functions *====================*/ @@ -564,7 +554,7 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) LV_ASSERT_OBJ(obj, LV_OBJX_NAME); LV_ASSERT_OBJ(parent, LV_OBJX_NAME); - if(obj->par == NULL) { + if(obj->parent == NULL) { LV_LOG_WARN("Can't set the parent of a screen"); return; } @@ -576,15 +566,31 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) lv_obj_invalidate(obj); + lv_obj_t * old_par = obj->parent; lv_point_t old_pos; - old_pos.x = lv_obj_get_x(obj); old_pos.y = lv_obj_get_y(obj); - lv_obj_t * old_par = obj->par; + lv_bidi_dir_t new_base_dir = lv_obj_get_base_dir(parent); + + if(new_base_dir != LV_BIDI_DIR_RTL) { + old_pos.x = lv_obj_get_x(obj); + } + else { + old_pos.x = old_par->coords.x2 - obj->coords.x2; + } + + _lv_ll_chg_list(&obj->parent->child_ll, &parent->child_ll, obj, true); + obj->parent = parent; + - lv_ll_chg_list(&obj->par->child_ll, &parent->child_ll, obj, true); - obj->par = parent; - lv_obj_set_pos(obj, old_pos.x, old_pos.y); + if(new_base_dir != LV_BIDI_DIR_RTL) { + lv_obj_set_pos(obj, old_pos.x, old_pos.y); + } + else { + /*Align to the right in case of RTL base dir*/ + lv_coord_t new_x = lv_obj_get_width(parent) - old_pos.x - lv_obj_get_width(obj); + lv_obj_set_pos(obj, new_x, old_pos.y); + } /*Notify the original parent because one of its children is lost*/ old_par->signal_cb(old_par, LV_SIGNAL_CHILD_CHG, NULL); @@ -606,11 +612,11 @@ void lv_obj_move_foreground(lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); /*Do nothing of already in the foreground*/ - if(lv_ll_get_head(&parent->child_ll) == obj) return; + if(_lv_ll_get_head(&parent->child_ll) == obj) return; lv_obj_invalidate(parent); - lv_ll_chg_list(&parent->child_ll, &parent->child_ll, obj, true); + _lv_ll_chg_list(&parent->child_ll, &parent->child_ll, obj, true); /*Notify the new parent about the child*/ parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); @@ -629,11 +635,11 @@ void lv_obj_move_background(lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); /*Do nothing of already in the background*/ - if(lv_ll_get_tail(&parent->child_ll) == obj) return; + if(_lv_ll_get_tail(&parent->child_ll) == obj) return; lv_obj_invalidate(parent); - lv_ll_chg_list(&parent->child_ll, &parent->child_ll, obj, false); + _lv_ll_chg_list(&parent->child_ll, &parent->child_ll, obj, false); /*Notify the new parent about the child*/ parent->signal_cb(parent, LV_SIGNAL_CHILD_CHG, obj); @@ -656,7 +662,12 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) LV_ASSERT_OBJ(obj, LV_OBJX_NAME); /*Convert x and y to absolute coordinates*/ - lv_obj_t * par = obj->par; + lv_obj_t * par = obj->parent; + + if(par == NULL) { + LV_LOG_WARN("lv_obj_set_pos: not changing position of screen object"); + return; + } x = x + par->coords.x1; y = y + par->coords.y1; @@ -686,7 +697,7 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) refresh_children_position(obj, diff.x, diff.y); /*Inform the object about its new coordinates*/ - obj->signal_cb(obj, LV_SIGNAL_CORD_CHG, &ori); + obj->signal_cb(obj, LV_SIGNAL_COORD_CHG, &ori); /*Send a signal to the parent too*/ par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); @@ -729,7 +740,6 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - /* Do nothing if the size is not changed */ /* It is very important else recursive resizing can * occur without size change*/ @@ -748,12 +758,13 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) obj->coords.y2 = obj->coords.y1 + h - 1; if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL) { obj->coords.x1 = obj->coords.x2 - w + 1; - } else { + } + else { obj->coords.x2 = obj->coords.x1 + w - 1; } /*Send a signal to the object with its new coordinates*/ - obj->signal_cb(obj, LV_SIGNAL_CORD_CHG, &ori); + obj->signal_cb(obj, LV_SIGNAL_COORD_CHG, &ori); /*Send a signal to the parent too*/ lv_obj_t * par = lv_obj_get_parent(obj); @@ -761,9 +772,8 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) /*Tell the children the parent's size has changed*/ lv_obj_t * i; - LV_LL_READ(obj->child_ll, i) - { - i->signal_cb(i, LV_SIGNAL_PARENT_SIZE_CHG, NULL); + _LV_LL_READ(obj->child_ll, i) { + i->signal_cb(i, LV_SIGNAL_PARENT_SIZE_CHG, &ori); } /*Invalidate the new area*/ @@ -799,21 +809,119 @@ void lv_obj_set_height(lv_obj_t * obj, lv_coord_t h) lv_obj_set_size(obj, lv_obj_get_width(obj), h); } +/** + * Set the width reduced by the left and right padding. + * @param obj pointer to an object + * @param w the width without paddings + */ +void lv_obj_set_width_fit(lv_obj_t * obj, lv_coord_t w) +{ + lv_style_int_t pleft = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN); + lv_style_int_t pright = lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN); + + lv_obj_set_width(obj, w - pleft - pright); +} + +/** + * Set the height reduced by the top and bottom padding. + * @param obj pointer to an object + * @param h the height without paddings + */ +void lv_obj_set_height_fit(lv_obj_t * obj, lv_coord_t h) +{ + lv_style_int_t ptop = lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN); + lv_style_int_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN); + + lv_obj_set_width(obj, h - ptop - pbottom); +} + +/** + * Set the width of an object by taking the left and right margin into account. + * The object width will be `obj_w = w - margon_left - margin_right` + * @param obj pointer to an object + * @param w new height including margins + */ +void lv_obj_set_width_margin(lv_obj_t * obj, lv_coord_t w) +{ + lv_style_int_t mleft = lv_obj_get_style_margin_left(obj, LV_OBJ_PART_MAIN); + lv_style_int_t mright = lv_obj_get_style_margin_right(obj, LV_OBJ_PART_MAIN); + + lv_obj_set_width(obj, w - mleft - mright); +} + +/** + * Set the height of an object by taking the top and bottom margin into account. + * The object height will be `obj_h = h - margon_top - margin_bottom` + * @param obj pointer to an object + * @param h new height including margins + */ +void lv_obj_set_height_margin(lv_obj_t * obj, lv_coord_t h) +{ + lv_style_int_t mtop = lv_obj_get_style_margin_top(obj, LV_OBJ_PART_MAIN); + lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(obj, LV_OBJ_PART_MAIN); + + lv_obj_set_height(obj, h - mtop - mbottom); +} + + /** * Align an object to an other object. * @param obj pointer to an object to align * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. * @param align type of alignment (see 'lv_align_t' enum) - * @param x_mod x coordinate shift after alignment - * @param y_mod y coordinate shift after alignment + * @param x_ofs x coordinate offset after alignment + * @param y_ofs y coordinate offset after alignment + */ +void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + if(base == NULL) base = lv_obj_get_parent(obj); + + LV_ASSERT_OBJ(base, LV_OBJX_NAME); + + lv_point_t new_pos; + _lv_area_align(&base->coords, &obj->coords, align, &new_pos); + + /*Bring together the coordination system of base and obj*/ + lv_obj_t * par = lv_obj_get_parent(obj); + lv_coord_t par_abs_x = par->coords.x1; + lv_coord_t par_abs_y = par->coords.y1; + new_pos.x += x_ofs; + new_pos.y += y_ofs; + new_pos.x -= par_abs_x; + new_pos.y -= par_abs_y; + + lv_obj_set_pos(obj, new_pos.x, new_pos.y); + +#if LV_USE_OBJ_REALIGN + /*Save the last align parameters to use them in `lv_obj_realign`*/ + obj->realign.align = align; + obj->realign.xofs = x_ofs; + obj->realign.yofs = y_ofs; + obj->realign.base = base; + obj->realign.origo_align = 0; +#endif +} + +/** + * Align an object's middle point to an other object. + * @param obj pointer to an object to align + * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. + * @param align type of alignment (see 'lv_align_t' enum) + * @param x_ofs x coordinate offset after alignment + * @param y_ofs y coordinate offset after alignment */ -void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod) +void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); lv_coord_t new_x = lv_obj_get_x(obj); lv_coord_t new_y = lv_obj_get_y(obj); + lv_coord_t obj_w_half = lv_obj_get_width(obj) / 2; + lv_coord_t obj_h_half = lv_obj_get_height(obj) / 2; + if(base == NULL) { base = lv_obj_get_parent(obj); } @@ -823,175 +931,22 @@ void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_co switch(align) { case LV_ALIGN_CENTER: - new_x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - new_y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = lv_obj_get_height(base) / 2 - obj_h_half; break; case LV_ALIGN_IN_TOP_LEFT: - new_x = 0; - new_y = 0; + new_x = -obj_w_half; + new_y = -obj_h_half; break; case LV_ALIGN_IN_TOP_MID: - new_x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - new_y = 0; + new_x = lv_obj_get_width(base) / 2 - obj_w_half; + new_y = -obj_h_half; break; case LV_ALIGN_IN_TOP_RIGHT: - new_x = lv_obj_get_width(base) - lv_obj_get_width(obj); - new_y = 0; - break; - - case LV_ALIGN_IN_BOTTOM_LEFT: - new_x = 0; - new_y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; - case LV_ALIGN_IN_BOTTOM_MID: - new_x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - new_y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; - - case LV_ALIGN_IN_BOTTOM_RIGHT: - new_x = lv_obj_get_width(base) - lv_obj_get_width(obj); - new_y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; - - case LV_ALIGN_IN_LEFT_MID: - new_x = 0; - new_y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; - - case LV_ALIGN_IN_RIGHT_MID: - new_x = lv_obj_get_width(base) - lv_obj_get_width(obj); - new_y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; - - case LV_ALIGN_OUT_TOP_LEFT: - new_x = 0; - new_y = -lv_obj_get_height(obj); - break; - - case LV_ALIGN_OUT_TOP_MID: - new_x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - new_y = -lv_obj_get_height(obj); - break; - - case LV_ALIGN_OUT_TOP_RIGHT: - new_x = lv_obj_get_width(base) - lv_obj_get_width(obj); - new_y = -lv_obj_get_height(obj); - break; - - case LV_ALIGN_OUT_BOTTOM_LEFT: - new_x = 0; - new_y = lv_obj_get_height(base); - break; - - case LV_ALIGN_OUT_BOTTOM_MID: - new_x = lv_obj_get_width(base) / 2 - lv_obj_get_width(obj) / 2; - new_y = lv_obj_get_height(base); - break; - - case LV_ALIGN_OUT_BOTTOM_RIGHT: - new_x = lv_obj_get_width(base) - lv_obj_get_width(obj); - new_y = lv_obj_get_height(base); - break; - - case LV_ALIGN_OUT_LEFT_TOP: - new_x = -lv_obj_get_width(obj); - new_y = 0; - break; - - case LV_ALIGN_OUT_LEFT_MID: - new_x = -lv_obj_get_width(obj); - new_y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; - - case LV_ALIGN_OUT_LEFT_BOTTOM: - new_x = -lv_obj_get_width(obj); - new_y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; - - case LV_ALIGN_OUT_RIGHT_TOP: - new_x = lv_obj_get_width(base); - new_y = 0; - break; - - case LV_ALIGN_OUT_RIGHT_MID: - new_x = lv_obj_get_width(base); - new_y = lv_obj_get_height(base) / 2 - lv_obj_get_height(obj) / 2; - break; - - case LV_ALIGN_OUT_RIGHT_BOTTOM: - new_x = lv_obj_get_width(base); - new_y = lv_obj_get_height(base) - lv_obj_get_height(obj); - break; - } - - /*Bring together the coordination system of base and obj*/ - lv_obj_t * par = lv_obj_get_parent(obj); - lv_coord_t base_abs_x = base->coords.x1; - lv_coord_t base_abs_y = base->coords.y1; - lv_coord_t par_abs_x = par->coords.x1; - lv_coord_t par_abs_y = par->coords.y1; - new_x += x_mod + base_abs_x; - new_y += y_mod + base_abs_y; - new_x -= par_abs_x; - new_y -= par_abs_y; - - lv_obj_set_pos(obj, new_x, new_y); - -#if LV_USE_OBJ_REALIGN - /*Save the last align parameters to use them in `lv_obj_realign`*/ - obj->realign.align = align; - obj->realign.xofs = x_mod; - obj->realign.yofs = y_mod; - obj->realign.base = base; - obj->realign.origo_align = 0; -#endif -} - -/** - * Align an object's middle point to an other object. - * @param obj pointer to an object to align - * @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it. - * @param align type of alignment (see 'lv_align_t' enum) - * @param x_mod x coordinate shift after alignment - * @param y_mod y coordinate shift after alignment - */ -void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_coord_t new_x = lv_obj_get_x(obj); - lv_coord_t new_y = lv_obj_get_y(obj); - - lv_coord_t obj_w_half = lv_obj_get_width(obj) / 2; - lv_coord_t obj_h_half = lv_obj_get_height(obj) / 2; - - if(base == NULL) { - base = lv_obj_get_parent(obj); - } - - LV_ASSERT_OBJ(base, LV_OBJX_NAME); - - - switch(align) { - case LV_ALIGN_CENTER: - new_x = lv_obj_get_width(base) / 2 - obj_w_half; - new_y = lv_obj_get_height(base) / 2 - obj_h_half; - break; - - case LV_ALIGN_IN_TOP_LEFT: - new_x = -obj_w_half; - new_y = -obj_h_half; - break; - case LV_ALIGN_IN_TOP_MID: - new_x = lv_obj_get_width(base) / 2 - obj_w_half; - new_y = -obj_h_half; - break; - - case LV_ALIGN_IN_TOP_RIGHT: - new_x = lv_obj_get_width(base) - obj_w_half; - new_y = -obj_h_half; + new_x = lv_obj_get_width(base) - obj_w_half; + new_y = -obj_h_half; break; case LV_ALIGN_IN_BOTTOM_LEFT: @@ -1085,8 +1040,8 @@ void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t base_abs_y = base->coords.y1; lv_coord_t par_abs_x = par->coords.x1; lv_coord_t par_abs_y = par->coords.y1; - new_x += x_mod + base_abs_x; - new_y += y_mod + base_abs_y; + new_x += x_ofs + base_abs_x; + new_y += y_ofs + base_abs_y; new_x -= par_abs_x; new_y -= par_abs_y; @@ -1095,8 +1050,8 @@ void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, #if LV_USE_OBJ_REALIGN /*Save the last align parameters to use them in `lv_obj_realign`*/ obj->realign.align = align; - obj->realign.xofs = x_mod; - obj->realign.yofs = y_mod; + obj->realign.xofs = x_ofs; + obj->realign.yofs = y_ofs; obj->realign.base = base; obj->realign.origo_align = 1; #endif @@ -1177,35 +1132,273 @@ void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right *--------------------*/ /** - * Set a new style for an object + * Add a new style to the style list of an object. * @param obj pointer to an object - * @param style_p pointer to the new style + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param style pointer to a style to add (Only its pointer will be saved) */ -void lv_obj_set_style(lv_obj_t * obj, const lv_style_t * style) +void lv_obj_add_style(lv_obj_t * obj, uint8_t part, lv_style_t * style) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - LV_ASSERT_STYLE(style); + if(style == NULL) return; + + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + if(style_dsc == NULL) { + LV_LOG_WARN("Can't find style with part: %d", part); + return; + } + + _lv_style_list_add_style(style_dsc, style); +#if LV_USE_ANIMATION + trans_del(obj, part, 0xFF, NULL); +#endif + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); +} + +/** + * Remove a style from the style list of an object. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param style pointer to a style to remove + */ +void lv_obj_remove_style(lv_obj_t * obj, uint8_t part, lv_style_t * style) +{ + if(style == NULL) return; + + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + if(style_dsc == NULL) { + LV_LOG_WARN("Can't find style with part: %d", part); + return; + } - obj->style_p = style; + _lv_style_list_remove_style(style_dsc, style); +#if LV_USE_ANIMATION + trans_del(obj, part, 0xFF, NULL); +#endif + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); +} - /*Send a signal about style change to every children with NULL style*/ - refresh_children_style(obj); +/** + * Reset a style to the default (empty) state. + * Release all used memories and cancel pending related transitions. + * Typically used in `LV_SIGN_CLEAN_UP. + * @param obj pointer to an object + * @param part the part of the object which style list should be reseted. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + */ +void lv_obj_clean_style_list(lv_obj_t * obj, uint8_t part) +{ + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + if(style_dsc == NULL) { + LV_LOG_WARN("lv_obj_clean_style_list: can't find style with `part`"); + return; + } - /*Notify the object about the style change too*/ - lv_obj_refresh_style(obj); + _lv_style_list_reset(style_dsc); +#if LV_USE_ANIMATION + trans_del(obj, part, 0xFF, NULL); +#endif } /** - * Notify an object about its style is modified + * Reset a style to the default (empty) state. + * Release all used memories and cancel pending related transitions. + * Also notifies the object about the style change. * @param obj pointer to an object + * @param part the part of the object which style list should be reseted. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` */ -void lv_obj_refresh_style(lv_obj_t * obj) +void lv_obj_reset_style_list(lv_obj_t * obj, uint8_t part) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_obj_clean_style_list(obj, part); - lv_obj_invalidate(obj); - obj->signal_cb(obj, LV_SIGNAL_STYLE_CHG, NULL); - lv_obj_invalidate(obj); + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); +} + +/** + * Set a local style property of a part of an object in a given state. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop a style property ORed with a state. + * E.g. `LV_STYLE_BORDER_WIDTH | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` + * @param the value to set + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has integer type + */ +void _lv_obj_set_style_local_int(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, lv_style_int_t value) +{ + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + _lv_style_list_set_local_int(style_dsc, prop, value); +#if LV_USE_ANIMATION + trans_del(obj, part, prop, NULL); +#endif + lv_obj_refresh_style(obj, prop & (~LV_STYLE_STATE_MASK)); +} + +/** + * Set a local style property of a part of an object in a given state. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop a style property ORed with a state. + * E.g. `LV_STYLE_BORDER_COLOR | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` + * @param the value to set + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has color type + */ +void _lv_obj_set_style_local_color(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, lv_color_t color) +{ + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + _lv_style_list_set_local_color(style_dsc, prop, color); +#if LV_USE_ANIMATION + trans_del(obj, part, prop, NULL); +#endif + lv_obj_refresh_style(obj, prop & (~LV_STYLE_STATE_MASK)); +} + +/** + * Set a local style property of a part of an object in a given state. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop a style property ORed with a state. + * E.g. `LV_STYLE_BORDER_OPA | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` + * @param the value to set + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has opacity type + */ +void _lv_obj_set_style_local_opa(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, lv_opa_t opa) +{ + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + _lv_style_list_set_local_opa(style_dsc, prop, opa); +#if LV_USE_ANIMATION + trans_del(obj, part, prop, NULL); +#endif + lv_obj_refresh_style(obj, prop & (~LV_STYLE_STATE_MASK)); +} + +/** + * Set a local style property of a part of an object in a given state. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop a style property ORed with a state. + * E.g. `LV_STYLE_TEXT_FONT | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` + * @param value the value to set + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has pointer type + */ +void _lv_obj_set_style_local_ptr(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, const void * value) +{ + lv_style_list_t * style_dsc = lv_obj_get_style_list(obj, part); + _lv_style_list_set_local_ptr(style_dsc, prop, value); +#if LV_USE_ANIMATION + trans_del(obj, part, prop, NULL); +#endif + lv_obj_refresh_style(obj, prop & (~LV_STYLE_STATE_MASK)); +} + +/** + * Remove a local style property from a part of an object with a given state. + * @param obj pointer to an object + * @param part the part of the object which style property should be removed. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop a style property ORed with a state. + * E.g. `LV_STYLE_TEXT_FONT | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)` + * @note shouldn't be used directly. Use the specific property remove functions instead. + * For example: `lv_obj_style_remove_border_opa()` + * @return true: the property was found and removed; false: teh property was not found + */ +bool lv_obj_remove_style_local_prop(lv_obj_t * obj, uint8_t part, lv_style_property_t prop) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_style_t * style = lv_obj_get_local_style(obj, part); + if(style) return lv_style_remove_prop(style, prop); + else return false; +} + +/** + * Notify an object (and its children) about its style is modified + * @param obj pointer to an object + * @param prop `LV_STYLE_PROP_ALL` or an `LV_STYLE_...` property. It is used to optimize what needs to be refreshed. + */ +void lv_obj_refresh_style(lv_obj_t * obj, lv_style_property_t prop) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + /*If a real style refresh is required*/ + bool real_refr = false; + switch(prop) { + case LV_STYLE_PROP_ALL: + case LV_STYLE_CLIP_CORNER: + case LV_STYLE_SIZE: + case LV_STYLE_TRANSFORM_WIDTH: + case LV_STYLE_TRANSFORM_HEIGHT: + case LV_STYLE_TRANSFORM_ANGLE: + case LV_STYLE_TRANSFORM_ZOOM: + case LV_STYLE_PAD_TOP: + case LV_STYLE_PAD_BOTTOM: + case LV_STYLE_PAD_LEFT: + case LV_STYLE_PAD_RIGHT: + case LV_STYLE_PAD_INNER: + case LV_STYLE_MARGIN_TOP: + case LV_STYLE_MARGIN_BOTTOM: + case LV_STYLE_MARGIN_LEFT: + case LV_STYLE_MARGIN_RIGHT: + case LV_STYLE_OUTLINE_WIDTH: + case LV_STYLE_OUTLINE_PAD: + case LV_STYLE_OUTLINE_OPA: + case LV_STYLE_SHADOW_WIDTH: + case LV_STYLE_SHADOW_OPA: + case LV_STYLE_SHADOW_OFS_X: + case LV_STYLE_SHADOW_OFS_Y: + case LV_STYLE_SHADOW_SPREAD: + case LV_STYLE_VALUE_LETTER_SPACE: + case LV_STYLE_VALUE_LINE_SPACE: + case LV_STYLE_VALUE_OFS_X: + case LV_STYLE_VALUE_OFS_Y: + case LV_STYLE_VALUE_ALIGN: + case LV_STYLE_VALUE_STR: + case LV_STYLE_VALUE_FONT: + case LV_STYLE_VALUE_OPA: + case LV_STYLE_TEXT_LETTER_SPACE: + case LV_STYLE_TEXT_LINE_SPACE: + case LV_STYLE_TEXT_FONT: + case LV_STYLE_LINE_WIDTH: + real_refr = true; + break; + default: + real_refr = false; + } + + if(real_refr) { + lv_obj_invalidate(obj); + obj->signal_cb(obj, LV_SIGNAL_STYLE_CHG, NULL); + + switch(prop) { + case LV_STYLE_PROP_ALL: + case LV_STYLE_MARGIN_TOP: + case LV_STYLE_MARGIN_BOTTOM: + case LV_STYLE_MARGIN_LEFT: + case LV_STYLE_MARGIN_RIGHT: + if(obj->parent) obj->parent->signal_cb(obj->parent, LV_SIGNAL_CHILD_CHG, NULL); + break; + } + + lv_obj_invalidate(obj); + + /*Send style change signals*/ + if(prop == LV_STYLE_PROP_ALL || (prop & LV_STYLE_INHERIT_MASK)) refresh_children_style(obj); + } + else { + lv_obj_invalidate(obj); + } } /** @@ -1215,18 +1408,11 @@ void lv_obj_refresh_style(lv_obj_t * obj) */ void lv_obj_report_style_mod(lv_style_t * style) { - LV_ASSERT_STYLE(style); - lv_disp_t * d = lv_disp_get_next(NULL); while(d) { lv_obj_t * i; - LV_LL_READ(d->scr_ll, i) - { - if(i->style_p == style || style == NULL) { - lv_obj_refresh_style(i); - } - + _LV_LL_READ(d->scr_ll, i) { report_style_mod_core(style, i); } d = lv_disp_get_next(d); @@ -1253,7 +1439,19 @@ void lv_obj_set_hidden(lv_obj_t * obj, bool en) if(!obj->hidden) lv_obj_invalidate(obj); /*Invalidate when not hidden (hidden objects are ignored) */ lv_obj_t * par = lv_obj_get_parent(obj); - par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); + if(par) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); +} + +/** + * Set whether advanced hit-testing is enabled on an object + * @param obj pointer to an object + * @param en true: advanced hit-testing is enabled + */ +void lv_obj_set_adv_hittest(lv_obj_t * obj, bool en) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + obj->adv_hittest = en == false ? 0 : 1; } /** @@ -1333,6 +1531,17 @@ void lv_obj_set_drag_parent(lv_obj_t * obj, bool en) obj->drag_parent = (en == true ? 1 : 0); } +/** +* Enable to use parent for gesture related operations. +* If trying to gesture the object the parent will be moved instead +* @param obj pointer to an object +* @param en true: enable the 'gesture parent' for the object +*/ +void lv_obj_set_gesture_parent(lv_obj_t * obj, bool en) +{ + obj->gesture_parent = (en == true ? 1 : 0); +} + /** * Propagate the events to the parent too * @param obj pointer to an object @@ -1345,6 +1554,11 @@ void lv_obj_set_parent_event(lv_obj_t * obj, bool en) obj->parent_event = (en == true ? 1 : 0); } +/** + * Set the base direction of the object + * @param obj pointer to an object + * @param dir the new base direction. `LV_BIDI_DIR_LTR/RTL/AUTO/INHERIT` + */ void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) { if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL && @@ -1363,57 +1577,157 @@ void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) } /** - * Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`) + * Set a bit or bits in the protect filed * @param obj pointer to an object - * @param en true: opa scaling is enabled for this object and all children; false: no opa scaling + * @param prot 'OR'-ed values from `lv_protect_t` */ -void lv_obj_set_opa_scale_enable(lv_obj_t * obj, bool en) +void lv_obj_add_protect(lv_obj_t * obj, uint8_t prot) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - obj->opa_scale_en = en ? 1 : 0; + obj->protect |= prot; } /** - * Set the opa scale of an object. - * The opacity of this object and all it's children will be scaled down with this factor. - * `lv_obj_set_opa_scale_enable(obj, true)` needs to be called to enable it. - * (not for all children just for the parent where to start the opa scaling) + * Clear a bit or bits in the protect filed * @param obj pointer to an object - * @param opa_scale a factor to scale down opacity [0..255] + * @param prot 'OR'-ed values from `lv_protect_t` */ -void lv_obj_set_opa_scale(lv_obj_t * obj, lv_opa_t opa_scale) +void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - obj->opa_scale = opa_scale; - lv_obj_invalidate(obj); + prot = (~prot) & 0xFF; + obj->protect &= prot; } /** - * Set a bit or bits in the protect filed + * Set the state (fully overwrite) of an object. + * If specified in the styles a transition animation will be started + * from the previous state to the current * @param obj pointer to an object - * @param prot 'OR'-ed values from `lv_protect_t` + * @param state the new state */ -void lv_obj_set_protect(lv_obj_t * obj, uint8_t prot) +void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) { + if(obj->state == new_state) return; + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - obj->protect |= prot; +#if LV_USE_ANIMATION == 0 + obj->state = new_state; + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); +#else + lv_state_t prev_state = obj->state; + obj->state = new_state; + + uint8_t part; + for(part = 0; part < _LV_OBJ_PART_REAL_LAST; part++) { + lv_style_list_t * style_list = lv_obj_get_style_list(obj, part); + if(style_list == NULL) break; /*No more style lists*/ + if(style_list->ignore_trans) continue; + + lv_style_int_t time = lv_obj_get_style_transition_time(obj, part); + lv_style_property_t props[LV_STYLE_TRANS_NUM_MAX]; + lv_style_int_t delay = lv_obj_get_style_transition_delay(obj, part); + lv_anim_path_t * path = lv_obj_get_style_transition_path(obj, part); + props[0] = lv_obj_get_style_transition_prop_1(obj, part); + props[1] = lv_obj_get_style_transition_prop_2(obj, part); + props[2] = lv_obj_get_style_transition_prop_3(obj, part); + props[3] = lv_obj_get_style_transition_prop_4(obj, part); + props[4] = lv_obj_get_style_transition_prop_5(obj, part); + props[5] = lv_obj_get_style_transition_prop_6(obj, part); + + uint8_t i; + for(i = 0; i < LV_STYLE_TRANS_NUM_MAX; i++) { + if(props[i] != 0) { + _lv_style_list_add_trans_style(style_list); + + lv_style_trans_t * tr = trans_create(obj, props[i], part, prev_state, new_state); + + /*If there is a pending anim for this property remove it*/ + if(tr) { + tr->obj = obj; + tr->prop = props[i]; + tr->part = part; + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, tr); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)trans_anim_cb); + lv_anim_set_start_cb(&a, trans_anim_start_cb); + lv_anim_set_ready_cb(&a, trans_anim_ready_cb); + lv_anim_set_values(&a, 0x00, 0xFF); + lv_anim_set_time(&a, time); + lv_anim_set_delay(&a, delay); + lv_anim_set_path(&a, path); + a.early_apply = 0; + lv_anim_start(&a); + } + + } + } + } +#endif + + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); + } /** - * Clear a bit or bits in the protect filed + * Add a given state or states to the object. The other state bits will remain unchanged. + * If specified in the styles a transition animation will be started + * from the previous state to the current * @param obj pointer to an object - * @param prot 'OR'-ed values from `lv_protect_t` + * @param state the state bits to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` */ -void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot) +void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - prot = (~prot) & 0xFF; - obj->protect &= prot; + lv_state_t new_state = obj->state | state; + if(obj->state != new_state) { + lv_obj_set_state(obj, new_state); + } +} + +/** + * Remove a given state or states to the object. The other state bits will remain unchanged. + * If specified in the styles a transition animation will be started + * from the previous state to the current + * @param obj pointer to an object + * @param state the state bits to remove. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + */ +void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_state_t new_state = obj->state & (~state); + if(obj->state != new_state) { + lv_obj_set_state(obj, new_state); + } +} + +#if LV_USE_ANIMATION +/** + * Finish all pending transitions on a part of an object + * @param obj pointer to an object + * @param part part of the object, e.g `LV_BRN_PART_MAIN` or `LV_OBJ_PART_ALL` for all parts + */ +void lv_obj_finish_transitions(lv_obj_t * obj, uint8_t part) +{ + /*Animate all related transition to the end value*/ + lv_style_trans_t * tr; + _LV_LL_READ_BACK(LV_GC_ROOT(_lv_obj_style_trans_ll), tr) { + if(tr->obj == obj && (part == tr->part || part == LV_OBJ_PART_ALL)) { + trans_anim_cb(tr, 255); + } + } + + /*Free all related transition data*/ + trans_del(obj, part, 0xFF, NULL); } +#endif /** * Set a an event handler function for an object. @@ -1458,7 +1772,9 @@ lv_res_t lv_event_send(lv_obj_t * obj, lv_event_t event, const void * data) */ lv_res_t lv_event_send_func(lv_event_cb_t event_xcb, lv_obj_t * obj, lv_event_t event, const void * data) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + if(obj != NULL) { + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + } /* Build a simple linked list from the objects used in the events * It's important to know if an this object was deleted by a nested event @@ -1496,8 +1812,8 @@ lv_res_t lv_event_send_func(lv_event_cb_t event_xcb, lv_obj_t * obj, lv_event_t } if(obj) { - if(obj->parent_event && obj->par) { - lv_res_t res = lv_event_send(obj->par, event, data); + if(obj->parent_event && obj->parent) { + lv_res_t res = lv_event_send(obj->parent, event, data); if(res != LV_RES_OK) { return LV_RES_INV; } @@ -1533,13 +1849,17 @@ void lv_obj_set_signal_cb(lv_obj_t * obj, lv_signal_cb_t signal_cb) * Send an event to the object * @param obj pointer to an object * @param event the type of the event from `lv_event_t`. + * @return LV_RES_OK or LV_RES_INV */ -void lv_signal_send(lv_obj_t * obj, lv_signal_t signal, void * param) +lv_res_t lv_signal_send(lv_obj_t * obj, lv_signal_t signal, void * param) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + if(obj == NULL) return LV_RES_OK; - if(obj->signal_cb) obj->signal_cb(obj, signal, param); -} + lv_res_t res = LV_RES_OK; + if(obj->signal_cb) res = obj->signal_cb(obj, signal, param); + + return res; +} /** * Set a new design function for an object @@ -1561,19 +1881,23 @@ void lv_obj_set_design_cb(lv_obj_t * obj, lv_design_cb_t design_cb) * Allocate a new ext. data for an object * @param obj pointer to an object * @param ext_size the size of the new ext. data - * @return Normal pointer to the allocated ext + * @return pointer to the allocated ext. + * If out of memory NULL is returned and the original ext is preserved */ void * lv_obj_allocate_ext_attr(lv_obj_t * obj, uint16_t ext_size) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - obj->ext_attr = lv_mem_realloc(obj->ext_attr, ext_size); + void * new_ext = lv_mem_realloc(obj->ext_attr, ext_size); + if(new_ext == NULL) return NULL; + obj->ext_attr = new_ext; return (void *)obj->ext_attr; } /** - * Send a 'LV_SIGNAL_REFR_EXT_SIZE' signal to the object + * Send a 'LV_SIGNAL_REFR_EXT_SIZE' signal to the object to refresh the extended draw area. + * he object needs to be invalidated by `lv_obj_invalidate(obj)` manually after this function. * @param obj pointer to an object */ void lv_obj_refresh_ext_draw_pad(lv_obj_t * obj) @@ -1583,7 +1907,6 @@ void lv_obj_refresh_ext_draw_pad(lv_obj_t * obj) obj->ext_draw_pad = 0; obj->signal_cb(obj, LV_SIGNAL_REFR_EXT_DRAW_PAD, NULL); - lv_obj_invalidate(obj); } /*======================= @@ -1621,17 +1944,15 @@ lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) const lv_obj_t * scr; - if(obj->par == NULL) + if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/ else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/ lv_disp_t * d; - LV_LL_READ(LV_GC_ROOT(_lv_disp_ll), d) - { + _LV_LL_READ(LV_GC_ROOT(_lv_disp_ll), d) { lv_obj_t * s; - LV_LL_READ(d->scr_ll, s) - { + _LV_LL_READ(d->scr_ll, s) { if(s == scr) return d; } } @@ -1653,7 +1974,7 @@ lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - return obj->par; + return obj->parent; } /** @@ -1670,9 +1991,10 @@ lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child) lv_obj_t * result = NULL; if(child == NULL) { - result = lv_ll_get_head(&obj->child_ll); - } else { - result = lv_ll_get_next(&obj->child_ll, child); + result = _lv_ll_get_head(&obj->child_ll); + } + else { + result = _lv_ll_get_next(&obj->child_ll, child); } return result; @@ -1692,9 +2014,10 @@ lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child) lv_obj_t * result = NULL; if(child == NULL) { - result = lv_ll_get_tail(&obj->child_ll); - } else { - result = lv_ll_get_prev(&obj->child_ll, child); + result = _lv_ll_get_tail(&obj->child_ll); + } + else { + result = _lv_ll_get_prev(&obj->child_ll, child); } return result; @@ -1712,7 +2035,7 @@ uint16_t lv_obj_count_children(const lv_obj_t * obj) lv_obj_t * i; uint16_t cnt = 0; - LV_LL_READ(obj->child_ll, i) cnt++; + _LV_LL_READ(obj->child_ll, i) cnt++; return cnt; } @@ -1728,8 +2051,7 @@ uint16_t lv_obj_count_children_recursive(const lv_obj_t * obj) lv_obj_t * i; uint16_t cnt = 0; - LV_LL_READ(obj->child_ll, i) - { + _LV_LL_READ(obj->child_ll, i) { cnt++; /*Count the child*/ cnt += lv_obj_count_children_recursive(i); /*recursively count children's children*/ } @@ -1762,14 +2084,16 @@ void lv_obj_get_inner_coords(const lv_obj_t * obj, lv_area_t * coords_p) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.border.part & LV_BORDER_LEFT) coords_p->x1 += style->body.border.width; + lv_border_side_t part = lv_obj_get_style_border_side(obj, LV_OBJ_PART_MAIN); + lv_coord_t w = lv_obj_get_style_border_width(obj, LV_OBJ_PART_MAIN); - if(style->body.border.part & LV_BORDER_RIGHT) coords_p->x2 -= style->body.border.width; + if(part & LV_BORDER_SIDE_LEFT) coords_p->x1 += w; - if(style->body.border.part & LV_BORDER_TOP) coords_p->y1 += style->body.border.width; + if(part & LV_BORDER_SIDE_RIGHT) coords_p->x2 -= w; - if(style->body.border.part & LV_BORDER_BOTTOM) coords_p->y2 -= style->body.border.width; + if(part & LV_BORDER_SIDE_TOP) coords_p->y1 += w; + + if(part & LV_BORDER_SIDE_BOTTOM) coords_p->y2 -= w; } /** @@ -1785,7 +2109,8 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) { rel_x = obj->coords.x1 - parent->coords.x1; - } else { + } + else { rel_x = obj->coords.x1; } return rel_x; @@ -1802,11 +2127,12 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj) lv_coord_t rel_y; lv_obj_t * parent = lv_obj_get_parent(obj); - if(parent) { - rel_y = obj->coords.y1 - parent->coords.y1; - } else { - rel_y = obj->coords.y1; - } + if(parent) { + rel_y = obj->coords.y1 - parent->coords.y1; + } + else { + rel_y = obj->coords.y1; + } return rel_y; } @@ -1843,9 +2169,10 @@ lv_coord_t lv_obj_get_width_fit(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); + lv_style_int_t left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN); + lv_style_int_t right = lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN); - return lv_obj_get_width(obj) - style->body.padding.left - style->body.padding.right; + return lv_obj_get_width(obj) - left - right; } /** @@ -1857,9 +2184,80 @@ lv_coord_t lv_obj_get_height_fit(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); + lv_style_int_t top = lv_obj_get_style_pad_top((lv_obj_t *)obj, LV_OBJ_PART_MAIN); + lv_style_int_t bottom = lv_obj_get_style_pad_bottom((lv_obj_t *)obj, LV_OBJ_PART_MAIN); + + return lv_obj_get_height(obj) - top - bottom; +} + +/** + * Get the height of an object by taking the top and bottom margin into account. + * The returned height will be `obj_h + margon_top + margin_bottom` + * @param obj pointer to an object + * @return the height including thee margins + */ +lv_coord_t lv_obj_get_height_margin(lv_obj_t * obj) +{ + lv_style_int_t mtop = lv_obj_get_style_margin_top(obj, LV_OBJ_PART_MAIN); + lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(obj, LV_OBJ_PART_MAIN); + + return lv_obj_get_height(obj) + mtop + mbottom; +} + +/** + * Get the width of an object by taking the left and right margin into account. + * The returned width will be `obj_w + margon_left + margin_right` + * @param obj pointer to an object + * @return the height including thee margins + */ +lv_coord_t lv_obj_get_width_margin(lv_obj_t * obj) +{ + lv_style_int_t mleft = lv_obj_get_style_margin_left(obj, LV_OBJ_PART_MAIN); + lv_style_int_t mright = lv_obj_get_style_margin_right(obj, LV_OBJ_PART_MAIN); + + return lv_obj_get_width(obj) + mleft + mright; +} + +/** + * Set that width reduced by the left and right padding of the parent. + * @param obj pointer to an object + * @param div indicates how many columns are assumed. + * If 1 the width will be set the the parent's width + * If 2 only half parent width - inner padding of the parent + * If 3 only third parent width - 2 * inner padding of the parent + * @param span how many columns are combined + * @return the width according to the given parameters + */ +lv_coord_t lv_obj_get_width_grid(lv_obj_t * obj, uint8_t div, uint8_t span) +{ + lv_coord_t obj_w = lv_obj_get_width_fit(obj); + lv_style_int_t pinner = lv_obj_get_style_pad_inner(obj, LV_OBJ_PART_MAIN); + + lv_coord_t r = (obj_w - (div - 1) * pinner) / div; + + r = r * span + (span - 1) * pinner; + return r; +} + +/** + * Get that height reduced by the top and bottom padding of the parent. + * @param obj pointer to an object + * @param div indicates how many rows are assumed. + * If 1 the height will be set the the parent's height + * If 2 only half parent height - inner padding of the parent + * If 3 only third parent height - 2 * inner padding of the parent + * @param span how many rows are combined + * @return the height according to the given parameters + */ +lv_coord_t lv_obj_get_height_grid(lv_obj_t * obj, uint8_t div, uint8_t span) +{ + lv_coord_t obj_h = lv_obj_get_height_fit(obj); + lv_style_int_t pinner = lv_obj_get_style_pad_inner(obj, LV_OBJ_PART_MAIN); - return lv_obj_get_height(obj) - style->body.padding.top - style->body.padding.bottom; + lv_coord_t r = (obj_h - (div - 1) * pinner) / div; + + r = r * span + (span - 1) * pinner; + return r; } /** @@ -1971,50 +2369,270 @@ lv_coord_t lv_obj_get_ext_draw_pad(const lv_obj_t * obj) * Appearance get *---------------*/ +lv_style_list_t * lv_obj_get_style_list(const lv_obj_t * obj, uint8_t part) +{ + if(part == LV_OBJ_PART_MAIN) return &((lv_obj_t *)obj)->style_list; + + lv_get_style_info_t info; + info.part = part; + info.result = NULL; + + lv_res_t res; + res = lv_signal_send((lv_obj_t *)obj, LV_SIGNAL_GET_STYLE, &info); + + if(res != LV_RES_OK) return NULL; + + return info.result; +} + /** - * Get the style pointer of an object (if NULL get style of the parent) + * Get a style property of a part of an object in the object's current state. + * If there is a running transitions it is taken into account * @param obj pointer to an object - * @return pointer to a style + * @param part the part of the object which style property should be get. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop the property to get. E.g. `LV_STYLE_BORDER_WIDTH`. + * The state of the object will be added internally + * @return the value of the property of the given part in the current state. + * If the property is not found a default value will be returned. + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_width()` + * @note for performance reasons it's not checked if the property really has integer type */ -const lv_style_t * lv_obj_get_style(const lv_obj_t * obj) +lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_style_property_t prop) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_style_property_t prop_ori = prop; - const lv_style_t * style_act = obj->style_p; - if(style_act == NULL) { - lv_obj_t * par = obj->par; + lv_style_attr_t attr; + attr.full = prop_ori >> 8; - while(par) { - if(par->style_p) { - if(par->style_p->glass == 0) { -#if LV_USE_GROUP == 0 - style_act = par->style_p; -#else - /*If a parent is focused then use then focused style*/ - lv_group_t * g = lv_obj_get_group(par); - if(lv_group_get_focused(g) == par) { - style_act = lv_group_mod_style(g, par->style_p); - } else { - style_act = par->style_p; - } -#endif - break; - } - } - par = par->par; + lv_style_int_t value_act; + lv_res_t res = LV_RES_INV; + const lv_obj_t * parent = obj; + while(parent) { + lv_style_list_t * dsc = lv_obj_get_style_list(parent, part); + + lv_state_t state = lv_obj_get_state(parent, part); + prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); + + res = _lv_style_list_get_int(dsc, prop, &value_act); + if(res == LV_RES_OK) return value_act; + + if(attr.bits.inherit == 0) break; + + /*If not found, check the `MAIN` style first*/ + if(part != LV_OBJ_PART_MAIN) { + part = LV_OBJ_PART_MAIN; + continue; + } + + /*Check the parent too.*/ + parent = lv_obj_get_parent(parent); + } + + /*Handle unset values*/ + prop = prop & (~LV_STYLE_STATE_MASK); + switch(prop) { + case LV_STYLE_BORDER_SIDE: + return LV_BORDER_SIDE_FULL; + case LV_STYLE_SIZE: + return LV_DPI / 20; + case LV_STYLE_SCALE_WIDTH: + return LV_DPI / 8; + case LV_STYLE_BG_GRAD_STOP: + return 255; + case LV_STYLE_TRANSFORM_ZOOM: + return LV_IMG_ZOOM_NONE; + } + + return 0; +} + +/** + * Get a style property of a part of an object in the object's current state. + * If there is a running transitions it is taken into account + * @param obj pointer to an object + * @param part the part of the object which style property should be get. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop the property to get. E.g. `LV_STYLE_BORDER_COLOR`. + * The state of the object will be added internally + * @return the value of the property of the given part in the current state. + * If the property is not found a default value will be returned. + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_color()` + * @note for performance reasons it's not checked if the property really has color type + */ +lv_color_t _lv_obj_get_style_color(const lv_obj_t * obj, uint8_t part, lv_style_property_t prop) +{ + lv_style_property_t prop_ori = prop; + + lv_style_attr_t attr; + attr.full = prop_ori >> 8; + + lv_color_t value_act; + lv_res_t res = LV_RES_INV; + const lv_obj_t * parent = obj; + while(parent) { + lv_style_list_t * dsc = lv_obj_get_style_list(parent, part); + + lv_state_t state = lv_obj_get_state(parent, part); + prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); + + res = _lv_style_list_get_color(dsc, prop, &value_act); + if(res == LV_RES_OK) return value_act; + + if(attr.bits.inherit == 0) break; + + /*If not found, check the `MAIN` style first*/ + if(part != LV_OBJ_PART_MAIN) { + part = LV_OBJ_PART_MAIN; + continue; } + + /*Check the parent too.*/ + parent = lv_obj_get_parent(parent); } -#if LV_USE_GROUP - if(obj->group_p) { - if(lv_group_get_focused(obj->group_p) == obj) { - style_act = lv_group_mod_style(obj->group_p, style_act); + + /*Handle unset values*/ + prop = prop & (~LV_STYLE_STATE_MASK); + switch(prop) { + case LV_STYLE_BG_COLOR: + case LV_STYLE_BG_GRAD_COLOR: + return LV_COLOR_WHITE; + } + + return LV_COLOR_BLACK; +} + +/** + * Get a style property of a part of an object in the object's current state. + * If there is a running transitions it is taken into account + * @param obj pointer to an object + * @param part the part of the object which style property should be get. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop the property to get. E.g. `LV_STYLE_BORDER_OPA`. + * The state of the object will be added internally + * @return the value of the property of the given part in the current state. + * If the property is not found a default value will be returned. + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has opacity type + */ +lv_opa_t _lv_obj_get_style_opa(const lv_obj_t * obj, uint8_t part, lv_style_property_t prop) +{ + lv_style_property_t prop_ori = prop; + + lv_style_attr_t attr; + attr.full = prop_ori >> 8; + + lv_opa_t value_act; + lv_res_t res = LV_RES_INV; + const lv_obj_t * parent = obj; + while(parent) { + lv_style_list_t * dsc = lv_obj_get_style_list(parent, part); + + lv_state_t state = lv_obj_get_state(parent, part); + prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); + + res = _lv_style_list_get_opa(dsc, prop, &value_act); + if(res == LV_RES_OK) return value_act; + + if(attr.bits.inherit == 0) break; + + /*If not found, check the `MAIN` style first*/ + if(part != LV_OBJ_PART_MAIN) { + part = LV_OBJ_PART_MAIN; + continue; + } + + /*Check the parent too.*/ + parent = lv_obj_get_parent(parent); + } + + /*Handle unset values*/ + prop = prop & (~LV_STYLE_STATE_MASK); + switch(prop) { + case LV_STYLE_BG_OPA: + case LV_STYLE_IMAGE_RECOLOR_OPA: + case LV_STYLE_PATTERN_RECOLOR_OPA: + return LV_OPA_TRANSP; + } + + return LV_OPA_COVER; +} + +/** + * Get a style property of a part of an object in the object's current state. + * If there is a running transitions it is taken into account + * @param obj pointer to an object + * @param part the part of the object which style property should be get. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @param prop the property to get. E.g. `LV_STYLE_TEXT_FONT`. + * The state of the object will be added internally + * @return the value of the property of the given part in the current state. + * If the property is not found a default value will be returned. + * @note shouldn't be used directly. Use the specific property get functions instead. + * For example: `lv_obj_style_get_border_opa()` + * @note for performance reasons it's not checked if the property really has pointer type + */ +const void * _lv_obj_get_style_ptr(const lv_obj_t * obj, uint8_t part, lv_style_property_t prop) +{ + lv_style_property_t prop_ori = prop; + + lv_style_attr_t attr; + attr.full = prop_ori >> 8; + + const void * value_act; + lv_res_t res = LV_RES_INV; + const lv_obj_t * parent = obj; + while(parent) { + lv_style_list_t * dsc = lv_obj_get_style_list(parent, part); + + lv_state_t state = lv_obj_get_state(parent, part); + prop = (uint16_t)prop_ori + ((uint16_t)state << LV_STYLE_STATE_POS); + + res = _lv_style_list_get_ptr(dsc, prop, &value_act); + if(res == LV_RES_OK) return value_act; + + if(attr.bits.inherit == 0) break; + + /*If not found, check the `MAIN` style first*/ + if(part != LV_OBJ_PART_MAIN) { + part = LV_OBJ_PART_MAIN; + continue; } + + /*Check the parent too.*/ + parent = lv_obj_get_parent(parent); } + + /*Handle unset values*/ + prop = prop & (~LV_STYLE_STATE_MASK); + switch(prop) { + case LV_STYLE_TEXT_FONT: + case LV_STYLE_VALUE_FONT: + return lv_theme_get_font_normal(); +#if LV_USE_ANIMATION + case LV_STYLE_TRANSITION_PATH: + return &lv_anim_path_def; #endif + } - if(style_act == NULL) style_act = &lv_style_plain; + return NULL; +} - return style_act; +/** + * Get the local style of a part of an object. + * @param obj pointer to an object + * @param part the part of the object which style property should be set. + * E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_PART_MAIN`, `LV_SLIDER_PART_KNOB` + * @return pointer to the local style if exists else `NULL`. + */ +lv_style_t * lv_obj_get_local_style(lv_obj_t * obj, uint8_t part) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_style_list_t * style_list = lv_obj_get_style_list(obj, part); + return lv_style_list_get_local_style(style_list); } /*----------------- @@ -2033,6 +2651,18 @@ bool lv_obj_get_hidden(const lv_obj_t * obj) return obj->hidden == 0 ? false : true; } +/** + * Get whether advanced hit-testing is enabled on an object + * @param obj pointer to an object + * @return true: advanced hit-testing is enabled + */ +bool lv_obj_get_adv_hittest(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + return obj->adv_hittest == 0 ? false : true; +} + /** * Get the click enable attribute of an object * @param obj pointer to an object @@ -2103,6 +2733,16 @@ bool lv_obj_get_drag_parent(const lv_obj_t * obj) return obj->drag_parent == 0 ? false : true; } +/** +* Get the gesture parent attribute of an object +* @param obj pointer to an object +* @return true: gesture parent is enabled +*/ +bool lv_obj_get_gesture_parent(const lv_obj_t * obj) +{ + return obj->gesture_parent == 0 ? false : true; +} + /** * Get the drag parent attribute of an object * @param obj pointer to an object @@ -2118,6 +2758,8 @@ bool lv_obj_get_parent_event(const lv_obj_t * obj) lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) { + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + #if LV_USE_BIDI const lv_obj_t * parent = obj; @@ -2134,38 +2776,6 @@ lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) #endif } - -/** - * Get the opa scale enable parameter - * @param obj pointer to an object - * @return true: opa scaling is enabled for this object and all children; false: no opa scaling - */ -lv_opa_t lv_obj_get_opa_scale_enable(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - return obj->opa_scale_en == 0 ? false : true; -} - -/** - * Get the opa scale parameter of an object - * @param obj pointer to an object - * @return opa scale [0..255] - */ -lv_opa_t lv_obj_get_opa_scale(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - const lv_obj_t * parent = obj; - - while(parent) { - if(parent->opa_scale_en) return parent->opa_scale; - parent = lv_obj_get_parent(parent); - } - - return LV_OPA_COVER; -} - /** * Get the protect field of an object * @param obj pointer to an object @@ -2191,6 +2801,24 @@ bool lv_obj_is_protected(const lv_obj_t * obj, uint8_t prot) return (obj->protect & prot) == 0 ? false : true; } +lv_state_t lv_obj_get_state(const lv_obj_t * obj, uint8_t part) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + if(part < _LV_OBJ_PART_REAL_LAST) return ((lv_obj_t *)obj)->state; + + /*If a real part is asked, then use the object's signal to get its state. + * A real object can be in different state then the main part + * and only the object itseld knows who to get it's state. */ + lv_get_state_info_t info; + info.part = part; + info.result = LV_STATE_DEFAULT; + lv_signal_send((lv_obj_t *)obj, LV_SIGNAL_GET_STATE_DSC, &info); + + return info.result; + +} + /** * Get the signal function of an object * @param obj pointer to an object @@ -2257,8 +2885,8 @@ void lv_obj_get_type(const lv_obj_t * obj, lv_obj_type_t * buf) lv_obj_type_t tmp; - memset(buf, 0, sizeof(lv_obj_type_t)); - memset(&tmp, 0, sizeof(lv_obj_type_t)); + _lv_memset_00(buf, sizeof(lv_obj_type_t)); + _lv_memset_00(&tmp, sizeof(lv_obj_type_t)); obj->signal_cb((lv_obj_t *)obj, LV_SIGNAL_GET_TYPE, &tmp); @@ -2309,11 +2937,10 @@ void lv_obj_set_user_data(lv_obj_t * obj, lv_obj_user_data_t data) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - memcpy(&obj->user_data, &data, sizeof(lv_obj_user_data_t)); + _lv_memcpy(&obj->user_data, &data, sizeof(lv_obj_user_data_t)); } #endif -#if LV_USE_GROUP /** * Get the group of the object * @param obj pointer to an object @@ -2323,7 +2950,12 @@ void * lv_obj_get_group(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +#if LV_USE_GROUP return obj->group_p; +#else + LV_UNUSED(obj); + return NULL; +#endif } /** @@ -2335,19 +2967,75 @@ bool lv_obj_is_focused(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +#if LV_USE_GROUP if(obj->group_p) { if(lv_group_get_focused(obj->group_p) == obj) return true; } - return false; -} +#else + LV_UNUSED(obj); + return false; #endif +} /*------------------- * OTHER FUNCTIONS *------------------*/ +/** + * Check if a given screen-space point is on an object's coordinates. + * + * This method is intended to be used mainly by advanced hit testing algorithms to check + * whether the point is even within the object (as an optimization). + * @param obj object to check + * @param point screen-space point + */ +bool lv_obj_is_point_on_coords(lv_obj_t * obj, const lv_point_t * point) +{ +#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY + lv_area_t ext_area; + ext_area.x1 = obj->coords.x1 - obj->ext_click_pad_hor; + ext_area.x2 = obj->coords.x2 + obj->ext_click_pad_hor; + ext_area.y1 = obj->coords.y1 - obj->ext_click_pad_ver; + ext_area.y2 = obj->coords.y2 + obj->ext_click_pad_ver; + + if(!_lv_area_is_point_on(&ext_area, point, 0)) { +#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL + lv_area_t ext_area; + ext_area.x1 = obj->coords.x1 - obj->ext_click_pad.x1; + ext_area.x2 = obj->coords.x2 + obj->ext_click_pad.x2; + ext_area.y1 = obj->coords.y1 - obj->ext_click_pad.y1; + ext_area.y2 = obj->coords.y2 + obj->ext_click_pad.y2; + + if(!_lv_area_is_point_on(&ext_area, point, 0)) { +#else + if(!_lv_area_is_point_on(&obj->coords, point, 0)) { +#endif + return false; + } + return true; +} + +/** + * Hit-test an object given a particular point in screen space. + * @param obj object to hit-test + * @param point screen-space point + * @return true if the object is considered under the point + */ +bool lv_obj_hittest(lv_obj_t * obj, lv_point_t * point) +{ + if(obj->adv_hittest) { + lv_hit_test_info_t hit_info; + hit_info.point = point; + hit_info.result = true; + obj->signal_cb(obj, LV_SIGNAL_HIT_TEST, &hit_info); + return hit_info.result; + } + else + return lv_obj_is_point_on_coords(obj, point); +} + /** * Used in the signal callback to handle `LV_SIGNAL_GET_TYPE` signal * @param obj pointer to an object @@ -2366,67 +3054,545 @@ lv_res_t lv_obj_handle_get_type_signal(lv_obj_type_t * buf, const char * name) return LV_RES_OK; } -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_obj_del_async_cb(void * obj) -{ - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - - lv_obj_del(obj); -} - /** - * Handle the drawing related tasks of the base objects. + * Initialize a rectangle descriptor from an object's styles * @param obj pointer to an object - * @param mask the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * @param return true/false, depends on 'mode' + * @param type type of style. E.g. `LV_OBJ_PART_MAIN`, `LV_BTN_STYLE_REL` or `LV_PAGE_STYLE_SCRL` + * @param draw_dsc the descriptor the initialize + * @note Only the relevant fields will be set. + * E.g. if `border width == 0` the other border properties won't be evaluated. */ -static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode) +void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint8_t part, lv_draw_rect_dsc_t * draw_dsc) { - if(mode == LV_DESIGN_COVER_CHK) { - - /*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/ - if(lv_area_is_in(mask_p, &obj->coords) == false) return false; + draw_dsc->radius = lv_obj_get_style_radius(obj, part); - /*Can cover the area only if fully solid (no opacity)*/ - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.opa < LV_OPA_MAX) return false; - - /* Because of the radius it is not sure the area is covered - * Check the areas where there is no radius*/ - lv_coord_t r = style->body.radius; +#if LV_USE_OPA_SCALE + lv_opa_t opa_scale = lv_obj_get_style_opa_scale(obj, part); + if(opa_scale <= LV_OPA_MIN) { + draw_dsc->bg_opa = LV_OPA_TRANSP; + draw_dsc->border_opa = LV_OPA_TRANSP; + draw_dsc->shadow_opa = LV_OPA_TRANSP; + draw_dsc->pattern_opa = LV_OPA_TRANSP; + draw_dsc->value_opa = LV_OPA_TRANSP; + return; + } +#endif - if(r == LV_RADIUS_CIRCLE) return false; + if(draw_dsc->bg_opa != LV_OPA_TRANSP) { + draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part); + if(draw_dsc->bg_opa > LV_OPA_MIN) { + draw_dsc->bg_color = lv_obj_get_style_bg_color(obj, part); + draw_dsc->bg_grad_dir = lv_obj_get_style_bg_grad_dir(obj, part); + if(draw_dsc->bg_grad_dir != LV_GRAD_DIR_NONE) { + draw_dsc->bg_grad_color = lv_obj_get_style_bg_grad_color(obj, part); + draw_dsc->bg_main_color_stop = lv_obj_get_style_bg_main_stop(obj, part); + draw_dsc->bg_grad_color_stop = lv_obj_get_style_bg_grad_stop(obj, part); + } - lv_area_t area_tmp; +#if LV_USE_BLEND_MODES + draw_dsc->bg_blend_mode = lv_obj_get_style_bg_blend_mode(obj, part); +#endif + } + } - /*Check horizontally without radius*/ - lv_obj_get_coords(obj, &area_tmp); - area_tmp.x1 += r; - area_tmp.x2 -= r; - if(lv_area_is_in(mask_p, &area_tmp) == false) return false; + if(draw_dsc->border_opa != LV_OPA_TRANSP) { + draw_dsc->border_width = lv_obj_get_style_border_width(obj, part); + if(draw_dsc->border_width) { + draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part); + if(draw_dsc->border_opa > LV_OPA_MIN) { + draw_dsc->border_side = lv_obj_get_style_border_side(obj, part); + draw_dsc->border_color = lv_obj_get_style_border_color(obj, part); + } +#if LV_USE_BLEND_MODES + draw_dsc->border_blend_mode = lv_obj_get_style_border_blend_mode(obj, part); +#endif + } + } - /*Check vertically without radius*/ - lv_obj_get_coords(obj, &area_tmp); - area_tmp.y1 += r; - area_tmp.y2 -= r; - if(lv_area_is_in(mask_p, &area_tmp) == false) return false; - } else if(mode == LV_DESIGN_DRAW_MAIN) { - const lv_style_t * style = lv_obj_get_style(obj); - lv_draw_rect(&obj->coords, mask_p, style, lv_obj_get_opa_scale(obj)); + if(draw_dsc->outline_opa != LV_OPA_TRANSP) { + draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part); + if(draw_dsc->outline_width) { + draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part); + if(draw_dsc->outline_opa > LV_OPA_MIN) { + draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part); + draw_dsc->outline_color = lv_obj_get_style_outline_color(obj, part); + } +#if LV_USE_BLEND_MODES + draw_dsc->outline_blend_mode = lv_obj_get_style_outline_blend_mode(obj, part); +#endif + } } - return true; -} - -/** - * Signal function of the basic object + if(draw_dsc->pattern_opa != LV_OPA_TRANSP) { + draw_dsc->pattern_image = lv_obj_get_style_pattern_image(obj, part); + if(draw_dsc->pattern_image) { + draw_dsc->pattern_opa = lv_obj_get_style_pattern_opa(obj, part); + if(draw_dsc->pattern_opa > LV_OPA_MIN) { + draw_dsc->pattern_recolor_opa = lv_obj_get_style_pattern_recolor_opa(obj, part); + draw_dsc->pattern_repeat = lv_obj_get_style_pattern_repeat(obj, part); + if(lv_img_src_get_type(draw_dsc->pattern_image) == LV_IMG_SRC_SYMBOL) { + draw_dsc->pattern_recolor = lv_obj_get_style_pattern_recolor(obj, part); + draw_dsc->pattern_font = lv_obj_get_style_text_font(obj, part); + } + else if(draw_dsc->pattern_recolor_opa > LV_OPA_MIN) { + draw_dsc->pattern_recolor = lv_obj_get_style_pattern_recolor(obj, part); + } +#if LV_USE_BLEND_MODES + draw_dsc->pattern_blend_mode = lv_obj_get_style_pattern_blend_mode(obj, part); +#endif + } + } + } +#if LV_USE_SHADOW + if(draw_dsc->shadow_opa > LV_OPA_MIN) { + draw_dsc->shadow_width = lv_obj_get_style_shadow_width(obj, part); + if(draw_dsc->shadow_width) { + draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part); + if(draw_dsc->shadow_opa > LV_OPA_MIN) { + draw_dsc->shadow_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part); + draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part); + draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part); + draw_dsc->shadow_color = lv_obj_get_style_shadow_color(obj, part); +#if LV_USE_BLEND_MODES + draw_dsc->shadow_blend_mode = lv_obj_get_style_shadow_blend_mode(obj, part); +#endif + } + } + } +#endif + + if(draw_dsc->value_opa > LV_OPA_MIN) { + draw_dsc->value_str = lv_obj_get_style_value_str(obj, part); + if(draw_dsc->value_str) { + draw_dsc->value_opa = lv_obj_get_style_value_opa(obj, part); + if(draw_dsc->value_opa > LV_OPA_MIN) { + draw_dsc->value_ofs_x = lv_obj_get_style_value_ofs_x(obj, part); + draw_dsc->value_ofs_y = lv_obj_get_style_value_ofs_y(obj, part); + draw_dsc->value_color = lv_obj_get_style_value_color(obj, part); + draw_dsc->value_font = lv_obj_get_style_value_font(obj, part); + draw_dsc->value_letter_space = lv_obj_get_style_value_letter_space(obj, part); + draw_dsc->value_line_space = lv_obj_get_style_value_line_space(obj, part); + draw_dsc->value_align = lv_obj_get_style_value_align(obj, part); +#if LV_USE_BLEND_MODES + draw_dsc->value_blend_mode = lv_obj_get_style_value_blend_mode(obj, part); +#endif + } + } + } + +#if LV_USE_OPA_SCALE + if(opa_scale < LV_OPA_MAX) { + draw_dsc->bg_opa = (uint16_t)((uint16_t)draw_dsc->bg_opa * opa_scale) >> 8; + draw_dsc->border_opa = (uint16_t)((uint16_t)draw_dsc->border_opa * opa_scale) >> 8; + draw_dsc->shadow_opa = (uint16_t)((uint16_t)draw_dsc->shadow_opa * opa_scale) >> 8; + draw_dsc->pattern_opa = (uint16_t)((uint16_t)draw_dsc->pattern_opa * opa_scale) >> 8; + draw_dsc->value_opa = (uint16_t)((uint16_t)draw_dsc->value_opa * opa_scale) >> 8; + } +#endif +} + +void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint8_t part, lv_draw_label_dsc_t * draw_dsc) +{ + draw_dsc->opa = lv_obj_get_style_text_opa(obj, part); + if(draw_dsc->opa <= LV_OPA_MIN) return; + +#if LV_USE_OPA_SCALE + lv_opa_t opa_scale = lv_obj_get_style_opa_scale(obj, part); + if(opa_scale < LV_OPA_MAX) { + draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8; + } + if(draw_dsc->opa <= LV_OPA_MIN) return; +#endif + + draw_dsc->color = lv_obj_get_style_text_color(obj, part); + draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part); + draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part); + draw_dsc->decor = lv_obj_get_style_text_decor(obj, part); +#if LV_USE_BLEND_MODES + draw_dsc->blend_mode = lv_obj_get_style_text_blend_mode(obj, part); +#endif + + draw_dsc->font = lv_obj_get_style_text_font(obj, part); + + if(draw_dsc->sel_start != LV_DRAW_LABEL_NO_TXT_SEL && draw_dsc->sel_end != LV_DRAW_LABEL_NO_TXT_SEL) { + draw_dsc->color = lv_obj_get_style_text_sel_color(obj, part); + } + +#if LV_USE_BIDI + draw_dsc->bidi_dir = lv_obj_get_base_dir(obj); +#endif +} + +void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint8_t part, lv_draw_img_dsc_t * draw_dsc) +{ + draw_dsc->opa = lv_obj_get_style_image_opa(obj, part); + if(draw_dsc->opa <= LV_OPA_MIN) return; + +#if LV_USE_OPA_SCALE + lv_opa_t opa_scale = lv_obj_get_style_opa_scale(obj, part); + if(opa_scale < LV_OPA_MAX) { + draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8; + } + if(draw_dsc->opa <= LV_OPA_MIN) return; +#endif + + draw_dsc->angle = 0; + draw_dsc->zoom = LV_IMG_ZOOM_NONE; + draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2; + draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2; + + draw_dsc->recolor_opa = lv_obj_get_style_image_recolor_opa(obj, part); + draw_dsc->recolor = lv_obj_get_style_image_recolor(obj, part); + +#if LV_USE_BLEND_MODES + draw_dsc->blend_mode = lv_obj_get_style_image_blend_mode(obj, part); +#endif +} + +void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint8_t part, lv_draw_line_dsc_t * draw_dsc) +{ + draw_dsc->opa = lv_obj_get_style_line_opa(obj, part); + if(draw_dsc->opa <= LV_OPA_MIN) return; + +#if LV_USE_OPA_SCALE + lv_opa_t opa_scale = lv_obj_get_style_opa_scale(obj, part); + if(opa_scale < LV_OPA_MAX) { + draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8; + } + if(draw_dsc->opa <= LV_OPA_MIN) return; +#endif + + draw_dsc->width = lv_obj_get_style_line_width(obj, part); + if(draw_dsc->width == 0) return; + + draw_dsc->color = lv_obj_get_style_line_color(obj, part); + + draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part); + if(draw_dsc->dash_width) { + draw_dsc->dash_gap = lv_obj_get_style_line_dash_gap(obj, part); + } + + draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part); + draw_dsc->round_end = draw_dsc->round_start; + +#if LV_USE_BLEND_MODES + draw_dsc->blend_mode = lv_obj_get_style_line_blend_mode(obj, part); +#endif +} + +/** + * Get the required extra size (around the object's part) to draw shadow, outline, value etc. + * @param obj poinr to an object + * @param part part of the object + */ +lv_coord_t lv_obj_get_draw_rect_ext_pad_size(lv_obj_t * obj, uint8_t part) +{ + lv_coord_t s = 0; + + lv_coord_t sh_width = lv_obj_get_style_shadow_width(obj, part); + if(sh_width) { + lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part); + if(sh_opa > LV_OPA_MIN) { + sh_width = sh_width / 2; /*THe blur adds only half width*/ + sh_width++; + sh_width += lv_obj_get_style_shadow_spread(obj, part); + lv_style_int_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part); + lv_style_int_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part); + sh_width += LV_MATH_MAX(LV_MATH_ABS(sh_ofs_x), LV_MATH_ABS(sh_ofs_y)); + s = LV_MATH_MAX(s, sh_width); + } + } + + const char * value_str = lv_obj_get_style_value_str(obj, part); + if(value_str) { + lv_opa_t value_opa = lv_obj_get_style_value_opa(obj, part); + if(value_opa > LV_OPA_MIN) { + lv_style_int_t letter_space = lv_obj_get_style_value_letter_space(obj, part); + lv_style_int_t line_space = lv_obj_get_style_value_letter_space(obj, part); + const lv_font_t * font = lv_obj_get_style_value_font(obj, part); + + lv_point_t txt_size; + _lv_txt_get_size(&txt_size, value_str, font, letter_space, line_space, LV_COORD_MAX, LV_TXT_FLAG_NONE); + + lv_area_t value_area; + value_area.x1 = 0; + value_area.y1 = 0; + value_area.x2 = txt_size.x - 1; + value_area.y2 = txt_size.y - 1; + + lv_style_int_t align = lv_obj_get_style_value_align(obj, part); + lv_style_int_t xofs = lv_obj_get_style_value_ofs_x(obj, part); + lv_style_int_t yofs = lv_obj_get_style_value_ofs_y(obj, part); + lv_point_t p_align; + _lv_area_align(&obj->coords, &value_area, align, &p_align); + + value_area.x1 += p_align.x + xofs; + value_area.y1 += p_align.y + yofs; + value_area.x2 += p_align.x + xofs; + value_area.y2 += p_align.y + yofs; + + s = LV_MATH_MAX(s, obj->coords.x1 - value_area.x1); + s = LV_MATH_MAX(s, obj->coords.y1 - value_area.y1); + s = LV_MATH_MAX(s, value_area.x2 - obj->coords.x2); + s = LV_MATH_MAX(s, value_area.y2 - obj->coords.y2); + } + } + + lv_style_int_t outline_width = lv_obj_get_style_outline_width(obj, part); + if(outline_width) { + lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part); + if(outline_opa > LV_OPA_MIN) { + lv_style_int_t outline_pad = lv_obj_get_style_outline_pad(obj, part); + s = LV_MATH_MAX(s, outline_pad + outline_width); + } + } + + lv_coord_t w = lv_obj_get_style_transform_width(obj, part); + lv_coord_t h = lv_obj_get_style_transform_height(obj, part); + lv_coord_t wh = LV_MATH_MAX(w, h); + if(wh > 0) s += wh; + + return s; +} + +/** + * Fade in (from transparent to fully cover) an object and all its children using an `opa_scale` animation. + * @param obj the object to fade in + * @param time duration of the animation [ms] + * @param delay wait before the animation starts [ms] + */ +void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay) +{ +#if LV_USE_ANIMATION + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)opa_scale_anim); + lv_anim_set_ready_cb(&a, fade_in_anim_ready); + lv_anim_set_time(&a, time); + lv_anim_set_delay(&a, delay); + lv_anim_start(&a); +#else + (void) obj; /*Unused*/ + (void) time; /*Unused*/ + (void) delay; /*Unused*/ +#endif +} + +/** + * Fade out (from fully cover to transparent) an object and all its children using an `opa_scale` animation. + * @param obj the object to fade in + * @param time duration of the animation [ms] + * @param delay wait before the animation starts [ms] + */ +void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay) +{ +#if LV_USE_ANIMATION + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_TRANSP); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)opa_scale_anim); + lv_anim_set_time(&a, time); + lv_anim_set_delay(&a, delay); + lv_anim_start(&a); +#else + (void) obj; /*Unused*/ + (void) time; /*Unused*/ + (void) delay; /*Unused*/ +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_obj_del_async_cb(void * obj) +{ + LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + + lv_obj_del(obj); +} + +static void obj_del_core(lv_obj_t * obj) +{ + /*Let the user free the resources used in `LV_EVENT_DELETE`*/ + lv_event_send(obj, LV_EVENT_DELETE, NULL); + + /*Delete from the group*/ +#if LV_USE_GROUP + lv_group_t * group = lv_obj_get_group(obj); + if(group) lv_group_remove_obj(obj); +#endif + + /*Remove the animations from this object*/ +#if LV_USE_ANIMATION + lv_anim_del(obj, NULL); + trans_del(obj, 0xFF, 0xFF, NULL); +#endif + + /*Delete the user data*/ +#if LV_USE_USER_DATA +#if LV_USE_USER_DATA_FREE + LV_USER_DATA_FREE(obj); +#endif +#endif + + /*Recursively delete the children*/ + lv_obj_t * i; + lv_obj_t * i_next; + i = _lv_ll_get_head(&(obj->child_ll)); + while(i != NULL) { + /*Get the next object before delete this*/ + i_next = _lv_ll_get_next(&(obj->child_ll), i); + + /*Call the recursive del to the child too*/ + obj_del_core(i); + + /*Set i to the next node*/ + i = i_next; + } + + lv_event_mark_deleted(obj); + + /* Reset all input devices if the object to delete is used*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { + if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { + lv_indev_reset(indev, obj); + } + if(indev->proc.types.pointer.last_pressed == obj) { + indev->proc.types.pointer.last_pressed = NULL; + } + +#if LV_USE_GROUP + if(indev->group == group && obj == lv_indev_get_obj_act()) { + lv_indev_reset(indev, obj); + } +#endif + indev = lv_indev_get_next(indev); + } + + /* All children deleted. + * Now clean up the object specific data*/ + obj->signal_cb(obj, LV_SIGNAL_CLEANUP, NULL); + + /*Remove the object from parent's children list*/ + lv_obj_t * par = lv_obj_get_parent(obj); + if(par == NULL) { /*It is a screen*/ + lv_disp_t * d = lv_obj_get_disp(obj); + _lv_ll_remove(&d->scr_ll, obj); + } + else { + _lv_ll_remove(&(par->child_ll), obj); + } + + /*Delete the base objects*/ + if(obj->ext_attr != NULL) lv_mem_free(obj->ext_attr); + lv_mem_free(obj); /*Free the object itself*/ +} + +/** + * Handle the drawing related tasks of the base objects. + * @param obj pointer to an object + * @param clip_area the object will be drawn only in this area + * @param mode LV_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') + * @param return an element of `lv_design_res_t` + */ +static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area, lv_design_mode_t mode) +{ + if(mode == LV_DESIGN_COVER_CHK) { + if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) return LV_DESIGN_RES_MASKED; + + /*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/ + lv_coord_t r = lv_obj_get_style_radius(obj, LV_OBJ_PART_MAIN); + lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_OBJ_PART_MAIN); + lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_OBJ_PART_MAIN); + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + coords.x1 -= w; + coords.x2 += w; + coords.y1 -= h; + coords.y2 += h; + + if(_lv_area_is_in(clip_area, &coords, r) == false) return LV_DESIGN_RES_NOT_COVER; + + if(lv_obj_get_style_bg_opa(obj, LV_OBJ_PART_MAIN) < LV_OPA_MAX) return LV_DESIGN_RES_NOT_COVER; + + if(lv_obj_get_style_bg_blend_mode(obj, LV_OBJ_PART_MAIN) != LV_BLEND_MODE_NORMAL) return LV_DESIGN_RES_NOT_COVER; + if(lv_obj_get_style_border_blend_mode(obj, LV_OBJ_PART_MAIN) != LV_BLEND_MODE_NORMAL) return LV_DESIGN_RES_NOT_COVER; + if(lv_obj_get_style_opa_scale(obj, LV_OBJ_PART_MAIN) < LV_OPA_MAX) return LV_DESIGN_RES_NOT_COVER; + + return LV_DESIGN_RES_COVER; + + } + else if(mode == LV_DESIGN_DRAW_MAIN) { + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + /*If the border is drawn later disable loading its properties*/ + if(lv_obj_get_style_border_post(obj, LV_OBJ_PART_MAIN)) { + draw_dsc.border_opa = LV_OPA_TRANSP; + } + + lv_obj_init_draw_rect_dsc(obj, LV_OBJ_PART_MAIN, &draw_dsc); + + lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_OBJ_PART_MAIN); + lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_OBJ_PART_MAIN); + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + coords.x1 -= w; + coords.x2 += w; + coords.y1 -= h; + coords.y2 += h; + + lv_draw_rect(&coords, clip_area, &draw_dsc); + + if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { + lv_draw_mask_radius_param_t * mp = _lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); + + lv_coord_t r = lv_obj_get_style_radius(obj, LV_OBJ_PART_MAIN); + + lv_draw_mask_radius_init(mp, &obj->coords, r, false); + /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ + lv_draw_mask_add(mp, obj + 8); + } + } + else if(mode == LV_DESIGN_DRAW_POST) { + if(lv_obj_get_style_clip_corner(obj, LV_OBJ_PART_MAIN)) { + lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); + _lv_mem_buf_release(param); + } + + /*If the border is drawn later disable loading other properties*/ + if(lv_obj_get_style_border_post(obj, LV_OBJ_PART_MAIN)) { + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + draw_dsc.bg_opa = LV_OPA_TRANSP; + draw_dsc.pattern_opa = LV_OPA_TRANSP; + draw_dsc.shadow_opa = LV_OPA_TRANSP; + lv_obj_init_draw_rect_dsc(obj, LV_OBJ_PART_MAIN, &draw_dsc); + + lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_OBJ_PART_MAIN); + lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_OBJ_PART_MAIN); + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + coords.x1 -= w; + coords.x2 += w; + coords.y1 -= h; + coords.y2 += h; + lv_draw_rect(&coords, clip_area, &draw_dsc); + } + } + + return LV_DESIGN_RES_OK; +} + +/** + * Signal function of the basic object * @param obj pointer to an object * @param sign signal type * @param param parameter for the signal (depends on signal type) @@ -2434,19 +3600,60 @@ static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mo */ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) { - if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); + if(sign == LV_SIGNAL_GET_STYLE) { + lv_get_style_info_t * info = param; + if(info->part == LV_OBJ_PART_MAIN) info->result = &obj->style_list; + else info->result = NULL; + return LV_RES_OK; + } + else if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); lv_res_t res = LV_RES_OK; if(sign == LV_SIGNAL_CHILD_CHG) { /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; - } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.shadow.width > obj->ext_draw_pad) obj->ext_draw_pad = style->body.shadow.width; - } else if(sign == LV_SIGNAL_STYLE_CHG) { + } + else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { + lv_coord_t d = lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN); + obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); + } +#if LV_USE_OBJ_REALIGN + else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) { + if(obj->realign.auto_realign) { + lv_obj_realign(obj); + } + } +#endif + else if(sign == LV_SIGNAL_STYLE_CHG) { lv_obj_refresh_ext_draw_pad(obj); } + else if(sign == LV_SIGNAL_PRESSED) { + lv_obj_add_state(obj, LV_STATE_PRESSED); + } + else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) { + lv_obj_clear_state(obj, LV_STATE_PRESSED); + } +#if LV_USE_GROUP + else if(sign == LV_SIGNAL_FOCUS) { + if(lv_group_get_editing(lv_obj_get_group(obj))) { + uint8_t state = LV_STATE_FOCUSED; + state |= LV_STATE_EDITED; + lv_obj_add_state(obj, state); + } + else { + lv_obj_add_state(obj, LV_STATE_FOCUSED); + lv_obj_clear_state(obj, LV_STATE_EDITED); + } + } + else if(sign == LV_SIGNAL_DEFOCUS) { + lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED); + } +#endif + else if(sign == LV_SIGNAL_CLEANUP) { + lv_obj_clean_style_list(obj, LV_OBJ_PART_MAIN); + } + return res; } @@ -2459,8 +3666,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff) { lv_obj_t * i; - LV_LL_READ(obj->child_ll, i) - { + _LV_LL_READ(obj->child_ll, i) { i->coords.x1 += x_diff; i->coords.y1 += y_diff; i->coords.x2 += x_diff; @@ -2472,21 +3678,32 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor /** * Refresh the style of all children of an object. (Called recursively) - * @param style_p refresh objects only with this style. + * @param style refresh objects only with this style_list. * @param obj pointer to an object */ -static void report_style_mod_core(void * style_p, lv_obj_t * obj) +static void report_style_mod_core(void * style, lv_obj_t * obj) { - lv_obj_t * i; - LV_LL_READ(obj->child_ll, i) - { - if(i->style_p == style_p || style_p == NULL) { - refresh_children_style(i); - lv_obj_refresh_style(i); + uint8_t part_sub; + for(part_sub = 0; part_sub != _LV_OBJ_PART_REAL_LAST; part_sub++) { + lv_style_list_t * dsc = lv_obj_get_style_list(obj, part_sub); + if(dsc == NULL) break; + + uint8_t ci; + for(ci = 0; ci < dsc->style_cnt; ci++) { + lv_style_t * class = lv_style_list_get_style(dsc, ci); + if(class == style || style == NULL) { + lv_obj_refresh_style(obj, LV_STYLE_PROP_ALL); + break; + } } + } - report_style_mod_core(style_p, i); + lv_obj_t * child = lv_obj_get_child(obj, NULL); + while(child) { + report_style_mod_core(style, child); + child = lv_obj_get_child(obj, child); } + } /** @@ -2498,102 +3715,281 @@ static void refresh_children_style(lv_obj_t * obj) { lv_obj_t * child = lv_obj_get_child(obj, NULL); while(child != NULL) { - if(child->style_p == NULL) { - refresh_children_style(child); /*Check children too*/ - lv_obj_refresh_style(child); /*Notify the child about the style change*/ - } else if(child->style_p->glass) { - /*Children with 'glass' parent might be effected if their style == NULL*/ - refresh_children_style(child); + lv_obj_invalidate(child); + child->signal_cb(child, LV_SIGNAL_STYLE_CHG, NULL); + lv_obj_invalidate(child); + + refresh_children_style(child); /*Check children too*/ + child = lv_obj_get_child(obj, child); + } +} + +static void base_dir_refr_children(lv_obj_t * obj) +{ + lv_obj_t * child; + child = lv_obj_get_child(obj, NULL); + + while(child) { + if(child->base_dir == LV_BIDI_DIR_INHERIT) { + lv_signal_send(child, LV_SIGNAL_BASE_DIR_CHG, NULL); + base_dir_refr_children(child); } + child = lv_obj_get_child(obj, child); } } +#if LV_USE_ANIMATION + +/** + * Allocate and initialize a transition for a property of an object if the properties value is different in the new state. + * It allocates `lv_style_trans_t` in `_lv_obj_style_trans_ll` and set only `start/end_values`. No animation will be created here. + * @param obj and object to add the transition + * @param prop the property to apply the transaction + * @param part the part of the object to apply the transaction + * @param prev_state the previous state of the objects + * @param new_state the new state of the object + * @return pointer to the allocated `the transaction` variable or `NULL` if no transtion created + */ +static lv_style_trans_t * trans_create(lv_obj_t * obj, lv_style_property_t prop, uint8_t part, lv_state_t prev_state, + lv_state_t new_state) +{ + lv_style_trans_t * tr; + lv_style_list_t * style_list = lv_obj_get_style_list(obj, part); + lv_style_t * style_trans = _lv_style_list_get_transition_style(style_list); + + /*Get the previous and current values*/ + if((prop & 0xF) < LV_STYLE_ID_COLOR) { /*Int*/ + style_list->skip_trans = 1; + obj->state = prev_state; + lv_style_int_t int1 = _lv_obj_get_style_int(obj, part, prop); + obj->state = new_state; + lv_style_int_t int2 = _lv_obj_get_style_int(obj, part, prop); + style_list->skip_trans = 0; + + if(int1 == int2) return NULL; + obj->state = prev_state; + int1 = _lv_obj_get_style_int(obj, part, prop); + obj->state = new_state; + _lv_style_set_int(style_trans, prop, int1); /*Be sure `trans_style` has a valid value */ + + if(prop == LV_STYLE_RADIUS) { + if(int1 == LV_RADIUS_CIRCLE || int2 == LV_RADIUS_CIRCLE) { + lv_coord_t whalf = lv_obj_get_width(obj) / 2; + lv_coord_t hhalf = lv_obj_get_width(obj) / 2; + if(int1 == LV_RADIUS_CIRCLE) int1 = LV_MATH_MIN(whalf + 1, hhalf + 1); + if(int2 == LV_RADIUS_CIRCLE) int2 = LV_MATH_MIN(whalf + 1, hhalf + 1); + } + } + + tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + LV_ASSERT_MEM(tr); + if(tr == NULL) return NULL; + tr->start_value._int = int1; + tr->end_value._int = int2; + } + else if((prop & 0xF) < LV_STYLE_ID_OPA) { /*Color*/ + style_list->skip_trans = 1; + obj->state = prev_state; + lv_color_t c1 = _lv_obj_get_style_color(obj, part, prop); + obj->state = new_state; + lv_color_t c2 = _lv_obj_get_style_color(obj, part, prop); + style_list->skip_trans = 0; + + if(c1.full == c2.full) return NULL; + obj->state = prev_state; + c1 = _lv_obj_get_style_color(obj, part, prop); + obj->state = new_state; + _lv_style_set_color(style_trans, prop, c1); /*Be sure `trans_style` has a valid value */ + + tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + LV_ASSERT_MEM(tr); + if(tr == NULL) return NULL; + tr->start_value._color = c1; + tr->end_value._color = c2; + } + else if((prop & 0xF) < LV_STYLE_ID_PTR) { /*Opa*/ + style_list->skip_trans = 1; + obj->state = prev_state; + lv_opa_t o1 = _lv_obj_get_style_opa(obj, part, prop); + obj->state = new_state; + lv_opa_t o2 = _lv_obj_get_style_opa(obj, part, prop); + style_list->skip_trans = 0; + + if(o1 == o2) return NULL; + + obj->state = prev_state; + o1 = _lv_obj_get_style_opa(obj, part, prop); + obj->state = new_state; + _lv_style_set_opa(style_trans, prop, o1); /*Be sure `trans_style` has a valid value */ + + tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + LV_ASSERT_MEM(tr); + if(tr == NULL) return NULL; + tr->start_value._opa = o1; + tr->end_value._opa = o2; + } + else { /*Ptr*/ + obj->state = prev_state; + style_list->skip_trans = 1; + const void * p1 = _lv_obj_get_style_ptr(obj, part, prop); + obj->state = new_state; + const void * p2 = _lv_obj_get_style_ptr(obj, part, prop); + style_list->skip_trans = 0; + + if(memcmp(&p1, &p2, sizeof(const void *)) == 0) return NULL; + obj->state = prev_state; + p1 = _lv_obj_get_style_ptr(obj, part, prop); + obj->state = new_state; + _lv_style_set_ptr(style_trans, prop, p1); /*Be sure `trans_style` has a valid value */ + + tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + LV_ASSERT_MEM(tr); + if(tr == NULL) return NULL; + tr->start_value._ptr = p1; + tr->end_value._ptr = p2; + } + + return tr; +} + /** - * Called by 'lv_obj_del' to delete the children objects - * @param obj pointer to an object (all of its children will be deleted) + * Remove the transition from objectt's part's property. + * - Remove the transition from `_lv_obj_style_trans_ll` and free it + * - Delete pending transitions + * @param obj pointer to an object which transition(s) should be removed + * @param part a part of object or 0xFF to remove from all parts + * @param prop a property or 0xFF to remove all porpeties + * @param tr_limit delete transitions only "older" then this. `NULL` is not used */ -static void delete_children(lv_obj_t * obj) +static void trans_del(lv_obj_t * obj, uint8_t part, lv_style_property_t prop, lv_style_trans_t * tr_limit) { - lv_obj_t * i; - lv_obj_t * i_next; - i = lv_ll_get_head(&(obj->child_ll)); - - /*Remove from the group; remove before transversing children so that - * the object still has access to all children during the - * LV_SIGNAL_DEFOCUS call*/ -#if LV_USE_GROUP - lv_group_t * group = lv_obj_get_group(obj); - if(group) lv_group_remove_obj(obj); -#endif + lv_style_trans_t * tr; + lv_style_trans_t * tr_prev; + tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + while(tr != NULL) { + if(tr == tr_limit) break; - while(i != NULL) { - /*Get the next object before delete this*/ - i_next = lv_ll_get_next(&(obj->child_ll), i); + /*'tr' might be deleted, so get the next object while 'tr' is valid*/ + tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); - /*Call the recursive del to the child too*/ - delete_children(i); + if(tr->obj == obj && (part == tr->part || part == 0xFF) && (prop == tr->prop || prop == 0xFF)) { + /* Remove the transitioned property from trans. style + * to allow changing it by normal styles*/ + lv_style_list_t * list = lv_obj_get_style_list(tr->obj, tr->part); + lv_style_t * style_trans = _lv_style_list_get_transition_style(list); + lv_style_remove_prop(style_trans, tr->prop); - /*Set i to the next node*/ - i = i_next; + lv_anim_del(tr, NULL); + _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); + lv_mem_free(tr); + } + tr = tr_prev; } +} - /*Let the suer free the resources used in `LV_EVENT_DELETE`*/ - lv_event_send(obj, LV_EVENT_DELETE, NULL); +static void trans_anim_cb(lv_style_trans_t * tr, lv_anim_value_t v) +{ + lv_style_list_t * list = lv_obj_get_style_list(tr->obj, tr->part); + lv_style_t * style = _lv_style_list_get_transition_style(list); - lv_event_mark_deleted(obj); + if((tr->prop & 0xF) < LV_STYLE_ID_COLOR) { /*Value*/ + lv_style_int_t x; + if(v == 0) x = tr->start_value._int; + else if(v == 255) x = tr->end_value._int; + else x = tr->start_value._int + ((int32_t)((int32_t)(tr->end_value._int - tr->start_value._int) * v) >> 8); + _lv_style_set_int(style, tr->prop, x); + } + else if((tr->prop & 0xF) < LV_STYLE_ID_OPA) { /*Color*/ + lv_color_t x; + if(v <= 0) x = tr->start_value._color; + else if(v >= 255) x = tr->end_value._color; + else x = lv_color_mix(tr->end_value._color, tr->start_value._color, v); + _lv_style_set_color(style, tr->prop, x); + } + else if((tr->prop & 0xF) < LV_STYLE_ID_PTR) { /*Opa*/ + lv_opa_t x; + if(v <= 0) x = tr->start_value._opa; + else if(v >= 255) x = tr->end_value._opa; + else x = tr->start_value._opa + (((tr->end_value._opa - tr->start_value._opa) * v) >> 8); + _lv_style_set_opa(style, tr->prop, x); + } + else { + const void * x; + if(v < 128) x = tr->start_value._ptr; + else x = tr->end_value._ptr; + _lv_style_set_ptr(style, tr->prop, x); + } + lv_obj_refresh_style(tr->obj, tr->prop); - /*Remove the animations from this object*/ -#if LV_USE_ANIMATION - lv_anim_del(obj, NULL); -#endif +} - /* Reset the input devices if - * the object to delete is used*/ - lv_indev_t * indev = lv_indev_get_next(NULL); - while(indev) { - if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { - lv_indev_reset(indev); - } +static void trans_anim_start_cb(lv_anim_t * a) +{ + lv_style_trans_t * tr = a->var; - if(indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; - } -#if LV_USE_GROUP - if(indev->group == group && obj == lv_indev_get_obj_act()) { - lv_indev_reset(indev); - } -#endif - indev = lv_indev_get_next(indev); + lv_style_property_t prop_tmp = tr->prop; + + /*Start the animation from the current value*/ + if((prop_tmp & 0xF) < LV_STYLE_ID_COLOR) { /*Int*/ + tr->start_value._int = _lv_obj_get_style_int(tr->obj, tr->part, prop_tmp); + } + else if((prop_tmp & 0xF) < LV_STYLE_ID_OPA) { /*Color*/ + tr->start_value._color = _lv_obj_get_style_color(tr->obj, tr->part, prop_tmp); + } + else if((prop_tmp & 0xF) < LV_STYLE_ID_PTR) { /*Opa*/ + tr->start_value._opa = _lv_obj_get_style_opa(tr->obj, tr->part, prop_tmp); + } + else { /*Ptr*/ + tr->start_value._ptr = _lv_obj_get_style_ptr(tr->obj, tr->part, prop_tmp); } - /* Clean up the object specific data*/ - obj->signal_cb(obj, LV_SIGNAL_CLEANUP, NULL); + /*Init prop to an invalid values to be sure `trans_del` won't delete this added `tr`*/ + tr->prop = 0; + /*Delete the relate transition if any*/ + trans_del(tr->obj, tr->part, prop_tmp, tr); - /*Remove the object from parent's children list*/ - lv_obj_t * par = lv_obj_get_parent(obj); - lv_ll_rem(&(par->child_ll), obj); + tr->prop = prop_tmp; - /*Delete the base objects*/ - if(obj->ext_attr != NULL) lv_mem_free(obj->ext_attr); - lv_mem_free(obj); /*Free the object itself*/ } -static void base_dir_refr_children(lv_obj_t * obj) +static void trans_anim_ready_cb(lv_anim_t * a) { - lv_obj_t * child; - child = lv_obj_get_child(obj, NULL); + lv_style_trans_t * tr = a->var; - while(child) { - if(child->base_dir == LV_BIDI_DIR_INHERIT) { - lv_signal_send(child, LV_SIGNAL_BASE_DIR_CHG, NULL); - base_dir_refr_children(child); + /* Remove the transitioned property from trans. style + * if there no more transitions for this property + * It allows changing it by normal styles*/ + + bool running = false; + lv_style_trans_t * tr_i; + _LV_LL_READ(LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) { + if(tr_i != tr && tr_i->obj == tr->obj && tr_i->part == tr->part && tr_i->prop == tr->prop) { + running = true; } + } - child = lv_obj_get_child(obj, child); + if(!running) { + lv_style_list_t * list = lv_obj_get_style_list(tr->obj, tr->part); + lv_style_t * style_trans = _lv_style_list_get_transition_style(list); + lv_style_remove_prop(style_trans, tr->prop); } + + _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); + lv_mem_free(tr); +} + +static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v) +{ + lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v); +} + +static void fade_in_anim_ready(lv_anim_t * a) +{ + lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); } +#endif static void lv_event_mark_deleted(lv_obj_t * obj) { @@ -2604,3 +4000,5 @@ static void lv_event_mark_deleted(lv_obj_t * obj) t = t->prev; } } + + diff --git a/src/src/lv_core/lv_obj.h b/src/src/lv_core/lv_obj.h index 8698718..20ad442 100644 --- a/src/src/lv_core/lv_obj.h +++ b/src/src/lv_core/lv_obj.h @@ -13,23 +13,19 @@ extern "C" { /********************* * INCLUDES *********************/ -#ifdef LV_CONF_INCLUDE_SIMPLE -#include "lv_conf.h" -#else -#include "../../../lv_conf.h" -#endif +#include "../lv_conf_internal.h" #include #include #include "lv_style.h" #include "../lv_misc/lv_types.h" #include "../lv_misc/lv_area.h" -#include "../lv_misc/lv_mem.h" -#include "../lv_misc/lv_ll.h" #include "../lv_misc/lv_color.h" -#include "../lv_misc/lv_log.h" -#include "../lv_misc/lv_bidi.h" #include "../lv_hal/lv_hal.h" +#include "../lv_draw/lv_draw_rect.h" +#include "../lv_draw/lv_draw_label.h" +#include "../lv_draw/lv_draw_line.h" +#include "../lv_draw/lv_draw_img.h" /********************* * DEFINES @@ -37,18 +33,18 @@ extern "C" { /*Error check of lv_conf.h*/ #if LV_HOR_RES_MAX == 0 || LV_VER_RES_MAX == 0 -#error "LittlevGL: LV_HOR_RES_MAX and LV_VER_RES_MAX must be greater than 0" +#error "LVGL: LV_HOR_RES_MAX and LV_VER_RES_MAX must be greater than 0" #endif #if LV_ANTIALIAS > 1 -#error "LittlevGL: LV_ANTIALIAS can be only 0 or 1" +#error "LVGL: LV_ANTIALIAS can be only 0 or 1" #endif #define LV_MAX_ANCESTOR_NUM 8 -#define LV_EXT_CLICK_AREA_OFF 0 -#define LV_EXT_CLICK_AREA_TINY 1 -#define LV_EXT_CLICK_AREA_FULL 2 +#define LV_EXT_CLICK_AREA_OFF 0 +#define LV_EXT_CLICK_AREA_TINY 1 +#define LV_EXT_CLICK_AREA_FULL 2 /********************** * TYPEDEFS @@ -65,11 +61,21 @@ enum { }; typedef uint8_t lv_design_mode_t; + +/** Design results */ +enum { + LV_DESIGN_RES_OK, /**< Draw ready */ + LV_DESIGN_RES_COVER, /**< Returned on `LV_DESIGN_COVER_CHK` if the areas is fully covered*/ + LV_DESIGN_RES_NOT_COVER, /**< Returned on `LV_DESIGN_COVER_CHK` if the areas is not covered*/ + LV_DESIGN_RES_MASKED, /**< Returned on `LV_DESIGN_COVER_CHK` if the areas is masked out (children also not cover)*/ +}; +typedef uint8_t lv_design_res_t; + /** * The design callback is used to draw the object on the screen. * It accepts the object, a mask area, and the mode in which to draw the object. */ -typedef bool (*lv_design_cb_t)(struct _lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode); +typedef lv_design_res_t (*lv_design_cb_t)(struct _lv_obj_t * obj, const lv_area_t * clip_area, lv_design_mode_t mode); enum { LV_EVENT_PRESSED, /**< The object has been pressed*/ @@ -80,14 +86,16 @@ enum { LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/ LV_EVENT_CLICKED, /**< Called on release if not dragged (regardless to long press)*/ - LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ - LV_EVENT_DRAG_BEGIN, + LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ + LV_EVENT_DRAG_BEGIN, LV_EVENT_DRAG_END, LV_EVENT_DRAG_THROW_BEGIN, + LV_EVENT_GESTURE, /**< The object has been getture*/ LV_EVENT_KEY, LV_EVENT_FOCUSED, LV_EVENT_DEFOCUSED, - LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved) */ + LV_EVENT_LEAVE, + LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved) */ LV_EVENT_INSERT, LV_EVENT_REFRESH, LV_EVENT_APPLY, /**< "Ok", "Apply" or similar specific button has clicked*/ @@ -110,22 +118,28 @@ enum { /*General signals*/ LV_SIGNAL_CLEANUP, /**< Object is being deleted */ LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ - LV_SIGNAL_CORD_CHG, /**< Object coordinates/size have changed */ + LV_SIGNAL_COORD_CHG, /**< Object coordinates/size have changed */ LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */ LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ LV_SIGNAL_BASE_DIR_CHG, /**