2 * Copyright 2012 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
19 #include "livebox/grid_reposition.h"
21 #include "homescreen-efl.h"
22 #include "livebox/livebox_utils.h"
23 #include "livebox/livebox_animator.h"
24 #include "livebox/livebox_panel.h"
27 #include "data_model.h"
31 Eina_Rectangle *pos_in_grid;
32 } Repositioned_Object_Data_t;
35 Evas_Object *repositioned_object;
36 Evas_Object *current_grid;
37 Evas_Object *origination_grid;
38 Repositioned_Object_Data_t repositioned_object_data;
39 Eina_List *repositioned_objects_in_grid;
43 bool intersection_found;
45 .repositioned_object = NULL,
47 .origination_grid = NULL,
48 .repositioned_object_data = {
52 .repositioned_objects_in_grid = NULL,
56 .intersection_found = true
59 static void __grid_reposition_drop_anim_cb(Anim_Data_t **ad);
60 static bool __grid_reposition_check_grid_intersection(Evas_Object *moved_item,
62 static bool __grid_reposition_check_item_intersection(Evas_Object *moved_item,
63 Evas_Object *grid_item);
64 static void __grid_reposition_save_item_start_data(Evas_Object *object);
65 static void __grid_reposition_make_space(void);
66 static void __grid_reposition_update_item_position(Eina_Rectangle *new_geometry);
68 Evas_Object *grid_reposition_get_current_glrid(void)
70 return s_info.current_grid;
73 Evas_Object *grid_reposition_get_repositioned_item(void)
75 return s_info.repositioned_object;
78 void grid_reposition_init(Evas_Object *grid, Evas_Object *repositioned_item)
91 if (!repositioned_item) {
92 LOGE("repositioned_item == NULL");
96 e = evas_object_evas_get(repositioned_item);
102 evas_pointer_canvas_xy_get(e, &mx, &my);
103 evas_object_geometry_get(repositioned_item, &ox, &oy, NULL, NULL);
105 s_info.offset_x = mx - ox;
106 s_info.offset_y = my - oy;
108 LOGD("MOUSE: (%d, %d); OFFSET: (%d, %d)", mx, my, s_info.offset_x,
111 s_info.current_grid = s_info.origination_grid = grid;
112 s_info.repositioned_object = repositioned_item;
114 __grid_reposition_save_item_start_data(repositioned_item);
117 void grid_reposition_start(void)
121 Evas_Object *page = NULL;
122 Evas_Object *grid = NULL;
124 int x = -1, y = -1, w = -1, h = -1;
126 page = livebox_utils_get_selected_livebox_layout();
128 LOGE("page == NULL");
132 grid = livebox_utils_get_livebox_container_grid(page);
134 LOGE("grid == NULL");
139 elm_grid_unpack(s_info.current_grid, s_info.repositioned_object);
140 evas_object_geometry_get(s_info.repositioned_object, &x, &y, &w, &h);
141 LOGD("Packing. Reposition start: %d; %d; %d; %d", x, y, w, h);
143 livebox_utils_get_cursor_pos(&mx, &my);
144 grid_reposition_move(mx, my);
146 livebox_utils_repack_grid_object(s_info.repositioned_object,
147 livebox_utils_get_shadow(), NULL, grid);
150 void grid_reposition_move(int mouse_x, int mouse_y)
152 if (!s_info.repositioned_object) {
153 LOGE("s_info.repositioned_object == NULL");
157 if (!s_info.current_grid) {
158 LOGE("s_info.current_grid == NULL");
162 evas_object_move(s_info.repositioned_object,
163 mouse_x - s_info.offset_x, mouse_y - s_info.offset_y);
164 s_info.intersection_found =
165 __grid_reposition_check_grid_intersection(s_info.repositioned_object,
166 s_info.current_grid);
169 if (livebox_panel_is_add_page_selected()) {
170 /*no intersection found but we can't drop on 'add page' page */
171 s_info.intersection_found = true;
172 livebox_utils_set_shadow_visibility(false);
173 } else if (!s_info.intersection_found) {
174 /*no intersection found so we can show the shadow */
175 livebox_utils_set_grid_object_pack(s_info.repositioned_object,
176 livebox_utils_get_shadow(), s_info.current_grid);
177 livebox_utils_set_shadow_visibility(true);
178 } else if (s_info.current_grid != s_info.origination_grid) {
179 /*intersection found and livebox was moved from diferent grid.
180 We can hide the shadow*/
181 __grid_reposition_make_space();
182 livebox_utils_set_shadow_visibility(false);
184 /* intersection found and livebox was moved from current grid.
185 We should display the shadow on the origination position */
187 __grid_reposition_make_space();
188 elm_grid_pack_set(livebox_utils_get_shadow(),
189 s_info.repositioned_object_data.pos_in_grid->x,
190 s_info.repositioned_object_data.pos_in_grid->y,
191 s_info.repositioned_object_data.pos_in_grid->w,
192 s_info.repositioned_object_data.pos_in_grid->h);
194 livebox_utils_set_shadow_visibility(true);
198 void grid_reposition_end(void)
200 Eina_Rectangle *start = NULL;
201 Eina_Rectangle *end = NULL;
206 Evas_Object *destination_grid = NULL;
208 if (!s_info.repositioned_object) {
209 LOGE("s_info.repositioned_object == NULL");
213 if (!s_info.current_grid) {
214 LOGE("s_info.current_grid == NULL");
218 if (!s_info.origination_grid) {
219 LOGE("s_info.origination_grid == NULL");
223 s_info.intersection_found = __grid_reposition_check_grid_intersection(
224 s_info.repositioned_object, s_info.current_grid);
226 if (!s_info.intersection_found) {
227 livebox_utils_convert_size_to_grid_coord(s_info.repositioned_object,
228 s_info.current_grid, &x, &y, &w, &h);
229 livebox_utils_normalize_grid_pos(x, y, w, h, &x, &y);
230 destination_grid = s_info.current_grid;
232 x = s_info.repositioned_object_data.pos_in_grid->x;
233 y = s_info.repositioned_object_data.pos_in_grid->y;
234 w = s_info.repositioned_object_data.pos_in_grid->w;
235 h = s_info.repositioned_object_data.pos_in_grid->h;
236 destination_grid = s_info.origination_grid;
239 start = livebox_utils_get_widget_rectangle(s_info.repositioned_object);
240 end = livebox_utils_convert_virtual_grid_geo_to_screen(destination_grid,
243 livebox_animator_play_geometry_set(s_info.repositioned_object,
244 LIVEBOX_REPOSITION_ANIM_TIME,
245 ECORE_POS_MAP_DECELERATE_FACTOR, 2, 0,
247 __grid_reposition_drop_anim_cb, &s_info.ad);
250 void grid_reposition_set_current_grid(Evas_Object *grid)
253 LOGE("grid == NULL");
254 s_info.current_grid = s_info.origination_grid;
258 s_info.current_grid = grid;
261 /* ================================== intersection check =====================*/
263 static Eina_Rectangle *_reposition_grid_item_pos_new_get(
264 Eina_Rectangle *grid_item, Eina_Rectangle *moved_item)
270 LOGE("grid_item == NULL");
275 LOGE("moved_item == NULL");
279 if (moved_item->y - grid_item->h >= 0) {
280 new_y = moved_item->y - grid_item->h;
282 new_y = moved_item->y + grid_item->h;
285 if (new_y < 0 || new_y > LIVEBOX_TOTAL_ROWS)
288 livebox_utils_normalize_grid_pos(grid_item->x, new_y, grid_item->w,
289 grid_item->h, &new_x, &new_y);
291 return eina_rectangle_new(new_x, new_y, grid_item->w, grid_item->h);
294 static bool _rectangle_containment_check(Eina_Rectangle *outer,
295 Eina_Rectangle *inner)
298 LOGE("outer == NULL");
303 LOGE("inner == NULL");
307 if (inner->x >= outer->x && inner->y >= outer->y &&
308 inner->x + inner->w <= outer->x + outer->w &&
309 inner->y + inner->h <= outer->y + outer->h) {
310 LOGD("RECTANGLE: [%d, %d - %d, %d] is IN [%d, %d - %d, %d]",
311 inner->x, inner->y, inner->w, inner->h,
312 outer->x, outer->y, outer->w, outer->h);
316 LOGD("RECTANGLE: [%d, %d - %d, %d] is NOT [%d, %d - %d, %d]",
317 inner->x, inner->y, inner->w, inner->h,
318 outer->x, outer->y, outer->w, outer->h);
324 static void __grid_reposition_make_space(void)
326 Eina_Rectangle *repo_obj_rec = NULL;
327 Eina_Rectangle *grid_obj_rec = NULL;
328 Eina_Rectangle *grid_obj_new_pos = NULL;
329 Eina_List *items_in_grid = NULL;
331 Evas_Object *obj = NULL;
332 int rx = -1, ry = -1, rw = -1, rh = -1;
333 bool contaiment = false;
334 bool intersection_in_grid = false;
335 bool can_space_make = false;
337 if (!s_info.current_grid) {
338 LOGE("s_info_current_grid == NULL");
342 if (!s_info.origination_grid) {
343 LOGE("s_info.origination_grid == NULL");
347 items_in_grid = livebox_utils_get_liveboxes_on_gird(
348 s_info.current_grid);
349 if (!items_in_grid) {
350 LOGE("items_in_grid == NULL");
354 livebox_utils_convert_size_to_grid_coord(s_info.repositioned_object,
355 s_info.current_grid, &rx, &ry, &rw, &rh);
356 livebox_utils_normalize_grid_pos(rx, ry, rw, rh, &rx, &ry);
358 repo_obj_rec = eina_rectangle_new(rx, ry, rw, rh);
360 LOGE("repo_obj_rec == NULL");
364 EINA_LIST_FOREACH(items_in_grid, l, obj) {
370 grid_obj_rec = livebox_utils_get_grid_widget_rectangle(obj);
372 LOGE("grid_obj_rec == NULL");
376 contaiment = _rectangle_containment_check(grid_obj_rec,
377 repo_obj_rec); /*moved obj in grid obj*/
380 contaiment = _rectangle_containment_check(repo_obj_rec,
381 grid_obj_rec); /*grid obj in moved obj*/
385 grid_obj_new_pos = _reposition_grid_item_pos_new_get(
386 grid_obj_rec, repo_obj_rec);
388 if (grid_obj_new_pos &&
389 !eina_rectangles_intersect(grid_obj_new_pos,
391 intersection_in_grid =
392 livebox_utils_check_rect_list_grid_interesction(
393 grid_obj_new_pos, obj, items_in_grid);
395 /*TODO: This call is not required when we assume
396 that no livebox can be put side by side*/
397 if (!intersection_in_grid) {
398 elm_grid_pack_set(obj,
402 grid_obj_new_pos->h);
403 can_space_make = true;
405 can_space_make = false;
406 eina_rectangle_free(grid_obj_new_pos);
407 eina_rectangle_free(grid_obj_rec);
411 eina_rectangle_free(grid_obj_new_pos);
415 eina_rectangle_free(grid_obj_rec);
419 __grid_reposition_update_item_position(repo_obj_rec);
421 eina_rectangle_free(repo_obj_rec);
422 eina_list_free(items_in_grid);
425 static void __grid_reposition_save_item_start_data(Evas_Object *object)
427 int x = -1, y = -1, w = -1, h = -1;
430 LOGE("object == NULL");
434 s_info.repositioned_object_data.obj = object;
435 elm_grid_pack_get(object, &x, &y, &w, &h);
437 s_info.repositioned_object_data.pos_in_grid = eina_rectangle_new(x, y,
441 static void __grid_reposition_update_item_position(Eina_Rectangle *new_geometry)
444 LOGE("new_geometry == NULL");
448 if (!s_info.repositioned_object_data.pos_in_grid) {
449 LOGE("s_info.repositioned_object_data.pos_in_grid == NULL");
453 s_info.repositioned_object_data.pos_in_grid->x = new_geometry->x;
454 s_info.repositioned_object_data.pos_in_grid->y = new_geometry->y;
455 s_info.repositioned_object_data.pos_in_grid->w = new_geometry->w;
456 s_info.repositioned_object_data.pos_in_grid->h = new_geometry->h;
459 static bool __grid_reposition_check_grid_intersection(Evas_Object *moved_item,
462 Eina_List *grid_items = NULL;
464 Evas_Object *grid_item = NULL;
467 LOGE("moved_item == NULL");
472 LOGE("grid == NULL");
476 grid_items = livebox_utils_get_liveboxes_on_gird(grid);
478 LOGE("grid_items == NULL");
482 EINA_LIST_FOREACH(grid_items, l, grid_item) {
484 LOGE("item == NULL");
488 if (__grid_reposition_check_item_intersection(moved_item,
489 grid_item) == true) {
490 eina_list_free(grid_items);
495 eina_list_free(grid_items);
499 static Eina_Rectangle *_normalized_rectangle_get(Evas_Object *obj)
505 Eina_Rectangle *rect = NULL;
507 if (!s_info.current_grid) {
508 LOGE("s_info.current_grid == NULL");
517 livebox_utils_convert_size_to_grid_coord(obj, s_info.current_grid,
519 livebox_utils_normalize_grid_pos(x, y, w, h, &x, &y);
520 rect = livebox_utils_convert_virtual_grid_geo_to_screen(s_info.current_grid,
524 LOGE("rect == NULL");
531 static bool __grid_reposition_check_item_intersection(Evas_Object *moved_item,
532 Evas_Object *grid_item)
534 Eina_Rectangle *moved_item_rec = NULL;
535 Eina_Rectangle *grid_item_rec = NULL;
539 LOGE("moved_item == NULL");
544 LOGE("grid_item == NULL");
548 moved_item_rec = _normalized_rectangle_get(moved_item);
549 if (!moved_item_rec) {
550 LOGE("moved_item_rec == NULL");
554 grid_item_rec = livebox_utils_get_widget_rectangle(grid_item);
555 if (!grid_item_rec) {
556 LOGE("grid_item_rec == NULL");
557 eina_rectangle_free(moved_item_rec);
561 ret = eina_rectangle_intersection(moved_item_rec, grid_item_rec);
563 eina_rectangle_free(moved_item_rec);
564 eina_rectangle_free(grid_item_rec);
569 static void _grid_reposition_update_data_model(Evas_Object *page)
571 Eina_List *items = NULL;
572 Tree_node_t *node = NULL;
573 Tree_node_t *page_node = NULL;
574 int x = 0, y = 0, w = 0, h = 0;
576 Evas_Object *livebox;
578 LOGI("DATA MODEL REPOSITION START");
580 elm_grid_pack_get(s_info.repositioned_object, &x, &y, &w, &h);
581 node = evas_object_data_get(s_info.repositioned_object, KEY_ICON_DATA);
583 LOGE("node == NULL");
587 page_node = evas_object_data_get(page, KEY_ICON_DATA);
589 LOGE("obj_node == NULL");
593 data_model_reposition_widget(page_node, node);
595 items = livebox_utils_get_liveboxes_on_page_list(page);
597 LOGD("items == NULL");
601 EINA_LIST_FOREACH(items, l, livebox) {
603 LOGE("livebox == NULL");
607 elm_grid_pack_get(livebox, &x, &y, &w, &h);
608 node = evas_object_data_get(livebox, KEY_ICON_DATA);
610 LOGE("node == NULL");
614 data_model_resize_widget(node, x, y, w, h);
617 home_screen_print_tree();
620 static void __grid_reposition_drop_anim_cb(Anim_Data_t **ad)
622 Evas_Object *page = NULL;
624 LOGI("DROP ANIM END");
626 if (!s_info.current_grid || !s_info.origination_grid ||
627 !s_info.repositioned_object) {
628 LOGE("s_info.current_grid == %p; s_info.origination_grid == %p;\
629 s_info.repositioned_object == %p", s_info.current_grid,
630 s_info.origination_grid, s_info.repositioned_object);
632 s_info.repositioned_object = NULL;
633 s_info.current_grid = NULL;
634 livebox_animator_del_grid(ad);
635 s_info.intersection_found = false;
637 s_info.repositioned_object_data.pos_in_grid);
640 livebox_utils_repack_grid_object(NULL, livebox_utils_get_shadow(),
641 s_info.current_grid, NULL);
643 if (!s_info.intersection_found) {
644 livebox_utils_repack_grid_object(s_info.repositioned_object,
645 s_info.repositioned_object,
647 s_info.current_grid);
649 page = livebox_scroller_get_page();
651 elm_grid_pack(s_info.origination_grid,
652 s_info.repositioned_object,
653 s_info.repositioned_object_data.pos_in_grid->x,
654 s_info.repositioned_object_data.pos_in_grid->y,
655 s_info.repositioned_object_data.pos_in_grid->w,
656 s_info.repositioned_object_data.pos_in_grid->h);
658 page = livebox_utils_get_prev_livebox_layout();
662 LOGE("page == NULL");
663 s_info.repositioned_object = NULL;
664 s_info.current_grid = NULL;
666 livebox_animator_del_grid(ad);
667 s_info.intersection_found = false;
669 s_info.repositioned_object_data.pos_in_grid);
673 _grid_reposition_update_data_model(page);
675 s_info.repositioned_object = NULL;
676 s_info.current_grid = NULL;
678 livebox_animator_del_grid(ad);
679 s_info.intersection_found = false;
680 eina_rectangle_free(s_info.repositioned_object_data.pos_in_grid);