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