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