[elm_gengrid] fix video bookmark icon position problem
[framework/uifw/elementary.git] / src / lib / elm_gengrid.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4 #include "elm_widget_gengrid.h"
5
6 // internally allocated
7 #define CLASS_ALLOCATED     0x3a70f00f
8
9 /* --
10  * TODO:
11  * Handle non-homogeneous objects too.
12  */
13
14 #define PRELOAD             1
15 #define REORDER_EFFECT_TIME 0.5
16 #define FX_MOVE_TIME 0.5
17
18 EAPI const char ELM_GENGRID_SMART_NAME[] = "elm_gengrid";
19 EAPI const char ELM_GENGRID_PAN_SMART_NAME[] = "elm_gengrid_pan";
20
21 #define GG_IT(_it) (_it->item)
22
23 static const Evas_Smart_Interface *_smart_interfaces[] =
24 {
25    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
26 };
27
28 static const char SIG_ACTIVATED[] = "activated";
29 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
30 static const char SIG_LONGPRESSED[] = "longpressed";
31 static const char SIG_SELECTED[] = "selected";
32 static const char SIG_UNSELECTED[] = "unselected";
33 static const char SIG_REALIZED[] = "realized";
34 static const char SIG_UNREALIZED[] = "unrealized";
35 static const char SIG_CHANGED[] = "changed";
36 static const char SIG_DRAG_START_UP[] = "drag,start,up";
37 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
38 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
39 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
40 static const char SIG_DRAG_STOP[] = "drag,stop";
41 static const char SIG_DRAG[] = "drag";
42 static const char SIG_SCROLL[] = "scroll";
43 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
44 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
45 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
46 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
47 static const char SIG_EDGE_TOP[] = "edge,top";
48 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
49 static const char SIG_EDGE_LEFT[] = "edge,left";
50 static const char SIG_EDGE_RIGHT[] = "edge,right";
51 static const char SIG_MOVED[] = "moved";
52 static const char SIG_INDEX_UPDATE[] = "index,update";
53 static const char SIG_HIGHLIGHTED[] = "highlighted";
54 static const char SIG_UNHIGHLIGHTED[] = "unhighlighted";
55 static const char SIG_LANG_CHANGED[] = "language,changed";
56
57 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
58    {SIG_ACTIVATED, ""},
59    {SIG_CLICKED_DOUBLE, ""},
60    {SIG_LONGPRESSED, ""},
61    {SIG_SELECTED, ""},
62    {SIG_UNSELECTED, ""},
63    {SIG_REALIZED, ""},
64    {SIG_UNREALIZED, ""},
65    {SIG_CHANGED, ""},
66    {SIG_DRAG_START_UP, ""},
67    {SIG_DRAG_START_DOWN, ""},
68    {SIG_DRAG_START_LEFT, ""},
69    {SIG_DRAG_START_RIGHT, ""},
70    {SIG_DRAG_STOP, ""},
71    {SIG_DRAG, ""},
72    {SIG_SCROLL, ""},
73    {SIG_SCROLL_ANIM_START, ""},
74    {SIG_SCROLL_ANIM_STOP, ""},
75    {SIG_SCROLL_DRAG_START, ""},
76    {SIG_SCROLL_DRAG_STOP, ""},
77    {SIG_EDGE_TOP, ""},
78    {SIG_EDGE_BOTTOM, ""},
79    {SIG_EDGE_LEFT, ""},
80    {SIG_EDGE_RIGHT, ""},
81    {SIG_MOVED, ""},
82    {SIG_HIGHLIGHTED, ""},
83    {SIG_UNHIGHLIGHTED, ""},
84    {SIG_LANG_CHANGED, ""},
85    {NULL, NULL}
86 };
87
88 EVAS_SMART_SUBCLASS_IFACE_NEW
89   (ELM_GENGRID_SMART_NAME, _elm_gengrid, Elm_Gengrid_Smart_Class,
90   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks,
91   _smart_interfaces);
92
93 ELM_INTERNAL_SMART_SUBCLASS_NEW
94   (ELM_GENGRID_PAN_SMART_NAME, _elm_gengrid_pan, Elm_Gengrid_Pan_Smart_Class,
95   Elm_Pan_Smart_Class, elm_pan_smart_class_get, NULL);
96
97 #if GENGRID_FX_SUPPORT
98 static Eina_Bool      _elm_gengrid_fx_capture(Evas_Object *obj, int level);
99 static void           _elm_gengrid_fx_play(Evas_Object *obj);
100 #endif
101
102 static void
103 _elm_gengrid_pan_smart_pos_max_get(const Evas_Object *obj,
104                                    Evas_Coord *x,
105                                    Evas_Coord *y);
106 static void
107 _elm_gengrid_pan_smart_pos_min_get(const Evas_Object *obj,
108                                    Evas_Coord *x,
109                                    Evas_Coord *y);
110
111 static Eina_Bool
112 _elm_gengrid_smart_translate(Evas_Object *obj)
113 {
114    evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
115
116    return EINA_TRUE;
117 }
118
119 static void
120 _item_show_region(void *data)
121 {
122    Elm_Gengrid_Smart_Data *sd = data;
123    Evas_Coord cvw, cvh, it_xpos = 0, it_ypos = 0, col = 0, row = 0, minx = 0, miny = 0;
124    Evas_Coord vw = 0, vh = 0;
125    Elm_Gen_Item *it;
126
127 #if GENGRID_FX_SUPPORT
128    if (sd->fx_first_captured) return;
129 #endif
130    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
131
132    if ((cvw != 0) && (cvh != 0))
133        {
134           int x = 0, y = 0;
135           if (sd->show_region)
136             it = sd->show_it;
137           else if (sd->bring_in)
138             it = sd->bring_in_it;
139
140           _elm_gengrid_pan_smart_pos_min_get(sd->pan_obj, &minx, &miny);
141
142           if (sd->horizontal && (sd->item_height > 0))
143             {
144                row = cvh / sd->item_height;
145                if (row <= 0) row = 1;
146                x = it->position / row;
147                if (x > 0) y = it->position % x;
148                if (x > 1)
149                  it_xpos = ((x - GG_IT(it)->prev_group) * sd->item_width)
150                     + (GG_IT(it)->prev_group * sd->group_item_width)
151                     + minx;
152                else it_xpos = minx;
153
154                it_ypos = y * sd->item_height + miny;
155                it->x = x;
156                it->y = y;
157             }
158           else if (sd->item_width > 0)
159             {
160                col = cvw / sd->item_width;
161                if (col <= 0) col = 1;
162                y = it->position / col;
163                if (y > 0) x = it->position % y;
164                it_xpos = x * sd->item_width + minx;
165                if (y > 1)
166                  it_ypos = ((y - GG_IT(it)->prev_group) * sd->item_height)
167                     + (GG_IT(it)->prev_group * sd->group_item_height)
168                     + miny;
169                else it_ypos = miny;
170
171                it->x = x;
172                it->y = y;
173             }
174
175           sd->s_iface->content_viewport_size_get(WIDGET(it), &vw, &vh);
176
177           if (sd->show_region)
178             {
179                sd->s_iface->content_region_show(WIDGET(it),
180                                            it_xpos, it_ypos, vw, vh);
181                sd->show_region = EINA_FALSE;
182             }
183           if (sd->bring_in)
184             {
185                sd->s_iface->region_bring_in(WIDGET(it),
186                                            it_xpos, it_ypos, vw, vh);
187                sd->bring_in = EINA_FALSE;
188             }
189        }
190 }
191
192 static void
193 _calc_job(void *data)
194 {
195    Elm_Gengrid_Smart_Data *sd = data;
196    Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
197    Elm_Gen_Item *it, *group_item = NULL;
198    int count_group = 0;
199    long count = 0;
200
201    sd->items_lost = 0;
202    sd->calc_job = NULL;
203
204    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
205
206    if ((cvw != 0) || (cvh != 0))
207      {
208         if ((sd->horizontal) && (sd->item_height > 0))
209           nmax = cvh / sd->item_height;
210         else if (sd->item_width > 0)
211           nmax = cvw / sd->item_width;
212
213         if (nmax < 1)
214           nmax = 1;
215
216         EINA_INLIST_FOREACH(sd->items, it)
217           {
218              if (GG_IT(it)->prev_group != count_group)
219                GG_IT(it)->prev_group = count_group;
220              if (it->group)
221                {
222                   count = count % nmax;
223                   if (count)
224                     sd->items_lost += nmax - count;
225                   count_group++;
226                   if (count) count = 0;
227                   group_item = it;
228                }
229              else
230                {
231                   if (it->parent != group_item)
232                     it->parent = group_item;
233                   count++;
234                }
235           }
236         count = sd->item_count + sd->items_lost - count_group;
237         if (sd->horizontal)
238           {
239              minw = (ceil(count / (float)nmax) * sd->item_width) +
240                (count_group * sd->group_item_width);
241              minh = nmax * sd->item_height;
242           }
243         else
244           {
245              minw = nmax * sd->item_width;
246              minh = (ceil(count / (float)nmax) * sd->item_height) +
247                (count_group * sd->group_item_height);
248           }
249
250         if ((minw != sd->minw) || (minh != sd->minh))
251           {
252              sd->minh = minh;
253              sd->minw = minw;
254              evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
255           }
256
257         sd->nmax = nmax;
258         evas_object_smart_changed(sd->pan_obj);
259      }
260 }
261
262 static void
263 _elm_gengrid_pan_smart_add(Evas_Object *obj)
264 {
265    /* here just to allocate our extended data */
266    EVAS_SMART_DATA_ALLOC(obj, Elm_Gengrid_Pan_Smart_Data);
267
268    ELM_PAN_CLASS(_elm_gengrid_pan_parent_sc)->base.add(obj);
269 }
270
271 static void
272 _elm_gengrid_pan_smart_move(Evas_Object *obj,
273                             Evas_Coord x __UNUSED__,
274                             Evas_Coord y __UNUSED__)
275 {
276    ELM_GENGRID_PAN_DATA_GET(obj, psd);
277
278    if (psd->wsd->calc_job) ecore_job_del(psd->wsd->calc_job);
279    psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wsd);
280 }
281
282 static void
283 _elm_gengrid_pan_smart_resize(Evas_Object *obj,
284                               Evas_Coord w,
285                               Evas_Coord h)
286 {
287    Evas_Coord ow, oh;
288
289    ELM_GENGRID_PAN_DATA_GET(obj, psd);
290
291    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
292    if ((ow == w) && (oh == h)) return;
293    if (psd->wsd->calc_job) ecore_job_del(psd->wsd->calc_job);
294    psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wsd);
295 }
296
297 static void
298 _item_unselect(Elm_Gen_Item *it)
299 {
300    Elm_Gen_Item_Type *item = GG_IT(it);
301
302    if ((it->generation < item->wsd->generation) || (!it->highlighted))
303      return;
304
305    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
306    evas_object_smart_callback_call(WIDGET(it), SIG_UNHIGHLIGHTED, it);
307    it->highlighted = EINA_FALSE;
308    if (it->selected)
309      {
310         it->selected = EINA_FALSE;
311         item->wsd->selected = eina_list_remove(item->wsd->selected, it);
312         evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
313      }
314 }
315
316 static void
317 _item_mouse_move_cb(void *data,
318                     Evas *evas __UNUSED__,
319                     Evas_Object *obj,
320                     void *event_info)
321 {
322    Elm_Gen_Item *it = data;
323    Evas_Event_Mouse_Move *ev = event_info;
324    Evas_Coord ox, oy, ow, oh, it_scrl_x, it_scrl_y;
325    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
326
327    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
328      {
329         if (!GG_IT(it)->wsd->on_hold)
330           {
331              GG_IT(it)->wsd->on_hold = EINA_TRUE;
332              if (!GG_IT(it)->wsd->was_selected)
333                _item_unselect(it);
334           }
335      }
336
337    if ((it->dragging) && (it->down))
338      {
339         if (it->long_timer)
340           {
341              ecore_timer_del(it->long_timer);
342              it->long_timer = NULL;
343           }
344         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
345         return;
346      }
347
348    if ((!it->down) || (GG_IT(it)->wsd->longpressed))
349      {
350         if (it->long_timer)
351           {
352              ecore_timer_del(it->long_timer);
353              it->long_timer = NULL;
354           }
355         if ((GG_IT(it)->wsd->reorder_mode) &&
356             (GG_IT(it)->wsd->reorder_it))
357           {
358              evas_object_geometry_get
359                (GG_IT(it)->wsd->pan_obj, &ox, &oy, &ow, &oh);
360
361              it_scrl_x = ev->cur.canvas.x -
362                GG_IT(it)->wsd->reorder_it->dx;
363              it_scrl_y = ev->cur.canvas.y -
364                GG_IT(it)->wsd->reorder_it->dy;
365
366              if (it_scrl_x < ox) GG_IT(it)->wsd->reorder_item_x = ox;
367              else if (it_scrl_x + GG_IT(it)->wsd->item_width > ox + ow)
368                GG_IT(it)->wsd->reorder_item_x =
369                  ox + ow - GG_IT(it)->wsd->item_width;
370              else GG_IT(it)->wsd->reorder_item_x = it_scrl_x;
371
372              if (it_scrl_y < oy) GG_IT(it)->wsd->reorder_item_y = oy;
373              else if (it_scrl_y + GG_IT(it)->wsd->item_height > oy + oh)
374                GG_IT(it)->wsd->reorder_item_y =
375                  oy + oh - GG_IT(it)->wsd->item_height;
376              else GG_IT(it)->wsd->reorder_item_y = it_scrl_y;
377
378              if (GG_IT(it)->wsd->calc_job)
379                ecore_job_del(GG_IT(it)->wsd->calc_job);
380              GG_IT(it)->wsd->calc_job =
381                ecore_job_add(_calc_job, GG_IT(it)->wsd);
382           }
383         return;
384      }
385
386    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
387      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
388
389    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
390    x = ev->cur.canvas.x - x;
391    y = ev->cur.canvas.y - y;
392    dx = x - it->dx;
393    adx = dx;
394
395    if (adx < 0) adx = -dx;
396    dy = y - it->dy;
397    ady = dy;
398
399    if (ady < 0) ady = -dy;
400    minw /= 2;
401    minh /= 2;
402
403    if ((adx > minw) || (ady > minh))
404      {
405         const char *left_drag, *right_drag;
406
407         if (!elm_widget_mirrored_get(WIDGET(it)))
408           {
409              left_drag = SIG_DRAG_START_LEFT;
410              right_drag = SIG_DRAG_START_RIGHT;
411           }
412         else
413           {
414              left_drag = SIG_DRAG_START_RIGHT;
415              right_drag = SIG_DRAG_START_LEFT;
416           }
417
418         it->dragging = 1;
419         if (it->long_timer)
420           {
421              ecore_timer_del(it->long_timer);
422              it->long_timer = NULL;
423           }
424         if (!GG_IT(it)->wsd->was_selected)
425           _item_unselect(it);
426
427         if (dy < 0)
428           {
429              if (ady > adx)
430                evas_object_smart_callback_call
431                  (WIDGET(it), SIG_DRAG_START_UP, it);
432              else
433                {
434                   if (dx < 0)
435                     evas_object_smart_callback_call(WIDGET(it), left_drag, it);
436                }
437           }
438         else
439           {
440              if (ady > adx)
441                evas_object_smart_callback_call
442                  (WIDGET(it), SIG_DRAG_START_DOWN, it);
443              else
444                {
445                   if (dx < 0)
446                     evas_object_smart_callback_call(WIDGET(it), left_drag, it);
447                   else
448                     evas_object_smart_callback_call
449                       (WIDGET(it), right_drag, it);
450                }
451           }
452      }
453 }
454
455 static Eina_Bool
456 _long_press_cb(void *data)
457 {
458    Elm_Gen_Item *it = data;
459    Elm_Gengrid_Smart_Data *sd = GG_IT(it)->wsd;
460
461    it->long_timer = NULL;
462    if (elm_widget_item_disabled_get(it) || (it->dragging))
463      return ECORE_CALLBACK_CANCEL;
464    sd->longpressed = EINA_TRUE;
465    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
466
467    if (sd->reorder_mode)
468      {
469         sd->reorder_it = it;
470         evas_object_raise(VIEW(it));
471         sd->s_iface->hold_set(WIDGET(it), EINA_TRUE);
472         sd->s_iface->bounce_allow_get
473           (WIDGET(it), &(GG_IT(it)->wsd->old_h_bounce),
474           &(GG_IT(it)->wsd->old_v_bounce));
475
476         sd->s_iface->bounce_allow_set(WIDGET(it), EINA_FALSE, EINA_FALSE);
477         edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
478      }
479
480    return ECORE_CALLBACK_CANCEL;
481 }
482
483 static void
484 _item_highlight(Elm_Gen_Item *it)
485 {
486    if ((GG_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)
487        || (!GG_IT(it)->wsd->highlight) || (it->highlighted) ||
488        (it->generation < GG_IT(it)->wsd->generation))
489      return;
490
491    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
492    evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
493    it->highlighted = EINA_TRUE;
494 }
495
496 static void
497 _item_mouse_down_cb(void *data,
498                     Evas *evas __UNUSED__,
499                     Evas_Object *obj,
500                     void *event_info)
501 {
502    Evas_Event_Mouse_Down *ev = event_info;
503    Elm_Gen_Item *it = data;
504    Evas_Coord x, y;
505
506    if (ev->button != 1) return;
507
508    it->down = 1;
509    it->dragging = 0;
510    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
511    it->dx = ev->canvas.x - x;
512    it->dy = ev->canvas.y - y;
513    GG_IT(it)->wsd->longpressed = EINA_FALSE;
514
515    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
516      GG_IT(it)->wsd->on_hold = EINA_TRUE;
517    else GG_IT(it)->wsd->on_hold = EINA_FALSE;
518
519    if (GG_IT(it)->wsd->on_hold) return;
520
521    GG_IT(it)->wsd->was_selected = it->selected;
522    _item_highlight(it);
523    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
524      {
525         evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
526         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
527      }
528    if (it->long_timer) ecore_timer_del(it->long_timer);
529    if (it->realized)
530      it->long_timer = ecore_timer_add
531          (_elm_config->longpress_timeout, _long_press_cb, it);
532    else
533      it->long_timer = NULL;
534 }
535
536 static void
537 _elm_gengrid_item_unrealize(Elm_Gen_Item *it,
538                             Eina_Bool calc)
539 {
540    Evas_Object *content;
541
542    if (!it->realized) return;
543    if (GG_IT(it)->wsd->reorder_it == it) return;
544 #if GENGRID_FX_SUPPORT
545    if ((GG_IT(it)->has_proxy_it) && (!GG_IT(it)->wsd->gengrid_clearing))
546      {
547         if (!eina_list_data_find(GG_IT(it)->wsd->pending_unrealized_items, it))
548           GG_IT(it)->wsd->pending_unrealized_items =
549              eina_list_append(GG_IT(it)->wsd->pending_unrealized_items, it);
550         return;
551      }
552 #endif
553    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
554    if (!calc)
555      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
556    if (it->long_timer)
557      {
558         ecore_timer_del(it->long_timer);
559         it->long_timer = NULL;
560      }
561
562    elm_widget_stringlist_free(it->texts);
563    it->texts = NULL;
564    elm_widget_stringlist_free(it->contents);
565    it->contents = NULL;
566    elm_widget_stringlist_free(it->states);
567    it->states = NULL;
568    EINA_LIST_FREE (it->content_objs, content)
569      evas_object_del(content);
570
571    it->unrealize_cb(it);
572
573    it->realized = EINA_FALSE;
574    it->want_unrealize = EINA_FALSE;
575    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
576    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
577 }
578
579 static void
580 _item_mouse_up_cb(void *data,
581                   Evas *evas __UNUSED__,
582                   Evas_Object *obj __UNUSED__,
583                   void *event_info)
584 {
585    Evas_Event_Mouse_Up *ev = event_info;
586    Eina_Bool dragged = EINA_FALSE;
587    Elm_Gengrid_Smart_Data *sd;
588    Elm_Gen_Item *it = data;
589
590    if (ev->button != 1) return;
591
592    sd = GG_IT(it)->wsd;
593
594    it->down = EINA_FALSE;
595    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
596      sd->on_hold = EINA_TRUE;
597    else sd->on_hold = EINA_FALSE;
598
599    if (it->long_timer)
600      {
601         ecore_timer_del(it->long_timer);
602         it->long_timer = NULL;
603      }
604    if (it->dragging)
605      {
606         it->dragging = EINA_FALSE;
607         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
608         dragged = EINA_TRUE;
609      }
610    if (sd->on_hold)
611      {
612         sd->longpressed = EINA_FALSE;
613         sd->on_hold = EINA_FALSE;
614         return;
615      }
616    if ((sd->reorder_mode) &&
617        (sd->reorder_it))
618      {
619         evas_object_smart_callback_call
620           (WIDGET(it), SIG_MOVED, sd->reorder_it);
621         sd->reorder_it = NULL;
622         sd->move_effect_enabled = EINA_FALSE;
623         if (sd->calc_job)
624           ecore_job_del(sd->calc_job);
625         sd->calc_job =
626           ecore_job_add(_calc_job, sd);
627
628         sd->s_iface->hold_set(WIDGET(it), EINA_FALSE);
629         sd->s_iface->bounce_allow_set
630           (WIDGET(it), GG_IT(it)->wsd->old_h_bounce,
631           GG_IT(it)->wsd->old_v_bounce);
632
633         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
634      }
635    if (sd->longpressed)
636      {
637         sd->longpressed = EINA_FALSE;
638         if (!sd->was_selected) _item_unselect(it);
639         sd->was_selected = EINA_FALSE;
640         return;
641      }
642    if (dragged)
643      {
644         if (it->want_unrealize)
645           _elm_gengrid_item_unrealize(it, EINA_FALSE);
646      }
647    if (elm_widget_item_disabled_get(it) || (dragged)) return;
648    if (sd->multi)
649      {
650         if (!it->selected)
651           {
652              _item_highlight(it);
653              it->sel_cb(it);
654           }
655         else _item_unselect(it);
656      }
657    else
658      {
659         if (!it->selected)
660           {
661              while (sd->selected)
662                _item_unselect(sd->selected->data);
663           }
664         else
665           {
666              const Eina_List *l, *l_next;
667              Elm_Gen_Item *item2;
668
669              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, item2)
670                if (item2 != it) _item_unselect(item2);
671           }
672         _item_highlight(it);
673         it->sel_cb(it);
674      }
675 }
676
677 static void
678 _elm_gengrid_item_index_update(Elm_Gen_Item *it)
679 {
680    if (it->position_update)
681      {
682         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
683         it->position_update = EINA_FALSE;
684      }
685 }
686
687 static void
688 _item_unrealize_cb(Elm_Gen_Item *it)
689 {
690    evas_object_del(VIEW(it));
691    VIEW(it) = NULL;
692    evas_object_del(it->spacer);
693    it->spacer = NULL;
694 }
695
696 static char *
697 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
698 {
699    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
700    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
701
702    if (it->itc->func.text_get)
703      {
704         const Eina_List *l;
705         const char *key;
706
707         if (!(it->texts)) it->texts =
708           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
709
710         EINA_LIST_FOREACH(it->texts, l, key)
711           {
712              char *s = it->itc->func.text_get
713                 ((void *)it->base.data, WIDGET(it), key);
714              return s;
715           }
716      }
717
718    return NULL;
719 }
720
721 static char *
722 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
723 {
724    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
725    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
726
727    if (it->base.disabled)
728      return strdup(E_("State: Disabled"));
729
730    return NULL;
731 }
732
733 static void
734 _access_on_highlight_cb(void *data)
735 {
736    Evas_Coord x, y, w, h;
737    Evas_Coord sx, sy, sw, sh;
738    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
739    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
740
741    ELM_GENGRID_DATA_GET(it->base.widget, sd);
742
743    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
744
745    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->obj, &sx, &sy, &sw, &sh);
746    if ((x < sx) || (y < sy) || ((x + w) > (sx + sw)) || ((y + h) > (sy + sh)))
747      elm_gengrid_item_bring_in((Elm_Object_Item *)it,
748                                ELM_GENGRID_ITEM_SCROLLTO_IN);
749 }
750
751 static void
752 _access_widget_item_register(Elm_Gen_Item *it)
753 {
754    Elm_Access_Info *ai;
755
756    _elm_access_widget_item_register((Elm_Widget_Item *)it);
757
758    ai = _elm_access_object_get(it->base.access_obj);
759
760    _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Gengrid Item"));
761    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
762    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
763    _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
764 }
765
766 static void
767 _item_realize(Elm_Gen_Item *it)
768 {
769    char buf[1024];
770    char style[1024];
771
772    if ((it->realized) ||
773        (it->generation < GG_IT(it)->wsd->generation))
774      return;
775
776    VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
777    edje_object_scale_set
778      (VIEW(it), elm_widget_scale_get(WIDGET(it)) * elm_config_scale_get());
779    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(WIDGET(it)));
780    evas_object_smart_member_add(VIEW(it), GG_IT(it)->wsd->pan_obj);
781    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
782    snprintf(style, sizeof(style), "item/%s",
783             it->itc->item_style ? it->itc->item_style : "default");
784    elm_widget_theme_object_set(WIDGET(it), VIEW(it), "gengrid", style,
785                                elm_widget_style_get(WIDGET(it)));
786    it->spacer =
787      evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
788    evas_object_color_set(it->spacer, 0, 0, 0, 0);
789    elm_widget_sub_object_add(WIDGET(it), it->spacer);
790    evas_object_size_hint_min_set(it->spacer, 2 * elm_config_scale_get(), 1);
791    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
792
793    /* access */
794    if (_elm_config->access_mode) _access_widget_item_register(it);
795
796    if (it->itc->func.text_get)
797      {
798         const Eina_List *l;
799         const char *key;
800
801         it->texts =
802           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
803         EINA_LIST_FOREACH(it->texts, l, key)
804           {
805              char *s = it->itc->func.text_get
806                  ((void *)it->base.data, WIDGET(it), key);
807              if (s)
808                {
809                   edje_object_part_text_escaped_set(VIEW(it), key, s);
810                   free(s);
811                }
812           }
813      }
814
815    if (it->itc->func.content_get)
816      {
817         const Eina_List *l;
818         const char *key;
819         Evas_Object *ic = NULL;
820
821         it->contents = elm_widget_stringlist_get
822             (edje_object_data_get(VIEW(it), "contents"));
823         EINA_LIST_FOREACH(it->contents, l, key)
824           {
825              if (it->itc->func.content_get)
826                ic = it->itc->func.content_get
827                    ((void *)it->base.data, WIDGET(it), key);
828              if (ic)
829                {
830                   it->content_objs = eina_list_append(it->content_objs, ic);
831                   edje_object_part_swallow(VIEW(it), key, ic);
832                   evas_object_show(ic);
833                   elm_widget_sub_object_add(WIDGET(it), ic);
834                }
835           }
836      }
837
838    if (it->itc->func.state_get)
839      {
840         const Eina_List *l;
841         const char *key;
842
843         it->states =
844           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "states"));
845         EINA_LIST_FOREACH(it->states, l, key)
846           {
847              Eina_Bool on = it->itc->func.state_get
848                  ((void *)it->base.data, WIDGET(it), l->data);
849              if (on)
850                {
851                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
852                   edje_object_signal_emit(VIEW(it), buf, "elm");
853                }
854           }
855      }
856
857    if (it->group)
858      {
859         if ((!GG_IT(it)->wsd->group_item_width)
860             && (!GG_IT(it)->wsd->group_item_height))
861           {
862              edje_object_size_min_restricted_calc
863                (VIEW(it), &GG_IT(it)->wsd->group_item_width,
864                &GG_IT(it)->wsd->group_item_height,
865                GG_IT(it)->wsd->group_item_width,
866                GG_IT(it)->wsd->group_item_height);
867           }
868      }
869    else
870      {
871         if ((!GG_IT(it)->wsd->item_width)
872             && (!GG_IT(it)->wsd->item_height))
873           {
874              edje_object_size_min_restricted_calc
875                (VIEW(it), &GG_IT(it)->wsd->item_width,
876                &GG_IT(it)->wsd->item_height,
877                GG_IT(it)->wsd->item_width,
878                GG_IT(it)->wsd->item_height);
879              elm_coords_finger_size_adjust
880                (1, &GG_IT(it)->wsd->item_width, 1,
881                &GG_IT(it)->wsd->item_height);
882           }
883
884         evas_object_event_callback_add
885           (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
886         evas_object_event_callback_add
887           (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
888         evas_object_event_callback_add
889           (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
890
891         _elm_gengrid_item_index_update(it);
892
893         if (it->selected)
894           edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
895         if (elm_widget_item_disabled_get(it))
896           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
897      }
898    evas_object_show(VIEW(it));
899
900    if (it->tooltip.content_cb)
901      {
902         elm_widget_item_tooltip_content_cb_set
903           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
904         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
905         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
906      }
907
908    if (it->mouse_cursor)
909      elm_widget_item_cursor_set(it, it->mouse_cursor);
910
911    it->realized = EINA_TRUE;
912    it->want_unrealize = EINA_FALSE;
913 }
914
915 static Eina_Bool
916 _reorder_item_move_animator_cb(void *data)
917 {
918    Elm_Gen_Item *it = data;
919    Evas_Coord dx, dy;
920    double tt, t;
921
922    tt = REORDER_EFFECT_TIME;
923    t = ((0.0 > (t = ecore_loop_time_get() -
924                   GG_IT(it)->moving_effect_start_time)) ? 0.0 : t);
925    dx = ((GG_IT(it)->tx - GG_IT(it)->ox) / 10)
926      * elm_config_scale_get();
927    dy = ((GG_IT(it)->ty - GG_IT(it)->oy) / 10)
928      * elm_config_scale_get();
929
930    if (t <= tt)
931      {
932         GG_IT(it)->rx += (1 * sin((t / tt) * (M_PI / 2)) * dx);
933         GG_IT(it)->ry += (1 * sin((t / tt) * (M_PI / 2)) * dy);
934      }
935    else
936      {
937         GG_IT(it)->rx += dx;
938         GG_IT(it)->ry += dy;
939      }
940
941    if ((((dx > 0) && (GG_IT(it)->rx >= GG_IT(it)->tx)) ||
942         ((dx <= 0) && (GG_IT(it)->rx <= GG_IT(it)->tx)))
943        && (((dy > 0) && (GG_IT(it)->ry >= GG_IT(it)->ty)) ||
944            ((dy <= 0) && (GG_IT(it)->ry <= GG_IT(it)->ty))))
945      {
946         evas_object_move(VIEW(it), GG_IT(it)->tx, GG_IT(it)->ty);
947         if (it->group)
948           {
949              Evas_Coord vw, vh;
950
951              evas_object_geometry_get
952                (GG_IT(it)->wsd->pan_obj, NULL, NULL, &vw, &vh);
953              if (GG_IT(it)->wsd->horizontal)
954                evas_object_resize
955                  (VIEW(it), GG_IT(it)->wsd->group_item_width, vh);
956              else
957                evas_object_resize
958                  (VIEW(it), vw, GG_IT(it)->wsd->group_item_height);
959           }
960         else
961           evas_object_resize(VIEW(it), GG_IT(it)->wsd->item_width,
962                              GG_IT(it)->wsd->item_height);
963         GG_IT(it)->moving = EINA_FALSE;
964         GG_IT(it)->item_reorder_move_animator = NULL;
965
966         return ECORE_CALLBACK_CANCEL;
967      }
968
969    evas_object_move(VIEW(it), GG_IT(it)->rx, GG_IT(it)->ry);
970    if (it->group)
971      {
972         Evas_Coord vw, vh;
973
974         evas_object_geometry_get
975           (GG_IT(it)->wsd->pan_obj, NULL, NULL, &vw, &vh);
976         if (GG_IT(it)->wsd->horizontal)
977           evas_object_resize
978             (VIEW(it), GG_IT(it)->wsd->group_item_width, vh);
979         else
980           evas_object_resize
981             (VIEW(it), vw, GG_IT(it)->wsd->group_item_height);
982      }
983    else
984      evas_object_resize
985        (VIEW(it), GG_IT(it)->wsd->item_width,
986        GG_IT(it)->wsd->item_height);
987
988    return ECORE_CALLBACK_RENEW;
989 }
990
991 static void
992 _item_place(Elm_Gen_Item *it,
993             Evas_Coord cx,
994             Evas_Coord cy)
995 {
996    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh, iw, ih, ww;
997    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
998    Eina_Bool reorder_item_move_forward = EINA_FALSE;
999    Elm_Gengrid_Smart_Data *wsd;
1000    Eina_Bool was_realized;
1001    Elm_Gen_Item_Type *item;
1002    long items_count;
1003
1004    item = GG_IT(it);
1005    wsd = GG_IT(it)->wsd;
1006
1007    it->x = cx;
1008    it->y = cy;
1009    if (wsd->horizontal) it->position = cx;
1010    else it->position = cy;
1011
1012    evas_object_geometry_get(wsd->pan_obj, &ox, &oy, &vw, &vh);
1013
1014    /* Preload rows/columns at each side of the Gengrid */
1015    cvx = ox - PRELOAD * wsd->item_width;
1016    cvy = oy - PRELOAD * wsd->item_height;
1017    cvw = vw + 2 * PRELOAD * wsd->item_width;
1018    cvh = vh + 2 * PRELOAD * wsd->item_height;
1019
1020    alignh = 0;
1021    alignw = 0;
1022
1023    items_count = wsd->item_count -
1024      eina_list_count(wsd->group_items) + wsd->items_lost;
1025    if (wsd->horizontal)
1026      {
1027         int columns, items_visible = 0, items_row;
1028
1029         if (wsd->item_height > 0)
1030           items_visible = vh / wsd->item_height;
1031         if (items_visible < 1)
1032           items_visible = 1;
1033
1034         columns = items_count / items_visible;
1035         if (items_count % items_visible)
1036           columns++;
1037
1038         tcw = (wsd->item_width * columns) + (wsd->group_item_width *
1039                                              eina_list_count(wsd->group_items));
1040         alignw = (vw - tcw) * wsd->align_x;
1041
1042         items_row = items_visible;
1043         if ((unsigned int)items_row > wsd->item_count)
1044           items_row = wsd->item_count;
1045         if (wsd->filled && (unsigned int)wsd->nmax
1046             > (unsigned int)wsd->item_count)
1047           tch = wsd->nmax * wsd->item_height;
1048         else
1049           tch = items_row * wsd->item_height;
1050         alignh = (vh - tch) * wsd->align_y;
1051      }
1052    else
1053      {
1054         unsigned int rows, items_visible = 0, items_col;
1055
1056         if (wsd->item_width > 0)
1057           items_visible = vw / wsd->item_width;
1058         if (items_visible < 1)
1059           items_visible = 1;
1060
1061         rows = items_count / items_visible;
1062         if (items_count % items_visible)
1063           rows++;
1064
1065         tch = (wsd->item_height * rows) + (wsd->group_item_height *
1066                                            eina_list_count(wsd->group_items));
1067         alignh = (vh - tch) * wsd->align_y;
1068
1069         items_col = items_visible;
1070         if (items_col > wsd->item_count)
1071           items_col = wsd->item_count;
1072         if (wsd->filled && (unsigned int)wsd->nmax
1073             > (unsigned int)wsd->item_count)
1074           tcw = wsd->nmax * wsd->item_width;
1075         else
1076           tcw = items_col * wsd->item_width;
1077         alignw = (vw - tcw) * wsd->align_x;
1078      }
1079
1080    if (it->group)
1081      {
1082         if (wsd->horizontal)
1083           {
1084              x = (((cx - item->prev_group) * wsd->item_width)
1085                   + (item->prev_group * wsd->group_item_width)) -
1086                wsd->pan_x + ox + alignw;
1087              y = oy;
1088              iw = wsd->group_item_width;
1089              ih = vh;
1090           }
1091         else
1092           {
1093              x = ox;
1094              y = (((cy - item->prev_group) * wsd->item_height)
1095                   + (item->prev_group * wsd->group_item_height))
1096                - wsd->pan_y + oy + alignh;
1097              iw = vw;
1098              ih = wsd->group_item_height;
1099           }
1100         item->gx = x;
1101         item->gy = y;
1102      }
1103    else
1104      {
1105         if (wsd->horizontal)
1106           {
1107              x = (((cx - item->prev_group) * wsd->item_width)
1108                   + (item->prev_group * wsd->group_item_width)) -
1109                wsd->pan_x + ox + alignw;
1110              y = (cy * wsd->item_height) - wsd->pan_y + oy + alignh;
1111           }
1112         else
1113           {
1114              x = (cx * wsd->item_width) - wsd->pan_x + ox + alignw;
1115              y = (((cy - item->prev_group)
1116                    * wsd->item_height) + (item->prev_group *
1117                                           wsd->group_item_height)) -
1118                wsd->pan_y + oy + alignh;
1119           }
1120         if (elm_widget_mirrored_get(WIDGET(it))) /* Switch items side
1121                                                   * and componsate for
1122                                                   * pan_x when in RTL
1123                                                   * mode */
1124           {
1125              evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
1126              x = ww - x - wsd->item_width - wsd->pan_x - wsd->pan_x;
1127           }
1128         iw = wsd->item_width;
1129         ih = wsd->item_height;
1130      }
1131
1132    was_realized = it->realized;
1133    if (ELM_RECTS_INTERSECT(x, y, iw, ih, cvx, cvy, cvw, cvh))
1134      {
1135         _item_realize(it);
1136         if (!was_realized)
1137           evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1138         if (it->parent)
1139           {
1140              if (wsd->horizontal)
1141                {
1142                   if (it->parent->item->gx < ox)
1143                     {
1144                        it->parent->item->gx = x + wsd->item_width -
1145                          wsd->group_item_width;
1146                        if (it->parent->item->gx > ox)
1147                          it->parent->item->gx = ox;
1148                     }
1149                   it->parent->item->group_realized = EINA_TRUE;
1150                }
1151              else
1152                {
1153                   if (it->parent->item->gy < oy)
1154                     {
1155                        it->parent->item->gy = y + wsd->item_height -
1156                          wsd->group_item_height;
1157                        if (it->parent->item->gy > oy)
1158                          it->parent->item->gy = oy;
1159                     }
1160                   it->parent->item->group_realized = EINA_TRUE;
1161                }
1162           }
1163         if (wsd->reorder_mode)
1164           {
1165              if (wsd->reorder_it)
1166                {
1167                   if (item->moving) return;
1168
1169                   if (!wsd->move_effect_enabled)
1170                     {
1171                        item->ox = x;
1172                        item->oy = y;
1173                     }
1174                   if (wsd->reorder_it == it)
1175                     {
1176                        evas_object_move(VIEW(it), wsd->reorder_item_x,
1177                                         wsd->reorder_item_y);
1178                        evas_object_resize(VIEW(it), iw, ih);
1179                        return;
1180                     }
1181                   else
1182                     {
1183                        Evas_Coord nx, ny, nw, nh;
1184
1185                        if (wsd->move_effect_enabled)
1186                          {
1187                             if ((item->ox != x) || (item->oy != y))
1188                               if (((wsd->old_pan_x == wsd->pan_x)
1189                                    && (wsd->old_pan_y == wsd->pan_y))
1190                                   || ((wsd->old_pan_x != wsd->pan_x) &&
1191                                       !(item->ox - wsd->pan_x
1192                                         + wsd->old_pan_x == x)) ||
1193                                   ((wsd->old_pan_y != wsd->pan_y) &&
1194                                    !(item->oy - wsd->pan_y +
1195                                      wsd->old_pan_y == y)))
1196                                 {
1197                                    item->tx = x;
1198                                    item->ty = y;
1199                                    item->rx = item->ox;
1200                                    item->ry = item->oy;
1201                                    item->moving = EINA_TRUE;
1202                                    item->moving_effect_start_time =
1203                                      ecore_loop_time_get();
1204                                    item->item_reorder_move_animator =
1205                                      ecore_animator_add
1206                                        (_reorder_item_move_animator_cb, it);
1207                                    return;
1208                                 }
1209                          }
1210
1211                        /* need fix here */
1212                        if (it->group)
1213                          {
1214                             if (wsd->horizontal)
1215                               {
1216                                  nx = x + (wsd->group_item_width / 2);
1217                                  ny = y;
1218                                  nw = 1;
1219                                  nh = vh;
1220                               }
1221                             else
1222                               {
1223                                  nx = x;
1224                                  ny = y + (wsd->group_item_height / 2);
1225                                  nw = vw;
1226                                  nh = 1;
1227                               }
1228                          }
1229                        else
1230                          {
1231                             nx = x + (wsd->item_width / 2);
1232                             ny = y + (wsd->item_height / 2);
1233                             nw = 1;
1234                             nh = 1;
1235                          }
1236
1237                        if (ELM_RECTS_INTERSECT
1238                              (wsd->reorder_item_x, wsd->reorder_item_y,
1239                              wsd->item_width, wsd->item_height,
1240                              nx, ny, nw, nh))
1241                          {
1242                             if (wsd->horizontal)
1243                               {
1244                                  if ((wsd->nmax * wsd->reorder_it->x +
1245                                       wsd->reorder_it->y) >
1246                                      (wsd->nmax * it->x + it->y))
1247                                    reorder_item_move_forward = EINA_TRUE;
1248                               }
1249                             else
1250                               {
1251                                  if ((wsd->nmax * wsd->reorder_it->y +
1252                                       wsd->reorder_it->x) >
1253                                      (wsd->nmax * it->y + it->x))
1254                                    reorder_item_move_forward = EINA_TRUE;
1255                               }
1256
1257                             wsd->items = eina_inlist_remove
1258                                 (wsd->items,
1259                                 EINA_INLIST_GET(wsd->reorder_it));
1260                             if (reorder_item_move_forward)
1261                               wsd->items = eina_inlist_prepend_relative
1262                                   (wsd->items,
1263                                   EINA_INLIST_GET(wsd->reorder_it),
1264                                   EINA_INLIST_GET(it));
1265                             else
1266                               wsd->items = eina_inlist_append_relative
1267                                   (wsd->items,
1268                                   EINA_INLIST_GET(wsd->reorder_it),
1269                                   EINA_INLIST_GET(it));
1270
1271                             wsd->reorder_item_changed = EINA_TRUE;
1272                             wsd->move_effect_enabled = EINA_TRUE;
1273                             if (wsd->calc_job)
1274                               ecore_job_del(wsd->calc_job);
1275                             wsd->calc_job =
1276                               ecore_job_add(_calc_job, wsd);
1277
1278                             return;
1279                          }
1280                     }
1281                }
1282              else if (item->item_reorder_move_animator)
1283                {
1284                   ecore_animator_del
1285                     (item->item_reorder_move_animator);
1286                   item->item_reorder_move_animator = NULL;
1287                   item->moving = EINA_FALSE;
1288                }
1289           }
1290         if (!it->group)
1291           {
1292
1293 #if GENGRID_FX_SUPPORT
1294              GG_IT(it)->scrl_x = x;
1295              GG_IT(it)->scrl_y = y;
1296              GG_IT(it)->w = iw;
1297              GG_IT(it)->h = ih;
1298 #endif
1299              evas_object_move(VIEW(it), x, y);
1300              evas_object_resize(VIEW(it), iw, ih);
1301           }
1302         else
1303           item->group_realized = EINA_TRUE;
1304      }
1305    else
1306      {
1307         if (!it->group)
1308           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1309         else
1310           item->group_realized = EINA_FALSE;
1311      }
1312 }
1313
1314 static void
1315 _group_item_place(Elm_Gengrid_Pan_Smart_Data *psd)
1316 {
1317    Evas_Coord iw, ih, vw, vh;
1318    Eina_Bool was_realized;
1319    Elm_Gen_Item *it;
1320    Eina_List *l;
1321
1322    evas_object_geometry_get(psd->wsd->pan_obj, NULL, NULL, &vw, &vh);
1323    if (psd->wsd->horizontal)
1324      {
1325         iw = psd->wsd->group_item_width;
1326         ih = vh;
1327      }
1328    else
1329      {
1330         iw = vw;
1331         ih = psd->wsd->group_item_height;
1332      }
1333    EINA_LIST_FOREACH(psd->wsd->group_items, l, it)
1334      {
1335         was_realized = it->realized;
1336         if (GG_IT(it)->group_realized)
1337           {
1338              _item_realize(it);
1339              if (!was_realized)
1340                evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1341              evas_object_move
1342                (VIEW(it), GG_IT(it)->gx,
1343                GG_IT(it)->gy);
1344              evas_object_resize(VIEW(it), iw, ih);
1345              evas_object_raise(VIEW(it));
1346           }
1347         else
1348           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1349      }
1350 }
1351
1352 static void
1353 _elm_gengrid_pan_smart_calculate(Evas_Object *obj)
1354 {
1355    Evas_Coord cx = 0, cy = 0;
1356    Elm_Gen_Item *it;
1357
1358    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1359
1360 #if GENGRID_FX_SUPPORT
1361    if (psd->wsd->fx_playing) return;
1362 #endif
1363
1364    if (!psd->wsd->nmax) return;
1365
1366    psd->wsd->reorder_item_changed = EINA_FALSE;
1367
1368    EINA_INLIST_FOREACH(psd->wsd->items, it)
1369      {
1370         if (it->group)
1371           {
1372              if (psd->wsd->horizontal)
1373                {
1374                   if (cy)
1375                     {
1376                        cx++;
1377                        cy = 0;
1378                     }
1379                }
1380              else
1381                {
1382                   if (cx)
1383                     {
1384                        cx = 0;
1385                        cy++;
1386                     }
1387                }
1388           }
1389         _item_place(it, cx, cy);
1390         if (psd->wsd->reorder_item_changed) return;
1391         if (it->group)
1392           {
1393              if (psd->wsd->horizontal)
1394                {
1395                   cx++;
1396                   cy = 0;
1397                }
1398              else
1399                {
1400                   cx = 0;
1401                   cy++;
1402                }
1403           }
1404         else
1405           {
1406              if (psd->wsd->horizontal)
1407                {
1408                   cy = (cy + 1) % psd->wsd->nmax;
1409                   if (!cy) cx++;
1410                }
1411              else
1412                {
1413                   cx = (cx + 1) % psd->wsd->nmax;
1414                   if (!cx) cy++;
1415                }
1416           }
1417      }
1418    _group_item_place(psd);
1419
1420    if ((psd->wsd->reorder_mode) && (psd->wsd->reorder_it))
1421      {
1422         if (!psd->wsd->reorder_item_changed)
1423           {
1424              psd->wsd->old_pan_x = psd->wsd->pan_x;
1425              psd->wsd->old_pan_y = psd->wsd->pan_y;
1426           }
1427         psd->wsd->move_effect_enabled = EINA_FALSE;
1428      }
1429    evas_object_smart_callback_call
1430      (ELM_WIDGET_DATA(psd->wsd)->obj, SIG_CHANGED, NULL);
1431    if ((psd->wsd->show_region || psd->wsd->bring_in))
1432      _item_show_region(psd->wsd);
1433
1434 #if GENGRID_FX_SUPPORT
1435    psd->wsd->rendered = EINA_TRUE;
1436    if (psd->wsd->fx_mode)
1437      {
1438         if (_elm_gengrid_fx_capture(ELM_WIDGET_DATA(psd->wsd)->obj, 1))
1439           _elm_gengrid_fx_play(ELM_WIDGET_DATA(psd->wsd)->obj);
1440      }
1441 #endif
1442 }
1443
1444 static void
1445 _elm_gengrid_pan_smart_pos_set(Evas_Object *obj,
1446                                Evas_Coord x,
1447                                Evas_Coord y)
1448 {
1449    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1450
1451    if ((x == psd->wsd->pan_x) && (y == psd->wsd->pan_y)) return;
1452    psd->wsd->pan_x = x;
1453    psd->wsd->pan_y = y;
1454    evas_object_smart_changed(obj);
1455 }
1456
1457 static void
1458 _elm_gengrid_pan_smart_pos_get(const Evas_Object *obj,
1459                                Evas_Coord *x,
1460                                Evas_Coord *y)
1461 {
1462    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1463
1464    if (x) *x = psd->wsd->pan_x;
1465    if (y) *y = psd->wsd->pan_y;
1466 }
1467
1468 static void
1469 _elm_gengrid_pan_smart_content_size_get(const Evas_Object *obj,
1470                                         Evas_Coord *w,
1471                                         Evas_Coord *h)
1472 {
1473    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1474
1475    if (w) *w = psd->wsd->minw;
1476    if (h) *h = psd->wsd->minh;
1477 }
1478
1479 static void
1480 _elm_gengrid_pan_smart_pos_max_get(const Evas_Object *obj,
1481                                    Evas_Coord *x,
1482                                    Evas_Coord *y)
1483 {
1484    Evas_Coord ow, oh;
1485
1486    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1487
1488    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1489    if (x)
1490      *x = (ow < psd->wsd->minw) ? psd->wsd->minw - ow : 0;
1491    if (y)
1492      *y = (oh < psd->wsd->minh) ? psd->wsd->minh - oh : 0;
1493 }
1494
1495 static void
1496 _elm_gengrid_pan_smart_pos_min_get(const Evas_Object *obj,
1497                                    Evas_Coord *x,
1498                                    Evas_Coord *y)
1499 {
1500    Evas_Coord mx = 0, my = 0;
1501
1502    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1503
1504    _elm_gengrid_pan_smart_pos_max_get(obj, &mx, &my);
1505    if (x)
1506      *x = -mx * psd->wsd->align_x;
1507    if (y)
1508      *y = -my * psd->wsd->align_y;
1509 }
1510
1511 static void
1512 _elm_gengrid_pan_smart_set_user(Elm_Gengrid_Pan_Smart_Class *sc)
1513 {
1514    ELM_PAN_CLASS(sc)->base.add = _elm_gengrid_pan_smart_add;
1515    ELM_PAN_CLASS(sc)->base.move = _elm_gengrid_pan_smart_move;
1516    ELM_PAN_CLASS(sc)->base.resize = _elm_gengrid_pan_smart_resize;
1517    ELM_PAN_CLASS(sc)->base.calculate = _elm_gengrid_pan_smart_calculate;
1518
1519    ELM_PAN_CLASS(sc)->pos_set = _elm_gengrid_pan_smart_pos_set;
1520    ELM_PAN_CLASS(sc)->pos_get = _elm_gengrid_pan_smart_pos_get;
1521    ELM_PAN_CLASS(sc)->pos_max_get = _elm_gengrid_pan_smart_pos_max_get;
1522    ELM_PAN_CLASS(sc)->pos_min_get = _elm_gengrid_pan_smart_pos_min_get;
1523    ELM_PAN_CLASS(sc)->content_size_get =
1524      _elm_gengrid_pan_smart_content_size_get;
1525
1526 }
1527
1528 static Eina_Bool
1529 _item_multi_select_left(Elm_Gengrid_Smart_Data *sd)
1530 {
1531    Elm_Object_Item *prev;
1532
1533    if (!sd->selected) return EINA_FALSE;
1534
1535    prev = elm_gengrid_item_prev_get(sd->last_selected_item);
1536    if (!prev) return EINA_TRUE;
1537
1538    if (elm_gengrid_item_selected_get(prev))
1539      {
1540         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
1541         sd->last_selected_item = prev;
1542         elm_gengrid_item_show
1543           (sd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
1544      }
1545    else
1546      {
1547         elm_gengrid_item_selected_set(prev, EINA_TRUE);
1548         elm_gengrid_item_show(prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1549      }
1550
1551    return EINA_TRUE;
1552 }
1553
1554 static Eina_Bool
1555 _item_multi_select_right(Elm_Gengrid_Smart_Data *sd)
1556 {
1557    Elm_Object_Item *next;
1558
1559    if (!sd->selected) return EINA_FALSE;
1560
1561    next = elm_gengrid_item_next_get(sd->last_selected_item);
1562    if (!next) return EINA_TRUE;
1563
1564    if (elm_gengrid_item_selected_get(next))
1565      {
1566         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
1567         sd->last_selected_item = next;
1568         elm_gengrid_item_show
1569           (sd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
1570      }
1571    else
1572      {
1573         elm_gengrid_item_selected_set(next, EINA_TRUE);
1574         elm_gengrid_item_show(next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1575      }
1576
1577    return EINA_TRUE;
1578 }
1579
1580 static Eina_Bool
1581 _item_multi_select_up(Elm_Gengrid_Smart_Data *sd)
1582 {
1583    unsigned int i;
1584    Eina_Bool r = EINA_TRUE;
1585
1586    if (!sd->selected) return EINA_FALSE;
1587
1588    for (i = 0; (r) && (i < sd->nmax); i++)
1589      r &= _item_multi_select_left(sd);
1590
1591    return r;
1592 }
1593
1594 static Eina_Bool
1595 _item_multi_select_down(Elm_Gengrid_Smart_Data *sd)
1596 {
1597    unsigned int i;
1598    Eina_Bool r = EINA_TRUE;
1599
1600    if (!sd->selected) return EINA_FALSE;
1601
1602    for (i = 0; (r) && (i < sd->nmax); i++)
1603      r &= _item_multi_select_right(sd);
1604
1605    return r;
1606 }
1607
1608 static Eina_Bool
1609 _all_items_deselect(Elm_Gengrid_Smart_Data *sd)
1610 {
1611    if (!sd->selected) return EINA_FALSE;
1612
1613    while (sd->selected)
1614      elm_gengrid_item_selected_set
1615        ((Elm_Object_Item *)sd->selected->data, EINA_FALSE);
1616
1617    return EINA_TRUE;
1618 }
1619
1620 static Eina_Bool
1621 _item_single_select_up(Elm_Gengrid_Smart_Data *sd)
1622 {
1623    unsigned int i;
1624    Elm_Gen_Item *prev;
1625
1626    if (!sd->selected)
1627      {
1628         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
1629         while ((prev) && (prev->generation < sd->generation))
1630           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
1631         elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1632         elm_gengrid_item_show
1633           ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1634         return EINA_TRUE;
1635      }
1636    else
1637      prev = (Elm_Gen_Item *)elm_gengrid_item_prev_get(sd->last_selected_item);
1638
1639    if (!prev) return EINA_FALSE;
1640
1641    for (i = 1; i < sd->nmax; i++)
1642      {
1643         Elm_Object_Item *tmp =
1644           elm_gengrid_item_prev_get((Elm_Object_Item *)prev);
1645         if (!tmp) return EINA_FALSE;
1646         prev = (Elm_Gen_Item *)tmp;
1647      }
1648
1649    _all_items_deselect(sd);
1650
1651    elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1652    elm_gengrid_item_show
1653      ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1654    return EINA_TRUE;
1655 }
1656
1657 static Eina_Bool
1658 _item_single_select_down(Elm_Gengrid_Smart_Data *sd)
1659 {
1660    unsigned int i;
1661    Elm_Gen_Item *next;
1662
1663    if (!sd->selected)
1664      {
1665         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1666         while ((next) && (next->generation < sd->generation))
1667           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
1668         elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1669         elm_gengrid_item_show
1670           ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1671         return EINA_TRUE;
1672      }
1673    else
1674      next = (Elm_Gen_Item *)elm_gengrid_item_next_get(sd->last_selected_item);
1675
1676    if (!next) return EINA_FALSE;
1677
1678    for (i = 1; i < sd->nmax; i++)
1679      {
1680         Elm_Object_Item *tmp =
1681           elm_gengrid_item_next_get((Elm_Object_Item *)next);
1682         if (!tmp) return EINA_FALSE;
1683         next = (Elm_Gen_Item *)tmp;
1684      }
1685
1686    _all_items_deselect(sd);
1687
1688    elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1689    elm_gengrid_item_show
1690      ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1691
1692    return EINA_TRUE;
1693 }
1694
1695 static Eina_Bool
1696 _item_single_select_left(Elm_Gengrid_Smart_Data *sd)
1697 {
1698    Elm_Gen_Item *prev;
1699
1700    if (!sd->selected)
1701      {
1702         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
1703         while ((prev) && (prev->generation < sd->generation))
1704           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
1705      }
1706    else
1707      prev = (Elm_Gen_Item *)elm_gengrid_item_prev_get(sd->last_selected_item);
1708
1709    if (!prev) return EINA_FALSE;
1710
1711    _all_items_deselect(sd);
1712
1713    elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1714    elm_gengrid_item_show
1715      ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1716
1717    return EINA_TRUE;
1718 }
1719
1720 static Eina_Bool
1721 _item_single_select_right(Elm_Gengrid_Smart_Data *sd)
1722 {
1723    Elm_Gen_Item *next;
1724
1725    if (!sd->selected)
1726      {
1727         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1728         while ((next) && (next->generation < sd->generation))
1729           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
1730      }
1731    else
1732      next = (Elm_Gen_Item *)elm_gengrid_item_next_get(sd->last_selected_item);
1733
1734    if (!next) return EINA_FALSE;
1735
1736    _all_items_deselect(sd);
1737
1738    elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1739    elm_gengrid_item_show
1740      ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1741
1742    return EINA_TRUE;
1743 }
1744
1745 static Eina_Bool
1746 _elm_gengrid_smart_event(Evas_Object *obj,
1747                          Evas_Object *src __UNUSED__,
1748                          Evas_Callback_Type type,
1749                          void *event_info)
1750 {
1751    Evas_Coord x = 0;
1752    Evas_Coord y = 0;
1753    Evas_Coord v_w = 0;
1754    Evas_Coord v_h = 0;
1755    Evas_Coord step_x = 0;
1756    Evas_Coord step_y = 0;
1757    Evas_Coord page_x = 0;
1758    Evas_Coord page_y = 0;
1759    Elm_Object_Item *it = NULL;
1760    Evas_Event_Key_Down *ev = event_info;
1761
1762    ELM_GENGRID_DATA_GET(obj, sd);
1763
1764    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1765    if (!sd->items) return EINA_FALSE;
1766    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1767    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1768
1769    sd->s_iface->content_pos_get(obj, &x, &y);
1770    sd->s_iface->step_size_get(obj, &step_x, &step_y);
1771    sd->s_iface->page_size_get(obj, &page_x, &page_y);
1772    sd->s_iface->content_viewport_size_get(obj, &v_w, &v_h);
1773
1774    if ((!strcmp(ev->keyname, "Left")) ||
1775        ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
1776      {
1777         if ((sd->horizontal) &&
1778             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1779               (_item_multi_select_up(sd)))
1780              || (_item_single_select_up(sd))))
1781           {
1782              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1783              return EINA_TRUE;
1784           }
1785         else if ((!sd->horizontal) &&
1786                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1787                    (_item_multi_select_left(sd)))
1788                   || (_item_single_select_left(sd))))
1789           {
1790              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1791              return EINA_TRUE;
1792           }
1793         else
1794           x -= step_x;
1795      }
1796    else if ((!strcmp(ev->keyname, "Right")) ||
1797             ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
1798      {
1799         if ((sd->horizontal) &&
1800             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1801               (_item_multi_select_down(sd)))
1802              || (_item_single_select_down(sd))))
1803           {
1804              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1805              return EINA_TRUE;
1806           }
1807         else if ((!sd->horizontal) &&
1808                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1809                    (_item_multi_select_right(sd)))
1810                   || (_item_single_select_right(sd))))
1811           {
1812              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1813              return EINA_TRUE;
1814           }
1815         else
1816           x += step_x;
1817      }
1818    else if ((!strcmp(ev->keyname, "Up")) ||
1819             ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
1820      {
1821         if ((sd->horizontal) &&
1822             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1823               (_item_multi_select_left(sd)))
1824              || (_item_single_select_left(sd))))
1825           {
1826              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1827              return EINA_TRUE;
1828           }
1829         else if ((!sd->horizontal) &&
1830                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1831                    (_item_multi_select_up(sd)))
1832                   || (_item_single_select_up(sd))))
1833           {
1834              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1835              return EINA_TRUE;
1836           }
1837         else
1838           y -= step_y;
1839      }
1840    else if ((!strcmp(ev->keyname, "Down")) ||
1841             ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
1842      {
1843         if ((sd->horizontal) &&
1844             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1845               (_item_multi_select_right(sd)))
1846              || (_item_single_select_right(sd))))
1847           {
1848              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1849              return EINA_TRUE;
1850           }
1851         else if ((!sd->horizontal) &&
1852                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1853                    (_item_multi_select_down(sd)))
1854                   || (_item_single_select_down(sd))))
1855           {
1856              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1857              return EINA_TRUE;
1858           }
1859         else
1860           y += step_y;
1861      }
1862    else if ((!strcmp(ev->keyname, "Home")) ||
1863             ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
1864      {
1865         it = elm_gengrid_first_item_get(obj);
1866         elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1867         elm_gengrid_item_selected_set(it, EINA_TRUE);
1868         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1869         return EINA_TRUE;
1870      }
1871    else if ((!strcmp(ev->keyname, "End")) ||
1872             ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
1873      {
1874         it = elm_gengrid_last_item_get(obj);
1875         elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1876         elm_gengrid_item_selected_set(it, EINA_TRUE);
1877         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1878         return EINA_TRUE;
1879      }
1880    else if ((!strcmp(ev->keyname, "Prior")) ||
1881             ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
1882      {
1883         if (sd->horizontal)
1884           {
1885              if (page_x < 0)
1886                x -= -(page_x * v_w) / 100;
1887              else
1888                x -= page_x;
1889           }
1890         else
1891           {
1892              if (page_y < 0)
1893                y -= -(page_y * v_h) / 100;
1894              else
1895                y -= page_y;
1896           }
1897      }
1898    else if ((!strcmp(ev->keyname, "Next")) ||
1899             ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
1900      {
1901         if (sd->horizontal)
1902           {
1903              if (page_x < 0)
1904                x += -(page_x * v_w) / 100;
1905              else
1906                x += page_x;
1907           }
1908         else
1909           {
1910              if (page_y < 0)
1911                y += -(page_y * v_h) / 100;
1912              else
1913                y += page_y;
1914           }
1915      }
1916    else if (!strcmp(ev->keyname, "Escape"))
1917      {
1918         if (!_all_items_deselect(sd)) return EINA_FALSE;
1919         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1920         return EINA_TRUE;
1921      }
1922    else if (((!strcmp(ev->keyname, "Return")) ||
1923              (!strcmp(ev->keyname, "KP_Enter")) ||
1924              (!strcmp(ev->keyname, "space")))
1925             && (!sd->multi) && (sd->selected))
1926      {
1927         it = elm_gengrid_selected_item_get(obj);
1928         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1929      }
1930    else return EINA_FALSE;
1931
1932    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1933    sd->s_iface->content_pos_set(obj, x, y, EINA_TRUE);
1934    return EINA_TRUE;
1935 }
1936
1937 static Eina_Bool
1938 _elm_gengrid_smart_on_focus(Evas_Object *obj)
1939 {
1940    ELM_GENGRID_DATA_GET(obj, sd);
1941
1942    if (!ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->on_focus(obj))
1943      return EINA_FALSE;
1944
1945    if (elm_widget_focus_get(obj) && (sd->selected) &&
1946        (!sd->last_selected_item))
1947      sd->last_selected_item = eina_list_data_get(sd->selected);
1948
1949    return EINA_TRUE;
1950 }
1951
1952 static Eina_Bool
1953 _elm_gengrid_smart_focus_next(const Evas_Object *obj,
1954                            Elm_Focus_Direction dir,
1955                            Evas_Object **next)
1956 {
1957    Eina_List *items = NULL;
1958    Elm_Gen_Item *it;
1959
1960    ELM_GENGRID_CHECK(obj) EINA_FALSE;
1961    ELM_GENGRID_DATA_GET(obj, sd);
1962
1963    EINA_INLIST_FOREACH(sd->items, it)
1964      {
1965         if (it->realized)
1966           items = eina_list_append(items, it->base.access_obj);
1967      }
1968
1969    return elm_widget_focus_list_next_get
1970             (obj, items, eina_list_data_get, dir, next);
1971 }
1972
1973 static void
1974 _mirrored_set(Evas_Object *obj,
1975               Eina_Bool rtl)
1976 {
1977    Elm_Gen_Item *it;
1978
1979    ELM_GENGRID_DATA_GET(obj, sd);
1980
1981    sd->s_iface->mirrored_set(obj, rtl);
1982
1983    if (!sd->items) return;
1984    it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1985
1986    while (it)
1987      {
1988         edje_object_mirrored_set(VIEW(it), rtl);
1989         elm_gengrid_item_update((Elm_Object_Item *)it);
1990         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
1991      }
1992 }
1993
1994 static Eina_Bool
1995 _elm_gengrid_smart_theme(Evas_Object *obj)
1996 {
1997    if (!ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->theme(obj))
1998      return EINA_FALSE;
1999
2000    _mirrored_set(obj, elm_widget_mirrored_get(obj));
2001
2002    return EINA_TRUE;
2003 }
2004
2005 static void
2006 _item_position_update(Eina_Inlist *list,
2007                       int idx)
2008 {
2009    Elm_Gen_Item *it;
2010
2011    EINA_INLIST_FOREACH(list, it)
2012      {
2013         it->position = idx++;
2014         it->position_update = EINA_TRUE;
2015      }
2016 }
2017
2018 static void
2019 _elm_gengrid_item_del_not_serious(Elm_Gen_Item *it)
2020 {
2021    elm_widget_item_pre_notify_del(it);
2022    it->generation = GG_IT(it)->wsd->generation - 1; /* This means that the
2023                                                      * item is deleted */
2024
2025    if ((it->relcount > 0) || (it->walking > 0)) return;
2026
2027    if (it->selected)
2028      GG_IT(it)->wsd->selected =
2029        eina_list_remove(GG_IT(it)->wsd->selected, it);
2030
2031    if (it->itc->func.del)
2032      it->itc->func.del((void *)it->base.data, WIDGET(it));
2033 }
2034
2035 static void
2036 _elm_gengrid_item_del_common(Elm_Gen_Item *it)
2037 {
2038    _elm_gengrid_item_del_not_serious(it);
2039
2040    GG_IT(it)->wsd->items = eina_inlist_remove
2041       (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2042
2043    if (it->tooltip.del_cb)
2044      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
2045    GG_IT(it)->wsd->walking -= it->walking;
2046    if (it->long_timer)
2047      {
2048         ecore_timer_del(it->long_timer);
2049         it->long_timer = NULL;
2050      }
2051    if (it->group)
2052      GG_IT(it)->wsd->group_items =
2053         eina_list_remove(GG_IT(it)->wsd->group_items, it);
2054
2055    if (GG_IT(it)->wsd->state)
2056      {
2057         eina_inlist_sorted_state_free(GG_IT(it)->wsd->state);
2058         GG_IT(it)->wsd->state = NULL;
2059      }
2060    if (GG_IT(it)->wsd->calc_job) ecore_job_del(GG_IT(it)->wsd->calc_job);
2061    GG_IT(it)->wsd->calc_job =
2062       ecore_job_add(GG_IT(it)->wsd->calc_cb, GG_IT(it)->wsd);
2063
2064    if (GG_IT(it)->wsd->last_selected_item == (Elm_Object_Item *)it)
2065      GG_IT(it)->wsd->last_selected_item = NULL;
2066    GG_IT(it)->wsd->item_count--;
2067 }
2068
2069 static void
2070 _elm_gengrid_item_del_serious(Elm_Gen_Item *it)
2071 {
2072 #if GENGRID_FX_SUPPORT
2073    if ((!GG_IT(it)->wsd->fx_mode) || (GG_IT(it)->wsd->gengrid_clearing))
2074 #endif
2075      {
2076         GG_IT(it)->wsd->items = eina_inlist_remove
2077            (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2078
2079      }
2080
2081    _elm_gengrid_item_del_common(it);
2082    free(it->item);
2083    it->item = NULL;
2084 }
2085
2086 static void
2087 _item_del(Elm_Gen_Item *it)
2088 {
2089    Evas_Object *obj = WIDGET(it);
2090
2091    evas_event_freeze(evas_object_evas_get(obj));
2092 #if GENGRID_FX_SUPPORT
2093    GG_IT(it)->has_proxy_it = EINA_FALSE;
2094 #endif
2095    GG_IT(it)->wsd->selected = eina_list_remove(GG_IT(it)->wsd->selected, it);
2096    if (it->realized) _elm_gengrid_item_unrealize(it, EINA_FALSE);
2097    _elm_gengrid_item_del_serious(it);
2098    elm_gengrid_item_class_unref((Elm_Gengrid_Item_Class *)it->itc);
2099    evas_event_thaw(evas_object_evas_get(obj));
2100    evas_event_thaw_eval(evas_object_evas_get(obj));
2101 }
2102
2103 static void
2104 _scroll_animate_start_cb(Evas_Object *obj,
2105                          void *data __UNUSED__)
2106 {
2107    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
2108 }
2109
2110 static void
2111 _scroll_animate_stop_cb(Evas_Object *obj,
2112                         void *data __UNUSED__)
2113 {
2114    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
2115 }
2116
2117 static void
2118 _scroll_drag_start_cb(Evas_Object *obj,
2119                       void *data __UNUSED__)
2120 {
2121    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
2122 }
2123
2124 static void
2125 _scroll_drag_stop_cb(Evas_Object *obj,
2126                      void *data __UNUSED__)
2127 {
2128    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
2129 }
2130
2131 static void
2132 _edge_left_cb(Evas_Object *obj,
2133               void *data __UNUSED__)
2134 {
2135    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2136 }
2137
2138 static void
2139 _edge_right_cb(Evas_Object *obj,
2140                void *data __UNUSED__)
2141 {
2142    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2143 }
2144
2145 static void
2146 _edge_top_cb(Evas_Object *obj,
2147              void *data __UNUSED__)
2148 {
2149    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2150 }
2151
2152 static void
2153 _edge_bottom_cb(Evas_Object *obj,
2154                 void *data __UNUSED__)
2155 {
2156    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2157 }
2158
2159 static void
2160 _scroll_cb(Evas_Object *obj,
2161            void *data __UNUSED__)
2162 {
2163    evas_object_smart_callback_call(obj, SIG_SCROLL, NULL);
2164 }
2165
2166 static int
2167 _elm_gengrid_item_compare(const void *data,
2168                           const void *data1)
2169 {
2170    Elm_Gen_Item *it, *item1;
2171    Eina_Compare_Cb cb = NULL;
2172    ptrdiff_t d;
2173
2174    it = ELM_GEN_ITEM_FROM_INLIST(data);
2175    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
2176    if (it && GG_IT(it)->wsd->item_compare_cb)
2177      cb = GG_IT(it)->wsd->item_compare_cb;
2178    else if (item1 && GG_IT(item1)->wsd->item_compare_cb)
2179      cb = GG_IT(item1)->wsd->item_compare_cb;
2180    if (cb && it && item1) return cb(it, item1);
2181    d = (char *)data - (char *)data1;
2182    if (d < 0) return -1;
2183    if (!d) return 0;
2184    return 1;
2185 }
2186
2187 static void
2188 _item_disable_hook(Elm_Object_Item *item)
2189 {
2190    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2191
2192    if (it->generation < GG_IT(it)->wsd->generation) return;
2193
2194    if (it->realized)
2195      {
2196         if (elm_widget_item_disabled_get(it))
2197           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
2198         else
2199           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
2200      }
2201 }
2202
2203 #if GENGRID_FX_SUPPORT
2204 static void
2205 _item_del_pre_fx_process(Elm_Gen_Item *it)
2206 {
2207    Evas_Object *obj = WIDGET(it);
2208
2209    _elm_gengrid_fx_capture(ELM_WIDGET_DATA(GG_IT(it)->wsd)->obj, 0);
2210    if (!eina_list_data_find(GG_IT(it)->wsd->pending_del_items, it))
2211      GG_IT(it)->wsd->pending_del_items = eina_list_append(GG_IT(it)->wsd->pending_del_items, it);
2212
2213    evas_object_event_callback_del_full
2214       (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
2215    evas_object_event_callback_del_full
2216       (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
2217    evas_object_event_callback_del_full
2218       (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
2219
2220    GG_IT(it)->wsd->items = eina_inlist_remove
2221       (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2222
2223    if (GG_IT(it)->wsd->calc_job) ecore_job_del(GG_IT(it)->wsd->calc_job);
2224    GG_IT(it)->wsd->calc_job =
2225       ecore_job_add(GG_IT(it)->wsd->calc_cb, GG_IT(it)->wsd);
2226 }
2227 #endif
2228
2229 //static void
2230 static Eina_Bool
2231 _item_del_pre_hook(Elm_Object_Item *item)
2232 {
2233    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2234
2235 #if GENGRID_FX_SUPPORT
2236    if ((GG_IT(it)->wsd->fx_mode) && (!GG_IT(it)->wsd->gengrid_clearing))
2237      {
2238         _item_del_pre_fx_process(it);
2239         return EINA_FALSE;
2240      }
2241 #endif
2242    if ((it->relcount > 0) || (it->walking > 0))
2243      {
2244         _elm_gengrid_item_del_not_serious(it);
2245         return EINA_TRUE;
2246      }
2247
2248    _item_del(it);
2249    return EINA_TRUE;
2250 }
2251
2252 static Evas_Object *
2253 _item_content_get_hook(Elm_Gen_Item *it,
2254                        const char *part)
2255 {
2256    return edje_object_part_swallow_get(VIEW(it), part);
2257 }
2258
2259 static const char *
2260 _item_text_get_hook(Elm_Gen_Item *it,
2261                     const char *part)
2262 {
2263    if (!it->itc->func.text_get) return NULL;
2264    return edje_object_part_text_get(VIEW(it), part);
2265 }
2266
2267 static void
2268 _item_signal_emit_hook(Elm_Object_Item *it,
2269                        const char *emission,
2270                        const char *source)
2271 {
2272    edje_object_signal_emit(VIEW(it), emission, source);
2273 }
2274
2275 static void
2276 _elm_gengrid_clear(Evas_Object *obj,
2277                    Eina_Bool standby)
2278 {
2279    Eina_Inlist *next, *l;
2280
2281    ELM_GENGRID_DATA_GET(obj, sd);
2282
2283    if (!standby) sd->generation++;
2284
2285    if (sd->state)
2286      {
2287         eina_inlist_sorted_state_free(sd->state);
2288         sd->state = NULL;
2289      }
2290
2291    if (sd->walking > 0)
2292      {
2293         sd->clear_me = EINA_TRUE;
2294         return;
2295      }
2296    evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2297
2298 #if GENGRID_FX_SUPPORT
2299    Elm_Gen_FX_Item *fi;
2300    Proxy_Item *pi;
2301    Elm_Gen_Item *it;
2302
2303    EINA_LIST_FREE(sd->capture_before_items, pi)
2304      {
2305         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
2306         if (pi->proxy) evas_object_del(pi->proxy);
2307         free(pi);
2308      }
2309    EINA_LIST_FREE(sd->capture_after_items, pi)
2310      {
2311         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
2312         if (pi->proxy) evas_object_del(pi->proxy);
2313         free(pi);
2314      }
2315    EINA_LIST_FREE(sd->fx_items, fi)
2316      {
2317         if (fi->trans) elm_transit_del(fi->trans);
2318         free(fi);
2319      }
2320    EINA_LIST_FREE (sd->pending_unrealized_items, it)
2321      {
2322         if ((it) && (GG_IT(it))) GG_IT(it)->has_proxy_it = EINA_FALSE;
2323         _elm_gengrid_item_unrealize(it, EINA_FALSE);
2324      }
2325    EINA_LIST_FREE (sd->pending_del_items, it)
2326      {
2327         _item_del(it);
2328         _elm_widget_item_free((Elm_Widget_Item *)it);
2329      }
2330    sd->gengrid_clearing = EINA_TRUE;
2331    sd->fx_playing = EINA_FALSE;
2332    sd->fx_first_captured = EINA_FALSE;
2333    sd->rendered = EINA_FALSE;
2334    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
2335 #endif
2336
2337    for (l = sd->items, next = l ? l->next : NULL;
2338         l;
2339         l = next, next = next ? next->next : NULL)
2340      {
2341         it = ELM_GEN_ITEM_FROM_INLIST(l);
2342
2343         if (it->generation < sd->generation)
2344           {
2345              Elm_Gen_Item *itn = NULL;
2346
2347              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
2348              if (itn) itn->walking++;  /* prevent early death of subitem */
2349              it->del_cb(it);
2350              elm_widget_item_free(it);
2351              if (itn) itn->walking--;
2352           }
2353      }
2354    sd->clear_me = EINA_FALSE;
2355    sd->pan_changed = EINA_TRUE;
2356    if (sd->calc_job)
2357      {
2358         ecore_job_del(sd->calc_job);
2359         sd->calc_job = NULL;
2360      }
2361    if (sd->selected) sd->selected = eina_list_free(sd->selected);
2362    if (sd->clear_cb) sd->clear_cb(sd);
2363    sd->pan_x = 0;
2364    sd->pan_y = 0;
2365    sd->minw = 0;
2366    sd->minh = 0;
2367
2368    if (sd->pan_obj)
2369      {
2370         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
2371         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
2372      }
2373    sd->s_iface->content_region_show(obj, 0, 0, 0, 0);
2374
2375 #if GENGRID_FX_SUPPORT
2376    sd->gengrid_clearing = EINA_FALSE;
2377 #endif
2378    evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2379    evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2380 }
2381
2382 static void
2383 _item_select(Elm_Gen_Item *it)
2384 {
2385    Evas_Object *obj = WIDGET(it);
2386
2387    if ((it->generation < GG_IT(it)->wsd->generation) || (it->decorate_it_set) ||
2388        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2389        (GG_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
2390      return;
2391    if (!it->selected)
2392      {
2393         it->selected = EINA_TRUE;
2394         GG_IT(it)->wsd->selected =
2395           eina_list_append(GG_IT(it)->wsd->selected, it);
2396      }
2397    else if (GG_IT(it)->wsd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS)
2398      return;
2399
2400    evas_object_ref(obj);
2401    it->walking++;
2402    GG_IT(it)->wsd->walking++;
2403    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
2404    if (it->generation == GG_IT(it)->wsd->generation)
2405      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
2406    it->walking--;
2407    GG_IT(it)->wsd->walking--;
2408    if ((GG_IT(it)->wsd->clear_me) && (!GG_IT(it)->wsd->walking))
2409      _elm_gengrid_clear(WIDGET(it), EINA_TRUE);
2410    else
2411      {
2412         if ((!it->walking) && (it->generation < GG_IT(it)->wsd->generation))
2413           {
2414              if (!it->relcount)
2415                {
2416                   it->del_cb(it);
2417                   elm_widget_item_free(it);
2418                }
2419           }
2420         else
2421           GG_IT(it)->wsd->last_selected_item = (Elm_Object_Item *)it;
2422      }
2423    evas_object_unref(obj);
2424 }
2425
2426 static Elm_Gen_Item *
2427 _elm_gengrid_item_new(Elm_Gengrid_Smart_Data *sd,
2428                       const Elm_Gen_Item_Class *itc,
2429                       const void *data,
2430                       Evas_Smart_Cb func,
2431                       const void *func_data)
2432 {
2433    Elm_Gen_Item *it;
2434
2435    if (!itc) return NULL;
2436
2437    it = elm_widget_item_new(ELM_WIDGET_DATA(sd)->obj, Elm_Gen_Item);
2438    if (!it) return NULL;
2439
2440    it->generation = sd->generation;
2441    it->itc = itc;
2442    elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
2443
2444    it->base.data = data;
2445    it->parent = NULL;
2446    it->func.func = func;
2447    it->func.data = func_data;
2448
2449    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
2450    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
2451    elm_widget_item_disable_hook_set(it, _item_disable_hook);
2452    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
2453    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
2454
2455    /* TEMPORARY */
2456    it->sel_cb = (Ecore_Cb)_item_select;
2457
2458    elm_widget_item_disable_hook_set(it, _item_disable_hook);
2459    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
2460    elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
2461    it->item = ELM_NEW(Elm_Gen_Item_Type);
2462
2463    GG_IT(it)->wsd = sd;
2464
2465    sd->item_count++;
2466    it->group = it->itc->item_style &&
2467      (!strcmp(it->itc->item_style, "group_index"));
2468
2469    it->del_cb = (Ecore_Cb)_item_del;
2470    it->highlight_cb = (Ecore_Cb)_item_highlight;
2471    it->unsel_cb = (Ecore_Cb)_item_unselect;
2472    it->unrealize_cb = (Ecore_Cb)_item_unrealize_cb;
2473
2474 #if GENGRID_FX_SUPPORT
2475    it->item->num = sd->item_count;
2476    if (sd->fx_mode)
2477      _elm_gengrid_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
2478 #endif
2479
2480    return it;
2481 }
2482
2483 /* common layout sizing won't apply here */
2484 static void
2485 _elm_gengrid_smart_sizing_eval(Evas_Object *obj __UNUSED__)
2486 {
2487    return;  /* no-op */
2488 }
2489
2490 static void
2491 _elm_gengrid_smart_add(Evas_Object *obj)
2492 {
2493    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
2494    Elm_Gengrid_Pan_Smart_Data *pan_data;
2495
2496    EVAS_SMART_DATA_ALLOC(obj, Elm_Gengrid_Smart_Data);
2497
2498    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.add(obj);
2499
2500    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
2501    evas_object_smart_member_add(priv->hit_rect, obj);
2502    elm_widget_sub_object_add(obj, priv->hit_rect);
2503
2504    /* common scroller hit rectangle setup */
2505    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
2506    evas_object_show(priv->hit_rect);
2507    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
2508
2509    elm_widget_can_focus_set(obj, EINA_TRUE);
2510
2511    priv->calc_cb = (Ecore_Cb)_calc_job;
2512
2513    priv->generation = 1;
2514
2515    elm_layout_theme_set(obj, "gengrid", "base", elm_widget_style_get(obj));
2516
2517    /* interface's add() routine issued AFTER the object's smart_add() */
2518    priv->s_iface = evas_object_smart_interface_get
2519        (obj, ELM_SCROLLABLE_IFACE_NAME);
2520
2521    priv->s_iface->objects_set
2522      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
2523
2524    priv->old_h_bounce = bounce;
2525    priv->old_v_bounce = bounce;
2526    priv->s_iface->bounce_allow_set(obj, bounce, bounce);
2527
2528    priv->s_iface->animate_start_cb_set(obj, _scroll_animate_start_cb);
2529    priv->s_iface->animate_stop_cb_set(obj, _scroll_animate_stop_cb);
2530    priv->s_iface->drag_start_cb_set(obj, _scroll_drag_start_cb);
2531    priv->s_iface->drag_stop_cb_set(obj, _scroll_drag_stop_cb);
2532    priv->s_iface->edge_left_cb_set(obj, _edge_left_cb);
2533    priv->s_iface->edge_right_cb_set(obj, _edge_right_cb);
2534    priv->s_iface->edge_top_cb_set(obj, _edge_top_cb);
2535    priv->s_iface->edge_bottom_cb_set(obj, _edge_bottom_cb);
2536    priv->s_iface->scroll_cb_set(obj, _scroll_cb);
2537
2538    priv->align_x = 0.5;
2539    priv->align_y = 0.5;
2540    priv->highlight = EINA_TRUE;
2541
2542 #if GENGRID_FX_SUPPORT
2543    priv->fx_mode = EINA_FALSE;
2544    priv->rendered = EINA_FALSE;
2545    priv->fx_first_captured = EINA_FALSE;
2546    priv->fx_playing = EINA_FALSE;
2547    priv->gengrid_clearing = EINA_FALSE;
2548 #endif
2549
2550    priv->pan_obj = evas_object_smart_add
2551        (evas_object_evas_get(obj), _elm_gengrid_pan_smart_class_new());
2552    pan_data = evas_object_smart_data_get(priv->pan_obj);
2553    pan_data->wsd = priv;
2554
2555    priv->s_iface->extern_pan_set(obj, priv->pan_obj);
2556 }
2557
2558 static void
2559 _elm_gengrid_smart_del(Evas_Object *obj)
2560 {
2561    ELM_GENGRID_DATA_GET(obj, sd);
2562
2563    elm_gengrid_clear(obj);
2564    evas_object_del(sd->pan_obj);
2565    sd->pan_obj = NULL;
2566
2567    if (sd->calc_job) ecore_job_del(sd->calc_job);
2568
2569    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.del(obj);
2570 }
2571
2572 static void
2573 _elm_gengrid_smart_move(Evas_Object *obj,
2574                         Evas_Coord x,
2575                         Evas_Coord y)
2576 {
2577    ELM_GENGRID_DATA_GET(obj, sd);
2578
2579    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.move(obj, x, y);
2580
2581    evas_object_move(sd->hit_rect, x, y);
2582 }
2583
2584 static void
2585 _elm_gengrid_smart_resize(Evas_Object *obj,
2586                           Evas_Coord w,
2587                           Evas_Coord h)
2588 {
2589    ELM_GENGRID_DATA_GET(obj, sd);
2590
2591    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.resize(obj, w, h);
2592
2593    evas_object_resize(sd->hit_rect, w, h);
2594 }
2595
2596 static void
2597 _elm_gengrid_smart_member_add(Evas_Object *obj,
2598                               Evas_Object *member)
2599 {
2600    ELM_GENGRID_DATA_GET(obj, sd);
2601
2602    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.member_add(obj, member);
2603
2604    if (sd->hit_rect)
2605      evas_object_raise(sd->hit_rect);
2606 }
2607
2608 static void
2609 _access_obj_process(Elm_Gengrid_Smart_Data * sd, Eina_Bool is_access)
2610 {
2611    Elm_Gen_Item *it;
2612
2613    EINA_INLIST_FOREACH(sd->items, it)
2614      {
2615         if (!it->realized) continue;
2616         if (is_access) _access_widget_item_register(it);
2617         else
2618           _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
2619
2620      }
2621 }
2622
2623 static void
2624 _access_hook(Evas_Object *obj, Eina_Bool is_access)
2625 {
2626    ELM_GENGRID_CHECK(obj);
2627    ELM_GENGRID_DATA_GET(obj, sd);
2628
2629    if (is_access)
2630      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
2631      _elm_gengrid_smart_focus_next;
2632    else
2633      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
2634
2635    _access_obj_process(sd, is_access);
2636 }
2637
2638 static void
2639 _elm_gengrid_smart_set_user(Elm_Gengrid_Smart_Class *sc)
2640 {
2641    ELM_WIDGET_CLASS(sc)->base.add = _elm_gengrid_smart_add;
2642    ELM_WIDGET_CLASS(sc)->base.del = _elm_gengrid_smart_del;
2643    ELM_WIDGET_CLASS(sc)->base.move = _elm_gengrid_smart_move;
2644    ELM_WIDGET_CLASS(sc)->base.resize = _elm_gengrid_smart_resize;
2645    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_gengrid_smart_member_add;
2646
2647    ELM_WIDGET_CLASS(sc)->on_focus = _elm_gengrid_smart_on_focus;
2648    ELM_WIDGET_CLASS(sc)->theme = _elm_gengrid_smart_theme;
2649    ELM_WIDGET_CLASS(sc)->event = _elm_gengrid_smart_event;
2650
2651    /* not a 'focus chain manager' */
2652    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
2653    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
2654    ELM_WIDGET_CLASS(sc)->translate = _elm_gengrid_smart_translate;
2655
2656    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_gengrid_smart_sizing_eval;
2657
2658    // ACCESS
2659    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
2660      ELM_WIDGET_CLASS(sc)->focus_next = _elm_gengrid_smart_focus_next;
2661
2662    ELM_WIDGET_CLASS(sc)->access = _access_hook;
2663 }
2664
2665 EAPI const Elm_Gengrid_Smart_Class *
2666 elm_gengrid_smart_class_get(void)
2667 {
2668    static Elm_Gengrid_Smart_Class _sc =
2669      ELM_GENGRID_SMART_CLASS_INIT_NAME_VERSION(ELM_GENGRID_SMART_NAME);
2670    static const Elm_Gengrid_Smart_Class *class = NULL;
2671    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
2672
2673    if (class)
2674      return class;
2675
2676    _elm_gengrid_smart_set(&_sc);
2677    esc->callbacks = _smart_callbacks;
2678    class = &_sc;
2679
2680    return class;
2681 }
2682
2683 EAPI Evas_Object *
2684 elm_gengrid_add(Evas_Object *parent)
2685 {
2686    Evas_Object *obj;
2687
2688    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2689
2690    obj = elm_widget_add(_elm_gengrid_smart_class_new(), parent);
2691    if (!obj) return NULL;
2692
2693    if (!elm_widget_sub_object_add(parent, obj))
2694      ERR("could not add %p as sub object of %p", obj, parent);
2695
2696    return obj;
2697 }
2698
2699 EAPI void
2700 elm_gengrid_item_size_set(Evas_Object *obj,
2701                           Evas_Coord w,
2702                           Evas_Coord h)
2703 {
2704    ELM_GENGRID_CHECK(obj);
2705    ELM_GENGRID_DATA_GET(obj, sd);
2706
2707    if ((sd->item_width == w) && (sd->item_height == h)) return;
2708    sd->item_width = w;
2709    sd->item_height = h;
2710    if (sd->calc_job) ecore_job_del(sd->calc_job);
2711    sd->calc_job = ecore_job_add(_calc_job, sd);
2712 }
2713
2714 EAPI void
2715 elm_gengrid_item_size_get(const Evas_Object *obj,
2716                           Evas_Coord *w,
2717                           Evas_Coord *h)
2718 {
2719    ELM_GENGRID_CHECK(obj);
2720    ELM_GENGRID_DATA_GET(obj, sd);
2721
2722    if (w) *w = sd->item_width;
2723    if (h) *h = sd->item_height;
2724 }
2725
2726 EAPI void
2727 elm_gengrid_group_item_size_set(Evas_Object *obj,
2728                                 Evas_Coord w,
2729                                 Evas_Coord h)
2730 {
2731    ELM_GENGRID_CHECK(obj);
2732    ELM_GENGRID_DATA_GET(obj, sd);
2733
2734    if ((sd->group_item_width == w) && (sd->group_item_height == h)) return;
2735    sd->group_item_width = w;
2736    sd->group_item_height = h;
2737    if (sd->calc_job) ecore_job_del(sd->calc_job);
2738    sd->calc_job = ecore_job_add(_calc_job, sd);
2739 }
2740
2741 EAPI void
2742 elm_gengrid_group_item_size_get(const Evas_Object *obj,
2743                                 Evas_Coord *w,
2744                                 Evas_Coord *h)
2745 {
2746    ELM_GENGRID_CHECK(obj);
2747    ELM_GENGRID_DATA_GET(obj, sd);
2748
2749    if (w) *w = sd->group_item_width;
2750    if (h) *h = sd->group_item_height;
2751 }
2752
2753 EAPI void
2754 elm_gengrid_align_set(Evas_Object *obj,
2755                       double align_x,
2756                       double align_y)
2757 {
2758    double old_h, old_y;
2759
2760    ELM_GENGRID_CHECK(obj);
2761    ELM_GENGRID_DATA_GET(obj, sd);
2762
2763    old_h = sd->align_x;
2764    old_y = sd->align_y;
2765
2766    if (align_x > 1.0)
2767      align_x = 1.0;
2768    else if (align_x < 0.0)
2769      align_x = 0.0;
2770    sd->align_x = align_x;
2771
2772    if (align_y > 1.0)
2773      align_y = 1.0;
2774    else if (align_y < 0.0)
2775      align_y = 0.0;
2776    sd->align_y = align_y;
2777
2778    if ((old_h != sd->align_x) || (old_y != sd->align_y))
2779      evas_object_smart_calculate(sd->pan_obj);
2780 }
2781
2782 EAPI void
2783 elm_gengrid_align_get(const Evas_Object *obj,
2784                       double *align_x,
2785                       double *align_y)
2786 {
2787    ELM_GENGRID_CHECK(obj);
2788    ELM_GENGRID_DATA_GET(obj, sd);
2789
2790    if (align_x) *align_x = sd->align_x;
2791    if (align_y) *align_y = sd->align_y;
2792 }
2793
2794 EAPI Elm_Object_Item *
2795 elm_gengrid_item_append(Evas_Object *obj,
2796                         const Elm_Gengrid_Item_Class *itc,
2797                         const void *data,
2798                         Evas_Smart_Cb func,
2799                         const void *func_data)
2800 {
2801    Elm_Gen_Item *it;
2802
2803    ELM_GENGRID_CHECK(obj) NULL;
2804    ELM_GENGRID_DATA_GET(obj, sd);
2805
2806    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2807    if (!it) return NULL;
2808
2809    sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
2810    it->position = eina_inlist_count(sd->items);
2811    it->position_update = EINA_TRUE;
2812
2813    if (it->group)
2814      sd->group_items = eina_list_prepend(sd->group_items, it);
2815
2816    if (sd->calc_job) ecore_job_del(sd->calc_job);
2817    sd->calc_job = ecore_job_add(_calc_job, sd);
2818
2819    return (Elm_Object_Item *)it;
2820 }
2821
2822 EAPI Elm_Object_Item *
2823 elm_gengrid_item_prepend(Evas_Object *obj,
2824                          const Elm_Gengrid_Item_Class *itc,
2825                          const void *data,
2826                          Evas_Smart_Cb func,
2827                          const void *func_data)
2828 {
2829    Elm_Gen_Item *it;
2830
2831    ELM_GENGRID_CHECK(obj) NULL;
2832    ELM_GENGRID_DATA_GET(obj, sd);
2833
2834    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2835    if (!it) return NULL;
2836
2837    sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
2838    _item_position_update(sd->items, 0);
2839
2840    if (it->group)
2841      sd->group_items = eina_list_append(sd->group_items, it);
2842
2843    if (sd->calc_job) ecore_job_del(sd->calc_job);
2844    sd->calc_job = ecore_job_add(_calc_job, sd);
2845
2846    return (Elm_Object_Item *)it;
2847 }
2848
2849 EAPI Elm_Object_Item *
2850 elm_gengrid_item_insert_before(Evas_Object *obj,
2851                                const Elm_Gengrid_Item_Class *itc,
2852                                const void *data,
2853                                Elm_Object_Item *relative,
2854                                Evas_Smart_Cb func,
2855                                const void *func_data)
2856 {
2857    Elm_Gen_Item *it;
2858    Eina_Inlist *tmp;
2859
2860    ELM_GENGRID_CHECK(obj) NULL;
2861    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
2862    ELM_GENGRID_DATA_GET(obj, sd);
2863
2864    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2865    if (!it) return NULL;
2866    sd->items = eina_inlist_prepend_relative
2867        (sd->items, EINA_INLIST_GET(it),
2868        EINA_INLIST_GET((Elm_Gen_Item *)relative));
2869    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
2870    _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position);
2871
2872    if (it->group)
2873      sd->group_items = eina_list_append_relative
2874          (sd->group_items, it, ((Elm_Gen_Item *)relative)->parent);
2875
2876    if (sd->calc_job) ecore_job_del(sd->calc_job);
2877    sd->calc_job = ecore_job_add(_calc_job, sd);
2878
2879    return (Elm_Object_Item *)it;
2880 }
2881
2882 EAPI Elm_Object_Item *
2883 elm_gengrid_item_insert_after(Evas_Object *obj,
2884                               const Elm_Gengrid_Item_Class *itc,
2885                               const void *data,
2886                               Elm_Object_Item *relative,
2887                               Evas_Smart_Cb func,
2888                               const void *func_data)
2889 {
2890    Elm_Gen_Item *it;
2891    Eina_Inlist *tmp;
2892
2893    ELM_GENGRID_CHECK(obj) NULL;
2894    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
2895    ELM_GENGRID_DATA_GET(obj, sd);
2896
2897    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2898    if (!it) return NULL;
2899    sd->items = eina_inlist_append_relative
2900        (sd->items, EINA_INLIST_GET(it),
2901        EINA_INLIST_GET((Elm_Gen_Item *)relative));
2902    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
2903    _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position + 1);
2904
2905    if (it->group)
2906      sd->group_items = eina_list_prepend_relative
2907          (sd->group_items, it, ((Elm_Gen_Item *)relative)->parent);
2908
2909    if (sd->calc_job) ecore_job_del(sd->calc_job);
2910    sd->calc_job = ecore_job_add(_calc_job, sd);
2911
2912    return (Elm_Object_Item *)it;
2913 }
2914
2915 EAPI Elm_Object_Item *
2916 elm_gengrid_item_sorted_insert(Evas_Object *obj,
2917                                const Elm_Gengrid_Item_Class *itc,
2918                                const void *data,
2919                                Eina_Compare_Cb comp,
2920                                Evas_Smart_Cb func,
2921                                const void *func_data)
2922 {
2923    Elm_Gen_Item *it;
2924
2925    ELM_GENGRID_CHECK(obj) NULL;
2926    ELM_GENGRID_DATA_GET(obj, sd);
2927
2928    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2929    if (!it) return NULL;
2930
2931    if (!sd->state)
2932      {
2933         sd->state = eina_inlist_sorted_state_new();
2934         eina_inlist_sorted_state_init(sd->state, sd->items);
2935      }
2936
2937    sd->item_compare_cb = comp;
2938    sd->items = eina_inlist_sorted_state_insert
2939        (sd->items, EINA_INLIST_GET(it), _elm_gengrid_item_compare, sd->state);
2940    _item_position_update(sd->items, 0);
2941
2942    if (sd->calc_job) ecore_job_del(sd->calc_job);
2943    sd->calc_job = ecore_job_add(_calc_job, sd);
2944
2945    return (Elm_Object_Item *)it;
2946 }
2947
2948 EAPI void
2949 elm_gengrid_horizontal_set(Evas_Object *obj,
2950                            Eina_Bool horizontal)
2951 {
2952    ELM_GENGRID_CHECK(obj);
2953    ELM_GENGRID_DATA_GET(obj, sd);
2954
2955    horizontal = !!horizontal;
2956    if (horizontal == sd->horizontal) return;
2957    sd->horizontal = horizontal;
2958
2959    /* Update the items to conform to the new layout */
2960    if (sd->calc_job) ecore_job_del(sd->calc_job);
2961    sd->calc_job = ecore_job_add(_calc_job, sd);
2962 }
2963
2964 EAPI Eina_Bool
2965 elm_gengrid_horizontal_get(const Evas_Object *obj)
2966 {
2967    ELM_GENGRID_CHECK(obj) EINA_FALSE;
2968    ELM_GENGRID_DATA_GET(obj, sd);
2969
2970    return sd->horizontal;
2971 }
2972
2973 EAPI void
2974 elm_gengrid_clear(Evas_Object *obj)
2975 {
2976    ELM_GENGRID_CHECK(obj);
2977
2978    _elm_gengrid_clear(obj, EINA_FALSE);
2979 }
2980
2981 EINA_DEPRECATED EAPI const Evas_Object *
2982 elm_gengrid_item_object_get(const Elm_Object_Item *it)
2983 {
2984    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
2985
2986    return VIEW(it);
2987 }
2988
2989 EAPI void
2990 elm_gengrid_item_update(Elm_Object_Item *item)
2991 {
2992    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2993
2994    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
2995
2996    if (!it->realized) return;
2997    if (it->want_unrealize) return;
2998
2999    _elm_gengrid_item_unrealize(it, EINA_FALSE);
3000    _item_realize(it);
3001    _item_place(it, it->x, it->y);
3002 }
3003
3004 EAPI const Elm_Gengrid_Item_Class *
3005 elm_gengrid_item_item_class_get(const Elm_Object_Item *it)
3006 {
3007    Elm_Gen_Item *item = (Elm_Gen_Item *)it;
3008
3009    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3010
3011    if (item->generation < GG_IT(item)->wsd->generation) return NULL;
3012    return item->itc;
3013 }
3014
3015 EAPI void
3016 elm_gengrid_item_item_class_update(Elm_Object_Item *item,
3017                                    const Elm_Gengrid_Item_Class *itc)
3018 {
3019    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3020
3021    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3022    EINA_SAFETY_ON_NULL_RETURN(itc);
3023
3024    if (it->generation < GG_IT(it)->wsd->generation) return;
3025    it->itc = itc;
3026    elm_gengrid_item_update(item);
3027 }
3028
3029 EAPI void
3030 elm_gengrid_item_pos_get(const Elm_Object_Item *it,
3031                          unsigned int *x,
3032                          unsigned int *y)
3033 {
3034    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3035
3036    if (x) *x = ((Elm_Gen_Item *)it)->x;
3037    if (y) *y = ((Elm_Gen_Item *)it)->y;
3038 }
3039
3040 EAPI void
3041 elm_gengrid_multi_select_set(Evas_Object *obj,
3042                              Eina_Bool multi)
3043 {
3044    ELM_GENGRID_CHECK(obj);
3045    ELM_GENGRID_DATA_GET(obj, sd);
3046
3047    sd->multi = !!multi;
3048 }
3049
3050 EAPI Eina_Bool
3051 elm_gengrid_multi_select_get(const Evas_Object *obj)
3052 {
3053    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3054    ELM_GENGRID_DATA_GET(obj, sd);
3055
3056    return sd->multi;
3057 }
3058
3059 EAPI Elm_Object_Item *
3060 elm_gengrid_selected_item_get(const Evas_Object *obj)
3061 {
3062    ELM_GENGRID_CHECK(obj) NULL;
3063    ELM_GENGRID_DATA_GET(obj, sd);
3064
3065    if (sd->selected) return sd->selected->data;
3066    return NULL;
3067 }
3068
3069 EAPI const Eina_List *
3070 elm_gengrid_selected_items_get(const Evas_Object *obj)
3071 {
3072    ELM_GENGRID_CHECK(obj) NULL;
3073    ELM_GENGRID_DATA_GET(obj, sd);
3074
3075    return sd->selected;
3076 }
3077
3078 EAPI void
3079 elm_gengrid_item_selected_set(Elm_Object_Item *item,
3080                               Eina_Bool selected)
3081 {
3082    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3083
3084    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3085
3086    if ((it->generation < GG_IT(it)->wsd->generation) ||
3087        elm_widget_item_disabled_get(it))
3088      return;
3089    selected = !!selected;
3090    if (it->selected == selected) return;
3091
3092    if (selected)
3093      {
3094         if (!GG_IT(it)->wsd->multi)
3095           {
3096              while (GG_IT(it)->wsd->selected)
3097                {
3098                   if (it->unhighlight_cb)
3099                     it->unhighlight_cb(GG_IT(it)->wsd->selected->data);
3100                   it->unsel_cb(GG_IT(it)->wsd->selected->data);
3101                }
3102           }
3103         it->highlight_cb(it);
3104         _item_select(it);
3105         return;
3106      }
3107    if (it->unhighlight_cb) it->unhighlight_cb(it);
3108    it->unsel_cb(it);
3109 }
3110
3111 EAPI Eina_Bool
3112 elm_gengrid_item_selected_get(const Elm_Object_Item *it)
3113 {
3114    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3115
3116    return ((Elm_Gen_Item *)it)->selected;
3117 }
3118
3119 EAPI Eina_List *
3120 elm_gengrid_realized_items_get(const Evas_Object *obj)
3121 {
3122    Eina_List *list = NULL;
3123    Elm_Gen_Item *it;
3124
3125    ELM_GENGRID_CHECK(obj) NULL;
3126    ELM_GENGRID_DATA_GET(obj, sd);
3127
3128    EINA_INLIST_FOREACH(sd->items, it)
3129      {
3130         if (it->realized) list = eina_list_append(list, (Elm_Object_Item *)it);
3131      }
3132    return list;
3133 }
3134
3135 EAPI void
3136 elm_gengrid_realized_items_update(Evas_Object *obj)
3137 {
3138    Eina_List *list, *l;
3139    Elm_Object_Item *it;
3140
3141    ELM_GENGRID_CHECK(obj);
3142
3143    list = elm_gengrid_realized_items_get(obj);
3144    EINA_LIST_FOREACH(list, l, it)
3145      elm_gengrid_item_update(it);
3146 }
3147
3148 static Evas_Object *
3149 _elm_gengrid_item_label_create(void *data,
3150                                Evas_Object *obj __UNUSED__,
3151                                Evas_Object *tooltip,
3152                                void *it   __UNUSED__)
3153 {
3154    Evas_Object *label = elm_label_add(tooltip);
3155    if (!label)
3156      return NULL;
3157    elm_object_style_set(label, "tooltip");
3158    elm_object_text_set(label, data);
3159    return label;
3160 }
3161
3162 static void
3163 _elm_gengrid_item_label_del_cb(void *data,
3164                                Evas_Object *obj __UNUSED__,
3165                                void *event_info __UNUSED__)
3166 {
3167    eina_stringshare_del(data);
3168 }
3169
3170 EAPI void
3171 elm_gengrid_item_tooltip_text_set(Elm_Object_Item *it,
3172                                   const char *text)
3173 {
3174    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3175
3176    text = eina_stringshare_add(text);
3177    elm_gengrid_item_tooltip_content_cb_set
3178      (it, _elm_gengrid_item_label_create, text,
3179      _elm_gengrid_item_label_del_cb);
3180 }
3181
3182 EAPI void
3183 elm_gengrid_item_tooltip_content_cb_set(Elm_Object_Item *item,
3184                                         Elm_Tooltip_Item_Content_Cb func,
3185                                         const void *data,
3186                                         Evas_Smart_Cb del_cb)
3187 {
3188    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3189
3190    ELM_GENGRID_ITEM_CHECK_OR_GOTO(it, error);
3191
3192    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
3193      return;
3194
3195    if (it->tooltip.del_cb)
3196      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3197    it->tooltip.content_cb = func;
3198    it->tooltip.data = data;
3199    it->tooltip.del_cb = del_cb;
3200    if (VIEW(it))
3201      {
3202         elm_widget_item_tooltip_content_cb_set
3203           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
3204         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
3205         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
3206      }
3207
3208    return;
3209
3210 error:
3211    if (del_cb) del_cb((void *)data, NULL, NULL);
3212 }
3213
3214 EAPI void
3215 elm_gengrid_item_tooltip_unset(Elm_Object_Item *item)
3216 {
3217    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3218
3219    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3220
3221    if ((VIEW(it)) && (it->tooltip.content_cb))
3222      elm_widget_item_tooltip_unset(it);
3223
3224    if (it->tooltip.del_cb)
3225      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3226    it->tooltip.del_cb = NULL;
3227    it->tooltip.content_cb = NULL;
3228    it->tooltip.data = NULL;
3229    it->tooltip.free_size = EINA_FALSE;
3230    if (it->tooltip.style)
3231      elm_gengrid_item_tooltip_style_set(item, NULL);
3232 }
3233
3234 EAPI void
3235 elm_gengrid_item_tooltip_style_set(Elm_Object_Item *it,
3236                                    const char *style)
3237 {
3238    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3239
3240    eina_stringshare_replace(&((Elm_Gen_Item *)it)->tooltip.style, style);
3241    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
3242 }
3243
3244 EAPI const char *
3245 elm_gengrid_item_tooltip_style_get(const Elm_Object_Item *it)
3246 {
3247    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3248
3249    return ((Elm_Gen_Item *)it)->tooltip.style;
3250 }
3251
3252 EAPI Eina_Bool
3253 elm_gengrid_item_tooltip_window_mode_set(Elm_Object_Item *it,
3254                                          Eina_Bool disable)
3255 {
3256    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3257
3258    ((Elm_Gen_Item *)it)->tooltip.free_size = disable;
3259    if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
3260
3261    return EINA_TRUE;
3262 }
3263
3264 EAPI Eina_Bool
3265 elm_gengrid_item_tooltip_window_mode_get(const Elm_Object_Item *it)
3266 {
3267    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3268
3269    return ((Elm_Gen_Item *)it)->tooltip.free_size;
3270 }
3271
3272 EAPI void
3273 elm_gengrid_item_cursor_set(Elm_Object_Item *it,
3274                             const char *cursor)
3275 {
3276    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3277
3278    eina_stringshare_replace(&((Elm_Gen_Item *)it)->mouse_cursor, cursor);
3279    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
3280 }
3281
3282 EAPI const char *
3283 elm_gengrid_item_cursor_get(const Elm_Object_Item *it)
3284 {
3285    return elm_widget_item_cursor_get(it);
3286 }
3287
3288 EAPI void
3289 elm_gengrid_item_cursor_unset(Elm_Object_Item *item)
3290 {
3291    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3292
3293    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3294    if (!it->mouse_cursor)
3295      return;
3296
3297    if (VIEW(it))
3298      elm_widget_item_cursor_unset(it);
3299
3300    eina_stringshare_del(it->mouse_cursor);
3301    it->mouse_cursor = NULL;
3302 }
3303
3304 EAPI void
3305 elm_gengrid_item_cursor_style_set(Elm_Object_Item *it,
3306                                   const char *style)
3307 {
3308    elm_widget_item_cursor_style_set(it, style);
3309 }
3310
3311 EAPI const char *
3312 elm_gengrid_item_cursor_style_get(const Elm_Object_Item *it)
3313 {
3314    return elm_widget_item_cursor_style_get(it);
3315 }
3316
3317 EAPI void
3318 elm_gengrid_item_cursor_engine_only_set(Elm_Object_Item *it,
3319                                         Eina_Bool engine_only)
3320 {
3321    elm_widget_item_cursor_engine_only_set(it, engine_only);
3322 }
3323
3324 EAPI Eina_Bool
3325 elm_gengrid_item_cursor_engine_only_get(const Elm_Object_Item *it)
3326 {
3327    return elm_widget_item_cursor_engine_only_get(it);
3328 }
3329
3330 EAPI void
3331 elm_gengrid_reorder_mode_set(Evas_Object *obj,
3332                              Eina_Bool reorder_mode)
3333 {
3334    ELM_GENGRID_CHECK(obj);
3335    ELM_GENGRID_DATA_GET(obj, sd);
3336
3337    sd->reorder_mode = !!reorder_mode;
3338 }
3339
3340 EAPI Eina_Bool
3341 elm_gengrid_reorder_mode_get(const Evas_Object *obj)
3342 {
3343    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3344    ELM_GENGRID_DATA_GET(obj, sd);
3345
3346    return sd->reorder_mode;
3347 }
3348
3349 EAPI void
3350 elm_gengrid_bounce_set(Evas_Object *obj,
3351                        Eina_Bool h_bounce,
3352                        Eina_Bool v_bounce)
3353 {
3354    ELM_GENGRID_CHECK(obj);
3355    ELM_GENGRID_DATA_GET(obj, sd);
3356
3357    sd->s_iface->bounce_allow_set(obj, !!h_bounce, !!v_bounce);
3358 }
3359
3360 EAPI void
3361 elm_gengrid_bounce_get(const Evas_Object *obj,
3362                        Eina_Bool *h_bounce,
3363                        Eina_Bool *v_bounce)
3364 {
3365    ELM_GENGRID_CHECK(obj);
3366    ELM_GENGRID_DATA_GET(obj, sd);
3367
3368    sd->s_iface->bounce_allow_get(obj, h_bounce, v_bounce);
3369 }
3370
3371 EAPI void
3372 elm_gengrid_page_relative_set(Evas_Object *obj,
3373                               double h_pagerel,
3374                               double v_pagerel)
3375 {
3376    Evas_Coord pagesize_h;
3377    Evas_Coord pagesize_v;
3378
3379    ELM_GENGRID_CHECK(obj);
3380    ELM_GENGRID_DATA_GET(obj, sd);
3381
3382    sd->s_iface->paging_get(obj, NULL, NULL, &pagesize_h, &pagesize_v);
3383    sd->s_iface->paging_set
3384      (obj, h_pagerel, v_pagerel, pagesize_h, pagesize_v);
3385 }
3386
3387 EAPI void
3388 elm_gengrid_page_relative_get(const Evas_Object *obj,
3389                               double *h_pagerel,
3390                               double *v_pagerel)
3391 {
3392    ELM_GENGRID_CHECK(obj);
3393    ELM_GENGRID_DATA_GET(obj, sd);
3394
3395    sd->s_iface->paging_get(obj, h_pagerel, v_pagerel, NULL, NULL);
3396 }
3397
3398 EAPI void
3399 elm_gengrid_page_size_set(Evas_Object *obj,
3400                           Evas_Coord h_pagesize,
3401                           Evas_Coord v_pagesize)
3402 {
3403    double pagerel_h;
3404    double pagerel_v;
3405
3406    ELM_GENGRID_CHECK(obj);
3407    ELM_GENGRID_DATA_GET(obj, sd);
3408
3409    sd->s_iface->paging_get(obj, &pagerel_h, &pagerel_v, NULL, NULL);
3410    sd->s_iface->paging_set
3411      (obj, pagerel_h, pagerel_v, h_pagesize, v_pagesize);
3412 }
3413
3414 EAPI void
3415 elm_gengrid_current_page_get(const Evas_Object *obj,
3416                              int *h_pagenumber,
3417                              int *v_pagenumber)
3418 {
3419    ELM_GENGRID_CHECK(obj);
3420    ELM_GENGRID_DATA_GET(obj, sd);
3421
3422    sd->s_iface->current_page_get(obj, h_pagenumber, v_pagenumber);
3423 }
3424
3425 EAPI void
3426 elm_gengrid_last_page_get(const Evas_Object *obj,
3427                           int *h_pagenumber,
3428                           int *v_pagenumber)
3429 {
3430    ELM_GENGRID_CHECK(obj);
3431    ELM_GENGRID_DATA_GET(obj, sd);
3432
3433    sd->s_iface->last_page_get(obj, h_pagenumber, v_pagenumber);
3434 }
3435
3436 EAPI void
3437 elm_gengrid_page_show(const Evas_Object *obj,
3438                       int h_pagenumber,
3439                       int v_pagenumber)
3440 {
3441    ELM_GENGRID_CHECK(obj);
3442    ELM_GENGRID_DATA_GET(obj, sd);
3443
3444    sd->s_iface->page_show((Evas_Object *)obj, h_pagenumber, v_pagenumber);
3445 }
3446
3447 EAPI void
3448 elm_gengrid_page_bring_in(const Evas_Object *obj,
3449                           int h_pagenumber,
3450                           int v_pagenumber)
3451 {
3452    ELM_GENGRID_CHECK(obj);
3453    ELM_GENGRID_DATA_GET(obj, sd);
3454
3455    sd->s_iface->page_bring_in((Evas_Object *)obj, h_pagenumber, v_pagenumber);
3456 }
3457
3458 EAPI void
3459 elm_gengrid_scroller_policy_set(Evas_Object *obj,
3460                                 Elm_Scroller_Policy policy_h,
3461                                 Elm_Scroller_Policy policy_v)
3462 {
3463    ELM_GENGRID_CHECK(obj);
3464    ELM_GENGRID_DATA_GET(obj, sd);
3465
3466    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
3467        (policy_v >= ELM_SCROLLER_POLICY_LAST))
3468      return;
3469
3470    sd->s_iface->policy_set(obj, policy_h, policy_v);
3471 }
3472
3473 EAPI void
3474 elm_gengrid_scroller_policy_get(const Evas_Object *obj,
3475                                 Elm_Scroller_Policy *policy_h,
3476                                 Elm_Scroller_Policy *policy_v)
3477 {
3478    Elm_Scroller_Policy s_policy_h, s_policy_v;
3479
3480    ELM_GENGRID_CHECK(obj);
3481    ELM_GENGRID_DATA_GET(obj, sd);
3482
3483    sd->s_iface->policy_get(obj, &s_policy_h, &s_policy_v);
3484    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
3485    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
3486 }
3487
3488 EAPI Elm_Object_Item *
3489 elm_gengrid_first_item_get(const Evas_Object *obj)
3490 {
3491    ELM_GENGRID_CHECK(obj) NULL;
3492    ELM_GENGRID_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
3493
3494    if (!sd->items) return NULL;
3495
3496    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
3497
3498    while ((it) && (it->generation < sd->generation))
3499      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3500
3501    return (Elm_Object_Item *)it;
3502 }
3503
3504 EAPI Elm_Object_Item *
3505 elm_gengrid_last_item_get(const Evas_Object *obj)
3506 {
3507    ELM_GENGRID_CHECK(obj) NULL;
3508    ELM_GENGRID_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
3509
3510    if (!sd->items) return NULL;
3511
3512    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
3513    while ((it) && (it->generation < sd->generation))
3514      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3515
3516    return (Elm_Object_Item *)it;
3517 }
3518
3519 EAPI Elm_Object_Item *
3520 elm_gengrid_item_next_get(const Elm_Object_Item *item)
3521 {
3522    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3523
3524    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3525
3526    while (it)
3527      {
3528         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3529         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
3530      }
3531
3532    return (Elm_Object_Item *)it;
3533 }
3534
3535 EAPI Elm_Object_Item *
3536 elm_gengrid_item_prev_get(const Elm_Object_Item *item)
3537 {
3538    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3539
3540    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3541
3542    while (it)
3543      {
3544         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3545         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
3546      }
3547
3548    return (Elm_Object_Item *)it;
3549 }
3550
3551 EAPI void
3552 elm_gengrid_item_show(Elm_Object_Item *item,
3553                       Elm_Gengrid_Item_Scrollto_Type type __UNUSED__)
3554 {
3555    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3556    Elm_Gengrid_Smart_Data *sd;
3557
3558    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3559    sd = GG_IT(it)->wsd;
3560
3561    if ((it->generation < sd->generation)) return;
3562
3563    sd->show_region = EINA_TRUE;
3564    sd->show_it = it;
3565
3566    if (sd->calc_job) ecore_job_del(sd->calc_job);
3567    sd->calc_job = ecore_job_add(_calc_job, sd);
3568 }
3569
3570 EAPI void
3571 elm_gengrid_item_bring_in(Elm_Object_Item *item,
3572                           Elm_Gengrid_Item_Scrollto_Type type __UNUSED__)
3573 {
3574    Elm_Gengrid_Smart_Data *sd;
3575    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3576
3577    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3578    sd = GG_IT(it)->wsd;
3579
3580    if (it->generation < sd->generation) return;
3581
3582    sd->bring_in = EINA_TRUE;
3583    sd->bring_in_it = it;
3584
3585    if (sd->calc_job) ecore_job_del(sd->calc_job);
3586    sd->calc_job = ecore_job_add(_calc_job, sd);
3587 }
3588
3589 EAPI void
3590 elm_gengrid_filled_set(Evas_Object *obj,
3591                        Eina_Bool fill)
3592 {
3593    ELM_GENGRID_CHECK(obj);
3594    ELM_GENGRID_DATA_GET(obj, sd);
3595
3596    fill = !!fill;
3597    if (sd->filled != fill)
3598      sd->filled = fill;
3599 }
3600
3601 EAPI Eina_Bool
3602 elm_gengrid_filled_get(const Evas_Object *obj)
3603 {
3604    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3605    ELM_GENGRID_DATA_GET(obj, sd);
3606
3607    return sd->filled;
3608 }
3609
3610 EAPI unsigned int
3611 elm_gengrid_items_count(const Evas_Object *obj)
3612 {
3613    ELM_GENGRID_CHECK(obj) 0;
3614    ELM_GENGRID_DATA_GET(obj, sd);
3615
3616    return sd->item_count;
3617 }
3618
3619 EAPI Elm_Gengrid_Item_Class *
3620 elm_gengrid_item_class_new(void)
3621 {
3622    Elm_Gengrid_Item_Class *itc;
3623
3624    itc = calloc(1, sizeof(Elm_Gengrid_Item_Class));
3625    if (!itc)
3626      return NULL;
3627    itc->version = CLASS_ALLOCATED;
3628    itc->refcount = 1;
3629    itc->delete_me = EINA_FALSE;
3630
3631    return itc;
3632 }
3633
3634 EAPI void
3635 elm_gengrid_item_class_free(Elm_Gengrid_Item_Class *itc)
3636 {
3637    if (!itc || (itc->version != CLASS_ALLOCATED)) return;
3638
3639    if (!itc->delete_me) itc->delete_me = EINA_TRUE;
3640    if (itc->refcount > 0) elm_gengrid_item_class_unref(itc);
3641    else
3642      {
3643         itc->version = 0;
3644         free(itc);
3645      }
3646 }
3647
3648 EAPI void
3649 elm_gengrid_item_class_ref(Elm_Gengrid_Item_Class *itc)
3650 {
3651    if (itc && (itc->version == CLASS_ALLOCATED))
3652      {
3653         itc->refcount++;
3654         if (itc->refcount == 0) itc->refcount--;
3655      }
3656 }
3657
3658 EAPI void
3659 elm_gengrid_item_class_unref(Elm_Gengrid_Item_Class *itc)
3660 {
3661    if (itc && (itc->version == CLASS_ALLOCATED))
3662      {
3663         if (itc->refcount > 0) itc->refcount--;
3664         if (itc->delete_me && (!itc->refcount))
3665           elm_gengrid_item_class_free(itc);
3666      }
3667 }
3668
3669 EAPI void
3670 elm_gengrid_select_mode_set(Evas_Object *obj,
3671                             Elm_Object_Select_Mode mode)
3672 {
3673    ELM_GENGRID_CHECK(obj);
3674    ELM_GENGRID_DATA_GET(obj, sd);
3675
3676    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
3677      return;
3678
3679    if (sd->select_mode != mode)
3680      sd->select_mode = mode;
3681 }
3682
3683 EAPI Elm_Object_Select_Mode
3684 elm_gengrid_select_mode_get(const Evas_Object *obj)
3685 {
3686    ELM_GENGRID_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
3687    ELM_GENGRID_DATA_GET(obj, sd);
3688
3689    return sd->select_mode;
3690 }
3691
3692 EAPI void
3693 elm_gengrid_highlight_mode_set(Evas_Object *obj,
3694                                Eina_Bool highlight)
3695 {
3696    ELM_GENGRID_CHECK(obj);
3697    ELM_GENGRID_DATA_GET(obj, sd);
3698
3699    sd->highlight = !!highlight;
3700 }
3701
3702 EAPI Eina_Bool
3703 elm_gengrid_highlight_mode_get(const Evas_Object *obj)
3704 {
3705    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3706    ELM_GENGRID_DATA_GET(obj, sd);
3707
3708    return sd->highlight;
3709 }
3710
3711 EAPI int
3712 elm_gengrid_item_index_get(const Elm_Object_Item *item)
3713 {
3714    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3715
3716    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, -1);
3717
3718    return it->position;
3719 }
3720
3721 EAPI void
3722 elm_gengrid_item_select_mode_set(Elm_Object_Item *item,
3723                                  Elm_Object_Select_Mode mode)
3724 {
3725    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3726
3727    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3728
3729    if (it->generation < GG_IT(it)->wsd->generation) return;
3730    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
3731      return;
3732
3733    if (it->select_mode != mode)
3734      it->select_mode = mode;
3735
3736    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3737      elm_gengrid_item_update(item);
3738 }
3739
3740 EAPI Elm_Object_Select_Mode
3741 elm_gengrid_item_select_mode_get(const Elm_Object_Item *item)
3742 {
3743    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3744
3745    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
3746
3747    return it->select_mode;
3748 }
3749
3750 #if GENGRID_FX_SUPPORT
3751 EAPI void
3752 elm_gengrid_fx_mode_set(Evas_Object *obj, Eina_Bool mode)
3753 {
3754    ELM_GENGRID_CHECK(obj);
3755    ELM_GENGRID_DATA_GET(obj, sd);
3756
3757    sd->fx_mode = mode;
3758 }
3759
3760 EAPI Eina_Bool
3761 elm_gengrid_fx_mode_get(const Evas_Object *obj)
3762 {
3763    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3764    ELM_GENGRID_DATA_GET(obj, sd);
3765
3766    return sd->fx_mode;
3767 }
3768
3769 static Proxy_Item *
3770 _elm_gengrid_proxy_item_new(const Elm_Object_Item *item)
3771 {
3772    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3773    if ((!it) || (!it->item)) return EINA_FALSE;
3774    int w, h;
3775
3776    Proxy_Item *pi = NULL;
3777    pi = calloc(1, sizeof(Proxy_Item));
3778    if (!pi) return NULL;
3779
3780    pi->proxy = evas_object_image_filled_add
3781       (evas_object_evas_get(ELM_WIDGET_DATA(GG_IT(it)->wsd)->obj));
3782    if (!pi->proxy) return EINA_FALSE;
3783    evas_object_clip_set(pi->proxy, evas_object_clip_get(GG_IT(it)->wsd->pan_obj));
3784    evas_object_smart_member_add(pi->proxy, GG_IT(it)->wsd->pan_obj);
3785    evas_object_hide(pi->proxy);
3786    evas_object_image_source_set(pi->proxy, VIEW(it));
3787
3788    GG_IT(it)->has_proxy_it = EINA_TRUE;
3789    pi->it = it;
3790    pi->num = it->item->num;
3791    pi->x = it->item->scrl_x;
3792    pi->y = it->item->scrl_y;
3793    pi->w = it->item->w;
3794    pi->h = it->item->h;
3795
3796    evas_object_geometry_get(VIEW(it), NULL, NULL, &w, &h);
3797
3798    if (w <= 0 || h <= 0)
3799      {
3800         evas_object_size_hint_min_get(VIEW(it), &w, &h);
3801         evas_object_size_hint_min_set(pi->proxy, w, h);
3802      }
3803    else evas_object_resize(pi->proxy, w, h);
3804
3805    return pi;
3806 }
3807
3808 static Eina_Bool
3809 _elm_gengrid_fx_capture(Evas_Object *obj, int level)
3810 {
3811    ELM_GENGRID_DATA_GET(obj, sd);
3812
3813    Elm_Gen_Item *it;
3814    Proxy_Item *pi;
3815    Evas_Coord ox, oy, ow, oh;
3816
3817    if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
3818    if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
3819    if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
3820
3821    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3822
3823    if (!level)
3824      {
3825         sd->fx_first_captured = EINA_TRUE;
3826         EINA_LIST_FREE(sd->capture_before_items, pi)
3827           {
3828              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
3829              if (pi->proxy) evas_object_del(pi->proxy);
3830              free(pi);
3831           }
3832      }
3833    else
3834      {
3835         EINA_LIST_FREE(sd->capture_after_items, pi)
3836           {
3837              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
3838              if (pi->proxy) evas_object_del(pi->proxy);
3839              free(pi);
3840           }
3841      }
3842    EINA_INLIST_FOREACH(sd->items, it)
3843      {
3844         if (it->realized)
3845           {
3846              pi = _elm_gengrid_proxy_item_new((Elm_Object_Item *)it);
3847              if (!pi) continue;
3848              if (!level)
3849                sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
3850              else
3851                sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
3852           }
3853      }
3854    return EINA_TRUE;
3855 }
3856
3857 static Elm_Gen_FX_Item *
3858 _elm_gengrid_fx_item_find(const Elm_Object_Item *item)
3859 {
3860    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3861    if (!it) return EINA_FALSE;
3862
3863    Elm_Gengrid_Smart_Data *sd = GG_IT(it)->wsd;
3864    if (!sd) return NULL;
3865
3866    Elm_Gen_FX_Item *fi = NULL;
3867    Eina_List *l;
3868
3869    EINA_LIST_FOREACH(sd->fx_items, l, fi)
3870      {
3871         if (fi->it == it) return fi;
3872      }
3873    return NULL;
3874 }
3875
3876 static Elm_Gen_FX_Item *
3877 _elm_gengrid_fx_item_new(const Proxy_Item *pi)
3878 {
3879    if ((!pi) || (!pi->it)) return NULL;
3880
3881    Elm_Gen_FX_Item *fi = NULL;
3882    fi = calloc(1, sizeof(Elm_Gen_FX_Item));
3883    if (!fi) return NULL;
3884
3885    fi->it = pi->it;
3886    GG_IT(fi->it)->fi = fi;
3887    fi->proxy = pi->proxy;
3888    fi->num = pi->num;
3889    fi->from.x = fi->to.x = pi->x;
3890    fi->from.y = fi->to.y = pi->y;
3891    fi->from.w = fi->to.w = pi->w;
3892    fi->from.h = fi->to.h = pi->h;
3893    fi->update = EINA_FALSE;
3894
3895    return fi;
3896 }
3897
3898 EAPI void
3899 _elm_gengrid_fx_items_make(Evas_Object *obj)
3900 {
3901    ELM_GENGRID_CHECK(obj);
3902    ELM_GENGRID_DATA_GET(obj, sd);
3903
3904    Elm_Gen_FX_Item *fi;
3905    Proxy_Item *pi;
3906    Eina_List *l;
3907    Evas_Coord ox, oy, ow, oh;
3908
3909    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3910
3911    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
3912      {
3913         fi = _elm_gengrid_fx_item_new(pi);
3914         if (fi) sd->fx_items = eina_list_append(sd->fx_items, fi);
3915      }
3916
3917    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
3918      {
3919         fi = _elm_gengrid_fx_item_find((Elm_Object_Item *)pi->it);
3920
3921         if (fi)
3922           {
3923              fi->type = ELM_GEN_ITEM_FX_TYPE_SAME;
3924              fi->update = EINA_TRUE;
3925              fi->to.x = pi->x;
3926              fi->to.y = pi->y;
3927              fi->to.w = pi->w;
3928              fi->to.h = pi->h;
3929           }
3930         else
3931           {
3932              fi = _elm_gengrid_fx_item_new(pi);
3933              if (fi)
3934                {
3935                   fi->type = ELM_GEN_ITEM_FX_TYPE_ADD;
3936                   fi->update = EINA_TRUE;
3937                   sd->fx_items = eina_list_append(sd->fx_items, fi);
3938                }
3939           }
3940      }
3941
3942    EINA_LIST_FOREACH(sd->fx_items, l, fi)
3943      {
3944         if (!fi->update)
3945           {
3946              fi->type = ELM_GEN_ITEM_FX_TYPE_DEL;
3947              fi->update = EINA_TRUE;
3948           }
3949      }
3950 }
3951
3952 static void
3953 _item_fx_op(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__, double progress __UNUSED__)
3954 {
3955    Elm_Gen_FX_Item *fi = data;
3956    Elm_Gengrid_Smart_Data *sd = GG_IT(fi->it)->wsd;
3957    if (fi->from.y == fi->to.y) evas_object_raise(fi->proxy);
3958    evas_object_raise(sd->alpha_bg);
3959    return;
3960 }
3961
3962
3963 static void
3964 _item_fx_done(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__)
3965 {
3966    Elm_Gen_FX_Item *fx_done_it = data;
3967    Elm_Gengrid_Smart_Data *sd = GG_IT(fx_done_it->it)->wsd;
3968
3969    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
3970
3971    evas_object_image_source_visible_set(fx_done_it->proxy, EINA_TRUE);
3972    evas_object_lower(fx_done_it->proxy);
3973
3974    evas_object_move(VIEW(fx_done_it->it), fx_done_it->to.x, fx_done_it->to.y);
3975    GG_IT(fx_done_it->it)->has_proxy_it = EINA_FALSE;
3976
3977    evas_object_clip_unset(fx_done_it->proxy);
3978 }
3979
3980 static void
3981 _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
3982 {
3983    Elm_Gen_FX_Item *fx_done_it = data;
3984    Elm_Gen_Item *it = NULL;
3985    Proxy_Item *pi = NULL;
3986    Eina_List *l;
3987    Elm_Gengrid_Smart_Data *sd = GG_IT(fx_done_it->it)->wsd;
3988
3989    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
3990
3991    sd->fx_items = eina_list_remove(sd->fx_items, fx_done_it);
3992    free(fx_done_it);
3993
3994    if (!eina_list_count(sd->fx_items))
3995      {
3996         EINA_LIST_FREE (sd->pending_unrealized_items, it)
3997           {
3998              GG_IT(it)->has_proxy_it = EINA_FALSE;
3999              _elm_gengrid_item_unrealize(it, EINA_FALSE);
4000           }
4001
4002         EINA_LIST_FREE (sd->pending_del_items, it)
4003           {
4004              _item_del(it);
4005              _elm_widget_item_free((Elm_Widget_Item *)it);
4006           }
4007         EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
4008            evas_object_hide(pi->proxy);
4009         EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
4010            evas_object_hide(pi->proxy);
4011
4012         sd->fx_playing = EINA_FALSE;
4013         sd->fx_first_captured = EINA_FALSE;
4014         evas_object_hide(sd->alpha_bg);
4015
4016         sd->pan_changed = EINA_TRUE;
4017         evas_object_smart_changed(sd->pan_obj);
4018      }
4019 }
4020
4021 static Evas_Object *
4022 _tray_alpha_bg_create(const Evas_Object *obj)
4023 {
4024    Evas_Object *bg = NULL;
4025    Evas_Coord ox, oy, ow, oh;
4026
4027    ELM_GENGRID_CHECK(obj) NULL;
4028    ELM_GENGRID_DATA_GET(obj, sd);
4029
4030    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4031    bg = evas_object_rectangle_add
4032       (evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4033    evas_object_color_set(bg, 0, 0, 0, 0);
4034    evas_object_resize(bg, ow, oh);
4035    evas_object_move(bg, ox, oy);
4036
4037    return bg;
4038 }
4039
4040 static void
4041 _elm_gengrid_fx_play(Evas_Object *obj)
4042 {
4043    ELM_GENGRID_CHECK(obj);
4044    ELM_GENGRID_DATA_GET(obj, sd);
4045
4046    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
4047    Elm_Gen_FX_Item *fi;
4048    Eina_List *l;
4049
4050    if (!sd->fx_mode) return;
4051
4052    EINA_LIST_FREE(sd->fx_items, fi)
4053      {
4054         if (fi->trans) elm_transit_del(fi->trans);
4055         free(fi);
4056      }
4057
4058    _elm_gengrid_fx_items_make(obj);
4059    if (!eina_list_count(sd->fx_items)) return;
4060    sd->fx_playing = EINA_TRUE;
4061
4062    if (!sd->alpha_bg) sd->alpha_bg = _tray_alpha_bg_create(obj);
4063    evas_object_show(sd->alpha_bg);
4064
4065    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4066    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
4067
4068    EINA_LIST_FOREACH(sd->fx_items, l, fi)
4069      {
4070         if (!fi->proxy) continue;
4071
4072         if ((fi->from.y <= oy) || (fi->from.y + fi->from.h >= oy + oh))
4073           {
4074              evas_object_move(VIEW(fi->it), fi->to.x, fi->to.y);
4075           }
4076         else if ((fi->to.y <= oy) || (fi->to.y + fi->to.h >= oy + oh))
4077           {
4078              evas_object_move(VIEW(fi->it), fi->from.x, fi->from.y);
4079           }
4080
4081         evas_object_resize(fi->proxy, fi->to.w, fi->to.h);
4082         evas_object_show(fi->proxy);
4083
4084         fi->trans = elm_transit_add();
4085         elm_transit_object_add(fi->trans, fi->proxy);
4086
4087         evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
4088         elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
4089
4090         if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME)
4091           {
4092              evas_object_raise(fi->proxy);
4093              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4094           }
4095
4096         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
4097           {
4098              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4099              elm_transit_effect_color_add(fi->trans, 0, 0, 0, 0, 255, 255, 255, 255);
4100              elm_transit_effect_zoom_add(fi->trans, 0.5, 1.0);
4101           }
4102         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
4103           {
4104              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4105              elm_transit_effect_color_add(fi->trans, 255, 255, 255, 255, 0, 0, 0, 0);
4106              elm_transit_effect_zoom_add(fi->trans, 1.0, 0.5);
4107           }
4108         elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
4109         elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
4110
4111         elm_transit_duration_set(fi->trans, FX_MOVE_TIME);
4112         elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
4113         elm_transit_go(fi->trans);
4114      }
4115 }
4116 #endif