mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 09:43:41 +08:00
feat(fragment): add fragment manager (a UI Controller concept) (#2940)
* adding lv_obj_controller * adding examples for lv_obj_controller * added some docs * formatted code * updated controller docs * updated controller docs * updated sample controller field * changed lv_controller_manager_parent to lv_controller_manager_get_parent * updated unmanaged controller creation/deletion * renamed lv_controller_manager_t * rename: controller -> fragment * formatted code * Update examples/others/fragment/lv_example_fragment.h Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * Update src/extra/others/fragment/lv_fragment.c Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * Update src/extra/others/fragment/lv_fragment.c Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * Update src/extra/others/fragment/lv_fragment.c Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * code cleanup * fragment creation rework * (wip) fragment manager * (wip) fragment manager * refactoring fragment * lifecycle fixes * updated fragment event callback * exposed states of fragment * added some docs * updated lv_fragment_managed_states_t name * updated docs * updated docs * updated lv_fragment_manager_dispatch_event docs * removed msgbox fragment * updated fragment docs * updated fragment docs * updated docs * updating examples * fixed example * reformatted code * fixed obj_created set timing * simplified fragment * improved fragment view del assertion * fixed a typo * fixed event_cb check in lv_obj_remove_event_cb_with_user_data * fixing fragment obj assertion * regenerated config * fixed fragment examples * fixed fragment examples * added missing examples * updated docs * fragment api cleanup * rename fragment struct names * added missing param doc * enabled test for 32bit build * feat(porting): add a macro lv_run_timer_handler_in_period to simplify porting (#3063) * feat(porting): add a macro lv_run_timer_handler_in_period to simplify porting * feat: update helper function and doc * doc(porting): update function names * revise to the original os.md * fix: fix typo * fix: mitigate warnings * chore: fix code formatting * fix(fsdrv): replacing sprintf with lv_snprintf for safety (#3079) * fix(Kconfig) remove duplicate LV_BUILD_EXAMPLES configuration * feat(refr) add reset of FPS statistics * fix(conf) mismatched macro judgment * feat(fsdrv) replacing sprintf with lv_snprintf for safety * feat(fsdrv) update stdio and win32 Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com> * fix warnings Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> Co-authored-by: Gabriel Wang <embedded_zhuoran@Hotmail.com> Co-authored-by: _VIFEXTech <1290176185@qq.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
parent
9f90d82e91
commit
e7736f2c32
81
docs/others/fragment.md
Normal file
81
docs/others/fragment.md
Normal file
@ -0,0 +1,81 @@
|
||||
```eval_rst
|
||||
.. include:: /header.rst
|
||||
:github_url: |github_link_base|/others/fragment.md
|
||||
```
|
||||
|
||||
# Fragment
|
||||
|
||||
Fragment is a concept copied from [Android](https://developer.android.com/guide/fragments).
|
||||
|
||||
It represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle,
|
||||
and can handle its own events. Like Android's Fragment that must be hosted by an activity or another fragment, Fragment
|
||||
in LVGL needs to be hosted by an object, or another fragment. The fragment’s view hierarchy becomes part of, or attaches
|
||||
to, the host’s view hierarchy.
|
||||
|
||||
Such concept also has some similarities
|
||||
to [UiViewController on iOS](https://developer.apple.com/documentation/uikit/uiviewcontroller).
|
||||
|
||||
Fragment Manager is a manager holding references to fragments attached to it, and has an internal stack to achieve
|
||||
navigation. You can use fragment manager to build navigation stack, or multi pane application easily.
|
||||
|
||||
## Usage
|
||||
|
||||
Enable `LV_USE_FRAGMENT` in `lv_conf.h`.
|
||||
|
||||
### Create Fragment Class
|
||||
|
||||
```c
|
||||
struct sample_fragment_t {
|
||||
/* IMPORTANT: don't miss this part */
|
||||
lv_fragment_t base;
|
||||
/* States, object references and data fields for this fragment */
|
||||
const char *title;
|
||||
};
|
||||
|
||||
const lv_fragment_class_t sample_cls = {
|
||||
/* Initialize something needed */
|
||||
.constructor_cb = sample_fragment_ctor,
|
||||
/* Create view objects */
|
||||
.create_obj_cb = sample_fragment_create_obj,
|
||||
/* IMPORTANT: size of your fragment struct */
|
||||
.instance_size = sizeof(struct sample_fragment_t)
|
||||
};
|
||||
```
|
||||
|
||||
### Use `lv_fragment_manager`
|
||||
|
||||
```c
|
||||
/* Create fragment instance, and objects will be added to container */
|
||||
lv_fragment_manager_t *manager = lv_fragment_manager_create(container, NULL);
|
||||
/* Replace current fragment with instance of sample_cls, and init_argument is user defined pointer */
|
||||
lv_fragment_manager_replace(manager, &sample_cls, init_argument);
|
||||
```
|
||||
|
||||
### Fragment Based Navigation
|
||||
|
||||
```c
|
||||
/* Add one instance into manager stack. View object of current fragment will be destroyed,
|
||||
* but instances created in class constructor will be kept.
|
||||
*/
|
||||
lv_fragment_manager_push(manager, &sample_cls, NULL);
|
||||
|
||||
/* Remove the top most fragment from the stack, and bring back previous one. */
|
||||
lv_fragment_manager_pop(manager);
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```eval_rst
|
||||
|
||||
.. include:: ../../examples/others/fragment/index.rst
|
||||
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```eval_rst
|
||||
|
||||
.. doxygenfile:: lv_fragment.h
|
||||
:project: lvgl
|
||||
|
||||
```
|
@ -13,5 +13,6 @@
|
||||
snapshot
|
||||
monkey
|
||||
gridnav
|
||||
fragment
|
||||
```
|
||||
|
||||
|
16
examples/others/fragment/index.rst
Normal file
16
examples/others/fragment/index.rst
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Basic fragment usage
|
||||
"""""""""""""""""""
|
||||
|
||||
.. lv_example:: others/fragment/lv_example_fragment_1
|
||||
:language: c
|
||||
|
||||
|
||||
|
||||
Stack navigation example
|
||||
"""""""""""""""""""
|
||||
|
||||
.. lv_example:: others/fragment/lv_example_fragment_2
|
||||
:language: c
|
||||
|
||||
|
38
examples/others/fragment/lv_example_fragment.h
Normal file
38
examples/others/fragment/lv_example_fragment.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file lv_example_fragment.h
|
||||
*/
|
||||
#ifndef LV_EXAMPLE_FRAGMENT_H
|
||||
#define LV_EXAMPLE_FRAGMENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void lv_example_fragment_1(void);
|
||||
|
||||
void lv_example_fragment_2(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EXAMPLE_fragment_H*/
|
47
examples/others/fragment/lv_example_fragment_1.c
Normal file
47
examples/others/fragment/lv_example_fragment_1.c
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file lv_example_fragment_1.c
|
||||
* @brief Basic usage of obj fragment
|
||||
*/
|
||||
#include "../../lv_examples.h"
|
||||
|
||||
#if LV_USE_FRAGMENT && LV_BUILD_EXAMPLES
|
||||
|
||||
static void sample_fragment_ctor(lv_fragment_t *self, void *args);
|
||||
|
||||
static lv_obj_t *sample_fragment_create_obj(lv_fragment_t *self, lv_obj_t *parent);
|
||||
|
||||
static lv_obj_t * root = NULL;
|
||||
|
||||
struct sample_fragment_t {
|
||||
lv_fragment_t base;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const lv_fragment_class_t sample_cls = {
|
||||
.constructor_cb = sample_fragment_ctor,
|
||||
.create_obj_cb = sample_fragment_create_obj,
|
||||
.instance_size = sizeof(struct sample_fragment_t)
|
||||
};
|
||||
|
||||
void lv_example_fragment_1(void)
|
||||
{
|
||||
root = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(root, LV_PCT(100), LV_PCT(100));
|
||||
lv_fragment_manager_t *manager = lv_fragment_manager_create(NULL);
|
||||
lv_fragment_t *fragment = lv_fragment_create(&sample_cls, "Fragment");
|
||||
lv_fragment_manager_replace(manager, fragment, &root);
|
||||
}
|
||||
|
||||
|
||||
static void sample_fragment_ctor(lv_fragment_t *self, void *args) {
|
||||
((struct sample_fragment_t *) self)->name = args;
|
||||
}
|
||||
|
||||
static lv_obj_t *sample_fragment_create_obj(lv_fragment_t *self, lv_obj_t *parent) {
|
||||
lv_obj_t *label = lv_label_create(parent);
|
||||
lv_obj_set_style_bg_opa(label, LV_OPA_COVER, 0);;
|
||||
lv_label_set_text_fmt(label, "Hello, %s!", ((struct sample_fragment_t *) self)->name);
|
||||
return label;
|
||||
}
|
||||
|
||||
#endif
|
111
examples/others/fragment/lv_example_fragment_2.c
Normal file
111
examples/others/fragment/lv_example_fragment_2.c
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* @file lv_example_fragment_2.c
|
||||
* @brief Navigation stack using obj fragment
|
||||
*/
|
||||
#include "../../lv_examples.h"
|
||||
|
||||
#if LV_USE_FRAGMENT && LV_USE_WIN && LV_BUILD_EXAMPLES
|
||||
|
||||
static void sample_fragment_ctor(lv_fragment_t *self, void *args);
|
||||
|
||||
static lv_obj_t *sample_fragment_create_obj(lv_fragment_t *self, lv_obj_t *parent);
|
||||
|
||||
static void sample_push_click(lv_event_t *e);
|
||||
|
||||
static void sample_pop_click(lv_event_t *e);
|
||||
|
||||
static void sample_fragment_inc_click(lv_event_t *e);
|
||||
|
||||
typedef struct sample_fragment_t {
|
||||
lv_fragment_t base;
|
||||
lv_obj_t *label;
|
||||
int depth;
|
||||
int counter;
|
||||
} sample_fragment_t;
|
||||
|
||||
static const lv_fragment_class_t sample_cls = {
|
||||
.constructor_cb = sample_fragment_ctor,
|
||||
.create_obj_cb = sample_fragment_create_obj,
|
||||
.instance_size = sizeof(sample_fragment_t)
|
||||
};
|
||||
|
||||
static lv_obj_t *container = NULL;
|
||||
|
||||
void lv_example_fragment_2(void)
|
||||
{
|
||||
lv_obj_t *root = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(root, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_layout(root, LV_LAYOUT_GRID);
|
||||
static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t row_dsc[] = {LV_GRID_FR(1), LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
lv_obj_set_grid_dsc_array(root, col_dsc, row_dsc);
|
||||
container = lv_obj_create(root);
|
||||
lv_obj_remove_style_all(container);
|
||||
lv_obj_set_grid_cell(container, LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_STRETCH, 0, 1);
|
||||
|
||||
lv_obj_t *push_btn = lv_btn_create(root);
|
||||
lv_obj_t *push_label = lv_label_create(push_btn);
|
||||
lv_label_set_text(push_label, "Push");
|
||||
|
||||
lv_obj_t *pop_btn = lv_btn_create(root);
|
||||
lv_obj_t *pop_label = lv_label_create(pop_btn);
|
||||
lv_label_set_text(pop_label, "Pop");
|
||||
lv_obj_set_grid_cell(push_btn, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_CENTER, 1, 1);
|
||||
lv_obj_set_grid_cell(pop_btn, LV_GRID_ALIGN_END, 1, 1, LV_GRID_ALIGN_CENTER, 1, 1);
|
||||
|
||||
lv_fragment_manager_t *manager = lv_fragment_manager_create(NULL);
|
||||
int depth = 0;
|
||||
lv_fragment_t *fragment = lv_fragment_create(&sample_cls, &depth);
|
||||
lv_fragment_manager_push(manager, fragment, &container);
|
||||
lv_obj_add_event_cb(push_btn, sample_push_click, LV_EVENT_CLICKED, manager);
|
||||
lv_obj_add_event_cb(pop_btn, sample_pop_click, LV_EVENT_CLICKED, manager);
|
||||
}
|
||||
|
||||
|
||||
static void sample_fragment_ctor(lv_fragment_t *self, void *args) {
|
||||
LV_UNUSED(args);
|
||||
((sample_fragment_t *) self)->depth = *((int *) args);
|
||||
((sample_fragment_t *) self)->counter = 0;
|
||||
}
|
||||
|
||||
static lv_obj_t *sample_fragment_create_obj(lv_fragment_t *self, lv_obj_t *parent) {
|
||||
sample_fragment_t *fragment = (sample_fragment_t *) self;
|
||||
lv_obj_t *content = lv_obj_create(parent);
|
||||
lv_obj_remove_style_all(content);
|
||||
lv_obj_set_style_bg_opa(content, LV_OPA_50, 0);
|
||||
lv_obj_set_style_bg_color(content, lv_palette_main(LV_PALETTE_YELLOW), 0);
|
||||
lv_obj_set_size(content, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_t *depth = lv_label_create(content);
|
||||
lv_label_set_text_fmt(depth, "Depth: %d", fragment->depth);
|
||||
lv_obj_t *label = lv_label_create(content);
|
||||
fragment->label = label;
|
||||
lv_label_set_text_fmt(label, "The button has been pressed %d times", fragment->counter);
|
||||
|
||||
lv_obj_t *inc_btn = lv_btn_create(content);
|
||||
lv_obj_t *inc_label = lv_label_create(inc_btn);
|
||||
lv_label_set_text(inc_label, "+1");
|
||||
lv_obj_add_event_cb(inc_btn, sample_fragment_inc_click, LV_EVENT_CLICKED, fragment);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
static void sample_push_click(lv_event_t *e) {
|
||||
lv_fragment_manager_t *manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
|
||||
size_t stack_size = lv_fragment_manager_get_stack_size(manager);
|
||||
lv_fragment_t *fragment = lv_fragment_create(&sample_cls, &stack_size);
|
||||
lv_fragment_manager_push(manager, fragment, &container);
|
||||
}
|
||||
|
||||
static void sample_pop_click(lv_event_t *e) {
|
||||
lv_fragment_manager_t *manager = (lv_fragment_manager_t *) lv_event_get_user_data(e);
|
||||
lv_fragment_manager_pop(manager);
|
||||
}
|
||||
|
||||
static void sample_fragment_inc_click(lv_event_t *e) {
|
||||
sample_fragment_t *fragment = (sample_fragment_t *) lv_event_get_user_data(e);
|
||||
fragment->counter++;
|
||||
lv_label_set_text_fmt(fragment->label, "The button has been pressed %d times", fragment->counter);
|
||||
}
|
||||
|
||||
#endif
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
#include "snapshot/lv_example_snapshot.h"
|
||||
#include "monkey/lv_example_monkey.h"
|
||||
#include "gridnav/lv_example_gridnav.h"
|
||||
#include "fragment/lv_example_fragment.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -37,4 +38,4 @@ extern "C" {
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EX_OTHERS_H*/
|
||||
#endif /*LV_EXAMPLE_OTHERS_H*/
|
||||
|
@ -657,6 +657,9 @@
|
||||
/*1: Enable grid navigation*/
|
||||
#define LV_USE_GRIDNAV 0
|
||||
|
||||
/*1: Enable lv_obj fragment*/
|
||||
#define LV_USE_FRAGMENT 0
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
@ -208,7 +208,7 @@ bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_c
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb) &&
|
||||
if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) &&
|
||||
obj->spec_attr->event_dsc[i].user_data == user_data) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
|
0
src/extra/others/fragment/README.md
Normal file
0
src/extra/others/fragment/README.md
Normal file
137
src/extra/others/fragment/lv_fragment.c
Normal file
137
src/extra/others/fragment/lv_fragment.c
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @file lv_fragment.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_fragment.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void cb_delete_assertion(lv_event_t * event);
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args)
|
||||
{
|
||||
LV_ASSERT_NULL(cls);
|
||||
LV_ASSERT_NULL(cls->create_obj_cb);
|
||||
LV_ASSERT(cls->instance_size > 0);
|
||||
lv_fragment_t * instance = lv_mem_alloc(cls->instance_size);
|
||||
lv_memset_00(instance, cls->instance_size);
|
||||
instance->cls = cls;
|
||||
instance->child_manager = lv_fragment_manager_create(instance);
|
||||
if(cls->constructor_cb) {
|
||||
cls->constructor_cb(instance, args);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void lv_fragment_del(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
if(fragment->managed) {
|
||||
lv_fragment_manager_remove(fragment->managed->manager, fragment);
|
||||
return;
|
||||
}
|
||||
if(fragment->obj) {
|
||||
lv_fragment_del_obj(fragment);
|
||||
}
|
||||
/* Objects will leak if this function called before objects deleted */
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
if(cls->destructor_cb) {
|
||||
cls->destructor_cb(fragment);
|
||||
}
|
||||
lv_fragment_manager_del(fragment->child_manager);
|
||||
lv_mem_free(fragment);
|
||||
}
|
||||
|
||||
lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
return fragment->managed->container;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
return lv_fragment_manager_get_parent_fragment(fragment->managed->manager);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container)
|
||||
{
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
if(states) {
|
||||
states->destroying_obj = false;
|
||||
}
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
lv_obj_t * obj = cls->create_obj_cb(fragment, container);
|
||||
LV_ASSERT_NULL(obj);
|
||||
fragment->obj = obj;
|
||||
lv_fragment_manager_create_obj(fragment->child_manager);
|
||||
if(states) {
|
||||
states->obj_created = true;
|
||||
lv_obj_add_event_cb(obj, cb_delete_assertion, LV_EVENT_DELETE, NULL);
|
||||
}
|
||||
if(cls->obj_created_cb) {
|
||||
cls->obj_created_cb(fragment, obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_fragment_del_obj(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
lv_fragment_manager_del_obj(fragment->child_manager);
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
if(states) {
|
||||
if(!states->obj_created) return;
|
||||
states->destroying_obj = true;
|
||||
bool cb_removed = lv_obj_remove_event_cb(fragment->obj, cb_delete_assertion);
|
||||
LV_ASSERT(cb_removed);
|
||||
}
|
||||
LV_ASSERT_NULL(fragment->obj);
|
||||
const lv_fragment_class_t * cls = fragment->cls;
|
||||
if(cls->obj_will_delete_cb) {
|
||||
cls->obj_will_delete_cb(fragment, fragment->obj);
|
||||
}
|
||||
lv_obj_del(fragment->obj);
|
||||
if(cls->obj_deleted_cb) {
|
||||
cls->obj_deleted_cb(fragment, fragment->obj);
|
||||
}
|
||||
if(states) {
|
||||
states->obj_created = false;
|
||||
}
|
||||
fragment->obj = NULL;
|
||||
}
|
||||
|
||||
void lv_fragment_recreate_obj(lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
lv_fragment_del_obj(fragment);
|
||||
lv_fragment_create_obj(fragment, *fragment->managed->container);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void cb_delete_assertion(lv_event_t * event)
|
||||
{
|
||||
LV_UNUSED(event);
|
||||
LV_ASSERT_MSG(0, "Please delete objects with lv_fragment_destroy_obj");
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
339
src/extra/others/fragment/lv_fragment.h
Normal file
339
src/extra/others/fragment/lv_fragment.h
Normal file
@ -0,0 +1,339 @@
|
||||
/**
|
||||
* Public header for Fragment
|
||||
* @file lv_fragment.h
|
||||
*/
|
||||
|
||||
#ifndef LV_FRAGMENT_H
|
||||
#define LV_FRAGMENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
#include "../../../core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_fragment_manager_t lv_fragment_manager_t;
|
||||
|
||||
typedef struct _lv_fragment_t lv_fragment_t;
|
||||
typedef struct _lv_fragment_class_t lv_fragment_class_t;
|
||||
typedef struct _lv_fragment_managed_states_t lv_fragment_managed_states_t;
|
||||
|
||||
struct _lv_fragment_t {
|
||||
/**
|
||||
* Class of this fragment
|
||||
*/
|
||||
const lv_fragment_class_t * cls;
|
||||
/**
|
||||
* Managed fragment states. If not null, then this fragment is managed.
|
||||
*
|
||||
* @warning Don't modify values inside this struct!
|
||||
*/
|
||||
lv_fragment_managed_states_t * managed;
|
||||
/**
|
||||
* Child fragment manager
|
||||
*/
|
||||
lv_fragment_manager_t * child_manager;
|
||||
/**
|
||||
* lv_obj returned by create_obj_cb
|
||||
*/
|
||||
lv_obj_t * obj;
|
||||
|
||||
};
|
||||
|
||||
struct _lv_fragment_class_t {
|
||||
/**
|
||||
* Constructor function for fragment class
|
||||
* @param self Fragment instance
|
||||
* @param args Arguments assigned by fragment manager
|
||||
*/
|
||||
void (*constructor_cb)(lv_fragment_t * self, void * args);
|
||||
|
||||
/**
|
||||
* Destructor function for fragment class
|
||||
* @param self Fragment instance, will be freed after this call
|
||||
*/
|
||||
void (*destructor_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Fragment attached to manager
|
||||
* @param self Fragment instance
|
||||
*/
|
||||
void (*attached_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Fragment detached from manager
|
||||
* @param self Fragment instance
|
||||
*/
|
||||
void (*detached_cb)(lv_fragment_t * self);
|
||||
|
||||
/**
|
||||
* Create objects
|
||||
* @param self Fragment instance
|
||||
* @param container Container of the objects should be created upon
|
||||
* @return Created object, NULL if multiple objects has been created
|
||||
*/
|
||||
lv_obj_t * (*create_obj_cb)(lv_fragment_t * self, lv_obj_t * container);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param self Fragment instance
|
||||
* @param obj lv_obj returned by create_obj_cb
|
||||
*/
|
||||
void (*obj_created_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Called before objects in the fragment will be deleted.
|
||||
*
|
||||
* @param self Fragment instance
|
||||
* @param obj object with this fragment
|
||||
*/
|
||||
void (*obj_will_delete_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Called when the object created by fragment received `LV_EVENT_DELETE` event
|
||||
* @param self Fragment instance
|
||||
* @param obj object with this fragment
|
||||
*/
|
||||
void (*obj_deleted_cb)(lv_fragment_t * self, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Handle event
|
||||
* @param self Fragment instance
|
||||
* @param which User-defined ID of event
|
||||
* @param data1 User-defined data
|
||||
* @param data2 User-defined data
|
||||
*/
|
||||
bool (*event_cb)(lv_fragment_t * self, int code, void * userdata);
|
||||
|
||||
/**
|
||||
* *REQUIRED*: Allocation size of fragment
|
||||
*/
|
||||
size_t instance_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fragment states
|
||||
*/
|
||||
typedef struct _lv_fragment_managed_states_t {
|
||||
/**
|
||||
* Class of the fragment
|
||||
*/
|
||||
const lv_fragment_class_t * cls;
|
||||
/**
|
||||
* Manager the fragment attached to
|
||||
*/
|
||||
lv_fragment_manager_t * manager;
|
||||
/**
|
||||
* Container object the fragment adding view to
|
||||
*/
|
||||
lv_obj_t * const * container;
|
||||
/**
|
||||
* Fragment instance
|
||||
*/
|
||||
lv_fragment_t * instance;
|
||||
/**
|
||||
* true between `create_obj_cb` and `obj_deleted_cb`
|
||||
*/
|
||||
bool obj_created;
|
||||
/**
|
||||
* true before `lv_fragment_del_obj` is called. Don't touch any object if this is true
|
||||
*/
|
||||
bool destroying_obj;
|
||||
/**
|
||||
* true if this fragment is in navigation stack that can be popped
|
||||
*/
|
||||
bool in_stack;
|
||||
} lv_fragment_managed_states_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create fragment manager instance
|
||||
* @param parent Parent fragment if this manager is placed inside another fragment, can be null.
|
||||
* @return Fragment manager instance
|
||||
*/
|
||||
lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent);
|
||||
|
||||
/**
|
||||
* Destroy fragment manager instance
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_del(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Create object of all fragments managed by this manager.
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted.
|
||||
* @param manager Fragment manager instance
|
||||
*/
|
||||
void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Attach fragment to manager, and add to container.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Detach and destroy fragment. If fragment is in navigation stack, remove from it.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
*/
|
||||
void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Attach fragment to manager and add to navigation stack.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Remove the top-most fragment for stack
|
||||
* @param manager Fragment manager instance
|
||||
* @return true if there is fragment to pop
|
||||
*/
|
||||
bool lv_fragment_manager_pop(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Replace fragment. Old item in the stack will be removed.
|
||||
* @param manager Fragment manager instance
|
||||
* @param fragment Fragment instance
|
||||
* @param container Pointer to container object for manager to add objects to
|
||||
*/
|
||||
void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container);
|
||||
|
||||
/**
|
||||
* Send event to top-most fragment
|
||||
* @param manager Fragment manager instance
|
||||
* @param code User-defined ID of event
|
||||
* @param userdata User-defined data
|
||||
* @return true if fragment returned true
|
||||
*/
|
||||
bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata);
|
||||
|
||||
/**
|
||||
* Get stack size of this fragment manager
|
||||
* @param manager Fragment manager instance
|
||||
* @return Stack size of this fragment manager
|
||||
*/
|
||||
size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Get top most fragment instance
|
||||
* @param manager Fragment manager instance
|
||||
* @return Top most fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Find first fragment instance in the container
|
||||
* @param manager Fragment manager instance
|
||||
* @param container Container which target fragment added to
|
||||
* @return First fragment instance in the container
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container);
|
||||
|
||||
/**
|
||||
* Get parent fragment
|
||||
* @param manager Fragment manager instance
|
||||
* @return Parent fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager);
|
||||
|
||||
|
||||
/**
|
||||
* Create a fragment instance.
|
||||
*
|
||||
* @param cls Fragment class. This fragment must return non null object.
|
||||
* @param args Arguments assigned by fragment manager
|
||||
* @return Fragment instance
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args);
|
||||
|
||||
/**
|
||||
* Destroy a fragment.
|
||||
* @param fragment Fragment instance.
|
||||
*/
|
||||
void lv_fragment_del(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get associated manager of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Fragment manager instance
|
||||
*/
|
||||
lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get container object of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Reference to container object
|
||||
*/
|
||||
lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Get parent fragment of this fragment
|
||||
* @param fragment Fragment instance
|
||||
* @return Parent fragment
|
||||
*/
|
||||
lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Create object by fragment.
|
||||
*
|
||||
* @param fragment Fragment instance.
|
||||
* @param container Container of the objects should be created upon.
|
||||
* @return Created object
|
||||
*/
|
||||
lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container);
|
||||
|
||||
/**
|
||||
* Delete created object of a fragment
|
||||
*
|
||||
* @param fragment Fragment instance.
|
||||
*/
|
||||
void lv_fragment_del_obj(lv_fragment_t * fragment);
|
||||
|
||||
/**
|
||||
* Destroy obj in fragment, and recreate them.
|
||||
* @param fragment Fragment instance
|
||||
*/
|
||||
void lv_fragment_recreate_obj(lv_fragment_t * fragment);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FRAGMENT_H*/
|
278
src/extra/others/fragment/lv_fragment_manager.c
Normal file
278
src/extra/others/fragment/lv_fragment_manager.c
Normal file
@ -0,0 +1,278 @@
|
||||
/**
|
||||
* @file lv_fragment_manager.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_fragment.h"
|
||||
|
||||
#if LV_USE_FRAGMENT
|
||||
|
||||
#include "../../../misc/lv_ll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_fragment_stack_item_t {
|
||||
lv_fragment_managed_states_t * states;
|
||||
} lv_fragment_stack_item_t;
|
||||
|
||||
struct _lv_fragment_manager_t {
|
||||
lv_fragment_t * parent;
|
||||
/**
|
||||
* Linked list to store attached fragments
|
||||
*/
|
||||
lv_ll_t attached;
|
||||
/**
|
||||
* Linked list to store fragments in stack
|
||||
*/
|
||||
lv_ll_t stack;
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void item_create_obj(lv_fragment_managed_states_t * item);
|
||||
|
||||
static void item_del_obj(lv_fragment_managed_states_t * item);
|
||||
|
||||
static void item_del_fragment(lv_fragment_managed_states_t * item);
|
||||
|
||||
static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent)
|
||||
{
|
||||
lv_fragment_manager_t * instance = lv_mem_alloc(sizeof(lv_fragment_manager_t));
|
||||
lv_memset_00(instance, sizeof(lv_fragment_manager_t));
|
||||
instance->parent = parent;
|
||||
_lv_ll_init(&instance->attached, sizeof(lv_fragment_managed_states_t));
|
||||
_lv_ll_init(&instance->stack, sizeof(lv_fragment_stack_item_t));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void lv_fragment_manager_del(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_managed_states_t * states;
|
||||
_LV_LL_READ_BACK(&manager->attached, states) {
|
||||
item_del_obj(states);
|
||||
item_del_fragment(states);
|
||||
}
|
||||
_lv_ll_clear(&manager->attached);
|
||||
_lv_ll_clear(&manager->stack);
|
||||
lv_mem_free(manager);
|
||||
}
|
||||
|
||||
void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack);
|
||||
lv_fragment_managed_states_t * states = NULL;
|
||||
_LV_LL_READ(&manager->attached, states) {
|
||||
if(states->in_stack && top->states != states) {
|
||||
/*Only create obj for top item in stack*/
|
||||
continue;
|
||||
}
|
||||
item_create_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_managed_states_t * states = NULL;
|
||||
_LV_LL_READ_BACK(&manager->attached, states) {
|
||||
item_del_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container);
|
||||
if(!manager->parent || manager->parent->managed->obj_created) {
|
||||
item_create_obj(states);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(fragment);
|
||||
LV_ASSERT_NULL(fragment->managed);
|
||||
LV_ASSERT(fragment->managed->manager == manager);
|
||||
lv_fragment_managed_states_t * states = fragment->managed;
|
||||
lv_fragment_managed_states_t * prev = NULL;
|
||||
bool was_top = false;
|
||||
if(states->in_stack) {
|
||||
void * stack_top = _lv_ll_get_tail(&manager->stack);
|
||||
lv_fragment_stack_item_t * stack = NULL;
|
||||
_LV_LL_READ_BACK(&manager->stack, stack) {
|
||||
if(stack->states == states) {
|
||||
was_top = stack_top == stack;
|
||||
void * stack_prev = _lv_ll_get_prev(&manager->stack, stack);
|
||||
if(!stack_prev) break;
|
||||
prev = ((lv_fragment_stack_item_t *) stack_prev)->states;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stack) {
|
||||
_lv_ll_remove(&manager->stack, stack);
|
||||
}
|
||||
}
|
||||
item_del_obj(states);
|
||||
item_del_fragment(states);
|
||||
_lv_ll_remove(&manager->attached, states);
|
||||
if(prev && was_top) {
|
||||
item_create_obj(prev);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack);
|
||||
if(top != NULL) {
|
||||
item_del_obj(top->states);
|
||||
}
|
||||
lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container);
|
||||
states->in_stack = true;
|
||||
/*Add fragment to the top of the stack*/
|
||||
lv_fragment_stack_item_t * item = _lv_ll_ins_tail(&manager->stack);
|
||||
lv_memset_00(item, sizeof(lv_fragment_stack_item_t));
|
||||
item->states = states;
|
||||
item_create_obj(states);
|
||||
}
|
||||
|
||||
bool lv_fragment_manager_pop(lv_fragment_manager_t * manager)
|
||||
{
|
||||
lv_fragment_t * top = lv_fragment_manager_get_top(manager);
|
||||
if(top == NULL) return false;
|
||||
lv_fragment_manager_remove(manager, top);
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container)
|
||||
{
|
||||
lv_fragment_t * top = lv_fragment_manager_find_by_container(manager, *container);
|
||||
if(top != NULL) {
|
||||
lv_fragment_manager_remove(manager, top);
|
||||
}
|
||||
lv_fragment_manager_add(manager, fragment, container);
|
||||
}
|
||||
|
||||
bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack);
|
||||
if(!top) return false;
|
||||
lv_fragment_managed_states_t * states = top->states;
|
||||
lv_fragment_t * instance = states->instance;
|
||||
if(!instance) return false;
|
||||
if(lv_fragment_manager_send_event(instance->child_manager, code, userdata)) return true;
|
||||
if(!states->cls->event_cb) return false;
|
||||
return states->cls->event_cb(instance, code, userdata);
|
||||
}
|
||||
|
||||
size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
return _lv_ll_get_len(&manager->stack);
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack);
|
||||
if(!top)return NULL;
|
||||
return top->states->instance;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
lv_fragment_managed_states_t * states;
|
||||
_LV_LL_READ(&manager->attached, states) {
|
||||
if(*states->container == container) return states->instance;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
return manager->parent;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void item_create_obj(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
LV_ASSERT(item->instance);
|
||||
lv_fragment_create_obj(item->instance, item->container ? *item->container : NULL);
|
||||
}
|
||||
|
||||
static void item_del_obj(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
lv_fragment_del_obj(item->instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach, then destroy fragment
|
||||
* @param item fragment states
|
||||
*/
|
||||
static void item_del_fragment(lv_fragment_managed_states_t * item)
|
||||
{
|
||||
lv_fragment_t * instance = item->instance;
|
||||
if(instance->cls->detached_cb) {
|
||||
instance->cls->detached_cb(instance);
|
||||
}
|
||||
instance->managed = NULL;
|
||||
lv_fragment_del(instance);
|
||||
item->instance = NULL;
|
||||
}
|
||||
|
||||
|
||||
static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment,
|
||||
lv_obj_t * const * container)
|
||||
{
|
||||
LV_ASSERT(manager);
|
||||
LV_ASSERT(fragment);
|
||||
LV_ASSERT(fragment->managed == NULL);
|
||||
lv_fragment_managed_states_t * item = _lv_ll_ins_tail(&manager->attached);
|
||||
lv_memset_00(item, sizeof(lv_fragment_managed_states_t));
|
||||
item->cls = fragment->cls;
|
||||
item->manager = manager;
|
||||
item->container = container;
|
||||
item->instance = fragment;
|
||||
fragment->managed = item;
|
||||
if(fragment->cls->attached_cb) {
|
||||
fragment->cls->attached_cb(fragment);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FRAGMENT*/
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
#include "snapshot/lv_snapshot.h"
|
||||
#include "monkey/lv_monkey.h"
|
||||
#include "gridnav/lv_gridnav.h"
|
||||
#include "fragment/lv_fragment.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
|
@ -2108,6 +2108,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*1: Enable lv_obj fragment*/
|
||||
#ifndef LV_USE_FRAGMENT
|
||||
#ifdef CONFIG_LV_USE_FRAGMENT
|
||||
#define LV_USE_FRAGMENT CONFIG_LV_USE_FRAGMENT
|
||||
#else
|
||||
#define LV_USE_FRAGMENT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
@ -286,7 +286,7 @@ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the pointer of the previous node after 'n_act'
|
||||
* Return with the pointer of the previous node before 'n_act'
|
||||
* @param ll_p pointer to linked list
|
||||
* @param n_act pointer a node
|
||||
* @return pointer to the previous node
|
||||
|
@ -189,6 +189,7 @@ set(LVGL_TEST_OPTIONS_FULL_32BIT
|
||||
-DLV_USE_SJPG=1
|
||||
-DLV_USE_GIF=1
|
||||
-DLV_USE_QRCODE=1
|
||||
-DLV_USE_FRAGMENT=1
|
||||
)
|
||||
|
||||
set(LVGL_TEST_OPTIONS_TEST_COMMON
|
||||
|
Loading…
Reference in New Issue
Block a user