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