1 /**
2  * @file lv_demo_high_res_app_ev_charging.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "lv_demo_high_res_private.h"
11 #if LV_USE_DEMO_HIGH_RES
12 
13 #include "../../src/widgets/image/lv_image.h"
14 #include "../../src/widgets/label/lv_label.h"
15 #include "../../src/widgets/span/lv_span_private.h"
16 #include "../../src/widgets/chart/lv_chart.h"
17 #include "../../src/widgets/arc/lv_arc.h"
18 
19 /*********************
20  *      DEFINES
21  *********************/
22 
23 /**********************
24  *      TYPEDEFS
25  **********************/
26 
27 typedef struct {
28     lv_obj_t * percent_label;
29     lv_obj_t * arc;
30     lv_obj_t * spent_label_large;
31     lv_span_t * spent_span_small;
32     lv_obj_t * saved_label;
33     lv_obj_t * charged_label;
34     lv_obj_t * time_to_full_label;
35     lv_obj_t * energy_consumed_label;
36     lv_obj_t * driving_range_label;
37     lv_obj_t * widget3;
38     lv_obj_t * charging_status_label;
39 } anim_state_t;
40 
41 /**********************
42  *  STATIC PROTOTYPES
43  **********************/
44 
45 static void bg_cont_delete_cb(lv_event_t * e);
46 static void base_obj_delete_cb(lv_event_t * e);
47 static void anim_state_apply(anim_state_t * anim_state, int32_t v);
48 static void anim_exec_cb(void * var, int32_t v);
49 static void anim_completed_cb(lv_anim_t * a);
50 static void back_clicked_cb(lv_event_t * e);
51 static void create_widget1(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets);
52 static lv_obj_t * widget2_chart_label(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const char * text);
53 static void create_widget2(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets);
54 static lv_obj_t * create_widget3_info(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const lv_image_dsc_t * img_dsc,
55                                       const char * text, const char * unit);
56 static void create_widget3(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets);
57 static void prepare_default_anim(lv_anim_t * a, int32_t start_v, lv_obj_t * base_obj);
58 static void charging_status_box_clicked_cb(lv_event_t * e);
59 
60 /**********************
61  *  STATIC VARIABLES
62  **********************/
63 
64 static const char start_charging_string[] = "Start charging";
65 static const char stop_charging_string[] = "Stop charging";
66 
67 /**********************
68  *      MACROS
69  **********************/
70 
71 /**********************
72  *   GLOBAL FUNCTIONS
73  **********************/
74 
lv_demo_high_res_app_ev_charging(lv_obj_t * base_obj)75 void lv_demo_high_res_app_ev_charging(lv_obj_t * base_obj)
76 {
77     lv_demo_high_res_ctx_t * c = lv_obj_get_user_data(base_obj);
78 
79     /* background */
80 
81     lv_obj_t * bg = base_obj;
82     lv_obj_remove_style_all(bg);
83     lv_obj_set_size(bg, LV_PCT(100), LV_PCT(100));
84 
85     lv_obj_t * bg_img = lv_image_create(bg);
86     lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_image_src_cb, bg_img,
87                                 &c->imgs[IMG_LIGHT_BG_EV_CHARGING]);
88 
89     lv_obj_t * bg_cont = lv_obj_create(bg);
90     lv_obj_remove_style_all(bg_cont);
91     lv_obj_set_size(bg_cont, LV_PCT(100), LV_PCT(100));
92     lv_obj_set_style_pad_top(bg_cont, c->sz->gap[7], 0);
93     int32_t app_padding = c->sz == &lv_demo_high_res_sizes_all[SIZE_SM] ? c->sz->gap[9] : c->sz->gap[10];
94     lv_obj_set_style_pad_bottom(bg_cont, app_padding, 0);
95     lv_obj_set_style_pad_hor(bg_cont, app_padding, 0);
96     c->ev_charging_bg_cont = bg_cont;
97     lv_obj_add_event_cb(bg_cont, bg_cont_delete_cb, LV_EVENT_DELETE, base_obj);
98 
99     anim_state_t * anim_state = NULL;
100     uint32_t base_obj_event_count = lv_obj_get_event_count(base_obj);
101     for(uint32_t i = 0; i < base_obj_event_count; i++) {
102         lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(base_obj, i);
103         lv_event_cb_t event_cb = lv_event_dsc_get_cb(event_dsc);
104         if(event_cb == base_obj_delete_cb) {
105             anim_state = lv_event_dsc_get_user_data(event_dsc);
106             break;
107         }
108     }
109     if(anim_state == NULL) {
110         anim_state = lv_malloc_zeroed(sizeof(anim_state_t));
111         LV_ASSERT_MALLOC(anim_state);
112         lv_obj_add_event_cb(base_obj, base_obj_delete_cb, LV_EVENT_DELETE, anim_state);
113     }
114     lv_obj_set_user_data(bg_cont, anim_state);
115 
116     /* top margin */
117 
118     lv_obj_t * top_margin = lv_demo_high_res_top_margin_create(bg_cont, 0, true, c);
119 
120     /* app info */
121 
122     lv_obj_t * app_info = lv_demo_high_res_simple_container_create(bg_cont, true, c->sz->gap[4], LV_FLEX_ALIGN_START);
123     lv_obj_align_to(app_info, top_margin, LV_ALIGN_OUT_BOTTOM_LEFT, 0, c->sz->gap[7]);
124 
125     lv_obj_t * back = lv_demo_high_res_simple_container_create(app_info, false, c->sz->gap[2], LV_FLEX_ALIGN_CENTER);
126     lv_obj_add_event_cb(back, back_clicked_cb, LV_EVENT_CLICKED, NULL);
127 
128     lv_obj_t * back_icon = lv_image_create(back);
129     lv_image_set_src(back_icon, c->imgs[IMG_ARROW_LEFT]);
130     lv_obj_add_style(back_icon, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_A8_IMG], 0);
131     lv_obj_add_flag(back_icon, LV_OBJ_FLAG_EVENT_BUBBLE);
132 
133     lv_obj_t * back_label = lv_label_create(back);
134     lv_label_set_text_static(back_label, "Back");
135     lv_obj_set_style_text_opa(back_label, LV_OPA_60, 0);
136     lv_obj_add_style(back_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
137     lv_obj_add_style(back_label, &c->fonts[FONT_HEADING_MD], 0);
138 
139     lv_obj_t * app_label = lv_label_create(app_info);
140     lv_label_set_text_static(app_label, "EV Charging");
141     lv_obj_add_style(app_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
142     lv_obj_add_style(app_label, &c->fonts[FONT_HEADING_LG], 0);
143 
144     /* widgets */
145 
146     int32_t widget_gap_padding = c->sz == &lv_demo_high_res_sizes_all[SIZE_SM] ? c->sz->gap[4] : c->sz->gap[7];
147     lv_obj_t * widgets = lv_demo_high_res_simple_container_create(bg_cont, false, widget_gap_padding, LV_FLEX_ALIGN_END);
148     lv_obj_set_align(widgets, LV_ALIGN_BOTTOM_RIGHT);
149 
150     create_widget1(c, widgets);
151     create_widget2(c, widgets);
152     create_widget3(c, widgets);
153 
154     anim_state_apply(anim_state, lv_subject_get_int(&c->ev_charging_progress));
155 }
156 
157 /**********************
158  *   STATIC FUNCTIONS
159  **********************/
160 
bg_cont_delete_cb(lv_event_t * e)161 static void bg_cont_delete_cb(lv_event_t * e)
162 {
163     lv_obj_t * base_obj = lv_event_get_user_data(e);
164     lv_demo_high_res_ctx_t * c = lv_obj_get_user_data(base_obj);
165     if(!c) return;
166     c->ev_charging_bg_cont = NULL;
167 }
168 
base_obj_delete_cb(lv_event_t * e)169 static void base_obj_delete_cb(lv_event_t * e)
170 {
171     anim_state_t * anim_state = lv_event_get_user_data(e);
172     lv_free(anim_state);
173 }
174 
anim_state_apply(anim_state_t * anim_state,int32_t v)175 static void anim_state_apply(anim_state_t * anim_state, int32_t v)
176 {
177     int32_t v_range_100 = lv_map(v, 0, EV_CHARGING_RANGE_END, 0, 100);
178     lv_label_set_text_fmt(anim_state->percent_label, "%"LV_PRId32"%%", v_range_100);
179     lv_arc_set_value(anim_state->arc, v_range_100);
180 
181     int32_t v_range_spent = lv_map(v, 0, EV_CHARGING_RANGE_END, 96, 176);
182     lv_label_set_text_fmt(anim_state->spent_label_large, "$%"LV_PRId32, v_range_spent);
183     char buf[32];
184     lv_snprintf(buf, sizeof(buf), "$%"LV_PRId32" - ", v_range_spent);
185     lv_span_set_text(anim_state->spent_span_small, buf);
186     lv_label_set_text_fmt(anim_state->saved_label, "$%"LV_PRId32, 340 - v_range_spent);
187 
188     int32_t v_range_charged = lv_map(v, 0, EV_CHARGING_RANGE_END, 640, 683);
189     lv_label_set_text_fmt(anim_state->charged_label, "%"LV_PRId32, v_range_charged);
190 
191     int32_t v_range_time_to_full = lv_map(v, 0, EV_CHARGING_RANGE_END, 72, 0);
192     int32_t whole = v_range_time_to_full / 10;
193     int32_t fraction = v_range_time_to_full % 10;
194     lv_label_set_text_fmt(anim_state->time_to_full_label,
195                           "%"LV_PRId32".%"LV_PRId32, whole, fraction);
196 
197     int32_t v_range_consumed = lv_map(v, 0, EV_CHARGING_RANGE_END, 0, 1012);
198     whole = v_range_consumed / 100;
199     fraction = v_range_consumed % 100;
200     lv_label_set_text_fmt(anim_state->energy_consumed_label,
201                           "%"LV_PRId32".%"LV_PRId32, whole, fraction);
202 
203     int32_t v_range_driving_range = lv_map(v, 0, EV_CHARGING_RANGE_END, 0, 240);
204     lv_label_set_text_fmt(anim_state->driving_range_label, "%"LV_PRId32, v_range_driving_range);
205 }
206 
anim_exec_cb(void * var,int32_t v)207 static void anim_exec_cb(void * var, int32_t v)
208 {
209     lv_obj_t * base_obj = var;
210     lv_demo_high_res_ctx_t * c = lv_obj_get_user_data(base_obj);
211 
212     lv_subject_set_int(&c->ev_charging_progress, v);
213 
214     if(c->ev_charging_bg_cont) {
215         anim_state_t * anim_state = lv_obj_get_user_data(c->ev_charging_bg_cont);
216         anim_state_apply(anim_state, v);
217     }
218 }
219 
anim_completed_cb(lv_anim_t * a)220 static void anim_completed_cb(lv_anim_t * a)
221 {
222     lv_obj_t * base_obj = lv_anim_get_user_data(a);
223     lv_anim_t new_a;
224     prepare_default_anim(&new_a, 0, base_obj);
225     lv_anim_set_delay(&new_a, 1000);
226     lv_anim_set_early_apply(&new_a, false);
227     lv_anim_start(&new_a);
228 }
229 
back_clicked_cb(lv_event_t * e)230 static void back_clicked_cb(lv_event_t * e)
231 {
232     lv_obj_t * back = lv_event_get_target_obj(e);
233 
234     lv_obj_t * base_obj = lv_obj_get_parent(lv_obj_get_parent(lv_obj_get_parent(back)));
235     lv_obj_clean(base_obj);
236     lv_demo_high_res_home(base_obj);
237 }
238 
create_widget1(lv_demo_high_res_ctx_t * c,lv_obj_t * widgets)239 static void create_widget1(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets)
240 {
241     lv_obj_t * bg_cont = lv_obj_get_parent(widgets);
242     anim_state_t * anim_state = lv_obj_get_user_data(bg_cont);
243 
244     lv_obj_t * widget = lv_obj_create(widgets);
245     lv_obj_remove_style_all(widget);
246     lv_obj_set_size(widget, c->sz->card_long_edge, c->sz->card_long_edge);
247     lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_obj_bg_image_src_cb, widget,
248                                 &c->imgs[IMG_LIGHT_WIDGET3_BG]);
249     lv_obj_set_style_pad_all(widget, c->sz->gap[7], 0);
250     lv_obj_set_flex_flow(widget, LV_FLEX_FLOW_COLUMN);
251 
252     lv_obj_t * title_box = lv_demo_high_res_simple_container_create(widget, true, c->sz->gap[1], LV_FLEX_ALIGN_START);
253 
254     lv_obj_t * gas_savings_label = lv_label_create(title_box);
255     lv_label_set_text_static(gas_savings_label, "Gas Savings");
256     lv_obj_add_style(gas_savings_label, &c->fonts[FONT_LABEL_MD], 0);
257     lv_obj_add_style(gas_savings_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
258     lv_obj_t * estimated_values_label = lv_label_create(title_box);
259     lv_label_set_text_static(estimated_values_label, "Estimated values");
260     lv_obj_add_style(estimated_values_label, &c->fonts[FONT_LABEL_SM], 0);
261     lv_obj_add_style(estimated_values_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
262     lv_obj_set_style_text_opa(estimated_values_label, LV_OPA_40, 0);
263 
264     lv_obj_t * saved_box = lv_obj_create(widget);
265     lv_obj_remove_style_all(saved_box);
266     lv_obj_set_width(saved_box, LV_PCT(100));
267     lv_obj_set_flex_grow(saved_box, 1);
268     lv_obj_set_flex_flow(saved_box, LV_FLEX_FLOW_COLUMN);
269     lv_obj_set_style_pad_row(saved_box, c->sz->gap[2], 0);
270     lv_obj_set_flex_align(saved_box, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
271 
272     lv_obj_t * saved_amount_label = lv_label_create(saved_box);
273     lv_obj_add_style(saved_amount_label, &c->fonts[FONT_LABEL_XL], 0);
274     lv_obj_add_style(saved_amount_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
275     anim_state->saved_label = saved_amount_label;
276     lv_obj_t * saved_label = lv_label_create(saved_box);
277     lv_label_set_text_static(saved_label, "Saved");
278     lv_obj_add_style(saved_label, &c->fonts[FONT_LABEL_SM], 0);
279     lv_obj_add_style(saved_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
280 
281     lv_obj_t * spent_box = lv_demo_high_res_simple_container_create(widget, true, c->sz->gap[2], LV_FLEX_ALIGN_START);
282 
283     lv_obj_t * total_spent_span = lv_spangroup_create(spent_box);
284     lv_obj_add_style(total_spent_span, &c->fonts[FONT_LABEL_XS], 0);
285     lv_obj_add_style(total_spent_span, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
286     lv_span_t * total_spent_amount = lv_spangroup_new_span(total_spent_span);
287     anim_state->spent_span_small = total_spent_amount;
288     lv_span_t * total_spent_label = lv_spangroup_new_span(total_spent_span);
289     lv_span_set_text_static(total_spent_label, "Total spent");
290     lv_style_set_text_opa(&total_spent_label->style, LV_OPA_40);
291 
292     lv_obj_t * total_spent_bar = lv_demo_high_res_simple_container_create(spent_box, false, c->sz->gap[1],
293                                                                           LV_FLEX_ALIGN_START);
294     for(int32_t i = 0; i < 11; i++) {
295         lv_obj_t * bar = lv_obj_create(total_spent_bar);
296         lv_obj_set_style_border_width(bar, 0, 0);
297         lv_obj_set_size(bar, c->sz->gap[2], c->sz->gap[8]);
298         lv_obj_set_style_radius(bar, LV_COORD_MAX, 0);
299         lv_obj_set_style_opa(bar, LV_OPA_TRANSP, LV_PART_SCROLLBAR);
300     }
301 
302     lv_obj_t * gas_equivalent_bar = lv_demo_high_res_simple_container_create(spent_box, false, c->sz->gap[1],
303                                                                              LV_FLEX_ALIGN_START);
304     for(int32_t i = 0; i < 26; i++) {
305         lv_obj_t * bar = lv_obj_create(gas_equivalent_bar);
306         lv_obj_set_style_border_width(bar, 0, 0);
307         lv_obj_set_size(bar, c->sz->gap[2], c->sz->gap[8]);
308         lv_obj_set_style_radius(bar, LV_COORD_MAX, 0);
309         lv_obj_set_style_opa(bar, LV_OPA_30, 0);
310         lv_obj_set_style_opa(bar, LV_OPA_TRANSP, LV_PART_SCROLLBAR);
311     }
312 
313     lv_obj_t * gas_equivalent_span = lv_spangroup_create(spent_box);
314     lv_obj_add_style(gas_equivalent_span, &c->fonts[FONT_LABEL_XS], 0);
315     lv_obj_add_style(gas_equivalent_span, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
316     lv_span_t * gas_equivalent_amount = lv_spangroup_new_span(gas_equivalent_span);
317     lv_span_set_text_static(gas_equivalent_amount, "$340 - ");
318     lv_span_t * gas_equivalent_label = lv_spangroup_new_span(gas_equivalent_span);
319     lv_span_set_text_static(gas_equivalent_label, "Gas Equivalent");
320     lv_style_set_text_opa(&gas_equivalent_label->style, LV_OPA_40);
321 }
322 
widget2_chart_label(lv_demo_high_res_ctx_t * c,lv_obj_t * parent,const char * text)323 static lv_obj_t * widget2_chart_label(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const char * text)
324 {
325     lv_obj_t * label = lv_label_create(parent);
326     lv_label_set_text_static(label, text);
327     lv_obj_add_style(label, &c->fonts[FONT_LABEL_XS], 0);
328     lv_obj_add_style(label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
329     lv_obj_set_style_text_opa(label, LV_OPA_40, 0);
330     return label;
331 }
332 
create_widget2(lv_demo_high_res_ctx_t * c,lv_obj_t * widgets)333 static void create_widget2(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets)
334 {
335     lv_obj_t * bg_cont = lv_obj_get_parent(widgets);
336     anim_state_t * anim_state = lv_obj_get_user_data(bg_cont);
337 
338     lv_obj_t * widget = lv_obj_create(widgets);
339     lv_obj_remove_style_all(widget);
340     lv_obj_set_size(widget, c->sz->card_long_edge, c->sz->card_long_edge);
341     lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_obj_bg_image_src_cb, widget,
342                                 &c->imgs[IMG_LIGHT_WIDGET1_BG]);
343     lv_obj_set_style_pad_all(widget, c->sz->gap[7], 0);
344     lv_obj_set_flex_flow(widget, LV_FLEX_FLOW_COLUMN);
345     lv_obj_set_flex_align(widget, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
346     lv_obj_set_style_pad_row(widget, 18, 0);
347 
348     lv_obj_t * title_label = lv_label_create(widget);
349     lv_label_set_text_static(title_label, "Last 14 days");
350     lv_obj_add_style(title_label, &c->fonts[FONT_LABEL_MD], 0);
351     lv_obj_add_style(title_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
352 
353     lv_obj_t * chart_grid = lv_obj_create(widget);
354     lv_obj_remove_style_all(chart_grid);
355     lv_obj_set_size(chart_grid, LV_PCT(100), LV_SIZE_CONTENT);
356     static const int32_t column_dsc[] = {LV_GRID_FR(1), LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
357     static const int32_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
358     lv_obj_set_style_grid_column_dsc_array(chart_grid, column_dsc, 0);
359     lv_obj_set_style_grid_row_dsc_array(chart_grid, row_dsc, 0);
360     lv_obj_set_layout(chart_grid, LV_LAYOUT_GRID);
361     lv_obj_set_style_pad_column(chart_grid, c->sz->gap[3], 0);
362     lv_obj_set_style_pad_row(chart_grid, 5, 0);
363 
364     lv_obj_t * chart = lv_chart_create(chart_grid);
365     lv_obj_set_height(chart, c->sz->small_chart_height);
366     lv_obj_set_style_bg_opa(chart, LV_OPA_TRANSP, 0);
367     lv_obj_set_style_pad_column(chart, c->sz->gap[1], 0);
368     lv_obj_set_style_radius(chart, c->sz->gap[3], LV_PART_ITEMS);
369     lv_obj_set_style_border_width(chart, 2, 0);
370     lv_obj_set_style_border_color(chart, lv_color_black(), 0);
371     lv_obj_set_style_border_side(chart, LV_BORDER_SIDE_BOTTOM, 0);
372     lv_obj_set_style_border_post(chart, true, 0);
373     lv_obj_set_style_radius(chart, 0, 0);
374     lv_obj_set_style_pad_all(chart, 0, 0);
375     lv_obj_set_grid_cell(chart, LV_GRID_ALIGN_STRETCH, 0, 1, LV_GRID_ALIGN_START, 0, 1);
376     lv_chart_set_type(chart, LV_CHART_TYPE_BAR);
377     lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 96);
378     lv_chart_set_div_line_count(chart, 3, 0);
379     lv_obj_set_style_line_opa(chart, LV_OPA_40, 0);
380     lv_obj_set_style_line_color(chart, lv_color_black(), 0);
381     lv_obj_set_style_line_dash_width(chart, 2, 0);
382     lv_obj_set_style_line_dash_gap(chart, 1, 0);
383     lv_chart_series_t * ser = lv_chart_add_series(chart, lv_color_white(), LV_CHART_AXIS_PRIMARY_Y);
384     static const int32_t chart_values[] = {45, 14, 78, 95, 45, 52, 78, 34, 63, 52, 38, 83, 63, 19, LV_CHART_POINT_NONE};
385     lv_chart_set_ext_y_array(chart, ser, (int32_t *)chart_values);
386     lv_chart_set_point_count(chart, sizeof(chart_values) / sizeof(*chart_values));
387     lv_chart_refresh(chart);
388 
389     lv_obj_t * hscale_label_1 = widget2_chart_label(c, chart_grid, "Aug 2");
390     lv_obj_set_grid_cell(hscale_label_1, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 1, 1);
391     lv_obj_t * hscale_label_2 = widget2_chart_label(c, chart_grid, "Sep 1");
392     lv_obj_set_grid_cell(hscale_label_2, LV_GRID_ALIGN_END, 0, 1, LV_GRID_ALIGN_START, 1, 1);
393 
394     lv_obj_t * vscale_label_1 = widget2_chart_label(c, chart_grid, "95\nkWh");
395     lv_obj_set_grid_cell(vscale_label_1, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_START, 0, 1);
396     lv_obj_t * vscale_label_2 = widget2_chart_label(c, chart_grid, "48");
397     lv_obj_set_grid_cell(vscale_label_2, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
398     lv_obj_t * vscale_label_3 = widget2_chart_label(c, chart_grid, "0");
399     lv_obj_set_grid_cell(vscale_label_3, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_END, 0, 1);
400 
401     lv_obj_t * totals_box = lv_obj_create(widget);
402     lv_obj_remove_style_all(totals_box);
403     lv_obj_set_size(totals_box, LV_PCT(100), LV_SIZE_CONTENT);
404     lv_obj_set_flex_flow(totals_box, LV_FLEX_FLOW_ROW);
405     lv_obj_set_flex_grow(totals_box, 1);
406     lv_obj_set_flex_align(totals_box, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_END);
407 
408     lv_obj_t * charged_box = lv_demo_high_res_simple_container_create(totals_box, true, c->sz->gap[2], LV_FLEX_ALIGN_START);
409 
410     lv_obj_t * charged_label = lv_label_create(charged_box);
411     lv_label_set_text_static(charged_label, "Total Charged");
412     lv_obj_add_style(charged_label, &c->fonts[FONT_LABEL_SM], 0);
413     lv_obj_add_style(charged_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
414 
415     lv_obj_t * charged_amount_box = lv_demo_high_res_simple_container_create(charged_box, false, c->sz->gap[1],
416                                                                              LV_FLEX_ALIGN_END);
417 
418     lv_obj_t * charged_amount_number = lv_label_create(charged_amount_box);
419     lv_obj_add_style(charged_amount_number, &c->fonts[FONT_LABEL_XL], 0);
420     lv_obj_add_style(charged_amount_number, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
421     anim_state->charged_label = charged_amount_number;
422 
423     lv_obj_t * charged_amount_kwh = lv_label_create(charged_amount_box);
424     lv_label_set_text_static(charged_amount_kwh, "kWh");
425     lv_obj_add_style(charged_amount_kwh, &c->fonts[FONT_LABEL_SM], 0);
426     lv_obj_add_style(charged_amount_kwh, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
427     lv_obj_set_style_text_opa(charged_amount_kwh, LV_OPA_40, 0);
428 
429     lv_obj_t * spent_box = lv_demo_high_res_simple_container_create(totals_box, true, c->sz->gap[2], LV_FLEX_ALIGN_START);
430     lv_obj_set_width(spent_box, LV_PCT(45));
431 
432     lv_obj_t * spent_label = lv_label_create(spent_box);
433     lv_label_set_text_static(spent_label, "Total Spent");
434     lv_obj_add_style(spent_label, &c->fonts[FONT_LABEL_SM], 0);
435     lv_obj_add_style(spent_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
436 
437     lv_obj_t * spent_amount_number = lv_label_create(spent_box);
438     lv_obj_add_style(spent_amount_number, &c->fonts[FONT_LABEL_XL], 0);
439     lv_obj_add_style(spent_amount_number, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
440     anim_state->spent_label_large = spent_amount_number;
441 }
442 
create_widget3_info(lv_demo_high_res_ctx_t * c,lv_obj_t * parent,const lv_image_dsc_t * img_dsc,const char * text,const char * unit)443 static lv_obj_t * create_widget3_info(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const lv_image_dsc_t * img_dsc,
444                                       const char * text, const char * unit)
445 {
446     lv_obj_t * info = lv_obj_create(parent);
447     lv_obj_remove_style_all(info);
448     lv_obj_set_height(info, LV_SIZE_CONTENT);
449     lv_obj_set_flex_flow(info, LV_FLEX_FLOW_COLUMN);
450     lv_obj_set_style_pad_row(info, c->sz->gap[4], 0);
451     lv_obj_set_flex_grow(info, 1);
452     lv_obj_set_style_bg_color(info, lv_color_white(), 0);
453     lv_obj_set_style_bg_opa(info, 16 * 255 / 100, 0);
454     lv_obj_set_style_radius(info, c->sz->gap[3], 0);
455     lv_obj_set_style_pad_all(info, c->sz->gap[5], 0);
456 
457     lv_obj_t * sub_box1 = lv_demo_high_res_simple_container_create(info, true, c->sz->gap[2], LV_FLEX_ALIGN_START);
458 
459     lv_obj_t * img = lv_image_create(sub_box1);
460     lv_image_set_src(img, img_dsc);
461     lv_obj_set_style_image_recolor_opa(img, LV_OPA_COVER, 0);
462     lv_obj_set_style_image_recolor(img, lv_color_white(), 0);
463 
464     lv_obj_t * label = lv_label_create(sub_box1);
465     lv_label_set_text_static(label, text);
466     lv_obj_add_style(label, &c->fonts[FONT_LABEL_SM], 0);
467     lv_obj_set_style_text_color(label, lv_color_white(), 0);
468 
469     lv_obj_t * sub_box2 = lv_demo_high_res_simple_container_create(info, false, c->sz->gap[1], LV_FLEX_ALIGN_END);
470 
471     lv_obj_t * label_number = lv_label_create(sub_box2);
472     lv_obj_add_style(label_number, &c->fonts[FONT_LABEL_LG], 0);
473     lv_obj_set_style_text_color(label_number, lv_color_white(), 0);
474 
475     lv_obj_t * label_unit = lv_label_create(sub_box2);
476     lv_label_set_text_static(label_unit, unit);
477     lv_obj_add_style(label_unit, &c->fonts[FONT_LABEL_SM], 0);
478     lv_obj_set_style_text_color(label_unit, lv_color_white(), 0);
479     lv_obj_set_style_text_opa(label_unit, LV_OPA_60, 0);
480 
481     return label_number;
482 }
483 
create_widget3(lv_demo_high_res_ctx_t * c,lv_obj_t * widgets)484 static void create_widget3(lv_demo_high_res_ctx_t * c, lv_obj_t * widgets)
485 {
486     lv_obj_t * bg_cont = lv_obj_get_parent(widgets);
487     lv_obj_t * base_obj = lv_obj_get_parent(bg_cont);
488     bool is_animating = NULL != lv_anim_get(base_obj, anim_exec_cb);
489     anim_state_t * anim_state = lv_obj_get_user_data(bg_cont);
490 
491     lv_obj_t * widget = lv_obj_create(widgets);
492     lv_obj_remove_style_all(widget);
493     lv_obj_set_size(widget, c->imgs[IMG_LIGHT_WIDGET5_BG]->header.w, c->imgs[IMG_LIGHT_WIDGET5_BG]->header.h);
494     lv_obj_set_style_pad_all(widget, c->sz->gap[7], 0);
495     lv_obj_set_flex_flow(widget, LV_FLEX_FLOW_COLUMN);
496     lv_obj_set_flex_align(widget, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
497     lv_obj_set_style_bg_image_src(widget, c->imgs[is_animating ? IMG_EV_CHARGING_WIDGET3_BG : IMG_EV_CHARGING_WIDGET3_1_BG],
498                                   0);
499     anim_state->widget3 = widget;
500 
501     lv_obj_t * top_label = lv_label_create(widget);
502     lv_label_set_text_static(top_label, "Charging");
503     lv_obj_set_width(top_label, LV_PCT(100));
504     lv_obj_add_style(top_label, &c->fonts[FONT_LABEL_MD], 0);
505     lv_obj_set_style_text_color(top_label, lv_color_white(), 0);
506 
507     lv_obj_t * arc = lv_arc_create(widget);
508     lv_obj_set_size(arc, c->sz->ev_charging_arc_diameter, c->sz->ev_charging_arc_diameter);
509     lv_arc_set_rotation(arc, 270);
510     lv_arc_set_bg_angles(arc, 0, 360);
511     lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
512     lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
513     lv_obj_set_style_arc_rounded(arc, false, 0);
514     lv_obj_set_style_arc_rounded(arc, false, LV_PART_INDICATOR);
515     lv_obj_set_style_arc_width(arc, 7, 0);
516     lv_obj_set_style_arc_width(arc, 7, LV_PART_INDICATOR);
517     lv_obj_set_style_arc_color(arc, lv_color_white(), 0);
518     lv_obj_set_style_arc_color(arc, lv_color_white(), LV_PART_INDICATOR);
519     lv_obj_set_style_arc_opa(arc, LV_OPA_20, 0);
520     lv_obj_set_flex_flow(arc, LV_FLEX_FLOW_COLUMN);
521     lv_obj_set_flex_align(arc, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
522     lv_obj_set_style_pad_row(arc, c->sz->gap[2], 0);
523     anim_state->arc = arc;
524 
525     lv_obj_t * percent_label = lv_label_create(arc);
526     lv_obj_add_style(percent_label, &c->fonts[FONT_LABEL_2XL], 0);
527     lv_obj_set_style_text_color(percent_label, lv_color_white(), 0);
528     anim_state->percent_label = percent_label;
529 
530     lv_obj_t * charging_status_box = lv_obj_create(arc);
531     lv_obj_remove_style_all(charging_status_box);
532     lv_obj_set_size(charging_status_box, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
533     lv_obj_set_style_pad_hor(charging_status_box, c->sz->gap[6], 0);
534     lv_obj_set_style_pad_ver(charging_status_box, c->sz->gap[3], 0);
535     lv_obj_set_style_bg_color(charging_status_box, lv_color_white(), 0);
536     lv_obj_set_style_bg_opa(charging_status_box, LV_OPA_30, 0);
537     lv_obj_set_style_radius(charging_status_box, LV_COORD_MAX, 0);
538     lv_obj_add_flag(charging_status_box, LV_OBJ_FLAG_CLICKABLE);
539     lv_obj_add_event_cb(charging_status_box, charging_status_box_clicked_cb, LV_EVENT_CLICKED, bg_cont);
540 
541     lv_obj_t * charging_status_label = lv_label_create(charging_status_box);
542     lv_obj_add_style(charging_status_label, &c->fonts[FONT_LABEL_SM], 0);
543     lv_obj_set_style_text_color(charging_status_label, lv_color_white(), 0);
544     lv_obj_center(charging_status_label);
545     lv_label_set_text_static(charging_status_label, is_animating ? stop_charging_string : start_charging_string);
546     anim_state->charging_status_label = charging_status_label;
547 
548     lv_obj_t * info_box = lv_demo_high_res_simple_container_create(widget, false, c->sz->gap[5], LV_FLEX_ALIGN_CENTER);
549     lv_obj_set_width(info_box, LV_PCT(100));
550     anim_state->time_to_full_label = create_widget3_info(c, info_box, c->imgs[IMG_TIME_ICON], "Time to\nfull charge", "h");
551     anim_state->energy_consumed_label = create_widget3_info(c, info_box, c->imgs[IMG_ENERGY_ICON], "Energy\nconsumed",
552                                                             "kW");
553     anim_state->driving_range_label = create_widget3_info(c, info_box, c->imgs[IMG_RANGE_ICON], "Driving\nRange", "km");
554 }
555 
prepare_default_anim(lv_anim_t * a,int32_t start_v,lv_obj_t * base_obj)556 static void prepare_default_anim(lv_anim_t * a, int32_t start_v, lv_obj_t * base_obj)
557 {
558     lv_anim_init(a);
559     lv_anim_set_values(a, start_v, EV_CHARGING_RANGE_END);
560     lv_anim_set_duration(a, (EV_CHARGING_RANGE_END - start_v) * 5);
561     lv_anim_set_exec_cb(a, anim_exec_cb);
562     lv_anim_set_completed_cb(a, anim_completed_cb);
563     lv_anim_set_var(a, base_obj);
564     lv_anim_set_user_data(a, base_obj);
565 }
566 
charging_status_box_clicked_cb(lv_event_t * e)567 static void charging_status_box_clicked_cb(lv_event_t * e)
568 {
569     lv_obj_t * bg_cont = lv_event_get_user_data(e);
570     lv_obj_t * base_obj = lv_obj_get_parent(bg_cont);
571     lv_demo_high_res_ctx_t * c = lv_obj_get_user_data(base_obj);
572     lv_obj_t * charging_status_box = lv_event_get_target_obj(e);
573     lv_obj_t * charging_status_label = lv_obj_get_child(charging_status_box, 0);
574     bool was_charging = lv_label_get_text(charging_status_label) == stop_charging_string;
575     lv_label_set_text_static(charging_status_label, was_charging ? start_charging_string : stop_charging_string);
576 
577     lv_obj_t * widget = lv_obj_get_parent(lv_obj_get_parent(charging_status_box));
578     lv_obj_set_style_bg_image_src(widget, c->imgs[was_charging ? IMG_EV_CHARGING_WIDGET3_1_BG : IMG_EV_CHARGING_WIDGET3_BG],
579                                   0);
580 
581     if(was_charging) {
582         lv_anim_delete(base_obj, anim_exec_cb);
583     }
584     else {
585         int32_t start_v = lv_subject_get_int(&c->ev_charging_progress);
586         if(start_v >= EV_CHARGING_RANGE_END) start_v = 0;
587 
588         lv_anim_t a;
589         prepare_default_anim(&a, start_v, base_obj);
590         lv_anim_start(&a);
591     }
592 }
593 
594 #endif /*LV_USE_DEMO_HIGH_RES*/
595