add key input handler in view_home
[profile/tv/apps/native/air_home.git] / src / view / view_home.c
1 /*
2
3  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <Elementary.h>
19 #include <app_debug.h>
20 #include <viewmgr.h>
21 #include <inputmgr.h>
22
23 #include "defs.h"
24 #include "view_home.h"
25 #include "data_home.h"
26 #include "datamgr.h"
27
28 struct _priv {
29         Evas_Object *win;
30         Evas_Object *base;
31         Eina_List *list;
32
33         struct datamgr *dm;
34         struct bar_item *foc;
35 };
36
37 struct bar_item {
38         Evas_Object *eo;
39
40         struct _priv *priv;
41 };
42
43 static inline Evas_Object *_add_layout(Evas_Object *base, const char *group,
44                 bool focus_allow)
45 {
46         Evas_Object *ly;
47
48         if (!base || !group) {
49                 _ERR("Invalid argument");
50                 return NULL;
51         }
52
53         ly = elm_layout_add(base);
54         if (!ly) {
55                 _ERR("failed to add layout");
56                 return false;
57         }
58         elm_layout_file_set(ly, EDJEFILE, group);
59         if (focus_allow)
60                 elm_object_focus_allow_set(ly, EINA_TRUE);
61         evas_object_show(ly);
62
63         return ly;
64 }
65
66 static inline Evas_Object *_add_icon(Evas_Object *eo, const char *file, const char *part)
67 {
68         Evas_Object *ic;
69
70         if (!eo || !file || !part) {
71                 _ERR("Invalid argument");
72                 return NULL;
73         }
74
75         ic = elm_icon_add(eo);
76         if (!ic) {
77                 _ERR("failed to add icon");
78                 return NULL;
79         }
80
81         elm_image_file_set(ic, file, NULL);
82         elm_object_part_content_set(eo, part, ic);
83
84         return ic;
85 }
86
87 static inline Evas_Object *_add_label(Evas_Object *eo, char *name,
88                 const char *style, const char *part)
89 {
90         Evas_Object *lbl;
91         const char *s;
92
93         if (!eo || !name || !style || !part) {
94                 _ERR("Invalid argument");
95                 return NULL;
96         }
97
98         lbl = elm_label_add(eo);
99         if (!lbl) {
100                 _ERR("failed to add label");
101                 return NULL;
102         }
103         elm_object_style_set(lbl, style);
104         s = edje_object_data_get(elm_layout_edje_get(eo), TITLE_WIDTH);
105         if (s)
106                 elm_label_wrap_width_set(lbl, atoi(s));
107         elm_object_text_set(lbl, name);
108         elm_object_part_content_set(eo, part, lbl);
109
110         return lbl;
111 }
112
113 static inline Evas_Object *_add_bg(Evas_Object *eo, const char *part)
114 {
115         Evas_Object *bg;
116
117         if (!eo || !part) {
118                 _ERR("Invalid argument");
119                 return NULL;
120         }
121
122         bg = evas_object_rectangle_add(evas_object_evas_get(eo));
123         if (!bg) {
124                 _ERR("failed to add label");
125                 return NULL;
126         }
127
128         evas_object_color_set(bg, COLOR_DEFAULT_R, COLOR_DEFAULT_G,
129                         COLOR_DEFAULT_B, COLOR_DEFAULT_A);
130         elm_object_part_content_set(eo, part, bg);
131
132         return bg;
133 }
134
135 static bool _add_navigations(Evas_Object *base)
136 {
137         Evas_Object *ly;
138
139         if (!base) {
140                 _ERR("Invalid argument");
141                 return false;
142         }
143
144         ly = _add_layout(base, GRP_HOME_DOWN_ARROW, true);
145         if (!ly) {
146                 _ERR("failed to add layout");
147                 return false;
148         }
149         elm_object_part_content_set(base, PART_HOME_DOWN_ARROW, ly);
150
151         ly = _add_layout(base, GRP_HOME_UP_ARROW, true);
152         if (!ly) {
153                 _ERR("failed to add layout");
154                 return false;
155         }
156         elm_object_part_content_set(base, PART_HOME_UP_ARROW, ly);
157
158         return true;
159 }
160
161 static void _focused(int id, void *data, Evas_Object *obj, Elm_Object_Item *item)
162 {
163         struct _priv *priv;
164         struct bar_item *bi;
165
166         if (!data) {
167                 _ERR("Invalid argument");
168                 return;
169         }
170
171         bi = data;
172         priv = bi->priv;
173         priv->foc = bi;
174
175         elm_object_signal_emit(obj, SIG_FOCUS, SRC_PROG);
176 }
177
178 static void _unfocused(int id, void *data, Evas_Object *obj, Elm_Object_Item *item)
179 {
180         elm_object_signal_emit(obj, SIG_UNFOCUS, SRC_PROG);
181 }
182
183 static input_handler eo_handler = {
184         .focused = _focused,
185         .unfocused = _unfocused
186 };
187
188 static struct bar_item *_pack_bar_item(struct _priv *priv, Evas_Object *box,
189                 struct datamgr_item *di)
190 {
191         struct bar_item *bi;
192         Evas_Object *eo, *ic, *focus_ic, *lbl, *focus_lbl, *bg;
193
194         if (!priv || !box || !di) {
195                 _ERR("Invalid argument");
196                 return NULL;
197         }
198
199         bi = calloc(1, sizeof(*bi));
200         if (!bi) {
201                 _ERR("failed to calloc bar item");
202                 return NULL;
203         }
204
205         eo = _add_layout(box, GRP_HOME_ITEM, true);
206         if (!eo) {
207                 _ERR("failed to add layout");
208                 free(bi);
209                 return NULL;
210         }
211
212         ic = _add_icon(eo, di->icon, PART_HOME_ITEM_ICON);
213         if (!ic)
214                 goto err;
215
216         focus_ic = _add_icon(eo, di->focus_icon, PART_HOME_ITEM_ICON_FOCUS);
217         if (!focus_ic)
218                 goto err;
219
220         lbl = _add_label(eo, di->title, STYLE_LABEL_TITLE, PART_HOME_ITEM_TITLE);
221         if (!lbl)
222                 goto err;
223
224         focus_lbl = _add_label(eo, di->title, STYLE_LABEL_TITLE_FOCUS,
225                         PART_HOME_ITEM_TITLE_FOCUS);
226         if (!focus_lbl)
227                 goto err;
228
229         bg = _add_bg(eo, PART_HOME_ITEM_BG);
230         if (!bg)
231                 goto err;
232
233         inputmgr_add_callback(eo, 0, &eo_handler, bi);
234         elm_box_pack_end(box, eo);
235
236         bi->priv = priv;
237         bi->eo = eo;
238
239         return bi;
240 err:
241         _ERR("failed to add home item");
242         evas_object_del(eo);
243         free(bi);
244
245         return NULL;
246 }
247
248 static bool _add_home_menu(struct _priv *priv, Evas_Object *base)
249 {
250         Eina_List *list, *l;
251         Evas_Object *scr, *box;
252         struct bar_item *bi;
253         struct datamgr_item *di;
254
255         if (!priv || !base) {
256                 _ERR("Invalid argument");
257                 return false;
258         }
259
260         scr = elm_scroller_add(base);
261         if (!scr) {
262                 _ERR("failed to add scroller");
263                 return false;
264         }
265         elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF,
266                         ELM_SCROLLER_POLICY_OFF);
267
268         box = elm_box_add(scr);
269         if (!box) {
270                 _ERR("failed to add box");
271                 evas_object_del(scr);
272                 return false;
273         }
274         evas_object_show(box);
275         elm_object_content_set(scr, box);
276         elm_object_part_content_set(base, PART_HOME_MENU_BAR, scr);
277         elm_box_horizontal_set(box, EINA_TRUE);
278
279         list = datamgr_get_items(priv->dm);
280         if (!list) {
281                 _ERR("failed to load list");
282                 evas_object_del(scr);
283                 return false;
284         }
285
286         EINA_LIST_FOREACH(list, l, di) {
287                 bi = _pack_bar_item(priv, box, di);
288                 if (!bi)
289                         continue;
290
291                 priv->list = eina_list_append(priv->list, bi);
292         }
293
294         return true;
295 }
296
297 static bool _add_home(struct _priv *priv, Evas_Object *base)
298 {
299         if (!priv || !base) {
300                 _ERR("Invalid argument");
301                 return false;
302         }
303
304         if (!_add_navigations(base)) {
305                 _ERR("failed to add navigations");
306                 return false;
307         }
308
309         if (!_add_home_menu(priv, base)) {
310                 _ERR("failed to add menu");
311                 return false;
312         }
313
314         return true;
315 }
316
317 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
318                 Evas_Event_Key_Down *ev)
319 {
320         if (!data) {
321                 _ERR("Invalid argument");
322                 return;
323         }
324
325         if (!strcmp(ev->keyname, KEY_DOWN)) {
326                 viewmgr_push_view(VIEW_RECENT);
327         } else if (!strcmp(ev->keyname, KEY_UP)) {
328                 /* It should be implemented later */
329         } else if (!strcmp(ev->keyname, KEY_ENTER) ||
330                         !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
331                 /* It should be implemented later */
332         } else if (!strcmp(ev->keyname, KEY_BACK) ||
333                         !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
334                 /* It should be implemented later */
335         }
336 }
337
338 static input_handler base_handler = {
339         .key_down = _key_down
340 };
341
342 static Evas_Object *_create(Evas_Object *win, void *data)
343 {
344         struct _priv *priv;
345         struct datamgr *dm;
346         Evas_Object *base;
347
348         if (!win) {
349                 _ERR("Invalid argument");
350                 return NULL;
351         }
352
353         priv = calloc(1, sizeof(*priv));
354         if (!priv) {
355                 _ERR("failed to calloc priv");
356                 return NULL;
357         }
358
359         dm = datamgr_init(datamgr_home_get_dclass(), VIEW_HOME);
360         if (!dm) {
361                 _ERR("failed to initialize datamgr");
362                 free(priv);
363                 return NULL;
364         }
365
366         base =_add_layout(win, GRP_HOME, false);
367         if (!base) {
368                 _ERR("failed to create base");
369                 datamgr_fini(dm);
370                 free(priv);
371                 return NULL;
372         }
373         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
374         elm_win_resize_object_add(win, base);
375
376         priv->win = win;
377         priv->base = base;
378         priv->dm = dm;
379
380         if (!_add_home(priv, base)) {
381                 _ERR("failed to load home");
382                 datamgr_fini(dm);
383                 evas_object_del(base);
384                 free(priv);
385                 return NULL;
386         }
387
388         viewmgr_set_view_data(VIEW_HOME, priv);
389         inputmgr_add_callback(base, 0, &base_handler, priv);
390
391         return base;
392 }
393
394 static void _show(void *data)
395 {
396         struct _priv *priv;
397
398         if (!data) {
399                 _ERR("Invalid argument");
400                 return;
401         }
402
403         priv = data;
404
405         evas_object_show(priv->base);
406         elm_object_signal_emit(priv->base, SIG_SHOW_NAVIGATION, SRC_PROG);
407
408         if (!priv->foc)
409                 priv->foc = eina_list_data_get(priv->list);
410         elm_object_focus_set(priv->foc->eo, EINA_TRUE);
411 }
412
413 static void _hide(void *data)
414 {
415         struct _priv *priv;
416
417         if (!data) {
418                 _ERR("Invalid argument");
419                 return;
420         }
421
422         priv = data;
423
424         evas_object_hide(priv->base);
425 }
426
427 static void _destroy(void *data)
428 {
429         struct _priv *priv;
430         struct bar_item *bi;
431
432         if (!data) {
433                 _ERR("Invalid argument");
434                 return;
435         }
436
437         priv = data;
438
439         EINA_LIST_FREE(priv->list, bi) {
440                 inputmgr_remove_callback(bi->eo, &eo_handler);
441                 evas_object_del(bi->eo);
442                 free(bi);
443         }
444
445         datamgr_fini(priv->dm);
446         inputmgr_remove_callback(priv->base, &base_handler);
447         evas_object_del(priv->base);
448
449         priv->list = NULL;
450         free(priv);
451 }
452
453 static view_class vclass = {
454         .view_id = VIEW_HOME,
455         .create = _create,
456         .show = _show,
457         .hide = _hide,
458         .destroy = _destroy
459 };
460
461 view_class *view_home_get_vclass(void)
462 {
463         return &vclass;
464 }
465