Log:
[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    evas_object_geometry_get(wsd->pan_obj, &ox, &oy, &vw, &vh);
1010
1011    /* Preload rows/columns at each side of the Gengrid */
1012    cvx = ox - PRELOAD * wsd->item_width;
1013    cvy = oy - PRELOAD * wsd->item_height;
1014    cvw = vw + 2 * PRELOAD * wsd->item_width;
1015    cvh = vh + 2 * PRELOAD * wsd->item_height;
1016
1017    alignh = 0;
1018    alignw = 0;
1019
1020    items_count = wsd->item_count -
1021      eina_list_count(wsd->group_items) + wsd->items_lost;
1022    if (wsd->horizontal)
1023      {
1024         int columns, items_visible = 0, items_row;
1025
1026         if (wsd->item_height > 0)
1027           items_visible = vh / wsd->item_height;
1028         if (items_visible < 1)
1029           items_visible = 1;
1030
1031         columns = items_count / items_visible;
1032         if (items_count % items_visible)
1033           columns++;
1034
1035         tcw = (wsd->item_width * columns) + (wsd->group_item_width *
1036                                              eina_list_count(wsd->group_items));
1037         alignw = (vw - tcw) * wsd->align_x;
1038
1039         items_row = items_visible;
1040         if ((unsigned int)items_row > wsd->item_count)
1041           items_row = wsd->item_count;
1042         if (wsd->filled && (unsigned int)wsd->nmax
1043             > (unsigned int)wsd->item_count)
1044           tch = wsd->nmax * wsd->item_height;
1045         else
1046           tch = items_row * wsd->item_height;
1047         alignh = (vh - tch) * wsd->align_y;
1048      }
1049    else
1050      {
1051         unsigned int rows, items_visible = 0, items_col;
1052
1053         if (wsd->item_width > 0)
1054           items_visible = vw / wsd->item_width;
1055         if (items_visible < 1)
1056           items_visible = 1;
1057
1058         rows = items_count / items_visible;
1059         if (items_count % items_visible)
1060           rows++;
1061
1062         tch = (wsd->item_height * rows) + (wsd->group_item_height *
1063                                            eina_list_count(wsd->group_items));
1064         alignh = (vh - tch) * wsd->align_y;
1065
1066         items_col = items_visible;
1067         if (items_col > wsd->item_count)
1068           items_col = wsd->item_count;
1069         if (wsd->filled && (unsigned int)wsd->nmax
1070             > (unsigned int)wsd->item_count)
1071           tcw = wsd->nmax * wsd->item_width;
1072         else
1073           tcw = items_col * wsd->item_width;
1074         alignw = (vw - tcw) * wsd->align_x;
1075      }
1076
1077    if (it->group)
1078      {
1079         if (wsd->horizontal)
1080           {
1081              x = (((cx - item->prev_group) * wsd->item_width)
1082                   + (item->prev_group * wsd->group_item_width)) -
1083                wsd->pan_x + ox + alignw;
1084              y = oy;
1085              iw = wsd->group_item_width;
1086              ih = vh;
1087           }
1088         else
1089           {
1090              x = ox;
1091              y = (((cy - item->prev_group) * wsd->item_height)
1092                   + (item->prev_group * wsd->group_item_height))
1093                - wsd->pan_y + oy + alignh;
1094              iw = vw;
1095              ih = wsd->group_item_height;
1096           }
1097         item->gx = x;
1098         item->gy = y;
1099      }
1100    else
1101      {
1102         if (wsd->horizontal)
1103           {
1104              x = (((cx - item->prev_group) * wsd->item_width)
1105                   + (item->prev_group * wsd->group_item_width)) -
1106                wsd->pan_x + ox + alignw;
1107              y = (cy * wsd->item_height) - wsd->pan_y + oy + alignh;
1108           }
1109         else
1110           {
1111              x = (cx * wsd->item_width) - wsd->pan_x + ox + alignw;
1112              y = (((cy - item->prev_group)
1113                    * wsd->item_height) + (item->prev_group *
1114                                           wsd->group_item_height)) -
1115                wsd->pan_y + oy + alignh;
1116           }
1117         if (elm_widget_mirrored_get(WIDGET(it))) /* Switch items side
1118                                                   * and componsate for
1119                                                   * pan_x when in RTL
1120                                                   * mode */
1121           {
1122              evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
1123              x = ww - x - wsd->item_width - wsd->pan_x - wsd->pan_x;
1124           }
1125         iw = wsd->item_width;
1126         ih = wsd->item_height;
1127      }
1128
1129    was_realized = it->realized;
1130    if (ELM_RECTS_INTERSECT(x, y, iw, ih, cvx, cvy, cvw, cvh))
1131      {
1132         _item_realize(it);
1133         if (!was_realized)
1134           evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1135         if (it->parent)
1136           {
1137              if (wsd->horizontal)
1138                {
1139                   if (it->parent->item->gx < ox)
1140                     {
1141                        it->parent->item->gx = x + wsd->item_width -
1142                          wsd->group_item_width;
1143                        if (it->parent->item->gx > ox)
1144                          it->parent->item->gx = ox;
1145                     }
1146                   it->parent->item->group_realized = EINA_TRUE;
1147                }
1148              else
1149                {
1150                   if (it->parent->item->gy < oy)
1151                     {
1152                        it->parent->item->gy = y + wsd->item_height -
1153                          wsd->group_item_height;
1154                        if (it->parent->item->gy > oy)
1155                          it->parent->item->gy = oy;
1156                     }
1157                   it->parent->item->group_realized = EINA_TRUE;
1158                }
1159           }
1160         if (wsd->reorder_mode)
1161           {
1162              if (wsd->reorder_it)
1163                {
1164                   if (item->moving) return;
1165
1166                   if (!wsd->move_effect_enabled)
1167                     {
1168                        item->ox = x;
1169                        item->oy = y;
1170                     }
1171                   if (wsd->reorder_it == it)
1172                     {
1173                        evas_object_move(VIEW(it), wsd->reorder_item_x,
1174                                         wsd->reorder_item_y);
1175                        evas_object_resize(VIEW(it), iw, ih);
1176                        return;
1177                     }
1178                   else
1179                     {
1180                        Evas_Coord nx, ny, nw, nh;
1181
1182                        if (wsd->move_effect_enabled)
1183                          {
1184                             if ((item->ox != x) || (item->oy != y))
1185                               if (((wsd->old_pan_x == wsd->pan_x)
1186                                    && (wsd->old_pan_y == wsd->pan_y))
1187                                   || ((wsd->old_pan_x != wsd->pan_x) &&
1188                                       !(item->ox - wsd->pan_x
1189                                         + wsd->old_pan_x == x)) ||
1190                                   ((wsd->old_pan_y != wsd->pan_y) &&
1191                                    !(item->oy - wsd->pan_y +
1192                                      wsd->old_pan_y == y)))
1193                                 {
1194                                    item->tx = x;
1195                                    item->ty = y;
1196                                    item->rx = item->ox;
1197                                    item->ry = item->oy;
1198                                    item->moving = EINA_TRUE;
1199                                    item->moving_effect_start_time =
1200                                      ecore_loop_time_get();
1201                                    item->item_reorder_move_animator =
1202                                      ecore_animator_add
1203                                        (_reorder_item_move_animator_cb, it);
1204                                    return;
1205                                 }
1206                          }
1207
1208                        /* need fix here */
1209                        if (it->group)
1210                          {
1211                             if (wsd->horizontal)
1212                               {
1213                                  nx = x + (wsd->group_item_width / 2);
1214                                  ny = y;
1215                                  nw = 1;
1216                                  nh = vh;
1217                               }
1218                             else
1219                               {
1220                                  nx = x;
1221                                  ny = y + (wsd->group_item_height / 2);
1222                                  nw = vw;
1223                                  nh = 1;
1224                               }
1225                          }
1226                        else
1227                          {
1228                             nx = x + (wsd->item_width / 2);
1229                             ny = y + (wsd->item_height / 2);
1230                             nw = 1;
1231                             nh = 1;
1232                          }
1233
1234                        if (ELM_RECTS_INTERSECT
1235                              (wsd->reorder_item_x, wsd->reorder_item_y,
1236                              wsd->item_width, wsd->item_height,
1237                              nx, ny, nw, nh))
1238                          {
1239                             if (wsd->horizontal)
1240                               {
1241                                  if ((wsd->nmax * wsd->reorder_it->x +
1242                                       wsd->reorder_it->y) >
1243                                      (wsd->nmax * it->x + it->y))
1244                                    reorder_item_move_forward = EINA_TRUE;
1245                               }
1246                             else
1247                               {
1248                                  if ((wsd->nmax * wsd->reorder_it->y +
1249                                       wsd->reorder_it->x) >
1250                                      (wsd->nmax * it->y + it->x))
1251                                    reorder_item_move_forward = EINA_TRUE;
1252                               }
1253
1254                             wsd->items = eina_inlist_remove
1255                                 (wsd->items,
1256                                 EINA_INLIST_GET(wsd->reorder_it));
1257                             if (reorder_item_move_forward)
1258                               wsd->items = eina_inlist_prepend_relative
1259                                   (wsd->items,
1260                                   EINA_INLIST_GET(wsd->reorder_it),
1261                                   EINA_INLIST_GET(it));
1262                             else
1263                               wsd->items = eina_inlist_append_relative
1264                                   (wsd->items,
1265                                   EINA_INLIST_GET(wsd->reorder_it),
1266                                   EINA_INLIST_GET(it));
1267
1268                             wsd->reorder_item_changed = EINA_TRUE;
1269                             wsd->move_effect_enabled = EINA_TRUE;
1270                             if (wsd->calc_job)
1271                               ecore_job_del(wsd->calc_job);
1272                             wsd->calc_job =
1273                               ecore_job_add(_calc_job, wsd);
1274
1275                             return;
1276                          }
1277                     }
1278                }
1279              else if (item->item_reorder_move_animator)
1280                {
1281                   ecore_animator_del
1282                     (item->item_reorder_move_animator);
1283                   item->item_reorder_move_animator = NULL;
1284                   item->moving = EINA_FALSE;
1285                }
1286           }
1287         if (!it->group)
1288           {
1289
1290 #if GENGRID_FX_SUPPORT
1291              GG_IT(it)->scrl_x = x;
1292              GG_IT(it)->scrl_y = y;
1293              GG_IT(it)->w = iw;
1294              GG_IT(it)->h = ih;
1295 #endif
1296              evas_object_move(VIEW(it), x, y);
1297              evas_object_resize(VIEW(it), iw, ih);
1298           }
1299         else
1300           item->group_realized = EINA_TRUE;
1301      }
1302    else
1303      {
1304         if (!it->group)
1305           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1306         else
1307           item->group_realized = EINA_FALSE;
1308      }
1309 }
1310
1311 static void
1312 _group_item_place(Elm_Gengrid_Pan_Smart_Data *psd)
1313 {
1314    Evas_Coord iw, ih, vw, vh;
1315    Eina_Bool was_realized;
1316    Elm_Gen_Item *it;
1317    Eina_List *l;
1318
1319    evas_object_geometry_get(psd->wsd->pan_obj, NULL, NULL, &vw, &vh);
1320    if (psd->wsd->horizontal)
1321      {
1322         iw = psd->wsd->group_item_width;
1323         ih = vh;
1324      }
1325    else
1326      {
1327         iw = vw;
1328         ih = psd->wsd->group_item_height;
1329      }
1330    EINA_LIST_FOREACH(psd->wsd->group_items, l, it)
1331      {
1332         was_realized = it->realized;
1333         if (GG_IT(it)->group_realized)
1334           {
1335              _item_realize(it);
1336              if (!was_realized)
1337                evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1338              evas_object_move
1339                (VIEW(it), GG_IT(it)->gx,
1340                GG_IT(it)->gy);
1341              evas_object_resize(VIEW(it), iw, ih);
1342              evas_object_raise(VIEW(it));
1343           }
1344         else
1345           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1346      }
1347 }
1348
1349 static void
1350 _elm_gengrid_pan_smart_calculate(Evas_Object *obj)
1351 {
1352    Evas_Coord cx = 0, cy = 0;
1353    Elm_Gen_Item *it;
1354
1355    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1356
1357 #if GENGRID_FX_SUPPORT
1358    if (psd->wsd->fx_playing) return;
1359 #endif
1360
1361    if (!psd->wsd->nmax) return;
1362
1363    psd->wsd->reorder_item_changed = EINA_FALSE;
1364
1365    EINA_INLIST_FOREACH(psd->wsd->items, it)
1366      {
1367         if (it->group)
1368           {
1369              if (psd->wsd->horizontal)
1370                {
1371                   if (cy)
1372                     {
1373                        cx++;
1374                        cy = 0;
1375                     }
1376                }
1377              else
1378                {
1379                   if (cx)
1380                     {
1381                        cx = 0;
1382                        cy++;
1383                     }
1384                }
1385           }
1386         _item_place(it, cx, cy);
1387         if (psd->wsd->reorder_item_changed) return;
1388         if (it->group)
1389           {
1390              if (psd->wsd->horizontal)
1391                {
1392                   cx++;
1393                   cy = 0;
1394                }
1395              else
1396                {
1397                   cx = 0;
1398                   cy++;
1399                }
1400           }
1401         else
1402           {
1403              if (psd->wsd->horizontal)
1404                {
1405                   cy = (cy + 1) % psd->wsd->nmax;
1406                   if (!cy) cx++;
1407                }
1408              else
1409                {
1410                   cx = (cx + 1) % psd->wsd->nmax;
1411                   if (!cx) cy++;
1412                }
1413           }
1414      }
1415    _group_item_place(psd);
1416
1417    if ((psd->wsd->reorder_mode) && (psd->wsd->reorder_it))
1418      {
1419         if (!psd->wsd->reorder_item_changed)
1420           {
1421              psd->wsd->old_pan_x = psd->wsd->pan_x;
1422              psd->wsd->old_pan_y = psd->wsd->pan_y;
1423           }
1424         psd->wsd->move_effect_enabled = EINA_FALSE;
1425      }
1426    evas_object_smart_callback_call
1427      (ELM_WIDGET_DATA(psd->wsd)->obj, SIG_CHANGED, NULL);
1428    if ((psd->wsd->show_region || psd->wsd->bring_in))
1429      _item_show_region(psd->wsd);
1430
1431 #if GENGRID_FX_SUPPORT
1432    psd->wsd->rendered = EINA_TRUE;
1433    if (psd->wsd->fx_mode)
1434      {
1435         if (_elm_gengrid_fx_capture(ELM_WIDGET_DATA(psd->wsd)->obj, 1))
1436           _elm_gengrid_fx_play(ELM_WIDGET_DATA(psd->wsd)->obj);
1437      }
1438 #endif
1439 }
1440
1441 static void
1442 _elm_gengrid_pan_smart_pos_set(Evas_Object *obj,
1443                                Evas_Coord x,
1444                                Evas_Coord y)
1445 {
1446    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1447
1448    if ((x == psd->wsd->pan_x) && (y == psd->wsd->pan_y)) return;
1449    psd->wsd->pan_x = x;
1450    psd->wsd->pan_y = y;
1451    evas_object_smart_changed(obj);
1452 }
1453
1454 static void
1455 _elm_gengrid_pan_smart_pos_get(const Evas_Object *obj,
1456                                Evas_Coord *x,
1457                                Evas_Coord *y)
1458 {
1459    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1460
1461    if (x) *x = psd->wsd->pan_x;
1462    if (y) *y = psd->wsd->pan_y;
1463 }
1464
1465 static void
1466 _elm_gengrid_pan_smart_content_size_get(const Evas_Object *obj,
1467                                         Evas_Coord *w,
1468                                         Evas_Coord *h)
1469 {
1470    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1471
1472    if (w) *w = psd->wsd->minw;
1473    if (h) *h = psd->wsd->minh;
1474 }
1475
1476 static void
1477 _elm_gengrid_pan_smart_pos_max_get(const Evas_Object *obj,
1478                                    Evas_Coord *x,
1479                                    Evas_Coord *y)
1480 {
1481    Evas_Coord ow, oh;
1482
1483    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1484
1485    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1486    if (x)
1487      *x = (ow < psd->wsd->minw) ? psd->wsd->minw - ow : 0;
1488    if (y)
1489      *y = (oh < psd->wsd->minh) ? psd->wsd->minh - oh : 0;
1490 }
1491
1492 static void
1493 _elm_gengrid_pan_smart_pos_min_get(const Evas_Object *obj,
1494                                    Evas_Coord *x,
1495                                    Evas_Coord *y)
1496 {
1497    Evas_Coord mx = 0, my = 0;
1498
1499    ELM_GENGRID_PAN_DATA_GET(obj, psd);
1500
1501    _elm_gengrid_pan_smart_pos_max_get(obj, &mx, &my);
1502    if (x)
1503      *x = -mx * psd->wsd->align_x;
1504    if (y)
1505      *y = -my * psd->wsd->align_y;
1506 }
1507
1508 static void
1509 _elm_gengrid_pan_smart_set_user(Elm_Gengrid_Pan_Smart_Class *sc)
1510 {
1511    ELM_PAN_CLASS(sc)->base.add = _elm_gengrid_pan_smart_add;
1512    ELM_PAN_CLASS(sc)->base.move = _elm_gengrid_pan_smart_move;
1513    ELM_PAN_CLASS(sc)->base.resize = _elm_gengrid_pan_smart_resize;
1514    ELM_PAN_CLASS(sc)->base.calculate = _elm_gengrid_pan_smart_calculate;
1515
1516    ELM_PAN_CLASS(sc)->pos_set = _elm_gengrid_pan_smart_pos_set;
1517    ELM_PAN_CLASS(sc)->pos_get = _elm_gengrid_pan_smart_pos_get;
1518    ELM_PAN_CLASS(sc)->pos_max_get = _elm_gengrid_pan_smart_pos_max_get;
1519    ELM_PAN_CLASS(sc)->pos_min_get = _elm_gengrid_pan_smart_pos_min_get;
1520    ELM_PAN_CLASS(sc)->content_size_get =
1521      _elm_gengrid_pan_smart_content_size_get;
1522
1523 }
1524
1525 static Eina_Bool
1526 _item_multi_select_left(Elm_Gengrid_Smart_Data *sd)
1527 {
1528    Elm_Object_Item *prev;
1529
1530    if (!sd->selected) return EINA_FALSE;
1531
1532    prev = elm_gengrid_item_prev_get(sd->last_selected_item);
1533    if (!prev) return EINA_TRUE;
1534
1535    if (elm_gengrid_item_selected_get(prev))
1536      {
1537         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
1538         sd->last_selected_item = prev;
1539         elm_gengrid_item_show
1540           (sd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
1541      }
1542    else
1543      {
1544         elm_gengrid_item_selected_set(prev, EINA_TRUE);
1545         elm_gengrid_item_show(prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1546      }
1547
1548    return EINA_TRUE;
1549 }
1550
1551 static Eina_Bool
1552 _item_multi_select_right(Elm_Gengrid_Smart_Data *sd)
1553 {
1554    Elm_Object_Item *next;
1555
1556    if (!sd->selected) return EINA_FALSE;
1557
1558    next = elm_gengrid_item_next_get(sd->last_selected_item);
1559    if (!next) return EINA_TRUE;
1560
1561    if (elm_gengrid_item_selected_get(next))
1562      {
1563         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
1564         sd->last_selected_item = next;
1565         elm_gengrid_item_show
1566           (sd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
1567      }
1568    else
1569      {
1570         elm_gengrid_item_selected_set(next, EINA_TRUE);
1571         elm_gengrid_item_show(next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1572      }
1573
1574    return EINA_TRUE;
1575 }
1576
1577 static Eina_Bool
1578 _item_multi_select_up(Elm_Gengrid_Smart_Data *sd)
1579 {
1580    unsigned int i;
1581    Eina_Bool r = EINA_TRUE;
1582
1583    if (!sd->selected) return EINA_FALSE;
1584
1585    for (i = 0; (r) && (i < sd->nmax); i++)
1586      r &= _item_multi_select_left(sd);
1587
1588    return r;
1589 }
1590
1591 static Eina_Bool
1592 _item_multi_select_down(Elm_Gengrid_Smart_Data *sd)
1593 {
1594    unsigned int i;
1595    Eina_Bool r = EINA_TRUE;
1596
1597    if (!sd->selected) return EINA_FALSE;
1598
1599    for (i = 0; (r) && (i < sd->nmax); i++)
1600      r &= _item_multi_select_right(sd);
1601
1602    return r;
1603 }
1604
1605 static Eina_Bool
1606 _all_items_deselect(Elm_Gengrid_Smart_Data *sd)
1607 {
1608    if (!sd->selected) return EINA_FALSE;
1609
1610    while (sd->selected)
1611      elm_gengrid_item_selected_set
1612        ((Elm_Object_Item *)sd->selected->data, EINA_FALSE);
1613
1614    return EINA_TRUE;
1615 }
1616
1617 static Eina_Bool
1618 _item_single_select_up(Elm_Gengrid_Smart_Data *sd)
1619 {
1620    unsigned int i;
1621    Elm_Gen_Item *prev;
1622
1623    if (!sd->selected)
1624      {
1625         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
1626         while ((prev) && (prev->generation < sd->generation))
1627           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
1628         elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1629         elm_gengrid_item_show
1630           ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1631         return EINA_TRUE;
1632      }
1633    else
1634      prev = (Elm_Gen_Item *)elm_gengrid_item_prev_get(sd->last_selected_item);
1635
1636    if (!prev) return EINA_FALSE;
1637
1638    for (i = 1; i < sd->nmax; i++)
1639      {
1640         Elm_Object_Item *tmp =
1641           elm_gengrid_item_prev_get((Elm_Object_Item *)prev);
1642         if (!tmp) return EINA_FALSE;
1643         prev = (Elm_Gen_Item *)tmp;
1644      }
1645
1646    _all_items_deselect(sd);
1647
1648    elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1649    elm_gengrid_item_show
1650      ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1651    return EINA_TRUE;
1652 }
1653
1654 static Eina_Bool
1655 _item_single_select_down(Elm_Gengrid_Smart_Data *sd)
1656 {
1657    unsigned int i;
1658    Elm_Gen_Item *next;
1659
1660    if (!sd->selected)
1661      {
1662         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1663         while ((next) && (next->generation < sd->generation))
1664           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
1665         elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1666         elm_gengrid_item_show
1667           ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1668         return EINA_TRUE;
1669      }
1670    else
1671      next = (Elm_Gen_Item *)elm_gengrid_item_next_get(sd->last_selected_item);
1672
1673    if (!next) return EINA_FALSE;
1674
1675    for (i = 1; i < sd->nmax; i++)
1676      {
1677         Elm_Object_Item *tmp =
1678           elm_gengrid_item_next_get((Elm_Object_Item *)next);
1679         if (!tmp) return EINA_FALSE;
1680         next = (Elm_Gen_Item *)tmp;
1681      }
1682
1683    _all_items_deselect(sd);
1684
1685    elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1686    elm_gengrid_item_show
1687      ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1688
1689    return EINA_TRUE;
1690 }
1691
1692 static Eina_Bool
1693 _item_single_select_left(Elm_Gengrid_Smart_Data *sd)
1694 {
1695    Elm_Gen_Item *prev;
1696
1697    if (!sd->selected)
1698      {
1699         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
1700         while ((prev) && (prev->generation < sd->generation))
1701           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
1702      }
1703    else
1704      prev = (Elm_Gen_Item *)elm_gengrid_item_prev_get(sd->last_selected_item);
1705
1706    if (!prev) return EINA_FALSE;
1707
1708    _all_items_deselect(sd);
1709
1710    elm_gengrid_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
1711    elm_gengrid_item_show
1712      ((Elm_Object_Item *)prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
1713
1714    return EINA_TRUE;
1715 }
1716
1717 static Eina_Bool
1718 _item_single_select_right(Elm_Gengrid_Smart_Data *sd)
1719 {
1720    Elm_Gen_Item *next;
1721
1722    if (!sd->selected)
1723      {
1724         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1725         while ((next) && (next->generation < sd->generation))
1726           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
1727      }
1728    else
1729      next = (Elm_Gen_Item *)elm_gengrid_item_next_get(sd->last_selected_item);
1730
1731    if (!next) return EINA_FALSE;
1732
1733    _all_items_deselect(sd);
1734
1735    elm_gengrid_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
1736    elm_gengrid_item_show
1737      ((Elm_Object_Item *)next, ELM_GENGRID_ITEM_SCROLLTO_IN);
1738
1739    return EINA_TRUE;
1740 }
1741
1742 static Eina_Bool
1743 _elm_gengrid_smart_event(Evas_Object *obj,
1744                          Evas_Object *src __UNUSED__,
1745                          Evas_Callback_Type type,
1746                          void *event_info)
1747 {
1748    Evas_Coord x = 0;
1749    Evas_Coord y = 0;
1750    Evas_Coord v_w = 0;
1751    Evas_Coord v_h = 0;
1752    Evas_Coord step_x = 0;
1753    Evas_Coord step_y = 0;
1754    Evas_Coord page_x = 0;
1755    Evas_Coord page_y = 0;
1756    Elm_Object_Item *it = NULL;
1757    Evas_Event_Key_Down *ev = event_info;
1758
1759    ELM_GENGRID_DATA_GET(obj, sd);
1760
1761    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1762    if (!sd->items) return EINA_FALSE;
1763    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1764    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1765
1766    sd->s_iface->content_pos_get(obj, &x, &y);
1767    sd->s_iface->step_size_get(obj, &step_x, &step_y);
1768    sd->s_iface->page_size_get(obj, &page_x, &page_y);
1769    sd->s_iface->content_viewport_size_get(obj, &v_w, &v_h);
1770
1771    if ((!strcmp(ev->keyname, "Left")) ||
1772        ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
1773      {
1774         if ((sd->horizontal) &&
1775             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1776               (_item_multi_select_up(sd)))
1777              || (_item_single_select_up(sd))))
1778           {
1779              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1780              return EINA_TRUE;
1781           }
1782         else if ((!sd->horizontal) &&
1783                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1784                    (_item_multi_select_left(sd)))
1785                   || (_item_single_select_left(sd))))
1786           {
1787              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1788              return EINA_TRUE;
1789           }
1790         else
1791           x -= step_x;
1792      }
1793    else if ((!strcmp(ev->keyname, "Right")) ||
1794             ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
1795      {
1796         if ((sd->horizontal) &&
1797             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1798               (_item_multi_select_down(sd)))
1799              || (_item_single_select_down(sd))))
1800           {
1801              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1802              return EINA_TRUE;
1803           }
1804         else if ((!sd->horizontal) &&
1805                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1806                    (_item_multi_select_right(sd)))
1807                   || (_item_single_select_right(sd))))
1808           {
1809              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1810              return EINA_TRUE;
1811           }
1812         else
1813           x += step_x;
1814      }
1815    else if ((!strcmp(ev->keyname, "Up")) ||
1816             ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
1817      {
1818         if ((sd->horizontal) &&
1819             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1820               (_item_multi_select_left(sd)))
1821              || (_item_single_select_left(sd))))
1822           {
1823              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1824              return EINA_TRUE;
1825           }
1826         else if ((!sd->horizontal) &&
1827                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1828                    (_item_multi_select_up(sd)))
1829                   || (_item_single_select_up(sd))))
1830           {
1831              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1832              return EINA_TRUE;
1833           }
1834         else
1835           y -= step_y;
1836      }
1837    else if ((!strcmp(ev->keyname, "Down")) ||
1838             ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
1839      {
1840         if ((sd->horizontal) &&
1841             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1842               (_item_multi_select_right(sd)))
1843              || (_item_single_select_right(sd))))
1844           {
1845              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1846              return EINA_TRUE;
1847           }
1848         else if ((!sd->horizontal) &&
1849                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
1850                    (_item_multi_select_down(sd)))
1851                   || (_item_single_select_down(sd))))
1852           {
1853              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1854              return EINA_TRUE;
1855           }
1856         else
1857           y += step_y;
1858      }
1859    else if ((!strcmp(ev->keyname, "Home")) ||
1860             ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
1861      {
1862         it = elm_gengrid_first_item_get(obj);
1863         elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1864         elm_gengrid_item_selected_set(it, EINA_TRUE);
1865         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1866         return EINA_TRUE;
1867      }
1868    else if ((!strcmp(ev->keyname, "End")) ||
1869             ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
1870      {
1871         it = elm_gengrid_last_item_get(obj);
1872         elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1873         elm_gengrid_item_selected_set(it, EINA_TRUE);
1874         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1875         return EINA_TRUE;
1876      }
1877    else if ((!strcmp(ev->keyname, "Prior")) ||
1878             ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
1879      {
1880         if (sd->horizontal)
1881           {
1882              if (page_x < 0)
1883                x -= -(page_x * v_w) / 100;
1884              else
1885                x -= page_x;
1886           }
1887         else
1888           {
1889              if (page_y < 0)
1890                y -= -(page_y * v_h) / 100;
1891              else
1892                y -= page_y;
1893           }
1894      }
1895    else if ((!strcmp(ev->keyname, "Next")) ||
1896             ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
1897      {
1898         if (sd->horizontal)
1899           {
1900              if (page_x < 0)
1901                x += -(page_x * v_w) / 100;
1902              else
1903                x += page_x;
1904           }
1905         else
1906           {
1907              if (page_y < 0)
1908                y += -(page_y * v_h) / 100;
1909              else
1910                y += page_y;
1911           }
1912      }
1913    else if (!strcmp(ev->keyname, "Escape"))
1914      {
1915         if (!_all_items_deselect(sd)) return EINA_FALSE;
1916         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1917         return EINA_TRUE;
1918      }
1919    else if (((!strcmp(ev->keyname, "Return")) ||
1920              (!strcmp(ev->keyname, "KP_Enter")) ||
1921              (!strcmp(ev->keyname, "space")))
1922             && (!sd->multi) && (sd->selected))
1923      {
1924         it = elm_gengrid_selected_item_get(obj);
1925         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1926      }
1927    else return EINA_FALSE;
1928
1929    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1930    sd->s_iface->content_pos_set(obj, x, y, EINA_TRUE);
1931    return EINA_TRUE;
1932 }
1933
1934 static Eina_Bool
1935 _elm_gengrid_smart_on_focus(Evas_Object *obj)
1936 {
1937    ELM_GENGRID_DATA_GET(obj, sd);
1938
1939    if (!ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->on_focus(obj))
1940      return EINA_FALSE;
1941
1942    if (elm_widget_focus_get(obj) && (sd->selected) &&
1943        (!sd->last_selected_item))
1944      sd->last_selected_item = eina_list_data_get(sd->selected);
1945
1946    return EINA_TRUE;
1947 }
1948
1949 static Eina_Bool
1950 _elm_gengrid_smart_focus_next(const Evas_Object *obj,
1951                            Elm_Focus_Direction dir,
1952                            Evas_Object **next)
1953 {
1954    Eina_List *items = NULL;
1955    Elm_Gen_Item *it;
1956
1957    ELM_GENGRID_CHECK(obj) EINA_FALSE;
1958    ELM_GENGRID_DATA_GET(obj, sd);
1959
1960    EINA_INLIST_FOREACH(sd->items, it)
1961      {
1962         if (it->realized)
1963           items = eina_list_append(items, it->base.access_obj);
1964      }
1965
1966    return elm_widget_focus_list_next_get
1967             (obj, items, eina_list_data_get, dir, next);
1968 }
1969
1970 static void
1971 _mirrored_set(Evas_Object *obj,
1972               Eina_Bool rtl)
1973 {
1974    Elm_Gen_Item *it;
1975
1976    ELM_GENGRID_DATA_GET(obj, sd);
1977
1978    sd->s_iface->mirrored_set(obj, rtl);
1979
1980    if (!sd->items) return;
1981    it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
1982
1983    while (it)
1984      {
1985         edje_object_mirrored_set(VIEW(it), rtl);
1986         elm_gengrid_item_update((Elm_Object_Item *)it);
1987         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
1988      }
1989 }
1990
1991 static Eina_Bool
1992 _elm_gengrid_smart_theme(Evas_Object *obj)
1993 {
1994    if (!ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->theme(obj))
1995      return EINA_FALSE;
1996
1997    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1998
1999    return EINA_TRUE;
2000 }
2001
2002 static void
2003 _item_position_update(Eina_Inlist *list,
2004                       int idx)
2005 {
2006    Elm_Gen_Item *it;
2007
2008    EINA_INLIST_FOREACH(list, it)
2009      {
2010         it->position = idx++;
2011         it->position_update = EINA_TRUE;
2012      }
2013 }
2014
2015 static void
2016 _elm_gengrid_item_del_not_serious(Elm_Gen_Item *it)
2017 {
2018    elm_widget_item_pre_notify_del(it);
2019    it->generation = GG_IT(it)->wsd->generation - 1; /* This means that the
2020                                                      * item is deleted */
2021
2022    if ((it->relcount > 0) || (it->walking > 0)) return;
2023
2024    if (it->selected)
2025      GG_IT(it)->wsd->selected =
2026        eina_list_remove(GG_IT(it)->wsd->selected, it);
2027
2028    if (it->itc->func.del)
2029      it->itc->func.del((void *)it->base.data, WIDGET(it));
2030 }
2031
2032 static void
2033 _elm_gengrid_item_del_common(Elm_Gen_Item *it)
2034 {
2035    _elm_gengrid_item_del_not_serious(it);
2036
2037    GG_IT(it)->wsd->items = eina_inlist_remove
2038       (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2039
2040    if (it->tooltip.del_cb)
2041      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
2042    GG_IT(it)->wsd->walking -= it->walking;
2043    if (it->long_timer)
2044      {
2045         ecore_timer_del(it->long_timer);
2046         it->long_timer = NULL;
2047      }
2048    if (it->group)
2049      GG_IT(it)->wsd->group_items =
2050         eina_list_remove(GG_IT(it)->wsd->group_items, it);
2051
2052    if (GG_IT(it)->wsd->state)
2053      {
2054         eina_inlist_sorted_state_free(GG_IT(it)->wsd->state);
2055         GG_IT(it)->wsd->state = NULL;
2056      }
2057    if (GG_IT(it)->wsd->calc_job) ecore_job_del(GG_IT(it)->wsd->calc_job);
2058    GG_IT(it)->wsd->calc_job =
2059       ecore_job_add(GG_IT(it)->wsd->calc_cb, GG_IT(it)->wsd);
2060
2061    if (GG_IT(it)->wsd->last_selected_item == (Elm_Object_Item *)it)
2062      GG_IT(it)->wsd->last_selected_item = NULL;
2063    GG_IT(it)->wsd->item_count--;
2064 }
2065
2066 static void
2067 _elm_gengrid_item_del_serious(Elm_Gen_Item *it)
2068 {
2069 #if GENGRID_FX_SUPPORT
2070    if ((!GG_IT(it)->wsd->fx_mode) || (GG_IT(it)->wsd->gengrid_clearing))
2071 #endif
2072      {
2073         GG_IT(it)->wsd->items = eina_inlist_remove
2074            (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2075
2076      }
2077
2078    _elm_gengrid_item_del_common(it);
2079    free(it->item);
2080    it->item = NULL;
2081 }
2082
2083 static void
2084 _item_del(Elm_Gen_Item *it)
2085 {
2086    Evas_Object *obj = WIDGET(it);
2087
2088    evas_event_freeze(evas_object_evas_get(obj));
2089 #if GENGRID_FX_SUPPORT
2090    GG_IT(it)->has_proxy_it = EINA_FALSE;
2091 #endif
2092    GG_IT(it)->wsd->selected = eina_list_remove(GG_IT(it)->wsd->selected, it);
2093    if (it->realized) _elm_gengrid_item_unrealize(it, EINA_FALSE);
2094    _elm_gengrid_item_del_serious(it);
2095    elm_gengrid_item_class_unref((Elm_Gengrid_Item_Class *)it->itc);
2096    evas_event_thaw(evas_object_evas_get(obj));
2097    evas_event_thaw_eval(evas_object_evas_get(obj));
2098 }
2099
2100 static void
2101 _scroll_animate_start_cb(Evas_Object *obj,
2102                          void *data __UNUSED__)
2103 {
2104    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
2105 }
2106
2107 static void
2108 _scroll_animate_stop_cb(Evas_Object *obj,
2109                         void *data __UNUSED__)
2110 {
2111    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
2112 }
2113
2114 static void
2115 _scroll_drag_start_cb(Evas_Object *obj,
2116                       void *data __UNUSED__)
2117 {
2118    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
2119 }
2120
2121 static void
2122 _scroll_drag_stop_cb(Evas_Object *obj,
2123                      void *data __UNUSED__)
2124 {
2125    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
2126 }
2127
2128 static void
2129 _edge_left_cb(Evas_Object *obj,
2130               void *data __UNUSED__)
2131 {
2132    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2133 }
2134
2135 static void
2136 _edge_right_cb(Evas_Object *obj,
2137                void *data __UNUSED__)
2138 {
2139    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2140 }
2141
2142 static void
2143 _edge_top_cb(Evas_Object *obj,
2144              void *data __UNUSED__)
2145 {
2146    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2147 }
2148
2149 static void
2150 _edge_bottom_cb(Evas_Object *obj,
2151                 void *data __UNUSED__)
2152 {
2153    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2154 }
2155
2156 static void
2157 _scroll_cb(Evas_Object *obj,
2158            void *data __UNUSED__)
2159 {
2160    evas_object_smart_callback_call(obj, SIG_SCROLL, NULL);
2161 }
2162
2163 static int
2164 _elm_gengrid_item_compare(const void *data,
2165                           const void *data1)
2166 {
2167    Elm_Gen_Item *it, *item1;
2168    Eina_Compare_Cb cb = NULL;
2169    ptrdiff_t d;
2170
2171    it = ELM_GEN_ITEM_FROM_INLIST(data);
2172    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
2173    if (it && GG_IT(it)->wsd->item_compare_cb)
2174      cb = GG_IT(it)->wsd->item_compare_cb;
2175    else if (item1 && GG_IT(item1)->wsd->item_compare_cb)
2176      cb = GG_IT(item1)->wsd->item_compare_cb;
2177    if (cb && it && item1) return cb(it, item1);
2178    d = (char *)data - (char *)data1;
2179    if (d < 0) return -1;
2180    if (!d) return 0;
2181    return 1;
2182 }
2183
2184 static void
2185 _item_disable_hook(Elm_Object_Item *item)
2186 {
2187    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2188
2189    if (it->generation < GG_IT(it)->wsd->generation) return;
2190
2191    if (it->realized)
2192      {
2193         if (elm_widget_item_disabled_get(it))
2194           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
2195         else
2196           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
2197      }
2198 }
2199
2200 #if GENGRID_FX_SUPPORT
2201 static void
2202 _item_del_pre_fx_process(Elm_Gen_Item *it)
2203 {
2204    Evas_Object *obj = WIDGET(it);
2205
2206    _elm_gengrid_fx_capture(ELM_WIDGET_DATA(GG_IT(it)->wsd)->obj, 0);
2207    if (!eina_list_data_find(GG_IT(it)->wsd->pending_del_items, it))
2208      GG_IT(it)->wsd->pending_del_items = eina_list_append(GG_IT(it)->wsd->pending_del_items, it);
2209
2210    evas_object_event_callback_del_full
2211       (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
2212    evas_object_event_callback_del_full
2213       (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
2214    evas_object_event_callback_del_full
2215       (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
2216
2217    GG_IT(it)->wsd->items = eina_inlist_remove
2218       (GG_IT(it)->wsd->items, EINA_INLIST_GET(it));
2219
2220    if (GG_IT(it)->wsd->calc_job) ecore_job_del(GG_IT(it)->wsd->calc_job);
2221    GG_IT(it)->wsd->calc_job =
2222       ecore_job_add(GG_IT(it)->wsd->calc_cb, GG_IT(it)->wsd);
2223 }
2224 #endif
2225
2226 //static void
2227 static Eina_Bool
2228 _item_del_pre_hook(Elm_Object_Item *item)
2229 {
2230    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2231
2232 #if GENGRID_FX_SUPPORT
2233    if ((GG_IT(it)->wsd->fx_mode) && (!GG_IT(it)->wsd->gengrid_clearing))
2234      {
2235         _item_del_pre_fx_process(it);
2236         return EINA_FALSE;
2237      }
2238 #endif
2239    if ((it->relcount > 0) || (it->walking > 0))
2240      {
2241         _elm_gengrid_item_del_not_serious(it);
2242         return EINA_TRUE;
2243      }
2244
2245    _item_del(it);
2246    return EINA_TRUE;
2247 }
2248
2249 static Evas_Object *
2250 _item_content_get_hook(Elm_Gen_Item *it,
2251                        const char *part)
2252 {
2253    return edje_object_part_swallow_get(VIEW(it), part);
2254 }
2255
2256 static const char *
2257 _item_text_get_hook(Elm_Gen_Item *it,
2258                     const char *part)
2259 {
2260    if (!it->itc->func.text_get) return NULL;
2261    return edje_object_part_text_get(VIEW(it), part);
2262 }
2263
2264 static void
2265 _item_signal_emit_hook(Elm_Object_Item *it,
2266                        const char *emission,
2267                        const char *source)
2268 {
2269    edje_object_signal_emit(VIEW(it), emission, source);
2270 }
2271
2272 static void
2273 _elm_gengrid_clear(Evas_Object *obj,
2274                    Eina_Bool standby)
2275 {
2276    Eina_Inlist *next, *l;
2277
2278    ELM_GENGRID_DATA_GET(obj, sd);
2279
2280    if (!standby) sd->generation++;
2281
2282    if (sd->state)
2283      {
2284         eina_inlist_sorted_state_free(sd->state);
2285         sd->state = NULL;
2286      }
2287
2288    if (sd->walking > 0)
2289      {
2290         sd->clear_me = EINA_TRUE;
2291         return;
2292      }
2293    evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2294
2295 #if GENGRID_FX_SUPPORT
2296    Elm_Gen_FX_Item *fi;
2297    Proxy_Item *pi;
2298    Elm_Gen_Item *it;
2299
2300    EINA_LIST_FREE(sd->capture_before_items, pi)
2301      {
2302         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
2303         if (pi->proxy) evas_object_del(pi->proxy);
2304         free(pi);
2305      }
2306    EINA_LIST_FREE(sd->capture_after_items, pi)
2307      {
2308         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
2309         if (pi->proxy) evas_object_del(pi->proxy);
2310         free(pi);
2311      }
2312    EINA_LIST_FREE(sd->fx_items, fi)
2313      {
2314         if (fi->trans) elm_transit_del(fi->trans);
2315         free(fi);
2316      }
2317    EINA_LIST_FREE (sd->pending_unrealized_items, it)
2318      {
2319         if ((it) && (GG_IT(it))) GG_IT(it)->has_proxy_it = EINA_FALSE;
2320         _elm_gengrid_item_unrealize(it, EINA_FALSE);
2321      }
2322    EINA_LIST_FREE (sd->pending_del_items, it)
2323      {
2324         _item_del(it);
2325         _elm_widget_item_free((Elm_Widget_Item *)it);
2326      }
2327    sd->gengrid_clearing = EINA_TRUE;
2328    sd->fx_playing = EINA_FALSE;
2329    sd->fx_first_captured = EINA_FALSE;
2330    sd->rendered = EINA_FALSE;
2331    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
2332 #endif
2333
2334    for (l = sd->items, next = l ? l->next : NULL;
2335         l;
2336         l = next, next = next ? next->next : NULL)
2337      {
2338         it = ELM_GEN_ITEM_FROM_INLIST(l);
2339
2340         if (it->generation < sd->generation)
2341           {
2342              Elm_Gen_Item *itn = NULL;
2343
2344              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
2345              if (itn) itn->walking++;  /* prevent early death of subitem */
2346              it->del_cb(it);
2347              elm_widget_item_free(it);
2348              if (itn) itn->walking--;
2349           }
2350      }
2351    sd->clear_me = EINA_FALSE;
2352    sd->pan_changed = EINA_TRUE;
2353    if (sd->calc_job)
2354      {
2355         ecore_job_del(sd->calc_job);
2356         sd->calc_job = NULL;
2357      }
2358    if (sd->selected) sd->selected = eina_list_free(sd->selected);
2359    if (sd->clear_cb) sd->clear_cb(sd);
2360    sd->pan_x = 0;
2361    sd->pan_y = 0;
2362    sd->minw = 0;
2363    sd->minh = 0;
2364
2365    if (sd->pan_obj)
2366      {
2367         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
2368         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
2369      }
2370    sd->s_iface->content_region_show(obj, 0, 0, 0, 0);
2371
2372 #if GENGRID_FX_SUPPORT
2373    sd->gengrid_clearing = EINA_FALSE;
2374 #endif
2375    evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2376    evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2377 }
2378
2379 static void
2380 _item_select(Elm_Gen_Item *it)
2381 {
2382    Evas_Object *obj = WIDGET(it);
2383
2384    if ((it->generation < GG_IT(it)->wsd->generation) || (it->decorate_it_set) ||
2385        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2386        (GG_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
2387      return;
2388    if (!it->selected)
2389      {
2390         it->selected = EINA_TRUE;
2391         GG_IT(it)->wsd->selected =
2392           eina_list_append(GG_IT(it)->wsd->selected, it);
2393      }
2394    else if (GG_IT(it)->wsd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS)
2395      return;
2396
2397    evas_object_ref(obj);
2398    it->walking++;
2399    GG_IT(it)->wsd->walking++;
2400    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
2401    if (it->generation == GG_IT(it)->wsd->generation)
2402      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
2403    it->walking--;
2404    GG_IT(it)->wsd->walking--;
2405    if ((GG_IT(it)->wsd->clear_me) && (!GG_IT(it)->wsd->walking))
2406      _elm_gengrid_clear(WIDGET(it), EINA_TRUE);
2407    else
2408      {
2409         if ((!it->walking) && (it->generation < GG_IT(it)->wsd->generation))
2410           {
2411              if (!it->relcount)
2412                {
2413                   it->del_cb(it);
2414                   elm_widget_item_free(it);
2415                }
2416           }
2417         else
2418           GG_IT(it)->wsd->last_selected_item = (Elm_Object_Item *)it;
2419      }
2420    evas_object_unref(obj);
2421 }
2422
2423 static Elm_Gen_Item *
2424 _elm_gengrid_item_new(Elm_Gengrid_Smart_Data *sd,
2425                       const Elm_Gen_Item_Class *itc,
2426                       const void *data,
2427                       Evas_Smart_Cb func,
2428                       const void *func_data)
2429 {
2430    Elm_Gen_Item *it;
2431
2432    if (!itc) return NULL;
2433
2434    it = elm_widget_item_new(ELM_WIDGET_DATA(sd)->obj, Elm_Gen_Item);
2435    if (!it) return NULL;
2436
2437    it->generation = sd->generation;
2438    it->itc = itc;
2439    elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
2440
2441    it->base.data = data;
2442    it->parent = NULL;
2443    it->func.func = func;
2444    it->func.data = func_data;
2445
2446    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
2447    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
2448    elm_widget_item_disable_hook_set(it, _item_disable_hook);
2449    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
2450    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
2451
2452    /* TEMPORARY */
2453    it->sel_cb = (Ecore_Cb)_item_select;
2454
2455    elm_widget_item_disable_hook_set(it, _item_disable_hook);
2456    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
2457    elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
2458    it->item = ELM_NEW(Elm_Gen_Item_Type);
2459
2460    GG_IT(it)->wsd = sd;
2461
2462    sd->item_count++;
2463    it->group = it->itc->item_style &&
2464      (!strcmp(it->itc->item_style, "group_index"));
2465
2466    it->del_cb = (Ecore_Cb)_item_del;
2467    it->highlight_cb = (Ecore_Cb)_item_highlight;
2468    it->unsel_cb = (Ecore_Cb)_item_unselect;
2469    it->unrealize_cb = (Ecore_Cb)_item_unrealize_cb;
2470
2471 #if GENGRID_FX_SUPPORT
2472    it->item->num = sd->item_count;
2473    if (sd->fx_mode)
2474      _elm_gengrid_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
2475 #endif
2476
2477    return it;
2478 }
2479
2480 /* common layout sizing won't apply here */
2481 static void
2482 _elm_gengrid_smart_sizing_eval(Evas_Object *obj __UNUSED__)
2483 {
2484    return;  /* no-op */
2485 }
2486
2487 static void
2488 _elm_gengrid_smart_add(Evas_Object *obj)
2489 {
2490    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
2491    Elm_Gengrid_Pan_Smart_Data *pan_data;
2492
2493    EVAS_SMART_DATA_ALLOC(obj, Elm_Gengrid_Smart_Data);
2494
2495    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.add(obj);
2496
2497    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
2498    evas_object_smart_member_add(priv->hit_rect, obj);
2499    elm_widget_sub_object_add(obj, priv->hit_rect);
2500
2501    /* common scroller hit rectangle setup */
2502    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
2503    evas_object_show(priv->hit_rect);
2504    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
2505
2506    elm_widget_can_focus_set(obj, EINA_TRUE);
2507
2508    priv->calc_cb = (Ecore_Cb)_calc_job;
2509
2510    priv->generation = 1;
2511
2512    elm_layout_theme_set(obj, "gengrid", "base", elm_widget_style_get(obj));
2513
2514    /* interface's add() routine issued AFTER the object's smart_add() */
2515    priv->s_iface = evas_object_smart_interface_get
2516        (obj, ELM_SCROLLABLE_IFACE_NAME);
2517
2518    priv->s_iface->objects_set
2519      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
2520
2521    priv->old_h_bounce = bounce;
2522    priv->old_v_bounce = bounce;
2523    priv->s_iface->bounce_allow_set(obj, bounce, bounce);
2524
2525    priv->s_iface->animate_start_cb_set(obj, _scroll_animate_start_cb);
2526    priv->s_iface->animate_stop_cb_set(obj, _scroll_animate_stop_cb);
2527    priv->s_iface->drag_start_cb_set(obj, _scroll_drag_start_cb);
2528    priv->s_iface->drag_stop_cb_set(obj, _scroll_drag_stop_cb);
2529    priv->s_iface->edge_left_cb_set(obj, _edge_left_cb);
2530    priv->s_iface->edge_right_cb_set(obj, _edge_right_cb);
2531    priv->s_iface->edge_top_cb_set(obj, _edge_top_cb);
2532    priv->s_iface->edge_bottom_cb_set(obj, _edge_bottom_cb);
2533    priv->s_iface->scroll_cb_set(obj, _scroll_cb);
2534
2535    priv->align_x = 0.5;
2536    priv->align_y = 0.5;
2537    priv->highlight = EINA_TRUE;
2538
2539 #if GENGRID_FX_SUPPORT
2540    priv->fx_mode = EINA_FALSE;
2541    priv->rendered = EINA_FALSE;
2542    priv->fx_first_captured = EINA_FALSE;
2543    priv->fx_playing = EINA_FALSE;
2544    priv->gengrid_clearing = EINA_FALSE;
2545 #endif
2546
2547    priv->pan_obj = evas_object_smart_add
2548        (evas_object_evas_get(obj), _elm_gengrid_pan_smart_class_new());
2549    pan_data = evas_object_smart_data_get(priv->pan_obj);
2550    pan_data->wsd = priv;
2551
2552    priv->s_iface->extern_pan_set(obj, priv->pan_obj);
2553 }
2554
2555 static void
2556 _elm_gengrid_smart_del(Evas_Object *obj)
2557 {
2558    ELM_GENGRID_DATA_GET(obj, sd);
2559
2560    elm_gengrid_clear(obj);
2561    evas_object_del(sd->pan_obj);
2562    sd->pan_obj = NULL;
2563
2564    if (sd->calc_job) ecore_job_del(sd->calc_job);
2565
2566    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.del(obj);
2567 }
2568
2569 static void
2570 _elm_gengrid_smart_move(Evas_Object *obj,
2571                         Evas_Coord x,
2572                         Evas_Coord y)
2573 {
2574    ELM_GENGRID_DATA_GET(obj, sd);
2575
2576    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.move(obj, x, y);
2577
2578    evas_object_move(sd->hit_rect, x, y);
2579 }
2580
2581 static void
2582 _elm_gengrid_smart_resize(Evas_Object *obj,
2583                           Evas_Coord w,
2584                           Evas_Coord h)
2585 {
2586    ELM_GENGRID_DATA_GET(obj, sd);
2587
2588    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.resize(obj, w, h);
2589
2590    evas_object_resize(sd->hit_rect, w, h);
2591 }
2592
2593 static void
2594 _elm_gengrid_smart_member_add(Evas_Object *obj,
2595                               Evas_Object *member)
2596 {
2597    ELM_GENGRID_DATA_GET(obj, sd);
2598
2599    ELM_WIDGET_CLASS(_elm_gengrid_parent_sc)->base.member_add(obj, member);
2600
2601    if (sd->hit_rect)
2602      evas_object_raise(sd->hit_rect);
2603 }
2604
2605 static void
2606 _access_obj_process(Elm_Gengrid_Smart_Data * sd, Eina_Bool is_access)
2607 {
2608    Elm_Gen_Item *it;
2609
2610    EINA_INLIST_FOREACH(sd->items, it)
2611      {
2612         if (!it->realized) continue;
2613         if (is_access) _access_widget_item_register(it);
2614         else
2615           _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
2616
2617      }
2618 }
2619
2620 static void
2621 _access_hook(Evas_Object *obj, Eina_Bool is_access)
2622 {
2623    ELM_GENGRID_CHECK(obj);
2624    ELM_GENGRID_DATA_GET(obj, sd);
2625
2626    if (is_access)
2627      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
2628      _elm_gengrid_smart_focus_next;
2629    else
2630      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
2631
2632    _access_obj_process(sd, is_access);
2633 }
2634
2635 static void
2636 _elm_gengrid_smart_set_user(Elm_Gengrid_Smart_Class *sc)
2637 {
2638    ELM_WIDGET_CLASS(sc)->base.add = _elm_gengrid_smart_add;
2639    ELM_WIDGET_CLASS(sc)->base.del = _elm_gengrid_smart_del;
2640    ELM_WIDGET_CLASS(sc)->base.move = _elm_gengrid_smart_move;
2641    ELM_WIDGET_CLASS(sc)->base.resize = _elm_gengrid_smart_resize;
2642    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_gengrid_smart_member_add;
2643
2644    ELM_WIDGET_CLASS(sc)->on_focus = _elm_gengrid_smart_on_focus;
2645    ELM_WIDGET_CLASS(sc)->theme = _elm_gengrid_smart_theme;
2646    ELM_WIDGET_CLASS(sc)->event = _elm_gengrid_smart_event;
2647
2648    /* not a 'focus chain manager' */
2649    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
2650    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
2651    ELM_WIDGET_CLASS(sc)->translate = _elm_gengrid_smart_translate;
2652
2653    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_gengrid_smart_sizing_eval;
2654
2655    // ACCESS
2656    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
2657      ELM_WIDGET_CLASS(sc)->focus_next = _elm_gengrid_smart_focus_next;
2658
2659    ELM_WIDGET_CLASS(sc)->access = _access_hook;
2660 }
2661
2662 EAPI const Elm_Gengrid_Smart_Class *
2663 elm_gengrid_smart_class_get(void)
2664 {
2665    static Elm_Gengrid_Smart_Class _sc =
2666      ELM_GENGRID_SMART_CLASS_INIT_NAME_VERSION(ELM_GENGRID_SMART_NAME);
2667    static const Elm_Gengrid_Smart_Class *class = NULL;
2668    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
2669
2670    if (class)
2671      return class;
2672
2673    _elm_gengrid_smart_set(&_sc);
2674    esc->callbacks = _smart_callbacks;
2675    class = &_sc;
2676
2677    return class;
2678 }
2679
2680 EAPI Evas_Object *
2681 elm_gengrid_add(Evas_Object *parent)
2682 {
2683    Evas_Object *obj;
2684
2685    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2686
2687    obj = elm_widget_add(_elm_gengrid_smart_class_new(), parent);
2688    if (!obj) return NULL;
2689
2690    if (!elm_widget_sub_object_add(parent, obj))
2691      ERR("could not add %p as sub object of %p", obj, parent);
2692
2693    return obj;
2694 }
2695
2696 EAPI void
2697 elm_gengrid_item_size_set(Evas_Object *obj,
2698                           Evas_Coord w,
2699                           Evas_Coord h)
2700 {
2701    ELM_GENGRID_CHECK(obj);
2702    ELM_GENGRID_DATA_GET(obj, sd);
2703
2704    if ((sd->item_width == w) && (sd->item_height == h)) return;
2705    sd->item_width = w;
2706    sd->item_height = h;
2707    if (sd->calc_job) ecore_job_del(sd->calc_job);
2708    sd->calc_job = ecore_job_add(_calc_job, sd);
2709 }
2710
2711 EAPI void
2712 elm_gengrid_item_size_get(const Evas_Object *obj,
2713                           Evas_Coord *w,
2714                           Evas_Coord *h)
2715 {
2716    ELM_GENGRID_CHECK(obj);
2717    ELM_GENGRID_DATA_GET(obj, sd);
2718
2719    if (w) *w = sd->item_width;
2720    if (h) *h = sd->item_height;
2721 }
2722
2723 EAPI void
2724 elm_gengrid_group_item_size_set(Evas_Object *obj,
2725                                 Evas_Coord w,
2726                                 Evas_Coord h)
2727 {
2728    ELM_GENGRID_CHECK(obj);
2729    ELM_GENGRID_DATA_GET(obj, sd);
2730
2731    if ((sd->group_item_width == w) && (sd->group_item_height == h)) return;
2732    sd->group_item_width = w;
2733    sd->group_item_height = h;
2734    if (sd->calc_job) ecore_job_del(sd->calc_job);
2735    sd->calc_job = ecore_job_add(_calc_job, sd);
2736 }
2737
2738 EAPI void
2739 elm_gengrid_group_item_size_get(const Evas_Object *obj,
2740                                 Evas_Coord *w,
2741                                 Evas_Coord *h)
2742 {
2743    ELM_GENGRID_CHECK(obj);
2744    ELM_GENGRID_DATA_GET(obj, sd);
2745
2746    if (w) *w = sd->group_item_width;
2747    if (h) *h = sd->group_item_height;
2748 }
2749
2750 EAPI void
2751 elm_gengrid_align_set(Evas_Object *obj,
2752                       double align_x,
2753                       double align_y)
2754 {
2755    double old_h, old_y;
2756
2757    ELM_GENGRID_CHECK(obj);
2758    ELM_GENGRID_DATA_GET(obj, sd);
2759
2760    old_h = sd->align_x;
2761    old_y = sd->align_y;
2762
2763    if (align_x > 1.0)
2764      align_x = 1.0;
2765    else if (align_x < 0.0)
2766      align_x = 0.0;
2767    sd->align_x = align_x;
2768
2769    if (align_y > 1.0)
2770      align_y = 1.0;
2771    else if (align_y < 0.0)
2772      align_y = 0.0;
2773    sd->align_y = align_y;
2774
2775    if ((old_h != sd->align_x) || (old_y != sd->align_y))
2776      evas_object_smart_calculate(sd->pan_obj);
2777 }
2778
2779 EAPI void
2780 elm_gengrid_align_get(const Evas_Object *obj,
2781                       double *align_x,
2782                       double *align_y)
2783 {
2784    ELM_GENGRID_CHECK(obj);
2785    ELM_GENGRID_DATA_GET(obj, sd);
2786
2787    if (align_x) *align_x = sd->align_x;
2788    if (align_y) *align_y = sd->align_y;
2789 }
2790
2791 EAPI Elm_Object_Item *
2792 elm_gengrid_item_append(Evas_Object *obj,
2793                         const Elm_Gengrid_Item_Class *itc,
2794                         const void *data,
2795                         Evas_Smart_Cb func,
2796                         const void *func_data)
2797 {
2798    Elm_Gen_Item *it;
2799
2800    ELM_GENGRID_CHECK(obj) NULL;
2801    ELM_GENGRID_DATA_GET(obj, sd);
2802
2803    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2804    if (!it) return NULL;
2805
2806    sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
2807    it->position = eina_inlist_count(sd->items);
2808    it->position_update = EINA_TRUE;
2809
2810    if (it->group)
2811      sd->group_items = eina_list_prepend(sd->group_items, it);
2812
2813    if (sd->calc_job) ecore_job_del(sd->calc_job);
2814    sd->calc_job = ecore_job_add(_calc_job, sd);
2815
2816    return (Elm_Object_Item *)it;
2817 }
2818
2819 EAPI Elm_Object_Item *
2820 elm_gengrid_item_prepend(Evas_Object *obj,
2821                          const Elm_Gengrid_Item_Class *itc,
2822                          const void *data,
2823                          Evas_Smart_Cb func,
2824                          const void *func_data)
2825 {
2826    Elm_Gen_Item *it;
2827
2828    ELM_GENGRID_CHECK(obj) NULL;
2829    ELM_GENGRID_DATA_GET(obj, sd);
2830
2831    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2832    if (!it) return NULL;
2833
2834    sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
2835    _item_position_update(sd->items, 0);
2836
2837    if (it->group)
2838      sd->group_items = eina_list_append(sd->group_items, it);
2839
2840    if (sd->calc_job) ecore_job_del(sd->calc_job);
2841    sd->calc_job = ecore_job_add(_calc_job, sd);
2842
2843    return (Elm_Object_Item *)it;
2844 }
2845
2846 EAPI Elm_Object_Item *
2847 elm_gengrid_item_insert_before(Evas_Object *obj,
2848                                const Elm_Gengrid_Item_Class *itc,
2849                                const void *data,
2850                                Elm_Object_Item *relative,
2851                                Evas_Smart_Cb func,
2852                                const void *func_data)
2853 {
2854    Elm_Gen_Item *it;
2855    Eina_Inlist *tmp;
2856
2857    ELM_GENGRID_CHECK(obj) NULL;
2858    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
2859    ELM_GENGRID_DATA_GET(obj, sd);
2860
2861    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2862    if (!it) return NULL;
2863    sd->items = eina_inlist_prepend_relative
2864        (sd->items, EINA_INLIST_GET(it),
2865        EINA_INLIST_GET((Elm_Gen_Item *)relative));
2866    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
2867    _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position);
2868
2869    if (it->group)
2870      sd->group_items = eina_list_append_relative
2871          (sd->group_items, it, ((Elm_Gen_Item *)relative)->parent);
2872
2873    if (sd->calc_job) ecore_job_del(sd->calc_job);
2874    sd->calc_job = ecore_job_add(_calc_job, sd);
2875
2876    return (Elm_Object_Item *)it;
2877 }
2878
2879 EAPI Elm_Object_Item *
2880 elm_gengrid_item_insert_after(Evas_Object *obj,
2881                               const Elm_Gengrid_Item_Class *itc,
2882                               const void *data,
2883                               Elm_Object_Item *relative,
2884                               Evas_Smart_Cb func,
2885                               const void *func_data)
2886 {
2887    Elm_Gen_Item *it;
2888    Eina_Inlist *tmp;
2889
2890    ELM_GENGRID_CHECK(obj) NULL;
2891    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
2892    ELM_GENGRID_DATA_GET(obj, sd);
2893
2894    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2895    if (!it) return NULL;
2896    sd->items = eina_inlist_append_relative
2897        (sd->items, EINA_INLIST_GET(it),
2898        EINA_INLIST_GET((Elm_Gen_Item *)relative));
2899    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
2900    _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position + 1);
2901
2902    if (it->group)
2903      sd->group_items = eina_list_prepend_relative
2904          (sd->group_items, it, ((Elm_Gen_Item *)relative)->parent);
2905
2906    if (sd->calc_job) ecore_job_del(sd->calc_job);
2907    sd->calc_job = ecore_job_add(_calc_job, sd);
2908
2909    return (Elm_Object_Item *)it;
2910 }
2911
2912 EAPI Elm_Object_Item *
2913 elm_gengrid_item_sorted_insert(Evas_Object *obj,
2914                                const Elm_Gengrid_Item_Class *itc,
2915                                const void *data,
2916                                Eina_Compare_Cb comp,
2917                                Evas_Smart_Cb func,
2918                                const void *func_data)
2919 {
2920    Elm_Gen_Item *it;
2921
2922    ELM_GENGRID_CHECK(obj) NULL;
2923    ELM_GENGRID_DATA_GET(obj, sd);
2924
2925    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
2926    if (!it) return NULL;
2927
2928    if (!sd->state)
2929      {
2930         sd->state = eina_inlist_sorted_state_new();
2931         eina_inlist_sorted_state_init(sd->state, sd->items);
2932      }
2933
2934    sd->item_compare_cb = comp;
2935    sd->items = eina_inlist_sorted_state_insert
2936        (sd->items, EINA_INLIST_GET(it), _elm_gengrid_item_compare, sd->state);
2937    _item_position_update(sd->items, 0);
2938
2939    if (sd->calc_job) ecore_job_del(sd->calc_job);
2940    sd->calc_job = ecore_job_add(_calc_job, sd);
2941
2942    return (Elm_Object_Item *)it;
2943 }
2944
2945 EAPI void
2946 elm_gengrid_horizontal_set(Evas_Object *obj,
2947                            Eina_Bool horizontal)
2948 {
2949    ELM_GENGRID_CHECK(obj);
2950    ELM_GENGRID_DATA_GET(obj, sd);
2951
2952    horizontal = !!horizontal;
2953    if (horizontal == sd->horizontal) return;
2954    sd->horizontal = horizontal;
2955
2956    /* Update the items to conform to the new layout */
2957    if (sd->calc_job) ecore_job_del(sd->calc_job);
2958    sd->calc_job = ecore_job_add(_calc_job, sd);
2959 }
2960
2961 EAPI Eina_Bool
2962 elm_gengrid_horizontal_get(const Evas_Object *obj)
2963 {
2964    ELM_GENGRID_CHECK(obj) EINA_FALSE;
2965    ELM_GENGRID_DATA_GET(obj, sd);
2966
2967    return sd->horizontal;
2968 }
2969
2970 EAPI void
2971 elm_gengrid_clear(Evas_Object *obj)
2972 {
2973    ELM_GENGRID_CHECK(obj);
2974
2975    _elm_gengrid_clear(obj, EINA_FALSE);
2976 }
2977
2978 EINA_DEPRECATED EAPI const Evas_Object *
2979 elm_gengrid_item_object_get(const Elm_Object_Item *it)
2980 {
2981    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
2982
2983    return VIEW(it);
2984 }
2985
2986 EAPI void
2987 elm_gengrid_item_update(Elm_Object_Item *item)
2988 {
2989    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
2990
2991    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
2992
2993    if (!it->realized) return;
2994    if (it->want_unrealize) return;
2995
2996    _elm_gengrid_item_unrealize(it, EINA_FALSE);
2997    _item_realize(it);
2998    _item_place(it, it->x, it->y);
2999 }
3000
3001 EAPI const Elm_Gengrid_Item_Class *
3002 elm_gengrid_item_item_class_get(const Elm_Object_Item *it)
3003 {
3004    Elm_Gen_Item *item = (Elm_Gen_Item *)it;
3005
3006    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3007
3008    if (item->generation < GG_IT(item)->wsd->generation) return NULL;
3009    return item->itc;
3010 }
3011
3012 EAPI void
3013 elm_gengrid_item_item_class_update(Elm_Object_Item *item,
3014                                    const Elm_Gengrid_Item_Class *itc)
3015 {
3016    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3017
3018    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3019    EINA_SAFETY_ON_NULL_RETURN(itc);
3020
3021    if (it->generation < GG_IT(it)->wsd->generation) return;
3022    it->itc = itc;
3023    elm_gengrid_item_update(item);
3024 }
3025
3026 EAPI void
3027 elm_gengrid_item_pos_get(const Elm_Object_Item *it,
3028                          unsigned int *x,
3029                          unsigned int *y)
3030 {
3031    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3032
3033    if (x) *x = ((Elm_Gen_Item *)it)->x;
3034    if (y) *y = ((Elm_Gen_Item *)it)->y;
3035 }
3036
3037 EAPI void
3038 elm_gengrid_multi_select_set(Evas_Object *obj,
3039                              Eina_Bool multi)
3040 {
3041    ELM_GENGRID_CHECK(obj);
3042    ELM_GENGRID_DATA_GET(obj, sd);
3043
3044    sd->multi = !!multi;
3045 }
3046
3047 EAPI Eina_Bool
3048 elm_gengrid_multi_select_get(const Evas_Object *obj)
3049 {
3050    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3051    ELM_GENGRID_DATA_GET(obj, sd);
3052
3053    return sd->multi;
3054 }
3055
3056 EAPI Elm_Object_Item *
3057 elm_gengrid_selected_item_get(const Evas_Object *obj)
3058 {
3059    ELM_GENGRID_CHECK(obj) NULL;
3060    ELM_GENGRID_DATA_GET(obj, sd);
3061
3062    if (sd->selected) return sd->selected->data;
3063    return NULL;
3064 }
3065
3066 EAPI const Eina_List *
3067 elm_gengrid_selected_items_get(const Evas_Object *obj)
3068 {
3069    ELM_GENGRID_CHECK(obj) NULL;
3070    ELM_GENGRID_DATA_GET(obj, sd);
3071
3072    return sd->selected;
3073 }
3074
3075 EAPI void
3076 elm_gengrid_item_selected_set(Elm_Object_Item *item,
3077                               Eina_Bool selected)
3078 {
3079    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3080
3081    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3082
3083    if ((it->generation < GG_IT(it)->wsd->generation) ||
3084        elm_widget_item_disabled_get(it))
3085      return;
3086    selected = !!selected;
3087    if (it->selected == selected) return;
3088
3089    if (selected)
3090      {
3091         if (!GG_IT(it)->wsd->multi)
3092           {
3093              while (GG_IT(it)->wsd->selected)
3094                {
3095                   if (it->unhighlight_cb)
3096                     it->unhighlight_cb(GG_IT(it)->wsd->selected->data);
3097                   it->unsel_cb(GG_IT(it)->wsd->selected->data);
3098                }
3099           }
3100         it->highlight_cb(it);
3101         _item_select(it);
3102         return;
3103      }
3104    if (it->unhighlight_cb) it->unhighlight_cb(it);
3105    it->unsel_cb(it);
3106 }
3107
3108 EAPI Eina_Bool
3109 elm_gengrid_item_selected_get(const Elm_Object_Item *it)
3110 {
3111    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3112
3113    return ((Elm_Gen_Item *)it)->selected;
3114 }
3115
3116 EAPI Eina_List *
3117 elm_gengrid_realized_items_get(const Evas_Object *obj)
3118 {
3119    Eina_List *list = NULL;
3120    Elm_Gen_Item *it;
3121
3122    ELM_GENGRID_CHECK(obj) NULL;
3123    ELM_GENGRID_DATA_GET(obj, sd);
3124
3125    EINA_INLIST_FOREACH(sd->items, it)
3126      {
3127         if (it->realized) list = eina_list_append(list, (Elm_Object_Item *)it);
3128      }
3129    return list;
3130 }
3131
3132 EAPI void
3133 elm_gengrid_realized_items_update(Evas_Object *obj)
3134 {
3135    Eina_List *list, *l;
3136    Elm_Object_Item *it;
3137
3138    ELM_GENGRID_CHECK(obj);
3139
3140    list = elm_gengrid_realized_items_get(obj);
3141    EINA_LIST_FOREACH(list, l, it)
3142      elm_gengrid_item_update(it);
3143 }
3144
3145 static Evas_Object *
3146 _elm_gengrid_item_label_create(void *data,
3147                                Evas_Object *obj __UNUSED__,
3148                                Evas_Object *tooltip,
3149                                void *it   __UNUSED__)
3150 {
3151    Evas_Object *label = elm_label_add(tooltip);
3152    if (!label)
3153      return NULL;
3154    elm_object_style_set(label, "tooltip");
3155    elm_object_text_set(label, data);
3156    return label;
3157 }
3158
3159 static void
3160 _elm_gengrid_item_label_del_cb(void *data,
3161                                Evas_Object *obj __UNUSED__,
3162                                void *event_info __UNUSED__)
3163 {
3164    eina_stringshare_del(data);
3165 }
3166
3167 EAPI void
3168 elm_gengrid_item_tooltip_text_set(Elm_Object_Item *it,
3169                                   const char *text)
3170 {
3171    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3172
3173    text = eina_stringshare_add(text);
3174    elm_gengrid_item_tooltip_content_cb_set
3175      (it, _elm_gengrid_item_label_create, text,
3176      _elm_gengrid_item_label_del_cb);
3177 }
3178
3179 EAPI void
3180 elm_gengrid_item_tooltip_content_cb_set(Elm_Object_Item *item,
3181                                         Elm_Tooltip_Item_Content_Cb func,
3182                                         const void *data,
3183                                         Evas_Smart_Cb del_cb)
3184 {
3185    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3186
3187    ELM_GENGRID_ITEM_CHECK_OR_GOTO(it, error);
3188
3189    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
3190      return;
3191
3192    if (it->tooltip.del_cb)
3193      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3194    it->tooltip.content_cb = func;
3195    it->tooltip.data = data;
3196    it->tooltip.del_cb = del_cb;
3197    if (VIEW(it))
3198      {
3199         elm_widget_item_tooltip_content_cb_set
3200           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
3201         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
3202         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
3203      }
3204
3205    return;
3206
3207 error:
3208    if (del_cb) del_cb((void *)data, NULL, NULL);
3209 }
3210
3211 EAPI void
3212 elm_gengrid_item_tooltip_unset(Elm_Object_Item *item)
3213 {
3214    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3215
3216    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3217
3218    if ((VIEW(it)) && (it->tooltip.content_cb))
3219      elm_widget_item_tooltip_unset(it);
3220
3221    if (it->tooltip.del_cb)
3222      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3223    it->tooltip.del_cb = NULL;
3224    it->tooltip.content_cb = NULL;
3225    it->tooltip.data = NULL;
3226    it->tooltip.free_size = EINA_FALSE;
3227    if (it->tooltip.style)
3228      elm_gengrid_item_tooltip_style_set(item, NULL);
3229 }
3230
3231 EAPI void
3232 elm_gengrid_item_tooltip_style_set(Elm_Object_Item *it,
3233                                    const char *style)
3234 {
3235    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3236
3237    eina_stringshare_replace(&((Elm_Gen_Item *)it)->tooltip.style, style);
3238    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
3239 }
3240
3241 EAPI const char *
3242 elm_gengrid_item_tooltip_style_get(const Elm_Object_Item *it)
3243 {
3244    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3245
3246    return ((Elm_Gen_Item *)it)->tooltip.style;
3247 }
3248
3249 EAPI Eina_Bool
3250 elm_gengrid_item_tooltip_window_mode_set(Elm_Object_Item *it,
3251                                          Eina_Bool disable)
3252 {
3253    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3254
3255    ((Elm_Gen_Item *)it)->tooltip.free_size = disable;
3256    if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
3257
3258    return EINA_TRUE;
3259 }
3260
3261 EAPI Eina_Bool
3262 elm_gengrid_item_tooltip_window_mode_get(const Elm_Object_Item *it)
3263 {
3264    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3265
3266    return ((Elm_Gen_Item *)it)->tooltip.free_size;
3267 }
3268
3269 EAPI void
3270 elm_gengrid_item_cursor_set(Elm_Object_Item *it,
3271                             const char *cursor)
3272 {
3273    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3274
3275    eina_stringshare_replace(&((Elm_Gen_Item *)it)->mouse_cursor, cursor);
3276    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
3277 }
3278
3279 EAPI const char *
3280 elm_gengrid_item_cursor_get(const Elm_Object_Item *it)
3281 {
3282    return elm_widget_item_cursor_get(it);
3283 }
3284
3285 EAPI void
3286 elm_gengrid_item_cursor_unset(Elm_Object_Item *item)
3287 {
3288    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3289
3290    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3291    if (!it->mouse_cursor)
3292      return;
3293
3294    if (VIEW(it))
3295      elm_widget_item_cursor_unset(it);
3296
3297    eina_stringshare_del(it->mouse_cursor);
3298    it->mouse_cursor = NULL;
3299 }
3300
3301 EAPI void
3302 elm_gengrid_item_cursor_style_set(Elm_Object_Item *it,
3303                                   const char *style)
3304 {
3305    elm_widget_item_cursor_style_set(it, style);
3306 }
3307
3308 EAPI const char *
3309 elm_gengrid_item_cursor_style_get(const Elm_Object_Item *it)
3310 {
3311    return elm_widget_item_cursor_style_get(it);
3312 }
3313
3314 EAPI void
3315 elm_gengrid_item_cursor_engine_only_set(Elm_Object_Item *it,
3316                                         Eina_Bool engine_only)
3317 {
3318    elm_widget_item_cursor_engine_only_set(it, engine_only);
3319 }
3320
3321 EAPI Eina_Bool
3322 elm_gengrid_item_cursor_engine_only_get(const Elm_Object_Item *it)
3323 {
3324    return elm_widget_item_cursor_engine_only_get(it);
3325 }
3326
3327 EAPI void
3328 elm_gengrid_reorder_mode_set(Evas_Object *obj,
3329                              Eina_Bool reorder_mode)
3330 {
3331    ELM_GENGRID_CHECK(obj);
3332    ELM_GENGRID_DATA_GET(obj, sd);
3333
3334    sd->reorder_mode = !!reorder_mode;
3335 }
3336
3337 EAPI Eina_Bool
3338 elm_gengrid_reorder_mode_get(const Evas_Object *obj)
3339 {
3340    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3341    ELM_GENGRID_DATA_GET(obj, sd);
3342
3343    return sd->reorder_mode;
3344 }
3345
3346 EAPI void
3347 elm_gengrid_bounce_set(Evas_Object *obj,
3348                        Eina_Bool h_bounce,
3349                        Eina_Bool v_bounce)
3350 {
3351    ELM_GENGRID_CHECK(obj);
3352    ELM_GENGRID_DATA_GET(obj, sd);
3353
3354    sd->s_iface->bounce_allow_set(obj, !!h_bounce, !!v_bounce);
3355 }
3356
3357 EAPI void
3358 elm_gengrid_bounce_get(const Evas_Object *obj,
3359                        Eina_Bool *h_bounce,
3360                        Eina_Bool *v_bounce)
3361 {
3362    ELM_GENGRID_CHECK(obj);
3363    ELM_GENGRID_DATA_GET(obj, sd);
3364
3365    sd->s_iface->bounce_allow_get(obj, h_bounce, v_bounce);
3366 }
3367
3368 EAPI void
3369 elm_gengrid_page_relative_set(Evas_Object *obj,
3370                               double h_pagerel,
3371                               double v_pagerel)
3372 {
3373    Evas_Coord pagesize_h;
3374    Evas_Coord pagesize_v;
3375
3376    ELM_GENGRID_CHECK(obj);
3377    ELM_GENGRID_DATA_GET(obj, sd);
3378
3379    sd->s_iface->paging_get(obj, NULL, NULL, &pagesize_h, &pagesize_v);
3380    sd->s_iface->paging_set
3381      (obj, h_pagerel, v_pagerel, pagesize_h, pagesize_v);
3382 }
3383
3384 EAPI void
3385 elm_gengrid_page_relative_get(const Evas_Object *obj,
3386                               double *h_pagerel,
3387                               double *v_pagerel)
3388 {
3389    ELM_GENGRID_CHECK(obj);
3390    ELM_GENGRID_DATA_GET(obj, sd);
3391
3392    sd->s_iface->paging_get(obj, h_pagerel, v_pagerel, NULL, NULL);
3393 }
3394
3395 EAPI void
3396 elm_gengrid_page_size_set(Evas_Object *obj,
3397                           Evas_Coord h_pagesize,
3398                           Evas_Coord v_pagesize)
3399 {
3400    double pagerel_h;
3401    double pagerel_v;
3402
3403    ELM_GENGRID_CHECK(obj);
3404    ELM_GENGRID_DATA_GET(obj, sd);
3405
3406    sd->s_iface->paging_get(obj, &pagerel_h, &pagerel_v, NULL, NULL);
3407    sd->s_iface->paging_set
3408      (obj, pagerel_h, pagerel_v, h_pagesize, v_pagesize);
3409 }
3410
3411 EAPI void
3412 elm_gengrid_current_page_get(const Evas_Object *obj,
3413                              int *h_pagenumber,
3414                              int *v_pagenumber)
3415 {
3416    ELM_GENGRID_CHECK(obj);
3417    ELM_GENGRID_DATA_GET(obj, sd);
3418
3419    sd->s_iface->current_page_get(obj, h_pagenumber, v_pagenumber);
3420 }
3421
3422 EAPI void
3423 elm_gengrid_last_page_get(const Evas_Object *obj,
3424                           int *h_pagenumber,
3425                           int *v_pagenumber)
3426 {
3427    ELM_GENGRID_CHECK(obj);
3428    ELM_GENGRID_DATA_GET(obj, sd);
3429
3430    sd->s_iface->last_page_get(obj, h_pagenumber, v_pagenumber);
3431 }
3432
3433 EAPI void
3434 elm_gengrid_page_show(const Evas_Object *obj,
3435                       int h_pagenumber,
3436                       int v_pagenumber)
3437 {
3438    ELM_GENGRID_CHECK(obj);
3439    ELM_GENGRID_DATA_GET(obj, sd);
3440
3441    sd->s_iface->page_show((Evas_Object *)obj, h_pagenumber, v_pagenumber);
3442 }
3443
3444 EAPI void
3445 elm_gengrid_page_bring_in(const Evas_Object *obj,
3446                           int h_pagenumber,
3447                           int v_pagenumber)
3448 {
3449    ELM_GENGRID_CHECK(obj);
3450    ELM_GENGRID_DATA_GET(obj, sd);
3451
3452    sd->s_iface->page_bring_in((Evas_Object *)obj, h_pagenumber, v_pagenumber);
3453 }
3454
3455 EAPI void
3456 elm_gengrid_scroller_policy_set(Evas_Object *obj,
3457                                 Elm_Scroller_Policy policy_h,
3458                                 Elm_Scroller_Policy policy_v)
3459 {
3460    ELM_GENGRID_CHECK(obj);
3461    ELM_GENGRID_DATA_GET(obj, sd);
3462
3463    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
3464        (policy_v >= ELM_SCROLLER_POLICY_LAST))
3465      return;
3466
3467    sd->s_iface->policy_set(obj, policy_h, policy_v);
3468 }
3469
3470 EAPI void
3471 elm_gengrid_scroller_policy_get(const Evas_Object *obj,
3472                                 Elm_Scroller_Policy *policy_h,
3473                                 Elm_Scroller_Policy *policy_v)
3474 {
3475    Elm_Scroller_Policy s_policy_h, s_policy_v;
3476
3477    ELM_GENGRID_CHECK(obj);
3478    ELM_GENGRID_DATA_GET(obj, sd);
3479
3480    sd->s_iface->policy_get(obj, &s_policy_h, &s_policy_v);
3481    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
3482    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
3483 }
3484
3485 EAPI Elm_Object_Item *
3486 elm_gengrid_first_item_get(const Evas_Object *obj)
3487 {
3488    ELM_GENGRID_CHECK(obj) NULL;
3489    ELM_GENGRID_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
3490
3491    if (!sd->items) return NULL;
3492
3493    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
3494
3495    while ((it) && (it->generation < sd->generation))
3496      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3497
3498    return (Elm_Object_Item *)it;
3499 }
3500
3501 EAPI Elm_Object_Item *
3502 elm_gengrid_last_item_get(const Evas_Object *obj)
3503 {
3504    ELM_GENGRID_CHECK(obj) NULL;
3505    ELM_GENGRID_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
3506
3507    if (!sd->items) return NULL;
3508
3509    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
3510    while ((it) && (it->generation < sd->generation))
3511      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3512
3513    return (Elm_Object_Item *)it;
3514 }
3515
3516 EAPI Elm_Object_Item *
3517 elm_gengrid_item_next_get(const Elm_Object_Item *item)
3518 {
3519    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3520
3521    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3522
3523    while (it)
3524      {
3525         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3526         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
3527      }
3528
3529    return (Elm_Object_Item *)it;
3530 }
3531
3532 EAPI Elm_Object_Item *
3533 elm_gengrid_item_prev_get(const Elm_Object_Item *item)
3534 {
3535    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3536
3537    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
3538
3539    while (it)
3540      {
3541         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3542         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
3543      }
3544
3545    return (Elm_Object_Item *)it;
3546 }
3547
3548 EAPI void
3549 elm_gengrid_item_show(Elm_Object_Item *item,
3550                       Elm_Gengrid_Item_Scrollto_Type type __UNUSED__)
3551 {
3552    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3553    Elm_Gengrid_Smart_Data *sd;
3554
3555    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3556    sd = GG_IT(it)->wsd;
3557
3558    if ((it->generation < sd->generation)) return;
3559
3560    sd->show_region = EINA_TRUE;
3561    sd->show_it = it;
3562
3563    if (sd->calc_job) ecore_job_del(sd->calc_job);
3564    sd->calc_job = ecore_job_add(_calc_job, sd);
3565 }
3566
3567 EAPI void
3568 elm_gengrid_item_bring_in(Elm_Object_Item *item,
3569                           Elm_Gengrid_Item_Scrollto_Type type __UNUSED__)
3570 {
3571    Elm_Gengrid_Smart_Data *sd;
3572    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3573
3574    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3575    sd = GG_IT(it)->wsd;
3576
3577    if (it->generation < sd->generation) return;
3578
3579    sd->bring_in = EINA_TRUE;
3580    sd->bring_in_it = it;
3581
3582    if (sd->calc_job) ecore_job_del(sd->calc_job);
3583    sd->calc_job = ecore_job_add(_calc_job, sd);
3584 }
3585
3586 EAPI void
3587 elm_gengrid_filled_set(Evas_Object *obj,
3588                        Eina_Bool fill)
3589 {
3590    ELM_GENGRID_CHECK(obj);
3591    ELM_GENGRID_DATA_GET(obj, sd);
3592
3593    fill = !!fill;
3594    if (sd->filled != fill)
3595      sd->filled = fill;
3596 }
3597
3598 EAPI Eina_Bool
3599 elm_gengrid_filled_get(const Evas_Object *obj)
3600 {
3601    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3602    ELM_GENGRID_DATA_GET(obj, sd);
3603
3604    return sd->filled;
3605 }
3606
3607 EAPI unsigned int
3608 elm_gengrid_items_count(const Evas_Object *obj)
3609 {
3610    ELM_GENGRID_CHECK(obj) 0;
3611    ELM_GENGRID_DATA_GET(obj, sd);
3612
3613    return sd->item_count;
3614 }
3615
3616 EAPI Elm_Gengrid_Item_Class *
3617 elm_gengrid_item_class_new(void)
3618 {
3619    Elm_Gengrid_Item_Class *itc;
3620
3621    itc = calloc(1, sizeof(Elm_Gengrid_Item_Class));
3622    if (!itc)
3623      return NULL;
3624    itc->version = CLASS_ALLOCATED;
3625    itc->refcount = 1;
3626    itc->delete_me = EINA_FALSE;
3627
3628    return itc;
3629 }
3630
3631 EAPI void
3632 elm_gengrid_item_class_free(Elm_Gengrid_Item_Class *itc)
3633 {
3634    if (!itc || (itc->version != CLASS_ALLOCATED)) return;
3635
3636    if (!itc->delete_me) itc->delete_me = EINA_TRUE;
3637    if (itc->refcount > 0) elm_gengrid_item_class_unref(itc);
3638    else
3639      {
3640         itc->version = 0;
3641         free(itc);
3642      }
3643 }
3644
3645 EAPI void
3646 elm_gengrid_item_class_ref(Elm_Gengrid_Item_Class *itc)
3647 {
3648    if (itc && (itc->version == CLASS_ALLOCATED))
3649      {
3650         itc->refcount++;
3651         if (itc->refcount == 0) itc->refcount--;
3652      }
3653 }
3654
3655 EAPI void
3656 elm_gengrid_item_class_unref(Elm_Gengrid_Item_Class *itc)
3657 {
3658    if (itc && (itc->version == CLASS_ALLOCATED))
3659      {
3660         if (itc->refcount > 0) itc->refcount--;
3661         if (itc->delete_me && (!itc->refcount))
3662           elm_gengrid_item_class_free(itc);
3663      }
3664 }
3665
3666 EAPI void
3667 elm_gengrid_select_mode_set(Evas_Object *obj,
3668                             Elm_Object_Select_Mode mode)
3669 {
3670    ELM_GENGRID_CHECK(obj);
3671    ELM_GENGRID_DATA_GET(obj, sd);
3672
3673    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
3674      return;
3675
3676    if (sd->select_mode != mode)
3677      sd->select_mode = mode;
3678 }
3679
3680 EAPI Elm_Object_Select_Mode
3681 elm_gengrid_select_mode_get(const Evas_Object *obj)
3682 {
3683    ELM_GENGRID_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
3684    ELM_GENGRID_DATA_GET(obj, sd);
3685
3686    return sd->select_mode;
3687 }
3688
3689 EAPI void
3690 elm_gengrid_highlight_mode_set(Evas_Object *obj,
3691                                Eina_Bool highlight)
3692 {
3693    ELM_GENGRID_CHECK(obj);
3694    ELM_GENGRID_DATA_GET(obj, sd);
3695
3696    sd->highlight = !!highlight;
3697 }
3698
3699 EAPI Eina_Bool
3700 elm_gengrid_highlight_mode_get(const Evas_Object *obj)
3701 {
3702    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3703    ELM_GENGRID_DATA_GET(obj, sd);
3704
3705    return sd->highlight;
3706 }
3707
3708 EAPI int
3709 elm_gengrid_item_index_get(const Elm_Object_Item *item)
3710 {
3711    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3712
3713    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, -1);
3714
3715    return it->position;
3716 }
3717
3718 EAPI void
3719 elm_gengrid_item_select_mode_set(Elm_Object_Item *item,
3720                                  Elm_Object_Select_Mode mode)
3721 {
3722    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3723
3724    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3725
3726    if (it->generation < GG_IT(it)->wsd->generation) return;
3727    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
3728      return;
3729
3730    if (it->select_mode != mode)
3731      it->select_mode = mode;
3732
3733    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3734      elm_gengrid_item_update(item);
3735 }
3736
3737 EAPI Elm_Object_Select_Mode
3738 elm_gengrid_item_select_mode_get(const Elm_Object_Item *item)
3739 {
3740    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3741
3742    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
3743
3744    return it->select_mode;
3745 }
3746
3747 #if GENGRID_FX_SUPPORT
3748 EAPI void
3749 elm_gengrid_fx_mode_set(Evas_Object *obj, Eina_Bool mode)
3750 {
3751    ELM_GENGRID_CHECK(obj);
3752    ELM_GENGRID_DATA_GET(obj, sd);
3753
3754    sd->fx_mode = mode;
3755 }
3756
3757 EAPI Eina_Bool
3758 elm_gengrid_fx_mode_get(const Evas_Object *obj)
3759 {
3760    ELM_GENGRID_CHECK(obj) EINA_FALSE;
3761    ELM_GENGRID_DATA_GET(obj, sd);
3762
3763    return sd->fx_mode;
3764 }
3765
3766 static Proxy_Item *
3767 _elm_gengrid_proxy_item_new(const Elm_Object_Item *item)
3768 {
3769    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3770    if ((!it) || (!it->item)) return EINA_FALSE;
3771    int w, h;
3772
3773    Proxy_Item *pi = NULL;
3774    pi = calloc(1, sizeof(Proxy_Item));
3775    if (!pi) return NULL;
3776
3777    pi->proxy = evas_object_image_filled_add
3778       (evas_object_evas_get(ELM_WIDGET_DATA(GG_IT(it)->wsd)->obj));
3779    if (!pi->proxy) return EINA_FALSE;
3780    evas_object_clip_set(pi->proxy, evas_object_clip_get(GG_IT(it)->wsd->pan_obj));
3781    evas_object_smart_member_add(pi->proxy, GG_IT(it)->wsd->pan_obj);
3782    evas_object_hide(pi->proxy);
3783    evas_object_image_source_set(pi->proxy, VIEW(it));
3784
3785    GG_IT(it)->has_proxy_it = EINA_TRUE;
3786    pi->it = it;
3787    pi->num = it->item->num;
3788    pi->x = it->item->scrl_x;
3789    pi->y = it->item->scrl_y;
3790    pi->w = it->item->w;
3791    pi->h = it->item->h;
3792
3793    evas_object_geometry_get(VIEW(it), NULL, NULL, &w, &h);
3794
3795    if (w <= 0 || h <= 0)
3796      {
3797         evas_object_size_hint_min_get(VIEW(it), &w, &h);
3798         evas_object_size_hint_min_set(pi->proxy, w, h);
3799      }
3800    else evas_object_resize(pi->proxy, w, h);
3801
3802    return pi;
3803 }
3804
3805 static Eina_Bool
3806 _elm_gengrid_fx_capture(Evas_Object *obj, int level)
3807 {
3808    ELM_GENGRID_DATA_GET(obj, sd);
3809
3810    Elm_Gen_Item *it;
3811    Proxy_Item *pi;
3812    Evas_Coord ox, oy, ow, oh;
3813
3814    if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
3815    if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
3816    if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
3817
3818    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3819
3820    if (!level)
3821      {
3822         sd->fx_first_captured = EINA_TRUE;
3823         EINA_LIST_FREE(sd->capture_before_items, pi)
3824           {
3825              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
3826              if (pi->proxy) evas_object_del(pi->proxy);
3827              free(pi);
3828           }
3829      }
3830    else
3831      {
3832         EINA_LIST_FREE(sd->capture_after_items, pi)
3833           {
3834              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
3835              if (pi->proxy) evas_object_del(pi->proxy);
3836              free(pi);
3837           }
3838      }
3839    EINA_INLIST_FOREACH(sd->items, it)
3840      {
3841         if (it->realized)
3842           {
3843              pi = _elm_gengrid_proxy_item_new((Elm_Object_Item *)it);
3844              if (!pi) continue;
3845              if (!level)
3846                sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
3847              else
3848                sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
3849           }
3850      }
3851    return EINA_TRUE;
3852 }
3853
3854 static Elm_Gen_FX_Item *
3855 _elm_gengrid_fx_item_find(const Elm_Object_Item *item)
3856 {
3857    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
3858    if (!it) return EINA_FALSE;
3859
3860    Elm_Gengrid_Smart_Data *sd = GG_IT(it)->wsd;
3861    if (!sd) return NULL;
3862
3863    Elm_Gen_FX_Item *fi = NULL;
3864    Eina_List *l;
3865
3866    EINA_LIST_FOREACH(sd->fx_items, l, fi)
3867      {
3868         if (fi->it == it) return fi;
3869      }
3870    return NULL;
3871 }
3872
3873 static Elm_Gen_FX_Item *
3874 _elm_gengrid_fx_item_new(const Proxy_Item *pi)
3875 {
3876    if ((!pi) || (!pi->it)) return NULL;
3877
3878    Elm_Gen_FX_Item *fi = NULL;
3879    fi = calloc(1, sizeof(Elm_Gen_FX_Item));
3880    if (!fi) return NULL;
3881
3882    fi->it = pi->it;
3883    GG_IT(fi->it)->fi = fi;
3884    fi->proxy = pi->proxy;
3885    fi->num = pi->num;
3886    fi->from.x = fi->to.x = pi->x;
3887    fi->from.y = fi->to.y = pi->y;
3888    fi->from.w = fi->to.w = pi->w;
3889    fi->from.h = fi->to.h = pi->h;
3890    fi->update = EINA_FALSE;
3891
3892    return fi;
3893 }
3894
3895 EAPI void
3896 _elm_gengrid_fx_items_make(Evas_Object *obj)
3897 {
3898    ELM_GENGRID_CHECK(obj);
3899    ELM_GENGRID_DATA_GET(obj, sd);
3900
3901    Elm_Gen_FX_Item *fi;
3902    Proxy_Item *pi;
3903    Eina_List *l;
3904    Evas_Coord ox, oy, ow, oh;
3905
3906    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3907
3908    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
3909      {
3910         fi = _elm_gengrid_fx_item_new(pi);
3911         if (fi) sd->fx_items = eina_list_append(sd->fx_items, fi);
3912      }
3913
3914    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
3915      {
3916         fi = _elm_gengrid_fx_item_find((Elm_Object_Item *)pi->it);
3917
3918         if (fi)
3919           {
3920              fi->type = ELM_GEN_ITEM_FX_TYPE_SAME;
3921              fi->update = EINA_TRUE;
3922              fi->to.x = pi->x;
3923              fi->to.y = pi->y;
3924              fi->to.w = pi->w;
3925              fi->to.h = pi->h;
3926           }
3927         else
3928           {
3929              fi = _elm_gengrid_fx_item_new(pi);
3930              if (fi)
3931                {
3932                   fi->type = ELM_GEN_ITEM_FX_TYPE_ADD;
3933                   fi->update = EINA_TRUE;
3934                   sd->fx_items = eina_list_append(sd->fx_items, fi);
3935                }
3936           }
3937      }
3938
3939    EINA_LIST_FOREACH(sd->fx_items, l, fi)
3940      {
3941         if (!fi->update)
3942           {
3943              fi->type = ELM_GEN_ITEM_FX_TYPE_DEL;
3944              fi->update = EINA_TRUE;
3945           }
3946      }
3947 }
3948
3949 static void
3950 _item_fx_op(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__, double progress __UNUSED__)
3951 {
3952    Elm_Gen_FX_Item *fi = data;
3953    Elm_Gengrid_Smart_Data *sd = GG_IT(fi->it)->wsd;
3954    if (fi->from.y == fi->to.y) evas_object_raise(fi->proxy);
3955    evas_object_raise(sd->alpha_bg);
3956    return;
3957 }
3958
3959
3960 static void
3961 _item_fx_done(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__)
3962 {
3963    Elm_Gen_FX_Item *fx_done_it = data;
3964    Elm_Gengrid_Smart_Data *sd = GG_IT(fx_done_it->it)->wsd;
3965
3966    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
3967
3968    evas_object_image_source_visible_set(fx_done_it->proxy, EINA_TRUE);
3969    evas_object_lower(fx_done_it->proxy);
3970
3971    evas_object_move(VIEW(fx_done_it->it), fx_done_it->to.x, fx_done_it->to.y);
3972    GG_IT(fx_done_it->it)->has_proxy_it = EINA_FALSE;
3973
3974    evas_object_clip_unset(fx_done_it->proxy);
3975 }
3976
3977 static void
3978 _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
3979 {
3980    Elm_Gen_FX_Item *fx_done_it = data;
3981    Elm_Gen_Item *it = NULL;
3982    Proxy_Item *pi = NULL;
3983    Eina_List *l;
3984    Elm_Gengrid_Smart_Data *sd = GG_IT(fx_done_it->it)->wsd;
3985
3986    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
3987
3988    sd->fx_items = eina_list_remove(sd->fx_items, fx_done_it);
3989    free(fx_done_it);
3990
3991    if (!eina_list_count(sd->fx_items))
3992      {
3993         EINA_LIST_FREE (sd->pending_unrealized_items, it)
3994           {
3995              GG_IT(it)->has_proxy_it = EINA_FALSE;
3996              _elm_gengrid_item_unrealize(it, EINA_FALSE);
3997           }
3998
3999         EINA_LIST_FREE (sd->pending_del_items, it)
4000           {
4001              _item_del(it);
4002              _elm_widget_item_free((Elm_Widget_Item *)it);
4003           }
4004         EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
4005            evas_object_hide(pi->proxy);
4006         EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
4007            evas_object_hide(pi->proxy);
4008
4009         sd->fx_playing = EINA_FALSE;
4010         sd->fx_first_captured = EINA_FALSE;
4011         evas_object_hide(sd->alpha_bg);
4012
4013         sd->pan_changed = EINA_TRUE;
4014         evas_object_smart_changed(sd->pan_obj);
4015      }
4016 }
4017
4018 static Evas_Object *
4019 _tray_alpha_bg_create(const Evas_Object *obj)
4020 {
4021    Evas_Object *bg = NULL;
4022    Evas_Coord ox, oy, ow, oh;
4023
4024    ELM_GENGRID_CHECK(obj) NULL;
4025    ELM_GENGRID_DATA_GET(obj, sd);
4026
4027    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4028    bg = evas_object_rectangle_add
4029       (evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4030    evas_object_color_set(bg, 0, 0, 0, 0);
4031    evas_object_resize(bg, ow, oh);
4032    evas_object_move(bg, ox, oy);
4033
4034    return bg;
4035 }
4036
4037 static void
4038 _elm_gengrid_fx_play(Evas_Object *obj)
4039 {
4040    ELM_GENGRID_CHECK(obj);
4041    ELM_GENGRID_DATA_GET(obj, sd);
4042
4043    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
4044    Elm_Gen_FX_Item *fi;
4045    Eina_List *l;
4046
4047    if (!sd->fx_mode) return;
4048
4049    EINA_LIST_FREE(sd->fx_items, fi)
4050      {
4051         if (fi->trans) elm_transit_del(fi->trans);
4052         free(fi);
4053      }
4054
4055    _elm_gengrid_fx_items_make(obj);
4056    if (!eina_list_count(sd->fx_items)) return;
4057    sd->fx_playing = EINA_TRUE;
4058
4059    if (!sd->alpha_bg) sd->alpha_bg = _tray_alpha_bg_create(obj);
4060    evas_object_show(sd->alpha_bg);
4061
4062    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4063    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
4064
4065    EINA_LIST_FOREACH(sd->fx_items, l, fi)
4066      {
4067         if (!fi->proxy) continue;
4068
4069         if ((fi->from.y <= oy) || (fi->from.y + fi->from.h >= oy + oh))
4070           {
4071              evas_object_move(VIEW(fi->it), fi->to.x, fi->to.y);
4072           }
4073         else if ((fi->to.y <= oy) || (fi->to.y + fi->to.h >= oy + oh))
4074           {
4075              evas_object_move(VIEW(fi->it), fi->from.x, fi->from.y);
4076           }
4077
4078         evas_object_resize(fi->proxy, fi->to.w, fi->to.h);
4079         evas_object_show(fi->proxy);
4080
4081         fi->trans = elm_transit_add();
4082         elm_transit_object_add(fi->trans, fi->proxy);
4083
4084         evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
4085         elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
4086
4087         if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME)
4088           {
4089              evas_object_raise(fi->proxy);
4090              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4091           }
4092
4093         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
4094           {
4095              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4096              elm_transit_effect_color_add(fi->trans, 0, 0, 0, 0, 255, 255, 255, 255);
4097              elm_transit_effect_zoom_add(fi->trans, 0.5, 1.0);
4098           }
4099         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
4100           {
4101              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
4102              elm_transit_effect_color_add(fi->trans, 255, 255, 255, 255, 0, 0, 0, 0);
4103              elm_transit_effect_zoom_add(fi->trans, 1.0, 0.5);
4104           }
4105         elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
4106         elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
4107
4108         elm_transit_duration_set(fi->trans, FX_MOVE_TIME);
4109         elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
4110         elm_transit_go(fi->trans);
4111      }
4112 }
4113 #endif