[elementary/index] Some APIs were modified or removed + fix build
[framework/uifw/elementary.git] / src / lib / elm_index.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_box.h"
4
5 typedef struct _Widget_Data Widget_Data;
6 typedef struct _Elm_Index_Item Elm_Index_Item;
7
8 struct _Widget_Data
9 {
10    Evas_Object *base;
11    Evas_Object *event[2];
12    Evas_Object *bx[2]; // 2 - for now all that's supported
13    Eina_List *items; // 1 list. yes N levels, but only 2 for now and # of items will be small
14    int level;
15    Evas_Coord dx, dy;
16    Ecore_Timer *delay;
17    Eina_Bool level_active[2];
18    Eina_Bool horizontal : 1;
19    Eina_Bool autohide_disabled : 1;
20    Eina_Bool down : 1;
21    Eina_Bool indicator_disabled : 1;
22 };
23
24 struct _Elm_Index_Item
25 {
26    ELM_WIDGET_ITEM;
27    const char *letter;
28    int level;
29    Evas_Smart_Cb func;
30    Eina_Bool selected : 1;
31 };
32
33 static const char *widtype = NULL;
34
35 static void _del_hook(Evas_Object *obj);
36 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
37 static void _theme_hook(Evas_Object *obj);
38 static void _sizing_eval(Evas_Object *obj);
39 static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
40 static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
41 static void _item_free(Elm_Index_Item *it);
42
43 static const char SIG_CHANGED[] = "changed";
44 static const char SIG_DELAY_CHANGED[] = "delay,changed";
45 static const char SIG_SELECTED[] = "selected";
46 static const char SIG_LEVEL_UP[] = "level,up";
47 static const char SIG_LEVEL_DOWN[] = "level,down";
48
49 static const Evas_Smart_Cb_Description _signals[] = {
50    {SIG_CHANGED, ""},
51    {SIG_DELAY_CHANGED, ""},
52    {SIG_SELECTED, ""},
53    {SIG_LEVEL_UP, ""},
54    {SIG_LEVEL_DOWN, ""},
55    {NULL, NULL}
56 };
57
58 static void
59 _del_pre_hook(Evas_Object *obj)
60 {
61    Widget_Data *wd = elm_widget_data_get(obj);
62    Elm_Index_Item *it;
63    if (!wd) return;
64    _index_box_clear(obj, wd->bx[wd->level], wd->level);
65    _index_box_clear(obj, wd->bx[0], 0);
66    while (wd->items)
67      {
68         it = wd->items->data;
69         _item_free(it);
70         elm_widget_item_free(it);
71      }
72    if (wd->delay) ecore_timer_del(wd->delay);
73 }
74
75 static void
76 _del_hook(Evas_Object *obj)
77 {
78    Widget_Data *wd = elm_widget_data_get(obj);
79    free(wd);
80 }
81
82 static void
83 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
84 {
85    Widget_Data *wd = data;
86    if (!wd) return;
87    _els_box_layout(o, priv, wd->horizontal, 1, 0);
88 }
89
90 static void
91 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
92 {
93    Widget_Data *wd = elm_widget_data_get(obj);
94    if (!wd) return;
95    edje_object_signal_emit(wd->base, emission, source);
96 }
97
98 static void
99 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
100 {
101    Widget_Data *wd = elm_widget_data_get(obj);
102    if (!wd) return;
103    edje_object_signal_callback_add(wd->base, emission, source, func_cb, data);
104 }
105
106 static void
107 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
108 {
109    Widget_Data *wd = elm_widget_data_get(obj);
110    edje_object_signal_callback_del_full(wd->base, emission, source, func_cb,
111                                         data);
112 }
113
114 static void
115 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
116 {
117    Widget_Data *wd = elm_widget_data_get(obj);
118    if (!wd) return;
119    if (!wd->horizontal)
120      edje_object_mirrored_set(wd->base, rtl);
121 }
122
123 static void
124 _theme_hook(Evas_Object *obj)
125 {
126    Evas_Coord minw = 0, minh = 0;
127    Widget_Data *wd = elm_widget_data_get(obj);
128    if (!wd) return;
129    _elm_widget_mirrored_reload(obj);
130
131    _index_box_clear(obj, wd->bx[0], 0);
132    _index_box_clear(obj, wd->bx[1], 1);
133    if (wd->horizontal)
134      _elm_theme_object_set(obj, wd->base, "index", "base/horizontal", elm_widget_style_get(obj));
135    else
136      {
137         _elm_theme_object_set(obj, wd->base, "index", "base/vertical", elm_widget_style_get(obj));
138         _mirrored_set(obj, elm_widget_mirrored_get(obj));
139      }
140    edje_object_part_swallow(wd->base, "elm.swallow.event.0", wd->event[0]);
141    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
142    evas_object_size_hint_min_set(wd->event[0], minw, minh);
143    edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
144    if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
145      {
146         if (!wd->bx[1])
147           {
148              wd->bx[1] = evas_object_box_add(evas_object_evas_get(wd->base));
149              evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
150              elm_widget_sub_object_add(obj, wd->bx[1]);
151           }
152         edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
153         evas_object_show(wd->bx[1]);
154      }
155    else if (wd->bx[1])
156      {
157         evas_object_del(wd->bx[1]);
158         wd->bx[1] = NULL;
159      }
160    if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
161      {
162         if (!wd->event[1])
163           {
164              wd->event[1] = evas_object_rectangle_add(evas_object_evas_get(wd->base));
165              evas_object_color_set(wd->event[1], 0, 0, 0, 0);
166              elm_widget_sub_object_add(obj, wd->event[1]);
167           }
168         edje_object_part_swallow(wd->base, "elm.swallow.event.1", wd->event[1]);
169         evas_object_size_hint_min_set(wd->event[1], minw, minh);
170      }
171    else if (wd->event[1])
172      {
173         evas_object_del(wd->event[1]);
174         wd->event[1] = NULL;
175      }
176    edje_object_message_signal_process(wd->base);
177    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
178    _sizing_eval(obj);
179    _index_box_auto_fill(obj, wd->bx[0], 0);
180    if (wd->autohide_disabled)
181      if (wd->level == 1)
182        _index_box_auto_fill(obj, wd->bx[1], 1);
183 }
184
185 static void
186 _sizing_eval(Evas_Object *obj)
187 {
188    Widget_Data *wd = elm_widget_data_get(obj);
189    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
190    if (!wd) return;
191    edje_object_size_min_calc(wd->base, &minw, &minh);
192    evas_object_size_hint_min_set(obj, minw, minh);
193    evas_object_size_hint_max_set(obj, maxw, maxh);
194 }
195
196 static Eina_Bool
197 _item_del_pre_hook(Elm_Object_Item *it)
198 {
199    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
200    if (!wd) return EINA_FALSE;
201    _item_free((Elm_Index_Item *) it);
202    _index_box_clear(WIDGET(it), wd->bx[wd->level], wd->level);
203    return EINA_TRUE;
204 }
205
206 static Elm_Index_Item *
207 _item_new(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
208 {
209    Widget_Data *wd = elm_widget_data_get(obj);
210    Elm_Index_Item *it;
211    if (!wd) return NULL;
212    it = elm_widget_item_new(obj, Elm_Index_Item);
213    if (!it) return NULL;
214    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
215    if (letter) it->letter = eina_stringshare_add(letter);
216    it->func = func;
217    it->base.data = data;
218    it->level = wd->level;
219    return it;
220 }
221
222 static Elm_Index_Item *
223 _item_find(Evas_Object *obj, const void *data)
224 {
225    Widget_Data *wd = elm_widget_data_get(obj);
226    Eina_List *l;
227    Elm_Index_Item *it;
228    if (!wd) return NULL;
229    EINA_LIST_FOREACH(wd->items, l, it)
230      if (it->base.data == data) return it;
231    return NULL;
232 }
233
234 static void
235 _item_free(Elm_Index_Item *it)
236 {
237    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
238    if (!wd) return;
239    wd->items = eina_list_remove(wd->items, it);
240    if (it->letter) eina_stringshare_del(it->letter);
241 }
242
243 // FIXME: always have index filled
244 static void
245 _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
246 {
247    Widget_Data *wd = elm_widget_data_get(obj);
248    Eina_Bool rtl;
249    Eina_List *l;
250    Elm_Index_Item *it;
251    Evas_Coord mw, mh, w, h;
252    int i = 0;
253    if (!wd) return;
254    if (wd->level_active[level]) return;
255    rtl = elm_widget_mirrored_get(obj);
256    evas_object_geometry_get(box, NULL, NULL, &w, &h);
257    EINA_LIST_FOREACH(wd->items, l, it)
258      {
259         Evas_Object *o;
260         const char *stacking;
261
262         if (it->level != level) continue;
263         o = edje_object_add(evas_object_evas_get(obj));
264         VIEW(it) = o;
265         edje_object_mirrored_set(VIEW(it), rtl);
266         if (i & 0x1)
267           _elm_theme_object_set(obj, o, "index", "item_odd/vertical", elm_widget_style_get(obj));
268         else
269           _elm_theme_object_set(obj, o, "index", "item/vertical", elm_widget_style_get(obj));
270         edje_object_part_text_set(o, "elm.text", it->letter);
271         edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
272         evas_object_size_hint_min_set(o, mw, mh);
273         evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
274         evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
275         elm_widget_sub_object_add(obj, o);
276         evas_object_box_append(box, o);
277         stacking = edje_object_data_get(o, "stacking");
278         if (stacking)
279           {
280              if (!strcmp(stacking, "below")) evas_object_lower(o);
281              else if (!strcmp(stacking, "above")) evas_object_raise(o);
282           }
283         evas_object_show(o);
284         i++;
285         evas_object_smart_calculate(box); // force a calc so we know the size
286         evas_object_size_hint_min_get(box, &mw, &mh);
287         if (mh > h)
288           {
289              _index_box_clear(obj, box, level);
290              if (i > 0)
291                {
292                   // FIXME: only i objects fit! try again. overflows right now
293                }
294           }
295      }
296    evas_object_smart_calculate(box);
297    wd->level_active[level] = 1;
298 }
299
300 static void
301 _index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
302 {
303    Widget_Data *wd = elm_widget_data_get(obj);
304    Eina_List *l;
305    Elm_Index_Item *it;
306    if (!wd) return;
307    if (!wd->level_active[level]) return;
308    EINA_LIST_FOREACH(wd->items, l, it)
309      {
310         if (!VIEW(it)) continue;
311         if (it->level != level) continue;
312         evas_object_del(VIEW(it));
313         VIEW(it) = NULL;
314      }
315    wd->level_active[level] = 0;
316 }
317
318 static Eina_Bool
319 _delay_change(void *data)
320 {
321    Widget_Data *wd = elm_widget_data_get(data);
322    Elm_Object_Item *item;
323    if (!wd) return ECORE_CALLBACK_CANCEL;
324    wd->delay = NULL;
325    item = elm_index_item_selected_get(data, wd->level);
326    if (item) evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, item);
327    return ECORE_CALLBACK_CANCEL;
328 }
329
330 static void
331 _sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
332 {
333    Widget_Data *wd = elm_widget_data_get(obj);
334    Elm_Index_Item *it, *it_closest, *it_last;
335    Eina_List *l;
336    Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
337    double cdv = 0.5;
338    Evas_Coord dist;
339    char *label = NULL, *last = NULL;
340    int i;
341    if (!wd) return;
342    for (i = 0; i <= wd->level; i++)
343      {
344         it_last = NULL;
345         it_closest  = NULL;
346         dist = 0x7fffffff;
347         evas_object_geometry_get(wd->bx[i], &bx, &by, &bw, &bh);
348         EINA_LIST_FOREACH(wd->items, l, it)
349           {
350              if (!((it->level == i) && (VIEW(it)))) continue;
351              if ((VIEW(it)) && (it->level != wd->level))
352                {
353                   if (it->selected)
354                     {
355                        it_closest = it;
356                        break;
357                     }
358                   continue;
359                }
360              if (it->selected)
361                {
362                   it_last = it;
363                   it->selected = 0;
364                }
365              evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
366              xx = x + (w / 2);
367              yy = y + (h / 2);
368              x = evx - xx;
369              y = evy - yy;
370              x = (x * x) + (y * y);
371              if ((x < dist) || (!it_closest))
372                {
373                   if (wd->horizontal)
374                     cdv = (double)(xx - bx) / (double)bw;
375                   else
376                     cdv = (double)(yy - by) / (double)bh;
377                   it_closest = it;
378                   dist = x;
379                }
380           }
381         if ((i == 0) && (wd->level == 0))
382           edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1",
383                                           cdv, cdv);
384         if (it_closest) it_closest->selected = 1;
385         if (it_closest != it_last)
386           {
387              if (it_last)
388                {
389                   const char *stacking, *selectraise;
390
391                   it = it_last;
392                   edje_object_signal_emit(VIEW(it), "elm,state,inactive", "elm");
393                   stacking = edje_object_data_get(VIEW(it), "stacking");
394                   selectraise = edje_object_data_get(VIEW(it), "selectraise");
395                   if ((selectraise) && (!strcmp(selectraise, "on")))
396                     {
397                        if ((stacking) && (!strcmp(stacking, "below")))
398                          evas_object_lower(VIEW(it));
399                     }
400                }
401              if (it_closest)
402                {
403                   const char *selectraise;
404
405                   it = it_closest;
406                   edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
407                   selectraise = edje_object_data_get(VIEW(it), "selectraise");
408                   if ((selectraise) && (!strcmp(selectraise, "on")))
409                     evas_object_raise(VIEW(it));
410                   evas_object_smart_callback_call((void *)obj, SIG_CHANGED, (void *)it);
411                   if (wd->delay) ecore_timer_del(wd->delay);
412                   wd->delay = ecore_timer_add(0.2, _delay_change, obj);
413                }
414           }
415         if (it_closest)
416           {
417              it = it_closest;
418              if (!last)
419                last = strdup(it->letter);
420              else
421                {
422                   if (!label) label = strdup(last);
423                   else
424                     {
425                        /* FIXME: realloc return NULL if the request fails */
426                        label = realloc(label, strlen(label) + strlen(last) + 1);
427                        strcat(label, last);
428                     }
429                   free(last);
430                   last = strdup(it->letter);
431                }
432           }
433      }
434    if (!label) label = strdup("");
435    if (!last) last = strdup("");
436    edje_object_part_text_set(wd->base, "elm.text.body", label);
437    edje_object_part_text_set(wd->base, "elm.text", last);
438    free(label);
439    free(last);
440 }
441
442 static void
443 _wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
444 {
445    Widget_Data *wd = elm_widget_data_get(data);
446    //   Evas_Event_Mouse_Wheel *ev = event_info;
447    //   Evas_Object *obj = o;
448    if (!wd) return;
449 }
450
451 static void
452 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
453 {
454    Widget_Data *wd = elm_widget_data_get(data);
455    Evas_Event_Mouse_Down *ev = event_info;
456    Evas_Coord x, y, w;
457    if (!wd) return;
458    if (ev->button != 1) return;
459    wd->down = 1;
460    evas_object_geometry_get(wd->base, &x, &y, &w, NULL);
461    wd->dx = ev->canvas.x - x;
462    wd->dy = ev->canvas.y - y;
463    if (!wd->autohide_disabled)
464      {
465         _index_box_clear(data, wd->bx[1], 1);
466         _index_box_auto_fill(data, wd->bx[0], 0);
467         edje_object_signal_emit(wd->base, "elm,state,active", "elm");
468      }
469    _sel_eval(data, ev->canvas.x, ev->canvas.y);
470    edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer",
471                                    (!edje_object_mirrored_get(wd->base)) ? wd->dx : (wd->dx - w), wd->dy);
472    if (wd->items && !wd->indicator_disabled)
473      edje_object_signal_emit(wd->base, "elm,indicator,state,active", "elm");
474 }
475
476 static void
477 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
478 {
479    Widget_Data *wd = elm_widget_data_get(data);
480    Evas_Event_Mouse_Up *ev = event_info;
481    Elm_Object_Item *item;
482    Elm_Index_Item *id_item;
483    if (!wd) return;
484    if (ev->button != 1) return;
485    wd->down = 0;
486    item = elm_index_item_selected_get(data, wd->level);
487    if (item)
488      {
489         evas_object_smart_callback_call(data, SIG_SELECTED, item);
490         id_item = (Elm_Index_Item *) item;
491         if (id_item->func)
492           id_item->func((void *)id_item->base.data, WIDGET(id_item), id_item);
493      }
494    if (!wd->autohide_disabled)
495      edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
496    edje_object_signal_emit(wd->base, "elm,state,level,0", "elm");
497    if (wd->items && !wd->indicator_disabled)
498      edje_object_signal_emit(wd->base, "elm,indicator,state,inactive", "elm");
499 }
500
501 static void
502 _mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
503 {
504    Widget_Data *wd = elm_widget_data_get(data);
505    Evas_Event_Mouse_Move *ev = event_info;
506    Evas_Coord minw = 0, minh = 0, x, y, dx, adx, w;
507    char buf[1024];
508    if (!wd) return;
509    if (!wd->down) return;
510    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
511    evas_object_geometry_get(wd->base, &x, &y, &w, NULL);
512    x = ev->cur.canvas.x - x;
513    y = ev->cur.canvas.y - y;
514    dx = x - wd->dx;
515    adx = dx;
516    if (adx < 0) adx = -dx;
517    edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer"
518                                    , (!edje_object_mirrored_get(wd->base)) ? x : (x - w), y);
519    if (!wd->horizontal)
520      {
521         if (adx > minw)
522           {
523              if (!wd->level)
524                {
525                   wd->level = 1;
526                   snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
527                   edje_object_signal_emit(wd->base, buf, "elm");
528                   evas_object_smart_callback_call(data, SIG_LEVEL_UP, NULL);
529                }
530           }
531         else
532           {
533              if (wd->level == 1)
534                {
535                   wd->level = 0;
536                   snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
537                   edje_object_signal_emit(wd->base, buf, "elm");
538                   evas_object_smart_callback_call(data, SIG_LEVEL_DOWN, NULL);
539                }
540           }
541      }
542    _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
543 }
544
545 EAPI Evas_Object *
546 elm_index_add(Evas_Object *parent)
547 {
548    Evas_Object *obj;
549    Evas_Object *o;
550    Evas *e;
551    Widget_Data *wd;
552    Evas_Coord minw, minh;
553
554    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
555
556    ELM_SET_WIDTYPE(widtype, "index");
557    elm_widget_type_set(obj, "index");
558    elm_widget_sub_object_add(parent, obj);
559    elm_widget_data_set(obj, wd);
560    elm_widget_del_hook_set(obj, _del_hook);
561    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
562    elm_widget_theme_hook_set(obj, _theme_hook);
563    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
564    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
565    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
566    elm_widget_can_focus_set(obj, EINA_FALSE);
567
568    wd->indicator_disabled = EINA_FALSE;
569    wd->horizontal = EINA_FALSE;
570    wd->autohide_disabled = EINA_FALSE;
571
572    wd->base = edje_object_add(e);
573    _elm_theme_object_set(obj, wd->base, "index", "base/vertical", "default");
574    elm_widget_resize_object_set(obj, wd->base);
575
576    o = evas_object_rectangle_add(e);
577    wd->event[0] = o;
578    evas_object_color_set(o, 0, 0, 0, 0);
579    minw = minh = 0;
580    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
581    evas_object_size_hint_min_set(o, minw, minh);
582    edje_object_part_swallow(wd->base, "elm.swallow.event.0", o);
583    elm_widget_sub_object_add(obj, o);
584    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _wheel, obj);
585    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
586    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
587    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
588    evas_object_show(o);
589    if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
590      {
591         o = evas_object_rectangle_add(e);
592         wd->event[1] = o;
593         evas_object_color_set(o, 0, 0, 0, 0);
594         evas_object_size_hint_min_set(o, minw, minh);
595         edje_object_part_swallow(wd->base, "elm.swallow.event.1", o);
596         elm_widget_sub_object_add(obj, o);
597      }
598
599    wd->bx[0] = evas_object_box_add(e);
600    evas_object_box_layout_set(wd->bx[0], _layout, wd, NULL);
601    elm_widget_sub_object_add(obj, wd->bx[0]);
602    edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
603    evas_object_show(wd->bx[0]);
604
605    if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
606      {
607         wd->bx[1] = evas_object_box_add(e);
608         evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
609         elm_widget_sub_object_add(obj, wd->bx[1]);
610         edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
611         evas_object_show(wd->bx[1]);
612      }
613
614    evas_object_smart_callbacks_descriptions_set(obj, _signals);
615
616    _mirrored_set(obj, elm_widget_mirrored_get(obj));
617    _sizing_eval(obj);
618    return obj;
619 }
620
621 EINA_DEPRECATED EAPI void
622 elm_index_active_set(Evas_Object *obj, Eina_Bool active)
623 {
624    elm_index_autohide_disabled_set(obj, !active);
625 }
626
627 EINA_DEPRECATED EAPI Eina_Bool
628 elm_index_active_get(const Evas_Object *obj)
629 {
630    return !elm_index_autohide_disabled_get(obj);
631 }
632
633 EAPI void
634 elm_index_autohide_disabled_set(Evas_Object *obj, Eina_Bool disabled)
635 {
636    ELM_CHECK_WIDTYPE(obj, widtype);
637    Widget_Data *wd = elm_widget_data_get(obj);
638    if (!wd) return;
639    disabled = !!disabled;
640    if (wd->autohide_disabled == disabled) return;
641    wd->autohide_disabled = disabled;
642    wd->level = 0;
643    if (wd->autohide_disabled)
644      {
645         _index_box_clear(obj, wd->bx[1], 1);
646         _index_box_auto_fill(obj, wd->bx[0], 0);
647         edje_object_signal_emit(wd->base, "elm,state,active", "elm");
648      }
649    else
650      edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
651 }
652
653 EAPI Eina_Bool
654 elm_index_autohide_disabled_get(const Evas_Object *obj)
655 {
656    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
657    Widget_Data *wd = elm_widget_data_get(obj);
658    if (!wd) return EINA_FALSE;
659    return wd->autohide_disabled;
660 }
661
662 EAPI void
663 elm_index_item_level_set(Evas_Object *obj, int level)
664 {
665    ELM_CHECK_WIDTYPE(obj, widtype);
666    Widget_Data *wd = elm_widget_data_get(obj);
667    if (!wd) return;
668    if (wd->level == level) return;
669    wd->level = level;
670 }
671
672 EAPI int
673 elm_index_item_level_get(const Evas_Object *obj)
674 {
675    ELM_CHECK_WIDTYPE(obj, widtype) 0;
676    Widget_Data *wd = elm_widget_data_get(obj);
677    if (!wd) return 0;
678    return wd->level;
679 }
680
681 EAPI Elm_Object_Item *
682 elm_index_item_selected_get(const Evas_Object *obj, int level)
683 {
684    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
685    Widget_Data *wd = elm_widget_data_get(obj);
686    Eina_List *l;
687    Elm_Index_Item *it;
688    if (!wd) return NULL;
689    EINA_LIST_FOREACH(wd->items, l, it)
690      {
691         if ((it->selected) && (it->level == level))
692           return (Elm_Object_Item *) it;
693      }
694    return NULL;
695 }
696
697 EAPI Elm_Object_Item *
698 elm_index_item_append(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
699 {
700    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
701    Widget_Data *wd = elm_widget_data_get(obj);
702    Elm_Index_Item *it;
703    if (!wd) return NULL;
704    it = _item_new(obj, letter, func, data);
705    if (!it) return NULL;
706    wd->items = eina_list_append(wd->items, it);
707    _index_box_clear(obj, wd->bx[wd->level], wd->level);
708    return (Elm_Object_Item *) it;
709 }
710
711 EAPI Elm_Object_Item *
712 elm_index_item_prepend(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
713 {
714    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
715    Widget_Data *wd = elm_widget_data_get(obj);
716    Elm_Index_Item *it;
717
718    if (!wd) return NULL;
719    it = _item_new(obj, letter, func, data);
720    if (!it) return NULL;
721    wd->items = eina_list_prepend(wd->items, it);
722    _index_box_clear(obj, wd->bx[wd->level], wd->level);
723    return (Elm_Object_Item *) it;
724 }
725
726 EINA_DEPRECATED EAPI Elm_Object_Item *
727 elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const Elm_Object_Item *relative)
728 {
729    return elm_index_item_insert_after(obj, (Elm_Object_Item *) relative, letter, NULL, item);
730 }
731
732 EINA_DEPRECATED EAPI Elm_Object_Item *
733 elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const Elm_Object_Item *relative)
734 {
735    return elm_index_item_insert_before(obj, (Elm_Object_Item *) relative, letter, NULL, item);
736 }
737
738 EAPI Elm_Object_Item *
739 elm_index_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *letter, Evas_Smart_Cb func, const void *data)
740 {
741    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
742    Widget_Data *wd = elm_widget_data_get(obj);
743    Elm_Index_Item *it;
744    if (!wd) return NULL;
745    if (!after) return elm_index_item_append(obj, letter, func, data);
746    it = _item_new(obj, letter, func, data);
747    if (!it) return NULL;
748    wd->items = eina_list_append_relative(wd->items, it, after);
749    _index_box_clear(obj, wd->bx[wd->level], wd->level);
750    return (Elm_Object_Item *) it;
751 }
752
753 EAPI Elm_Object_Item *
754 elm_index_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *letter, Evas_Smart_Cb func, const void *data)
755 {
756    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
757    Widget_Data *wd = elm_widget_data_get(obj);
758    Elm_Index_Item *it;
759    if (!wd) return NULL;
760    if (!before) return elm_index_item_prepend(obj, letter, func, data);
761    it = _item_new(obj, letter, func, data);
762    if (!it) return NULL;
763    wd->items = eina_list_prepend_relative(wd->items, it, before);
764    _index_box_clear(obj, wd->bx[wd->level], wd->level);
765    return (Elm_Object_Item *) it;
766 }
767
768 EAPI Elm_Object_Item *
769 elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func)
770 {
771    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
772    Widget_Data *wd = elm_widget_data_get(obj);
773    Eina_List *lnear;
774    Elm_Index_Item *it;
775    int cmp;
776
777    if (!wd) return NULL;
778    if (!(wd->items))
779      return elm_index_item_append(obj, letter, func, data);
780
781    it = _item_new(obj, letter, func, data);
782    if (!it) return NULL;
783
784    lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
785    if (cmp < 0)
786      wd->items =  eina_list_append_relative_list(wd->items, it, lnear);
787    else if (cmp > 0)
788      wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
789    else
790      {
791         /* If cmp_data_func is not provided, append a duplicated item */
792         if (!cmp_data_func)
793           wd->items =  eina_list_append_relative_list(wd->items, it, lnear);
794         else
795           {
796              Elm_Index_Item *p_it = eina_list_data_get(lnear);
797              if (cmp_data_func(p_it->base.data, it->base.data) >= 0)
798                p_it->base.data = it->base.data;
799              _item_free(it);
800              elm_widget_item_free(it);
801           }
802      }
803    _index_box_clear(obj, wd->bx[wd->level], wd->level);
804    return (Elm_Object_Item *) it;
805 }
806
807 EAPI void
808 elm_index_item_del(Evas_Object *obj __UNUSED__, Elm_Object_Item *it)
809 {
810    elm_object_item_del(it);
811 }
812
813 EAPI Elm_Object_Item *
814 elm_index_item_find(Evas_Object *obj, const void *data)
815 {
816    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
817    Widget_Data *wd = elm_widget_data_get(obj);
818    if (!wd) return NULL;
819    return (Elm_Object_Item *) _item_find(obj, data);
820 }
821
822 EAPI void
823 elm_index_item_clear(Evas_Object *obj)
824 {
825    ELM_CHECK_WIDTYPE(obj, widtype);
826    Widget_Data *wd = elm_widget_data_get(obj);
827    Elm_Index_Item *it;
828    Eina_List *l, *clear = NULL;
829    if (!wd) return;
830    _index_box_clear(obj, wd->bx[wd->level], wd->level);
831    EINA_LIST_FOREACH(wd->items, l, it)
832      {
833         if (it->level != wd->level) continue;
834         clear = eina_list_append(clear, it);
835      }
836    EINA_LIST_FREE(clear, it)
837      {
838         _item_free(it);
839         elm_widget_item_free(it);
840      }
841 }
842
843 EINA_DEPRECATED EAPI void
844 elm_index_item_go(Evas_Object *obj, int level __UNUSED__)
845 {
846    elm_index_level_go(obj, level);
847 }
848
849 EAPI void
850 elm_index_level_go(Evas_Object *obj, int level __UNUSED__)
851 {
852    ELM_CHECK_WIDTYPE(obj, widtype);
853    Widget_Data *wd = elm_widget_data_get(obj);
854    if (!wd) return;
855    _index_box_auto_fill(obj, wd->bx[0], 0);
856    if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
857 }
858
859 EAPI void *
860 elm_index_item_data_get(const Elm_Object_Item *it)
861 {
862    return elm_object_item_data_get(it);
863 }
864
865 EAPI void
866 elm_index_item_data_set(Elm_Object_Item *it, const void *data)
867 {
868    elm_object_item_data_set(it, (void *) data);
869 }
870
871 EAPI void
872 elm_index_indicator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
873 {
874    ELM_CHECK_WIDTYPE(obj, widtype);
875    Widget_Data *wd = elm_widget_data_get(obj);
876    if (!wd) return;
877
878    disabled = !!disabled;
879    if (wd->indicator_disabled == disabled) return;
880    wd->indicator_disabled = disabled;
881    if (!wd->items) return;
882    if (disabled)
883      edje_object_signal_emit(wd->base, "elm,indicator,state,inactive", "elm");
884    else
885      edje_object_signal_emit(wd->base, "elm,indicator,state,active", "elm");
886 }
887
888 EAPI Eina_Bool
889 elm_index_indicator_disabled_get(const Evas_Object *obj)
890 {
891    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
892    Widget_Data *wd = elm_widget_data_get(obj);
893    if (!wd) return EINA_FALSE;
894
895    return wd->indicator_disabled;
896 }
897
898 EAPI void
899 elm_index_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb func)
900 {
901    elm_object_item_del_cb_set(it, func);
902 }
903
904 EAPI const char *
905 elm_index_item_letter_get(const Elm_Object_Item *it)
906 {
907    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
908    return ((Elm_Index_Item *) it)->letter;
909 }
910