feat(docs): reorganize docs (#7136)
This commit is contained in:
115
docs/details/other-components/file_explorer.rst
Normal file
115
docs/details/other-components/file_explorer.rst
Normal file
@@ -0,0 +1,115 @@
|
||||
.. _file_explorer:
|
||||
|
||||
=============
|
||||
File Explorer
|
||||
=============
|
||||
|
||||
``lv_file_explorer`` provides an API to browse the contents of the file
|
||||
system. ``lv_file_explorer`` only provides the file browsing function,
|
||||
but does not provide the actual file operation function. In other words,
|
||||
you can't click a picture file to open and view the picture like a PC.
|
||||
``lv_file_explorer`` will tell you the full path and name of the
|
||||
currently clicked file. The file operation function needs to be
|
||||
implemented by the user.
|
||||
|
||||
The file list in ``lv_file_explorer`` is based on
|
||||
:ref:`lv_table`, and the quick access bar is based on
|
||||
:ref:`lv_list`. Therefore, care should be taken to ensure
|
||||
that :ref:`lv_table` and :ref:`lv_list` are
|
||||
enabled.
|
||||
|
||||
.. _file_explorer_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_FILE_EXPLORER` in ``lv_conf.h``.
|
||||
|
||||
First use :cpp:expr:`lv_file_explorer_create(lv_screen_active())` to create a file
|
||||
explorer, The default size is the screen size. After that, you can
|
||||
customize the style like widget.
|
||||
|
||||
Quick access
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The quick access bar is optional. You can turn off
|
||||
:c:macro:`LV_FILE_EXPLORER_QUICK_ACCESS` in ``lv_conf.h`` so that the quick
|
||||
access bar will not be created. This can save some memory, but not much.
|
||||
After the quick access bar is created, it can be hidden by clicking the
|
||||
button at the top left corner of the browsing area, which is very useful
|
||||
for small screen devices.
|
||||
|
||||
You can use
|
||||
:cpp:expr:`lv_file_explorer_set_quick_access_path(file_explorer, LV_FILE_EXPLORER_QA_XX, "path")`
|
||||
to set the path of the quick access bar. The items of the quick access
|
||||
bar are fixed. Currently, there are the following items:
|
||||
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_HOME`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_MUSIC`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_PICTURES`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_VIDEO`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_DOCS`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_MNT`
|
||||
- :cpp:enumerator:`LV_FILE_EXPLORER_QA_FS`
|
||||
|
||||
.. _file_explorer_sort:
|
||||
|
||||
Sort
|
||||
~~~~
|
||||
|
||||
You can use
|
||||
:cpp:expr:`lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_XX)` to set
|
||||
sorting method.
|
||||
|
||||
There are the following sorting methods:
|
||||
|
||||
- :cpp:enumerator:`LV_EXPLORER_SORT_NONE`
|
||||
- :cpp:enumerator:`LV_EXPLORER_SORT_KIND`
|
||||
|
||||
You can customize the sorting. Before custom sort, please set the
|
||||
default sorting to :cpp:enumerator:`LV_EXPLORER_SORT_NONE`. The default is
|
||||
:cpp:enumerator:`LV_EXPLORER_SORT_NONE`.
|
||||
|
||||
.. _file_explorer_events:
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
- :cpp:enumerator:`LV_EVENT_READY` Sent when a directory is opened. You can customize
|
||||
the sort.
|
||||
- :cpp:enumerator:`LV_EVENT_VALUE_CHANGED` Sent when an item (file) in the file list
|
||||
is clicked.
|
||||
|
||||
You can use :cpp:func:`lv_file_explorer_get_cur_path` to get the current path
|
||||
and :cpp:func:`lv_file_explorer_get_sel_fn` to get the name of the currently
|
||||
selected file in the event processing function. For example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static void file_explorer_event_handler(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
char * cur_path = lv_file_explorer_get_cur_path(widget);
|
||||
char * sel_fn = lv_file_explorer_get_sel_fn(widget);
|
||||
LV_LOG_USER("%s%s", cur_path, sel_fn);
|
||||
}
|
||||
}
|
||||
|
||||
You can also save the obtained **path** and **file** name into an array
|
||||
through functions such as :cpp:func:`strcpy` and :cpp:func:`strcat` for later use.
|
||||
|
||||
.. _file_explorer_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/file_explorer/index.rst
|
||||
|
||||
.. _file_explorer_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
118
docs/details/other-components/font_manager.rst
Normal file
118
docs/details/other-components/font_manager.rst
Normal file
@@ -0,0 +1,118 @@
|
||||
.. _font_manager:
|
||||
|
||||
============
|
||||
Font Manager
|
||||
============
|
||||
|
||||
Font Manager is a secondary encapsulation based on :ref:`freetype`, which
|
||||
facilitates upper-level applications to manage and use vector fonts. Currently
|
||||
supported functions include:
|
||||
|
||||
- Font resource reference counting (reduces repeated creation of font resources).
|
||||
- Font resource concatenation (font fallback).
|
||||
- Font resource recycling mechanism (buffers recently deleted font resources to reduce the time overhead of repeated creation).
|
||||
|
||||
|
||||
.. _font_manager_usage:
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
Enable :c:macro:`LIB_FREETYPE` and `LV_USE_FONT_MANAGER` in ``lv_conf.h``.
|
||||
|
||||
Configure :c:macro:`LV_FONT_MANAGER_NAME_MAX_LEN` to set the maximum length of the font name.
|
||||
|
||||
Initialize Font Manager
|
||||
-----------------------
|
||||
|
||||
Use :cpp:func:`lv_font_manager_create` to create a font manager, where the
|
||||
:cpp:func:`recycle_cache_size` parameter is used to set the number of font recycling
|
||||
caches,which can improve font creation efficiency.
|
||||
|
||||
Use :cpp:func:`lv_font_manager_add_path_static` to add a mapping between the font
|
||||
file path and the custom font name, so that the application can access the font
|
||||
resources more conveniently. It should be noted that if the file path is not static
|
||||
(assigned from a local variable), please use :cpp:func:`lv_font_manager_add_path` to
|
||||
add the path. This API will copy the path content to the internal management.
|
||||
|
||||
Use :cpp:func:`lv_font_manager_remove_path` to remove the font path mapping.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static lv_font_manager_t * g_font_manager = NULL;
|
||||
|
||||
void font_manager_init(void)
|
||||
{
|
||||
/* Create font manager, with 8 fonts recycling buffers */
|
||||
g_font_manager = lv_font_manager_create(8);
|
||||
|
||||
/* Add font path mapping to font manager */
|
||||
lv_font_manager_add_path_static(g_font_manager, "Lato-Regular", "./lvgl/examples/libs/freetype/Lato-Regular.ttf");
|
||||
lv_font_manager_add_path_static(g_font_manager, "MyFont", "./path/to/myfont.ttf");
|
||||
}
|
||||
|
||||
Create Font from Font Manager
|
||||
-----------------------------
|
||||
|
||||
Use :cpp:func:`lv_font_manager_create_font` to create a font. The parameters are
|
||||
basically the same as :cpp:func:`lv_freetype_font_create`.
|
||||
|
||||
The :cpp:func:`font_family` parameter can be filled with the names of multiple fonts
|
||||
(separated by ``,``) to achieve font concatenation (when the corresponding glyph is
|
||||
not found in a font file, it will automatically search from the next concatenated
|
||||
font).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static lv_font_t * g_font = NULL;
|
||||
|
||||
/* Create font from font manager */
|
||||
lv_font_t * g_font = lv_font_manager_create_font(g_font_manager,
|
||||
"Lato-Regular,MyFont",
|
||||
LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
|
||||
24,
|
||||
LV_FREETYPE_FONT_STYLE_NORMAL);
|
||||
|
||||
/* Create label with the font */
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
lv_obj_set_style_text_font(label, g_font, 0);
|
||||
lv_label_set_text(label, "Hello World!");
|
||||
|
||||
Delete Font
|
||||
-----------
|
||||
|
||||
Use :cpp:func:`lv_font_manager_delete_font` to delete the font.
|
||||
The font manager will mark the font resource as a recyclable font so that it can be
|
||||
quickly created next time.
|
||||
|
||||
Note that you need to delete the widget that references the font first, and then
|
||||
delete the font to avoid accessing wild pointers.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Delete label and font */
|
||||
lv_obj_delete(label);
|
||||
lv_font_manager_delete_font(g_font_manager, g_font);
|
||||
g_font = NULL;
|
||||
|
||||
Delete Font Manager
|
||||
-------------------
|
||||
|
||||
Use :cpp:func:`lv_font_manager_delete` to destroy the entire font manager. It should
|
||||
be noted that before destruction, it is necessary to ensure that the application has
|
||||
deleted all fonts using :cpp:func:`lv_font_manager_delete_font`. The font manager
|
||||
will check the reference status of all allocated fonts. If there are still fonts
|
||||
being referenced, the font manager will fail to destroy and return false.
|
||||
|
||||
|
||||
.. _font_manager_example:
|
||||
|
||||
Example
|
||||
*******
|
||||
|
||||
.. include:: ../../examples/others/font_manager/index.rst
|
||||
|
||||
.. _font_manager_api:
|
||||
|
||||
API
|
||||
***
|
||||
86
docs/details/other-components/fragment.rst
Normal file
86
docs/details/other-components/fragment.rst
Normal file
@@ -0,0 +1,86 @@
|
||||
.. _fragment:
|
||||
|
||||
========
|
||||
Fragment
|
||||
========
|
||||
|
||||
Fragment is a concept copied from
|
||||
`Android <https://developer.android.com/guide/fragments>`__.
|
||||
|
||||
It represents a reusable portion of your app's UI. A fragment defines
|
||||
and manages its own layout, has its own lifecycle, and can handle its
|
||||
own events. Like Android's Fragment that must be hosted by an activity
|
||||
or another fragment, Fragment in LVGL needs to be hosted by a Widget,
|
||||
or another fragment. The fragment's view hierarchy becomes part of, or
|
||||
attaches to, the host's view hierarchy.
|
||||
|
||||
Such concept also has some similarities to `UiViewController on
|
||||
iOS <https://developer.apple.com/documentation/uikit/uiviewcontroller>`__.
|
||||
|
||||
Fragment Manager is a manager holding references to fragments attached
|
||||
to it, and has an internal stack to achieve navigation. You can use
|
||||
fragment manager to build navigation stack, or multi pane application
|
||||
easily.
|
||||
|
||||
.. _fragment_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_FRAGMENT` in ``lv_conf.h``.
|
||||
|
||||
Create Fragment Class
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct sample_fragment_t {
|
||||
/* IMPORTANT: don't miss this part */
|
||||
lv_fragment_t base;
|
||||
/* States, object references and data fields for this fragment */
|
||||
const char *title;
|
||||
};
|
||||
|
||||
const lv_fragment_class_t sample_cls = {
|
||||
/* Initialize something needed */
|
||||
.constructor_cb = sample_fragment_ctor,
|
||||
/* Create view objects */
|
||||
.create_obj_cb = sample_fragment_create_obj,
|
||||
/* IMPORTANT: size of your fragment struct */
|
||||
.instance_size = sizeof(struct sample_fragment_t),
|
||||
};
|
||||
|
||||
Use ``lv_fragment_manager``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Create fragment instance, and Widgets will be added to container */
|
||||
lv_fragment_manager_t *manager = lv_fragment_manager_create(container, NULL);
|
||||
/* Replace current fragment with instance of sample_cls, and init_argument is user defined pointer */
|
||||
lv_fragment_manager_replace(manager, &sample_cls, init_argument);
|
||||
|
||||
Fragment Based Navigation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Add one instance into manager stack. View object of current fragment will be destroyed,
|
||||
* but instances created in class constructor will be kept.
|
||||
*/
|
||||
lv_fragment_manager_push(manager, &sample_cls, NULL);
|
||||
|
||||
/* Remove the top most fragment from the stack, and bring back previous one. */
|
||||
lv_fragment_manager_pop(manager);
|
||||
|
||||
.. _fragment_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/fragment/index.rst
|
||||
|
||||
.. _fragment_api:
|
||||
|
||||
API
|
||||
---
|
||||
83
docs/details/other-components/gridnav.rst
Normal file
83
docs/details/other-components/gridnav.rst
Normal file
@@ -0,0 +1,83 @@
|
||||
.. _gridnav:
|
||||
|
||||
===============
|
||||
Grid navigation
|
||||
===============
|
||||
|
||||
Grid navigation (gridnav for short) is a feature that changes the
|
||||
currently focused child Widget as arrow keys are pressed.
|
||||
|
||||
If the children are arranged into a grid-like layout then the up, down,
|
||||
left and right arrows move focus to the nearest sibling in the
|
||||
respective direction.
|
||||
|
||||
It doesn't matter how the children are positioned, as only the current x
|
||||
and y coordinates are considered. This means that gridnav works with
|
||||
manually positioned children, as well as :ref:`flex` and
|
||||
:ref:`grid` layouts.
|
||||
|
||||
Gridnav also works if the children are arranged into a single row or
|
||||
column. That makes it useful, for example, to simplify navigation on a
|
||||
:ref:`List widget <lv_list>`.
|
||||
|
||||
Gridnav assumes that the Widget to which gridnav is added is part of a
|
||||
:ref:`group <indev_groups>`. This way, if the Widget with
|
||||
gridnav has focus, the arrow key presses are automatically forwarded to
|
||||
the Widget so that gridnav can process the arrow keys.
|
||||
|
||||
To move the focus to the next widget of the group use
|
||||
:cpp:enumerator:`LV_KEY_NEXT` or :cpp:enumerator:`LV_KEY_PREV`.
|
||||
Optionally you can also use :cpp:func:`lv_group_focus_next`
|
||||
or :cpp:func:`lv_group_focus_prev` or the ``TAB``
|
||||
key on keyboard as usual.
|
||||
|
||||
If the container is scrollable and the focused child is out of the view,
|
||||
gridnav will automatically scroll the child into view.
|
||||
|
||||
.. _gridnav_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To add the gridnav feature to a Widget use
|
||||
:cpp:expr:`lv_gridnav_add(cont, flags)`.
|
||||
|
||||
``flags`` control the behavior of gridnav:
|
||||
|
||||
- :cpp:enumerator:`LV_GRIDNAV_CTRL_NONE`: Default settings
|
||||
- :cpp:enumerator:`LV_GRIDNAV_CTRL_ROLLOVER`: If there is no next/previous Widget in a
|
||||
direction, the focus goes to the Widget in the next/previous row (on
|
||||
left/right keys) or first/last row (on up/down keys)
|
||||
- :cpp:enumerator:`LV_GRIDNAV_CTRL_SCROLL_FIRST`: If an arrow is pressed and the focused
|
||||
Widget can be scrolled in that direction then it will be scrolled instead of
|
||||
going to the next/previous Widget. If there is no more room for scrolling the
|
||||
next/previous Widget will be focused normally
|
||||
- :cpp:enumerator:`LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY`: Only use the left/right keys
|
||||
for grid navigation. Up/down key events will be sent to the focused Widget.
|
||||
- :cpp:enumerator:`LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY`: Only use the up/down keys
|
||||
for grid navigation. Left/right key events will be sent to the focused Widget.
|
||||
|
||||
:cpp:enumerator:`LV_GRIDNAV_CTRL_HORIZONTAL_MOVE_ONLY` and :cpp:enumerator:`LV_GRIDNAV_CTRL_VERTICAL_MOVE_ONLY`
|
||||
should not be used together.
|
||||
|
||||
:cpp:expr:`lv_gridnav_remove(cont)` Removes gridnav from a Widget.
|
||||
|
||||
Focusable Widgets
|
||||
-----------------
|
||||
|
||||
A Widget needs to be clickable or click focusable
|
||||
(:cpp:enumerator:`LV_OBJ_FLAG_CLICKABLE` or :cpp:enumerator:`LV_OBJ_FLAG_CLICK_FOCUSABLE`) and not
|
||||
hidden (:cpp:enumerator:`LV_OBJ_FLAG_HIDDEN`) to be focusable by gridnav.
|
||||
|
||||
.. _gridnav_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/gridnav/index.rst
|
||||
|
||||
.. _gridnav_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
127
docs/details/other-components/ime_pinyin.rst
Normal file
127
docs/details/other-components/ime_pinyin.rst
Normal file
@@ -0,0 +1,127 @@
|
||||
.. _ime_pinyin:
|
||||
|
||||
==========
|
||||
Pinyin IME
|
||||
==========
|
||||
|
||||
Pinyin IME provides API to provide Chinese Pinyin input method (Chinese
|
||||
input) for keyboard object, which supports 26 key and 9 key input modes.
|
||||
You can think of ``lv_ime_pinyin`` as a Pinyin input method plug-in for
|
||||
keyboard objects.
|
||||
|
||||
Normally, an environment where :ref:`lv_keyboard` can
|
||||
run can also run ``lv_ime_pinyin``. There are two main influencing
|
||||
factors: the size of the font file and the size of the dictionary.
|
||||
|
||||
|
||||
.. _ime_pinyin_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_IME_PINYIN` in ``lv_conf.h``.
|
||||
|
||||
First use :cpp:expr:`lv_ime_pinyin_create(lv_screen_active())` to create a Pinyin
|
||||
input method plug-in, then use
|
||||
:cpp:expr:`lv_ime_pinyin_set_keyboard(pinyin_ime, kb)` to add the ``keyboard``
|
||||
you created to the Pinyin input method plug-in. You can use
|
||||
:cpp:expr:`lv_ime_pinyin_set_dict(pinyin_ime, your_dict)` to use a custom
|
||||
dictionary (if you don't want to use the built-in dictionary at first,
|
||||
you can disable :c:macro:`LV_IME_PINYIN_USE_DEFAULT_DICT` in ``lv_conf.h``,
|
||||
which can save a lot of memory space).
|
||||
|
||||
The built-in thesaurus is customized based on the
|
||||
**LV_FONT_SIMSUN_16_CJK** font library, which currently only has more
|
||||
than ``1,000`` most common CJK radicals, so it is recommended to use
|
||||
custom fonts and thesaurus.
|
||||
|
||||
In the process of using the Pinyin input method plug-in, you can change
|
||||
the keyboard and dictionary at any time.
|
||||
|
||||
|
||||
Custom dictionary
|
||||
-----------------
|
||||
|
||||
If you don't want to use the built-in Pinyin dictionary, you can use the
|
||||
custom dictionary. Or if you think that the built-in phonetic dictionary
|
||||
consumes a lot of memory, you can also use a custom dictionary.
|
||||
|
||||
Customizing the dictionary is very simple.
|
||||
|
||||
First, set :c:macro:`LV_IME_PINYIN_USE_DEFAULT_DICT` to ``0`` in ``lv_conf.h``
|
||||
|
||||
Then, write a dictionary in the following format.
|
||||
|
||||
|
||||
Dictionary format
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The arrangement order of each pinyin syllable is very important. You
|
||||
need to customize your own thesaurus according to the Hanyu Pinyin
|
||||
syllable table. You can read
|
||||
`here <https://baike.baidu.com/item/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E9%9F%B3%E8%8A%82/9167981>`__
|
||||
to learn about the Hanyu Pinyin syllables and the syllable table.
|
||||
|
||||
Then, write your own dictionary according to the following format:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_100ask_pinyin_dict_t your_pinyin_dict[] = {
|
||||
{ "a", "啊阿呵吖" },
|
||||
{ "ai", "埃挨哎唉哀皑蔼矮碍爱隘癌艾" },
|
||||
{ "an", "按安暗岸俺案鞍氨胺厂广庵揞犴铵桉谙鹌埯黯" },
|
||||
{ "ang", "昂肮盎仰" },
|
||||
{ "ao", "凹敖熬翱袄傲奥懊澳" },
|
||||
{ "ba", "芭捌叭吧笆八疤巴拔跋靶把坝霸罢爸扒耙" },
|
||||
{ "bai", "白摆佰败拜柏百稗伯" },
|
||||
/* ...... */
|
||||
{ "zuo", "昨左佐做作坐座撮琢柞"},
|
||||
{NULL, NULL}
|
||||
|
||||
**The last item** must end with ``{null, null}``, or it will not work
|
||||
properly.
|
||||
|
||||
|
||||
.. _ime_pinyin_apply_new_dictionary:
|
||||
|
||||
Apply new dictionary
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After writing a dictionary according to the above dictionary format, you
|
||||
only need to call this function to set up and use your dictionary:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_obj_t * pinyin_ime = lv_100ask_pinyin_ime_create(lv_screen_active());
|
||||
lv_100ask_pinyin_ime_set_dict(pinyin_ime, your_pinyin_dict);
|
||||
|
||||
|
||||
.. _ime_pinyin_modes:
|
||||
|
||||
Modes
|
||||
-----
|
||||
|
||||
The lv_ime_pinyin have the following modes:
|
||||
|
||||
- :cpp:enumerator:`LV_IME_PINYIN_MODE_K26`: Pinyin 26 key input mode
|
||||
- :cpp:enumerator:`LV_IME_PINYIN_MODE_K9`: Pinyin 9 key input mode
|
||||
- :cpp:enumerator:`LV_IME_PINYIN_MODE_K9_NUMBER`: Numeric keypad mode
|
||||
|
||||
The ``TEXT`` modes' layout contains buttons to change mode.
|
||||
|
||||
To set the mode manually, use :cpp:expr:`lv_ime_pinyin_set_mode(pinyin_ime, mode)`.
|
||||
The default mode is :cpp:enumerator:`LV_IME_PINYIN_MODE_K26`.
|
||||
|
||||
|
||||
.. _ime_pinyin_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/ime/index.rst
|
||||
|
||||
.. _ime_pinyin_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
41
docs/details/other-components/imgfont.rst
Normal file
41
docs/details/other-components/imgfont.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
.. _lv_imgfont:
|
||||
|
||||
==========
|
||||
Image font
|
||||
==========
|
||||
|
||||
Draw image in **label** or **span** obj with :cpp:type:`lv_imgfont`. This is often used to
|
||||
display Unicode emoji icons in text.
|
||||
|
||||
Supported image formats: determined by enabled LVGL :ref:`image decoders <overview_image_decoder>`.
|
||||
|
||||
.. _lv_imgfont_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_IMGFONT` in ``lv_conf.h``.
|
||||
|
||||
To create a new *imgfont* use :cpp:expr:`lv_imgfont_create(height, path_cb, user_data)`.
|
||||
|
||||
- ``height`` Font size.
|
||||
- ``path_cb`` A function to get the image path of a character.
|
||||
Return ``NULL`` if no image should be shown, but the character itself.
|
||||
- ``user_data`` Pointer to user data.
|
||||
|
||||
To use the *imgfont* in a label, reference it:
|
||||
:cpp:expr:`lv_obj_set_style_text_font(label, imgfont, LV_PART_MAIN)`
|
||||
|
||||
To destroy the *imgfont* that is no longer used, use :cpp:expr:`lv_imgfont_destroy(imgfont)`.
|
||||
|
||||
.. _lv_imgfont_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/imgfont/index.rst
|
||||
|
||||
.. _lv_imgfont_api:
|
||||
|
||||
API
|
||||
---
|
||||
20
docs/details/other-components/index.rst
Normal file
20
docs/details/other-components/index.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
.. _others:
|
||||
|
||||
================
|
||||
Other Components
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
file_explorer
|
||||
font_manager
|
||||
fragment
|
||||
gridnav
|
||||
ime_pinyin
|
||||
imgfont
|
||||
monkey
|
||||
obj_id
|
||||
obj_property
|
||||
observer
|
||||
snapshot
|
||||
48
docs/details/other-components/monkey.rst
Normal file
48
docs/details/other-components/monkey.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
.. _monkey:
|
||||
|
||||
======
|
||||
Monkey
|
||||
======
|
||||
|
||||
A simple monkey test. Use random input to stress test the application.
|
||||
|
||||
.. _monkey_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable :c:macro:`LV_USE_MONKEY` in ``lv_conf.h``.
|
||||
|
||||
First configure monkey, use :c:struct:`lv_monkey_config_t` to define the
|
||||
configuration structure, set the ``type`` (check :ref:`Input Devices <indev>`
|
||||
for the supported types), and then set the
|
||||
range of ``period_range`` and ``input_range``, the monkey will output
|
||||
random operations at random times within this range. Call
|
||||
:cpp:func:`lv_monkey_create` to create monkey. Finally call
|
||||
:cpp:expr:`lv_monkey_set_enable(monkey, true)` to enable monkey.
|
||||
|
||||
If you want to pause the monkey, call
|
||||
:cpp:expr:`lv_monkey_set_enable(monkey, false)`. To delete the monkey, call
|
||||
:cpp:expr:`lv_monkey_delete(monkey)`.
|
||||
|
||||
Note that ``input_range`` has different meanings in different ``type``:
|
||||
|
||||
- :cpp:enumerator:`LV_INDEV_TYPE_POINTER`: No effect, click randomly within the pixels of the screen resolution.
|
||||
- :cpp:enumerator:`LV_INDEV_TYPE_ENCODER`: The minimum and maximum values of ``enc_diff``.
|
||||
- :cpp:enumerator:`LV_INDEV_TYPE_BUTTON`: The minimum and maximum values of ``btn_id``.
|
||||
Use :cpp:func:`lv_monkey_get_indev` to get the input device, and use
|
||||
:cpp:func:`lv_indev_set_button_points` to map the key ID to the coordinates.
|
||||
- :cpp:enumerator:`LV_INDEV_TYPE_KEYPAD`: No effect, Send random :ref:`indev_keys`.
|
||||
|
||||
.. _monkey_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/monkey/index.rst
|
||||
|
||||
.. _monkey_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
66
docs/details/other-components/obj_id.rst
Normal file
66
docs/details/other-components/obj_id.rst
Normal file
@@ -0,0 +1,66 @@
|
||||
.. _obj_id:
|
||||
|
||||
=========
|
||||
Widget ID
|
||||
=========
|
||||
|
||||
LVGL provides an optional field in :cpp:type:`lv_obj_t` to store the Widget ID.
|
||||
Widget ID can be used in many cases, for example, to identify the Widget.
|
||||
Or we can store a program backtrace to where the Widget is created.
|
||||
|
||||
.. _obj_id_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Enable this feature by setting :c:macro:`LV_USE_OBJ_ID` to `1` in ``lv_conf.h``.
|
||||
|
||||
Enable :c:macro:`LV_OBJ_ID_AUTO_ASSIGN` to automatically assign an ID to Widget when it's created.
|
||||
It's done by calling function :cpp:func:`lv_obj_assign_id` from :cpp:func:`lv_obj_constructor`.
|
||||
|
||||
You can either use your own ID generator by defining the function :cpp:func:`lv_obj_assign_id` or you can utilize the built-in one.
|
||||
To use the builtin ID generator, set :c:macro:`LV_USE_OBJ_ID_BUILTIN` to `1`.
|
||||
|
||||
You can directly access the ID by :cpp:expr:`lv_obj_get_id(widget)` or use API :cpp:expr:`lv_obj_stringify_id(widget, buf, len)`
|
||||
to get a string representation of the ID.
|
||||
|
||||
Use custom ID generator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Set :c:macro:`LV_USE_OBJ_ID_BUILTIN` to `0` in ``lv_conf.h``.
|
||||
|
||||
Below APIs needed to be implemented and linked to lvgl.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void lv_obj_set_id(lv_obj_t * widget, void * id);
|
||||
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * widget);
|
||||
void lv_obj_free_id(lv_obj_t * widget);
|
||||
const char * lv_obj_stringify_id(lv_obj_t * widget, char * buf, uint32_t len);
|
||||
int lv_obj_id_compare(void * id1, void * id2);
|
||||
|
||||
|
||||
:cpp:func:`lv_obj_assign_id` is called when a Widget is created. The Widget final class is passed from
|
||||
parameter ``class_p``. Note it may be different than :cpp:expr:`obj->class_p` which is the class
|
||||
currently being constructed.
|
||||
|
||||
:cpp:func:`lv_obj_free_id` is called when Widget is deconstructed. Free any resource allocated in :cpp:func:`lv_obj_assign_id`.
|
||||
|
||||
:cpp:func:`lv_obj_stringify_id` converts id to a string representation. The string is stored in ``buf``.
|
||||
|
||||
Dump Widget Tree
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Use API ``lv_obj_dump_tree(lv_obj_t * widget, int depth)`` to dump the Widget Tree.
|
||||
It will walk through all children and print the Widget ID together with Widget address.
|
||||
|
||||
This is useful to debug UI crash. From log we can rebuilt UI the moment before crash.
|
||||
For example, if the obj is stored to a :cpp:expr:`timer->user_data`, but obj is deleted when timer expired.
|
||||
Timer callback will crash because of accessing wild pointer.
|
||||
From the dump log we can clearly see that the obj does not exist.
|
||||
|
||||
Find child by ID
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Use API ``lv_obj_t * lv_obj_get_child_by_id(const lv_obj_t * widget, void * id)`` to find a child by ID.
|
||||
It will walk through all children and return the first child with the given ID.
|
||||
89
docs/details/other-components/obj_property.rst
Normal file
89
docs/details/other-components/obj_property.rst
Normal file
@@ -0,0 +1,89 @@
|
||||
.. _obj_property:
|
||||
|
||||
===============
|
||||
Widget Property
|
||||
===============
|
||||
|
||||
Widgets have many properties that can decide what they look like and how they behave.
|
||||
For example, the size, position, color, font, etc. are properties of a widget.
|
||||
Specially, widget local style is also a property of a widget.
|
||||
|
||||
.. _obj_property_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Two APIs are provided to get/set widget properties. It can be enabled by setting
|
||||
:c:macro:`LV_USE_OBJ_PROPERTY` to `1` in ``lv_conf.h``.
|
||||
|
||||
Set :c:macro:`LV_USE_OBJ_PROPERTY_NAME` to `1` in order to use property name instead of ID.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef struct {
|
||||
lv_prop_id_t id;
|
||||
union {
|
||||
int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers) */
|
||||
const void * ptr; /**< Constant pointers (font, cone text, etc) */
|
||||
lv_color_t color; /**< Colors */
|
||||
lv_value_precise_t precise; /**< float or int for precise value */
|
||||
struct {
|
||||
lv_style_value_t style; /**< Make sure it's the first element in struct. */
|
||||
uint32_t selector; /**< Style selector, lv_part_t | lv_state_t */
|
||||
};
|
||||
};
|
||||
} lv_property_t;
|
||||
|
||||
lv_result_t lv_obj_set_property(lv_obj_t * widget, const lv_property_t * value);
|
||||
lv_property_t lv_obj_get_property(lv_obj_t * widget, lv_prop_id_t id);
|
||||
|
||||
lv_prop_id_t lv_obj_property_get_id(const lv_obj_class_t * clz, const char * name);
|
||||
|
||||
.. _obj_property_id:
|
||||
|
||||
Property ID
|
||||
~~~~~~~~~~~
|
||||
|
||||
:cpp:type:`lv_prop_id_t` identifies which property to get/set. :cpp:type:`lv_property_t` is an enum value
|
||||
defined in ``lv_obj_property.h`` that are grouped by widget class. You can add your own
|
||||
widget property ID following same rule and using helper macro :c:macro:`LV_PROPERTY_ID`.
|
||||
Do make sure the ID is unique across all widgets.
|
||||
|
||||
|
||||
Property ID is a 32-bit value. The higher 4bits indicates the property value type.
|
||||
The lower 28bits is the property ID.
|
||||
|
||||
Note that :cpp:type:`lv_style_prop_t` is also valid property ID.
|
||||
|
||||
.. _obj_property_value:
|
||||
|
||||
Property Value
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Property value is a union of all possible property types including integer, pointer and color.
|
||||
``_style`` is kept their just to indicate it's compatible with ``style`` value type.
|
||||
|
||||
|
||||
A Step Further
|
||||
--------------
|
||||
The unified widget property set/get API is useful when developing wrapper layer for other
|
||||
modules like micropython, lua, or for an external animation engine.
|
||||
|
||||
For pointer type of property value, which typically points to a specific struct, it still needs
|
||||
additional code to convert values from dict, table etc to a C struct before setting to widget.
|
||||
|
||||
Another possible use case is to ease of creating UI from lots of code. For example, you can gather
|
||||
all properties to an array now and set properties with a for loop.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_property_t props[] = {
|
||||
{ .id = LV_PROPERTY_IMAGE_SRC, .ptr = &img_demo_widgets_avatar, },
|
||||
{ .id = LV_PROPERTY_IMAGE_PIVOT, .ptr = &pivot_50, },
|
||||
{ .id = LV_PROPERTY_IMAGE_SCALE, .num = 128, },
|
||||
{ .id = LV_PROPERTY_OBJ_FLAG_CLICKABLE, .num = 1, },
|
||||
{ .id = LV_STYLE_IMAGE_OPA, .num = 128, },
|
||||
{ .id = LV_STYLE_BG_COLOR, .color = (lv_color_t){.red = 0x11, .green = 0x22, .blue = 0x33}, },
|
||||
}
|
||||
|
||||
LV_OBJ_SET_PROPERTY_ARRAY(widget, props);
|
||||
342
docs/details/other-components/observer.rst
Normal file
342
docs/details/other-components/observer.rst
Normal file
@@ -0,0 +1,342 @@
|
||||
.. _observer:
|
||||
|
||||
========
|
||||
Observer
|
||||
========
|
||||
|
||||
.. _observer_overview:
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
The ``lv_observer`` module implements a standard `Observer pattern <https://en.wikipedia.org/wiki/Observer_pattern>`__.
|
||||
|
||||
It consists of:
|
||||
|
||||
- **subjects**: each containing a value
|
||||
- **observers**: attached to subjects to be notified on value change
|
||||
|
||||
|
||||
A typical use case looks like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
//It's a global variable
|
||||
lv_subject_t my_subject;
|
||||
|
||||
/*-------
|
||||
* main.c
|
||||
*-------*/
|
||||
|
||||
extern lv_subject_t my_subject;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
//Initialize the subject as integer with the default value of 10
|
||||
lv_subject_init_int(&my_subject, 10);
|
||||
|
||||
some_module_init();
|
||||
}
|
||||
|
||||
/*--------------
|
||||
* some_module.c
|
||||
*--------------*/
|
||||
|
||||
extern lv_subject_t some_subject;
|
||||
|
||||
//Will be called when the related subject's value changes
|
||||
static void some_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
int32_t v = lv_subject_get_int(subject);
|
||||
do_something(v);
|
||||
}
|
||||
|
||||
void some_module_init(void)
|
||||
{
|
||||
//Subscribe to a subject
|
||||
lv_subject_add_observer(&some_subject, some_observer_cb, NULL);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
* some_system.c
|
||||
*--------------*/
|
||||
|
||||
extern lv_subject_t some_subject;
|
||||
|
||||
void some_event(void)
|
||||
{
|
||||
//Set the subject's value to 30. It will notify `some_observer_cb`
|
||||
lv_subject_set_int(&some_subject, 30);
|
||||
}
|
||||
|
||||
|
||||
.. _observer_subject:
|
||||
|
||||
Subject
|
||||
*******
|
||||
|
||||
Subject initialization
|
||||
----------------------
|
||||
|
||||
Subjects have to be static or global :cpp:type:`lv_subject_t` type variables.
|
||||
|
||||
To initialize a subject use ``lv_subject_init_<type>(&subject, params, init_value)``.
|
||||
The following initializations exist for types:
|
||||
|
||||
- **Integer** ``void lv_subject_init_int(lv_subject_t * subject, int32_t value)``
|
||||
- **String** ``void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value)``
|
||||
- **Pointer** ``void lv_subject_init_pointer(lv_subject_t * subject, void * value)``
|
||||
- **Color** ``void lv_subject_init_color(lv_subject_t * subject, lv_color_t color)``
|
||||
- **Group** ``void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len)``
|
||||
|
||||
|
||||
Set subject value
|
||||
-----------------
|
||||
|
||||
The following functions can be used to set a subject's value:
|
||||
|
||||
- **Integer** ``void lv_subject_set_int(lv_subject_t * subject, int32_t value)``
|
||||
- **String** ``void lv_subject_copy_string(lv_subject_t * subject, char * buf)``
|
||||
- **Pointer** ``void lv_subject_set_pointer(lv_subject_t * subject, void * ptr)``
|
||||
- **Color** ``void lv_subject_set_color(lv_subject_t * subject, lv_color_t color)``
|
||||
|
||||
Get subject's value
|
||||
-------------------
|
||||
|
||||
The following functions can be used to get a subject's value:
|
||||
|
||||
|
||||
- **Integer** ``int32_t lv_subject_get_int(lv_subject_t * subject)``
|
||||
- **String** ``const char * lv_subject_get_string(lv_subject_t * subject)``
|
||||
- **Pointer** ``const void * lv_subject_get_pointer(lv_subject_t * subject)``
|
||||
- **Color** ``lv_color_t lv_subject_get_color(lv_subject_t * subject)``
|
||||
|
||||
|
||||
Get subject's previous value
|
||||
----------------------------
|
||||
|
||||
The following functions can be used to get a subject's previous value:
|
||||
|
||||
|
||||
- **Integer** ``int32_t lv_subject_get_previous_int(lv_subject_t * subject)``
|
||||
- **String** ``const char * lv_subject_get_previous_string(lv_subject_t * subject)``
|
||||
- **Pointer** ``const void * lv_subject_get_previous_pointer(lv_subject_t * subject)``
|
||||
- **Color** ``lv_color_t lv_subject_get_previous_color(lv_subject_t * subject)``
|
||||
|
||||
.. _observer_observer:
|
||||
|
||||
Observer
|
||||
********
|
||||
|
||||
Subscribe to a subject
|
||||
----------------------
|
||||
|
||||
To subscribe to a subject the following function can be used:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer(&some_subject, some_observer_cb, user_data);
|
||||
|
||||
|
||||
Where the observer callback should look like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static void some_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
It's also possible to save a target widget when subscribing to a subject.
|
||||
In this case when widget is deleted, it will automatically unsubscribe from the subject.
|
||||
|
||||
In the observer callback :cpp:expr:`lv_observer_get_target(observer)` can be used to get the saved widget.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_obj(&some_subject, some_observer_cb, widget, user_data);
|
||||
|
||||
|
||||
In more generic case any pointer can be saved a target:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_observer_t * observer = lv_subject_add_observer_with_target(&some_subject, some_observer_cb, some_pointer, user_data);
|
||||
|
||||
|
||||
|
||||
Unsubscribe from a subject
|
||||
--------------------------
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* `observer` is the return value of `lv_subject_add_observer*` */
|
||||
lv_observer_remove(observer);
|
||||
|
||||
To unsubscribe a widget from a given or all subject use:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_obj_remove_from_subject(widget, subject); /* `subject` can be NULL to unsubcribe from all */
|
||||
|
||||
.. _observer_subject_groups:
|
||||
|
||||
Subject groups
|
||||
**************
|
||||
|
||||
There are cases when a subject changes and the value of some other subjects are also required by the observer.
|
||||
As a practical example imagine an instrument which measures either voltage or current.
|
||||
To display the measured value on a label 3 things are required:
|
||||
|
||||
1. What do we measure (current or voltage)?
|
||||
2. What is the measured value?
|
||||
3. What is the range or unit (mV, V, mA, A)?
|
||||
|
||||
When any of these 3 parameters changes the label needs to be updated,
|
||||
and it needs to know all 3 parameters to compose its text.
|
||||
|
||||
To handle this you can create an array from some existing subjects and pass
|
||||
this array as a parameter when you initialize a subject with group type.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static lv_subject_t * subject_list[3] = {&subject_1, &subject_2, &subject_3};
|
||||
lv_subject_init_group(&subject_all, subject_list, 3); /*The last parameter is the number of elements */
|
||||
|
||||
You can add observers to subject groups in the regular way.
|
||||
The trick is that when any element of the group is notified the subject group will be notified as well.
|
||||
|
||||
The above Voltage/Current measurement example looks like this in the practice:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
|
||||
lv_subject_t subject_mode; //Voltage or Current
|
||||
lv_subject_t subject_value; //Measured value
|
||||
lv_subject_t subject_unit; //The unit
|
||||
lv_subject_t subject_all; //It will be the subject group
|
||||
lv_subject_t * subject_list[3] = {&subject_mode, &subject_value, &subject_unit}; //The elements of the group
|
||||
|
||||
lv_subject_init_int(&subject_mode, 0); //Let's say 0 is Voltage, 1 is Current
|
||||
lv_subject_init_int(&subject_value, 0);
|
||||
lv_subject_init_pointer(&subject_unit, "V");
|
||||
lv_subject_init_group(&subject_all, subject_list, 3);
|
||||
|
||||
lv_subject_add_observer_obj(&subject_all, all_observer_cb, label, NULL);
|
||||
|
||||
...
|
||||
|
||||
static void all_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||
{
|
||||
lv_obj_t * label = lv_observer_get_target(observer);
|
||||
lv_subject_t * subject_mode = lv_subject_get_group_element(subject, 0);
|
||||
lv_subject_t * subject_value = lv_subject_get_group_element(subject, 1);
|
||||
lv_subject_t * subject_unit = lv_subject_get_group_element(subject, 2);
|
||||
|
||||
int32_t mode = lv_subject_get_int(subject_mode);
|
||||
int32_t value = lv_subject_get_int(subject_value);
|
||||
const char * unit = lv_subject_get_pointer(subject_unit);
|
||||
|
||||
lv_label_set_text_fmt(label, "%s: %d %s", mode ? "Current" : "Voltage", value, unit);
|
||||
}
|
||||
|
||||
|
||||
.. _observer_widget_binding:
|
||||
|
||||
Widget binding
|
||||
**************
|
||||
|
||||
Base Widget
|
||||
-----------
|
||||
|
||||
Set a Widget flag if an integer subject's value is equal to a reference value, clear the flag otherwise
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_obj_bind_flag_if_eq(widget, &subject, LV_OBJ_FLAG_*, ref_value);
|
||||
|
||||
Set a Widget flag if an integer subject's value is not equal to a reference value, clear the flag otherwise
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_obj_bind_flag_if_not_eq(widget, &subject, LV_OBJ_FLAG_*, ref_value);
|
||||
|
||||
Set a Widget state if an integer subject's value is equal to a reference value, clear the flag otherwise
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_obj_bind_state_if_eq(widget, &subject, LV_STATE_*, ref_value);
|
||||
|
||||
Set a Widget state if an integer subject's value is not equal to a reference value, clear the flag otherwise
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_obj_bind_state_if_not_eq(widget, &subject, LV_STATE_*, ref_value);
|
||||
|
||||
Set an integer subject to 1 when a Widget is checked and set it 0 when unchecked.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_obj_bind_checked(widget, &subject);
|
||||
|
||||
Label
|
||||
-----
|
||||
|
||||
Bind an integer, string, or pointer (pointing to a string) subject to a label.
|
||||
An optional format string can be added with 1 format specifier (e.g. ``"%d °C"``)
|
||||
If the format string is ``NULL`` the value will be used directly. In this case on string and pointer type subjects can be used.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_label_bind_text(widget, &subject, format_string);
|
||||
|
||||
|
||||
Arc
|
||||
---
|
||||
|
||||
Bind an integer subject to an arc's value.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_arc_bind_value(widget, &subject);
|
||||
|
||||
Slider
|
||||
------
|
||||
|
||||
Bind an integer subject to a slider's value
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_slider_bind_value(widget, &subject);
|
||||
|
||||
Roller
|
||||
------
|
||||
|
||||
Bind an integer subject to a roller's value
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_roller_bind_value(widget, &subject);
|
||||
|
||||
|
||||
Drop-down
|
||||
---------
|
||||
Bind an integer subject to a drop-down's value
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
observer = lv_dropdown_bind_value(widget, &subject);
|
||||
|
||||
.. _observer_example:
|
||||
|
||||
Example
|
||||
*******
|
||||
|
||||
.. include:: ../../examples/others/observer/index.rst
|
||||
|
||||
.. _observer_api:
|
||||
|
||||
API
|
||||
***
|
||||
77
docs/details/other-components/snapshot.rst
Normal file
77
docs/details/other-components/snapshot.rst
Normal file
@@ -0,0 +1,77 @@
|
||||
.. _snapshot:
|
||||
|
||||
========
|
||||
Snapshot
|
||||
========
|
||||
|
||||
Snapshot provides API to take snapshot image for LVGL Widget together
|
||||
with its children. The image will look exactly like the Widget on display.
|
||||
|
||||
.. _snapshot_usage:
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Simply call API :cpp:func:`lv_snapshot_take` to generate the image descriptor
|
||||
which can be set as image Widget src using :cpp:func:`lv_image_set_src`.
|
||||
|
||||
Note, only following color formats are supported for now:
|
||||
|
||||
- :cpp:enumerator:`LV_COLOR_FORMAT_RGB565`
|
||||
- :cpp:enumerator:`LV_COLOR_FORMAT_RGB888`
|
||||
- :cpp:enumerator:`LV_COLOR_FORMAT_XRGB8888`
|
||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB8888`
|
||||
|
||||
Free the Image
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The memory :cpp:func:`lv_snapshot_take` uses are dynamically allocated using
|
||||
:cpp:func:`lv_draw_buf_create`. Use API :cpp:func:`lv_draw_buf_destroy` to free the memory it
|
||||
takes. This will firstly free memory the image data takes, then the
|
||||
image descriptor.
|
||||
|
||||
The snapshot image which is the draw buffer returned by :cpp:func:`lv_snapshot_take`
|
||||
normally won't be added to cache because it can be drawn directly. So you don't need
|
||||
to invalidate cache by :cpp:func:`lv_image_cache_drop` before destroy the draw buffer.
|
||||
|
||||
Below code snippet explains usage of this API.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void update_snapshot(lv_obj_t * widget, lv_obj_t * img_snapshot)
|
||||
{
|
||||
lv_draw_buf_t* snapshot = (void*)lv_image_get_src(img_snapshot);
|
||||
if(snapshot) {
|
||||
lv_draw_buf_destroy(snapshot);
|
||||
}
|
||||
snapshot = lv_snapshot_take(widget, LV_COLOR_FORMAT_ARGB8888);
|
||||
lv_image_set_src(img_snapshot, snapshot);
|
||||
}
|
||||
|
||||
Use Existing Buffer
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If the snapshot needs update now and then, or simply caller provides memory, use API
|
||||
``lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * widget, lv_color_format_t cf, lv_draw_buf_t * draw_buf);``
|
||||
for this case. It's caller's responsibility to create and destroy the draw buffer.
|
||||
|
||||
If snapshot is generated successfully, the image descriptor is updated
|
||||
and image data will be stored to provided ``buf``.
|
||||
|
||||
Note that snapshot may fail if provided buffer is not enough, which may
|
||||
happen when Widget size changes. It's recommended to use API
|
||||
:cpp:func:`lv_snapshot_reshape_draw_buf` to prepare the buffer firstly and if it
|
||||
fails, destroy the existing draw buffer and call `lv_snapshot_take` directly.
|
||||
|
||||
.. _snapshot_example:
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. include:: ../../examples/others/snapshot/index.rst
|
||||
|
||||
.. _snapshot_api:
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user