docs(xml): next set of XML-doc refinements (#8740)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
Victor Wheeler
2025-09-05 08:33:31 -06:00
committed by GitHub
parent fccd5f2383
commit e2c77ac678
12 changed files with 278 additions and 185 deletions
+4 -4
View File
@@ -1,8 +1,8 @@
.. _xml_build_ui:
.. _xml_building_uis:
=========
Build UIs
=========
============
Building UIs
============
.. toctree::
:class: toctree-1-deep
@@ -13,6 +13,8 @@ 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
**********
@@ -41,6 +43,7 @@ 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
----------------------
@@ -50,6 +53,7 @@ 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
--------------
@@ -59,12 +63,14 @@ 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
-------
@@ -92,9 +98,12 @@ Example
</view>
</component>
Widgets
*******
Properties
----------
@@ -106,6 +115,7 @@ Properties are the core part of describing a Widget's API.
<prop name="text" type="string" help="Text of the label."/>
</api>
Parameters
----------
@@ -137,6 +147,7 @@ Unset parameters fall back to:
- Their default value (if defined)
- Type-specific defaults (e.g., 0, false, NULL)
Mapping
-------
@@ -148,6 +159,7 @@ 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>
---------
@@ -168,6 +180,7 @@ Only used with Widgets, this tag defines enums for parameter values.
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.
.. _xml_widget_element:
<element>
@@ -1,11 +1,10 @@
.. _xml_main_tags:
=========
Main tags
=========
=============
Main XML Tags
=============
.. toctree::
:class: toctree-1-deep
:maxdepth: 2
api
@@ -7,12 +7,12 @@ View
Overview
********
The ``<view>`` tag can be used in:
The ``<view>`` tag can be used as a child of the following tags:
- ``<component>``\ s
- ``<widget>``\ s
- ``<screen>``\ s
- ``<test>``\ s
- ``<component>``
- ``<widget>``
- ``<screen>``
- ``<test>``
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:
@@ -26,6 +26,8 @@ using already defined ``widget``\ s and ``component``\ s. For example:
</lv_button>
</view>
Extends
*******
@@ -9,7 +9,7 @@ Overview
Components are one of the main building blocks for creating new UI elements.
``<component>``\ s support the following child XML tags:
``<component>`` elements may contain the following child elements:
- :ref:`<consts> <xml_consts>`
- :ref:`<api> <xml_api>`
@@ -19,33 +19,38 @@ Components are one of the main building blocks for creating new UI elements.
Although they can't contain C code, they are very powerful:
- 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 the global styles can be used
- Local constants can be defined, and the 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
- 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.
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.
Usage from XML
**************
Using Components from XML
*************************
In XML Files
------------
Using Components in XMLs is very intuitive. The name of the components can be used as XML tag
in the ``<view>`` of other Components, Screens, and Widgets.
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.
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 file. Once the data is saved, each component
can be registered, and instances can be created after that.
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.
.. code-block:: xml
@@ -57,8 +62,9 @@ can be registered, and instances can be created after that.
</view>
</component>
:ref:`Styles <xml_styles>`, :ref:`Constants <xml_consts>`, and :ref:`custom API <component_custom_api>`
can also be described in the XML files.
:ref:`Styles <xml_styles>`, :ref:`Constants <xml_consts>`, and a
:ref:`custom API <component_custom_properties>` can also be described in the XML files.
Registration
------------
@@ -68,15 +74,18 @@ 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.
This is required to make LVGL recognize the Component by name.
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.
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.
During registration, the ``<view>`` of the Component is saved in RAM as a template for
creating instances of that Component.
When loaded from a file, the file name is used as the Component name.
.. 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.
During registration, the ``<view>`` of the Component is saved in RAM.
Instantiation
-------------
@@ -87,7 +96,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 manually-created Widget.
The created Widget is a normal LVGL Widget that can be used like any other Widget.
The last parameter can be ``NULL`` or an attribute list, like this:
@@ -103,8 +112,10 @@ 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);
Usage from Exported Code
************************
Using Components from Exported C Code
*************************************
From each Component XML file, a C and H file is exported with a single function inside:
@@ -125,28 +136,31 @@ If the user needs to access or modify values dynamically, it is recommended to u
The user can also call these ``..._create()`` functions at any time from application code
to create new components on demand.
Extending
*********
Additionally, when a Component is created, it can use the extended Widget's attributes
(see ``<view extends="...">`` in the code examples below).
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.)
This means that Components inherit the API of the extended Widget as well.
.. _component_custom_api:
.. _component_custom_properties:
Custom Properties
*****************
The properties of child elements can be adjusted, such as:
The properties of child elements can be set directly, such as:
.. code-block:: xml
<my_button x="10" width="200"/>
However, it's also possible to define custom properties in the ``<api>`` tag.
The properties then can be passed to any properties of the children by
referencing them by ``$``. For example:
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:
.. code-block:: xml
@@ -161,7 +175,7 @@ referencing them by ``$``. For example:
</view>
</component>
And it can be used like
And it can be used by other Components like this:
.. code-block:: xml
@@ -175,19 +189,21 @@ And it can be used like
</component>
In this setup, the ``btn_text`` property is mandatory, however it can be made optional
by setting a default value:
by providing a default value like this:
.. 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 on a Component. Styles and Constants are also shown.
``text`` label property in a Component. Styles and Constants are also shown.
.. code-block:: xml
@@ -225,20 +241,28 @@ 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");
/* Creates a button with "None" text */
/* Create 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
@@ -15,31 +15,34 @@ Screens work very similarly to Components. Both can be:
- Loaded from XML
- Contain Widgets and Components as children
Screens are wrapped in the ``<screen>`` XML root element and used to organize
Screens have ``<screen>`` as their root element and are used to organize
the content of the UI.
Screens can have only the following child XML tags:
``<screen>`` elements may contain only the following child elements:
- :ref:`<consts> <xml_consts>`
- :ref:`<styles> <xml_styles>`, and
- :ref:`<view> <xml_view>`
That is, Screens **cannot** have an :ref:`<api> <xml_api>` or :ref:`<preview> <xml_preview>`.
That is, Screens **cannot** have :ref:`<api> <xml_api>` or :ref:`<preview> <xml_preview>`
elements.
Usage
*****
Each XML file describes a :ref:`Screen <screens>`. The name of the XML file will
also be the name of the Screen.
Each Screen XML file defines a :ref:`Screen <screens>`. The name of the XML file will
be the name of the Screen.
This example illustrates a screen in XML. In the example, a ``<my_header>``
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.
.. code-block:: xml
<screen>
<consts>
<string name="title" value="Main menu"/>
<string name="title" value="Main Menu"/>
</consts>
<styles>
@@ -59,31 +62,37 @@ and a ``<my_main_cont>`` component is used to keep the screen simple.
</view>
</screen>
Code export
Code Export
***********
When the C code is exported from the UI |nbsp| Editor, ``screen_name_gen.c/h`` files are exported,
When C code is exported from the UI |nbsp| Editor, ``screen_name_gen.c/h`` files are exported,
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.
Preview
*******
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
Since Screens are related to target hardware specified 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's very common to load or create Screens on a button click or other events.
It is very common to load or create Screens from a button-click or other type of event.
Both are supported by adding special XML tags as children of Components or Widgets:
@@ -93,15 +102,15 @@ 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 that has the name "first".
<!-- Load an already created screen named "first".
Note that here the name of the instance is used,
and not the name of the XML file. -->
not the name of the XML file. -->
<screen_load_event screen="first" trigger="clicked" anim_type="fade"/>
<!-- Create an instance of "about" and load it.
Note that here the name of the XML file is used. -->
<!-- Create an instance of "about" Screen and load it.
Note that the name of the XML file is used. -->
<screen_create_event screen="about" trigger="long_pressed"/>
</lv_button>
</view>
Learn more on :ref:`XML Events <xml_events_screen>` page.
Learn more on the :ref:`XML Events <xml_events_screen>` page.
@@ -11,9 +11,9 @@ Overview
:trim:
Besides components and Screens, Widgets are the other main building blocks of UIs.
The XML file of the Widgets is wrapped in a ``<widget>`` XML root element.
XML files defining Widgets have ``<widget>`` as their XML root element.
``<widget>``\ s support the following child XML tags:
``<widget>`` elements may contain the following child elements:
- :ref:`<consts> <xml_consts>`
- :ref:`<api> <xml_api>`
@@ -21,23 +21,25 @@ The XML file of the Widgets is wrapped in a ``<widget>`` XML root element.
- :ref:`<view> <xml_view>`
- :ref:`<previews> <xml_preview>`
Just like Components, Widgets also can be the children of other Widgets and Components.
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>`__.
The main difference is that Widgets are written in C and compiled into the application.
It 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's
pretty simple as 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>`__
Built-in Widgets
****************
The built-in LVGL widgets (e.g. :ref:`lv_slider`, :ref:`lv_label`, :ref:`lv_chart`, etc.) already
have XML parsers and therefore are available in XML.
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.
For example:
Example:
.. code-block:: xml
@@ -45,20 +47,23 @@ For example:
<lv_label x="10" text="Hello"/>
</view>
The built-in widgets are
The built-in widgets are:
- 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>`__).
It is used only in the UI |nbsp| Editor to validate and autocomplete properties.
(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's possible to create new widgets in the same way as the built-in LVGL widgets are handled.
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:
@@ -78,6 +83,8 @@ the ``<widget>`` root element is used, the following .C/.H files are generated a
functions according to the set attributes. Only a
skeleton is exported once.
Usage
*****
@@ -142,7 +149,7 @@ After registration, a Widget can be created like this from C code:
lv_xml_create(lv_screen_active(), "lv_label", attrs);
And in XML it can be used like
And in XML it can be used like this:
.. code-block:: xml
@@ -150,17 +157,18 @@ And in XML it can be used like
<lv_label width="100" text="I'm a label!" wrap="scroll"/>
</view>
Adding Custom Code
------------------
``<widget_name>.c`` contains three hooks:
- **Constructor hook**: Called when the Widget and all its children are created. Any
modifications can be done on the children here.
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.
- **Event hook**: Called at the beginning of the Widget's event callback to perform
any custom action.
any custom actions.
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
@@ -168,13 +176,23 @@ 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.
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 in the ``<api>``
tag of the Widget's XML.
Just like any other Widget API properties, Elements also can be defined within the
``<api>`` element of the Widget's XML.
Learn more about the Elements in the documentation page of :ref:`<api> <xml_widget_element>`.
Learn more about Elements under the :ref:`<api> element documentation <xml_widget_element>`.
API
***
.. API startswith: lv_xml_widget_
.. API equals: lv_xml_create
@@ -1,8 +1,8 @@
.. _xml_translation:
============
Translations
============
=====================
Language Translations
=====================
Overview
********
@@ -10,7 +10,10 @@ Overview
The XML translation module allows defining and using translated strings directly within XML files.
It's built on top of :ref:`LVGL's translation module <translation>`.
Check it out to learn more about selecting the active language, retrieving translations, and fallback behavior.
Check it out to learn more about selecting the active language, retrieving
translations, and fallback behavior.
Usage
@@ -13,17 +13,18 @@ Overview
The collection of Components, Widgets, Screens, Images, Fonts, etc., is called a
Component Library.
A Component Library can be fully self-sufficient, but it can also reference data from
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
etc. You can find the XML files that describe the LVGL Widgets
`here <https://github.com/lvgl/lvgl/tree/master/xmls>`__.
A project always has at least 2 Component Libraries: that of LVGL as mentioned
above, and its own where the Screens, Components, and Widgets of the project are
defined. A project may include additional Component Libraries.
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
@@ -63,33 +64,30 @@ A typical structure for a Component Library looks like this:
└── image2.png
Visibility
**********
Name Visibility
***************
The content of all ``globals.xml`` files is part of a common global scope, and
any Components, Widgets or Screens defined therein can be used in all .XML files.
In the context of UI components defined in XML files, there are two namespaces:
Styles, constants, and other data defined in the XML file of Components, Widgets, or Screens
are local to that XML file.
:global namespace:
Thus, there are two namespaces:
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.
1. **local namespace** within the given XML file of Components, Widgets and Screens.
2. **global namespace** created from the data in the ``globals.xml`` file from each
Component Library included.
:local namespace:
To find names referenced in XML files, the local namespace is checked first, and if
a name is not found there, then the global namespace is checked.
The names of defined Components, Widgets and Screens become part of the global
namespace and must be unique therein. This ensures that each Component has a unique
name.
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 developer deems appropriate.
anything else the development team deems appropriate.
LVGL's UI |nbsp| Editor will show an error if there is a name conflict.
@@ -105,7 +103,7 @@ 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.
:<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.
+53 -32
View File
@@ -7,15 +7,33 @@ Introduction
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
:trim:
The LVGL XML Module implements LVGL's Declarative UI by loading UI elements written in
XML. 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
provides features like:
.. glossary::
- Instant preview of the XML files
- Autocomplete and Syntax highlighting
- Online preview for collaboration and testing
- `Figma <https://www.figma.com/>`__ integration to easily reimplement Figma designs
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::
@@ -60,7 +78,7 @@ push it back to the git repository so that other projects can be updated from it
The built-in Widgets of LVGL are considered ``the core Component Library`` which is
always available.
A UI editor project can have any number of Component Libraries but will always
A UI Editor project can have any number of Component Libraries but will always
have at least 2:
- LVGL's built-in Widgets, and
@@ -88,11 +106,11 @@ but rather compiled into the application as C code. The main characteristics of
- 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 handwritten Widget can be accessed from XML by:
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 some examples here. <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__
`See examples here. <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__
Components
@@ -109,10 +127,11 @@ The main characteristics of Components are:
- 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).
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 children as part of Screens and other Components.
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.
Screens
@@ -124,7 +143,7 @@ Screens
- 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 do not have an API.
- They can be referenced in Screen load events.
- They can be referenced in Screen-load events.
@@ -148,7 +167,7 @@ will be children of these root elements:
children and their properties.
This is a simple example illustrating what an LVGL XML Component looks like.
Note that only the basic features are shown here.
Only basic features are shown.
.. code-block:: xml
@@ -183,34 +202,36 @@ Usage Teaser
LVGL's UI editor can be used in two different ways.
Export C and H Files
--------------------
The Widgets, Components, Screens, images, fonts, etc., can be converted to .C/.H files having
plain LVGL code. The exported code works the same way as if it was written by the
user.
code that accesses the LVGL API in the same way user-written code does.
In this case, the XML files are not required anymore to run the C code (unless modifications may
be made later and code is exported again).
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 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.
The XML files were used only during editing/implementing the Widgets and Components to save
recompilation time and optionally leverage other useful UI |nbsp| Editor features.
Load the UI from XML
--------------------
Although the Widgets' code always needs to be exported in C and compiled into the
application (just like the built-in LVGL Widgets are also part of the application), the Components'
XML can be loaded and any number of instances can be created at runtime.
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 the UI from XML practically has 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.
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 XMLs 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
12 kB/component).
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 12 kB/component).
+3 -2
View File
@@ -13,8 +13,9 @@ Overview
A single ``project.xml`` file should be created for each project where the following
content is specified:
:<folders>: Specifies the path to Component Libraries. LVGL's base Widgets are
always loaded automatically.
:<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.
+37 -32
View File
@@ -11,15 +11,15 @@ Naming conventions
:trim:
- A standard XML syntax is used.
- Lowercase letters with ``_`` separation are used for attribute names.
- Tag names follow the usual variable-name rules: they must start with a letter or
- 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
``'_'`` 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 with ``$``.
- ``consts`` can be referenced with ``#``.
- ``params`` can be referenced using ``$`` as a name prefix.
- ``consts`` can be referenced using ``#`` as a name prefix.
- ``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
Types
*****
Data Types
**********
All of the types can be used as API property types, but only a subset of them can be
All of the data 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 -2B to 2B by default.
:int: Integer number in the range of roughly -2 billion to 2 billion by default.
(Same as ``int32_t`` in C.)
:px: Simple pixel units. The unit ``px`` can be omitted.
:px: Simple pixel units. The unit suffix ``px`` can be omitted from the numeric value.
:%: Percentage. ``%`` must be appended to the value as the unit.
(Means the same as :cpp:expr:`lv_pct()`.)
@@ -53,7 +53,8 @@ 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'"``.
property or string array, ``'`` should be used. E.g. ``foo="'a' 'b'"``
represents an array of 2 strings.
:color: A color stored as 24-bit RGB (:cpp:expr:`lv_color_t`).
@@ -64,47 +65,50 @@ 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 unit
:time_ms: Means some time in milliseconds
: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 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.
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".
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.
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.
Most of these connections are done automatically (e.g., for styles, fonts, images,
animations, gradients, etc.), but others need to be connected manually (e.g., event
callbacks where the callback itself is available only in the code).
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).
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.
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.
To create these connections, functions like
- ``lv_xml_register_image(scope, name, pointer)``
- ``lv_xml_register_font(scope, name, pointer)``
- ``lv_xml_register_event_cb(scope, name, callback)``
- :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)`
- etc.
can be used. Later, a pointer to the object can be retrieved by
- ``lv_xml_get_image(scope, name)``
- ``lv_xml_get_font(scope, name)``
- ``lv_xml_get_event_cb(scope, name)``
- :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)`
- 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 *`,
@@ -113,7 +117,8 @@ returns the a component's local scope.
: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 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's XML file. In exported code it's a function like ``lv_obj_t * my_screen_create(void)``
Arrays
------
@@ -121,7 +126,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 a parameter after the array.
In the exported code ``N`` is passed as 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
@@ -146,7 +151,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.
@@ -157,7 +162,7 @@ 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. For example, for
Types can be compound, meaning multiple options/types are possible. Example for
width: ``type="px|%|content"``.
@@ -169,7 +174,7 @@ For example:
- Enums: ``type="dir(top bottom)"``
- Colors: ``type="color(0xff0000 0x00ff00 0x0000ff)"``
- Strings: ``type="string('Ok' 'Cancel')``
- 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.