set elm_image_fill_outside_set in utils
[profile/tv/apps/native/air_home.git] / src / view / view_photo.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_photo.h"
26 #include "utils.h"
27
28 #define GENGRID_ITEM_SIZE 200
29
30 enum input_handler_type {
31         INPUT_HANDLER_TYPE_GRID,
32         INPUT_HANDLER_TYPE_NO_CONTENTS,
33         INPUT_HANDLER_TYPE_DONE,
34         INPUT_HANDLER_TYPE_CANCEL
35 };
36
37 struct _priv {
38         Evas_Object *win;
39         Evas_Object *base;
40         Evas_Object *grid;
41         Evas_Object *ly;
42         Evas_Object *popup;
43         Elm_Gengrid_Item_Class *grid_ic;
44         Eina_List *plist;
45         Elm_Object_Item *cur;
46
47         struct datamgr *dm;
48 };
49
50 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
51                 Evas_Event_Key_Down *ev);
52
53 static void _mouse_up(int id, void *data, Evas *e, Evas_Object *obj,
54                 Evas_Event_Mouse_Up *ev);
55
56 static input_handler handler = {
57         .key_down = _key_down,
58         .mouse_up = _mouse_up
59 };
60
61 static void _delete_popup(struct _priv *priv, Evas_Object *obj)
62 {
63         inputmgr_remove_callback(obj, &handler);
64         evas_object_del(priv->popup);
65         priv->popup = NULL;
66 }
67
68 static void _select_done(struct _priv *priv, Evas_Object *obj)
69 {
70         char *thumb;
71
72         _delete_popup(priv, obj);
73         elm_object_focus_allow_set(priv->grid, EINA_TRUE);
74         thumb = elm_object_item_data_get(priv->cur);
75         if (thumb) {
76                 viewmgr_update_view(VIEW_USER_EDIT,
77                                 UPDATE_TYPE_PHOTO, thumb);
78                                 viewmgr_pop_view();
79         }
80 }
81
82 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
83                 Evas_Event_Key_Down *ev)
84 {
85         struct _priv *priv = data;
86
87         switch (id) {
88         case INPUT_HANDLER_TYPE_GRID:
89                 /* fallthrough */
90         case INPUT_HANDLER_TYPE_NO_CONTENTS:
91                 if (!strcmp(ev->keyname, KEY_BACK) ||
92                                 !strcmp(ev->keyname, KEY_BACK_REMOTE))
93                         viewmgr_pop_view();
94                 break;
95         case INPUT_HANDLER_TYPE_DONE:
96                 if (!data)
97                         return;
98
99                 priv = data;
100                 if (!strcmp(ev->keyname, KEY_ENTER) ||
101                                 !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
102                         _select_done(priv, obj);
103                 } else if (!strcmp(ev->keyname, KEY_BACK) ||
104                                 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
105                         _delete_popup(priv, obj);
106                         elm_object_focus_allow_set(priv->grid, EINA_TRUE);
107                         elm_object_focus_set(priv->grid, EINA_TRUE);
108                 }
109                 break;
110         case INPUT_HANDLER_TYPE_CANCEL:
111                 if (!data)
112                         return;
113
114                 priv = data;
115                 if (!strcmp(ev->keyname, KEY_ENTER) ||
116                                 !strcmp(ev->keyname, KEY_ENTER_REMOTE) ||
117                                 !strcmp(ev->keyname, KEY_BACK) ||
118                                 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
119                         _delete_popup(priv, obj);
120                         elm_object_focus_allow_set(priv->grid, EINA_TRUE);
121                         elm_object_focus_set(priv->grid, EINA_TRUE);
122                 }
123                 break;
124         default:
125                 return;
126         }
127 }
128
129 static void _mouse_up(int id, void *data, Evas *e, Evas_Object *obj,
130                 Evas_Event_Mouse_Up *ev)
131 {
132         struct _priv *priv;
133
134         switch (id) {
135         case INPUT_HANDLER_TYPE_DONE:
136                 if (!data)
137                         return;
138
139                 priv = data;
140                 _select_done(priv, obj);
141                 break;
142         case INPUT_HANDLER_TYPE_CANCEL:
143                 if (!data)
144                         return;
145
146                 priv = data;
147                 _delete_popup(priv, obj);
148                 elm_object_focus_allow_set(priv->grid, EINA_TRUE);
149                 elm_object_focus_set(priv->grid, EINA_TRUE);
150                 break;
151         default:
152                 return;
153         }
154 }
155
156 static Evas_Object *_create(Evas_Object *win, void *data)
157 {
158         struct _priv *priv;
159         struct datamgr *dm;
160         Evas_Object *base;
161
162         if (!win) {
163                 _ERR("Invalid argument");
164                 return NULL;
165         }
166
167         priv = calloc(1, sizeof(*priv));
168         if (!priv) {
169                 _ERR("failed to calloc priv");
170                 return NULL;
171         }
172
173         dm = datamgr_init(datamgr_photo_get_dclass(), VIEW_PHOTO);
174         if (!dm) {
175                 _ERR("failed to initialize datamgr");
176                 free(priv);
177                 return NULL;
178         }
179
180         base = utils_add_layout(win, GRP_PHOTO, false, NULL);
181         if (!base) {
182                 _ERR("failed to create base");
183                 datamgr_fini(dm);
184                 free(priv);
185                 return NULL;
186         }
187         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
188                         EVAS_HINT_EXPAND);
189         elm_win_resize_object_add(win, base);
190
191         priv->win = win;
192         priv->base = base;
193         priv->dm = dm;
194
195         viewmgr_set_view_data(VIEW_PHOTO, priv);
196
197         return base;
198 }
199
200 static void _load_no_content(struct _priv *priv)
201 {
202         Evas_Object *ly;
203
204         ly = utils_add_layout(priv->base, GRP_PHOTO_NO_CONTENT, true,
205                         PART_PHOTO_LIST);
206         if (!ly) {
207                 _ERR("failed to create layout");
208                 return;
209         }
210         evas_object_show(ly);
211         inputmgr_add_callback(ly, INPUT_HANDLER_TYPE_NO_CONTENTS, &handler,
212                         NULL);
213
214         priv->ly = ly;
215 }
216
217 static Evas_Object *_add_photo_grid(struct _priv *priv)
218 {
219         Evas_Object *grid;
220
221         grid = elm_gengrid_add(priv->base);
222         if (!grid) {
223                 _ERR("failed to add gend grid");
224                 return NULL;
225         }
226         evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND,
227                         EVAS_HINT_EXPAND);
228         elm_object_part_content_set(priv->base, PART_PHOTO_LIST, grid);
229         elm_gengrid_select_mode_set(grid, ELM_OBJECT_SELECT_MODE_ALWAYS);
230         elm_gengrid_multi_select_set(grid, EINA_FALSE);
231         elm_gengrid_item_size_set(grid,
232                         GENGRID_ITEM_SIZE * elm_config_scale_get(),
233                         GENGRID_ITEM_SIZE * elm_config_scale_get());
234         elm_gengrid_horizontal_set(grid, EINA_TRUE);
235         elm_scroller_policy_set(grid, ELM_SCROLLER_POLICY_OFF,
236                         ELM_SCROLLER_POLICY_OFF);
237         elm_gengrid_align_set(grid, 0.0, 0.5);
238         evas_object_show(grid);
239
240         inputmgr_add_callback(grid, INPUT_HANDLER_TYPE_GRID, &handler, priv);
241
242         return grid;
243 }
244
245 static Evas_Object *_get_grid_content(void *data, Evas_Object *obj,
246                 const char *part)
247 {
248         Evas_Object *img = NULL;
249
250         if (!strcmp(part, PART_SWALLOW_ICON)) {
251                 img = utils_add_icon(obj, data, NULL);
252                 if (!img) {
253                         _ERR("failed to add image");
254                         return NULL;
255                 }
256         }
257
258         return img;
259 }
260
261 static void _add_viewer_popup(struct _priv *priv, char *file)
262 {
263         Evas_Object *popup, *ly, *cancel_btn, *done_btn, *img;
264
265         popup = utils_add_popup(priv->base, NULL, NULL);
266         if (!popup) {
267                 _ERR("failed to add popup");
268                 return;
269         }
270
271         ly = utils_add_layout(popup, GRP_PHOTO_VIEWER, false,
272                         PART_SWALLOW_CONTENT);
273         if (!ly) {
274                 _ERR("failed to add layout");
275                 evas_object_del(popup);
276                 return;
277         }
278
279         cancel_btn = utils_add_button(ly, MESSAGE_CANCEL,
280                         PART_PHOTO_VIEWER_CANCEL);
281         if (!cancel_btn) {
282                 _ERR("failed to add cancel button");
283                 evas_object_del(popup);
284                 return;
285         }
286         inputmgr_add_callback(cancel_btn, INPUT_HANDLER_TYPE_CANCEL, &handler,
287                         priv);
288
289         done_btn = utils_add_button(ly, MESSAGE_DONE, PART_PHOTO_VIEWER_DONE);
290         if (!done_btn) {
291                 _ERR("failed to add done button");
292                 evas_object_del(popup);
293                 return;
294         }
295         inputmgr_add_callback(done_btn, INPUT_HANDLER_TYPE_DONE, &handler,
296                         priv);
297
298         elm_object_focus_set(cancel_btn, EINA_TRUE);
299
300         img = utils_add_icon(ly, file, PART_PHOTO_VIEWER);
301         if (!img) {
302                 _ERR("failed to add icon");
303                 evas_object_del(popup);
304                 return;
305         }
306
307         elm_object_focus_set(cancel_btn, EINA_TRUE);
308         priv->popup = popup;
309 }
310
311 static void _select_item(void *data, Evas_Object *obj, void *ei)
312 {
313         struct _priv *priv = data;
314         char *thumb;
315
316         thumb = elm_object_item_data_get(ei);
317         if (!thumb) {
318                 _ERR("failed to get data");
319                 return;
320         }
321
322         elm_object_focus_allow_set(priv->grid, EINA_FALSE);
323         _add_viewer_popup(priv, thumb);
324
325         priv->cur = ei;
326 }
327
328 static bool _add_photo_item(struct _priv *priv, Evas_Object *grid,
329                 Eina_List *dlist)
330 {
331         Elm_Gengrid_Item_Class *ic;
332         Elm_Object_Item *item;
333         Eina_List *l;
334         char *thumb;
335
336         elm_gengrid_clear(grid);
337
338         ic = elm_gengrid_item_class_new();
339         if (!ic) {
340                 _ERR("failed to add gengrid item class");
341                 return false;
342         }
343
344         ic->item_style = STYLE_GENGRID_ITEM;
345         ic->func.text_get = NULL;
346         ic->func.content_get = _get_grid_content;
347         ic->func.state_get = NULL;
348         ic->func.del = NULL;
349
350         EINA_LIST_FOREACH(dlist, l, thumb) {
351                 item = elm_gengrid_item_append(grid, ic, thumb,
352                                 _select_item, priv);
353                 if (!item)
354                         continue;
355
356                 elm_object_item_data_set(item, thumb);
357                 priv->plist = eina_list_append(priv->plist, item);
358         }
359
360         priv->cur = elm_gengrid_first_item_get(grid);
361         priv->grid_ic = ic;
362
363         return true;
364 }
365
366 static void _load_photo(struct _priv *priv)
367 {
368         Eina_List *dlist;
369         Evas_Object *grid;
370
371         dlist = datamgr_get_items(priv->dm);
372         if (!dlist) {
373                 _load_no_content(priv);
374                 return;
375         }
376
377         grid = _add_photo_grid(priv);
378         if (!grid) {
379                 _ERR("failed to add grid");
380                 return;
381         }
382
383         if (!_add_photo_item(priv, grid, dlist)) {
384                 _ERR("failed to add photo item");
385                 evas_object_del(grid);
386                 _load_no_content(priv);
387                 return;
388         }
389
390         elm_win_focus_highlight_enabled_set(priv->win, EINA_TRUE);
391         priv->grid = grid;
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
407         _load_photo(priv);
408
409         if (priv->ly)
410                 elm_object_focus_set(priv->ly, EINA_TRUE);
411         else
412                 elm_object_focus_set(priv->grid, EINA_TRUE);
413 }
414
415 static void _hide(void *data)
416 {
417         struct _priv *priv;
418
419         if (!data) {
420                 _ERR("Invalid argument");
421                 return;
422         }
423
424         priv = data;
425         if (priv->ly) {
426                 inputmgr_remove_callback(priv->ly, &handler);
427                 evas_object_del(priv->ly);
428                 priv->ly = NULL;
429         } else {
430                 elm_gengrid_item_class_free(priv->grid_ic);
431                 inputmgr_remove_callback(priv->grid, &handler);
432                 evas_object_del(priv->grid);
433                 priv->grid = NULL;
434         }
435
436         evas_object_hide(priv->base);
437         elm_win_focus_highlight_enabled_set(priv->win, EINA_FALSE);
438 }
439
440 static void _destroy(void *data)
441 {
442         struct _priv *priv;
443
444         if (!data) {
445                 _ERR("Invalid argument");
446                 return;
447         }
448
449         priv = data;
450
451         evas_object_del(priv->base);
452         free(priv);
453 }
454
455 static view_class vclass = {
456         .view_id = VIEW_PHOTO,
457         .create = _create,
458         .show = _show,
459         .hide = _hide,
460         .destroy = _destroy
461 };
462
463 view_class *view_photo_get_vclass(void)
464 {
465         return &vclass;
466 }