EFL migration revision 67547
[framework/uifw/elementary.git] / src / lib / elm_diskselector.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_scroller.h"
4
5 #ifndef MAX
6 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
7 #endif
8
9 #ifndef CEIL
10 #define CEIL(a) (((a) % 2 != 0) ? ((a) / 2 + 1) : ((a) / 2))
11 #endif
12
13 #define DISPLAY_ITEM_NUM_MIN 3
14
15 typedef struct _Widget_Data Widget_Data;
16 typedef struct _Elm_Diskselector_Item Elm_Diskselector_Item;
17
18 struct _Widget_Data
19 {
20    Evas_Object *self;
21    Evas_Object *scroller;
22    Evas_Object *main_box;
23    Evas_Object *left_blank;
24    Evas_Object *right_blank;
25    Elm_Diskselector_Item *selected_item;
26    Elm_Diskselector_Item *first;
27    Elm_Diskselector_Item *second;
28    Elm_Diskselector_Item *s_last;
29    Elm_Diskselector_Item *last;
30    Eina_List *items;
31    Eina_List *r_items;
32    Eina_List *over_items;
33    Eina_List *under_items;
34    int item_count, len_threshold, len_side, display_item_num;
35    Ecore_Idle_Enterer *idler;
36    Ecore_Idle_Enterer *check_idler;
37    Evas_Coord minw, minh;
38    Eina_Bool init:1;
39    Eina_Bool round:1;
40    Eina_Bool display_item_num_by_api:1;
41 };
42
43 struct _Elm_Diskselector_Item
44 {
45    ELM_WIDGET_ITEM;
46    Eina_List *node;
47    Evas_Object *icon;
48    const char *label;
49    Evas_Smart_Cb func;
50 };
51
52 static const char *widtype = NULL;
53
54 static Eina_Bool _move_scroller(void *data);
55 static void _del_hook(Evas_Object * obj);
56 static void _del_pre_hook(Evas_Object * obj);
57 static void _sizing_eval(Evas_Object * obj);
58 static void _theme_hook(Evas_Object * obj);
59 static void _on_focus_hook(void *data, Evas_Object *obj);
60 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
61 static void _sub_del(void *data, Evas_Object * obj, void *event_info);
62 static void _round_items_del(Widget_Data *wd);
63 static void _scroller_move_cb(void *data, Evas_Object *obj, void *event_info);
64 static void _item_click_cb(void *data, Evas_Object *obj __UNUSED__,
65                            const char *emission __UNUSED__,
66                            const char *source __UNUSED__);
67 static void _selected_item_indicate(Elm_Diskselector_Item *it);
68 static void _item_text_set_hook(Elm_Object_Item *it,
69                                 const char *part,
70                                 const char *label);
71 static const char * _item_text_get_hook(const Elm_Object_Item *it,
72                                         const char *part);
73 static void _item_content_set_hook(Elm_Object_Item *it,
74                                    const char *part,
75                                    Evas_Object *content);
76 static Evas_Object * _item_content_get_hook(const Elm_Object_Item *it,
77                                             const char *part);
78
79 static const char SIG_SELECTED[] = "selected";
80 static const Evas_Smart_Cb_Description _signals[] = {
81        {SIG_SELECTED, ""},
82        {NULL, NULL}
83 };
84
85 static void
86 _diskselector_object_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
87 {
88    Widget_Data *wd;
89    Evas_Coord w, h;
90
91    wd = elm_widget_data_get(data);
92    if (!wd) return;
93
94    if ((wd->minw == -1) && (wd->minh == -1))
95       elm_coords_finger_size_adjust(6, &wd->minw, 1, &wd->minh);
96    edje_object_size_min_restricted_calc
97       (elm_smart_scroller_edje_object_get
98           (wd->scroller), &wd->minw, &wd->minh, wd->minw, wd->minh);
99    evas_object_size_hint_min_set(obj, wd->minw, wd->minh);
100    evas_object_size_hint_max_set(obj, -1, -1);
101
102    evas_object_geometry_get(wd->scroller, NULL, NULL, &w, &h);
103    if (wd->round)
104      evas_object_resize(wd->main_box, (w / wd->display_item_num) * (wd->item_count + (CEIL(wd->display_item_num) * 2)), h);
105    else
106      evas_object_resize(wd->main_box, (w / wd->display_item_num) * (wd->item_count + CEIL(wd->display_item_num)), h);
107
108    elm_smart_scroller_paging_set(wd->scroller, 0, 0,
109                                  (int)(w / wd->display_item_num), 0);
110
111    if (!wd->idler)
112      wd->idler = ecore_idle_enterer_before_add(_move_scroller, data);
113 }
114
115 static void
116 _item_del(Elm_Diskselector_Item *item)
117 {
118    if (!item) return;
119    eina_stringshare_del(item->label);
120    if (item->icon)
121      evas_object_del(item->icon);
122 }
123
124 static int
125 _count_letter(const char *str)
126 {
127    int pos = 0;
128    int code = 0, chnum;
129
130    for (chnum = 0; ; chnum++)
131      {
132         pos = evas_string_char_next_get(str, pos, &code);
133         if (code == 0) break;
134      }
135    return chnum;
136 }
137
138 static int
139 _check_letter(const char *str, int length)
140 {
141    int pos = 0;
142    int code = 0, chnum;
143
144    for (chnum = 0; ; chnum++)
145      {
146         if (chnum == length) break;
147         pos = evas_string_char_next_get(str, pos, &code);
148         if (code == 0) break;
149      }
150    return pos;
151 }
152
153 static Eina_Bool
154 _check_string(void *data)
155 {
156    int mid, steps, length, diff;
157    Elm_Diskselector_Item *it;
158    Eina_List *list, *l;
159    Evas_Coord ox, ow;
160    char buf[1024];
161    Widget_Data *wd = data;
162
163    evas_object_geometry_get(wd->scroller, &ox, NULL, &ow, NULL);
164    if (ow <= 0)
165      return EINA_FALSE;
166    if (!wd->init)
167      return EINA_FALSE;
168    if (!wd->round)
169      list = wd->items;
170    else
171      list = wd->r_items;
172
173    EINA_LIST_FOREACH(list, l, it)
174      {
175         Evas_Coord x, w;
176         int len;
177         evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
178         /* item not visible */
179         if ((x + w <= ox) || (x >= ox + ow))
180           continue;
181
182         len = _count_letter(it->label);
183 //        // FIXME: len should be # of ut8f letters. ie count using utf8 string walk, not stringshare len
184 //        len = eina_stringshare_strlen(it->label);
185
186         if (x <= ox + 5)
187           edje_object_signal_emit(VIEW(it), "elm,state,left_side",
188                                   "elm");
189         else if (x + w >= ox + ow - 5)
190           edje_object_signal_emit(VIEW(it), "elm,state,right_side",
191                                   "elm");
192         else
193           {
194              if ((wd->len_threshold) && (len > wd->len_threshold))
195                edje_object_signal_emit(VIEW(it), "elm,state,center_small",
196                                        "elm");
197              else
198                edje_object_signal_emit(VIEW(it), "elm,state,center",
199                                        "elm");
200           }
201
202         // if len is les that the limit len, skip anyway
203         if (len <= wd->len_side)
204           continue;
205
206         steps = len - wd->len_side + 1;
207         mid = x + w / 2;
208         if (mid <= ox + ow / 2)
209           diff = (ox + ow / 2) - mid;
210         else
211           diff = mid - (ox + ow / 2);
212
213         length = len - (int)(diff * steps / (ow / 3));
214         length = MAX(length, wd->len_side);
215         // limit string len to "length" ut8f chars
216         length = _check_letter(it->label, length);
217         // cut it off at byte mark returned form _check_letter
218         strncpy(buf, it->label, length);
219         buf[length] = '\0';
220         edje_object_part_text_set(VIEW(it), "elm.text", buf);
221      }
222
223    if (wd->check_idler)
224      ecore_idle_enterer_del(wd->check_idler);
225    wd->check_idler = NULL;
226    return EINA_FALSE;
227 }
228
229 static void
230 _item_del_pre_hook(Elm_Object_Item *it)
231 {
232    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
233    Elm_Diskselector_Item *item, *item2, *dit;
234    Eina_List *l;
235    int i = 0;
236    Widget_Data *wd;
237    item = (Elm_Diskselector_Item *) it;
238    wd = elm_widget_data_get(WIDGET(item));
239    if (!wd) return;
240
241    elm_box_unpack(wd->main_box, VIEW(item));
242
243    if (wd->round)
244      wd->r_items = eina_list_remove(wd->r_items, item);
245
246    wd->items = eina_list_remove(wd->items, item);
247
248    if (wd->selected_item == item)
249      {
250         dit = (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
251         if (dit != item)
252           wd->selected_item = dit;
253         else
254           wd->selected_item = eina_list_nth(wd->items, 1);
255
256         _selected_item_indicate(wd->selected_item);
257      }
258
259    _item_del(item);
260    wd->item_count -= 1;
261
262    if (wd->round)
263      {
264         if (!wd->item_count)
265           {
266              evas_object_hide(wd->VIEW(first));
267              evas_object_hide(wd->VIEW(second));
268              evas_object_hide(wd->VIEW(last));
269              evas_object_hide(wd->VIEW(s_last));
270
271              EINA_LIST_FOREACH(wd->under_items, l, item2)
272                evas_object_hide(VIEW(item2));
273
274              EINA_LIST_FOREACH(wd->over_items, l, item2)
275                evas_object_hide(VIEW(item2));
276           }
277         else
278           {
279              dit = eina_list_nth(wd->items, 0);
280              if (dit)
281                {
282                   eina_stringshare_replace(&wd->first->label, dit->label);
283                   edje_object_part_text_set(wd->VIEW(first), "elm.text",
284                                             wd->first->label);
285                }
286              dit = eina_list_nth(wd->items, 1);
287              if (dit)
288                {
289                   eina_stringshare_replace(&wd->second->label, dit->label);
290                   edje_object_part_text_set(wd->VIEW(second), "elm.text",
291                                             wd->second->label);
292                }
293              // if more than 3 itmes should be displayed
294              for (i = 2; i < CEIL(wd->display_item_num); i++)
295                {
296                   dit = eina_list_nth(wd->items, i);
297                   item2 = eina_list_nth(wd->over_items, i - 2);
298                   eina_stringshare_replace(&item2->label, dit->label);
299                   edje_object_part_text_set(VIEW(item2), "elm.text", item2->label);
300                }
301
302              dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 1);
303              if (dit)
304                {
305                   eina_stringshare_replace(&wd->last->label, dit->label);
306                   edje_object_part_text_set(wd->VIEW(last), "elm.text",
307                                             wd->last->label);
308                }
309              dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 2);
310              if (dit)
311                {
312                   eina_stringshare_replace(&wd->s_last->label, dit->label);
313                   edje_object_part_text_set(wd->VIEW(s_last), "elm.text",
314                                             wd->s_last->label);
315                }
316              // if more than 3 itmes should be displayed
317              for (i = 3; i <= CEIL(wd->display_item_num); i++)
318                {
319                   dit = eina_list_nth(wd->items, wd->item_count - i);
320                   item2 = eina_list_nth(wd->under_items, i - 3);
321                   eina_stringshare_replace(&item2->label, dit->label);
322                   edje_object_part_text_set(VIEW(item2), "elm.text",
323                                             item2->label);
324                }
325           }
326      }
327    wd->check_idler = ecore_idle_enterer_before_add(_check_string, wd);
328    _sizing_eval(wd->self);
329
330 }
331
332 static Elm_Diskselector_Item *
333 _item_new(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data)
334 {
335    Elm_Diskselector_Item *it;
336    const char *style = elm_widget_style_get(obj);
337
338    it = elm_widget_item_new(obj, Elm_Diskselector_Item);
339    if (!it) return NULL;
340
341    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
342    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
343    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
344    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
345    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
346
347    it->label = eina_stringshare_add(label);
348    it->icon = icon;
349    it->func = func;
350    it->base.data = data;
351    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
352    _elm_theme_object_set(obj, VIEW(it), "diskselector", "item", style);
353    evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND,
354                                     EVAS_HINT_EXPAND);
355    evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL,
356                                    EVAS_HINT_FILL);
357    evas_object_show(VIEW(it));
358
359    if (it->label)
360      {
361         edje_object_part_text_set(VIEW(it), "elm.text", it->label);
362         edje_object_signal_callback_add(VIEW(it), "elm,action,click", "", _item_click_cb, it);
363      }
364    if (it->icon)
365      {
366         evas_object_size_hint_min_set(it->icon, 24, 24);
367         evas_object_size_hint_max_set(it->icon, 40, 40);
368         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
369         evas_object_show(it->icon);
370         elm_widget_sub_object_add(obj, it->icon);
371      }
372    return it;
373 }
374
375 static void
376 _theme_data_get(Widget_Data *wd)
377 {
378    const char* str;
379    Evas_Object *parent;
380    str = edje_object_data_get(wd->right_blank, "len_threshold");
381    if (str) wd->len_threshold = MAX(0, atoi(str));
382    else wd->len_threshold = 0;
383
384    if (!wd->display_item_num_by_api)
385      {
386         str = edje_object_data_get(wd->right_blank, "display_item_num");
387         if (str) wd->display_item_num = MAX(DISPLAY_ITEM_NUM_MIN, atoi(str));
388         else wd->display_item_num = DISPLAY_ITEM_NUM_MIN;
389      }
390
391    str = edje_object_data_get(wd->right_blank, "min_width");
392    if (str) wd->minw = MAX(-1, atoi(str)) * elm_scale_get();
393    else
394      {
395         parent = elm_widget_parent_widget_get(wd->self);
396         if (!parent) wd->minw = -1;
397         else evas_object_geometry_get(parent, NULL, NULL, &wd->minw, NULL);
398      }
399
400    str = edje_object_data_get(wd->right_blank, "min_height");
401    if (str) wd->minh = MAX(-1, atoi(str)) * elm_scale_get();
402    else wd->minh = -1;
403 }
404
405 static void
406 _del_hook(Evas_Object * obj)
407 {
408    Widget_Data *wd = elm_widget_data_get(obj);
409    if (!wd) return;
410    free(wd);
411 }
412
413 static void
414 _del_pre_hook(Evas_Object * obj)
415 {
416    Elm_Diskselector_Item *it;
417    Eina_List *l;
418
419    Widget_Data *wd = elm_widget_data_get(obj);
420    if (!wd) return;
421
422    if (wd->left_blank)
423      evas_object_del(wd->left_blank);
424    if (wd->right_blank)
425      evas_object_del(wd->right_blank);
426    if (wd->last)
427      {
428         eina_stringshare_del(wd->last->label);
429         evas_object_del(wd->VIEW(last));
430         free(wd->last);
431      }
432    if (wd->s_last)
433      {
434         eina_stringshare_del(wd->s_last->label);
435         evas_object_del(wd->VIEW(s_last));
436         free(wd->s_last);
437      }
438    if (wd->second)
439      {
440         eina_stringshare_del(wd->second->label);
441         evas_object_del(wd->VIEW(second));
442         free(wd->second);
443      }
444    if (wd->first)
445      {
446         eina_stringshare_del(wd->first->label);
447         evas_object_del(wd->VIEW(first));
448         free(wd->first);
449      }
450
451    EINA_LIST_FOREACH(wd->under_items, l, it)
452      {
453         if (it)
454           {
455              eina_stringshare_del(it->label);
456              evas_object_del(VIEW(it));
457              free(it);
458           }
459      }
460
461    EINA_LIST_FOREACH(wd->over_items, l, it)
462    {
463      if (it)
464         {
465            eina_stringshare_del(it->label);
466            evas_object_del(VIEW(it));
467            free(it);
468         }
469    }
470
471    EINA_LIST_FREE(wd->items, it)
472      {
473         _item_del(it);
474         elm_widget_item_free(it);
475      }
476    eina_list_free(wd->r_items);
477 }
478
479 static void
480 _sizing_eval(Evas_Object * obj)
481 {
482    Widget_Data *wd = elm_widget_data_get(obj);
483    if (!wd) return;
484    _diskselector_object_resize(obj, NULL, obj, NULL);
485 }
486
487 static void
488 _theme_hook(Evas_Object * obj)
489 {
490    Eina_List *l;
491    Elm_Diskselector_Item *it;
492    Widget_Data *wd = elm_widget_data_get(obj);
493    if (!wd) return;
494
495    if (wd->scroller)
496      elm_smart_scroller_object_theme_set(obj, wd->scroller, "diskselector",
497                                          "base", elm_widget_style_get(obj));
498    if (wd->round)
499      {
500         EINA_LIST_FOREACH(wd->r_items, l, it)
501           {
502              _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
503                                    elm_widget_style_get(obj));
504              edje_object_part_text_set(VIEW(it), "elm.text", it->label);
505           }
506      }
507    else
508      {
509         EINA_LIST_FOREACH(wd->items, l, it)
510           {
511              _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
512                                    elm_widget_style_get(obj));
513              edje_object_part_text_set(VIEW(it), "elm.text", it->label);
514           }
515      }
516    _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
517                                    elm_widget_style_get(obj));
518    _theme_data_get(wd);
519    _sizing_eval(obj);
520 }
521
522 static void
523 _sub_del(void *data __UNUSED__, Evas_Object * obj, void *event_info)
524 {
525    Widget_Data *wd = elm_widget_data_get(obj);
526    Evas_Object *sub = event_info;
527    Elm_Diskselector_Item *it;
528    const Eina_List *l;
529
530    if (!wd) return;
531    if (!sub) abort();
532    if (sub == wd->scroller)
533      wd->scroller = NULL;
534    else
535      {
536         EINA_LIST_FOREACH(wd->items, l, it)
537           {
538              if (sub == it->icon)
539                {
540                   it->icon = NULL;
541                   _sizing_eval(obj);
542                   break;
543                }
544           }
545      }
546 }
547
548 static void
549 _select_item(Elm_Diskselector_Item *it)
550 {
551    if (!it) return;
552    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
553    wd->selected_item = it;
554    _selected_item_indicate(wd->selected_item);
555    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
556    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
557 }
558
559 static void
560 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
561 {
562    Widget_Data *wd = elm_widget_data_get(obj);
563    if (!wd)
564      return;
565
566    if (elm_widget_focus_get(obj))
567      {
568         edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
569         evas_object_focus_set(wd->self, EINA_TRUE);
570      }
571    else
572      {
573         edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
574         evas_object_focus_set(wd->self, EINA_FALSE);
575      }
576 }
577
578 static Eina_Bool
579 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
580 {
581    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
582    Evas_Event_Key_Down *ev = event_info;
583    Widget_Data *wd = elm_widget_data_get(obj);
584    if (!wd) return EINA_FALSE;
585    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
586    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
587
588    Elm_Diskselector_Item *it = NULL;
589    Eina_List *l;
590
591    if (!wd->selected_item) {
592         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
593         return EINA_TRUE;
594    }
595
596    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")) ||
597        (!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
598      {
599         l = wd->selected_item->node->prev;
600         if ((!l) && (wd->round))
601           l = eina_list_last(wd->items);
602      }
603    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")) ||
604             (!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
605      {
606         l = wd->selected_item->node->next;
607         if ((!l) && (wd->round))
608           l = wd->items;
609      }
610    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
611      l = wd->items;
612    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
613      l = eina_list_last(wd->items);
614    else return EINA_FALSE;
615
616    if (l)
617      it = eina_list_data_get(l);
618
619    if (it)
620      {
621         wd->selected_item = it;
622         if (!wd->idler)
623           wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
624      }
625
626    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
627    return EINA_TRUE;
628 }
629
630 static void
631 _selected_item_indicate(Elm_Diskselector_Item *it)
632 {
633    Elm_Diskselector_Item *item;
634    Eina_List *l;
635    Widget_Data *wd;
636    wd = elm_widget_data_get(WIDGET(it));
637
638    if (!wd) return;
639
640    EINA_LIST_FOREACH(wd->r_items, l, item)
641      {
642         if (!strcmp(item->label, it->label)) edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
643         else
644            edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
645      }
646 }
647
648 static void
649 _item_click_cb(void *data, Evas_Object *obj __UNUSED__,
650                const char *emission __UNUSED__, const char *source __UNUSED__)
651 {
652    Elm_Diskselector_Item *it = data;
653
654    if (!it) return;
655
656    Widget_Data *wd;
657    wd = elm_widget_data_get(WIDGET(it));
658
659    if (!wd) return;
660
661    if (wd->selected_item != it)
662      {
663         wd->selected_item = it;
664         _selected_item_indicate(wd->selected_item);
665      }
666
667    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
668 }
669
670 static void
671 _scroller_move_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
672 {
673    Evas_Coord x, y, w, h, bw;
674    Widget_Data *wd = data;
675
676    _check_string(wd);
677    elm_smart_scroller_child_pos_get(obj, &x, &y);
678    elm_smart_scroller_child_viewport_size_get(obj, &w, &h);
679    if (wd->round)
680      {
681         evas_object_geometry_get(wd->main_box, NULL, NULL, &bw, NULL);
682         if (x > ((w / wd->display_item_num) * (wd->item_count + (wd->display_item_num % 2))))
683            elm_smart_scroller_child_region_show(wd->scroller,
684                                                x - ((w / wd->display_item_num) * wd->item_count),
685                                                y, w, h);
686         else if (x < 0)
687            elm_smart_scroller_child_region_show(wd->scroller,
688                                                x + ((w / wd->display_item_num) * wd->item_count),
689                                                y, w, h);
690      }
691 }
692
693 static void
694 _scroller_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
695 {
696    Elm_Diskselector_Item *it;
697    Widget_Data *wd = data;
698    Evas_Coord x, w, ow;
699    Eina_List *l, *list;
700
701    if (wd->idler) return;
702
703    if (!wd->round)
704      list = wd->items;
705    else
706      list = wd->r_items;
707
708    evas_object_geometry_get(wd->scroller, NULL, NULL, &ow, NULL);
709    EINA_LIST_FOREACH(list, l, it)
710      {
711         evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
712         if (abs((int)(ow / 2 - (int)(x + w / 2))) < 10) break;
713      }
714
715    if (!it) return;
716    _select_item(it);
717 }
718
719 static Eina_Bool
720 _move_scroller(void *data)
721 {
722    Evas_Object *obj = data;
723    Widget_Data *wd;
724    Eina_List *list, *l;
725    Elm_Diskselector_Item *dit;
726    Evas_Coord y, w, h;
727    int i;
728
729    wd = elm_widget_data_get(obj);
730    if (!wd) return EINA_FALSE;
731
732    if (!wd->round)
733      {
734         i = 0;
735         list = wd->items;
736      }
737    else
738      {
739         i = 1;
740         list = wd->r_items;
741      }
742
743    EINA_LIST_FOREACH(list, l, dit)
744      {
745         if (wd->selected_item == dit)
746            break;
747         i++;
748      }
749
750    if (wd->round) i -= CEIL(wd->display_item_num);
751
752    if (!dit)
753      {
754         wd->selected_item =
755            (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
756         return EINA_FALSE;
757      }
758
759    evas_object_geometry_get(wd->scroller, NULL, &y, &w, &h);
760    //move scroller in two steps for getting smooth launching effect.
761    if (i > 2)
762      elm_smart_scroller_child_region_show(wd->scroller, w / wd->display_item_num * (i-2), y, w, h);
763    elm_smart_scroller_region_bring_in(wd->scroller, w / wd->display_item_num * i, y, w, h);
764
765    _select_item(dit);
766    if (wd->idler)
767      {
768         ecore_idle_enterer_del(wd->idler);
769         wd->idler = NULL;
770      }
771    wd->init = EINA_TRUE;
772    _check_string(wd);
773
774    return EINA_TRUE;
775 }
776
777 static void
778 _round_item_del(Widget_Data *wd, Elm_Diskselector_Item *it)
779 {
780    if (!it) return;
781    elm_box_unpack(wd->main_box, VIEW(it));
782    wd->r_items = eina_list_remove(wd->r_items, it);
783    eina_stringshare_del(it->label);
784    elm_widget_item_free(it);
785 }
786
787 static void
788 _round_items_del(Widget_Data *wd)
789 {
790    Eina_List *l;
791    Elm_Diskselector_Item * it;
792
793    _round_item_del(wd, wd->last);
794    wd->last = NULL;
795    _round_item_del(wd, wd->s_last);
796    wd->s_last = NULL;
797    _round_item_del(wd, wd->second);
798    wd->second = NULL;
799    _round_item_del(wd, wd->first);
800    wd->first = NULL;
801
802    EINA_LIST_FOREACH(wd->under_items, l, it)
803      {
804         _round_item_del(wd, it);
805      }
806    wd->under_items = eina_list_free(wd->under_items);
807
808    EINA_LIST_FOREACH(wd->over_items, l, it)
809      {
810         _round_item_del(wd, it);
811      }
812    wd->over_items = eina_list_free(wd->over_items);
813 }
814
815 static void
816 _round_items_add(Widget_Data *wd)
817 {
818    Elm_Diskselector_Item *dit;
819    Elm_Diskselector_Item *it;
820    Elm_Diskselector_Item *temp_it;
821    int i = 0;
822    dit = it = eina_list_nth(wd->items, 0);
823    if (!dit) return;
824
825    if (!wd->first)
826      {
827         wd->first = _item_new(WIDGET(it), it->icon, it->label, it->func,
828                               it->base.data);
829         wd->first->node = it->node;
830         wd->r_items = eina_list_append(wd->r_items, wd->first);
831      }
832
833    it = eina_list_nth(wd->items, 1);
834    if (!it)
835      it = dit;
836    if (!wd->second)
837      {
838         wd->second = _item_new(WIDGET(it), it->icon, it->label, it->func,
839                                it->base.data);
840         wd->second->node = it->node;
841         wd->r_items = eina_list_append(wd->r_items, wd->second);
842      }
843
844    // if more than 3 itmes should be displayed
845    for (i = 2; i < CEIL(wd->display_item_num); i++)
846      {
847         it = eina_list_nth(wd->items, i);
848         if (!it) it = dit;
849         temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
850         wd->over_items = eina_list_append(wd->over_items, temp_it);
851         wd->r_items = eina_list_append(wd->r_items, temp_it);
852      }
853
854    it = eina_list_nth(wd->items, wd->item_count - 1);
855    if (!it)
856      it = dit;
857    if (!wd->last)
858      {
859         wd->last = _item_new(WIDGET(it), it->icon, it->label, it->func,
860                              it->base.data);
861         wd->last->node = it->node;
862         wd->r_items = eina_list_prepend(wd->r_items, wd->last);
863      }
864
865    it = eina_list_nth(wd->items, wd->item_count - 2);
866    if (!it)
867      it = dit;
868    if (!wd->s_last)
869      {
870         wd->s_last = _item_new(WIDGET(it), it->icon, it->label, it->func,
871                                it->base.data);
872         wd->s_last->node = it->node;
873         wd->r_items = eina_list_prepend(wd->r_items, wd->s_last);
874      }
875
876    // if more than 3 itmes should be displayed
877    for (i = 3; i <= CEIL(wd->display_item_num); i++)
878      {
879         it = eina_list_nth(wd->items, wd->item_count - i);
880         if (!it) it = dit;
881         temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
882         wd->under_items = eina_list_append(wd->under_items, temp_it);
883         wd->r_items = eina_list_prepend(wd->r_items, temp_it);
884      }
885 }
886
887 static void
888 _item_icon_set(Elm_Diskselector_Item *it, Evas_Object *icon)
889 {
890    if (it->icon == icon) return;
891    if (it->icon)
892      evas_object_del(it->icon);
893    it->icon = icon;
894    if (VIEW(it))
895      {
896         evas_object_size_hint_min_set(it->icon, 24, 24);
897         evas_object_size_hint_max_set(it->icon, 40, 40);
898         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
899         evas_object_show(it->icon);
900         elm_widget_sub_object_add(WIDGET(it), it->icon);
901      }
902 }
903
904 static void
905 _check_identical_item(Elm_Diskselector_Item *it, Evas_Object *icon)
906 {
907    Widget_Data *wd;
908    Elm_Diskselector_Item *dit;
909    Eina_List *l;
910    int idx = 0;
911    int ic = 0;
912    int ac = 0;
913
914    wd = elm_widget_data_get(WIDGET(it));
915    if (!wd) return;
916
917    if (wd->round)
918      {
919         // Get index from indentical item from round items
920         EINA_LIST_FOREACH(wd->r_items, l, dit)
921           {
922              if (it == dit) break;
923              idx++;
924           }
925
926         // No item to match
927         ic = eina_list_count(wd->r_items);
928         if (idx >= ic) return;
929         dit = NULL;
930
931         // Number of added items: CEIL(wd->display_item_num)
932         ac = CEIL(wd->display_item_num);
933
934         if (((idx >= 0) && (idx < ac)) ||
935             ((idx >= ac) && (idx < (2 * ac))))
936           {
937               // Selected item: under, low region
938              dit = eina_list_nth(wd->r_items,
939                                  idx + ic - (2 * ac));
940           }
941         else if (((idx >= (ic - ac)) && (idx < ic)) ||
942                  ((idx >= (ic - (2 * ac))) && (idx < ic - ac)))
943           {
944               // Selected item: over, high region
945               dit = eina_list_nth(wd->r_items,
946                                   idx - ic + (2 * ac));
947           }
948
949         if(dit) _item_icon_set(dit, icon);
950         _sizing_eval(wd->self);
951      }
952 }
953
954 static void
955 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
956 {
957    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
958    Elm_Diskselector_Item *item;
959    if (part && strcmp(part, "default")) return;
960    item = (Elm_Diskselector_Item *) it;
961    eina_stringshare_replace(&item->label, label);
962    edje_object_part_text_set(VIEW(item), "elm.text", item->label);
963 }
964
965 static const char *
966 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
967 {
968    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
969    if (part && strcmp(part, "default")) return NULL;
970    return ((Elm_Diskselector_Item *) it)->label;
971 }
972
973 static void
974 _item_content_set_hook(Elm_Object_Item *it,
975                        const char *part,
976                        Evas_Object *content)
977 {
978    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
979    if (part && strcmp(part, "icon")) return;
980    _item_icon_set((Elm_Diskselector_Item *) it, content);
981    _check_identical_item((Elm_Diskselector_Item *) it, content);
982 }
983
984 static Evas_Object *
985 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
986 {
987    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
988    if (part && strcmp(part, "icon")) return NULL;
989    return ((Elm_Diskselector_Item *) it)->icon;
990 }
991
992 EAPI Evas_Object *
993 elm_diskselector_add(Evas_Object *parent)
994 {
995    Evas *e;
996    Evas_Object *obj;
997    Widget_Data *wd;
998
999    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1000
1001    ELM_SET_WIDTYPE(widtype, "diskselector");
1002    elm_widget_type_set(obj, "diskselector");
1003    elm_widget_sub_object_add(parent, obj);
1004    elm_widget_data_set(obj, wd);
1005    elm_widget_del_hook_set(obj, _del_hook);
1006    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1007    elm_widget_theme_hook_set(obj, _theme_hook);
1008    elm_widget_can_focus_set(obj, EINA_TRUE);
1009    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1010    elm_widget_event_hook_set(obj, _event_hook);
1011
1012    wd->self = obj;
1013    wd->item_count = 0;
1014    wd->round = EINA_FALSE;
1015    wd->init = EINA_FALSE;
1016    wd->len_side = 3;
1017    wd->display_item_num_by_api = EINA_FALSE;
1018
1019    wd->scroller = elm_smart_scroller_add(e);
1020    elm_smart_scroller_widget_set(wd->scroller, obj);
1021    _theme_hook(obj);
1022    elm_widget_resize_object_set(obj, wd->scroller);
1023    elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
1024                                  ELM_SMART_SCROLLER_POLICY_OFF);
1025    elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_TRUE, EINA_FALSE);
1026    evas_object_smart_callback_add(wd->scroller, "scroll", _scroller_move_cb,
1027                                   wd);
1028    evas_object_smart_callback_add(wd->scroller, "animate,stop",
1029                                   _scroller_stop_cb, wd);
1030    _elm_theme_object_set(obj, wd->scroller, "diskselector", "base",
1031                          "default");
1032    evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
1033                                   _diskselector_object_resize, obj);
1034
1035    wd->main_box = elm_box_add(parent);
1036    elm_box_horizontal_set(wd->main_box, EINA_TRUE);
1037    elm_box_homogeneous_set(wd->main_box, EINA_TRUE);
1038    evas_object_size_hint_weight_set(wd->main_box, EVAS_HINT_EXPAND,
1039                                     EVAS_HINT_EXPAND);
1040    evas_object_size_hint_align_set(wd->main_box, EVAS_HINT_FILL,
1041                                    EVAS_HINT_FILL);
1042    _elm_theme_object_set(obj, wd->main_box, "diskselector", "base",
1043                          "default");
1044    elm_widget_sub_object_add(obj, wd->main_box);
1045
1046    elm_smart_scroller_child_set(wd->scroller, wd->main_box);
1047
1048    wd->left_blank = edje_object_add(evas_object_evas_get(obj));
1049    _elm_theme_object_set(obj, wd->left_blank, "diskselector", "item",
1050                          "default");
1051    evas_object_size_hint_weight_set(wd->left_blank, EVAS_HINT_EXPAND,
1052                                     EVAS_HINT_EXPAND);
1053    evas_object_size_hint_align_set(wd->left_blank, EVAS_HINT_FILL,
1054                                    EVAS_HINT_FILL);
1055    elm_box_pack_end(wd->main_box, wd->left_blank);
1056    evas_object_show(wd->left_blank);
1057
1058    wd->right_blank = edje_object_add(evas_object_evas_get(obj));
1059    _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
1060                          "default");
1061    evas_object_size_hint_weight_set(wd->right_blank, EVAS_HINT_EXPAND,
1062                                     EVAS_HINT_EXPAND);
1063    evas_object_size_hint_align_set(wd->right_blank, EVAS_HINT_FILL,
1064                                    EVAS_HINT_FILL);
1065    elm_box_pack_end(wd->main_box, wd->right_blank);
1066    evas_object_show(wd->right_blank);
1067
1068    _theme_data_get(wd);
1069
1070    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1071    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1072    _sizing_eval(obj);
1073    return obj;
1074 }
1075
1076 EAPI Eina_Bool
1077 elm_diskselector_round_get(const Evas_Object *obj)
1078 {
1079    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1080    Widget_Data *wd = elm_widget_data_get(obj);
1081    if (!wd) return EINA_FALSE;
1082    return wd->round;
1083 }
1084
1085 EAPI void
1086 elm_diskselector_round_set(Evas_Object * obj, Eina_Bool round)
1087 {
1088    Eina_List *elist;
1089    Elm_Diskselector_Item *it;
1090
1091    ELM_CHECK_WIDTYPE(obj, widtype);
1092    Widget_Data *wd = elm_widget_data_get(obj);
1093    if (!wd) return;
1094
1095    if (wd->round == round)
1096      return;
1097
1098    wd->round = round;
1099    if (round)
1100      {
1101         wd->r_items = eina_list_clone(wd->items);
1102         elm_box_unpack(wd->main_box, wd->left_blank);
1103         evas_object_hide(wd->left_blank);
1104         elm_box_unpack(wd->main_box, wd->right_blank);
1105         evas_object_hide(wd->right_blank);
1106         if (!wd->items)
1107           return;
1108
1109         _round_items_add(wd);
1110
1111         if (wd->last)
1112           elm_box_pack_start(wd->main_box, wd->VIEW(last));
1113         if (wd->s_last)
1114           elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1115
1116         // if more than 3 items should be displayed
1117         EINA_LIST_FOREACH(wd->under_items, elist, it)
1118            elm_box_pack_start(wd->main_box, VIEW(it));
1119
1120         if (wd->first)
1121           elm_box_pack_end(wd->main_box, wd->VIEW(first));
1122         if (wd->second)
1123           elm_box_pack_end(wd->main_box, wd->VIEW(second));
1124
1125         // if more than 3 items should be displayed
1126         EINA_LIST_FOREACH(wd->over_items, elist, it)
1127            elm_box_pack_end(wd->main_box, VIEW(it));
1128      }
1129    else
1130      {
1131         _round_items_del(wd);
1132         elm_box_pack_start(wd->main_box, wd->left_blank);
1133         elm_box_pack_end(wd->main_box, wd->right_blank);
1134         eina_list_free(wd->r_items);
1135         wd->r_items = NULL;
1136      }
1137
1138    _selected_item_indicate(wd->selected_item);
1139    _sizing_eval(obj);
1140 }
1141
1142 EAPI int
1143 elm_diskselector_side_label_length_get(const Evas_Object *obj)
1144 {
1145    ELM_CHECK_WIDTYPE(obj, widtype) 0;
1146    Widget_Data *wd = elm_widget_data_get(obj);
1147    if (!wd) return 0;
1148    return wd->len_side;
1149 }
1150
1151 EAPI void
1152 elm_diskselector_side_label_length_set(Evas_Object *obj, int len)
1153 {
1154    ELM_CHECK_WIDTYPE(obj, widtype);
1155    Widget_Data *wd = elm_widget_data_get(obj);
1156    if (!wd) return;
1157    wd->len_side = len;
1158 }
1159
1160 EAPI void
1161 elm_diskselector_side_label_lenght_set(Evas_Object *obj, int len)
1162 {
1163    return elm_diskselector_side_label_length_set(obj, len);
1164 }
1165
1166 EAPI int
1167 elm_diskselector_side_label_lenght_get(const Evas_Object *obj)
1168 {
1169    return elm_diskselector_side_label_length_get(obj);
1170 }
1171
1172 EAPI void
1173 elm_diskselector_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1174 {
1175    ELM_CHECK_WIDTYPE(obj, widtype);
1176    Widget_Data *wd = elm_widget_data_get(obj);
1177    if (!wd) return;
1178    if (wd->scroller)
1179      elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
1180 }
1181
1182 EAPI void
1183 elm_diskselector_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1184 {
1185    ELM_CHECK_WIDTYPE(obj, widtype);
1186    Widget_Data *wd = elm_widget_data_get(obj);
1187    if (!wd) return;
1188    elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
1189 }
1190
1191 EAPI void
1192 elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
1193 {
1194    ELM_CHECK_WIDTYPE(obj, widtype);
1195    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
1196    Widget_Data *wd = elm_widget_data_get(obj);
1197    if ((!wd) || (!wd->scroller)) return;
1198    elm_smart_scroller_policy_get(wd->scroller, &s_policy_h, &s_policy_v);
1199    *policy_h = (Elm_Scroller_Policy) s_policy_h;
1200    *policy_v = (Elm_Scroller_Policy) s_policy_v;
1201 }
1202
1203 EAPI void
1204 elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
1205 {
1206    ELM_CHECK_WIDTYPE(obj, widtype);
1207    Widget_Data *wd = elm_widget_data_get(obj);
1208    if ((!wd) || (!wd->scroller)) return;
1209    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1210        (policy_v >= ELM_SCROLLER_POLICY_LAST))
1211      return;
1212    elm_smart_scroller_policy_set(wd->scroller, policy_h, policy_v);
1213 }
1214
1215 EAPI void
1216 elm_diskselector_clear(Evas_Object *obj)
1217 {
1218    ELM_CHECK_WIDTYPE(obj, widtype);
1219    Widget_Data *wd = elm_widget_data_get(obj);
1220    Elm_Diskselector_Item *it;
1221
1222    if (!wd) return;
1223    if (!wd->items) return;
1224
1225    wd->selected_item = NULL;
1226    EINA_LIST_FREE(wd->items, it)
1227      {
1228         _item_del(it);
1229         elm_widget_item_free(it);
1230      }
1231    _round_items_del(wd);
1232    _sizing_eval(obj);
1233 }
1234
1235 EAPI const Eina_List *
1236 elm_diskselector_items_get(const Evas_Object *obj)
1237 {
1238    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1239    Widget_Data *wd = elm_widget_data_get(obj);
1240    if (!wd) return NULL;
1241    return wd->items;
1242 }
1243
1244 EAPI Elm_Object_Item *
1245 elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
1246 {
1247    Elm_Diskselector_Item *it;
1248    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1249    Widget_Data *wd = elm_widget_data_get(obj);
1250    if (!wd) return NULL;
1251
1252    it = _item_new(obj, icon, label, func, data);
1253    wd->items = eina_list_append(wd->items, it);
1254    it->node = eina_list_last(wd->items);
1255    wd->item_count++;
1256    if (wd->round)
1257      {
1258         _round_items_del(wd);
1259         wd->r_items = eina_list_append(wd->r_items, it);
1260         _round_items_add(wd);
1261         if (wd->last)
1262           elm_box_pack_start(wd->main_box, wd->VIEW(last));
1263         if (wd->s_last)
1264           elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1265         elm_box_pack_end(wd->main_box, VIEW(it));
1266         if (wd->first)
1267           elm_box_pack_end(wd->main_box, wd->VIEW(first));
1268         if (wd->second)
1269           elm_box_pack_end(wd->main_box, wd->VIEW(second));
1270      }
1271    else
1272      {
1273         elm_box_unpack(wd->main_box, wd->right_blank);
1274         elm_box_pack_end(wd->main_box, VIEW(it));
1275         elm_box_pack_end(wd->main_box, wd->right_blank);
1276      }
1277    if (!wd->selected_item)
1278      wd->selected_item = it;
1279    if (!wd->idler)
1280      wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
1281    _sizing_eval(obj);
1282    return (Elm_Object_Item *) it;
1283 }
1284
1285 EAPI void
1286 elm_diskselector_item_del(Elm_Object_Item * it)
1287 {
1288    elm_object_item_del(it);
1289 }
1290
1291 EAPI const char *
1292 elm_diskselector_item_label_get(const Elm_Object_Item * it)
1293 {
1294    return _item_text_get_hook(it, NULL);
1295 }
1296
1297 EAPI void
1298 elm_diskselector_item_label_set(Elm_Object_Item * it, const char *label)
1299 {
1300    _item_text_set_hook(it, NULL, label);
1301 }
1302
1303 EAPI Elm_Object_Item *
1304 elm_diskselector_selected_item_get(const Evas_Object *obj)
1305 {
1306    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1307    Widget_Data *wd = elm_widget_data_get(obj);
1308    if (!wd) return NULL;
1309    return (Elm_Object_Item *) wd->selected_item;
1310 }
1311
1312 EAPI void
1313 elm_diskselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1314 {
1315    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1316    Widget_Data *wd;
1317    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1318    wd = elm_widget_data_get(WIDGET(item));
1319    if (!wd) return;
1320
1321    if ((wd->selected_item == item) && (selected))
1322      return;
1323
1324    if ((wd->selected_item == item) && (!selected))
1325      wd->selected_item = eina_list_data_get(wd->items);
1326    else
1327      {
1328         wd->selected_item = item;
1329         _selected_item_indicate(wd->selected_item);
1330      }
1331
1332    if (!wd->idler)
1333      wd->idler = ecore_idle_enterer_before_add(_move_scroller, WIDGET(item));
1334 }
1335
1336 EAPI Eina_Bool
1337 elm_diskselector_item_selected_get(const Elm_Object_Item *it)
1338 {
1339    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1340    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
1341    if (!wd) return EINA_FALSE;
1342    return (wd->selected_item == ((Elm_Diskselector_Item *) it));
1343 }
1344
1345 EAPI void
1346 elm_diskselector_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb func)
1347 {
1348    elm_object_item_del_cb_set(it, func);
1349 }
1350
1351 EAPI void *
1352 elm_diskselector_item_data_get(const Elm_Object_Item *it)
1353 {
1354    return elm_object_item_data_get(it);
1355 }
1356
1357 EAPI Evas_Object *
1358 elm_diskselector_item_icon_get(const Elm_Object_Item *it)
1359 {
1360    return _item_content_get_hook(it, NULL);
1361 }
1362
1363 EAPI void
1364 elm_diskselector_item_icon_set(Elm_Object_Item *it, Evas_Object *icon)
1365 {
1366    _item_content_set_hook(it, NULL, icon);
1367 }
1368
1369 EAPI Elm_Object_Item *
1370 elm_diskselector_item_prev_get(const Elm_Object_Item *it)
1371 {
1372    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1373    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1374    if (item->node->prev) return item->node->prev->data;
1375    else return NULL;
1376 }
1377
1378 EAPI Elm_Object_Item *
1379 elm_diskselector_item_next_get(const Elm_Object_Item *it)
1380 {
1381    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1382    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1383    if (item->node->next) return item->node->next->data;
1384    else return NULL;
1385 }
1386
1387 EAPI Elm_Object_Item *
1388 elm_diskselector_first_item_get(const Evas_Object *obj)
1389 {
1390    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1391    Widget_Data *wd = elm_widget_data_get(obj);
1392    if (!wd || !wd->items) return NULL;
1393    return eina_list_data_get(wd->items);
1394 }
1395
1396 EAPI Elm_Object_Item *
1397 elm_diskselector_last_item_get(const Evas_Object *obj)
1398 {
1399    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1400    Widget_Data *wd = elm_widget_data_get(obj);
1401    if (!wd || !wd->items) return NULL;
1402    return eina_list_data_get(eina_list_last(wd->items));
1403 }
1404
1405 EAPI void
1406 elm_diskselector_item_tooltip_text_set(Elm_Object_Item *it, const char *text)
1407 {
1408    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1409    elm_widget_item_tooltip_text_set(it, text);
1410 }
1411
1412 EAPI void
1413 elm_diskselector_item_tooltip_content_cb_set(Elm_Object_Item *it, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
1414 {
1415    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1416    elm_widget_item_tooltip_content_cb_set(it, func, data, del_cb);
1417 }
1418
1419 EAPI void
1420 elm_diskselector_item_tooltip_unset(Elm_Object_Item *it)
1421 {
1422    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1423    elm_widget_item_tooltip_unset(it);
1424 }
1425
1426 EAPI void
1427 elm_diskselector_item_tooltip_style_set(Elm_Object_Item *it, const char *style)
1428 {
1429    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1430    elm_widget_item_tooltip_style_set(it, style);
1431 }
1432
1433 EAPI const char *
1434 elm_diskselector_item_tooltip_style_get(const Elm_Object_Item *it)
1435 {
1436    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1437    return elm_widget_item_tooltip_style_get(it);
1438 }
1439
1440 EAPI void
1441 elm_diskselector_item_cursor_set(Elm_Object_Item *it, const char *cursor)
1442 {
1443    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1444    elm_widget_item_cursor_set(it, cursor);
1445 }
1446
1447 EAPI const char *
1448 elm_diskselector_item_cursor_get(const Elm_Object_Item *it)
1449 {
1450    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1451    return elm_widget_item_cursor_get(it);
1452 }
1453
1454 EAPI void
1455 elm_diskselector_item_cursor_unset(Elm_Object_Item *it)
1456 {
1457    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1458    elm_widget_item_cursor_unset(it);
1459 }
1460
1461 EAPI void
1462 elm_diskselector_item_cursor_style_set(Elm_Object_Item *it, const char *style)
1463 {
1464    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1465    elm_widget_item_cursor_style_set(it, style);
1466 }
1467
1468 EAPI const char *
1469 elm_diskselector_item_cursor_style_get(const Elm_Object_Item *it)
1470 {
1471    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1472    return elm_widget_item_cursor_style_get(it);
1473 }
1474
1475 EAPI void
1476 elm_diskselector_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only)
1477 {
1478    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1479    elm_widget_item_cursor_engine_only_set(it, engine_only);
1480 }
1481
1482 EAPI Eina_Bool
1483 elm_diskselector_item_cursor_engine_only_get(const Elm_Object_Item *it)
1484 {
1485    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1486    return elm_widget_item_cursor_engine_only_get(it);
1487 }
1488
1489 EAPI void
1490 elm_diskselector_display_item_num_set(Evas_Object *obj, int num)
1491 {
1492    ELM_CHECK_WIDTYPE(obj, widtype);
1493    Widget_Data *wd = elm_widget_data_get(obj);
1494    if (!wd) return;
1495    if (num < DISPLAY_ITEM_NUM_MIN) num = DISPLAY_ITEM_NUM_MIN;
1496    wd->display_item_num = num;
1497    wd->display_item_num_by_api = EINA_TRUE;
1498 }
1499
1500 EAPI int
1501 elm_diskselector_display_item_num_get(const Evas_Object *item)
1502 {
1503    ELM_CHECK_WIDTYPE(item, widtype) (-1);
1504    Widget_Data *wd = elm_widget_data_get(item);
1505    if (!wd) return -1;
1506    return wd->display_item_num;
1507 }