set elm_image_fill_outside_set in utils
[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
317         ic = utils_add_icon(eo, di->focus_icon, PART_RECENT_ICON);
318         if (!ic)
319                 _ERR("failed to add icon");
320
321         lbl = utils_add_label(eo, di->title, STYLE_LABEL_RECENT_TITLE,
322                         PART_RECENT_TITLE);
323         if (!lbl) {
324                 _ERR("failed to add title");
325                 evas_object_del(eo);
326                 free(bi);
327                 return NULL;
328         }
329
330         if(di->subtitle) {
331                 sub_lbl = utils_add_label(eo, di->subtitle,
332                                 STYLE_LABEL_RECENT_SUBTITLE,
333                                 PART_RECENT_SUBTITLE);
334                 if (!sub_lbl)
335                         _ERR("failed to add sub title");
336         }
337
338         elm_object_focus_next_object_set(eo, priv->del_btn, ELM_FOCUS_UP);
339         inputmgr_add_callback(eo, INPUT_HANDLER_TYPE_EO, &handler, bi);
340         elm_box_pack_end(box, eo);
341
342         bi->eo = eo;
343         bi->di = di;
344
345         return bi;
346 }
347
348 static void _load_recent(struct _priv *priv)
349 {
350         Eina_List *list, *l;
351         Evas_Object *scr, *box;
352         struct _bar_item *bi;
353         struct datamgr_item *di;
354
355         list = datamgr_get_items(priv->dm);
356         if (!list) {
357                 elm_object_part_text_set(priv->base, PART_RECENT_NO_CONTENTS,
358                                 MESSAGE_NO_CONTENTS);
359                 _add_delete_btn(priv, IMAGE_RECENT_DELETE_DIS,
360                                 IMAGE_RECENT_DELETE_DIS,
361                                 INPUT_HANDLER_TYPE_DISABLE_DELETE);
362                 return;
363         }
364
365         scr = utils_add_scroller(priv->base);
366         if (!scr) {
367                 _ERR("failed to add scroller");
368                 return;
369         }
370
371         box = utils_add_box(scr, true);
372         if (!box) {
373                 _ERR("failed to add box");
374                 evas_object_del(scr);
375                 return;
376         }
377         elm_object_content_set(scr, box);
378         elm_object_part_content_set(priv->base, PART_RECENT_CONTENTS, scr);
379         elm_object_part_text_set(priv->base, PART_RECENT_NO_CONTENTS, "");
380         elm_box_padding_set(box, PADDING_BOX * elm_config_scale_get(), 0);
381
382         _add_delete_btn(priv, IMAGE_RECENT_DELETE_NOR, IMAGE_RECENT_DELETE_FOC,
383                         INPUT_HANDLER_TYPE_DELETE);
384
385         EINA_LIST_FOREACH(list, l, di) {
386                 bi = _pack_item(priv, box, di);
387                 if (!bi)
388                         continue;
389
390                 bi->priv = priv;
391                 priv->list = eina_list_append(priv->list, bi);
392         }
393         priv->scr = scr;
394         priv->box = box;
395 }
396
397 static void _show(void *data)
398 {
399         struct _priv *priv;
400         struct _bar_item *bi;
401
402         if (!data) {
403                 _ERR("Invalid argument");
404                 return;
405         }
406
407         priv = data;
408
409         evas_object_show(priv->base);
410         elm_object_signal_emit(priv->base, SIG_SHOW_RECENT, SRC_PROG);
411
412         _load_recent(priv);
413
414         if (!priv->list) {
415                 elm_object_focus_set(priv->del_btn, EINA_TRUE);
416         } else {
417                 bi = eina_list_data_get(priv->list);
418                 elm_object_focus_set(bi->eo, EINA_TRUE);
419         }
420 }
421
422 static void _unload_recent(struct _priv *priv)
423 {
424         struct _bar_item *bi;
425
426         EINA_LIST_FREE(priv->list, bi) {
427                 inputmgr_remove_callback(bi->eo, &handler);
428                 evas_object_del(bi->eo);
429                 free(bi);
430         }
431
432         elm_box_clear(priv->box);
433         evas_object_del(priv->scr);
434         inputmgr_remove_callback(priv->del_btn, &handler);
435         evas_object_del(priv->del_btn);
436
437         priv->del_btn = NULL;
438         priv->box = NULL;
439         priv->scr = NULL;
440         priv->list = NULL;
441 }
442
443 static void _hide(void *data)
444 {
445         struct _priv *priv;
446
447         if (!data) {
448                 _ERR("Invalid argument");
449                 return;
450         }
451
452         priv = data;
453
454         _unload_recent(priv);
455
456         evas_object_hide(priv->base);
457 }
458
459 static void _destroy(void *data)
460 {
461         struct _priv *priv;
462
463         if (!data) {
464                 _ERR("Invalid argument");
465                 return;
466         }
467
468         priv = data;
469
470         _unload_recent(priv);
471
472         datamgr_fini(priv->dm);
473         evas_object_del(priv->base);
474         free(priv);
475 }
476
477 static view_class vclass = {
478         .view_id = VIEW_RECENT,
479         .create = _create,
480         .show = _show,
481         .hide = _hide,
482         .destroy = _destroy
483 };
484
485 view_class *view_recent_get_vclass(void)
486 {
487         return &vclass;
488 }
489