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