Files
STM32F4-Base/Lib/lvgl/src/misc/lv_tree.c
T
2026-08-30 08:57:07 +08:00

190 lines
4.9 KiB
C

/**
* @file lv_tree.c
* Tree.
* The nodes are dynamically allocated by the 'lv_mem' module,
*/
/*********************
* INCLUDES
*********************/
#include "lv_tree.h"
#include "../stdlib/lv_mem.h"
#include "../stdlib/lv_string.h"
#include "lv_assert.h"
/*********************
* DEFINES
*********************/
#define INIT_CHILDREN_CAP 4
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
const lv_tree_class_t lv_tree_node_class = {
.base_class = NULL,
.instance_size = sizeof(lv_tree_node_t),
.constructor_cb = NULL,
.destructor_cb = NULL,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
static void _lv_tree_node_construct(const lv_tree_class_t * class_p, lv_tree_node_t * node)
{
if(node->class_p->base_class) {
const lv_tree_class_t * original_class_p = node->class_p;
node->class_p = node->class_p->base_class;
_lv_tree_node_construct(class_p, node);
node->class_p = original_class_p;
}
if(node->class_p->constructor_cb) node->class_p->constructor_cb(class_p, node);
}
static void _lv_tree_node_destruct(lv_tree_node_t * node)
{
if(node->class_p->destructor_cb) node->class_p->destructor_cb(node->class_p, node);
if(node->class_p->base_class) {
node->class_p = node->class_p->base_class;
_lv_tree_node_destruct(node);
}
}
static uint32_t get_instance_size(const lv_tree_class_t * class_p)
{
const lv_tree_class_t * base = class_p;
while(base && base->instance_size == 0)
base = base->base_class;
LV_ASSERT_NULL(base);
return base->instance_size;
}
static lv_tree_node_t * _lv_tree_class_create_node(const lv_tree_class_t * class_p, lv_tree_node_t * parent)
{
uint32_t s = get_instance_size(class_p);
lv_tree_node_t * node = lv_malloc(s);
if(node == NULL) return NULL;
lv_memzero(node, s);
node->class_p = class_p;
node->parent = parent;
node->child_cap = INIT_CHILDREN_CAP;
node->children = lv_malloc(sizeof(lv_tree_node_t *) * node->child_cap);
if(parent != NULL) {
parent->child_cnt++;
if(parent->child_cnt == parent->child_cap) {
parent->child_cap <<= 1;
parent->children = lv_realloc(parent->children, sizeof(lv_tree_node_t *) * parent->child_cap);
}
parent->children[parent->child_cnt - 1] = node;
}
return node;
}
lv_tree_node_t * lv_tree_node_create(const lv_tree_class_t * class_p, lv_tree_node_t * parent)
{
LV_ASSERT_NULL(class_p);
lv_tree_node_t * node = _lv_tree_class_create_node(class_p, parent);
LV_ASSERT_NULL(node);
_lv_tree_node_construct(node->class_p, node);
return node;
}
static bool _lv_tree_node_destructor_cb(const lv_tree_node_t * n, void * user_data)
{
LV_UNUSED(user_data);
if(n) {
lv_tree_node_t * node = (lv_tree_node_t *)n;
_lv_tree_node_destruct(node);
lv_free(node->children);
lv_free(node);
}
return true;
}
void lv_tree_node_delete(lv_tree_node_t * node)
{
if(node) {
if(node->parent) {
/* Remove from parent */
lv_tree_node_t * parent = node->parent;
for(uint32_t i = 0; i < parent->child_cnt; i++) {
if(parent->children[i] == node) {
parent->children[i] = NULL;
}
}
}
lv_tree_walk(node, LV_TREE_WALK_POST_ORDER, _lv_tree_node_destructor_cb, NULL, NULL, NULL);
}
}
bool lv_tree_walk(const lv_tree_node_t * node,
lv_tree_walk_mode_t mode,
lv_tree_traverse_cb_t cb,
lv_tree_before_cb_t bcb,
lv_tree_after_cb_t acb,
void * user_data)
{
if(node && cb) {
if(mode == LV_TREE_WALK_PRE_ORDER) {
if(bcb && !bcb(node, user_data)) {
return false;
}
if(!cb(node, user_data)) {
return false;
}
}
for(uint32_t i = 0; i < node->child_cnt; i++) {
if(!lv_tree_walk(node->children[i], mode, cb, bcb, acb, user_data)) {
return false;
}
}
if(mode == LV_TREE_WALK_PRE_ORDER) {
if(acb) {
acb(node, user_data);
}
}
if(mode == LV_TREE_WALK_POST_ORDER) {
if(bcb && !bcb(node, user_data)) {
return false;
}
if(!cb(node, user_data)) {
return false;
}
if(acb) {
acb(node, user_data);
}
return true;
}
else {
return true;
}
}
else {
return true;
}
}