mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-18 00:25:17 +08:00
docs(xml): restructure and extend the XML docs (#8495)
This commit is contained in:
committed by
GitHub
parent
3bcefbc68f
commit
dec36ddb69
@@ -20,4 +20,3 @@ Auxiliary Modules
|
||||
snapshot
|
||||
test
|
||||
translation
|
||||
xml/index
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
.. _xml_components:
|
||||
|
||||
==========
|
||||
Components
|
||||
==========
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
``<component>`` the following child elements:
|
||||
|
||||
- ``<consts>``,
|
||||
- ``<api>``,
|
||||
- ``<styles>``, and
|
||||
- ``<view>``.
|
||||
|
||||
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 Exported Code
|
||||
************************
|
||||
|
||||
From each Component XML file, a C and H file is exported with a single function inside:
|
||||
|
||||
.. 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
|
||||
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.
|
||||
|
||||
If the user needs to access or modify values dynamically, it is recommended to use a
|
||||
:ref:`Subject <observer_subject>`.
|
||||
|
||||
The user can also call these ``..._create()`` functions at any time from application code.
|
||||
|
||||
|
||||
|
||||
Usage from XML
|
||||
**************
|
||||
|
||||
|
||||
Registration
|
||||
------------
|
||||
|
||||
Once a Component is created (e.g., ``my_button``), it can be registered by calling either:
|
||||
|
||||
- ``lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml");``
|
||||
- ``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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Instantiation
|
||||
-------------
|
||||
|
||||
After registration, a new instance of any registered Component can be created with:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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 last parameter can be ``NULL`` or an attribute list, like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Can be local */
|
||||
char * my_button_attrs[] = {
|
||||
"x", "10",
|
||||
"y", "-10",
|
||||
"align", "bottom_left",
|
||||
"btn_text", "New button",
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
lv_obj_t * btn1 = lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
|
||||
|
||||
|
||||
|
||||
Parameters
|
||||
**********
|
||||
|
||||
The properties of child elements can be adjusted, such as:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<lv_label x="10" text="Hello"/>
|
||||
|
||||
These parameters can be set to a fixed value. However, with the help of ``<prop>``
|
||||
elements inside the ``<api>`` tag, they can also be passed when an instance is
|
||||
created. Only the whole property can be passed, but not individual ``<param>``
|
||||
elements.
|
||||
|
||||
Additionally, when a Component is created, it can use the extended Widget's attributes
|
||||
(see ``<view extends="...">`` in the code examples below).
|
||||
|
||||
This means that Components inherit the API of the extended Widget as well.
|
||||
|
||||
The following example demonstrates parameter passing and the use of the
|
||||
``text`` label property on a Component:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- h3.xml -->
|
||||
<component>
|
||||
<view extends="lv_label"/>
|
||||
</component>
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- red_button.xml -->
|
||||
<component>
|
||||
<api>
|
||||
<prop type="string" name="btn_text" default="None"/>
|
||||
</api>
|
||||
<view extends="lv_button" style_radius="0" style_bg_color="0xff0000">
|
||||
<h3 text="Some text"/>
|
||||
<h3 text="$btn_text" y="40"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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 */
|
||||
lv_xml_create(lv_screen_active(), "red_button", NULL);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
|
||||
Example
|
||||
*******
|
||||
|
||||
.. include:: ../../../examples/others/xml/index.rst
|
||||
|
||||
|
||||
|
||||
API
|
||||
***
|
||||
@@ -1,32 +0,0 @@
|
||||
.. _xml_component:
|
||||
|
||||
====================
|
||||
XML - Declarative UI
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 1
|
||||
|
||||
intro
|
||||
component_library
|
||||
project
|
||||
syntax
|
||||
|
||||
components
|
||||
screens
|
||||
widgets
|
||||
|
||||
preview
|
||||
api
|
||||
styles
|
||||
consts
|
||||
view
|
||||
fonts
|
||||
images
|
||||
events
|
||||
subjects
|
||||
animations
|
||||
translation
|
||||
test
|
||||
license
|
||||
@@ -1,123 +0,0 @@
|
||||
.. _xml_screens:
|
||||
|
||||
=======
|
||||
Screens
|
||||
=======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Screens work very similarly to Components. Both can be:
|
||||
|
||||
- Loaded from XML
|
||||
- Contain Widgets and Components as children
|
||||
- Have ``<styles>``
|
||||
- Have ``<consts>``
|
||||
- Have a ``<view>``
|
||||
|
||||
However, Screens **cannot** have an ``<api>``.
|
||||
|
||||
It's also possible to define ``<screen permanent="true">`` which
|
||||
will make the screen created automatically.
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
Each XML file describes a :ref:`Screen <screens>`. The name of the XML file will
|
||||
also be the name of the Screen.
|
||||
|
||||
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.
|
||||
|
||||
This example illustrates a screen in XML:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<screen>
|
||||
<consts>
|
||||
<string name="title" value="Main menu"/>
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
<style name="dark" bg_color="0x333"/>
|
||||
</styles>
|
||||
|
||||
<view>
|
||||
<header label="#title"/>
|
||||
<selector_container styles="dark">
|
||||
<button text="Weather" icon="cloudy"/>
|
||||
<button text="Messages" icon="envelope"/>
|
||||
<button text="Settings" icon="cogwheel"/>
|
||||
<button text="About" icon="questionmark"/>
|
||||
</selector_container>
|
||||
</view>
|
||||
</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).
|
||||
|
||||
The difference between load and create is that:
|
||||
|
||||
- **load**: Just loads an already existing screen. When the screen is left, it remains in memory,
|
||||
so all states are preserved.
|
||||
- **create**: The screen is created dynamically, and when it's left, it is deleted, so all changes are lost
|
||||
(unless they are saved in ``subjects``).
|
||||
|
||||
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"``.
|
||||
- ``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.
|
||||
|
||||
This is a simple example of both load and create:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- screen1.xml -->
|
||||
<screen>
|
||||
<view style_bg_color="0xff7788" name="first">
|
||||
<lv_button>
|
||||
<lv_label text="Create"/>
|
||||
<!-- Create an instance of "screen2" and load it.
|
||||
Note that here the name of the XML file is used. -->
|
||||
<screen_create_event screen="screen2" anim_type="over_right" duration="500" delay="1000"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
<!-- screen2.xml -->
|
||||
<screen>
|
||||
<view style_bg_color="0x77ff88" name="second">
|
||||
<lv_button>
|
||||
<lv_label text="Load"/>
|
||||
<!-- Load an already created screen that has the name "first".
|
||||
Note that here the name of the instance is used,
|
||||
and not the name of the XML file. -->
|
||||
<screen_load_event screen="first"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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.*/
|
||||
lv_obj_t * screen1 = lv_xml_create(NULL, "screen1", NULL);
|
||||
lv_screen_load(screen1);
|
||||
@@ -1,7 +0,0 @@
|
||||
.. _xml_view:
|
||||
|
||||
=========
|
||||
View
|
||||
=========
|
||||
|
||||
TODO
|
||||
@@ -1,120 +0,0 @@
|
||||
.. _xml_widgets:
|
||||
|
||||
=======
|
||||
Widgets
|
||||
=======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Widgets are written in C and compiled into the application.
|
||||
They can be referenced from Components, and their API can be used via the exposed attributes
|
||||
(e.g., label text or slider value).
|
||||
|
||||
Using the UI |nbsp| Editor, all the following .C/.H files can be exported from the XML of the Widgets:
|
||||
|
||||
:<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 (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
|
||||
*****
|
||||
|
||||
|
||||
XML Parser
|
||||
----------
|
||||
|
||||
To make the 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
|
||||
|
||||
void * lv_xml_label_create(lv_xml_parser_state_t * state, const char ** attrs)
|
||||
{
|
||||
/* Create the label */
|
||||
void * obj = lv_label_create(lv_xml_state_get_parent(state));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_xml_label_apply(lv_xml_parser_state_t * state, const char ** attrs)
|
||||
{
|
||||
void * obj = lv_xml_state_get_item(state);
|
||||
|
||||
/* Apply the common properties, e.g., width, height, styles, flags, etc. */
|
||||
lv_xml_obj_apply(state, attrs);
|
||||
|
||||
/* Process the label-specific attributes */
|
||||
for(int i = 0; attrs[i]; i += 2) {
|
||||
const char * name = attrs[i];
|
||||
const char * value = attrs[i + 1];
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper to convert the string to enum values */
|
||||
static lv_label_long_mode_t long_mode_text_to_enum(const char * txt)
|
||||
{
|
||||
if(lv_streq("wrap", txt)) return LV_LABEL_LONG_WRAP;
|
||||
if(lv_streq("scroll", txt)) return LV_LABEL_LONG_SCROLL;
|
||||
|
||||
LV_LOG_WARN("%s is an unknown value for label's long_mode", txt);
|
||||
return 0; /* Return 0 in the absence of a better option. */
|
||||
}
|
||||
|
||||
A Widget XML processor can be registered like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_xml_widget_register("lv_label", lv_xml_label_create, lv_xml_label_apply);
|
||||
|
||||
After registration, a Widget can be created like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
const char * attrs[] = {
|
||||
"text", "Click here",
|
||||
"align", "center",
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
lv_xml_create(lv_screen_active(), "lv_label", attrs);
|
||||
|
||||
LVGL automatically registers its built-in Widgets, so only custom Widgets need to be
|
||||
registered manually.
|
||||
|
||||
|
||||
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.
|
||||
- **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.
|
||||
|
||||
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
|
||||
``<widget_name>_gen.h``.
|
||||
|
||||
Besides these, any custom code and functions can be freely implemented in this file.
|
||||
+43
-18
@@ -4,6 +4,10 @@
|
||||
Fonts
|
||||
=====
|
||||
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
@@ -84,26 +88,47 @@ created, and in the initialization function of the Component Library (e.g.,
|
||||
In ``lv_style_set_text_font(&style1, <font_name>)``, the created font is referenced.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
Constants can also be used with fonts.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<consts>
|
||||
<int name="font_size" value="32">
|
||||
<variant name="size" case="small" value="24"/>
|
||||
</int>
|
||||
</consts>
|
||||
|
||||
<fonts>
|
||||
<bin name="medium" src_path="file.ttf" range="0x20-0x7f" symbols="°" size="#font_size"/>
|
||||
</fonts>
|
||||
|
||||
|
||||
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 |nbsp| 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.
|
||||
+20
-32
@@ -13,28 +13,14 @@ Overview
|
||||
An ``<images>`` section can be added to ``globals.xml`` files. If present, it
|
||||
describes how to map images with names.
|
||||
|
||||
(Later, it might also be possible in Components and Widgets to define local images to
|
||||
keep the global space cleaner.)
|
||||
|
||||
Currently ``<file>`` is the only supported child element, and ``<convert>`` is not
|
||||
yet implemented.
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<images>
|
||||
<file name="avatar" src_path="avatar1.png">
|
||||
<convert path="raw/avatar.svg" width="100px" color_format="L8"/>
|
||||
</file>
|
||||
|
||||
<data name="logo" src_path="logo1.png" color-format="rgb565" memory="RAM2">
|
||||
<convert path="https://foo.com/image.png" width="50%" height="80%"
|
||||
color_format="RGB565"/>
|
||||
</data>
|
||||
<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:
|
||||
@@ -48,10 +34,11 @@ 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.
|
||||
|
||||
|
||||
For simplicity, in the UI |nbsp| Editor preview, images are always loaded as files.
|
||||
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
|
||||
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
|
||||
@@ -64,25 +51,26 @@ to
|
||||
|
||||
<data name="my_logo"/>
|
||||
|
||||
To register an image path or data in the XML engine use:
|
||||
|
||||
Constants
|
||||
---------
|
||||
.. code-block:: cpp
|
||||
|
||||
Constants can be used with images as well.
|
||||
lv_xml_register_image(scope, "image_name", data)
|
||||
|
||||
.. code-block:: xml
|
||||
``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:
|
||||
|
||||
<consts>
|
||||
<int name="icon_size" value="32">
|
||||
<variant name="size" case="small" value="16"/>
|
||||
</int>
|
||||
</consts>
|
||||
.. code-block:: cpp
|
||||
|
||||
<images>
|
||||
<data name="icon_apply" src_path="apply.png">
|
||||
<convert path="raw/apply.png" width="#icon_size"/>
|
||||
</data>
|
||||
</images>
|
||||
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 |nbsp| 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.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.. _xml_assets:
|
||||
|
||||
======
|
||||
Assets
|
||||
======
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
images
|
||||
fonts
|
||||
|
||||
+64
@@ -51,6 +51,70 @@ 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).
|
||||
|
||||
The difference between load and create is that:
|
||||
|
||||
- **load**: Just loads an already existing screen. When the screen is left, it remains in memory,
|
||||
so all states are preserved.
|
||||
- **create**: The screen is created dynamically, and when it's left, it is deleted, so all changes are lost
|
||||
(unless they are saved in ``subjects``).
|
||||
|
||||
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"``.
|
||||
- ``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.
|
||||
|
||||
This is a simple example of both load and create:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- screen1.xml -->
|
||||
<screen>
|
||||
<view style_bg_color="0xff7788" name="first">
|
||||
<lv_button>
|
||||
<lv_label text="Create"/>
|
||||
<!-- Create an instance of "screen2" and load it.
|
||||
Note that here the name of the XML file is used. -->
|
||||
<screen_create_event screen="screen2" anim_type="over_right" duration="500" delay="1000"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
<!-- screen2.xml -->
|
||||
<screen>
|
||||
<view style_bg_color="0x77ff88" name="second">
|
||||
<lv_button>
|
||||
<lv_label text="Load"/>
|
||||
<!-- Load an already created screen that has the name "first".
|
||||
Note that here the name of the instance is used,
|
||||
and not the name of the XML file. -->
|
||||
<screen_load_event screen="first"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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.*/
|
||||
lv_obj_t * screen1 = lv_xml_create(NULL, "screen1", NULL);
|
||||
lv_obj_set_name(screen1, "first"); /*Will be referenced by this name when loaded*/
|
||||
lv_screen_load(screen1);
|
||||
|
||||
|
||||
Set subject value
|
||||
*****************
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.. _xml_build_ui:
|
||||
|
||||
=========
|
||||
Build UIs
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 1
|
||||
|
||||
root_elements/index
|
||||
main_tags/index
|
||||
assets/index
|
||||
events
|
||||
subjects
|
||||
translation
|
||||
+18
-16
@@ -5,6 +5,7 @@ API
|
||||
===
|
||||
|
||||
The ``<api>`` tag can be a child of ``<widget>`` and ``<component>`` tags.
|
||||
(``<screen>``\ s don't support custom APIs.)
|
||||
|
||||
The only common point is that both Widgets and Components support having
|
||||
``<prop>`` (properties) in the ``<api>`` tag to describe their interface.
|
||||
@@ -55,8 +56,8 @@ Default values
|
||||
Since each property is passed as an argument to the create function, each must have a value.
|
||||
This can be ensured by:
|
||||
|
||||
- Setting them in the XML instance
|
||||
- Providing a default value, e.g., ``<prop name="foo" type="string" default="bar"/>``
|
||||
- Simply setting them in the XML instance
|
||||
- Providing a default value in the ``<api>``, e.g., ``<prop name="foo" type="string" default="bar"/>``
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
@@ -72,7 +73,7 @@ Example
|
||||
<!-- my_button.xml -->
|
||||
<component>
|
||||
<api>
|
||||
<prop name="button_icon" type="image"/>
|
||||
<prop name="button_icon" type="image" default="NULL"/>
|
||||
<prop name="button_label" type="string" default="Label"/>
|
||||
</api>
|
||||
|
||||
@@ -167,6 +168,8 @@ 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>
|
||||
---------
|
||||
|
||||
@@ -175,22 +178,27 @@ Also exclusive to Widgets, elements define sub-widgets or internal structures
|
||||
|
||||
They support ``<arg>`` and ``<prop>``:
|
||||
|
||||
- ``<arg>``\ s are required and used for creation.
|
||||
- ``<arg>``\ s are required and used when creating/getting the element.
|
||||
- ``<prop>``\ s are optional and mapped to setters.
|
||||
|
||||
Elements are referenced as ``<widget-element>`` in views.
|
||||
|
||||
Name parts are separated by `-` (not allowed inside names).
|
||||
Name parts are separated by `-` ( as `-` is not allowed inside names).
|
||||
|
||||
Element `access` types:
|
||||
|
||||
- ``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.
|
||||
|
||||
``type="obj"`` allows children; custom types do not.
|
||||
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.
|
||||
|
||||
Only the API can be defined in XML for elements; implementations must be in C.
|
||||
If the type is ``type="lv_obj"`` it allows the element to have children widgets or components.
|
||||
|
||||
Note that, only the API can be defined in XML for elements; implementations must be in C.
|
||||
|
||||
access="add"
|
||||
~~~~~~~~~~~~
|
||||
@@ -234,9 +242,7 @@ Used for internal/implicit elements:
|
||||
<api>
|
||||
<element name="control_button" type="obj" help="A control button of my_widget" access="get">
|
||||
<arg name="index" type="int"/>
|
||||
<prop name="title">
|
||||
<param name="text" type="string"/>
|
||||
</prop>
|
||||
<prop name="title" type="string"/>
|
||||
</element>
|
||||
</api>
|
||||
|
||||
@@ -265,12 +271,8 @@ Used for indexed access, like setting values in a table:
|
||||
<api>
|
||||
<element name="item" type="obj" access="set">
|
||||
<arg name="index" type="int"/>
|
||||
<prop name="icon">
|
||||
<param name="icon_src" type="img_src"/>
|
||||
</prop>
|
||||
<prop name="color">
|
||||
<param name="color" type="color"/>
|
||||
</prop>
|
||||
<prop name="icon" type="img_src"/>
|
||||
<prop name="color" type="color"/>
|
||||
</element>
|
||||
</api>
|
||||
|
||||
-31
@@ -18,7 +18,6 @@ The supported types are:
|
||||
- ``bool``
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
@@ -41,33 +40,3 @@ And they can be used like this:
|
||||
<styles>
|
||||
<style name="style1" bg_color="#color1"/>
|
||||
</styles>
|
||||
|
||||
|
||||
|
||||
Variants
|
||||
********
|
||||
|
||||
Constants support a ``<variant>`` attribute to change the constants at compile time. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<consts>
|
||||
<px name="pad" value="8" help="General padding">
|
||||
<variant name="size" case="small" value="4"/>
|
||||
<variant name="size" case="large" value="12"/>
|
||||
</px>
|
||||
</consts>
|
||||
|
||||
from which the following C code can be exported:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if SIZE == SMALL
|
||||
#define PAD 4
|
||||
#elif SIZE == LARGE
|
||||
#define PAD 12
|
||||
#else
|
||||
#define PAD 8
|
||||
#endif
|
||||
|
||||
Where ``SMALL`` and ``LARGE`` are just preprocessor defines with incremental values.
|
||||
@@ -0,0 +1,16 @@
|
||||
.. _xml_main_tags:
|
||||
|
||||
=========
|
||||
Main tags
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
api
|
||||
consts
|
||||
styles
|
||||
view
|
||||
animations
|
||||
preview
|
||||
+11
-3
@@ -21,6 +21,7 @@ For example, you might want to:
|
||||
- Set margins.
|
||||
- Change the size of the preview.
|
||||
|
||||
``style_radius`` can be used to make preview rounded.
|
||||
|
||||
|
||||
Usage
|
||||
@@ -44,9 +45,16 @@ Example
|
||||
|
||||
<component>
|
||||
<previews>
|
||||
<preview name="small_dark" width="content" height="100" style_bg_color="0x333" style_pad_all="32"/>
|
||||
<preview name="centered" width="200" height="100" flex="row center"/>
|
||||
<preview name="large_light" width="1980" height="1080" style_bg_color="0xeeeeee"/>
|
||||
|
||||
<preview name="small_dark_round"
|
||||
width="240" height="240"
|
||||
style_bg_color="0x333" style_pad_all="32"
|
||||
style_radius="32"/>
|
||||
|
||||
<preview name="large_light"
|
||||
width="1980" height="1080"
|
||||
style_bg_color="0xeeeeee"/>
|
||||
|
||||
</previews>
|
||||
|
||||
<view>
|
||||
@@ -0,0 +1,51 @@
|
||||
.. _xml_view:
|
||||
|
||||
=========
|
||||
View
|
||||
=========
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
The ``<view>`` tag can be used in:
|
||||
|
||||
- ``<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:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view>
|
||||
<lv_button width="200">
|
||||
<my_icon src="image1"/>
|
||||
<lv_label text="Click me"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
|
||||
Extends
|
||||
*******
|
||||
|
||||
The ``<view>`` itself is also a widget or component, which will become the parent of the children.
|
||||
To define the type of the ``<view>``, use the ``extends`` attribute. For example, ``extends="lv_slider"``.
|
||||
In this case, an ``lv_slider`` will be created first, and the children will be added to it.
|
||||
|
||||
By adding properties to the ``<view>``, the extended type can be customized. For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view extends="lv_slider" width="100%" style_bg_color="0xff8800" flex_flow="row">
|
||||
<style name="my_style" selector="pressed|knob"/>
|
||||
<lv_label text="Current value: "/>
|
||||
<lv_label bind_text="subject_1"/>
|
||||
</view>
|
||||
|
||||
Rules for the 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>``
|
||||
@@ -0,0 +1,244 @@
|
||||
.. _xml_components:
|
||||
|
||||
==========
|
||||
Components
|
||||
==========
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
Components are one of the main building blocks for creating new UI elements.
|
||||
|
||||
``<component>``\ s support the following child XML tags:
|
||||
|
||||
- :ref:`<consts> <xml_consts>`
|
||||
- :ref:`<api> <xml_api>`
|
||||
- :ref:`<styles> <xml_styles>`, and
|
||||
- :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 (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
|
||||
|
||||
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
|
||||
**************
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- my_button.xml -->
|
||||
<component>
|
||||
<view extends="lv_button" flex_flow="row">
|
||||
<lv_image src="logo"/>
|
||||
<my_h3 text="Title"/>
|
||||
</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.
|
||||
|
||||
Registration
|
||||
------------
|
||||
|
||||
Once a Component is created (e.g., ``my_button``), it can be registered by calling either:
|
||||
|
||||
- :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.
|
||||
|
||||
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
|
||||
-------------
|
||||
|
||||
After registration, a new instance of any registered Component can be created with:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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 last parameter can be ``NULL`` or an attribute list, like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Can be local */
|
||||
char * my_button_attrs[] = {
|
||||
"x", "10",
|
||||
"y", "-10",
|
||||
"align", "bottom_left",
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
lv_obj_t * btn1 = lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
|
||||
|
||||
Usage from Exported Code
|
||||
************************
|
||||
|
||||
From each Component XML file, a C and H file is exported with a single function inside:
|
||||
|
||||
.. 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
|
||||
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.
|
||||
|
||||
If the user needs to access or modify values dynamically, it is recommended to use a
|
||||
: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.
|
||||
|
||||
Extending
|
||||
*********
|
||||
|
||||
Additionally, when a Component is created, it can use the extended Widget's attributes
|
||||
(see ``<view extends="...">`` in the code examples below).
|
||||
|
||||
This means that Components inherit the API of the extended Widget as well.
|
||||
|
||||
.. _component_custom_api:
|
||||
|
||||
Custom Properties
|
||||
*****************
|
||||
|
||||
The properties of child elements can be adjusted, 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:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- my_button.xml -->
|
||||
<component>
|
||||
<api>
|
||||
<prop name="btn_text" type="string"/>
|
||||
</api>
|
||||
|
||||
<view extends="lv_button">
|
||||
<lv_label text="$btn_text"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
And it can be used like
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- my_list.xml -->
|
||||
<component>
|
||||
<view>
|
||||
<my_button btn_text="First"/>
|
||||
<my_button btn_text="Second"/>
|
||||
<my_button btn_text="Third"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
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.
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
The following example demonstrates parameter passing and the use of the
|
||||
``text`` label property on a Component. Styles and Constants are also shown.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- h3.xml -->
|
||||
<component>
|
||||
<view extends="lv_label" style_text_color="0xffff00"/>
|
||||
</component>
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<!-- red_button.xml -->
|
||||
<component>
|
||||
<api>
|
||||
<prop type="string" name="btn_text" default="None"/>
|
||||
</api>
|
||||
|
||||
<consts>
|
||||
<int name="thin" value="2"/>
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
<style name="pressed_style" border_width="#thin" border_color="0xff0000"/>
|
||||
</styles>
|
||||
|
||||
<view extends="lv_button" style_radius="0" style_bg_color="0xff0000">
|
||||
<style name="pressed_style" selector="pressed"/>
|
||||
|
||||
<h3 text="Some text"/>
|
||||
<h3 text="$btn_text" y="40"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
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 */
|
||||
lv_xml_create(lv_screen_active(), "red_button", NULL);
|
||||
|
||||
/* 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
|
||||
***
|
||||
@@ -0,0 +1,14 @@
|
||||
.. _xml_root_elements:
|
||||
|
||||
=============
|
||||
Root elements
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
components
|
||||
widgets
|
||||
screens
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
.. _xml_screens:
|
||||
|
||||
=======
|
||||
Screens
|
||||
=======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
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
|
||||
the content of the UI.
|
||||
|
||||
Screens can have only the following child XML tags:
|
||||
|
||||
- :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>`.
|
||||
|
||||
Usage
|
||||
*****
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<screen>
|
||||
<consts>
|
||||
<string name="title" value="Main menu"/>
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
<style name="dark" bg_color="0x333"/>
|
||||
</styles>
|
||||
|
||||
<view>
|
||||
<my_header label="#title"/>
|
||||
<my_main_cont>
|
||||
<style name="dark"/>
|
||||
|
||||
<button text="Weather" icon="cloudy"/>
|
||||
<button text="Messages" icon="envelope"/>
|
||||
<button text="Settings" icon="cogwheel"/>
|
||||
<button text="About" icon="questionmark"/>
|
||||
</my_main_cont>
|
||||
</view>
|
||||
</screen>
|
||||
|
||||
Code export
|
||||
***********
|
||||
|
||||
When the 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
|
||||
``<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.
|
||||
|
||||
Both are supported by adding special XML tags as children of Components or Widgets:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view>
|
||||
<lv_button>
|
||||
<lv_label text="Click or Long press me"/>
|
||||
|
||||
<!-- Load an already created screen that has the name "first".
|
||||
Note that here the name of the instance is used,
|
||||
and 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. -->
|
||||
<screen_create_event screen="about" trigger="long_pressed"/>
|
||||
</lv_button>
|
||||
</view>
|
||||
|
||||
Learn more on :ref:`XML Events <xml_events_screen>` page.
|
||||
@@ -0,0 +1,180 @@
|
||||
.. _xml_widgets:
|
||||
|
||||
=======
|
||||
Widgets
|
||||
=======
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
: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.
|
||||
|
||||
``<widget>``\ s support the following child XML tags:
|
||||
|
||||
- :ref:`<consts> <xml_consts>`
|
||||
- :ref:`<api> <xml_api>`
|
||||
- :ref:`<styles> <xml_styles>`, and
|
||||
- :ref:`<view> <xml_view>`
|
||||
- :ref:`<previews> <xml_preview>`
|
||||
|
||||
Just like Components, Widgets also can be the children of other Widgets and Components.
|
||||
|
||||
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.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view>
|
||||
<lv_label x="10" text="Hello"/>
|
||||
</view>
|
||||
|
||||
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.
|
||||
- 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.
|
||||
|
||||
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
|
||||
*****
|
||||
|
||||
XML Parser
|
||||
----------
|
||||
|
||||
To make the 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
|
||||
|
||||
void * lv_xml_label_create(lv_xml_parser_state_t * state, const char ** attrs)
|
||||
{
|
||||
/* Create the label */
|
||||
void * obj = lv_label_create(lv_xml_state_get_parent(state));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_xml_label_apply(lv_xml_parser_state_t * state, const char ** attrs)
|
||||
{
|
||||
void * obj = lv_xml_state_get_item(state);
|
||||
|
||||
/* Apply the common properties, e.g., width, height, styles, flags, etc. */
|
||||
lv_xml_obj_apply(state, attrs);
|
||||
|
||||
/* Process the label-specific attributes */
|
||||
for(int i = 0; attrs[i]; i += 2) {
|
||||
const char * name = attrs[i];
|
||||
const char * value = attrs[i + 1];
|
||||
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper to convert strings to enum values */
|
||||
static lv_label_long_mode_t long_mode_text_to_enum(const char * txt)
|
||||
{
|
||||
if(lv_streq("wrap", txt)) return LV_LABEL_LONG_WRAP;
|
||||
if(lv_streq("scroll", txt)) return LV_LABEL_LONG_SCROLL;
|
||||
|
||||
LV_LOG_WARN("%s is an unknown value for label's long_mode", txt);
|
||||
return 0; /* Return 0 in the absence of a better option. */
|
||||
}
|
||||
|
||||
A Widget XML processor can be registered like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_xml_widget_register("lv_label", lv_xml_label_create, lv_xml_label_apply);
|
||||
|
||||
After registration, a Widget can be created like this from C code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
const char * attrs[] = {
|
||||
"text", "Click here",
|
||||
"align", "center",
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
lv_xml_create(lv_screen_active(), "lv_label", attrs);
|
||||
|
||||
And in XML it can be used like
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<view>
|
||||
<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.
|
||||
- **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.
|
||||
|
||||
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
|
||||
``<widget_name>_gen.h``.
|
||||
|
||||
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.
|
||||
|
||||
Just like any other Widget API properties, Elements also can be defined in the ``<api>``
|
||||
tag of the Widget's XML.
|
||||
|
||||
Learn more about the Elements in the documentation page of :ref:`<api> <xml_widget_element>`.
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
.. _xml_subjects:
|
||||
|
||||
========
|
||||
Subjects
|
||||
========
|
||||
=======================
|
||||
Data binding (Subjects)
|
||||
=======================
|
||||
|
||||
Overview
|
||||
********
|
||||
+2
-7
@@ -9,6 +9,8 @@ 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.
|
||||
|
||||
|
||||
Usage
|
||||
@@ -51,10 +53,3 @@ Some widget properties support a ``*-translated`` suffix to refer to translation
|
||||
|
||||
This sets the label's text to the translated string for ``"dog"``.
|
||||
|
||||
|
||||
|
||||
More Details
|
||||
************
|
||||
|
||||
For information on selecting the active language, retrieving translations, and fallback behavior,
|
||||
refer to the general :ref:`LVGL translation module <translation>`.
|
||||
@@ -0,0 +1,14 @@
|
||||
.. _xml_main:
|
||||
|
||||
====================
|
||||
XML - Declarative UI
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
overview/index
|
||||
build_ui/index
|
||||
test
|
||||
license
|
||||
+18
-13
@@ -12,21 +12,26 @@ License
|
||||
1. Overview
|
||||
===========
|
||||
|
||||
The LVGL XML Format (the "Specification") defines an XML-based language for describing user interfaces within the LVGL ecosystem.
|
||||
The LVGL XML Specification (the "Specification") defines an XML-based language for describing user interfaces within the LVGL ecosystem.
|
||||
|
||||
This Specification is protected by copyright. It is provided with limited rights of use as outlined below.
|
||||
|
||||
The purpose of this license is to ensure that the Specification remains freely usable for application developers working with LVGL,
|
||||
while restricting its use in third-party UI editors or design tools.
|
||||
This protects the long-term integrity and sustainability of the LVGL ecosystem by preventing unlicensed tools
|
||||
from reusing or replicating the Specification in ways that compete with official LVGL offerings.
|
||||
|
||||
|
||||
2. Permitted Usage
|
||||
==================
|
||||
|
||||
You are permitted to:
|
||||
|
||||
- Use this format in **any firmware or embedded application** built on top of the official `LVGL library <https://github.com/lvgl/lvgl>`_ (MIT-licensed).
|
||||
- Use this Specification in **any firmware or embedded application** built on top of the official `LVGL library <https://github.com/lvgl/lvgl>`_ (MIT-licensed).
|
||||
- Use the LVGL XML loader freely in accordance with its MIT license.
|
||||
- Use the format with the **LVGL UI Editor** and **official LVGL tools such as the CLI or XML loader**.
|
||||
- Write, load, edit, or generate user interfaces described in the LVGL XML format for **internal use** only, including automation or configuration tools used solely inside your organization.
|
||||
- Create **internal scripts or plugins** that help your own developers use or manage this format, as long as these are **not shared outside your organization or made publicly available**.
|
||||
- Use the Specification with the **LVGL UI Editor** and **official LVGL tools such as the CLI or XML loader**.
|
||||
- Write, load, edit, or generate user interfaces described in the LVGL XML Specification for **internal use** only, including automation or configuration tools used solely inside your organization.
|
||||
- Create **internal scripts or plugins** that help your own developers use or manage this Specification, as long as these are **not shared outside your organization or made publicly available**.
|
||||
- Share XML-based UI files within customer firmware or projects that target LVGL-based embedded systems.
|
||||
|
||||
|
||||
@@ -35,11 +40,11 @@ You are permitted to:
|
||||
|
||||
You are **not permitted** to:
|
||||
|
||||
- Create, release, or distribute any **UI editor, visual builder, layout designer, code generator, or tool** that reads, writes, or interprets this format — **whether commercial, open-source, or intended for public use, use by customers or partners, or any use outside your own organization** — without written permission from LVGL LLC.
|
||||
- Create, release, or distribute any **UI editor, visual builder, layout designer, code generator, or tool** that reads, writes, or interprets XML files using this Specification — **whether commercial, open-source, or intended for public use, use by customers or partners, or any use outside your own organization** — without written permission from LVGL LLC.
|
||||
- Implement or extend this Specification in any **software or platform that provides UI creation, editing, or design capabilities similar to those in the LVGL UI Editor**.
|
||||
- Build public APIs, plugins, converters, or SDKs based on this format.
|
||||
- Share or publish internal tooling built around this format.
|
||||
- Embed this format into general-purpose design tools or frameworks outside the LVGL ecosystem.
|
||||
- Build public APIs, plugins, converters, or SDKs based on this Specification.
|
||||
- Share or publish internal tooling built around this Specification.
|
||||
- Use this Specification into general-purpose design tools or frameworks outside the LVGL ecosystem.
|
||||
|
||||
These restrictions apply regardless of whether the software is commercial, free, or open-source.
|
||||
|
||||
@@ -48,16 +53,16 @@ These restrictions apply regardless of whether the software is commercial, free,
|
||||
|
||||
You are **explicitly permitted** to:
|
||||
|
||||
- Use this XML format in your own projects.
|
||||
- Use XML files with this Specification in your own projects.
|
||||
- Load XMLs at runtime using LVGL’s XML loader.
|
||||
- Generate XMLs using the LVGL UI Editor.
|
||||
- Customize XMLs manually or with internal utilities.
|
||||
- Share LVGL-based projects with XML files as part of a commercial product or firmware.
|
||||
|
||||
If you are building embedded software using LVGL, **this license does not affect you**.
|
||||
This license only applies to **UI development tools** that **read, generate, or process this XML format for UI development purposes** in a public or commercial manner.
|
||||
This license only applies to **UI development tools** that **read, generate, or process XML files using this Specification for UI development purposes** in a public or commercial manner.
|
||||
|
||||
You may create **internal tools** to aid development using the format, but these must not be published, sold, or shared externally without a license.
|
||||
You may create **internal tools** to aid development using the Specification, but these must not be published, sold, or shared externally without a license.
|
||||
|
||||
|
||||
5. Trademarks
|
||||
@@ -69,7 +74,7 @@ This license does not grant any rights to use the LVGL name, logo, or trademarks
|
||||
6. Licensing and Permissions
|
||||
============================
|
||||
|
||||
To request permission for broader use or commercial licensing (e.g. using this format in your own UI tool), contact:
|
||||
To request permission for broader use or commercial licensing (e.g. using this Specification in your own UI tool), contact:
|
||||
|
||||
**lvgl@lvgl.io**
|
||||
|
||||
+2
-35
@@ -17,7 +17,7 @@ A Component Library can be fully self-sufficient, but it can also reference data
|
||||
other Component Libraries.
|
||||
|
||||
LVGL itself is a Component Library that supplies the built-in Widgets, data types,
|
||||
etc., so typically Component Libraries use at least the core LVGL data. You can
|
||||
etc. You can
|
||||
find the XML files that describe the LVGL Widgets
|
||||
`here <https://github.com/lvgl/lvgl/tree/master/xmls>`__.
|
||||
|
||||
@@ -26,7 +26,6 @@ above, and its own where the Screens, Components, and Widgets of the project are
|
||||
defined. A project may include additional Component Libraries.
|
||||
|
||||
|
||||
|
||||
Structure
|
||||
*********
|
||||
|
||||
@@ -64,7 +63,6 @@ A typical structure for a Component Library looks like this:
|
||||
└── image2.png
|
||||
|
||||
|
||||
|
||||
Visibility
|
||||
**********
|
||||
|
||||
@@ -124,22 +122,6 @@ included by all generated header files --- not only in the sub-folders where
|
||||
constants, fonts, and other global data are available for all Widgets and new Widgets.
|
||||
|
||||
|
||||
Variants
|
||||
--------
|
||||
|
||||
``<const_variant>`` can be used by constants to create variants that can be selected at compile time.
|
||||
This can be used to select a different display size, color scheme, etc.
|
||||
|
||||
``<style_variant>`` can be used by styles only, to modify styles at runtime. To
|
||||
select the current style variant, an integer :ref:`Subject <observer_subject>` (i.e.
|
||||
a Subject containing an integer value in the Observer Pattern implemented in
|
||||
``lv_observer.c/.h``) ``<style_variant.name>_variant`` is created. Styles can
|
||||
subscribe to this, and the style properties can be changed according to the selected
|
||||
variant's integer value. (See `observer` for details about how to do this.)
|
||||
|
||||
All possible variants should be defined in ``globals.xml``.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
@@ -148,21 +130,6 @@ A ``globals.xml`` file of a Component Library might look like this:
|
||||
.. code-block:: xml
|
||||
|
||||
<globals>
|
||||
<config name="mylib" help="This is my great Component Library"/>
|
||||
<const_variants>
|
||||
<const_variant name="size" help="Select the size">
|
||||
<case name="small" help="Assets for 320x240 Screen"/>
|
||||
<case name="large" help="Assets for 1280x768 Screen"/>
|
||||
</const_variant>
|
||||
</const_variants>
|
||||
|
||||
<style_variants>
|
||||
<style_variant name="color" help="Select the color of the UI">
|
||||
<case name="red" help="Select a red theme"/>
|
||||
<case name="blue" help="Select a blue theme"/>
|
||||
</style_variant>
|
||||
</style_variants>
|
||||
|
||||
<api>
|
||||
<enumdef name="mode">
|
||||
<enum name="slow"/>
|
||||
@@ -176,7 +143,7 @@ A ``globals.xml`` file of a Component Library might look like this:
|
||||
</consts>
|
||||
|
||||
<styles>
|
||||
<style name="card" bg_color="0xeee" radius="#small_unit" padding="12px"/>
|
||||
<style name="style_red" bg_color="0xff0000">
|
||||
</styles>
|
||||
|
||||
<images>
|
||||
@@ -0,0 +1,15 @@
|
||||
.. _xml_overview:
|
||||
|
||||
========
|
||||
Overview
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:class: toctree-1-deep
|
||||
:maxdepth: 2
|
||||
|
||||
intro
|
||||
component_library
|
||||
project
|
||||
syntax
|
||||
|
||||
+52
-70
@@ -4,24 +4,21 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
.. |nbsp| unicode:: U+000A0 .. NO-BREAK SPACE
|
||||
:trim:
|
||||
|
||||
LVGL is capable of loading UI elements written in XML. The XML file can be written by hand, but
|
||||
it's highly recommended to use LVGL's UI |nbsp| Editor to write the XML files. The UI |nbsp| Editor provides
|
||||
it's highly recommended to use `LVGL's UI |nbsp| Editor <https://lvgl.io/editor>`__ to write the XML files. The UI |nbsp| Editor provides
|
||||
features like:
|
||||
|
||||
- Instant preview the XML files
|
||||
- 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 the designs
|
||||
|
||||
.. warning::
|
||||
|
||||
The UI |nbsp| Editor and the XML loader are still under development and not production ready.
|
||||
The UI |nbsp| Editor and the XML loader are still under development and not production-ready.
|
||||
Consider them as an open beta, or experimental features.
|
||||
|
||||
Describing the UI in XML in a declarative manner offers several advantages:
|
||||
@@ -32,30 +29,6 @@ Describing the UI in XML in a declarative manner offers several advantages:
|
||||
- XML can be used to generate LVGL code in any language.
|
||||
- XML helps to separate the view from the internal logic.
|
||||
|
||||
Currently supported features:
|
||||
|
||||
- Load XML Components at runtime from file or any type of input
|
||||
- Nest Components and Widgets to any depth
|
||||
- Dynamically create instances of XML Components in C
|
||||
- Register images and font that can be accessed by name later in the XML data (only from
|
||||
file, no C file is generated for images and fonts)
|
||||
- Constants are working for Widget- and style-properties
|
||||
- Parameters can be defined, passed and used for Components
|
||||
- Most of the built-in Widgets are supported, even the complex ones (``label``, ``slider``,
|
||||
``bar``, ``button``, ``chart``, ``scale``, ``button matrix``, ``table``, etc.)
|
||||
- Style sheets and local styles can be assigned to parts and states supporting
|
||||
almost all style properties
|
||||
|
||||
Limitations:
|
||||
|
||||
- Screens are not supported yet (only Components)
|
||||
- Events are not supported yet.
|
||||
- Animations are not supported yet.
|
||||
- Observer pattern Subjects are not supported yet.
|
||||
- The documentation is not complete yet.
|
||||
|
||||
|
||||
|
||||
Concept
|
||||
*******
|
||||
|
||||
@@ -63,40 +36,37 @@ The XML files are Component-oriented. To be more specific, they are ``Component-
|
||||
That is, they are structured in a way to make it easy to create reusable Component Libraries.
|
||||
|
||||
For example, a company can have a Component Library for the basic Widgets for all its products
|
||||
(smart home, smart watch, smart oven, etc.), and create other industry-specific Libraries
|
||||
(smart-home specific, smart-watch specific, etc.) containing only a few extra Widgets.
|
||||
(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.
|
||||
|
||||
These Component Libraries are independent, can be reused across many products, and
|
||||
can be freely versioned and managed.
|
||||
|
||||
Imagine a Component Library as a collection of XML files, images, fonts, and other
|
||||
assets stored in a git repository, which can be a submodule in many projects.
|
||||
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 just fix it in just one
|
||||
If someone finds a bug in the Component Library, they can just fix it in one
|
||||
place and push it back to the git repository so that other projects can be updated
|
||||
from it.
|
||||
|
||||
The built-in Widgets of LVGL are also considered a ``Component Library`` which is
|
||||
always available.
|
||||
|
||||
A UI |nbsp| Editor project can have any number of Component Libraries and will always have
|
||||
A UI |nbsp| 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
|
||||
********************************
|
||||
|
||||
It is important to distinguish between :dfn:`Widgets` and :dfn:`Components`.
|
||||
|
||||
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
|
||||
: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. The main characteristics of Widgets are:
|
||||
|
||||
- In XML, they start with a ``<widget>`` root element.
|
||||
@@ -104,7 +74,7 @@ but rather compiled into the application. The main characteristics of Widgets ar
|
||||
- They are built using ``lv_obj_class`` objects.
|
||||
- They have custom and complex logic inside.
|
||||
- They cannot be loaded from XML at runtime because the custom code cannot be loaded.
|
||||
- They have a large API with ``set/get/add`` functions.
|
||||
- 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:
|
||||
@@ -113,26 +83,27 @@ Any handwritten Widget can be accessed from XML by:
|
||||
2. Writing and registering an XML parser for it.
|
||||
`See some examples here. <https://github.com/lvgl/lvgl/tree/master/src/others/xml/parsers>`__
|
||||
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
:dfn:`Components` are built from other Components and Widgets, and can be loaded at runtime.
|
||||
:dfn:`Components` are built from other Components and Widgets, 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 at runtime as they describe only visual aspects of the UI.
|
||||
- They can be loaded from XML as they don't contain custom C code, only XML.
|
||||
- They are built from Widgets or other Components.
|
||||
- They can be used for styling Widgets.
|
||||
- They can be used for styling Widgets and other Components.
|
||||
- They can contain (as children) Widgets 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
|
||||
of 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 Components as part of a :ref:`Screen's <screens>` :ref:`Widget Tree
|
||||
<basic_data_flow>` according to their structure.
|
||||
thereafter create children as part of Screens and other Components.
|
||||
|
||||
Screens
|
||||
-------
|
||||
|
||||
:dfn:`Screens` are similar to Components:
|
||||
|
||||
@@ -142,22 +113,20 @@ thereafter create Components as part of a :ref:`Screen's <screens>` :ref:`Widget
|
||||
- They do not have an API.
|
||||
- They can be referenced in Screen load events.
|
||||
|
||||
|
||||
|
||||
Syntax Teaser
|
||||
*************
|
||||
|
||||
Each Widget or Component XML file describes a single Widget or Component. The root
|
||||
element for Widgets, Components, and Screens are ``<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
|
||||
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:
|
||||
|
||||
:<api>: Describes the properties that can be ``set`` for a Widget or Component.
|
||||
Properties can be referenced ysubg ``$``. For Widgets, custom enums can
|
||||
Properties can be referenced by ``$``. For Widgets, custom enums can
|
||||
also be defined with the ``<enumdef>`` tag.
|
||||
:<consts>: Specifies constants (local to the Widget or Component) for colors, sizes,
|
||||
and other values. Constant values can be referenced using ``#``.
|
||||
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
|
||||
@@ -183,35 +152,48 @@ Note that only the basic features are shown here.
|
||||
<style name="red" bg_color="0xff0000"/>
|
||||
</styles>
|
||||
|
||||
<view extends="lv_button" width="#size" styles="blue red:pressed">
|
||||
<my_h3 text="$btn_text" align="center" color="#orange" style_text_color:checked="0x00ff00"/>
|
||||
<view extends="lv_button" width="#size">
|
||||
<style name="blue"/>
|
||||
<style name="red" selector="pressed"/>
|
||||
<my_h3 text="$btn_text"
|
||||
color="#orange"
|
||||
align="center"/>
|
||||
</view>
|
||||
</component>
|
||||
|
||||
|
||||
|
||||
Usage Teaser
|
||||
************
|
||||
|
||||
LVGL's UI |nbsp| Editor can be used in two different ways.
|
||||
|
||||
|
||||
Export C and H Files
|
||||
--------------------
|
||||
|
||||
The Widgets, Components, images, fonts, etc., can be converted to .C/.H files with
|
||||
plain LVGL code. The exported code works the same way as if it was written by the
|
||||
user. In this case, the XML files are not required anymore unless modifications may
|
||||
be made later. 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.
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
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. 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)`.
|
||||
XML can be loaded and any number of instances can be created at runtime.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
1–2 kB/component).
|
||||
+1
-2
@@ -20,6 +20,7 @@ content is specified:
|
||||
for each Screen according to the specified displays.
|
||||
|
||||
|
||||
In LVGL's Editor the ``folders``, ``memory`` and `` <display color_format="..."/>`` are not supported yet.
|
||||
|
||||
Example
|
||||
*******
|
||||
@@ -34,8 +35,6 @@ Example
|
||||
</folders>
|
||||
|
||||
<targets>
|
||||
<renesas-RA8D1-EK gpu="true"/>
|
||||
|
||||
<target name="small">
|
||||
<display width="320" height="240" color_format="RGB565"/>
|
||||
<memory name="int_ram" size="128K"/>
|
||||
+16
-14
@@ -90,18 +90,21 @@ to specify which variable a given name refers to.
|
||||
|
||||
To create these connections, functions like
|
||||
|
||||
- ``lv_xml_register_image(&ctx, name, pointer)``
|
||||
- ``lv_xml_register_font(&ctx, name, pointer)``
|
||||
- ``lv_xml_register_event_cb(&ctx, 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
|
||||
|
||||
- ``lv_xml_get_image(&ctx, name)``
|
||||
- ``lv_xml_get_font(&ctx, name)``
|
||||
- ``lv_xml_get_event_cb(&ctx, 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.
|
||||
|
||||
: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 *`,
|
||||
@@ -118,14 +121,15 @@ 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.
|
||||
:string[...NULL]: An array terminated with a ``NULL`` element. ``NULL`` can be
|
||||
replaced by any value, e.g., ``grid_template_last``.
|
||||
:string[5]: An array that must have exactly 5 elements.
|
||||
replaced by any value.
|
||||
:string[5]: An array that must have exactly 5 elements. In the exported code only the array will be passed
|
||||
as the Widget assumes the given number of elements.
|
||||
:string[]: No ``NULL`` termination and no count parameter, used when the
|
||||
number of elements is not known or delivered via another
|
||||
mechanism, such as via a function parameter.
|
||||
|
||||
|
||||
Enums
|
||||
-----
|
||||
|
||||
@@ -142,9 +146,7 @@ For example:
|
||||
<enum name="inverted" help="Inverted mode"/>
|
||||
</enumdef>
|
||||
|
||||
<prop name="mode" help="help">
|
||||
<param name="mode" type="enum:my_widget_mode" help="help"/>
|
||||
</prop>
|
||||
<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.
|
||||
@@ -169,5 +171,5 @@ For example:
|
||||
- Colors: ``type="color(0xff0000 0x00ff00 0x0000ff)"``
|
||||
- Strings: ``type="string('Ok' 'Cancel')``
|
||||
|
||||
These are checked in the UI |nbsp| Editor, and if an invalid option is selected, it
|
||||
will be highlighted as an error.
|
||||
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.
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _xml_test:
|
||||
|
||||
====
|
||||
Test
|
||||
====
|
||||
==========
|
||||
UI Testing
|
||||
==========
|
||||
|
||||
Overview
|
||||
********
|
||||
@@ -77,6 +77,7 @@ Details
|
||||
details/common-widget-features/index
|
||||
details/widgets/index
|
||||
details/main-modules/index
|
||||
details/xml/index
|
||||
details/auxiliary-modules/index
|
||||
details/libs/index
|
||||
details/debugging/index
|
||||
|
||||
@@ -223,7 +223,7 @@ lv_translation_tag_dsc_t * lv_translation_add_tag(lv_translation_pack_t * pack,
|
||||
{
|
||||
if(pack->is_static) {
|
||||
LV_LOG_WARN("Can't add tag `%s` to static translation pack `%p`", tag_name, (void *)pack);
|
||||
return LV_RESULT_INVALID;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_translation_tag_dsc_t tag;
|
||||
|
||||
+3
-3
@@ -22,14 +22,14 @@
|
||||
|
||||
<element name="column" access="set">
|
||||
<arg name="column" type="int" help=""/>
|
||||
<arg name="width" type="px" help="width of the column"/>
|
||||
<prop name="width" type="px" help="width of the column"/>
|
||||
</element>
|
||||
|
||||
<element name="cell" access="set">
|
||||
<arg name="row" type="int" help=""/>
|
||||
<arg name="column" type="int" help=""/>
|
||||
<arg name="value" type="string" help=""/>
|
||||
<arg name="ctrl" type="enum:lv_table_cell_ctrl+" help=""/>
|
||||
<prop name="value" type="string" help=""/>
|
||||
<prop name="ctrl" type="enum:lv_table_cell_ctrl+" help=""/>
|
||||
</element>
|
||||
</api>
|
||||
</widget>
|
||||
|
||||
Reference in New Issue
Block a user