Fix the elm_shutdown bug in _elm_shutdown_config.
[framework/uifw/elementary.git] / src / lib / elm_index.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_box.h"
4 #include "elm_widget_index.h"
5
6 EAPI const char ELM_INDEX_SMART_NAME[] = "elm_index";
7
8 #define INDEX_DELAY_CHANGE_TIME 0.2
9
10 static const char SIG_CHANGED[] = "changed";
11 static const char SIG_DELAY_CHANGED[] = "delay,changed";
12 static const char SIG_SELECTED[] = "selected";
13 static const char SIG_LEVEL_UP[] = "level,up";
14 static const char SIG_LEVEL_DOWN[] = "level,down";
15 static const char SIG_LANG_CHANGED[] = "language,changed";
16
17 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
18    {SIG_CHANGED, ""},
19    {SIG_DELAY_CHANGED, ""},
20    {SIG_SELECTED, ""},
21    {SIG_LEVEL_UP, ""},
22    {SIG_LEVEL_DOWN, ""},
23    {SIG_LANG_CHANGED, ""},
24    {NULL, NULL}
25 };
26
27 EVAS_SMART_SUBCLASS_NEW
28   (ELM_INDEX_SMART_NAME, _elm_index, Elm_Index_Smart_Class,
29   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
30
31 static Eina_Bool
32 _elm_index_smart_translate(Evas_Object *obj)
33 {
34    evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
35    return EINA_TRUE;
36 }
37
38 static void
39 _item_free(Elm_Index_Item *it)
40 {
41    ELM_INDEX_DATA_GET(WIDGET(it), sd);
42
43    sd->items = eina_list_remove(sd->items, it);
44
45    if (it->omitted)
46      it->omitted = eina_list_free(it->omitted);
47
48    if (it->letter)
49      eina_stringshare_del(it->letter);
50 }
51
52 static void
53 _box_custom_layout(Evas_Object *o,
54                    Evas_Object_Box_Data *priv,
55                    void *data)
56 {
57    Elm_Index_Smart_Data *sd = data;
58
59    _els_box_layout(o, priv, sd->horizontal, 1, 0);
60 }
61
62 static void
63 _index_box_clear(Evas_Object *obj,
64                  Evas_Object *box __UNUSED__,
65                  int level)
66 {
67    Eina_List *l;
68    Elm_Index_Item *it;
69
70    ELM_INDEX_DATA_GET(obj, sd);
71
72    if (!sd->level_active[level]) return;
73
74    EINA_LIST_FOREACH(sd->items, l, it)
75      {
76         if (!VIEW(it)) continue;
77         if (it->level != level) continue;
78
79         evas_object_del(VIEW(it));
80         VIEW(it) = NULL;
81      }
82
83    sd->level_active[level] = 0;
84 }
85
86 static char *
87 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
88 {
89    const char *txt = NULL;
90
91    Elm_Index_Item *it = (Elm_Index_Item *)data;
92    ELM_INDEX_ITEM_CHECK_OR_RETURN(it, NULL);
93
94    txt = elm_widget_access_info_get(obj);
95    if (!txt) txt = it->letter;
96    if (txt) return strdup(txt);
97
98    return NULL;
99 }
100
101 static void
102 _access_widget_item_activate_cb(void *data __UNUSED__,
103                                 Evas_Object *part_obj __UNUSED__,
104                                 Elm_Object_Item *it)
105 {
106    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
107 }
108
109 static void
110 _access_widget_item_register(Elm_Index_Item *it)
111 {
112    Elm_Access_Info *ai;
113
114    _elm_access_widget_item_register((Elm_Widget_Item *)it);
115
116    ai = _elm_access_object_get(it->base.access_obj);
117
118    _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Index Item"));
119    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
120    _elm_access_activate_callback_set
121      (ai, _access_widget_item_activate_cb, NULL);
122 }
123
124 static void
125 _omit_calc(void *data, int num_of_items, int max_num_of_items)
126 {
127    Elm_Index_Smart_Data *sd = data;
128    int max_group_num, num_of_extra_items, i, g, size, sum, *group_pos, *omit_info;
129    Elm_Index_Omit *o;
130    Elm_Index_Item *it;
131    Eina_List *l;
132
133    EINA_LIST_FREE(sd->omit, o)
134      free(o);
135
136    EINA_LIST_FOREACH(sd->items, l, it)
137      {
138         if (it->omitted)
139           it->omitted = eina_list_free(it->omitted);
140         if (it->head) it->head = NULL;
141      }
142
143    if ((max_num_of_items < 3) || (num_of_items <= max_num_of_items)) return;
144
145    max_group_num = (max_num_of_items - 1) / 2;
146    num_of_extra_items = num_of_items - max_num_of_items;
147
148    group_pos = (int *)malloc(sizeof(int) * max_group_num);
149    omit_info = (int *)malloc(sizeof(int) * max_num_of_items);
150
151    if (num_of_extra_items >= max_group_num)
152      {
153         g = 1;
154         for (i = 0; i < max_group_num; i++)
155           {
156              group_pos[i] = g;
157              g += 2;
158           }
159      }
160    else
161      {
162         size = max_num_of_items / (num_of_extra_items + 1);
163         g = size;
164         for (i = 0; i < num_of_extra_items; i++)
165           {
166              group_pos[i] = g;
167              g += size;
168           }
169      }
170    for (i = 0; i < max_num_of_items; i++)
171      omit_info[i] = 1;
172    for (i = 0; i < num_of_extra_items; i++)
173      omit_info[group_pos[i % max_group_num]]++;
174
175    sum = 0;
176    for (i = 0; i < max_num_of_items; i++)
177      {
178         if (omit_info[i] > 1)
179           {
180              o = (Elm_Index_Omit *)malloc(sizeof(Elm_Index_Omit));
181              o->offset = sum;
182              o->count = omit_info[i];
183              sd->omit = eina_list_append(sd->omit, o);
184           }
185         sum += omit_info[i];
186      }
187
188    free(group_pos);
189    free(omit_info);
190 }
191
192 // FIXME: always have index filled
193 static void
194 _index_box_auto_fill(Evas_Object *obj,
195                      Evas_Object *box,
196                      int level)
197 {
198    int i = 0, max_num_of_items = 0, num_of_items = 0, g = 0, skip = 0;
199    Eina_List *l;
200    Eina_Bool rtl;
201    Elm_Index_Item *it, *head = NULL;
202    Evas_Coord mw, mh, ih;
203    Evas_Object *o;
204    Elm_Index_Omit *om;
205
206    ELM_INDEX_DATA_GET(obj, sd);
207
208    if (sd->level_active[level]) return;
209
210    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, NULL, NULL, NULL, &ih);
211
212    rtl = elm_widget_mirrored_get(obj);
213
214    if (sd->omit_enabled)
215      {
216         o = edje_object_add(evas_object_evas_get(obj));
217         elm_widget_theme_object_set
218            (obj, o, "index", "item/vertical",
219             elm_widget_style_get(obj));
220
221         edje_object_size_min_restricted_calc(o, NULL, &mh, 0, 0);
222
223         EINA_LIST_FOREACH(sd->items, l, it)
224            if (it->level == level) num_of_items++;
225
226         if (mh != 0)
227           max_num_of_items = ih / mh;
228
229         _omit_calc(sd, num_of_items, max_num_of_items);
230      }
231
232    om = eina_list_nth(sd->omit, g);
233    EINA_LIST_FOREACH(sd->items, l, it)
234      {
235         const char *stacking;
236
237         if (it->level != level) continue;
238
239         if ((om) && (i == om->offset))
240           {
241              skip = om->count;
242              skip--;
243              head = it;
244              it->head = head;
245              head->omitted = eina_list_append(head->omitted, it);
246              om = eina_list_nth(sd->omit, ++g);
247           }
248         else if (skip > 0)
249           {
250              skip--;
251              i++;
252              if (head)
253                {
254                   it->head = head;
255                   head->omitted = eina_list_append(head->omitted, it);
256                }
257              continue;
258           }
259
260         o = edje_object_add(evas_object_evas_get(obj));
261         VIEW(it) = o;
262         edje_object_mirrored_set(VIEW(it), rtl);
263
264         if (sd->horizontal)
265           {
266              if (i & 0x1)
267                elm_widget_theme_object_set
268                  (obj, o, "index", "item_odd/horizontal",
269                  elm_widget_style_get(obj));
270              else
271                elm_widget_theme_object_set
272                  (obj, o, "index", "item/horizontal",
273                  elm_widget_style_get(obj));
274           }
275         else
276           {
277              if (i & 0x1)
278                elm_widget_theme_object_set
279                  (obj, o, "index", "item_odd/vertical",
280                  elm_widget_style_get(obj));
281              else
282                elm_widget_theme_object_set
283                  (obj, o, "index", "item/vertical",
284                  elm_widget_style_get(obj));
285           }
286
287         if (skip > 0)
288           edje_object_part_text_escaped_set(o, "elm.text", "*");
289         else
290           edje_object_part_text_escaped_set(o, "elm.text", it->letter);
291         edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
292         evas_object_size_hint_min_set(o, mw, mh);
293         evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
294         evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
295         elm_widget_sub_object_add(obj, o);
296         evas_object_box_append(box, o);
297         stacking = edje_object_data_get(o, "stacking");
298
299         if (stacking)
300           {
301              if (!strcmp(stacking, "below")) evas_object_lower(o);
302              else if (!strcmp(stacking, "above"))
303                evas_object_raise(o);
304           }
305
306         evas_object_show(o);
307
308         i++;
309
310         // ACCESS
311         if ((it->level == 0) && (_elm_config->access_mode))
312           _access_widget_item_register(it);
313      }
314
315    // TIZEN ONLY adjust the last item's theme according to winset gui
316    if (sd->items)
317      {
318         it = eina_list_nth(sd->items, i - 1);
319         edje_object_signal_emit(VIEW(it), "elm,last,item", "elm");
320      }
321    // TIZEN ONLY
322
323    evas_object_smart_calculate(box);
324    sd->level_active[level] = 1;
325 }
326
327 static void
328 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
329 {
330    ELM_INDEX_DATA_GET(obj, sd);
331
332    if (!sd->horizontal)
333      edje_object_mirrored_set(ELM_WIDGET_DATA(sd)->resize_obj, rtl);
334 }
335
336 static Eina_Bool
337 _elm_index_smart_theme(Evas_Object *obj)
338 {
339    Evas_Coord minw = 0, minh = 0;
340    Elm_Index_Item *it;
341
342    ELM_INDEX_DATA_GET(obj, sd);
343
344    _index_box_clear(obj, sd->bx[0], 0);
345    _index_box_clear(obj, sd->bx[1], 1);
346
347    if (sd->horizontal)
348      eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "base/horizontal");
349    else
350      {
351         eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "base/vertical");
352         _mirrored_set(obj, elm_widget_mirrored_get(obj));
353      }
354
355    if (!ELM_WIDGET_CLASS(_elm_index_parent_sc)->theme(obj)) return EINA_FALSE;
356
357    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
358    evas_object_size_hint_min_set(sd->event[0], minw, minh);
359
360    if (edje_object_part_exists
361          (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.index.1"))
362      {
363         if (!sd->bx[1])
364           {
365              sd->bx[1] = evas_object_box_add(evas_object_evas_get(obj));
366              evas_object_box_layout_set
367                (sd->bx[1], _box_custom_layout, sd, NULL);
368              elm_widget_sub_object_add(obj, sd->bx[1]);
369           }
370         elm_layout_content_set(obj, "elm.swallow.index.1", sd->bx[1]);
371      }
372    else if (sd->bx[1])
373      {
374         evas_object_del(sd->bx[1]);
375         sd->bx[1] = NULL;
376      }
377    if (edje_object_part_exists
378          (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.event.1"))
379      {
380         if (!sd->event[1])
381           {
382              sd->event[1] =
383                evas_object_rectangle_add(evas_object_evas_get(obj));
384              evas_object_color_set(sd->event[1], 0, 0, 0, 0);
385              elm_widget_sub_object_add(obj, sd->event[1]);
386           }
387         elm_layout_content_set(obj, "elm.swallow.event.1", sd->event[1]);
388         evas_object_size_hint_min_set(sd->event[1], minw, minh);
389      }
390    else if (sd->event[1])
391      {
392         evas_object_del(sd->event[1]);
393         sd->event[1] = NULL;
394      }
395    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
396
397    elm_layout_sizing_eval(obj);
398    _index_box_auto_fill(obj, sd->bx[0], 0);
399
400    if (sd->autohide_disabled)
401      {
402         if (sd->level == 1) _index_box_auto_fill(obj, sd->bx[1], 1);
403         elm_layout_signal_emit(obj, "elm,state,active", "elm");
404      }
405    else elm_layout_signal_emit(obj, "elm,state,inactive", "elm");
406
407    it = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
408    if (it)
409      {
410         if (it->head)
411           edje_object_signal_emit(VIEW(it->head), "elm,state,active", "elm");
412         else
413           edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
414      }
415
416    return EINA_TRUE;
417 }
418
419 static void
420 _elm_index_smart_sizing_eval(Evas_Object *obj)
421 {
422    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
423
424    ELM_INDEX_DATA_GET(obj, sd);
425
426    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
427    evas_object_size_hint_min_set(obj, minw, minh);
428    evas_object_size_hint_max_set(obj, maxw, maxh);
429 }
430
431 static Eina_Bool
432 _item_del_pre_hook(Elm_Object_Item *it)
433 {
434    ELM_INDEX_DATA_GET(WIDGET(it), sd);
435
436    _item_free((Elm_Index_Item *)it);
437    _index_box_clear(WIDGET(it), sd->bx[sd->level], sd->level);
438
439    return EINA_TRUE;
440 }
441
442 static Elm_Index_Item *
443 _item_new(Evas_Object *obj,
444           const char *letter,
445           Evas_Smart_Cb func,
446           const void *data)
447 {
448    Elm_Index_Item *it;
449
450    ELM_INDEX_DATA_GET(obj, sd);
451
452    it = elm_widget_item_new(obj, Elm_Index_Item);
453    if (!it) return NULL;
454
455    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
456    if (letter) it->letter = eina_stringshare_add(letter);
457    it->func = func;
458    it->base.data = data;
459    it->level = sd->level;
460
461    return it;
462 }
463
464 static Elm_Index_Item *
465 _item_find(Evas_Object *obj,
466            const void *data)
467 {
468    Eina_List *l;
469    Elm_Index_Item *it;
470
471    ELM_INDEX_DATA_GET(obj, sd);
472
473    EINA_LIST_FOREACH(sd->items, l, it)
474      if (it->base.data == data) return it;
475
476    return NULL;
477 }
478
479 static Eina_Bool
480 _delay_change_cb(void *data)
481 {
482    Elm_Object_Item *item;
483
484    ELM_INDEX_DATA_GET(data, sd);
485
486    sd->delay = NULL;
487    item = elm_index_selected_item_get(data, sd->level);
488    if (item) evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, item);
489
490    return ECORE_CALLBACK_CANCEL;
491 }
492
493 static void
494 _sel_eval(Evas_Object *obj,
495           Evas_Coord evx,
496           Evas_Coord evy)
497 {
498    Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
499    Elm_Index_Item *it, *it_closest, *it_last, *om_closest;
500    char *label = NULL, *last = NULL;
501    double cdv = 0.5;
502    Evas_Coord dist;
503    Eina_List *l;
504    int i, j, size, dh, dx, dy;
505
506    ELM_INDEX_DATA_GET(obj, sd);
507
508    for (i = 0; i <= sd->level; i++)
509      {
510         it_last = NULL;
511         it_closest = NULL;
512         om_closest = NULL;
513         dist = 0x7fffffff;
514         evas_object_geometry_get(sd->bx[i], &bx, &by, &bw, &bh);
515
516         EINA_LIST_FOREACH(sd->items, l, it)
517           {
518              if (it->level != i) continue;
519              if (it->level != sd->level)
520                {
521                   if (it->selected)
522                     {
523                        it_closest = it;
524                        break;
525                     }
526                   continue;
527                }
528              if (it->selected)
529                {
530                   it_last = it;
531                   it->selected = 0;
532                }
533              if (VIEW(it))
534                {
535                   evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
536                   xx = x + (w / 2);
537                   yy = y + (h / 2);
538                   x = evx - xx;
539                   y = evy - yy;
540                   x = (x * x) + (y * y);
541                   if ((x < dist) || (!it_closest))
542                     {
543                        if (sd->horizontal)
544                          cdv = (double)(xx - bx) / (double)bw;
545                        else
546                          cdv = (double)(yy - by) / (double)bh;
547                        it_closest = it;
548                        dist = x;
549                     }
550                }
551           }
552         if ((i == 0) && (sd->level == 0))
553           edje_object_part_drag_value_set
554             (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.index.1", cdv, cdv);
555
556         if (it_closest && it_closest->omitted)
557           {
558              it = it_closest;
559              size = eina_list_count(it->omitted);
560              evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
561              dist = 0x7fffffff;
562              dh = h / size;
563              if (dh == 0)
564                printf("too many index items to omit\n"); //FIXME
565              else
566                {
567                   for (j = 0; j < size; j++)
568                     {
569                        xx = x + (w / 2);
570                        yy = y + (dh * j) + (dh / 2);
571                        dx = evx - xx;
572                        dy = evy - yy;
573                        dx = (dx * dx) + (dy * dy);
574                        if ((dx < dist) || (!om_closest))
575                          {
576                             om_closest = eina_list_nth(it->omitted, j);
577                             dist = dx;
578                          }
579                     }
580                }
581           }
582
583         if (om_closest) om_closest->selected = 1;
584         else if (it_closest) it_closest->selected = 1;
585
586         if (it_closest != it_last)
587           {
588              if (it_last)
589                {
590                   const char *stacking, *selectraise;
591
592                   it = it_last;
593                   if (it->head)
594                     {
595                        if (it->head != it_closest) it = it->head;
596                        else it = NULL;
597                     }
598                   if (it)
599                     {
600                        edje_object_signal_emit
601                           (VIEW(it), "elm,state,inactive", "elm");
602                        stacking = edje_object_data_get(VIEW(it), "stacking");
603                        selectraise = edje_object_data_get(VIEW(it), "selectraise");
604                        if ((selectraise) && (!strcmp(selectraise, "on")))
605                          {
606                             if ((stacking) && (!strcmp(stacking, "below")))
607                               evas_object_lower(VIEW(it));
608                          }
609                     }
610                }
611              if (it_closest)
612                {
613                   const char *selectraise;
614
615                   it = it_closest;
616
617                   if (!((it_last) && (it_last->head) && (it_last->head == it_closest)))
618                     {
619                        edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
620                        selectraise = edje_object_data_get(VIEW(it), "selectraise");
621                        if ((selectraise) && (!strcmp(selectraise, "on")))
622                          evas_object_raise(VIEW(it));
623                     }
624
625                   if (om_closest)
626                     evas_object_smart_callback_call
627                        (obj, SIG_CHANGED, om_closest);
628                   else
629                     evas_object_smart_callback_call
630                        (obj, SIG_CHANGED, it);
631                   if (sd->delay) ecore_timer_del(sd->delay);
632                   sd->delay = ecore_timer_add(sd->delay_change_time,
633                                               _delay_change_cb, obj);
634                }
635           }
636         if (it_closest)
637           {
638              if (om_closest) it = om_closest;
639              else it = it_closest;
640              if (!last && it->letter) last = strdup(it->letter);
641              else
642                {
643                   if (!label && last) label = strdup(last);
644                   else
645                     {
646                        if (label && last)
647                          {
648                             label = realloc(label, strlen(label) +
649                                             strlen(last) + 1);
650                             if (!label) return;
651                             strcat(label, last);
652                          }
653                     }
654                   free(last);
655                   if (it->letter) last = strdup(it->letter);
656                }
657           }
658      }
659    if (!label) label = strdup("");
660    if (!last) last = strdup("");
661
662    elm_layout_text_set(obj, "elm.text.body", label);
663    elm_layout_text_set(obj, "elm.text", last);
664
665    free(label);
666    free(last);
667 }
668
669 static void
670 _on_mouse_wheel(void *data __UNUSED__,
671                 Evas *e __UNUSED__,
672                 Evas_Object *o __UNUSED__,
673                 void *event_info __UNUSED__)
674 {
675 }
676
677 static void
678 _on_mouse_down(void *data,
679                Evas *e __UNUSED__,
680                Evas_Object *o __UNUSED__,
681                void *event_info)
682 {
683    Evas_Event_Mouse_Down *ev = event_info;
684    Evas_Coord x, y, w;
685
686    ELM_INDEX_DATA_GET(data, sd);
687
688    if (ev->button != 1) return;
689    sd->down = 1;
690    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, NULL);
691    sd->dx = ev->canvas.x - x;
692    sd->dy = ev->canvas.y - y;
693    if (!sd->autohide_disabled)
694      {
695         _index_box_clear(data, sd->bx[1], 1);
696         elm_layout_signal_emit(data, "elm,state,active", "elm");
697      }
698    _sel_eval(data, ev->canvas.x, ev->canvas.y);
699    edje_object_part_drag_value_set
700      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.pointer",
701      (!elm_object_mirrored_get(data)) ? sd->dx : (sd->dx - w), sd->dy);
702    if (sd->items && !sd->indicator_disabled)
703      elm_layout_signal_emit(data, "elm,indicator,state,active", "elm");
704 }
705
706 static void
707 _on_mouse_up(void *data,
708              Evas *e __UNUSED__,
709              Evas_Object *o __UNUSED__,
710              void *event_info)
711 {
712    Evas_Event_Mouse_Up *ev = event_info;
713    Elm_Object_Item *item;
714    Elm_Index_Item *id_item;
715
716    ELM_INDEX_DATA_GET(data, sd);
717
718    if (ev->button != 1) return;
719    sd->down = 0;
720    item = elm_index_selected_item_get(data, sd->level);
721    if (item)
722      {
723         evas_object_smart_callback_call(data, SIG_SELECTED, item);
724         id_item = (Elm_Index_Item *)item;
725         if (id_item->func)
726           id_item->func((void *)id_item->base.data, WIDGET(id_item), id_item);
727      }
728    if (!sd->autohide_disabled)
729      elm_layout_signal_emit(data, "elm,state,inactive", "elm");
730
731    elm_layout_signal_emit(data, "elm,state,level,0", "elm");
732    if (sd->items && !sd->indicator_disabled)
733      elm_layout_signal_emit(data, "elm,indicator,state,inactive", "elm");
734 }
735
736 static void
737 _on_mouse_move(void *data,
738                Evas *e __UNUSED__,
739                Evas_Object *o __UNUSED__,
740                void *event_info)
741 {
742    Evas_Event_Mouse_Move *ev = event_info;
743    Evas_Coord minw = 0, minh = 0, x, y, dx, adx, w;
744    char buf[1024];
745
746    ELM_INDEX_DATA_GET(data, sd);
747
748    if (!sd->down) return;
749    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
750    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, NULL);
751    x = ev->cur.canvas.x - x;
752    y = ev->cur.canvas.y - y;
753    dx = x - sd->dx;
754    adx = dx;
755    if (adx < 0) adx = -dx;
756    edje_object_part_drag_value_set
757      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.pointer",
758      (!edje_object_mirrored_get(ELM_WIDGET_DATA(sd)->resize_obj)) ?
759      x : (x - w), y);
760    if (!sd->horizontal)
761      {
762         if (adx > minw)
763           {
764              if (!sd->level)
765                {
766                   sd->level = 1;
767                   snprintf(buf, sizeof(buf), "elm,state,level,%i", sd->level);
768                   elm_layout_signal_emit(data, buf, "elm");
769                   evas_object_smart_callback_call(data, SIG_LEVEL_UP, NULL);
770                }
771           }
772         else
773           {
774              if (sd->level == 1)
775                {
776                   sd->level = 0;
777                   snprintf(buf, sizeof(buf), "elm,state,level,%i", sd->level);
778                   elm_layout_signal_emit(data, buf, "elm");
779                   evas_object_smart_callback_call(data, SIG_LEVEL_DOWN, NULL);
780                }
781           }
782      }
783    _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
784 }
785
786 static void
787 _access_activate_cb(void *data,
788                     Evas_Object *part_obj __UNUSED__,
789                     Elm_Object_Item *item __UNUSED__)
790 {
791    Elm_Index_Item *it;
792    ELM_INDEX_DATA_GET(data, sd);
793
794    it = eina_list_nth(sd->items, 0);
795    _elm_access_highlight_set(it->base.access_obj);
796    sd->index_focus = EINA_TRUE;
797 }
798
799 static void
800 _access_index_register(Evas_Object *obj)
801 {
802    Evas_Object *ao;
803    Elm_Access_Info *ai;
804    elm_widget_can_focus_set(obj, EINA_TRUE);
805
806    ao = _elm_access_edje_object_part_object_register
807               (obj, elm_layout_edje_get(obj), "access");
808    ai = _elm_access_object_get(ao);
809
810    _elm_access_text_set
811      (ai, ELM_ACCESS_TYPE, E_("Index"));
812    _elm_access_activate_callback_set
813      (ai, _access_activate_cb, obj);
814 }
815
816 static void
817 _index_resize_cb(void *data,
818                  Evas *e __UNUSED__,
819                  Evas_Object *obj __UNUSED__,
820                  void *event_info __UNUSED__)
821 {
822    ELM_INDEX_DATA_GET_OR_RETURN(data, sd);
823
824    if (!sd->omit_enabled) return;
825
826    Elm_Index_Item *it;
827
828    _index_box_clear(data, sd->bx[0], 0);
829    _index_box_auto_fill(data, sd->bx[0], 0);
830
831    it = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
832    if (it)
833      {
834         if (it->head)
835           edje_object_signal_emit(VIEW(it->head), "elm,state,active", "elm");
836         else
837           edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
838      }
839 }
840
841 static void
842 _elm_index_smart_add(Evas_Object *obj)
843 {
844    Evas_Object *o;
845    Evas_Coord minw, minh;
846
847    EVAS_SMART_DATA_ALLOC(obj, Elm_Index_Smart_Data);
848
849    ELM_WIDGET_CLASS(_elm_index_parent_sc)->base.add(obj);
850
851    elm_layout_theme_set
852      (obj, "index", "base/vertical", elm_widget_style_get(obj));
853
854    o = evas_object_rectangle_add(evas_object_evas_get(obj));
855    priv->event[0] = o;
856    evas_object_color_set(o, 0, 0, 0, 0);
857    minw = minh = 0;
858    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
859    evas_object_size_hint_min_set(o, minw, minh);
860    elm_layout_content_set(obj, "elm.swallow.event.0", o);
861    elm_widget_sub_object_add(obj, o);
862
863    evas_object_event_callback_add
864      (obj, EVAS_CALLBACK_RESIZE, _index_resize_cb, obj);
865    evas_object_event_callback_add
866      (o, EVAS_CALLBACK_MOUSE_WHEEL, _on_mouse_wheel, obj);
867    evas_object_event_callback_add
868      (o, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, obj);
869    evas_object_event_callback_add
870      (o, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up, obj);
871    evas_object_event_callback_add
872      (o, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move, obj);
873
874    if (edje_object_part_exists
875          (ELM_WIDGET_DATA(priv)->resize_obj, "elm.swallow.event.1"))
876      {
877         o = evas_object_rectangle_add(evas_object_evas_get(obj));
878         priv->event[1] = o;
879         evas_object_color_set(o, 0, 0, 0, 0);
880         evas_object_size_hint_min_set(o, minw, minh);
881         elm_layout_content_set(obj, "elm.swallow.event.1", o);
882         elm_widget_sub_object_add(obj, o);
883      }
884
885    priv->bx[0] = evas_object_box_add(evas_object_evas_get(obj));
886    evas_object_box_layout_set(priv->bx[0], _box_custom_layout, priv, NULL);
887    elm_widget_sub_object_add(obj, priv->bx[0]);
888    elm_layout_content_set(obj, "elm.swallow.index.0", priv->bx[0]);
889    evas_object_show(priv->bx[0]);
890
891    priv->delay_change_time = INDEX_DELAY_CHANGE_TIME;
892    priv->omit_enabled = 1;
893
894    if (edje_object_part_exists
895          (ELM_WIDGET_DATA(priv)->resize_obj, "elm.swallow.index.1"))
896      {
897         priv->bx[1] = evas_object_box_add(evas_object_evas_get(obj));
898         evas_object_box_layout_set
899           (priv->bx[1], _box_custom_layout, priv, NULL);
900         elm_widget_sub_object_add(obj, priv->bx[1]);
901         elm_layout_content_set(obj, "elm.swallow.index.1", priv->bx[1]);
902         evas_object_show(priv->bx[1]);
903      }
904
905    _mirrored_set(obj, elm_widget_mirrored_get(obj));
906    elm_layout_sizing_eval(obj);
907    elm_widget_can_focus_set(obj, EINA_FALSE);
908
909    // ACCESS
910    if (_elm_config->access_mode)
911      {
912         elm_index_autohide_disabled_set(obj, EINA_TRUE);
913         elm_layout_signal_emit(obj, "elm,access,state,active", "elm");
914         _access_index_register(obj);
915      }
916 }
917
918 static void
919 _elm_index_smart_del(Evas_Object *obj)
920 {
921    Elm_Index_Item *it;
922    Elm_Index_Omit *o;
923
924    ELM_INDEX_DATA_GET(obj, sd);
925
926    while (sd->items)
927      {
928         it = sd->items->data;
929         _item_free(it);
930         elm_widget_item_del(it);
931      }
932
933    EINA_LIST_FREE(sd->omit, o)
934      free(o);
935
936    if (sd->delay) ecore_timer_del(sd->delay);
937
938    ELM_WIDGET_CLASS(_elm_index_parent_sc)->base.del(obj);
939 }
940
941 static Eina_Bool
942 _elm_index_smart_focus_next(const Evas_Object *obj,
943                             Elm_Focus_Direction dir,
944                             Evas_Object **next)
945 {
946    Eina_List *items = NULL;
947    Eina_List *l = NULL;
948    Elm_Index_Item *it;
949    Evas_Object *ao;
950    Evas_Object *po;
951    Eina_Bool ret;
952
953    ELM_INDEX_CHECK(obj) EINA_FALSE;
954    ELM_INDEX_DATA_GET(obj, sd);
955
956    if (!sd->autohide_disabled)
957      elm_layout_signal_emit((Evas_Object *)obj, "elm,state,active", "elm");
958
959    po = (Evas_Object *)edje_object_part_object_get
960               (elm_layout_edje_get(obj), "access");
961    ao = evas_object_data_get(po, "_part_access_obj");
962    items = eina_list_append(items, ao);
963
964    if (sd->index_focus)
965      {
966       EINA_LIST_FOREACH(sd->items, l, it)
967         {
968            if (it->level != 0) continue;
969            items = eina_list_append(items, it->base.access_obj);
970         }
971      }
972
973    ret = elm_widget_focus_list_next_get
974             (obj, items, eina_list_data_get, dir, next);
975
976    if (!ret)
977      {
978         sd->index_focus = EINA_FALSE;
979
980         Evas_Object *it_access_obj = eina_list_nth(items, eina_list_count(items) - 1);
981
982         items = eina_list_free(items);
983         items = eina_list_append(items, it_access_obj);
984         items = eina_list_append(items, ao);
985
986         ret = elm_widget_focus_list_next_get(obj, items, eina_list_data_get, dir, next);
987
988         // to hide index item, if there is nothing to focus on autohide disalbe mode
989         if (!sd->autohide_disabled)
990           elm_layout_signal_emit((Evas_Object *)obj, "elm,state,inactive", "elm");
991      }
992
993    return ret;
994 }
995
996 static void
997 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
998 {
999    Eina_List *l;
1000    Elm_Index_Item *it;
1001
1002    ELM_INDEX_DATA_GET(obj, sd);
1003
1004    EINA_LIST_FOREACH(sd->items, l, it)
1005      {
1006         if (it->level != 0) continue;
1007         if (is_access) _access_widget_item_register(it);
1008         else _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
1009      }
1010
1011    if (is_access)
1012      {
1013         elm_index_autohide_disabled_set(obj, EINA_TRUE);
1014         elm_layout_signal_emit(obj, "elm,access,state,active", "elm");
1015         _access_index_register(obj);
1016      }
1017    else
1018      {
1019         // opposition of  _access_index_register();
1020         elm_index_autohide_disabled_set(obj, EINA_FALSE);
1021         elm_layout_signal_emit(obj, "elm,access,state,inactive", "elm");
1022         elm_widget_can_focus_set(obj, EINA_FALSE);
1023         _elm_access_edje_object_part_object_unregister
1024              (obj, elm_layout_edje_get(obj), "access");
1025      }
1026 }
1027
1028 static void
1029 _access_hook(Evas_Object *obj, Eina_Bool is_access)
1030 {
1031    ELM_INDEX_CHECK(obj);
1032    ELM_INDEX_DATA_GET(obj, sd);
1033
1034    if (is_access)
1035      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
1036      _elm_index_smart_focus_next;
1037    else
1038      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
1039    _access_obj_process(obj, is_access);
1040 }
1041
1042 static void
1043 _elm_index_smart_set_user(Elm_Index_Smart_Class *sc)
1044 {
1045    ELM_WIDGET_CLASS(sc)->base.add = _elm_index_smart_add;
1046    ELM_WIDGET_CLASS(sc)->base.del = _elm_index_smart_del;
1047
1048    ELM_WIDGET_CLASS(sc)->theme = _elm_index_smart_theme;
1049    ELM_WIDGET_CLASS(sc)->translate = _elm_index_smart_translate;
1050
1051    /* not a 'focus chain manager' */
1052    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
1053    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1054
1055    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_index_smart_sizing_eval;
1056
1057    if (_elm_config->access_mode)
1058      ELM_WIDGET_CLASS(sc)->focus_next = _elm_index_smart_focus_next;
1059
1060    ELM_WIDGET_CLASS(sc)->access = _access_hook;
1061 }
1062
1063 EAPI const Elm_Index_Smart_Class *
1064 elm_index_smart_class_get(void)
1065 {
1066    static Elm_Index_Smart_Class _sc =
1067      ELM_INDEX_SMART_CLASS_INIT_NAME_VERSION(ELM_INDEX_SMART_NAME);
1068    static const Elm_Index_Smart_Class *class = NULL;
1069    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1070
1071    if (class)
1072      return class;
1073
1074    _elm_index_smart_set(&_sc);
1075    esc->callbacks = _smart_callbacks;
1076    class = &_sc;
1077
1078    return class;
1079 }
1080
1081 EAPI Evas_Object *
1082 elm_index_add(Evas_Object *parent)
1083 {
1084    Evas_Object *obj;
1085
1086    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1087
1088    obj = elm_widget_add(_elm_index_smart_class_new(), parent);
1089    if (!obj) return NULL;
1090
1091    if (!elm_widget_sub_object_add(parent, obj))
1092      ERR("could not add %p as sub object of %p", obj, parent);
1093
1094    return obj;
1095 }
1096
1097 EAPI void
1098 elm_index_autohide_disabled_set(Evas_Object *obj,
1099                                 Eina_Bool disabled)
1100 {
1101    ELM_INDEX_CHECK(obj);
1102    ELM_INDEX_DATA_GET(obj, sd);
1103
1104    disabled = !!disabled;
1105    if (sd->autohide_disabled == disabled) return;
1106    sd->autohide_disabled = disabled;
1107    sd->level = 0;
1108    if (sd->autohide_disabled)
1109      {
1110         _index_box_clear(obj, sd->bx[1], 1);
1111         elm_layout_signal_emit(obj, "elm,state,active", "elm");
1112      }
1113    else
1114      elm_layout_signal_emit(obj, "elm,state,inactive", "elm");
1115
1116    //FIXME: Should be update indicator based on the indicator visiblility
1117 }
1118
1119 EAPI Eina_Bool
1120 elm_index_autohide_disabled_get(const Evas_Object *obj)
1121 {
1122    ELM_INDEX_CHECK(obj) EINA_FALSE;
1123    ELM_INDEX_DATA_GET(obj, sd);
1124
1125    return sd->autohide_disabled;
1126 }
1127
1128 EAPI void
1129 elm_index_item_level_set(Evas_Object *obj,
1130                          int level)
1131 {
1132    ELM_INDEX_CHECK(obj);
1133    ELM_INDEX_DATA_GET(obj, sd);
1134
1135    if (sd->level == level) return;
1136    sd->level = level;
1137 }
1138
1139 EAPI int
1140 elm_index_item_level_get(const Evas_Object *obj)
1141 {
1142    ELM_INDEX_CHECK(obj) 0;
1143    ELM_INDEX_DATA_GET(obj, sd);
1144
1145    return sd->level;
1146 }
1147
1148 //FIXME: Should update indicator based on the autohidden status & indicator visiblility
1149 EAPI void
1150 elm_index_item_selected_set(Elm_Object_Item *it,
1151                             Eina_Bool selected)
1152 {
1153    Elm_Index_Item *it_sel, *it_last;
1154    Evas_Object *obj = WIDGET(it);
1155
1156    ELM_INDEX_ITEM_CHECK_OR_RETURN(it);
1157    ELM_INDEX_DATA_GET(obj, sd);
1158
1159    selected = !!selected;
1160    it_sel = (Elm_Index_Item *)it;
1161    if (it_sel->selected == selected) return;
1162
1163    if (selected)
1164      {
1165         it_last = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
1166
1167         if (it_last)
1168           {
1169              it_last->selected = 0;
1170              if (it_last->head)
1171                edje_object_signal_emit(VIEW(it_last->head), "elm,state,inactive", "elm");
1172              else
1173                edje_object_signal_emit(VIEW(it_last), "elm,state,inactive", "elm");
1174           }
1175         it_sel->selected = 1;
1176         if (it_sel->head)
1177           edje_object_signal_emit(VIEW(it_sel->head), "elm,state,active", "elm");
1178         else
1179           edje_object_signal_emit(VIEW(it_sel), "elm,state,active", "elm");
1180
1181         evas_object_smart_callback_call
1182            (obj, SIG_CHANGED, it);
1183         evas_object_smart_callback_call
1184            (obj, SIG_SELECTED, it);
1185         if (sd->delay) ecore_timer_del(sd->delay);
1186         sd->delay = ecore_timer_add(sd->delay_change_time,
1187                                     _delay_change_cb, obj);
1188      }
1189    else
1190      {
1191         it_sel->selected = 0;
1192         if (it_sel->head)
1193           edje_object_signal_emit(VIEW(it_sel->head), "elm,state,inactive", "elm");
1194         else
1195           edje_object_signal_emit(VIEW(it_sel), "elm,state,inactive", "elm");
1196      }
1197 }
1198
1199 EAPI Elm_Object_Item *
1200 elm_index_selected_item_get(const Evas_Object *obj,
1201                             int level)
1202 {
1203    Eina_List *l;
1204    Elm_Index_Item *it;
1205
1206    ELM_INDEX_CHECK(obj) NULL;
1207    ELM_INDEX_DATA_GET(obj, sd);
1208
1209    EINA_LIST_FOREACH(sd->items, l, it)
1210      {
1211         if ((it->selected) && (it->level == level))
1212           return (Elm_Object_Item *)it;
1213      }
1214
1215    return NULL;
1216 }
1217
1218 EAPI Elm_Object_Item *
1219 elm_index_item_append(Evas_Object *obj,
1220                       const char *letter,
1221                       Evas_Smart_Cb func,
1222                       const void *data)
1223 {
1224    Elm_Index_Item *it;
1225
1226    ELM_INDEX_CHECK(obj) NULL;
1227    ELM_INDEX_DATA_GET(obj, sd);
1228
1229    it = _item_new(obj, letter, func, data);
1230    if (!it) return NULL;
1231
1232    sd->items = eina_list_append(sd->items, it);
1233    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1234
1235    return (Elm_Object_Item *)it;
1236 }
1237
1238 EAPI Elm_Object_Item *
1239 elm_index_item_prepend(Evas_Object *obj,
1240                        const char *letter,
1241                        Evas_Smart_Cb func,
1242                        const void *data)
1243 {
1244    Elm_Index_Item *it;
1245
1246    ELM_INDEX_CHECK(obj) NULL;
1247    ELM_INDEX_DATA_GET(obj, sd);
1248
1249    it = _item_new(obj, letter, func, data);
1250    if (!it) return NULL;
1251
1252    sd->items = eina_list_prepend(sd->items, it);
1253    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1254
1255    return (Elm_Object_Item *)it;
1256 }
1257
1258 EINA_DEPRECATED EAPI Elm_Object_Item *
1259 elm_index_item_prepend_relative(Evas_Object *obj,
1260                                 const char *letter,
1261                                 const void *item,
1262                                 const Elm_Object_Item *relative)
1263 {
1264    return elm_index_item_insert_before
1265             (obj, (Elm_Object_Item *)relative, letter, NULL, item);
1266 }
1267
1268 EAPI Elm_Object_Item *
1269 elm_index_item_insert_after(Evas_Object *obj,
1270                             Elm_Object_Item *after,
1271                             const char *letter,
1272                             Evas_Smart_Cb func,
1273                             const void *data)
1274 {
1275    Elm_Index_Item *it;
1276
1277    ELM_INDEX_CHECK(obj) NULL;
1278    ELM_INDEX_DATA_GET(obj, sd);
1279
1280    if (!after) return elm_index_item_append(obj, letter, func, data);
1281
1282    it = _item_new(obj, letter, func, data);
1283    if (!it) return NULL;
1284
1285    sd->items = eina_list_append_relative(sd->items, it, after);
1286    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1287
1288    return (Elm_Object_Item *)it;
1289 }
1290
1291 EAPI Elm_Object_Item *
1292 elm_index_item_insert_before(Evas_Object *obj,
1293                              Elm_Object_Item *before,
1294                              const char *letter,
1295                              Evas_Smart_Cb func,
1296                              const void *data)
1297 {
1298    Elm_Index_Item *it;
1299
1300    ELM_INDEX_CHECK(obj) NULL;
1301    ELM_INDEX_DATA_GET(obj, sd);
1302
1303    if (!before) return elm_index_item_prepend(obj, letter, func, data);
1304
1305    it = _item_new(obj, letter, func, data);
1306    if (!it) return NULL;
1307
1308    sd->items = eina_list_prepend_relative(sd->items, it, before);
1309    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1310
1311    return (Elm_Object_Item *)it;
1312 }
1313
1314 EAPI Elm_Object_Item *
1315 elm_index_item_sorted_insert(Evas_Object *obj,
1316                              const char *letter,
1317                              Evas_Smart_Cb func,
1318                              const void *data,
1319                              Eina_Compare_Cb cmp_func,
1320                              Eina_Compare_Cb cmp_data_func)
1321 {
1322    Elm_Index_Item *it;
1323    Eina_List *lnear;
1324    int cmp;
1325
1326    ELM_INDEX_CHECK(obj) NULL;
1327    ELM_INDEX_DATA_GET(obj, sd);
1328
1329    if (!(sd->items)) return elm_index_item_append(obj, letter, func, data);
1330
1331    it = _item_new(obj, letter, func, data);
1332    if (!it) return NULL;
1333
1334    lnear = eina_list_search_sorted_near_list(sd->items, cmp_func, it, &cmp);
1335    if (cmp < 0)
1336      sd->items = eina_list_append_relative_list(sd->items, it, lnear);
1337    else if (cmp > 0)
1338      sd->items = eina_list_prepend_relative_list(sd->items, it, lnear);
1339    else
1340      {
1341         /* If cmp_data_func is not provided, append a duplicated item */
1342         if (!cmp_data_func)
1343           sd->items = eina_list_append_relative_list(sd->items, it, lnear);
1344         else
1345           {
1346              Elm_Index_Item *p_it = eina_list_data_get(lnear);
1347              if (cmp_data_func(p_it->base.data, it->base.data) >= 0)
1348                p_it->base.data = it->base.data;
1349              _item_free(it);
1350              elm_widget_item_del(it);
1351              it = NULL;
1352           }
1353      }
1354    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1355
1356    if (!it) return NULL;
1357    return (Elm_Object_Item *)it;
1358 }
1359
1360 EAPI Elm_Object_Item *
1361 elm_index_item_find(Evas_Object *obj,
1362                     const void *data)
1363 {
1364    ELM_INDEX_CHECK(obj) NULL;
1365
1366    return (Elm_Object_Item *)_item_find(obj, data);
1367 }
1368
1369 EAPI void
1370 elm_index_item_clear(Evas_Object *obj)
1371 {
1372    Elm_Index_Item *it;
1373    Eina_List *l, *clear = NULL;
1374
1375    ELM_INDEX_CHECK(obj);
1376    ELM_INDEX_DATA_GET(obj, sd);
1377
1378    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1379    EINA_LIST_FOREACH(sd->items, l, it)
1380      {
1381         if (it->level != sd->level) continue;
1382         clear = eina_list_append(clear, it);
1383      }
1384    EINA_LIST_FREE (clear, it)
1385      {
1386         _item_free(it);
1387         elm_widget_item_del(it);
1388      }
1389 }
1390
1391 EAPI void
1392 elm_index_level_go(Evas_Object *obj,
1393                    int level __UNUSED__)
1394 {
1395    ELM_INDEX_CHECK(obj);
1396    ELM_INDEX_DATA_GET(obj, sd);
1397
1398    _index_box_clear(obj, sd->bx[0], 0);
1399    _index_box_auto_fill(obj, sd->bx[0], 0);
1400    if (sd->level == 1)
1401      {
1402         _index_box_clear(obj, sd->bx[1], 1);
1403         _index_box_auto_fill(obj, sd->bx[1], 1);
1404      }
1405 }
1406
1407 EAPI void
1408 elm_index_indicator_disabled_set(Evas_Object *obj,
1409                                  Eina_Bool disabled)
1410 {
1411    ELM_INDEX_CHECK(obj);
1412    ELM_INDEX_DATA_GET(obj, sd);
1413
1414    disabled = !!disabled;
1415    if (sd->indicator_disabled == disabled) return;
1416    sd->indicator_disabled = disabled;
1417    if (!sd->items) return;
1418    if (disabled)
1419      elm_layout_signal_emit(obj, "elm,indicator,state,inactive", "elm");
1420    else
1421      elm_layout_signal_emit(obj, "elm,indicator,state,active", "elm");
1422 }
1423
1424 EAPI Eina_Bool
1425 elm_index_indicator_disabled_get(const Evas_Object *obj)
1426 {
1427    ELM_INDEX_CHECK(obj) EINA_FALSE;
1428    ELM_INDEX_DATA_GET(obj, sd);
1429
1430    return sd->indicator_disabled;
1431 }
1432
1433 EAPI const char *
1434 elm_index_item_letter_get(const Elm_Object_Item *it)
1435 {
1436    ELM_INDEX_ITEM_CHECK_OR_RETURN(it, NULL);
1437
1438    return ((Elm_Index_Item *)it)->letter;
1439 }
1440
1441 EAPI void
1442 elm_index_horizontal_set(Evas_Object *obj,
1443                          Eina_Bool horizontal)
1444 {
1445    ELM_INDEX_CHECK(obj);
1446    ELM_INDEX_DATA_GET(obj, sd);
1447
1448    horizontal = !!horizontal;
1449    if (horizontal == sd->horizontal) return;
1450
1451    sd->horizontal = horizontal;
1452    if (horizontal)
1453      sd->omit_enabled = EINA_FALSE;
1454    _elm_index_smart_theme(obj);
1455 }
1456
1457 EAPI Eina_Bool
1458 elm_index_horizontal_get(const Evas_Object *obj)
1459 {
1460    ELM_INDEX_CHECK(obj) EINA_FALSE;
1461    ELM_INDEX_DATA_GET(obj, sd);
1462
1463    return sd->horizontal;
1464 }
1465
1466 EAPI void
1467 elm_index_delay_change_time_set(Evas_Object *obj, double delay_change_time)
1468 {
1469    ELM_INDEX_CHECK(obj);
1470    ELM_INDEX_DATA_GET(obj, sd);
1471
1472    sd->delay_change_time = delay_change_time;
1473 }
1474
1475 EAPI double
1476 elm_index_delay_change_time_get(const Evas_Object *obj)
1477 {
1478    ELM_INDEX_CHECK(obj) 0.0;
1479    ELM_INDEX_DATA_GET(obj, sd);
1480
1481    return sd->delay_change_time;
1482 }
1483
1484 EAPI void
1485 elm_index_omit_enabled_set(Evas_Object *obj,
1486                            Eina_Bool enabled)
1487 {
1488    ELM_INDEX_CHECK(obj);
1489    ELM_INDEX_DATA_GET(obj, sd);
1490
1491    if (sd->horizontal) return;
1492
1493    enabled = !!enabled;
1494    if (sd->omit_enabled == enabled) return;
1495    sd->omit_enabled = enabled;
1496
1497    _index_box_clear(obj, sd->bx[0], 0);
1498    _index_box_auto_fill(obj, sd->bx[0], 0);
1499    if (sd->level == 1)
1500      {
1501         _index_box_clear(obj, sd->bx[1], 1);
1502         _index_box_auto_fill(obj, sd->bx[1], 1);
1503      }
1504 }
1505
1506 EAPI Eina_Bool
1507 elm_index_omit_enabled_get(const Evas_Object *obj)
1508 {
1509    ELM_INDEX_CHECK(obj) EINA_FALSE;
1510    ELM_INDEX_DATA_GET(obj, sd);
1511
1512    return sd->omit_enabled;
1513 }