811106bd297223036178d83d33c071fe5b511ddd
[profile/tv/apps/native/air_home.git] / src / view / view_recent.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.h"
25 #include "data_recent.h"
26 #include "datamgr.h"
27 #include "utils.h"
28
29 #define MESSAGE_NO_CONTENTS "No Contents"
30 #define PADDING_BOX 26
31
32 enum input_handler_type {
33         INPUT_HANDLER_TYPE_EO,
34         INPUT_HANDLER_TYPE_DELETE,
35         INPUT_HANDLER_TYPE_DISABLE_DELETE
36 };
37
38 enum recent_item_type {
39         RECENT_ITEM_ICON = 0x00,
40         RECENT_ITEM_PREVIEW = 0x01
41 };
42
43 struct _priv {
44         Evas_Object *win;
45         Evas_Object *base;
46         Evas_Object *del_btn;
47         Evas_Object *scr;
48         Evas_Object *box;
49         Eina_List *list;
50
51         struct _bar_item *cur;
52         struct datamgr *dm;
53 };
54
55 struct _bar_item {
56         Evas_Object *eo;
57
58         struct datamgr_item *di;
59         struct _priv *priv;
60 };
61
62 static void _focused(int id, void *data, Evas_Object *obj,
63                 Elm_Object_Item *item)
64 {
65         struct _bar_item *bi;
66
67         switch (id) {
68         case INPUT_HANDLER_TYPE_EO:
69                 if (!data)
70                         return;
71
72                 bi = data;
73                 bi->priv->cur = bi;
74                 /* fallthrought */
75         case INPUT_HANDLER_TYPE_DELETE:
76                 elm_object_signal_emit(obj, SIG_FOCUS, SRC_PROG);
77                 break;
78         default:
79                 return;
80         }
81 }
82
83 static void _unfocused(int id, void *data, Evas_Object *obj,
84                 Elm_Object_Item *item)
85 {
86         switch (id) {
87         case INPUT_HANDLER_TYPE_EO:
88         case INPUT_HANDLER_TYPE_DELETE:
89                 elm_object_signal_emit(obj, SIG_UNFOCUS, SRC_PROG);
90                 break;
91         default:
92                 return;
93         }
94 }
95
96 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
97                 Evas_Event_Key_Down *ev)
98 {
99         struct _priv *priv;
100         struct _bar_item *bi;
101
102         if (!data) {
103                 _ERR("Invalid argument");
104                 return;
105         }
106
107         switch (id) {
108         case INPUT_HANDLER_TYPE_EO:
109                 bi = data;
110                 priv = bi->priv;
111
112                 if (!strcmp(ev->keyname, KEY_DOWN) ||
113                                 !strcmp(ev->keyname, KEY_BACK) ||
114                                 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
115                         elm_object_signal_emit(priv->base, SIG_HIDE_RECENT,
116                                         SRC_PROG);
117                 } else if (!strcmp(ev->keyname, KEY_ENTER) ||
118                                 !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
119                         datamgr_select_item(priv->dm, bi->di);
120                 }
121                 break;
122         case INPUT_HANDLER_TYPE_DELETE:
123                 priv = data;
124
125                 if (!strcmp(ev->keyname, KEY_ENTER) ||
126                                 !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
127                         elm_object_signal_emit(priv->base, SIG_HIDE_RECENT,
128                                         SRC_PROG);
129                 } else if (!strcmp(ev->keyname, KEY_ENTER) ||
130                                 !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
131                         datamgr_clear_item(priv->dm);
132                         elm_object_signal_emit(priv->base, SIG_HIDE_RECENT,
133                                         SRC_PROG);
134                 } else if (!strcmp(ev->keyname, KEY_DOWN)) {
135                         if (!priv->cur)
136                                 priv->cur = eina_list_data_get(priv->list);
137                         elm_object_focus_set(priv->cur->eo, EINA_TRUE);
138                 }
139                 break;
140         case INPUT_HANDLER_TYPE_DISABLE_DELETE:
141                 priv = data;
142
143                 if (!strcmp(ev->keyname, KEY_DOWN) ||
144                                 !strcmp(ev->keyname, KEY_BACK) ||
145                                 !strcmp(ev->keyname, KEY_BACK_REMOTE)){
146                         elm_object_signal_emit(priv->base, SIG_HIDE_RECENT,
147                                         SRC_PROG);
148                 }
149                 break;
150         default:
151                 return;
152         }
153 }
154
155 static void _mouse_down(int id, void *data, Evas *e, Evas_Object *obj,
156                 Evas_Event_Mouse_Down *ev)
157 {
158         struct _bar_item *bi;
159         struct _priv *priv;
160
161         if (!data) {
162                 _ERR("Invalid argument");
163                 return;
164         }
165
166         switch (id) {
167         case INPUT_HANDLER_TYPE_EO:
168                 bi = data;
169                 priv = bi->priv;
170
171                 datamgr_select_item(priv->dm, bi->di);
172                 break;
173         case INPUT_HANDLER_TYPE_DELETE:
174                 priv = data;
175
176                 datamgr_clear_item(priv->dm);
177                 elm_object_signal_emit(priv->base, SIG_HIDE_RECENT,
178                                 SRC_PROG);
179                 break;
180         default:
181                 return;
182         }
183 }
184
185 static input_handler handler = {
186         .focused = _focused,
187         .unfocused = _unfocused,
188         .key_down = _key_down,
189         .mouse_down = _mouse_down
190 };
191
192 static void _hide_done(void *data, Evas_Object *obj, const char *emission,
193                 const char *source)
194 {
195         viewmgr_pop_view();
196 }
197
198 static void _add_delete_btn(struct _priv *priv, const char *ic_image,
199                 const char *focus_ic_image, enum input_handler_type type)
200 {
201         Evas_Object *btn, *ic, *focus_ic;
202
203         btn = utils_add_layout(priv->base, GRP_RECENT_DELETE, true,
204                         PART_RECENT_DELETE_ICON);
205         if (!btn) {
206                 _ERR("failed to add delete icon");
207                 return;
208         }
209         evas_object_show(btn);
210
211         ic = utils_add_icon(btn, ic_image, PART_RECENT_DELETE);
212         if (!ic) {
213                 _ERR("failed to add icon");
214                 evas_object_del(btn);
215                 return;
216         }
217
218         focus_ic = utils_add_icon(btn, focus_ic_image,
219                         PART_RECENT_DELETE_FOCUS);
220         if (!focus_ic) {
221                 _ERR("failed to add focus icon");
222                 evas_object_del(btn);
223                 return;
224         }
225
226         inputmgr_add_callback(btn, type, &handler, priv);
227
228         priv->del_btn = btn;
229 }
230
231 static Evas_Object *_create(Evas_Object *win, void *data)
232 {
233         struct _priv *priv;
234         struct datamgr *dm;
235         Evas_Object *base;
236
237         if (!win) {
238                 _ERR("Invalid argument");
239                 return NULL;
240         }
241
242         priv = calloc(1, sizeof(*priv));
243         if (!priv) {
244                 _ERR("failed to calloc priv");
245                 return NULL;
246         }
247
248         dm = datamgr_init(datamgr_recent_get_dclass(), VIEW_RECENT);
249         if (!dm) {
250                 _ERR("failed to initialize datamgr");
251                 free(priv);
252                 return NULL;
253         }
254
255         base = utils_add_layout(win, GRP_RECENT, false, NULL);
256         if (!base) {
257                 _ERR("failed to create base");
258                 datamgr_fini(dm);
259                 free(priv);
260                 return NULL;
261         }
262         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
263                         EVAS_HINT_EXPAND);
264         elm_win_resize_object_add(win, base);
265
266         priv->win = win;
267         priv->base = base;
268         priv->dm = dm;
269
270         viewmgr_set_view_data(VIEW_RECENT, priv);
271         elm_object_signal_callback_add(base, SIG_HIDE_RECENT_DONE, SRC_EDJE,
272                         _hide_done, NULL);
273
274         return base;
275 }
276
277 static struct _bar_item *_pack_item(struct _priv *priv, Evas_Object *box,
278                 struct datamgr_item *di)
279 {
280         Evas_Object *eo, *lbl, *sub_lbl, *thumb, *ic;
281         struct _bar_item *bi;
282         const char *group;
283
284         switch (di->type) {
285         case RECENT_ITEM_PREVIEW:
286                 group = GRP_RECENT_PREVIEW;
287                 break;
288         case RECENT_ITEM_ICON:
289                 group = GRP_RECENT_ICON;
290                 break;
291         default:
292                 return NULL;
293         }
294
295         bi = calloc(1, sizeof(*bi));
296         if (!bi) {
297                 _ERR("failed to calloc bar item");
298                 return NULL;
299         }
300
301         eo = utils_add_layout(box, group, true, NULL);
302         if (!eo) {
303                 _ERR("failed to add layout");
304                 free(bi);
305                 return NULL;
306         }
307         evas_object_show(eo);
308
309         thumb = utils_add_icon(eo, di->icon, PART_RECENT_THUMBNAIL);
310         if (!thumb) {
311                 _ERR("failed to add thumb");
312                 evas_object_del(eo);
313                 free(bi);
314                 return NULL;
315         }
316         elm_image_fill_outside_set(thumb, EINA_TRUE);
317
318         ic = utils_add_icon(eo, di->focus_icon, PART_RECENT_ICON);
319         if (!ic)
320                 _ERR("failed to add icon");
321
322         lbl = utils_add_label(eo, di->title, STYLE_LABEL_RECENT_TITLE,
323                         PART_RECENT_TITLE);
324         if (!lbl) {
325                 _ERR("failed to add title");
326                 evas_object_del(eo);
327                 free(bi);
328                 return NULL;
329         }
330
331         if(di->subtitle) {
332                 sub_lbl = utils_add_label(eo, di->subtitle,
333                                 STYLE_LABEL_RECENT_SUBTITLE,
334                                 PART_RECENT_SUBTITLE);
335                 if (!sub_lbl)
336                         _ERR("failed to add sub title");
337         }
338
339         elm_object_focus_next_object_set(eo, priv->del_btn, ELM_FOCUS_UP);
340         inputmgr_add_callback(eo, INPUT_HANDLER_TYPE_EO, &handler, bi);
341         elm_box_pack_end(box, eo);
342
343         bi->eo = eo;
344         bi->di = di;
345
346         return bi;
347 }
348
349 static void _load_recent(struct _priv *priv)
350 {
351         Eina_List *list, *l;
352         Evas_Object *scr, *box;
353         struct _bar_item *bi;
354         struct datamgr_item *di;
355
356         list = datamgr_get_items(priv->dm);
357         if (!list) {
358                 elm_object_part_text_set(priv->base, PART_RECENT_NO_CONTENTS,
359                                 MESSAGE_NO_CONTENTS);
360                 _add_delete_btn(priv, IMAGE_RECENT_DELETE_DIS,
361                                 IMAGE_RECENT_DELETE_DIS,
362                                 INPUT_HANDLER_TYPE_DISABLE_DELETE);
363                 return;
364         }
365
366         scr = utils_add_scroller(priv->base);
367         if (!scr) {
368                 _ERR("failed to add scroller");
369                 return;
370         }
371
372         box = utils_add_box(scr, true);
373         if (!box) {
374                 _ERR("failed to add box");
375                 evas_object_del(scr);
376                 return;
377         }
378         elm_object_content_set(scr, box);
379         elm_object_part_content_set(priv->base, PART_RECENT_CONTENTS, scr);
380         elm_object_part_text_set(priv->base, PART_RECENT_NO_CONTENTS, "");
381         elm_box_padding_set(box, PADDING_BOX * elm_config_scale_get(), 0);
382
383         _add_delete_btn(priv, IMAGE_RECENT_DELETE_NOR, IMAGE_RECENT_DELETE_FOC,
384                         INPUT_HANDLER_TYPE_DELETE);
385
386         EINA_LIST_FOREACH(list, l, di) {
387                 bi = _pack_item(priv, box, di);
388                 if (!bi)
389                         continue;
390
391                 bi->priv = priv;
392                 priv->list = eina_list_append(priv->list, bi);
393         }
394         priv->scr = scr;
395         priv->box = box;
396 }
397
398 static void _show(void *data)
399 {
400         struct _priv *priv;
401         struct _bar_item *bi;
402
403         if (!data) {
404                 _ERR("Invalid argument");
405                 return;
406         }
407
408         priv = data;
409
410         evas_object_show(priv->base);
411         elm_object_signal_emit(priv->base, SIG_SHOW_RECENT, SRC_PROG);
412
413         _load_recent(priv);
414
415         if (!priv->list) {
416                 elm_object_focus_set(priv->del_btn, EINA_TRUE);
417         } else {
418                 bi = eina_list_data_get(priv->list);
419                 elm_object_focus_set(bi->eo, EINA_TRUE);
420         }
421 }
422
423 static void _unload_recent(struct _priv *priv)
424 {
425         struct _bar_item *bi;
426
427         EINA_LIST_FREE(priv->list, bi) {
428                 inputmgr_remove_callback(bi->eo, &handler);
429                 evas_object_del(bi->eo);
430                 free(bi);
431         }
432
433         elm_box_clear(priv->box);
434         evas_object_del(priv->scr);
435         inputmgr_remove_callback(priv->del_btn, &handler);
436         evas_object_del(priv->del_btn);
437
438         priv->del_btn = NULL;
439         priv->box = NULL;
440         priv->scr = NULL;
441         priv->list = NULL;
442 }
443
444 static void _hide(void *data)
445 {
446         struct _priv *priv;
447
448         if (!data) {
449                 _ERR("Invalid argument");
450                 return;
451         }
452
453         priv = data;
454
455         _unload_recent(priv);
456
457         evas_object_hide(priv->base);
458 }
459
460 static void _destroy(void *data)
461 {
462         struct _priv *priv;
463
464         if (!data) {
465                 _ERR("Invalid argument");
466                 return;
467         }
468
469         priv = data;
470
471         _unload_recent(priv);
472
473         datamgr_fini(priv->dm);
474         evas_object_del(priv->base);
475         free(priv);
476 }
477
478 static view_class vclass = {
479         .view_id = VIEW_RECENT,
480         .create = _create,
481         .show = _show,
482         .hide = _hide,
483         .destroy = _destroy
484 };
485
486 view_class *view_recent_get_vclass(void)
487 {
488         return &vclass;
489 }
490