544e17ec65eaafbc4367adf5059dd3ff082a0c5a
[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 Evas_Object *_create(Evas_Object *win, void *data)
318 {
319         struct _priv *priv;
320         struct datamgr *dm;
321         Evas_Object *base;
322
323         if (!win) {
324                 _ERR("Invalid argument");
325                 return NULL;
326         }
327
328         priv = calloc(1, sizeof(*priv));
329         if (!priv) {
330                 _ERR("failed to calloc priv");
331                 return NULL;
332         }
333
334         dm = datamgr_init(datamgr_home_get_dclass(), VIEW_HOME);
335         if (!dm) {
336                 _ERR("failed to initialize datamgr");
337                 free(priv);
338                 return NULL;
339         }
340
341         base =_add_layout(win, GRP_HOME, false);
342         if (!base) {
343                 _ERR("failed to create base");
344                 datamgr_fini(dm);
345                 free(priv);
346                 return NULL;
347         }
348         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
349         elm_win_resize_object_add(win, base);
350
351         priv->win = win;
352         priv->base = base;
353         priv->dm = dm;
354
355         if (!_add_home(priv, base)) {
356                 _ERR("failed to load home");
357                 datamgr_fini(dm);
358                 evas_object_del(base);
359                 free(priv);
360                 return NULL;
361         }
362
363         viewmgr_set_view_data(VIEW_HOME, priv);
364
365         return base;
366 }
367
368 static void _show(void *data)
369 {
370         struct _priv *priv;
371
372         if (!data) {
373                 _ERR("Invalid argument");
374                 return;
375         }
376
377         priv = data;
378
379         evas_object_show(priv->base);
380         elm_object_signal_emit(priv->base, SIG_SHOW_NAVIGATION, SRC_PROG);
381
382         if (!priv->foc)
383                 priv->foc = eina_list_data_get(priv->list);
384         elm_object_focus_set(priv->foc->eo, EINA_TRUE);
385 }
386
387 static void _hide(void *data)
388 {
389         struct _priv *priv;
390
391         if (!data) {
392                 _ERR("Invalid argument");
393                 return;
394         }
395
396         priv = data;
397
398         evas_object_hide(priv->base);
399 }
400
401 static void _destroy(void *data)
402 {
403         struct _priv *priv;
404         struct bar_item *bi;
405
406         if (!data) {
407                 _ERR("Invalid argument");
408                 return;
409         }
410
411         priv = data;
412
413         EINA_LIST_FREE(priv->list, bi) {
414                 inputmgr_remove_callback(bi->eo, &eo_handler);
415                 evas_object_del(bi->eo);
416                 free(bi);
417         }
418
419         datamgr_fini(priv->dm);
420         evas_object_del(priv->base);
421
422         priv->list = NULL;
423         free(priv);
424 }
425
426 static view_class vclass = {
427         .view_id = VIEW_HOME,
428         .create = _create,
429         .show = _show,
430         .hide = _hide,
431         .destroy = _destroy
432 };
433
434 view_class *view_home_get_vclass(void)
435 {
436         return &vclass;
437 }
438