1 /* This is a small demo of the high-performance GUIX graphics framework. */
2 
3 #include "demo_guix_smart_watch.h"
4 
5 #define MEMORY_POOL_BUFFER_SIZE  DISPLAY_1_X_RESOLUTION * DISPLAY_1_Y_RESOLUTION * 8
6 #define ANIMATION_MIN_SLIDING_DIST 5
7 
8 extern UINT win32_graphics_driver_setup_24xrgb(GX_DISPLAY* display);
9 
10 /* Define prototypes.  */
11 VOID start_guix(VOID);
12 VOID root_window_draw(GX_WINDOW* root);
13 UINT root_window_event_process(GX_WINDOW* window, GX_EVENT* event_ptr);
14 VOID demo_thread_entry(ULONG thread_input);
15 
16 /* Create stack and control block for demo thread. */
17 static TX_THREAD demo_thread;
18 static ULONG demo_thread_stack[1024];
19 
20 /* Define variables.  */
21 GX_WINDOW_ROOT *root;
22 TIME system_time = {12, 9, 4, 15, 35, 0};
23 static INT screen_clock_record_hour = -1;
24 static INT screen_clock_record_minute = -1;
25 static TX_BYTE_POOL memory_pool;
26 static GX_UBYTE memory_pool_buffer[MEMORY_POOL_BUFFER_SIZE];
27 
28 static GX_ANIMATION slide_animation;
29 static GX_EVENT slide_pen_down_event;
30 static GX_BOOL slide_pen_down_valid = GX_FALSE;
31 
32 /* Define screen lists for slide animation. */
33 static GX_WIDGET *container_screen_list[] = {
34     (GX_WIDGET*)&page_1_container_screen,
35     (GX_WIDGET*)&page_2_container_screen,
36     (GX_WIDGET*)&page_3_container_screen,
37     GX_NULL
38 };
39 
40 static GX_WIDGET* page_1_screen_list[] = {
41     (GX_WIDGET*)&message_screen,
42     (GX_WIDGET*)&music_screen,
43     (GX_WIDGET*)&weather_screen,
44     (GX_WIDGET*)&SanDiego_weather_screen,
45     (GX_WIDGET*)&LosAngeles_weather_screen,
46     (GX_WIDGET*)&SanFrancisco_weather_screen,
47     GX_NULL
48 };
49 
50 static GX_WIDGET* page_2_screen_list[] = {
51     (GX_WIDGET*)&clock_1_screen,
52     (GX_WIDGET*)&clock_2_screen,
53     (GX_WIDGET*)&home_screen,
54     (GX_WIDGET*)&clock_3_screen,
55     (GX_WIDGET*)&clock_4_screen,
56     (GX_WIDGET*)&clock_5_screen,
57     GX_NULL
58 };
59 
60 static GX_WIDGET* page_3_screen_list[] = {
61     (GX_WIDGET*)&yoga_screen,
62     (GX_WIDGET*)&ekg_screen,
63     (GX_WIDGET*)&fitness_screen,
64     (GX_WIDGET*)&calories_screen,
65     (GX_WIDGET*)&run_screen,
66     (GX_WIDGET*)&stand_screen,
67     GX_NULL
68 };
69 
70 #ifndef WIN32
71 #define USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
72 #endif
73 
74 #ifdef USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
75 #define ANIMATION_CANVAS_WIDTH (258 * 2)
76 #define ANIMATION_CANVAS_HEIGHT (289 * 2)
77 
78 GX_COLOR animation_canvas_memory[ANIMATION_CANVAS_WIDTH * ANIMATION_CANVAS_HEIGHT];
79 GX_CANVAS              animation_canvas;
80 GX_WINDOW_ROOT         animation_root;
81 #endif
82 
83 /******************************************************************************************/
84 /* Application entry.                                                                     */
85 /******************************************************************************************/
main(int argc,char ** argv)86 int main(int argc, char** argv)
87 {
88     tx_kernel_enter();
89     return(0);
90 }
91 
92 /******************************************************************************************/
93 /* Define memory allocator function.                                                     */
94 /******************************************************************************************/
memory_allocate(ULONG size)95 VOID *memory_allocate(ULONG size)
96 {
97     VOID *memptr;
98 
99     if (tx_byte_allocate(&memory_pool, &memptr, size, TX_NO_WAIT) == TX_SUCCESS)
100     {
101         return memptr;
102     }
103     return NULL;
104 }
105 
106 /******************************************************************************************/
107 /* Define memory de-allocator function.                                                   */
108 /******************************************************************************************/
memory_free(VOID * mem)109 VOID memory_free(VOID *mem)
110 {
111     tx_byte_release(mem);
112 }
113 
114 /******************************************************************************************/
115 /* Define tx_application_define function.                                                 */
116 /******************************************************************************************/
tx_application_define(void * first_unused_memory)117 VOID tx_application_define(void *first_unused_memory)
118 {
119     tx_thread_create(&demo_thread, "Demo Thread", demo_thread_entry, 0,
120         demo_thread_stack, sizeof(demo_thread_stack),
121         GX_SYSTEM_THREAD_PRIORITY + 1,
122         GX_SYSTEM_THREAD_PRIORITY + 1, TX_NO_TIME_SLICE, TX_AUTO_START);
123 }
124 
125 /******************************************************************************************/
126 /* Initiate and run GUIX.                                                                 */
127 /******************************************************************************************/
demo_thread_entry(ULONG thread_input)128 VOID demo_thread_entry(ULONG thread_input)
129 {
130 #ifdef USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
131 GX_RECTANGLE size;
132 #endif
133 
134     /* Create byte pool*/
135     tx_byte_pool_create(&memory_pool, "memory_pol", memory_pool_buffer, MEMORY_POOL_BUFFER_SIZE);
136 
137     /* Initialize GUIX. */
138     gx_system_initialize();
139 
140     /* Assign memory alloc/free functions. */
141     gx_system_memory_allocator_set(memory_allocate, memory_free);
142 
143     /* Configure display. */
144     gx_studio_display_configure(DISPLAY_1, win32_graphics_driver_setup_24xrgb, LANGUAGE_ENGLISH, DISPLAY_1_THEME_1, &root);
145 
146     /* Create main screens. */
147     gx_studio_named_widget_create("main_screen", (GX_WIDGET *)root, GX_NULL);
148     gx_studio_named_widget_create("home_button", (GX_WIDGET*)root, GX_NULL);
149     gx_studio_named_widget_create("page_1_container_screen", GX_NULL, GX_NULL);
150     gx_studio_named_widget_create("page_2_container_screen", (GX_WIDGET *)&main_screen, GX_NULL);
151     gx_studio_named_widget_create("page_3_container_screen", GX_NULL, GX_NULL);
152 
153     /* Create page 1 screens. */
154     gx_studio_named_widget_create("message_screen", GX_NULL, GX_NULL);
155     gx_studio_named_widget_create("music_screen", GX_NULL, GX_NULL);
156     gx_studio_named_widget_create("weather_screen", (GX_WIDGET *)&page_1_container_screen, GX_NULL);
157     gx_studio_named_widget_create("SanDiego_weather_screen", GX_NULL, GX_NULL);
158     gx_studio_named_widget_create("LosAngeles_weather_screen", GX_NULL, GX_NULL);
159     gx_studio_named_widget_create("SanFrancisco_weather_screen", GX_NULL, GX_NULL);
160 
161     /* Create page 2 screens. */
162     gx_studio_named_widget_create("home_screen", (GX_WIDGET *)&page_2_container_screen, GX_NULL);
163     gx_studio_named_widget_create("clock_1_screen", GX_NULL, GX_NULL);
164     gx_studio_named_widget_create("clock_2_screen", GX_NULL, GX_NULL);
165     gx_studio_named_widget_create("clock_3_screen", GX_NULL, GX_NULL);
166     gx_studio_named_widget_create("clock_4_screen", GX_NULL, GX_NULL);
167     gx_studio_named_widget_create("clock_5_screen", GX_NULL, GX_NULL);
168 
169     /* Create page 3 screens.  */
170     gx_studio_named_widget_create("calories_screen", GX_NULL, GX_NULL);
171     gx_studio_named_widget_create("ekg_screen", GX_NULL, GX_NULL);
172     gx_studio_named_widget_create("fitness_screen", (GX_WIDGET *)&page_3_container_screen, GX_NULL);
173     gx_studio_named_widget_create("run_screen", GX_NULL, GX_NULL);
174     gx_studio_named_widget_create("stand_screen", GX_NULL, GX_NULL);
175     gx_studio_named_widget_create("yoga_screen", GX_NULL, GX_NULL);
176     screens_initialize();
177 
178     gx_studio_named_widget_create("screen_slide_parent", GX_NULL, GX_NULL);
179 
180     /* Reset root window draw function.  */
181     gx_widget_draw_set((GX_WIDGET *)root, root_window_draw);
182 
183     /* Reset root window event process function.  */
184     gx_widget_event_process_set((GX_WIDGET *)root, root_window_event_process);
185 
186     /* Create slide animation control block.  */
187     gx_animation_create(&slide_animation);
188 
189 #ifdef USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
190     gx_canvas_create(&animation_canvas, GX_NULL,
191         root->gx_window_root_canvas->gx_canvas_display,
192         GX_CANVAS_SIMPLE,
193         ANIMATION_CANVAS_WIDTH, ANIMATION_CANVAS_HEIGHT,
194         animation_canvas_memory, ANIMATION_CANVAS_WIDTH * ANIMATION_CANVAS_HEIGHT * sizeof(GX_COLOR));
195 
196     gx_utility_rectangle_define(&size, 0, 0, ANIMATION_CANVAS_WIDTH - 1, ANIMATION_CANVAS_HEIGHT - 1);
197     gx_window_root_create(&animation_root, "animation_root", &animation_canvas, GX_STYLE_BORDER_NONE, GX_NULL, &size);
198     gx_canvas_hide(&animation_canvas);
199 
200     gx_canvas_hardware_layer_bind(&animation_canvas, 2);
201 #endif
202 
203     /* Show the root window.  */
204     gx_widget_show(root);
205 
206     /* start GUIX thread */
207     gx_system_start();
208 }
209 
210 /******************************************************************************************/
211 /* Find visible screen from screen list.                                                  */
212 /******************************************************************************************/
find_visible_screen_of_screen_list(GX_WIDGET ** screen_list)213 static GX_WIDGET *find_visible_screen_of_screen_list(GX_WIDGET **screen_list)
214 {
215     INT index = 0;
216     while (screen_list[index])
217     {
218         if (screen_list[index]->gx_widget_status & GX_STATUS_VISIBLE)
219         {
220             return screen_list[index];
221         }
222 
223         index++;
224     }
225 
226     return GX_NULL;
227 }
228 
229 /******************************************************************************************/
230 /* Get page list by specified container screen.                                           */
231 /******************************************************************************************/
get_page_screen_list(GX_WIDGET * screen_container)232 static GX_WIDGET **get_page_screen_list(GX_WIDGET *screen_container)
233 {
234     GX_WIDGET** page_list = GX_NULL;
235 
236     switch (screen_container->gx_widget_id)
237     {
238     case ID_PAGE_1_CONTAINER_SCREEN:
239         page_list = page_1_screen_list;
240         break;
241 
242     case ID_PAGE_2_CONTAINER_SCREEN:
243         page_list = page_2_screen_list;
244         break;
245 
246     case ID_PAGE_3_CONTAINER_SCREEN:
247         page_list = page_3_screen_list;
248         break;
249     }
250 
251     return page_list;
252 }
253 
254 /******************************************************************************************/
255 /* Get screen container by specified screen.                                              */
256 /******************************************************************************************/
get_screen_container(GX_WIDGET * screen)257 static GX_WIDGET *get_screen_container(GX_WIDGET* screen)
258 {
259     GX_WIDGET** screen_list;
260     INT index = 0;
261     INT j;
262 
263     while (container_screen_list[index])
264     {
265         screen_list = get_page_screen_list(container_screen_list[index]);
266         j = 0;
267 
268         while (screen_list[j])
269         {
270             if (screen_list[j] == screen)
271             {
272                 return container_screen_list[index];
273             }
274             j++;
275         }
276         index++;
277     }
278 
279     return GX_NULL;
280 }
281 
282 /******************************************************************************************/
283 /* Enable vertical slide animation.                                                       */
284 /******************************************************************************************/
enable_vertical_slide_animation()285 static GX_BOOL enable_vertical_slide_animation()
286 {
287     GX_ANIMATION_INFO slide_animation_info;
288 
289     memset(&slide_animation_info, 0, sizeof(GX_ANIMATION_INFO));
290     slide_animation_info.gx_animation_parent = (GX_WIDGET*)&main_screen;
291     slide_animation_info.gx_animation_style = GX_ANIMATION_SCREEN_DRAG | GX_ANIMATION_VERTICAL | GX_ANIMATION_WRAP | GX_ANIMATION_BLOCK_MOVE;
292     slide_animation_info.gx_animation_id = SCREEN_DRAG_ANIMATION_ID;
293     slide_animation_info.gx_animation_frame_interval = 20 / GX_SYSTEM_TIMER_MS;
294     slide_animation_info.gx_animation_slide_screen_list = container_screen_list;
295     slide_animation_info.gx_animation_start_alpha = 255;
296     slide_animation_info.gx_animation_end_alpha = 255;
297 #ifdef USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
298     gx_animation_canvas_define(&slide_animation, &animation_canvas);
299 #endif
300 
301     gx_animation_drag_enable(&slide_animation, (GX_WIDGET*)&main_screen, &slide_animation_info);
302 
303     return GX_SUCCESS;
304 }
305 
306 /******************************************************************************************/
307 /* Enable horizontal slide animation.                                                     */
308 /******************************************************************************************/
enable_horizontal_slide_animation()309 static GX_BOOL enable_horizontal_slide_animation()
310 {
311     GX_ANIMATION_INFO slide_animation_info;
312 
313     memset(&slide_animation_info, 0, sizeof(GX_ANIMATION_INFO));
314 
315     /* Find the visible page container screen.  */
316     slide_animation_info.gx_animation_parent = find_visible_screen_of_screen_list(container_screen_list);
317 
318     if (slide_animation_info.gx_animation_parent)
319     {
320         slide_animation_info.gx_animation_style = GX_ANIMATION_SCREEN_DRAG | GX_ANIMATION_HORIZONTAL | GX_ANIMATION_WRAP | GX_ANIMATION_BLOCK_MOVE;
321         slide_animation_info.gx_animation_id = SCREEN_DRAG_ANIMATION_ID;
322         slide_animation_info.gx_animation_frame_interval = 20 / GX_SYSTEM_TIMER_MS;
323         slide_animation_info.gx_animation_slide_screen_list = get_page_screen_list(slide_animation_info.gx_animation_parent);
324         slide_animation_info.gx_animation_start_alpha = 255;
325         slide_animation_info.gx_animation_end_alpha = 255;
326 #ifdef USE_CANVAS_FOR_SCREEN_SLIDE_ANIMATION
327         gx_animation_canvas_define(&slide_animation, &animation_canvas);
328 #endif
329 
330         /* Enable slide animation for the visible page container screen.  */
331         gx_animation_drag_enable(&slide_animation, slide_animation_info.gx_animation_parent, &slide_animation_info);
332 
333         return GX_SUCCESS;
334     }
335 
336     return GX_FALSE;
337 }
338 
339 /******************************************************************************************/
340 /* Update system clock.                                                                   */
341 /******************************************************************************************/
system_clock_update()342 static VOID system_clock_update()
343 {
344 #ifdef WIN32
345     SYSTEMTIME local_time;
346     GetLocalTime(&local_time);
347 
348     system_time.month = local_time.wMonth;
349     system_time.day = local_time.wDay;
350     system_time.day_of_week = local_time.wDayOfWeek;
351     system_time.hour = local_time.wHour;
352     system_time.minute = local_time.wMinute;
353     system_time.second = local_time.wSecond;
354 #else
355     system_time.second++;
356     if (system_time.second >= 60)
357     {
358         system_time.second = 0;
359         system_time.minute++;
360 
361         if (system_time.minute >= 60)
362         {
363             system_time.minute = 0;
364         }
365     }
366 #endif
367 }
368 
369 /******************************************************************************************/
370 /* Clear time record of screens.                                                          */
371 /******************************************************************************************/
clear_screen_clock_record()372 VOID clear_screen_clock_record()
373 {
374     screen_clock_record_hour = -1;
375     screen_clock_record_minute = -1;
376 }
377 
378 /******************************************************************************************/
379 /* Update screen clock.                                                                   */
380 /******************************************************************************************/
screen_clock_update(GX_NUMERIC_PROMPT * hour,GX_NUMERIC_PROMPT * minute,GX_PROMPT * second)381 VOID screen_clock_update(GX_NUMERIC_PROMPT *hour, GX_NUMERIC_PROMPT *minute, GX_PROMPT *second)
382 {
383     GX_RESOURCE_ID text_color_id;
384 
385     if (screen_clock_record_hour != system_time.hour)
386     {
387         gx_numeric_prompt_value_set(hour, system_time.hour);
388         screen_clock_record_hour = system_time.hour;
389     }
390 
391     if (screen_clock_record_minute != system_time.minute)
392     {
393         gx_numeric_prompt_value_set(minute, system_time.minute);
394         screen_clock_record_minute = system_time.minute;
395     }
396 
397     if (second)
398     {
399         if (system_time.second & 0x1)
400         {
401             text_color_id = GX_COLOR_ID_WHITE;
402         }
403         else
404         {
405             text_color_id = GX_COLOR_ID_GRAY;
406         }
407 
408         gx_prompt_text_color_set(second, text_color_id, text_color_id, text_color_id);
409     }
410 }
411 
412 /******************************************************************************************/
413 /* Send event to current screen.                                                          */
414 /******************************************************************************************/
send_event_to_current_screen(INT event_type)415 static VOID send_event_to_current_screen(INT event_type)
416 {
417     GX_EVENT myevent;
418     GX_WIDGET *parent;
419 
420     /* Find visible screen container.  */
421     parent = find_visible_screen_of_screen_list(container_screen_list);
422 
423     /* Find visible screen.  */
424     parent = find_visible_screen_of_screen_list(get_page_screen_list(parent));
425 
426     if (parent)
427     {
428         memset(&myevent, 0, sizeof(GX_EVENT));
429         myevent.gx_event_type = event_type;
430         myevent.gx_event_target = parent;
431         parent->gx_widget_event_process_function(parent, &myevent);
432     }
433 }
434 
435 /******************************************************************************************/
436 /* Slide to home screen.                                                                  */
437 /******************************************************************************************/
slide_to_home_screen()438 static VOID slide_to_home_screen()
439 {
440     GX_WIDGET *current_screen_container;
441     GX_WIDGET *target_screen_container;
442     GX_WIDGET *current_screen;
443     GX_WIDGET *target_screen = (GX_WIDGET *)&home_screen;
444 
445     /* Find the visible page container screen.  */
446     current_screen_container = find_visible_screen_of_screen_list(container_screen_list);
447 
448     /* Find visible screen.  */
449     current_screen = find_visible_screen_of_screen_list(get_page_screen_list(current_screen_container));
450 
451     if (current_screen == target_screen)
452     {
453         return;
454     }
455 
456     target_screen_container = get_screen_container(target_screen);
457 
458     if (current_screen_container == target_screen_container)
459     {
460         page_screen_slide(current_screen, target_screen);
461     }
462     else
463     {
464         container_screen_slide(current_screen, target_screen);
465     }
466 }
467 
468 /******************************************************************************************/
469 /* Start animation to slide from current screen to the specified screen of the same page. */
470 /******************************************************************************************/
page_screen_slide(GX_WIDGET * current_screen,GX_WIDGET * target_screen)471 VOID page_screen_slide(GX_WIDGET *current_screen, GX_WIDGET *target_screen)
472 {
473     GX_WIDGET *screen_container;
474     GX_WIDGET **screen_list;
475     INT current_screen_index = 0;
476     INT target_screen_index = 0;
477     INT index = 0;
478     GX_ANIMATION *animation;
479     GX_ANIMATION_INFO animation_info;
480     GX_RECTANGLE *parent_size;
481     GX_RECTANGLE size;
482     INT width;
483     INT distance;
484 
485     if (slide_animation.gx_animation_status != GX_ANIMATION_IDLE)
486     {
487         return;
488     }
489 
490     send_event_to_current_screen(USER_EVENT_ANIMATION_STOP);
491 
492     /* Find the visible page container screen.  */
493     screen_container = find_visible_screen_of_screen_list(container_screen_list);
494 
495     /* Find screen list for the visible screen container.  */
496     screen_list = get_page_screen_list(screen_container);
497 
498     while (screen_list[index])
499     {
500         if (screen_list[index] == current_screen)
501         {
502             current_screen_index = index;
503         }
504         else if (screen_list[index] == target_screen)
505         {
506             target_screen_index = index;
507         }
508 
509         index++;
510     }
511 
512     parent_size = &screen_container->gx_widget_size;
513     width = parent_size->gx_rectangle_right - parent_size->gx_rectangle_left + 1;
514     distance = width * (target_screen_index - current_screen_index);
515 
516     size = *parent_size;
517 
518     if (target_screen_index > current_screen_index)
519     {
520         size.gx_rectangle_right = size.gx_rectangle_left + distance + width - 1;
521     }
522     else
523     {
524         size.gx_rectangle_left = size.gx_rectangle_right + distance - width + 1;
525     }
526 
527     gx_widget_resize(&screen_slide_parent, &size);
528 
529     memset(&animation_info, 0, sizeof(GX_ANIMATION_INFO));
530     animation_info.gx_animation_frame_interval = 1;
531     animation_info.gx_animation_id = SCREEN_SLIDE_ANIMATION_ID;
532     animation_info.gx_animation_steps = 300 / GX_SYSTEM_TIMER_MS;
533     animation_info.gx_animation_start_alpha = 255;
534     animation_info.gx_animation_end_alpha = 255;
535     animation_info.gx_animation_parent = screen_container;
536     animation_info.gx_animation_target = (GX_WIDGET *)&screen_slide_parent;
537     animation_info.gx_animation_start_position.gx_point_x = size.gx_rectangle_left;
538     animation_info.gx_animation_start_position.gx_point_y = size.gx_rectangle_top;
539     animation_info.gx_animation_end_position.gx_point_x= size.gx_rectangle_left - distance;
540     animation_info.gx_animation_end_position.gx_point_y = size.gx_rectangle_top;
541     animation_info.gx_animation_style = GX_ANIMATION_TRANSLATE | GX_ANIMATION_BLOCK_MOVE;
542 
543     index = current_screen_index;
544     while (1)
545     {
546         gx_widget_attach(&screen_slide_parent, screen_list[index]);
547 
548         size.gx_rectangle_left = parent_size->gx_rectangle_left + (width * (index - current_screen_index));
549         size.gx_rectangle_right = size.gx_rectangle_left + width - 1;
550         gx_widget_resize(screen_list[index], &size);
551 
552         if (index == target_screen_index)
553         {
554             break;
555         }
556 
557         if (current_screen_index < target_screen_index)
558         {
559             index++;
560         }
561         else
562         {
563             index--;
564         }
565     }
566 
567     if (gx_system_animation_get(&animation) == GX_SUCCESS)
568     {
569         gx_animation_start(animation, &animation_info);
570     }
571 }
572 
573 /******************************************************************************************/
574 /* Start animation to slide from current screen to the specified screen of another page.  */
575 /******************************************************************************************/
container_screen_slide(GX_WIDGET * current_screen,GX_WIDGET * target_screen)576 VOID container_screen_slide(GX_WIDGET* current_screen, GX_WIDGET* target_screen)
577 {
578     GX_WIDGET *current_screen_container;
579     GX_WIDGET *target_screen_container;
580     GX_WIDGET **screen_list;
581     INT current_screen_index = 0;
582     INT target_screen_index = 0;
583     INT index = 0;
584     GX_ANIMATION* animation;
585     GX_ANIMATION_INFO animation_info;
586     GX_RECTANGLE *parent_size;
587     GX_RECTANGLE size;
588     INT height;
589     INT distance;
590     GX_WIDGET* child = GX_NULL;
591 
592     if (slide_animation.gx_animation_status != GX_ANIMATION_IDLE)
593     {
594         return;
595     }
596 
597     send_event_to_current_screen(USER_EVENT_ANIMATION_STOP);
598 
599     /* Find the visible page container screen.  */
600     current_screen_container = find_visible_screen_of_screen_list(container_screen_list);
601     target_screen_container = get_screen_container(target_screen);
602 
603     gx_widget_first_child_get(target_screen_container, &child);
604     if (child != target_screen)
605     {
606         gx_widget_detach(child);
607         gx_widget_attach(target_screen_container, target_screen);
608         gx_widget_shift(target_screen,
609             target_screen_container->gx_widget_size.gx_rectangle_left - target_screen->gx_widget_size.gx_rectangle_left,
610             target_screen_container->gx_widget_size.gx_rectangle_top - target_screen->gx_widget_size.gx_rectangle_top, GX_FALSE);
611     }
612 
613     /* Find screen list for the visible screen container.  */
614     screen_list = container_screen_list;
615 
616     while (screen_list[index])
617     {
618         if (screen_list[index] == current_screen_container)
619         {
620             current_screen_index = index;
621         }
622         else if (screen_list[index] == target_screen_container)
623         {
624             target_screen_index = index;
625         }
626 
627         index++;
628     }
629 
630     parent_size = &main_screen.gx_widget_size;
631     height = parent_size->gx_rectangle_bottom - parent_size->gx_rectangle_top + 1;
632     distance = height * (target_screen_index - current_screen_index);
633 
634     size = *parent_size;
635 
636     if (target_screen_index > current_screen_index)
637     {
638         size.gx_rectangle_bottom = size.gx_rectangle_top + distance + height - 1;
639     }
640     else
641     {
642         size.gx_rectangle_top = size.gx_rectangle_bottom + distance - height + 1;
643     }
644 
645     gx_widget_resize(&screen_slide_parent, &size);
646 
647     memset(&animation_info, 0, sizeof(GX_ANIMATION_INFO));
648     animation_info.gx_animation_frame_interval = 1;
649     animation_info.gx_animation_id = SCREEN_SLIDE_ANIMATION_ID;
650     animation_info.gx_animation_steps = 300 / GX_SYSTEM_TIMER_MS;
651     animation_info.gx_animation_start_alpha = 255;
652     animation_info.gx_animation_end_alpha = 255;
653     animation_info.gx_animation_parent = (GX_WIDGET *)&main_screen;
654     animation_info.gx_animation_target = (GX_WIDGET *)&screen_slide_parent;
655     animation_info.gx_animation_start_position.gx_point_x = size.gx_rectangle_left;
656     animation_info.gx_animation_start_position.gx_point_y = size.gx_rectangle_top;
657     animation_info.gx_animation_end_position.gx_point_x = size.gx_rectangle_left;
658     animation_info.gx_animation_end_position.gx_point_y = size.gx_rectangle_top - distance;
659     animation_info.gx_animation_style = GX_ANIMATION_TRANSLATE | GX_ANIMATION_BLOCK_MOVE;
660 
661     index = current_screen_index;
662 
663     while(1)
664     {
665         gx_widget_attach(&screen_slide_parent, screen_list[index]);
666 
667         size.gx_rectangle_top = parent_size->gx_rectangle_top + (height * (index - current_screen_index));
668         size.gx_rectangle_bottom = size.gx_rectangle_top + height - 1;
669         gx_widget_resize(screen_list[index], &size);
670 
671         if (index == target_screen_index)
672         {
673             break;
674         }
675 
676         if (current_screen_index < target_screen_index)
677         {
678             index++;
679         }
680         else
681         {
682             index--;
683         }
684     }
685 
686     if (gx_system_animation_get(&animation) == GX_SUCCESS)
687     {
688         gx_animation_start(animation, &animation_info);
689     }
690 }
691 
692 /******************************************************************************************/
693 /* Override the default drawing of the home button.                                       */
694 /******************************************************************************************/
root_home_button_draw(GX_PIXELMAP_BUTTON * widget)695 VOID root_home_button_draw(GX_PIXELMAP_BUTTON* widget)
696 {
697     if (widget->gx_widget_style & GX_STYLE_BUTTON_PUSHED)
698     {
699         gx_pixelmap_button_draw(widget);
700     }
701 }
702 
703 /******************************************************************************************/
704 /* Override the default drawing of the root window.                                       */
705 /******************************************************************************************/
root_window_draw(GX_WINDOW * root)706 VOID root_window_draw(GX_WINDOW* root)
707 {
708     GX_PIXELMAP* map = GX_NULL;
709 
710     /* Call default root window draw. */
711     gx_window_draw(root);
712 
713     gx_context_pixelmap_get(GX_PIXELMAP_ID_MICROSOFT_AZURE_LOGO, &map);
714 
715     if (map)
716     {
717         /* Draw logo. */
718         gx_canvas_pixelmap_draw(15, 15, map);
719     }
720 
721     gx_context_pixelmap_get(GX_PIXELMAP_ID_WATCH, &map);
722 
723     if (map)
724     {
725         /* Draw smart watch frame.  */
726         gx_context_fill_color_set(GX_COLOR_ID_WHITE);
727         gx_canvas_pixelmap_draw((DISPLAY_1_X_RESOLUTION - map->gx_pixelmap_width) >> 1, 0, map);
728     }
729 }
730 
731 /******************************************************************************************/
732 /* Override the default event processing of the root window to handle signals from my     */
733 /* child widgets.                                                                         */
734 /******************************************************************************************/
root_window_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)735 UINT root_window_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
736 {
737     switch (event_ptr->gx_event_type)
738     {
739     case GX_SIGNAL(ID_HOME_BUTTON, GX_EVENT_CLICKED):
740         slide_to_home_screen();
741         break;
742 
743     default:
744         return gx_window_root_event_process((GX_WINDOW_ROOT*)window, event_ptr);
745     }
746 
747     return 0;
748 }
749 
750 /******************************************************************************************/
751 /* Override the default event processing of the "main_screen" to handle signals from my   */
752 /* child widgets.                                                                         */
753 /******************************************************************************************/
main_screen_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)754 UINT main_screen_event_process(GX_WINDOW* window, GX_EVENT* event_ptr)
755 {
756     UINT status = GX_SUCCESS;
757     INT horizontal_dist;
758     INT vertical_dist;
759     GX_WIDGET *parent;
760 
761     switch (event_ptr->gx_event_type)
762     {
763     case GX_EVENT_SHOW:
764 
765         /* Update system time. */
766         system_clock_update();
767 
768         /* Start a timer to update time. */
769         gx_system_timer_start(window, SYSTEM_CLOCK_TIMER_ID, GX_TICKS_SECOND, GX_TICKS_SECOND);
770 
771         status = gx_window_event_process(window, event_ptr);
772 
773         if(home_screen.gx_widget_status & GX_STATUS_VISIBLE)
774         {
775             gx_sprite_start(&home_screen.home_screen_sprite, 0);
776         }
777         break;
778 
779     case GX_EVENT_TIMER:
780         if (event_ptr->gx_event_payload.gx_event_timer_id == SYSTEM_CLOCK_TIMER_ID)
781         {
782             system_clock_update();
783             music_play_progress_update();
784         }
785         break;
786 
787     case GX_EVENT_PEN_DOWN:
788         if (slide_animation.gx_animation_status == GX_ANIMATION_IDLE)
789         {
790             /* Reserve pen down event for later use.  */
791             slide_pen_down_event = *event_ptr;
792             slide_pen_down_valid = GX_TRUE;
793         }
794         break;
795 
796     case GX_EVENT_PEN_DRAG:
797         if (slide_animation.gx_animation_status == GX_ANIMATION_IDLE && slide_pen_down_valid)
798         {
799             horizontal_dist = GX_ABS(slide_pen_down_event.gx_event_payload.gx_event_pointdata.gx_point_x - event_ptr->gx_event_payload.gx_event_pointdata.gx_point_x);
800             vertical_dist = GX_ABS(slide_pen_down_event.gx_event_payload.gx_event_pointdata.gx_point_y - event_ptr->gx_event_payload.gx_event_pointdata.gx_point_y);
801 
802             if ((horizontal_dist > ANIMATION_MIN_SLIDING_DIST) || vertical_dist > ANIMATION_MIN_SLIDING_DIST)
803             {
804                 if (horizontal_dist > vertical_dist)
805                 {
806                     /* Horizontal slide direction. */
807                     status = enable_horizontal_slide_animation();
808                 }
809                 else
810                 {
811                     /* Vertical slide direction. */
812                     status = enable_vertical_slide_animation();
813                 }
814 
815                 if (status == GX_SUCCESS)
816                 {
817                     send_event_to_current_screen(USER_EVENT_ANIMATION_STOP);
818 
819                     parent = slide_animation.gx_animation_info.gx_animation_parent;
820 
821                     /* Pass pen down and pen drag event to slide animation parent to process sliding animation.  */
822                     parent->gx_widget_event_process_function(parent, &slide_pen_down_event);
823                     parent->gx_widget_event_process_function(parent, event_ptr);
824                 }
825             }
826         }
827         break;
828 
829     case GX_EVENT_ANIMATION_COMPLETE:
830         if (event_ptr->gx_event_sender == SCREEN_DRAG_ANIMATION_ID)
831         {
832             /* Disable slide animation.  */
833             gx_animation_drag_disable(&slide_animation, slide_animation.gx_animation_info.gx_animation_parent);
834 
835             send_event_to_current_screen(USER_EVENT_ANIMATION_START);
836         }
837         else if (event_ptr->gx_event_sender == SCREEN_SLIDE_ANIMATION_ID)
838         {
839             gx_widget_attach(screen_slide_parent.gx_widget_parent, screen_slide_parent.gx_widget_last_child);
840             parent = screen_slide_parent.gx_widget_first_child;
841             while (parent)
842             {
843                 gx_widget_detach(parent);
844                 parent = parent->gx_widget_next;
845             }
846             gx_widget_detach(&screen_slide_parent);
847             send_event_to_current_screen(USER_EVENT_ANIMATION_START);
848         }
849         break;
850 
851     case GX_EVENT_PEN_UP:
852         if (slide_animation.gx_animation_status == GX_ANIMATION_IDLE)
853         {
854             /* Disable slide animation.  */
855             gx_animation_drag_disable(&slide_animation, slide_animation.gx_animation_info.gx_animation_parent);
856         }
857         slide_pen_down_valid = GX_FALSE;
858         break;
859 
860     default:
861         return gx_window_event_process((GX_WINDOW*)window, event_ptr);
862     }
863 
864     return status;
865 }