The source code moved from the SPIN with license changed to Flora 1.1
[apps/native/home/homescreen-efl.git] / src / livebox / livebox_utils.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 <math.h>
18
19 #include "livebox/livebox_utils.h"
20 #include "homescreen-efl.h"
21
22 static struct
23 {
24         Evas_Object *selected_livebox;
25         Evas_Object *selected_livebox_layout;
26         Evas_Object *prev_livebox_layout;
27         Evas_Object *shadow;
28 }
29 s_info = {
30         .selected_livebox = NULL,
31         .selected_livebox_layout = NULL,
32         .prev_livebox_layout = NULL,
33         .shadow = NULL,
34 };
35
36 static Evas_Object *__livebox_utils_create_grid_bg(Evas_Object *parent);
37 static Eina_Rectangle *__livebox_utils_get_grid_rectangle(Evas_Object *obj);
38 static bool __livebox_utils_check_intersection(Evas_Object *obj_a,
39         Eina_Rectangle *rect);
40
41 Eina_Rectangle *livebox_utils_get_widget_rectangle(Evas_Object *obj)
42 {
43         int x = -1;
44         int y = -1;
45         int w = -1;
46         int h = -1;
47         Eina_Rectangle *rect = NULL;
48
49         if (!obj) {
50                 LOGE("obj == NULL");
51                 return NULL;
52         }
53         evas_object_geometry_get(obj, &x, &y, &w, &h);
54
55         rect = eina_rectangle_new(x, y, w, h);
56         if (!rect) {
57                 LOGE("rect == NULL");
58                 return NULL;
59         }
60
61         return rect;
62 }
63
64 Eina_Rectangle *livebox_utils_get_grid_widget_rectangle(Evas_Object *obj)
65 {
66         int x = -1;
67         int y = -1;
68         int w = -1;
69         int h = -1;
70         Eina_Rectangle *rect = NULL;
71
72         if (!obj) {
73                 LOGE("obj == NULL");
74                 return NULL;
75         }
76         elm_grid_pack_get(obj, &x, &y, &w, &h);
77
78         rect = eina_rectangle_new(x, y, w, h);
79         if (!rect) {
80                 LOGE("rect == NULL");
81                 return NULL;
82         }
83
84         return rect;
85 }
86
87 Eina_Rectangle *livebox_utils_convert_virtual_grid_geo_to_screen(Evas_Object *grid,
88         int x, int y, int w, int h)
89 {
90         int gx = -1;
91         int gy = -1;
92         int gw = -1;
93         int gh = -1;
94
95         int vw = -1;
96         int vh = -1;
97
98         Eina_Rectangle *rec = NULL;
99
100         if (!grid) {
101                 LOGE("grid == NULL");
102                 return NULL;
103         }
104
105         evas_object_geometry_get(grid, &gx, &gy, &gw, &gh);
106         elm_grid_size_get(grid, &vw, &vh);
107
108         rec = eina_rectangle_new(
109                 gx + (int)((float)x/vw * gw),
110                 gy + (int)((float)y/vh * gh),
111                 (int)((float)w/vw*gw),
112                 (int)((float)h/vh*gh)
113         );
114
115         if (!rec) {
116                 LOGE("rec == NULL");
117                 return NULL;
118         }
119
120         return rec;
121 }
122
123 bool livebox_utils_check_rect_list_grid_interesction(Eina_Rectangle *rect,
124         Evas_Object *obj, Eina_List *list)
125 {
126         Eina_List *l = NULL;
127         Evas_Object *list_obj = NULL;
128
129         if (!list) {
130                 LOGE("list == NULL");
131                 return true;
132         }
133
134         EINA_LIST_FOREACH(list, l, list_obj) {
135                 if (!list_obj) {
136                         LOGE("list_obj == NULL");
137                         continue;
138                 }
139
140                 if (list_obj != obj && __livebox_utils_check_intersection(
141                         list_obj, rect)) {
142                         LOGD("Intersection found");
143                         return true;
144                 }
145         }
146
147         return false;
148 }
149
150 Eina_List *livebox_utils_get_liveboxes_on_gird(Evas_Object *grid)
151 {
152         Eina_List *livebox_list = NULL;
153
154         if (!grid) {
155                 LOGE("grid == NULL");
156                 return NULL;
157         }
158
159         livebox_list = elm_grid_children_get(grid);
160         if (!livebox_list) {
161                 LOGE("livebox_list == NULL");
162                 return NULL;
163         }
164         livebox_list = eina_list_remove(livebox_list, s_info.shadow);
165
166         return livebox_list;
167 }
168
169
170 Eina_List *livebox_utils_get_liveboxes_on_page_list(Evas_Object *obj)
171 {
172         Evas_Object *grid = NULL;
173
174         if (!obj) {
175                 LOGE("o == NULL");
176                 return NULL;
177         }
178
179         grid = elm_layout_content_get(obj, SIGNAL_CONTENT_SOURCE);
180         if (!grid) {
181                 LOGE("grid == NULL");
182                 return NULL;
183         }
184
185         return livebox_utils_get_liveboxes_on_gird(grid);
186 }
187 /* ---------------------------------------------------------------------------*/
188
189 Evas_Object *livebox_utils_get_selected_livebox_layout(void)
190 {
191         return s_info.selected_livebox_layout;
192 }
193
194 Evas_Object *livebox_utils_get_prev_livebox_layout(void)
195 {
196         return s_info.prev_livebox_layout;
197 }
198
199 Evas_Object *livebox_utils_selected_livebox_get(void)
200 {
201         return s_info.selected_livebox;
202 }
203
204 void livebox_utils_set_selected_livebox(Evas_Object *livebox,
205         Evas_Object *layout)
206 {
207         LOGD("Selected_livebox_layout = %p; prev = %p",
208                 s_info.selected_livebox_layout, s_info.prev_livebox_layout);
209
210         s_info.prev_livebox_layout = s_info.selected_livebox_layout;
211         s_info.selected_livebox = livebox;
212         s_info.selected_livebox_layout = layout;
213 }
214
215 Evas_Object *livebox_utils_get_livebox_container_grid(Evas_Object *container)
216 {
217         Evas_Object *grid = elm_layout_content_get(container, "content");
218         if (!grid) {
219                 LOGE("grid == NULL");
220                 return NULL;
221         }
222
223         return grid;
224 }
225
226
227 void livebox_utils_set_grid_object_pack(Evas_Object *livebox,
228         Evas_Object *item_to_pack, Evas_Object *grid)
229 {
230         int x = -1, y = -1, w = -1, h = -1;
231         int out_x, out_y;
232
233         if (!grid) {
234                 LOGE("grid == NULL");
235                 return;
236         }
237
238         if (!livebox) {
239                 LOGE("livebox == NULL");
240                 return;
241         }
242
243         if (!item_to_pack) {
244                 LOGE("item_to_pack == NULL");
245                 return;
246         }
247
248         livebox_utils_convert_size_to_grid_coord(livebox, grid, &x, &y, &w, &h);
249         livebox_utils_normalize_grid_pos(x, y, w, h, &out_x, &out_y);
250         elm_grid_pack_set(item_to_pack, out_x, out_y, w, h);
251 }
252
253 void livebox_utils_repack_grid_object(Evas_Object *livebox,
254         Evas_Object *item_to_pack, Evas_Object *grid_from, Evas_Object *grid_to)
255 {
256         int x = -1, y = -1, w = -1, h = -1;
257         int out_x, out_y;
258
259         if (!item_to_pack) {
260                 LOGE("item_to_pack == NULL");
261                 return;
262         }
263
264         if (grid_from) {
265                 elm_grid_pack_get(item_to_pack, &x, &y, &w, &h);
266                 LOGD("Unpacking from: %p -> %d %d %d %d",
267                         grid_from, x, y, w, h);
268
269                 elm_grid_unpack(grid_from, item_to_pack);
270         }
271
272         if (livebox && grid_to) {
273                 livebox_utils_convert_size_to_grid_coord(livebox,
274                         grid_to, &x, &y, &w, &h);
275                 livebox_utils_normalize_grid_pos(x, y, w, h, &out_x, &out_y);
276                 elm_grid_pack(grid_to, item_to_pack, out_x, out_y, w, h);
277         }
278 }
279
280
281 void livebox_utils_convert_size_to_grid_coord(Evas_Object *livebox, Evas_Object *grid,
282         int *out_x, int *out_y, int *out_w, int *out_h)
283 {
284         int lx = 0, ly, lw = 0, lh = 0;
285         int gx = 0, gy, gw = 0, gh = 0;
286         float ratio_x = 0, ratio_y = 0;
287
288         if (!livebox) {
289                 LOGE("livebox == NULL");
290                 return;
291         }
292
293         if (!grid) {
294                 LOGE("grid == NULL");
295                 return;
296         }
297
298         if (!out_w || !out_h) {
299                 LOGE("output: out_w == %p; out_h == %p", out_w, out_h);
300                 return;
301         }
302
303         evas_object_geometry_get(livebox, &lx, &ly, &lw, &lh);
304         evas_object_geometry_get(grid,    &gx, &gy, &gw, &gh);
305
306         if (gw == 0 || gh == 0) {
307                 LOGE("Grid wrong size gw == %d; gh == %d", gw, gh);
308                 return;
309         }
310
311         lx -= gx;
312         ly -= gy;
313
314         ratio_x = (float)lx / gw;
315         ratio_y = (float)ly / gh;
316
317         *out_x = round(ratio_x * LIVEBOX_TOTAL_COLUMNS);
318         *out_y = round(ratio_y * LIVEBOX_TOTAL_ROWS);
319
320         ratio_x = (float)lw / gw;
321         ratio_y = (float)lh / gh;
322
323         *out_w = round(ratio_x * LIVEBOX_TOTAL_COLUMNS);
324         *out_h = round(ratio_y * LIVEBOX_TOTAL_ROWS);
325
326         *out_x /= LIVEBOX_GRID_ROWS_CELLS_MULTI;
327         *out_x *= LIVEBOX_GRID_ROWS_CELLS_MULTI;
328
329         *out_y /= LIVEBOX_GRID_ROWS_CELLS_MULTI;
330         *out_y *= LIVEBOX_GRID_ROWS_CELLS_MULTI;
331 }
332
333 void livebox_utils_normalize_grid_pos(int obj_x, int obj_y, int obj_w,
334         int obj_h, int *out_x, int *out_y)
335 {
336         int dx = obj_x + obj_w;
337         int dy = obj_y + obj_h;
338
339         if (dx > LIVEBOX_TOTAL_COLUMNS)
340                 obj_x = (LIVEBOX_TOTAL_COLUMNS - obj_w);
341
342         if (dy > LIVEBOX_TOTAL_ROWS)
343                 obj_y = (LIVEBOX_TOTAL_ROWS - obj_h);
344
345         if (obj_x < 0)
346                 obj_x = 0;
347
348         if (obj_y < 0)
349                 obj_y = 0;
350
351         *out_x = obj_x;
352         *out_y = obj_y;
353 }
354
355 /* -------------------------------------- SHADOW -----------------------------*/
356
357 Evas_Object *livebox_utils_get_shadow()
358 {
359         if (!s_info.shadow) {
360                 LOGE("s_info.shadow == NULL");
361                 return NULL;
362         }
363
364         return s_info.shadow;
365 }
366
367 void livebox_utils_shadow_unpack(void)
368 {
369         Evas_Object *page = NULL;
370         Evas_Object *grid = NULL;
371
372         page = livebox_utils_selected_livebox_get();
373         if (!page) {
374                 LOGE("page == NULL");
375                 return;
376         }
377
378         grid = livebox_utils_get_livebox_container_grid(page);
379         if (!grid) {
380                 LOGE("grid == NULL");
381                 return;
382         }
383
384         livebox_utils_repack_grid_object(NULL, livebox_utils_get_shadow(),
385                 grid, NULL);
386 }
387
388 void livebox_utils_create_shadow(Evas_Object *parent)
389 {
390         Evas *e = NULL;
391         Evas_Object *shadow = NULL;
392
393         if (!parent) {
394                 LOGE("parent == NULL");
395                 return;
396         }
397
398         e = evas_object_evas_get(parent);
399         if (!e) {
400                 LOGE("parent == NULL");
401                 return;
402         }
403
404
405         shadow = evas_object_rectangle_add(e);
406         if (!shadow) {
407                 LOGE("shadow == NULL");
408                 return;
409         }
410
411         s_info.shadow = shadow;
412         evas_object_color_set(shadow, LIVEBOX_GRID_BG_ALPHA,
413                 LIVEBOX_GRID_BG_ALPHA, LIVEBOX_GRID_BG_ALPHA,
414                 LIVEBOX_GRID_BG_ALPHA);
415         evas_object_pass_events_set(shadow, true);
416 }
417
418 void livebox_utils_set_shadow_visibility(bool visible)
419 {
420         if (!s_info.shadow) {
421                 LOGE("s_info.shadow == NULL");
422                 return;
423         }
424
425         if (visible) {
426                 evas_object_color_set(s_info.shadow, LIVEBOX_GRID_BG_ALPHA,
427                         LIVEBOX_GRID_BG_ALPHA, LIVEBOX_GRID_BG_ALPHA,
428                         LIVEBOX_GRID_BG_ALPHA);
429                 evas_object_show(s_info.shadow);
430         } else {
431                 evas_object_color_set(s_info.shadow, 0, 0, 0, 0);
432                 evas_object_hide(s_info.shadow);
433         }
434 }
435
436 void livebox_utils_create_grid_shadow_clipper(Evas_Object *livebox_container)
437 {
438         Evas_Object *grid_bg = NULL;
439
440         if (!livebox_container) {
441                 LOGD("livebox_container == NULL");
442                 return;
443         }
444
445         grid_bg = __livebox_utils_create_grid_bg(livebox_container);
446         if (!grid_bg) {
447                 LOGD("grid_bg == NULL");
448                 return;
449         }
450
451         elm_object_part_content_set(livebox_container, PART_GRID_BG, grid_bg);
452         evas_object_clip_set(grid_bg, s_info.shadow);
453
454         elm_layout_signal_emit(livebox_container,
455                 SIGNAL_GRID_SHADOW_HIDE, PART_GRID_BG);
456 }
457
458 static Evas_Object *__livebox_utils_create_grid_bg(Evas_Object *parent)
459 {
460         Evas *e = NULL;
461         Evas_Object *table = NULL;
462         Evas_Object *item;
463         int i = 0, j = 0;
464         int w = -1, h = -1;
465
466         if (!parent) {
467                 LOGE("parent == NULL");
468                 return NULL;
469         }
470
471         e = evas_object_evas_get(parent);
472         if (!e) {
473                 LOGE("parent == NULL");
474                 return NULL;
475         }
476
477         table = elm_table_add(parent);
478         if (!table) {
479                 LOGE("table == NULL");
480                 return NULL;
481         }
482
483         w = (LIVEBOX_GRID_BG_PADDING /
484                 (float)ROOT_WIN_W) * home_screen_get_root_width();
485         h = (LIVEBOX_GRID_BG_PADDING /
486                 (float)ROOT_WIN_H) * home_screen_get_root_height();
487
488         elm_table_padding_set(table, w, h);
489         elm_table_homogeneous_set(table, EINA_TRUE);
490
491         for (i = 0; i < LIVEBOX_GRID_COLUMNS; ++i) {
492                 for (j = 0; j < LIVEBOX_GRID_ROWS; ++j) {
493                         item = evas_object_rectangle_add(e);
494                         if (!item) {
495                                 LOGE("item == NULL");
496                                 evas_object_del(table);
497                                 return NULL;
498                         }
499
500                         evas_object_color_set(item, 255, 255, 255, 255);
501                         evas_object_pass_events_set(item, true);
502                         evas_object_show(item);
503                         evas_object_size_hint_weight_set(item,
504                                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
505                         evas_object_size_hint_fill_set(item,
506                                 EVAS_HINT_FILL, EVAS_HINT_FILL);
507                         elm_table_pack(table, item, i, j, 1, 1);
508                 }
509         }
510
511         return table;
512 }
513
514 void livebox_utils_get_cursor_pos(int *mx, int *my)
515 {
516         Evas *e = evas_object_evas_get(home_screen_get_win());
517         if (!e) {
518                 LOGE("e == NULL");
519                 return;
520         }
521         evas_pointer_canvas_xy_get(e, mx, my);
522 }
523
524 static Eina_Rectangle *__livebox_utils_get_grid_rectangle(Evas_Object *obj)
525 {
526         LOGD("");
527         Eina_Rectangle *rect;
528         int x = -1, y = -1, w = -1, h = -1;
529         if (!obj) {
530                 LOGE("obj == NULL");
531                 return NULL;
532         }
533
534         elm_grid_pack_get(obj, &x, &y, &w, &h);
535         rect = eina_rectangle_new(x, y, w, h);
536
537         if (!rect) {
538                 LOGE("rect == NULL");
539                 return NULL;
540         }
541
542         return rect;
543 }
544
545 static bool __livebox_utils_check_intersection(Evas_Object *obj_a,
546         Eina_Rectangle *rect)
547 {
548         Eina_Rectangle *rect_o = NULL;
549         bool out = true;
550
551         if (!obj_a) {
552                 LOGE("obj == NULL");
553                 return true;
554         }
555
556         rect_o = __livebox_utils_get_grid_rectangle(obj_a);
557
558         if (!rect_o || !rect) {
559                 LOGE("Rectangle not created: rect_o = %p; rect = %p",
560                         rect_o, rect);
561                 return true;
562         }
563
564         LOGD("Intersection: <%dx%d - %dx%d> - <%dx%d - %dx%d>",
565                 rect_o->x, rect_o->y, rect_o->w, rect_o->h,
566                 rect->x, rect->y, rect->w, rect->h);
567
568         out = eina_rectangles_intersect(rect_o, rect);
569
570         eina_rectangle_free(rect_o);
571
572         return out;
573 }