1 /**
2 * @file lv_demo_high_res_home.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
17 /*********************
18 * DEFINES
19 *********************/
20
21 /**********************
22 * TYPEDEFS
23 **********************/
24
25 typedef void (*app_cb_t)(lv_obj_t * base_obj);
26
27 /**********************
28 * STATIC PROTOTYPES
29 **********************/
30
31 static void theme_observer_accent_span_cb(lv_observer_t * observer, lv_subject_t * subject);
32 static void app_card_click_cb(lv_event_t * e);
33 static void app_card_create(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const char * text,
34 const lv_image_dsc_t * icon_img_dsc, app_cb_t app_cb);
35 static void set_light_theme_event_cb(lv_event_t * e);
36 static void set_dark_theme_event_cb(lv_event_t * e);
37 static void time_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
38 static void date_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
39 static void hi_lo_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
40
41 /**********************
42 * STATIC VARIABLES
43 **********************/
44
45 /**********************
46 * MACROS
47 **********************/
48
49 /**********************
50 * GLOBAL FUNCTIONS
51 **********************/
52
lv_demo_high_res_home(lv_obj_t * base_obj)53 void lv_demo_high_res_home(lv_obj_t * base_obj)
54 {
55 lv_demo_high_res_ctx_t * c = lv_obj_get_user_data(base_obj);
56
57 /* background */
58
59 lv_obj_t * bg = base_obj;
60 lv_obj_remove_style_all(bg);
61 lv_obj_set_size(bg, LV_PCT(100), LV_PCT(100));
62
63 lv_obj_t * bg_img = lv_image_create(bg);
64 lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_image_src_cb, bg_img, &c->imgs[IMG_LIGHT_BG_HOME]);
65
66 lv_obj_t * bg_cont = lv_obj_create(bg);
67 lv_obj_remove_style_all(bg_cont);
68 lv_obj_set_size(bg_cont, LV_PCT(100), LV_PCT(100));
69 lv_obj_set_flex_flow(bg_cont, LV_FLEX_FLOW_COLUMN);
70 lv_obj_set_style_pad_top(bg_cont, c->sz->gap[7], 0);
71
72 /* top margin */
73
74 lv_demo_high_res_top_margin_create(bg_cont,
75 c->sz == &lv_demo_high_res_sizes_all[SIZE_SM] ? c->sz->gap[9] : c->sz->gap[10], false, c);
76
77 /* info area */
78
79 lv_obj_t * info_area = lv_obj_create(bg_cont);
80 lv_obj_remove_style_all(info_area);
81 lv_obj_set_width(info_area, LV_PCT(100));
82 lv_obj_set_style_pad_left(info_area, c->sz->gap[10], 0);
83 lv_obj_set_style_pad_right(info_area, c->sz->gap[10], 0);
84 lv_obj_set_flex_grow(info_area, 1);
85 lv_obj_set_flex_flow(info_area, LV_FLEX_FLOW_ROW);
86 lv_obj_set_flex_align(info_area, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
87
88 lv_obj_t * date_and_time = lv_demo_high_res_simple_container_create(info_area, true, c->sz->gap[4],
89 LV_FLEX_ALIGN_START);
90
91 lv_obj_t * date = lv_spangroup_create(date_and_time);
92 lv_obj_add_style(date, &c->fonts[FONT_HEADING_MD], 0);
93 lv_obj_add_style(date, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
94 lv_spangroup_new_span(date);
95 lv_span_t * day_and_month = lv_spangroup_new_span(date);
96 lv_subject_add_observer_obj(&c->th, theme_observer_accent_span_cb, date, day_and_month);
97 lv_subject_add_observer_obj(&c->subject_groups.date.group, date_observer_cb, date, c);
98
99 lv_obj_t * time = lv_spangroup_create(date_and_time);
100 lv_obj_add_style(time, &c->fonts[FONT_HEADING_XXL], 0);
101 lv_obj_add_style(time, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
102 lv_spangroup_new_span(time);
103 lv_span_t * minute = lv_spangroup_new_span(time);
104 lv_subject_add_observer_obj(&c->th, theme_observer_accent_span_cb, time, minute);
105 lv_subject_add_observer_obj(&c->subject_groups.time.group, time_observer_cb, time, c);
106
107 lv_obj_t * weather = lv_demo_high_res_simple_container_create(info_area, false, 50, LV_FLEX_ALIGN_END);
108 lv_obj_t * weather_left = lv_demo_high_res_simple_container_create(weather, true, c->sz->gap[2], LV_FLEX_ALIGN_START);
109
110 lv_obj_t * weather_img = lv_image_create(weather_left);
111 lv_image_set_src(weather_img, c->imgs[IMG_WEATHER]);
112 lv_obj_add_style(weather_img, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_A8_IMG], 0);
113
114 lv_obj_t * weather_left_bottom = lv_demo_high_res_simple_container_create(weather_left, true, c->sz->gap[3],
115 LV_FLEX_ALIGN_START);
116
117 lv_obj_t * weather_label = lv_label_create(weather_left_bottom);
118 lv_label_set_text_static(weather_label, "Cloudy");
119 lv_obj_add_style(weather_label, &c->styles[STYLE_COLOR_ACCENT][STYLE_TYPE_TEXT], 0);
120 lv_obj_add_style(weather_label, &c->fonts[FONT_LABEL_MD], 0);
121
122 lv_obj_t * weather_hi_lo_label = lv_label_create(weather_left_bottom);
123 lv_obj_add_style(weather_hi_lo_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
124 lv_obj_add_style(weather_hi_lo_label, &c->fonts[FONT_LABEL_MD], 0);
125 lv_subject_add_observer_obj(&c->temperature_units_are_celsius, hi_lo_observer_cb, weather_hi_lo_label, NULL);
126
127 lv_obj_t * weather_right = lv_demo_high_res_simple_container_create(weather, true, c->sz->gap[2], LV_FLEX_ALIGN_CENTER);
128
129 lv_obj_t * weather_temperature_label = lv_label_create(weather_right);
130 lv_obj_add_style(weather_temperature_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
131 lv_obj_add_style(weather_temperature_label, &c->fonts[FONT_HEADING_XL], 0);
132 lv_demo_high_res_label_bind_temperature(weather_temperature_label, &c->api.subjects.temperature_outdoor, c);
133
134 lv_obj_t * weather_temperature_location_label = lv_label_create(weather_right);
135 lv_label_set_text_static(weather_temperature_location_label, "Outdoor");
136 lv_obj_add_style(weather_temperature_location_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
137 lv_obj_add_style(weather_temperature_location_label, &c->fonts[FONT_LABEL_MD], 0);
138
139 /* apps */
140
141 lv_obj_t * apps = lv_obj_create(bg_cont);
142 lv_obj_remove_style_all(apps);
143 lv_obj_set_size(apps, LV_PCT(100), LV_SIZE_CONTENT);
144 lv_obj_set_style_pad_bottom(apps, c->sz->gap[10], 0);
145 lv_obj_set_style_pad_left(apps, c->sz->gap[10], 0);
146 lv_obj_set_style_pad_right(apps, c->sz->gap[10], 0);
147 lv_obj_set_style_border_side(apps, LV_BORDER_SIDE_BOTTOM, 0);
148 lv_obj_set_style_border_color(apps, lv_color_black(), 0);
149 lv_obj_set_style_border_width(apps, 1, 0);
150 lv_obj_set_style_border_opa(apps, 8 * 255 / 100, 0);
151 lv_obj_set_flex_flow(apps, LV_FLEX_FLOW_ROW);
152 lv_obj_set_style_pad_column(apps, c->sz->gap[6], 0);
153 app_card_create(c, apps, "EV Charging", c->imgs[IMG_EV_CHARGING_APP_ICON], lv_demo_high_res_app_ev_charging);
154 app_card_create(c, apps, "Smart Home", c->imgs[IMG_SMART_HOME_APP_ICON], lv_demo_high_res_app_smart_home);
155 app_card_create(c, apps, "Smart Meter", c->imgs[IMG_SMART_METER_APP_ICON], lv_demo_high_res_app_smart_meter);
156 app_card_create(c, apps, "Thermostat", c->imgs[IMG_THERMOSTAT_APP_ICON], lv_demo_high_res_app_thermostat);
157 app_card_create(c, apps, "About", c->imgs[IMG_ABOUT_APP_ICON], lv_demo_high_res_app_about);
158
159 /* bottom_margin */
160
161 lv_obj_t * bottom_margin = lv_obj_create(bg_cont);
162 lv_obj_remove_style_all(bottom_margin);
163 lv_obj_set_size(bottom_margin, LV_PCT(100), c->sz->home_bottom_margin_height);
164 lv_obj_set_flex_flow(bottom_margin, LV_FLEX_FLOW_ROW);
165 lv_obj_set_flex_align(bottom_margin, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
166 lv_obj_set_style_pad_left(bottom_margin, c->sz->gap[10], 0);
167 lv_obj_set_style_pad_right(bottom_margin, c->sz->gap[10], 0);
168
169 lv_obj_t * logo = lv_image_create(bottom_margin);
170 lv_obj_set_height(logo, c->sz->icon[1]);
171 lv_image_set_inner_align(logo, LV_IMAGE_ALIGN_STRETCH);
172 lv_image_set_src(logo, c->logo_path);
173 int32_t scale = lv_image_get_scale_y(logo);
174 lv_image_set_inner_align(logo, LV_IMAGE_ALIGN_DEFAULT);
175 lv_image_set_scale(logo, scale);
176
177 lv_obj_t * theme_selector = lv_demo_high_res_simple_container_create(bottom_margin, false, c->sz->gap[4],
178 LV_FLEX_ALIGN_CENTER);
179 lv_obj_set_style_pad_all(theme_selector, c->sz->gap[1], 0); /* for icon outline */
180 lv_obj_set_style_pad_right(bottom_margin, lv_obj_get_style_pad_right(bottom_margin, 0) - c->sz->gap[1],
181 0); /* compensate parent `bottom_margin` */
182
183 lv_obj_t * theme_label = lv_label_create(theme_selector);
184 lv_label_set_text_static(theme_label, "Theme:");
185 lv_obj_add_style(theme_label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
186 lv_obj_add_style(theme_label, &c->fonts[FONT_LABEL_SM], 0);
187
188 lv_obj_t * light_theme_icon = lv_image_create(theme_selector);
189 lv_obj_set_style_radius(light_theme_icon, LV_COORD_MAX, 0);
190 lv_obj_set_style_outline_pad(light_theme_icon, -1, 0); /* FIXME */
191 if(((const lv_demo_high_res_theme_t *) lv_subject_get_pointer(&c->th)) == &lv_demo_high_res_theme_light)
192 lv_obj_set_style_outline_width(light_theme_icon, 2, 0);
193 lv_obj_add_style(light_theme_icon, &c->styles[STYLE_COLOR_ACCENT][STYLE_TYPE_OBJ], 0);
194 lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_image_src_cb, light_theme_icon,
195 &c->imgs[IMG_LIGHT_LIGHT_THEME_ICON]);
196
197 lv_obj_t * dark_theme_icon = lv_image_create(theme_selector);
198 lv_obj_set_style_radius(dark_theme_icon, LV_COORD_MAX, 0);
199 lv_obj_set_style_outline_pad(dark_theme_icon, -1, 0); /* FIXME */
200 if(((const lv_demo_high_res_theme_t *) lv_subject_get_pointer(&c->th)) == &lv_demo_high_res_theme_dark)
201 lv_obj_set_style_outline_width(dark_theme_icon, 2, 0);
202 lv_obj_add_style(dark_theme_icon, &c->styles[STYLE_COLOR_ACCENT][STYLE_TYPE_OBJ], 0);
203 lv_subject_add_observer_obj(&c->th, lv_demo_high_res_theme_observer_image_src_cb, dark_theme_icon,
204 &c->imgs[IMG_LIGHT_DARK_THEME_ICON]);
205
206 lv_obj_add_flag(light_theme_icon, LV_OBJ_FLAG_CLICKABLE);
207 lv_obj_set_user_data(light_theme_icon, dark_theme_icon);
208 lv_obj_add_event_cb(light_theme_icon, set_light_theme_event_cb, LV_EVENT_CLICKED, c);
209 lv_obj_add_flag(dark_theme_icon, LV_OBJ_FLAG_CLICKABLE);
210 lv_obj_set_user_data(dark_theme_icon, light_theme_icon);
211 lv_obj_add_event_cb(dark_theme_icon, set_dark_theme_event_cb, LV_EVENT_CLICKED, c);
212 }
213
214 /**********************
215 * STATIC FUNCTIONS
216 **********************/
217
theme_observer_accent_span_cb(lv_observer_t * observer,lv_subject_t * subject)218 static void theme_observer_accent_span_cb(lv_observer_t * observer, lv_subject_t * subject)
219 {
220 lv_span_t * span = lv_observer_get_user_data(observer);
221 const lv_demo_high_res_theme_t * th = lv_subject_get_pointer(subject);
222
223 lv_style_set_text_color(&span->style, th->accent);
224 }
225
app_card_click_cb(lv_event_t * e)226 static void app_card_click_cb(lv_event_t * e)
227 {
228 lv_obj_t * app_card = lv_event_get_target_obj(e);
229 app_cb_t app_cb = (app_cb_t)((uintptr_t)lv_event_get_user_data(e));
230
231 lv_obj_t * base_obj = lv_obj_get_parent(lv_obj_get_parent(lv_obj_get_parent(app_card)));
232 lv_obj_clean(base_obj);
233 app_cb(base_obj);
234 }
235
app_card_create(lv_demo_high_res_ctx_t * c,lv_obj_t * parent,const char * text,const lv_image_dsc_t * icon_img_dsc,app_cb_t app_cb)236 static void app_card_create(lv_demo_high_res_ctx_t * c, lv_obj_t * parent, const char * text,
237 const lv_image_dsc_t * icon_img_dsc, app_cb_t app_cb)
238 {
239 if(icon_img_dsc == NULL) return;
240 lv_obj_t * app_card = lv_obj_create(parent);
241 lv_obj_remove_style_all(app_card);
242 lv_obj_set_size(app_card, c->sz->card_long_edge, c->sz->card_short_edge);
243 lv_obj_set_style_radius(app_card, c->sz->gap[6], 0);
244 lv_obj_set_style_bg_opa(app_card, 16 * 255 / 100, 0);
245 lv_obj_set_style_pad_all(app_card, c->sz->gap[7], 0);
246 lv_obj_add_style(app_card, &c->styles[STYLE_COLOR_ACCENT][STYLE_TYPE_OBJ], 0);
247 lv_obj_add_event_cb(app_card, app_card_click_cb, LV_EVENT_CLICKED, (void *)((lv_uintptr_t)app_cb));
248
249 lv_obj_t * label = lv_label_create(app_card);
250 lv_label_set_text(label, text);
251 lv_obj_set_align(label, LV_ALIGN_BOTTOM_LEFT);
252 lv_obj_add_style(label, &c->styles[STYLE_COLOR_BASE][STYLE_TYPE_TEXT], 0);
253 lv_obj_add_style(label, &c->fonts[FONT_LABEL_MD], 0);
254
255 lv_obj_t * icon = lv_image_create(app_card);
256 lv_obj_set_size(icon, icon_img_dsc->header.w, icon_img_dsc->header.h);
257 lv_image_set_inner_align(icon, LV_IMAGE_ALIGN_CENTER);
258 lv_image_set_src(icon, icon_img_dsc);
259 lv_obj_set_style_bg_opa(icon, LV_OPA_COVER, 0);
260 lv_obj_set_style_bg_color(icon, lv_color_white(), 0);
261 lv_obj_set_style_radius(icon, LV_COORD_MAX, 0);
262 lv_obj_add_style(icon, &c->styles[STYLE_COLOR_ACCENT][STYLE_TYPE_A8_IMG], 0);
263 lv_obj_add_flag(icon, LV_OBJ_FLAG_EVENT_BUBBLE);
264 }
265
set_light_theme_event_cb(lv_event_t * e)266 static void set_light_theme_event_cb(lv_event_t * e)
267 {
268 lv_obj_t * obj = lv_event_get_target_obj(e);
269 lv_obj_set_style_outline_width(obj, 2, 0);
270 obj = lv_obj_get_user_data(obj);
271 lv_obj_set_style_outline_width(obj, 0, 0);
272
273 lv_demo_high_res_ctx_t * c = lv_event_get_user_data(e);
274
275 const lv_demo_high_res_theme_t * th = lv_subject_get_pointer(&c->th);
276 if(th == &lv_demo_high_res_theme_light) return;
277
278 lv_subject_set_pointer(&c->th, (void *)&lv_demo_high_res_theme_light);
279 }
280
set_dark_theme_event_cb(lv_event_t * e)281 static void set_dark_theme_event_cb(lv_event_t * e)
282 {
283 lv_obj_t * obj = lv_event_get_target_obj(e);
284 lv_obj_set_style_outline_width(obj, 2, 0);
285 obj = lv_obj_get_user_data(obj);
286 lv_obj_set_style_outline_width(obj, 0, 0);
287
288 lv_demo_high_res_ctx_t * c = lv_event_get_user_data(e);
289
290 const lv_demo_high_res_theme_t * th = lv_subject_get_pointer(&c->th);
291 if(th == &lv_demo_high_res_theme_dark) return;
292
293 lv_subject_set_pointer(&c->th, (void *)&lv_demo_high_res_theme_dark);
294 }
295
time_observer_cb(lv_observer_t * observer,lv_subject_t * subject)296 static void time_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
297 {
298 LV_UNUSED(subject);
299 lv_obj_t * spangroup = lv_observer_get_target_obj(observer);
300 lv_demo_high_res_ctx_t * c = lv_observer_get_user_data(observer);
301
302 char buf[16];
303
304 lv_snprintf(buf, sizeof(buf), "%02"LV_PRId32, lv_subject_get_int(&c->api.subjects.hour));
305 lv_span_set_text(lv_spangroup_get_child(spangroup, 0), buf);
306
307 lv_snprintf(buf, sizeof(buf), ":%02"LV_PRId32, lv_subject_get_int(&c->api.subjects.minute));
308 lv_span_set_text(lv_spangroup_get_child(spangroup, 1), buf);
309 }
310
date_observer_cb(lv_observer_t * observer,lv_subject_t * subject)311 static void date_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
312 {
313 LV_UNUSED(subject);
314 lv_obj_t * spangroup = lv_observer_get_target_obj(observer);
315 lv_demo_high_res_ctx_t * c = lv_observer_get_user_data(observer);
316
317 char buf[32];
318
319 lv_snprintf(buf, sizeof(buf), "%s, ", lv_subject_get_pointer(&c->api.subjects.week_day_name));
320 lv_span_set_text(lv_spangroup_get_child(spangroup, 0), buf);
321 lv_snprintf(buf, sizeof(buf), "%"PRId32" %s", lv_subject_get_int(&c->api.subjects.month_day),
322 lv_subject_get_pointer(&c->api.subjects.month_name));
323 lv_span_set_text(lv_spangroup_get_child(spangroup, 1), buf);
324 }
325
hi_lo_observer_cb(lv_observer_t * observer,lv_subject_t * subject)326 static void hi_lo_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
327 {
328 lv_obj_t * weather_hi_lo_label = lv_observer_get_target_obj(observer);
329 lv_label_set_text_static(weather_hi_lo_label,
330 lv_subject_get_int(subject) ? "H: 19\xc2\xb0 L: 10\xc2\xb0" : "H: 66.2\xc2\xb0 L: 50\xc2\xb0");
331 }
332
333 #endif /*LV_USE_DEMO_HIGH_RES*/
334