diff --git a/docs/src/details/xml/build_ui/events.rst b/docs/src/details/xml/build_ui/events.rst index adef36450c..f119213cf4 100644 --- a/docs/src/details/xml/build_ui/events.rst +++ b/docs/src/details/xml/build_ui/events.rst @@ -55,6 +55,7 @@ The ``user_data`` is optional. If omitted, ``NULL`` will be passed. .. _xml_events_screen: + Screen Load and Create events ***************************** @@ -63,9 +64,9 @@ of a widget or component, screens can be loaded or created on a trigger (e.g. cl The difference between load and create is that: -- **load**: Just loads an already existing screen. When the screen is left, it remains in memory, +- **load**: Just loads an already existing screen. After leaving the screen, 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 +- **create**: The screen is created dynamically, and when leaving the screen, it is deleted, so all changes are lost (unless they are saved in ``subjects``). Both tags support the following optional attributes: @@ -73,7 +74,7 @@ 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. +- ``delay``: Wait time before loading the screen in milliseconds. Default: ``0``. This is a simple example of both load and create: @@ -81,11 +82,10 @@ This is a simple example of both load and create: - + - + @@ -93,13 +93,11 @@ This is a simple example of both load and create: - + - - + + @@ -111,10 +109,8 @@ This is a simple example of both load and create: /*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 ***************** diff --git a/src/others/xml/lv_xml.c b/src/others/xml/lv_xml.c index ef65b2a6a5..2a8e7af8c9 100644 --- a/src/others/xml/lv_xml.c +++ b/src/others/xml/lv_xml.c @@ -177,10 +177,14 @@ void * lv_xml_create_in_scope(lv_obj_t * parent, lv_xml_component_scope_t * pare #if LV_USE_OBJ_NAME /*Set a default indexed name*/ - if(state.item && lv_obj_get_name(state.item) == NULL) { - char name_buf[128]; - lv_snprintf(name_buf, sizeof(name_buf), "%s_#", scope->name); - lv_obj_set_name(state.item, name_buf); + if(state.item) { + if(state.scope.is_screen) { + lv_obj_set_name(state.item, scope->name); + } + else if(lv_obj_get_name(state.item) == NULL) { + char name_buf[128]; + lv_snprintf(name_buf, sizeof(name_buf), "%s_#", scope->name); + } } #endif @@ -206,6 +210,10 @@ void * lv_xml_create(lv_obj_t * parent, const char * name, const char ** attrs) * So leave state.scope = NULL which means the global context.*/ state.item = p->create_cb(&state, attrs); + if(state.item == NULL) { + LV_LOG_WARN("Couldn't create widget."); + return NULL; + } if(attrs) { p->apply_cb(&state, attrs); } @@ -215,7 +223,11 @@ void * lv_xml_create(lv_obj_t * parent, const char * name, const char ** attrs) lv_xml_component_scope_t * scope = lv_xml_component_get_scope(name); if(scope) { item = lv_xml_create_in_scope(parent, NULL, scope, attrs); - + if(item == NULL) { + LV_LOG_WARN("Couldn't create component."); + return NULL; + } + const char * value_of_name = NULL; if(attrs) { lv_xml_parser_state_t state; lv_xml_parser_state_init(&state); @@ -228,8 +240,21 @@ void * lv_xml_create(lv_obj_t * parent, const char * name, const char ** attrs) p = lv_xml_widget_get_extended_widget_processor(scope->extends); p->apply_cb(&state, attrs); +#if LV_USE_OBJ_NAME + value_of_name = lv_xml_get_value_of(attrs, "name"); + if(value_of_name) lv_obj_set_name(item, value_of_name); +#endif } + /*Set a default indexed name for non screens*/ +#if LV_USE_OBJ_NAME + if(lv_obj_get_parent(item) && value_of_name == NULL) { + char name_buf[128]; + lv_snprintf(name_buf, sizeof(name_buf), "%s_#", scope->name); + lv_obj_set_name(item, name_buf); + } +#endif + return item; } diff --git a/src/others/xml/lv_xml_component.c b/src/others/xml/lv_xml_component.c index 2e8d845d1e..77f6b86d0b 100644 --- a/src/others/xml/lv_xml_component.c +++ b/src/others/xml/lv_xml_component.c @@ -94,7 +94,6 @@ lv_obj_t * lv_xml_component_process(lv_xml_parser_state_t * state, const char * lv_widget_processor_t * extended_proc = lv_xml_widget_get_extended_widget_processor(scope->extends); extended_proc->apply_cb(state, attrs); - #if LV_USE_OBJ_NAME /*Set a default indexed name*/ if(state->item) { diff --git a/tests/src/test_cases/xml/test_xml_screen_event.c b/tests/src/test_cases/xml/test_xml_screen_event.c index a8ff4119a6..2e68fd905b 100644 --- a/tests/src/test_cases/xml/test_xml_screen_event.c +++ b/tests/src/test_cases/xml/test_xml_screen_event.c @@ -18,7 +18,7 @@ void test_xml_screen_event_1(void) { const char * screen1_xml = { " " - " " + " " " " " " " " @@ -29,10 +29,10 @@ void test_xml_screen_event_1(void) const char * screen2_xml = { " " - " " + " " " " " " - " " + " " " " " " " " @@ -46,31 +46,32 @@ void test_xml_screen_event_1(void) lv_obj_t * screen1; screen1 = lv_xml_create(NULL, "screen1", NULL); - TEST_ASSERT_NOT_NULL(lv_display_get_screen_by_name(NULL, "first")); + TEST_ASSERT_NOT_NULL(lv_display_get_screen_by_name(NULL, "screen1")); lv_screen_load(screen1); lv_test_mouse_click_at(10, 10); lv_test_wait(200); /*There is a delay so stays on the first screen*/ - TEST_ASSERT_EQUAL_STRING("first", lv_obj_get_name(lv_screen_active())); + TEST_ASSERT_EQUAL_STRING("screen1", lv_obj_get_name(lv_screen_active())); /*second should be created*/ - TEST_ASSERT_NOT_NULL(lv_display_get_screen_by_name(NULL, "second")); + TEST_ASSERT_NOT_NULL(lv_display_get_screen_by_name(NULL, "screen2")); lv_test_wait(1300); - TEST_ASSERT_EQUAL_STRING("second", lv_obj_get_name(lv_screen_active())); + /*second screen should be loaded*/ + TEST_ASSERT_EQUAL_STRING("screen2", lv_obj_get_name(lv_screen_active())); /*No delay, go back the first screen immediately*/ lv_test_mouse_click_at(10, 10); - TEST_ASSERT_EQUAL_STRING("first", lv_obj_get_name(lv_screen_active())); + TEST_ASSERT_EQUAL_STRING("screen1", lv_obj_get_name(lv_screen_active())); /*second should be deleted*/ - TEST_ASSERT_NULL(lv_display_get_screen_by_name(NULL, "second")); + TEST_ASSERT_NULL(lv_display_get_screen_by_name(NULL, "screen2")); /*Clean up*/ lv_screen_load(default_screen); lv_obj_delete(screen1); - TEST_ASSERT_NULL(lv_display_get_screen_by_name(NULL, "first")); + TEST_ASSERT_NULL(lv_display_get_screen_by_name(NULL, "screen1")); } #endif