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