Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/libs/lvgl/lv_objx/lv_bar.c
1476 views
1
2
3
/**
4
* @file lv_bar.c
5
*
6
*/
7
8
/*********************
9
* INCLUDES
10
*********************/
11
#include "lv_bar.h"
12
#if USE_LV_BAR != 0
13
14
#include "../lv_draw/lv_draw.h"
15
#include "../lv_themes/lv_theme.h"
16
#include "../lv_misc/lv_anim.h"
17
#include <stdio.h>
18
19
/*********************
20
* DEFINES
21
*********************/
22
23
/**********************
24
* TYPEDEFS
25
**********************/
26
27
/**********************
28
* STATIC PROTOTYPES
29
**********************/
30
static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode_t mode);
31
static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param);
32
33
/**********************
34
* STATIC VARIABLES
35
**********************/
36
static lv_design_func_t ancestor_design_f;
37
static lv_signal_func_t ancestor_signal;
38
39
/**********************
40
* MACROS
41
**********************/
42
43
/**********************
44
* GLOBAL FUNCTIONS
45
**********************/
46
47
/**
48
* Create a bar objects
49
* @param par pointer to an object, it will be the parent of the new bar
50
* @param copy pointer to a bar object, if not NULL then the new object will be copied from it
51
* @return pointer to the created bar
52
*/
53
lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
54
{
55
LV_LOG_TRACE("lv_bar create started");
56
57
/*Create the ancestor basic object*/
58
lv_obj_t * new_bar = lv_obj_create(par, copy);
59
lv_mem_assert(new_bar);
60
if(new_bar == NULL) return NULL;
61
62
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_bar);
63
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_bar);
64
65
/*Allocate the object type specific extended data*/
66
lv_bar_ext_t * ext = lv_obj_allocate_ext_attr(new_bar, sizeof(lv_bar_ext_t));
67
lv_mem_assert(ext);
68
if(ext == NULL) return NULL;
69
70
ext->min_value = 0;
71
ext->max_value = 100;
72
ext->cur_value = 0;
73
ext->sym = 0;
74
ext->style_indic = &lv_style_pretty_color;
75
76
lv_obj_set_signal_func(new_bar, lv_bar_signal);
77
lv_obj_set_design_func(new_bar, lv_bar_design);
78
79
/*Init the new bar object*/
80
if(copy == NULL) {
81
lv_obj_set_click(new_bar, false);
82
lv_obj_set_size(new_bar, LV_DPI * 2, LV_DPI / 3);
83
lv_bar_set_value(new_bar, ext->cur_value);
84
85
lv_theme_t * th = lv_theme_get_current();
86
if(th) {
87
lv_bar_set_style(new_bar, LV_BAR_STYLE_BG, th->bar.bg);
88
lv_bar_set_style(new_bar, LV_BAR_STYLE_INDIC, th->bar.indic);
89
} else {
90
lv_obj_set_style(new_bar, &lv_style_pretty);
91
}
92
} else {
93
lv_bar_ext_t * ext_copy = lv_obj_get_ext_attr(copy);
94
ext->min_value = ext_copy->min_value;
95
ext->max_value = ext_copy->max_value;
96
ext->cur_value = ext_copy->cur_value;
97
ext->style_indic = ext_copy->style_indic;
98
ext->sym = ext_copy->sym;
99
/*Refresh the style with new signal function*/
100
lv_obj_refresh_style(new_bar);
101
102
lv_bar_set_value(new_bar, ext->cur_value);
103
}
104
105
LV_LOG_INFO("bar created");
106
107
return new_bar;
108
}
109
110
/*=====================
111
* Setter functions
112
*====================*/
113
114
/**
115
* Set a new value on the bar
116
* @param bar pointer to a bar object
117
* @param value new value
118
*/
119
void lv_bar_set_value(lv_obj_t * bar, int16_t value)
120
{
121
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
122
if(ext->cur_value == value) return;
123
124
ext->cur_value = value > ext->max_value ? ext->max_value : value;
125
ext->cur_value = ext->cur_value < ext->min_value ? ext->min_value : ext->cur_value;
126
lv_obj_invalidate(bar);
127
}
128
129
#if USE_LV_ANIMATION
130
/**
131
* Set a new value with animation on the bar
132
* @param bar pointer to a bar object
133
* @param value new value
134
* @param anim_time animation time in milliseconds
135
*/
136
void lv_bar_set_value_anim(lv_obj_t * bar, int16_t value, uint16_t anim_time)
137
{
138
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
139
if(ext->cur_value == value) return;
140
141
int16_t new_value;
142
new_value = value > ext->max_value ? ext->max_value : value;
143
new_value = new_value < ext->min_value ? ext->min_value : new_value;
144
145
lv_anim_t a;
146
a.var = bar;
147
a.start = ext->cur_value;
148
a.end = new_value;
149
a.fp = (lv_anim_fp_t)lv_bar_set_value;
150
a.path = lv_anim_path_linear;
151
a.end_cb = NULL;
152
a.act_time = 0;
153
a.time = anim_time;
154
a.playback = 0;
155
a.playback_pause = 0;
156
a.repeat = 0;
157
a.repeat_pause = 0;
158
159
lv_anim_create(&a);
160
}
161
#endif
162
163
164
/**
165
* Set minimum and the maximum values of a bar
166
* @param bar pointer to the bar object
167
* @param min minimum value
168
* @param max maximum value
169
*/
170
void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max)
171
{
172
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
173
if(ext->min_value == min && ext->max_value == max) return;
174
175
ext->max_value = max;
176
ext->min_value = min;
177
if(ext->cur_value > max) {
178
ext->cur_value = max;
179
lv_bar_set_value(bar, ext->cur_value);
180
}
181
if(ext->cur_value < min) {
182
ext->cur_value = min;
183
lv_bar_set_value(bar, ext->cur_value);
184
}
185
lv_obj_invalidate(bar);
186
}
187
188
/**
189
* Make the bar symmetric to zero. The indicator will grow from zero instead of the minimum position.
190
* @param bar pointer to a bar object
191
* @param en true: enable disable symmetric behavior; false: disable
192
*/
193
void lv_bar_set_sym(lv_obj_t * bar, bool en)
194
{
195
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
196
ext->sym = en ? 1 : 0;
197
}
198
199
/**
200
* Set a style of a bar
201
* @param bar pointer to a bar object
202
* @param type which style should be set
203
* @param style pointer to a style
204
*/
205
void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, lv_style_t * style)
206
{
207
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
208
209
switch(type) {
210
case LV_BAR_STYLE_BG:
211
lv_obj_set_style(bar, style);
212
break;
213
case LV_BAR_STYLE_INDIC:
214
ext->style_indic = style;
215
lv_obj_refresh_ext_size(bar);
216
break;
217
}
218
}
219
220
/*=====================
221
* Getter functions
222
*====================*/
223
224
/**
225
* Get the value of a bar
226
* @param bar pointer to a bar object
227
* @return the value of the bar
228
*/
229
int16_t lv_bar_get_value(const lv_obj_t * bar)
230
{
231
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
232
return ext->cur_value;
233
}
234
235
/**
236
* Get the minimum value of a bar
237
* @param bar pointer to a bar object
238
* @return the minimum value of the bar
239
*/
240
int16_t lv_bar_get_min_value(const lv_obj_t * bar)
241
{
242
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
243
return ext->min_value;
244
}
245
246
/**
247
* Get the maximum value of a bar
248
* @param bar pointer to a bar object
249
* @return the maximum value of the bar
250
*/
251
int16_t lv_bar_get_max_value(const lv_obj_t * bar)
252
{
253
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
254
return ext->max_value;
255
}
256
257
/**
258
* Get whether the bar is symmetric or not.
259
* @param bar pointer to a bar object
260
* @return true: symmetric is enabled; false: disable
261
*/
262
bool lv_bar_get_sym(lv_obj_t * bar)
263
{
264
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
265
return ext->sym ? true : false;
266
}
267
268
/**
269
* Get a style of a bar
270
* @param bar pointer to a bar object
271
* @param type which style should be get
272
* @return style pointer to a style
273
*/
274
lv_style_t * lv_bar_get_style(const lv_obj_t * bar, lv_bar_style_t type)
275
{
276
lv_style_t * style = NULL;
277
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
278
279
switch(type) {
280
case LV_BAR_STYLE_BG:
281
style = lv_obj_get_style(bar);
282
break;
283
case LV_BAR_STYLE_INDIC:
284
style = ext->style_indic;
285
break;
286
default:
287
style = NULL;
288
break;
289
}
290
291
return style;
292
}
293
294
/**********************
295
* STATIC FUNCTIONS
296
**********************/
297
298
/**
299
* Handle the drawing related tasks of the bars
300
* @param bar pointer to an object
301
* @param mask the object will be drawn only in this area
302
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
303
* (return 'true' if yes)
304
* LV_DESIGN_DRAW: draw the object (always return 'true')
305
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
306
* @param return true/false, depends on 'mode'
307
*/
308
static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode_t mode)
309
{
310
if(mode == LV_DESIGN_COVER_CHK) {
311
/*Return false if the object is not covers the mask area*/
312
return ancestor_design_f(bar, mask, mode);
313
} else if(mode == LV_DESIGN_DRAW_MAIN) {
314
lv_opa_t opa_scale = lv_obj_get_opa_scale(bar);
315
316
#if USE_LV_GROUP == 0
317
ancestor_design_f(bar, mask, mode);
318
#else
319
/* Draw the borders later if the bar is focused.
320
* At value = 100% the indicator can cover to whole background and the focused style won't be visible*/
321
if(lv_obj_is_focused(bar)) {
322
lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG);
323
lv_style_t style_tmp;
324
lv_style_copy(&style_tmp, style_bg);
325
style_tmp.body.border.width = 0;
326
lv_draw_rect(&bar->coords, mask, &style_tmp, opa_scale);
327
} else {
328
ancestor_design_f(bar, mask, mode);
329
}
330
#endif
331
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
332
333
if(ext->cur_value != ext->min_value || ext->sym) {
334
lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
335
lv_area_t indic_area;
336
lv_area_copy(&indic_area, &bar->coords);
337
indic_area.x1 += style_indic->body.padding.hor;
338
indic_area.x2 -= style_indic->body.padding.hor;
339
indic_area.y1 += style_indic->body.padding.ver;
340
indic_area.y2 -= style_indic->body.padding.ver;
341
342
lv_coord_t w = lv_area_get_width(&indic_area);
343
lv_coord_t h = lv_area_get_height(&indic_area);
344
345
if(w >= h) {
346
/*Horizontal*/
347
indic_area.x2 = (int32_t)((int32_t)w * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
348
indic_area.x2 = indic_area.x1 + indic_area.x2 - 1;
349
350
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
351
/*Calculate the coordinate of the zero point*/
352
lv_coord_t zero;
353
zero = indic_area.x1 + (-ext->min_value * w) / (ext->max_value - ext->min_value);
354
if(indic_area.x2 > zero) indic_area.x1 = zero;
355
else {
356
indic_area.x1 = indic_area.x2;
357
indic_area.x2 = zero;
358
}
359
}
360
} else {
361
indic_area.y1 = (int32_t)((int32_t)h * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
362
indic_area.y1 = indic_area.y2 - indic_area.y1 + 1;
363
364
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
365
/*Calculate the coordinate of the zero point*/
366
lv_coord_t zero;
367
zero = indic_area.y2 - (-ext->min_value * h) / (ext->max_value - ext->min_value);
368
if(indic_area.y1 < zero) indic_area.y2 = zero;
369
else {
370
indic_area.y2 = indic_area.y1;
371
indic_area.y1 = zero;
372
}
373
}
374
}
375
376
377
/*Draw the indicator*/
378
lv_draw_rect(&indic_area, mask, style_indic, opa_scale);
379
}
380
} else if(mode == LV_DESIGN_DRAW_POST) {
381
#if USE_LV_GROUP
382
/*Draw the border*/
383
if(lv_obj_is_focused(bar)) {
384
lv_opa_t opa_scale = lv_obj_get_opa_scale(bar);
385
lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG);
386
lv_style_t style_tmp;
387
lv_style_copy(&style_tmp, style_bg);
388
style_tmp.body.empty = 1;
389
style_tmp.body.shadow.width = 0;
390
lv_draw_rect(&bar->coords, mask, &style_tmp, opa_scale);
391
}
392
#endif
393
394
}
395
return true;
396
}
397
398
/**
399
* Signal function of the bar
400
* @param bar pointer to a bar object
401
* @param sign a signal type from lv_signal_t enum
402
* @param param pointer to a signal specific variable
403
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
404
*/
405
static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param)
406
{
407
lv_res_t res;
408
409
/* Include the ancient signal function */
410
res = ancestor_signal(bar, sign, param);
411
if(res != LV_RES_OK) return res;
412
413
if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
414
lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
415
if(style_indic->body.shadow.width > bar->ext_size) bar->ext_size = style_indic->body.shadow.width;
416
} else if(sign == LV_SIGNAL_GET_TYPE) {
417
lv_obj_type_t * buf = param;
418
uint8_t i;
419
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
420
if(buf->type[i] == NULL) break;
421
}
422
buf->type[i] = "lv_bar";
423
}
424
425
return res;
426
}
427
428
429
#endif
430
431