d43c3441ac361e127a2d476e813872208b6f2501
[profile/tv/apps/native/settings.git] / src / view_system_clock.c
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <utilX.h>
18
19 #include "dbg.h"
20 #include "def.h"
21 #include "stdbool.h"
22 #include "viewmgr.h"
23 #include "utils.h"
24 #include "data_wrapper.h"
25 #include "settings_provider.h"
26 #include "view_system_clock.h"
27
28 #define DATA_ID "system_clock_data"
29 #define MAX_ITEMS 2
30 #define ITEM_HEIGHT 82
31 #define POS_ADJUST (39 * 2)
32 #define ITEMID "itemdata"
33 #define CLOCK_ITEM 0
34 #define MANUAL "1"
35
36 #define SUBLIST_WIDTH 310.0
37 #define LEFT_MARGIN 70.0
38 #define LEFT_OFFSET (SUBLIST_WIDTH + LEFT_MARGIN)
39
40 #define SIG_DISMISSED "dismissed"
41 #define SIG_FOCUSED "focused"
42 #define SIG_UNFOCUSED "unfocused"
43 #define SIG_CLICKED "clicked"
44
45 struct _sysclk_data {
46         Evas_Object *win;
47         Evas_Object *base;
48         Evas_Object *ctxpopup;
49         Evas_Object *box;
50         Eina_Array *array;
51
52         int count;
53         int sel_idx;
54         struct settingview_data *vdata;
55         struct setting_mgr *mgr;
56
57         struct evas_obj_data ugd;
58         struct obj_geometry_data *ogd;
59 };
60
61 static void _destroy(Evas_Object *base);
62 static void _hide(Evas_Object *base);
63
64 /**
65 * Exit system clock sublist view.
66 *
67 * @param[in]: data : the user data of system clock sublist view.
68 *
69 * @return: void.
70 */
71 static void _exit_view(struct _sysclk_data *data)
72 {
73         if (!data || !data->base)
74                 return;
75
76         _hide(data->base);
77
78         settingmgr_view_pop(data->mgr);
79 }
80
81 /**
82 * Get item list.
83 *
84 * @param[in]: vdata : view data.
85 * @param[out]: count : number of item.
86 *
87 * @return: eina list containing items or null if error occurred.
88 */
89 static Eina_List *_get_item_list(struct settingview_data *vdata, int *count)
90 {
91         Eina_List *list;
92
93         if (!vdata || !count) {
94                 _ERR("Invalid arguments");
95                 return NULL;
96         }
97
98         list = settingitem_get_data_list(viewdata_get_parentitem(vdata));
99         if (!list) {
100                 *count = 0;
101                 return NULL;
102         }
103
104         *count = eina_list_count(list);
105
106         return list;
107 }
108
109 /**
110 * Get selected value: Manual or Auto.
111 *
112 * @param[in]: data : the user data of system clock sublist view.
113 *
114 * @return: the selected value or null if error occurred.
115 */
116 static char *_get_selected_value(struct _sysclk_data *data)
117 {
118         struct settingitem *item;
119
120         if (!data || !data->vdata) {
121                 _ERR("Invalid argument");
122                 return NULL;
123         }
124
125         item = viewdata_get_parentitem(data->vdata);
126         if (!item) {
127                 _ERR("Get item failed");
128                 return NULL;
129         }
130
131         return provider_get_list_value(item);
132 }
133
134 /**
135 * Set selected value: Manual or Auto.
136 *
137 * @param[in]: data : the user data of system clock sublist view.
138 * @param[in]: obj : the selected object.
139 *
140 * @return: void.
141 */
142 static void _set_selected_value(struct _sysclk_data *data, Evas_Object *obj)
143 {
144         struct settingitem *item;
145         char *selval;
146         int ret;
147
148         if (!data || !data->vdata || !obj) {
149                 _ERR("Invalid argument");
150                 return;
151         }
152
153         item = viewdata_get_parentitem(data->vdata);
154         if (!item) {
155                 _ERR("Get item failed");
156                 return;
157         }
158
159         selval = evas_object_data_get(obj, ITEMID);
160         if (selval) {
161                 ret = provider_set_list_value(item, selval);
162                 if (ret != 0)
163                         _ERR("Set list value failed");
164         }
165 }
166
167 /**
168 * Evas_Smart_Cb type callback for handling foucs in event.
169 *
170 * @param[in]: priv : the user data.
171 * @param[in]: obj : the corresponding object which the foucs in event occurred.
172 * @param[in]: ev : event info.
173 *
174 * @return: void.
175 */
176 static void _subitem_focusin_cb(void *priv, Evas_Object *obj, void *ev)
177 {
178         struct _sysclk_data *data;
179         char *value;
180         char *selval;
181
182         if (!obj || !priv) {
183                 _ERR("Invalid arguments\n");
184                 return;
185         }
186
187         data = priv;
188
189         value = evas_object_data_get(obj, ITEMID);
190         if (!value) {
191                 _ERR("Get value from btn failed\n");
192                 return;
193         }
194
195         selval = _get_selected_value(data);
196         if (!selval) {
197                 _ERR("_get_selected_value failed\n");
198                 return;
199         }
200
201         if (!strncmp(selval, value, strlen(selval))) {
202                 elm_object_signal_emit(obj, CTXPOPUPBTN_ICON_FOCUSED,
203                                 CTXPOPUPBTN_ICON_SOURCE);
204         }
205
206         elm_object_signal_emit(obj, CTXPOPUPBTN_BUTTON_FOCUSED,
207                         CTXPOPUPBTN_BUTTON_SOURCE);
208
209         provider_release_list_value(selval);
210 }
211
212 /**
213 * Evas_Smart_Cb type callback for handling focus out event.
214 *
215 * @param[in]: priv : the user data.
216 * @param[in]: obj : the corresponding object which the focus out event occurred.
217 * @param[in]: ev : event info.
218 *
219 * @return: void.
220 */
221 static void _subitem_focusout_cb(void *priv, Evas_Object *obj, void *ev)
222 {
223         struct _sysclk_data *data;
224         char *value;
225         char *selval;
226
227         if (!obj || !priv) {
228                 _ERR("Invalid arguments\n");
229                 return;
230         }
231
232         data = priv;
233
234         value = evas_object_data_get(obj, ITEMID);
235         if (!value) {
236                 _ERR("Get value from btn failed\n");
237                 return;
238         }
239
240         selval = _get_selected_value(data);
241         if (!selval) {
242                 _ERR("_get_selected_value failed\n");
243                 return;
244         }
245
246         if (!strncmp(selval, value, strlen(selval)))
247                 elm_object_signal_emit(obj, CTXPOPUPBTN_BUTTON_HIGHLIGHT,
248                                 CTXPOPUPBTN_BUTTON_SOURCE);
249         else
250                 elm_object_signal_emit(obj, CTXPOPUPBTN_BUTTON_UNFOCUSED,
251                                 CTXPOPUPBTN_BUTTON_SOURCE);
252
253         provider_release_list_value(selval);
254 }
255
256 /**
257 * Evas_Smart_Cb type callback for handling click event.
258 *
259 * @param[in]: priv : the user data.
260 * @param[in]: obj : the corresponding object which the click event occurred.
261 * @param[in]: ev : event info.
262 *
263 * @return: void.
264 */
265 static void _subitem_clicked_cb(void *priv, Evas_Object *obj, void *ev)
266 {
267         struct _sysclk_data *data;
268         struct settingitem *item;
269         Eina_List *list;
270         char *value;
271         const char *id;
272         const char *name;
273
274         if (!priv || !obj)
275                 return;
276
277         data = priv;
278
279         _set_selected_value(data, obj);
280
281         value = evas_object_data_get(obj, ITEMID);
282         if (!value) {
283                 _ERR("get value from obj failed. DATA_ID: %s", ITEMID);
284                 return;
285         }
286
287         if (!strncmp(value, MANUAL, BUF_SIZE)) {
288                 _hide(data->base);
289
290                 list = viewdata_get_childitems_list(data->vdata);
291                 if (!list) {
292                         _ERR("list of clock is null.");
293                         return;
294                 }
295
296                 item = eina_list_nth(list, CLOCK_ITEM);
297                 if (!item) {
298                         _ERR("there is no clock_mode item in list.");
299                         return;
300                 }
301
302                 id = settingitem_get_id(item);
303                 if (!id) {
304                         _ERR("get item id failed.");
305                         return;
306                 }
307
308                 name = settingitem_get_display_name(item);
309                 if (!name) {
310                         _ERR("get display_name failed.");
311                         return;
312                 }
313
314                 data->ugd.display_name = name;
315
316                 settingmgr_view_push(data->mgr, id, (void *)&data->ugd);
317         } else {
318                 _exit_view(data);
319         }
320 }
321
322 /**
323 * Evas_Object_Event_Cb type callback for handling key press event.
324 *
325 * @param[in]: priv : the user data.
326 * @param[in]: e : the evas canvas.
327 * @param[in]: obj : the corresponding object which the key press event occurred.
328 * @param[in]: ei : event info.
329 *
330 * @return: void.
331 */
332 static void _subitem_keypress_cb(void *priv, Evas *e,
333                 Evas_Object *obj, void *ei)
334 {
335         Evas_Event_Key_Down *ev;
336         struct _sysclk_data *data;
337
338         if (!priv || !ei)
339                 return;
340
341         data = priv;
342         ev = ei;
343
344         if (!ev->keyname)
345                 return;
346
347         if (!strncmp(ev->keyname, KEY_BACK, BUF_SIZE) || !strncmp(ev->keyname, KEY_BACK_REMOTE, BUF_SIZE))
348                 _exit_view(data);
349 }
350
351 /**
352 * Create system clock sublist items.
353 *
354 * @param[in]: data : the user data.
355 * @param[in]: list : the eina list containing items.
356 * @param[in]: selval : the current selected value of item.
357 *
358 * @return: 0 - Success, -1 - Fail.
359 */
360 static int _add_sysclk_sublist_item(struct _sysclk_data *data,
361                 Eina_List *list, const char *selval)
362 {
363         Evas_Object *box, *cp, *btn, *del_btn;
364         Eina_Array *array;
365         Eina_Array_Iterator aiter;
366         struct listitem *li;
367         Eina_List *iter;
368         const char *disp, *value;
369         int idx, i, j;
370
371         if (!data || !list || !data->ctxpopup || !selval) {
372                 _ERR("invalid arguments.");
373                 return -1;
374         }
375
376         cp = data->ctxpopup;
377
378         box = utils_add_box(cp);
379         if (!box) {
380                 _ERR("utils add box to ctxpopup failed.");
381                 return -1;
382         }
383
384         elm_object_content_set(cp, box);
385
386         array = eina_array_new(1);
387         if (!array) {
388                 _ERR("eina array new failed.");
389                 evas_object_del(box);
390                 return -1;
391         }
392
393         i = idx = 0;
394         EINA_LIST_FOREACH(list, iter, li) {
395                 disp = listitem_get_display_name(li);
396                 if (!disp) {
397                         _ERR("display name of list item is null.");
398                         goto error;
399                 }
400
401                 btn = utils_add_btn(box, CTXPOPUPBTN_STYLE, disp, EINA_TRUE);
402                 if (!btn) {
403                         _ERR("utils add button failed.");
404                         goto error;
405                 }
406
407                 value = listitem_get_value(li);
408                 if (!value) {
409                         _ERR("value of this list item is null.");
410                         goto error;
411                 }
412
413                 if (!strncmp(selval, value, strlen(selval))) {
414                         elm_object_signal_emit(btn,
415                                         CTXPOPUPBTN_BUTTON_HIGHLIGHT,
416                                         CTXPOPUPBTN_BUTTON_SOURCE);
417                         idx = i;
418                 }
419
420                 evas_object_data_set(btn, ITEMID, value);
421
422                 evas_object_smart_callback_add(btn, SIG_FOCUSED,
423                                 _subitem_focusin_cb, data);
424                 evas_object_smart_callback_add(btn, SIG_UNFOCUSED,
425                                 _subitem_focusout_cb, data);
426                 evas_object_smart_callback_add(btn, SIG_CLICKED,
427                                 _subitem_clicked_cb, data);
428                 evas_object_event_callback_add(btn, EVAS_CALLBACK_KEY_DOWN,
429                                 _subitem_keypress_cb, data);
430
431                 elm_box_pack_end(box, btn);
432                 eina_array_push(array, btn);
433
434                 if (i == 0)
435                         elm_object_focus_set(btn, EINA_TRUE);
436
437                 i++;
438         }
439
440         data->box = box;
441         data->array = array;
442         data->sel_idx = idx;
443
444         return 0;
445
446 error:
447         EINA_ARRAY_ITER_NEXT(array, j, del_btn, aiter) {
448                 if (del_btn)
449                         evas_object_del(del_btn);
450         }
451
452         evas_object_del(box);
453         eina_array_free(array);
454
455         return -1;
456 }
457
458 /**
459 * Create system clock sublist view.
460 *
461 * @param[in]: data : the user data.
462 *
463 * @return: 0 - Success, -1 - Fail.
464 */
465 static int _draw_sysclk_sublist(struct _sysclk_data *data)
466 {
467         Evas_Object *ctxpopup;
468         char *selval;
469         struct settingview_data *vdata;
470         struct obj_geometry_data *ogd;
471         Eina_List *itlist;
472         int xpos, ypos, height, count, r;
473         double ratio;
474
475         if (!data || !data->ctxpopup || !data->ogd || !data->vdata) {
476                 _ERR("Invalid argument\n");
477                 return -1;
478         }
479
480         ctxpopup = data->ctxpopup;
481         vdata = data->vdata;
482         ogd = data->ogd;
483
484         count = 0;
485         itlist = _get_item_list(vdata, &count);
486         if (!itlist) {
487                 _ERR("Get item list failed");
488                 return -1;
489         }
490
491         data->count = count;
492
493         selval = _get_selected_value(data);
494         if (!selval) {
495                 _ERR("Get selected value failed");
496                 return -1;
497         }
498
499         if (count > MAX_ITEMS) {
500                 _ERR("system clock sublist is too many.");
501                 goto error;
502         }
503
504         r = _add_sysclk_sublist_item(data, itlist, selval);
505         if (r != 0) {
506                 _ERR("add system clock sublist items failed.");
507                 goto error;
508         }
509
510         if (ogd->width <= 0) {
511                 _ERR("width of object is less than 0.");
512                 goto error;
513         }
514
515         ratio = (ogd->width - LEFT_OFFSET) / ogd->width;
516         xpos = ogd->x + ogd->width * ratio;
517         ypos = ogd->y;
518
519         height = data->count * ITEM_HEIGHT;
520
521         if (ypos > WIN_HEIGHT)
522                 ypos = ypos - height;
523
524         evas_object_move(ctxpopup, xpos * ELM_SCALE, ypos * ELM_SCALE);
525
526         utils_set_focus_directions(data->array, data->count);
527
528         provider_release_list_value(selval);
529
530         return 0;
531
532 error:
533         provider_release_list_value(selval);
534         return -1;
535 }
536
537 /**
538 * Evas_Smart_Cb type callback for handling ctxpopup dismissed event.
539 *
540 * @param[in]: priv : the user data.
541 * @param[in]: obj : the corresponding object which the dismissed event occurred.
542 * @param[in]: ev : event info.
543 *
544 * @return: void.
545 */
546 static void _ctxpopup_dismissed(void *priv, Evas_Object *obj,
547                 void *ev)
548 {
549         struct _sysclk_data *data;
550
551         if (!priv || !obj)
552                 return;
553
554         data = priv;
555
556         _hide(data->base);
557
558         settingmgr_view_pop(data->mgr);
559 }
560
561 /**
562 * Create all the UI components of system clock sublist view.
563 *
564 * @param[in]: mgr : view manager of settings views.
565 * @param[in]: view : data of view.
566 * @param[in]: prev : the user data.
567 *
568 * @return: the base layout of system clock view or null
569 *              if error occurred.
570 */
571 static Evas_Object *_create(struct setting_mgr *mgr,
572                 struct settingview_data *view, void *prev)
573 {
574         Evas_Object *base;
575         Evas_Object *ctxpopup;
576         Evas_Object *win;
577         struct _sysclk_data *data;
578         struct evas_obj_data *ugd;
579         struct obj_geometry_data *ogd;
580
581         if (!mgr || !view || !prev) {
582                 _ERR("Invalid argument!\n");
583                 return NULL;
584         }
585
586         ugd = prev;
587         ogd = evas_object_data_get(ugd->cur_btn, DATA_ID);
588
589         win = settingmgr_get_win(mgr);
590         if (!win) {
591                 _ERR("settingmgr get window failed.");
592                 return NULL;
593         }
594
595         data = calloc(1, sizeof(*data));
596         if (!data) {
597                 _ERR("Unable to allocate memory.");
598                 return NULL;
599         }
600
601         data->ugd = *ugd;
602
603         base = elm_layout_add(win);
604         if (!base) {
605                 free(data);
606                 return NULL;
607         }
608
609         elm_layout_file_set(base, EDJ_FILE, SUBLIST_VIEW_PAGE);
610
611         ctxpopup = utils_add_ctxpopup(win, SUBLIST_CTXPOPUP_STYLE1);
612         if (!ctxpopup) {
613                 _ERR("Fail to add ctxpopup");
614                 evas_object_del(base);
615                 free(data);
616                 return NULL;
617         }
618
619         evas_object_smart_callback_add(ctxpopup, SIG_DISMISSED,
620                         _ctxpopup_dismissed, data);
621
622         data->mgr = mgr;
623         data->win = win;
624         data->base = base;
625         data->ctxpopup = ctxpopup;
626         data->vdata = view;
627         data->ogd = ogd;
628
629         evas_object_data_set(base, DATA_ID, data);
630
631         if (_draw_sysclk_sublist(data) == -1) {
632                 _ERR("Error in drawing items function\n");
633                 evas_object_del(base);
634                 evas_object_del(ctxpopup);
635                 free(data);
636                 return NULL;
637         }
638
639         return base;
640 }
641
642 /**
643 * Show the system clock view.
644 *
645 * @param[in]: base : the base layout of system clock view.
646 *
647 * @return: void.
648 */
649 static void _show(Evas_Object *base)
650 {
651         struct _sysclk_data *data;
652
653         if (!base) {
654                 _ERR("Invalid argument\n");
655                 return;
656         }
657
658         data = evas_object_data_get(base, DATA_ID);
659         if (!data) {
660                 _ERR("Get sublist data failed\n");
661                 return;
662         }
663
664         evas_object_show(data->ctxpopup);
665         evas_object_show(base);
666 }
667
668 /**
669 * Destroy the system clock view.
670 *
671 * @param[in]: base : the base layout of system clock view.
672 *
673 * @return: void.
674 */
675 static void _destroy(Evas_Object *base)
676 {
677         struct _sysclk_data *data;
678
679         if (!base)
680                 return;
681
682         data = evas_object_data_get(base, DATA_ID);
683         if (!data) {
684                 _ERR("Invalid arguments");
685                 evas_object_del(data->ctxpopup);
686                 evas_object_del(base);
687                 return;
688         }
689
690         if (data->array) {
691                 eina_array_free(data->array);
692                 data->array = NULL;
693         }
694
695         evas_object_del(data->ctxpopup);
696         evas_object_del(base);
697
698         if (data->vdata)
699                 viewdata_release(data->vdata);
700
701         free(data);
702 }
703
704 /**
705 * Hide the system clock view.
706 *
707 * @param[in]: base : the base layout of system clock view.
708 *
709 * @return: void.
710 */
711 static void _hide(Evas_Object *base)
712 {
713         struct _sysclk_data *data;
714
715         if (!base)
716                 return;
717
718         data = evas_object_data_get(base, DATA_ID);
719         if (!data) {
720                 _ERR("Invalid arguments");
721                 return;
722         }
723
724         evas_object_hide(base);
725         evas_object_hide(data->ctxpopup);
726 }
727
728 /**
729 * Refresh Manual/Auto text of system clock item.
730 *
731 * @param[in]: base : the base layout of system clock view.
732 *
733 * @return: void.
734 */
735 static void _refresh(Evas_Object *base)
736 {
737         struct _sysclk_data *data;
738
739         if (!base) {
740                 _ERR("the base of system clock is null.");
741                 return;
742         }
743
744         data = evas_object_data_get(base, DATA_ID);
745         if (!data) {
746                 _ERR("data get failed. DATA_ID: %s", DATA_ID);
747                 return;
748         }
749
750         _exit_view(data);
751 }
752
753 /**
754 * view class of system clock view.
755 */
756 static struct setting_class _vclass = {
757         .title = VCLASS_TITLE_SYSTEM_CLOCK,
758         .create = _create,
759         .show = _show,
760         .destroy = _destroy,
761         .hide = _hide,
762         .refresh = _refresh,
763         .hide_view = 0
764 };
765
766 /**
767 * Return view class of system clock view.
768 *
769 * @param: void.
770 *
771 * @return: the view class of system clock view.
772 */
773 struct setting_class *view_system_clock_get_vclass(void)
774 {
775         return &_vclass;
776 }