mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 05:26:18 +08:00
docs(xml): fix not using the docs (#7785)
This commit is contained in:
committed by
GitHub
parent
80ee18b612
commit
97aa6b8629
@@ -18,4 +18,4 @@ Other Components
|
|||||||
obj_property
|
obj_property
|
||||||
observer
|
observer
|
||||||
snapshot
|
snapshot
|
||||||
xml
|
xml/index
|
||||||
|
|||||||
@@ -1,313 +0,0 @@
|
|||||||
.. _xml:
|
|
||||||
|
|
||||||
====================
|
|
||||||
XML - Declarative UI
|
|
||||||
====================
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
************
|
|
||||||
|
|
||||||
LVGL is capable of loading UI elements written in XML.
|
|
||||||
Although still under development, the basics are already functional, serving as a preview.
|
|
||||||
|
|
||||||
This declarative language serves as the backend for LVGL's UI editor (currently under development),
|
|
||||||
which enables faster and more maintainable UI implementation.
|
|
||||||
|
|
||||||
Note that, the UI editor is not required to utilize LVGL's XML loading capabilities.
|
|
||||||
|
|
||||||
Describing the UI in XML in a declarative manner offers several advantages:
|
|
||||||
|
|
||||||
- XML files can be loaded at runtime (e.g., from an SD card) to change the application build.
|
|
||||||
- XML is simpler to write than C, enabling people with different skill sets to create LVGL UIs.
|
|
||||||
- XML is textual data, making it easy to parse and manipulate with scripts.
|
|
||||||
- XML can be used to generate LVGL code in any language.
|
|
||||||
- XML helps to separate the view from the logic.
|
|
||||||
|
|
||||||
Currently supported features:
|
|
||||||
|
|
||||||
- Load XML components at runtime from file or data
|
|
||||||
- Nest components and widgets any deep
|
|
||||||
- Dynamically create instances of XML components in C
|
|
||||||
- Register images and font that can be accessed by name later in the XMLs
|
|
||||||
- Constants are working for widget and style properties
|
|
||||||
- Parameters can be defined and passed and used for components
|
|
||||||
- Basic built in widgets (label, slider, bar, button, etc)
|
|
||||||
- Style sheets and :ref:`local styles <style_local>` that can be assigned to parts
|
|
||||||
and states support the basic style properties
|
|
||||||
|
|
||||||
Limitations:
|
|
||||||
|
|
||||||
- Only basic widgets are supported with limited functionality.
|
|
||||||
- Only a few style properties are supported.
|
|
||||||
- Events are not supported yet.
|
|
||||||
- Animations are not supported yet.
|
|
||||||
- Subjects are not supported yet.
|
|
||||||
- The documentation is not complete yet.
|
|
||||||
|
|
||||||
Main Concept
|
|
||||||
------------
|
|
||||||
|
|
||||||
It's important to distinguish between widgets and components:
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
- Similar to LVGL's built-in widgets.
|
|
||||||
- Built from classes.
|
|
||||||
- Have a large API with set/get/add/etc. functions.
|
|
||||||
- Support "internal widgets" (e.g., tabview's tabs, dropdown's list).
|
|
||||||
- Have custom and complex logic inside.
|
|
||||||
- Cannot be loaded from XML at runtime because custom code cannot be loaded.
|
|
||||||
|
|
||||||
Components are built from other components and widgets and can be loaded at runtime.
|
|
||||||
The main characteristics of components are:
|
|
||||||
|
|
||||||
- Built from widgets or other components.
|
|
||||||
- Can be used for styling widgets.
|
|
||||||
- Can contain widgets or other components.
|
|
||||||
- Cannot have custom C code.
|
|
||||||
- Can be loaded from XML at runtime as they describe only the visuals.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Components
|
|
||||||
**********
|
|
||||||
|
|
||||||
Overview
|
|
||||||
--------
|
|
||||||
|
|
||||||
In light of the above, only components can be loaded from XML.
|
|
||||||
An example of a ``my_button`` component looks like this:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<component>
|
|
||||||
<consts>
|
|
||||||
<px name="size" value="100"/>
|
|
||||||
<color name="orange" value="0xffa020"/>
|
|
||||||
</consts>
|
|
||||||
|
|
||||||
<api>
|
|
||||||
<prop name="btn_text" default="Apply" type="string"/>
|
|
||||||
</api>
|
|
||||||
|
|
||||||
<styles>
|
|
||||||
<style name="blue" bg_color="0x0000ff" radius="2"/>
|
|
||||||
<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>
|
|
||||||
</component>
|
|
||||||
|
|
||||||
- ``<component>``: The root element.
|
|
||||||
- ``<consts>``: Constants with ``int``, ``px``, ``string``, ``color``, or ``style`` types.
|
|
||||||
Constants can later be referenced as ``#name``.
|
|
||||||
- ``<params>``: Parameters with ``int``, ``px``, ``string``, ``color``, or ``style`` types.
|
|
||||||
Parameters can later be referenced as ``$name``.
|
|
||||||
- ``<styles>``: ``<style>`` properties can be defined with names and properties.
|
|
||||||
- ``<view>``: Describes how the component looks. Can reference constants, parameters, and styles.
|
|
||||||
|
|
||||||
Naming conventions:
|
|
||||||
|
|
||||||
- A standard XML syntax is used.
|
|
||||||
- Lowercase letters with ``_`` separation are used for attribute names.
|
|
||||||
- The usual variable name rules apply for attribute and tag names: only letters, numbers, `'_'` and can't start with a number.
|
|
||||||
- LVGL API is followed as much as possible, e.g., ``align="center"``, ``bg_color="0xff0000"``.
|
|
||||||
- ``params`` can be referenced with ``$``
|
|
||||||
- ``consts`` can be referenced with ``#``
|
|
||||||
- ``styles`` can be attached to states and/or parts like ``styles="red blue:pressed green:focused:scrollbar"``
|
|
||||||
- Local styles can be used like ``<lv_label style_text_color="0xff0000" style_text_color:checked="0x00ff00"``
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
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 save some relevant data internally.
|
|
||||||
This is required to make LVGL recognize the components by name.
|
|
||||||
When loaded from a file, the file name is used as the component name.
|
|
||||||
|
|
||||||
After this, a new instance of any of the registered components can be created with:
|
|
||||||
``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
|
|
||||||
----------
|
|
||||||
|
|
||||||
It is possible to pass parameters to child components and widgets.
|
|
||||||
These parameters can be set on a parent widget or provided by the user.
|
|
||||||
|
|
||||||
Additionally, it's possible to use the extended widget's attributes
|
|
||||||
(see ``<view extends="...">``) when a widget or component is created.
|
|
||||||
This means that components and widgets inherit the API of the extended widget
|
|
||||||
as well.
|
|
||||||
|
|
||||||
The following example demonstrates parameter chaining 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="$btn_text"/>
|
|
||||||
</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);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Widgets
|
|
||||||
*******
|
|
||||||
|
|
||||||
Overview
|
|
||||||
--------
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
To make the widgets accessible from XML, an XML parser needs to be registered for each widget.
|
|
||||||
The XML parser for the slider looks like this:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
void * lv_xml_label_create(lv_xml_parser_state_t * state, const char ** attrs)
|
|
||||||
{
|
|
||||||
/* Create the label */
|
|
||||||
void * item = lv_label_create(lv_xml_state_get_parent(state));
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lv_xml_label_apply(lv_xml_parser_state_t * state, const char ** attrs)
|
|
||||||
{
|
|
||||||
void * item = lv_xml_state_get_item(state);
|
|
||||||
|
|
||||||
/*Apply the common properties, e.g. width, height, styles flags etc*/
|
|
||||||
lv_xml_obj_apply(state, attrs);
|
|
||||||
|
|
||||||
/* Apply the common properties, e.g., width, height, styles, flags, etc. */
|
|
||||||
lv_obj_xml_apply_attrs(state, item, 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(item, value);
|
|
||||||
if(lv_streq("long_mode", name)) lv_label_set_long_mode(item, long_mode_text_to_enum_value(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper to convert the string to enum values */
|
|
||||||
static lv_label_long_mode_t long_mode_text_to_enum_value(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 process can be registered like
|
|
||||||
:cpp:expr:`lv_xml_widget_register("lv_label", lv_xml_label_create, lv_xml_label_apply)`
|
|
||||||
|
|
||||||
After this, 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.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Images and Fonts
|
|
||||||
****************
|
|
||||||
|
|
||||||
In an XML file, images and fonts can be referenced via a name like this:
|
|
||||||
``<lv_image src="image1" style_text_font="font1"/>``
|
|
||||||
|
|
||||||
The font and image names must be mapped to the actual resources in the following way:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_xml_register_image("image1", "path/to/logo.png");
|
|
||||||
lv_xml_register_image("image2", &some_image_dsc);
|
|
||||||
|
|
||||||
lv_xml_register_font("font1", &arial_14);
|
|
||||||
|
|
||||||
The built-in fonts are automatically registered with names like
|
|
||||||
``"lv_montserrat_16"``.
|
|
||||||
|
|
||||||
The registration functions should be called after
|
|
||||||
:cpp:expr:`lv_init()` but before :cpp:expr:`lv_xml_create(...)`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
|
||||||
*******
|
|
||||||
|
|
||||||
.. include:: ../../examples/others/xml/index.rst
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _xml_api:
|
|
||||||
|
|
||||||
API
|
|
||||||
***
|
|
||||||
@@ -23,34 +23,36 @@ Structure
|
|||||||
|
|
||||||
A typical structure for a component library looks like this:
|
A typical structure for a component library looks like this:
|
||||||
|
|
||||||
- ``name_of_the_component_library``
|
.. code-block:: none
|
||||||
- ``globals.xml``
|
|
||||||
- ``component``
|
name_of_the_component_library
|
||||||
- ``component1.xml``
|
├── globals.xml
|
||||||
- ``component2.xml``
|
├── components
|
||||||
- ``other_folders``
|
│ ├── component1.xml
|
||||||
- ``component3.xml``
|
│ ├── component2.xml
|
||||||
- ``component4.xml``
|
│ └── other_folder
|
||||||
- ``widgets``
|
│ ├── component3.xml
|
||||||
- ``widget1``
|
│ └── component4.xml
|
||||||
- ``widget1.xml``
|
├── widgets
|
||||||
- ``widget1.c``
|
│ ├── widget1
|
||||||
- ``widget1.h``
|
│ │ ├── widget1.xml
|
||||||
- ``widget1_gen.c``
|
│ │ ├── widget1.c
|
||||||
- ``widget1_gen.h``
|
│ │ ├── widget1.h
|
||||||
- ``widget1_private_gen.h``
|
│ │ ├── widget1_gen.c
|
||||||
- ``widget1_xml_parser.c``
|
│ │ ├── widget1_gen.h
|
||||||
- ``widget2``
|
│ │ ├── widget1_private_gen.h
|
||||||
- Same as widget1
|
│ │ └── widget1_xml_parser.c
|
||||||
- ``screens``
|
│ └── widget2
|
||||||
- ``screen1.xml``
|
│ └── ...same as widget1...
|
||||||
- ``screen2.xml``
|
├── screens
|
||||||
- ``fonts``
|
│ ├── screen1.xml
|
||||||
- ``font1.ttf``
|
│ └── screen2.xml
|
||||||
- ``font2.ttf``
|
├── fonts
|
||||||
- ``images``
|
│ ├── font1.ttf
|
||||||
- ``image1.png``
|
│ └── font2.ttf
|
||||||
- ``image2.png``
|
└── images
|
||||||
|
├── image1.png
|
||||||
|
└── image2.png
|
||||||
|
|
||||||
Visibility
|
Visibility
|
||||||
**********
|
**********
|
||||||
@@ -105,43 +107,43 @@ A ``globals.xml`` file of a component library can look like this:
|
|||||||
|
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<globals>
|
<globals>
|
||||||
<config name="mylib" help="This is my great component library"/>
|
<config name="mylib" help="This is my great component library"/>
|
||||||
<const_variants>
|
<const_variants>
|
||||||
<const_variant name="size" help="Select the size">
|
<const_variant name="size" help="Select the size">
|
||||||
<case name="small" help="Assets for 320x240 screen"/>
|
<case name="small" help="Assets for 320x240 screen"/>
|
||||||
<case name="large" help="Assets for 1280x768 screen"/>
|
<case name="large" help="Assets for 1280x768 screen"/>
|
||||||
</const_variant>
|
</const_variant>
|
||||||
</const_variants>
|
</const_variants>
|
||||||
|
|
||||||
<style_variants>
|
<style_variants>
|
||||||
<style_variant name="color" help="Select the color of the UI">
|
<style_variant name="color" help="Select the color of the UI">
|
||||||
<case name="red" help="Select a red theme"/>
|
<case name="red" help="Select a red theme"/>
|
||||||
<case name="blue" help="Select a blue theme"/>
|
<case name="blue" help="Select a blue theme"/>
|
||||||
</style_variant>
|
</style_variant>
|
||||||
</style_variants>
|
</style_variants>
|
||||||
|
|
||||||
<api>
|
<api>
|
||||||
<enumdef name="mode">
|
<enumdef name="mode">
|
||||||
<enum name="slow"/>
|
<enum name="slow"/>
|
||||||
<enum name="fast"/>
|
<enum name="fast"/>
|
||||||
</enumdef>
|
</enumdef>
|
||||||
</api>
|
</api>
|
||||||
|
|
||||||
<consts>
|
<consts>
|
||||||
<px name="small_unit" value="8"/>
|
<px name="small_unit" value="8"/>
|
||||||
<px name="large_unit" value="16"/>
|
<px name="large_unit" value="16"/>
|
||||||
</consts>
|
</consts>
|
||||||
|
|
||||||
<styles>
|
<styles>
|
||||||
<style name="card" bg_color="0xeee" radius="#small_unit" padding="12px"/>
|
<style name="card" bg_color="0xeee" radius="#small_unit" padding="12px"/>
|
||||||
</styles>
|
</styles>
|
||||||
|
|
||||||
<images>
|
<images>
|
||||||
<file name="arrow_left" src="A:/images/arrow_left.png"/>
|
<file name="arrow_left" src="A:/images/arrow_left.png"/>
|
||||||
</images>
|
</images>
|
||||||
|
|
||||||
<fonts>
|
<fonts>
|
||||||
<tinyttf name="big" src="A:/fonts/arial.ttf" size="28"/>
|
<tinyttf name="big" src="A:/fonts/arial.ttf" size="28"/>
|
||||||
</fonts>
|
</fonts>
|
||||||
</globals>
|
</globals>
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ Usage
|
|||||||
<convert path="raw/avatar.svg" width="100px" color_format="L8"/>
|
<convert path="raw/avatar.svg" width="100px" color_format="L8"/>
|
||||||
</file>
|
</file>
|
||||||
|
|
||||||
<data name="logo" src_path="logo1.png">
|
<data name="logo" src_path="logo1.png" color-format="rgb565" memory="RAM2">
|
||||||
<convert path="https://foo.com/image.png" width="50%" height="80%"
|
<convert path="https://foo.com/image.png" width="50%" height="80%"
|
||||||
color_format="RGB565" memory="RAM2"/>
|
color_format="RGB565"/>
|
||||||
</data>
|
</data>
|
||||||
</images>
|
</images>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
.. _others:
|
.. _others:
|
||||||
|
|
||||||
================
|
====================
|
||||||
Other Components
|
XML - Declarative UI
|
||||||
================
|
====================
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ features like:
|
|||||||
- Online preview for collaboration and testing
|
- Online preview for collaboration and testing
|
||||||
- Figma integration to easily reimplement the designs
|
- Figma integration to easily reimplement the designs
|
||||||
|
|
||||||
``warning``
|
.. warning::
|
||||||
|
|
||||||
The UI Editor and the XML loader are still under development and not production ready.
|
The UI Editor and the XML loader are still under development and not production ready.
|
||||||
Consider them as an open beta, or experimental features.
|
Consider them as an open beta, or experimental features.
|
||||||
|
|
||||||
Describing the UI in XML in a declarative manner offers several advantages:
|
Describing the UI in XML in a declarative manner offers several advantages:
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,15 @@ Example
|
|||||||
|
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<previews>
|
<component>
|
||||||
<preview name="small_dark" width="200" height="100" style_bg_color="0x333" style_pad_all="32"/>
|
<previews>
|
||||||
<preview name="centered" width="200" height="100" flex="row center"/>
|
<preview name="small_dark" width="content" height="100" style_bg_color="0x333" style_pad_all="32"/>
|
||||||
<preview name="large_light" width="1980" height="1080" style_bg_color="0xeeeeee"/>
|
<preview name="centered" width="200" height="100" flex="row center"/>
|
||||||
</previews>
|
<preview name="large_light" width="1980" height="1080" style_bg_color="0xeeeeee"/>
|
||||||
|
</previews>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
...
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</component>
|
||||||
Reference in New Issue
Block a user