aboutsummaryrefslogtreecommitdiff
path: root/src/core/lv_obj_property.c
blob: e9bc411d04ac1037c88bf1f841f871bcf0213ff1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/**
 * @file lv_obj_id.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_obj_private.h"
#include "../core/lv_obj.h"
#include "../stdlib/lv_string.h"
#include "../misc/lv_utils.h"
#include "lv_obj_property.h"
#include "lv_obj_class_private.h"

#if LV_USE_OBJ_PROPERTY

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

typedef void (*lv_property_set_int_t)(lv_obj_t *, int32_t);
typedef void (*lv_property_set_bool_t)(lv_obj_t *, bool);
typedef void (*lv_property_set_precise_t)(lv_obj_t *, lv_value_precise_t);
typedef void (*lv_property_set_color_t)(lv_obj_t *, lv_color_t);
typedef void (*lv_property_set_point_t)(lv_obj_t *, lv_point_t *);
typedef void (*lv_property_set_pointer_t)(lv_obj_t *, const void *);
typedef lv_result_t (*lv_property_setter_t)(lv_obj_t *, lv_prop_id_t, const lv_property_t *);

typedef int32_t (*lv_property_get_int_t)(const lv_obj_t *);
typedef bool (*lv_property_get_bool_t)(const lv_obj_t *);
typedef lv_value_precise_t (*lv_property_get_precise_t)(const lv_obj_t *);
typedef lv_color_t (*lv_property_get_color_t)(const lv_obj_t *);
typedef lv_point_t (*lv_property_get_point_t)(lv_obj_t *);
typedef void * (*lv_property_get_pointer_t)(const lv_obj_t *);
typedef lv_result_t (*lv_property_getter_t)(const lv_obj_t *, lv_prop_id_t, lv_property_t *);

/**********************
 *  STATIC PROTOTYPES
 **********************/

static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set);
static int32_t property_name_compare(const void * ref, const void * element);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value)
{
    LV_ASSERT(obj && value);

    uint32_t index = LV_PROPERTY_ID_INDEX(value->id);
    if(value->id == LV_PROPERTY_ID_INVALID || index > LV_PROPERTY_ID_ANY) {
        LV_LOG_WARN("Invalid property id set to %p", obj);
        return LV_RESULT_INVALID;
    }

    if(index < LV_PROPERTY_ID_START) {
        lv_obj_set_local_style_prop(obj, index, value->style, value->selector);
        return LV_RESULT_OK;
    }

    return obj_property(obj, value->id, (lv_property_t *)value, true);
}

lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count)
{
    for(uint32_t i = 0; i < count; i++) {
        lv_result_t result = lv_obj_set_property(obj, &value[i]);
        if(result != LV_RESULT_OK) {
            return result;
        }
    }

    return LV_RESULT_OK;
}

lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id)
{
    lv_result_t result;
    lv_property_t value = { 0 };

    uint32_t index = LV_PROPERTY_ID_INDEX(id);
    if(id == LV_PROPERTY_ID_INVALID || index > LV_PROPERTY_ID_ANY) {
        LV_LOG_WARN("Invalid property id to get from %p", obj);
        value.id = LV_PROPERTY_ID_INVALID;
        value.num = 0;
        return value;
    }

    if(index < LV_PROPERTY_ID_START) {
        lv_obj_get_local_style_prop(obj, index, &value.style, 0);
        value.id = id;
        value.selector = 0;
        return value;
    }

    result = obj_property(obj, id, &value, false);
    if(result != LV_RESULT_OK)
        value.id = LV_PROPERTY_ID_INVALID;

    return value;
}

lv_property_t lv_obj_get_style_property(lv_obj_t * obj, lv_prop_id_t id, uint32_t selector)
{
    lv_property_t value;
    uint32_t index = LV_PROPERTY_ID_INDEX(id);

    if(index == LV_PROPERTY_ID_INVALID || index >= LV_PROPERTY_ID_START) {
        LV_LOG_WARN("invalid style property id %d", id);
        value.id = LV_PROPERTY_ID_INVALID;
        value.num = 0;
        return value;
    }

    lv_obj_get_local_style_prop(obj, id, &value.style, selector);
    value.id = id;
    value.selector = selector;
    return value;
}

lv_prop_id_t lv_obj_property_get_id(const lv_obj_t * obj, const char * name)
{
#if LV_USE_OBJ_PROPERTY_NAME
    const lv_obj_class_t * clz;
    const lv_property_name_t * names;
    lv_property_name_t * found;

    for(clz = obj->class_p; clz; clz = clz->base_class) {
        names = clz->property_names;
        if(names == NULL) {
            /* try base class*/
            continue;
        }

        found = lv_utils_bsearch(name, names, clz->names_count, sizeof(lv_property_name_t), property_name_compare);
        if(found) return found->id;
    }

    /*Check style property*/
    found = lv_utils_bsearch(name, lv_style_property_names, sizeof(lv_style_property_names) / sizeof(lv_property_name_t),
                             sizeof(lv_property_name_t), property_name_compare);
    if(found) return found->id;
#else
    LV_UNUSED(obj);
    LV_UNUSED(name);
    LV_UNUSED(property_name_compare);
#endif
    return LV_PROPERTY_ID_INVALID;
}

/**********************
 *  STATIC FUNCTIONS
 **********************/

static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set)
{
    const lv_property_ops_t * properties;
    const lv_property_ops_t * prop;

    const lv_obj_class_t * clz;
    uint32_t index = LV_PROPERTY_ID_INDEX(id);

    for(clz = obj->class_p ; clz; clz = clz->base_class) {
        properties = clz->properties;
        if(properties == NULL) {
            /* try base class*/
            continue;
        }

        if(id != LV_PROPERTY_ID_ANY && (index < clz->prop_index_start || index > clz->prop_index_end)) {
            /* try base class*/
            continue;
        }

        /*Check if there's setter available for this class*/
        for(uint32_t i = 0; i < clz->properties_count; i++) {
            prop = &properties[i];

            /*pass id and value directly to widget's property method*/
            if(prop->id == LV_PROPERTY_ID_ANY) {
                value->id = prop->id;
                if(set) return ((lv_property_setter_t)prop->setter)(obj, id, value);
                else return ((lv_property_getter_t)prop->getter)(obj, id, value);
            }

            /*Not this id, check next*/
            if(prop->id != id)
                continue;

            /*id matched but we got null pointer to functions*/
            if(set ? prop->setter == NULL : prop->getter == NULL) {
                LV_LOG_WARN("NULL %s provided, id: %d", set ? "setter" : "getter", id);
                return LV_RESULT_INVALID;
            }

            /*Update value id if it's a read*/
            if(!set) value->id = prop->id;

            switch(LV_PROPERTY_ID_TYPE(prop->id)) {
                case LV_PROPERTY_TYPE_INT: {
                        if(set)((lv_property_set_int_t)(prop->setter))(obj, value->num);
                        else value->num = ((lv_property_get_int_t)(prop->getter))(obj);
                        break;
                    }
                case LV_PROPERTY_TYPE_BOOL: {
                        if(set)((lv_property_set_bool_t)(prop->setter))(obj, value->enable);
                        else value->enable = ((lv_property_get_bool_t)(prop->getter))(obj);
                        break;
                    }

                case LV_PROPERTY_TYPE_PRECISE: {
                        if(set)((lv_property_set_precise_t)(prop->setter))(obj, value->precise);
                        else value->precise = ((lv_property_get_precise_t)(prop->getter))(obj);
                        break;
                    }
                case LV_PROPERTY_TYPE_COLOR: {
                        if(set)((lv_property_set_color_t)prop->setter)(obj, value->color);
                        else value->color = ((lv_property_get_color_t)(prop->getter))(obj);
                        break;
                    }
                case LV_PROPERTY_TYPE_POINT: {
                        lv_point_t * point = &value->point;
                        if(set)((lv_property_set_point_t)(prop->setter))(obj, point);
                        else *point = ((lv_property_get_point_t)(prop->getter))(obj);
                        break;
                    }
                case LV_PROPERTY_TYPE_POINTER:
                case LV_PROPERTY_TYPE_IMGSRC:
                case LV_PROPERTY_TYPE_TEXT:
                case LV_PROPERTY_TYPE_OBJ:
                case LV_PROPERTY_TYPE_DISPLAY:
                case LV_PROPERTY_TYPE_FONT: {
                        if(set)((lv_property_set_pointer_t)(prop->setter))(obj, value->ptr);
                        else value->ptr = ((lv_property_get_pointer_t)(prop->getter))(obj);
                        break;
                    }
                default: {
                        LV_LOG_WARN("Unknown property id: 0x%08x", prop->id);
                        return LV_RESULT_INVALID;
                    }
            }

            return LV_RESULT_OK;
        }

        /*If no setter found, try base class then*/
    }

    LV_LOG_WARN("Unknown property id: 0x%08x", id);
    return LV_RESULT_INVALID;
}

static int property_name_compare(const void * ref, const void * element)
{
    const lv_property_name_t * prop = element;
    return lv_strcmp(ref, prop->name);
}

#endif /*LV_USE_OBJ_PROPERTY*/