- Changed all text based instances of LVGL to uppercase (Only instances referring to LVGL the project, not instances referring to the ‘lvgl’ directory structure in the repository, or in URL links)
- Standardized bulleted/numbered list capitalization and punctuation
- Fixed several typos and spelling errors
- Changed minor grammatical errors and structure for clarity.
Instead of returning bool to indicate that there is more data to read
set data->continue_reading = true.
It's less error porne because if the user doesn't set the flag the indev will be read once
which is usually the inteded behaviour.
* Extra: widgets: add a new widget animation image
This widget is a combination of img and animation,
could achieve animation effects by
constantly switching a series imgs.
Signed-off-by: Qiang Zhao <qiang.zhao@nxp.com>
Signed-off-by: Hui Song <hui.song_1@nxp.com>
Signed-off-by: Xiaolin He <xiaolin.he@nxp.com>
* example: add animimg example
Signed-off-by: Qiang Zhao <qiang.zhao@nxp.com>
* feat(theme_default) improvements to dark mode
* fix(theme_default) adjust scrollbar opacity in dark mode so it's visually similar to light mode
* fix(theme_default) improve contrast in dark mode
* fix(obj) Add missing getter and setter for user_data
This is needed for Micropython bindings, which stores a reference to the Python object which wraps the LVGL object.
* Added comments to lv_obj_[get/set]_user_data
This way the MicroPython won't allow manually setting this field.
And it can't be set manually becasue the user data needs to be set too.
So lv_style_transition_dsc_init() should be used to initialize the fields of lv_style_transition_dsc_t
lv_anim_path_t was required for the MicroPython binding becase the callback couldn't attached dircetly to the styles
However, in v8, path_cb is used in the style transitons which has user_data and that user data is passed to the transition animation. Hence the path_cb sees the the same user data during the animaton as when it was registered to the transiton.
To maintain uniformity of comment formatting, but primarily to work around a deficiency in the rust library bindgen (0.58 and earlier), comments should be separated by a newline.
* fix(class): correct the typo error in comment
* fix(class): return directly if the memory allocation fail
* fix(class): remove the unused code
* fix(class): remove parent argument from lv_obj_construct
since this argumnet is really used
* fix(class): replace stddef.h with stdint.h
since uint32_t is defined in stdint.h
When a display is registered the act_screen, top_layer and sys_layer are created with the default theme.
If a new theme is set immediatelly after the driver regsitration (with lv_theme_set_act) the created screens should use the styles from the new theme.
If there are more obejct do not add the theme becasue it's possibelt that the user already added styles to the screens and applying the theme would clear these styles.
follow up the commit:
commit e9cc1c2d46
Author: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
Date: Wed Mar 10 13:07:15 2021 +0100
feat(driver): raname lv_disp_buf_t to lv_disp_draw_buf_t + save only the drv's pointer in lv_disp_t
* fix(disp): correct the typo error in comment
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
* fix(disp): fix the field definition
1.change rotated from 3bits to 2bits since lv_disp_rot_t has only four value
2.change inv_p from 10bits to uint16_t to avoid the bit operation
3.reorder bg_opa to save the memory space
* fix(disp): remove the unnecessary field zero
since lv_memset_00 is already done for the main struct
* fix(disp): handle the out of memmory gracefully
* fix(disp): delete the refresh timer in lv_disp_remove
* fix(disp): handle NULL pointer correctly in lv_disp_[g|s]et_rotation
like other similar(allow NULL disp) functions
* fix(disp): call lv_area_set_[width|height] in lv_disp_drv_update
to remove one extra row and column
follow up the commit:
commit e9cc1c2d46
Author: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
Date: Wed Mar 10 13:07:15 2021 +0100
feat(driver): raname lv_disp_buf_t to lv_disp_draw_buf_t + save only the drv's pointer in lv_disp_t
* feat(mem): add initial version of tlsf
from : https://github.com/mattconte/tlsf
commit: deff9ab509341f264addbd3c8ada533678591905
* feat(mem): switch the default allocator to tlsf
* fix(mem): remove the preserved small buffer
since the builtin allocator(tlsf) is fast enough now
* fix(mem): change LV_MEM_ADD_JUNK to 0
to speed up the normal operation
Remove dead code in lv_label and lv_spinbox, there is already lv_obj_handle_get_type_signal() call higher up.
Change lv_led to use lv_obj_handle_get_type_signal() like other widgets do.
* fix(hal indev): correct the typo and adjust the alignment
* fix(hal indev): remove the unnecessary forward declaration
* fix(hal indev): relayout the bitfiled to save space
* fix(hal indev): remove the unnecessary memory zero
* fix(hal indev): remove the initial hardcode value for scroll_throw
* fix(style): remove the wrong first break statement from lv_style_prop_get_default
and correct the comment and style
* fix(style): handle the out of memory gracefully in lv_style_[set|remove]_prop
* fix(fs): don't allocate lv_fs_file_t in lv_fs_open
avoid the unnecessary allocation
* fix(fs): apply the similar file open/close change to dir open/close
avoid the unnecessary allocation
commit 06917a6ec3
* fix(image decoder): fix memory leak when no decoder can be used
and handle the out of memory gracefully
* fix(image decoder): zero the output fields after each iteration
to clean the stale info saved by try failed decoder and remove img_data
zero from lv_img_decoder_built_in_open since it has be done in the loop
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
* fix(gc): remove the unused variables from gc
* fix(gc): correct typo(from _lv_img_defoder_ll to _lv_img_decoder_ll)
* fix(gc): change _lv_drv_ll to _lv_fsdrv_ll
since only instances fo lv_fs_drv_t can be added to this list
* fix(gc): Iterate the root variables only when they are really used
to save the memory space
* fix(image cache): move cache_temp to gc.h
and rename it to _lv_img_cache_single
* fix(mem): reutrn NULL in lv_mem_buf_get if allocation fail
* fix(mem): refine the loop in alloc_core to simplify the logic
* fix(mem): remove the lv_mem_buf declaration from lv_mem.h
since it already declared in gc.h
* fix(timer): remove LV_GC_INCLUDE inclusion since it doesn't need anymore
please see commit d6ca15a749 for more info
* fix(timer): implement lv_timer_create directly
and call it in lv_timer_create_basic
* fix(timer): exclude the return value computing from the idle time
and change handler_start and time_till_next to local variables
* fix(timer): restart the timer process loop correctly
* fix(timer): skip the count pause timer into next timeout
it's wrong to check repeat_count since the timer is always
removed from the list once the repeat_count change to zero
* fix(timer): remove zero task_deleted and task_created in lv_task_exec
since the loop in lv_task_handler already do the same thing
* fix(image cache): don't need zero dec_dsc field individually
since the next _lv_memset_00 cover this field too and
* fix(image cache): shouldn't call lv_img_decoder_close when lv_img_decoder_open fail
* fix(image cache): fix the cache match algo
1.check cache entry is LV_IMG_SRC_FILE before invoke strcmp
2.ensure lv_img_cache_invalidate_src use the same algo
* fix(style): correct the comment and alignment
* fix(style): remove the unused macro and inclusion
* fix(style): correct _lv_style_get_xxx with the right pointer type
* fix(style): handle the out of memory gracefully
* fix(style): unify the term usage(class->style)
* fix(style): remove the unnecessary mask in _lv_style_get_xxx
since get_property_index ensure the returned state is a subset of required
* fix(style): centralize the style validation in one place
* fix(style): reuse the new_prop_size in _lv_style_set_xxx
* fix(style): correct the return value of get_style_prop in big endian machine
* fix(image decoder): replace lv_style.h with lv_color.h
since image decoder doesn't depends on style subsystem
and correct the related comment and some error handling
* fix(image decoder): fix memory leak when no decoder can be used
and handle the out of memory gracefully
* fix(image decoder): zero the output fields after each iteration
to clean the stale info saved by try failed decoder and remove img_data
zero from lv_img_decoder_built_in_open since it has be done in the loop
* fix(image decoder): check .bin suffix in lv_img_decoder_built_in_info
align with what has done in lv_img_decoder_built_in_open
* fix(image decoder): embed lv_fs_file_t directly to save the memory
and handle the abnormal case gracefully(avoid crash or leak)
* fix(image decoder): simplify decode builtin alpha/index bitmap
* fix(anim): relayout lv_anim_t to save 4 bytes
and fix the minor comment issue
* fix(anim): unify the type of time and animation to int32_t or uint32_t
since lv_anim_t use these types internally
* fix(anim): Don't need initialize last_task_run
since lv_anim_start will do this if the list is empty
and remove -1 to improve the accuracy
* fix(anim): remove the return value from anim_ready_handler
since no caller really use the return value
* fix(math): _lv_map check x >= max_in first
_lv_map return max_out when min_in equals max_in,
since the animation module require this behaviour
* fix(anim): normalize the time elapse by lv_map
* fix(anim): avoid iterate the list twice in anim_task
* fix(theme): the minor typo error
* fix(style): make lv_style_reset work with zerod memory
* fix(theme): fix the memory leak when lv_theme_xxx_init is called twice
due to inited variable forget to set to 1
* fix(theme): empty theme should call lv_obj_refresh_style too
and remove lv_obj_clean_style_list since the same thing is
already done in the common code(clear_styles)
* fix(lv_conf_internal.h): remove esp specific inclusion
since the same thing is already included in lv_conf_kconfig.h
* fix(library.json): change space to tab
* fix(anim): relayout lv_anim_t to save 4 bytes
and fix the minor comment issue
* fix(anim): unify the type of time and animation to int32_t or uint32_t
since lv_anim_t use these types internally
* fix(anim): Don't need initialize last_task_run
since lv_anim_start will do this if the list is empty
and remove -1 to improve the accuracy
* fix(anim): remove the return value from anim_ready_handler
since no caller really use the return value
* fix(anim): normalize the time elapse by lv_map
* fix(anim): avoid iterate the list twice in anim_task
* Add component.mk file for esp-idf make commands
* component.mk: Check for IDF_VER
Checks for IDF_VER when adding COMPONENT_SRCDIRS and COMPONENT_ADD_INCLUDEDIRS
to avoid definig them when not using LVGL as ESP-IDF component.
* component.mk: Remove info messages
* fix(font): Remove the unnecessary and duplicated inclusion
and correct some wrong comment too
* fix(font): Handle the out of memory gracefully in decompression case
and remove the check of gdsc since it is impossible to become null
* fix(font): Use the correct type to avoid the cast and shift
* fix(font): Change the bit field width to occupy the whole byte
* fix(font): Correct _LV_STR_SYMBOL_ generation command
and add _LV_STR_SYMBOL_BULLET to the list
* fix(font): lv_font_load shouldn't call lv_fs_close if lv_fs_open fail
* fix(font): read_bits should return 0 not -1 in error case
to avoid read_bits_signed waste time to extend the sign bit
* fix(font): Correct the return type of read_bits to unsgined int
and extend the sign bit more efficient and correct
* fix(font): Sync LV_FONT_FMT_TXT_CMAP_ value to binary font spec
and then remove the hard code value from source code:
https://github.com/lvgl/lv_font_conv/blame/master/doc/font_spec.md#L96
remove zero fields statement too since font_dsc->cmaps already zero at line 334.
* fix(font): Improve the performance by reading cmap table by once
* fix(font): Improve the loading performance if the header is multipled by 8bits
* fix(font): Read loca table in batch if the size is 32bits
* fix(font): Load the underline related attributes
spec here:
https://github.com/lvgl/lv_font_conv/blame/master/doc/font_spec.md#L55-L56
* fix(task): Remove the unnecessary cast and init
and correct the comment too
* fix(task): Implement lv_task_create directly
to avoid lv_task_set_prio which is a time consuming operation.
* fix(task): Exclude the return value computing from the idle time
and change handler_start and time_till_next to local variables
* fix(task): Remove zero task_deleted and task_created in lv_task_exec
since the loop in lv_task_handler already do the same thing
* fix(color): Return the opposite value in lv_color_premult when LV_COLOR_DEPTH equals 1
and correct the comment too
* fix(color): Correct the comment and alignment issue
* fix(color): Remove LV_COLOR_[SET|GET]_G16_SWAP
to simplify LV_COLOR_16_SWAP process
* fix(color): Correct the cast usage
* fix(color): Remove LV_MATH_ABS in lv_color_rgb_to_hsv
since delta can never become a negative number
* fix(color): Align LV_COLOR_[SET|GET]_A1 with other similar macro
* fix(area): Correct r_sqrd and dist(int32_t to uint32_t)
since these two variables never become negative
* fix(area): Return early in _lv_area_is_in if pointer outside area
The origin code always does the full check if radius != 0, but it
is unnecessary when is_in equals true.
* fix(mem): Utilize ALIGN_MASK as much as possible
to avoid check LV_ARCH_64 again and again and
correct the comment about MEM_UNIT
* fix(mem): Simplify _lv_memset implementation by SET8/SET32/REPEAT8 macro
* fix(mem): Handle the out of memory gracefully in _lv_mem_buf_get
don't modify the state in the failure
* fix(mem): Remove the unnecessary memset, memcpy and assignment
* Move LV_GC_INCLUDE to the common place(gc.h)
to avoid the duplication in many source files
* fix(theme template): Always initialize _lv_theme_material_styles
just like what other theme do
* fix(fs): Check driver ready in lv_fs_dir_open and lv_fs_free_space
* fix(fs): Avoid the memory leak in lv_fs_open and lv_fs_dir_open
* fix(fs): Fix typo error in lv_fs_trunc(tell_cb should be trunc_cb)
* fix(fs): Make lv_fs_dir_close same as lv_fs_close when dir_close_cb equals NULL
* fix(fs): Handle the struct cleanup correctly
* improve(fs): Don't allocate memory when file_size or rddir_size equal zero
pass the address of file_d or dir_d to open_cb or dir_open_cb instead, so
implementor can point file_d/dir_d to other location. In many cases(POSIX),
file system will allocate the context for us, this improvement could avoid
we allocate the 4/8 bytes intermediate space.
* fix(async): Move lv_async_info_t from lv_async.h to lv_async.c
since the user don't need know the implementation detail
* fix(async): Don't set user_data again
since lv_task_create already save it for us
1.all argument of _lv_bezier3 should be uint32_t since the input and output are unsigned
2.the return type of _lv_map should be int32_t since the type of output range is int32_t
3.remove the unnecessary cast
* Trim trailing whitespace from Kconfig
* Replace all tab to space in Kconfig
* Add more dependence between opions to Kconfig
* Add LV_USE_FONT_SUBPX for LV_FONT_SUBPX_BGR in Kconfig
* Fix typo error(LV_USE_DROPBOX->LV_USE_DROPDOWN) in Kconfig
* Remove LV_THEME_MATERIAL dependence from the child of LV_THEME_DEFAULT_FLAG
since LV_THEME_DEFAULT_FLAG already depends on LV_THEME_MATERIAL
* Rename LV_MEM_SIZE_BYTES to LV_MEM_SIZE_KILOBYTES
since this opion use KiB as the unit
* Release v7.7.0
* Fix(indev): Don't leave edit mode if there is only
one object in the group
* Remove unnecessary judgment conditions
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
* Removed src/lv_conf_zephyr.h
Removed src/lv_conf_zephyr.h as it is maintained in the Zephyr build it self.
* CMakeLists.txt: Added support for Zephyr RTOS
Added support to build LVGL as library for Zephyr RTOS
* Added support to use LVGL repo as Zephyr module
Added support to use the LVGL repository as a Zephyr module repository
* quote string defaults for Kconfig values to eliminate warnings
* don't add \ in default for LV_TICK_CUSTOM_SYS_TIME_EXPR
(tho its needed on linux and MacOS) as I can't test on Windows
* Fix division by zero issue when all points are equal
As the title says, when all the points are equal, it attempts division by zero, and in some cases it can result in funny behavior.
Slightly kludgy fix, but not a significant performance impact.
* Actually fix the division by zero issue both ways
Previous commit was slightly broken and only worked one way
* Fix range setting instead of drawing
* Missing y_tmp
* Removed LV_CONF_SKIP definition from CMake to avoid redefinition warnings; added more Kconfig options
* Bumped up version and removed unnecessary default values
* Added user data configuration to KConfig
* Moved user data options to "Feature Usage" menu
* Add option to align title text in window
I found that i really needed a basic way to align the title text in a window, and therefore i did a bit of tinkering and came up with this solution. Mind you that I'm very new to this so it might not be the most optimal way. I have tested a bit and it pretty looked promising,
I have of course written the alignments as I felt was most suitable, but I shouldn't be the judge of that.
Current alignment:
LV_TXT_FLAG_CENTER makes the text align in the center of the header but ensures it can’t overextend into to header button area;
LV_TXT_FLAG_RIGHT makes the text align at the right side, but takes the right side header buttons into account
LV_TXT_FLAG_FIT & LV_TXT_FLAG_EXPAND I wasn’t too sure about what to do so as of now it just aligns them as normal
LV_TXT_FLAG_NONE Is equal to no flag set by the user and therefore I have just set it to the default coords, like normal. The text then align at the left side.
* Update lv_win.h
* Added functions
Added function to set and get alignment of the header title as requested
* Added functions
Added setter and getter functions for the header title alignment as requested
* Kconfig: Add missing _HEX to LV_COLOR_TRANSP option.
* lv_conf_checker: Define LV_CONF_SKIP if CONFIG_LV_CONF_SKIP is defined.
* fix(indev): disabled object shouldn't absorb clicks but let the parent to be clicked
* Update README.md
* fix(arabic): support processing again alraedy processed texts with _lv_txt_ap_proc
* fix(textarea): support Arabic letter connections
fixes#1888
* Fix#1924: incorrect date on changelog
December 1st is two weeks from 7.7.2 release.
* Kconfig: Fix LV_CONF_MINIMAL related options.
* fix(arabic): support Arabic letter connections
fixes#1920
* fix(arabic): support Arabic letter connections in value string property
* Update CHANGELOG.md
* Update CHANGELOG.md
* Kconfig: Add Zephyr specific code.
* fix: fix double include in lv_obj.c
fix#1926
* Removed trailing semi-colon from macros (#1928)
* Removed commented out test definition
Removed commented out test definition LV_BUILD_TEST
* Remove blank line
* Fix comment spelling
* Added blank line
* Removed trailing semi-colon in macros
* fix(indev): in LV_INDEV_TYPE_BUTTON recognize 1 cycle long presses too
Fixes https://forum.lvgl.io/t/bug-in-indev-button-proc-misses-buttons-that-are-pressed-for-a-single-callback/3699
* fix(arc): make arc work with encoder
fixes https://forum.lvgl.io/t/lv-arc-with-encoder-lv-group/3769
* fix(slider): adjusting the left knob too with encoder
https://forum.lvgl.io/t/slider-with-2-knobs-and-encoder-functionality/3770
* fix(arc_draw): remove statments that do nothing
fix#1930
* Change LV_DRAW_BUF_MAX_NUM to LV_MEM_BUF_MAX_NUM (#1931)
* Update CHANGELOG.md
* fix(draw polygon): join adjacent points if they are on the same coordinate
* fix(draw polygon): fix memory leak and vertex joining
* fix(style): invalidate cache on every PART
Inherited properties on parts other than MAIN needs to be recached on property change beacuse they
are inherted from MAIN
fixes#1933
* fix(anim): fix bounce path
* fix(slider): do not let edit left knob in non-range mode
* Update ROADMAP.md
* Fix hardfault when DCache is disabled with no callback (#1935)
* fix(linemeter): fix invalidation when setting new value
The old complex but more optimal invalidation was buggy in some cases
fixes#1904
* fix(linemeter): fix invalidation when setting new value
The old complex but more optimal invalidation was buggy in some cases
fixes#1904
* fix(table): add missing invalidation when changeing cell type
fixes https://forum.lvgl.io/t/bug-of-table-click-to-change-style/3842
* CMakeLists.txt: Let the user configure whether LV_ATTRIBUTE_FAST_MEM is IRAM_ATTR (#1939)
* fix(slider): fix left/right knob control with encoder
* fix(img): increase the size of invalidated area in lv_img_set_zoom
Becasue of the pivot placement there can be some rounding errors
* feat(perf_monitor): add lv_refr_get_fps_avg()
* Add 8px and 10px montserrat fonts to build (#1941)
* Fix#1942: lv_textarea_set_pwd_mode not changing to bullets
Thanks to @fvanroie for investigating.
* fix(material): make button pressed color darker (#1940)
* simplify touch handling in the Arduino example
* Update ROADMAP.md
* Update ROADMAP.md
* feat(lv_conf_kconfig): add LV_CONF_KCONFIG_EXTERNAL_INCLUDE
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>
Co-authored-by: xennex22 <25083624+xennex22@users.noreply.github.com>
Co-authored-by: incity <610455681@qq.com>
Co-authored-by: Andrey <spirit@spirit.re>
Co-authored-by: defogprog <22955033+defogprog@users.noreply.github.com>
* Removed commented out test definition
Removed commented out test definition LV_BUILD_TEST
* Remove blank line
* Fix comment spelling
* Added blank line
* Removed trailing semi-colon in macros
It was difficult to handle the pressed angle on the arc when it crossed the 360 degree boundery.
The solution is to handle the angle relative to the bg_start_angle. This way no angle can be larger than 360.
The other issue was the case when a smaller than min. or larger than max. angle was pressed.
It is handled by introducing 'min_close' flag which stores which end is closer on the last valid press
and prefer this end in uncleary situation.
Fixes a compiler warning in lv_font_fmt_txt.c when compressed fonts are
disabled (LV_USE_FONT_COMPRESSED=0):
/home/maureen/zephyrproject/modules/lib/gui/lvgl/src/lv_font/lv_font_fmt_txt.c:349:13: warning: 'decompress' defined but not used [-Wunused-function]
349 | static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp, bool prefilter)
| ^~~~~~~~~~
This was found after upgrading Zephyr to use LVGL v7.6.1, building with
the Zephyr SDK 0.11.3 toolchain.
Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
* create the fmt version of setting text for msgbox.
* define _lv_txt_set_text_vfmt and change the body of lv_msgbox_set_text_fmt.
* make lv_label_refr_text out of static.
* fix a bug in _lv_txt_set_text_vfmt
* lv_conf_checker: Update lv_conf_checker so it is ESP-IDF aware.
Include ESP-IDF headers and lv_conf_kconfig.h when using the ESP-IDF framework.
Also remove the CONFIG_LV_CONF_SKIP as it is not generated by the Kconfig file.
* lv_conf_checker: Always include lv_conf_kconfig.h.
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
* update lv_obj_refresh_style describtion.
* cursor added.
* refresh chart after setting the cursor
* add new direction and a bug fixed.
* fixed the wrong changes for header file.
* rename lv_cursor_direction_t enum members.
* add lv_chart_get_x_from_index and lv_chart_get_y_from_index
* lv_chart_get_x_from_index supports column chart type too.
* fix the error of no lv_coord_t value return.
* fix a bug based on the coord is with respect to the series area.
* make get_series_area function global.
* fix the name of get_series_area function.
* add the description of the added functions.
* chart cursor minor fixes
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
* PXP: Updated area threshold, fixed symbol names, minor fixes
- Area threshold of 1 left from debugging, changed to 32 for performance
reasons.
- Fixed naming convention of symbols (prefix LV_GPU_)
- Fixed include paths (no need to add src folder into include paths)
- Comments changed to doxygen
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Code formatting
Applied code-format.sh script.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* Corrected bug in styles of labels with selections
Text selection color (text_selection_color) property was incorrectly
being applied to the text color if there was a selection. The sel_color
property in the label descriptor was initialized to blue. This property
was intended to be the label background color under a selection.
* Add new property for the color of selected text
New property for labels: text_sel_font_color
This property will change the color of the font within selected text.
* Rename text selection color properties
Per feedback from issue #1820, sel_color is now sel_bg_color and
sel_font_color is now sel_color. This results in clearer naming.
Co-authored-by: Ryan Powers <ryan.powers@envision-tek.com>
* Allow inclusion of local lv_conf_internal.h
A wrapper library cna contain an lv_conf.h file and it would be automatically picked up by the buildsystem
* Guard __has_include and simplify code
* Make number sign indentation consistent
Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>
VG-Lite accelerated features:
- fill (+ transparency)
- BLIT (+ transparency)
Limitation:
Image width must be aligned to 16 for VG-Lite to process the buffer.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* update lv_obj_refresh_style describtion.
* fmt version of lv_table_set_cell_value added.
* fix a bug.
* add include lv_printf.h
* fix a bug for LV_USE_BIDI in lv_table_set_cell_value_fmt
* fix a missed part for arabic_persian chars in lv_table_set_cell_value
* PXP: Added basic PXP acceleration
PXP accelerated features:
- fill (+ opacity)
- BLIT (+ opacity)
- recoloring (+ opacity)
- color keying (+ opacity)
Recoloring + color keying simultaneously not supported.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Added abstraction for interrupt handling
Previous imlpementation used IRQ polling on PXP, which doesn't allow
real CPU offload. Therefore added set of callbacks for interrupt
handling that should be implemented by user, with possible RTOS
integration.
Default/example implementation of callbacks for bare metal and FreeRTOS
provided (lv_gpu_nxp_pxp_osa.c), enabled by
LV_USE_GPU_NXP_PXP_DEFAULT_OSA switch, accesible via pxp_default_cfg
structure.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Optimized cache flushing
Previous implementation flushed areas of (LCD width * object height)
size. Cache flush is expensive operation and flushing line by line,
smallest possible area, boost performance by shortening time spent on
cache flushes.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Added documentation for NXP PXP accelerator
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: added missing extern c in header files
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Fixed ifdefs - Removed LV_USE_GPU, fixed internal config
LV_USE_GPU is not intended as a global GPU enable switch. It's used only
for gpu_blend_cb and gpu_fill_cb callbacks, which are obsolete. This
patch removes LV_USE_GPU dependency for PXP code, so it's enabled only
with LV_USE_GPU_NXP_PXP symbol.
Added missing symbols to internal conf, so automatic testd can pass
build step.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Default OSA changed to PXP auto-initialization
Auto init feature added so if user run FreeRTOS or bare-metal, no PXP
Init code is required. Renamed symbol to be more clear.
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Documentation moved to docs repo
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
* PXP: Fixed alpha configuration
- Coverity issue: AS blend config used uninitialized structure. No
impact on functionality, as blend module is not used (porter-duff blends
in this case)
- Alpha config fixed - swapped alpha values produced different result
from SW render
Signed-off-by: Jozef Bastek <jozef.bastek@nxp.com>
Fetch both head and merge commits of "pull" refs. This would allow the CI script to first try checkout the merge commit (which is `github.sha` on PR) and only if that fails, default to checking out the PR head.
* Fixed infinite loop during calculation size of lv_list
* Fixed msvc 2019 compiler error C4576 when using the LVGL inside C++ code
* Refactoring to make autocomplete less noisy
* Improve compatibility with ARM Compiler V6 with C++98 mode
* Replaced non-ascii symbol
* Fixed CI build error
* Refactoring, added ability to override _LV_COLOR_HAS_MODERN_CPP
Lines in canvas buffers are byte aligned so buffers might request larger size and contain unused bits.
The previous documented calc method would often result in a buffer size smaller than what was expected by LVGL, leading to memory corruption and program crash.
Remove use of c++ keyword 'new' from function parameter in
lv_theme_set_base() function.
Add function lv_checkbox_set_state(lv_obj_t * cb, lv_btn_state_t state).
Add function lv_checkbox_get_state(const lv_obj_t * cb)
Update Change log.
Many current OSes ship newer versions (e.g. 3.8) and they work OK
for this, so I don't think 3.6 is required specifically.
Versions older than 3.6 wouldn't work, though, since f-strings
are used.
Found that new structure parmaeter ext_buf_assigned needs to be
initialised to false in lv_chart_add_series() as sometimes is set true
depending on what was previously in the heap where it was allocated.
- change the wording to say "message box" and not "button matrix"
- parameter name should be cb and not xcb due MicroPython
- also corrected comment for lv_async_call in lv_async.h
/**
* Set the index of the x-axis start point in the data array
* @param chart pointer to a chart object
* @param ser pointer to a data series on 'chart'
* @param id the index of the x point in the data array
*/
void lv_chart_set_x_start_point(lv_obj_t * chart, lv_chart_series_t *
ser, uint16_t id);
/**
* Set an external array of data points to use for the chart
* NOTE: It is the users responsibility to make sure the point_cnt
matches the external array size.
* @param chart pointer to a chart object
* @param ser pointer to a data series on 'chart'
* @param array external array of points for chart
*/
void lv_chart_set_ext_array(lv_obj_t * chart, lv_chart_series_t * ser,
lv_coord_t array[], uint16_t point_cnt );
/**
* Set an individual point value in the chart series directly based on
index
* @param chart pointer to a chart object
* @param ser pointer to a data series on 'chart'
* @param value value to assign to array point
* @param id the index of the x point in the array
*/
void lv_chart_set_point_id(lv_obj_t * chart, lv_chart_series_t * ser,
lv_coord_t value, uint16_t id);
/**
* get the current index of the x-axis start point in the data array
* @param chart pointer to a chart object
* @param ser pointer to a data series on 'chart'
* @return the index of the current x start point in the data array
*/
uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t
* ser);
/**
* Get an individual point value in the chart series directly based on
index
* @param chart pointer to a chart object
* @param ser pointer to a data series on 'chart'
* @param id the index of the x point in the array
* @return value of array point at index id
*/
lv_coord_t lv_chart_get_point_id(lv_obj_t * chart, lv_chart_series_t *
ser, uint16_t id);
unary negation operator was being applied to an usigned int in three
places. I'm not sure what the other compilers are doing to accept
the current code , but I have cast the unsigned ints to a signed one
before applying the unary operator.
unary negation operator was being applied to an usigned int in three
places. I'm not sure what the other compilers are doing to accept
the current code , but I have cast the unsigned ints to a signed one
before applying the unary operator.
This routine tried to optimize a special case of setting the label text to the same address as previously set, but it did not consider whether the prior set was static and tried to realloc non-allocated memory.
Otherwise an error is generated with some compilers. Passing a const parameter is the right way to do it, but all the obj and widget functions would need to be updated.
Rollover functionakity changed.
Increase: if new value is over max, set to max first, then reset to minimum
Decrease: if new value is below min, set to min first, then reset to maximum
Will crash on calling while no indev returned conditions, such as delayed for an deletion of objects automatically when idle(no interactive inputs).
Perhaps we will think of that it is "your" responsibility to check before calling. well, I think it may not be easy for the one who does not familar with the library, and I stucked here and debug for hours.
The rollover functionalty allows the spinbox to turn aound the range of values. Increasing over maximum values restarts from minimum value. Decreasing below minimum value restarts fro maximum value.
Make sure that the variable px_opa in lv_draw_letter is initialized,
else a compile time warring will occur .
Signed-off-by: Jan Van Winkel <jan.van_winkel@dxplore.eu>
lv_refr_area: Updated height for area refresh to correctly include areas that are a height of only 1 pixel.
lv_img_design: Updated draw loop to account for objects that are 1 pixel in height or width.
lv_draw_arc.c -> line 218
Removed unsed fast_atan2() function which appears to have been moved to
lv_math.c as lv_atan2() function.
lv_font_heb_16.c -> line 1
Fixed inconsistent include path.
lv_label.c -> line 734
Added (char*) cast to const char* variable 'txt' to silence compiler
warning when LV_USE_BIDI is disabled.
lv_style.c -> line 93
Removed this line
lv_style.c -> line 97
Reverted this line to remove override of LV_FONT_DEFAULT defined in
lv_conf.h
Flushing flag is used to wait for the finish of the transfer. If this
is reset to 0, the other parts of the code will start accessing the buf_act
(see src/lv_core/lv_refr.c:106) and thus may create a race condition. Exchanging
the resetting to 0 and memset will fix this issue.
Pass pointer to disp->driver to rounder_cb in lv_inv_area instead of
pointer to disp_refr->driver as lv_inv_area is called when no refresh is
ongoing (lv_disp_drv_register).
Signed-off-by: Jan Van Winkel <jan.van_winkel@dxplore.eu>
Enable/disable font declarations according to font macros. This is required for Micropython otherwise we would get a declaration with a missing definition.
Updated sed line which generates _LV_STR enum for Micropython binding
The wrong animation function was used for the delete, and so the animation was never deleted.
Must force animation callback on delete, so that the correct selection highlighting is shown.
Functions that are declared but not defined will cause the micropython build to fail, since it would assume, from file header, that these functions are available and will try to call them (linker error)
when we want to add set data by `lv_chart_set_next` to a chart in `LV_CHART_MODE_CIRCULAR` mode we don't need to invalidate the whole chart object so these functions are added to just invalidate the added data area.
fixes bug introduced in 4f50a5a: when the LV_SIGNAL_PRESSED is generated by keypad input device (through LV_GROUP_KEY_ENTER key), it does not carry information about position (the position information is overlayed with key information in lv_indev_proc_t struct in this case), so we cannot touch it
When building LittlevGL with a rather recent compiler (tested with GCC
7.3.1 provided by Arm), `-Wall`, `-Wextra` and `-Werror` activated and
`LV_LOG_LEVEL` set to `LV_LOG_LEVEL_TRACE`, compilation fails due to a
type limits error in lv_log.c
if(level >= LV_LOG_LEVEL) {
^~
because the comparison is always true, since level is a `lv_log_level_t`
(that is a typedef for `uint8_t`) and `LV_LOG_LEVEL_TRACE` equals 0.
Fix that by making `lv_log_level_t` a typedef to `int8_t`.
Fixes#690
This makes the cost of adding a data point independent of array size.
Changing the array size is more complicated, but that will most likely
happen a lot less than adding a data point.
To ensure that all licensing criteria is met all repositories of the LVGL project apply a process called DCO (Developer's Certificate of Origin).
The text of DCO can be read here: https://developercertificate.org/
For a more detailed description see the [Documentation](https://docs.lvgl.io/latest/en/html/contributing/index.html#developer-certification-of-origin-dco) site.
By contributing to any repositories of the LVGL project you state that your contribution corresponds with the DCO.
No further action is required if your contribution fulfills the DCO. If you are not sure about it feel free to ask us in a comment.
stale-issue-message:'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message:'This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
close-issue-message:'This issue was closed because it has been stalled for 7 days with no activity.'
- name:Automatically close issues that don't follow the issue template
uses:lucasbento/auto-close-issues@v1.0.2
with:
github-token:${{ secrets.GITHUB_TOKEN }}
issue-close-message:"@${issue.user.login}: hello! :wave:\n\nThis issue is being automatically closed because it does not follow the issue template."# optional property
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:
**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.**
https://littlevgl.com
<h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
## Key features
* **Powerful building blocks** buttons, charts, lists, sliders, images, etc.
* **Advanced graphics** with animations, anti-aliasing, opacity, smooth scrolling
1. Call `lv_tick_inc(x)` every `x` milliseconds in a Timer or Task (`x` should be between 1 and 10)
2. Register a function which can **copy a pixel array** to an area of the screen.
3. Register a function which can **read an input device**. (E.g. touch pad)
4. Copy `lv_conf_templ.h` as `lv_conf.h` and set at least `LV_HOR_RES`, `LV_VER_RES` and `LV_COLOR_DEPTH`.
5. Call `lv_task_handler()` periodically every few milliseconds.
For a detailed description visit https://littlevgl.com/porting
Or check the [Porting tutorial](https://github.com/littlevgl/lv_examples/blob/master/lv_tutorial/0_porting/lv_tutorial_porting.c)
## Project set-up
1.**Clone** or [Download](https://littlevgl.com/download) the lvgl repository: `git clone https://github.com/littlevgl/lvgl.git`
2.**Create project** with your preferred IDE and add the *lvgl* folder
3. Copy **lvgl/lv_conf_templ.h** as **lv_conf.h** next to the *lvgl* folder
4. In the lv_conf.h delete the first `#if 0` and its `#endif`. Leave the default configuration for the first try.
5. In your *main.c*: #include "lvgl/lvgl.h"
6. In your *main function*:
* lvgl_init();
* tick, display and input device initialization (see above)
7. To **test** create a label: `lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);`
8. In the main *while(1)* call `lv_task_handler();` and make a few milliseconds delay (e.g. `my_delay_ms(5);`)
9. Compile the code and load it to your embedded hardware
<p align="center">
LVGL provides everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint.
</p>
## PC Simulator
You can test the graphics library in a PC simulator, if you don't have an embedded hardware. The simulator uses [SDL2](https://www.libsdl.org/) library to emulate a display on your monitor and a touch pad with your mouse.
This list shows the recommended way of learning the library:
1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes)
2. Read the [Introduction](https://docs.lvgl.io/latest/en/html/intro/index.html) page of the documentation (5 minutes)
3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/latest/en/html/get-started/quick-overview.html) page (15 minutes)
4. Set up a [Simulator](https://docs.lvgl.io/latest/en/html/get-started/pc-simulator.html) (10 minutes)
5. Try out some [Examples](https://github.com/lvgl/lv_examples/)
6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/latest/en/html/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_&type=&language=)
7. Read the [Overview](https://docs.lvgl.io/latest/en/html/overview/index.html) page to get a better understanding of the library (2-3 hours)
8. Check the documentation of the [Widgets](https://docs.lvgl.io/latest/en/html/widgets/index.html) to see their features and usage
9. If you have questions go to the [Forum](http://forum.lvgl.io/)
10. Read the [Contributing](https://docs.lvgl.io/latest/en/html/contributing/index.html) guide to see how you can help to improve LVGL (15 minutes)
## Examples
For more examples see the [lv_examples](https://github.com/lvgl/lv_examples) repository.
### Button with label
```c
lv_obj_t*btn=lv_btn_create(lv_scr_act(),NULL);/*Add a button to the current screen*/
lv_obj_set_pos(btn,10,10);/*Set its position*/
lv_obj_set_size(btn,100,50);/*Set its size*/
lv_obj_set_event_cb(btn,btn_event_cb);/*Assign a callback to the button*/
lv_obj_t*label=lv_label_create(btn,NULL);/*Add a label to the button*/
lv_label_set_text(label,"Button");/*Set the labels text*/
...
voidbtn_event_cb(lv_obj_t*btn,lv_event_tevent)
{
if(event==LV_EVENT_CLICKED){
printf("Clicked\n");
}
}
```

### LVGL from Micropython
Learn more about [Micropython](https://docs.lvgl.io/latest/en/html/get-started/micropython.html).
```python
# Create a Button and a Label
scr=lv.obj()
btn=lv.btn(scr)
btn.align(lv.scr_act(),lv.ALIGN.CENTER,0,0)
label=lv.label(btn)
label.set_text("Button")
# Load the screen
lv.scr_load(scr)
```
## Contributing
See [CONTRIBUTING.md](https://github.com/littlevgl/lvgl/blob/master/docs/CONTRIBUTING.md)
LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosing your own project under in LVGL.
## Donate
If you are pleased with this graphics library, found it useful, or are happy with the support you got, please help its further development:
For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/latest/en/html/contributing/index.html) section of the documentation.
v8.0 brings many new features like simplified and more powerful scrolling, new layouts inspired by CSS Flexbox and Grid, simplified and improved widgets, more powerful events, hookable drawing, and more.
v8 is a major change and therefore it's not backward compatible with v7.
### Directory structure
- The `lv_` prefix is removed from the folder names
- The `docs` is moved to the `lvgl` repository
- The `examples` are moved to the `lvgl` repository
- Create an `src/extra` folder for complex widgets:
- It makes the core LVGL leaner
- In `extra` we can have a lot and specific widgets
- Good place for contributions
### Widget changes
-`lv_cont` removed, layout features are moved to `lv_obj`
-`lv_page` removed, scroll features are moved to `lv_obj`
-`lv_objmask` the same can be achieved by events
-`lv_meter` added as the unioin of `lv_linemeter` and `lv_gauge`
-`lv_span` new widget mimicing HTML `<span>`
-`lv_animing` new widget for simple slideshow animations
- \+ many minor changes and improvements
### New scrolling
- Support "elastic" scrolling when scrolled in
- Support scroll chaining among any objects types (not only `lv_pages`s)
- Remove `lv_drag`. Similar effect can be achieved by setting the position in `LV_EVENT_PRESSING`
- Add snapping
- Add snap stop to scroll max 1 snap point
### New layouts
- [CSS Grid](https://css-tricks.com/snippets/css/a-guide-to-grid/)-like layout support
- [CSS Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)-like layout support
### Styles
- Optimize and simplify styles
- State is saved in the object instead of the style property
- Object size and position can be set in styles too
### Events
- Allow adding multiple events to an object
- A `user_data` can be attached to the added events
### Driver changes
-`lv_disp_drv_t`, `lv_indev_drv_t`, `lv_fs_drv_t` needs to be `static`
-`...disp_buf...` is renamed to `draw_buf`. See an initialization example [here](https://github.com/lvgl/lv_sim_eclipse_sdl/blob/e164e3591c3e1e3bf3464d19e0dcdc67b2e6a791/main.c#L87-L97).
- No partial update if two screen sized buffers are set
-`disp_drv->full_refresh = 1` makes always the whole display redraw.
-`hor_res` and `ver_res` need to be set in `disp_drv`
-`indev_read_cb` returns `void`. To indicate that there is more that to read set `data->continue_reading = 1` in the `read_cb`
### Other changes
- Remove the copy parameter from create functions
- Simplified File system interface API
- Use a more generic inheritance
- The built-in themes are reworked
-`lv_obj_align` now saved the alignment and realigns the object automatically but can't be used to align to other than the parent
-`lv_obj_align_to` can align to an object but doesn't save the alignment
-`lv_pct(x)` can be used to set the size and position in percentage
- There are many other changes in widgets that are not detailed here. Please refer to the documentation of the widgets.
### New release policy
- We will follow [Release branches with GitLab flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html#release-branches-with-gitlab-flow)
- Minor releases are expected in every 3-4 month
-`master` will always contain the latest changes
### Migrating from v7 to v8
- First and foremost, create a new `lv_conf.h` based on `lv_conf_template.h`.
- To try the new version it's recommended to use a simulator project and see the examples.
- When migrating your project to v8
- Update the drivers are described above
- Update the styles
- Update the events
- Use the new layouts instead of `lv_cont` features
- Use `lv_obj` instead of `lv_page`
- The other parts are mainly minor renames and refactoring. See the functions' documentation for descriptions.
## v7.11.0 (16.03.2021)
### New features
- Add better screen orientation management with software rotation support
- Decide text animation's direction based on base_dir (when using LV_USE_BIDI)
### Bugfixes
- fix(gauge) fix needle invalidation
- fix(bar) correct symmetric handling for vertical sliders
## v7.10.1 (16.02.2021)
### Bugfixes
- fix(draw) overlap outline with background to prevent aliasing artifacts
- fix(indev) clear the indev's `act_obj` in `lv_indev_reset`
- fix(text) fix out of bounds read in `_lv_txt_get_width`
- fix(list) scroll list when button is focused using LV_KEY_NEXT/PREV
- fix(text) improve Arabic contextual analysis by adding hyphen processing and proper handling of lam-alef sequence
- fix(delete) delete animation after the children are deleted
- fix(gauge) consider paddings for needle images
## v7.10.0 (02.02.2021)
### New features
- feat(indev) allow input events to be passed to disabled objects
- feat(spinbox) add inline get_step function for MicroPython support
### Bugfixes
- fix(btnmatrix) fix lv_btnmatrix_get_active_btn_text() when used in a group
## v7.9.1 (19.01.2021)
### Bugfixes
- fix(cpicker) fix division by zero
- fix(dropdown) fix selecting options after the last one
- fix(msgbox) use the animation time provided
- fix(gpu_nxp_pxp) fix incorrect define name
- fix(indev) don't leave edit mode if there is only one object in the group
- *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.
-`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_template.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.
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [atom@github.com](mailto:atom@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team using the [contact form](https://lvgl.io/about). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
Use [misc/lv_templ.c](https://github.com/lvgl/lvgl/blob/master/src/misc/lv_templ.c) and [misc/lv_templ.h](https://github.com/lvgl/lvgl/blob/master/src/misc/lv_templ.h)
## Naming conventions
* Words are separated by '_'
* In variable and function names use only lower case letters (e.g. *height_tmp*)
* In enums and defines use only upper case letters (e.g. *e.g. MAX_LINE_NUM*)
* Global names (API):
* start with *lv*
* followed by module name: *btn*, *label*, *style* etc.
* followed by the action (for functions): *set*, *get*, *refr* etc.
* closed with the subject: *name*, *size*, *state* etc.
* Typedefs
* 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:
* 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 200 lines (except very straightforwards)
* Variables:
* One line, one declaration (BAD: char x, y;)
* Use `<stdint.h>` (*uint8_t*, *int32_t* etc)
* 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)
## Comments
Before every function have a comment like this:
```c
/**
* Return with the screen of an object
* @param obj pointer to an object
* @return pointer to a screen
*/
lv_obj_t*lv_obj_get_scr(lv_obj_t*obj);
```
Always use `/*Something*/` format and NOT `//Something`
Write readable code to avoid descriptive comments like:
`x++; /*Add 1 to x*/`.
The code should show clearly what you are doing.
You should write **why** have you done this:
`x++; /*Because of closing '\0' of the string*/`
Short "code summaries" of a few lines are accepted. E.g. `/*Calculate the new coordinates*/`
In comments use \` \` when referring to a variable. E.g. ``/*Update the value of `x_act`*/``
### Formatting
Here is example to show bracket placing and using of white spaces:
```c
/**
* Set a new text for a label. Memory will be allocated to store the text by the label.
* @param label pointer to a label object
* @param text '\0' terminated character string. NULL to refresh with the current text.
It's glad to see that you are interested in Contributing to LittlevGL!
In this guide you can learn how can you help to develop LittlevGL.
### Table Of Content
* [Who can contribute?](#who-can-contribute)
* [How to report an issue?](#how-to-report-a-bug)
* [How to suggest a feature?](#how-to-suggest-a-feature)
* [How to implement a feature?](#how-to-implement-a-feature)
* [Styling guide](#styling-guide)
## Who can contribute?
As graphical interfaces for embedded systems has an increasing relevance today you also might find important to work with a good graphics library. Now - independently from skills, programming level or any personal attributes - you can influence and help the development of Littlev Graphics Library with:
* Report an issue
* Suggest feature
* Fix an issue
* Implement a feature
* Help with testing bugfixes and new features
Please, take a look at [CODE_OF_CONDUCT](https://github.com/littlevgl/lvgl/blob/master/docs/CODE_OF_CONDUCT.md)
There are few **general rules**
* We use [GitHub's issue tracker](https://github.com/littlevgl/lvgl/issues)
* Be kind and respectful. Starting with "Hi" is always a good idea :)
* If somebody helped you give a feedback.
* One issue should be about one topic. If you have other questions please open a new issue.
* Always create an issue before creating a [Pull request](https://help.github.com/articles/about-pull-requests/) to discuss the idea first
* Create small, "digestible" Pull requests.
* Tell your remarks in a structured way. Use paragraphs and the [Markdown](https://guides.github.com/features/mastering-markdown/) support of GitHub.
* Be sure you are using the latest version (from `master` branch)
* Keep in mind LittlevGL should be and should remain:
- usable on small MCUs as well (think about memory footprint)
- compilable with "non-standard" tools like Arduino (no gcc specific options)
- C compatible (no C++ specific code and features)
- all configuration should be in `lv_conf.h`. (Instead of modifying the library)
- the API clean and easiy to understand
## How to report a bug?
If you found a **simple and straightforward bug** like:
* misspelling (in comments function/variable names or grammatical issues in comments)
* not handled error cases (negative array index, overflow etc)
* anything else which can be fixed locally with a few lines of code
* or defective documentation
then tell:
* where you found the bug (which file/function/variable)
* how can it cause problem
* what is your suggested solution if you have
If you faced with **something more complex** like:
* might be simple but you don't know its origin
* affects a whole file, module or even the architecture
* needs deeper discussion
then please
* tell what do you experience
* tell what do you expect to happen
* tell how to reproduce the issue
* provide a simplified code example (better if can be tested with copy-paste)
* attache your lv_conf.h (if you feel it's important)
* logs and long codes should be attached in a file (instead of copying into a comment)
## How to suggest a feature?
If you have a good and useful idea open issue to tell it! Please note the followings on suggesting new features:
* What the new feature is about?
* Why/Where/In which case is it useful/helpful/relevant?
* Can you mention real life usecases/examples for the use this feature?
* Can you help in implementing it?
Your suggestion can have 4 possible outcomes:
1. This feature is already exists. In this case you will learn how to achieve your goal.
2. You can simply realize it with the current functionality.
3. Although it's a new feature but it would break LittlevGL's platform independent and/or resource minimalist nature.
4. It's really a new feature which would be good to be in LittlevGL. Hurray! In a discussion we figure out the technical details and implementation options. With the knowledge of how to do it somebody can implement the new feature.
Keep in mind if you wouldn't like to do the implementation there is no guarantee that it will be ready in the near future.
However, if you would like to force it, take a look at this page: [Feature request service](http://www.gl.littlev.hu/services#feature)
## How to implement a feature?
In [docs/TODO_MINOR.md](https://github.com/littlevgl/lvgl/blob/master/docs/TODO_MINOR.md) and [docs/TODO_PATCH.md](https://github.com/littlevgl/lvgl/blob/master/docs/TODO_PATCH.md) you can see some ideas which are waiting for somebody to realize them! If want to deal with a feature from these files, please start an issue and discuss the details.
The new feature should be in a new branch.
## Styling guide
### File format
Use [lv_misc/lv_templ.c](https://github.com/littlevgl/lvgl/blob/master/lv_misc/lv_templ.c) and [lv_misc/lv_templ.h](https://github.com/littlevgl/lvgl/blob/master/lv_misc/lv_templ.h)
### Naming conventions
* Words are separated by '_'
* In variable and function names use only lower case letters (e.g. *height_tmp*)
* In enums and defines use only upper case letters (e.g. *e.g. MAX_LINE_NUM*)
* Global names (API):
* starts with *lv*
* followed by module name: *btn*, *label*, *style* etc.
* followed by the action (for functions): *set*, *get*, *refr* etc.
* closed with the subject: *name*, *size*, *state* etc.
* Typedefs
* prefer `typedef struct` and `typedef enum` instead of `struct name` and `enum name`
* always add a closing *..._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
### Coding guide
* Functions:
* Try to write function shorter than is 50 lines
* Always shorter than 100 lines (except very straightforwards)
* Variables:
* One line, one declaration (BAD: char x, y;)
* Use `<stdint.h>` (*uint8_t*, *int32_t* etc)
* Declare variables when 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)
### Comments
Before every function have a comment like this:
```c
/**
* Return with the screen of an object
* @param obj pointer to an object
* @return pointer to a screen
*/
lv_obj_t*lv_obj_get_scr(lv_obj_t*obj);
```eval_rst
.. include:: /header.rst
:github_url: |github_link_base|/CONTRIBUTING.md
```
Always use `/* Something */` format and NOT `//Something`
# Contributing
Write readable code to avoid descriptive comments like:
`x++; /* Add 1 to x */`.
The code should show clearly what you are doing.
## Introduction
You should write **why** have you done this:
`x++; /*Because of closing '\0' of the string */`
Join LVGL's community and leave your footprint in the library!
Short "code summaries" of a few lines are accepted. E.g. `/*Calculate the new coordinates*/`
There are a lot of ways to contribute to LVGL even if you are are new to the library or even new to programming.
In comments use \` \` when referring to a variable. E.g. ``/*Update the value of `x_act`*/``
It might be scary to make the first step but you have nothing to be afraid of.
A friendly and helpful community is waiting for you. Get to know like-minded people and make something great together.
### Formatting
Here is example to show bracket placing and using of white spaces:
```c
/**
* Set a new text for a label. Memory will be allocated to store the text by the label.
* @param label pointer to a label object
* @param text '\0' terminated character string. NULL to refresh with the current text.
So let's find which contribution option fits you the best and help you join the development of LVGL!
Before getting started here are some guidelines to make contribution smoother:
- Be kind and friendly.
- Be sure to read the relevant part of the documentation before posting a question.
- Ask questions in the [Forum](https://forum.lvgl.io/) and use [GitHub](https://github.com/lvgl/) for development-related discussions.
- Always fill out the post or issue templates in the Forum or GitHub (or at least provide equivalent information). It makes understanding your contribution or issue easier and you will get a useful response faster.
- If possible send an absolute minimal but buildable code example in order to reproduce the issue. Be sure it contains all the required variable declarations, constants, and assets (images, fonts).
- Use [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) to format your posts. You can learn it in 10 minutes.
- Speak about one thing in one issue or topic. It makes your post easier to find later for someone with the same question.
- Give feedback and close the issue or mark the topic as solved if your question is answered.
- For non-trivial fixes and features, it's better to open an issue first to discuss the details instead of sending a pull request directly.
- Please read and follow the <a href="https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md">Coding style</a> guide.
## Pull request
Merging new code into the lvgl, documentation, blog, examples, and other repositories happen via *Pull requests* (PR for short).
A PR is a notification like "Hey, I made some updates to your project. Here are the changes, you can add them if you want."
To do this you need a copy (called fork) of the original project under your account, make some changes there, and notify the original repository about your updates.
You can see what it looks like on GitHub for LVGL here: [https://github.com/lvgl/lvgl/pulls](https://github.com/lvgl/lvgl/pulls).
To add your changes you can edit files online on GitHub and send a new Pull request from there (recommended for small changes) or
add the updates in your favorite editor/IDE and use git to publish the changes (recommended for more complex updates).
### From GitHub
1. Navigate to the file you want to edit.
2. Click the Edit button in the top right-hand corner.
3. Add your changes to the file.
4. Add a commit message on the bottom of the page.
5. Click the *Propose changes* button.
### From command line
The instructions describe the main `lvgl` repository but it works the same way for the other repositories.
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 your forked repository.
3. Add your changes. You can create a *feature branch* from *master* for the updates: `git checkout -b the-new-feature`
4. Commit and push your changes to the forked `lvgl` repository.
5. Create a PR on GitHub from the page of your `lvgl` repository (`https://github.com/<YOUR_NAME>/lvgl`) by clicking the *"New pull request"* button. Don't forget to select the branch where you added your changes.
7. Set the base branch. It means where you want to merge your update. In the `lvgl` repo fixes go to `master`, new features to `dev` branch.
8. Describe what is in the update. An example code is welcome if applicable.
9. If you need to make more changes, just update your forked `lvgl` repo with new commits. They will automatically appear in the PR.
## Developer Certification of Origin (DCO)
### Overview
To ensure all licensing criteria are met for every repository of the LVGL project, we apply a process called DCO (Developer's Certificate of Origin).
The text of DCO can be read here: [https://developercertificate.org/](https://developercertificate.org/).
By contributing to any repositories of the LVGL project you agree that your contribution complies with the DCO.
If your contribution fulfills the requirements of the DCO no further action is needed. If you are unsure feel free to ask us in a comment.
### Accepted licenses and copyright notices
To make the DCO easier to digest, here are some practical guides about specific cases:
#### Your own work
The simplest case is when the contribution is solely your own work.
In this case you can just send a Pull Request without worrying about any licensing issues.
#### Use code from online source
If the code you would like to add is based on an article, post or comment on a website (e.g. StackOverflow) the license and/or rules of that site should be followed.
For example in case of StackOwerflow a notice like this can be used:
```
/* The original version of this code-snippet was published on StackOverflow.
if(label == NULL) return; /*No bracket only if the command is inline with the if statement*/
lv_obj_inv(label);
lv_label_ext_t * ext = lv_obj_get_ext(label);
/*Comment before a section */
if(text == ext->txt || text == NULL) { /*Bracket of statements start inline*/
lv_label_refr_text(label);
return;
}
...
}
... code snippet here ...
```
Use 4 spaces indentation instead of tab.
#### Use MIT licensed code
As LVGL is MIT licensed, other MIT licensed code can be integrated without issues.
The MIT license requires a copyright notice be added to the derived work. Any derivative work based on MIT licensed code must copy the original work's license file or text.
You can use **astyle** to format the code. The required config flies are: `docs/astyle_c` and `docs/astyle_h`.
<!-- Place this tag where you want the button to render. -->
<a class="github-button" href="https://github.com/lvgl/lvgl" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star lvgl/lvgl on GitHub">Star</a>
This simple click makes LVGL more visible on GitHub and makes it more attractive to other people.
So with this, you already helped a lot!
### Tell what you have achieved
Have you already started using LVGL in a [Simulator](/get-started/pc-simulator), a development board, or on your custom hardware?
Was it easy or were there some obstacles? Are you happy with the result?
Showing your project to others is a win-win situation because it increases your and LVGL's reputation at the same time.
You can post about your project on Twitter, Facebook, LinkedIn, create a YouTube video, and so on.
Only one thing: On social media don't forget to add a link to `https://lvgl.io` or `https://github.com/lvgl` and use the hashtag `#lvgl`. Thank you! :)
You can also open a new topic in the [My projects](https://forum.lvgl.io/c/my-projects/10) category of the Forum.
The [LVGL Blog](https://blog.lvgl.io) welcomes posts from anyone.
It's a good place to talk about a project you created with LVGL, write a tutorial, or share some nice tricks.
The latest blog posts are shown on the [homepage of LVGL](https://lvgl.io) to make your work more visible.
The blog is hosted on GitHub. If you add a post GitHub automatically turns it into a website.
See the [README](https://github.com/lvgl/blog) of the blog repo to see how to add your post.
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)
Any of these help to spread the word and familiarize new developers with LVGL.
If you don't want to speak about your project publicly, feel free to use [Contact form](https://lvgl.io/#contact) on lvgl.io to private message to us.
### Write examples
As you learn LVGL you will probably play with the features of widgets. Why not publish your experiments?
Each widgets' documentation contains examples. For instance, here are the examples of the [Drop-down list](/widgets/core/dropdown#examples) widget.
The examples are directly loaded from the [lvgl/examples](https://github.com/lvgl/lvgl/tree/master/examples) folder.
So all you need to do is send a [Pull request](#pull-request) to the [lvgl](https://github.com/lvgl/lvgl) repository and follow some conventions:
- Name the examples like `lv_example_<widget_name>_<index>`.
- Make the example as short and simple as possible.
- Add comments to explain what the example does.
- Use 320x240 resolution.
- Update `index.rst` in the example's folder with your new example. To see how other examples are added, look in the [lvgl/examples/widgets](https://github.com/lvgl/lvgl/tree/master/examples/widgets) folder.
### Improve the docs
As you read the documentation you might see some typos or unclear sentences. All the documentation is located in the [lvgl/docs](https://github.com/lvgl/lvgl/tree/master/docs) folder.
For typos and straightforward fixes, you can simply edit the file on GitHub.
Note that the documentation is also formatted in [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
### Report bugs
As you use LVGL you might find bugs. Before reporting them be sure to check the relevant parts of the documentation.
If it really seems like a bug feel free to open an [issue on GitHub](https://github.com/lvgl/lvgl/issues).
When filing the issue be sure to fill out the template. It helps find the root of the problem while avoiding extensive questions and exchanges with other developers.
### Send fixes
The beauty of open-source software is you can easily dig in to it to understand how it works. You can also fix or adjust it as you wish.
If you found and fixed a bug don't hesitate to send a [Pull request](#pull-request) with the fix.
In your Pull request please also add a line to [`CHANGELOG.md`](https://github.com/lvgl/lvgl/blob/master/CHANGELOG.md).
### Join the conversations in the Forum
It feels great to know you are not alone if something is not working. It's even better to help others when they struggle with something.
While you were learning LVGL you might have had questions and used the Forum to get answers. As a result, you probably have more knowledge about how LVGL works.
One of the best ways to give back is to use the Forum and answer the questions of newcomers - like you were once.
Just read the titles and if you are familiar with the topic don't hesitate to share your thoughts and suggestions.
Participating in the discussions is one of the best ways to become part of the project and get to know like-minded people!
### Add features
We collect the planned features in GitHub on the [Roadmap](/ROADMAP) page. If you are interested in any of them feel free to share your opinion and/or participate in the the implementation.
Other features which are (still) not on the road map are listed in the [Feature request](https://forum.lvgl.io/c/feature-request/9) category of the Forum.
If you have a feature idea for LVGL please use the Forum to share it!
Make sure to check that there isn't an existing post; if there is, you should comment on it to show that there is increased interest in an existing request.
When adding a new features the followings also needs to be updated:
- Add a line to [CHANGELOG.md](https://github.com/lvgl/lvgl/blob/master/CHANGELOG.md).
- Update the documentation.
- Add an example if applicable. See this [guide](#write-examples).
### Become a maintainer
If you want to become part of the core development team, you can become a maintainer of a repository.
By becoming a maintainer:
- You get write access to that repo:
- Add code directly without sending a pull request
- Accept pull requests
- Close/reopen/edit issues
- Your input has higher impact when we are making decisions
You can become a maintainer by invitation, however the following conditions need to met
1. Have > 50 replies in the Forum. You can look at your stats [here](https://forum.lvgl.io/u?period=all)
2. Send > 5 non-trivial pull requests to the repo where you would like to be a maintainer
If you are interested, just send a message (e.g. from the Forum) to the current maintainers of the repository. They will check if the prerequisites are met.
Note that meeting the prerequisites is not a guarantee of acceptance, i.e. if the conditions are met you won't automatically become a maintainer.
It's up to the current maintainers to make the decision.
### Move your project repository under LVGL organization
Besides the core `lvgl` repository there are other repos for ports to development boards, IDEs or other environment.
If you ported LVGL to a new platform we can host it under the LVGL organization among the other repos.
This way your project will become part of the whole LVGL project and can get more visibility.
If you are interested in this opportunity just open an [issue in lvgl repo](https://github.com/lvgl/lvgl/issues) and tell what you have!
If we agree that your port fit well into the LVGL organization, we will open a repository for your project where you will have admin rights.
To make this concept sustainable there a few rules to follow:
- You need to add a README to your repo.
- We expect to maintain the repo to some extent:
- Follow at least the major versions of LVGL
- Respond to the issues (in a reasonable time)
- If there is no activity in a repo for 1 year it will be archived
This is a summary for planned new features and a collection of ideas.
This list indicates only the current intention and it can be changed.
## v8.X
-`lv_snapshot`: buffer a widget and all of its children into an image. he source widget can be on a different screen too. The result image can be transformed.
- Add radio button support
- Unit testing (gtest?). See [#1658](https://github.com/lvgl/lvgl/issues/1658)
- Benchmarking (gem5?). See [#1660](https://github.com/lvgl/lvgl/issues/1660)
- chart: pre-delete `X` pint after the lastly set
- chart: autoscroll to the right
- 9-patch support for `lv_imgbtn`.
- Handle stride. See [#1858](https://github.com/lvgl/lvgl/issues/1858)
- Optimize line and circle drawing and masking
## Ideas
- Reconsider color format management for run time color format setting, and custom color format usage. (Also [RGB888](https://github.com/lvgl/lvgl/issues/1722))
- Make gradients more versatile
- Make image transformations more versatile
- Switch to RGBA colors in styles
- Consider direct binary font format support
- Simplify `group`s. Discussion is [here](https://forum.lvgl.io/t/lv-group-tabindex/2927/3).
- Use [generate-changelog](https://github.com/lob/generate-changelog) to automatically generate changelog
- lv_mem_alloc_aligned(size, align)
- Text node. See [#1701](https://github.com/lvgl/lvgl/issues/1701#issuecomment-699479408)
- CPP binding. See [Forum](https://forum.lvgl.io/t/is-it-possible-to-officially-support-optional-cpp-api/2736)
- Optimize font decompression
- Need coverage report for tests
- Need static analyze (via coverity.io or somehing else)
- Support dot_begin and dot_middle long modes for labels
- Add new label alignment modes. [#1656](https://github.com/lvgl/lvgl/issues/1656)
- Support larger images: [#1892](https://github.com/lvgl/lvgl/issues/1892)
---
## v8
- Create an `extra` folder for complex widgets
- It makes the core LVGL leaner
- In `extra` we can have a lot and specific widgets
- Good place for contributions
- New scrolling:
- See [feat/new-scroll](https://github.com/lvgl/lvgl/tree/feat/new-scroll) branch and [#1614](https://github.com/lvgl/lvgl/issues/1614)) issue.
- Remove `lv_page` and support scrolling on `lv_obj`
- Support "elastic" scrolling when scrolled in
- Support scroll chaining among any objects types (not only `lv_pages`s)
- Remove `lv_drag`. Similar effect can be achieved by setting the position in `LV_EVENT_PRESSING`
- Add snapping
- Add snap stop to scroll max 1 snap point
- Already working
- New layouts:
- See [#1615](https://github.com/lvgl/lvgl/issues/1615) issue
- [CSS Grid](https://css-tricks.com/snippets/css/a-guide-to-grid/)-like layout support
- [CSS Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)-like layout support
- Remove `lv_cont` and support layouts on `lv_obj`
- Simplified File system interface ([feat/new_fs_api](https://github.com/lvgl/lvgl/tree/feat/new-fs-api) branch) to make porting easier
- Work in progress
- Remove the align parameter from `lv_canvas_draw_text`
- Remove the copy parameter from create functions
- Optimize and simplifie styles [#1832](https://github.com/lvgl/lvgl/issues/1832)
- Use a more generic inheritenace [#1919](https://github.com/lvgl/lvgl/issues/1919)
paragraph_node=nodes.raw(text=f"Click to try in the simulator!<br/><a target='_blank' href='https://sim.lvgl.io/v7/micropython/ports/javascript/bundle_out/index.html?script_startup=https://raw.githubusercontent.com/lvgl/lv_examples/{env.config.example_commit_hash}/src/header.py&script=https://raw.githubusercontent.com/lvgl/lv_examples/{env.config.built_example_commit_hash}/{example_name}/{example_name}.py'><img alt='{example_name}' src='https://raw.githubusercontent.com/lvgl/lv_examples/{env.config.built_example_commit_hash}/{example_name}/{example_name}.png'/></a>",format='html')
The [core LVGL library](https://github.com/lvgl/lvgl) and the [examples](https://github.com/lvgl/lv_examples) are directly available as Arduino libraries.
Note that you need to choose a powerful enough board to run LVGL and your GUI. See the [requirements of LVGL](https://docs.lvgl.io/latest/en/html/intro/index.html#requirements).
For example ESP32 is a good candidate to create your UI with LVGL.
## Get the LVGL Ardunio library
LVGL can be installed via the Arduino IDE Library Manager or as a .ZIP library.
It will also install [lv_exmaples](https://github.com/lvgl/lv_examples) which contains a lot of examples and demos to try LVGL.
## Set up drivers
To get started it's recommended to use [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) library as a TFT driver to simplify testing.
To make it work setup `TFT_eSPI` according to your TFT display type via editing either
-`User_Setup.h`
- or by selecting a configuration in the `User_Setup_Select.h`
Both files are located in `TFT_eSPI` library's folder.
## Configure LVGL
LVGL has its own configuration file called `lv_conf.h`. When LVGL is installed the followings needs to be done to configure it:
1. Go to directory of the installed Arduino libraries
2. Go to `lvgl` and copy `lv_conf_template.h` as `lv_conf.h` into the Arduino Libraries directory next to the `lvgl` library folder.
3. Open `lv_conf.h` and change the first `#if 0` to `#if 1`
4. Set the resolution of your display in `LV_HOR_RES_MAX` and `LV_VER_RES_MAX`
5. Set the color depth of you display in `LV_COLOR_DEPTH`
6. Set `LV_TICK_CUSTOM 1`
## Configure the examples
`lv_examples` can be configures similarly to LVGL but it's configuration file is called `lv_ex_conf.h`.
1. Go to directory of the installed Arduino libraries
2. Go to `lv_examples` and copy `lv_ex_template.h` as `lv_ex_conf.h` next to the `lv_examples` folder.
3. Open `lv_ex_conf.h` and change the first `#if 0` to `#if 1`
4. Enable the demos you want to use. (The small examples starting with `lv_ex_...()` are always enabled.)
## Initialize LVGL and run an example
Take a look at [LVGL_Arduino.ino](https://github.com/lvgl/lvgl/blob/master/examples/LVGL_Arduino.ino) to see how to initialize LVGL.
TFT_eSPI is used as the display driver.
In the INO file you can see how to register a display and a touch pad for LVGL and call an example.
Note that, there is no dedicated INO file for every example but you can call functions like `lv_ex_btn1()` or `lv_ex_slider1()` to run an example.
For the full list of examples see the [README of lv_examples](https://github.com/lvgl/lv_examples/blob/master/README.md).
## Debugging and logging
In case of trouble LVGL can display debug information.
In the `LVGL_Arduino.ino` example there is `my_print` method, which allow to send this debug information to the serial interface.
To enable this feature you have to edit `lv_conf.h` file and enable logging in the section `log settings`:
```c
/*Log settings*/
#define USE_LV_LOG 1 /*Enable/disable the log module*/
#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
*/
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
```
After enabling the log module and setting LV_LOG_LEVEL accordingly the output log is sent to the `Serial` port @ 115200 bps.
Since v7.7.1 LVGL includes a Kconfig file, so LVGL can be used as an ESP-IDF v4 component.
## Get the LVGL demo project for ESP32
We've created [lv_port_esp32](https://github.com/lvgl/lv_port_esp32), a project using ESP-IDF and LVGL to show one of the demos from [lv_examples](https://github.com/lvgl/lv_examples).
You are able to configure the project to use one of the many supported display controllers, see [lvgl_esp32_drivers](https://github.com/lvgl/lvgl_esp32_drivers) for a complete list
of supported display and indev (touch) controllers.
## Use LVGL in your ESP32 project
### Prerequisites
ESP-IDF v4 framework is the suggested version to use.
### Get LVGL
You are suggested to add LVGL as a "component". This component can be located inside a directory named "components" on your project root directory.
When your project is a git repository you can include LVGL as a git submodule:
The above command will clone LVGL's main repository into the `components/lvgl` directory. LVGL includes a `CMakeLists.txt` file that sets some configuration options so you can use LVGL right away.
When you are ready to configure LVGL launch the configuration menu with `idf.py menuconfig` on your project root directory, go to `Component config` and then `LVGL configuration`.
## Use lvgl_esp32_drivers in your project
You are suggested to add `lvgl_esp32_drivers` as a "component". This component can be located inside a directory named "components" on your project root directory.
When your project is a git repository you can include `lvgl_esp32_drivers` as a git submodule:
There are several ways to get your feet wet with LVGL. Here is one recommended order of documents to read and things to play with when you are learning to use LVGL:
1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes)
2. Read the [Introduction](https://docs.lvgl.io/latest/en/html/intro/index.html) page of the documentation (5 minutes)
3. Read the [Quick overview](https://docs.lvgl.io/latest/en/html/get-started/quick-overview.html) page of the documentation (15 minutes)
4. Set up a [Simulator](https://docs.lvgl.io/latest/en/html/get-started/pc-simulator.html) (10 minutes)
5. Try out some [Examples](https://github.com/lvgl/lv_examples/)
6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/latest/en/html/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_&type=&language=)
7. Read the [Overview](https://docs.lvgl.io/latest/en/html/overview/index.html) page to get a better understanding of the library. (2-3 hours)
8. Check the documentation of the [Widgets](https://docs.lvgl.io/latest/en/html/widgets/index.html) to see their features and usage
9. If you have questions got to the [Forum](http://forum.lvgl.io/)
10. Read the [Contributing](https://docs.lvgl.io/latest/en/html/contributing/index.html) guide to see how you can help to improve LVGL (15 minutes)
[Micropython](http://micropython.org/) is Python for microcontrollers.
Using Micropython, you can write Python3 code and run it even on a bare metal architecture with limited resources.
### Highlights of Micropython
- **Compact** - Fits and runs within just 256k of code space and 16k of RAM. No OS is needed, although you can also run it with an OS, if you want.
- **Compatible** - Strives to be as compatible as possible with normal Python (known as CPython).
- **Versatile** - Supports many architectures (x86, x86-64, ARM, ARM Thumb, Xtensa).
- **Interactive** - No need for the compile-flash-boot cycle. With the REPL (interactive prompt) you can type commands and execute them immediately, run scripts etc.
- **Popular** - Many platforms are supported. The user base is growing bigger. Notable forks: [MicroPython](https://github.com/micropython/micropython), [CircuitPython](https://github.com/adafruit/circuitpython), [MicroPython_ESP32_psRAM_LoBo](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo)
- **Embedded Oriented** - Comes with modules specifically for embedded systems, such as the [machine module](https://docs.micropython.org/en/latest/library/machine.html#classes) for accessing low-level hardware (I/O pins, ADC, UART, SPI, I2C, RTC, Timers etc.)
---
## Why Micropython + LVGL?
Currently, Micropython [does not have a good high-level GUI library](https://forum.micropython.org/viewtopic.php?f=18&t=5543) by default. LVGL is an [Object Oriented Component Based](https://blog.lvgl.io/2018-12-13/extend-lvgl-objects) high-level GUI library, which seems to be a natural candidate to map into a higher level language, such as Python. LVGL is implemented in C and its APIs are in C.
### Here are some advantages of using LVGL in Micropython:
- Develop GUI in Python, a very popular high level language. Use paradigms such as Object Oriented Programming.
- Usually, GUI development requires multiple iterations to get things right. With C, each iteration consists of **`Change code` > `Build` > `Flash` > `Run`**.
In Micropython it's just **`Change code` > `Run`** ! You can even run commands interactively using the [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) (the interactive prompt)
### Micropython + LVGL could be used for:
- Fast prototyping GUI.
- Shortening the cycle of changing and fine-tuning the GUI.
- Modelling the GUI in a more abstract way by defining reusable composite objects, taking advantage of Python's language features such as Inheritance, Closures, List Comprehension, Generators, Exception Handling, Arbitrary Precision Integers and others.
- Make LVGL accessible to a larger audience. No need to know C in order to create a nice GUI on an embedded system.
This goes well with [CircuitPython vision](https://learn.adafruit.com/welcome-to-circuitpython/what-is-circuitpython). CircuitPython was designed with education in mind, to make it easier for new or unexperienced users to get started with embedded development.
- Creating tools to work with LVGL at a higher level (e.g. drag-and-drop designer).
---
## So what does it look like?
> TL;DR:
> It's very much like the C API, but Object Oriented for LVGL components.
Let's dive right into an example!
### A simple example
```python
importlvglaslv
lv.init()
scr=lv.obj()
btn=lv.btn(scr)
btn.align(lv.scr_act(),lv.ALIGN.CENTER,0,0)
label=lv.label(btn)
label.set_text("Button")
lv.scr_load(scr)
```
## How can I use it?
### Online Simulator
If you want to experiment with LVGL + Micropython without downloading anything - you can use our online simulator!
It's a fully functional LVGL + Micropython that runs entirely in the browser and allows you to edit a python script and run it.
[Click here to experiment on the online simulator](https://sim.lvgl.io/)
Note: the online simulator is available for lvgl v6 and v7.
### PC Simulator
Micropython is ported to many platforms. One notable port is "unix", which allows you to build and run Micropython (+LVGL) on a Linux machine. (On a Windows machine you might need Virtual Box or WSL or MinGW or Cygwin etc.)
[Click here to know more information about building and running the unix port](https://github.com/lvgl/lv_micropython)
### Embedded platform
In the end, the goal is to run it all on an embedded platform.
Both Micropython and LVGL can be used on many embedded architectures, such as stm32, ESP32 etc.
You would also need display and input drivers. We have some sample drivers (ESP32+ILI9341, as well as some other examples), but chances are you would want to create your own input/display drivers for your specific hardware.
Drivers can be implemented either in C as a Micropython module, or in pure Micropython!
## Where can I find more information?
- In this [Blog Post](https://blog.lvgl.io/2019-02-20/micropython-bindings)
[NuttX](https://nuttx.apache.org/) is a mature and secure real-time operating system (RTOS) with an emphasis on technical standards compliance and small size.
It is scalable from 8-bit to 64-bit microcontrollers and microprocessors and compliant with the Portable Operating System Interface (POSIX) and the American National Standards Institute (ANSI) standards and with many Linux-like subsystems.
The best way to think about NuttX is to think of it as a small Unix/Linux for microcontrollers.
### Highlights of NuttX
- **Small** - Fits and runs in microcontrollers as small as 32KB Flash and 8KB of RAM.
- **Compliant** - Strives to be as compatible as possible with POSIX and Linux.
- **Versatile** - Supports many architectures (ARM, ARM Thumb, AVR, MIPS, OpenRISC, RISC-V 32-bit and 64-bit, RX65N, x86-64, Xtensa, Z80/Z180, etc).
- **Modular** - Its modular design allows developers to select only what really matters and use modules to include new features.
- **Popular** - NuttX is used by many companies around the world. Probably you already used a product with NuttX without knowing it was running NuttX.
- **Predictable** - NuttX is a preemptible Realtime kernel, so you can use it to create predictable applications for realtime control.
---
## Why NuttX + LVGL?
Although NuttX has its own graphic library called [NX](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629474), LVGL is a good alternative because users could find more eye-candy demos and they can reuse code from previous projects.
LVGL is an [Object Oriented Component Based](https://blog.lvgl.io/2018-12-13/extend-lvgl-objects) high-level GUI library, that could fit very well for a RTOS with advanced features like NuttX.
LVGL is implemented in C and its APIs are in C.
### Here are some advantages of using LVGL in NuttX
- Develop GUI in Linux first and when it is done just compile it for NuttX. Nothing more, no wasting of time.
- Usually, GUI development for low level RTOS requires multiple iterations to get things right, where each iteration consists of **`Change code` > `Build` > `Flash` > `Run`**.
Using LVGL, Linux and NuttX you can reduce this process and just test everything on your computer and when it is done, compile it on NuttX and that is it.
### NuttX + LVGL could be used for
- GUI demos to demonstrate your board graphics capacities.
- Fast prototyping GUI for MVP (Minimum Viable Product) presentation.
- visualize sensor data directly and easily on the board without using a computer.
- Final products with a GUI without a touchscreen (i.e. 3D Printer Interface using Rotary Encoder to Input data).
- Final products with a touchscreen (and all sorts of bells and whistles).
---
## How to get started with NuttX and LVGL?
There are many boards in the NuttX mainline (https://github.com/apache/incubator-nuttx) with support for LVGL.
Let's use the [STM32F429IDISCOVERY](https://www.st.com/en/evaluation-tools/32f429idiscovery.html) as example because it is a very popular board.
### First you need to install the pre-requisite on your system
Let's use the [Windows Subsystem for Linux](https://acassis.wordpress.com/2018/01/10/how-to-build-nuttx-on-windows-10/)
NXP has integrated LVGL into the MCUXpresso SDK packages for several of their general
purpose and crossover microcontrollers, allowing easy evaluation and migration into your
product design. [Download an SDK for a supported board](https://www.nxp.com/design/software/embedded-software/littlevgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY?&tid=vanLITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY)
today and get started with your next GUI application.
## Creating new project with LVGL
Downloading the MCU SDK example project is recommended as a starting point. It comes fully
configured with LVGL (and with PXP support if module is present), no additional integration
work is required.
## Adding HW acceleration for NXP iMX RT platforms using PXP (PiXel Pipeline) engine for existing projects
Several drawing features in LVGL can be offloaded to PXP engine. In order to use CPU time while PXP
is running, RTOS is required to block the LVGL drawing thread and switch to another task, or simply to
idle task, where CPU could be suspended to save power.
You can try out LVGL **using only your PC** (i.e. without any development boards). LVGL will run on a simulator environment on the PC where anyone can write and experiment the real LVGL applications.
Using the simulator on the PC has the following advantages:
- Hardware independent - Write code, run it on the PC and see the result on the PC monitor.
- Cross-platform - Any Windows, Linux or MacOS system can run the PC simulator.
- Portability - the written code is portable, which means you can simply copy it when using an embedded hardware.
- Easy Validation - The simulator is also very useful to report bugs because it means common platform for every user. So it's a good idea to reproduce a bug in the simulator and use the code snippet in the [Forum](https://forum.lvgl.io).
## Select an IDE
The simulator is ported to various IDEs (Integrated Development Environments). Choose your favorite IDE, read its README on GitHub, download the project, and load it to the IDE.
- [Eclipse with SDL driver](https://github.com/lvgl/lv_sim_eclipse_sdl): Recommended on Linux and Mac
- [CodeBlocks](https://github.com/lvgl/lv_sim_codeblocks_win): Recommended on Windows
- [VisualStudio with SDL driver](https://github.com/lvgl/lv_sim_visual_studio_sdl): For Windows
- [VSCode with SDL driver](https://github.com/lvgl/lv_sim_vscode_sdl): Recommended on Linux and Mac
- [PlatformIO with SDL driver](https://github.com/lvgl/lv_platformio): Recommended on Linux and Mac
You can use any IDE for the development but, for simplicity, the configuration for Eclipse CDT is what we'll focus on in this tutorial.
The following section describes the set-up guide of Eclipse CDT in more details.
**Note: If you are on Windows, it's usually better to use the Visual Studio or CodeBlocks projects instead. They work out of the box without requiring extra steps.**
## Set-up Eclipse CDT
### Install Eclipse CDT
[Eclipse CDT](https://eclipse.org/cdt/) is a C/C++ IDE.
Eclipse is a Java based software therefore be sure **Java Runtime Environment** is installed on your system.
On Debian-based distros (e.g. Ubuntu): `sudo apt-get install default-jre`
Note: If you are using other distros, then please refer and install 'Java Runtime Environment' suitable to your distro.
Note: If you are using macOS and get a "Failed to create the Java Virtual Machine" error, uninstall any other Java JDK installs and install Java JDK 8u. This should fix the problem.
You can download Eclipse's CDT from: [https://www.eclipse.org/cdt/downloads.php](https://www.eclipse.org/cdt/downloads.php). Start the installer and choose *Eclipse CDT* from the list.
### Install SDL 2
The PC simulator uses the [SDL 2](https://www.libsdl.org/download-2.0.php) cross platform library to simulate a TFT display and a touch pad.
#### Linux
On **Linux** you can easily install SDL2 using a terminal:
1. Find the current version of SDL2: `apt-cache search libsdl2 (e.g. libsdl2-2.0-0)`
2. Install SDL2: `sudo apt-get install libsdl2-2.0-0` (replace with the found version)
3. Install SDL2 development package: `sudo apt-get install libsdl2-dev`
4. If build essentials are not installed yet: `sudo apt-get install build-essential`
#### Windows
If you are using **Windows** firstly you need to install MinGW ([64 bit version](http://mingw-w64.org/doku.php/download)). After installing MinGW, do the following steps to add SDL2:
1. Download the development libraries of SDL.
Go to [https://www.libsdl.org/download-2.0.php](https://www.libsdl.org/download-2.0.php) and download _Development Libraries: SDL2-devel-2.0.5-mingw.tar.gz_
2. Decompress the file and go to _x86_64-w64-mingw32_ directory (for 64 bit MinGW) or to _i686-w64-mingw32_ (for 32 bit MinGW)
3. Copy _..._mingw32/include/SDL2_ folder to _C:/MinGW/.../x86_64-w64-mingw32/include_
4. Copy _..._mingw32/lib/_ content to _C:/MinGW/.../x86_64-w64-mingw32/lib_
5. Copy _..._mingw32/bin/SDL2.dll_ to _{eclipse_worksapce}/pc_simulator/Debug/_. Do it later when Eclipse is installed.
Note: If you are using **Microsoft Visual Studio** instead of Eclipse then you don't have to install MinGW.
#### OSX
On **OSX** you can easily install SDL2 with brew: `brew install sdl2`
If something is not working, then please refer [this tutorial](http://lazyfoo.net/tutorials/SDL/01_hello_SDL/index.php) to get started with SDL.
### Pre-configured project
A pre-configured graphics library project (based on the latest release) is always available to get started easily.
You can find the latest one on [GitHub](https://github.com/lvgl/lv_sim_eclipse_sdl).
(Please note that, the project is configured for Eclipse CDT).
### Add the pre-configured project to Eclipse CDT
Run Eclipse CDT. It will show a dialogue about the **workspace path**. Before accepting the path, check that path and copy (and unzip) the downloaded pre-configured project there. After that, you can accept the workspace path. Of course you can modify this path but, in that case copy the project to the corresponding location.
Close the start up window and go to **File->Import** and choose **General->Existing project into Workspace**. **Browse the root directory** of the project and click **Finish**
On **Windows** you have to do two additional things:
- Copy the **SDL2.dll** into the project's Debug folder
- Right click on the project -> Project properties -> C/C++ Build -> Settings -> Libraries -> Add ... and add _mingw32_ above SDLmain and SDL. (The order is important: mingw32, SDLmain, SDL)
### Compile and Run
Now you are ready to run LVGL on your PC. Click on the Hammer Icon on the top menu bar to Build the project. If you have done everything right, then you will not get any errors. Note that on some systems additional steps might be required to "see" SDL 2 from Eclipse but, in most of cases the configurations in the downloaded project is enough.
After a success build, click on the Play button on the top menu bar to run the project. Now a window should appear in the middle of your screen.
Now you are ready to use LVGL and begin development on your PC.
Here you can learn the most important things about LVGL.
You should read this first to get a general impression and read the detailed [Porting](/porting/index) and [Overview](/overview/index) sections after that.
## Get started in a simulator
Instead of porting LVGL to embedded hardware straight away, it's highly recommended to get started in a simulator first.
LVGL is ported to many IDEs to be sure you will find your favorite one.
Go to the [Simulators](/get-started/pc-simulator) section to get ready-to-use projects that can be run on your PC.
This way you can save the time of porting for now and get some experience with LVGL immediately.
## Add LVGL into your project
If you would rather try LVGL on your own project follow these steps:
- [Download](https://github.com/lvgl/lvgl/archive/master.zip) or clone the library from GitHub with `git clone https://github.com/lvgl/lvgl.git`.
- Copy the `lvgl` folder into your project.
- Copy `lvgl/lv_conf_template.h` as `lv_conf.h` next to the `lvgl` folder, change the first `#if 0` to `1` to enable the file's content and set the `LV_COLOR_DEPTH` defines.
- Include `lvgl/lvgl.h` in files where you need to use LVGL related functions.
- 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.
Alternatively, configure `LV_TICK_CUSTOM` (see `lv_conf.h`) so that LVGL can retrieve the current time directly.
- Call `lv_init()`
- Create a draw buffer: LVGL will render the graphics here first, and send the rendered image to the display.
The buffer size can be set freely but 1/10 screen size is a good starting point.
```c
staticlv_disp_draw_buf_tdraw_buf;
staticlv_color_tbuf1[DISP_HOR_RES*DISP_VER_RES/10];/*Declare a buffer for 1/10 screen size*/
lv_disp_draw_buf_init(&draw_buf,buf1,NULL,MY_DISP_HOR_RES*MY_DISP_VER_SER/10);/*Initialize the display buffer.*/
```
- Implement and register a function which can copy the rendered image to an area of your display:
```c
lv_disp_drv_tdisp_drv;/*Descriptor of a display driver*/
/*`touchpad_is_pressed` and `touchpad_get_xy` needs to be implemented by you*/
if(touchpad_is_pressed()){
data->state=LV_INDEV_STATE_PRESSED;
touchpad_get_xy(&data->point.x,&data->point.y);
}else{
data->state=LV_INDEV_STATE_RELEASED;
}
}
```
- Call `lv_timer_handler()` periodically every few milliseconds in the main `while(1)` loop or in an operating system task.
It will redraw the screen if required, handle input devices, animation etc.
For a more detailed guide go to the [Porting](/porting/index) section.
## Learn the basics
### Widgets
The graphical elements like Buttons, Labels, Sliders, Charts etc. are called objects or widgets. Go to [Widgets](/widgets/index) to see the full list of available widgets.
Every object has a parent object where it is created. For example if a label is created on a button, the button is the parent of label.
The child object moves with the parent and if the parent is deleted the children will be deleted too.
Children can be visible only on their parent. It other words, the parts of the children outside of the parent are clipped.
A Screen is the "root" parent. You can have any number of screens.
To get the current screen call `lv_scr_act()`, and to load a screen use `lv_scr_load(scr1)`.
You can create a new object with `lv_<type>_create(parent)`. It will return an `lv_obj_t *` variable that can be used as a reference to the object to set its parameters.
For example:
```c
lv_obj_t*slider1=lv_slider_create(lv_scr_act());
```
To set some basic attributes `lv_obj_set_<parameter_name>(obj, <value>)` functions can be used. For example:
```c
lv_obj_set_x(btn1,30);
lv_obj_set_y(btn1,10);
lv_obj_set_size(btn1,200,50);
```
The widgets have type specific parameters too which can be set by `lv_<widget_type>_set_<parameter_name>(obj, <value>)` functions. For example:
```c
lv_slider_set_value(slider1,70,LV_ANIM_ON);
```
To see the full API visit the documentation of the widgets or the related header file (e.g. [lvgl/src/widgets/lv_slider.h](https://github.com/lvgl/lvgl/blob/master/src/widgets/lv_slider.h)).
### Events
Events are used to inform the user that something has happened with an object.
You can assign one or more callbacks to an object which will be called if the object is clicked, released, dragged, being deleted etc.
A callback is assigned like this:
```c
lv_obj_add_event_cb(btn,btn_event_cb,LV_EVENT_CLICKED,NULL);/*Assign a callback to the button*/
...
voidbtn_event_cb(lv_event_t*e)
{
printf("Clicked\n");
}
```
Instead of `LV_EVENT_CLICKED``LV_EVENT_ALL` can be used too to call the callback for any event.
From `lv_event_t * e` the current event code can be get with
```c
lv_event_code_tcode=lv_event_get_code(e);
```
The object that triggered the event can be retrieved with
```c
lv_obj_t*obj=lv_event_get_target(e);
```
To learn all features of the events go to the [Event overview](/overview/event) section.
### Parts
Widgets might be built from one or more *parts*. For example a button has only one part called `LV_PART_MAIN`.
However, a [Slider](/widgets/core/slider) has `LV_PART_MAIN`, `LV_PART_INDICATOR` and `LV_PART_KNOB`.
By using parts you can apply different styles to different parts. (See below)
To learn which parts are used by which object read the widgets' documentation.
### States
The objects can be in a combination of the following states:
-`LV_STATE_DEFAULT` Normal, released state
-`LV_STATE_CHECKED` Toggled or checked state
-`LV_STATE_FOCUSED` Focused via keypad or encoder or clicked via touchpad/mouse
-`LV_STATE_FOCUS_KEY` Focused via keypad or encoder but not via touchpad/mouse
-`LV_STATE_EDITED` Edit by an encoder
-`LV_STATE_HOVERED` Hovered by mouse (not supported now)
-`LV_STATE_PRESSED` Being pressed
-`LV_STATE_SCROLLED` Being scrolled
-`LV_STATE_DISABLED` Disabled
For example, if you press an object it will automatically go to `LV_STATE_FOCUSED` and `LV_STATE_PRESSED` state and when you release it, the `LV_STATE_PRESSED` state will be removed.
To check if an object is in a given state use `lv_obj_has_state(obj, LV_STATE_...)`. It will return `true` if the object is in that state at that time.
To manually add or remove states use
```c
lv_obj_add_state(obj,LV_STATE_...);
lv_obj_clear_state(obj,LV_STATE_...);
```
### Styles
Styles contains properties such as background color, border width, font, etc to describe the appearance of the objects.
The styles are `lv_style_t` variables. Only their pointer is saved in the objects so they need to be static or global.
Before using a style it needs to be initialized with `lv_style_init(&style1)`. After that properties can be added. For example:
If the *part* is `LV_PART_MAIN` it can be omitted:
```c
lv_obj_add_style(btn1,&style1,LV_STATE_PRESSED);/*Equal to LV_PART_MAIN | LV_STATE_PRESSED*/
```
Similarly, `LV_STATE_DEFAULT` can be omitted too:
```c
lv_obj_add_style(slider1,&style1,LV_PART_INDICATOR);/*Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT*/
```
For `LV_STATE_DEFAULT` and `LV_PART_MAIN` simply write `0`:
```c
lv_obj_add_style(btn1,&style1,0);/*Equal to LV_PART_MAIN | LV_STATE_DEFAULT*/
```
The styles can be cascaded (similarly to CSS). It means you can add more styles to a part of an object.
For example `style_btn` can set a default button appearance, and `style_btn_red` can overwrite the background color to make the button red:
```c
lv_obj_add_style(btn1,&style_btn,0);
lv_obj_add_style(btn1,&style1_btn_red,0);
```
If a property is not set on for the current state the style with `LV_STATE_DEFAULT` will be used. If the property is not defined even in the default state a default value is used.
Some properties (typically the text-related ones) can be inherited. It means if a property is not set in an object it will be searched in its parents too.
For example, you can set the font once in the screen's style and all text on that screen will inherit it by default.
Local style properties also can be added to the objects. It creates a style which resides inside the object and which is used only by the object:
<a href="intro/index.html"><img class="home-img" src="_static/img/home_1.png" alt="Get familiar with the LVGL project"></a>
<a href="get-started/index.html"><img class="home-img" src="_static/img/home_2.png" alt="Learn the basic of LVGL and its usage on various platforms"></a>
<a href="porting/index.html"><img class="home-img" src="_static/img/home_3.png" alt="See how to port LVGL to any platform"></a>
<a href="overview/index.html"><img class="home-img" src="_static/img/home_4.png" alt="Learn the how LVGL works in more detail"></a>
<a href="widgets/index.html"><img class="home-img" src="_static/img/home_5.png" alt="Take a look at the description of the available widgets"></a>
<a href="CONTRIBUTING.html"><img class="home-img" src="_static/img/home_6.png" alt="Be part of the development of LVGL"></a>
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.
## Key features
- Powerful building blocks such as buttons, charts, lists, sliders, images, etc.
- Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling
- Various input devices such as touchpad, mouse, keyboard, encoder, etc.
- Multi-language support with UTF-8 encoding
- Multi-display support, i.e. use multiple TFT, monochrome displays simultaneously
- Fully customizable graphic elements with CSS-like styles
- Hardware independent: use with any microcontroller or display
- Scalable: able to operate with little memory (64 kB Flash, 16 kB RAM)
- OS, external memory and GPU supported but not required
- Single frame buffer operation even with advanced graphic effects
- Written in C for maximal compatibility (C++ compatible)
- Simulator to start embedded GUI design on a PC without embedded hardware
- Binding to MicroPython
- Tutorials, examples, themes for rapid GUI design
- Documentation is available online and PDF
- Free and open-source under MIT license
## Requirements
Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are:
<ul>
<li> 16, 32 or 64 bit microcontroller or processor</li>
<li>> 16 MHz clock speed is recommended</li>
<li> Flash/ROM: > 64 kB for the very essential components (> 180 kB is recommended)</li>
<li> RAM:
<ul>
<li> Static RAM usage: ~2 kB depending on the used features and objects types</li>
<li> Stack: > 2kB (> 8 kB is recommended)</li>
<li> Dynamic data (heap): > 4 KB (> 32 kB is recommended if using several objects).
Set by <em>LV_MEM_SIZE</em> in <em>lv_conf.h</em>. </li>
<em>Note that memory usage may vary depending on architecture, compiler and build options.</em>
## License
The LVGL project (including all repositories) is licensed under [MIT license](https://github.com/lvgl/lvgl/blob/master/LICENCE.txt).
It means you can use it even in commercial projects.
It's not mandatory but we highly appreciate it if you write a few words about your project in the [My projects](https://forum.lvgl.io/c/my-projects/10) category of the forum or a private message to [lvgl.io](https://lvgl.io/#contact).
Although you can get LVGL for free there is a massive amount of work behind it. It's created by a group of volunteers who made it available for you intheir free time.
To make the LVGL project sustainable, please consider [contributing](/CONTRIBUTING) to the project.
You can choose from [many different ways of contributing](/CONTRIBUTING) such as simply writing a tweet about you are using LVGL, fixing bugs, translating the documentation, or even becoming a maintainer.
## Repository layout
All repositories of the LVGL project are hosted on GitHub: https://github.com/lvgl
You will find these repositories there:
- [lvgl](https://github.com/lvgl/lvgl) The library itself with many [examples](https://github.com/lvgl/lvgl/blob/master/examples/).
- [lv_demos](https://github.com/lvgl/lv_demos) Demos created with LVGL.
- [lv_drivers](https://github.com/lvgl/lv_drivers) Display and input device drivers
- [blog](https://github.com/lvgl/blog) Source of the blog's site (https://blog.lvgl.io)
- [sim](https://github.com/lvgl/sim) Source of the online simulator's site (https://sim.lvgl.io)
- [lv_sim_...](https://github.com/lvgl?q=lv_sim&type=&language=) Simulator projects for various IDEs and platforms
- [lv_port_...](https://github.com/lvgl?q=lv_port&type=&language=) LVGL ports to development boards
- [lv_binding_..](https://github.com/lvgl?q=lv_binding&type=&language=l) Bindings to other languages
- [lv_...](https://github.com/lvgl?q=lv_&type=&language=) Ports to other platforms
## Release policy
The core repositories follow the rules of [Semantic versioning](https://semver.org/):
- Major versions for incompatible API changes. E.g. v5.0.0, v6.0.0
- Minor version for new but backward-compatible functionalities. E.g. v6.1.0, v6.2.0
- Patch version for backward-compatible bug fixes. E.g. v6.1.1, v6.1.2
Tags like `vX.Y.Z` are createdfor every release.
### Release cycle
- Bugfixes: Released on demand even weekly
- Minor releases: Every 3-4 months
- Major releases: Approximatelly yearly
### Branches
The core repositories have at least the following branches:
-`master` latest version, patches are merged directly here.
-`release/vX.Y` stable versions of the minor releases
-`fix/some-description` temporal branches for bug fixes
-`feat/some-description` temporal branches for features
### Changelog
The changes are recorded in [CHANGELOG.md](/CHANGELOG).
### Version support
Before v8 every minor release of major releases is supported for 1 year.
From v8 every minor release is supported for 1 year.
| Version | Release date | Support end | Active |
|---------|--------------|-------------|--------|
| v5.3 | Feb 1, 2019 |Feb 1, 2020 | No |
| v6.1 | Nov 26, 2019 |Nov 26, 2020 | No |
| v7.11 | Mar 16, 2021 |Mar 16, 2022 | Yes |
| v8.0 | In progress | | |
## FAQ
### Where can I ask questions?
You can ask questions in the forum: [https://forum.lvgl.io/](https://forum.lvgl.io/).
We use [GitHub issues](https://github.com/lvgl/lvgl/issues) for development related discussion.
So you should use them only if your question or issue is tightly related to the development of the library.
### Is my MCU/hardware supported?
Every MCU which is capable of driving a display via Parallel port, SPI, RGB interface or anything else and fulfills the [Requirements](#requirements) is supported by LLVGL.
This includes:
- "Common" MCUs like STM32F, STM32H, NXP Kinetis, LPC, iMX, dsPIC33, PIC32 etc.
- Bluetooth, GSM, WiFi modules like Nordic NRF and Espressif ESP32
- Linux with frame buffer device such as /dev/fb0. This includes Single-board computers like the Raspberry Pi
- And anything else with a strong enough MCU and a periphery to drive a display
### Is my display supported?
LVGL needs just one simple driver function to copy an array of pixels into a given area of the display.
If you can do this with your display then you can use that display with LVGL.
Some examples of the supported display types:
- TFTs with 16 or 24 bit color depth
- Monitors with HDMI port
- Small monochrome displays
- Gray-scale displays
- even LED matrices
- or any other display where you can control the color/state of the pixels
See the [Porting](/porting/display) section to learn more.
### Nothing happens, my display driver is not called. What have I missed?
Be sure you are calling `lv_tick_inc(x)` in an interrupt and `lv_timer_handler()` in your main `while(1)`.
Learn more in the [Tick](/porting/tick) and [Task handler](/porting/task-handler) section.
### Why is the display driver called only once? Only the upper part of the display is refreshed.
Be sure you are calling `lv_disp_flush_ready(drv)` at the end of your "*display flush callback*".
### Why do I see only garbage on the screen?
Probably there a bug in your display driver. Try the following code without using LVGL. You should see a square with red-blue gradient.
The Flexbox (or Flex for short) is a subset of [CSS Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).
It can arrange items into rows or columns (tracks), handle wrapping, adjust the spacing between the items and tracks, handle *grow* to make the item(s) fill the remaining space with respect to min/max width and height.
To make an object flex container call `lv_obj_set_layout(obj, LV_LAYOUT_FLEX)`.
Note that the flex layout feature of LVGL needs to be globally enabled with `LV_USE_FLEX` in `lv_conf.h`.
## Terms
- tracks: the rows or columns
- main direction: row or column, the direction in which the items are placed
- cross direction: perpendicular to the main direction
- wrap: if there there is no more space in the track a new track is started
- grow: if set on an item it will grow to fill the remaining space on the track.
The available space will be distributed among items respective to the their grow value (larger value means more space)
- gap: the space between the rows and columns or the items on a track
## Simple interface
With the following functions you can set a Flex layout on any parent.
### Flex flow
`lv_obj_set_flex_flow(obj, flex_flow)`
The possible values for `flex_flow` are:
-`LV_FLEX_FLOW_ROW` Place the children in a row without wrapping
-`LV_FLEX_FLOW_COLUMN` Place the children in a column without wrapping
-`LV_FLEX_FLOW_ROW_WRAP` Place the children in a row with wrapping
-`LV_FLEX_FLOW_COLUMN_WRAP` Place the children in a column with wrapping
-`LV_FLEX_FLOW_ROW_REVERSE` Place the children in a row without wrapping but in reversed order
-`LV_FLEX_FLOW_COLUMN_REVERSE` Place the children in a column without wrapping but in reversed order
-`LV_FLEX_FLOW_ROW_WRAP_REVERSE` Place the children in a row without wrapping but in reversed order
-`LV_FLEX_FLOW_COLUMN_WRAP_REVERSE` Place the children in a column without wrapping but in reversed order
### Flex align
To manage the placement of the children use `lv_obj_set_flex_align(obj, main_place, cross_place, track_cross_place)`
-`main_place` determines how to distribute the items in their track on the main axis. E.g. flush the items to the right on `LV_FLEX_FLOW_ROW_WRAP`. (It's called `justify-content` in CSS)
-`cross_place` determines how to distribute the items in their track on the cross axis. E.g. if the items have different height place them to the bottom of the track. (It's called `align-items` in CSS)
-`track_cross_place` determines how to distribute the tracks (It's called `align-content` in CSS)
The possible values are:
-`LV_FLEX_ALIGN_START` means left on a horizontally and top vertically. (default)
-`LV_FLEX_ALIGN_END` means right on a horizontally and bottom vertically
-`LV_FLEX_ALIGN_CENTER` simply center
-`LV_FLEX_ALIGN_SPACE_EVENLY` items are distributed so that the spacing between any two items (and the space to the edges) is equal. Does not apply to `track_cross_place`.
-`LV_FLEX_ALIGN_SPACE_AROUND` items are evenly distributed in the track with equal space around them.
Note that visually the spaces aren’t equal, since all the items have equal space on both sides.
The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies. Not applies to `track_cross_place`.
-`LV_FLEX_ALIGN_SPACE_BETWEEN` items are evenly distributed in the track: first item is on the start line, last item on the end line. Not applies to `track_cross_place`.
### Flex grow
Flex grow can be used to make one or more children fill the available space on the track. If more children has grow the available space will be distributed proportionally to the grow values.
For example let's there is 400 px remaining space and 4 object with grow:
-`A` with grow = 1
-`B` with grow = 1
-`C` with grow = 2
`A` and `B` will have 100 px size, and `C` will have 200 px size.
Flex grow can be set on a child with `lv_obj_set_flex_flow(child, value)`. `value` needs to be > 1 or 0 to disable grow on the child.
## Style interface
All the Flex-related values are style properties under the hood and you can use them similarly to any other style property. The following flex related style properties exist:
-`FLEX_FLOW`
-`FLEX_MAIN_PLACE`
-`FLEX_CROSS_PLACE`
-`FLEX_TRACK_PLACE`
-`FLEX_GROW`
## Other features
### RTL
If the base direction of the container is set the `LV_BASE_DIR_RTL` the meaning of `LV_FLEX_ALIGN_START` and `LV_FLEX_ALIGN_END` is swapped on `ROW` layouts. I.e. `START` will mean right.
The items on `ROW` layouts, and tracks of `COLUMN` layouts will be placed from right to left.
### New track
You can force Flex to put an item into a new line with `lv_obj_add_flag(child, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)`.
The Grid layout is a subset of [CSS Flexbox](https://css-tricks.com/snippets/css/complete-guide-grid/).
It can arrange items into 2D "table" that has rows or columns (tracks). The item can span through multiple columns or rows.
The track's size can be set in pixel, to the largest item (`LV_GRID_CONTENT`) or in "Free unit" (FR) to distribute the free space proportionally.
To make an object a grid container call `lv_obj_set_layout(obj, LV_LAYOUT_GRID)`.
Note that the grid layout feature of LVGL needs to be globally enabled with `LV_USE_GRID` in `lv_conf.h`.
## Terms
- tracks: the rows or columns
- free unit (FR): if set on track's size is set in `FR` it will grow to fill the remaining space on the parent.
- gap: the space between the rows and columns or the items on a track
## Simple interface
With the following functions you can easily set a Grid layout on any parent.
### Grid descriptors
First you need to describe the size of rows and columns. It can be done by declaring 2 arrays and the track sizes in them. The last element must be `LV_GRID_TEMPLATE_LAST`.
For example:
```
static lv_coord_t column_dsc[] = {100, 400, LV_GRID_TEMPLATE_LAST}; /*2 columns with 100 and 400 ps width*/
To set the descriptors on a parent use `lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc)`.
Besides simple settings the size in pixel you can use two special values:
-`LV_GRID_CONTENT` set the width to the largest children on this track
-`LV_GRID_FR(X)` tell what portion of the remaining space should be used by this track. Larger value means larger space.
### Grid items
By default the children are not added to the grid. They need to be added manually to a cell.
To do this call `lv_obj_set_grid_cell(child, column_align, column_pos, column_span, row_align, row_pos, row_span)`.
`column_align` and `row_align` determine how to align the children in its cell. The possible values are:
-`LV_GRID_ALIGN_START` means left on a horizontally and top vertically. (default)
-`LV_GRID_ALIGN_END` means right on a horizontally and bottom vertically
-`LV_GRID_ALIGN_CENTER` simply center
`colum_pos` and `row_pos` means the zero based index of the cell into the item should be placed.
`colum_span` and `row_span` means how many tracks should the item involve from the start cell. Must be > 1.
### Grid align
If there are some empty space the track can be aligned several ways:
-`LV_GRID_ALIGN_START` means left on a horizontally and top vertically. (default)
-`LV_GRID_ALIGN_END` means right on a horizontally and bottom vertically
-`LV_GRID_ALIGN_CENTER` simply center
-`LV_GRID_ALIGN_SPACE_EVENLY` items are distributed so that the spacing between any two items (and the space to the edges) is equal. Not applies to `track_cross_place`.
-`LV_GRID_ALIGN_SPACE_AROUND` items are evenly distributed in the track with equal space around them.
Note that visually the spaces aren’t equal, since all the items have equal space on both sides.
The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies. Not applies to `track_cross_place`.
-`LV_GRID_ALIGN_SPACE_BETWEEN` items are evenly distributed in the track: first item is on the start line, last item on the end line. Not applies to `track_cross_place`.
To set the track's alignment use `lv_obj_set_grid_align(obj, column_align, row_align)`.
## Style interface
All the Grid related values are style properties under the hood and you can use them similarly to any other style properties. The following Grid related style properties exist:
-`GRID_COLUMN_DSC_ARRAY`
-`GRID_ROW_DSC_ARRAY`
-`GRID_COLUMN_ALIGN`
-`GRID_ROW_ALIGN`
-`GRID_CELL_X_ALIGN`
-`GRID_CELL_COLUMN_POS`
-`GRID_CELL_COLUMN_SPAN`
-`GRID_CELL_Y_ALIGN`
-`GRID_CELL_ROW_POS`
-`GRID_CELL_ROW_SPAN`
## Other features
### RTL
If the base direction of the container is set to `LV_BASE_DIR_RTL`, the meaning of `LV_GRID_ALIGN_START` and `LV_GRID_ALIGN_END` is swapped. I.e. `START` will mean right-most.
You can automatically change the value of a variable between a start and an end value using animations.
The animation will happen by periodically calling an "animator" function with the corresponding value parameter.
The *animator* functions have the following prototype:
```c
voidfunc(void*var,lv_anim_var_tvalue);
```
This prototype is compatible with the majority of the *set* functions of LVGL. For example `lv_obj_set_x(obj, value)` or `lv_obj_set_width(obj, value)`
## Create an animation
To create an animation an `lv_anim_t` variable has to be initialized and configured with `lv_anim_set_...()` functions.
/*Time to wait before starting the animation [ms]*/
lv_anim_set_delay(&a,delay);
/*Set path (curve). Default is linear*/
lv_anim_set_path(&a,lv_anim_path_ease_in);
/*Set a callback to call when animation is ready.*/
lv_anim_set_ready_cb(&a,ready_cb);
/*Set a callback to call when animation is started (after delay).*/
lv_anim_set_start_cb(&a,start_cb);
/*Play the animation backward too with this duration. Default is 0 (disabled) [ms]*/
lv_anim_set_playback_time(&a,wait_time);
/*Delay before playback. Default is 0 (disabled) [ms]*/
lv_anim_set_playback_delay(&a,wait_time);
/*Number of repetitions. Default is 1. LV_ANIM_REPEAT_INFINIT for infinite repetition*/
lv_anim_set_repeat_count(&a,wait_time);
/*Delay before repeat. Default is 0 (disabled) [ms]*/
lv_anim_set_repeat_delay(&a,wait_time);
/*true (default): apply the start vale immediately, false: apply start vale after delay when then anim. really starts. */
lv_anim_set_early_apply(&a,true/false);
/* START THE ANIMATION
*------------------*/
lv_anim_start(&a);/*Start the animation*/
```
You can apply multiple different animations on the same variable at the same time.
For example, animate the x and y coordinates with `lv_obj_set_x` and `lv_obj_set_y`. However, only one animation can exist with a given variable and function pair.
Therefore `lv_anim_start()` will delete the already existing variable-function animations.
## Animation path
You can determinate the path of animation. The most simple case is linear, meaning the current value between *start* and *end* is changed with fixed steps.
A *path* is a function which calculates the next value to set based on the current state of the animation. Currently, there are the following built-in paths functions:
-`lv_anim_path_linear` linear animation
-`lv_anim_path_step` change in one step at the end
-`lv_anim_path_ease_in` slow at the beginning
-`lv_anim_path_ease_out` slow at the end
-`lv_anim_path_ease_in_out` slow at the beginning and at the end
-`lv_anim_path_overshoot` overshoot the end value
-`lv_anim_path_bounce` bounce back a little from the end value (like hitting a wall)
## Speed vs time
By default, you set the animation time. But in some cases, setting the animation speed is more practical.
The `lv_anim_speed_to_time(speed, start, end)` function calculates the required time in milliseconds to reach the end value from a start value with the given speed.
The speed is interpreted in _unit/sec_ dimension. For example, `lv_anim_speed_to_time(20,0,100)` will yield 5000 milliseconds. For example, in case of `lv_obj_set_x`*unit* is pixels so *20* means *20 px/sec* speed.
## Delete animations
You can delete an animation with `lv_anim_del(var, func)` if you provide the animated variable and its animator function.
The color module handles all color-related functions like changing color depth, creating colors from hex code, converting between color depths, mixing colors, etc.
`lv_color_t` is used to store a color, its fileds are set according to `LV_COLOR_DEPTH` in `lv_conf.h`. (See below)
You may set `LV_COLOR_16_SWAP` in `lv_conf.h` to swap the bytes of *RGB565* colors. You may need this to send the 16-bit colors via a byte-oriented interface like SPI. As 16-bit numbers are stored in Little Endian format (lower byte on the lower address), the interface will send the lower byte first. However, displays usually need the higher byte first. A mismatch in the byte order will result in highly distorted colors.
## Creating colors
### RGB
Create colors from Red, Green and Blue channel values
```c
//All channels are 0-255
lv_color_tc=lv_color_make(red,green,blue);
//From hex code 0x000000..0xFFFFFF interpreted as RED + GREEN + BLUE
lv_color_tc=lv_color_hex(0x123456);
//From 3 digits. Same as lv_color_hex(0x112233)
lv_color_tc=lv_color_hex3(0x123);
```
### HSV
Create colors from Hue, Saturation and Value values
```c
//h = 0..359, s = 0..100, v = 0..100
lv_color_tc=lv_color_hsv_to_rgb(h,s,v);
//All channels are 0-255
lv_color_hsv_tc_hsv=lv_color_rgb_to_hsv(r,g,b);
//From lv_color_t variable
lv_color_hsv_tc_hsv=lv_color_to_hsv(color);
```
### Palette
LVGL includes [material design's palette](https://vuetifyjs.com/en/styles/colors/#material-colors). In this all color have a main as well as four darker and five lighter variants.
The names of the colors are as follows:
-`LV_PALETTE_RED`
-`LV_PALETTE_PINK`
-`LV_PALETTE_PURPLE`
-`LV_PALETTE_DEEP_PURPLE`
-`LV_PALETTE_INDIGO`
-`LV_PALETTE_BLUE`
-`LV_PALETTE_LIGHT_BLUE`
-`LV_PALETTE_CYAN`
-`LV_PALETTE_TEAL`
-`LV_PALETTE_GREEN`
-`LV_PALETTE_LIGHT_GREEN`
-`LV_PALETTE_LIME`
-`LV_PALETTE_YELLOW`
-`LV_PALETTE_AMBER`
-`LV_PALETTE_ORANGE`
-`LV_PALETTE_DEEP_ORANGE`
-`LV_PALETTE_BROWN`
-`LV_PALETTE_BLUE_GREY`
-`LV_PALETTE_GREY`
To get the main color use `lv_color_t c = lv_palette_main(LV_PALETTE_...)`.
For the lighter variants of a palette color use `lv_color_t c = lv_palette_lighten(LV_PALETTE_..., v)`. `v` can be 1..5.
For the darker variants of a palette color use `lv_color_t c = lv_palette_darken(LV_PALETTE_..., v)`. `v` can be 1..4.
Similarly to many other parts of LVGL, the concept of setting the coordinates was inspired by CSS. By no means a complete implementation of the standard but subsets of CSS were implemented (sometimes with minor adjustments).
In shorts this means:
- the set coordinates (size, position, layouts, etc) are stored in styles
- support min-width, max-width, min-height, max-height
- have pixel, percentage, and "content" units
- x=0; y=0 coordinate means the to top-left corner of the parent plus the left/top padding plus border width
- width/height means the full size, the "content area" is smaller with padding and border width
- a subset of flexbox and grid layouts are supported
### Units
- pixel: Simply a position in pixels. A simple integer always means pixel. E.g. `lv_obj_set_x(btn, 10)`
- percentage: The percentage of the size of the object or its parent (depending on the property). The `lv_pct(value)` converts a value to percentage. E.g. `lv_obj_set_width(btn, lv_pct(50))`
-`LV_SIZE_CONTENT`: Special value to set the width/height of an object to involve all the children. Its similar to `auto` in CSS. E.g. `lv_obj_set_width(btn, LV_SIZE_CONTENT)`.
An object's "box" is built from the following parts:
- bounding box: the width/height of the elements.
- border width: the width of the border.
- padding: space between the sides of the object and its children.
- content: the content area which size if the bounding box reduced by the border width and the size of the paddings.

The border is drawn inside the bounding box. Inside the border LVGL keeps "padding size" to place the children.
The outline is drawn outside of the bounding box.
### Important notes
This section describes special cases in which LVGL's behavior might be unexpected.
#### Postponed coordinate calculation
LVGL doesn't recalculate all the coordinate changes immediately. This is done to improve performance.
Instead, the objects are marked as "dirty" and before redrawing the screen LVGL checks if there are any "dirty" objects. If so it refreshes their position, size and layout.
In other words, if you need to get the any coordinate of an object and it the coordinates were just changed LVGL's needs to be forced to recalculate the coordinates.
To do this call `lv_obj_update_layout(obj)`.
The size and position might depend on the parent or layout. Therefore `lv_obj_update_layout` recalculates the coordinates of all objects on the screen of `obj`.
#### Removing styles
As it's described in the [Using styles](#using-styles) section the coordinates can be set via style properties too.
To be more precise under the hood every style coordinate related property is stored as style a property. If you use `lv_obj_set_x(obj, 20)` LVGL saves `x=20` in the local style of the object.
It's an internal mechanism and doesn't matter much as you use LVGL. However, there is one case in which you need to aware of that. If the style(s) of an object are removed by
```c
lv_obj_remove_style_all(obj)
```
or
```c
lv_obj_remove_style(obj,NULL,LV_PART_MAIN);
```
the earlier set coordinates will be removed as well.
For example:
```c
/*The size of obj1 will be set back to the default in the end*/
lv_obj_set_size(obj1,200,100);/*Now obj1 has 200;100 size*/
lv_obj_remove_style_all(obj1);/*It removes the set sizes*/
/*obj2 will have 200;100 size in the end */
lv_obj_remove_style_all(obj2);
lv_obj_set_size(obj2,200,100);
```
## Position
### Simple way
To simple set the x and y coordinates of an object use
```c
lv_obj_set_x(obj,10);
lv_obj_set_y(obj,20);
lv_obj_set_pos(obj,10,20);//Or in one function
```
By default the the x and y coordinates are measured from the top left corner of the parent's content area.
For example if the parent has 5 pixels padding on every side, the above code will place `obj` at (15, 25) because the content area starts after the padding.
If percentage values are calculated from the parents content area size.
```c
lv_obj_set_x(btn,lv_pct(10));//x = 10 % of parant content area width
```
### Align
In some cases it's convenient to change the origin of the positioning from the the default top left. If the origin is changed e.g. to bottom-right, the (0,0) position means: align to the bottom-right corner.
To change the origin use:
```c
lv_obj_set_align(obj,align);
```
Tochangethealignmentandsetnewcoordinates:
```c
lv_obj_align(obj,align,x,y);
```
The following alignment options can be used:
-`LV_ALIGN_TOP_LEFT`
-`LV_ALIGN_TOP_MID`
-`LV_ALIGN_TOP_RIGHT`
-`LV_ALIGN_BOTTOM_LEFT`
-`LV_ALIGN_BOTTOM_MID`
-`LV_ALIGN_BOTTOM_RIGHT`
-`LV_ALIGN_LEFT_MID`
-`LV_ALIGN_RIGHT_MID`
-`LV_ALIGN_CENTER`
It quite common to align a children to the center of its parent, there fore is a dedicated function for it:
```c
lv_obj_center(obj);
//Has the same effect
lv_obj_align(obj,LV_ALIGN_CENTER,0,0);
```
If the parent's size changes the set alignment and position of the children is applied again automatically.
The functions introduced above aligns the object to its parent. However it's also possible to align an object to an arbitrary object.
Note that - unlike with `lv_obj_align()` - `lv_obj_align_to()` can not realign the object if its coordinates or the reference object's coordinates changes.
## Size
### Simple way
The width and the height of an object can be set easily as well:
```c
lv_obj_set_width(obj,200);
lv_obj_set_height(obj,100);
lv_obj_set_size(obj,200,100);//Or in one function
```
Percentage values are calculated based on the parent's content area size. For example to set the object's height to the screen height:
Under the hood the position, size and alignment properties are style properties.
The above described "simple functions" hide the style related code for the sake of simplicity and set the position, size, and alignment properties in the local styles of the obejct.
However, using styles as to set the coordinates has some great advantages:
- It makes it easy to set the width/height/etc for several objects together. E.g. make all the sliders 100x10 pixels sized.
- It also makes possible to modify the values in one place.
- The values can be overwritten by other styles. For example `style_btn` makes the object `100x50` by default but adding `style_full_width` overwrites only the width of the object.
- The object can have different position or size in different state. E.g. 100 px wide in `LV_STATE_DEFAULT` but 120 px in `LV_STATE_PRESSED`.
- Style transitions can be used to make the coordinate changes smooth.
Here are some examples to set an object's size using a style:
```c
staticlv_style_tstyle;
lv_style_init(&style);
lv_style_set_width(&style,100);
lv_obj_t*btn=lv_btn_create(lv_scr_act());
lv_obj_add_style(btn,&style,LV_PART_MAIN);
```
As you will see below there are some other great features of size and position setting.
However, to keep the LVGL's API lean only the most common coordinate setting features have a "simple" version and the more complex features can be used via styles.
## Translation
Let's say the there are 3 buttons next to each other. Their position is set as described above.
Now you want to move a buttons up a little when it's pressed.
One way to achieve this is setting a new Y coordinate for pressed state:
It works but it's not really flexible because the pressed coordinate is hard-coded. If the buttons are not at y=100 `style_pressed` won't work as expected. To solve this translations can be used:
Translation is applied from the current position of the object.
Percentage values can be used in translations as well. The percentage is relative to the size of the object (and not to the size of the parent). For example `lv_pct(50)` will move the object with half of its width/height.
The translation is applied after the layouts are calculated. Therefore, even the layouted objects' position can be translated.
The translation actually moves the object. It means it makes the scrollbars and `LV_SIZE_CONTENT` sized objects react to the position change.
## Transformation
Similarly to the position the size can be changed relative to the current size as well.
The transformed width and height are added on both sides of the object. This means 10 px transformed width makes the object 2x10 pixel wider.
Unlike position translation, the size transformation doesn't make the object "really" larger. In other words scrollbars, layouts, `LV_SIZE_CONTENT` will not consider the transformed size.
Hence size transformation if "only" a visual effect.
This code makes the a button larger when it's pressed:
Similarly to CSS, LVGL also support `min-width`, `max-width`, `min-height` and `max-height`. These are limits preventing an object's size to be smaller/larger then these values.
They are especially useful if the size is set by percentage or `LV_SIZE_CONTENT`.
```c
staticlv_style_tstyle_max_height;
lv_style_init(&style_max_height);
lv_style_set_y(&style_max_height,200);
lv_obj_set_height(obj,lv_pct(100));
lv_obj_add_style(obj,&style_max_height,LV_STATE_DEFAULT);//Limit the height to 200 px
```
Percentage values can be used as well which are relative to the size of the parent's content area size.
```c
staticlv_style_tstyle_max_height;
lv_style_init(&style_max_height);
lv_style_set_y(&style_max_height,lv_pct(50));
lv_obj_set_height(obj,lv_pct(100));
lv_obj_add_style(obj,&style_max_height,LV_STATE_DEFAULT);//Limit the height to half parent height
```
## Layout
### Overview
Layouts can update the position and size of an object's children. They can be used to automatically arrange the children into a line or column, or in much more complicated forms.
The position and size set by the layout overwrites the "normal" x, y, width, and height settings.
There is only one function that is the same for every layout: `lv_obj_set_layout(obj, <LAYOUT_NAME>)` sets the layout on an object.
For the further settings of the parent and children see the documentations of the given layout.
### Built-in layout
LVGL comes with two very powerful layouts:
- Flexbox
- Grid
Both are heavily inspired by the CSS layouts with the same name.
### Flags
There are some flags that can be used on object to affect how they behave with layouts:
-`LV_OBJ_FLAG_HIDDEN` Hidden object are ignored from layout calculations.
-`LV_OBJ_FLAG_IGNORE_LAYOUT` The object is simply ignored by the layouts. Its coordinates can be set as usual.
-`LV_OBJ_FLAG_FLOATING` Same as `LV_OBJ_FLAG_IGNORE_LAYOUT` but the object with `LV_OBJ_FLAG_FLOATING` will be ignored from `LV_SIZE_CONTENT` calculations.
These flags can be added/removed with `lv_obj_add/clear_flag(obj, FLAG);`
### Adding new layouts
LVGL can be freely extended by a custom layouts like this:
``` important:: The basic concept of *display* in LVGL is explained in the [Porting](/porting/display) section. So before reading further, please read the [Porting](/porting/display) section first.
```
## Multiple display support
In LVGL, you can have multiple displays, each with their own driver and objects. The only limitation is that every display needs to be have same color depth (as defined in `LV_COLOR_DEPTH`).
If the displays are different in this regard the rendered image can be converted to the correct format in the drivers `flush_cb`.
Creating more displays is easy: just initialize more display buffers and register another driver for every display.
When you create the UI, use `lv_disp_set_default(disp)` to tell the library on which display to create objects.
Why would you want multi-display support? Here are some examples:
- Have a "normal" TFT display with local UI and create "virtual" screens on VNC on demand. (You need to add your VNC driver).
- Have a large TFT display and a small monochrome display.
- Have some smaller and simple displays in a large instrument or technology.
- Have two large TFT displays: one for a customer and one for the shop assistant.
### Using only one display
Using more displays can be useful but in most cases it's not required. Therefore, the whole concept of multi-display is completely hidden if you register only one display.
By default, the lastly created (and only) display is used.
`lv_scr_act()`, `lv_scr_load(scr)`, `lv_layer_top()`, `lv_layer_sys()`, `LV_HOR_RES` and `LV_VER_RES` are always applied on the most recently created (default) screen.
If you pass `NULL` as `disp` parameter to display related function, usually the default display will be used.
E.g. `lv_disp_trig_activity(NULL)` will trigger a user activity on the default screen. (See below in [Inactivity](#Inactivity)).
### Mirror display
To mirror the image of the display to another display, you don't need to use the multi-display support. Just transfer the buffer received in `drv.flush_cb` to the other display too.
### Split image
You can create a larger display from smaller ones. You can create it as below:
1. Set the resolution of the displays to the large display's resolution.
2. In `drv.flush_cb`, truncate and modify the `area` parameter for each display.
3. Send the buffer's content to each display with the truncated area.
## Screens
Every display has each set of [Screens](overview/object#screen-the-most-basic-parent) and the object on the screens.
Be sure not to confuse displays and screens:
* **Displays** are the physical hardware drawing the pixels.
* **Screens** are the high-level root objects associated with a particular display. One display can have multiple screens associated with it, but not vice versa.
Screens can be considered the highest level containers which have no parent.
The screen's size is always equal to its display and size their position is (0;0). Therefore, the screens coordinates can't be changed, i.e. `lv_obj_set_pos()`, `lv_obj_set_size()` or similar functions can't be used on screens.
A screen can be created from any object type but the two most typical types are the [Base object](/widgets/obj) and the [Image](/widgets/core/img) (to create a wallpaper).
To create a screen, use `lv_obj_t * scr = lv_<type>_create(NULL, copy)`. `copy` can be an other screen to copy it.
To load a screen, use `lv_scr_load(scr)`. To get the active screen, use `lv_scr_act()`. These functions works on the default display. If you want to to specify which display to work on, use `lv_disp_get_scr_act(disp)` and `lv_disp_load_scr(disp, scr)`. Screen can be loaded with animations too. Read more [here](object.html#load-screens).
Screens can be deleted with `lv_obj_del(scr)`, but ensure that you do not delete the currently loaded screen.
### Transparent screens
Usually, the opacity of the screen is `LV_OPA_COVER` to provide a solid background for its children. If it's not the case (opacity < 100%) the display's background color or image will be visible.
See the [Display background](#display-background) section for more details. If the display's background opacity is also not `LV_OPA_COVER` LVGL has no solid background to draw.
This configuration (transparent screen and display) could be used to create for example OSD menus where a video is played on a lower layer, and a menu is overlayed on an upper layer.
To handle transparent displays special (slower) color mixing algorithms need to be used by LVGL so this feature needs to enabled with `LV_COLOR_SCREEN_TRANSP` in `lv_conf.h`.
As this mode operates on the Alpha channel of the pixels `LV_COLOR_DEPTH = 32` is also required. The Alpha channel of 32-bit colors will be 0 where there are no objects and 255 where there are solid objects.
In summary, to enable transparent screen and displays to create OSD menu-like UIs:
- Enable `LV_COLOR_SCREEN_TRANSP` in `lv_conf.h`
- Be sure to use `LV_COLOR_DEPTH 32`
- Set the screens opacity to `LV_OPA_TRANSP` e.g. with `lv_obj_set_style_local_bg_opa(lv_scr_act(), LV_OBJMASK_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP)`
- Set the display opacity to `LV_OPA_TRANSP` with `lv_disp_set_bg_opa(NULL, LV_OPA_TRANSP);`
## Features of displays
### Inactivity
The user's inactivity is measured on each display. Every use of an [Input device](/overview/indev) (if [associated with the display](/porting/indev#other-features)) counts as an activity.
To get time elapsed since the last activity, use `lv_disp_get_inactive_time(disp)`. If `NULL` is passed, the overall smallest inactivity time will be returned from all displays (**not the default display**).
You can manually trigger an activity using `lv_disp_trig_activity(disp)`. If `disp` is `NULL`, the default screen will be used (**and not all displays**).
### Background
Every display has background color, a background image and background opacity properties. They become visible when the current screen is transparent or not positioned to cover the whole display.
Background color is a simple color to fill the display. It can be adjusted with `lv_disp_set_bg_color(disp, color)`;
Background image is a path to a file or a pointer to an `lv_img_dsc_t` variable (converted image) to be used as wallpaper. It can be set with `lv_disp_set_bg_color(disp, &my_img)`;
If the background image is set (not `NULL`) the background won't be filled with `bg_color`.
The opacity of the background color or image can be adjusted with `lv_disp_set_bg_opa(disp, opa)`.
The `disp` parameter of these functions can be `NULL` to refer it to the default display.
With LVGL, you don't need to draw anything manually. Just create objects (like buttons, labels, arc, etc), move and change them, and LVGL will refresh and redraw what is required.
However, it might be useful to have a basic understanding of how drawing happens in LVGL to add customization, make it easier to find bugs or just out of curiosity.
The basic concept is to not draw directly to the screen, but draw to an internal draw buffer first. When drawing (rendering) is ready, that buffer is copied to the screen.
The draw buffer can be smaller than the screen's size. LVGL will simply render in "tiles" that fit into the given draw buffer.
This approach has two main advantages compared to directly drawing to the screen:
1. It avoids flickering while the layers of the UI are drawn. For example, if LVGL drawn directly into the display, when drawing a *background + button + text*, each "stage" would be visible for a short time .
2. It's faster to modify a buffer in internal RAM and finally write one pixel only once than reading/writing the display directly on each pixel access.
(e.g. via a display controller with SPI interface).
Note that this concept is different from "traditional" double buffering where there are 2 screen sized frame buffers:
one holds the current image to show on the display, and rendering happens to the other (inactive) frame buffer, and they are swapped when the rendering is finished.
The main difference is that with LVGL you don't have to store 2 frame buffers (which usually requires external RAM) but only smaller draw buffer(s) that can easily fit into the internal RAM too.
## Mechanism of screen refreshing
Be sure to get familiar with the [Buffering modes of LVGL](/porting/display) first.
LVGL refreshes the screen in the following steps:
1. Something happens on the UI which requires redrawing. For example, a button is pressed, a chart is changed, an animation happened, etc.
2. LVGL saves the changed object's old and new area into a buffer, called an *Invalid area buffer*. For optimization, in some cases, objects are not added to the buffer:
- Hidden objects are not added.
- Objects completely out of their parent are not added.
- Areas partially out of the parent are cropped to the parent's area.
- The objects on other screens are not added.
3. In every `LV_DISP_DEF_REFR_PERIOD` (set in `lv_conf.h`) the followings happen:
- LVGL checks the invalid areas and joins the adjacent or intersecting areas.
- Takes the first joined area, if it's smaller than the *draw buffer*, then simply render the area's content into the *draw buffer*.
If the area doesn't fit into the buffer, draw as many lines as possible to the *draw buffer*.
- When the area is rendered, call `flush_cb` from the display driver to refresh the display.
- If the area was larger than the buffer, render the remaining parts too.
- Do the same with all the joined areas.
When an area is redrawn, the library searches the top most object which covers that area, and starts drawing from that object.
For example, if a button's label has changed, the library will see that it's enough to draw the button under the text, and that it's not required to draw the screen under the button too.
The difference between buffering modes regarding the drawing mechanism is the following:
1.**One buffer** - LVGL needs to wait for `lv_disp_flush_ready()` (called from `flush_cb`) before starting to redraw the next part.
2.**Two buffers** - LVGL can immediately draw to the second buffer when the first is sent to `flush_cb` because the flushing should be done by DMA (or similar hardware) in the background.
3.**Double buffering** - `flush_cb` should only swap the address of the frame buffer.
## Masking
*Masking* is the basic concept of LVGL's draw engine.
To use LVGL it's not required to know about the mechanisms described here, but you might find interesting to know how drawing works under hood.
Knowing about masking comes in handy if you want to customize drawing.
To learn masking let's learn the steps of drawing first.
LVGL performs the following steps to render any shape, image or text. It can be considered as a drawing pipeline.
1.**Prepare the draw descriptors** Create a draw descriptor from an object's styles (e.g. `lv_draw_rect_dsc_t`). This gives us the parameters for drawing, for example the colors, widths, opacity, fonts, radius, etc.
2.**Call the draw function** Call the draw function with the draw descriptor and some other parameters (e.g. `lv_draw_rect()`). It renders the primitive shape to the current draw buffer.
3.**Create masks** If the shape is very simple and doesn't require masks go to #5. Else create the required masks (e.g. a rounded rectangle mask)
4.**Calculate all the added mask**. It creates 0..255 values into a *mask buffer* with the "shape" of the created masks.
E.g. in case of a "line mask" according to the parameters of the mask, keep one side of the buffer as it is (255 by default) and set the rest to 0 to indicate that this side should be removed.
5.**Blend a color or image** During blending masks (make some pixels transparent or opaque), blending modes (additive, subtractive, etc) and opacity are handled.
LVGL has the following built-in mask types which can be calculated and applied real-time:
-`LV_DRAW_MASK_TYPE_LINE` Removes a side from a line (top, bottom, left or right). `lv_draw_line` uses 4 of it.
Essentially, every (skew) line is bounded with 4 line masks by forming a rectangle.
-`LV_DRAW_MASK_TYPE_RADIUS` Removes the inner or outer parts of a rectangle which can have radius. It's also used to create circles by setting the radius to large value (`LV_RADIUS_CIRCLE`)
-`LV_DRAW_MASK_TYPE_ANGLE` Removes a circle sector. It is used by `lv_draw_arc` to remove the "empty" sector.
-`LV_DRAW_MASK_TYPE_FADE` Create a vertical fade (change opacity)
-`LV_DRAW_MASK_TYPE_MAP` The mask is stored in an array and the necessary parts are applied
Masks are used the create almost every basic primitives:
- **letters** Create a mask from the letter and draw a rectangle with the letter's color considering the mask.
- **line** Created from 4 "line masks", to mask out the left, right, top and bottom part of the line to get perfectly perpendicular line ending.
- **rounded rectangle** A mask is created real-time to add radius to the corners.
- **clip corner** To clip to overflowing content (usually children) on the rounded corners also a rounded rectangle mask is applied.
- **rectangle border** Same as a rounded rectangle, but inner part is masked out too.
- **arc drawing** A circle border is drawn, but an arc mask is applied too.
- **ARGB images** The alpha channel is separated into a mask and the image is drawn as a normal RGB image.
## Hook drawing
Although widgets can be very well customized by styles there might be cases when something really custom is required.
To ensure a great level of flexibility LVGL sends a lot events during drawing with parameters that tell what LVGL is about to draw.
Some fields of these parameters can be modified to draw something else or any custom drawing can be added manually.
A good use case for it is the [Button matrix](/widgets/core/btnmatrix) widget. By default its buttons can be styled in different states but you can't style the buttons one by one.
However, an event is sent for every button and you can for example tell LVGL to use different colors on a specific button or to manually draw an image on some buttons.
Below each of these events are described in detail.
### Main drawing
These events are related to the actual drawing of the object. E.g. drawing of buttons, texts, etc happens here.
`lv_event_get_clip_area(event)` can be used to get the current clip area. The clip area is required in draw functions to make them draw only on a limited area.
#### LV_EVENT_DRAW_MAIN_BEGIN
Sent before starting to draw an object. This is a good place to add masks manually. E.g. add a line mask that "removes" the right side of an object.
#### LV_EVENT_DRAW_MAIN
The actual drawing of the object happens in this event. E.g. a rectangle for a button is drawn here. First, the widgets' internal events are called to perform drawing and after that you can draw anything on top of them.
For example you can add a custom text or an image.
#### LV_EVENT_DRAW_MAIN_END
Called when the main drawing is finished. You can draw anything here as well and it's also good place to remove the masks created in `LV_EVENT_DRAW_MAIN_BEGIN`.
### Post drawing
Post drawing events are called when all the children of an object are drawn. For example LVGL use the post drawing phase to draw the scrollbars because they should be above all the children.
`lv_event_get_clip_area(event)` can be used to get the current clip area.
#### LV_EVENT_DRAW_POST_BEGIN
Sent before starting the post draw phase. Masks can be added here too to mask out the post drawn content.
#### LV_EVENT_DRAW_POST
The actual drawing should happen here.
#### LV_EVENT_DRAW_POST_END
Called when post drawing has finished. If the masks were not removed in `LV_EVENT_DRAW_MAIN_END` they should be removed here.
### Part drawing
When LVGL draws a part of an object (e.g. a slider's indicator, a table's cell or a button matrix's button) it sends events before and after drawing that part with some context of the drawing.
It allows changing the parts on a very low level with masks, extra drawing, or changing the parameters that LVGL is planning to use for drawing.
In these events an `lv_obj_draw_part_t` structure is used to describe the context of the drawing. Not all fields are set for every part and widget.
To see which fields are set for a widget see the widget's documentation.
`lv_obj_draw_part_t` has the following fields:
```c
// Always set
constlv_area_t*clip_area;// The current clip area, required if you need to draw something in the event
uint32_tpart;// The current part for which the event is sent
uint32_tid;// The index of the part. E.g. a button's index on button matrix or table cell index.
// Draw desciptors, set only if related
lv_draw_rect_dsc_t*rect_dsc;// A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts
lv_draw_label_dsc_t*label_dsc;// A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts
lv_draw_line_dsc_t*line_dsc;// A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts
lv_draw_img_dsc_t*img_dsc;// A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts
lv_draw_arc_dsc_t*arc_dsc;// A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts
// Other paramters
lv_area_t*draw_area;// The area of the part being drawn
constlv_point_t*p1;// A point calculated during drawing. E.g. a point of chart or the center of an arc.
constlv_point_t*p2;// A point calculated during drawing. E.g. a point of chart.
chartext[16];// A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.
lv_coord_tradius;// E.g. the radius of an arc (not the corner radius).
int32_tvalue;// A value calculated during drawing. E.g. Chart's tick line value.
constvoid*sub_part_ptr;// A pointer the identifies something in the part. E.g. chart series.
```
`lv_event_get_draw_part_dsc(event)` can be used to get a pointer to `lv_obj_draw_part_t`.
#### LV_EVENT_DRAW_PART_BEGIN
Start the drawing of a part. This is a good place to modify the draw descriptors (e.g. `rect_dsc`), or add masks.
#### LV_EVENT_DRAW_PART_END
Finish the drawing of a part. This is a good place to draw extra content on the part, or remove the masks added in `LV_EVENT_DRAW_PART_BEGIN`.
### Others
#### LV_EVENT_COVER_CHECK
This event is used to check whether an object fully covers an area or not.
`lv_event_get_cover_area(event)` returns an pointer to an area to check and `lv_event_set_cover_res(event, res)` can be used to set one of these results:
-`LV_COVER_RES_COVER` the areas is fully covered by the object
-`LV_COVER_RES_NOT_COVER` the areas is not covered by the object
-`LV_COVER_RES_MASKED` there is a mask on the object so it can not cover the area
Here are some reasons why an object would be unable to fully cover an area:
- It's simply not fully in area
- It has a radius
- It has not 100% background opacity
- It's an ARGB or chroma keyed image
- It does not have normal blending mode. In this case LVGL needs to know the colors under the object to do the blending properly
- It's a text, etc
In short if for any reason the area below the object is visible than it doesn't cover that area.
Before sending this event LVGL checks if at least the widget's coordinates fully cover the area or not. If not the event is not called.
You need to check only the drawing you have added. The existing properties known by widget are handled in the widget's internal events.
E.g. if a widget has > 0 radius it might not cover an area but you need to handle `radius` only if you will modify it and the widget can't know about it.
#### LV_EVENT_REFR_EXT_DRAW_SIZE
If you need to draw outside of a widget LVGL needs to know about it to provide the extra space for drawing.
Let's say you create an event the writes the current value of a slider above its knob. In this case LVGL needs to know that the slider's draw area should be larger with the size required for the text.
You can simple set the required draw area with `lv_event_set_ext_draw_size(e, size)`.
Events are triggered in LVGL when something happens which might be interesting to the user, e.g. when an object
- is clicked
- is scrolled
- has its value changed
- is redrawn, etc.
## Add events to the object
The user can assign callback functions to an object to see its events. In practice, it looks like this:
```c
lv_obj_t*btn=lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(btn,my_event_cb,LV_EVENT_CLICKED,NULL);/*Assign an event callback*/
...
staticvoidmy_event_cb(lv_event_t*event)
{
printf("Clicked\n");
}
```
In the example `LV_EVENT_CLICKED` means that only the click event will call `my_event_cb`. See the [list of event codes](#event-codes) for all the options.
`LV_EVENT_ALL` can be used to receive all the events.
The last parameter of `lv_obj_add_event_cb` is a pointer to any custom data that will be available in the event. It will be described later in more detail.
The events will be called in the order as they were added.
More objects can use the same *event callback*.
## Remove event(s) from an object
Events can be removed from an object with the `lv_obj_remove_event_cb(obj, event_cb)` function or `lv_obj_remove_event_dsc(obj, event_dsc)`. `event_dsc` is a pointer returned by `lv_obj_add_event_cb`.
## Event codes
The event codes can be grouped into these categories:
- Input device events
- Drawing events
- Other events
- Special events
- Custom events
All objects (such as Buttons/Labels/Sliders etc.) regardless their type receive the *Input device*, *Drawing* and *Other* events.
However the *Special events* are specific to a particular widget type. See the [widgets' documentation](/widgets/index) to learn when they are sent,
*Custom events* are added by the user and therefore these are never sent by LVGL.
The following event codes exist:
### Input device events
-`LV_EVENT_PRESSED` The object has been pressed
-`LV_EVENT_PRESSING` The object is being pressed (called continuously while pressing)
-`LV_EVENT_PRESS_LOST` The object is still being pressed but slid cursor/finger off of the object
-`LV_EVENT_SHORT_CLICKED` The object was pressed for a short period of time, then released it. Not called if scrolled.
-`LV_EVENT_LONG_PRESSED` Object has been pressed for at least the `long_press_time` specified in the input device driver. Not called if scrolled.
-`LV_EVENT_LONG_PRESSED_REPEAT` Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.
-`LV_EVENT_CLICKED` Called on release if the object did not scroll (regardless of long press)
-`LV_EVENT_RELEASED` Called in every case when the object has been released
-`LV_EVENT_SCROLL_BEGIN` Scrolling begins. The event paramter is `NULL` or an `lv_anim_t *` with the scroll animation descriptor to modify if required.
-`LV_EVENT_SCROLL_END` Scrolling ends.
-`LV_EVENT_SCROLL` The object was scrolled
-`LV_EVENT_GESTURE` A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());`
-`LV_EVENT_KEY` A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`
-`LV_EVENT_FOCUSED` The object is focused
-`LV_EVENT_DEFOCUSED` The object is defocused
-`LV_EVENT_LEAVE` The object is defocused but still selected
-`LV_EVENT_HIT_TEST` Perform advanced hit-testing. Use `lv_hit_test_info_t * a = lv_event_get_hit_test_info(e)` and check if `a->point` can click the object or not. If not set `a->res = false`
### Drawing events
-`LV_EVENT_COVER_CHECK` Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.
-`LV_EVENT_REFR_EXT_DRAW_SIZE` Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size. Overwrite it only with a larger value.
-`LV_EVENT_DRAW_MAIN_BEGIN` Starting the main drawing phase.
-`LV_EVENT_DRAW_MAIN` Perform the main drawing
-`LV_EVENT_DRAW_MAIN_END` Finishing the main drawing phase
-`LV_EVENT_DRAW_POST_BEGIN` Starting the post draw phase (when all children are drawn)
-`LV_EVENT_DRAW_POST` Perform the post draw phase (when all children are drawn)
-`LV_EVENT_DRAW_POST_END` Finishing the post draw phase (when all children are drawn)
-`LV_EVENT_DRAW_PART_BEGIN` Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. Learn more [here](/overview/drawing).
-`LV_EVENT_DRAW_PART_END` Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. Learn more [here](/overview/drawing).
### Other events
-`LV_EVENT_DELETE` Object is being deleted
-`LV_EVENT_CHILD_CHANGED` Child was removed/added
-`LV_EVENT_SIZE_CHANGED` Object coordinates/size have changed
-`LV_EVENT_STYLE_CHANGED` Object's style has changed
-`LV_EVENT_BASE_DIR_CHANGED` The base dir has changed
-`LV_EVENT_GET_SELF_SIZE` Get the internal size of a widget
### Special events
-`LV_EVENT_VALUE_CHANGED` The object's value has changed (i.e. slider moved)
-`LV_EVENT_INSERT` A text is being inserted to the object. The event data is `char *` being inserted.
-`LV_EVENT_REFRESH` Notify the object to refresh something on it (for the user)
-`LV_EVENT_READY` A process has finished
-`LV_EVENT_CANCEL` A process has been canceled
### Custom events
Any custom event codes can be registered by `uint32_t MY_EVENT_1 = lv_event_register_id();`
And can be sent to any object with `lv_event_send(obj, MY_EVENT_1, &some_data)`
## Sending events
To manually send events to an object, use `lv_event_send(obj, <EVENT_CODE> &some_data)`.
For example, this can be used to manually close a message box by simulating a button press (although there are simpler ways to do this):
```c
/*Simulate the press of the first button (indexes start from zero)*/
`LV_EVENT_REFRESH` is special event because it's designed to be used by the user to notify an object to refresh itself. Some examples:
- notify a label to refresh its text according to one or more variables (e.g. current time)
- refresh a label when the language changes
- enable a button if some conditions are met (e.g. the correct PIN is entered)
- add/remove styles to/from an object if a limit is exceeded, etc
## Fields of lv_event_t
`lv_event_t` is the only parameter passed to event callback and it contains all the data about the event. The following values can be gotten from it:
-`lv_event_get_code(e)` get the event code
-`lv_event_get_target(e)` get the object to which the event is sent
-`lv_event_get_original_target(e)` get the object to which the event is sent originally sent (different from `lv_event_get_target` if [event bubbling](#event-bubbling) is enabled)
-`lv_event_get_user_data(e)` get the pointer passed as the last parameter of `lv_obj_add_event_cb`.
-`lv_event_get_param(e)` get the parameter passed as the last parameter of `lv_event_send`
## Event bubbling
If `lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE)` is enabled all events will be sent to the object's parent too. If the parent also has `LV_OBJ_FLAG_EVENT_BUBBLE` enabled the event will be sent to its parent too, and so on.
The *target* parameter of the event is always the current target object, not the original object. To get the original target call `lv_event_get_original_target(e)` in the event handler.
LVGL has a 'File system' abstraction module that enables you to attach any type of file system.
The file system is identified by a drive letter.
For example, if the SD card is associated with the letter `'S'`, a file can be reached like `"S:path/to/file.txt"`.
## Ready to use drivers
The [lv_fs_if](https://github.com/lvgl/lv_fs_if) repository contains ready to use drivers using POSIX, standard C and [FATFS](http://elm-chan.org/fsw/ff/00index_e.html) API.
See it's [README](https://github.com/lvgl/lv_fs_if#readme) for the details.
## Add a driver
### Registering a driver
To add a driver, `lv_fs_drv_t` needs to be initialized like below. `lv_fs_drv_t` needs to be static, global or dynamically allocated and not a local varaible.
```c
staticlv_fs_drv_tdrv;/*Needs to be static or global*/
lv_fs_drv_init(&drv);/*Basic initialization*/
drv.letter='S';/*An uppercase letter to identify the drive */
drv.ready_cb=my_ready_cb;/*Callback to tell if the drive is ready to use */
drv.open_cb=my_open_cb;/*Callback to open a file */
drv.close_cb=my_close_cb;/*Callback to close a file */
drv.read_cb=my_read_cb;/*Callback to read a file */
drv.write_cb=my_write_cb;/*Callback to write a file */
drv.seek_cb=my_seek_cb;/*Callback to seek in a file (Move cursor) */
drv.tell_cb=my_tell_cb;/*Callback to tell the cursor position */
drv.dir_open_cb=my_dir_open_cb;/*Callback to open directory to read its content */
drv.dir_read_cb=my_dir_read_cb;/*Callback to read a directory's content */
drv.dir_close_cb=my_dir_close_cb;/*Callback to close a directory */
drv.user_data=my_user_data;/*Any custom data if required*/
lv_fs_drv_register(&drv);/*Finally register the drive*/
```
Any of the callbacks can be `NULL` to indicate that operation is not supported.
`path` is path after the driver letter (e.g. "S:path/to/file.txt" -> "path/to/file.txt"). `mode` can be `LV_FS_MODE_WR` or `LV_FS_MODE_RD` to open for write or read.
The return value is a pointer the *file object* the describes the opened file or `NULL` if there were any issues (e.g. the file wasn't found).
The returned file object will be passed to to other file system related callbacks. (see below)
### Other callbacks
The other callbacks are quite similar. For example `write_cb` looks like this:
*The mode in `lv_fs_open` can be `LV_FS_MODE_WR` to open for write or `LV_FS_MODE_RD | LV_FS_MODE_WR` for both*
This example shows how to read a directory's content. It's up to the driver how to mark the directories, but it can be a good practice to insert a `'/'` in front of the directory name.
```c
lv_fs_dir_tdir;
lv_fs_res_tres;
res=lv_fs_dir_open(&dir,"S:/folder");
if(res!=LV_FS_RES_OK)my_error_handling();
charfn[256];
while(1){
res=lv_fs_dir_read(&dir,fn);
if(res!=LV_FS_RES_OK){
my_error_handling();
break;
}
/*fn is empty, if not more files to read*/
if(strlen(fn)==0){
break;
}
printf("%s\n",fn);
}
lv_fs_dir_close(&dir);
```
## Use drivers for images
[Image](/widgets/core/img) objects can be opened from files too (besides variables stored in the flash).
To use files in image widgets the following callbacks are required:
In LVGL fonts are collections of bitmaps and other information required to render the images of the letters (glyph).
A font is stored in a `lv_font_t` variable and can be set in a style's *text_font* field. For example:
```c
lv_style_set_text_font(&my_style,LV_STATE_DEFAULT,&lv_font_montserrat_28);/*Set a larger font*/
```
The fonts have a **bpp (bits per pixel)** property. It shows how many bits are used to describe a pixel in the font. The value stored for a pixel determines the pixel's opacity.
This way, with higher *bpp*, the edges of the letter can be smoother. The possible *bpp* values are 1, 2, 4 and 8 (higher value means better quality).
The *bpp* also affects the required memory size to store the font. For example, *bpp = 4* makes the font nearly 4 times larger compared to *bpp = 1*.
Your editor needs to be configureed to save your code/text as UTF-8 (usually this the default) and be sure that, `LV_TXT_ENC` is set to `LV_TXT_ENC_UTF8` in *lv_conf.h*. (This is the default value)
If all works well, a ✓ character should be displayed.
## Built-in fonts
There are several built-in fonts in different sizes, which can be enabled in `lv_conf.h` by *LV_FONT_...* defines.
### Normal fonts
Containing all the ASCII characters, the degree symbol (U+00B0), the bullet symbol (U+2022) and the built-in symbols (see below).
-`LV_FONT_MONTSERRAT_12` 12 px font
-`LV_FONT_MONTSERRAT_14` 14 px font
-`LV_FONT_MONTSERRAT_16` 16 px font
-`LV_FONT_MONTSERRAT_18` 18 px font
-`LV_FONT_MONTSERRAT_20` 20 px font
-`LV_FONT_MONTSERRAT_22` 22 px font
-`LV_FONT_MONTSERRAT_24` 24 px font
-`LV_FONT_MONTSERRAT_26` 26 px font
-`LV_FONT_MONTSERRAT_28` 28 px font
-`LV_FONT_MONTSERRAT_30` 30 px font
-`LV_FONT_MONTSERRAT_32` 32 px font
-`LV_FONT_MONTSERRAT_34` 34 px font
-`LV_FONT_MONTSERRAT_36` 36 px font
-`LV_FONT_MONTSERRAT_38` 38 px font
-`LV_FONT_MONTSERRAT_40` 40 px font
-`LV_FONT_MONTSERRAT_42` 42 px font
-`LV_FONT_MONTSERRAT_44` 44 px font
-`LV_FONT_MONTSERRAT_46` 46 px font
-`LV_FONT_MONTSERRAT_48` 48 px font
### Special fonts
-`LV_FONT_MONTSERRAT_12_SUBPX` Same as normal 12 px font but with [subpixel rendering](#subpixel-rendering)
-`LV_FONT_MONTSERRAT_28_COMPRESSED` Same as normal 28 px font but [compressed font](#compress-fonts) with 3 bpp
-`LV_FONT_DEJAVU_16_PERSIAN_HEBREW` 16 px font with normal range + Hebrew, Arabic, Persian letters and all their forms
-`LV_FONT_SIMSUN_16_CJK`16 px font with normal range + 1000 most common CJK radicals
-`LV_FONT_UNSCII_8` 8 px pixel perfect font with only ASCII characters
-`LV_FONT_UNSCII_16` 16 px pixel perfect font with only ASCII characters
The built-in fonts are **global variables** with names like `lv_font_montserrat_16` for a 16 px hight font. To use them in a style, just add a pointer to a font variable like shown above.
The built-in fonts with *bpp = 4* contain the ASCII characters and use the [Montserrat](https://fonts.google.com/specimen/Montserrat) font.
In addition to the ASCII range, the following symbols are also added to the built-in fonts from the [FontAwesome](https://fontawesome.com/) font.
Most of the languages use Left-to-Right (LTR for short) writing direction, however some languages (such as Hebrew, Persian or Arabic) uses Right-to-Left (RTL for short) direction.
LVGL not only supports RTL texts but supports mixed (a.k.a. bidirectional, BiDi) text rendering too. Some examples:

BiDi support is enabled by `LV_USE_BIDI` in *lv_conf.h*
All texts have a base direction (LTR or RTL) which determines some rendering rules and the default alignment of the text (Left or Right).
However, in LVGL, base direction is applied not only for labels. It's a general property which can be set for every object.
If unset then it will be inherited from the parent.
So it's enough to set the base direction of the screen and every object will inherit it.
The default base direction of screen can be set by `LV_BIDI_BASE_DIR_DEF` in *lv_conf.h* and other objects inherit the base direction from their parent.
To set an object's base direction use `lv_obj_set_base_dir(obj, base_dir)`. The possible base direction are:
-`LV_BIDI_DIR_LTR`: Left to Right base direction
-`LV_BIDI_DIR_RTL`: Right to Left base direction
-`LV_BIDI_DIR_AUTO`: Auto detect base direction
-`LV_BIDI_DIR_INHERIT`: Inherit the base direction from the parent (default for non-screen objects)
This list summarizes the effect of RTL base direction on objects:
- Create objects by default on the right
-`lv_tabview`: displays tabs from right to left
-`lv_checkbox`: Show the box on the right
-`lv_btnmatrix`: Show buttons from right to left
-`lv_list`: Show the icon on the right
-`lv_dropdown`: Align the options to the right
- The texts in `lv_table`, `lv_btnmatrix`, `lv_keyboard`, `lv_tabview`, `lv_dropdown`, `lv_roller` are "BiDi processed" to be displayed correctly
### Arabic and Persian support
There are some special rules to display Arabic and Persian characters: the *form* of the character depends on their position in the text.
A different form of the same letter needs to be used if it isolated, start, middle or end position. Besides these some conjunction rules also should be taken into account.
LVGL supports to apply these rules if `LV_USE_ARABIC_PERSIAN_CHARS` is enabled.
However, there some limitations:
- Only displaying texts is supported (e.g. on labels), text inputs (e.g. text area) don't support this feature.
- Static text (i.e. const) is not processed. E.g. texts set by `lv_label_set_text()` will be "Arabic processed" but `lv_lable_set_text_static()` won't.
- Text get functions (e.g. `lv_label_get_text()`) will return the processed text.
### Subpixel rendering
Subpixel rendering allows for tripling the horizontal resolution by rendering on Red, Green and Blue channel instead of pixel level. This takes advantage of the position of physical color channels of each pixel, resulting in higher quality letter anti-aliasing. Learn more [here](https://en.wikipedia.org/wiki/Subpixel_rendering).
For subpixel rendering the fonts need to be generated with special settings:
- In the online converter tick the `Subpixel` box
- In the command line tool use `--lcd` flag. Note that the generated font needs about 3 times more memory.
Subpixel rendering works only if the color channels of the pixels have a horizontal layout. That is the R, G, B channels are next each other and not above each other.
The order of color channels also needs to match with the library settings. By default LVGL assumes `RGB` order, however this can be swapped by setting `LV_SUBPX_BGR 1` in *lv_conf.h*.
### Compress fonts
The bitmaps of the fonts can be compressed by
- ticking the `Compressed` check box in the online converter
- not passing `--no-compress` flag to the offline converter (compression is applied by default)
The compression is more effective with larger fonts and higher bpp. However, it's about 30% slower to render the compressed fonts.
Therefore it's recommended to compress only the largest fonts of user interface, because
- they need the most memory
- they can be compressed better
- and probably they are used less frequently then the medium sized fonts, so the performance cost is smaller.
## Add new font
There are several ways to add a new font to your project:
1. The simplest method is to use the [Online font converter](https://lvgl.io/tools/fontconverter). Just set the parameters, click the *Convert* button, copy the font to your project and use it. **Be sure to carefully read the steps provided on that site or you will get an error while converting.**
2. Use the [Offline font converter](https://github.com/lvgl/lv_font_conv). (Requires Node.js to be installed)
3. If you want to create something like the built-in fonts (Roboto font and symbols) but in different size and/or ranges, you can use the `built_in_font_gen.py` script in `lvgl/scripts/built_in_font` folder.
(This requires Python and `lv_font_conv` to be installed)
To declare the font in a file, use `LV_FONT_DECLARE(my_font_name)`.
To make the fonts globally available (like the builtin fonts), add them to `LV_FONT_CUSTOM_DECLARE` in *lv_conf.h*.
## Add new symbols
The built-in symbols are created from the [FontAwesome](https://fontawesome.com/) font.
1. Search symbol on [https://fontawesome.com](https://fontawesome.com). For example the [USB symbol](https://fontawesome.com/icons/usb?style=brands). Copy it's Unicode ID which is `0xf287` in this case.
2. Open the [Online font converter](https://lvgl.io/tools/fontconverter). Add Add [FontAwesome.woff](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff). .
3. Set the parameters such as Name, Size, BPP. You'll use this name to declare and use the font in your code.
4. Add the Unicode ID of the symbol to the range field. E.g.` 0xf287` for the USB symbol. More symbols can be enumerated with `,`.
5. Convert the font and copy it to your project. Make sure to compile the .c file of your font.
6. Declare the font using `extern lv_font_t my_font_name;` or simply `LV_FONT_DECLARE(my_font_name);`.
**Using the symbol**
1. Convert the Unicode value to UTF8, for example on [this site](http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=f287&mode=hex). For `0xf287` the *Hex UTF-8 bytes* are `EF 8A 87`.
2. Create a `define` from the UTF8 values: `#define MY_USB_SYMBOL "\xEF\x8A\x87"`
3. Create a label and set the text. Eg. `lv_label_set_text(label, MY_USB_SYMBOL)`
Note - `lv_label_set_text(label, MY_USB_SYMBOL)` searches for this symbol in the font defined in `style.text.font` properties. To use the symbol you may need to change it. Eg ` style.text.font = my_font_name`
## Load font at run-time
`lv_font_load` can be used to load a font from a file. The font to load needs to have a special binary format. (Not TTF or WOFF).
Use [lv_font_conv](https://github.com/lvgl/lv_font_conv/) with `--format bin` option to generate an LVGL compatible font file.
Note that to load a font [LVGL's filesystem](/overview/file-system) needs to be enabled and a driver needs to be added.
Example
```c
lv_font_t*my_font;
my_font=lv_font_load(X/path/to/my_font.bin);
/*Use the font*/
/*Free the font if not required anymore*/
lv_font_free(my_font);
```
## Add a new font engine
LVGL's font interface is designed to be very flexible.
But even so you don't need to use LVGL's internal font engine: you can add your own.
For example, use [FreeType](https://www.freetype.org/) to real-time render glyphs from TTF fonts or use an external flash to store the font's bitmap and read them when the library needs them.
A ready to use FreeType can be found in [lv_freetype](https://github.com/lvgl/lv_lib_freetype) repository.
To do this a custom `lv_font_t` variable needs to be created:
```c
/*Describe the properties of a font*/
lv_font_tmy_font;
my_font.get_glyph_dsc=my_get_glyph_dsc_cb;/*Set a callback to get info about gylphs*/
my_font.get_glyph_bitmap=my_get_glyph_bitmap_cb;/*Set a callback to get bitmap of a glyp*/
my_font.line_height=height;/*The real line height where any text fits*/
my_font.base_line=base_line;/*Base line measured from the top of line_height*/
my_font.dsc=something_required;/*Store any implementation specific data here*/
my_font.user_data=user_data;/*Optionally some extra user data*/
...
/* Get info about glyph of `unicode_letter` in `font` font.
* Store the result in `dsc_out`.
* The next letter (`unicode_letter_next`) might be used to calculate the width required by this glyph (kerning)
An image can be a file or variable which stores the bitmap itself and some metadata.
## Store images
You can store images in two places
- as a variable in the internal memory (RAM or ROM)
- as a file
### Variables
The images stored internally in a variable are composed mainly of an `lv_img_dsc_t` structure with the following fields:
- **header**
- *cf* Color format. See [below](#color-format)
- *w* width in pixels (<= 2048)
- *h* height in pixels (<= 2048)
- *always zero* 3 bits which need to be always zero
- *reserved* reserved for future use
- **data** pointer to an array where the image itself is stored
- **data_size** length of `data` in bytes
These are usually stored within a project as C files. They are linked into the resulting executable like any other constant data.
### Files
To deal with files you need to add a *Drive* to LVGL. In short, a *Drive* is a collection of functions (*open*, *read*, *close*, etc.) registered in LVGL to make file operations.
You can add an interface to a standard file system (FAT32 on SD card) or you create your simple file system to read data from an SPI Flash memory.
In every case, a *Drive* is just an abstraction to read and/or write data to memory.
See the [File system](/overview/file-system) section to learn more.
Images stored as files are not linked into the resulting executable, and must be read to RAM before being drawn. As a result, they are not as resource-friendly as variable images. However, they are easier to replace without needing to recompile the main program.
## Color formats
Various built-in color formats are supported:
- **LV_IMG_CF_TRUE_COLOR** Simply stores the RGB colors (in whatever color depth LVGL is configured for).
- **LV_IMG_CF_TRUE_COLOR_ALPHA** Like `LV_IMG_CF_TRUE_COLOR` but it also adds an alpha (transparency) byte for every pixel.
- **LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED** Like `LV_IMG_CF_TRUE_COLOR` but if a pixel has `LV_COLOR_TRANSP` (set in *lv_conf.h*) color the pixel will be transparent.
- **LV_IMG_CF_INDEXED_1/2/4/8BIT** Uses a palette with 2, 4, 16 or 256 colors and stores each pixel in 1, 2, 4 or 8 bits.
- **LV_IMG_CF_ALPHA_1/2/4/8BIT** **Only stores the Alpha value on 1, 2, 4 or 8 bits.** The pixels take the color of `style.image.color` and the set opacity. The source image has to be an alpha channel. This is ideal for bitmaps similar to fonts (where the whole image is one color but you'd like to be able to change it).
The bytes of the `LV_IMG_CF_TRUE_COLOR` images are stored in the following order.
For 32-bit color depth:
- Byte 0: Blue
- Byte 1: Green
- Byte 2: Red
- Byte 3: Alpha
For 16-bit color depth:
- Byte 0: Green 3 lower bit, Blue 5 bit
- Byte 1: Red 5 bit, Green 3 higher bit
- Byte 2: Alpha byte (only with LV_IMG_CF_TRUE_COLOR_ALPHA)
For 8-bit color depth:
- Byte 0: Red 3 bit, Green 3 bit, Blue 2 bit
- Byte 2: Alpha byte (only with LV_IMG_CF_TRUE_COLOR_ALPHA)
You can store images in a *Raw* format to indicate that it's not encoded with one of the built-in color formats and an external [Image decoder](#image-decoder) needs to be used to decode the image.
- **LV_IMG_CF_RAW** Indicates a basic raw image (e.g. a PNG or JPG image).
- **LV_IMG_CF_RAW_ALPHA** Indicates that the image has alpha and an alpha byte is added for every pixel.
- **LV_IMG_CF_RAW_CHROME_KEYED** Indicates that the image is chroma-keyed as described in `LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED` above.
## Add and use images
You can add images to LVGL in two ways:
- using the online converter
- manually create images
### Online converter
The online Image converter is available here: https://lvgl.io/tools/imageconverter
Adding an image to LVGL via online converter is easy.
1. You need to select a *BMP*, *PNG* or *JPG* image first.
2. Give the image a name that will be used within LVGL.
3. Select the [Color format](#color-formats).
4. Select the type of image you want. Choosing a binary will generate a `.bin` file that must be stored separately and read using the [file support](#files). Choosing a variable will generate a standard C file that can be linked into your project.
5. Hit the *Convert* button. Once the conversion is finished, your browser will automatically download the resulting file.
In the converter C arrays (variables), the bitmaps for all the color depths (1, 8, 16 or 32) are included in the C file, but only the color depth that matches `LV_COLOR_DEPTH` in *lv_conf.h* will actually be linked into the resulting executable.
In case of binary files, you need to specify the color format you want:
- RGB332 for 8-bit color depth
- RGB565 for 16-bit color depth
- RGB565 Swap for 16-bit color depth (two bytes are swapped)
- RGB888 for 32-bit color depth
### Manually create an image
If you are generating an image at run-time, you can craft an image variable to display it using LVGL. For example:
```c
uint8_tmy_img_data[]={0x00,0x01,0x02,...};
staticlv_img_dsc_tmy_img_dsc={
.header.always_zero=0,
.header.w=80,
.header.h=60,
.data_size=80*60*LV_COLOR_DEPTH/8,
.header.cf=LV_IMG_CF_TRUE_COLOR,/*Set the color format*/
.data=my_img_data,
};
```
If the color format is `LV_IMG_CF_TRUE_COLOR_ALPHA` you can set `data_size` like `80 * 60 * LV_IMG_PX_SIZE_ALPHA_BYTE`.
Another (possibly simpler) option to create and display an image at run-time is to use the [Canvas](/widgets/core/canvas) object.
### Use images
The simplest way to use an image in LVGL is to display it with an [lv_img](/widgets/core/img) object:
```c
lv_obj_t*icon=lv_img_create(lv_scr_act(),NULL);
/*From variable*/
lv_img_set_src(icon,&my_icon_dsc);
/*From file*/
lv_img_set_src(icon,"S:my_icon.bin");
```
If the image was converted with the online converter, you should use `LV_IMG_DECLARE(my_icon_dsc)` to declare the image in the file where you want to use it.
## Image decoder
As you can see in the [Color formats](#color-formats) section, LVGL supports several built-in image formats. In many cases, these will be all you need. LVGL doesn't directly support, however, generic image formats like PNG or JPG.
To handle non-built-in image formats, you need to use external libraries and attach them to LVGL via the *Image decoder* interface.
The image decoder consists of 4 callbacks:
- **info** get some basic info about the image (width, height and color format).
- **open** open the image: either store the decoded image or set it to `NULL` to indicate the image can be read line-by-line.
- **read** if *open* didn't fully open the image this function should give some decoded data (max 1 line) from a given position.
- **close** close the opened image, free the allocated resources.
You can add any number of image decoders. When an image needs to be drawn, the library will try all the registered image decoders until it finds one which can open the image, i.e. one which knows that format.
The `LV_IMG_CF_TRUE_COLOR_...`, `LV_IMG_INDEXED_...` and `LV_IMG_ALPHA_...` formats (essentially, all non-`RAW` formats) are understood by the built-in decoder.
### Custom image formats
The easiest way to create a custom image is to use the online image converter and set `Raw`, `Raw with alpha` or `Raw with chroma-keyed` format. It will just take every byte of the binary file you uploaded and write it as the image "bitmap". You then need to attach an image decoder that will parse that bitmap and generate the real, renderable bitmap.
`header.cf` will be `LV_IMG_CF_RAW`, `LV_IMG_CF_RAW_ALPHA` or `LV_IMG_CF_RAW_CHROME_KEYED` accordingly. You should choose the correct format according to your needs: fully opaque image, use alpha channel or use chroma keying.
After decoding, the *raw* formats are considered *True color* by the library. In other words, the image decoder must decode the *Raw* images to *True color* according to the format described in [#color-formats](Color formats) section.
If you want to create a custom image, you should use `LV_IMG_CF_USER_ENCODED_0..7` color formats. However, the library can draw the images only in *True color* format (or *Raw* but finally it's supposed to be in *True color* format).
The `LV_IMG_CF_USER_ENCODED_...` formats are not known by the library and therefore they should be decoded to one of the known formats from [#color-formats](Color formats) section.
It's possible to decode the image to a non-true color format first (for example: `LV_IMG_INDEXED_4BITS`) and then call the built-in decoder functions to convert it to *True color*.
With *User encoded* formats, the color format in the open function (`dsc->header.cf`) should be changed according to the new format.
### Register an image decoder
Here's an example of getting LVGL to work with PNG images.
First, you need to create a new image decoder and set some functions to open/close the PNG files. It should looks like this:
```c
/*Create a new decoder and register functions */
lv_img_decoder_t*dec=lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec,decoder_info);
lv_img_decoder_set_open_cb(dec,decoder_open);
lv_img_decoder_set_close_cb(dec,decoder_close);
/**
* Get info about a PNG image
* @param decoder pointer to the decoder where this function belongs
* @param src can be file name or pointer to a C array
* @param header store the info here
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
/*Call the built-in close function if the built-in open/read_line was used*/
lv_img_decoder_built_in_close(decoder,dsc);
}
```
So in summary:
- In `decoder_info`, you should collect some basic information about the image and store it in `header`.
- In `decoder_open`, you should try to open the image source pointed by `dsc->src`. Its type is already in `dsc->src_type == LV_IMG_SRC_FILE/VARIABLE`.
If this format/type is not supported by the decoder, return `LV_RES_INV`.
However, if you can open the image, a pointer to the decoded *True color* image should be set in `dsc->img_data`.
If the format is known but you don't want to decode the entire image (e.g. no memory for it) set `dsc->img_data = NULL` to call `read_line` to get the pixels.
- In `decoder_close` you should free all the allocated resources.
-`decoder_read` is optional. Decoding the whole image requires extra memory and some computational overhead.
However, if can decode one line of the image without decoding the whole image, you can save memory and time.
To indicate that the *line read* function should be used, set `dsc->img_data = NULL` in the open function.
### Manually use an image decoder
LVGL will use the registered image decoder automatically if you try and draw a raw image (i.e. using the `lv_img` object) but you can use them manually too. Create a `lv_img_decoder_dsc_t` variable to describe the decoding session and call `lv_img_decoder_open()`.
Sometimes it takes a lot of time to open an image.
Continuously decoding a PNG image or loading images from a slow external memory would be inefficient and detrimental to the user experience.
Therefore, LVGL caches a given number of images. Caching means some images will be left open, hence LVGL can quickly access them from `dsc->img_data` instead of needing to decode them again.
Of course, caching images is resource-intensive as it uses more RAM (to store the decoded image). LVGL tries to optimize the process as much as possible (see below), but you will still need to evaluate if this would be beneficial for your platform or not. If you have a deeply embedded target which decodes small images from a relatively fast storage medium, image caching may not be worth it.
### Cache size
The number of cache entries can be defined in `LV_IMG_CACHE_DEF_SIZE` in *lv_conf.h*. The default value is 1 so only the most recently used image will be left open.
The size of the cache can be changed at run-time with `lv_img_cache_set_size(entry_num)`.
### Value of images
When you use more images than cache entries, LVGL can't cache all of the images. Instead, the library will close one of the cached images (to free space).
To decide which image to close, LVGL uses a measurement it previously made of how long it took to open the image. Cache entries that hold slower-to-open images are considered more valuable and are kept in the cache as long as possible.
If you want or need to override LVGL's measurement, you can manually set the *time to open* value in the decoder open function in `dsc->time_to_open = time_ms` to give a higher or lower value. (Leave it unchanged to let LVGL set it.)
Every cache entry has a *"life"* value. Every time an image opening happens through the cache, the *life* value of all entries is decreased to make them older.
When a cached image is used, its *life* value is increased by the *time to open* value to make it more alive.
If there is no more space in the cache, the entry with the smallest life value will be closed.
### Memory usage
Note that the cached image might continuously consume memory. For example, if 3 PNG images are cached, they will consume memory while they are open.
Therefore, it's the user's responsibility to be sure there is enough RAM to cache even the largest images at the same time.
### Clean the cache
Let's say you have loaded a PNG image into a `lv_img_dsc_t my_png` variable and use it in an `lv_img` object. If the image is already cached and you then change the underlying PNG file, you need to notify LVGL to cache the image again. Otherwise, there is no easy way of detecting that the underlying file changed and LVGL will still draw the old image.
To do this, use `lv_img_cache_invalidate_src(&my_png)`. If `NULL` is passed as a parameter, the whole cache will be cleaned.
LV_IMG_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
lv_obj_t * cursor_obj = lv_img_create(lv_scr_act(), NULL); /*Create an image object for the cursor */
lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
lv_indev_set_cursor(mouse_indev, cursor_obj); /*Connect the image object to the driver*/
```
Note that the cursor object should have `lv_obj_set_click(cursor_obj, false)`.
For images, *clicking* is disabled by default.
## Keypad and encoder
You can fully control the user interface without touchpad or mouse using a keypad or encoder(s). It works similar to the *TAB* key on the PC to select the element in an application or a web page.
### Groups
The objects, you want to control with keypad or encoder, needs to be added to a *Group*.
In every group, there is exactly one focused object which receives the pressed keys or the encoder actions.
For example, if a [Text area](/widgets/core/textarea) is focused and you press some letter on a keyboard, the keys will be sent and inserted into the text area.
Similarly, if a [Slider](/widgets/core/slider) is focused and you press the left or right arrows, the slider's value will be changed.
You need to associate an input device with a group. An input device can send the keys to only one group but, a group can receive data from more than one input device too.
To create a group use `lv_group_t * g = lv_group_create()` and to add an object to the group use `lv_group_add_obj(g, obj)`.
To associate a group with an input device use `lv_indev_set_group(indev, g)`, where `indev` is the return value of `lv_indev_drv_register()`
#### Keys
There are some predefined keys which have special meaning:
- **LV_KEY_NEXT** Focus on the next object
- **LV_KEY_PREV** Focus on the previous object
- **LV_KEY_ENTER** Triggers `LV_EVENT_PRESSED/CLICKED/LONG_PRESSED` etc. events
- **LV_KEY_UP** Increase value or move upwards
- **LV_KEY_DOWN** Decrease value or move downwards
- **LV_KEY_RIGHT** Increase value or move the the right
- **LV_KEY_LEFT** Decrease value or move the the left
- **LV_KEY_ESC** Close or exit (E.g. close a [Drop down list](/widgets/core/dropdown))
- **LV_KEY_DEL** Delete (E.g. a character on the right in a [Text area](/widgets/core/textarea))
- **LV_KEY_BACKSPACE** Delete a character on the left (E.g. in a [Text area](/widgets/core/textarea))
- **LV_KEY_HOME** Go to the beginning/top (E.g. in a [Text area](/widgets/core/textarea))
- **LV_KEY_END** Go to the end (E.g. in a [Text area](/widgets/core/textarea)))
The most important special keys are `LV_KEY_NEXT/PREV`, `LV_KEY_ENTER` and `LV_KEY_UP/DOWN/LEFT/RIGHT`.
In your `read_cb` function, you should translate some of your keys to these special keys to navigate in the group and interact with the selected object.
Usually, it's enough to use only `LV_KEY_LEFT/RIGHT` because most of the objects can be fully controlled with them.
With an encoder, you should use only `LV_KEY_LEFT`, `LV_KEY_RIGHT`, and `LV_KEY_ENTER`.
#### Edit and navigate mode
Since a keypad has plenty of keys, it's easy to navigate between the objects and edit them using the keypad. But the encoders have a limited number of "keys" and hence it is difficult to navigate using the default options. *Navigate* and *Edit* are created to avoid this problem with the encoders.
In *Navigate* mode, the encoders `LV_KEY_LEFT/RIGHT` is translated to `LV_KEY_NEXT/PREV`. Therefore the next or previous object will be selected by turning the encoder.
Pressing `LV_KEY_ENTER` will change to *Edit* mode.
In *Edit* mode, `LV_KEY_NEXT/PREV` is usually used to edit the object.
Depending on the object's type, a short or long press of `LV_KEY_ENTER` changes back to *Navigate* mode.
Usually, an object which can not be pressed (like a [Slider](/widgets/core/slider)) leaves *Edit* mode on short click. But with objects where short click has meaning (e.g. [Button](/widgets/core/btn)), a long press is required.
#### Default group
Interactive widgets - such as buttons, checkboxes, sliders, etc - can be automatically added to a default group.
Just create a group with `lv_group_t * g = lv_group_create();` and set the default group with `lv_group_set_default(g);`
Don't forget to assign the input device(s) to the default group with ` lv_indev_set_group(my_indev, g);`.
### Styling
If an object is focused either by clicking it via touchpad, or focused via an encoder or keypad it goes to `LV_STATE_FOCUSED`. Hence focused styles will be applied on it.
If the object goes to edit mode it goes to `LV_STATE_FOCUSED | LV_STATE_EDITED` state so these style properties will be shown.
For a more detaild description read the [Style](https://docs.lvgl.io/v7/en/html/overview/style.html) section.
By default, LVGL draws new objects on top of old objects.
For example, assume we added a button to a parent object named button1 and then another button named button2. Then button1 (with its child object(s)) will be in the background and can be covered by button2 and its children.

```c
/*Create a screen*/
lv_obj_t*scr=lv_obj_create(NULL,NULL);
lv_scr_load(scr);/*Load the screen*/
/*Create 2 buttons*/
lv_obj_t*btn1=lv_btn_create(scr,NULL);/*Create a button on the screen*/
lv_btn_set_fit(btn1,true,true);/*Enable to automatically set the size according to the content*/
lv_obj_set_pos(btn1,60,40);/*Set the position of the button*/
lv_obj_t*btn2=lv_btn_create(scr,btn1);/*Copy the first button*/
lv_obj_set_pos(btn2,180,80);/*Set the position of the button*/
/*Add labels to the buttons*/
lv_obj_t*label1=lv_label_create(btn1,NULL);/*Create a label on the first button*/
lv_label_set_text(label1,"Button 1");/*Set the text of the label*/
lv_obj_t*label2=lv_label_create(btn2,NULL);/*Create a label on the second button*/
lv_label_set_text(label2,"Button 2");/*Set the text of the label*/
/*Delete the second label*/
lv_obj_del(label2);
```
## Bring to the foreground
There are several ways to bring an object to the foreground:
- Use `lv_obj_set_top(obj, true)`. If `obj` or any of its children is clicked, then LVGL will automatically bring the object to the foreground.
It works similarly to a typical GUI on a PC. When a window in the background is clicked, it will come to the foreground automatically.
- Use `lv_obj_move_foreground(obj)` to explicitly tell the library to bring an object to the foreground. Similarly, use `lv_obj_move_background(obj)` to move to the background.
- When `lv_obj_set_parent(obj, new_parent)` is used, `obj` will be on the foreground on the `new_parent`.
## Top and sys layers
LVGL uses two special layers named as `layer_top` and `layer_sys`.
Both are visible and common on all screens of a display. **They are not, however, shared among multiple physical displays.** The `layer_top` is always on top of the default screen (`lv_scr_act()`), and `layer_sys` is on top of `layer_top`.
The `layer_top` can be used by the user to create some content visible everywhere. For example, a menu bar, a pop-up, etc. If the `click` attribute is enabled, then `layer_top` will absorb all user click and acts as a modal.
```c
lv_obj_set_click(lv_layer_top(),true);
```
The `layer_sys` is also used for similar purposes on LVGL. For example, it places the mouse cursor above all layers to be sure it's always visible.
In LVGL the **basic building blocks** of a user interface are the objects, also called *Widgets*.
For example a [Button](/widgets/core/btn), [Label](/widgets/core/label), [Image](/widgets/core/img), [List](/widgets/extra/list), [Chart](/widgets/extra/chart) or [Text area](/widgets/core/textarea).
You can see all the [Object types](/widgets/index) here.
All objects are referenced using an `lv_obj_t` pointer as a handle. This pointer can later be used to set or get the attributes of the object.
## Attributes
### Basic attributes
All object types share some basic attributes:
- Position
- Size
- Parent
- Styles
- Event handlers
- Etc
You can set/get these attributes with `lv_obj_set_...` and `lv_obj_get_...` functions. For example:
```c
/*Set basic object attributes*/
lv_obj_set_size(btn1,100,50);/*Set a button's size*/
lv_obj_set_pos(btn1,20,30);/*Set a button's position*/
```
To see all the available functions visit the [Base object's documentation](/widgets/obj).
### Specific attributes
The object types have special attributes too. For example, a slider has
- Minimum and maximum values
- Current value
For these special attributes, every object type may have unique API functions. For example for a slider:
```c
/*Set slider specific attributes*/
lv_slider_set_range(slider1,0,100);/*Set the min. and max. values*/
lv_slider_set_value(slider1,40,LV_ANIM_ON);/*Set the current value (position)*/
```
The API of the widgets is described in their [Documentation](/widgets/index) but you can also check the respective header files (e.g. *widgets/lv_slider.h*)
## Working mechanisms
### Parent-child structure
A parent object can be considered as the container of its children. Every object has exactly one parent object (except screens), but a parent can have any number of children.
There is no limitation for the type of the parent but, there are typical parent (e.g. button) and typical child (e.g. label) objects.
### Moving together
If the position of the parent changes the children will move with the parent.
Therefore all positions are relative to the parent.

```c
lv_obj_t*parent=lv_obj_create(lv_scr_act());/*Create a parent object on the current screen*/
lv_obj_set_size(parent,100,80);/*Set the size of the parent*/
lv_obj_t*obj1=lv_obj_create(parent);/*Create an object on the previously created parent object*/
lv_obj_set_pos(obj1,10,10);/*Set the position of the new object*/
```
Modify the position of the parent:

```c
lv_obj_set_pos(parent,50,50);/*Move the parent. The child will move with it.*/
```
(For simplicity the adjusting of colors of the objects is not shown in the example.)
### Visibility only on the parent
If a child is partially or fully out of its parent then the parts outside will not be visible.

```c
lv_obj_set_x(obj1,-30);/*Move the child a little bit off the parent*/
```
### Create and delete objects
In LVGL objects can be created and deleted dynamically in run time. It means only the currently created (existing) objects consume RAM.
This allows for the creation of a screen just when a button is clicked to open it, and for deletion of screens when a new screen is loaded.
UIs can be created based on the current environment of the device. For example one can create meters, charts, bars and sliders based on the currently attached sensors.
Every widget has its own **create** function with a prototype like this:
In most of the cases the create functions have only a *parent* parameter that tells on which object create the new widget.
The return value is a pointer to the created object with `lv_obj_t *` type.
There is a common **delete** function for all object types. It deletes the object and all of its children.
```c
voidlv_obj_del(lv_obj_t*obj);
```
`lv_obj_del` will delete the object immediately.
If for any reason you can't delete the object immediately you can use `lv_obj_del_async(obj)` that will perform the deletion on the next call of `lv_timer_handler()`.
This is useful e.g. if you want to delete the parent of an object in the child's `LV_EVENT_DELETE` handler.
You can remove all the children of an object (but not the object itself) using `lv_obj_clean(obj)`.
## Screens
### Create screens
The screens are special objects which have no parent object. So they can be created like:
```c
lv_obj_t*scr1=lv_obj_create(NULL);
```
Screens can be created with any object type. For example, a [Base object](/widgets/obj) or an image to make a wallpaper.
### Get the active screen
There is always an active screen on each display. By default, the library creates and loads a "Base object" as a screen for each display.
To get the currently active screen use the `lv_scr_act()` function.
### Load screens
To load a new screen, use `lv_scr_load(scr1)`.
### Layers
There are two automatically generated layers:
- top layer
- system layer
They are independent of the screens and they will be shown on every screen. The *top layer* is above every object on the screen and the *system layer* is above the *top layer* too.
You can add any pop-up windows to the *top layer* freely. But, the *system layer* is restricted to system-level things (e.g. mouse cursor will be placed here in `lv_indev_set_cursor()`).
The `lv_layer_top()` and `lv_layer_sys()` functions return pointers to the top and system layers respectively.
Read the [Layer overview](/overview/layer) section to learn more about layers.
#### Load screen with animation
A new screen can be loaded with animation too using `lv_scr_load_anim(scr, transition_type, time, delay, auto_del)`. The following transition types exist:
-`LV_SCR_LOAD_ANIM_NONE`: switch immediately after `delay` milliseconds
-`LV_SCR_LOAD_ANIM_OVER_LEFT/RIGHT/TOP/BOTTOM` move the new screen over the current towards the given direction
-`LV_SCR_LOAD_ANIM_MOVE_LEFT/RIGHT/TOP/BOTTOM` move both the current and new screens towards the given direction
-`LV_SCR_LOAD_ANIM_FADE_ON` fade the new screen over the old screen
Setting `auto_del` to `true` will automatically delete the old screen when the animation is finished.
The new screen will become active (returned by `lv_scr_act()`) when the animations starts after `delay` time.
### Handling multiple displays
Screens are created on the currently selected *default display*.
The *default display* is the last registered display with `lv_disp_drv_register` or you can explicitly select a new default display using `lv_disp_set_default(disp)`.
`lv_scr_act()`, `lv_scr_load()` and `lv_scr_load_anim()` operate on the default screen.
Visit [Multi-display support](/overview/display) to learn more.
## Parts
The widgets are built from multiple parts. For example a [Base object](/widgets/obj) uses the main and scrollbar parts but a [Slider](/widgets/core/slider) uses the main, the indicator and the knob parts.
Parts are similar to *pseudo elements* in CSS.
The following predefined parts exist in LVGL:
-`LV_PART_MAIN` A background like rectangle*/``
-`LV_PART_SCROLLBAR` The scrollbar(s)
-`LV_PART_INDICATOR` Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox
-`LV_PART_KNOB` Like a handle to grab to adjust the value*/
-`LV_PART_SELECTED` Indicate the currently selected option or section
-`LV_PART_ITEMS` Used if the widget has multiple similar elements (e.g. tabel cells)*/
-`LV_PART_TICKS` Ticks on scales e.g. for a chart or meter
-`LV_PART_CURSOR` Mark a specific place e.g. text area's or chart's cursor
-`LV_PART_CUSTOM_FIRST` Custom parts can be added from here.
The main purpose of parts to allow styling the "components" of the widgets.
Therefore the parts are described in more detail in the [Style overview](/overview/style) section.
## States
The object can be in a combination of the following states:
-`LV_STATE_DEFAULT` Normal, released state
-`LV_STATE_CHECKED` Toggled or checked state
-`LV_STATE_FOCUSED` Focused via keypad or encoder or clicked via touchpad/mouse
-`LV_STATE_FOCUS_KEY` Focused via keypad or encoder but not via touchpad/mouse
-`LV_STATE_EDITED` Edit by an encoder
-`LV_STATE_HOVERED` Hovered by mouse (not supported now)
-`LV_STATE_PRESSED` Being pressed
-`LV_STATE_SCROLLED` Being scrolled
-`LV_STATE_DISABLED` Disabled state
-`LV_STATE_USER_1` Custom state
-`LV_STATE_USER_2` Custom state
-`LV_STATE_USER_3` Custom state
-`LV_STATE_USER_4` Custom state
The states are usually automatically changed by the library as the user presses, releases, focuses etc an object.
However, the states can be changed manually too.
To set or clear given state (but leave the other states untouched) use `lv_obj_add/clear_state(obj, LV_STATE_...)`
In both cases ORed state values can be used as well. E.g. `lv_obj_add_state(obj, part, LV_STATE_PRESSED | LV_PRESSED_CHECKED)`.
To learn more about the states read the related section of the [Style overview](/overview/style).
In LVGL scrolling works very intuitively: if an object is out of its parent content area (the size without paddings), the parent becomes scrollable and scrollbar(s) will appear. That's it.
Any object can be scrollable including `lv_obj_t`, `lv_img`, `lv_btn`, `lv_meter`, etc
The object can either be scrolled either horizontally or vertically in one stroke; diagonal scrolling is not possible.
### Scrollbar
#### Mode
The scrollbars are displayed according to the set `mode`. The following `mode`s exist:
-`LV_SCROLLBAR_MODE_OFF` Never show the scrollbars
-`LV_SCROLLBAR_MODE_ON` Always show the scrollbars
-`LV_SCROLLBAR_MODE_ACTIVE` Show scroll bars while object is being scrolled
-`LV_SCROLLBAR_MODE_AUTO` Show scroll bars when the content is large enough to be scrolled
`lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_...)` set the scrollbar mode on an object.
#### Styling
The scrollbars have their own dedicated part, called `LV_PART_SCROLLBAR`. For example a scrollbar can turned to red like this:
The object goes to `LV_STATE_SCROLLED` state while it's being scrolled. It allows adding different style to the scrollbar or the object itself when scrolled.
This code makes the scrollbar blue when the object is scrolled:
-`LV_EVENT_SCROLL` Scroll happened. Triggered on every position change.
Scroll events
## Basic example
TODO
## Features of scrolling
Besides managing "normal" scrolling there are many interesting and useful additional features too.
### Scrollable
It's possible to make an object non-scrollable with `lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE)`.
Non-scrollable object can still propagate the scrolling (chain) to the parents.
The direction in which scrolling can happen can be controlled by `lv_obj_set_scroll_dir(obj, LV_DIR_...)`.
The following values are possible for the direction:
-`LV_DIR_TOP` only scroll up
-`LV_DIR_LEFT` only scroll left
-`LV_DIR_BOTTOM` only scroll down
-`LV_DIR_RIGHT` only scroll right
-`LV_DIR_HOR` only scroll horizontally
-`LV_DIR_TOP` only scroll vertically
-`LV_DIR_ALL` scroll any directions
OR-ed values are also possible. E.g. `LV_DIR_TOP | LV_DIR_LEFT`.
### Scroll chain
If an object can't be scrolled further (e.g. it's content has reached the bottom most position) the scrolling is propagated to it's parent. If the parent an be scrolled in that direction than it will be scrolled instead.
It propagets to the grandparent and grand-grandparents too.
The propagation on scrolling is called "scroll chaining" and it can be enabled/disabled with the `LV_OBJ_FLAG_SCROLL_CHAIN` flag.
If chaining is disabled the propagation stops on the object and the parent(s) won't be scrolled.
### Scroll momentum
When the user scrolls an object and releases it, LVGL can emulate a momentum for the scrolling. It's like the object was thrown and scrolling slows down smoothly.
The scroll momentum can be enabled/disabled with the `LV_OBJ_FLAG_SCROLL_MOMENTUM` flag.
### Elastic scroll
Normally the content can't be scrolled inside the object. That is the top side of the content can't be below the top side of the object.
However, with `LV_OBJ_FLAG_SCROLL_ELASTIC` a fancy effect can be added when the user "over-scrolls" the content. The scrolling slows down, and the content can be scrolled inside the object.
When the object is released the content scrolled in it will be animated back to the valid position.
### Snapping
The children of an object can be snapped according to specific rules when scrolling ends. Children can be made snappable individually with the `LV_OBJ_FLAG_SNAPABLE` flag. (Note misspelling of the flag name: your code needs to spell it with one P.)
The object can align the snapped children in 4 ways:
-`LV_SCROLL_SNAP_NONE` Snapping is disabled. (default)
-`LV_SCROLL_SNAP_START` Align the children to the left/top side of the scrolled object
-`LV_SCROLL_SNAP_END` Align the children to the right/bottom side of the scrolled object
-`LV_SCROLL_SNAP_CENTER` Align the children to the center of the scrolled object
The alignment can be set with `lv_obj_set_scroll_snap_x/y(obj, LV_SCROLL_SNAP_...)`:
Under the hood the following happens:
1. User scrolls an object and releases the screen
2. LVGL calculates where the scroll would end considering scroll momentum
3. LVGL finds the nearest scroll point
4. LVGL scrolls to the snap point with an animation
### Scroll one
The "scroll one" feature tells LVGL to allow scrolling only one snappable child at a time.
So this requires to make the children snappable (LV_OBJ_FLAG_SNAPABLE spelled with one P in code) and and set a scroll snap alignment different from `LV_SCROLL_SNAP_NONE`.
This feature can be enabled by the `LV_OBJ_FLAG_SCROLL_ONE` flag.
### Scroll on focus
Imagine that there a lot of objects in a group that are on scrollable object. Pressing the "Tab" button focuses the next object but it might be out of the visible area of the scrollable object.
If the "scroll on focus" features is enabled LVGL will automatically scroll to the objects to bring the children into the view.
The scrolling happens recursively therefore even nested scrollable object are handled properly.
The object will be scrolled to the view even if it's on a different page of a tabview.
## Scroll manually
The following API functions allow to manually scroll objects:
-`lv_obj_scroll_by(obj, x, y, LV_ANIM_ON/OFF)` scroll by `x` and `y` values
-`lv_obj_scroll_to(obj, x, y, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the top left corner
-`lv_obj_scroll_to_x(obj, x, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the left side
-`lv_obj_scroll_to_y(obj, y, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the left side
## Self size
Self size is a property of an object. Normally, the user shouldn't use this parameter but if a custom widget is created it might be useful.
In short, self size tell the size of the content. To understand it better take the example of a table.
Let's say it has 10 rows each with 50 px height. So the total height of the content is 500 px. In other words the "self height" is 500 px.
If the user sets only 200 px height for the table LVGL will see that the self size is larger and make the table scrollable.
It means not only the children can make an object scrollable but a larger self size too.
LVGL uses the `LV_EVENT_GET_SELF_SIZE` event to get the self size of an object. Here is an example to see how to handle the event
```c
if(event_code==LV_EVENT_GET_SELF_SIZE){
lv_point_t*p=lv_event_get_param(e);
//If x or y < 0 then it doesn't neesd to be calculated now
Sets the width of object. Pixel, percentage and `LV_SIZE_CONTENT` values can be used. Percentage values are relative to the width of the parent's content area.
Sets the height of object. Pixel, percentage and `LV_SIZE_CONTENT` can be used. Percentage values are relative to the height of the parent's content area.
Set the X coordinate of the object considering the set `align`. Pixel and percentage values can be used. Percentage values are relative to the width of the parent's content area.
Set the Y coordinate of the object considering the set `align`. Pixel and percentage values can be used. Percentage values are relative to the height of the parent's content area.
Set the alignment which determines from which point of the parent the X and Y coordinates should be interpreted. The possible values are: `LV_ALIGN_TOP_LEFT/MID/RIGHT`, `LV_ALIGN_BOTTOM_LEFT/MID/RIGHT`, `LV_ALIGN_LEFT/RIGHT_MID`, `LV_ALIGN_CENTER`
Make the object wider on both sides with this value. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's width.
Make the object higher on both sides with this value. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's height.
Move the object with this value in X direction. Applied after layouts, aligns and other positioning. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's width.
Move the object with this value in Y direction. Applied after layouts, aligns and other positioning. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's height.
Zoom image-like objects. Multiplied with the zoom set on the object. The value 256 (or `LV_IMG_ZOOM_NONE`) means normal size, 128 half size, 512 double size, and so on
Scale down all opacity values of the object by this factor. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
The animation time in milliseconds. Its meaning is widget specific. E.g. blink time of the cursor on the text area or scroll time of a roller. See the widgets' documentation to learn more.
Set the layout if the object. The children will be repositioned and resized according to the policies set for the layout. For the possible values see the documentation of the layouts.
Set the opacity of the background. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set the point from which the background color should start for gradients. 0 means to top/left side, 255 the bottom/right side, 128 the center, and so on
Set the opacity of the background image. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set the intensity of background image recoloring. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means no mixing, 256, `LV_OPA_100` or `LV_OPA_COVER` means full recoloring, other values or LV_OPA_10, LV_OPA_20, etc are interpreted proportionally.
Set the opcitiy of the border. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set which side(s) the border should be drawn. The possible values are `LV_BORDER_SIDE_NONE/TOP/BOTTOM/LEFT/RIGHT/INTERNAL`. OR-ed calues an be used as well, e.g. `LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_LEFT`.
Set the opacity of the text. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set how to align the lines of the text. Note that it doesn't align the object itself, only the lines inside the object. The possible values are `LV_TEXT_ALIGN_LEFT/CENTER/RIGHT/AUTO`. `LV_TEXT_ALIGN_AUTO` detect the text base direction and uses left or right alignment accordingly
Set the opacity of an image. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set the intensity of the color mixing. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set the opacity of the outline. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set the opacity of the shadow. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 256, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc indicate semi-transparency.
Set an image from which the arc will be masked out. It's useful to display complex effects on the arcs. Can be a pointer to `lv_img_dsc_t` or a path to a file
*Styles* are used to set the appearance of the objects. Styles in lvgl are heavily inspired by CSS. The concept in nutshell is as follows:
- A style is an `lv_style_t` variable which can hold properties like border width, text color and so on. It's similar to a `class` in CSS.
- Styles can be assigned to objects to change their appearance. During the assignment the target part (*pseudo element* in CSS) and target state (*pseudo class*) can be specified.
For example one can add `style_blue` to the knob of a slider when it's in pressed state.
- The same style can be used by any number of objects.
- Styles can be cascaded which means multiple styles can be assigned to an object and each style can have different properties.
Therefore not all properties have to be specified in style. LVLG will look for a property until a style defines it or use a default if it's not spefied by any of the styles.
For example `style_btn` can result in a default gray button and `style_btn_red` can add only a `background-color=red` to overwrite the background color.
- Later added styles have higher precedence. It means if a property is specified in two styles the later added will be used.
- Some properties (e.g. text color) can be inherited from the parent(s) if it's not specified in the object.
- Objects can have local styles that have higher precedence than "normal" styles.
- Unlike CSS (where pseudo-classes describe different states, e.g. `:focus`), in LVGL a property is assigned to a given state.
- Transitions can be applied when the object changes state.
## States
The objects can be in the combination of the following states:
-`LV_STATE_DEFAULT` (0x0000) Normal, released state
-`LV_STATE_CHECKED` (0x0001) Toggled or checked state
-`LV_STATE_FOCUSED` (0x0002) Focused via keypad or encoder or clicked via touchpad/mouse
-`LV_STATE_FOCUS_KEY` (0x0004) Focused via keypad or encoder but not via touchpad/mouse
-`LV_STATE_EDITED` (0x0008) Edit by an encoder
-`LV_STATE_HOVERED` (0x0010) Hovered by mouse (not supported now)
-`LV_STATE_PRESSED` (0x0020) Being pressed
-`LV_STATE_SCROLLED` (0x0040) Being scrolled
-`LV_STATE_DISABLED` (0x0080) Disabled state
-`LV_STATE_USER_1` (0x1000) Custom state
-`LV_STATE_USER_2` (0x2000) Custom state
-`LV_STATE_USER_3` (0x4000) Custom state
-`LV_STATE_USER_4` (0x8000) Custom state
The combination states the object can be focused and pressed at the same time. This is represented as `LV_STATE_FOCUSED | LV_STATE_PRESSED`.
The style can be added to any state and state combination.
For example, setting a different background color for default and pressed state.
If a property is not defined in a state the best matching state's property will be used. Typically this means the property with `LV_STATE_DEFAULT` is used.˛
If the property is not set even for the default state the default value will be used. (See later)
But what does the "best matching state's property" really mean?
States have a precedence which is shown by their value (see in the above list). A higher value means higher precedence.
To determine which state's property to use let's take an example. Imagine the background color is defined like this:
-`LV_STATE_DEFAULT`: white
-`LV_STATE_PRESSED`: gray
-`LV_STATE_FOCUSED`: red
1. By the default the object is in default state, so it's a simple case: the property is perfectly defined in the object's current state as white.
2. When the object is pressed there are 2 related properties: default with white (default is related to every state) and pressed with gray.
The pressed state has 0x0020 precedence which is higher than the default state's 0x0000 precedence, so gray color will be used.
3. When the object is focused the same thing happens as in pressed state and red color will be used. (Focused state has higher precedence than default state).
4. When the object is focused and pressed both gray and red would work, but the pressed state has higher precedence than focused so gray color will be used.
5. It's possible to set e.g rose color for `LV_STATE_PRESSED | LV_STATE_FOCUSED`.
In this case, this combined state has 0x0020 + 0x0002 = 0x0022 precedence, which is higher than the pressed state's precedence so rose color would be used.
6. When the object is in checked state there is no property to set the background color for this state. So for lack of a better option, the object remains white from the default state's property.
Some practical notes:
- The precedence (value) of states is quite intuitive and it's something the user would expect naturally. E.g. if an object is focused the user will still want to see if it's pressed, therefore pressed state has a higher precedence.
If the focused state had a higher precedence it would overwrite the pressed color.
- If you want to set a property for all states (e.g. red background color) just set it for the default state. If the object can't find a property for its current state it will fall back to the default state's property.
- Use ORed states to describe the properties for complex cases. (E.g. pressed + checked + focused)
- It might be a good idea to use different style elements for different states.
For example, finding background colors for released, pressed, checked + pressed, focused, focused + pressed, focused + pressed + checked, etc states is quite difficult.
Instead, for example, use the background color for pressed and checked states and indicate the focused state with a different border color.
## Cascading styles
It's not required to set all the properties in one style. It's possible to add more styles to an object andlet the later added style to modify or extend appearance.
For example, create a general gray button style and create a new for red buttons where only the new background color is set.
This is much like in CSS when used classes are listed like `<div class=".btn .btn-red">`.
Styles added later have precedence over ones set earlier. So in the gray/red button example above, the normal button style should be added first and the red style second.
However, the precedence coming from states are still taken into account.
So let's examine the following case:
- the basic button style defines dark-gray color for default state and light-gray color pressed state
- the red button style defines the background color as red only in the default state
In this case, when the button is released (it's in default state) it will be red because a perfect match is found in the most recently added style (red).
When the button is pressed the light-gray color is a better match because it describes thecurrent state perfectly, so the button will be light-gray.
## Inheritance
Some properties (typically that are related to texts) can be inherited from the parent object's styles.
Inheritance is applied only if the given property is not set in the object's styles (even in default state).
In this case, if the property is inheritable, the property's value will be searched in the parents too until an object specifies a value for the property. The parents will use their own state to detemine the value.
So if a button is pressed, and the text color comes from here, the pressed text color will be used.
## Parts
Objects can have *parts* which can have their own styles.
The following predefined parts exist in LVGL:
-`LV_PART_MAIN` A background like rectangle*/
-`LV_PART_SCROLLBAR` The scrollbar(s)
-`LV_PART_INDICATOR` Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox
-`LV_PART_KNOB` Like a handle to grab to adjust the value*/
-`LV_PART_SELECTED` Indicate the currently selected option or section
-`LV_PART_ITEMS` Used if the widget has multiple similar elements (e.g. table cells)*/
-`LV_PART_TICKS` Ticks on scales e.g. for a chart or meter
-`LV_PART_CURSOR` Mark a specific place e.g. text area's or chart's cursor
-`LV_PART_CUSTOM_FIRST` Custom parts can be added from here.
For example a [Slider](/widgets/core/slider) has three parts:
- Background
- Indiactor
- Knob
It means the all three parts of the slider can have their own styles. See later how to add style styles to objects and parts.
## Initialize styles and set/get properties
Styles are stored in `lv_style_t` variables. Style variables should be `static`, global or dynamically allocated.
In other words they can not be local variables in functions which are destroyed when the function exists.
Before using a style it should be initialized with `lv_style_init(&my_style)`.
After initializing the style properties can be set or added to it.
Property set functions looks like this: `lv_style_set_<property_name>(&style, <value>);` For example:
-`num` for integer, boolean and opacity properties
-`color` for color properties
-`ptr` for pointer properties
To reset a style (free all its data) use
```c
lv_style_reset(&style);
```
## Add and remove styles to a widget
A style on its own is not that useful, it needs to be assigned to an object to take effect.
### Add styles
To add a style to an object use `lv_obj_add_style(obj, &style, <selector>)`. `<selector>` is an OR-ed value of parts and state to which the style should be added. Some examples:
-`LV_PART_MAIN | LV_STATE_DEFAULT`
-`LV_STATE_PRESSED`: The main part in pressed state. `LV_PART_MAIN` can be omitted
-`LV_PART_SCROLLBAR`: The scrollbar part in the default state. `LV_STATE_DEFAULT` can be omitted.
-`LV_PART_SCROLLBAR | LV_STATE_SCROLLED`: The scrollbar part when the object is being scrolled
-`0` Same as `LV_PART_MAIN | LV_STATE_DEFAULT`.
-`LV_PART_INDICATOR | LV_STATE_PRESSED | LV_STATE_CHECKED` The indicator part when the object is pressed and checked at the same time.
lv_obj_add_style(btn,&btn_red,LV_STATE_PRESSED);/*Overwrite only a some colors to red when pressed*/
```
### Remove styles
To remove all styles from an object use `lv_obj_remove_style_all(obj)`.
To remove specific styles use `lv_obj_remove_style(obj, style, selector)`. This function will remove `style` only if the `selector` matches with the `selector` used in `lv_obj_add_style`.
`style` can be `NULL` to check only the `selector` and remove all matching styles. The `selector` can use the `LV_STATE_ANY` and `LV_PART_ANY` values to remove the style with any state or part.
### Report style changes
If a style which is already assigned to object changes (i.e. a property is added or changed) the objects using that style should be notified. There are 3 options to do this:
1. If you know that the changed properties can be applied by a simple redraw (e.g. color or opacity changes) just call `lv_obj_invalidate(obj)` or `lv_obj_invalideate(lv_scr_act())`.
2. If more complex style properties were changed or added, and you know which object(s) are affected by that style call `lv_obj_refresh_style(obj, part, property)`.
To refresh all parts and properties use `lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY)`.
3. To make LVGL check all objects to see whether they use the style and refresh them when needed call `lv_obj_report_style_change(&style)`. If `style` is `NULL` all objects will be notified about the style change.
### Get a property's value on an object
To get a final value of property - considering cascading, inheritance, local styles and transitions (see below) - get functions like this can be used:
`lv_obj_get_style_<property_name>(obj, <part>)`.
These functions uses the object's current state and if no better candidate returns a default value.
Besides "normal" styles, the objects can store local styles too. This concept is similar to inline styles in CSS (e.g. `<div style="color:red">`) with some modification.
So local styles are like normal styles but they can't be shared among other objects. If used, local styles are allocated automatically, and freed when the object is deleted.
They are useful to add local customization to the object.
Unlike in CSS, in LVGL local styles can be assigned to states (*pseudo-classes*) and parts (*pseudo-elements*).
To set a local property use functions like `lv_obj_set_style_local_<property_name>(obj, <value>, <selector>);`
For the full list of style properties click [here](/overview/style-props).
### Typical background properties
In the documentation of the widgets you will see sentences like "The widget use the typical background properties". The "typical background properties" are the ones related to:
- Background
- Border
- Outline
- Shadow
- Padding
- Width and height transformation
- X and Y translation
## Transitions
By default, when an object changes state (e.g. it's pressed) the new properties from the new state are set immediately. However, with transitions it's possible to play an animation on state change.
For example, on pressing a button its background color can be animated to the pressed color over 300 ms.
The parameters of the transitions are stored in the styles. It's possible to set
- the time of the transition
- the delay before starting the transition
- the animation path (also known as timing or easing function)
- the properties to animate
The transition properties can be defined for each state. For example, setting 500 ms transition time in default state will mean that when the object goes to the default state a 500 ms transition time will be applied.
Setting 100 ms transition time in the pressed state will mean a 100 ms transition time when going to pressed state.
So this example configuration will result in going to pressed state quickly and then going back to default slowly.
To describe a transition an `lv_transition_dsc_t` variable needs to initialized and added to a style:
```c
/*Only its pointer is saved so must static, global or dynamically allocated */
Themes are a collection of styles. If there is an active theme LVGL applies it on every created widget.
This will give a default appearance to the UI which can then be modified by adding further styles.
Every display can have a different theme. For example you could have a colorful theme on a TFT and monochrome theme on a secondary monochrome display.
To set a theme for a display, 2 steps are required:
1. Initialize a theme
2. Assign the initialized theme to a display.
Theme initialization functions can have different prototype. This example shows how to set the "default" theme:
```c
lv_theme_t*th=lv_theme_default_init(display,/*Use the DPI, size, etc from this display*/
LV_COLOR_PALETTE_BLUE,LV_COLOR_PALETTE_CYAN,/*Primary and secondary palette*/
false,/*Light or dark mode*/
&lv_font_montserrat_10,&lv_font_montserrat_14,&lv_font_montserrat_18);/*Small, normal, large fonts*/
lv_disp_set_theme(display,th);/*Assign the theme to the display*/
```
The themes can be enabled in `lv_conf.h`. If the default theme is enabled by `LV_USE_THEME_DEFAULT 1` LVGL automatically initializes and sets it when a display is created.
### Extending themes
Built-in themes can be extended.
If a custom theme is created a parent theme can be selected. The parent theme's styles will be added before the custom theme's styles.
Any number of themes can be chained this way. E.g. default theme -> custom theme -> dark theme.
`lv_theme_set_parent(new_theme, base_theme)` extends the `base_theme` with the `new_theme`.
LVGL has a built-in timer system. You can register a function to have it be called periodically. The timers are handled and called in `lv_timer_handler()`, which needs to be called every few milliseconds.
See [Porting](/porting/task-handler) for more information.
The timers are non-preemptive, which means a timer cannot interrupt another timer. Therefore, you can call any LVGL related function in a timer.
## Create a timer
To create a new timer, use `lv_timer_create(timer_cb, period_ms, user_data)`. It will create an `lv_timer_t *` variable, which can be used later to modify the parameters of the timer.
`lv_timer_create_basic()` can also be used. This allows you to create a new timer without specifying any parameters.
A timer callback should have `void (*lv_timer_cb_t)(lv_timer_t *);` prototype.
For example:
```c
voidmy_timer(lv_timer_t*timer)
{
/*Use the user_data*/
uint32_t*user_data=timer->user_data;
printf("my_timer called with user data: %d\n",*user_data);
`lv_timer_ready(timer)` makes the timer run on the next call of `lv_timer_handler()`.
`lv_timer_reset(timer)` resets the period of a timer. It will be called again after the defined period of milliseconds has elapsed.
## Set parameters
You can modify some parameters of the timers later:
-`lv_timer_set_cb(timer, new_cb)`
-`lv_timer_set_period(timer, new_period)`
## Repeat count
You can make a timer repeat only a given number of times with `lv_timer_set_repeat_count(timer, count)`. The timer will automatically be deleted after being called the defined number of times. Set the count to `-1` to repeat indefinitely.
## Measure idle time
You can get the idle percentage time of `lv_timer_handler` with `lv_timer_get_idle()`. Note that, it doesn't measure the idle time of the overall system, only `lv_timer_handler`.
It can be misleading if you use an operating system and call `lv_timer_handler` in a timer, as it won't actually measure the time the OS spends in an idle thread.
## Asynchronous calls
In some cases, you can't do an action immediately. For example, you can't delete an object because something else is still using it or you don't want to block the execution now.
For these cases, `lv_async_call(my_function, data_p)` can be used to make `my_function` be called on the next call of `lv_timer_handler`. `data_p` will be passed to function when it's called.
Note that, only the pointer of the data is saved so you need to ensure that the variable will be "alive" while the function is called. It can be *static*, global or dynamically allocated data.
For example:
```c
voidmy_screen_clean_up(void*scr)
{
/*Free some resources related to `scr`*/
/*Finally delete the screen*/
lv_obj_del(scr);
}
...
/*Do somethings with the object on the current screen*/
/*Delete screen on next call of `lv_timer_handler`, so not now.*/
lv_async_call(my_screen_clean_up,lv_scr_act());
/*The screen is still valid so you can do other things with it*/
```
If you just want to delete an object, and don't need to clean anything up in `my_screen_cleanup`, you could just use `lv_obj_del_async`, which will delete the object on the next call to `lv_timer_handler`.
Note that `lv_disp_draw_buf_t` needs to be static, global or dynamically allocated and not a local variable destroyed if goes out of the scope.
As you can see the draw buffer can be smaller than the screen. In this case, the larger areas will be redrawn in smaller parts that fit into the draw buffer(s).
If only a small area changes (e.g. a button is pressed) then only that area will be refreshed.
A larger buffer results in better performance but above 1/10 screen sized buffer(s) there is no significant performance improvement.
Therefore it's recommended to choose the size of the draw buffer(s) to at least 1/10 screen sized.
If only **one buffer** is used LVGL draws the content of the screen into that draw buffer and sends it to the display.
This way LVGL needs to wait until the content of the buffer is sent to the display before drawing something new in it.
If **two buffers** are used LVGL can draw into one buffer while the content of the other buffer is sent to display in the background.
DMA or other hardware should be used to transfer the data to the display to let the MCU draw meanwhile.
This way, the rendering and refreshing of the display become parallel.
In the display driver (`lv_disp_drv_t`) the `full_refresh` bit can be enabled to force LVGL to always redraw the whole screen. This works in both *one buffer* and *two buffers* modes.
If `full_refresh` is enabled and 2 screen sized draw buffers are provided, LVGL's display handling works like "traditional" double buffering.
This means in `flush_cb` only the address of the frame buffer needs to be changed to the provided pointer (`color_p` parameter).
This configuration should be used if the MCU has LCD controller periphery and not with an external display controller (e.g. ILI9341 or SSD1963).
You can measure the performance of different draw buffer configurations using the [benchmark example](https://github.com/lvgl/lv_demos/tree/master/src/lv_demo_benchmark).
## Display driver
Once the buffer initialization is ready a `lv_disp_drv_t` display driver needs to be
1. initialized with `lv_disp_drv_init(&disp_drv)`
2. its fields need to be set
3. it needs to be registered in LVGL with `lv_disp_drv_register(&disp_drv)`
Note that `lv_disp_drv_t` also needs to be static, global or dynamically allocated and not a local variable destroyed if goes out of the scope.
### Mandatory fields
In the most simple case only the following fields of `lv_disp_drv_t` need to be set:
-`draw_buf` pointer to an initialized `lv_disp_draw_buf_t` variable.
-`hor_res` horizontal resolution of the display in pixels.
-`ver_res` vertical resolution of the display in pixels.
-`flush_cb` a callback function to copy a buffer's content to a specific area of the display.
`lv_disp_flush_ready(&disp_drv)` needs to be called when flushing is ready.
LVGL might render the screen in multiple chunks and therefore call `flush_cb` multiple times. To see if the current one is the last chunk of rendering use `lv_disp_flush_is_last(&disp_drv)`.
### Optional fields
There are some optional data fields:
-`color_chroma_key` A color which will be drawn as transparent on chrome keyed images. Set to `LV_COLOR_CHROMA_KEY` by default from `lv_conf.h`.
-`anti_aliasing` use anti-aliasing (edge smoothing). Enabled by default if `LV_COLOR_DEPTH` is set to at least 16 in `lv_conf.h`.
-`rotated` and `sw_rotate` See the [Rotation](#rotation) section below.
-`screen_transp` if `1` the screen itself can have transparency as well. `LV_COLOR_SCREEN_TRANSP` needs to enabled in `lv_conf.h` and requires `LV_COLOR_DEPTH 32`.
-`user_data` A custom `void `user data for the driver..
Some other optional callbacks to make easier and more optimal to work with monochrome, grayscale or other non-standard RGB displays:
-`rounder_cb` Round the coordinates of areas to redraw. E.g. a 2x2 px can be converted to 2x8.
It can be used if the display controller can refresh only areas with specific height or width (usually 8 px height with monochrome displays).
-`set_px_cb` a custom function to write the draw buffer. It can be used to store the pixels more compactly in the draw buffer if the display has a special color format. (e.g. 1-bit monochrome, 2-bit grayscale etc.)
This way the buffers used in `lv_disp_draw_buf_t` can be smaller to hold only the required number of bits for the given area size. Note that, rendering with `set_px_cb` is slower than normal rendering.
-`monitor_cb` A callback function that tells how many pixels were refreshed in how much time. Called when the last chunk is rendered and sent to the display.
-`clean_dcache_cb` A callback for cleaning any caches related to the display.
LVGL has built-in support to several GPUs (see `lv_conf.h`) but if something else is required these functions can be used to make LVGL use a GPU:
-`gpu_fill_cb` fill an area in the memory with a color.
-`gpu_wait_cb` if any GPU function returns while the GPU is still working, LVGLwill use this function when required to make sure GPU rendering is ready.
### Examples
All together it looks like this:
```c
staticlv_disp_drv_tdisp_drv;/*A variable to hold the drivers. Must be static or global.*/
LVGL supports rotation of the display in 90 degree increments. You can select whether you'd like software rotation or hardware rotation.
If you select software rotation (`sw_rotate` flag set to 1), LVGL will perform the rotation for you. Your driver can and should assume that the screen width and height have not changed. Simply flush pixels to the display as normal. Software rotation requires no additional logic in your `flush_cb` callback.
There is a noticeable amount of overhead to performing rotation in software, which is why hardware rotation is also available. In this mode, LVGL draws into the buffer as though your screen now has the width and height inverted. You are responsible for rotating the provided pixels yourself.
The default rotation of your display when it is initialized can be set using the `rotated` flag. The available options are `LV_DISP_ROT_NONE`, `LV_DISP_ROT_90`, `LV_DISP_ROT_180`, or `LV_DISP_ROT_270`. The rotation values are relative to how you would rotate the physical display in the clockwise direction. Thus, `LV_DISP_ROT_90` means you rotate the hardware 90 degrees clockwise, and the display rotates 90 degrees counterclockwise to compensate.
(Note for users upgrading from 7.10.0 and older: these new rotation enum values match up with the old 0/1 system for rotating 90 degrees, so legacy code should continue to work as expected. Software rotation is also disabled by default for compatibility.)
Display rotation can also be changed at runtime using the `lv_disp_set_rotation(disp, rot)` API.
Support for software rotation is a new feature, so there may be some glitches/bugs depending on your configuration. If you encounter a problem please open an issue on [GitHub](https://github.com/lvgl/lvgl/issues).
## Further reading
- [lv_port_disp_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_disp_template.c) for a template for your own driver.
- [Drawing](/overview/drawing) to learn more about how rendering works in LVGL.
- [Display features](/overview/display) to learn more about higher level display features.
To set a mouse cursor use `lv_indev_set_cursor(my_indev, &img_cursor)`. (`my_indev` is the return value of `lv_indev_drv_register`)
### Keypad or keyboard
Full keyboards with all the letters or simple keypads with a few navigation buttons belong here.
To use a keyboard/keypad:
- Register a `read_cb` function with `LV_INDEV_TYPE_KEYPAD` type.
- An object group has to be created: `lv_group_t * g = lv_group_create()` and objects have to be added to it with `lv_group_add_obj(g, obj)`
- The created group has to be assigned to an input device: `lv_indev_set_group(my_indev, g)` (`my_indev` is the return value of `lv_indev_drv_register`)
- Use `LV_KEY_...` to navigate among the objects in the group. See `lv_core/lv_group.h` for the available keys.
In short, the Encoder input devices work like this:
- By turning the encoder you can focus on the next/previous object.
- When you press the encoder on a simple object (like a button), it will be clicked.
- If you press the encoder on a complex object (like a list, message box, etc.) the object will go to edit mode whereby turning the encoder you can navigate inside the object.
- To leave edit mode press long the button.
To use an *Encoder* (similarly to the *Keypads*) the objects should be added to groups.
static uint32_t last_btn = 0; /*Store the last pressed button*/
int btn_pr = my_btn_read(); /*Get the ID (0,1,2...) of the pressed button*/
if(btn_pr >= 0) { /*Is there a button press? (E.g. -1 indicated no button was pressed)*/
last_btn = btn_pr; /*Save the ID of the pressed button*/
data->state = LV_INDEV_STATE_PRESSED; /*Set the pressed state*/
} else {
data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/
}
data->btn = last_btn; /*Save the last button*/
}
```
## Other features
### Parameters
The default value of the following parameters can changed in `lv_indev_drv_t`:
- `scroll_limit` Number of pixels to slide before actually scrolling the object.
- `scroll_throw` Scroll throw (momentum) slow-down in [%]. Greater value means faster slow-down.
- `long_press_time` Press time to send `LV_EVENT_LONG_PRESSED` (in milliseconds)
- `long_press_rep_time` Interval of sending `LV_EVENT_LONG_PRESSED_REPEAT` (in milliseconds)
- `read_timer` pointer to the `lv_timer` which reads the input device. Its parameters can be changed by `lv_timer_...()` functions. `LV_INDEV_DEF_READ_PERIOD` in `lv_conf.h` sets the default read period.
### Feedback
Besides `read_cb` a `feedback_cb` callback can be also specified in `lv_indev_drv_t`.
`feedback_cb` is called when any type of event is sent by the input devices (independently from its type). This allows generating feedback for the user, e.g. to play a sound on `LV_EVENT_CLICKED`.
### Associating with a display
Every input device is associated with a display. By default, a new input device is added to the lastly created or the explicitly selected (using `lv_disp_set_default()`) display.
The associated display is stored and can be changed in `disp` field of the driver.
### Buffered reading
By default LVGL calls `read_cb` periodically. This way there is a chance that some user gestures are missed.
To solve this you can write an event driven driver for your input device that buffers measured data. In `read_cb` you can set the buffered data instead of reading the input device.
You can set the `data->continue_reading` flag to tell that LVGL there is more data to read and it should call the `read_cb` again.
## Further reading
- [lv_port_indev_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_indev_template.c) for a template for your own driver.
- [INdev features](/overview/display) to learn more about higher level input device features.
However, in the following conditions it's valid to call LVGL related functions:
- In *events*. Learn more in [Events](/overview/event).
- In *lv_timer*. Learn more in [Timers](/overview/timer).
## Tasks and threads
If you need to use real tasks or threads, you need a mutex which should be invoked before the call of `lv_timer_handler` and released after it.
Also, you have to use the same mutex in other tasks and threads around every LVGL (`lv_...`) related function call and code.
This way you can use LVGL in a real multitasking environment. Just make use of a mutex to avoid the concurrent calling of LVGL functions.
## Interrupts
Try to avoid calling LVGL functions from interrupt handlers (except `lv_tick_inc()` and `lv_disp_flush_ready()`). But if you need to do this you have to disable the interrupt which uses LVGL functions while `lv_timer_handler` is running.
It's a better approach to set a flag or some value and periodically check it in an `lv_timer`.
LVGL is available on GitHub: [https://github.com/lvgl/lvgl](https://github.com/lvgl/lvgl).
You can clone it or download the latest version of the library from GitHub.
The graphics library itself is the **lvgl** directory which should be copied into your project.
## Configuration file
There is a configuration header file for LVGL called **lv_conf.h**. In this you can set the library's basic behavior, disable unused modules and features, adjust the size of memory buffers in compile-time, etc.
Copy **lvgl/lv_conf_template.h** next to the *lvgl* directory and rename it to *lv_conf.h*. Open the file and change the `#if 0` at the beginning to `#if 1` to enable its content.
*lv_conf.h* can be copied to another place as well but then you should add `LV_CONF_INCLUDE_SIMPLE` define to your compiler options (e.g. `-DLV_CONF_INCLUDE_SIMPLE` for gcc compiler) and set the include path manually.
In this case LVGL will attempt to include `lv_conf.h` simply with `#include "lv_conf.h"`.
In the config file comments explain the meaning of the options. Be sure to set at least `LV_COLOR_DEPTH` according to your display's color depth.
## Initialization
To use the graphics library you have to initialize it and the other components too. The order of the initialization is:
1. Call `lv_init()`.
2. Initialize your drivers.
3. Register the display and input devices drivers in LVGL. Lear more about [Display](/porting/display) and [Input device](/porting/indev) registration.
4. Call `lv_tick_inc(x)` every `x` milliseconds in an interrupt to tell the elapsed time. [Learn more](/porting/tick).
5. Call `lv_timer_handler()` every few milliseconds to handle LVGL related tasks. [Learn more](/porting/task-handler).
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.