feat(xml): make <style> and <bind> properties child tags instead of props

This commit is contained in:
Gabor Kiss-Vamosi
2025-05-26 23:35:27 +02:00
parent 3ecd37e667
commit 02b079f0a2
19 changed files with 498 additions and 489 deletions
@@ -7,18 +7,21 @@ Events
Overview
********
``<lv_event>`` tags can be added as a child of any Widget to react to user inputs or other value changes.
There are several ways to define events for user interactions. These events can be added as children of any widget.
Right now, only a single event type is supported to call user-defined callbacks.
Triggers
********
In all event types, the ``trigger`` attribute defines what kind of user action should trigger the event.
All LVGL event types are supported with straightforward mapping:
Usage
*****
- :cpp:enumerator:`LV_EVENT_ALL`: ``"all"``
- :cpp:enumerator:`LV_EVENT_CLICKED`: ``"clicked"``
- :cpp:enumerator:`LV_EVENT_PRESSED`: ``"pressed"``
- etc.
Call function
-------------
*************
User-defined functions can be called like this:
@@ -26,20 +29,19 @@ User-defined functions can be called like this:
<view>
<lv_button width="200" height="100">
<lv_event-call_function callback="my_callback_1" trigger="clicked" user_data="some_text"/>
<event_cb callback="my_callback_1" trigger="clicked" user_data="some_text"/>
<lv_label text="Hello"/>
</lv_button>
</view>
When the XML is loaded at runtime, the callback name needs to be mapped to a function by using:
:cpp:expr:`lv_xml_register_event_cb("my_callback_1", an_event_handler)`.
When the XML is loaded at runtime, the callback name needs to be mapped to a function using
:cpp:expr:`lv_xml_register_event_cb("my_callback_1", an_event_handler);`.
The callback should have the standard LVGL event callback signature:
The callback should follow the standard LVGL event callback signature:
``void an_event_handler(lv_event_t * e);``
In the exported C code, it is assumed that there is a function with the exact name
specified as the callback name. For example, ``callback="my_callback_1"`` will be
exported as:
In the exported C code, it is assumed that a function with the exact name exists.
For example, ``callback="my_callback_1"`` will be exported as:
.. code-block:: c
@@ -47,13 +49,42 @@ exported as:
lv_obj_add_event_cb(obj, my_callback_1, LV_EVENT_CLICKED, "some_text");
For triggers, all LVGL event types are supported with straightforward mapping:
.. What is a trigger?
- :cpp:enumerator:`LV_EVENT_ALL`: ``"all"``
- :cpp:enumerator:`LV_EVENT_CLICKED`: ``"clicked"``
- :cpp:enumerator:`LV_EVENT_PRESSED`: ``"pressed"``
- etc.
The ``user_data`` is optional. If omitted, ``NULL`` will be passed.
Set subject value
*****************
It's possible to set a :ref:`Subject <observer_subject>` value on user interaction by adding a special child to any widget:
.. code-block:: xml
<view>
<lv_button width="200" height="100">
<subject_set_int trigger="clicked" subject="subject1" value="10"/>
<subject_set_string trigger="clicked" subject="subject2" value="Hello"/>
<lv_label text="Set to 10"/>
</lv_button>
</view>
The usage is straightforward: the specified ``subject`` will be set to the given ``value`` when the ``trigger`` occurs.
Increment subject value
***********************
Incrementing or decrementing a :ref:`Subject <observer_subject>` value can be defined as follows:
.. code-block:: xml
<view>
<lv_button width="200" height="100">
<subject_increment trigger="clicked" subject="subject1" step="10"/>
<subject_increment trigger="clicked" subject="subject2" step="-10" min="0" max="50"/>
</lv_button>
</view>
The ``<subject_increment>`` element defines a ``step`` to be added to the subject's current value when the ``trigger`` occurs.
Optionally, ``min`` and/or ``max`` can be set to limit the subject's value.
If ``step`` is **negative**, the subject's value will be decremented.
**Note:** Only integer subjects are supported by ``<subject_increment>``.
@@ -9,9 +9,6 @@ Overview
In XML files, both style sheets (:cpp:expr:`lv_style_t`) and local styles can be used.
Style variants are also supported to change style properties at runtime.
Style Sheets
************
@@ -30,11 +27,14 @@ Styles can be referenced like this in the ``<view>``:
.. code-block:: xml
<view>
<slider styles="main red:indicator red:knob:focused"/>
<lv_slider value="20">
<style name="main"/>
<style name="red" selector"knob"/>
<style name="blue" selector="knob focused"/>
</lv_slider>
</view>
As shown in the example, parts and states are appended after a ``:`` to the style's name.
As shown in the example, parts and states can be set as ``selector``.
Local Styles
@@ -47,7 +47,6 @@ Local styles can be used directly in a Widget, for example:
<lv_label style_bg_opa="200" style_bg_opa:disabled="100"/>
Gradients
*********
@@ -4,50 +4,79 @@
Subjects
========
To connect values of the Widget internally or to external data, :ref:`Subjects
<observer_subject>` can be used. For example, an internally connected value could be
a slider's value mapped to a label. Externally connected data could be the current
number of users shown on a label.
Overview
********
To handle internal connections, local Subjects can be created like this:
With the help of :ref:`Subjects <observer_subject>`, the interface of the UI can be created.
.. code-block:: xml
A subject is a global data item whose value can be set either from the application or the UI, and whose value
can be bound to widget properties.
<subjects>
<int name="a" value="20"/>
<string name="b" value="Hello"/>
<group name="a_and_b" value="a b"/>
</subjects>
For example, a ``room1_temperature`` subject's value can be set in the application when the temperature
is measured, and can be bound to a label like this:
These Subjects can be used in Widget APIs like:
.. code-block:: xml
.. code-block:: xml
<lv_label bind_text="room1_temperature"/>
<view>
<label bind_text="a 'Progress: %d'"/>
</view>
Defining subjects
*****************
When generating code, the Subjects are saved in the Widget's data and are used like this:
Subjects can be created in ``globals.xml`` like this:
.. code-block:: c
.. code-block:: xml
lv_subject_init_int(&my_widget->subject_a, 20);
lv_subject_init_string(&my_widget->subject_b, "Hello");
<globals>
<subjects>
<int name="battery_power" value="32"/>
<string name="user_name" value="John"/>
</subjects>
</globals>
my_widget->subject_a_and_b_list = lv_malloc(sizeof(lv_subject_t *) * 2);
my_widget->subject_a_and_b_list[0] = &my_widget->subject_a;
my_widget->subject_a_and_b_list[1] = &my_widget->subject_b;
lv_subject_init_group(&my_widget->subject_a_and_b, my_widget->subject_a_and_b_list);
As the example shows, a subject consists of a type, name, and initial value.
Currently, only integer and string types are supported.
If the connection is more complex and not supported out of the box, it can be handled from code.
Simple binding
**************
External Subjects are defined in the API of the Widget:
Some widgets (e.g., label, slider) support binding the subject's value directly to the widget.
These bindings use attributes that start with ``bind_*`` and reference a subject.
.. code-block:: xml
.. code-block:: xml
<api>
<prop name="bind_value" help="">
<param name="subject" type="subject" help=""/>
<param name="max_value" type="int" help="Just another parameter, e.g., to limit the value"/>
</prop>
</api>
<lv_slider bind_value="some_subject"/>
<lv_label bind_text="some_subject"/>
Once a binding is created, if the subject's value changes (e.g., by adjusting the slider),
all bound widgets will be updated automatically.
Complex binding
***************
In more complex cases—when a binding requires multiple parameters—the binding can be added as a child element of a widget.
This allows binding multiple subjects with different parameters. For example:
.. code-block:: xml
<lv_label text="Hello world">
<lv_obj-bind_flag_if_eq subject="subject1" flag="hidden" ref_value="10"/>
<lv_obj-bind_flag_if_gt subject="subject1" flag="clickable" ref_value="20"/>
</lv_label>
Explanation of complex bindings:
- ``<lv_obj-bind_flag_if_eq>`` — Set a flag if the subject's value **equals** the reference value.
- ``<lv_obj-bind_flag_if_not_eq>`` — Set a flag if the subject's value **does not equal** the reference value.
- ``<lv_obj-bind_flag_if_gt>`` — Set a flag if the subject's value is **greater than** the reference value.
- ``<lv_obj-bind_flag_if_ge>`` — Set a flag if the subject's value is **greater than or equal to** the reference value.
- ``<lv_obj-bind_flag_if_lt>`` — Set a flag if the subject's value is **less than** the reference value.
- ``<lv_obj-bind_flag_if_le>`` — Set a flag if the subject's value is **less than or equal to** the reference value.
- ``<lv_obj-bind_state_if_eq>`` — Set a state if the subject's value **equals** the reference value.
- ``<lv_obj-bind_state_if_not_eq>`` — Set a state if the subject's value **does not equal** the reference value.
- ``<lv_obj-bind_state_if_gt>`` — Set a state if the subject's value is **greater than** the reference value.
- ``<lv_obj-bind_state_if_ge>`` — Set a state if the subject's value is **greater than or equal to** the reference value.
- ``<lv_obj-bind_state_if_lt>`` — Set a state if the subject's value is **less than** the reference value.
- ``<lv_obj-bind_state_if_le>`` — Set a state if the subject's value is **less than or equal to** the reference value.
Note: The ``lv_obj-`` prefix can be omitted. For example, you can simply write ``<bind_state_if_gt>`` instead.
+5 -8
View File
@@ -39,7 +39,6 @@
#include "parsers/lv_xml_checkbox_parser.h"
#include "parsers/lv_xml_canvas_parser.h"
#include "parsers/lv_xml_calendar_parser.h"
#include "parsers/lv_xml_event_parser.h"
#include "../../libs/expat/expat.h"
#include "../../draw/lv_draw_image.h"
@@ -110,15 +109,14 @@ void lv_xml_init(void)
lv_xml_widget_register("lv_calendar-header_dropdown", lv_xml_calendar_header_dropdown_create,
lv_xml_calendar_header_dropdown_apply);
lv_xml_widget_register("lv_event-call_function", lv_xml_event_call_function_create, lv_xml_event_call_function_apply);
lv_xml_widget_register("lv_obj-style", lv_obj_xml_style_create, lv_obj_xml_style_apply);
lv_xml_widget_register("lv_obj-event_cb", lv_obj_xml_event_cb_create, lv_obj_xml_event_cb_apply);
lv_xml_widget_register("lv_obj-subject_set", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
lv_xml_widget_register("lv_obj-subject_set_int", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
lv_xml_widget_register("lv_obj-subject_set_string", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
lv_xml_widget_register("lv_obj-subject_increment", lv_obj_xml_subject_increment_create,
lv_obj_xml_subject_increment_apply);
lv_xml_widget_register("lv_obj-screen_load_event", lv_obj_xml_screen_load_event_create,
lv_obj_xml_sscreen_load_event_apply);
// lv_xml_widget_register("lv_obj-screen_load_event", lv_obj_xml_screen_load_event_create,
// lv_obj_xml_sscreen_load_event_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_eq", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_not_eq", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
lv_xml_widget_register("lv_obj-bind_flag_if_gt", lv_obj_xml_bind_flag_create, lv_obj_xml_bind_flag_apply);
@@ -508,9 +506,8 @@ static void resolve_params(lv_xml_component_scope_t * item_scope, lv_xml_compone
{
uint32_t i;
for(i = 0; item_attrs[i]; i += 2) {
const char * name = item_attrs[i];
const char * value = item_attrs[i + 1];
if(lv_streq(name, "styles")) continue; /*Styles will handle it themselves*/
if(value[0] == '$') {
/*E.g. the ${my_color} value is the my_color attribute name on the parent*/
const char * name_clean = &value[1]; /*skips `$`*/
+72
View File
@@ -218,6 +218,78 @@ lv_blend_mode_t lv_xml_blend_mode_to_enum(const char * txt)
return 0; /*Return 0 in lack of a better option. */
}
lv_event_code_t lv_xml_trigger_text_to_enum_value(const char * txt)
{
if(lv_streq("all", txt)) return LV_EVENT_ALL;
if(lv_streq("pressed", txt)) return LV_EVENT_PRESSED;
if(lv_streq("pressing", txt)) return LV_EVENT_PRESSING;
if(lv_streq("press_lost", txt)) return LV_EVENT_PRESS_LOST;
if(lv_streq("short_clicked", txt)) return LV_EVENT_SHORT_CLICKED;
if(lv_streq("single_clicked", txt)) return LV_EVENT_SINGLE_CLICKED;
if(lv_streq("double_clicked", txt)) return LV_EVENT_DOUBLE_CLICKED;
if(lv_streq("triple_clicked", txt)) return LV_EVENT_TRIPLE_CLICKED;
if(lv_streq("long_pressed", txt)) return LV_EVENT_LONG_PRESSED;
if(lv_streq("long_pressed_repeat", txt)) return LV_EVENT_LONG_PRESSED_REPEAT;
if(lv_streq("clicked", txt)) return LV_EVENT_CLICKED;
if(lv_streq("released", txt)) return LV_EVENT_RELEASED;
if(lv_streq("scroll_begin", txt)) return LV_EVENT_SCROLL_BEGIN;
if(lv_streq("scroll_throw_begin", txt)) return LV_EVENT_SCROLL_THROW_BEGIN;
if(lv_streq("scroll_end", txt)) return LV_EVENT_SCROLL_END;
if(lv_streq("scroll", txt)) return LV_EVENT_SCROLL;
if(lv_streq("gesture", txt)) return LV_EVENT_GESTURE;
if(lv_streq("key", txt)) return LV_EVENT_KEY;
if(lv_streq("rotary", txt)) return LV_EVENT_ROTARY;
if(lv_streq("focused", txt)) return LV_EVENT_FOCUSED;
if(lv_streq("defocused", txt)) return LV_EVENT_DEFOCUSED;
if(lv_streq("leave", txt)) return LV_EVENT_LEAVE;
if(lv_streq("hit_test", txt)) return LV_EVENT_HIT_TEST;
if(lv_streq("indev_reset", txt)) return LV_EVENT_INDEV_RESET;
if(lv_streq("hover_over", txt)) return LV_EVENT_HOVER_OVER;
if(lv_streq("hover_leave", txt)) return LV_EVENT_HOVER_LEAVE;
if(lv_streq("cover_check", txt)) return LV_EVENT_COVER_CHECK;
if(lv_streq("refr_ext_draw_size", txt)) return LV_EVENT_REFR_EXT_DRAW_SIZE;
if(lv_streq("draw_main_begin", txt)) return LV_EVENT_DRAW_MAIN_BEGIN;
if(lv_streq("draw_main", txt)) return LV_EVENT_DRAW_MAIN;
if(lv_streq("draw_main_end", txt)) return LV_EVENT_DRAW_MAIN_END;
if(lv_streq("draw_post_begin", txt)) return LV_EVENT_DRAW_POST_BEGIN;
if(lv_streq("draw_post", txt)) return LV_EVENT_DRAW_POST;
if(lv_streq("draw_post_end", txt)) return LV_EVENT_DRAW_POST_END;
if(lv_streq("draw_task_added", txt)) return LV_EVENT_DRAW_TASK_ADDED;
if(lv_streq("value_changed", txt)) return LV_EVENT_VALUE_CHANGED;
if(lv_streq("insert", txt)) return LV_EVENT_INSERT;
if(lv_streq("refresh", txt)) return LV_EVENT_REFRESH;
if(lv_streq("ready", txt)) return LV_EVENT_READY;
if(lv_streq("cancel", txt)) return LV_EVENT_CANCEL;
if(lv_streq("create", txt)) return LV_EVENT_CREATE;
if(lv_streq("delete", txt)) return LV_EVENT_DELETE;
if(lv_streq("child_changed", txt)) return LV_EVENT_CHILD_CHANGED;
if(lv_streq("child_created", txt)) return LV_EVENT_CHILD_CREATED;
if(lv_streq("child_deleted", txt)) return LV_EVENT_CHILD_DELETED;
if(lv_streq("screen_unload_start", txt)) return LV_EVENT_SCREEN_UNLOAD_START;
if(lv_streq("screen_load_start", txt)) return LV_EVENT_SCREEN_LOAD_START;
if(lv_streq("screen_loaded", txt)) return LV_EVENT_SCREEN_LOADED;
if(lv_streq("screen_unloaded", txt)) return LV_EVENT_SCREEN_UNLOADED;
if(lv_streq("size_changed", txt)) return LV_EVENT_SIZE_CHANGED;
if(lv_streq("style_changed", txt)) return LV_EVENT_STYLE_CHANGED;
if(lv_streq("layout_changed", txt)) return LV_EVENT_LAYOUT_CHANGED;
if(lv_streq("get_self_size", txt)) return LV_EVENT_GET_SELF_SIZE;
if(lv_streq("invalidate_area", txt)) return LV_EVENT_INVALIDATE_AREA;
if(lv_streq("resolution_changed", txt)) return LV_EVENT_RESOLUTION_CHANGED;
if(lv_streq("color_format_changed", txt)) return LV_EVENT_COLOR_FORMAT_CHANGED;
if(lv_streq("refr_request", txt)) return LV_EVENT_REFR_REQUEST;
if(lv_streq("refr_start", txt)) return LV_EVENT_REFR_START;
if(lv_streq("refr_ready", txt)) return LV_EVENT_REFR_READY;
if(lv_streq("render_start", txt)) return LV_EVENT_RENDER_START;
if(lv_streq("render_ready", txt)) return LV_EVENT_RENDER_READY;
if(lv_streq("flush_start", txt)) return LV_EVENT_FLUSH_START;
if(lv_streq("flush_finish", txt)) return LV_EVENT_FLUSH_FINISH;
if(lv_streq("flush_wait_start", txt)) return LV_EVENT_FLUSH_WAIT_START;
if(lv_streq("flush_wait_finish", txt)) return LV_EVENT_FLUSH_WAIT_FINISH;
if(lv_streq("vsync", txt)) return LV_EVENT_VSYNC;
LV_LOG_WARN("%s is an unknown value for event's trigger", txt);
return LV_EVENT_LAST; /*Indicate error*/
}
/**********************
* STATIC FUNCTIONS
+7
View File
@@ -125,6 +125,13 @@ lv_layout_t lv_xml_layout_to_enum(const char * txt);
*/
lv_blend_mode_t lv_xml_blend_mode_to_enum(const char * txt);
/**
* Convert a an event trigger string to enum
* @param txt e.g. "clicked"
* @return the related enum, e.g. `LV_EVENT_CLICKED`
*/
lv_event_code_t lv_xml_trigger_text_to_enum_value(const char * txt);
/**********************
* MACROS
**********************/
-37
View File
@@ -318,43 +318,6 @@ const char * lv_xml_style_string_process(char * txt, lv_style_selector_t * selec
return style_name;
}
void lv_xml_style_add_to_obj(lv_xml_parser_state_t * state, lv_obj_t * obj, const char * text)
{
char * str = lv_strdup(text);
char * str_ori = str;
/* Split the string based on space and colons */
char * onestyle_str = lv_xml_split_str(&str, ' ');
while(onestyle_str != NULL) {
/* Parse the parts and states after the space */
lv_style_selector_t selector = 0;
const char * style_name = lv_xml_style_string_process(onestyle_str, &selector);
if(style_name != NULL) {
lv_xml_style_t * xml_style = NULL;
/*Resolve parameters or just find the style*/
if(style_name[0] == '$') {
/*E.g. `$pr_style` style name means use the value
*coming from the parent's `pr_style` named attribute*/
const char * name_clean = &style_name[1];
const char * parent_style_name = lv_xml_get_value_of(state->parent_attrs, name_clean);
if(parent_style_name) {
xml_style = lv_xml_get_style_by_name(state->parent_scope, parent_style_name);
}
}
else {
xml_style = lv_xml_get_style_by_name(&state->scope, style_name);
}
if(xml_style) {
/* Apply with the selector */
lv_obj_add_style(obj, &xml_style->style, selector);
}
}
onestyle_str = lv_xml_split_str(&str, ' ');
}
lv_free(str_ori);
}
lv_xml_style_t * lv_xml_get_style_by_name(lv_xml_component_scope_t * scope, const char * style_name_raw)
{
const char * style_name = strrchr(style_name_raw, '.');
-8
View File
@@ -40,14 +40,6 @@ typedef struct _lv_xml_style_t {
*/
lv_result_t lv_xml_style_register(lv_xml_component_scope_t * scope, const char ** attrs);
/**
* Add the styles to an object. Handles multiple styles and selectors too.
* @param state the parser state
* @param obj the target widget
* @param text the styles' string, e.g. "blue red:pressed:knob"
*/
void lv_xml_style_add_to_obj(lv_xml_parser_state_t * state, lv_obj_t * obj, const char * text);
/**
* Convert a style state to enum
* @param txt e.g. "pressed"
@@ -1,169 +0,0 @@
/**
* @file lv_xml_event_parser.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_xml_event_parser.h"
#if LV_USE_XML
#include "../../../lvgl.h"
#include "../../../lvgl_private.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static lv_event_code_t trigger_text_to_enum_value(const char * txt);
static void free_user_data_event_cb(lv_event_t * e);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void * lv_xml_event_call_function_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
const char * trigger = lv_xml_get_value_of(attrs, "trigger");
lv_event_code_t code = LV_EVENT_CLICKED;
if(trigger) code = trigger_text_to_enum_value(trigger);
if(code == LV_EVENT_LAST) {
LV_LOG_WARN("Couldn't add call function event because \"%s\" trigger is invalid.", trigger);
return NULL;
}
const char * cb_txt = lv_xml_get_value_of(attrs, "callback");
if(cb_txt == NULL) {
LV_LOG_WARN("callback is mandatory for event-call_function");
return NULL;
}
lv_obj_t * obj = lv_xml_state_get_parent(state);
lv_event_cb_t cb = lv_xml_get_event_cb(&state->scope, cb_txt);
if(cb == NULL) {
LV_LOG_WARN("Couldn't add call function event because \"%s\" callback is not found.", cb_txt);
/*Don't return NULL.
*When the component is isolated e.g. in the editor the callback is not registered */
return obj;
}
const char * user_data_xml = lv_xml_get_value_of(attrs, "user_data");
char * user_data = NULL;
if(user_data_xml) user_data = lv_strdup(user_data_xml);
lv_obj_add_event_cb(obj, cb, code, user_data);
if(user_data) lv_obj_add_event_cb(obj, free_user_data_event_cb, LV_EVENT_DELETE, user_data);
return obj;
}
void lv_xml_event_call_function_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(state);
LV_UNUSED(attrs);
/*Nothing to apply*/
}
/**********************
* STATIC FUNCTIONS
**********************/
static void free_user_data_event_cb(lv_event_t * e)
{
char * user_data = lv_event_get_user_data(e);
lv_free(user_data);
}
static lv_event_code_t trigger_text_to_enum_value(const char * txt)
{
if(lv_streq("all", txt)) return LV_EVENT_ALL;
if(lv_streq("pressed", txt)) return LV_EVENT_PRESSED;
if(lv_streq("pressing", txt)) return LV_EVENT_PRESSING;
if(lv_streq("press_lost", txt)) return LV_EVENT_PRESS_LOST;
if(lv_streq("short_clicked", txt)) return LV_EVENT_SHORT_CLICKED;
if(lv_streq("single_clicked", txt)) return LV_EVENT_SINGLE_CLICKED;
if(lv_streq("double_clicked", txt)) return LV_EVENT_DOUBLE_CLICKED;
if(lv_streq("triple_clicked", txt)) return LV_EVENT_TRIPLE_CLICKED;
if(lv_streq("long_pressed", txt)) return LV_EVENT_LONG_PRESSED;
if(lv_streq("long_pressed_repeat", txt)) return LV_EVENT_LONG_PRESSED_REPEAT;
if(lv_streq("clicked", txt)) return LV_EVENT_CLICKED;
if(lv_streq("released", txt)) return LV_EVENT_RELEASED;
if(lv_streq("scroll_begin", txt)) return LV_EVENT_SCROLL_BEGIN;
if(lv_streq("scroll_throw_begin", txt)) return LV_EVENT_SCROLL_THROW_BEGIN;
if(lv_streq("scroll_end", txt)) return LV_EVENT_SCROLL_END;
if(lv_streq("scroll", txt)) return LV_EVENT_SCROLL;
if(lv_streq("gesture", txt)) return LV_EVENT_GESTURE;
if(lv_streq("key", txt)) return LV_EVENT_KEY;
if(lv_streq("rotary", txt)) return LV_EVENT_ROTARY;
if(lv_streq("focused", txt)) return LV_EVENT_FOCUSED;
if(lv_streq("defocused", txt)) return LV_EVENT_DEFOCUSED;
if(lv_streq("leave", txt)) return LV_EVENT_LEAVE;
if(lv_streq("hit_test", txt)) return LV_EVENT_HIT_TEST;
if(lv_streq("indev_reset", txt)) return LV_EVENT_INDEV_RESET;
if(lv_streq("hover_over", txt)) return LV_EVENT_HOVER_OVER;
if(lv_streq("hover_leave", txt)) return LV_EVENT_HOVER_LEAVE;
if(lv_streq("cover_check", txt)) return LV_EVENT_COVER_CHECK;
if(lv_streq("refr_ext_draw_size", txt)) return LV_EVENT_REFR_EXT_DRAW_SIZE;
if(lv_streq("draw_main_begin", txt)) return LV_EVENT_DRAW_MAIN_BEGIN;
if(lv_streq("draw_main", txt)) return LV_EVENT_DRAW_MAIN;
if(lv_streq("draw_main_end", txt)) return LV_EVENT_DRAW_MAIN_END;
if(lv_streq("draw_post_begin", txt)) return LV_EVENT_DRAW_POST_BEGIN;
if(lv_streq("draw_post", txt)) return LV_EVENT_DRAW_POST;
if(lv_streq("draw_post_end", txt)) return LV_EVENT_DRAW_POST_END;
if(lv_streq("draw_task_added", txt)) return LV_EVENT_DRAW_TASK_ADDED;
if(lv_streq("value_changed", txt)) return LV_EVENT_VALUE_CHANGED;
if(lv_streq("insert", txt)) return LV_EVENT_INSERT;
if(lv_streq("refresh", txt)) return LV_EVENT_REFRESH;
if(lv_streq("ready", txt)) return LV_EVENT_READY;
if(lv_streq("cancel", txt)) return LV_EVENT_CANCEL;
if(lv_streq("create", txt)) return LV_EVENT_CREATE;
if(lv_streq("delete", txt)) return LV_EVENT_DELETE;
if(lv_streq("child_changed", txt)) return LV_EVENT_CHILD_CHANGED;
if(lv_streq("child_created", txt)) return LV_EVENT_CHILD_CREATED;
if(lv_streq("child_deleted", txt)) return LV_EVENT_CHILD_DELETED;
if(lv_streq("screen_unload_start", txt)) return LV_EVENT_SCREEN_UNLOAD_START;
if(lv_streq("screen_load_start", txt)) return LV_EVENT_SCREEN_LOAD_START;
if(lv_streq("screen_loaded", txt)) return LV_EVENT_SCREEN_LOADED;
if(lv_streq("screen_unloaded", txt)) return LV_EVENT_SCREEN_UNLOADED;
if(lv_streq("size_changed", txt)) return LV_EVENT_SIZE_CHANGED;
if(lv_streq("style_changed", txt)) return LV_EVENT_STYLE_CHANGED;
if(lv_streq("layout_changed", txt)) return LV_EVENT_LAYOUT_CHANGED;
if(lv_streq("get_self_size", txt)) return LV_EVENT_GET_SELF_SIZE;
if(lv_streq("invalidate_area", txt)) return LV_EVENT_INVALIDATE_AREA;
if(lv_streq("resolution_changed", txt)) return LV_EVENT_RESOLUTION_CHANGED;
if(lv_streq("color_format_changed", txt)) return LV_EVENT_COLOR_FORMAT_CHANGED;
if(lv_streq("refr_request", txt)) return LV_EVENT_REFR_REQUEST;
if(lv_streq("refr_start", txt)) return LV_EVENT_REFR_START;
if(lv_streq("refr_ready", txt)) return LV_EVENT_REFR_READY;
if(lv_streq("render_start", txt)) return LV_EVENT_RENDER_START;
if(lv_streq("render_ready", txt)) return LV_EVENT_RENDER_READY;
if(lv_streq("flush_start", txt)) return LV_EVENT_FLUSH_START;
if(lv_streq("flush_finish", txt)) return LV_EVENT_FLUSH_FINISH;
if(lv_streq("flush_wait_start", txt)) return LV_EVENT_FLUSH_WAIT_START;
if(lv_streq("flush_wait_finish", txt)) return LV_EVENT_FLUSH_WAIT_FINISH;
if(lv_streq("vsync", txt)) return LV_EVENT_VSYNC;
LV_LOG_WARN("%s is an unknown value for event's trigger", txt);
return LV_EVENT_LAST; /*Indicate error*/
}
#endif /* LV_USE_XML */
@@ -1,40 +0,0 @@
/**
* @file lv_xml_event_parser.h
*
*/
#ifndef LV_EVENT_XML_PARSER_H
#define LV_EVENT_XML_PARSER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_xml.h"
#if LV_USE_XML
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void * lv_xml_event_call_function_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_xml_event_call_function_apply(lv_xml_parser_state_t * state, const char ** attrs);
/**********************
* MACROS
**********************/
#endif /* LV_USE_XML */
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EVENT_XML_PARSE_H*/
+107 -103
View File
@@ -19,17 +19,6 @@
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_subject_t * subject;
int32_t v;
} subject_set_user_data_t;
typedef struct {
lv_subject_t * subject;
int32_t step;
int32_t range_min;
int32_t range_max;
} subject_increment_user_data_t;
/**********************
* STATIC PROTOTYPES
@@ -133,7 +122,6 @@ void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs)
else if(lv_streq("pressed", name)) lv_obj_set_state(item, LV_STATE_PRESSED, lv_xml_to_bool(value));
else if(lv_streq("scrolled", name)) lv_obj_set_state(item, LV_STATE_SCROLLED, lv_xml_to_bool(value));
else if(lv_streq("disabled", name)) lv_obj_set_state(item, LV_STATE_DISABLED, lv_xml_to_bool(value));
else if(lv_streq("styles", name)) lv_xml_style_add_to_obj(state, item, value);
else if(lv_streq("bind_checked", name)) {
lv_subject_t * subject = lv_xml_get_subject(&state->scope, value);
@@ -141,47 +129,7 @@ void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs)
lv_obj_bind_checked(item, subject);
}
else {
LV_LOG_WARN("Subject \"%s\" doesn't exist in lv_obj bind_checked", value);
}
}
else if(name_len >= 16 && lv_memcmp("bind_state_if_", name, 14) == 0) {
lv_observer_t * (*cb)(lv_obj_t * obj, lv_subject_t * subject, lv_state_t flag, int32_t ref_value) = NULL;
if(name[14] == 'e' && name[15] == 'q') cb = lv_obj_bind_state_if_eq;
else if(name[14] == 'n' && name[15] == 'o') cb = lv_obj_bind_state_if_not_eq;
else if(name[14] == 'g' && name[15] == 't') cb = lv_obj_bind_state_if_gt;
else if(name[14] == 'g' && name[15] == 'e') cb = lv_obj_bind_state_if_ge;
else if(name[14] == 'l' && name[15] == 't') cb = lv_obj_bind_state_if_lt;
else if(name[14] == 'l' && name[15] == 'e') cb = lv_obj_bind_state_if_le;
if(cb) {
char buf[128];
lv_strlcpy(buf, value, sizeof(buf));
char * bufp = buf;
const char * subject_str = lv_xml_split_str(&bufp, ' ');
const char * state_str = lv_xml_split_str(&bufp, ' ');
const char * ref_value_str = lv_xml_split_str(&bufp, ' ');
if(subject_str == NULL) {
LV_LOG_WARN("Subject is missing in lv_obj bind_state");
}
else if(state_str == NULL) {
LV_LOG_WARN("State is missing in lv_obj bind_state");
}
else if(ref_value_str == NULL) {
LV_LOG_WARN("Reference value is missing in lv_obj bind_state");
}
else {
lv_subject_t * subject = lv_xml_get_subject(&state->scope, subject_str);
if(subject == NULL) {
LV_LOG_WARN("Subject \"%s\" doesn't exist in lv_obj bind_state", value);
}
else {
lv_state_t obj_state = lv_xml_state_to_enum(state_str);
int32_t ref_value = lv_xml_atoi(ref_value_str);
cb(item, subject, obj_state, ref_value);
}
}
LV_LOG_WARN("Subject `%s` doesn't exist in lv_obj bind_checked", value);
}
}
@@ -191,9 +139,9 @@ void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs)
}
}
void * lv_obj_xml_style_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
@@ -202,80 +150,91 @@ void lv_obj_xml_style_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
const char * name = lv_xml_get_value_of(attrs, "name");
if(name == NULL) {
LV_LOG_WARN("`name` is missing from <style>");
/*Silently ignore this issue, as it might valid the name is not resolved during
*parameter replacement if there is no default value.*/
return;
}
lv_xml_style_t * xml_style = lv_xml_get_style_by_name(&state->scope, name);
if(xml_style == NULL) {
LV_LOG_WARN("`%s` style is not found", name);
return;
}
lv_xml_style_t * xml_style = lv_xml_get_style_by_name(state->parent_scope, name);
lv_style_selector_t selector = 0;
const char * selector_str = lv_xml_get_value_of(attrs, "selector");
if(selector_str) {
char buf[256];
lv_strncpy(buf, selector_str, sizeof(buf));
char * bufp = buf;
const char * selector_cur = lv_xml_split_str(&bufp, ' ');
while(buf != NULL) {
char * bufp = buf;
const char * next = lv_xml_split_str(&bufp, ' ');
while(next) {
/* Handle different states and parts */
selector |= lv_xml_style_state_to_enum(selector_cur);
selector |= lv_xml_style_part_to_enum(selector_cur);
selector |= lv_xml_style_state_to_enum(next);
selector |= lv_xml_style_part_to_enum(next);
/* Move to the next token */
selector_cur = lv_xml_split_str(&bufp, ' ');
next = lv_xml_split_str(&bufp, ' ');
}
}
void * item = lv_xml_state_get_parent(state);
lv_obj_add_style(item, xml_style->style, selector);
lv_obj_add_style(item, &xml_style->style, selector);
}
void * lv_obj_xml_event_cb_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
void lv_obj_xml_event_cb_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
const char * trigger = lv_xml_get_value_of(attrs, "trigger");
const char * trigger_str = lv_xml_get_value_of(attrs, "trigger_str");
lv_event_code_t code = LV_EVENT_CLICKED;
if(trigger) code = trigger_text_to_enum_value(trigger);
if(trigger_str) code = lv_xml_trigger_text_to_enum_value(trigger_str);
if(code == LV_EVENT_LAST) {
LV_LOG_WARN("Couldn't add call function event because \"%s\" trigger is invalid.", trigger);
LV_LOG_WARN("Couldn't add call function event because `%s` trigger is invalid.", trigger_str);
return;
}
const char * cb_txt = lv_xml_get_value_of(attrs, "callback");
if(cb_txt == NULL) {
const char * cb_str = lv_xml_get_value_of(attrs, "callback");
if(cb_str == NULL) {
LV_LOG_WARN("callback is mandatory for event-call_function");
return;
}
lv_obj_t * obj = lv_xml_state_get_parent(state);
lv_event_cb_t cb = lv_xml_get_event_cb(&state->scope, cb_txt);
lv_event_cb_t cb = lv_xml_get_event_cb(&state->scope, cb_str);
if(cb == NULL) {
LV_LOG_WARN("Couldn't add call function event because \"%s\" callback is not found.", cb_txt);
LV_LOG_WARN("Couldn't add call function event because `%s` callback is not found.", cb_str);
return;
}
const char * user_data_xml = lv_xml_get_value_of(attrs, "user_data");
const char * user_data_str = lv_xml_get_value_of(attrs, "user_data");
char * user_data = NULL;
if(user_data_xml) user_data = lv_strdup(user_data_xml);
if(user_data_str) user_data = lv_strdup(user_data_str);
lv_obj_add_event_cb(obj, cb, code, user_data);
if(user_data) lv_obj_add_event_cb(obj, free_user_data_event_cb, LV_EVENT_DELETE, user_data);
}
void * lv_obj_xml_subject_set_event_create(lv_xml_parser_state_t * state, const char ** attrs)
void * lv_obj_xml_subject_set_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
void lv_obj_xml_subject_set_event_apply(lv_xml_parser_state_t * state, const char ** attrs)
void lv_obj_xml_subject_set_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
/*If the tag_name is */
bool int_subject = lv_streq(state->tag_name, "lv_obj-subject_set_int") ||
lv_streq(state->tag_name, "subject_set_int");
const char * subject_str = lv_xml_get_value_of(attrs, "subject");
const char * trigger_str = lv_xml_get_value_of(attrs, "trigger");
const char * value_str = lv_xml_get_value_of(attrs, "value");
@@ -290,37 +249,89 @@ void lv_obj_xml_subject_set_event_apply(lv_xml_parser_state_t * state, const cha
return;
}
lv_event_code_t code = LV_EVENT_CLICKED;
const char * trigger = lv_xml_get_value_of(attrs, "trigger");
if(trigger) code = trigger_text_to_enum_value(trigger);
if(code == LV_EVENT_LAST) {
LV_LOG_WARN("Couldn't apply <subject_set_event> because \"%s\" trigger is invalid.", trigger);
lv_event_code_t trigger = LV_EVENT_CLICKED;
if(trigger_str) trigger = lv_xml_trigger_text_to_enum_value(trigger_str);
if(trigger == LV_EVENT_LAST) {
LV_LOG_WARN("Couldn't apply <subject_set_event> because `%s` trigger is invalid.", trigger_str);
return;
}
lv_subject_t * subject = lv_xml_get_subject(&state->scope, subject_str);
if(subject == NULL) {
LV_LOG_WARN("Subject \"%s\" doesn't exist in <lv_obj-subject_set>", subject_str);
LV_LOG_WARN("Subject `%s` doesn't exist in <lv_obj-subject_set>", subject_str);
return;
}
bool type_ok = (subject->type == LV_SUBJECT_TYPE_INT && int_subject) ||
(subject->type == LV_SUBJECT_TYPE_STRING && !int_subject);
if(!type_ok) {
LV_LOG_WARN("`%s` subject has incorrect type in <lv_obj-subject_set>", subject_str);
return;
}
int32_t value = lv_xml_atoi(value_str);
void * item = lv_xml_state_get_item(state);
// subject_increment_user_data_t
lv_obj_add_event_cb(item, subject_set_cb, code, (void *)(lv_uintptr_t) value);
if(int_subject) {
lv_obj_add_subject_set_int(item, subject, trigger, lv_xml_atoi(value_str));
}
else {
lv_obj_add_subject_set_string(item, subject, trigger, value_str);
}
}
lv_xml_widget_register("lv_obj-subject_set", lv_obj_xml_subject_set_create, lv_obj_xml_subject_set_apply);
lv_xml_widget_register("lv_obj-subject_increment", lv_obj_xml_subject_increment_create,
lv_obj_xml_subject_increment_apply)
lv_xml_widget_register("lv_obj-screen_load_event", lv_obj_xml_screen_load_event_create,
lv_obj_xml_sscreen_load_event_apply);
void * lv_obj_xml_subject_increment_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
void lv_obj_xml_subject_increment_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
const char * subject_str = lv_xml_get_value_of(attrs, "subject");
const char * trigger_str = lv_xml_get_value_of(attrs, "trigger");
const char * step_str = lv_xml_get_value_of(attrs, "step");
const char * min_str = lv_xml_get_value_of(attrs, "min");
const char * max_str = lv_xml_get_value_of(attrs, "max");
if(subject_str == NULL) {
LV_LOG_WARN("`subject` is missing in <lv_obj-subject_increment>");
return;
}
if(step_str == NULL) {
LV_LOG_WARN("`value` is missing in <lv_obj-subject_increment>");
return;
}
lv_event_code_t trigger = LV_EVENT_CLICKED;
if(trigger_str) trigger = lv_xml_trigger_text_to_enum_value(trigger_str);
if(trigger == LV_EVENT_LAST) {
LV_LOG_WARN("Couldn't apply <subject_increment> because `%s` trigger is invalid.", trigger_str);
return;
}
lv_subject_t * subject = lv_xml_get_subject(&state->scope, subject_str);
if(subject == NULL) {
LV_LOG_WARN("Subject `%s` doesn't exist in <lv_obj-subject_increment>", subject_str);
return;
}
if(subject->type != LV_SUBJECT_TYPE_INT) {
LV_LOG_WARN("`%s` subject should have integer type in <lv_obj-subject_increment>", subject_str);
return;
}
void * item = lv_xml_state_get_item(state);
int32_t step = step_str ? lv_xml_atoi(step_str) : 1;
int32_t min_v = min_str ? lv_xml_atoi(min_str) : INT32_MIN;
int32_t max_v = max_str ? lv_xml_atoi(max_str) : INT32_MAX;
lv_obj_add_subject_increment(item, subject, trigger, step, min_v, max_v);
}
void * lv_obj_xml_bind_flag_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
@@ -360,7 +371,7 @@ void lv_obj_xml_bind_flag_apply(lv_xml_parser_state_t * state, const char ** att
else {
lv_subject_t * subject = lv_xml_get_subject(&state->scope, subject_str);
if(subject == NULL) {
LV_LOG_WARN("Subject \"%s\" doesn't exist in lv_obj bind_flag", subject_str);
LV_LOG_WARN("Subject `%s` doesn't exist in lv_obj bind_flag", subject_str);
}
else {
lv_obj_flag_t flag = flag_to_enum(flag_str);
@@ -373,6 +384,7 @@ void lv_obj_xml_bind_flag_apply(lv_xml_parser_state_t * state, const char ** att
void * lv_obj_xml_bind_state_create(lv_xml_parser_state_t * state, const char ** attrs)
{
LV_UNUSED(attrs);
void * item = lv_xml_state_get_parent(state);
return item;
}
@@ -412,7 +424,7 @@ void lv_obj_xml_bind_state_apply(lv_xml_parser_state_t * state, const char ** at
else {
lv_subject_t * subject = lv_xml_get_subject(&state->scope, subject_str);
if(subject == NULL) {
LV_LOG_WARN("Subject \"%s\" doesn't exist in lv_obj_bind_state", subject_str);
LV_LOG_WARN("Subject `%s` doesn't exist in bind_state", subject_str);
}
else {
lv_state_t s = lv_xml_state_to_enum(state_str);
@@ -602,16 +614,8 @@ static void apply_styles(lv_xml_parser_state_t * state, lv_obj_t * obj, const ch
else SET_STYLE_IF(grid_cell_y_align, lv_xml_grid_align_to_enum(value));
}
static void subject_set_cb(lv_event_t * e)
{
int32_t v
}
static void free_user_data_event_cb(lv_event_t * e)
{
char * user_data = lv_event_get_user_data(e);
lv_free(user_data);
lv_free(lv_event_get_user_data(e));
}
#endif /* LV_USE_XML */
@@ -27,6 +27,18 @@ extern "C" {
void * lv_xml_obj_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_xml_obj_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_style_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_style_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_event_cb_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_event_cb_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_subject_set_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_subject_set_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_subject_increment_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_subject_increment_apply(lv_xml_parser_state_t * state, const char ** attrs);
void * lv_obj_xml_bind_flag_create(lv_xml_parser_state_t * state, const char ** attrs);
void lv_obj_xml_bind_flag_apply(lv_xml_parser_state_t * state, const char ** attrs);
+4 -1
View File
@@ -18,6 +18,9 @@
<view extends="lv_obj" style_radius="3" width="#size" height="content" style_bg_color="$bg_color" >
<lv_label text="$title" align="left_mid"/>
<my_button styles="$btn_rel_style $btn_pr_style:pressed" btn_text="$action" align="right_mid"/>
<my_button btn_text="$action" align="right_mid">
<style name="$btn_rel_style"/>
<style name="$btn_pr_style" selector="pressed"/>
</my_button>
</view>
</component>
+3 -2
View File
@@ -20,8 +20,9 @@
</lv_spangroup>
<lv_scale total_tick_count="31" show_label="true" major_tick_every="6"
range="10 110" width="300"
styles="scale_main scale_indic:indicator">
range="10 110" width="300">
<style name="scale_main"/>
<style name="scale_indic" selector="indicator"/>
<lv_scale-section range="30 60" style_indicator="scale_sectoion_indic"/>
</lv_scale>
+2 -2
View File
@@ -47,7 +47,7 @@ void test_xml_event_call_function_attr(void)
NULL, NULL,
};
lv_xml_create(button, "lv_event-call_function", event_attrs);
lv_xml_create(button, "event_cb", event_attrs);
const char * label_attrs[] = {
@@ -75,7 +75,7 @@ void test_xml_event_call_function_component(void)
"<component>"
" <view extends=\"lv_button\" x=\"5\" y=\"5\">"
" <lv_label text=\"Click me\"/>"
" <lv_event-call_function trigger=\"clicked\" callback=\"count_cb\" user_data=\"3\"/>"
" <lv_obj-event_cb trigger=\"clicked\" callback=\"count_cb\" user_data=\"3\"/>"
" </view>"
"</component>"
};
+66 -54
View File
@@ -127,36 +127,39 @@ void test_xml_component_params(void)
{
const char * h3_xml =
"<component>"
"<api>"
"<prop name=\"style\" type=\"style\"/>"
"</api>"
"<view extends=\"lv_label\" styles=\"$style\">"
"</view>"
" <api>"
" <prop name=\"style\" type=\"style\"/>"
" </api>"
" <view extends=\"lv_label\">"
" <style name=\"$style\"/>"
" </view>"
"</component>";
const char * red_button_xml =
"<component>"
"<api>"
"<prop type=\"string\" name=\"btn_text\"/>"
"<prop type=\"style\" name=\"label_style\"/>"
"</api>"
"<view extends=\"lv_button\" style_radius=\"0\" style_bg_color=\"0xff0000\">"
"<h3 text=\"$btn_text\" style=\"$label_style\"/>"
"</view>"
" <api>"
" <prop type=\"string\" name=\"btn_text\"/>"
" <prop type=\"style\" name=\"label_style\"/>"
" </api>"
" <view extends=\"lv_button\" style_radius=\"0\" style_bg_color=\"0xff0000\">"
" <h3 text=\"$btn_text\"> "
" <style name=\"$label_style\"/>"
" </h3>"
" </view>"
"</component>";
const char * card_xml =
"<component>"
"<api>"
"<prop type=\"string\" name=\"action\" default=\"Default\"/>"
"</api>"
"<styles>"
"<style name=\"style1\" text_color=\"0xffff00\"/>"
"</styles>"
"<view width=\"200\" height=\"content\">"
"<h3 text=\"Title\" align=\"top_mid\" style_text_color=\"0xff0000\"/>"
"<red_button btn_text=\"$action\" label_style=\"style1\" y=\"20\"/>"
"</view>"
" <api>"
" <prop type=\"string\" name=\"action\" default=\"Default\"/>"
" </api>"
" <styles>"
" <style name=\"style1\" text_color=\"0xffff00\"/>"
" </styles>"
" <view width=\"200\" height=\"content\">"
" <h3 text=\"Title\" align=\"top_mid\" style_text_color=\"0xff0000\"/>"
" <red_button btn_text=\"$action\" label_style=\"style1\" y=\"20\"/>"
" </view>"
"</component>";
lv_xml_component_register_from_data("h3", h3_xml);
@@ -180,17 +183,20 @@ void test_xml_component_consts(void)
{
const char * h3_xml =
"<component>"
"<consts>"
"<string name=\"action\" value=\"Log in\"/>"
"<color name=\"dark_color\" value=\"0x804000\"/>"
"<color name=\"accent_color\" value=\"0xff8000\"/>"
"<int name=\"size\" value=\"200\"/>"
"</consts>"
"<styles>"
"<style name=\"style1\" bg_color=\"#dark_color\" bg_opa=\"255\"/>"
"</styles>"
"<view extends=\"lv_label\" width=\"#size\" style_text_color=\"#accent_color\" text=\"#action\" styles=\"style1\">"
"</view>"
" <consts>"
" <string name=\"action\" value=\"Log in\"/>"
" <color name=\"dark_color\" value=\"0x804000\"/>"
" <color name=\"accent_color\" value=\"0xff8000\"/>"
" <int name=\"size\" value=\"200\"/>"
" </consts>"
""
" <styles>"
" <style name=\"style1\" bg_color=\"#dark_color\" bg_opa=\"255\"/>"
" </styles>"
""
" <view extends=\"lv_label\" width=\"#size\" style_text_color=\"#accent_color\" text=\"#action\">"
" <style name=\"style1\"/>"
" </view>"
"</component>";
lv_xml_component_register_from_data("h3", h3_xml);
@@ -204,13 +210,15 @@ void test_xml_component_styles(void)
{
const char * my_btn_xml =
"<component>"
"<styles>"
"<style name=\"rel_style\" bg_color=\"0xff0000\"/>"
"<style name=\"pr_style\" bg_color=\"0x800000\"/>"
"</styles>"
"<view extends=\"lv_button\" style_text_color=\"0x0000ff\" style_text_color:checked=\"0xa0a0ff\" styles=\"rel_style pr_style:checked\">"
"<lv_label/>"
"</view>"
" <styles>"
" <style name=\"rel_style\" bg_color=\"0xff0000\"/>"
" <style name=\"pr_style\" bg_color=\"0x800000\"/>"
" </styles>"
" <view extends=\"lv_button\" style_text_color=\"0x0000ff\" style_text_color:checked=\"0xa0a0ff\">"
" <style name=\"rel_style\"/>"
" <style name=\"pr_style\" selector=\"checked\"/>"
" <lv_label/>"
" </view>"
"</component>";
lv_xml_component_register_from_data("my_btn", my_btn_xml);
@@ -236,12 +244,12 @@ void test_xml_error_resilience_syntax_ok(void)
" </consts>"
""
" <styles>"
" <style name=\"rel_style\" bg_color=\"0xff0000\" not_a_prop=\"0xff0000\"/>"
" <inv_style name=\"rel_style\" bg_color=\"0x800000\"/>"
" <style name=\"rel_style\" bg_color=\"0xff0000\" not_a_prop=\"0xff0000\"/>"
" <inv_style name=\"rel_style\" bg_color=\"0x800000\"/>"
" <style bg_color=\"0x800000\"/>"
" </styles>"
""
" <view extends=\"not_a_widget\" style_text_color=\"0x0000ff\" style_text_color:checked=\"0x8080ff\" styles=\"rel_style pr_style:checked\">"
" <view extends=\"not_a_widget\" style_text_color=\"0x0000ff\" style_text_color:checked=\"0x8080ff\">"
" <unknown/>"
" <lv_label not_an_attr=\"40\"/>"
" </view>"
@@ -257,17 +265,21 @@ void test_xml_image_and_font(void)
{
const char * btn_xml =
"<component>"
"<consts>"
"<font name=\"font1\" value=\"lv_montserrat_18\"/>"
"<image name=\"image1\" value=\"test_img1\"/>"
"</consts>"
"<styles>"
"<style name=\"style_rel\" text_font=\"#font1\" text_color=\"0xffffff\" bg_image_src=\"#image1\" bg_image_tiled=\"true\" radius=\"0\"/>"
"<style name=\"style_chk\" text_font=\"lv_montserrat_16\" text_color=\"0xffff00\" bg_image_src=\"test_img2\"/>"
"</styles>"
"<view extends=\"lv_obj\" width=\"100\" height=\"70\" styles=\"style_rel style_chk:checked\" >"
"<lv_label text=\"hello\" align=\"center\" style_bg_color=\"0x888888\" style_bg_opa=\"200\"/>"
"</view>"
" <consts>"
" <font name=\"font1\" value=\"lv_montserrat_18\"/>"
" <image name=\"image1\" value=\"test_img1\"/>"
" </consts>"
""
" <styles>"
" <style name=\"style_rel\" text_font=\"#font1\" text_color=\"0xffffff\" bg_image_src=\"#image1\" bg_image_tiled=\"true\" radius=\"0\"/>"
" <style name=\"style_chk\" text_font=\"lv_montserrat_16\" text_color=\"0xffff00\" bg_image_src=\"test_img2\"/>"
" </styles>"
""
" <view extends=\"lv_obj\" width=\"100\" height=\"70\">"
" <style name=\"style_rel\"/>"
" <style name=\"style_chk\" selector=\"checked\"/>"
" <lv_label text=\"hello\" align=\"center\" style_bg_color=\"0x888888\" style_bg_opa=\"200\"/>"
" </view>"
"</component>";
/*Monstserrat fonts are registered by LVGL */
+2 -1
View File
@@ -130,7 +130,8 @@ void test_xml_style_same_name(void)
" <style name=\"hello\" figma_node_id=\"1234\" bg_opa=\"20\" border_side=\"right\"/>"
" </styles>"
""
" <view styles=\"hello\">"
" <view>"
" <style name=\"hello\"/>"
" </view>"
"</component>";
+69
View File
@@ -25,6 +25,75 @@
<enum name="items" help="Some help"/>
</enumdef>
<enumdef name="lv_event">
<enum name="all" help=""/>
<enum name="pressed" help=""/>
<enum name="pressing" help=""/>
<enum name="press_lost" help=""/>
<enum name="short_clicked" help=""/>
<enum name="single_clicked" help=""/>
<enum name="double_clicked" help=""/>
<enum name="triple_clicked" help=""/>
<enum name="long_pressed" help=""/>
<enum name="long_pressed_repeat" help=""/>
<enum name="clicked" help=""/>
<enum name="released" help=""/>
<enum name="scroll_begin" help=""/>
<enum name="scroll_throw_begin" help=""/>
<enum name="scroll_end" help=""/>
<enum name="scroll" help=""/>
<enum name="gesture" help=""/>
<enum name="key" help=""/>
<enum name="rotary" help=""/>
<enum name="focused" help=""/>
<enum name="defocused" help=""/>
<enum name="leave" help=""/>
<enum name="hit_test" help=""/>
<enum name="indev_reset" help=""/>
<enum name="hover_over" help=""/>
<enum name="hover_leave" help=""/>
<enum name="cover_check" help=""/>
<enum name="refr_ext_draw_size" help=""/>
<enum name="draw_main_begin" help=""/>
<enum name="draw_main" help=""/>
<enum name="draw_main_end" help=""/>
<enum name="draw_post_begin" help=""/>
<enum name="draw_post" help=""/>
<enum name="draw_post_end" help=""/>
<enum name="draw_task_added" help=""/>
<enum name="value_changed" help=""/>
<enum name="insert" help=""/>
<enum name="refresh" help=""/>
<enum name="ready" help=""/>
<enum name="cancel" help=""/>
<enum name="create" help=""/>
<enum name="delete" help=""/>
<enum name="child_changed" help=""/>
<enum name="child_created" help=""/>
<enum name="child_deleted" help=""/>
<enum name="screen_unload_start" help=""/>
<enum name="screen_load_start" help=""/>
<enum name="screen_loaded" help=""/>
<enum name="screen_unloaded" help=""/>
<enum name="size_changed" help=""/>
<enum name="style_changed" help=""/>
<enum name="layout_changed" help=""/>
<enum name="get_self_size" help=""/>
<enum name="invalidate_area" help=""/>
<enum name="resolution_changed" help=""/>
<enum name="color_format_changed" help=""/>
<enum name="refr_request" help=""/>
<enum name="refr_start" help=""/>
<enum name="refr_ready" help=""/>
<enum name="render_start" help=""/>
<enum name="render_ready" help=""/>
<enum name="flush_start" help=""/>
<enum name="flush_finish" help=""/>
<enum name="flush_wait_start" help=""/>
<enum name="flush_wait_finish" help=""/>
<enum name="vsync" help=""/>
</enumdef>
<enumdef name="lv_align">
<enum name="default" help="Some help"/>
<enum name="top_left" help="Some help"/>
+27 -1
View File
@@ -39,6 +39,33 @@ Example
<enum name="user_4" help="Custom flag, free to use by user"/>
</enumdef>
<element name="style" access="add" type="void">
<arg name="name" type="style"/>
<arg name="selector" type="selector+"/>
</element>
<element name="event_cb" access="add">
<arg name="name" type="string"/>
<arg name="trigger" type="lv_event"/>
<arg name="cb" type="event_cb"/>
</element>
<element name="subject_set" access="add">
<arg name="name" type="string"/>
<arg name="trigger" type="lv_event"/>
<arg name="subject" type="subject"/>
<arg name="value" type="int"/>
</element>
<element name="subject_increment" access="add">
<arg name="name" type="string"/>
<arg name="trigger" type="lv_event"/>
<arg name="subject" type="subject"/>
<arg name="step" type="int"/>
<arg name="min" type="int" default="-2000000"/>
<arg name="max" type="int" default="2000000"/>
</element>
<element name="bind_flag_if_eq" access="bind" >
<arg name="subject" type="subject"/>
<arg name="flag" type="enum:lv_obj_flag"/>
@@ -118,7 +145,6 @@ Example
<prop name="height" type="coords"/>
<prop name="width" type="coords"/>
<prop name="align" type="enum:lv_align"/>
<prop name="styles" type="styles[]"/>
<prop name="ext_click_area" type="int"/>