[access][index] register access object after elm_object_style_set();
[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 void
337 _access_activate_cb(void *data,
338                     Evas_Object *part_obj __UNUSED__,
339                     Elm_Object_Item *item __UNUSED__)
340 {
341    Elm_Index_Item *it;
342    ELM_INDEX_DATA_GET(data, sd);
343
344    it = eina_list_nth(sd->items, 0);
345    _elm_access_highlight_set(it->base.access_obj);
346    sd->index_focus = EINA_TRUE;
347 }
348
349 static void
350 _access_index_register(Evas_Object *obj)
351 {
352    Evas_Object *ao;
353    Elm_Access_Info *ai;
354    elm_widget_can_focus_set(obj, EINA_TRUE);
355
356    ao = _elm_access_edje_object_part_object_register
357               (obj, elm_layout_edje_get(obj), "access");
358    ai = _elm_access_object_get(ao);
359
360    _elm_access_text_set
361      (ai, ELM_ACCESS_TYPE, E_("Index"));
362    _elm_access_activate_callback_set
363      (ai, _access_activate_cb, obj);
364 }
365
366 static Eina_Bool
367 _elm_index_smart_theme(Evas_Object *obj)
368 {
369    Evas_Coord minw = 0, minh = 0;
370    Elm_Index_Item *it;
371
372    ELM_INDEX_DATA_GET(obj, sd);
373
374    _index_box_clear(obj, sd->bx[0], 0);
375    _index_box_clear(obj, sd->bx[1], 1);
376
377    if (sd->horizontal)
378      eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "base/horizontal");
379    else
380      {
381         eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "base/vertical");
382         _mirrored_set(obj, elm_widget_mirrored_get(obj));
383      }
384
385    if (!ELM_WIDGET_CLASS(_elm_index_parent_sc)->theme(obj)) return EINA_FALSE;
386
387    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
388    evas_object_size_hint_min_set(sd->event[0], minw, minh);
389
390    if (edje_object_part_exists
391          (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.index.1"))
392      {
393         if (!sd->bx[1])
394           {
395              sd->bx[1] = evas_object_box_add(evas_object_evas_get(obj));
396              evas_object_box_layout_set
397                (sd->bx[1], _box_custom_layout, sd, NULL);
398              elm_widget_sub_object_add(obj, sd->bx[1]);
399           }
400         elm_layout_content_set(obj, "elm.swallow.index.1", sd->bx[1]);
401      }
402    else if (sd->bx[1])
403      {
404         evas_object_del(sd->bx[1]);
405         sd->bx[1] = NULL;
406      }
407    if (edje_object_part_exists
408          (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.event.1"))
409      {
410         if (!sd->event[1])
411           {
412              sd->event[1] =
413                evas_object_rectangle_add(evas_object_evas_get(obj));
414              evas_object_color_set(sd->event[1], 0, 0, 0, 0);
415              elm_widget_sub_object_add(obj, sd->event[1]);
416           }
417         elm_layout_content_set(obj, "elm.swallow.event.1", sd->event[1]);
418         evas_object_size_hint_min_set(sd->event[1], minw, minh);
419      }
420    else if (sd->event[1])
421      {
422         evas_object_del(sd->event[1]);
423         sd->event[1] = NULL;
424      }
425    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
426
427    elm_layout_sizing_eval(obj);
428    _index_box_auto_fill(obj, sd->bx[0], 0);
429
430    if (sd->autohide_disabled)
431      {
432         if (sd->level == 1) _index_box_auto_fill(obj, sd->bx[1], 1);
433         elm_layout_signal_emit(obj, "elm,state,active", "elm");
434      }
435    else elm_layout_signal_emit(obj, "elm,state,inactive", "elm");
436
437    it = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
438    if (it)
439      {
440         if (it->head)
441           edje_object_signal_emit(VIEW(it->head), "elm,state,active", "elm");
442         else
443           edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
444      }
445
446    /* access */
447    if (_elm_config->access_mode)
448      {
449         elm_index_autohide_disabled_set(obj, EINA_TRUE);
450         elm_layout_signal_emit(obj, "elm,access,state,active", "elm");
451         _access_index_register(obj);
452      }
453
454    return EINA_TRUE;
455 }
456
457 static void
458 _elm_index_smart_sizing_eval(Evas_Object *obj)
459 {
460    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
461
462    ELM_INDEX_DATA_GET(obj, sd);
463
464    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
465    evas_object_size_hint_min_set(obj, minw, minh);
466    evas_object_size_hint_max_set(obj, maxw, maxh);
467 }
468
469 static Eina_Bool
470 _item_del_pre_hook(Elm_Object_Item *it)
471 {
472    ELM_INDEX_DATA_GET(WIDGET(it), sd);
473
474    _item_free((Elm_Index_Item *)it);
475    _index_box_clear(WIDGET(it), sd->bx[sd->level], sd->level);
476
477    return EINA_TRUE;
478 }
479
480 static Elm_Index_Item *
481 _item_new(Evas_Object *obj,
482           const char *letter,
483           Evas_Smart_Cb func,
484           const void *data)
485 {
486    Elm_Index_Item *it;
487
488    ELM_INDEX_DATA_GET(obj, sd);
489
490    it = elm_widget_item_new(obj, Elm_Index_Item);
491    if (!it) return NULL;
492
493    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
494    if (letter) it->letter = eina_stringshare_add(letter);
495    it->func = func;
496    it->base.data = data;
497    it->level = sd->level;
498
499    return it;
500 }
501
502 static Elm_Index_Item *
503 _item_find(Evas_Object *obj,
504            const void *data)
505 {
506    Eina_List *l;
507    Elm_Index_Item *it;
508
509    ELM_INDEX_DATA_GET(obj, sd);
510
511    EINA_LIST_FOREACH(sd->items, l, it)
512      if (it->base.data == data) return it;
513
514    return NULL;
515 }
516
517 static Eina_Bool
518 _delay_change_cb(void *data)
519 {
520    Elm_Object_Item *item;
521
522    ELM_INDEX_DATA_GET(data, sd);
523
524    sd->delay = NULL;
525    item = elm_index_selected_item_get(data, sd->level);
526    if (item) evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, item);
527
528    return ECORE_CALLBACK_CANCEL;
529 }
530
531 static void
532 _sel_eval(Evas_Object *obj,
533           Evas_Coord evx,
534           Evas_Coord evy)
535 {
536    Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
537    Elm_Index_Item *it, *it_closest, *it_last, *om_closest;
538    char *label = NULL, *last = NULL;
539    double cdv = 0.5;
540    Evas_Coord dist;
541    Eina_List *l;
542    int i, j, size, dh, dx, dy;
543
544    ELM_INDEX_DATA_GET(obj, sd);
545
546    for (i = 0; i <= sd->level; i++)
547      {
548         it_last = NULL;
549         it_closest = NULL;
550         om_closest = NULL;
551         dist = 0x7fffffff;
552         evas_object_geometry_get(sd->bx[i], &bx, &by, &bw, &bh);
553
554         EINA_LIST_FOREACH(sd->items, l, it)
555           {
556              if (it->level != i) continue;
557              if (it->level != sd->level)
558                {
559                   if (it->selected)
560                     {
561                        it_closest = it;
562                        break;
563                     }
564                   continue;
565                }
566              if (it->selected)
567                {
568                   it_last = it;
569                   it->selected = 0;
570                }
571              if (VIEW(it))
572                {
573                   evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
574                   xx = x + (w / 2);
575                   yy = y + (h / 2);
576                   x = evx - xx;
577                   y = evy - yy;
578                   x = (x * x) + (y * y);
579                   if ((x < dist) || (!it_closest))
580                     {
581                        if (sd->horizontal)
582                          cdv = (double)(xx - bx) / (double)bw;
583                        else
584                          cdv = (double)(yy - by) / (double)bh;
585                        it_closest = it;
586                        dist = x;
587                     }
588                }
589           }
590         if ((i == 0) && (sd->level == 0))
591           edje_object_part_drag_value_set
592             (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.index.1", cdv, cdv);
593
594         if (it_closest && it_closest->omitted)
595           {
596              it = it_closest;
597              size = eina_list_count(it->omitted);
598              evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
599              dist = 0x7fffffff;
600              dh = h / size;
601              if (dh == 0)
602                printf("too many index items to omit\n"); //FIXME
603              else
604                {
605                   for (j = 0; j < size; j++)
606                     {
607                        xx = x + (w / 2);
608                        yy = y + (dh * j) + (dh / 2);
609                        dx = evx - xx;
610                        dy = evy - yy;
611                        dx = (dx * dx) + (dy * dy);
612                        if ((dx < dist) || (!om_closest))
613                          {
614                             om_closest = eina_list_nth(it->omitted, j);
615                             dist = dx;
616                          }
617                     }
618                }
619           }
620
621         if (om_closest) om_closest->selected = 1;
622         else if (it_closest) it_closest->selected = 1;
623
624         if (it_closest != it_last)
625           {
626              if (it_last)
627                {
628                   const char *stacking, *selectraise;
629
630                   it = it_last;
631                   if (it->head)
632                     {
633                        if (it->head != it_closest) it = it->head;
634                        else it = NULL;
635                     }
636                   if (it)
637                     {
638                        edje_object_signal_emit
639                           (VIEW(it), "elm,state,inactive", "elm");
640                        stacking = edje_object_data_get(VIEW(it), "stacking");
641                        selectraise = edje_object_data_get(VIEW(it), "selectraise");
642                        if ((selectraise) && (!strcmp(selectraise, "on")))
643                          {
644                             if ((stacking) && (!strcmp(stacking, "below")))
645                               evas_object_lower(VIEW(it));
646                          }
647                     }
648                }
649              if (it_closest)
650                {
651                   const char *selectraise;
652
653                   it = it_closest;
654
655                   if (!((it_last) && (it_last->head) && (it_last->head == it_closest)))
656                     {
657                        edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
658                        selectraise = edje_object_data_get(VIEW(it), "selectraise");
659                        if ((selectraise) && (!strcmp(selectraise, "on")))
660                          evas_object_raise(VIEW(it));
661                     }
662
663                   if (om_closest)
664                     evas_object_smart_callback_call
665                        (obj, SIG_CHANGED, om_closest);
666                   else
667                     evas_object_smart_callback_call
668                        (obj, SIG_CHANGED, it);
669                   if (sd->delay) ecore_timer_del(sd->delay);
670                   sd->delay = ecore_timer_add(sd->delay_change_time,
671                                               _delay_change_cb, obj);
672                }
673           }
674         if (it_closest)
675           {
676              if (om_closest) it = om_closest;
677              else it = it_closest;
678              if (!last && it->letter) last = strdup(it->letter);
679              else
680                {
681                   if (!label && last) label = strdup(last);
682                   else
683                     {
684                        if (label && last)
685                          {
686                             label = realloc(label, strlen(label) +
687                                             strlen(last) + 1);
688                             if (!label) return;
689                             strcat(label, last);
690                          }
691                     }
692                   free(last);
693                   if (it->letter) last = strdup(it->letter);
694                }
695           }
696      }
697    if (!label) label = strdup("");
698    if (!last) last = strdup("");
699
700    elm_layout_text_set(obj, "elm.text.body", label);
701    elm_layout_text_set(obj, "elm.text", last);
702
703    free(label);
704    free(last);
705 }
706
707 static void
708 _on_mouse_wheel(void *data __UNUSED__,
709                 Evas *e __UNUSED__,
710                 Evas_Object *o __UNUSED__,
711                 void *event_info __UNUSED__)
712 {
713 }
714
715 static void
716 _on_mouse_down(void *data,
717                Evas *e __UNUSED__,
718                Evas_Object *o __UNUSED__,
719                void *event_info)
720 {
721    Evas_Event_Mouse_Down *ev = event_info;
722    Evas_Coord x, y, w;
723
724    ELM_INDEX_DATA_GET(data, sd);
725
726    if (ev->button != 1) return;
727    sd->down = 1;
728    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, NULL);
729    sd->dx = ev->canvas.x - x;
730    sd->dy = ev->canvas.y - y;
731    if (!sd->autohide_disabled)
732      {
733         _index_box_clear(data, sd->bx[1], 1);
734         elm_layout_signal_emit(data, "elm,state,active", "elm");
735      }
736    _sel_eval(data, ev->canvas.x, ev->canvas.y);
737    edje_object_part_drag_value_set
738      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.pointer",
739      (!elm_object_mirrored_get(data)) ? sd->dx : (sd->dx - w), sd->dy);
740    if (sd->items && !sd->indicator_disabled)
741      elm_layout_signal_emit(data, "elm,indicator,state,active", "elm");
742 }
743
744 static void
745 _on_mouse_up(void *data,
746              Evas *e __UNUSED__,
747              Evas_Object *o __UNUSED__,
748              void *event_info)
749 {
750    Evas_Event_Mouse_Up *ev = event_info;
751    Elm_Object_Item *item;
752    Elm_Index_Item *id_item;
753
754    ELM_INDEX_DATA_GET(data, sd);
755
756    if (ev->button != 1) return;
757    sd->down = 0;
758    item = elm_index_selected_item_get(data, sd->level);
759    if (item)
760      {
761         evas_object_smart_callback_call(data, SIG_SELECTED, item);
762         id_item = (Elm_Index_Item *)item;
763         if (id_item->func)
764           id_item->func((void *)id_item->base.data, WIDGET(id_item), id_item);
765      }
766    if (!sd->autohide_disabled)
767      elm_layout_signal_emit(data, "elm,state,inactive", "elm");
768
769    elm_layout_signal_emit(data, "elm,state,level,0", "elm");
770    if (sd->items && !sd->indicator_disabled)
771      elm_layout_signal_emit(data, "elm,indicator,state,inactive", "elm");
772 }
773
774 static void
775 _on_mouse_move(void *data,
776                Evas *e __UNUSED__,
777                Evas_Object *o __UNUSED__,
778                void *event_info)
779 {
780    Evas_Event_Mouse_Move *ev = event_info;
781    Evas_Coord minw = 0, minh = 0, x, y, dx, adx, w;
782    char buf[1024];
783
784    ELM_INDEX_DATA_GET(data, sd);
785
786    if (!sd->down) return;
787    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
788    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, NULL);
789    x = ev->cur.canvas.x - x;
790    y = ev->cur.canvas.y - y;
791    dx = x - sd->dx;
792    adx = dx;
793    if (adx < 0) adx = -dx;
794    edje_object_part_drag_value_set
795      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.dragable.pointer",
796      (!edje_object_mirrored_get(ELM_WIDGET_DATA(sd)->resize_obj)) ?
797      x : (x - w), y);
798    if (!sd->horizontal)
799      {
800         if (adx > minw)
801           {
802              if (!sd->level)
803                {
804                   sd->level = 1;
805                   snprintf(buf, sizeof(buf), "elm,state,level,%i", sd->level);
806                   elm_layout_signal_emit(data, buf, "elm");
807                   evas_object_smart_callback_call(data, SIG_LEVEL_UP, NULL);
808                }
809           }
810         else
811           {
812              if (sd->level == 1)
813                {
814                   sd->level = 0;
815                   snprintf(buf, sizeof(buf), "elm,state,level,%i", sd->level);
816                   elm_layout_signal_emit(data, buf, "elm");
817                   evas_object_smart_callback_call(data, SIG_LEVEL_DOWN, NULL);
818                }
819           }
820      }
821    _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
822 }
823
824 static void
825 _index_resize_cb(void *data,
826                  Evas *e __UNUSED__,
827                  Evas_Object *obj __UNUSED__,
828                  void *event_info __UNUSED__)
829 {
830    ELM_INDEX_DATA_GET_OR_RETURN(data, sd);
831
832    if (!sd->omit_enabled) return;
833
834    Elm_Index_Item *it;
835
836    _index_box_clear(data, sd->bx[0], 0);
837    _index_box_auto_fill(data, sd->bx[0], 0);
838
839    it = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
840    if (it)
841      {
842         if (it->head)
843           edje_object_signal_emit(VIEW(it->head), "elm,state,active", "elm");
844         else
845           edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
846      }
847 }
848
849 static void
850 _elm_index_smart_add(Evas_Object *obj)
851 {
852    Evas_Object *o;
853    Evas_Coord minw, minh;
854
855    EVAS_SMART_DATA_ALLOC(obj, Elm_Index_Smart_Data);
856
857    ELM_WIDGET_CLASS(_elm_index_parent_sc)->base.add(obj);
858
859    elm_layout_theme_set
860      (obj, "index", "base/vertical", elm_widget_style_get(obj));
861
862    o = evas_object_rectangle_add(evas_object_evas_get(obj));
863    priv->event[0] = o;
864    evas_object_color_set(o, 0, 0, 0, 0);
865    minw = minh = 0;
866    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
867    evas_object_size_hint_min_set(o, minw, minh);
868    elm_layout_content_set(obj, "elm.swallow.event.0", o);
869    elm_widget_sub_object_add(obj, o);
870
871    evas_object_event_callback_add
872      (obj, EVAS_CALLBACK_RESIZE, _index_resize_cb, obj);
873    evas_object_event_callback_add
874      (o, EVAS_CALLBACK_MOUSE_WHEEL, _on_mouse_wheel, obj);
875    evas_object_event_callback_add
876      (o, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, obj);
877    evas_object_event_callback_add
878      (o, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up, obj);
879    evas_object_event_callback_add
880      (o, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move, obj);
881
882    if (edje_object_part_exists
883          (ELM_WIDGET_DATA(priv)->resize_obj, "elm.swallow.event.1"))
884      {
885         o = evas_object_rectangle_add(evas_object_evas_get(obj));
886         priv->event[1] = o;
887         evas_object_color_set(o, 0, 0, 0, 0);
888         evas_object_size_hint_min_set(o, minw, minh);
889         elm_layout_content_set(obj, "elm.swallow.event.1", o);
890         elm_widget_sub_object_add(obj, o);
891      }
892
893    priv->bx[0] = evas_object_box_add(evas_object_evas_get(obj));
894    evas_object_box_layout_set(priv->bx[0], _box_custom_layout, priv, NULL);
895    elm_widget_sub_object_add(obj, priv->bx[0]);
896    elm_layout_content_set(obj, "elm.swallow.index.0", priv->bx[0]);
897    evas_object_show(priv->bx[0]);
898
899    priv->delay_change_time = INDEX_DELAY_CHANGE_TIME;
900    priv->omit_enabled = 1;
901
902    if (edje_object_part_exists
903          (ELM_WIDGET_DATA(priv)->resize_obj, "elm.swallow.index.1"))
904      {
905         priv->bx[1] = evas_object_box_add(evas_object_evas_get(obj));
906         evas_object_box_layout_set
907           (priv->bx[1], _box_custom_layout, priv, NULL);
908         elm_widget_sub_object_add(obj, priv->bx[1]);
909         elm_layout_content_set(obj, "elm.swallow.index.1", priv->bx[1]);
910         evas_object_show(priv->bx[1]);
911      }
912
913    _mirrored_set(obj, elm_widget_mirrored_get(obj));
914    elm_layout_sizing_eval(obj);
915    elm_widget_can_focus_set(obj, EINA_FALSE);
916
917    // ACCESS
918    if (_elm_config->access_mode)
919      {
920         elm_index_autohide_disabled_set(obj, EINA_TRUE);
921         elm_layout_signal_emit(obj, "elm,access,state,active", "elm");
922         _access_index_register(obj);
923      }
924 }
925
926 static void
927 _elm_index_smart_del(Evas_Object *obj)
928 {
929    Elm_Index_Item *it;
930    Elm_Index_Omit *o;
931
932    ELM_INDEX_DATA_GET(obj, sd);
933
934    while (sd->items)
935      {
936         it = sd->items->data;
937         elm_widget_item_del(it);
938      }
939
940    EINA_LIST_FREE(sd->omit, o)
941      free(o);
942
943    if (sd->delay) ecore_timer_del(sd->delay);
944
945    ELM_WIDGET_CLASS(_elm_index_parent_sc)->base.del(obj);
946 }
947
948 static Eina_Bool
949 _elm_index_smart_focus_next(const Evas_Object *obj,
950                             Elm_Focus_Direction dir,
951                             Evas_Object **next)
952 {
953    Eina_List *items = NULL;
954    Eina_List *l = NULL;
955    Elm_Index_Item *it;
956    Evas_Object *ao;
957    Evas_Object *po;
958    Eina_Bool ret;
959
960    ELM_INDEX_CHECK(obj) EINA_FALSE;
961    ELM_INDEX_DATA_GET(obj, sd);
962
963    if (!sd->autohide_disabled)
964      elm_layout_signal_emit((Evas_Object *)obj, "elm,state,active", "elm");
965
966    po = (Evas_Object *)edje_object_part_object_get
967               (elm_layout_edje_get(obj), "access");
968    ao = evas_object_data_get(po, "_part_access_obj");
969    items = eina_list_append(items, ao);
970
971    if (sd->index_focus)
972      {
973       EINA_LIST_FOREACH(sd->items, l, it)
974         {
975            if (it->level != 0) continue;
976            items = eina_list_append(items, it->base.access_obj);
977         }
978      }
979
980    ret = elm_widget_focus_list_next_get
981             (obj, items, eina_list_data_get, dir, next);
982
983    if (!ret)
984      {
985         sd->index_focus = EINA_FALSE;
986
987         Evas_Object *it_access_obj = eina_list_nth(items, eina_list_count(items) - 1);
988
989         items = eina_list_free(items);
990         items = eina_list_append(items, it_access_obj);
991         items = eina_list_append(items, ao);
992
993         ret = elm_widget_focus_list_next_get(obj, items, eina_list_data_get, dir, next);
994
995         // to hide index item, if there is nothing to focus on autohide disalbe mode
996         if (!sd->autohide_disabled)
997           elm_layout_signal_emit((Evas_Object *)obj, "elm,state,inactive", "elm");
998      }
999
1000    return ret;
1001 }
1002
1003 static void
1004 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1005 {
1006    Eina_List *l;
1007    Elm_Index_Item *it;
1008
1009    ELM_INDEX_DATA_GET(obj, sd);
1010
1011    EINA_LIST_FOREACH(sd->items, l, it)
1012      {
1013         if (it->level != 0) continue;
1014         if (is_access) _access_widget_item_register(it);
1015         else _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
1016      }
1017
1018    if (is_access)
1019      {
1020         elm_index_autohide_disabled_set(obj, EINA_TRUE);
1021         elm_layout_signal_emit(obj, "elm,access,state,active", "elm");
1022         _access_index_register(obj);
1023      }
1024    else
1025      {
1026         // opposition of  _access_index_register();
1027         elm_index_autohide_disabled_set(obj, EINA_FALSE);
1028         elm_layout_signal_emit(obj, "elm,access,state,inactive", "elm");
1029         elm_widget_can_focus_set(obj, EINA_FALSE);
1030         _elm_access_edje_object_part_object_unregister
1031              (obj, elm_layout_edje_get(obj), "access");
1032      }
1033 }
1034
1035 static void
1036 _access_hook(Evas_Object *obj, Eina_Bool is_access)
1037 {
1038    ELM_INDEX_CHECK(obj);
1039    ELM_INDEX_DATA_GET(obj, sd);
1040
1041    if (is_access)
1042      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
1043      _elm_index_smart_focus_next;
1044    else
1045      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
1046    _access_obj_process(obj, is_access);
1047 }
1048
1049 static void
1050 _elm_index_smart_set_user(Elm_Index_Smart_Class *sc)
1051 {
1052    ELM_WIDGET_CLASS(sc)->base.add = _elm_index_smart_add;
1053    ELM_WIDGET_CLASS(sc)->base.del = _elm_index_smart_del;
1054
1055    ELM_WIDGET_CLASS(sc)->theme = _elm_index_smart_theme;
1056    ELM_WIDGET_CLASS(sc)->translate = _elm_index_smart_translate;
1057
1058    /* not a 'focus chain manager' */
1059    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
1060    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1061
1062    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_index_smart_sizing_eval;
1063
1064    if (_elm_config->access_mode)
1065      ELM_WIDGET_CLASS(sc)->focus_next = _elm_index_smart_focus_next;
1066
1067    ELM_WIDGET_CLASS(sc)->access = _access_hook;
1068 }
1069
1070 EAPI const Elm_Index_Smart_Class *
1071 elm_index_smart_class_get(void)
1072 {
1073    static Elm_Index_Smart_Class _sc =
1074      ELM_INDEX_SMART_CLASS_INIT_NAME_VERSION(ELM_INDEX_SMART_NAME);
1075    static const Elm_Index_Smart_Class *class = NULL;
1076    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1077
1078    if (class)
1079      return class;
1080
1081    _elm_index_smart_set(&_sc);
1082    esc->callbacks = _smart_callbacks;
1083    class = &_sc;
1084
1085    return class;
1086 }
1087
1088 EAPI Evas_Object *
1089 elm_index_add(Evas_Object *parent)
1090 {
1091    Evas_Object *obj;
1092
1093    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1094
1095    obj = elm_widget_add(_elm_index_smart_class_new(), parent);
1096    if (!obj) return NULL;
1097
1098    if (!elm_widget_sub_object_add(parent, obj))
1099      ERR("could not add %p as sub object of %p", obj, parent);
1100
1101    return obj;
1102 }
1103
1104 EAPI void
1105 elm_index_autohide_disabled_set(Evas_Object *obj,
1106                                 Eina_Bool disabled)
1107 {
1108    ELM_INDEX_CHECK(obj);
1109    ELM_INDEX_DATA_GET(obj, sd);
1110
1111    disabled = !!disabled;
1112    if (sd->autohide_disabled == disabled) return;
1113    sd->autohide_disabled = disabled;
1114    sd->level = 0;
1115    if (sd->autohide_disabled)
1116      {
1117         _index_box_clear(obj, sd->bx[1], 1);
1118         elm_layout_signal_emit(obj, "elm,state,active", "elm");
1119      }
1120    else
1121      elm_layout_signal_emit(obj, "elm,state,inactive", "elm");
1122
1123    //FIXME: Should be update indicator based on the indicator visiblility
1124 }
1125
1126 EAPI Eina_Bool
1127 elm_index_autohide_disabled_get(const Evas_Object *obj)
1128 {
1129    ELM_INDEX_CHECK(obj) EINA_FALSE;
1130    ELM_INDEX_DATA_GET(obj, sd);
1131
1132    return sd->autohide_disabled;
1133 }
1134
1135 EAPI void
1136 elm_index_item_level_set(Evas_Object *obj,
1137                          int level)
1138 {
1139    ELM_INDEX_CHECK(obj);
1140    ELM_INDEX_DATA_GET(obj, sd);
1141
1142    if (sd->level == level) return;
1143    sd->level = level;
1144 }
1145
1146 EAPI int
1147 elm_index_item_level_get(const Evas_Object *obj)
1148 {
1149    ELM_INDEX_CHECK(obj) 0;
1150    ELM_INDEX_DATA_GET(obj, sd);
1151
1152    return sd->level;
1153 }
1154
1155 //FIXME: Should update indicator based on the autohidden status & indicator visiblility
1156 EAPI void
1157 elm_index_item_selected_set(Elm_Object_Item *it,
1158                             Eina_Bool selected)
1159 {
1160    Elm_Index_Item *it_sel, *it_last;
1161    Evas_Object *obj = WIDGET(it);
1162
1163    ELM_INDEX_ITEM_CHECK_OR_RETURN(it);
1164    ELM_INDEX_DATA_GET(obj, sd);
1165
1166    selected = !!selected;
1167    it_sel = (Elm_Index_Item *)it;
1168    if (it_sel->selected == selected) return;
1169
1170    if (selected)
1171      {
1172         it_last = (Elm_Index_Item *)elm_index_selected_item_get(obj, sd->level);
1173
1174         if (it_last)
1175           {
1176              it_last->selected = 0;
1177              if (it_last->head)
1178                edje_object_signal_emit(VIEW(it_last->head), "elm,state,inactive", "elm");
1179              else
1180                edje_object_signal_emit(VIEW(it_last), "elm,state,inactive", "elm");
1181           }
1182         it_sel->selected = 1;
1183         if (it_sel->head)
1184           edje_object_signal_emit(VIEW(it_sel->head), "elm,state,active", "elm");
1185         else
1186           edje_object_signal_emit(VIEW(it_sel), "elm,state,active", "elm");
1187
1188         evas_object_smart_callback_call
1189            (obj, SIG_CHANGED, it);
1190         evas_object_smart_callback_call
1191            (obj, SIG_SELECTED, it);
1192         if (sd->delay) ecore_timer_del(sd->delay);
1193         sd->delay = ecore_timer_add(sd->delay_change_time,
1194                                     _delay_change_cb, obj);
1195      }
1196    else
1197      {
1198         it_sel->selected = 0;
1199         if (it_sel->head)
1200           edje_object_signal_emit(VIEW(it_sel->head), "elm,state,inactive", "elm");
1201         else
1202           edje_object_signal_emit(VIEW(it_sel), "elm,state,inactive", "elm");
1203      }
1204 }
1205
1206 EAPI Elm_Object_Item *
1207 elm_index_selected_item_get(const Evas_Object *obj,
1208                             int level)
1209 {
1210    Eina_List *l;
1211    Elm_Index_Item *it;
1212
1213    ELM_INDEX_CHECK(obj) NULL;
1214    ELM_INDEX_DATA_GET(obj, sd);
1215
1216    EINA_LIST_FOREACH(sd->items, l, it)
1217      {
1218         if ((it->selected) && (it->level == level))
1219           return (Elm_Object_Item *)it;
1220      }
1221
1222    return NULL;
1223 }
1224
1225 EAPI Elm_Object_Item *
1226 elm_index_item_append(Evas_Object *obj,
1227                       const char *letter,
1228                       Evas_Smart_Cb func,
1229                       const void *data)
1230 {
1231    Elm_Index_Item *it;
1232
1233    ELM_INDEX_CHECK(obj) NULL;
1234    ELM_INDEX_DATA_GET(obj, sd);
1235
1236    it = _item_new(obj, letter, func, data);
1237    if (!it) return NULL;
1238
1239    sd->items = eina_list_append(sd->items, it);
1240    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1241
1242    return (Elm_Object_Item *)it;
1243 }
1244
1245 EAPI Elm_Object_Item *
1246 elm_index_item_prepend(Evas_Object *obj,
1247                        const char *letter,
1248                        Evas_Smart_Cb func,
1249                        const void *data)
1250 {
1251    Elm_Index_Item *it;
1252
1253    ELM_INDEX_CHECK(obj) NULL;
1254    ELM_INDEX_DATA_GET(obj, sd);
1255
1256    it = _item_new(obj, letter, func, data);
1257    if (!it) return NULL;
1258
1259    sd->items = eina_list_prepend(sd->items, it);
1260    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1261
1262    return (Elm_Object_Item *)it;
1263 }
1264
1265 EINA_DEPRECATED EAPI Elm_Object_Item *
1266 elm_index_item_prepend_relative(Evas_Object *obj,
1267                                 const char *letter,
1268                                 const void *item,
1269                                 const Elm_Object_Item *relative)
1270 {
1271    return elm_index_item_insert_before
1272             (obj, (Elm_Object_Item *)relative, letter, NULL, item);
1273 }
1274
1275 EAPI Elm_Object_Item *
1276 elm_index_item_insert_after(Evas_Object *obj,
1277                             Elm_Object_Item *after,
1278                             const char *letter,
1279                             Evas_Smart_Cb func,
1280                             const void *data)
1281 {
1282    Elm_Index_Item *it;
1283
1284    ELM_INDEX_CHECK(obj) NULL;
1285    ELM_INDEX_DATA_GET(obj, sd);
1286
1287    if (!after) return elm_index_item_append(obj, letter, func, data);
1288
1289    it = _item_new(obj, letter, func, data);
1290    if (!it) return NULL;
1291
1292    sd->items = eina_list_append_relative(sd->items, it, after);
1293    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1294
1295    return (Elm_Object_Item *)it;
1296 }
1297
1298 EAPI Elm_Object_Item *
1299 elm_index_item_insert_before(Evas_Object *obj,
1300                              Elm_Object_Item *before,
1301                              const char *letter,
1302                              Evas_Smart_Cb func,
1303                              const void *data)
1304 {
1305    Elm_Index_Item *it;
1306
1307    ELM_INDEX_CHECK(obj) NULL;
1308    ELM_INDEX_DATA_GET(obj, sd);
1309
1310    if (!before) return elm_index_item_prepend(obj, letter, func, data);
1311
1312    it = _item_new(obj, letter, func, data);
1313    if (!it) return NULL;
1314
1315    sd->items = eina_list_prepend_relative(sd->items, it, before);
1316    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1317
1318    return (Elm_Object_Item *)it;
1319 }
1320
1321 EAPI Elm_Object_Item *
1322 elm_index_item_sorted_insert(Evas_Object *obj,
1323                              const char *letter,
1324                              Evas_Smart_Cb func,
1325                              const void *data,
1326                              Eina_Compare_Cb cmp_func,
1327                              Eina_Compare_Cb cmp_data_func)
1328 {
1329    Elm_Index_Item *it;
1330    Eina_List *lnear;
1331    int cmp;
1332
1333    ELM_INDEX_CHECK(obj) NULL;
1334    ELM_INDEX_DATA_GET(obj, sd);
1335
1336    if (!(sd->items)) return elm_index_item_append(obj, letter, func, data);
1337
1338    it = _item_new(obj, letter, func, data);
1339    if (!it) return NULL;
1340
1341    lnear = eina_list_search_sorted_near_list(sd->items, cmp_func, it, &cmp);
1342    if (cmp < 0)
1343      sd->items = eina_list_append_relative_list(sd->items, it, lnear);
1344    else if (cmp > 0)
1345      sd->items = eina_list_prepend_relative_list(sd->items, it, lnear);
1346    else
1347      {
1348         /* If cmp_data_func is not provided, append a duplicated item */
1349         if (!cmp_data_func)
1350           sd->items = eina_list_append_relative_list(sd->items, it, lnear);
1351         else
1352           {
1353              Elm_Index_Item *p_it = eina_list_data_get(lnear);
1354              if (cmp_data_func(p_it->base.data, it->base.data) >= 0)
1355                p_it->base.data = it->base.data;
1356              elm_widget_item_del(it);
1357              it = NULL;
1358           }
1359      }
1360    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1361
1362    if (!it) return NULL;
1363    return (Elm_Object_Item *)it;
1364 }
1365
1366 EAPI Elm_Object_Item *
1367 elm_index_item_find(Evas_Object *obj,
1368                     const void *data)
1369 {
1370    ELM_INDEX_CHECK(obj) NULL;
1371
1372    return (Elm_Object_Item *)_item_find(obj, data);
1373 }
1374
1375 EAPI void
1376 elm_index_item_clear(Evas_Object *obj)
1377 {
1378    Elm_Index_Item *it;
1379    Eina_List *l, *clear = NULL;
1380
1381    ELM_INDEX_CHECK(obj);
1382    ELM_INDEX_DATA_GET(obj, sd);
1383
1384    _index_box_clear(obj, sd->bx[sd->level], sd->level);
1385    EINA_LIST_FOREACH(sd->items, l, it)
1386      {
1387         if (it->level != sd->level) continue;
1388         clear = eina_list_append(clear, it);
1389      }
1390    EINA_LIST_FREE (clear, it)
1391      elm_widget_item_del(it);
1392 }
1393
1394 EAPI void
1395 elm_index_level_go(Evas_Object *obj,
1396                    int level __UNUSED__)
1397 {
1398    ELM_INDEX_CHECK(obj);
1399    ELM_INDEX_DATA_GET(obj, sd);
1400
1401    _index_box_clear(obj, sd->bx[0], 0);
1402    _index_box_auto_fill(obj, sd->bx[0], 0);
1403    if (sd->level == 1)
1404      {
1405         _index_box_clear(obj, sd->bx[1], 1);
1406         _index_box_auto_fill(obj, sd->bx[1], 1);
1407      }
1408 }
1409
1410 EAPI void
1411 elm_index_indicator_disabled_set(Evas_Object *obj,
1412                                  Eina_Bool disabled)
1413 {
1414    ELM_INDEX_CHECK(obj);
1415    ELM_INDEX_DATA_GET(obj, sd);
1416
1417    disabled = !!disabled;
1418    if (sd->indicator_disabled == disabled) return;
1419    sd->indicator_disabled = disabled;
1420    if (!sd->items) return;
1421    if (disabled)
1422      elm_layout_signal_emit(obj, "elm,indicator,state,inactive", "elm");
1423    else
1424      elm_layout_signal_emit(obj, "elm,indicator,state,active", "elm");
1425 }
1426
1427 EAPI Eina_Bool
1428 elm_index_indicator_disabled_get(const Evas_Object *obj)
1429 {
1430    ELM_INDEX_CHECK(obj) EINA_FALSE;
1431    ELM_INDEX_DATA_GET(obj, sd);
1432
1433    return sd->indicator_disabled;
1434 }
1435
1436 EAPI const char *
1437 elm_index_item_letter_get(const Elm_Object_Item *it)
1438 {
1439    ELM_INDEX_ITEM_CHECK_OR_RETURN(it, NULL);
1440
1441    return ((Elm_Index_Item *)it)->letter;
1442 }
1443
1444 EAPI void
1445 elm_index_horizontal_set(Evas_Object *obj,
1446                          Eina_Bool horizontal)
1447 {
1448    ELM_INDEX_CHECK(obj);
1449    ELM_INDEX_DATA_GET(obj, sd);
1450
1451    horizontal = !!horizontal;
1452    if (horizontal == sd->horizontal) return;
1453
1454    sd->horizontal = horizontal;
1455    if (horizontal)
1456      sd->omit_enabled = EINA_FALSE;
1457    _elm_index_smart_theme(obj);
1458 }
1459
1460 EAPI Eina_Bool
1461 elm_index_horizontal_get(const Evas_Object *obj)
1462 {
1463    ELM_INDEX_CHECK(obj) EINA_FALSE;
1464    ELM_INDEX_DATA_GET(obj, sd);
1465
1466    return sd->horizontal;
1467 }
1468
1469 EAPI void
1470 elm_index_delay_change_time_set(Evas_Object *obj, double delay_change_time)
1471 {
1472    ELM_INDEX_CHECK(obj);
1473    ELM_INDEX_DATA_GET(obj, sd);
1474
1475    sd->delay_change_time = delay_change_time;
1476 }
1477
1478 EAPI double
1479 elm_index_delay_change_time_get(const Evas_Object *obj)
1480 {
1481    ELM_INDEX_CHECK(obj) 0.0;
1482    ELM_INDEX_DATA_GET(obj, sd);
1483
1484    return sd->delay_change_time;
1485 }
1486
1487 EAPI void
1488 elm_index_omit_enabled_set(Evas_Object *obj,
1489                            Eina_Bool enabled)
1490 {
1491    ELM_INDEX_CHECK(obj);
1492    ELM_INDEX_DATA_GET(obj, sd);
1493
1494    if (sd->horizontal) return;
1495
1496    enabled = !!enabled;
1497    if (sd->omit_enabled == enabled) return;
1498    sd->omit_enabled = enabled;
1499
1500    _index_box_clear(obj, sd->bx[0], 0);
1501    _index_box_auto_fill(obj, sd->bx[0], 0);
1502    if (sd->level == 1)
1503      {
1504         _index_box_clear(obj, sd->bx[1], 1);
1505         _index_box_auto_fill(obj, sd->bx[1], 1);
1506      }
1507 }
1508
1509 EAPI Eina_Bool
1510 elm_index_omit_enabled_get(const Evas_Object *obj)
1511 {
1512    ELM_INDEX_CHECK(obj) EINA_FALSE;
1513    ELM_INDEX_DATA_GET(obj, sd);
1514
1515    return sd->omit_enabled;
1516 }