1 
2 #include "demo_guix_home_automation.h"
3 
4 /* Define light information structure. */
5 typedef struct LIGHTS_INFO_STRUCT{
6     LIGHTS_BASE_CONTROL_BLOCK *light; /* Pointer to the light controller. */
7     GX_RESOURCE_ID color_text_id; /* Description of the light color. */
8     INT radial_angle; /* Current value of the light control radial slider. */
9     INT power; /* Energy use of the light. */
10     GX_RESOURCE_ID selected_map_id; /* ID of the pixelmap for filling the selected part of the radial slider. */
11     GX_BOOL enabled; /* On/Off status of the light. */
12 }LIGHT_INFO;
13 
14 /* Information about light in various rooms. */
15 static LIGHT_INFO light_info_list[] = {
16     { &lights_page_1.lights_page_1_kitchen, GX_STRING_ID_COLD_WHITE, 37, 0, GX_PIXELMAP_ID_WHEEL_WHITE_COLD, GX_TRUE},
17     { &lights_page_1.lights_page_1_master_bedroom,  GX_STRING_ID_RGB_LIGHT, 100, 0, GX_PIXELMAP_ID_WHEEL_RED, GX_TRUE },
18     { &lights_page_2.lights_page_2_kids_bedroom,  GX_STRING_ID_RGB_LIGHT, 29, 0,GX_PIXELMAP_ID_WHEEL_GREEN, GX_TRUE },
19     { &lights_page_2.lights_page_2_living_room,  GX_STRING_ID_RGB_LIGHT, 29, 0, GX_PIXELMAP_ID_WHEEL_BLUE_DARK, GX_TRUE },
20     { &lights_page_3.lights_page_3_dinning_room,  GX_STRING_ID_WARM_WHITE, 37, 0, GX_PIXELMAP_ID_WHEEL_WHITE_WARM, GX_TRUE },
21     { &lights_page_3.lights_page_3_outdoor_patio,  GX_STRING_ID_RGB_LIGHT, 99, 0, GX_PIXELMAP_ID_WHEEL_BLUE_LIGHT, GX_TRUE },
22     { &lights_page_4.lights_page_4_office,  GX_STRING_ID_RGB_LIGHT, 28, 0, GX_PIXELMAP_ID_WHEEL_PURPLE, GX_TRUE },
23     { GX_NULL, 0, 0, 0, 0, 0}
24 };
25 
26 extern GX_ANIMATION slide_animation;
27 extern int screen_animation_count;
28 
29 UINT string_length_get(GX_CONST GX_CHAR* input_string, UINT max_string_length);
30 
31 /******************************************************************************************/
32 /* Retrieve light information with the specified light controller pointer.                */
33 /******************************************************************************************/
light_info_get(LIGHTS_BASE_CONTROL_BLOCK * light)34 static LIGHT_INFO *light_info_get(LIGHTS_BASE_CONTROL_BLOCK *light)
35 {
36     LIGHT_INFO *info = light_info_list;
37 
38     while (info->light)
39     {
40         if (info->light == light)
41         {
42             return info;
43         }
44 
45         info++;
46     }
47 
48     return GX_NULL;
49 }
50 
51 /******************************************************************************************/
52 /* Retrieve selected pixelmap id for slider in light screen.                              */
53 /******************************************************************************************/
light_selected_map_id_get(GX_RADIAL_SLIDER * slider)54 GX_RESOURCE_ID light_selected_map_id_get(GX_RADIAL_SLIDER *slider)
55 {
56     LIGHT_INFO *info = light_info_list;
57 
58     while (info->light)
59     {
60         if (&info->light->lights_base_radial_slider == slider)
61         {
62             return info->selected_map_id;
63         }
64 
65         info++;
66     }
67 
68     return 0;
69 }
70 
71 /******************************************************************************************/
72 /* Update bottom information of light screen.                                             */
73 /******************************************************************************************/
update_bottom_info_of_lights()74 static VOID update_bottom_info_of_lights()
75 {
76     LIGHT_INFO *info = light_info_list;
77     int energy_in_use = 0;
78     int enabled = 0;
79     int disabled = 0;
80 
81     /* Calculate the total enery in use and the number of enabled/disabled lights. */
82     while (info->light)
83     {
84         if (info->enabled)
85         {
86             energy_in_use += info->power;
87             enabled++;
88         }
89         else
90         {
91             disabled++;
92         }
93 
94         info++;
95     }
96 
97     /* Display the number of enabled lights. */
98     gx_numeric_prompt_value_set(&lights_screen.lights_screen_num_on, enabled);
99 
100     /* Display the number of disabled lights. */
101     gx_numeric_prompt_value_set(&lights_screen.lights_screen_num_off, disabled);
102 
103     /* Display the total energy in use. */
104     gx_numeric_prompt_value_set(&lights_screen.lights_screen_energy_in_use, energy_in_use);
105 }
106 
107 /******************************************************************************************/
108 /* Update information for specified light.                                                */
109 /******************************************************************************************/
power_value_update(LIGHT_INFO * info,int radial_angle)110 static VOID power_value_update(LIGHT_INFO *info, int radial_angle)
111 {
112     INT angle;
113     INT angle_range = (MAX_ANGLE - MIN_ANGLE);
114     INT value;
115     INT xpos;
116 
117     /* Calcualte the light intensity. */
118     angle = MAX_ANGLE - radial_angle;
119     value = angle * 100 / angle_range;
120 
121     /* Display the light intensity. */
122     gx_numeric_prompt_value_set(&info->light->lights_base_power_percent_value, value);
123 
124     if (value < 10)
125     {
126         xpos = 165;
127     }
128     else  if (value < 100)
129     {
130         xpos = 179;
131     }
132     else
133     {
134         xpos = 192;
135     }
136 
137     xpos += info->light->base.gx_widget_size.gx_rectangle_left;
138 
139     /* Shift light intensity widget to make it in the center of the radial slider. */
140     gx_widget_shift(&info->light->lights_base_precent_lable, xpos - info->light->lights_base_precent_lable.gx_widget_size.gx_rectangle_left, 0, GX_TRUE);
141 
142     /* Calcualte the energy of the light. */
143     value = angle * MAX_POWER / angle_range;
144     info->power = value;
145 
146     /* Display the energy of the light. */
147     gx_numeric_prompt_value_set(&info->light->lights_base_power_value, value);
148 }
149 
150 /******************************************************************************************/
151 /* Event handler for light close button click.                                            */
152 /* This function detaches light control radial slider, attaches light open button,        */
153 /* and updates light information in bottom area.                                          */
154 /******************************************************************************************/
on_close_button_clicked(LIGHTS_BASE_CONTROL_BLOCK * base)155 static VOID on_close_button_clicked(LIGHTS_BASE_CONTROL_BLOCK *base)
156 {
157     LIGHT_INFO *info = light_info_get(base);
158 
159     if (info && info->enabled)
160     {
161         info->enabled = GX_FALSE;
162 
163         /* detach radial slider. */
164         gx_widget_detach(&base->lights_base_radial_slider);
165 
166         /* detach icon ruller. */
167         gx_widget_detach(&base->lights_base_icon_ruller);
168 
169         gx_widget_detach(&base->lights_base_button_close);
170 
171         /* attach open button. */
172         gx_widget_attach((GX_WIDGET *)base, &base->lights_base_button_open);
173 
174         update_bottom_info_of_lights();
175     }
176 }
177 
178 /******************************************************************************************/
179 /* Event handler for light open button click.                                             */
180 /* This function attaches light control radial slider, attaches light close button,       */
181 /* and updates light information in bottom area.                                          */
182 /******************************************************************************************/
on_open_button_clicked(LIGHTS_BASE_CONTROL_BLOCK * base)183 static VOID on_open_button_clicked(LIGHTS_BASE_CONTROL_BLOCK *base)
184 {
185     LIGHT_INFO *info = light_info_get(base);
186 
187     if (info && (!info->enabled))
188     {
189         info->enabled = GX_TRUE;
190 
191         /* attach icon ruller. */
192         gx_widget_attach((GX_WIDGET *)base, &base->lights_base_icon_ruller);
193 
194         gx_widget_attach((GX_WIDGET *)base, &base->lights_base_button_close);
195 
196         /* attach radial slider. */
197         gx_widget_attach((GX_WIDGET *)base, &base->lights_base_radial_slider);
198 
199         /* detach open button. */
200         gx_widget_detach(&base->lights_base_button_open);
201 
202         update_bottom_info_of_lights();
203     }
204 }
205 
206 /******************************************************************************************/
207 /* Reset status of light.                                                                 */
208 /******************************************************************************************/
light_status_reset(LIGHT_INFO * info)209 static VOID light_status_reset(LIGHT_INFO *info)
210 {
211     GX_WIDGET *child;
212 
213     /* Hide all children of light controller. */
214     child = info->light->base.gx_widget_first_child;
215     while (child)
216     {
217         gx_widget_hide(child);
218         child = child->gx_widget_next;
219     }
220 
221     /* Reset light control radial slider value. */
222     gx_radial_slider_angle_set(&info->light->lights_base_radial_slider, MAX_ANGLE);
223 
224     /* Reset light intensity value. */
225     gx_numeric_prompt_value_set(&info->light->lights_base_power_percent_value, 0);
226 
227     /* Reset light energy value. */
228     gx_numeric_prompt_value_set(&info->light->lights_base_power_value, 0);
229 }
230 
231 /******************************************************************************************/
232 /* Reset status of light screen.                                                          */
233 /******************************************************************************************/
lights_screen_reset()234 VOID lights_screen_reset()
235 {
236     LIGHT_INFO *info = light_info_list;
237 
238     while (info->light)
239     {
240         if (info->light->base.gx_widget_status & GX_STATUS_VISIBLE)
241         {
242             light_status_reset(info);
243         }
244 
245         info++;
246     }
247 }
248 
249 /******************************************************************************************/
250 /* Start children animations for visible light controller, this function is called when   */
251 /* light pages switched.                                                                  */
252 /******************************************************************************************/
lights_screen_animation_start()253 VOID lights_screen_animation_start()
254 {
255     LIGHT_INFO *info = light_info_list;
256     GX_WIDGET *child;
257 
258     while (info->light)
259     {
260         if (info->light->base.gx_widget_status & GX_STATUS_VISIBLE)
261         {
262             /* Light controller is visible. */
263 
264             if (!(info->light->base.controller_base_title.gx_widget_status & GX_STATUS_VISIBLE))
265             {
266                 /* Title of the light controller is not visible, which means light page switched.
267                    start children animations for the light controller. */
268 
269                 /* Disable drag slide animation before screen item animations complete. */
270                 gx_animation_drag_disable(&slide_animation, (GX_WIDGET *)&lights_screen.base.screen_base_slide_win);
271 
272                 /* Disable pagination buttons to avoid button click while animations is on. */
273                 pagination_button_enable_disable((GX_WINDOW *)&lights_screen.base, GX_FALSE);
274 
275                 /* Slide in light controller title. */
276                 title_animation_start(&info->light->base);
277 
278                 if (info->enabled)
279                 {
280                     /* If the light controller is on, start animation to move light control radial slider from initial
281                        value to current value. */
282                     gx_radial_slider_animation_start(&info->light->lights_base_radial_slider, info->radial_angle);
283                 }
284 
285                 /* Show children of the light controller. */
286                 child = info->light->base.gx_widget_first_child;
287                 while (child)
288                 {
289                     gx_widget_show(child);
290                     child = child->gx_widget_next;
291                 }
292             }
293         }
294         else
295         {
296             /* Reset status of light controller. */
297             light_status_reset(info);
298         }
299 
300         info++;
301     }
302 }
303 
304 /******************************************************************************************/
305 /* Stop all animations in lights screen.                                                  */
306 /******************************************************************************************/
lights_screen_animation_stop()307 VOID lights_screen_animation_stop()
308 {
309     LIGHT_INFO *info = light_info_list;
310 
311     while (info->light)
312     {
313         if (info->light->base.gx_widget_status & GX_STATUS_VISIBLE)
314         {
315             /* Light controller is visible. */
316             gx_animation_delete(GX_NULL, (GX_WIDGET *)&info->light->base);
317         }
318 
319         info++;
320     }
321 
322     screen_animation_count = 0;
323 }
324 
325 /******************************************************************************************/
326 /* Callback function of radial slider, which is called after every animation step.        */
327 /******************************************************************************************/
radial_slider_value_update(GX_RADIAL_SLIDER * slider)328 VOID radial_slider_value_update(GX_RADIAL_SLIDER *slider)
329 {
330     LIGHT_INFO *info = light_info_get((LIGHTS_BASE_CONTROL_BLOCK *)slider->gx_widget_parent);
331 
332     if (info && (slider->gx_widget_status & GX_STATUS_VISIBLE))
333     {
334         info->radial_angle = slider->gx_radial_slider_info.gx_radial_slider_info_current_angle;
335 
336         /* Update light energy value. */
337         power_value_update(info, info->radial_angle);
338 
339         /* Update summary light information in bottom. */
340         update_bottom_info_of_lights();
341     }
342 }
343 
344 /******************************************************************************************/
345 /* Format function of numeric prompt.                                                     */
346 /******************************************************************************************/
power_value_format(GX_NUMERIC_PROMPT * prompt,INT value)347 VOID power_value_format(GX_NUMERIC_PROMPT *prompt, INT value)
348 {
349     INT index;
350 
351     gx_utility_ltoa(value / 10000, prompt->gx_numeric_prompt_buffer, GX_NUMERIC_PROMPT_BUFFER_SIZE);
352 
353     index = string_length_get(prompt->gx_numeric_prompt_buffer, GX_NUMERIC_PROMPT_BUFFER_SIZE);
354     prompt->gx_numeric_prompt_buffer[index++] = '.';
355 
356     gx_utility_ltoa(value % 10000, prompt->gx_numeric_prompt_buffer + index, GX_NUMERIC_PROMPT_BUFFER_SIZE - index);
357 }
358 
359 /******************************************************************************************/
360 /* Override the default event processing of templates based on "lights_base" to handle    */
361 /* signals from my child widgets.                                                         */
362 /******************************************************************************************/
lights_base_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)363 UINT lights_base_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
364 {
365     switch (event_ptr->gx_event_type)
366     {
367     case GX_SIGNAL(ID_RADIAL_SLIDER, GX_EVENT_SLIDER_VALUE):
368         radial_slider_value_update(&((LIGHTS_BASE_CONTROL_BLOCK *)window)->lights_base_radial_slider);
369         break;
370 
371     case GX_SIGNAL(ID_CLOSE, GX_EVENT_CLICKED):
372         on_close_button_clicked((LIGHTS_BASE_CONTROL_BLOCK *)window);
373         break;
374 
375     case GX_SIGNAL(ID_OPEN, GX_EVENT_CLICKED):
376         on_open_button_clicked((LIGHTS_BASE_CONTROL_BLOCK *)window);
377         break;
378 
379     default:
380         return gx_window_event_process(window, event_ptr);
381     }
382 
383     return 0;
384 }
385 
386 /******************************************************************************************/
387 /* Initiate light screen information.                                                     */
388 /******************************************************************************************/
lights_screen_init()389 VOID lights_screen_init()
390 {
391     LIGHT_INFO *info = light_info_list;
392 
393     while (info->light)
394     {
395         /* Set light color text. */
396         gx_prompt_text_id_set(&info->light->lights_base_color_text, info->color_text_id);
397 
398         /* detach open button. */
399         gx_widget_detach(&info->light->lights_base_button_open);
400 
401         light_status_reset(info);
402 
403         info++;
404     }
405 
406     lights_title_init();
407 
408     /* Set add button text to "ADD LIGHT". */
409     gx_prompt_text_id_set(&lights_screen.base.screen_base_add_text, GX_STRING_ID_ADD_LIGHT);
410 }