1 /* This is a small demo of the high-performance GUIX graphics framework. */
2 
3 #include "demo_guix_home_automation.h"
4 
5 /* Define the ThreadX demo thread control block and stack.  */
6 TX_BYTE_POOL       memory_pool;
7 
8 #define CLOCK_TIMER         20
9 
10 #define SCRATCHPAD_PIXELS (DISPLAY_1_X_RESOLUTION * DISPLAY_1_Y_RESOLUTION * 2)
11 
12 /* Define memory for memory pool. */
13 GX_COLOR           scratchpad[SCRATCHPAD_PIXELS];
14 
15 GX_WINDOW_ROOT    *root;
16 
17 /* Define prototypes.   */
18 VOID  guix_setup(void);
19 extern UINT win32_graphics_driver_setup_24xrgb(GX_DISPLAY *display);
20 VOID clock_update();
21 VOID fade_in_home_window();
22 VOID fade_out_home_window();
23 VOID toggle_screen(GX_WIDGET *new_screen);
24 
25 /* Define animation variable for screen slide animation.  */
26 GX_ANIMATION slide_animation;
27 
28 /* Define GX_PIXELMAP type variable to receive pixelmap data decoded from background jpeg. */
29 GX_PIXELMAP main_screen_bg;
30 
31 /* Define application varaible to record current screen and overrall energy used today. */
32 APP_INFO app_info = { (GX_WIDGET *)&main_screen.main_screen_home_window, GX_NULL, 8746594 };
33 
34 const GX_CHAR *day_names[7] = {
35     "Sunday",
36     "Monday",
37     "Tuesday",
38     "Wednesday",
39     "Thursday",
40     "Friday",
41     "Saturday"
42 };
43 
44 const GX_CHAR *month_names[12] = {
45     "Jan",
46     "Feb",
47     "Mar",
48     "Apr",
49     "May",
50     "Jun",
51     "Jul",
52     "Aug",
53     "Sep",
54     "Oct",
55     "Nov",
56     "Dec"
57 };
58 
59 /******************************************************************************************/
60 /* Application entry.                                                                     */
61 /******************************************************************************************/
main(int argc,char ** argv)62 int main(int argc, char ** argv)
63 {
64     tx_kernel_enter();
65     return(0);
66 }
67 
68 /******************************************************************************************/
69 /* Define memory allocator function.                                                     */
70 /******************************************************************************************/
memory_allocate(ULONG size)71 VOID *memory_allocate(ULONG size)
72 {
73     VOID *memptr;
74 
75     if (tx_byte_allocate(&memory_pool, &memptr, size, TX_NO_WAIT) == TX_SUCCESS)
76     {
77         return memptr;
78     }
79     return NULL;
80 }
81 
82 /******************************************************************************************/
83 /* Define memory de-allocator function.                                                   */
84 /******************************************************************************************/
memory_free(VOID * mem)85 void memory_free(VOID *mem)
86 {
87     tx_byte_release(mem);
88 }
89 
90 /******************************************************************************************/
91 /* Define tx_application_define function.                                                 */
92 /******************************************************************************************/
tx_application_define(void * first_unused_memory)93 VOID tx_application_define(void *first_unused_memory)
94 {
95 
96     /* create byte pool. */
97     tx_byte_pool_create(&memory_pool, "scratchpad", scratchpad,
98         SCRATCHPAD_PIXELS * sizeof(GX_COLOR));
99 
100     guix_setup();
101 }
102 
103 /******************************************************************************************/
104 /* Initiate and run GUIX.                                                                 */
105 /******************************************************************************************/
guix_setup()106 VOID  guix_setup()
107 {
108     /* Initialize GUIX. */
109     gx_system_initialize();
110 
111     /* install our memory allocator and de-allocator */
112     gx_system_memory_allocator_set(memory_allocate, memory_free);
113 
114     /* Configure display. */
115     gx_studio_display_configure(DISPLAY_1, win32_graphics_driver_setup_24xrgb,
116         LANGUAGE_ENGLISH, DISPLAY_1_THEME_1, &root);
117 
118     /* Create the main screen and attach it to root window. */
119     gx_studio_named_widget_create("main_screen", (GX_WIDGET *)root, GX_NULL);
120 
121     /* The screen control blocks in this case are statically defined, so
122        we can create them all at startup. It is also an option to dynamically
123        allocate the control block memory.
124     */
125 
126     gx_studio_named_widget_create("lights_screen", GX_NULL, GX_NULL);
127     gx_studio_named_widget_create("lights_page_1", GX_NULL, GX_NULL);
128     gx_studio_named_widget_create("lights_page_2", GX_NULL, GX_NULL);
129     gx_studio_named_widget_create("lights_page_3", GX_NULL, GX_NULL);
130     gx_studio_named_widget_create("lights_page_4", GX_NULL, GX_NULL);
131     lights_screen_init();
132 
133     gx_studio_named_widget_create("locks_screen", GX_NULL, GX_NULL);
134     gx_studio_named_widget_create("locks_page_1", GX_NULL, GX_NULL);
135     gx_studio_named_widget_create("locks_page_2", GX_NULL, GX_NULL);
136     gx_studio_named_widget_create("locks_page_3", GX_NULL, GX_NULL);
137     locks_screen_init();
138 
139     gx_studio_named_widget_create("thermostat_screen", GX_NULL, GX_NULL);
140     gx_studio_named_widget_create("thermostat_page_1", GX_NULL, GX_NULL);
141     gx_studio_named_widget_create("thermostat_page_2", GX_NULL, GX_NULL);
142     gx_studio_named_widget_create("thermostat_page_3", GX_NULL, GX_NULL);
143     gx_studio_named_widget_create("thermostat_page_4", GX_NULL, GX_NULL);
144     thermostat_screen_init();
145 
146     gx_studio_named_widget_create("weather_screen", GX_NULL, GX_NULL);
147     gx_studio_named_widget_create("win_Las_Vegas", GX_NULL, GX_NULL);
148     gx_studio_named_widget_create("win_New_York", GX_NULL, GX_NULL);
149     gx_studio_named_widget_create("win_San_Diego", GX_NULL, GX_NULL);
150     weather_screen_init();
151 
152     gx_studio_named_widget_create("passcode_screen", GX_NULL, GX_NULL);
153 
154     /* Create slide animation control block.  */
155     gx_animation_create(&slide_animation);
156 
157     /* Initialize "main_screen_by" varaible. */
158     memset(&main_screen_bg, 0, sizeof(GX_PIXELMAP));
159 
160     /* Show the root window to make it and main screen visible.  */
161     gx_widget_show(root);
162 
163     /* Let GUIX run */
164     gx_system_start();
165 }
166 
167 /******************************************************************************************/
168 /* Override the default event processing of "main_screen" to handle signals from my child */
169 /* widgets.                                                                               */
170 /******************************************************************************************/
main_screen_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)171 UINT main_screen_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
172 {
173     switch (event_ptr->gx_event_type)
174     {
175     case GX_EVENT_SHOW:
176         clock_update();
177 
178         /* Start a timer to update current time. */
179         gx_system_timer_start((GX_WIDGET *)window, CLOCK_TIMER, GX_TICKS_SECOND, GX_TICKS_SECOND);
180 
181         /* Call default event process. */
182         gx_window_event_process(window, event_ptr);
183         break;
184 
185     case GX_SIGNAL(ID_LIGHTS, GX_EVENT_CLICKED):
186         on_footer_menu_clicked(ID_FOOTER_LIGHTS);
187         break;
188 
189     case GX_SIGNAL(ID_THERMOSTAT, GX_EVENT_CLICKED):
190         on_footer_menu_clicked(ID_FOOTER_THERMOSTAT);
191         break;
192 
193     case GX_SIGNAL(ID_LOCKS, GX_EVENT_CLICKED):
194         on_footer_menu_clicked(ID_FOOTER_LOCKS);
195         break;
196 
197     case GX_SIGNAL(ID_WEATHER, GX_EVENT_CLICKED):
198         on_footer_menu_clicked(ID_FOOTER_WEATHER);
199         break;
200 
201     case GX_EVENT_TIMER:
202         if (event_ptr->gx_event_payload.gx_event_timer_id == CLOCK_TIMER)
203         {
204             clock_update();
205         }
206         break;
207 
208     default:
209         return gx_window_event_process(window, event_ptr);
210     }
211 
212     return 0;
213 }
214 
215 /******************************************************************************************/
216 /* Decode main screen background jpeg.                                                    */
217 /* The background jpeg is saved in the resource data in "raw" format, meaning it is still */
218 /* a jpeg encoded graphic image. We need to decode and color space convert the raw jpeg   */
219 /* data to create a GUIX pixelmap before we can draw the image.                           */
220 /******************************************************************************************/
decode_main_screen_jpeg()221 static VOID decode_main_screen_jpeg()
222 {
223     GX_IMAGE_READER reader;
224     GX_PIXELMAP *map;
225 
226     /* get a pointer to the raw jpeg data */
227     gx_context_pixelmap_get(GX_PIXELMAP_ID_HOME_BG, &map);
228 
229     /* create an image reader object */
230     gx_image_reader_create(&reader, map->gx_pixelmap_data, map->gx_pixelmap_data_size, GX_COLOR_FORMAT_24XRGB, 0);
231 
232     /* decode and color space convert the jpeg to produce a GUIX compatible pixelmap image */
233     gx_image_reader_start(&reader, &main_screen_bg);
234 }
235 
236 /******************************************************************************************/
237 /* Override the default draw function of "main_screen".                                   */
238 /******************************************************************************************/
main_screen_draw(GX_WINDOW * window)239 VOID main_screen_draw(GX_WINDOW *window)
240 {
241     gx_window_background_draw(window);
242 
243     /* If this is the first time drawing, then we need to decompress the raw jpeg
244        image we use to paint the screen background
245     */
246     if (!main_screen_bg.gx_pixelmap_data)
247     {
248         decode_main_screen_jpeg();
249     }
250 
251     /* unless something went wrong, the pixelmap data should now be populated in
252        GUIX pixelmap format
253     */
254     if (main_screen_bg.gx_pixelmap_data)
255     {
256         /* Draw background map. */
257         gx_canvas_pixelmap_draw(window->gx_widget_size.gx_rectangle_left,
258             window->gx_widget_size.gx_rectangle_top, &main_screen_bg);
259     }
260     gx_widget_children_draw(window);
261 }
262 
263 
264 /******************************************************************************************/
265 /* Fade out home window from main screen.                                                 */
266 /******************************************************************************************/
fade_out_home_window()267 VOID fade_out_home_window()
268 {
269     GX_EVENT my_event;
270 
271     memset(&my_event, 0, sizeof(GX_EVENT));
272 
273     /* "USER_EVENT_FADE_OUT_HOME_WINDOW" is an user defined event that will trigger a
274        set of actions. You are able to define those events and actions in studio. */
275     my_event.gx_event_type = USER_EVENT_FADE_OUT_HOME_WINDOW;
276     my_event.gx_event_target = (GX_WIDGET *)&main_screen;
277     gx_system_event_send(&my_event);
278 }
279 
280 /******************************************************************************************/
281 /* Fade out home window to main screen.                                                   */
282 /******************************************************************************************/
fade_in_home_window(int event_type)283 VOID fade_in_home_window(int event_type)
284 {
285     GX_EVENT my_event;
286 
287     memset(&my_event, 0, sizeof(GX_EVENT));
288 
289     /* "USER_EVENT_FADE_IN_HOME_WINDOW" is an user defined event that will trigger a
290     set of actions. You are able to define those events and actions in studio. */
291     my_event.gx_event_type = USER_EVENT_FADE_IN_HOME_WINDOW;
292     my_event.gx_event_target = (GX_WIDGET *)&main_screen;
293     gx_system_event_send(&my_event);
294 }
295 
296 /******************************************************************************************/
297 /* Switch to a new screen.                                                                */
298 /******************************************************************************************/
toggle_screen(GX_WIDGET * new_screen)299 VOID toggle_screen(GX_WIDGET *new_screen)
300 {
301     if (!new_screen || new_screen->gx_widget_id == app_info.current_screen->gx_widget_id)
302     {
303         /* no change. */
304         return;
305     }
306 
307     /* Reset status of current screen. */
308     switch (app_info.current_screen->gx_widget_id)
309     {
310     case ID_LIGHTS_SCREEN:
311         lights_screen_reset();
312         break;
313 
314     case ID_THERMOSTAT_SCREEN:
315         thermostat_screen_reset();
316         break;
317 
318     case ID_LOCKS_SCREEN:
319         locks_screen_reset();
320         break;
321 
322     case ID_WEATHER_SCREEN:
323         weather_screen_reset();
324         break;
325     }
326 
327     if (app_info.current_screen == (GX_WIDGET *)&main_screen.main_screen_home_window)
328     {
329         /* If current screen is home window, fade out home window. */
330         fade_out_home_window();
331     }
332     else
333     {
334         /* Detach current screen. */
335         gx_widget_detach(app_info.current_screen);
336     }
337 
338     /* Attach new screen. */
339     gx_widget_attach((GX_WIDGET *)&main_screen, new_screen);
340 
341     /* Start child widget animations for new screen. */
342     switch (new_screen->gx_widget_id)
343     {
344     case ID_LIGHTS_SCREEN:
345         lights_screen_animation_start();
346         break;
347 
348     case ID_THERMOSTAT_SCREEN:
349         thermostat_screen_animation_start();
350         break;
351 
352     case ID_LOCKS_SCREEN:
353         locks_screen_animation_start();
354         break;
355 
356     case ID_WEATHER_SCREEN:
357         weather_screen_animation_start();
358         break;
359     }
360 
361     app_info.previous_screen = app_info.current_screen;
362     app_info.current_screen = new_screen;
363 }
364 
365 /******************************************************************************************/
366 /* Update clock of main screen.                                                           */
367 /******************************************************************************************/
clock_update()368 VOID clock_update()
369 {
370 #ifdef WIN32
371     GX_RESOURCE_ID am_pm_id;
372     GX_CHAR date_string[20];
373     GX_STRING string;
374 
375     SYSTEMTIME local_time;
376     GetLocalTime(&local_time);
377     if (local_time.wHour < 12)
378     {
379         am_pm_id = GX_STRING_ID_AM;
380     }
381     else
382     {
383         am_pm_id = GX_STRING_ID_PM;
384     }
385     gx_numeric_prompt_value_set(&main_screen.main_screen_hour, (GX_VALUE)local_time.wHour);
386     gx_numeric_prompt_value_set(&main_screen.main_screen_minute, (GX_VALUE)local_time.wMinute);
387     gx_prompt_text_id_set(&main_screen.main_screen_am_pm, am_pm_id);
388 
389     sprintf(date_string, "%s, %s %02d", day_names[local_time.wDayOfWeek], month_names[local_time.wMonth - 1], local_time.wDay);
390     string.gx_string_ptr = date_string;
391     string.gx_string_length = sizeof(date_string) - 1;
392     gx_prompt_text_set_ext(&main_screen.main_screen_date, &string);
393 
394     if (local_time.wSecond & 0x1)
395     {
396         gx_widget_fill_color_set(&main_screen.main_screen_lower_dot, GX_COLOR_ID_WHITE, GX_COLOR_ID_WHITE, GX_COLOR_ID_WHITE);
397         gx_widget_fill_color_set(&main_screen.main_screen_upper_dot, GX_COLOR_ID_WHITE, GX_COLOR_ID_WHITE, GX_COLOR_ID_WHITE);
398     }
399     else
400     {
401         gx_widget_fill_color_set(&main_screen.main_screen_lower_dot, GX_COLOR_ID_GRAY, GX_COLOR_ID_GRAY, GX_COLOR_ID_GRAY);
402         gx_widget_fill_color_set(&main_screen.main_screen_upper_dot, GX_COLOR_ID_GRAY, GX_COLOR_ID_GRAY, GX_COLOR_ID_GRAY);
403     }
404 
405 #else
406 
407     /* add embedded target RTC retrieval here */
408 #endif
409 
410     app_info.overall_energy_today += 5;
411 
412     /* Display the overall energy in use. */
413     gx_numeric_prompt_value_set(&lights_screen.lights_screen_overall_today, app_info.overall_energy_today);
414     gx_numeric_prompt_value_set(&thermostat_screen.thermostat_screen_overall_today, app_info.overall_energy_today);
415 }
416 
417 /******************************************************************************************/
418 /* Custom defined draw function for radial slider widget.                                 */
419 /* This custom radial slider draw function is to support filling selected circular        */
420 /* track with pixelmap.                                                                   */
421 /******************************************************************************************/
custom_radial_slider_draw(GX_RADIAL_SLIDER * slider)422 VOID custom_radial_slider_draw(GX_RADIAL_SLIDER *slider)
423 {
424     GX_PIXELMAP           *map = GX_NULL;
425     GX_RESOURCE_ID         map_id;
426     GX_RADIAL_SLIDER_INFO *info = &slider->gx_radial_slider_info;
427     INT                    xpos;
428     INT                    ypos;
429     INT                    angle = info->gx_radial_slider_info_current_angle;
430     GX_POINT               inner_pt;
431     GX_POINT               outer_pt;
432     GX_RECTANGLE           dirty[3];
433     GX_CANVAS             *canvas;
434     GX_RECTANGLE          *size;
435     GX_VALUE               xcenter;
436     GX_VALUE               ycenter;
437 
438     /* Call default widget draw. */
439     gx_widget_background_draw((GX_WIDGET *)slider);
440 
441     size = &slider->gx_widget_size;
442 
443     /* Pick up the pointer to the background pixelmap. */
444     gx_context_pixelmap_get(info->gx_radial_slider_info_background_pixelmap, &map);
445 
446     if (map)
447     {
448         /* Draw background pixelmap. */
449         gx_canvas_pixelmap_draw(size->gx_rectangle_left, size->gx_rectangle_top, map);
450     }
451 
452     /* Calculate radial slider center coordinates. */
453     xcenter = (GX_VALUE)(info->gx_radial_slider_info_xcenter + size->gx_rectangle_left);
454     ycenter = (GX_VALUE)(info->gx_radial_slider_info_ycenter + size->gx_rectangle_top);
455 
456     /* Get the point on the inner circle of the track with given center point, radius and angle. */
457     gx_utility_circle_point_get(xcenter,
458         ycenter,
459         info->gx_radial_slider_info_radius - (info->gx_radial_slider_info_track_width >> 1),
460         angle,
461         &inner_pt);
462 
463     /* Get the point on the outer circle of the track with given center point, radius and angle. */
464     gx_utility_circle_point_get(xcenter,
465         ycenter,
466         info->gx_radial_slider_info_radius + (info->gx_radial_slider_info_track_width >> 1),
467         angle,
468         &outer_pt);
469 
470     /* Pickup drawing canvas. */
471     gx_widget_canvas_get(slider, &canvas);
472 
473     if (angle != info->gx_radial_slider_info_max_angle)
474     {
475         map_id = light_selected_map_id_get(slider);
476 
477         if (!map_id)
478         {
479             map_id = GX_PIXELMAP_ID_WHEEL_THERMOSTAT;
480         }
481 
482         /* Get the pointer of the pixelmap for filling the selected circular track. */
483         gx_context_pixelmap_get(map_id, &map);
484 
485         if (map)
486         {
487             xpos = size->gx_rectangle_left + 5;
488             ypos = size->gx_rectangle_top + 3;
489 
490             memset(dirty, 0, sizeof(dirty));
491 
492             /* Caculate clipping areas of the selected circular track. */
493             if (angle >= 180)
494             {
495                 dirty[0].gx_rectangle_left = size->gx_rectangle_left;
496                 dirty[0].gx_rectangle_top = outer_pt.gx_point_y;
497                 dirty[0].gx_rectangle_right = xcenter;
498                 dirty[0].gx_rectangle_bottom = size->gx_rectangle_bottom;
499 
500                 dirty[1].gx_rectangle_left = (inner_pt.gx_point_x + outer_pt.gx_point_x) >> 1;
501                 dirty[1].gx_rectangle_top = inner_pt.gx_point_y;
502                 dirty[1].gx_rectangle_right = xcenter;
503                 dirty[1].gx_rectangle_bottom = outer_pt.gx_point_y - 1;
504             }
505             else if (angle >= 90)
506             {
507                 dirty[0].gx_rectangle_left = size->gx_rectangle_left;
508                 dirty[0].gx_rectangle_top = inner_pt.gx_point_y;
509                 dirty[0].gx_rectangle_right = xcenter;
510                 dirty[0].gx_rectangle_bottom = size->gx_rectangle_bottom;
511 
512                 dirty[1].gx_rectangle_left = size->gx_rectangle_left;
513                 dirty[1].gx_rectangle_top = outer_pt.gx_point_y;
514                 dirty[1].gx_rectangle_right = (inner_pt.gx_point_x + outer_pt.gx_point_x) >> 1;
515                 dirty[1].gx_rectangle_bottom = inner_pt.gx_point_y - 1;
516             }
517             else if (angle >= 0)
518             {
519                 dirty[0].gx_rectangle_left = size->gx_rectangle_left;
520                 dirty[0].gx_rectangle_top = size->gx_rectangle_top;
521                 dirty[0].gx_rectangle_right = xcenter;
522                 dirty[0].gx_rectangle_bottom = size->gx_rectangle_bottom;
523 
524                 dirty[1].gx_rectangle_left = xcenter + 1;
525                 dirty[1].gx_rectangle_top = size->gx_rectangle_top;
526                 dirty[1].gx_rectangle_right = size->gx_rectangle_right;
527                 dirty[1].gx_rectangle_bottom = outer_pt.gx_point_y;
528 
529                 dirty[2].gx_rectangle_left = xcenter + 1;
530                 dirty[2].gx_rectangle_top = outer_pt.gx_point_y + 1;
531                 dirty[2].gx_rectangle_right = (inner_pt.gx_point_x + outer_pt.gx_point_x) >> 1;
532                 dirty[2].gx_rectangle_bottom = inner_pt.gx_point_y;
533             }
534             else
535             {
536                 dirty[0].gx_rectangle_left = size->gx_rectangle_left;
537                 dirty[0].gx_rectangle_top = size->gx_rectangle_top;
538                 dirty[0].gx_rectangle_right = xcenter;
539                 dirty[0].gx_rectangle_bottom = size->gx_rectangle_bottom;
540 
541                 dirty[1].gx_rectangle_left = xcenter + 1;
542                 dirty[1].gx_rectangle_top = size->gx_rectangle_top;
543                 dirty[1].gx_rectangle_right = size->gx_rectangle_right;
544                 dirty[1].gx_rectangle_bottom = inner_pt.gx_point_y;
545 
546                 dirty[2].gx_rectangle_left = (inner_pt.gx_point_x + outer_pt.gx_point_x) >> 1;
547                 dirty[2].gx_rectangle_top = inner_pt.gx_point_y + 1;
548                 dirty[2].gx_rectangle_right = size->gx_rectangle_right;
549                 dirty[2].gx_rectangle_bottom = outer_pt.gx_point_y;
550             }
551 
552             /* Draw selected circular track with clipping. */
553             if (dirty[0].gx_rectangle_right > dirty[0].gx_rectangle_left &&
554                 dirty[0].gx_rectangle_bottom > dirty[0].gx_rectangle_top)
555             {
556                 gx_canvas_drawing_initiate(canvas, slider, &dirty[0]);
557                 gx_canvas_pixelmap_draw(xpos, ypos, map);
558                 gx_canvas_drawing_complete(canvas, GX_FALSE);
559             }
560 
561             if (dirty[1].gx_rectangle_right > dirty[1].gx_rectangle_left &&
562                 dirty[1].gx_rectangle_bottom > dirty[1].gx_rectangle_top)
563             {
564                 gx_canvas_drawing_initiate(canvas, slider, &dirty[1]);
565                 gx_canvas_pixelmap_draw(xpos, ypos, map);
566                 gx_canvas_drawing_complete(canvas, GX_FALSE);
567             }
568 
569             if (dirty[2].gx_rectangle_right > dirty[2].gx_rectangle_left &&
570                 dirty[2].gx_rectangle_bottom > dirty[2].gx_rectangle_top)
571             {
572                 gx_canvas_drawing_initiate(canvas, slider, &dirty[2]);
573                 gx_canvas_pixelmap_draw(xpos, ypos, map);
574                 gx_canvas_drawing_complete(canvas, GX_FALSE);
575             }
576         }
577     }
578 
579     /* Pick up the pointer of the needle pixelmap. */
580     gx_context_pixelmap_get(slider->gx_radial_slider_info.gx_radial_slider_info_needle_pixelmap, &map);
581 
582     if (map)
583     {
584         /* Calculate start coordicates for needle draw. */
585         xpos = (inner_pt.gx_point_x + outer_pt.gx_point_x) >> 1;
586         ypos = (inner_pt.gx_point_y + outer_pt.gx_point_y) >> 1;
587 
588         xpos -= 15;
589         ypos -= 15;
590 
591         /* Define needle draw area. */
592         gx_utility_rectangle_define(&dirty[0], xpos, ypos, xpos + map->gx_pixelmap_width - 1, ypos + map->gx_pixelmap_height - 1);
593 
594         /* Initiates drawing on the specified canvas. */
595         gx_canvas_drawing_initiate(canvas, slider, &dirty[0]);
596 
597         /* Draw needle pixelmap. */
598         gx_canvas_pixelmap_draw(xpos, ypos, map);
599 
600         /* Completes drawing on the specified canvas. */
601         gx_canvas_drawing_complete(canvas, GX_FALSE);
602     }
603 
604     /* Draw children widgets. */
605     gx_widget_children_draw((GX_WIDGET *)slider);
606 }
607 
608 /******************************************************************************************/
609 /* Value format function for "hour" and "minute" prompt.                                  */
610 /******************************************************************************************/
time_format(GX_NUMERIC_PROMPT * prompt,INT value)611 VOID time_format(GX_NUMERIC_PROMPT *prompt, INT value)
612 {
613     INT index = 0;
614 
615     sprintf(prompt->gx_numeric_prompt_buffer, "%02d", value);
616     if (value < 10)
617     {
618         prompt->gx_numeric_prompt_buffer[index++] = '0';
619     }
620 
621     /* Convert an integer value to ASCII string. */
622     gx_utility_ltoa(value, prompt->gx_numeric_prompt_buffer + index, GX_NUMERIC_PROMPT_BUFFER_SIZE);
623 }
624 
625 /******************************************************************************************/
626 /* Calculate string length.                                                               */
627 /******************************************************************************************/
string_length_get(GX_CONST GX_CHAR * input_string,UINT max_string_length)628 UINT string_length_get(GX_CONST GX_CHAR* input_string, UINT max_string_length)
629 {
630     UINT length = 0;
631 
632     if (input_string)
633     {
634         /* Traverse the string.  */
635         for (length = 0; input_string[length]; length++)
636         {
637             /* Check if the string length is bigger than the max string length.  */
638             if (length >= max_string_length)
639             {
640                 break;
641             }
642         }
643     }
644 
645     return length;
646 }
647