mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-26 11:07:34 +08:00
docs(xml): reorganize and add better descriptions (#8818)
This commit is contained in:
committed by
GitHub
parent
4f40572ac7
commit
115bce48f3
@@ -1,8 +1,8 @@
|
||||
.. _freetype:
|
||||
|
||||
================
|
||||
FreeType Support
|
||||
================
|
||||
====================
|
||||
FreeType Font Engine
|
||||
====================
|
||||
|
||||
**FreeType** is a freely available software library to render fonts.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _tiny_ttf:
|
||||
|
||||
====================
|
||||
Tiny TTF font engine
|
||||
Tiny TTF Font Engine
|
||||
====================
|
||||
|
||||
The lv_tiny_ttf extension allows using TrueType fonts in LVGL using the
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
.. _xml_fonts:
|
||||
|
||||
=====
|
||||
Fonts
|
||||
=====
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
In XML, fonts are considered external resources. A target font engine needs to be selected
|
||||
and named in order to be referenced in XML files later.
|
||||
|
||||
Registering Fonts
|
||||
*****************
|
||||
|
||||
From File
|
||||
---------
|
||||
|
||||
Fonts used directly from a TTF file can be listed in the ``<fonts>`` section
|
||||
of ``globals.xml``.
|
||||
|
||||
Each child of ``<fonts>`` starts with the desired font engine's name, a
|
||||
``name`` property, and other properties depending on the selected engine.
|
||||
|
||||
``as_file`` must be set to ``true`` to indicate that the font is treated as a file.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<globals>
|
||||
<fonts>
|
||||
<bin as_file="false" name="medium" src="path/to/file.ttf" range="0x20-0x7f" symbols="°" size="24"/>
|
||||
<tiny_ttf as_file="true" name="big" src_path="path/to/file.ttf" range="0x20-0x7f" size="48"/>
|
||||
</fonts>
|
||||
</globals>
|
||||
|
||||
When registering ``globals.xml`` with
|
||||
:cpp:expr:`lv_xml_component_register_from_file("A:path/to/globals.xml")`,
|
||||
fonts are automatically created with the selected font engine and mapped to the given names.
|
||||
|
||||
The fonts can have relative paths in ``globals.xml``. Before registering ``globals.xml``,
|
||||
:cpp:expr:`lv_xml_set_default_asset_path("path/prefix/")` can be called to set the parent folder.
|
||||
The font paths will then be appended to this base path.
|
||||
|
||||
From Data
|
||||
---------
|
||||
|
||||
If a font is used from C data (arrays) compiled into the firmware, the font's pointer can be registered
|
||||
to XML like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_xml_register_font(scope, "font_name", &my_font);
|
||||
|
||||
Fonts must be registered before any XML files referencing them are registered, so that the font data
|
||||
is already known.
|
||||
|
||||
In LVGL's UI Editor, when using fonts as data, it's also necessary to add the fonts to
|
||||
``globals.xml`` with ``as_file=false``, so the Editor can generate the required
|
||||
C files and also perform validation when referencing data fonts.
|
||||
|
||||
Usage in XML
|
||||
************
|
||||
|
||||
Once a font is registered, it can be referenced by its name in styles or even ``<api>`` properties:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<component>
|
||||
<api>
|
||||
<prop name="title_font" type="font" default="my_font_32"/>
|
||||
</api>
|
||||
|
||||
<styles>
|
||||
<style name="subtitle" text_font="my_font_24"/>
|
||||
</styles>
|
||||
|
||||
<view flex_flow="column">
|
||||
<lv_label style_text_font="$title_font" text="Title"/>
|
||||
<lv_label text="I'm the subtitle">
|
||||
<style name="subtitle"/>
|
||||
</lv_label>
|
||||
</view>
|
||||
|
||||
Font Engines
|
||||
************
|
||||
|
||||
``<bin>``
|
||||
---------
|
||||
|
||||
Binary fonts can either reference:
|
||||
|
||||
1. A ".bin" font file created by LVGL's Font converter from a TTF file (when ``as_file="true"``).
|
||||
The font will be loaded by :cpp:expr:`lv_binfont_create`.
|
||||
2. An :cpp:expr:`lv_font_t` pointer compiled into the firmware (``as_file="false"``).
|
||||
No loading is needed as :cpp:expr:`lv_font_t` can be used directly.
|
||||
|
||||
``<bin>`` fonts require these properties:
|
||||
|
||||
:``name``: The name to reference the font later
|
||||
:``src_path``: Path to the font file
|
||||
:``size``: Font size in px (e.g., "12")
|
||||
:``bpp``: Bits-per-pixel: 1, 2, 4, or 8
|
||||
:``as_file``: ``true`` if the font is a ".bin" file, ``false`` if it is an :cpp:expr:`lv_font_t` in C
|
||||
|
||||
LVGL's UI Editor always generates a call to :cpp:expr:`lv_xml_register_font` using the set ``name``.
|
||||
If ``as_file`` is:
|
||||
|
||||
- ``false``: It generates a C file with the :cpp:expr:`lv_font_t` structs.
|
||||
- ``true``: It generates a ".bin" file.
|
||||
|
||||
Binary fonts also support selecting a subset of characters:
|
||||
|
||||
:``range``: For example, ``"0x30-0x39 0x100-0x200"`` to specify Unicode ranges to include.
|
||||
The default is ``"0x20-0x7F"`` to cover the ASCII range.
|
||||
:``symbols``: List of extra characters to add, e.g., ``"°ÁŐÚ"``. Can be used together with ``range``.
|
||||
Default is empty (no extras).
|
||||
|
||||
``<tiny_ttf>``
|
||||
--------------
|
||||
|
||||
TinyTTF fonts use the :ref:`tiny_ttf` engine to load TTF files directly or from data.
|
||||
|
||||
Required properties:
|
||||
|
||||
:``name``: The name to reference the font later
|
||||
:``src_path``: Path to the font file
|
||||
:``size``: Font size in px (e.g., "12")
|
||||
:``as_file``: ``true`` or ``false``
|
||||
|
||||
LVGL's UI Editor generates a call to :cpp:expr:`lv_xml_register_font` using the set ``name``.
|
||||
If ``as_file`` is:
|
||||
|
||||
- ``false``: A C file with raw file data is also generated.
|
||||
- ``true``: Nothing else is generated, as the TTF file will be used directly.
|
||||
|
||||
``<freetype>``
|
||||
--------------
|
||||
|
||||
FreeType fonts use the :ref:`freetype` engine to load TTF files directly. Loading from data is not supported,
|
||||
so ``as_file`` is always considered ``true``.
|
||||
|
||||
Required properties:
|
||||
|
||||
:``name``: The name to reference the font later
|
||||
:``src_path``: Path to the font file
|
||||
:``size``: Font size in px (e.g., "12")
|
||||
|
||||
LVGL's UI Editor generates a call to :cpp:expr:`lv_xml_register_font` using the set ``name``.
|
||||
@@ -0,0 +1,77 @@
|
||||
.. _xml_images:
|
||||
|
||||
======
|
||||
Images
|
||||
======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
In XML, images are considered external resources that need to be named in order to be referenced in
|
||||
XML files. Below is how to map images with names.
|
||||
|
||||
Registering Images
|
||||
******************
|
||||
|
||||
From File
|
||||
---------
|
||||
|
||||
If the images are used as files (e.g., PNG images loaded from a file system),
|
||||
they can be simply added to ``globals.xml``:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<images>
|
||||
<file name="avatar" src_path="images/avatar1.png"/>
|
||||
<file name="logo" src_path="images/path/to/my_logo.png"/>
|
||||
</images>
|
||||
|
||||
When registering ``globals.xml`` with
|
||||
:cpp:expr:`lv_xml_component_register_from_file("A:path/to/globals.xml")`,
|
||||
names are automatically mapped to the path.
|
||||
|
||||
The images can have relative paths in ``globals.xml``. Before registering ``globals.xml``,
|
||||
:cpp:expr:`lv_xml_set_default_asset_path("path/prefix/")` can be called to set the parent folder.
|
||||
The path of the image files will be appended to the path set here.
|
||||
|
||||
From Data
|
||||
---------
|
||||
|
||||
If the images are converted to arrays and compiled into the firmware, they need to be
|
||||
registered explicitly using:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
lv_xml_register_image(NULL, "image_name", &my_image)
|
||||
|
||||
where ``my_image`` is an :cpp:type:`lv_image_dsc_t`.
|
||||
|
||||
After that, it can be used identically to image files:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<lv_image src="image_name" align="center"/>
|
||||
|
||||
Usage in XML
|
||||
************
|
||||
|
||||
After registration, the images can be referenced by their name:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<lv_image src="avatar" align="center"/>
|
||||
|
||||
Notes for the UI Editor
|
||||
***********************
|
||||
|
||||
When using LVGL's UI Editor, images can be added to ``globals.xml`` using the
|
||||
``<data>`` tag instead of ``<file>``.
|
||||
|
||||
In this case, the Editor will generate the C array (:cpp:type:`lv_image_dsc_t`)
|
||||
and also generate code to register the images.
|
||||
|
||||
It's also possible to set the target ``color_format="..."`` of the images. All typical
|
||||
color formats are supported, like i1...i8, a1...a8, rgb565, rgb888, argb8888, etc.
|
||||
@@ -1,134 +0,0 @@
|
||||
.. _xml_fonts:
|
||||
|
||||
=====
|
||||
Fonts
|
||||
=====
|
||||
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
A ``<fonts>`` section can be added in ``globals.xml`` files.
|
||||
Later, it might be supported in Components and Widgets to define local fonts and keep
|
||||
the global space cleaner.
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
The following section creates a mapping between font names and their paths with various attributes:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<fonts>
|
||||
<bin as_file="false" name="medium" src="path/to/file.ttf" range="0x20-0x7f" symbols="°" size="24"/>
|
||||
<tiny_ttf as_file="true" name="big" src_path="path/to/file.ttf" range="0x20-0x7f" symbols="auto" size="48"/>
|
||||
<freetype name="chinese" src_path="file.ttf" size="48" custom_freetype_attribute="abc"/>
|
||||
</fonts>
|
||||
|
||||
In ``<styles>`` and ``<view>``, fonts can then be referenced by their name, e.g.,
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<style name="style1" text_font="medium"/>
|
||||
|
||||
The tag name determines how the font is loaded. Currently, only ``tiny_ttf as_file="true"`` is supported.
|
||||
|
||||
- ``bin``:
|
||||
|
||||
- If ``as_file="true"``: Converts the font file to ``bin`` (see `lv_font_conv`)
|
||||
which will be loaded by ``lv_binfont_create()``.
|
||||
- If ``as_file="false"`` (default): On export, the font file will be converted to a
|
||||
C array LVGL font that can be used directly by LVGL.
|
||||
|
||||
- ``tiny_ttf``:
|
||||
|
||||
- If ``as_file="true"``: Can be loaded directly by ``lv_tiny_ttf_create_file()``.
|
||||
- If ``as_file="false"`` (default): The font file will be converted to a raw C
|
||||
array on export that will be loaded by ``lv_tiny_ttf_create_data()``.
|
||||
|
||||
- ``freetype``: The file can be loaded directly by ``lv_freetype_font_create()``.
|
||||
|
||||
For simplicity, if ``as_file="false"``, fonts will be loaded as files in the preview.
|
||||
Setting ``as_file="false"`` affects only the C export.
|
||||
|
||||
If the UI is created from XML at runtime and a ``globals.xml`` is parsed, the
|
||||
``as_file="false"`` tags are skipped because it is assumed that the user manually
|
||||
creates the mapping. This is because the XML parser cannot automatically map an LVGL
|
||||
font definition like:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_font_t my_font_24;
|
||||
|
||||
to
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<bin name="my_font_24"/>
|
||||
|
||||
|
||||
Exported Code
|
||||
-------------
|
||||
|
||||
When C code is exported, global ``const lv_font_t * <font_name>`` variables are
|
||||
created, and in the initialization function of the Component Library (e.g.,
|
||||
``my_lib_init_gen()``), the actual font is assigned.
|
||||
|
||||
.. Note: :cpp:expr: role cannot be used here because it doesn't know how to parse
|
||||
the ampersand and angle brackets. An alternate approach could be to make the
|
||||
arguments "style1_p, font_name", but leaving the ampersand there seems more
|
||||
appropriate due to that IS the normal way to pass a style as an argument.
|
||||
So it was made into a literal string instead to avoid the parsing error.
|
||||
|
||||
In ``lv_style_set_text_font(&style1, <font_name>)``, the created font is referenced.
|
||||
|
||||
|
||||
Default Font
|
||||
------------
|
||||
|
||||
``"lv_font_default"`` can be used to access ``LV_FONT_DEFAULT``. Other built-in fonts
|
||||
are not exposed by default.
|
||||
|
||||
|
||||
Registering fonts
|
||||
-----------------
|
||||
|
||||
If the UI is created from XML at runtime and a ``globals.xml`` is parsed, the ``<... as_file="false">`` tags are skipped
|
||||
because it is assumed that the user manually created the mapping.
|
||||
This is because the XML parser cannot automatically map fonts like:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_font_t my_font;
|
||||
|
||||
to
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<data name="my_font"/>
|
||||
|
||||
To register a font in the XML engine use:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_xml_register_font(scope, "font_name", &my_font);
|
||||
|
||||
``scope`` is usually ``NULL`` to register the font in the global scope.
|
||||
To register a font locally for a component you can get its scope with:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_xml_component_get_scope("component_name");
|
||||
|
||||
After calling this function, when ``"font_name"`` is used as a font in XML, ``&my_font`` will be used.
|
||||
|
||||
Notes for the UI Editor
|
||||
-----------------------
|
||||
|
||||
For simplicity, in the UI editor's preview, fonts are always loaded as tinyttf fonts.
|
||||
It makes the preview dynamic as no code export and compilation is needed when a font changes.
|
||||
@@ -1,76 +0,0 @@
|
||||
.. _xml_images:
|
||||
|
||||
======
|
||||
Images
|
||||
======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
An ``<images>`` section can be added to ``globals.xml`` files. If present, it
|
||||
describes how to map images with names.
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<images>
|
||||
<file name="avatar" src_path="avatar1.png"/>
|
||||
<data name="logo" src_path="logo1.png" color-format="rgb565" />
|
||||
</images>
|
||||
|
||||
- ``<file>`` means that the image source is used as a file path:
|
||||
- ``<data>`` means that the image is converted to a C array on export.
|
||||
|
||||
In both cases in the exported C code global ``const void * <image_name>`` variables are created and in the
|
||||
initialization function of the Component Library (e.g. ``my_lib_init_gen()``) either the path or
|
||||
the pointer to the converted :cpp:type:`lv_image_dsc_t` pointers are assigned to that variable.
|
||||
|
||||
In :cpp:expr:`lv_image_set_src(image, image_name)` ``image_name`` is used
|
||||
instead of the path or :cpp:type:`lv_image_dsc_t` pointer.
|
||||
|
||||
|
||||
Registering images
|
||||
------------------
|
||||
|
||||
If the UI is created from XML at runtime and a ``globals.xml`` is parsed, the ``<data>`` tags are skipped
|
||||
because it is assumed that the user manually created the mapping. This is because the XML parser cannot
|
||||
automatically map an image like:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_image_dsc_t my_logo;
|
||||
|
||||
to
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<data name="my_logo"/>
|
||||
|
||||
To register an image path or data in the XML engine use:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
lv_xml_register_image(scope, "image_name", data)
|
||||
|
||||
``scope`` is usually ``NULL`` to register the image in the global scope.
|
||||
To register an image locally for a component you can get its scope with:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
lv_xml_component_get_scope("component_name")
|
||||
|
||||
After calling this function, when ``"image_name"`` is used as an image source in XML, ``data``
|
||||
(can be a path or a pointer to an image descriptor) will be used.
|
||||
|
||||
|
||||
Notes for the UI Editor
|
||||
-----------------------
|
||||
|
||||
For simplicity, in the UI editor's preview, images are always loaded as files.
|
||||
It makes the preview dynamic so no code export and compilation is needed when an image changes.
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
.. _xml_building_uis:
|
||||
|
||||
============
|
||||
Building UIs
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 1
|
||||
|
||||
root_elements/index
|
||||
main_tags/index
|
||||
assets/index
|
||||
events
|
||||
subjects
|
||||
translation
|
||||
@@ -1,15 +0,0 @@
|
||||
.. _xml_main_tags:
|
||||
|
||||
=============
|
||||
Main XML Tags
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
consts
|
||||
styles
|
||||
view
|
||||
animations
|
||||
preview
|
||||
@@ -1,14 +0,0 @@
|
||||
.. _xml_root_elements:
|
||||
|
||||
=============
|
||||
Root elements
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
components
|
||||
widgets
|
||||
screens
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.. _xml_features:
|
||||
|
||||
========
|
||||
Features
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
subjects
|
||||
tests
|
||||
translations
|
||||
@@ -10,6 +10,7 @@ XML - Declarative UI
|
||||
:maxdepth: 2
|
||||
|
||||
overview/index
|
||||
build_ui/index
|
||||
test
|
||||
ui_elements/index
|
||||
assets/index
|
||||
features/index
|
||||
license
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
.. _xml_component_library:
|
||||
|
||||
=================
|
||||
Component Library
|
||||
=================
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
The collection of Components, Widgets, Screens, Images, Fonts, etc., is called a
|
||||
Component Library.
|
||||
|
||||
A Component Library can be fully self-contained, or it can also reference data from
|
||||
other Component Libraries.
|
||||
|
||||
LVGL itself is a Component Library that supplies the built-in Widgets, data types,
|
||||
etc. You can find the XML files that describe the LVGL Widgets
|
||||
`here <https://github.com/lvgl/lvgl/tree/master/xmls>`__.
|
||||
|
||||
An LVGL firmware project that uses external XML files to define part (or all) of its
|
||||
user interface (UI) always has at least 2 Component Libraries: that of LVGL as
|
||||
mentioned above, and at least 1 Component Library where a related set of Screens,
|
||||
Components, and Widgets of the project are defined. A project may include additional
|
||||
Component Libraries.
|
||||
|
||||
|
||||
Structure
|
||||
*********
|
||||
|
||||
A typical structure for a Component Library looks like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
name_of_the_component_library
|
||||
├── globals.xml
|
||||
├── components
|
||||
│ ├── component1.xml
|
||||
│ ├── component2.xml
|
||||
│ └── other_folder
|
||||
│ ├── component3.xml
|
||||
│ └── component4.xml
|
||||
├── widgets
|
||||
│ ├── widget1
|
||||
│ │ ├── widget1.xml
|
||||
│ │ ├── widget1.c
|
||||
│ │ ├── widget1.h
|
||||
│ │ ├── widget1_gen.c
|
||||
│ │ ├── widget1_gen.h
|
||||
│ │ ├── widget1_private_gen.h
|
||||
│ │ └── widget1_xml_parser.c
|
||||
│ └── widget2
|
||||
│ └── ...same as widget1...
|
||||
├── screens
|
||||
│ ├── screen1.xml
|
||||
│ └── screen2.xml
|
||||
├── fonts
|
||||
│ ├── font1.ttf
|
||||
│ └── font2.ttf
|
||||
└── images
|
||||
├── image1.png
|
||||
└── image2.png
|
||||
|
||||
|
||||
Name Visibility
|
||||
***************
|
||||
|
||||
In the context of UI components defined in XML files, there are two namespaces:
|
||||
|
||||
:global namespace:
|
||||
|
||||
Created from the combined data from the ``globals.xml`` file from each included
|
||||
Component Library, the names of :ref:`Subjects <observer_subject>`, enumerations,
|
||||
constants, styles, fonts and images defined therein can be referenced from all
|
||||
XML files used in a project.
|
||||
|
||||
:local namespace:
|
||||
|
||||
Names created within all other XML files can only be referenced from within those
|
||||
XML files. Exception: names of defined Components, Widgets and Screens become
|
||||
part of the global namespace, and therefore must be unique within the global
|
||||
namespace. This ensures each Component has a unique name.
|
||||
|
||||
All data belonging to the LVGL core Component Library is prefixed by ``lv_``
|
||||
(e.g., ``lv_label``, ``lv_font_default``).
|
||||
|
||||
A custom Component can be prefixed with ``watch_``, ``small_``, ``light_``, or
|
||||
anything else the development team deems appropriate.
|
||||
|
||||
LVGL's UI |nbsp| Editor will show an error if there is a name conflict.
|
||||
|
||||
|
||||
|
||||
``globals.xml``
|
||||
***************
|
||||
|
||||
A single ``globals.xml`` file should be created in the root directory of each
|
||||
Component Library. The definitions in it do not belong to any specific Widget but
|
||||
are available throughout the entire UI, Widgets, and all XML files. The valid tags
|
||||
in it are:
|
||||
|
||||
:<config>: Can specify name and help.
|
||||
:<api>: Used with ``<enumdefs>`` to show possible values for Widget or Component attributes.
|
||||
:<subjects>: List of :ref:`Subjects <observer_subject>`; can be considered the API of a Component Library.
|
||||
:<consts>: Globally available constants.
|
||||
:<styles>: Globally available styles.
|
||||
:<fonts>: Globally available fonts.
|
||||
:<images>: Globally available images.
|
||||
:<const_variants>: See below.
|
||||
:<style_variants>: See below.
|
||||
|
||||
The ``globals.xml`` must be the only ``globals.xml`` file within the Component
|
||||
Library's folder tree.
|
||||
|
||||
From each ``globals.xml`` file, a ``<config.name>.h`` file is generated, which is
|
||||
included by all generated header files --- not only in the sub-folders where
|
||||
``globals.xml`` is created, but in all exported .C and .H files. This ensures that
|
||||
constants, fonts, and other global data are available for all Widgets and new Widgets.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
A ``globals.xml`` file of a Component Library might look like this:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<globals>
|
||||
<api>
|
||||
<enumdef name="mode">
|
||||
<enum name="slow"/>
|
||||
<enum name="fast"/>
|
||||
</enumdef>
|
||||
</api>
|
||||
|
||||
<consts>
|
||||
<px name="small_unit" value="8"/>
|
||||
<px name="large_unit" value="16"/>
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
<style name="style_red" bg_color="0xff0000">
|
||||
</styles>
|
||||
|
||||
<images>
|
||||
<file name="arrow_left" src="A:/images/arrow_left.png"/>
|
||||
</images>
|
||||
|
||||
<fonts>
|
||||
<tiny_ttf name="big" src="A:/fonts/arial.ttf" size="28"/>
|
||||
</fonts>
|
||||
</globals>
|
||||
@@ -9,7 +9,5 @@ Overview
|
||||
:maxdepth: 2
|
||||
|
||||
intro
|
||||
component_library
|
||||
project
|
||||
syntax
|
||||
|
||||
|
||||
@@ -7,132 +7,93 @@ Introduction
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
.. glossary::
|
||||
|
||||
Declarative UI
|
||||
|
||||
Declarative UI (user interface) is an approach to UI creation in which the
|
||||
creator describes *what* elements are needed in the UI, what data they are
|
||||
bound to, and to some degree, what they should look like, but can leave out
|
||||
details such as their exact position or in what sequence they should be
|
||||
created at run time.
|
||||
|
||||
Imperative UI
|
||||
|
||||
Imperative UI is an approach to UI creation in which the creator describes
|
||||
every detail of how the UI is created at run time. Imperative UI is the
|
||||
UI-building approach you use when you build your LVGL UI in C code.
|
||||
|
||||
The LVGL XML Module implements LVGL's :term:`Declarative UI` by loading UI elements
|
||||
written in XML. The XML file can be written by hand, but it is considerably more
|
||||
efficient to write the XML files using `LVGL's UI Editor <https://lvgl.io/editor>`__
|
||||
and thus highly recommended. This UI Editor provides features like:
|
||||
|
||||
- instant preview of the XML files,
|
||||
- auto-complete,
|
||||
- syntax highlighting,
|
||||
- online preview for collaboration and testing,
|
||||
- `Figma <https://www.figma.com/>`__ integration to efficiently implement Figma
|
||||
designs in LVGL.
|
||||
|
||||
.. warning::
|
||||
|
||||
The UI editor and the XML loader are still under development and not
|
||||
production-ready. Consider them as an open beta or experimental features.
|
||||
The LVGL XML Module implements LVGL's Declarative UI by making it possible to
|
||||
describe UIs in XML.
|
||||
|
||||
Describing the UI in XML in a declarative manner offers several advantages:
|
||||
|
||||
- XML files can be loaded at runtime (e.g. from an SD card) allowing you to change
|
||||
- XML files can be loaded at runtime (e.g., from an SD card), allowing you to change
|
||||
the application's UI without changing the firmware.
|
||||
- XML files can be loaded dynamically as well, which allows for things like creating
|
||||
UIs from plugins or apps that are downloaded by the firmware.
|
||||
- XML files can also be loaded dynamically, enabling use cases such as creating
|
||||
UIs from plugins or apps downloaded by the firmware.
|
||||
- XML is simpler to write than C, enabling people with different skill sets to create LVGL UIs.
|
||||
- XML is textual data, making it easy to parse and manipulate with a large number of
|
||||
programming and scripting languages.
|
||||
- XML can be used to generate LVGL code in any language.
|
||||
- XML helps to separate the view from the internal logic.
|
||||
- The XML syntax uses the same properties as the C API, so it's easy to learn. E.g.
|
||||
style properties like bg_color, line_width, or widget properties like width,
|
||||
height, label text, etc.
|
||||
- A powerful data binding engine allows you to easily bind the widgets to global data.
|
||||
- XML helps separate the view from the internal logic.
|
||||
- The XML syntax uses the same properties as the C API, so it's easy to learn. E.g.,
|
||||
style properties like ``bg_color``, ``line_width``, or widget properties like ``width``,
|
||||
``height``, label ``text``, etc.
|
||||
- A powerful data binding engine allows you to easily bind widgets to global data.
|
||||
|
||||
The XML file can be written by hand, but it's highly recommended to use `LVGL's
|
||||
UI editor <https://lvgl.io/editor>`__ to write the XML files. This UI editor
|
||||
makes UI development much faster by providing features like:
|
||||
|
||||
- Instant preview of the XML files (components, screens)
|
||||
- Inspector mode to visualize widget sizes, paddings, etc.
|
||||
- Generate C code from XML files
|
||||
- Autocomplete and syntax highlighting
|
||||
- Online share/preview for collaboration and testing
|
||||
- `Figma <https://www.figma.com/>`__ integration to easily reimplement Figma designs
|
||||
|
||||
Concept
|
||||
*******
|
||||
.. warning::
|
||||
|
||||
The XML files are Component-oriented. To be more specific, they are ``Component-Library`` oriented.
|
||||
That is, they are structured in a way to make it easy to create reusable Component Libraries.
|
||||
The UI editor and the XML loader are still under development and not
|
||||
production-ready. Consider them as open beta or experimental features.
|
||||
|
||||
For example, a company can have a Component Library for the basic Widgets for all its products
|
||||
(generic widgets for all smart devices), and create other industry-specific Libraries
|
||||
(smart-home specific, smart-watch specific, etc.) containing only a few extra Widgets and Components.
|
||||
Using the XML files
|
||||
*******************
|
||||
|
||||
These Component Libraries are independent, can be reused across many products, and can
|
||||
be independently versioned and managed. Imagine a Component Library as a collection
|
||||
of XML files that describe Widgets, Components, Screens, images, fonts, and other
|
||||
assets stored in a git repository, which can be a submodule in many projects. If
|
||||
someone finds a bug in the Component Library, they can simply fix it in one place and
|
||||
push it back to the git repository so that other projects can be updated from it.
|
||||
If writing XMLs by hand, the concept is very simple:
|
||||
|
||||
The built-in Widgets of LVGL are considered ``the core Component Library`` which is
|
||||
always available.
|
||||
1. When ``LV_USE_XML`` is enabled, LVGL's built-in widgets and other XML parsers for styles, events,
|
||||
data bindings, etc., are registered automatically.
|
||||
2. The XML files created by the user (such as Screens, Components, Images, Fonts, etc.) can be
|
||||
registered (loaded) at runtime, and screen or component instances can also be created based on the
|
||||
XML "blueprints".
|
||||
3. The widgets created from XML look like any normal widgets, so functions of the C API can be applied
|
||||
to them. E.g., start an animation, add a special style, etc.
|
||||
|
||||
A UI Editor project can have any number of Component Libraries but will always
|
||||
have at least 2:
|
||||
|
||||
- LVGL's built-in Widgets, and
|
||||
- XML-based definitions of Screen contents, along with other project-specific Components.
|
||||
|
||||
|
||||
|
||||
Widgets, Components, and Screens
|
||||
********************************
|
||||
UI Elements
|
||||
***********
|
||||
|
||||
It is important to distinguish between :dfn:`Widgets`, :dfn:`Components`, and :dfn:`Screens`.
|
||||
|
||||
|
||||
Widgets
|
||||
-------
|
||||
|
||||
:dfn:`Widgets` are the core building blocks of the UI and are **not meant to be loaded at runtime**
|
||||
but rather compiled into the application as C code. The main characteristics of Widgets are:
|
||||
but rather compiled into the application as C code. The main characteristics of Widgets are:
|
||||
|
||||
- In XML, they start with a ``<widget>`` root element.
|
||||
- They are similar to LVGL's built-in Widgets.
|
||||
- They are built using ``lv_obj_class`` objects.
|
||||
- They have custom and complex logic inside.
|
||||
- They are similar to LVGL's built-in widgets.
|
||||
- They can contain custom and complex logic.
|
||||
- They cannot be loaded from XML at runtime because the custom code cannot be loaded.
|
||||
- They can have a large API with ``set/get/add`` functions.
|
||||
- They can themselves contain Widgets as children (e.g. ``Tabview``'s tabs, ``Dropdown``'s lists).
|
||||
|
||||
Any custom Widgets you create can be accessed from XML by:
|
||||
|
||||
1. Defining its API in an XML file.
|
||||
2. Writing and registering an XML parser for it.
|
||||
`See examples here. <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__
|
||||
|
||||
- They can have a large and custom API with ``set/get/add`` functions.
|
||||
- A custom XML parser is needed to map XML properties to API function calls.
|
||||
- They can be compound, containing other Widgets (e.g., ``Tabview``'s tabs, ``Dropdown``'s lists).
|
||||
- In the UI editor, they can also be described in XML to create visuals more quickly and export C code.
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
:dfn:`Components` are built from Widgets and/or other Components, and **can be loaded at runtime**.
|
||||
:dfn:`Components` are simpler UI elements and **can be loaded at runtime**.
|
||||
The main characteristics of Components are:
|
||||
|
||||
- In XML, they start with a ``<component>`` root element.
|
||||
- They are built in XML only and cannot have custom C code.
|
||||
- They can be loaded from XML as they don't contain custom C code, only XML.
|
||||
- They are built from Widgets and/or other Components.
|
||||
- They can be used for styling Widgets and other Components.
|
||||
- They can contain (as children) Widgets and/or other Components.
|
||||
- They can have a simple API to pass properties to their children (e.g. ``btn_text`` to a Label's text).
|
||||
- They are defined only in XML and cannot have custom C code (but they can call C functions as event callbacks).
|
||||
- They can be loaded from XML since they contain only XML.
|
||||
- They can be used for styling Widgets and other Components, using data bindings via subjects, defining animations, etc.
|
||||
- As children, they can contain Widgets and/or other Components.
|
||||
- They can have a simple API to pass properties to their children (e.g., ``btn_text`` to a Label's text).
|
||||
|
||||
Regardless of whether the XML was written manually or by the UI |nbsp| Editor, the XML
|
||||
files defining Components can be registered in LVGL, and after that, instances can be
|
||||
created. In other words, LVGL can just read the XML files, "learn" the Components
|
||||
from them, and thereafter create those components as children of Screens and/or other
|
||||
Components.
|
||||
Whether the XML was written manually or by the UI |nbsp| Editor, the files
|
||||
defining Components can be registered in LVGL, and after that, instances can be created.
|
||||
|
||||
In other words, LVGL can read the XML files, "learn" the Components from them, and
|
||||
thereafter create children as part of Screens and other Components.
|
||||
|
||||
Screens
|
||||
-------
|
||||
@@ -141,36 +102,56 @@ Screens
|
||||
|
||||
- In XML, they start with a ``<screen>`` root element.
|
||||
- They are built from Widgets and/or other Components to describe the :ref:`Screen <screens>`.
|
||||
- They can be loaded from XML at runtime as they describe only visual aspects of the UI.
|
||||
- They can be loaded from XML at runtime since they describe only visual aspects of the UI.
|
||||
- They do not have an API.
|
||||
- They can be referenced in Screen-load events.
|
||||
- They can be referenced in screen load events.
|
||||
|
||||
Global data
|
||||
***********
|
||||
|
||||
``globals.xml`` is a special XML file in which globally available
|
||||
|
||||
Syntax Teaser
|
||||
*************
|
||||
- styles
|
||||
- constants
|
||||
- images
|
||||
- fonts
|
||||
- subjects for data bindings
|
||||
|
||||
Each Widget, Component, or Screen XML file describes a single UI element. The root
|
||||
element for Widgets, Components, and Screens is ``<widget>``, ``<component>``, and
|
||||
``<screen>`` respectively. Other than that, the contained XML elements are almost
|
||||
identical. This is a high-level overview of the most important XML elements that
|
||||
will be children of these root elements:
|
||||
can be defined.
|
||||
|
||||
:<api>: Describes the properties that can be ``set`` for a Widget or Component.
|
||||
Properties can be referenced by ``$``. For Widgets, custom enums can
|
||||
also be defined with the ``<enumdef>`` tag.
|
||||
Multiple ``globals.xml`` files can be loaded if needed, but each will be saved in the same global scope,
|
||||
meaning duplicated items will be added only once.
|
||||
|
||||
Usage Teaser
|
||||
************
|
||||
|
||||
Each Component or Screen XML file describes a single UI element.
|
||||
|
||||
The syntax and supported XML tags are very similar in all three.
|
||||
|
||||
Note that for Widgets, XML can be used to export C code in LVGL's UI Editor.
|
||||
|
||||
This is a high-level overview of the most important XML elements that
|
||||
can be children of these root elements:
|
||||
|
||||
:<api>: Describes the properties that can be ``set`` in a Component.
|
||||
Properties can be referenced by ``$``.
|
||||
:<consts>: Specifies constants (local to the Widget or Component) for colors, sizes,
|
||||
and other values. Constant values can be referenced using ``#``.
|
||||
:<styles>: Describes style (``lv_style_t``) objects that can be referenced (and
|
||||
shared) by Widgets and Components later.
|
||||
:<view>: Specifies the appearance of the Widget or Component by describing the
|
||||
:<styles>: Describes style (``lv_style_t``) objects that can be referenced
|
||||
by Widgets and Components later.
|
||||
:<view>: Specifies the appearance of the Widget, Component, or Screen by describing the
|
||||
children and their properties.
|
||||
|
||||
An XML component
|
||||
----------------
|
||||
|
||||
This is a simple example illustrating what an LVGL XML Component looks like.
|
||||
Only basic features are shown.
|
||||
Note that only the basic features are shown here.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- my_button.xml -->
|
||||
<component>
|
||||
<consts>
|
||||
<px name="size" value="100"/>
|
||||
@@ -195,43 +176,32 @@ Only basic features are shown.
|
||||
</view>
|
||||
</component>
|
||||
|
||||
Load the UI from XML
|
||||
--------------------
|
||||
|
||||
The Component XML can be loaded, and any number of instances can be created at runtime.
|
||||
|
||||
Usage Teaser
|
||||
************
|
||||
In the simplest case, a Component can be registered with
|
||||
:cpp:expr:`lv_xml_component_register_from_file("A:path/to/my_button.xml")` and an instance can be created with
|
||||
:cpp:expr:`lv_obj_t * obj = lv_xml_create(parent, "my_button", NULL)`.
|
||||
|
||||
LVGL's UI editor can be used in two different ways.
|
||||
Note that loading the UI from XML has practically no impact on performance.
|
||||
Once the XML files are registered and the UI is created, it behaves the same way
|
||||
as if it were created from C code.
|
||||
|
||||
Registering XML files and creating instances is not memory-hungry nor slow. The biggest
|
||||
memory overhead is that the ``<view>`` of the Components is saved in RAM (typically
|
||||
1–2 kB per component).
|
||||
|
||||
Export C and H Files
|
||||
--------------------
|
||||
|
||||
The Widgets, Components, Screens, images, fonts, etc., can be converted to .C/.H files having
|
||||
code that accesses the LVGL API in the same way user-written code does.
|
||||
By using LVGL's UI Editor, the Widgets, Components, Screens, images, fonts, etc., can be
|
||||
converted to .C/.H files containing plain LVGL code.
|
||||
|
||||
In this case, the XML files are not required anymore to run the C code (unless modifications
|
||||
are made later and code is exported again).
|
||||
The exported code works the same way as if it were written by the user.
|
||||
|
||||
The XML files were used only during Widget and Component creation to save
|
||||
recompilation time and optionally to take advantage of other useful UI editor features.
|
||||
In this case, the XML files are not required anymore to run the C code.
|
||||
|
||||
|
||||
Load the UI from XML
|
||||
--------------------
|
||||
|
||||
Although Widgets' XML always needs to be exported in C and compiled into the
|
||||
application (just like the built-in LVGL Widgets' C code is compiled into the
|
||||
application), the XML for Components can be loaded (learned) at runtime, and
|
||||
thereafter any number of instances of them can be created.
|
||||
|
||||
In the simplest case, a Component can be registered with
|
||||
:cpp:expr:`lv_xml_component_register_from_file(path)` and an instance can be created with
|
||||
:cpp:expr:`lv_obj_t * obj = lv_xml_create(parent, "my_button", NULL)`.
|
||||
|
||||
Note that loading UI components from XML has virtually no impact on performance.
|
||||
Once the XML files are registered and the UI is created, the performance, appearance
|
||||
and behavior are exactly the same as if it were created from C code.
|
||||
|
||||
Registering XML Components and creating instances are neither memory hungry nor slow.
|
||||
The biggest memory overhead is that the ``<view>`` of the Components is saved in RAM
|
||||
(typically 1–2 kB/component).
|
||||
The XML files are used only during the editing/implementation of the Widgets, Components, and Screens to save
|
||||
recompilation time and optionally leverage other useful UI |nbsp| Editor features.
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
.. _xml_project:
|
||||
|
||||
=======
|
||||
Project
|
||||
=======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
A single ``project.xml`` file should be created for each project where the following
|
||||
content is specified:
|
||||
|
||||
:<folders>: Specifies the list of paths to Component Libraries. LVGL's base Widgets are
|
||||
always loaded automatically, and therefore do not need to be specified
|
||||
in this list.
|
||||
:<targets>: Describes various hardware configurations, allowing the UI |nbsp| Editor
|
||||
to check if the UI is out of resources and to select different previews
|
||||
for each Screen according to the specified displays.
|
||||
|
||||
|
||||
In LVGL's Editor the ``folders``, ``memory`` and `` <display color_format="..."/>`` are not supported yet.
|
||||
|
||||
Example
|
||||
*******
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<project>
|
||||
<folders>
|
||||
<folder path="../widget_lib1"/>
|
||||
<folder path="/home/user/work/ui_libs/modern"/>
|
||||
<folder path="https://github.com/user/repo"/>
|
||||
</folders>
|
||||
|
||||
<targets>
|
||||
<target name="small">
|
||||
<display width="320" height="240" color_format="RGB565"/>
|
||||
<memory name="int_ram" size="128K"/>
|
||||
<memory name="ext_ram" size="2M"/>
|
||||
<memory name="int_flash" size="512K"/>
|
||||
<memory name="ext_flash" size="32M"/>
|
||||
</target>
|
||||
|
||||
<target name="large">
|
||||
<display width="1024" height="768" color_format="XRGB8888"/>
|
||||
<memory name="int_ram" size="128K"/>
|
||||
<memory name="ext_ram" size="2M"/>
|
||||
<memory name="int_flash" size="512K"/>
|
||||
<memory name="ext_flash" size="32M"/>
|
||||
</target>
|
||||
</targets>
|
||||
</project>
|
||||
@@ -11,15 +11,15 @@ Naming conventions
|
||||
:trim:
|
||||
|
||||
- A standard XML syntax is used.
|
||||
- Lowercase letters with ``'_'`` separators are used for attribute names.
|
||||
- Tag names follow the usual C variable-name rules: they must start with a letter or
|
||||
- Lowercase letters with ``_`` separation are used for attribute names.
|
||||
- Tag names follow the usual variable-name rules: they must start with a letter or
|
||||
``'_'`` and the rest of the name may be comprised of letters, ``'_'`` and digits.
|
||||
- The LVGL API is followed as much as possible, e.g., ``align="center"``, ``bg_color="0xff0000"``.
|
||||
- For colors, all these syntaxes are supported (similar to CSS colors): ``0x112233``,
|
||||
``#112233``, ``112233``, ``0x123``, ``#123``, ``123``. Note that like CSS,
|
||||
``0x123``, ``#123`` and ``123`` all mean ``#112233``.
|
||||
- ``params`` can be referenced using ``$`` as a name prefix.
|
||||
- ``consts`` can be referenced using ``#`` as a name prefix.
|
||||
- ``params`` can be referenced with ``$``.
|
||||
- ``consts`` can be referenced with ``#``.
|
||||
- ``styles`` can be attached to states and/or parts like this:
|
||||
``styles="style1 style2:pressed style3:focused:scrollbar"``.
|
||||
- Local styles (i.e. styles that are stored within the Component and thus not shared
|
||||
@@ -28,10 +28,10 @@ Naming conventions
|
||||
|
||||
|
||||
|
||||
Data Types
|
||||
**********
|
||||
Types
|
||||
*****
|
||||
|
||||
All of the data types can be used as API property types, but only a subset of them can be
|
||||
All of the types can be used as API property types, but only a subset of them can be
|
||||
used as constant and :ref:`Subject <observer_subject>` types.
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ The following simple built-in types are supported:
|
||||
|
||||
:bool: a ``true`` or ``false``.
|
||||
|
||||
:int: Integer number in the range of roughly -2 billion to 2 billion by default.
|
||||
:int: Integer number in the range of roughly -2B to 2B by default.
|
||||
(Same as ``int32_t`` in C.)
|
||||
|
||||
:px: Simple pixel units. The unit suffix ``px`` can be omitted from the numeric value.
|
||||
:px: Simple pixel units. The unit ``px`` can be omitted.
|
||||
|
||||
:%: Percentage. ``%`` must be appended to the value as the unit.
|
||||
(Means the same as :cpp:expr:`lv_pct()`.)
|
||||
@@ -53,8 +53,7 @@ The following simple built-in types are supported:
|
||||
:content: Means ``LV_SIZE_CONTENT``.
|
||||
|
||||
:string: Simple NUL-terminated string. When multiple strings are used in a
|
||||
property or string array, ``'`` should be used. E.g. ``foo="'a' 'b'"``
|
||||
represents an array of 2 strings.
|
||||
property or string array, ``'`` should be used. E.g. ``foo="'a' 'b'"``.
|
||||
|
||||
:color: A color stored as 24-bit RGB (:cpp:expr:`lv_color_t`).
|
||||
|
||||
@@ -65,50 +64,47 @@ The following simple built-in types are supported:
|
||||
|
||||
:screen: Pointer to a screen (also :cpp:expr:`lv_obj_t *`).
|
||||
|
||||
:time_ms: Means some time in milliseconds
|
||||
:time_ms: Means some time in milliseconds unit
|
||||
|
||||
:deg_0.1: Degrees with 0.1 resolution
|
||||
|
||||
:scale_1/256: Scale/Zoom, where 256 means 100%, 128 means 50%, 512 means 200% etc.
|
||||
|
||||
|
||||
Name-based types
|
||||
----------------
|
||||
|
||||
In XML files, fonts, images, styles, etc., are used by their names, rather than by
|
||||
pointers as they are in C. For example, a style is defined like ``<style name="red"
|
||||
bg_color="0xff0000"/>``. Later, it can be referenced by its name: "red".
|
||||
In XML files, fonts, images, styles, etc., are not used by pointer but by string
|
||||
names. For example, a style is defined like ``<style name="red" bg_color="0xff0000"/>``.
|
||||
Later, they can be referenced by their names.
|
||||
|
||||
This means that the actual objects need to be bound to the names when the UI is loaded
|
||||
from XML files so LVGL knows what each name means.
|
||||
This means that the actual values need to be bound to the names when the UI is loaded
|
||||
from XML, otherwise, LVGL wouldn't know what a name means.
|
||||
|
||||
Most of these connections are done automatically (e.g., for styles, fonts, images,
|
||||
animations, gradients, etc.), but others need to be connected manually in C code
|
||||
(e.g., event callbacks where the callback itself is available only in C code).
|
||||
animations, gradients, etc.), but others need to be connected manually (e.g., event
|
||||
callbacks where the callback itself is available only in the code).
|
||||
|
||||
For fonts and images, the connections are created automatically if the source is an
|
||||
XML file. If the font or image is compiled into the application (as a C array), the
|
||||
user needs to specify which variable a given name refers to.
|
||||
For fonts and images, the connections are created automatically if the source is a file.
|
||||
If the font or image is compiled into the application (as a C array), the user needs
|
||||
to specify which variable a given name refers to.
|
||||
|
||||
To create these connections, functions like
|
||||
|
||||
- :cpp:expr:`lv_xml_register_image(scope, name, pointer)`
|
||||
- :cpp:expr:`lv_xml_register_font(scope, name, pointer)`
|
||||
- :cpp:expr:`lv_xml_register_event_cb(scope, name, callback)`
|
||||
- ``lv_xml_register_image(scope, name, pointer)``
|
||||
- ``lv_xml_register_font(scope, name, pointer)``
|
||||
- ``lv_xml_register_event_cb(scope, name, callback)``
|
||||
- etc.
|
||||
|
||||
can be used. Later, a pointer to the object can be retrieved by
|
||||
|
||||
- :cpp:expr:`lv_xml_get_image(scope, name)`
|
||||
- :cpp:expr:`lv_xml_get_font(scope, name)`
|
||||
- :cpp:expr:`lv_xml_get_event_cb(scope, name)`
|
||||
- ``lv_xml_get_image(scope, name)``
|
||||
- ``lv_xml_get_font(scope, name)``
|
||||
- ``lv_xml_get_event_cb(scope, name)``
|
||||
- etc.
|
||||
|
||||
``scope`` can be ``NULL`` to use the global scope or :cpp:expr:`lv_xml_component_get_scope("my_component")`
|
||||
returns the a component's local scope.
|
||||
|
||||
The passed ``name`` strings can be bound to:
|
||||
|
||||
:style: Name of a style. :cpp:expr:`lv_xml_get_style_by_name(&ctx, name)` returns an :cpp:expr:`lv_style_t *`.
|
||||
:font: Name of a font. :cpp:expr:`lv_xml_get_font(&ctx, name)` returns an :cpp:expr:`lv_font_t *`.
|
||||
:image: Name of an image. :cpp:expr:`lv_xml_get_image(&ctx, name)` returns an :cpp:expr:`const void *`,
|
||||
@@ -117,8 +113,7 @@ The passed ``name`` strings can be bound to:
|
||||
:subject: Name of a :ref:`Subject <observer_subject>`. :cpp:expr:`lv_xml_get_subject(&ctx, name)` returns an :cpp:expr:`lv_subject_t *`.
|
||||
:grad: Name of a gradient. :cpp:expr:`lv_xml_get_grad(&ctx, name)` returns an :cpp:expr:`lv_grad_dsc_t *`.
|
||||
:event_cb: Name of an event callback. :cpp:expr:`lv_xml_get_event_cb(&ctx, name)` returns an :cpp:expr:`lv_event_cb_t`.
|
||||
:screen_create_cb: In XML it's the name of a screen's XML file. In exported code it's a function like ``lv_obj_t * my_screen_create(void)``
|
||||
|
||||
:screen_create_cb: In XML it's the name of a screen XML file. In exported code it's a function like ``lv_obj_t * my_screen_create(void)``
|
||||
|
||||
Arrays
|
||||
------
|
||||
@@ -126,7 +121,7 @@ Arrays
|
||||
An array of any type can be defined in four ways:
|
||||
|
||||
:int[N]: An integer array with ``N`` elements.
|
||||
In the exported code ``N`` is passed as a parameter after the array.
|
||||
In the exported code ``N`` is passed a parameter after the array.
|
||||
:string[...NULL]: An array terminated with a ``NULL`` element. ``NULL`` can be
|
||||
replaced by any value.
|
||||
:string[5]: An array that must have exactly 5 elements. In the exported code only the array will be passed
|
||||
@@ -151,7 +146,7 @@ For example:
|
||||
<enum name="inverted" help="Inverted mode"/>
|
||||
</enumdef>
|
||||
|
||||
<prop name="mode" help="help" type="enum:my_widget_mode" help="help"/>
|
||||
<prop name="mode" help="help"type="enum:my_widget_mode" help="help"/>
|
||||
</api>
|
||||
|
||||
When used as a type, a ``+`` suffix means multiple values can be selected and ORed.
|
||||
@@ -162,19 +157,19 @@ For example: ``type="axis+"``. In this case, the options should be separated by
|
||||
Compound types
|
||||
--------------
|
||||
|
||||
Types can be compound, meaning multiple options/types are possible. Example for
|
||||
Types can be compound, meaning multiple options/types are possible. For example, for
|
||||
width: ``type="px|%|content"``.
|
||||
|
||||
|
||||
Limiting accepted values
|
||||
------------------------
|
||||
|
||||
|
||||
**Not supported yet; the examples below illustrate the planned syntax.**
|
||||
|
||||
It is also possible to limit the possible options the user can select from an enum.
|
||||
For example:
|
||||
|
||||
- Enums: ``type="dir(top bottom)"``
|
||||
- Colors: ``type="color(0xff0000 0x00ff00 0x0000ff)"``
|
||||
- Strings: ``type="string('Ok' 'Cancel')"``
|
||||
|
||||
Limiting accepted values is not supported yet, however in the UI |nbsp| Editor if
|
||||
an invalid option is selected, it will be highlighted as an error.
|
||||
- Strings: ``type="string('Ok' 'Cancel')``
|
||||
|
||||
+33
-30
@@ -1,4 +1,4 @@
|
||||
.. _xml_animations:
|
||||
.. _xml_animations:
|
||||
|
||||
==========
|
||||
Animations
|
||||
@@ -13,7 +13,7 @@ Timelines are composed of simple animations. For example: *"change the ``bg_opa`
|
||||
of ``my_button_2`` from 0 to 255 in 500 ms."*
|
||||
|
||||
Each component can define its own timeline animations, which can then be played by the
|
||||
component itself or by any parent components.
|
||||
component itself or by any parent component.
|
||||
|
||||
Defining Timelines
|
||||
------------------
|
||||
@@ -26,31 +26,33 @@ Example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<animations>
|
||||
<component>
|
||||
<animations>
|
||||
|
||||
<!-- Show the component and its children -->
|
||||
<timeline name="load">
|
||||
<animation prop="translate_x" target="self" start="-30" end="0" duration="500"/>
|
||||
<animation prop="opa" target="icon" start="0" end="255" duration="500"/>
|
||||
<animation prop="opa" target="text" start="0" end="255" duration="500" delay="200"/>
|
||||
</timeline>
|
||||
<!-- Show the component and its children -->
|
||||
<timeline name="load">
|
||||
<animation prop="translate_x" target="self" start="-30" end="0" duration="500"/>
|
||||
<animation prop="opa" target="icon" start="0" end="255" duration="500"/>
|
||||
<animation prop="opa" target="text" start="0" end="255" duration="500" delay="200"/>
|
||||
</timeline>
|
||||
|
||||
<!-- Shake horizontally -->
|
||||
<timeline name="shake">
|
||||
<animation prop="translate_x" target="self" start="0" end="-30" duration="150"/>
|
||||
<animation prop="translate_x" target="self" start="-30" end="30" duration="300" delay="150"/>
|
||||
<animation prop="translate_x" target="self" start="30" end="0" duration="150" delay="450"/>
|
||||
</timeline>
|
||||
</animations>
|
||||
<!-- Shake horizontally -->
|
||||
<timeline name="shake">
|
||||
<animation prop="translate_x" target="self" start="0" end="-30" duration="150"/>
|
||||
<animation prop="translate_x" target="self" start="-30" end="30" duration="300" delay="150"/>
|
||||
<animation prop="translate_x" target="self" start="30" end="0" duration="150" delay="450"/>
|
||||
</timeline>
|
||||
</animations>
|
||||
|
||||
<view>
|
||||
<lv_button width="200">
|
||||
<my_icon name="icon" src="image1"/>
|
||||
<lv_label name="text" text="Click me"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
<view>
|
||||
<lv_button width="200">
|
||||
<my_icon name="icon" src="image1"/>
|
||||
<lv_label name="text" text="Click me"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
In summary: inside ``<animations>``, you can define ``<timeline>``\ s, each with a unique name
|
||||
In summary: inside ``<animations>``, you can define ``<timeline>``\s, each with a unique name
|
||||
that you can reference later.
|
||||
|
||||
Inside a ``<timeline>``, you add ``<animation>``\ s to describe each step.
|
||||
@@ -83,29 +85,30 @@ Example:
|
||||
</custom_button>
|
||||
</view>
|
||||
|
||||
You set a ``target`` UI element and select one of its ``timeline``s to play.
|
||||
You set a ``target`` UI element and select one of its ``timeline``\ s to play.
|
||||
If ``target="self"``, the timeline is looked up in the current component/widget/screen
|
||||
(i.e. in the current XML file).
|
||||
|
||||
You can also set ``delay`` and ``reverse="true"`` when playing a timeline.
|
||||
You can also set a ``delay`` and ``reverse="true"`` when playing a timeline.
|
||||
|
||||
Under the Hood
|
||||
--------------
|
||||
|
||||
Understanding how timelines work internally helps use them effectively.
|
||||
Understanding how timelines work internally helps in using them effectively.
|
||||
|
||||
When an XML file is registered, the contents of the ``<animations>`` section are parsed,
|
||||
and the animation data is stored as a blueprint.
|
||||
|
||||
When an instance of a component or screen is created, ``lv_anim_timeline``\ s are
|
||||
created and initialized from the saved blueprint. Each instance gets its own copy.
|
||||
When an instance of a component or screen is created, ``lv_anim_timeline``\s are
|
||||
created and initialized from the saved blueprint. Each instance gets its own copy of the timelines.
|
||||
|
||||
When a ``<play_timeline_event>`` is added to a UI element, the target and timeline
|
||||
names are saved as strings. (It can't use pointers as the event can reference UI elements
|
||||
that will be created only later in the ``<view>``.)
|
||||
|
||||
Finally, when the trigger event happens, LVGL finds the target widget by the saved name,
|
||||
Finally, when the play timeline event is triggered, LVGL finds the target widget by the saved name,
|
||||
retrieves the specified timeline, and starts it.
|
||||
|
||||
Since each instance has its own timeline, you can have multiple components (e.g. 10 ``<list_item>``\ s)
|
||||
Since each instance has its own timeline, you can have multiple components (e.g. 10 ``<list_item>``\s)
|
||||
and play their ``load`` timelines independently with different delays.
|
||||
|
||||
+70
-59
@@ -13,8 +13,6 @@ The only common point is that both Widgets and Components support having
|
||||
However, as Widgets and Components work very differently (Widgets have C code,
|
||||
but Components are pure XML), even properties are interpreted differently.
|
||||
|
||||
|
||||
|
||||
Components
|
||||
**********
|
||||
|
||||
@@ -23,8 +21,8 @@ Overview
|
||||
|
||||
While Widgets can have complex ``set``/``get`` APIs, Components are very simple.
|
||||
|
||||
When their XML is converted to a C file, only a ``create`` function is generated,
|
||||
where all the ``<prop>``\ s are arguments. For example:
|
||||
When a component's XML is converted to C files, only a ``create`` function is generated,
|
||||
where all the ``<prop>``\s are arguments. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -33,7 +31,29 @@ where all the ``<prop>``\ s are arguments. For example:
|
||||
<prop name="prop2" type="string"/>
|
||||
</api>
|
||||
|
||||
This generates the following C function:
|
||||
Referencing properties
|
||||
----------------------
|
||||
|
||||
``<prop>``\ s are simply forwarded to Widget or Component APIs.
|
||||
For example, if a component has ``<prop name="button_label" type="string"/>``,
|
||||
it can be used in a label child as ``<lv_label text="$button_label"/>``.
|
||||
|
||||
In the code generated by LVGL's UI Editor, these are passed as arguments in create/set functions.
|
||||
|
||||
Default values
|
||||
--------------
|
||||
|
||||
Since each property is passed as an argument to the create function, each must have a value.
|
||||
This can be ensured by:
|
||||
|
||||
- Simply setting them in the XML instance
|
||||
- Providing a default value in the ``<api>``, e.g., ``<prop name="title" type="string" default="my_default_text"/>``
|
||||
|
||||
Code generation
|
||||
---------------
|
||||
|
||||
LVGL's UI Editor can also generate code from the component's XML. Depending on the ``<api>``, a function like
|
||||
this is generated:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -43,34 +63,12 @@ These properties are set once (at creation time), and there are no specific
|
||||
``set`` functions to modify the property later. LVGL's general API can still be
|
||||
used to modify any widget in the component, but no dedicated API functions are generated.
|
||||
|
||||
|
||||
Referencing properties
|
||||
----------------------
|
||||
|
||||
``<prop>``\ s are simply forwarded to widget or component APIs.
|
||||
For example, if a component has ``<prop name="button_label" type="string"/>``,
|
||||
it can be used in a label as ``<lv_label text="$button_label"/>``.
|
||||
|
||||
In the generated code, these are passed as arguments in create/set functions.
|
||||
|
||||
|
||||
Default values
|
||||
--------------
|
||||
|
||||
Since each property is passed as an argument to the create function, each must have a value.
|
||||
This can be ensured by:
|
||||
|
||||
- Simply setting them in the XML instance
|
||||
- Providing a default value in the ``<api>``, e.g., ``<prop name="foo" type="string" default="bar"/>``
|
||||
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Note that none of the Widget API features such as ``<param>``, ``<enumdef>``, or ``<element>``
|
||||
can be used for Components. Only simple properties that are forwarded are supported.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
@@ -98,12 +96,9 @@ Example
|
||||
</view>
|
||||
</component>
|
||||
|
||||
|
||||
|
||||
Widgets
|
||||
*******
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
@@ -115,7 +110,6 @@ Properties are the core part of describing a Widget's API.
|
||||
<prop name="text" type="string" help="Text of the label."/>
|
||||
</api>
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
@@ -147,7 +141,6 @@ Unset parameters fall back to:
|
||||
- Their default value (if defined)
|
||||
- Type-specific defaults (e.g., 0, false, NULL)
|
||||
|
||||
|
||||
Mapping
|
||||
-------
|
||||
|
||||
@@ -155,11 +148,10 @@ Each ``<prop>`` is mapped to a ``set`` function. This mapping is implemented
|
||||
in the Widget's XML parser.
|
||||
See `the LVGL XML parsers <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`_.
|
||||
|
||||
If ``<param>``s are used, they are passed to the same ``set`` function.
|
||||
If ``<param>``\ s are used, they are passed to the same ``set`` function.
|
||||
If a property is not set on a Widget instance, it is skipped and the Widget's
|
||||
built-in default is used.
|
||||
|
||||
|
||||
<enumdef>
|
||||
---------
|
||||
|
||||
@@ -177,41 +169,59 @@ Only used with Widgets, this tag defines enums for parameter values.
|
||||
</prop>
|
||||
</api>
|
||||
|
||||
Enum values are ignored in export; the names are used and resolved by the compiler.
|
||||
XML parsers must handle mapping enum names to C enums.
|
||||
|
||||
The actual values of the enum fields are not important during code export as only the names are used and resolved by the compiler.
|
||||
XML parsers must handle mapping enum string names (e.g. ``"normal"``) to C enums (e.g. ``MY_WIDGET_MODE_NORMAL``).
|
||||
|
||||
.. _xml_widget_element:
|
||||
|
||||
<element>
|
||||
---------
|
||||
``<element>``
|
||||
-------------
|
||||
|
||||
Also exclusive to Widgets, elements define sub-widgets or internal structures
|
||||
(e.g., chart series, dropdown list, tab views).
|
||||
(e.g., chart series, dropdown lists, tab views).
|
||||
|
||||
They support ``<arg>`` and ``<prop>``:
|
||||
Elements are also very useful to create "slots" (similar to tabview tabs), like a content and header area for a window widget, where
|
||||
children can be created directly.
|
||||
|
||||
- ``<arg>``\ s are required and used when creating/getting the element.
|
||||
- ``<prop>``\ s are optional and mapped to setters.
|
||||
Elements are described inside the ``<api>`` tag, and they can have ``<arg>`` and ``<prop>`` children:
|
||||
|
||||
Elements are referenced as ``<widget-element>`` in views.
|
||||
- ``<arg>``\s are required and used when creating/getting the element.
|
||||
- ``<prop>``\s are optional and mapped to setters.
|
||||
|
||||
Name parts are separated by `-` ( as `-` is not allowed inside names).
|
||||
Here's an example to define an "indicator" that can be added dynamically to a widget. It will create `my_indicator_t *`
|
||||
elements, the same way as, for example, :cpp:expr:`lv_chart_add_series` works.
|
||||
|
||||
Element `access` types:
|
||||
.. code-block:: xml
|
||||
|
||||
- ``add``: Create multiple elements dynamically.
|
||||
- ``get``: Access implicitly created elements.
|
||||
- ``set``: Access indexed parts (e.g., table cells).
|
||||
- ``custom``: Map custom C function to XML.
|
||||
<api>
|
||||
<element name="indicator" type="my_indicator_t" help="The indicator of my_widget" access="add">
|
||||
<!-- args are passed when the element is created -->
|
||||
<arg name="color" type="color"/>
|
||||
<arg name="max_value" type="int"/>
|
||||
|
||||
As ``add`` and ``get`` elements return an object they also have a type.
|
||||
This type can be any custom type, for example, `type="my_data"`. In the exported code the
|
||||
<!-- props can be set by setters at any time -->
|
||||
<prop name="value" type="int"/>
|
||||
</element>
|
||||
</api>
|
||||
|
||||
Element `access` types can be:
|
||||
|
||||
- ``add``: Create multiple elements dynamically. For example, tabview tabs.
|
||||
- ``get``: Access implicitly created elements. For example, dropdown lists.
|
||||
- ``set``: Access indexed parts. For example, table cells.
|
||||
- ``custom``: Map custom C functions to XML, e.g. ``bind_state_is_eq``
|
||||
|
||||
As ``add`` and ``get`` elements return an object, they also have a type.
|
||||
This type can be any custom type, for example, `type="my_data"`. In the exported code, the
|
||||
return value will be saved in a ``my_data_t *`` variable.
|
||||
|
||||
If the type is ``type="lv_obj"`` it allows the element to have children widgets or components.
|
||||
If the type is ``type="lv_obj"``, it allows the element to have child widgets or components.
|
||||
|
||||
Note that, only the API can be defined in XML for elements; implementations must be in C.
|
||||
Elements are referenced as ``<widget-element>`` in the ``<view>``.
|
||||
The parts of the name are separated by `-`. As `-` is not allowed inside names, it's safe to use
|
||||
as a separator.
|
||||
|
||||
Note that only the API can be defined in XML for elements; implementations must be in C.
|
||||
|
||||
access="add"
|
||||
~~~~~~~~~~~~
|
||||
@@ -238,7 +248,7 @@ Used in a view:
|
||||
<my_widget-indicator name="indic1" color="0xff0000" max_value="120" value="30"/>
|
||||
</my_widget>
|
||||
|
||||
Generates:
|
||||
LVGL's UI Editor generates this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -267,7 +277,7 @@ Used in a view:
|
||||
<my_widget-control_button name="btn1" index="3" title="Hello"/>
|
||||
</my_widget>
|
||||
|
||||
Generates:
|
||||
LVGL's UI Editor generates this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -297,7 +307,7 @@ Used in a view:
|
||||
<my_widget-item index="3" icon_src="image1" color="0xff0000"/>
|
||||
</my_widget>
|
||||
|
||||
Generates:
|
||||
LVGL's UI Editor generates this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -308,7 +318,7 @@ access="custom"
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Used to describe any custom API functions with a custom name.
|
||||
"custom" elements can have only arguments and no `type` so they are pure setters.
|
||||
"custom" elements can have only arguments and no `type`, so they are pure setters.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -326,8 +336,9 @@ Used in a view:
|
||||
<my_widget-bind_color subject="subject_1" color="0xff0000" ref_value="15"/>
|
||||
</my_widget>
|
||||
|
||||
Generates:
|
||||
LVGL's UI Editor generates this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void my_widget_bind_color(lv_obj_t * parent, lv_subject_t * subject, lv_color_t color, int32_t ref_value);
|
||||
|
||||
+52
-81
@@ -9,48 +9,47 @@ Overview
|
||||
|
||||
Components are one of the main building blocks for creating new UI elements.
|
||||
|
||||
``<component>`` elements may contain the following child elements:
|
||||
``<component>``\ s support the following child XML tags:
|
||||
|
||||
- :ref:`<consts> <xml_consts>`
|
||||
- :ref:`<api> <xml_api>`
|
||||
- :ref:`<styles> <xml_styles>`, and
|
||||
- :ref:`<styles> <xml_styles>`
|
||||
- :ref:`<view> <xml_view>`
|
||||
- :ref:`<previews> <xml_preview>`
|
||||
|
||||
Although they can't contain C code, they are very powerful:
|
||||
|
||||
- They can extend another Component or Widget (an "inherited" base Component or
|
||||
Widget can be specified).
|
||||
- Components can be built from Widgets and/or other Components.
|
||||
- A custom API can be defined.
|
||||
- Local styles can be defined, and global styles can be referenced.
|
||||
- Local constants can be defined, and global constants can be referenced.
|
||||
- Events can be added as function calls, or responses to changes of Subject values,
|
||||
or responses to Screens being created or loaded. See :ref:`XML Events <xml_events>`.
|
||||
- Previews can be defined to preview the components in various settings.
|
||||
- They can extend another Component or Widget (the base can be defined)
|
||||
- Components can be built from Widgets and other Components
|
||||
- A custom API can be defined
|
||||
- Local styles can be defined, and global styles can be used
|
||||
- Local constants can be defined, and global constants can be used
|
||||
- Function calls, subject changes, or screen load/create events can be added. See :ref:`XML Events <xml_events>`
|
||||
- Previews can be defined to preview the components in various settings in the UI Editor
|
||||
|
||||
When a Component is created, it can extend another Component or Widget like ``<view extends="lv_slider">``.
|
||||
If a Widget is extended, the component can use the Widget's API, e.g., ``<view extends="lv_slider" min_value="20">``.
|
||||
If a Component is extended, the ``<api>`` properties can be used: ``<view extends="my_button" button_text="Apply">``.
|
||||
|
||||
Unlike Widgets (which are always compiled into the application), Components can either:
|
||||
|
||||
1. be loaded at runtime from XML, or
|
||||
2. be exported to C code and compiled with the application.
|
||||
|
||||
|
||||
|
||||
Using Components from XML
|
||||
*************************
|
||||
2. be exported to C code by LVGL's UI Editor and compiled with the application.
|
||||
|
||||
Using the XML files
|
||||
*******************
|
||||
|
||||
In XML Files
|
||||
------------
|
||||
|
||||
Using Components in XMLs is very intuitive. The name of the components can be used as
|
||||
the name of the XML tag in the ``<view>`` of other Components, Screens, and Widgets.
|
||||
Using Components in XML is very intuitive. The name of the Component can be used as an XML tag
|
||||
in the ``<view>`` of other Components, Screens, and Widgets.
|
||||
|
||||
The Component properties are just XML attributes.
|
||||
|
||||
To load Components from file, it's assumed that the XML files are saved to the device
|
||||
either as data (byte array) or as a file. Once the data is saved, each component
|
||||
can be registered, after which instances of that Component can be created.
|
||||
To load Components from files, it's assumed that the XML files are saved to the device
|
||||
either as data (byte array) or as files. Once the data is saved, each Component
|
||||
can be registered, and instances can be created after that.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -62,9 +61,8 @@ can be registered, after which instances of that Component can be created.
|
||||
</view>
|
||||
</component>
|
||||
|
||||
:ref:`Styles <xml_styles>`, :ref:`Constants <xml_consts>`, and a
|
||||
:ref:`custom API <component_custom_properties>` can also be described in the XML files.
|
||||
|
||||
:ref:`Styles <xml_styles>`, :ref:`Constants <xml_consts>`, and :ref:`custom API <component_custom_api>`
|
||||
can also be described in the XML files.
|
||||
|
||||
Registration
|
||||
------------
|
||||
@@ -74,18 +72,15 @@ Once a Component is created (e.g., ``my_button``), it can be registered by calli
|
||||
- :cpp:expr:`lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml")`
|
||||
- :cpp:expr:`lv_xml_component_register_from_data("my_button", xml_data_of_my_button)`
|
||||
|
||||
These registration functions process the XML data and store relevant information
|
||||
internally by name. When loaded from a file, the file name is used as the Component
|
||||
name.
|
||||
These registration functions process the XML data and store relevant information internally.
|
||||
This is required to make LVGL recognize the Component by name.
|
||||
|
||||
During registration, the ``<view>`` of the Component is saved in RAM as a template for
|
||||
creating instances of that Component.
|
||||
Note that the "A:" in the above path is a file system "driver identifier letter" from
|
||||
:ref:`file_system` and used accordingly. See that documentation for details.
|
||||
|
||||
.. note::
|
||||
|
||||
Note that the "A:" in the above path is a file system "driver identifier letter" from
|
||||
:ref:`file_system` and used accordingly. See that documentation for details.
|
||||
When loaded from a file, the file name is used as the Component name.
|
||||
|
||||
During registration, the ``<view>`` of the Component is saved in RAM.
|
||||
|
||||
Instantiation
|
||||
-------------
|
||||
@@ -96,7 +91,7 @@ After registration, a new instance of any registered Component can be created wi
|
||||
|
||||
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "my_button", NULL);
|
||||
|
||||
The created Widget is a normal LVGL Widget that can be used like any other Widget.
|
||||
The created Widget is a normal LVGL Widget that can be used like any other manually-created Widget.
|
||||
|
||||
The last parameter can be ``NULL`` or an attribute list, like this:
|
||||
|
||||
@@ -112,55 +107,45 @@ The last parameter can be ``NULL`` or an attribute list, like this:
|
||||
|
||||
lv_obj_t * btn1 = lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
|
||||
|
||||
Using the Exported Code
|
||||
***********************
|
||||
|
||||
If loading XML at runtime is not needed, LVGL's UI Editor can be used to export C and H files from the XML files of the Components.
|
||||
The resulting code is completely self-sufficient and the XML files are not needed anymore. The resulting code is similar to what one could write by hand as well.
|
||||
|
||||
Using Components from Exported C Code
|
||||
*************************************
|
||||
|
||||
From each Component XML file, a C and H file is exported with a single function inside:
|
||||
The exported code looks like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_obj_t * component_name_create(lv_obj_t * parent, ...api properties...);
|
||||
|
||||
where 'component_name' (in the function above) is replaced by the Component's XML
|
||||
where ``component_name`` is replaced by the Component's XML
|
||||
file name.
|
||||
|
||||
When a Component is used in another Component's XML code and the code is exported,
|
||||
this ``create`` function will be called. This means that Components do not have a
|
||||
detailed set/get API but can be created with a fixed set of parameters.
|
||||
detailed set/get API, but are created with a fixed set of parameters.
|
||||
|
||||
If the user needs to access or modify values dynamically, it is recommended to use a
|
||||
:ref:`Data bindings via Subject <xml_subjects>`.
|
||||
If the user needs to access or modify values dynamically, it is recommended to use
|
||||
:ref:`Data bindings via Subject <xml_subjects>`.
|
||||
|
||||
The user can also call these ``..._create()`` functions at any time from application code
|
||||
to create new components on demand.
|
||||
to create new Components on demand.
|
||||
|
||||
|
||||
|
||||
Extending
|
||||
*********
|
||||
|
||||
When a Component is defined as "extending" a Widget, it effectively inherits that
|
||||
Widget's attributes, and they can be used with that Component.
|
||||
(See ``<view extends="...">`` in the code examples below.)
|
||||
|
||||
|
||||
|
||||
.. _component_custom_properties:
|
||||
.. _component_custom_api:
|
||||
|
||||
Custom Properties
|
||||
*****************
|
||||
|
||||
The properties of child elements can be set directly, such as:
|
||||
The properties of child elements can be adjusted, such as:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<my_button x="10" width="200"/>
|
||||
|
||||
It is also possible to define custom properties in the ``<api>`` tag.
|
||||
Those properties then can thereafter be referenced in any properties of the children
|
||||
by using a ``$`` prefix with its name. Example:
|
||||
However, it's also possible to define custom properties in the ``<api>`` tag.
|
||||
These properties can then be passed to any properties of the children by
|
||||
referencing them using ``$``. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -175,7 +160,7 @@ by using a ``$`` prefix with its name. Example:
|
||||
</view>
|
||||
</component>
|
||||
|
||||
And it can be used by other Components like this:
|
||||
And it can be used like:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -188,22 +173,20 @@ And it can be used by other Components like this:
|
||||
</view>
|
||||
</component>
|
||||
|
||||
In this setup, the ``btn_text`` property is mandatory, however it can be made optional
|
||||
by providing a default value like this:
|
||||
In this setup, the ``btn_text`` property is mandatory. However, it can be made optional
|
||||
by setting a default value:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<prop name="btn_text" type="string" default="Title"/>
|
||||
|
||||
See :ref:`<api> <xml_api>` for more details, and :ref:`XML Syntax <xml_syntax>` for all the supported types.
|
||||
|
||||
|
||||
See :ref:`<api> <xml_api>` for more details and :ref:`XML Syntax <xml_syntax>` for all the supported types.
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
The following example demonstrates parameter passing and the use of the
|
||||
``text`` label property in a Component. Styles and Constants are also shown.
|
||||
``text`` label property on a Component. Styles and Constants are also shown.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -241,28 +224,16 @@ The following example demonstrates parameter passing and the use of the
|
||||
lv_xml_component_register_from_file("A:path/to/h3.xml");
|
||||
lv_xml_component_register_from_file("A:path/to/red_button.xml");
|
||||
|
||||
/* Create a button with "None" text. */
|
||||
/* Creates a button with "None" text */
|
||||
lv_xml_create(lv_screen_active(), "red_button", NULL);
|
||||
|
||||
/* Use attributes to set the button text. */
|
||||
/* Use attributes to set the button text */
|
||||
const char * attrs[] = {
|
||||
"btn_text", "Click here",
|
||||
NULL, NULL,
|
||||
};
|
||||
lv_xml_create(lv_screen_active(), "red_button", attrs);
|
||||
|
||||
|
||||
|
||||
Live Example
|
||||
*************
|
||||
|
||||
.. include:: ../../../../../../examples/others/xml/index.rst
|
||||
|
||||
|
||||
|
||||
API
|
||||
***
|
||||
|
||||
.. API startswith: lv_xml_component_
|
||||
|
||||
.. API equals: lv_xml_create
|
||||
+2
-2
@@ -17,7 +17,6 @@ The supported types are:
|
||||
- ``opa``
|
||||
- ``bool``
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
@@ -33,10 +32,11 @@ Constants can be used in:
|
||||
- Style properties
|
||||
- Widget and Component properties
|
||||
|
||||
And they can be used like this:
|
||||
Constant values can be referenced by ``#constant_name``. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<styles>
|
||||
<style name="style1" bg_color="#color1"/>
|
||||
</styles>
|
||||
|
||||
+6
-8
@@ -51,16 +51,13 @@ For example, ``callback="my_callback_1"`` will be exported as:
|
||||
|
||||
The ``user_data`` is optional. If omitted, ``NULL`` will be passed.
|
||||
|
||||
|
||||
.. _xml_events_screen:
|
||||
|
||||
|
||||
|
||||
Screen Load and Create events
|
||||
*****************************
|
||||
|
||||
By using the ``<screen_load_event>`` and ``<screen_create_event>`` tags as a child
|
||||
of a widget or component, screens can be loaded or created on a trigger (e.g. click).
|
||||
By using the ``<screen_load_event>`` and ``<screen_create_event>`` tags as children
|
||||
of a widget or component, screens can be loaded or created on a trigger (e.g., click).
|
||||
|
||||
The difference between load and create is that:
|
||||
|
||||
@@ -71,8 +68,8 @@ The difference between load and create is that:
|
||||
|
||||
Both tags support the following optional attributes:
|
||||
|
||||
- ``trigger``: Event code that triggers the action (e.g. ``"clicked"``, ``"long_pressed"``, etc). Default: ``"clicked"``.
|
||||
- ``anim_type``: Describes how the screen is loaded (e.g. ``"move_right"``, ``"fade_in"``). Default: ``"none"``.
|
||||
- ``trigger``: Event code that triggers the action (e.g., ``"clicked"``, ``"long_pressed"``, etc.). Default: ``"clicked"``.
|
||||
- ``anim_type``: Describes how the screen is loaded (e.g., ``"move_right"``, ``"fade_in"``). Default: ``"none"``.
|
||||
- ``duration``: Length of the animation in milliseconds. Default: ``0``. Only used if ``anim_type`` is not ``"none"``.
|
||||
- ``delay``: Wait time before loading the screen in milliseconds. Default: ``0``.
|
||||
|
||||
@@ -107,7 +104,7 @@ This is a simple example of both load and create:
|
||||
lv_xml_component_register_from_data("screen1", screen1_xml);
|
||||
lv_xml_component_register_from_data("screen2", screen2_xml);
|
||||
|
||||
/*Create an instance of screen_1 so that it can loaded from screen2.*/
|
||||
/* Create an instance of screen1 so that it can be loaded from screen2. */
|
||||
lv_obj_t * screen1 = lv_xml_create(NULL, "screen1", NULL);
|
||||
lv_screen_load(screen1);
|
||||
|
||||
@@ -153,3 +150,4 @@ If ``step`` is **negative**, the subject's value will be decremented.
|
||||
Only integer ``step`` values are supported now.
|
||||
|
||||
**Note:** Only integer subjects are supported by ``<subject_increment>``.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
.. _xml_ui_elements:
|
||||
|
||||
===========
|
||||
UI Elements
|
||||
===========
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
components
|
||||
widgets
|
||||
screens
|
||||
animations
|
||||
api
|
||||
consts
|
||||
events
|
||||
preview
|
||||
styles
|
||||
view
|
||||
+17
-6
@@ -16,13 +16,12 @@ These are **not** exported to code and are **not** loaded from XML.
|
||||
They are used only by the UI |nbsp| Editor to describe the context of the Component.
|
||||
For example, you might want to:
|
||||
|
||||
- Change the background of the Editor's preview to dark.
|
||||
- Center the Component.
|
||||
- Set margins.
|
||||
- Change the size of the preview.
|
||||
|
||||
``style_radius`` can be used to make preview rounded.
|
||||
- change the background of the Editor's preview to dark,
|
||||
- center the Component,
|
||||
- set margins,
|
||||
- change the size of the preview.
|
||||
|
||||
``style_radius`` can be used to make the preview rounded.
|
||||
|
||||
Usage
|
||||
*****
|
||||
@@ -36,7 +35,18 @@ You can think of a ``<preview>`` tag as an ``lv_obj`` where the following proper
|
||||
It is also possible to define multiple previews, and in the UI |nbsp| Editor, you can
|
||||
select one of them.
|
||||
|
||||
For Screens
|
||||
-----------
|
||||
|
||||
Screens don't support the :ref:`<preview> <xml_preview>` tag because it doesn't make
|
||||
sense to preview each screen in different resolutions.
|
||||
|
||||
As Screens are related to the target hardware in the ``project.xml`` file, multiple
|
||||
``<display>`` elements can be defined. In the UI |nbsp| Editor, when a Screen is being developed,
|
||||
the user can select from all the defined displays in the Preview, and the Screen will be shown with
|
||||
the given resolution and color depth.
|
||||
|
||||
This is useful for verifying responsive designs.
|
||||
|
||||
Example
|
||||
*******
|
||||
@@ -62,3 +72,4 @@ Example
|
||||
</view>
|
||||
|
||||
</component>
|
||||
|
||||
+22
-24
@@ -15,34 +15,35 @@ Screens work very similarly to Components. Both can be:
|
||||
- Loaded from XML
|
||||
- Contain Widgets and Components as children
|
||||
|
||||
Screens have ``<screen>`` as their root element and are used to organize
|
||||
Screens are wrapped in the ``<screen>`` XML root element and used to organize
|
||||
the content of the UI.
|
||||
|
||||
``<screen>`` elements may contain only the following child elements:
|
||||
Screens can have only the following child XML tags:
|
||||
|
||||
- :ref:`<consts> <xml_consts>`
|
||||
- :ref:`<styles> <xml_styles>`, and
|
||||
- :ref:`<styles> <xml_styles>`
|
||||
- :ref:`<view> <xml_view>`
|
||||
|
||||
That is, Screens **cannot** have :ref:`<api> <xml_api>` or :ref:`<preview> <xml_preview>`
|
||||
elements.
|
||||
|
||||
That is, Screens **cannot** have:
|
||||
|
||||
- :ref:`<api> <xml_api>`: Screens are always created as they are, with no parameters.
|
||||
- :ref:`<preview> <xml_preview>`: In LVGL's UI Editor, ``<preview>`` is used to set the style, size, and other parameters of the previewing "screen". For Screens, the
|
||||
preview options are defined in ``project.xml``. Learn more in :ref:`Screen preview <xml_screen_preview>`
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
Each Screen XML file defines a :ref:`Screen <screens>`. The name of the XML file will
|
||||
be the name of the Screen.
|
||||
Each XML file describes a :ref:`Screen <screens>`. The name of the XML file will
|
||||
also be the name of the Screen.
|
||||
|
||||
This example illustrates a Screen in XML. In the example, a ``<my_header>``
|
||||
and a ``<my_main_cont>`` component is used to keep the screen simple.
|
||||
This example illustrates a screen in XML. In the example, a ``<my_header>``
|
||||
and a ``<my_main_cont>`` component are used to keep the screen simple.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<screen>
|
||||
<consts>
|
||||
<string name="title" value="Main Menu"/>
|
||||
<string name="title" value="Main menu"/>
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
@@ -62,17 +63,15 @@ and a ``<my_main_cont>`` component is used to keep the screen simple.
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
|
||||
|
||||
Code Export
|
||||
Code export
|
||||
***********
|
||||
|
||||
When C code is exported from the UI |nbsp| Editor, ``screen_name_gen.c/h`` files are exported,
|
||||
LVGL's UI Editor can export C code for Screens as well. It generates ``screen_name_gen.c/h`` files,
|
||||
containing only a single ``lv_obj_t * screen_name_create(void)`` create function.
|
||||
|
||||
By using this function, any number of screen instances can be created and loaded as needed.
|
||||
|
||||
|
||||
.. _xml_screen_preview:
|
||||
|
||||
Preview
|
||||
*******
|
||||
@@ -80,19 +79,17 @@ Preview
|
||||
Screens don't support the :ref:`<preview> <xml_preview>` tag because it doesn't make
|
||||
sense to preview each screen in different resolutions.
|
||||
|
||||
Since Screens are related to target hardware specified in the ``project.xml`` file, multiple
|
||||
As Screens are related to the target hardware in the ``project.xml`` file, multiple
|
||||
``<display>`` elements can be defined. In the UI |nbsp| Editor, when a Screen is being developed,
|
||||
the user can select from all the defined displays in the Preview, and the Screen will be shown with
|
||||
the given resolution and color depth.
|
||||
|
||||
This is useful for verifying responsive designs.
|
||||
|
||||
|
||||
|
||||
Events
|
||||
******
|
||||
|
||||
It is very common to load or create Screens from a button-click or other type of event.
|
||||
It's very common to load or create Screens on a button click or other events.
|
||||
|
||||
Both are supported by adding special XML tags as children of Components or Widgets:
|
||||
|
||||
@@ -102,15 +99,16 @@ Both are supported by adding special XML tags as children of Components or Widge
|
||||
<lv_button>
|
||||
<lv_label text="Click or Long press me"/>
|
||||
|
||||
<!-- Load an already created screen named "first".
|
||||
<!-- Load an already created screen that has the name "first".
|
||||
Note that here the name of the instance is used,
|
||||
not the name of the XML file. -->
|
||||
and not the name of the XML file. -->
|
||||
<screen_load_event screen="first" trigger="clicked" anim_type="fade"/>
|
||||
|
||||
<!-- Create an instance of "about" Screen and load it.
|
||||
Note that the name of the XML file is used. -->
|
||||
<!-- Create an instance of "about" and load it.
|
||||
Note that here the name of the XML file is used. -->
|
||||
<screen_create_event screen="about" trigger="long_pressed"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
|
||||
Learn more on the :ref:`XML Events <xml_events_screen>` page.
|
||||
|
||||
+40
-10
@@ -9,7 +9,6 @@ Overview
|
||||
|
||||
In XML files, both style sheets (:cpp:expr:`lv_style_t`) and local styles can be used.
|
||||
|
||||
|
||||
Style Sheets
|
||||
************
|
||||
|
||||
@@ -22,7 +21,8 @@ In the ``<styles>`` section, styles and their properties can be defined like thi
|
||||
border_width="2px"
|
||||
border_color="0xff0000"/>
|
||||
|
||||
Styles can be referenced like this in the ``<view>``\ :
|
||||
Styles can be referenced like this in the ``<view>``:
|
||||
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -30,22 +30,53 @@ Styles can be referenced like this in the ``<view>``\ :
|
||||
<lv_slider value="20">
|
||||
<style name="main"/>
|
||||
<style name="red" selector="knob"/>
|
||||
<style name="blue" selector="knob focused"/>
|
||||
<style name="blue" selector="knob|focused"/>
|
||||
</lv_slider>
|
||||
</view>
|
||||
|
||||
As shown in the example, parts and states can be set as ``selector``\ .
|
||||
As shown in the example, parts and states can be set using ``selector``.
|
||||
|
||||
Style binding
|
||||
*************
|
||||
|
||||
Instead of directly adding styles to the UI elements it's also possible to add them conditionally
|
||||
when a :ref:`Subject <observer_how_to_use>`\ 's value equals to a reference value.
|
||||
|
||||
It works at runtime and it's a great way to check the appearace or event the layout based on a condition.
|
||||
|
||||
A typical use case is the light/dark theme switching. It requires
|
||||
|
||||
- a subject such as ``dark_theme_on``
|
||||
- some default style that are added normally with the ``<style>`` tag
|
||||
- some dark styles to check the required colors to dark
|
||||
|
||||
Here is an example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<component>
|
||||
<styles>
|
||||
<style name="style_base" bg_color="0xeee" text_color="0x111" radius="20" />
|
||||
<style name="style_dark" bg_color="0x333" text_color="0xeee" radius="20" />
|
||||
</styles>
|
||||
|
||||
<view extends="lv_button">
|
||||
<style name="style_base" />
|
||||
<bind_style name="style_dark" subject="dark_theme_on" ref_value="1"/>
|
||||
<lv_label text="Apply"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
Local Styles
|
||||
************
|
||||
|
||||
Local styles can be used directly in a Widget, for example:
|
||||
Local styles can be used directly, for example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<lv_label style_bg_opa="200" style_bg_opa:disabled="100"/>
|
||||
<lv_label style_bg_opa="200" style_bg_color="0x123456"/>
|
||||
|
||||
Selectors are not supported for local style properties yet.
|
||||
|
||||
Gradients
|
||||
*********
|
||||
@@ -65,11 +96,12 @@ or
|
||||
|
||||
<lv_button style_bg_grad="grad1"/>
|
||||
|
||||
Note that gradients are not supported in LVGL's UI Editor yet.
|
||||
|
||||
Horizontal or Vertical Gradient
|
||||
-------------------------------
|
||||
|
||||
To define a simple ``<horizontal>`` or ``<vertical>`` gradients:
|
||||
To define a simple ``<horizontal>`` or ``<vertical>`` gradient:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -80,7 +112,6 @@ To define a simple ``<horizontal>`` or ``<vertical>`` gradients:
|
||||
</horizontal>
|
||||
</gradients>
|
||||
|
||||
|
||||
Linear Gradient
|
||||
---------------
|
||||
|
||||
@@ -95,7 +126,6 @@ To define a skewed gradient from two points:
|
||||
</linear>
|
||||
</gradients>
|
||||
|
||||
|
||||
Radial Gradient
|
||||
---------------
|
||||
|
||||
@@ -110,7 +140,6 @@ To define a radial gradient:
|
||||
</radial>
|
||||
</gradients>
|
||||
|
||||
|
||||
Conical Gradient
|
||||
----------------
|
||||
|
||||
@@ -124,3 +153,4 @@ To define a conical gradient:
|
||||
<stop color="#00ff00" opa="100%"/>
|
||||
</conical>
|
||||
</gradients>
|
||||
|
||||
+8
-9
@@ -7,15 +7,15 @@ View
|
||||
Overview
|
||||
********
|
||||
|
||||
The ``<view>`` tag can be used as a child of the following tags:
|
||||
The ``<view>`` tag can be used in:
|
||||
|
||||
- ``<component>``
|
||||
- ``<widget>``
|
||||
- ``<screen>``
|
||||
- ``<test>``
|
||||
- ``<component>``\ s
|
||||
- ``<widget>``\ s
|
||||
- ``<screen>``\ s
|
||||
- ``<test>``\ s
|
||||
|
||||
to describe how these items look. Inside ``<view>``, children can be added in a nested way
|
||||
using already defined ``widget``\ s and ``component``\ s. For example:
|
||||
using already defined ``widget``\s and ``component``\s. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -26,8 +26,6 @@ using already defined ``widget``\ s and ``component``\ s. For example:
|
||||
</lv_button>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
Extends
|
||||
*******
|
||||
|
||||
@@ -45,9 +43,10 @@ By adding properties to the ``<view>``, the extended type can be customized. For
|
||||
<lv_label bind_text="subject_1"/>
|
||||
</view>
|
||||
|
||||
Rules for the allowed values of ``extends``:
|
||||
Rules for allowed values of ``extends``:
|
||||
|
||||
- ``<component>``: can extend both ``<widget>``\ s and ``<component>``\ s
|
||||
- ``<widget>``: can extend only ``<widget>``\ s
|
||||
- ``<screen>``: cannot extend anything
|
||||
- ``<test>``: can extend ``<widget>``, ``<component>``, or ``<screen>``
|
||||
|
||||
+78
-83
@@ -10,88 +10,61 @@ Overview
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Besides components and Screens, Widgets are the other main building blocks of UIs.
|
||||
XML files defining Widgets have ``<widget>`` as their XML root element.
|
||||
Besides Components and Screens, Widgets are the other main building blocks of UIs.
|
||||
|
||||
``<widget>`` elements may contain the following child elements:
|
||||
The XML file of a Widget is wrapped in a ``<widget>`` XML root element.
|
||||
|
||||
``<widget>``\s support the following child XML tags:
|
||||
|
||||
- :ref:`<consts> <xml_consts>`
|
||||
- :ref:`<api> <xml_api>`
|
||||
- :ref:`<styles> <xml_styles>`, and
|
||||
- :ref:`<styles> <xml_styles>`
|
||||
- :ref:`<view> <xml_view>`
|
||||
- :ref:`<previews> <xml_preview>`
|
||||
|
||||
Just like Components, Widgets can also be the children of other Widgets and Components.
|
||||
|
||||
The main difference is that Widgets are written in C and compiled into the
|
||||
application. This means, unlike Components, Widgets can contain custom C code. For
|
||||
example, when a property is set, any complex C code can run to set that value.
|
||||
|
||||
To connect the C code to XML, XML parser functions need to be implemented and registered. It is
|
||||
pretty simple since LVGL already provides all the helper functions and the required libraries. Also there
|
||||
are `many XML parser examples here <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__.
|
||||
Just like Components, Widgets can also be children of other Widgets and Components.
|
||||
|
||||
Note that Widgets cannot be loaded from XML directly, but it's possible to write and register
|
||||
simple XML parsers for Widgets. When a Widget is referenced in a Component's or Screen's XML,
|
||||
the XML parser will be called to map the properties to C function calls.
|
||||
|
||||
LVGL already provides all the helper functions and required libraries. There are also
|
||||
`many XML parser examples here <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__
|
||||
for the built-in LVGL Widgets.
|
||||
|
||||
Built-in Widgets
|
||||
****************
|
||||
|
||||
LVGL already has XML parsers for LVGL's built-in widgets (e.g. :ref:`lv_slider`,
|
||||
:ref:`lv_label`, :ref:`lv_chart`, etc.), which makes them available in XML.
|
||||
The built-in LVGL widgets (e.g., :ref:`lv_slider`, :ref:`lv_label`, :ref:`lv_chart`, etc.) already
|
||||
have XML parsers and are therefore available in XML.
|
||||
|
||||
Example:
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view>
|
||||
<lv_label x="10" text="Hello"/>
|
||||
</view>
|
||||
<component>
|
||||
<view>
|
||||
<lv_label x="10" text="Hello"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
The built-in widgets are:
|
||||
The built-in widgets consist of:
|
||||
|
||||
- pure C code
|
||||
(e.g. `lv_slider.c <https://github.com/lvgl/lvgl/tree/master/src/widgets/slider/lv_slider.c>`__)
|
||||
- an XML file to define only the API
|
||||
(e.g. `lv_slider.xml <https://github.com/lvgl/lvgl/blob/master/xmls/lv_slider.xml>`__)
|
||||
(used only in the UI |nbsp| Editor to validate and autocomplete properties)
|
||||
- an XML parser C file to map the XML attributes to C functions.
|
||||
(e.g. `lv_xml_slider_parser.c <https://github.com/lvgl/lvgl/blob/master/src/others/xml/parsers/lv_xml_slider_parser.c>`__)
|
||||
|
||||
|
||||
|
||||
Creating New Widgets
|
||||
********************
|
||||
|
||||
It is possible to create new Widgets that can be treated in the same way as built-in
|
||||
LVGL Widgets.
|
||||
|
||||
However, using the UI |nbsp| Editor it's much faster and simpler. When an XML file is created and
|
||||
the ``<widget>`` root element is used, the following .C/.H files are generated automatically:
|
||||
|
||||
:<widget_name>_gen.h: Contains the generated API implementation of the widget
|
||||
(overwritten on each code export).
|
||||
:<widget_name>_private_gen.h: Contains private API and the data for the widget
|
||||
(overwritten on each code export).
|
||||
:<widget_name>_gen.c: Contains the internals of the Widget, e.g. constructor with the children,
|
||||
destructors, event handler, etc. (overwritten on each code export).
|
||||
:<widget_name>.h: Includes ``<widget_name>_gen.h`` and allows the user to
|
||||
define custom APIs. Only a skeleton is exported once.
|
||||
:<widget_name>.c: Contains hooks from ``<widget_name>_gen.c`` and allows
|
||||
the user to write custom code. Only a skeleton is
|
||||
exported once.
|
||||
:<widget_name>_xml_parser.c: Processes the XML strings and calls the required
|
||||
functions according to the set attributes. Only a
|
||||
skeleton is exported once.
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
- Pure C code
|
||||
(e.g., `lv_slider.c <https://github.com/lvgl/lvgl/tree/master/src/widgets/slider/lv_slider.c>`__)
|
||||
- An XML file to define only the API
|
||||
(e.g., `lv_slider.xml <https://github.com/lvgl/lvgl/blob/master/xmls/lv_slider.xml>`__),
|
||||
used only in the UI |nbsp| Editor to validate and autocomplete properties
|
||||
- An XML parser C file to map the XML attributes to C functions
|
||||
(e.g., `lv_xml_slider_parser.c <https://github.com/lvgl/lvgl/blob/master/src/others/xml/parsers/lv_xml_slider_parser.c>`__)
|
||||
|
||||
XML Parser
|
||||
----------
|
||||
**********
|
||||
|
||||
To make the Widgets accessible from XML, an XML parser needs to be created and
|
||||
Write a parser
|
||||
--------------
|
||||
|
||||
To make Widgets accessible from XML, an XML parser needs to be created and
|
||||
registered for each Widget. The XML parser for the label Widget looks like this:
|
||||
|
||||
.. code-block:: c
|
||||
@@ -117,7 +90,7 @@ registered for each Widget. The XML parser for the label Widget looks like this:
|
||||
|
||||
if(lv_streq("text", name)) lv_label_set_text(obj, value);
|
||||
if(lv_streq("long_mode", name)) lv_label_set_long_mode(obj, long_mode_text_to_enum(value));
|
||||
/* Process more props here */
|
||||
/* Process more props here ... */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +104,13 @@ registered for each Widget. The XML parser for the label Widget looks like this:
|
||||
return 0; /* Return 0 in the absence of a better option. */
|
||||
}
|
||||
|
||||
A Widget XML processor can be registered like this:
|
||||
By using lines like ``if(lv_streq("text", name)) lv_label_set_text(obj, value);``,
|
||||
any ``set`` function can be mapped to XML properties.
|
||||
|
||||
Register a widget
|
||||
-----------------
|
||||
|
||||
A Widget XML processor can be registered as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -147,9 +126,9 @@ After registration, a Widget can be created like this from C code:
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
lv_xml_create(lv_screen_active(), "lv_label", attrs);
|
||||
lv_obj_t * label = lv_xml_create(lv_screen_active(), "lv_label", attrs);
|
||||
|
||||
And in XML it can be used like this:
|
||||
And in XML, it can be used like this:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
@@ -157,18 +136,43 @@ And in XML it can be used like this:
|
||||
<lv_label width="100" text="I'm a label!" wrap="scroll"/>
|
||||
</view>
|
||||
|
||||
Usage in LVGL's UI Editor
|
||||
*************************
|
||||
|
||||
New widget
|
||||
----------
|
||||
|
||||
It's possible to create new widgets by writing C code manually (the same way as built-in LVGL widgets are created),
|
||||
however, using the UI |nbsp| Editor is much faster and simpler.
|
||||
|
||||
When an XML file is created and the ``<widget>`` root element is used, the following .C/.H files are generated automatically:
|
||||
|
||||
:<widget_name>_gen.h: Contains the generated API implementation of the Widget
|
||||
(overwritten on each code export)
|
||||
:<widget_name>_private_gen.h: Contains private API and data for the Widget
|
||||
(overwritten on each code export)
|
||||
:<widget_name>_gen.c: Contains the internals of the Widget, e.g., constructor with children,
|
||||
destructor, event handler, etc. (overwritten on each code export)
|
||||
:<widget_name>.h: Includes ``<widget_name>_gen.h`` and allows the user to
|
||||
define custom APIs. Only a skeleton is exported once
|
||||
:<widget_name>.c: Contains hooks from ``<widget_name>_gen.c`` and allows
|
||||
the user to write custom code. Only a skeleton is
|
||||
exported once
|
||||
:<widget_name>_xml_parser.c: Processes the XML strings and calls the required
|
||||
functions according to the set attributes. Only a
|
||||
skeleton is exported once
|
||||
|
||||
Adding Custom Code
|
||||
------------------
|
||||
|
||||
``<widget_name>.c`` contains three hooks:
|
||||
|
||||
- **Constructor hook**: Called when the Widget and all its children are created. Any
|
||||
modifications to the children can be done here.
|
||||
- **Destructor hook**: Called when the Widget is deleted. All manually allocated
|
||||
memory needs to be freed here.
|
||||
- **Constructor hook**: Called when the Widget and all its children are created.
|
||||
Any modifications can be done on the children here.
|
||||
- **Destructor hook**: Called when the Widget is deleted.
|
||||
All manually allocated memory needs to be freed here.
|
||||
- **Event hook**: Called at the beginning of the Widget's event callback to perform
|
||||
any custom actions.
|
||||
any custom action.
|
||||
|
||||
In this C file, the ``set`` functions for each API ``<prop>`` also need to be
|
||||
implemented. The declaration of these functions is automatically exported in
|
||||
@@ -176,23 +180,14 @@ implemented. The declaration of these functions is automatically exported in
|
||||
|
||||
Besides these, any custom code and functions can be freely implemented in this file.
|
||||
|
||||
|
||||
Elements
|
||||
--------
|
||||
|
||||
Elements are internal parts of the widget that can be accessed and/or created dynamically.
|
||||
For example, tabs of a tabview, list of a dropdown, series of a chart, etc..
|
||||
Elements are internal parts of the Widget that can be accessed and/or created dynamically.
|
||||
For example: tabs of a tabview, list of a dropdown, series of a chart, etc.
|
||||
|
||||
Just like any other Widget API properties, Elements also can be defined within the
|
||||
``<api>`` element of the Widget's XML.
|
||||
Just like any other Widget API properties, Elements can also be defined in the ``<api>``
|
||||
tag of the Widget's XML.
|
||||
|
||||
Learn more about Elements under the :ref:`<api> element documentation <xml_widget_element>`.
|
||||
Learn more about Elements in the documentation page for :ref:`<api> <xml_widget_element>`.
|
||||
|
||||
|
||||
|
||||
API
|
||||
***
|
||||
|
||||
.. API startswith: lv_xml_widget_
|
||||
|
||||
.. API equals: lv_xml_create
|
||||
Reference in New Issue
Block a user