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