1 /**
2 * @file lv_demo_smartwatch_list.c
3 * App list screen layout & functions. Contains a list of apps that can be opened/launched.
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_demo_smartwatch.h"
10 #if LV_USE_DEMO_SMARTWATCH
11
12 #include "lv_demo_smartwatch_private.h"
13 #include "lv_demo_smartwatch_list.h"
14
15 /*********************
16 * DEFINES
17 *********************/
18
19 #define MAX_APPS 15
20
21 /**********************
22 * TYPEDEFS
23 **********************/
24
25 /**
26 * app object details
27 */
28 typedef struct {
29 const char * name; /**< name of the app. Shown on the app list */
30 const lv_image_dsc_t * icon; /**< icon of the app. Shown on the app list */
31 lv_obj_t ** main; /**< root object of the app */
32 } app_t;
33
34 /**********************
35 * STATIC PROTOTYPES
36 **********************/
37 static void create_screen_list(void);
38 static void add_external_app(const char * app_name, int index, const void * img);
39 static void add_app_list(const char * app_name, int index, const void * img);
40
41 static void app_list_clicked_event_cb(lv_event_t * e);
42 static void app_list_clicked_external_event_cb(lv_event_t * e);
43
44 /**********************
45 * STATIC VARIABLES
46 **********************/
47 static lv_obj_t * app_list_screen;
48 static lv_obj_t * app_list;
49
50 static app_t apps[MAX_APPS];
51 static uint32_t num_apps;
52
53 /**********************
54 * MACROS
55 **********************/
56
57 /**********************
58 * GLOBAL FUNCTIONS
59 **********************/
60
lv_demo_smartwatch_register_app_cb(const char * name,const lv_image_dsc_t * icon,lv_obj_t ** entry)61 void lv_demo_smartwatch_register_app_cb(const char * name, const lv_image_dsc_t * icon, lv_obj_t ** entry)
62 {
63 if(num_apps >= MAX_APPS) {
64 LV_LOG_WARN("Maximum apps reached. Cannot add more apps");
65 return;
66 }
67 apps[num_apps].name = name;
68 apps[num_apps].icon = icon;
69 apps[num_apps].main = entry;
70 add_external_app(name, num_apps, icon);
71 num_apps++;
72 }
73
lv_demo_smartwatch_list_create(lv_obj_t * parent)74 void lv_demo_smartwatch_list_create(lv_obj_t * parent)
75 {
76
77 app_list_screen = lv_tileview_add_tile(parent, 1, 1, LV_DIR_LEFT);
78 lv_obj_remove_flag(app_list_screen, LV_OBJ_FLAG_SCROLLABLE);
79 lv_obj_set_style_bg_color(app_list_screen, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
80 lv_obj_set_style_bg_opa(app_list_screen, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
81
82 create_screen_list();
83
84 }
85
lv_demo_smartwatch_list_load(lv_screen_load_anim_t anim_type,uint32_t time,uint32_t delay)86 void lv_demo_smartwatch_list_load(lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay)
87 {
88 lv_demo_smartwatch_home_load(anim_type, time, delay);
89 }
90
lv_demo_smartwatch_app_close(void)91 void lv_demo_smartwatch_app_close(void)
92 {
93 lv_demo_smartwatch_home_load(LV_SCR_LOAD_ANIM_MOVE_RIGHT, 500, 0);
94 }
95
lv_demo_smartwatch_app_list_loading(void)96 void lv_demo_smartwatch_app_list_loading(void)
97 {
98 lv_obj_scroll_by(app_list, 0, 1, LV_ANIM_OFF);
99 lv_obj_scroll_by(app_list, 0, -1, LV_ANIM_OFF);
100
101 lv_obj_set_scrollbar_mode(app_list, lv_demo_smartwatch_get_scrollbar_mode());
102 }
103
lv_demo_smartwatch_get_tile_app_list(void)104 lv_obj_t * lv_demo_smartwatch_get_tile_app_list(void)
105 {
106 return app_list_screen;
107 }
108
109
110 /**********************
111 * STATIC FUNCTIONS
112 **********************/
113
app_list_clicked_external_event_cb(lv_event_t * e)114 static void app_list_clicked_external_event_cb(lv_event_t * e)
115 {
116 lv_event_code_t event_code = lv_event_get_code(e);
117
118 uint32_t index = (uint32_t)(intptr_t)lv_event_get_user_data(e);
119
120 lv_obj_t * active_screen = lv_screen_active();
121 if(active_screen != lv_demo_smartwatch_get_tileview()) {
122 /* event was triggered but the current screen is no longer active */
123 return;
124 }
125 if(event_code == LV_EVENT_CLICKED) {
126 if(index >= num_apps) {
127 LV_LOG_WARN("Clicked app out of bounds. Cannot launch app");
128 lv_demo_smartwatch_show_dialog("App Error", "App list out of bounds");
129 return;
130 }
131 if(*apps[index].main == NULL) {
132 LV_LOG_WARN("Main object of clicked app is null. Cannot launch app");
133 lv_demo_smartwatch_show_dialog("App Error", "Unable to load main object");
134 return;
135 }
136 lv_screen_load_anim(*apps[index].main, LV_SCR_LOAD_ANIM_MOVE_LEFT, 500, 0, false);
137 }
138 }
139
app_list_clicked_event_cb(lv_event_t * e)140 static void app_list_clicked_event_cb(lv_event_t * e)
141 {
142 lv_obj_t * active_screen = lv_screen_active();
143 if(active_screen != lv_demo_smartwatch_get_tileview()) {
144 /* event was triggered but the current screen is no longer active */
145 return;
146 }
147 int index = (int)(intptr_t)lv_event_get_user_data(e);
148 lv_demo_smartwatch_set_load_app_list(true); /* flag was open from app list */
149 switch(index) {
150 case 0:
151 lv_demo_smartwatch_notifications_load(LV_SCR_LOAD_ANIM_MOVE_LEFT, 500, 0);
152 break;
153 case 1:
154 lv_demo_smartwatch_weather_load(LV_SCR_LOAD_ANIM_MOVE_LEFT, 500, 0);
155 break;
156 case 2:
157 lv_demo_smartwatch_settings_load(LV_SCR_LOAD_ANIM_MOVE_LEFT, 500, 0);
158 break;
159 case 3:
160 lv_demo_smartwatch_qr_load(LV_SCR_LOAD_ANIM_MOVE_BOTTOM, 500, 0);
161 break;
162 }
163 }
164
add_external_app(const char * app_name,int index,const void * img)165 static void add_external_app(const char * app_name, int index, const void * img)
166 {
167 lv_obj_t * panel = lv_obj_create(app_list);
168 lv_obj_set_width(panel, lv_pct(90));
169 lv_obj_set_height(panel, 64);
170 lv_obj_set_align(panel, LV_ALIGN_CENTER);
171 lv_obj_remove_flag(panel, LV_OBJ_FLAG_SCROLLABLE);
172 lv_obj_set_style_radius(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
173 lv_obj_set_style_bg_color(panel, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
174 lv_obj_set_style_bg_opa(panel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
175 lv_obj_set_style_border_color(panel, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
176 lv_obj_set_style_border_opa(panel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
177 lv_obj_set_style_border_width(panel, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
178 lv_obj_set_style_border_side(panel, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN | LV_STATE_DEFAULT);
179 lv_obj_set_style_pad_left(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
180 lv_obj_set_style_pad_right(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
181 lv_obj_set_style_pad_top(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
182 lv_obj_set_style_pad_bottom(panel, 5, LV_PART_MAIN | LV_STATE_DEFAULT);
183
184 lv_obj_t * icon = lv_image_create(panel);
185 lv_image_set_src(icon, img);
186 lv_obj_set_width(icon, LV_SIZE_CONTENT);
187 lv_obj_set_height(icon, LV_SIZE_CONTENT);
188 lv_obj_set_align(icon, LV_ALIGN_LEFT_MID);
189 lv_obj_add_flag(icon, LV_OBJ_FLAG_ADV_HITTEST);
190 lv_obj_remove_flag(icon, LV_OBJ_FLAG_SCROLLABLE);
191 lv_image_set_scale(icon, 150);
192
193 lv_obj_t * label = lv_label_create(panel);
194 lv_obj_set_width(label, LV_SIZE_CONTENT);
195 lv_obj_set_height(label, LV_SIZE_CONTENT);
196 lv_obj_set_x(label, 60);
197 lv_obj_set_y(label, 3);
198 lv_obj_set_align(label, LV_ALIGN_LEFT_MID);
199 lv_label_set_text(label, app_name);
200 lv_label_set_long_mode(label, LV_LABEL_LONG_CLIP);
201 lv_obj_set_style_text_font(label, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT);
202
203 lv_obj_add_event_cb(panel, app_list_clicked_external_event_cb, LV_EVENT_CLICKED, (void *)(intptr_t)index);
204 }
205
add_app_list(const char * app_name,int index,const void * img)206 static void add_app_list(const char * app_name, int index, const void * img)
207 {
208 lv_obj_t * panel = lv_obj_create(app_list);
209 lv_obj_set_width(panel, lv_pct(90));
210 lv_obj_set_height(panel, 64);
211 lv_obj_set_align(panel, LV_ALIGN_CENTER);
212 lv_obj_remove_flag(panel, LV_OBJ_FLAG_SCROLLABLE);
213 lv_obj_set_style_radius(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
214 lv_obj_set_style_bg_color(panel, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
215 lv_obj_set_style_bg_opa(panel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
216 lv_obj_set_style_border_color(panel, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
217 lv_obj_set_style_border_opa(panel, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
218 lv_obj_set_style_border_width(panel, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
219 lv_obj_set_style_border_side(panel, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN | LV_STATE_DEFAULT);
220 lv_obj_set_style_pad_left(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
221 lv_obj_set_style_pad_right(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
222 lv_obj_set_style_pad_top(panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
223 lv_obj_set_style_pad_bottom(panel, 5, LV_PART_MAIN | LV_STATE_DEFAULT);
224
225 lv_obj_t * icon = lv_image_create(panel);
226 lv_image_set_src(icon, img);
227 lv_obj_set_width(icon, LV_SIZE_CONTENT);
228 lv_obj_set_height(icon, LV_SIZE_CONTENT);
229 lv_obj_set_align(icon, LV_ALIGN_LEFT_MID);
230 lv_obj_add_flag(icon, LV_OBJ_FLAG_ADV_HITTEST);
231 lv_obj_remove_flag(icon, LV_OBJ_FLAG_SCROLLABLE);
232 lv_image_set_scale(icon, 150);
233
234 lv_obj_t * label = lv_label_create(panel);
235 lv_obj_set_width(label, LV_SIZE_CONTENT);
236 lv_obj_set_height(label, LV_SIZE_CONTENT);
237 lv_obj_set_x(label, 60);
238 lv_obj_set_y(label, 3);
239 lv_obj_set_align(label, LV_ALIGN_LEFT_MID);
240 lv_label_set_text(label, app_name);
241 lv_label_set_long_mode(label, LV_LABEL_LONG_CLIP);
242 lv_obj_set_style_text_font(label, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT);
243
244 lv_obj_add_event_cb(panel, app_list_clicked_event_cb, LV_EVENT_CLICKED, (void *)(intptr_t)index);
245 }
246
create_screen_list(void)247 static void create_screen_list(void)
248 {
249 app_list = lv_obj_create(app_list_screen);
250 lv_obj_set_width(app_list, lv_pct(100));
251 lv_obj_set_height(app_list, lv_pct(100));
252 lv_obj_set_align(app_list, LV_ALIGN_TOP_MID);
253 lv_obj_set_flex_flow(app_list, LV_FLEX_FLOW_COLUMN);
254 lv_obj_set_flex_align(app_list, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
255 lv_obj_set_scrollbar_mode(app_list, LV_SCROLLBAR_MODE_OFF);
256 lv_obj_set_scroll_dir(app_list, LV_DIR_VER);
257 lv_obj_set_style_radius(app_list, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
258 lv_obj_set_style_bg_color(app_list, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
259 lv_obj_set_style_bg_opa(app_list, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
260 lv_obj_set_style_border_width(app_list, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
261 lv_obj_set_style_pad_left(app_list, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
262 lv_obj_set_style_pad_right(app_list, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
263 lv_obj_set_style_pad_top(app_list, 50, LV_PART_MAIN | LV_STATE_DEFAULT);
264 lv_obj_set_style_pad_bottom(app_list, 70, LV_PART_MAIN | LV_STATE_DEFAULT);
265
266 add_app_list("Notifications", 0, &img_notifications_app_icon);
267 add_app_list("Weather", 1, &img_weather_app_icon);
268 add_app_list("QR Codes", 3, &img_qr_icon);
269 add_app_list("Settings", 2, &img_general_settings_icon);
270
271 lv_obj_add_event_cb(app_list, lv_demo_smartwatch_scroll_event, LV_EVENT_ALL, NULL);
272 }
273
274 #endif /*LV_USE_DEMO_SMARTWATCH*/
275