735b3dedc30dd21a36e78eec2e6af3f024bf9bcf
[apps/home/gallery.git] / src / features / gl-popup.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *     http://www.tizenopensource.org/license
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16
17 #include <appsvc.h>
18 #include "gallery.h"
19 #include "gl-popup.h"
20 #include "gl-ui-util.h"
21 #include "gl-util.h"
22 #include "gl-debug.h"
23 #include "gl-listview.h"
24 #include "gl-progressbar.h"
25 #include "gl-strings.h"
26 #include "gl-button.h"
27
28 #define GL_POPUP_OBJ_DATA_KEY "popup_list_data"
29 #define GL_GENLIST_ITEM_STYLE_1TEXT "1text"
30 #define GL_GENLIST_ITEM_STYLE_1TEXT_1ICON "1text.1icon"
31 #define GL_GENLIST_ITEM_STYLE_1TEXT_1ICON_2 "1text.1icon.2"
32 #define GL_POPUP_STYLE_MIN_MENUSTYLE "min_menustyle"
33
34 #define GL_POPUP_MENUSTYLE_WIDTH (614*elm_config_scale_get())
35 #define GL_POPUP_MENUSTYLE_HEIGHT(x) ((113*x-1)*elm_config_scale_get())
36 #define GL_POPUP_MENUSTYLE_HEIGHT_MAX (408*elm_config_scale_get())
37
38 #define GL_POPUP_TIMEOUT_1S 1.0
39 #define GL_POPUP_TIMEOUT_2S 2.0
40 #define GL_POPUP_TIMEOUT_3S 3.0
41
42 static Eina_Bool __gl_popup_timeout_cb(void *data)
43 {
44         GL_CHECK_FALSE(data);
45         gl_appdata *ad = (gl_appdata *)data;
46         if (ad->popupinfo.del_timer) {
47                 ecore_timer_del(ad->popupinfo.del_timer);
48                 ad->popupinfo.del_timer = NULL;
49         }
50
51         if (ad->popupinfo.popup) {
52                 evas_object_del(ad->popupinfo.popup);
53                 ad->popupinfo.popup = NULL;
54         }
55         return ECORE_CALLBACK_CANCEL;
56 }
57
58 static int __gl_popup_add_timer(void *data, double to_inc)
59 {
60         GL_CHECK_VAL(data, -1);
61         gl_appdata *ad = (gl_appdata *)data;
62         if (ad->popupinfo.del_timer) {
63                 ecore_timer_del(ad->popupinfo.del_timer);
64                 ad->popupinfo.del_timer = NULL;
65         }
66
67         ad->popupinfo.del_timer = ecore_timer_add(to_inc, __gl_popup_timeout_cb,
68                                                   data);
69         return 0;
70 }
71
72 static void __gl_popup_del_resp_cb(void *data, Evas_Object *obj,
73                                    void *event_info)
74 {
75         GL_CHECK(obj);
76         GL_CHECK(data);
77         gl_appdata *ad = (gl_appdata *)data;
78         const char *text = NULL;
79
80         text = elm_object_text_get(obj);
81         GL_CHECK(text);
82         gl_dbg("Button: %s, mode: %d", text, ad->popupinfo.popup_mode);
83
84         if (!g_strcmp0(text, GL_STR_YES)) {
85                 if (ad->popupinfo.popup_mode == GL_POPUP_ALBUM_DELETE)
86                         gl_del_albums(ad);
87         }
88
89         if (ad->popupinfo.popup) {
90                 evas_object_del(ad->popupinfo.popup);
91                 ad->popupinfo.popup = NULL;
92         }
93 }
94
95 static void _gl_popup_move_to_album(void *data)
96 {
97         GL_CHECK(data);
98         gl_appdata *ad = (gl_appdata *)data;
99         gl_dbg("");
100         /**
101         * 'move_album_id == NULL' is new album case,
102         * other move/save to some existed album.
103         */
104         if (ad->albuminfo.move_album_id)
105                 gl_move_to_album(ad);
106         else
107                 gl_ui_move_to_newalbum(ad);
108 }
109
110 static void _gl_popup_resp_cb(void *data, Evas_Object *obj, void *event_info)
111 {
112         GL_CHECK(data);
113         gl_appdata *ad = (gl_appdata *)data;
114         int mode = ad->popupinfo.popup_mode;
115         Ecore_IMF_Context *imf = ad->entryinfo.imf_context;
116         const char *text = NULL;
117
118         text = elm_object_text_get(obj);
119         GL_CHECK(text);
120         gl_dbg("Button: %s, mode: %d", text, mode);
121
122         if (mode == GL_POPUP_ALBUM_NEW_EMPTY ||
123             mode == GL_POPUP_ALBUM_NEW_DUPLICATE ||
124             mode == GL_POPUP_ALBUM_NEW_INVALID) {
125                 if (!g_strcmp0(text, GL_STR_YES) ||
126                     !g_strcmp0(text, GL_STR_OK)) {
127                         ad->entryinfo.entry_mode = GL_ENTRY_NEW_ALBUM;
128                         evas_object_show(ad->entryinfo.imf_entry);
129                         elm_object_focus_set(ad->entryinfo.imf_entry, EINA_TRUE);
130                         ecore_imf_context_input_panel_show(imf);
131                 } else if (!g_strcmp0(text, GL_STR_NO) ||
132                            !g_strcmp0(text, GL_STR_CANCEL)) {
133                         if (ad->entryinfo.imf_entry)
134                                 ecore_imf_context_input_panel_hide(imf);
135
136                         gl_ui_cancel_new_album(ad);
137                 }
138         } else if (mode == GL_POPUP_ALBUM_RENAME_EMPTY ||
139             mode == GL_POPUP_ALBUM_RENAME_DUPLICATE ||
140             mode == GL_POPUP_ALBUM_RENAME_INVALID) {
141                 if (!g_strcmp0(text, GL_STR_YES) ||
142                     !g_strcmp0(text, GL_STR_OK)) {
143                         evas_object_show(ad->entryinfo.imf_entry);
144                         elm_object_focus_set(ad->entryinfo.imf_entry, EINA_TRUE);
145                         ecore_imf_context_input_panel_show(imf);
146                 } else if (!g_strcmp0(text, GL_STR_NO) ||
147                            !g_strcmp0(text, GL_STR_CANCEL)) {
148                         if (ad->entryinfo.imf_entry)
149                                 ecore_imf_context_input_panel_hide(imf);
150                         gl_ui_cancel_rename_album(ad);
151                 }
152         } else if (mode == GL_POPUP_NOBUT_APPEXIT) {
153                 if (ad->popupinfo.popup) {
154                         evas_object_del(ad->popupinfo.popup);
155                         ad->popupinfo.popup = NULL;
156                 }
157                 elm_exit();
158                 return;
159         } else if (mode == GL_POPUP_NOBUT_ENTRY) {
160                 evas_object_show(ad->entryinfo.imf_entry);
161                 elm_object_focus_set(ad->entryinfo.imf_entry, EINA_TRUE);
162                 ecore_imf_context_input_panel_show(imf);
163         }
164
165         if (ad->popupinfo.popup) {
166                 evas_object_del(ad->popupinfo.popup);
167                 ad->popupinfo.popup = NULL;
168         }
169 }
170
171
172 static char *
173 _gl_popup_list_get_text(void *data, Evas_Object * obj, const char *part)
174 {
175         GL_CHECK_NULL(obj);
176         GL_CHECK_NULL(data);
177         /* Get 'ad' via 'popup_list_data' */
178         gl_appdata *ad = (gl_appdata *)evas_object_data_get(obj, GL_POPUP_OBJ_DATA_KEY);
179         GL_CHECK_NULL(ad);
180
181         int mode = ad->popupinfo.popup_mode;
182         const char *label = NULL;
183         /**
184         * Use index for album move,
185         * mainly for showing 'New album'
186         */
187         int idx = 0;
188
189         if (!strcmp(part, "elm.text"))
190         {
191                 switch (mode)
192                 {
193                 case GL_POPUP_THUMB_MOVE:
194                         idx = (int)data;
195                         /* 1, Prevent pass NULL data */
196                         idx -= 2;
197                         if (idx == -1)
198                         {
199                                 label = GL_STR_NEW_ALBUM;       //add "New album" item.
200                         }
201                         else
202                         {
203                                 Eina_List *album_list = NULL;
204
205                                 if (ad->albuminfo.cluster_list && ad->albuminfo.cluster_list->clist)
206                                 {
207                                         album_list = ad->albuminfo.cluster_list->clist;
208                                 }
209                                 else
210                                 {
211                                         gl_dbgE("cluster list is NULL.");
212                                         return NULL;
213                                 }
214
215                                 gl_cluster *album_item = eina_list_nth(album_list, idx);
216                                 if (album_item && album_item->cluster &&
217                                     album_item->cluster->uuid &&
218                                     album_item->cluster->display_name) {
219                                         if (strlen(album_item->cluster->display_name))
220                                         {
221                                                 label = album_item->cluster->display_name;
222                                         }
223                                         else if (gl_db_is_root_path(ad, album_item->cluster->uuid, NULL))       //"root" case, set display name as "No Name"
224                                         {
225                                                 label = GL_ALBUM_PHOME_ROOT_NAME;
226                                         }
227                                         else
228                                         {
229                                                 gl_dbgE("Album name[%s] is wrong!", album_item->cluster->display_name);
230                                                 label = GL_ALBUM_PHOME_ROOT_NAME;
231                                         }
232                                 }
233                         }
234                         break;
235                 default:
236                         gl_dbg("default: wrong mode.");
237                         break;
238                 }
239
240                 if (label)
241                 {
242                         return strdup(label);
243                 }
244                 else
245                 {
246                         gl_dbgE("label is NULL");
247                         return NULL;
248                 }
249         }
250         else
251         {
252                 return NULL;
253         }
254 }
255
256 static Evas_Object *
257 _gl_popup_list_get_icon(void *data, Evas_Object * obj, const char *part)
258 {
259         gl_dbg("");
260         return NULL;
261 }
262
263 static Evas_Object *
264 _gl_popup_create_list(void *data, Evas_Object * parent, const char *item_type)
265 {
266         GL_CHECK_NULL(parent);
267         GL_CHECK_NULL(data);
268         gl_appdata *ad = (gl_appdata *)data;
269         gl_dbg("");
270
271         if (item_type)
272         {
273                 ad->popupinfo.popuplit.item_style = item_type;
274         }
275         else
276         {
277                 ad->popupinfo.popuplit.item_style = GL_GENLIST_ITEM_STYLE_1TEXT;
278         }
279         ad->popupinfo.popuplit.func.text_get = _gl_popup_list_get_text;
280         ad->popupinfo.popuplit.func.content_get = _gl_popup_list_get_icon;
281         ad->popupinfo.popuplit.func.state_get = NULL;
282         ad->popupinfo.popuplit.func.del = NULL;
283
284         Evas_Object *genlist = elm_genlist_add(parent);
285         evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
286         evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
287
288         /* Attach 'ad' to genlist with 'GL_POPUP_OBJ_DATA_KEY' key to prevent use global variable. */
289         evas_object_data_set(genlist, GL_POPUP_OBJ_DATA_KEY, data);
290
291         return genlist;
292 }
293
294 static void
295 _gl_popup_move_cb(void *data, Evas_Object * obj, void *event_info)
296 {
297         gl_dbg("");
298         Elm_Object_Item *item = (Elm_Object_Item *) event_info;
299         if (item)
300         {
301                 elm_genlist_item_selected_set(item, EINA_FALSE);
302         }
303
304         /* Get 'ad' via 'GL_POPUP_OBJ_DATA_KEY' */
305         GL_CHECK(obj);
306         gl_appdata *ad = (gl_appdata *)evas_object_data_get(obj, GL_POPUP_OBJ_DATA_KEY);
307         GL_CHECK(ad);
308         if (ad->albuminfo.move_album_id) {
309                 free(ad->albuminfo.move_album_id);
310                 ad->albuminfo.move_album_id = NULL;
311         }
312         if (data)
313                 ad->albuminfo.move_album_id = strdup((char *)data);
314         gl_dbg("Dest album id: %s", ad->albuminfo.move_album_id);
315
316         if (ad->popupinfo.popup) {
317                 evas_object_del(ad->popupinfo.popup);
318                 ad->popupinfo.popup = NULL;
319         }
320
321         _gl_popup_move_to_album(ad);
322 }
323
324 /* Append items to list in popup for 'Move' */
325 static int _gl_popup_append_move_items(void *data, Evas_Object *genlist)
326 {
327         gl_dbg("");
328         GL_CHECK_VAL(genlist, -1);
329         GL_CHECK_VAL(data, -1);
330         gl_appdata *ad = (gl_appdata *)data;
331         int idx = 0;
332         int i = 0;
333         int item_cnt = 0;
334         Eina_List *album_list = NULL;
335         int all_count = 0;
336         gl_cluster *album_item = NULL;
337         Elm_Genlist_Item_Class *plit = &(ad->popupinfo.popuplit);
338         gl_cluster *current_album = ad->albuminfo.current_album;
339         GL_CHECK_VAL(current_album, -1);
340         GL_CHECK_VAL(current_album->cluster, -1);
341         GL_CHECK_VAL(current_album->cluster->uuid, -1);
342
343         idx++;
344         elm_genlist_item_append(genlist, plit, (void *)idx, NULL,
345                                 ELM_GENLIST_ITEM_NONE, _gl_popup_move_cb,
346                                 NULL);
347         item_cnt++;
348
349         if (ad->albuminfo.cluster_list && ad->albuminfo.cluster_list->clist) {
350                 album_list = ad->albuminfo.cluster_list->clist;
351                 all_count = eina_list_count(album_list);
352         } else {
353                 gl_dbgE("cluster list is NULL");
354                 return -1;
355         }
356
357         for (i = 0; i < all_count; i++) {
358                 album_item = eina_list_nth(album_list, i);
359                 GL_CHECK_VAL(album_item, -1);
360                 GL_CHECK_VAL(album_item->cluster, -1);
361                 GL_CHECK_VAL(album_item->cluster->display_name, -1);
362
363                 idx++;
364                 GL_CHECK_VAL(album_item->cluster->uuid, -1);
365                 if (g_strcmp0(album_item->cluster->uuid, current_album->cluster->uuid)) {
366                         /* so guaranty 'All' album is the first genlist item. */
367                         if (!g_strcmp0(album_item->cluster->uuid, GL_ALBUM_ALL_ID))
368                                 gl_dbg("Met All album, get next.");
369                         else {
370                                 elm_genlist_item_append(genlist, plit,
371                                                         (void *)idx, NULL,
372                                                         ELM_GENLIST_ITEM_NONE,
373                                                         _gl_popup_move_cb,
374                                                         album_item->cluster->uuid);
375                                 item_cnt++;
376                         }
377                 }
378         }
379         return item_cnt;
380 }
381
382 int gl_popup_create_albums_del_popup(void *data)
383 {
384         GL_CHECK_VAL(data, -1);
385         gl_appdata *ad = (gl_appdata *)data;
386         gl_dbg("");
387
388         if (ad->popupinfo.popup != NULL) {
389                 gl_dbg("The existed popup is deleted");
390                 evas_object_del(ad->popupinfo.popup);
391         }
392
393         Evas_Object *popup = elm_popup_add(ad->maininfo.win);
394         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
395
396         elm_object_text_set(popup, GL_STR_DELETE_COMFIRMATION);
397         Evas_Object *btn1 = NULL;
398         Evas_Object *btn2 = NULL;
399         btn1 = _gl_but_create_but_popup(popup, GL_STR_YES,
400                                         __gl_popup_del_resp_cb, data);
401         btn2 = _gl_but_create_but_popup(popup, GL_STR_NO,
402                                         __gl_popup_del_resp_cb, data);
403         elm_object_part_content_set(popup, "button1", btn1);
404         elm_object_part_content_set(popup, "button2", btn2);
405
406         evas_object_show(popup);
407         ad->popupinfo.popup = popup;
408         ad->popupinfo.popup_mode = GL_POPUP_ALBUM_DELETE;
409         return 0;
410 }
411
412 static Evas_Object *_gl_popup_set_box(Evas_Object *parent,
413                                         Evas_Object *genlist, int item_cnt)
414 {
415         GL_CHECK_NULL(parent);
416         GL_CHECK_NULL(genlist);
417         Evas_Object *box = elm_box_add(parent);
418
419         if (item_cnt < 4)
420                 evas_object_size_hint_min_set(box, GL_POPUP_MENUSTYLE_WIDTH,
421                                               GL_POPUP_MENUSTYLE_HEIGHT(item_cnt));
422         else
423                 evas_object_size_hint_min_set(box, GL_POPUP_MENUSTYLE_WIDTH,
424                                               GL_POPUP_MENUSTYLE_HEIGHT_MAX);
425
426         evas_object_show(genlist);
427         elm_box_pack_end(box, genlist);
428         return box;
429 }
430
431 int
432 gl_popup_create_title_popup(void *data, gl_popup_mode mode, char *title, char *desc)
433 {
434         GL_CHECK_VAL(data, -1);
435         gl_appdata *ad = (gl_appdata *)data;
436         gl_dbg("");
437
438         if (ad->popupinfo.popup)
439         {
440                 gl_dbg("Delete existed popup.");
441                 evas_object_del(ad->popupinfo.popup);
442         }
443
444         Evas_Object *popup = elm_popup_add(ad->maininfo.win);
445         ad->popupinfo.popup = popup;
446         ad->popupinfo.popup_mode = mode;
447         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
448         elm_object_text_set(popup, desc);
449         Evas_Object *genlist = NULL;
450         Evas_Object *box = NULL;
451         int g_cnt = 0;
452         Evas_Object *btn1 = NULL;
453
454         switch (mode) {
455         case GL_POPUP_THUMB_MOVE:
456                 elm_object_style_set(popup, GL_POPUP_STYLE_MIN_MENUSTYLE);
457                 elm_object_part_text_set(popup, "title,text", title);
458                 btn1 = _gl_but_create_but_popup(popup, GL_STR_CANCEL,
459                                                 _gl_popup_resp_cb, data);
460                 elm_object_part_content_set(popup, "button1", btn1);
461
462                 genlist = _gl_popup_create_list(ad, popup, NULL);
463                 if ((g_cnt = _gl_popup_append_move_items(ad, genlist)) < 0) {
464                         gl_dbgE("_gl_popup_append_move_items failed!");
465                         goto POPUP_FAILED;
466                 }
467                 box = _gl_popup_set_box(popup, genlist, g_cnt);
468                 elm_object_content_set(popup, box);
469                 break;
470         default:
471                 gl_dbg("Unexpected mode!");
472                 break;
473         }
474
475         evas_object_show(popup);
476         return 0;
477
478  POPUP_FAILED:
479         gl_dbgE("POPUP_FAILED");
480         evas_object_del(popup);
481         ad->popupinfo.popup = NULL;
482         return -1;
483 }
484
485 int gl_popup_create_popup(void *data, gl_popup_mode mode, char *desc)
486 {
487         GL_CHECK_VAL(data, -1);
488         gl_appdata *ad = (gl_appdata *)data;
489         gl_dbg("");
490
491         if (ad->popupinfo.popup) {
492                 gl_dbg("The existed popup is deleted");
493                 evas_object_del(ad->popupinfo.popup);
494                 ad->popupinfo.popup = NULL;
495         }
496
497         /**
498         * Pogressbar is showed during moving or deleting medias,
499         * don't delete it while show popup.
500         */
501         if (mode != GL_POPUP_NOBUT_MOV_DEL)
502                 gl_pb_del_pbar(ad);
503
504         Evas_Object *popup = elm_popup_add(ad->maininfo.win);
505         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND,
506                                          EVAS_HINT_EXPAND);
507         elm_object_text_set(popup, desc);
508         Evas_Object *btn1 = NULL;
509         Evas_Object *btn2 = NULL;
510
511         switch (mode) {
512         case GL_POPUP_NOBUT:
513         case GL_POPUP_NOBUT_APPEXIT:
514         case GL_POPUP_NOBUT_ENTRY:
515                 __gl_popup_add_timer(ad, GL_POPUP_TIMEOUT_3S);
516                 break;
517         case GL_POPUP_NOBUT_1S:
518         case GL_POPUP_NOBUT_MOV_DEL:
519                 __gl_popup_add_timer(ad, GL_POPUP_TIMEOUT_3S);
520                 break;
521         case GL_POPUP_ONEBUT:
522                 btn1 = _gl_but_create_but_popup(popup, GL_STR_OK,
523                                                 _gl_popup_resp_cb, data);
524                 elm_object_part_content_set(popup, "button1", btn1);
525                 break;
526         case GL_POPUP_TWOBUT:
527                 btn1 = _gl_but_create_but_popup(popup, GL_STR_OK,
528                                                 _gl_popup_resp_cb, data);
529                 elm_object_part_content_set(popup, "button1", btn1);
530                 btn2 = _gl_but_create_but_popup(popup, GL_STR_CANCEL,
531                                                 _gl_popup_resp_cb, data);
532                 elm_object_part_content_set(popup, "button2", btn2);
533                 break;
534         case GL_POPUP_ALBUM_NEW_EMPTY:
535         case GL_POPUP_ALBUM_NEW_DUPLICATE:
536         case GL_POPUP_ALBUM_NEW_INVALID:
537         case GL_POPUP_ALBUM_RENAME_EMPTY:
538         case GL_POPUP_ALBUM_RENAME_DUPLICATE:
539         case GL_POPUP_ALBUM_RENAME_INVALID:
540                 btn1 = _gl_but_create_but_popup(popup, GL_STR_YES,
541                                                 _gl_popup_resp_cb, data);
542                 elm_object_part_content_set(popup, "button1", btn1);
543                 btn2 = _gl_but_create_but_popup(popup, GL_STR_NO,
544                                                 _gl_popup_resp_cb, data);
545                 elm_object_part_content_set(popup, "button2", btn2);
546                 break;
547         default:
548                 gl_dbgE("Other popup mode...");
549                 break;
550         }
551
552         evas_object_show(popup);
553
554         /* Focus popup and IMF hide */
555         if (mode == GL_POPUP_NOBUT_ENTRY)
556                 elm_object_focus_set(popup, TRUE);
557
558         ad->popupinfo.popup = popup;
559         ad->popupinfo.popup_mode = mode;
560
561         return 0;
562 }
563
564 /* Update popup contents */
565 int gl_popup_update_content(void *data, gl_popup_mode mode)
566 {
567         GL_CHECK_VAL(data, -1);
568         gl_appdata *ad = (gl_appdata *)data;
569         GL_CHECK_VAL(ad->popupinfo.popup, -1);
570         gl_dbg("mode: %d.", mode);
571
572         Evas_Object *content = elm_object_content_get(ad->popupinfo.popup);
573         GL_CHECK_VAL(content, -1);
574         Eina_List *chidren = elm_box_children_get(content);
575         GL_CHECK_VAL(chidren, -1);
576         Evas_Object *genlist = eina_list_nth(chidren, 0);
577         GL_CHECK_VAL(genlist, -1);
578         elm_genlist_clear(genlist);
579         int cnt = 0;
580
581         switch (mode) {
582         case GL_POPUP_THUMB_MOVE:
583                 if ((cnt = _gl_popup_append_move_items(ad, genlist)) < 0) {
584                         gl_dbgE("_gl_popup_append_move_items failed!");
585                         return -1;
586                 }
587                 break;
588         default:
589                 break;
590         }
591
592         return 0;
593 }