01f5490989be30fe10cc9238f86aaa1b726a3602
[profile/mobile/apps/native/homescreen-efl.git] / src / homescreen-efl.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 <tizen.h>
18 #include <Elementary.h>
19 #include <app.h>
20 #include <app_preference.h>
21 #include <system_settings.h>
22 #include <alloca.h>
23 #include "homescreen-efl.h"
24 #include "key.h"
25 #include "option_menu.h"
26 #include "livebox/livebox_panel.h"
27 #include "livebox/livebox_utils.h"
28 #include "mouse.h"
29 #include "app_mgr.h"
30 #include "app_icon.h"
31 #include "all_apps.h"
32 #include "data_model.h"
33 #include "layout.h"
34 #include "folder_panel.h"
35 #include "livebox_all_pages.h"
36 #include "mouse.h"
37 #include "popup.h"
38
39 static struct {
40         Evas_Object *win;
41         Evas_Object *bg;
42         Evas_Object *gradient_bg;
43         Evas_Object *conformant;
44         Evas_Object *layout;
45         Evas_Object *all_apps;
46         Evas_Object *home;
47         int root_width;
48         int root_height;
49         homescreen_view_t view_type;
50         bool is_bg_blurred;
51 } s_info = {
52         .win = NULL,
53         .bg = NULL,
54         .gradient_bg = NULL,
55         .conformant = NULL,
56         .layout = NULL,
57         .all_apps = NULL,
58         .home = NULL,
59         .root_width = 0,
60         .root_height = 0,
61         .view_type = HOMESCREEN_VIEW_HOME,
62         .is_bg_blurred = false
63 };
64
65 static bool mvc_badge_refresh_enable = true;
66
67 /*======================================UI HELPER FUNCTIONS========================*/
68 static void __homescreen_efl_create_base_gui(void);
69 static void __homescreen_efl_win_delete_request_cb(void *data, Evas_Object *obj, void *event_info);
70 static void __homescreen_efl_get_window_size(Evas_Object *win);
71 static void __homescreen_efl_home_btn_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
72 static void __homescreen_efl_menu_btn_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
73 static void __homescreen_efl_attach_badge_callback(void);
74 static void __homescreen_efl_detach_badge_callback(void);
75 static bool __homescreen_efl_update_icon_label(Tree_node_t *parent, Tree_node_t *node, void *data);
76 static void __homescreen_efl_make_gradient_bg(void);
77 static void __homescreen_efl_show_gradient_bg(void);
78 static void __homescreen_efl_show_normal_bg(void);
79
80 /*======================================APP CONTROL CALLBACKS=======================*/
81 static bool __homescreen_efl_app_create_cb(void *data);
82 static void __homescreen_efl_app_control_cb(app_control_h app_control, void *data);
83 static void __homescreen_efl_app_pause_cb(void *data);
84 static void __homescreen_efl_app_resume_cb(void *data);
85 static void __homescreen_efl_app_terminate_cb(void *data);
86
87
88 /*============================UI CALLBACKS==========================================*/
89 static void __homescreen_efl_lang_changed_cb(app_event_info_h event_info, void *user_data);
90 static void __homescreen_efl_orient_changed_cb(app_event_info_h event_info, void *user_data);
91 static void __homescreen_efl_region_changed_cb(app_event_info_h event_info, void *user_data);
92 static void __homescreen_efl_low_battery_cb(app_event_info_h event_info, void *user_data);
93 static void __homescreen_efl_low_memory_cb(app_event_info_h event_info, void *user_data);
94
95 /*====================  MVC Controller functions implementation: ===================*/
96 static bool __update_all_badges_count(Tree_node_t *parent, Tree_node_t *node, void *data);
97 static void __badge_change_cb(unsigned int action, const char *app_id, unsigned int count, void *user_data);
98 static bool __homescreen_efl_update_icon_badge(Tree_node_t *parent, Tree_node_t *node, void *data);
99 static void __homescreen_efl_badge_count_update_cb(void *app_item);
100 static void __homescreen_efl_activate_chooser_caption(void);
101 static void __homescreen_efl_deactivate_chooser_caption(void);
102 static void __homescreen_efl_chooser_caption_done_button_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
103 static void __homescreen_efl_chooser_caption_cancel_button_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
104 static bool __homescreen_efl_free_grid_item(Tree_node_t *page, Tree_node_t *item, void *data);
105 static bool __homescreen_efl_increment_page(Tree_node_t *parent, Tree_node_t *item, void *data);
106 static bool __homescreen_efl_attach_all_apps_grid_item(Tree_node_t *page, Tree_node_t *item, void *data);
107 static void __homescreen_efl_apply_data_model_to_view(void);
108 static void __homescreen_efl_show_all_apps(void);
109 static void __homescreen_efl_show_home_view(void);
110 static void __homescreen_efl_home_bg_changed_cb(system_settings_key_e key, void *data);
111 static void __homescreen_efl_apply_home_bg_effect(bool is_on);
112 static Eina_Bool __homescreen_efl_show_all_apps_anim(void *data, double pos);
113 static Eina_Bool __homescreen_efl_show_home_anim(void *data, double pos);
114 /*====================PUBLIC FUNCTIONS IMPLEMENTATION===============================*/
115
116 /*used to iterate over data model:*/
117 static bool folder_count_pending = false;
118 static unsigned int folder_badge_counter = 0;
119
120 int main(int argc, char *argv[])
121 {
122         dlog_print(DLOG_DEBUG, LOG_TAG, "Starting homescreen-efl");
123
124         int ret = 0;
125         ui_app_lifecycle_callback_s event_callback = {0,};
126         app_event_handler_h handlers[5] = {NULL, };
127
128         event_callback.create = __homescreen_efl_app_create_cb;
129         event_callback.terminate = __homescreen_efl_app_terminate_cb;
130         event_callback.pause = __homescreen_efl_app_pause_cb;
131         event_callback.resume = __homescreen_efl_app_resume_cb;
132         event_callback.app_control = __homescreen_efl_app_control_cb;
133
134         ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, __homescreen_efl_low_battery_cb, NULL);
135         ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, __homescreen_efl_low_memory_cb, NULL);
136         ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, __homescreen_efl_orient_changed_cb, NULL);
137         ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, __homescreen_efl_lang_changed_cb, NULL);
138         ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, __homescreen_efl_region_changed_cb, NULL);
139         ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);
140
141         ret = ui_app_main(argc, argv, &event_callback, NULL);
142         if (ret != APP_ERROR_NONE)
143                 dlog_print(DLOG_ERROR, LOG_TAG, "ui_app_main() is failed. err = %d", ret);
144
145         s_info.view_type = HOMESCREEN_VIEW_HOME;
146
147         return ret;
148 }
149
150 HAPI int home_screen_get_root_width(void)
151 {
152         return s_info.root_width;
153 }
154
155 HAPI int home_screen_get_root_height(void)
156 {
157         return s_info.root_height;
158 }
159
160 HAPI Evas_Object *home_screen_get_win(void)
161 {
162         return s_info.win;
163 }
164
165 HAPI Evas_Object *home_screen_get_layout(void)
166 {
167         return s_info.layout;
168 }
169
170 HAPI homescreen_view_t home_screen_get_view_type(void)
171 {
172         return s_info.view_type;
173 }
174
175 HAPI void home_screen_set_view_type(homescreen_view_t view)
176 {
177         switch (view) {
178         case HOMESCREEN_VIEW_HOME:
179                 __homescreen_efl_apply_home_bg_effect(false);
180                 __homescreen_efl_show_normal_bg();
181                 if (s_info.view_type == HOMESCREEN_VIEW_ALL_APPS) {
182                         all_apps_set_view_mode(view);
183                         __homescreen_efl_show_home_view();
184                 }
185                 else if(s_info.view_type == HOMESCREEN_VIEW_HOME_EDIT)
186                         elm_object_signal_emit(s_info.layout, SIGNAL_BOTTOM_BUTTONS_HOME_STATE_SET, SIGNAL_SOURCE);
187                 break;
188         case HOMESCREEN_VIEW_HOME_EDIT:
189                 LOGI("HOMESCREEN_VIEW_HOME_EDIT");
190                 elm_object_signal_emit(s_info.layout, SIGNAL_BOTTOM_BUTTONS_HOME_EDIT_STATE_SET, SIGNAL_SOURCE);
191                 break;
192         case HOMESCREEN_VIEW_HOME_ALL_PAGES:
193                 LOGI("HOMESCREEN_VIEW_HOME_ALL_PAGES");
194                 livebox_all_pages_show();
195                 break;
196         case HOMESCREEN_VIEW_ALL_APPS:
197                 __homescreen_efl_apply_home_bg_effect(true);
198                 __homescreen_efl_show_gradient_bg();
199                 if (s_info.view_type == HOMESCREEN_VIEW_HOME)
200                         __homescreen_efl_show_all_apps();
201
202                 if (s_info.view_type == HOMESCREEN_VIEW_ALL_APPS_CHOOSE)
203                         __homescreen_efl_deactivate_chooser_caption();
204                 all_apps_set_view_mode(view);
205                 elm_object_signal_emit(s_info.layout, SIGNAL_BOTTOM_BUTTONS_ALL_APPS_STATE_SET, SIGNAL_SOURCE);
206                 __badge_change_cb(0, NULL, 0, NULL);
207                 break;
208         case HOMESCREEN_VIEW_ALL_APPS_EDIT:
209                 LOGI("HOMESCREEN_VIEW_ALL_APPS_EDIT");
210                 if (s_info.view_type == HOMESCREEN_VIEW_ALL_APPS_CHOOSE)
211                         __homescreen_efl_deactivate_chooser_caption();
212                 all_apps_set_view_mode(view);
213                 elm_object_signal_emit(s_info.layout, SIGNAL_BOTTOM_BUTTONS_ALL_APPS_EDIT_STATE_SET, SIGNAL_SOURCE);
214                 break;
215         case HOMESCREEN_VIEW_ALL_APPS_CHOOSE:
216                 LOGI("HOMESCREEN_VIEW_ALL_APPS_CHOOSE");
217                 __homescreen_efl_activate_chooser_caption();
218                 all_apps_set_view_mode(view);
219                 break;
220         case HOMESCREEN_VIEW_UNKNOWN:
221                 LOGI("HOMESCREEN_VIEW_UNKNOWN");
222                 break;
223         default:
224                 LOGE("UKNOWN VIEW TYPE");
225                 break;
226         }
227
228         s_info.view_type = view;
229 }
230
231 HAPI void home_screen_set_indice_state(indice_type_t indice)
232 {
233         switch (indice) {
234         case INDICE_NEXT_PAGE_ON:
235                 elm_object_signal_emit(s_info.layout, SIGNAL_NEXT_PAGE_INDICE_SHOW, SIGNAL_SOURCE);
236                 break;
237         case INDICE_PREV_PAGE_ON:
238                 elm_object_signal_emit(s_info.layout, SIGNAL_PREV_PAGE_INDICE_SHOW, SIGNAL_SOURCE);
239                 break;
240         case INDICE_OFF:
241                 elm_object_signal_emit(s_info.layout, SIGNAL_INDICE_HIDE, SIGNAL_SOURCE);
242                 break;
243         default:
244                 break;
245         }
246 }
247
248 HAPI void home_screen_mvc_set_ly_scale(Evas_Object *layout)
249 {
250         Evas_Object *edje = NULL;
251         int width = -1;
252         int height = -1;
253
254         if (!layout) {
255                 LOGE("[FAILED][invalid parameter]");
256                 return;
257         }
258
259         edje = elm_layout_edje_get(layout);
260
261         width = s_info.root_width;
262         height = s_info.root_height;
263
264         if (width == HD_WIDTH && height == HD_HEIGHT) {
265                 LOGD("HD_RES");
266                 edje_object_scale_set(edje, HD_SCALE_FACTOR);
267         } else if(width == QHD_WIDTH && height == QHD_HEIGHT) {
268                 LOGD("QHD_RES");
269                 edje_object_scale_set(edje, QHD_SCALE_FACTOR);
270         } else if(width == WVGA_WIDTH && height == WVGA_HEIGHT) {
271                 LOGD("WVGA_RES");
272                 edje_object_scale_set(edje, WVGA_SCALE_FACTOR);
273         } else if(width == UHD_WIDTH && height == UHD_HEIGHT) {
274                 edje_object_scale_set(edje, UHD_SCALE_FACTOR);
275         }
276 }
277
278 HAPI void home_screen_close_all_apps_choose_view(void)
279 {
280         folder_panel_cancel_add_icon();
281         folder_panel_set_click_ignore_state(false);
282         data_model_check_all_apps(data_model_get_all_apps(), false);
283         home_screen_set_view_type(HOMESCREEN_VIEW_ALL_APPS);
284 }
285
286 /*====================END OF PUBLIC FUNCTIONS IMPLEMENTATION=========================*/
287
288 static void __homescreen_efl_win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
289 {
290         ui_app_exit();
291 }
292
293 static Evas_Object *_create_conformant(void)
294 {
295         Evas_Object *conformant = NULL;
296
297         if (!s_info.win) {
298                 LOGE("Window is not created");
299                 return NULL;
300         }
301
302         conformant = elm_conformant_add(s_info.win);
303         if (!conformant) {
304                 LOGE("Failed to create conformant");
305                 return NULL;
306         }
307         elm_win_conformant_set(s_info.win, EINA_TRUE);
308
309         evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
310         elm_win_resize_object_add(s_info.win, conformant);
311
312         elm_win_indicator_mode_set(s_info.win, ELM_WIN_INDICATOR_SHOW);
313         elm_win_indicator_opacity_set(s_info.win, ELM_WIN_INDICATOR_TRANSLUCENT);
314         elm_object_signal_emit(conformant, "elm,state,indicator,overlap", "elm");
315
316         evas_object_show(conformant);
317
318         return conformant;
319 }
320
321 static void __homescreen_efl_create_base_gui(void)
322 {
323         char edj_path[PATH_MAX] = {0, };
324         const char *bg_path = util_get_res_file_path(IMAGE_DIR"/default_bg.png");
325         char trbuf[PATH_MAX] = {0, };
326         char *buf = NULL;
327         int ret = -1;
328
329         /* Window */
330         s_info.win = elm_win_util_standard_add(PACKAGE, PACKAGE);
331         // evas_object_resize(s_info.win, 1440, 2560);
332         elm_win_autodel_set(s_info.win, EINA_TRUE);
333
334         evas_object_smart_callback_add(s_info.win, "delete,request", __homescreen_efl_win_delete_request_cb, NULL);
335
336         /*Background*/
337         s_info.bg = evas_object_image_filled_add(evas_object_evas_get(s_info.win));
338
339         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &buf);
340         if (!buf || ret != SYSTEM_SETTINGS_ERROR_NONE) {
341                 evas_object_image_file_set(s_info.bg, bg_path, "bg");
342         } else {
343                 evas_object_image_file_set(s_info.bg, buf, "bg");
344                 free(buf);
345         }
346
347         system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, __homescreen_efl_home_bg_changed_cb, NULL);
348
349         elm_win_resize_object_add(s_info.win, s_info.bg);
350         evas_object_show(s_info.bg);
351
352         __homescreen_efl_get_window_size(s_info.win);
353
354         /* Conformant */
355         s_info.conformant = _create_conformant();
356
357         // /* Base Layout */
358         snprintf(edj_path, sizeof(edj_path), "%s", util_get_res_file_path(EDJE_DIR"/home.edj"));
359         s_info.layout = elm_layout_add(s_info.win);
360         elm_layout_file_set(s_info.layout, edj_path, GROUP_HOME_LY);
361         evas_object_size_hint_weight_set(s_info.layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
362         elm_win_resize_object_add(s_info.win, s_info.layout);
363         evas_object_show(s_info.layout);
364
365         home_screen_mvc_set_ly_scale(s_info.layout);
366
367         s_info.home = livebox_panel_create(s_info.layout);
368         if (!s_info.home) {
369                 evas_object_del(s_info.win);
370                 evas_object_del(s_info.bg);
371                 evas_object_del(s_info.conformant);
372                 evas_object_del(s_info.layout);
373
374                 LOGE("s_info.home == NULL");
375                 return;
376         }
377
378         elm_object_part_content_set(s_info.layout, PART_CONTENT, s_info.home);
379
380         /* Show window after base gui is set up */
381         dlog_print(DLOG_INFO, LOG_TAG ,"WINDOW SIZE IS : %d %d", s_info.root_width, s_info.root_height);
382         evas_object_show(s_info.win);
383         elm_object_signal_callback_add(s_info.layout, SIGNAL_HOME_BTN_CLICKED, SIGNAL_SOURCE, __homescreen_efl_home_btn_clicked, NULL);
384         elm_object_signal_callback_add(s_info.layout, SIGNAL_MENU_BTN_CLICKED, SIGNAL_SOURCE, __homescreen_efl_menu_btn_clicked, NULL);
385
386         /*Chooser caption setup:*/
387         elm_layout_signal_callback_add(s_info.layout, "mouse,clicked,*",
388                 "chooser_caption_left_clickable_space",
389                 __homescreen_efl_chooser_caption_cancel_button_cb, NULL);
390         elm_layout_signal_callback_add(s_info.layout, "mouse,clicked,*",
391                 "chooser_caption_right_clickable_space",
392                 __homescreen_efl_chooser_caption_done_button_cb, NULL);
393
394         snprintf(trbuf, sizeof(trbuf), _("IDS_MEMO_HEADER_PD_SELECTED_ABB2"), 0);
395         layout_main_caption_set_menu_texts(trbuf,
396                 _("IDS_TPLATFORM_ACBUTTON_CANCEL_ABB"),
397                 _("IDS_TPLATFORM_ACBUTTON_DONE_ABB"));
398 }
399
400 /*TODO: coding convention!*/
401 bool tree_print_cb(Tree_node_t *parent_node, Tree_node_t *tn, void *data)
402 {
403         app_item_t *item = tn->data;
404         app_item_t *parent = NULL;
405
406         if (tn->parent)
407                 parent = tn->parent->data;
408
409         LOGD("TYPE: %2d; PARENT name: %12.12s; id: %2d | ITEM appid: %28.28s; id: %2d; [%d, %d; %d, %d]; %s",
410                         item->type,
411                         parent ? parent->appid  : "NULL",
412                         parent ? parent->unique_id : -1,
413                         item->appid,
414                         item->unique_id,
415                         item->col,
416                         item->row,
417                         item->col_span,
418                         item->row_span,
419                         item->content_info);
420
421         return true;
422 }
423
424 /*TODO: coding convention!*/
425 void home_screen_print_tree(void)
426 {
427         LOGD("TREE TEST START");
428         data_model_iterate(data_model_get_data(), tree_print_cb, NULL);
429 }
430
431 static void __homescreen_efl_attach_badge_callback(void)
432 {
433         app_mgr_register_badge_callback(__badge_change_cb);
434 }
435
436 static void __homescreen_efl_detach_badge_callback(void)
437 {
438         app_mgr_unregister_badge_callback(__badge_change_cb);
439 }
440
441 static bool __homescreen_efl_app_create_cb(void *data)
442 {
443         elm_config_accel_preference_set("3d");
444         ecore_animator_frametime_set(FRAMES_PER_SECOND);
445
446         key_register();
447         mouse_register();
448
449         __homescreen_efl_create_base_gui();
450         folder_panel_init_module();
451         app_mgr_init();
452
453         if(!data_model_load_db()) {
454                 data_model_load_app_mgr();
455         }
456
457         livebox_panel_fill();
458         livebox_panel_set_content(s_info.layout);
459         __homescreen_efl_attach_badge_callback();
460
461         home_screen_mvc_update_view();
462         return true;
463 }
464
465 static void __homescreen_efl_app_control_cb(app_control_h app_control, void *data)
466 {
467         elm_win_activate(s_info.win);
468 }
469
470 static void __homescreen_efl_app_pause_cb(void *data)
471 {
472         /* Take necessary actions when application becomes invisible. */
473         livebox_panel_paused();
474 }
475
476 static void __homescreen_efl_app_resume_cb(void *data)
477 {
478         /* Take necessary actions when application becomes visible. */
479         livebox_panel_resumed();
480 }
481
482 static void __homescreen_efl_app_terminate_cb(void *data)
483 {
484         /* Release all resources. */
485         __homescreen_efl_detach_badge_callback();
486         mouse_unregister();
487         key_unregister();
488         app_mgr_deinit();
489         all_apps_del();
490         popup_destroy();
491         folder_panel_deinit_module();
492         data_model_free();
493         livebox_panel_destroy();
494 }
495
496 static bool __homescreen_efl_update_icon_label(Tree_node_t *parent, Tree_node_t *node, void *data)
497 {
498         if(!node || !node->data)
499                 return false;
500
501         /*update model*/
502         if (node->data->label && node->data->type == APP_ITEM_ICON) {
503                 free(node->data->label);
504                 node->data->label = app_mgr_get_app_label(node->data->appid);
505         }
506
507         /*update view*/
508         elm_object_part_text_set(node->data->layout, PART_ICON_NAME, node->data->label);
509
510         return true;
511 }
512
513 static void __homescreen_efl_make_gradient_bg(void)
514 {
515 #ifdef HOME_HOME_SCREEN_GRADIENT_ENABLED
516         Evas_Map *m = NULL;
517         Evas_Colorspace ec = EVAS_COLORSPACE_ARGB8888;
518         char *image_raw_data = NULL;
519         int image_width = 0;
520         int image_height = 0;
521         int r = 0;
522         int g = 0;
523         int b = 0;
524         int a = 0;
525
526         if(!s_info.bg)
527                 return;
528
529         ec = evas_object_image_colorspace_get(s_info.bg);
530
531         if(ec != EVAS_COLORSPACE_ARGB8888)
532                 return;
533
534         image_raw_data = evas_object_image_data_get(s_info.bg, EINA_FALSE);
535         if(!image_raw_data)
536                 return;
537
538         evas_object_image_size_get(s_info.bg, &image_width, &image_height);
539         if(image_width == 0 || image_height == 0)
540                 return;
541
542         if(!s_info.gradient_bg)
543                 s_info.gradient_bg = evas_object_rectangle_add(evas_object_evas_get(s_info.win));
544
545         if(!s_info.gradient_bg)
546                 return;
547
548         evas_object_resize(s_info.gradient_bg, s_info.root_width, s_info.root_height);
549
550         m = evas_map_new(4);
551         if(!m)
552                 return;
553
554         evas_map_util_points_populate_from_object(m, s_info.gradient_bg);
555
556         r = image_raw_data[2] & 0xff;
557         g = image_raw_data[1] & 0xff;
558         b = image_raw_data[0] & 0xff;
559         a = image_raw_data[3] & 0xff;
560         evas_map_point_color_set(m, 0, r, g, b, a);
561
562         r = image_raw_data[4*image_width -4 + 2] & 0xff;
563         g = image_raw_data[4*image_width -4 + 1] & 0xff;
564         b = image_raw_data[4*image_width -4 + 0] & 0xff;
565         a = image_raw_data[4*image_width -4 + 3] & 0xff;
566         evas_map_point_color_set(m, 1, r, g, b, a);
567
568         r = image_raw_data[4*image_width -4 + (image_height-1)*4*image_width + 2] & 0xff;
569         g = image_raw_data[4*image_width -4 + (image_height-1)*4*image_width + 1] & 0xff;
570         b = image_raw_data[4*image_width -4 + (image_height-1)*4*image_width + 0] & 0xff;
571         a = image_raw_data[4*image_width -4 + (image_height-1)*4*image_width + 3] & 0xff;
572         evas_map_point_color_set(m, 2, r, g, b, a);
573
574         r = image_raw_data[(image_height-1)*4*image_width + 2] & 0xff;
575         g = image_raw_data[(image_height-1)*4*image_width + 1] & 0xff;
576         b = image_raw_data[(image_height-1)*4*image_width + 0] & 0xff;
577         a = image_raw_data[(image_height-1)*4*image_width + 3] & 0xff;
578         evas_map_point_color_set(m, 3, r, g, b, a);
579
580         evas_object_map_set(s_info.gradient_bg, m);
581         evas_object_map_enable_set(s_info.gradient_bg, EINA_TRUE);
582         evas_map_free(m);
583 #endif
584 }
585
586 static void __homescreen_efl_show_gradient_bg(void)
587 {
588 #ifdef HOME_HOME_SCREEN_GRADIENT_ENABLED
589         if(s_info.gradient_bg) {
590                 evas_object_hide(s_info.bg);
591                 elm_win_resize_object_del(s_info.win, s_info.bg);
592                 elm_win_resize_object_add(s_info.win, s_info.gradient_bg);
593                 evas_object_show(s_info.gradient_bg);
594                 evas_object_raise(s_info.layout);
595         }
596 #endif
597 }
598
599 static void __homescreen_efl_show_normal_bg(void)
600 {
601 #ifdef HOME_HOME_SCREEN_GRADIENT_ENABLED
602         evas_object_hide(s_info.gradient_bg);
603         elm_win_resize_object_del(s_info.win, s_info.gradient_bg);
604         elm_win_resize_object_add(s_info.win, s_info.bg);
605         evas_object_show(s_info.bg);
606         evas_object_raise(s_info.layout);
607 #endif
608 }
609
610 static void __homescreen_efl_lang_changed_cb(app_event_info_h event_info, void *user_data)
611 {
612         data_model_iterate(NULL, __homescreen_efl_update_icon_label, NULL);
613 }
614
615 static void __homescreen_efl_orient_changed_cb(app_event_info_h event_info, void *user_data)
616 {
617         /*APP_EVENT_DEVICE_ORIENTATION_CHANGED*/
618 }
619
620 static void __homescreen_efl_region_changed_cb(app_event_info_h event_info, void *user_data)
621 {
622         /*APP_EVENT_REGION_FORMAT_CHANGED*/
623 }
624
625 static void __homescreen_efl_low_battery_cb(app_event_info_h event_info, void *user_data)
626 {
627         /*APP_EVENT_LOW_BATTERY*/
628 }
629
630 static void __homescreen_efl_low_memory_cb(app_event_info_h event_info, void *user_data)
631 {
632         /*APP_EVENT_LOW_MEMORY*/
633 }
634
635 static void __homescreen_efl_get_window_size(Evas_Object *win)
636 {
637         elm_win_screen_size_get(win, NULL, NULL, &s_info.root_width, &s_info.root_height);
638         dlog_print(DLOG_DEBUG, LOG_TAG, "Width: [%d], Height: [%d]", s_info.root_width, s_info.root_height);
639 }
640
641 static void __homescreen_efl_home_btn_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
642 {
643         homescreen_view_t view_t = home_screen_get_view_type();
644
645         if (view_t == HOMESCREEN_VIEW_HOME) {
646                 home_screen_set_view_type(HOMESCREEN_VIEW_ALL_APPS);
647         } else if (view_t == HOMESCREEN_VIEW_ALL_APPS) {
648                 home_screen_set_view_type(HOMESCREEN_VIEW_HOME);
649         }
650 }
651
652 static void __homescreen_efl_menu_btn_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
653 {
654         homescreen_view_t view = home_screen_get_view_type();
655
656         switch (view) {
657         case HOMESCREEN_VIEW_HOME:
658         case HOMESCREEN_VIEW_ALL_APPS:
659                 option_menu_show();
660                 break;
661         default:
662                 break;
663         }
664 }
665
666 /*====================  MVC Controller functions implementation: ===================*/
667
668 /*TODO: code convention!*/
669 void home_screen_mvc_item_uninstall_cb(Tree_node_t *item)
670 {
671         if (!item || !item->data)
672                 return;
673
674         if (item->data->type == APP_ITEM_ICON) {
675                 app_mgr_uninstall_app(item->data->appid);
676                 data_model_uninstall_application(item);
677         } else {/*folder item type:*/
678                 data_model_delete_folder(item);
679         }
680
681         /*by default model is being sorted:*/
682         data_model_sort(NULL);
683         data_model_free_empty_pages(NULL);
684         __homescreen_efl_apply_data_model_to_view();
685         all_apps_remove_empty_pages();
686 }
687
688 void home_screen_mvc_update_view(void)
689 {
690         data_model_sort(NULL);
691         __homescreen_efl_apply_data_model_to_view();
692 }
693
694 void home_screen_mvc_drag_item_to_folder_cb(Tree_node_t *dragged_item, Tree_node_t *folder)
695 {
696         if (dragged_item && folder) {
697                 if (!folder->last)
698                         data_model_append_node_to_folder(folder, dragged_item); /*there were no pages in folder*/
699                 else
700                         data_model_reposition_item(dragged_item, folder->last, folder->last->last, REPOSITION_SIDE_TO_RIGHT, FOLDER_APPS_PAGE);
701
702                 /*for now model is always sorted:*/
703                 data_model_sort(NULL);
704                 data_model_free_empty_pages(NULL);
705                 __homescreen_efl_apply_data_model_to_view();
706                 all_apps_remove_empty_pages();
707         }
708 }
709
710 /*TODO:All mvc funcitons will be moved to separeted file.*/
711 void home_screen_mvc_drag_item_from_folder_cb(void)
712 {
713         __homescreen_efl_apply_data_model_to_view();
714 }
715
716 static void __homescreen_efl_activate_chooser_caption(void)
717 {
718         data_model_check_all_apps(data_model_get_all_apps(), false);
719         elm_layout_signal_emit(s_info.layout, SIGNAL_CHOOSER_CAPTION_ACTIVATE, SIGNAL_SOURCE);
720         elm_win_indicator_mode_set(s_info.win, ELM_WIN_INDICATOR_HIDE);
721 }
722
723 static void __homescreen_efl_deactivate_chooser_caption(void)
724 {
725         elm_layout_signal_emit(s_info.layout, SIGNAL_CHOOSER_CAPTION_DEACTIVATE, SIGNAL_SOURCE);
726         elm_win_indicator_mode_set(s_info.win, ELM_WIN_INDICATOR_SHOW);
727 }
728
729 static bool __homescreen_efl_free_grid_item(Tree_node_t *page, Tree_node_t *item, void *data)
730 {
731         if (!item->data || !item->data->grid_item) {
732                 LOGE("__homescreen_efl_free_grid_item, skipping: %d %d", item->data, item->data ? item->data->type : -1);
733                 return true;
734         }
735
736         if (!item->data->layout)
737                 LOGD("__homescreen_efl_free_grid_item, %s item->data->layout == NULL", item->data->label);
738
739         all_apps_detach_from_grid(item->data->grid_item);
740         item->data->grid_item = NULL;
741         evas_object_hide(item->data->layout);
742
743         return true;
744 }
745
746 static bool __homescreen_efl_increment_page(Tree_node_t *parent, Tree_node_t *item, void *data)
747 {
748         (*((int *)data))++;
749
750         return true;
751 }
752
753 static bool __homescreen_efl_attach_all_apps_grid_item(Tree_node_t *page, Tree_node_t *item, void *data)
754 {
755         if (!item->data) {
756                 LOGE("__homescreen_efl_attach_all_apps_grid_item, skipping: %d", item->data);
757                 return true;
758         }
759
760         item->data->grid_item = all_apps_attach_to_grid(item->data->layout, *(int *)data);
761
762         if (!item->data->grid_item) {
763         /*failed to attach item - there is no room in page scroller
764         so we have to add another page. This problem does not concern folders.*/
765
766                 if (!all_apps_append_page(page))
767                         LOGE("Could not create page for item: %s", item->data->label);
768         }
769
770         app_icon_set_view_mode(item->data->layout, home_screen_get_view_type(), false);
771
772         return true;
773 }
774
775 static bool _folder_grid_item_att(Tree_node_t *page, Tree_node_t *item, void *data)
776 {
777         if (!item->data || !page->parent || !page->parent->data ||
778                 page->parent->data->type != APP_ITEM_FOLDER ||
779                 folder_panel_get_opened_folder_item() != page->parent->data) {
780                 LOGE("_folder_grid_item_att, skipping: %s dest_folder: %d", item->data ? item->data->appid : NULL);
781                 return true;
782         }
783
784         item->data->grid_item = folder_panel_attach_to_grid(item->data->layout, ((app_item_t *)page->parent->data)->data);
785
786         return true;
787 }
788
789 static bool _folder_data_model_to_view_apply_cb(Tree_node_t *page, Tree_node_t *item, void *data)
790 {
791         if (!item->data || item->data->type != APP_ITEM_FOLDER)
792                 return true;
793
794         data_model_iterate_pages(item, NULL, __homescreen_efl_free_grid_item, NULL);
795         data_model_iterate_pages(item, NULL, _folder_grid_item_att, NULL);
796         app_icon_update_folder_icon(item);
797         return true;
798 }
799
800 static void __homescreen_efl_apply_data_model_to_view(void)
801 {
802         int page_counter = -1;
803         Tree_node_t *apps_root = data_model_get_all_apps();
804
805         if (!apps_root || !apps_root->data || apps_root->data->type != APP_ITEM_ALL_APPS_ROOT) {
806                 LOGE("Can't apply view [apps root]: %d %d", apps_root, apps_root ? apps_root->data : NULL);
807                 return;
808         }
809
810         mvc_badge_refresh_enable = false;
811
812         data_model_iterate_pages(NULL, NULL, __homescreen_efl_free_grid_item, NULL);
813         data_model_iterate_pages(NULL, NULL, _folder_data_model_to_view_apply_cb, NULL);
814         data_model_iterate_pages(NULL, __homescreen_efl_increment_page, __homescreen_efl_attach_all_apps_grid_item, &page_counter);
815         all_apps_update_dynamic_index_count();
816
817         mvc_badge_refresh_enable = true;
818
819         __badge_change_cb(0, NULL, 0, NULL);
820 }
821
822 static bool _checked_items_get(Tree_node_t *root, Tree_node_t *item, void *list)
823 {
824         Eina_List **checked_items_list = (Eina_List **)list;
825
826         if (item->data && item->data->is_checked) {
827                 *checked_items_list = eina_list_append(*checked_items_list, item);
828                 item->data->is_checked = false;
829         }
830
831         return true;
832 }
833
834 static void __homescreen_efl_chooser_caption_done_button_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
835 {
836         /*Folder creation/modification:*/
837         app_item_t *destination_folder_data = NULL;
838         Eina_List *iterator = NULL, *checked_items_list = NULL;
839         Tree_node_t *item = NULL;
840         Tree_node_t *destination_folder = folder_panel_get_opened_folder_node();
841
842         if (!destination_folder) {
843                 destination_folder_data = app_item_create(APP_ITEM_FOLDER, -1, "", NULL, NULL, NULL, NULL, true, 0, 0, 0, 0, NULL);
844
845                 if (!destination_folder_data) {
846                         LOGE("caption_done_button_cb: failed to create destination_folder_data");
847                         return;
848                 }
849
850                 destination_folder = data_model_create_folder(destination_folder_data);
851
852                 if (!destination_folder) {
853                         LOGE("caption_done_button_cb: failed to create destination_folder");
854                         folder_panel_cancel_add_icon();
855                         folder_panel_set_click_ignore_state(false);
856                         app_item_free(destination_folder_data);
857                         return;
858                 }
859                 folder_panel_create(destination_folder);
860         }
861
862         /*all checked items should be added to the folder:*/
863         data_model_iterate(NULL, _checked_items_get, &checked_items_list);
864
865         EINA_LIST_FOREACH(checked_items_list, iterator, item)
866                 data_model_append_node_to_folder(destination_folder, item);
867
868         eina_list_free(checked_items_list);
869         /*for now they are always sorted:*/
870         data_model_sort(NULL);
871
872         folder_panel_cancel_add_icon();
873         folder_panel_set_click_ignore_state(false);
874
875         data_model_free_empty_pages(NULL);
876         home_screen_set_view_type(HOMESCREEN_VIEW_ALL_APPS);
877         __homescreen_efl_apply_data_model_to_view();
878         all_apps_remove_empty_pages();
879 }
880
881 static void __homescreen_efl_chooser_caption_cancel_button_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
882 {
883         home_screen_close_all_apps_choose_view();
884 }
885
886 static void __homescreen_efl_show_all_apps(void)
887 {
888         livebox_panel_unset_content(s_info.layout);
889         all_apps_show();
890
891         if (!s_info.all_apps)
892                 s_info.all_apps = all_apps_create(s_info.layout, NULL);
893
894         elm_object_part_content_unset(s_info.layout, PART_CONTENT);
895
896         evas_object_hide(s_info.all_apps);
897         evas_object_move(s_info.all_apps, 0, s_info.root_height);
898
899         elm_object_signal_emit(s_info.layout, SIGNAL_BLOCK_EVENTS, SIGNAL_SOURCE);
900         app_icon_set_click_ignore(true);
901
902         ecore_animator_timeline_add(APPS_SHOW_HIDE_ANIMATION_TIME, __homescreen_efl_show_all_apps_anim, NULL);
903 }
904
905 static void __homescreen_efl_show_home_view(void)
906 {
907         elm_object_part_content_unset(s_info.layout, PART_CONTENT);
908         all_apps_hide();
909         elm_object_signal_emit(s_info.layout, SIGNAL_BOTTOM_BUTTONS_HOME_STATE_SET, SIGNAL_SOURCE);
910
911         elm_object_signal_emit(s_info.layout, SIGNAL_BLOCK_EVENTS, SIGNAL_SOURCE);
912         app_icon_set_click_ignore(true);
913
914         ecore_animator_timeline_add(APPS_SHOW_HIDE_ANIMATION_TIME, __homescreen_efl_show_home_anim, NULL);
915 }
916
917 static bool __update_all_badges_count(Tree_node_t *parent, Tree_node_t *node, void *data)
918 {
919         app_item_t *item = NULL;
920
921         if (node) {
922                 item = node->data;
923                 __homescreen_efl_badge_count_update_cb(item);
924         }
925
926         return true;
927 }
928
929 static void __badge_change_cb(unsigned int action, const char *app_id, unsigned int count, void *user_data)
930 {
931         data_model_iterate(NULL, __update_all_badges_count, NULL);
932 }
933
934 static bool __homescreen_efl_update_icon_badge(Tree_node_t *parent, Tree_node_t *node, void *data)
935 {
936         app_item_t *app = (app_item_t *)data;
937
938         if (!folder_count_pending && app != node->data)
939                 return true;
940
941         if (!folder_count_pending && app == node->data) {
942                 folder_count_pending = true;
943                 data_model_iterate(node, __homescreen_efl_update_icon_badge, app);
944                 folder_count_pending = false;
945         }
946
947         if (folder_count_pending && node->data->type == APP_ITEM_ICON)
948                 folder_badge_counter += node->data->badge_count;
949
950         if (!folder_count_pending && app == node->data)
951                 return false;
952
953         return true;
954 }
955
956 static void __homescreen_efl_badge_count_update_cb(void *app_item)
957 {
958         app_item_t *app = (app_item_t *)app_item;
959
960         if (!mvc_badge_refresh_enable)
961                 return;
962
963         if (!app) {
964                 LOGE("badge_count_update_cb: app_item is NULL");
965                 return;
966         }
967
968         if (app->type == APP_ITEM_ICON && !app_mgr_app_get_badge_count(app->appid, &app->badge_count)) {
969                 LOGE("badge_count_update_cb: get_badge_count returned error");
970                 return;
971         }
972
973         if (app->type == APP_ITEM_FOLDER) {
974                 folder_count_pending = false;
975                 folder_badge_counter = 0;
976                 data_model_iterate(NULL, __homescreen_efl_update_icon_badge, app);
977                 app->badge_count = folder_badge_counter;
978         }
979
980         app_icon_show_badge(app->layout, app->badge_count);
981 }
982
983 static void __homescreen_efl_home_bg_changed_cb(system_settings_key_e key, void *data)
984 {
985         char *buf = NULL;
986         int ret = -1;
987
988         if (!s_info.bg) {
989                 LOGE("[FAILED][bg=NULL]");
990                 return;
991         }
992
993         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &buf);
994         if (!buf || ret != SYSTEM_SETTINGS_ERROR_NONE) {
995                 LOGE("[FAILED][failed to get bg path]");
996                 return;
997         }
998
999         evas_object_image_file_set(s_info.bg, buf, "bg");
1000         free(buf);
1001
1002         __homescreen_efl_make_gradient_bg();
1003 }
1004
1005 static void __homescreen_efl_apply_home_bg_effect(bool is_on)
1006 {
1007         #ifndef HOME_HOME_SCREEN_BLUR_ENABLED
1008                 return;
1009         #endif
1010         char *buf = NULL;
1011
1012         /*source data and destination data (pixel values)*/
1013         uint32_t *src = NULL, *dst = NULL;
1014
1015         /*values of channels in each pixel*/
1016         uint32_t A = 0, R = 0, G = 0, B = 0;
1017
1018         /*helper variables*/
1019         uint32_t *s = NULL, *d = NULL, w = 0, p = 0;
1020
1021         int width = -1, height = -1;
1022
1023         /*iterators*/
1024         int i = 0, j = 0, k = 0;
1025
1026         /*kernel used for transform the image*/
1027         uint8_t kernel[25];
1028         const int size = COUNT_OF(kernel);
1029         const int half = size / 2;
1030
1031         if (!s_info.bg) {
1032                 LOGE("[FAILED][bg=NULL]");
1033                 return;
1034         }
1035
1036         /*if is_on == false, then restore original image data*/
1037         if (!is_on) {
1038                 /*restore original data and return;*/
1039                 system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &buf);
1040                 if (!buf) {
1041                         LOGE("[FAILED][failed to get bg path]");
1042                         return;
1043                 }
1044
1045                 evas_object_image_file_set(s_info.bg, buf, "bg");
1046                 free(buf);
1047                 s_info.is_bg_blurred = false;
1048                 return;
1049         }
1050
1051         evas_object_image_size_get(s_info.bg, &width, &height);
1052         src = evas_object_image_data_get(s_info.bg, EINA_TRUE);
1053
1054         /*if image is already blurred then we should not perform once again*/
1055         if (s_info.is_bg_blurred)
1056                 return;
1057
1058         dst = (uint32_t *) alloca(sizeof(uint32_t) * width * height);
1059         if (!dst) {
1060                 LOGE("[FAILED][dst=NULL]");
1061                 return;
1062         }
1063
1064         /*Fill the kernel*/
1065         w = 0;
1066         for (i = 0; i < size; i++) {
1067                 double f = i - half;
1068                 w += kernel[i] = exp(-f * f / 60.0) * 40;
1069         }
1070
1071         /*Apply modifications from src - > dst*/
1072         for (i = 0; i < height; i++) {
1073                 s = (uint32_t *) (src + i * width);
1074                 d = (uint32_t *) (dst + i * width);
1075
1076                 for (j = 0; j < width; j++) {
1077                         A = R = G = B = 0;
1078                         for (k = 0; k < size; k++) {
1079                                 if (j - half + k < 0 || j - half + k >= width) {
1080                                         d[j] = s[j];
1081                                         continue;
1082                                 }
1083
1084                                 p = s[j - half + k];
1085
1086                                 A = (p & 0xff000000);
1087                                 R += ((p >> 16) & 0xff) * kernel[k];
1088                                 G += ((p >>  8) & 0xff) * kernel[k];
1089                                 B += ((p >>  0) & 0xff) * kernel[k];
1090                         }
1091                         d[j] = A | (((uint32_t)(R / w)) << 16) | (((uint32_t)(G / w)) << 8) | ((uint32_t)(B / w));
1092                 }
1093         }
1094
1095         /*Apply modification from dst -> srcs*/
1096         for (i = 0; i < height; i++) {
1097                 s = (uint32_t *) (dst + i * width);
1098                 d = (uint32_t *) (src + i * width);
1099                 for (j = 0; j < width; j++) {
1100                         A = R = G = B = 0;
1101                         for (k = 0; k < size; k++) {
1102                                 if (i - half + k < 0 || i - half + k >= height) {
1103                                         d[j] = s[j];
1104                                         continue;
1105                                 }
1106
1107                                 s = (uint32_t *) (dst + (i - half + k) * width);
1108                                 p = s[j];
1109
1110                                 A = (p & 0xff000000);
1111                                 R += ((p >> 16) & 0xff) * kernel[k];
1112                                 G += ((p >>  8) & 0xff) * kernel[k];
1113                                 B += ((p >>  0) & 0xff) * kernel[k];
1114                         }
1115                         d[j] = A | (((uint32_t)(R / w)) << 16) | (((uint32_t)(G / w)) << 8) | ((uint32_t)(B / w));
1116                 }
1117         }
1118
1119         s_info.is_bg_blurred = true;
1120         evas_object_image_data_update_add(s_info.bg, 0, 0, width, height);
1121 }
1122
1123 static Eina_Bool __homescreen_efl_show_all_apps_anim(void *data, double pos)
1124 {
1125         Evas_Object *box = elm_object_content_get(s_info.all_apps);
1126
1127         evas_object_show(s_info.all_apps);
1128         evas_object_move(s_info.all_apps, 0, (1.0 - pos) * ALL_APPS_ANIMATION_DELTA_Y);
1129         evas_object_move(s_info.home, 0, -pos * ALL_APPS_ANIMATION_HOME_DELTA_Y);
1130
1131         evas_object_color_set(box, 255, 255, 255, pos*(double)255);
1132
1133         if (pos >= 1.0) {
1134                 elm_object_part_content_set(s_info.layout, PART_CONTENT, s_info.all_apps);
1135                 all_apps_show();
1136                 elm_object_signal_emit(s_info.layout, SIGNAL_UNBLOCK_EVENTS, SIGNAL_SOURCE);
1137                 return ECORE_CALLBACK_DONE;
1138         }
1139
1140         return ECORE_CALLBACK_RENEW;
1141 }
1142
1143 static Eina_Bool __homescreen_efl_show_home_anim(void *data, double pos)
1144 {
1145         Evas_Object *box = elm_object_content_get(s_info.all_apps);
1146
1147         evas_object_move(s_info.all_apps, 0, pos * ALL_APPS_ANIMATION_DELTA_Y);
1148         evas_object_move(s_info.home, 0, -(1.0 - pos ) * ALL_APPS_ANIMATION_HOME_DELTA_Y);
1149
1150         evas_object_color_set(box, 255, 255, 255, (1.0 - pos * 2.0)*(double)255);
1151
1152         if (pos >= 1.0) {
1153                 if (s_info.layout && elm_object_part_content_get(s_info.layout, PART_CONTENT) == NULL && s_info.home) {
1154                         elm_object_part_content_set(s_info.layout, PART_CONTENT, s_info.home);
1155                         livebox_panel_set_content(s_info.layout);
1156                 }
1157
1158                 elm_object_signal_emit(s_info.layout, SIGNAL_UNBLOCK_EVENTS, SIGNAL_SOURCE);
1159                 return ECORE_CALLBACK_DONE;
1160         }
1161
1162         return ECORE_CALLBACK_RENEW;
1163 }