The source code moved from the SPIN with license changed to Flora 1.1
[apps/native/home/homescreen-efl.git] / src / app_grid.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.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 "app_grid.h"
18 #include "homescreen-efl.h"
19 #include "app_item.h"
20 #include "app_icon.h"
21 #include "page_scroller.h"
22 #include "all_apps.h"
23 #include "folder_panel.h"
24 #include "util.h"
25 #include "popup.h"
26 #include "data_model.h"
27
28 typedef enum {
29         NEXT_PAGE_CB = 0,
30         PREV_PAGE_CB,
31         NONE_PAGE_CB
32 } page_change_action_t;
33
34 typedef enum {
35         MODE_NORMAL = 0,
36         MODE_EDIT,
37         MODE_FOLDER,
38 } possible_view_modes_t;
39
40 typedef struct {
41         page_change_action_t action;
42         Evas_Object *parent;
43 } change_page_data_t;
44
45 static struct {
46         Tree_node_t *repositioned_node;
47         Tree_node_t *opened_folder_node;
48         Tree_node_t *destination_folder;
49         Evas_Object *repositioned_icon_layout;
50         Evas_Object *src_grid;
51         Evas_Object *repositioned_icon;
52         Elm_Object_Item *repositioned_item;
53         int src_idx;
54         bool is_dnd_on;
55         Evas_Coord dx;
56         Evas_Coord dy;
57         Elm_Gengrid_Item_Class *gic;
58         Evas_Coord w;
59         Evas_Coord h;
60         int f_x;
61         int f_y;
62         int f_w;
63         int f_h;
64         Ecore_Timer *change_page_timer;
65         Ecore_Timer *outside_folder_timer;
66         change_page_data_t cp_data;
67 } s_info = {
68         .repositioned_node = NULL,
69         .opened_folder_node = NULL,
70         .destination_folder = NULL,
71         .repositioned_icon_layout = NULL,
72         .src_grid = NULL,
73         .repositioned_icon = NULL,
74         .repositioned_item = NULL,
75         .src_idx = 1,
76         .is_dnd_on = false,
77         .gic = NULL,
78         .dx = -1,
79         .dy = -1,
80         .w = -1,
81         .h = -1,
82         .f_x = -1,
83         .f_y = -1,
84         .f_w = -1,
85         .f_h = -1,
86         .change_page_timer = NULL,
87         .outside_folder_timer = NULL,
88         .cp_data = {
89                 action: NONE_PAGE_CB,
90                 parent: NULL
91         }
92 };
93
94 /*================================= PRIVATE FUNCTIONS ============================================*/
95 static bool __app_grid_fill(Evas_Object *grid, Tree_node_t *data);
96 static Evas_Object *__app_grid_create_ly(Evas_Object *parent);
97 static bool __app_grid_resize(Evas_Object *app_grid, Evas_Coord new_w, Evas_Coord new_h);
98 static Evas_Object *__app_grid_get_icon_container_ptr(Elm_Object_Item *it);
99 static Eina_Bool __app_grid_change_page_cb(void *data);
100 static void __app_grid_check_page_change(Evas_Object *scroller, int x, int y);
101 static void __app_grid_clear_reposition_structure(void);
102 static Eina_Bool __app_grid_close_folder_cb(void *data);
103 static Evas_Object *__app_grid_create_item_container(Evas_Object *parent);
104
105 /*================================= GENGRID CALLBACK FUNCTIONS ===================================*/
106 static void __app_grid_item_longpressed_cb(void *data, Evas_Object *obj, void *ei);
107 static Evas_Object *__app_grid_get_content(void *data, Evas_Object *obj, const char *part);
108 static Eina_Bool __app_grid_get_state(void *data, Evas_Object *obj, const char *part);
109 static void __app_grid_del_content(void *data, Evas_Object *obj);
110 static char *__app_grid_get_text(void *data, Evas_Object *obj, const char *part);
111 static void __app_grid_resize_cb(void *data, Evas *e, Evas_Object *obj, void *ei);
112
113 /*================================= MOUSE HANDLERS ===============================================*/
114 static Eina_Bool _app_grid_mouse_move_cb(void *data, int type, void *event);
115 static Eina_Bool __app_grid_mouse_up_cb(void *data, int type, void *event);
116
117 /*================================= DND FUNCTIONS ================================================*/
118 static void __app_grid_return_to_origin_pos(void);
119 static void __app_grid_dnd_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y,
120                 Elm_Xdnd_Action action);
121 static void __app_grid_dnd_drag_done_cb(void *data, Evas_Object *obj);
122 static void __app_grid_dnd_pos_changed_cb(void *data, Evas_Object *obj, Evas_Coord x,
123                 Evas_Coord y, Elm_Xdnd_Action action);
124
125 /*================================= PUBLIC FUNCTIONS DEFS ========================================*/
126 HAPI Evas_Object *app_grid_create(Evas_Object *parent, Tree_node_t *data, Evas_Coord gengrid_width,
127                         Evas_Coord gengrid_height, app_grid_type_t type)
128 {
129         Evas_Object *gengrid = NULL;
130         Evas_Object *layout = NULL;
131         Evas_Object *rect = NULL;
132
133         if (!parent) {
134                 LOGE("[INVALID_PARAM]['parent'='%p']", parent);
135                 return NULL;
136         }
137
138         rect = evas_object_rectangle_add(evas_object_evas_get(parent));
139         if (!rect) {
140                 LOGE("[FAILED][rect=NULL]");
141                 return NULL;
142         }
143
144         layout = __app_grid_create_ly(parent);
145         if (!layout) {
146                 LOGE("[FAILED][__app_grid_create_ly]");
147                 evas_object_del(rect);
148                 return NULL;
149         }
150
151         evas_object_color_set(rect, 0, 0, 0, 0);
152         evas_object_size_hint_min_set(rect, gengrid_width, gengrid_height);
153         evas_object_size_hint_max_set(rect, gengrid_width, gengrid_height);
154         elm_object_part_content_set(layout, PART_APP_GRID_SIZE_SETTER, rect);
155
156         gengrid = elm_gengrid_add(layout);
157         if (!gengrid) {
158                 LOGE("[FAILED][elm_gengrid_add]");
159                 evas_object_del(layout);
160                 evas_object_del(rect);
161                 return NULL;
162         }
163
164         evas_object_size_hint_weight_set(gengrid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
165         evas_object_show(gengrid);
166
167         if (!s_info.gic) {
168                 if (!(s_info.gic = elm_gengrid_item_class_new())) {
169                         LOGE("[FAILED][elm_gengrid_item_class_new]");
170                         evas_object_del(layout);
171                         evas_object_del(rect);
172                         return NULL;
173                 }
174
175                 s_info.gic->item_style  = "default";
176                 s_info.gic->func.content_get = __app_grid_get_content;
177                 s_info.gic->func.del = __app_grid_del_content;
178                 s_info.gic->func.text_get = __app_grid_get_text;
179                 s_info.gic->func.state_get = __app_grid_get_state;
180
181                 ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _app_grid_mouse_move_cb, parent);
182                 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, __app_grid_mouse_up_cb, NULL);
183         }
184
185         elm_object_scale_set(gengrid, 0.5);
186
187         elm_gengrid_select_mode_set(gengrid, ELM_OBJECT_SELECT_MODE_NONE);
188         elm_gengrid_reorder_mode_set(gengrid, EINA_FALSE);
189         elm_gengrid_align_set(gengrid, 0.0, 0.0);
190
191         if (!__app_grid_fill(gengrid, data)) {
192                 LOGE("[FAILED][__app_grid_fill]");
193                 evas_object_del(layout);
194                 evas_object_del(rect);
195                 return NULL;
196         }
197
198         if (type == APP_GRID_TYPE_ALL_APPS) {
199                 s_info.w = gengrid_width;
200                 s_info.h = gengrid_height;
201         } else if (type == APP_GRID_TYPE_FOLDER) {
202                 elm_object_signal_emit(layout, SIGNAL_APP_GRID_BG_HIDE, SIGNAL_SOURCE);
203         }
204
205         elm_object_part_content_set(layout, PART_APP_GRID_CONTENT, gengrid);
206         evas_object_smart_callback_add(gengrid, "longpressed", __app_grid_item_longpressed_cb, NULL);
207
208         elm_drop_target_add(gengrid, ELM_SEL_FORMAT_TARGETS,
209                                 NULL, NULL, NULL, NULL, __app_grid_dnd_pos_cb, NULL, NULL, NULL);
210
211         data->data->layout = layout;
212         evas_object_event_callback_add(gengrid, EVAS_CALLBACK_RESIZE, __app_grid_resize_cb, (void *)type);
213
214         /*It is used only internal.*/
215         evas_object_data_set(gengrid, KEY_APP_GRID_DATA, layout);
216
217         elm_scroller_movement_block_set(gengrid, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
218         elm_scroller_movement_block_set(gengrid, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
219         elm_gengrid_wheel_disabled_set(gengrid, EINA_TRUE);
220
221         return layout;
222 }
223
224 HAPI Elm_Object_Item *app_grid_append_item(Evas_Object *layout, Evas_Object *icon_to_append)
225 {
226         LOGD("");
227         Elm_Object_Item *result = NULL;
228         Evas_Object *container = NULL;
229
230         if (!layout || !icon_to_append) {
231                 LOGE("[INVALID_PARAM][layout='%p'][icon_to_append='%p']", layout, icon_to_append);
232                 return NULL;
233         }
234
235         Evas_Object *grid = elm_object_part_content_get(layout, PART_APP_GRID_CONTENT);
236         if (!grid) {
237                 LOGE("[FAILED][elm_object_part_content_get]");
238                 return NULL;
239         }
240
241         if (!(result = elm_gengrid_item_append(grid, s_info.gic,
242                         (container = app_grid_item_pack(grid, icon_to_append)), NULL, NULL))) {
243                 LOGE("Failed to append item");
244                 return NULL;
245         }
246
247         evas_object_show(icon_to_append);
248         return result;
249 }
250
251 HAPI Elm_Object_Item *app_grid_insert_item_relative(Evas_Object *layout, Evas_Object *item,
252                                 Elm_Object_Item *rel_it)
253 {
254         Evas_Object *app_grid = NULL, *container = NULL;
255         Elm_Object_Item *result = NULL;
256         int dst_idx = -1;
257
258         if (!layout || !item) {
259                 LOGE("[INVALID_PARAM][layout='%p'][item='%p']", layout, item);
260                 return NULL;
261         }
262
263         app_grid = elm_object_part_content_get(layout, PART_APP_GRID_CONTENT);
264         if (!app_grid) {
265                 LOGE("[FAILED][elm_object_part_content_get]");
266                 return NULL;
267         }
268
269         if (rel_it) {
270                 dst_idx = elm_gengrid_item_index_get(rel_it);
271
272                 if ((s_info.src_grid == app_grid && s_info.src_idx > dst_idx)
273                                 || (s_info.src_grid != app_grid)) {
274                         if (!(result = elm_gengrid_item_insert_before(app_grid, s_info.gic,
275                                 (container = app_grid_item_pack(app_grid, item)), rel_it, NULL, NULL))) {
276                                 LOGE("[FAILED][elm_gengrid_item_insert_before]");
277                                 evas_object_del(container);
278                                 return NULL;
279                         }
280                 } else if (s_info.src_grid == app_grid && s_info.src_idx < dst_idx) {
281                         if (!(result = elm_gengrid_item_insert_after(app_grid, s_info.gic,
282                                 (container = app_grid_item_pack(app_grid, item)), rel_it, NULL, NULL))) {
283                                 LOGE("[FAILED][elm_gengrid_item_insert_before]");
284                                 return NULL;
285                         }
286                 }
287         } else {
288                 if (!(result = elm_gengrid_item_append(app_grid, s_info.gic,
289                                 (container = app_grid_item_pack(app_grid, item)), NULL, NULL))) {
290                         LOGE("[FAILED][elm_gengrid_item_append]");
291                         return NULL;
292                 }
293         }
294
295         evas_object_show(item);
296         return result;
297 }
298
299 HAPI Evas_Object *app_grid_item_pack(Evas_Object *p, Evas_Object *c)
300 {
301         Evas_Object *container = NULL;
302
303         if (!p) { /*When c is null it is not a big problem...it creates then empty gengrid item */
304                 LOGD("[ERR][INVALID_PARAM]['p'='%p']", p);
305                 return NULL;
306         }
307
308         /*This items will be removed when gengrid items will be deleted.
309         It was checked in EVAS_CALLBACK_DEL function. */
310         container = __app_grid_create_item_container(home_screen_get_win());
311         if (!container) {
312                 LOGE("[FAILED][container=NULL]");
313                 return NULL;
314         }
315
316         if (c)
317                 elm_object_part_content_set(container, PART_APP_GRID_ITEM, c);
318
319         return container;
320 }
321
322 HAPI void app_grid_unpack_item(Elm_Object_Item *item)
323 {
324         Evas_Object *container = NULL;
325
326         if (!item) {
327                 LOGE("[INVALID_PARAM][item=NULL]");
328                 return;
329         }
330
331         container = elm_object_item_part_content_get(item, GRID_CONTENT);
332         if (!container) {
333                 LOGE("[FAILED][elm_object_item_part_content_get]");
334                 return;
335         }
336
337         elm_object_part_content_unset(container, PART_APP_GRID_ITEM);
338 }
339
340 HAPI Eina_Bool app_grid_get_item_content(Elm_Object_Item *item, Evas_Object **icon,
341                                 Tree_node_t **data)
342 {
343         Evas_Object *ic = NULL;
344         Evas_Object *container = NULL;
345
346         if (!item) {
347                 LOGE("[INVALID_PARAM][item='%p']", item);
348                 return EINA_FALSE;
349         }
350
351         container = elm_object_item_part_content_get(item, GRID_CONTENT);
352         if (!container) {
353                 LOGE("[FAILED][elm_object_item_part_content_get]");
354                 return EINA_FALSE;
355         }
356
357         ic = elm_object_part_content_get(container, PART_APP_GRID_ITEM);
358         if (!ic) {
359                 LOGE("[FAILED][eina_list_data_get]");
360                 return EINA_FALSE;
361         }
362
363         if (icon)
364                 *icon = ic;
365
366         if (data) {
367                 *data = evas_object_data_get(ic, KEY_ICON_DATA);
368                 if (!(*data)) {
369                         LOGE("[FAILED][evas_object_data_get]");
370                         /*eina_list_free(box_content);*/
371                         return EINA_FALSE;
372                 }
373         }
374         return EINA_TRUE;
375 }
376
377 /*=====================GENGRID CALLBACKS IMPLEMENTATION===========================================*/
378 static void __app_grid_item_longpressed_cb(void *data, Evas_Object *obj, void *ei)
379 {
380         Elm_Object_Item *it = (Elm_Object_Item *)ei;
381         Evas_Coord x, y, w, h, m_x, m_y;
382         Evas_Object *icon_layout = NULL;
383         Evas_Object *icon = NULL;
384         Tree_node_t *icon_node = NULL;
385
386         if (!it || !app_grid_get_item_content(it, &icon_layout, NULL)) {
387                 LOGE("[FAILED][app_grid_item_content_get]");
388                 return;
389         }
390
391         if (!evas_object_data_get(icon_layout, KEY_IS_REPOSITIONABLE))
392                 return;
393
394         if (home_screen_get_view_type() == HOMESCREEN_VIEW_ALL_APPS_CHOOSE)
395                 return;
396
397         if (home_screen_get_view_type() == HOMESCREEN_VIEW_ALL_APPS) {
398                 home_screen_set_view_type(HOMESCREEN_VIEW_ALL_APPS_EDIT);
399                 elm_drag_cancel(obj);
400         }
401
402         if (!icon_layout) {
403                 LOGE("[FAILED][icon_layout=NULL]");
404                 return;
405         }
406
407         icon = elm_object_part_content_get(icon_layout, PART_ICON_CONTENT);
408         if (!icon) {
409                 LOGE("[FAILED][icon=NULL]");
410                 return;
411         }
412
413         icon_node = evas_object_data_get(icon_layout, KEY_ICON_DATA);
414         if (!icon_node) {
415                 LOGE("[FAILED][icon_node=NULL]");
416                 return;
417         }
418
419         /*check if the repositioned item is from a folder.
420         It is necessary for removing item from the folder.*/
421         if (icon_node->parent && icon_node->parent->parent && icon_node->parent->parent->data
422                                 && icon_node->parent->parent->data->type == APP_ITEM_FOLDER) {
423                 s_info.opened_folder_node = icon_node->parent->parent;
424                 folder_panel_get_folder_geometry(&s_info.f_x, &s_info.f_y, &s_info.f_w, &s_info.f_h);
425         }
426
427         evas_object_geometry_get(icon, &x, &y, &w, &h);
428         evas_pointer_output_xy_get(evas_object_evas_get(obj), &m_x, &m_y);
429         s_info.dx = abs(m_x - x);
430         s_info.dy = abs(m_y - y);
431
432         /*check if user perform longpress action on icon or on item.
433         (item is a container for icon..is bigger because it must have place also for icon name)*/
434         if ((m_x >= x && m_x <= x+w) && (m_y >= y && m_y <= y + h)) {
435                 s_info.repositioned_icon_layout = icon_layout;
436                 s_info.repositioned_icon = icon;
437                 s_info.repositioned_item = it;
438                 s_info.repositioned_node = icon_node;
439                 s_info.src_grid = obj;
440                 s_info.src_idx = elm_gengrid_item_index_get(s_info.repositioned_item);
441                 s_info.is_dnd_on = true;
442
443                 app_grid_unpack_item(it);
444
445                 elm_drag_start(icon, ELM_SEL_FORMAT_TARGETS, "dnd", ELM_XDND_ACTION_MOVE,
446                         NULL, NULL, __app_grid_dnd_pos_changed_cb, NULL, NULL, NULL, __app_grid_dnd_drag_done_cb, obj);
447
448                 evas_object_data_set(icon, KEY_REPOSITION_DATA, icon_layout);
449                 /*This is necessary for hide only box content in grid*/
450                 elm_object_part_content_unset(icon_layout, PART_ICON_CONTENT);
451                 evas_object_hide(icon_layout);
452                 all_apps_set_scrolling_blocked_state(true);
453                 folder_panel_enable_entry(false);
454         }
455 }
456
457 static char *__app_grid_get_text(void *data, Evas_Object *obj, const char *part)
458 {
459         return NULL;
460 }
461
462 static Evas_Object *__app_grid_get_content(void *data, Evas_Object *obj, const char *part)
463 {
464         if (!data) {
465                 LOGE("[INVALID_PARAM][data='%p']", data);
466                 return NULL;
467         }
468
469         if (!strcmp(GRID_CONTENT, part))
470                 return (Evas_Object *) data;
471
472         return NULL;
473 }
474
475 static Eina_Bool __app_grid_get_state(void *data, Evas_Object *obj, const char *part)
476 {
477         return EINA_FALSE;
478 }
479
480 static void __app_grid_del_content(void *data, Evas_Object *obj)
481 {
482         LOGD("DELETING :  ", evas_object_type_get(obj));
483
484 }
485
486 static void __app_grid_resize_cb(void *data, Evas *e, Evas_Object *obj, void *ei)
487 {
488         int w = -1, h = -1, item_w = -1, item_h = -1;
489         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
490
491         if ((app_grid_type_t)data == APP_GRID_TYPE_ALL_APPS) {
492                 item_w = w/APP_COLS;
493                 item_h = h/APP_ROWS;
494         } else if ((app_grid_type_t)data == APP_GRID_TYPE_FOLDER) {
495                 item_w = w/FOLDER_COL_APPS - FOLDER_ITEM_MARGIN*home_screen_get_root_width();
496                 item_h = h/FOLDER_ROW_APPS;
497         }
498
499         elm_gengrid_item_size_set(obj, item_w, item_h);
500 }
501
502 /*=========================== MOUSE HANDLERS =====================================================*/
503 static Eina_Bool __app_grid_mouse_up_cb(void *data, int type, void *event)
504 {
505         home_screen_set_indice_state(INDICE_OFF);
506         return ECORE_CALLBACK_RENEW;
507 }
508
509 static Eina_Bool _app_grid_mouse_move_cb(void *data, int type, void *event)
510 {
511         if (s_info.is_dnd_on) {
512                 Evas_Object *scroller = (Evas_Object *) data;
513                 Ecore_Event_Mouse_Move *move = event;
514                 __app_grid_check_page_change(scroller, move->x, move->y);
515         }
516
517         return ECORE_CALLBACK_RENEW;
518 }
519
520 /*========================= PRIVATE FUNCTIONS ====================================================*/
521 static bool __app_grid_fill(Evas_Object *grid, Tree_node_t *data)
522 {
523         Evas_Object *icon = NULL, *box = NULL;
524         app_item_t *item = NULL;
525         Tree_node_t *it = NULL;
526
527         if (!data || !grid) {
528                 LOGE("[INVALID_PARAM][grid='%p'][data='%p']", grid, data);
529                 return false;
530         }
531
532         TREE_NODE_FOREACH(data, it) {
533                 item = it->data;
534                 if (!item) {
535                         LOGE("[FAILED][item=%p", item);
536                         continue;
537                 }
538
539                 if (!item->exec || !item->icon || !item->label || !item->appid) {
540                         LOGE("[FAILED][exec='%p'][icon='%p'][label='%p'][appid='%p']",
541                                 item->exec, item->label, item->icon, item->appid);
542                         continue;
543                 }
544
545                 LOGI("add item: [%s]", item->label);
546
547                 if (item->type == APP_ITEM_ICON) {
548                         icon = app_icon_create(it, APP_ICON_TYPE_APP);
549                 } else if (item->type == APP_ITEM_FOLDER) {
550                         folder_panel_create(it);
551                         app_icon_update_folder_icon(it);
552                         icon = item->layout;
553                 }
554
555                 if (!icon) {
556                         LOGE("[FAILED][app_icon_create]");
557                         return false;
558                 }
559
560                 if (!(item->grid_item = elm_gengrid_item_append(grid, s_info.gic,
561                                 (box = app_grid_item_pack(grid, icon)), NULL, NULL))) {
562                         LOGE("Failed to append an item!");
563                         evas_object_del(box);
564                         if (!box) {/*app_grid_item_pack had failed so the icon is still allocated:*/
565                                 app_icon_destroy(icon);
566                         }
567                         return false;
568                 }
569
570                 item->layout = icon;
571         }
572
573         return true;
574 }
575
576 static Evas_Object *__app_grid_create_ly(Evas_Object *parent)
577 {
578         Evas_Object *ly = NULL;
579
580         if (!parent) {
581                 LOGE("[INVALID_PARAM][parent='%p']", parent);
582                 return NULL;
583         }
584
585         ly = elm_layout_add(parent);
586         if (!ly) {
587                 LOGE("[FAILED][elm_layout_add]");
588                 return NULL;
589         }
590
591         if (!elm_layout_file_set(ly, EDJE_DIR"/app_grid.edj", GROUP_APP_GRID)) {
592                 LOGE("[FAILED][elm_layout_file_set][%s]", EDJE_DIR"/app_grid.edj");
593                 evas_object_del(ly);
594                 return NULL;
595         }
596
597         evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
598         evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
599         evas_object_show(ly);
600
601         return ly;
602 }
603
604 void app_grid_set_view_mode(Evas_Object *app_grid, homescreen_view_t view)
605 {
606         if (!app_grid) {
607                 LOGE("[INVALID_PARAM]");
608                 return;
609         }
610
611         switch (view) {
612         case HOMESCREEN_VIEW_ALL_APPS:
613                 elm_object_signal_emit(app_grid, SIGNAL_CHOOSE_MODE_OFF, SIGNAL_SOURCE);
614                 elm_object_signal_emit(app_grid, SIGNAL_EDIT_MODE_OFF, SIGNAL_SOURCE);
615                 __app_grid_resize(app_grid, s_info.w, s_info.h);
616                 break;
617         case HOMESCREEN_VIEW_ALL_APPS_EDIT:
618                 elm_object_signal_emit(app_grid, SIGNAL_CHOOSE_MODE_OFF, SIGNAL_SOURCE);
619                 elm_object_signal_emit(app_grid, SIGNAL_EDIT_MODE_ON, SIGNAL_SOURCE);
620                 __app_grid_resize(app_grid, EDIT_MODE_SCALE*s_info.w, EDIT_MODE_SCALE*s_info.h);
621                 break;
622         case HOMESCREEN_VIEW_ALL_APPS_CHOOSE:
623                 elm_object_signal_emit(app_grid, SIGNAL_EDIT_MODE_OFF, SIGNAL_SOURCE);
624                 elm_object_signal_emit(app_grid, SIGNAL_CHOOSE_MODE_ON, SIGNAL_SOURCE);
625                 __app_grid_resize(app_grid, CHOOSE_MODE_SCALE*s_info.w, CHOOSE_MODE_SCALE*s_info.h);
626                 break;
627         default:
628                 LOGE("[FAILED][type='%d']", view);
629                 break;
630         }
631 }
632
633 static bool __app_grid_resize(Evas_Object *app_grid, Evas_Coord new_w, Evas_Coord new_h)
634 {
635         Evas_Object *gengrid = NULL;
636
637         Evas_Coord new_item_w = new_w/APP_COLS;
638         Evas_Coord new_item_h = new_h/APP_ROWS;
639
640         if (!app_grid) {
641                 LOGE("[INVALID_PARAM][app_grid='%p']", app_grid);
642                 return false;
643         }
644
645         gengrid = elm_object_part_content_get(app_grid, PART_APP_GRID_CONTENT);
646         if (!gengrid) {
647                 LOGE("[FAILED][elm_object_part_content_get]");
648                 return false;
649         }
650
651         if (new_item_w < 0 || new_item_h < 0) {
652                 LOGE("[INVALID_SIZE]");
653                 return false;
654         }
655
656         /*elm_gengrid_item_size_set(gengrid, new_item_w, new_item_h);*/
657
658         return true;
659 }
660
661 static Eina_Bool __app_grid_change_page_cb(void *data)
662 {
663         LOGI("__app_grid_change_page_cb");
664         change_page_data_t *ch_page_data = (change_page_data_t *) data;
665         Evas_Object *parent = NULL;
666
667         s_info.change_page_timer = NULL;
668
669         if (!ch_page_data) {
670                 LOGE("[INVALID_PARAM][ch_page_data='%p']", ch_page_data);
671                 return ECORE_CALLBACK_CANCEL;
672         } else if (!ch_page_data->parent) {
673                 LOGE("[INVALID_PARAM][ch_page_data->parent='%p']", ch_page_data->parent);
674                 return ECORE_CALLBACK_CANCEL;
675         }
676
677         parent = ch_page_data->parent;
678
679         if (ch_page_data->action == NEXT_PAGE_CB) {
680                 LOGI("next_page_signal");
681                 elm_object_signal_emit(parent, SIGNAL_NEXT_PAGE_CHANGE, SIGNAL_SOURCE);
682         }
683
684         if (ch_page_data->action == PREV_PAGE_CB) {
685                 LOGI("prev_page_signal");
686                 elm_object_signal_emit(parent, SIGNAL_PREV_PAGE_CHANGE, SIGNAL_SOURCE);
687         }
688
689         return ECORE_CALLBACK_CANCEL;
690 }
691
692 static void __app_grid_check_page_change(Evas_Object *scroller, int x, int y)
693 {
694         if (!scroller) {
695                 LOGE("[INVALID_PARAM][scroller='%p']", scroller);
696                 return;
697         }
698
699         s_info.cp_data.parent = scroller;
700         home_screen_set_indice_state(INDICE_OFF);
701
702         if (x < CHANGE_PAGE_RIGHT_AREA * home_screen_get_root_width() &&
703                 x > CHANGE_PAGE_LEFT_AREA * home_screen_get_root_width()  &&
704                 s_info.change_page_timer) {
705                 ecore_timer_del(s_info.change_page_timer);
706                 s_info.change_page_timer = NULL;
707                 return;
708         }
709
710         if (x >= CHANGE_PAGE_RIGHT_AREA * home_screen_get_root_width()) {
711                 home_screen_set_indice_state(INDICE_NEXT_PAGE_ON);
712                 s_info.cp_data.action = NEXT_PAGE_CB;
713         }
714
715         if (x <= CHANGE_PAGE_LEFT_AREA * home_screen_get_root_width()) {
716                 home_screen_set_indice_state(INDICE_PREV_PAGE_ON);
717                 s_info.cp_data.action = PREV_PAGE_CB;
718         }
719
720         if (!s_info.change_page_timer) {
721                 s_info.change_page_timer = ecore_timer_add(CHANGE_PAGE_TIMER, __app_grid_change_page_cb,
722                                 (void *) &s_info.cp_data);
723         }
724 }
725
726 static Evas_Object *__app_grid_get_icon_container_ptr(Elm_Object_Item *it)
727 {
728         Evas_Object *container = NULL;
729
730         if (!it) {
731                 LOGE("[INVALID_PARAM][it='%p']", it);
732                 return NULL;
733         }
734
735         container = elm_object_item_part_content_get(it, GRID_CONTENT);
736         return container;
737 }
738
739 static void __app_grid_clear_reposition_structure(void)
740 {
741         s_info.destination_folder = NULL;
742         s_info.repositioned_icon_layout = NULL;
743         s_info.repositioned_item = NULL;
744         s_info.repositioned_icon = NULL;
745         s_info.repositioned_node = NULL;
746         s_info.opened_folder_node = NULL;
747         s_info.src_grid = NULL;
748         s_info.src_idx = -1;
749         s_info.is_dnd_on = false;
750
751         s_info.f_x = -1;
752         s_info.f_y = -1;
753         s_info.f_w = -1;
754         s_info.f_h = -1;
755
756         if (s_info.outside_folder_timer) {
757                 ecore_timer_del(s_info.outside_folder_timer);
758                 s_info.outside_folder_timer = NULL;
759         }
760
761         if (s_info.change_page_timer) {
762                 ecore_timer_del(s_info.change_page_timer);
763                 s_info.change_page_timer = NULL;
764         }
765 }
766
767 static Eina_Bool __app_grid_close_folder_cb(void *data)
768 {
769         data_model_detach_from_folder(s_info.opened_folder_node, s_info.repositioned_node);
770         folder_panel_close_folder();
771         return EINA_FALSE;
772 }
773
774 static Evas_Object *__app_grid_create_item_container(Evas_Object *parent)
775 {
776         Evas_Object *container = NULL;
777
778         if (!parent) {
779                 LOGE("[INVALID_PARAM]");
780                 return NULL;
781         }
782
783         container = elm_layout_add(parent);
784
785         if (!elm_layout_file_set(container, EDJE_DIR"/app_grid.edj", GROUP_APP_GRID_ITEM_CONTAINER)) {
786                 LOGE("[FAILED][elm_layout_file_set][%s]", EDJE_DIR"/app_grid.edj");
787                 evas_object_del(container);
788                 return NULL;
789         }
790
791         evas_object_size_hint_weight_set(container, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
792         evas_object_show(container);
793         return container;
794 }
795
796 /*=============================== DND FUNCTIONS ==================================================*/
797
798 static void __app_grid_return_to_origin_pos(void)
799 {
800         Evas_Object *container = NULL;
801
802         if (!s_info.repositioned_item || !s_info.repositioned_icon_layout) {
803                 LOGE("[FAILED][repositioned_item='%p'][repositioned_icon='%p']",
804                                 s_info.repositioned_item, s_info.repositioned_icon_layout);
805                 return;
806         }
807
808         container = __app_grid_get_icon_container_ptr(s_info.repositioned_item);
809         if (!container) {
810                 LOGE("[FAILED][__app_grid_get_icon_container_ptr]");
811                 return;
812         }
813
814         elm_object_part_content_set(container, PART_APP_GRID_ITEM, s_info.repositioned_icon_layout);
815         elm_object_part_content_set(s_info.repositioned_icon_layout,
816                                 PART_ICON_CONTENT, s_info.repositioned_icon);
817         evas_object_show(s_info.repositioned_icon_layout);
818 }
819
820 static void __app_grid_dnd_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y,
821                                 Elm_Xdnd_Action action)
822 {
823         static Elm_Object_Item *it = NULL;
824         Evas_Object *icon = NULL;
825         Evas_Object *old_icon = NULL;
826         Elm_Object_Item *old_it = it;
827         Tree_node_t *destination_icon_data = NULL;
828
829         it = elm_gengrid_at_xy_item_get(obj, x, y, NULL, NULL);
830
831         app_grid_get_item_content(old_it, &old_icon, NULL);
832         app_grid_get_item_content(it, &icon, &destination_icon_data);
833
834         if (!s_info.repositioned_node || !s_info.repositioned_node->data) {
835                 LOGE("[INVALID_DATA]");
836                 return;
837         }
838
839         if (it != old_it) {
840                 elm_object_signal_emit(old_icon, SIGNAL_UNHIGHLIGHT_FOLDER, SIGNAL_SOURCE);
841                 /*function not be invoked when s_info.repositioned_node == NULL;*/
842                 if (s_info.repositioned_node->data->type == APP_ITEM_FOLDER ||
843                         folder_panel_get_items_count(destination_icon_data) >= FOLDER_MAX_ITEMS) {
844                         elm_object_signal_emit(icon, SIGNAL_HIGHLIGHT_IMPOSSIBLE_FOLDER, SIGNAL_SOURCE);
845                 } else {
846                         elm_object_signal_emit(icon, SIGNAL_HIGHLIGHT_FOLDER, SIGNAL_SOURCE);
847                 }
848         }
849
850         if (destination_icon_data && destination_icon_data->data->type == APP_ITEM_FOLDER) {
851                 s_info.destination_folder = destination_icon_data;
852         } else {
853                 s_info.destination_folder = NULL;
854         }
855 }
856
857 static void __app_grid_dnd_drag_done_cb(void *data, Evas_Object *obj)
858 {
859         Tree_node_t *folder = s_info.destination_folder;
860         Tree_node_t *item = s_info.repositioned_node;
861         Tree_node_t *src_folder = s_info.opened_folder_node;
862
863         char trbuf[PATH_MAX] = {0, };
864
865         /*Check if folder has empty space*/
866         if (item && folder && folder_panel_get_items_count(folder) < FOLDER_MAX_ITEMS
867                 && item->data->type != APP_ITEM_FOLDER) {
868                 home_screen_mvc_drag_item_to_folder_cb(item, folder);
869                 evas_object_hide(s_info.repositioned_icon);
870         } else if (item && folder && folder_panel_get_items_count(folder) >= FOLDER_MAX_ITEMS) {
871                 popup_data_t *p_data = popup_create_data();
872                 if (!p_data) {
873                         LOGE("[FAILED][failed to create popup data]");
874                         return;
875                 }
876
877                 snprintf(trbuf, sizeof(trbuf), _("IDS_HS_TPOP_MAXIMUM_NUMBER_OF_APPLICATIONS_IN_FOLDER_HPD_REACHED"),
878                         FOLDER_APPS_PAGE);
879
880                 p_data->type = POPUP_INFO;
881                 p_data->popup_title_text = NULL;
882                 p_data->popup_content_text = strdup(trbuf);
883                 p_data->popup_confirm_text = NULL;
884                 p_data->popup_cancel_text = NULL;
885                 p_data->orientation = ELM_POPUP_ORIENT_CENTER;
886                 p_data->visible_time = 1.5;
887
888                 popup_show(p_data, NULL, NULL, NULL);
889
890                 __app_grid_return_to_origin_pos();
891         } else if (item && src_folder && !folder_panel_is_folder_visible()) {
892                 home_screen_mvc_drag_item_from_folder_cb();
893                 elm_object_part_content_set(s_info.repositioned_icon_layout, PART_ICON_CONTENT,
894                                 s_info.repositioned_icon);
895                 app_icon_set_view_mode(s_info.repositioned_icon_layout, home_screen_get_view_type(), false);
896         } else {
897                 __app_grid_return_to_origin_pos();
898         }
899
900         if (folder && folder->data->layout)
901                 elm_object_signal_emit(folder->data->layout, SIGNAL_UNHIGHLIGHT_FOLDER, SIGNAL_SOURCE);
902
903         __app_grid_clear_reposition_structure();
904         all_apps_set_scrolling_blocked_state(false);
905         folder_panel_enable_entry(true);
906 }
907
908 static void __app_grid_dnd_pos_changed_cb(void *data, Evas_Object *obj, Evas_Coord x,
909                                 Evas_Coord y, Elm_Xdnd_Action action)
910 {
911         evas_object_move(obj, x - s_info.dx, y - s_info.dy);
912
913         if (folder_panel_is_folder_visible()) {
914                 if ((y <= s_info.f_y || y >= s_info.f_y + s_info.f_h) && !s_info.outside_folder_timer) {
915                         s_info.outside_folder_timer = ecore_timer_add(1.0, __app_grid_close_folder_cb, NULL);
916                         if (!s_info.outside_folder_timer) {
917                                 LOGE("[FAILED][timer=NULL]");
918                                 return;
919                         }
920                 } else if (y >= s_info.f_y && y <= s_info.f_y + s_info.f_h) {
921                         ecore_timer_del(s_info.outside_folder_timer);
922                         s_info.outside_folder_timer = NULL;
923                 }
924         }
925 }