1 /* This is a small demo of the high-performance GUIX graphics framework. */
2
3 #include "demo_guix_car_infotainment.h"
4
5 #define MEMORY_POOL_BUFFER_SIZE (MAIN_DISPLAY_X_RESOLUTION * MAIN_DISPLAY_Y_RESOLUTION) * 5
6
7 /* Define total number animatin steps. */
8 #define TOTAL_NUMBER_ANIMATION_STEPS 10
9
10 #define CURRENT_NUMBER_VAL_GET(target_val) \
11 (target_val * number_animation_step / TOTAL_NUMBER_ANIMATION_STEPS)
12
13 #define ARC_RANGE 33
14 #define ARC_INTERVAL 36
15 #define ARC_COUNT 8
16
17 #define MAX_MPH 150
18 #define MIN_MPH 0
19
20 typedef struct ARC_INFO_STRUCT {
21 INT start_angle;
22 INT end_angle;
23 }ARC_INFO;
24
25 ARC_INFO arc_info_list[ARC_COUNT + 1];
26
27 /* Define prototypes. */
28 VOID guix_setup(void);
29 extern UINT win32_graphics_driver_setup_24xrgb(GX_DISPLAY* display);
30 VOID clock_update();
31 VOID time_update();
32
33 /* Define memory for memory pool. */
34 GX_UBYTE memory_pool_buffer[MEMORY_POOL_BUFFER_SIZE];
35 TX_BYTE_POOL memory_pool;
36 GX_WINDOW_ROOT *root;
37
38 /* Define variables. */
39 INT local_time_second = 0;
40 GX_WINDOW *current_screen = (GX_WINDOW *)&main_screen;
41 INT bottom_button_alpha = 255;
42 static INT number_animation_step;
43 static INT target_remain_miles = 382;
44 static INT target_battery_usage = 86;
45 static INT MPH_values[] = { 45, 46, 48, 50, 54, 56, 57, 58, 60, 64, 68 };
46 static INT MPH_value_index = 0;
47
48 /******************************************************************************************/
49 /* Application entry. */
50 /******************************************************************************************/
main(int argc,char ** argv)51 int main(int argc, char ** argv)
52 {
53 tx_kernel_enter();
54 return(0);
55 }
56
57 /******************************************************************************************/
58 /* Define memory allocator function. */
59 /******************************************************************************************/
memory_allocate(ULONG size)60 VOID *memory_allocate(ULONG size)
61 {
62 VOID *memptr;
63
64 if (tx_byte_allocate(&memory_pool, &memptr, size, TX_NO_WAIT) == TX_SUCCESS)
65 {
66 return memptr;
67 }
68 return NULL;
69 }
70
71 /******************************************************************************************/
72 /* Define memory de-allocator function. */
73 /******************************************************************************************/
memory_free(VOID * mem)74 void memory_free(VOID *mem)
75 {
76 tx_byte_release(mem);
77 }
78
79 /******************************************************************************************/
80 /* Define tx_application_define function. */
81 /******************************************************************************************/
tx_application_define(void * first_unused_memory)82 VOID tx_application_define(void *first_unused_memory)
83 {
84 /* create byte pool. */
85 tx_byte_pool_create(&memory_pool, "memory pool", memory_pool_buffer, MEMORY_POOL_BUFFER_SIZE);
86
87 guix_setup();
88 }
89
90 /******************************************************************************************/
91 /* Initialize some information used by main screen. */
92 /******************************************************************************************/
main_screen_init()93 VOID main_screen_init()
94 {
95 INT index;
96 GX_RADIAL_SLIDER_INFO* info = &main_screen.main_screen_radial_slider.gx_radial_slider_info;
97
98 arc_info_list[0].end_angle = info->gx_radial_slider_info_max_angle;
99 arc_info_list[0].start_angle = arc_info_list[0].end_angle - ARC_RANGE;
100
101 for (index = 1; index < ARC_COUNT; index++)
102 {
103 arc_info_list[index].start_angle = arc_info_list[index - 1].start_angle - ARC_INTERVAL;
104 arc_info_list[index].end_angle = arc_info_list[index - 1].end_angle - ARC_INTERVAL;
105 }
106
107 arc_info_list[ARC_COUNT].start_angle = 0;
108 arc_info_list[ARC_COUNT].end_angle = 0;
109 }
110
111 /******************************************************************************************/
112 /* Initiate and run GUIX. */
113 /******************************************************************************************/
guix_setup()114 VOID guix_setup()
115 {
116
117 /* Initialize GUIX. */
118 gx_system_initialize();
119
120 /* install our memory allocator and de-allocator */
121 gx_system_memory_allocator_set(memory_allocate, memory_free);
122
123 gx_studio_display_configure(MAIN_DISPLAY, win32_graphics_driver_setup_24xrgb,
124 LANGUAGE_ENGLISH, MAIN_DISPLAY_THEME_1, &root);
125
126 /* Create the gauge_window */
127 gx_studio_named_widget_create("main_screen", (GX_WIDGET *)root, GX_NULL);
128 main_screen_init();
129
130 /* Create vehicle scrreen. */
131 gx_studio_named_widget_create("vehicle_screen", GX_NULL, GX_NULL);
132
133 /* Create climate scrreen. */
134 gx_studio_named_widget_create("climate_screen", GX_NULL, GX_NULL);
135
136 /* Create phone scrreen. */
137 gx_studio_named_widget_create("phone_screen", GX_NULL, GX_NULL);
138
139 /* Create audio screen. */
140 gx_studio_named_widget_create("audio_screen", GX_NULL, GX_NULL);
141
142 /* Create video screen. */
143 gx_studio_named_widget_create("video_screen", GX_NULL, GX_NULL);
144
145 /* Show the root window to make it and patients screen visible. */
146 gx_widget_show(root);
147
148 /* Let GUIX run */
149 gx_system_start();
150 }
151
152 /******************************************************************************************/
153 /* Start number animation. */
154 /******************************************************************************************/
number_animation_start()155 static VOID number_animation_start()
156 {
157 number_animation_step = 0;
158 gx_system_timer_start(&main_screen, TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION, 40 / GX_SYSTEM_TIMER_MS, 40 / GX_SYSTEM_TIMER_MS);
159 }
160
161 /******************************************************************************************/
162 /* Update number animation. */
163 /******************************************************************************************/
number_animation_update()164 static VOID number_animation_update()
165 {
166 INT val;
167 number_animation_step++;
168
169 gx_numeric_prompt_value_set(&main_screen.main_screen_remain_miles, CURRENT_NUMBER_VAL_GET(target_remain_miles));
170 val = CURRENT_NUMBER_VAL_GET(target_battery_usage);
171 gx_numeric_prompt_value_set(&main_screen.main_screen_remain_battery, val);
172 gx_progress_bar_value_set(&main_screen.main_screen_battery_progress_bar, val);
173
174 if (number_animation_step == TOTAL_NUMBER_ANIMATION_STEPS)
175 {
176 gx_system_timer_stop(&main_screen, TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION);
177 }
178 }
179
180 /******************************************************************************************/
181 /* Update speedometer animation. */
182 /******************************************************************************************/
speedometer_aniomation_update()183 static VOID speedometer_aniomation_update()
184 {
185 GX_RADIAL_SLIDER_INFO *info = &main_screen.main_screen_radial_slider.gx_radial_slider_info;
186 INT angle;
187
188 if (MPH_value_index + 1 < sizeof(MPH_values) / sizeof(INT))
189 {
190 MPH_value_index++;
191 }
192 else
193 {
194 MPH_value_index = 0;
195 }
196
197 gx_numeric_prompt_value_set(&main_screen.main_screen_MPH_val, MPH_values[MPH_value_index]);
198
199 /* Convert MPH value to radial progress bar value. */
200 angle = MPH_values[MPH_value_index] * (info->gx_radial_slider_info_max_angle - info->gx_radial_slider_info_min_angle) / MAX_MPH;
201 angle = info->gx_radial_slider_info_max_angle - angle;
202 gx_radial_slider_angle_set(&main_screen.main_screen_radial_slider, angle);
203 }
204
205 /******************************************************************************************/
206 /* Override the default event processing of "main_screen" to handle signals from my child */
207 /* widgets. */
208 /******************************************************************************************/
main_screen_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)209 UINT main_screen_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
210 {
211 switch (event_ptr->gx_event_type)
212 {
213 case GX_EVENT_SHOW:
214 clock_update();
215
216 gx_system_timer_start(window, TIMER_ID_SECOND, GX_TICKS_SECOND, GX_TICKS_SECOND);
217
218 gx_system_timer_start(&main_screen, TIMER_ID_MAIN_SCREEN_SPEEDOMETER_ANIMATION, GX_TICKS_SECOND / 2, GX_TICKS_SECOND / 2);
219
220 /* Start number animation. */
221 number_animation_start();
222
223 /* Call default window event process. */
224 base_event_process(window, event_ptr);
225 break;
226
227 case GX_EVENT_TIMER:
228 switch (event_ptr->gx_event_payload.gx_event_timer_id)
229 {
230 case TIMER_ID_SECOND:
231 time_update();
232 break;
233
234 case TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION:
235 /* Update number animation. */
236 number_animation_update();
237 break;
238
239 case TIMER_ID_MAIN_SCREEN_SPEEDOMETER_ANIMATION:
240 /* Update speedometer animation. */
241 speedometer_aniomation_update();
242 break;
243 }
244 break;
245
246 case GX_SIGNAL(ID_VEHICLE_MODE_BUTTON, GX_EVENT_CLICKED):
247 ToggleScreen((GX_WINDOW*)&vehicle_screen);
248 break;
249
250 default:
251 return base_event_process(window, event_ptr);
252 }
253
254 return GX_SUCCESS;
255 }
256
257 /******************************************************************************************/
258 /* Switch screen. */
259 /******************************************************************************************/
ToggleScreen(GX_WINDOW * new_win)260 VOID ToggleScreen(GX_WINDOW *new_win)
261 {
262 if (new_win != current_screen)
263 {
264 if (!new_win->gx_widget_parent)
265 {
266 gx_widget_attach(root, (GX_WIDGET*)new_win);
267 }
268 else
269 {
270 gx_widget_show((GX_WIDGET*)new_win);
271 }
272 gx_widget_hide((GX_WIDGET*)current_screen);
273
274 if (new_win->gx_widget_id != ID_VIDEO_SCREEN)
275 {
276 gx_widget_attach(new_win, &main_screen.main_screen_btn_window);
277 gx_widget_attach(new_win, &main_screen.main_screen_on_off_btn);
278 }
279 current_screen = new_win;
280 }
281 }
282
283 /******************************************************************************************/
284 /* Update clock of main screen. */
285 /******************************************************************************************/
clock_update()286 VOID clock_update()
287 {
288 #ifdef WIN32
289 SYSTEMTIME local_time;
290 GetLocalTime(&local_time);
291
292 gx_numeric_prompt_value_set(&main_screen.main_screen_time_hour, local_time.wHour);
293 gx_numeric_prompt_value_set(&main_screen.main_screen_time_minute, local_time.wMinute);
294 local_time_second = local_time.wSecond;
295 #else
296 #endif
297 }
298
299 /******************************************************************************************/
300 /* Update time. */
301 /******************************************************************************************/
time_update()302 VOID time_update()
303 {
304 GX_RESOURCE_ID color_id;
305
306 if (local_time_second & 0x1)
307 {
308 if (main_screen.main_screen_weather_win.gx_widget_style & GX_STYLE_ENABLED)
309 {
310 color_id = GX_COLOR_ID_WHITE;
311 }
312 else
313 {
314 color_id = GX_COLOR_ID_DISABLED_FILL;
315 }
316 }
317 else
318 {
319 color_id = GX_COLOR_ID_GRAY;
320 }
321
322 gx_widget_fill_color_set(&main_screen.main_screen_second_dot_up, color_id, color_id, color_id);
323 gx_widget_fill_color_set(&main_screen.main_screen_second_dot_down, color_id, color_id, color_id);
324 local_time_second++;
325
326 if (local_time_second >= 60)
327 {
328 clock_update();
329 }
330 }
331
332 /******************************************************************************************/
333 /* Define time value format callback. */
334 /******************************************************************************************/
time_value_format(GX_NUMERIC_PROMPT * prompt,INT value)335 VOID time_value_format(GX_NUMERIC_PROMPT *prompt, INT value)
336 {
337 INT index = 0;
338
339 if (value < 10)
340 {
341 prompt->gx_numeric_prompt_buffer[index++] = '0';
342 prompt->gx_numeric_prompt_buffer[index++] = '0' + value;
343 }
344 else
345 {
346 prompt->gx_numeric_prompt_buffer[index++] = '0' + (value / 10);
347 prompt->gx_numeric_prompt_buffer[index++] = '0' + (value % 10);
348 }
349
350 prompt->gx_numeric_prompt_buffer[index++] = '\0';
351 }
352
353 /******************************************************************************************/
354 /* Define custom pixelmap button draw function. */
355 /******************************************************************************************/
custom_pixelmap_button_draw(GX_PIXELMAP_BUTTON * button)356 VOID custom_pixelmap_button_draw(GX_PIXELMAP_BUTTON* button)
357 {
358 GX_WIDGET* child = button->gx_widget_first_child;
359 GX_BRUSH* brush;
360
361 gx_context_brush_get(&brush);
362
363 if (button->gx_widget_id != ID_ON_OFF_BTN)
364 {
365 brush->gx_brush_alpha = bottom_button_alpha;
366 }
367
368 while (child)
369 {
370 if (button->gx_widget_style & GX_STYLE_BUTTON_PUSHED)
371 {
372 gx_widget_style_add(child, GX_STYLE_DRAW_SELECTED);
373 }
374 else
375 {
376 gx_widget_style_remove(child, GX_STYLE_DRAW_SELECTED);
377 }
378
379 child = child->gx_widget_next;
380 }
381
382 gx_pixelmap_button_draw(button);
383 }
384
385
386 /******************************************************************************************/
387 /* Custom defined draw function for main screen radial slider widget. */
388 /******************************************************************************************/
radial_slider_draw(GX_RADIAL_SLIDER * slider)389 VOID radial_slider_draw(GX_RADIAL_SLIDER* slider)
390 {
391 GX_RADIAL_SLIDER_INFO* info = &slider->gx_radial_slider_info;
392 GX_PIXELMAP* map;
393 INT xpos;
394 INT ypos;
395 ARC_INFO* arc = arc_info_list;
396 INT start_angle;
397 INT radius;
398 INT angle = info->gx_radial_slider_info_current_angle;
399 GX_POINT inner_pt;
400 GX_POINT outer_pt;
401
402 /* Call default widget background draw. */
403 gx_widget_background_draw((GX_WIDGET*)slider);
404
405 gx_context_pixelmap_get(info->gx_radial_slider_info_background_pixelmap, &map);
406
407 xpos = slider->gx_widget_size.gx_rectangle_left;
408 ypos = slider->gx_widget_size.gx_rectangle_top;
409
410 if (map)
411 {
412 gx_context_fill_color_set(GX_COLOR_ID_BLUE);
413
414 /* Draw background pixelmap. */
415 gx_canvas_pixelmap_draw(xpos, ypos, map);
416 }
417
418 gx_context_brush_width_set(4);
419 gx_context_brush_define(GX_COLOR_ID_LIGHT_GREEN, GX_COLOR_ID_LIGHT_GREEN, GX_BRUSH_ALIAS | GX_BRUSH_ROUND);
420
421 xpos += info->gx_radial_slider_info_xcenter;
422 ypos += info->gx_radial_slider_info_ycenter;
423
424 radius = info->gx_radial_slider_info_radius;
425 radius += (info->gx_radial_slider_info_track_width / 2);
426 radius -= 2;
427
428 /* Fill outer ring with disconnected arcs. */
429 while (arc->start_angle < arc->end_angle)
430 {
431 if (info->gx_radial_slider_info_current_angle < arc->start_angle)
432 {
433 start_angle = arc->start_angle;
434 }
435 else
436 {
437 start_angle = info->gx_radial_slider_info_current_angle;
438 }
439
440 if (start_angle < arc->end_angle)
441 {
442 gx_canvas_arc_draw(xpos, ypos, radius, start_angle, arc->end_angle);
443 }
444
445 if (start_angle == info->gx_radial_slider_info_current_angle)
446 {
447 break;
448 }
449
450 arc++;
451 }
452
453 /* Get the point on the inner circle of the track with given center point, radius and angle. */
454 gx_utility_circle_point_get(xpos,
455 ypos,
456 info->gx_radial_slider_info_radius - (info->gx_radial_slider_info_track_width >> 1) + 1,
457 angle,
458 &inner_pt);
459
460 /* Get the point on the outer circle of the track with given center point, radius and angle. */
461 gx_utility_circle_point_get(xpos,
462 ypos,
463 info->gx_radial_slider_info_radius + (info->gx_radial_slider_info_track_width >> 1) - 1,
464 angle,
465 &outer_pt);
466
467 /* Draw needle. */
468 gx_canvas_line_draw(inner_pt.gx_point_x, inner_pt.gx_point_y, outer_pt.gx_point_x, outer_pt.gx_point_y);
469
470 /* Draw children widgets. */
471 gx_widget_children_draw((GX_WIDGET*)slider);
472 }