elementary - modified item_del_pre_hook function prototype.
[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 Eina_Bool
230 _item_del_pre_hook(Elm_Object_Item *it)
231 {
232    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
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 EINA_FALSE;
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    return EINA_TRUE;
331 }
332
333 static Elm_Diskselector_Item *
334 _item_new(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data)
335 {
336    Elm_Diskselector_Item *it;
337    const char *style = elm_widget_style_get(obj);
338
339    it = elm_widget_item_new(obj, Elm_Diskselector_Item);
340    if (!it) return NULL;
341
342    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
343    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
344    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
345    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
346    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
347
348    it->label = eina_stringshare_add(label);
349    it->icon = icon;
350    it->func = func;
351    it->base.data = data;
352    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
353    _elm_theme_object_set(obj, VIEW(it), "diskselector", "item", style);
354    evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND,
355                                     EVAS_HINT_EXPAND);
356    evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL,
357                                    EVAS_HINT_FILL);
358    evas_object_show(VIEW(it));
359
360    if (it->label)
361      {
362         edje_object_part_text_set(VIEW(it), "elm.text", it->label);
363         edje_object_signal_callback_add(VIEW(it), "elm,action,click", "", _item_click_cb, it);
364      }
365    if (it->icon)
366      {
367         evas_object_size_hint_min_set(it->icon, 24, 24);
368         evas_object_size_hint_max_set(it->icon, 40, 40);
369         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
370         evas_object_show(it->icon);
371         elm_widget_sub_object_add(obj, it->icon);
372      }
373    return it;
374 }
375
376 static void
377 _theme_data_get(Widget_Data *wd)
378 {
379    const char* str;
380    Evas_Object *parent;
381    str = edje_object_data_get(wd->right_blank, "len_threshold");
382    if (str) wd->len_threshold = MAX(0, atoi(str));
383    else wd->len_threshold = 0;
384
385    if (!wd->display_item_num_by_api)
386      {
387         str = edje_object_data_get(wd->right_blank, "display_item_num");
388         if (str) wd->display_item_num = MAX(DISPLAY_ITEM_NUM_MIN, atoi(str));
389         else wd->display_item_num = DISPLAY_ITEM_NUM_MIN;
390      }
391
392    str = edje_object_data_get(wd->right_blank, "min_width");
393    if (str) wd->minw = MAX(-1, atoi(str)) * elm_scale_get();
394    else
395      {
396         parent = elm_widget_parent_widget_get(wd->self);
397         if (!parent) wd->minw = -1;
398         else evas_object_geometry_get(parent, NULL, NULL, &wd->minw, NULL);
399      }
400
401    str = edje_object_data_get(wd->right_blank, "min_height");
402    if (str) wd->minh = MAX(-1, atoi(str)) * elm_scale_get();
403    else wd->minh = -1;
404 }
405
406 static void
407 _del_hook(Evas_Object * obj)
408 {
409    Widget_Data *wd = elm_widget_data_get(obj);
410    if (!wd) return;
411    free(wd);
412 }
413
414 static void
415 _del_pre_hook(Evas_Object * obj)
416 {
417    Elm_Diskselector_Item *it;
418    Eina_List *l;
419
420    Widget_Data *wd = elm_widget_data_get(obj);
421    if (!wd) return;
422
423    if (wd->left_blank)
424      evas_object_del(wd->left_blank);
425    if (wd->right_blank)
426      evas_object_del(wd->right_blank);
427    if (wd->last)
428      {
429         eina_stringshare_del(wd->last->label);
430         evas_object_del(wd->VIEW(last));
431         free(wd->last);
432      }
433    if (wd->s_last)
434      {
435         eina_stringshare_del(wd->s_last->label);
436         evas_object_del(wd->VIEW(s_last));
437         free(wd->s_last);
438      }
439    if (wd->second)
440      {
441         eina_stringshare_del(wd->second->label);
442         evas_object_del(wd->VIEW(second));
443         free(wd->second);
444      }
445    if (wd->first)
446      {
447         eina_stringshare_del(wd->first->label);
448         evas_object_del(wd->VIEW(first));
449         free(wd->first);
450      }
451
452    EINA_LIST_FOREACH(wd->under_items, l, it)
453      {
454         if (it)
455           {
456              eina_stringshare_del(it->label);
457              evas_object_del(VIEW(it));
458              free(it);
459           }
460      }
461
462    EINA_LIST_FOREACH(wd->over_items, l, it)
463    {
464      if (it)
465         {
466            eina_stringshare_del(it->label);
467            evas_object_del(VIEW(it));
468            free(it);
469         }
470    }
471
472    EINA_LIST_FREE(wd->items, it)
473      {
474         _item_del(it);
475         elm_widget_item_free(it);
476      }
477    eina_list_free(wd->r_items);
478 }
479
480 static void
481 _sizing_eval(Evas_Object * obj)
482 {
483    Widget_Data *wd = elm_widget_data_get(obj);
484    if (!wd) return;
485    _diskselector_object_resize(obj, NULL, obj, NULL);
486 }
487
488 static void
489 _theme_hook(Evas_Object * obj)
490 {
491    Eina_List *l;
492    Elm_Diskselector_Item *it;
493    Widget_Data *wd = elm_widget_data_get(obj);
494    if (!wd) return;
495
496    if (wd->scroller)
497      elm_smart_scroller_object_theme_set(obj, wd->scroller, "diskselector",
498                                          "base", elm_widget_style_get(obj));
499    if (wd->round)
500      {
501         EINA_LIST_FOREACH(wd->r_items, l, it)
502           {
503              _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
504                                    elm_widget_style_get(obj));
505              edje_object_part_text_set(VIEW(it), "elm.text", it->label);
506           }
507      }
508    else
509      {
510         EINA_LIST_FOREACH(wd->items, l, it)
511           {
512              _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
513                                    elm_widget_style_get(obj));
514              edje_object_part_text_set(VIEW(it), "elm.text", it->label);
515           }
516      }
517    _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
518                                    elm_widget_style_get(obj));
519    _theme_data_get(wd);
520    _sizing_eval(obj);
521 }
522
523 static void
524 _sub_del(void *data __UNUSED__, Evas_Object * obj, void *event_info)
525 {
526    Widget_Data *wd = elm_widget_data_get(obj);
527    Evas_Object *sub = event_info;
528    Elm_Diskselector_Item *it;
529    const Eina_List *l;
530
531    if (!wd) return;
532    if (!sub) abort();
533    if (sub == wd->scroller)
534      wd->scroller = NULL;
535    else
536      {
537         EINA_LIST_FOREACH(wd->items, l, it)
538           {
539              if (sub == it->icon)
540                {
541                   it->icon = NULL;
542                   _sizing_eval(obj);
543                   break;
544                }
545           }
546      }
547 }
548
549 static void
550 _select_item(Elm_Diskselector_Item *it)
551 {
552    if (!it) return;
553    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
554    wd->selected_item = it;
555    _selected_item_indicate(wd->selected_item);
556    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
557    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
558 }
559
560 static void
561 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
562 {
563    Widget_Data *wd = elm_widget_data_get(obj);
564    if (!wd)
565      return;
566
567    if (elm_widget_focus_get(obj))
568      {
569         edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
570         evas_object_focus_set(wd->self, EINA_TRUE);
571      }
572    else
573      {
574         edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
575         evas_object_focus_set(wd->self, EINA_FALSE);
576      }
577 }
578
579 static Eina_Bool
580 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
581 {
582    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
583    Evas_Event_Key_Down *ev = event_info;
584    Widget_Data *wd = elm_widget_data_get(obj);
585    if (!wd) return EINA_FALSE;
586    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
587    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
588
589    Elm_Diskselector_Item *it = NULL;
590    Eina_List *l;
591
592    if (!wd->selected_item) {
593         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
594         return EINA_TRUE;
595    }
596
597    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")) ||
598        (!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
599      {
600         l = wd->selected_item->node->prev;
601         if ((!l) && (wd->round))
602           l = eina_list_last(wd->items);
603      }
604    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")) ||
605             (!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
606      {
607         l = wd->selected_item->node->next;
608         if ((!l) && (wd->round))
609           l = wd->items;
610      }
611    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
612      l = wd->items;
613    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
614      l = eina_list_last(wd->items);
615    else return EINA_FALSE;
616
617    if (l)
618      it = eina_list_data_get(l);
619
620    if (it)
621      {
622         wd->selected_item = it;
623         if (!wd->idler)
624           wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
625      }
626
627    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
628    return EINA_TRUE;
629 }
630
631 static void
632 _selected_item_indicate(Elm_Diskselector_Item *it)
633 {
634    Elm_Diskselector_Item *item;
635    Eina_List *l;
636    Widget_Data *wd;
637    wd = elm_widget_data_get(WIDGET(it));
638
639    if (!wd) return;
640
641    EINA_LIST_FOREACH(wd->r_items, l, item)
642      {
643         if (!strcmp(item->label, it->label)) edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
644         else
645            edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
646      }
647 }
648
649 static void
650 _item_click_cb(void *data, Evas_Object *obj __UNUSED__,
651                const char *emission __UNUSED__, const char *source __UNUSED__)
652 {
653    Elm_Diskselector_Item *it = data;
654
655    if (!it) return;
656
657    Widget_Data *wd;
658    wd = elm_widget_data_get(WIDGET(it));
659
660    if (!wd) return;
661
662    if (wd->selected_item != it)
663      {
664         wd->selected_item = it;
665         _selected_item_indicate(wd->selected_item);
666      }
667
668    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
669 }
670
671 static void
672 _scroller_move_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
673 {
674    Evas_Coord x, y, w, h, bw;
675    Widget_Data *wd = data;
676
677    _check_string(wd);
678    elm_smart_scroller_child_pos_get(obj, &x, &y);
679    elm_smart_scroller_child_viewport_size_get(obj, &w, &h);
680    if (wd->round)
681      {
682         evas_object_geometry_get(wd->main_box, NULL, NULL, &bw, NULL);
683         if (x > ((w / wd->display_item_num) * (wd->item_count + (wd->display_item_num % 2))))
684            elm_smart_scroller_child_region_show(wd->scroller,
685                                                x - ((w / wd->display_item_num) * wd->item_count),
686                                                y, w, h);
687         else if (x < 0)
688            elm_smart_scroller_child_region_show(wd->scroller,
689                                                x + ((w / wd->display_item_num) * wd->item_count),
690                                                y, w, h);
691      }
692 }
693
694 static void
695 _scroller_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
696 {
697    Elm_Diskselector_Item *it;
698    Widget_Data *wd = data;
699    Evas_Coord x, w, ow;
700    Eina_List *l, *list;
701
702    if (wd->idler) return;
703
704    if (!wd->round)
705      list = wd->items;
706    else
707      list = wd->r_items;
708
709    evas_object_geometry_get(wd->scroller, NULL, NULL, &ow, NULL);
710    EINA_LIST_FOREACH(list, l, it)
711      {
712         evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
713         if (abs((int)(ow / 2 - (int)(x + w / 2))) < 10) break;
714      }
715
716    if (!it) return;
717    _select_item(it);
718 }
719
720 static Eina_Bool
721 _move_scroller(void *data)
722 {
723    Evas_Object *obj = data;
724    Widget_Data *wd;
725    Eina_List *list, *l;
726    Elm_Diskselector_Item *dit;
727    Evas_Coord y, w, h;
728    int i;
729
730    wd = elm_widget_data_get(obj);
731    if (!wd) return EINA_FALSE;
732
733    if (!wd->round)
734      {
735         i = 0;
736         list = wd->items;
737      }
738    else
739      {
740         i = 1;
741         list = wd->r_items;
742      }
743
744    EINA_LIST_FOREACH(list, l, dit)
745      {
746         if (wd->selected_item == dit)
747            break;
748         i++;
749      }
750
751    if (wd->round) i -= CEIL(wd->display_item_num);
752
753    if (!dit)
754      {
755         wd->selected_item =
756            (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
757         return EINA_FALSE;
758      }
759
760    evas_object_geometry_get(wd->scroller, NULL, &y, &w, &h);
761    //move scroller in two steps for getting smooth launching effect.
762    if (i > 2)
763      elm_smart_scroller_child_region_show(wd->scroller, w / wd->display_item_num * (i-2), y, w, h);
764    elm_smart_scroller_region_bring_in(wd->scroller, w / wd->display_item_num * i, y, w, h);
765
766    _select_item(dit);
767    if (wd->idler)
768      {
769         ecore_idle_enterer_del(wd->idler);
770         wd->idler = NULL;
771      }
772    wd->init = EINA_TRUE;
773    _check_string(wd);
774
775    return EINA_TRUE;
776 }
777
778 static void
779 _round_item_del(Widget_Data *wd, Elm_Diskselector_Item *it)
780 {
781    if (!it) return;
782    elm_box_unpack(wd->main_box, VIEW(it));
783    wd->r_items = eina_list_remove(wd->r_items, it);
784    eina_stringshare_del(it->label);
785    elm_widget_item_free(it);
786 }
787
788 static void
789 _round_items_del(Widget_Data *wd)
790 {
791    Eina_List *l;
792    Elm_Diskselector_Item * it;
793
794    _round_item_del(wd, wd->last);
795    wd->last = NULL;
796    _round_item_del(wd, wd->s_last);
797    wd->s_last = NULL;
798    _round_item_del(wd, wd->second);
799    wd->second = NULL;
800    _round_item_del(wd, wd->first);
801    wd->first = NULL;
802
803    EINA_LIST_FOREACH(wd->under_items, l, it)
804      {
805         _round_item_del(wd, it);
806      }
807    wd->under_items = eina_list_free(wd->under_items);
808
809    EINA_LIST_FOREACH(wd->over_items, l, it)
810      {
811         _round_item_del(wd, it);
812      }
813    wd->over_items = eina_list_free(wd->over_items);
814 }
815
816 static void
817 _round_items_add(Widget_Data *wd)
818 {
819    Elm_Diskselector_Item *dit;
820    Elm_Diskselector_Item *it;
821    Elm_Diskselector_Item *temp_it;
822    int i = 0;
823    dit = it = eina_list_nth(wd->items, 0);
824    if (!dit) return;
825
826    if (!wd->first)
827      {
828         wd->first = _item_new(WIDGET(it), it->icon, it->label, it->func,
829                               it->base.data);
830         wd->first->node = it->node;
831         wd->r_items = eina_list_append(wd->r_items, wd->first);
832      }
833
834    it = eina_list_nth(wd->items, 1);
835    if (!it)
836      it = dit;
837    if (!wd->second)
838      {
839         wd->second = _item_new(WIDGET(it), it->icon, it->label, it->func,
840                                it->base.data);
841         wd->second->node = it->node;
842         wd->r_items = eina_list_append(wd->r_items, wd->second);
843      }
844
845    // if more than 3 itmes should be displayed
846    for (i = 2; i < CEIL(wd->display_item_num); i++)
847      {
848         it = eina_list_nth(wd->items, i);
849         if (!it) it = dit;
850         temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
851         wd->over_items = eina_list_append(wd->over_items, temp_it);
852         wd->r_items = eina_list_append(wd->r_items, temp_it);
853      }
854
855    it = eina_list_nth(wd->items, wd->item_count - 1);
856    if (!it)
857      it = dit;
858    if (!wd->last)
859      {
860         wd->last = _item_new(WIDGET(it), it->icon, it->label, it->func,
861                              it->base.data);
862         wd->last->node = it->node;
863         wd->r_items = eina_list_prepend(wd->r_items, wd->last);
864      }
865
866    it = eina_list_nth(wd->items, wd->item_count - 2);
867    if (!it)
868      it = dit;
869    if (!wd->s_last)
870      {
871         wd->s_last = _item_new(WIDGET(it), it->icon, it->label, it->func,
872                                it->base.data);
873         wd->s_last->node = it->node;
874         wd->r_items = eina_list_prepend(wd->r_items, wd->s_last);
875      }
876
877    // if more than 3 itmes should be displayed
878    for (i = 3; i <= CEIL(wd->display_item_num); i++)
879      {
880         it = eina_list_nth(wd->items, wd->item_count - i);
881         if (!it) it = dit;
882         temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
883         wd->under_items = eina_list_append(wd->under_items, temp_it);
884         wd->r_items = eina_list_prepend(wd->r_items, temp_it);
885      }
886 }
887
888 static void
889 _item_icon_set(Elm_Diskselector_Item *it, Evas_Object *icon)
890 {
891    if (it->icon == icon) return;
892    if (it->icon)
893      evas_object_del(it->icon);
894    it->icon = icon;
895    if (VIEW(it))
896      {
897         evas_object_size_hint_min_set(it->icon, 24, 24);
898         evas_object_size_hint_max_set(it->icon, 40, 40);
899         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
900         evas_object_show(it->icon);
901         elm_widget_sub_object_add(WIDGET(it), it->icon);
902      }
903 }
904
905 static void
906 _check_identical_item(Elm_Diskselector_Item *it, Evas_Object *icon)
907 {
908    Widget_Data *wd;
909    Elm_Diskselector_Item *dit;
910    Eina_List *l;
911    int idx = 0;
912    int ic = 0;
913    int ac = 0;
914
915    wd = elm_widget_data_get(WIDGET(it));
916    if (!wd) return;
917
918    if (wd->round)
919      {
920         // Get index from indentical item from round items
921         EINA_LIST_FOREACH(wd->r_items, l, dit)
922           {
923              if (it == dit) break;
924              idx++;
925           }
926
927         // No item to match
928         ic = eina_list_count(wd->r_items);
929         if (idx >= ic) return;
930         dit = NULL;
931
932         // Number of added items: CEIL(wd->display_item_num)
933         ac = CEIL(wd->display_item_num);
934
935         if (((idx >= 0) && (idx < ac)) ||
936             ((idx >= ac) && (idx < (2 * ac))))
937           {
938               // Selected item: under, low region
939              dit = eina_list_nth(wd->r_items,
940                                  idx + ic - (2 * ac));
941           }
942         else if (((idx >= (ic - ac)) && (idx < ic)) ||
943                  ((idx >= (ic - (2 * ac))) && (idx < ic - ac)))
944           {
945               // Selected item: over, high region
946               dit = eina_list_nth(wd->r_items,
947                                   idx - ic + (2 * ac));
948           }
949
950         if(dit) _item_icon_set(dit, icon);
951         _sizing_eval(wd->self);
952      }
953 }
954
955 static void
956 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
957 {
958    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
959    Elm_Diskselector_Item *item;
960    if (part && strcmp(part, "default")) return;
961    item = (Elm_Diskselector_Item *) it;
962    eina_stringshare_replace(&item->label, label);
963    edje_object_part_text_set(VIEW(item), "elm.text", item->label);
964 }
965
966 static const char *
967 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
968 {
969    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
970    if (part && strcmp(part, "default")) return NULL;
971    return ((Elm_Diskselector_Item *) it)->label;
972 }
973
974 static void
975 _item_content_set_hook(Elm_Object_Item *it,
976                        const char *part,
977                        Evas_Object *content)
978 {
979    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
980    if (part && strcmp(part, "icon")) return;
981    _item_icon_set((Elm_Diskselector_Item *) it, content);
982    _check_identical_item((Elm_Diskselector_Item *) it, content);
983 }
984
985 static Evas_Object *
986 _item_content_get_hook(const Elm_Object_Item *it, const char *part)
987 {
988    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
989    if (part && strcmp(part, "icon")) return NULL;
990    return ((Elm_Diskselector_Item *) it)->icon;
991 }
992
993 EAPI Evas_Object *
994 elm_diskselector_add(Evas_Object *parent)
995 {
996    Evas *e;
997    Evas_Object *obj;
998    Widget_Data *wd;
999
1000    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1001
1002    ELM_SET_WIDTYPE(widtype, "diskselector");
1003    elm_widget_type_set(obj, "diskselector");
1004    elm_widget_sub_object_add(parent, obj);
1005    elm_widget_data_set(obj, wd);
1006    elm_widget_del_hook_set(obj, _del_hook);
1007    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1008    elm_widget_theme_hook_set(obj, _theme_hook);
1009    elm_widget_can_focus_set(obj, EINA_TRUE);
1010    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1011    elm_widget_event_hook_set(obj, _event_hook);
1012
1013    wd->self = obj;
1014    wd->item_count = 0;
1015    wd->round = EINA_FALSE;
1016    wd->init = EINA_FALSE;
1017    wd->len_side = 3;
1018    wd->display_item_num_by_api = EINA_FALSE;
1019
1020    wd->scroller = elm_smart_scroller_add(e);
1021    elm_smart_scroller_widget_set(wd->scroller, obj);
1022    _theme_hook(obj);
1023    elm_widget_resize_object_set(obj, wd->scroller);
1024    elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
1025                                  ELM_SMART_SCROLLER_POLICY_OFF);
1026    elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_TRUE, EINA_FALSE);
1027    evas_object_smart_callback_add(wd->scroller, "scroll", _scroller_move_cb,
1028                                   wd);
1029    evas_object_smart_callback_add(wd->scroller, "animate,stop",
1030                                   _scroller_stop_cb, wd);
1031    _elm_theme_object_set(obj, wd->scroller, "diskselector", "base",
1032                          "default");
1033    evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
1034                                   _diskselector_object_resize, obj);
1035
1036    wd->main_box = elm_box_add(parent);
1037    elm_box_horizontal_set(wd->main_box, EINA_TRUE);
1038    elm_box_homogeneous_set(wd->main_box, EINA_TRUE);
1039    evas_object_size_hint_weight_set(wd->main_box, EVAS_HINT_EXPAND,
1040                                     EVAS_HINT_EXPAND);
1041    evas_object_size_hint_align_set(wd->main_box, EVAS_HINT_FILL,
1042                                    EVAS_HINT_FILL);
1043    _elm_theme_object_set(obj, wd->main_box, "diskselector", "base",
1044                          "default");
1045    elm_widget_sub_object_add(obj, wd->main_box);
1046
1047    elm_smart_scroller_child_set(wd->scroller, wd->main_box);
1048
1049    wd->left_blank = edje_object_add(evas_object_evas_get(obj));
1050    _elm_theme_object_set(obj, wd->left_blank, "diskselector", "item",
1051                          "default");
1052    evas_object_size_hint_weight_set(wd->left_blank, EVAS_HINT_EXPAND,
1053                                     EVAS_HINT_EXPAND);
1054    evas_object_size_hint_align_set(wd->left_blank, EVAS_HINT_FILL,
1055                                    EVAS_HINT_FILL);
1056    elm_box_pack_end(wd->main_box, wd->left_blank);
1057    evas_object_show(wd->left_blank);
1058
1059    wd->right_blank = edje_object_add(evas_object_evas_get(obj));
1060    _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
1061                          "default");
1062    evas_object_size_hint_weight_set(wd->right_blank, EVAS_HINT_EXPAND,
1063                                     EVAS_HINT_EXPAND);
1064    evas_object_size_hint_align_set(wd->right_blank, EVAS_HINT_FILL,
1065                                    EVAS_HINT_FILL);
1066    elm_box_pack_end(wd->main_box, wd->right_blank);
1067    evas_object_show(wd->right_blank);
1068
1069    _theme_data_get(wd);
1070
1071    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1072    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1073    _sizing_eval(obj);
1074    return obj;
1075 }
1076
1077 EAPI Eina_Bool
1078 elm_diskselector_round_get(const Evas_Object *obj)
1079 {
1080    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1081    Widget_Data *wd = elm_widget_data_get(obj);
1082    if (!wd) return EINA_FALSE;
1083    return wd->round;
1084 }
1085
1086 EAPI void
1087 elm_diskselector_round_set(Evas_Object * obj, Eina_Bool round)
1088 {
1089    Eina_List *elist;
1090    Elm_Diskselector_Item *it;
1091
1092    ELM_CHECK_WIDTYPE(obj, widtype);
1093    Widget_Data *wd = elm_widget_data_get(obj);
1094    if (!wd) return;
1095
1096    if (wd->round == round)
1097      return;
1098
1099    wd->round = round;
1100    if (round)
1101      {
1102         wd->r_items = eina_list_clone(wd->items);
1103         elm_box_unpack(wd->main_box, wd->left_blank);
1104         evas_object_hide(wd->left_blank);
1105         elm_box_unpack(wd->main_box, wd->right_blank);
1106         evas_object_hide(wd->right_blank);
1107         if (!wd->items)
1108           return;
1109
1110         _round_items_add(wd);
1111
1112         if (wd->last)
1113           elm_box_pack_start(wd->main_box, wd->VIEW(last));
1114         if (wd->s_last)
1115           elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1116
1117         // if more than 3 items should be displayed
1118         EINA_LIST_FOREACH(wd->under_items, elist, it)
1119            elm_box_pack_start(wd->main_box, VIEW(it));
1120
1121         if (wd->first)
1122           elm_box_pack_end(wd->main_box, wd->VIEW(first));
1123         if (wd->second)
1124           elm_box_pack_end(wd->main_box, wd->VIEW(second));
1125
1126         // if more than 3 items should be displayed
1127         EINA_LIST_FOREACH(wd->over_items, elist, it)
1128            elm_box_pack_end(wd->main_box, VIEW(it));
1129      }
1130    else
1131      {
1132         _round_items_del(wd);
1133         elm_box_pack_start(wd->main_box, wd->left_blank);
1134         elm_box_pack_end(wd->main_box, wd->right_blank);
1135         eina_list_free(wd->r_items);
1136         wd->r_items = NULL;
1137      }
1138
1139    _selected_item_indicate(wd->selected_item);
1140    _sizing_eval(obj);
1141 }
1142
1143 EAPI int
1144 elm_diskselector_side_label_length_get(const Evas_Object *obj)
1145 {
1146    ELM_CHECK_WIDTYPE(obj, widtype) 0;
1147    Widget_Data *wd = elm_widget_data_get(obj);
1148    if (!wd) return 0;
1149    return wd->len_side;
1150 }
1151
1152 EAPI void
1153 elm_diskselector_side_label_length_set(Evas_Object *obj, int len)
1154 {
1155    ELM_CHECK_WIDTYPE(obj, widtype);
1156    Widget_Data *wd = elm_widget_data_get(obj);
1157    if (!wd) return;
1158    wd->len_side = len;
1159 }
1160
1161 EAPI void
1162 elm_diskselector_side_label_lenght_set(Evas_Object *obj, int len)
1163 {
1164    return elm_diskselector_side_label_length_set(obj, len);
1165 }
1166
1167 EAPI int
1168 elm_diskselector_side_label_lenght_get(const Evas_Object *obj)
1169 {
1170    return elm_diskselector_side_label_length_get(obj);
1171 }
1172
1173 EAPI void
1174 elm_diskselector_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1175 {
1176    ELM_CHECK_WIDTYPE(obj, widtype);
1177    Widget_Data *wd = elm_widget_data_get(obj);
1178    if (!wd) return;
1179    if (wd->scroller)
1180      elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
1181 }
1182
1183 EAPI void
1184 elm_diskselector_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1185 {
1186    ELM_CHECK_WIDTYPE(obj, widtype);
1187    Widget_Data *wd = elm_widget_data_get(obj);
1188    if (!wd) return;
1189    elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
1190 }
1191
1192 EAPI void
1193 elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
1194 {
1195    ELM_CHECK_WIDTYPE(obj, widtype);
1196    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
1197    Widget_Data *wd = elm_widget_data_get(obj);
1198    if ((!wd) || (!wd->scroller)) return;
1199    elm_smart_scroller_policy_get(wd->scroller, &s_policy_h, &s_policy_v);
1200    *policy_h = (Elm_Scroller_Policy) s_policy_h;
1201    *policy_v = (Elm_Scroller_Policy) s_policy_v;
1202 }
1203
1204 EAPI void
1205 elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
1206 {
1207    ELM_CHECK_WIDTYPE(obj, widtype);
1208    Widget_Data *wd = elm_widget_data_get(obj);
1209    if ((!wd) || (!wd->scroller)) return;
1210    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1211        (policy_v >= ELM_SCROLLER_POLICY_LAST))
1212      return;
1213    elm_smart_scroller_policy_set(wd->scroller, policy_h, policy_v);
1214 }
1215
1216 EAPI void
1217 elm_diskselector_clear(Evas_Object *obj)
1218 {
1219    ELM_CHECK_WIDTYPE(obj, widtype);
1220    Widget_Data *wd = elm_widget_data_get(obj);
1221    Elm_Diskselector_Item *it;
1222
1223    if (!wd) return;
1224    if (!wd->items) return;
1225
1226    wd->selected_item = NULL;
1227    EINA_LIST_FREE(wd->items, it)
1228      {
1229         _item_del(it);
1230         elm_widget_item_free(it);
1231      }
1232    _round_items_del(wd);
1233    _sizing_eval(obj);
1234 }
1235
1236 EAPI const Eina_List *
1237 elm_diskselector_items_get(const Evas_Object *obj)
1238 {
1239    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1240    Widget_Data *wd = elm_widget_data_get(obj);
1241    if (!wd) return NULL;
1242    return wd->items;
1243 }
1244
1245 EAPI Elm_Object_Item *
1246 elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
1247 {
1248    Elm_Diskselector_Item *it;
1249    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1250    Widget_Data *wd = elm_widget_data_get(obj);
1251    if (!wd) return NULL;
1252
1253    it = _item_new(obj, icon, label, func, data);
1254    wd->items = eina_list_append(wd->items, it);
1255    it->node = eina_list_last(wd->items);
1256    wd->item_count++;
1257    if (wd->round)
1258      {
1259         _round_items_del(wd);
1260         wd->r_items = eina_list_append(wd->r_items, it);
1261         _round_items_add(wd);
1262         if (wd->last)
1263           elm_box_pack_start(wd->main_box, wd->VIEW(last));
1264         if (wd->s_last)
1265           elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1266         elm_box_pack_end(wd->main_box, VIEW(it));
1267         if (wd->first)
1268           elm_box_pack_end(wd->main_box, wd->VIEW(first));
1269         if (wd->second)
1270           elm_box_pack_end(wd->main_box, wd->VIEW(second));
1271      }
1272    else
1273      {
1274         elm_box_unpack(wd->main_box, wd->right_blank);
1275         elm_box_pack_end(wd->main_box, VIEW(it));
1276         elm_box_pack_end(wd->main_box, wd->right_blank);
1277      }
1278    if (!wd->selected_item)
1279      wd->selected_item = it;
1280    if (!wd->idler)
1281      wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
1282    _sizing_eval(obj);
1283    return (Elm_Object_Item *) it;
1284 }
1285
1286 EAPI void
1287 elm_diskselector_item_del(Elm_Object_Item * it)
1288 {
1289    elm_object_item_del(it);
1290 }
1291
1292 EAPI const char *
1293 elm_diskselector_item_label_get(const Elm_Object_Item * it)
1294 {
1295    return _item_text_get_hook(it, NULL);
1296 }
1297
1298 EAPI void
1299 elm_diskselector_item_label_set(Elm_Object_Item * it, const char *label)
1300 {
1301    _item_text_set_hook(it, NULL, label);
1302 }
1303
1304 EAPI Elm_Object_Item *
1305 elm_diskselector_selected_item_get(const Evas_Object *obj)
1306 {
1307    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1308    Widget_Data *wd = elm_widget_data_get(obj);
1309    if (!wd) return NULL;
1310    return (Elm_Object_Item *) wd->selected_item;
1311 }
1312
1313 EAPI void
1314 elm_diskselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1315 {
1316    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1317    Widget_Data *wd;
1318    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1319    wd = elm_widget_data_get(WIDGET(item));
1320    if (!wd) return;
1321
1322    if ((wd->selected_item == item) && (selected))
1323      return;
1324
1325    if ((wd->selected_item == item) && (!selected))
1326      wd->selected_item = eina_list_data_get(wd->items);
1327    else
1328      {
1329         wd->selected_item = item;
1330         _selected_item_indicate(wd->selected_item);
1331      }
1332
1333    if (!wd->idler)
1334      wd->idler = ecore_idle_enterer_before_add(_move_scroller, WIDGET(item));
1335 }
1336
1337 EAPI Eina_Bool
1338 elm_diskselector_item_selected_get(const Elm_Object_Item *it)
1339 {
1340    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1341    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
1342    if (!wd) return EINA_FALSE;
1343    return (wd->selected_item == ((Elm_Diskselector_Item *) it));
1344 }
1345
1346 EAPI void
1347 elm_diskselector_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb func)
1348 {
1349    elm_object_item_del_cb_set(it, func);
1350 }
1351
1352 EAPI void *
1353 elm_diskselector_item_data_get(const Elm_Object_Item *it)
1354 {
1355    return elm_object_item_data_get(it);
1356 }
1357
1358 EAPI Evas_Object *
1359 elm_diskselector_item_icon_get(const Elm_Object_Item *it)
1360 {
1361    return _item_content_get_hook(it, NULL);
1362 }
1363
1364 EAPI void
1365 elm_diskselector_item_icon_set(Elm_Object_Item *it, Evas_Object *icon)
1366 {
1367    _item_content_set_hook(it, NULL, icon);
1368 }
1369
1370 EAPI Elm_Object_Item *
1371 elm_diskselector_item_prev_get(const Elm_Object_Item *it)
1372 {
1373    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1374    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1375    if (item->node->prev) return item->node->prev->data;
1376    else return NULL;
1377 }
1378
1379 EAPI Elm_Object_Item *
1380 elm_diskselector_item_next_get(const Elm_Object_Item *it)
1381 {
1382    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1383    Elm_Diskselector_Item *item = (Elm_Diskselector_Item *) it;
1384    if (item->node->next) return item->node->next->data;
1385    else return NULL;
1386 }
1387
1388 EAPI Elm_Object_Item *
1389 elm_diskselector_first_item_get(const Evas_Object *obj)
1390 {
1391    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1392    Widget_Data *wd = elm_widget_data_get(obj);
1393    if (!wd || !wd->items) return NULL;
1394    return eina_list_data_get(wd->items);
1395 }
1396
1397 EAPI Elm_Object_Item *
1398 elm_diskselector_last_item_get(const Evas_Object *obj)
1399 {
1400    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1401    Widget_Data *wd = elm_widget_data_get(obj);
1402    if (!wd || !wd->items) return NULL;
1403    return eina_list_data_get(eina_list_last(wd->items));
1404 }
1405
1406 EAPI void
1407 elm_diskselector_item_tooltip_text_set(Elm_Object_Item *it, const char *text)
1408 {
1409    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1410    elm_widget_item_tooltip_text_set(it, text);
1411 }
1412
1413 EAPI void
1414 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)
1415 {
1416    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1417    elm_widget_item_tooltip_content_cb_set(it, func, data, del_cb);
1418 }
1419
1420 EAPI void
1421 elm_diskselector_item_tooltip_unset(Elm_Object_Item *it)
1422 {
1423    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1424    elm_widget_item_tooltip_unset(it);
1425 }
1426
1427 EAPI void
1428 elm_diskselector_item_tooltip_style_set(Elm_Object_Item *it, const char *style)
1429 {
1430    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1431    elm_widget_item_tooltip_style_set(it, style);
1432 }
1433
1434 EAPI const char *
1435 elm_diskselector_item_tooltip_style_get(const Elm_Object_Item *it)
1436 {
1437    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1438    return elm_widget_item_tooltip_style_get(it);
1439 }
1440
1441 EAPI void
1442 elm_diskselector_item_cursor_set(Elm_Object_Item *it, const char *cursor)
1443 {
1444    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1445    elm_widget_item_cursor_set(it, cursor);
1446 }
1447
1448 EAPI const char *
1449 elm_diskselector_item_cursor_get(const Elm_Object_Item *it)
1450 {
1451    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1452    return elm_widget_item_cursor_get(it);
1453 }
1454
1455 EAPI void
1456 elm_diskselector_item_cursor_unset(Elm_Object_Item *it)
1457 {
1458    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1459    elm_widget_item_cursor_unset(it);
1460 }
1461
1462 EAPI void
1463 elm_diskselector_item_cursor_style_set(Elm_Object_Item *it, const char *style)
1464 {
1465    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1466    elm_widget_item_cursor_style_set(it, style);
1467 }
1468
1469 EAPI const char *
1470 elm_diskselector_item_cursor_style_get(const Elm_Object_Item *it)
1471 {
1472    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1473    return elm_widget_item_cursor_style_get(it);
1474 }
1475
1476 EAPI void
1477 elm_diskselector_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only)
1478 {
1479    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1480    elm_widget_item_cursor_engine_only_set(it, engine_only);
1481 }
1482
1483 EAPI Eina_Bool
1484 elm_diskselector_item_cursor_engine_only_get(const Elm_Object_Item *it)
1485 {
1486    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1487    return elm_widget_item_cursor_engine_only_get(it);
1488 }
1489
1490 EAPI void
1491 elm_diskselector_display_item_num_set(Evas_Object *obj, int num)
1492 {
1493    ELM_CHECK_WIDTYPE(obj, widtype);
1494    Widget_Data *wd = elm_widget_data_get(obj);
1495    if (!wd) return;
1496    if (num < DISPLAY_ITEM_NUM_MIN) num = DISPLAY_ITEM_NUM_MIN;
1497    wd->display_item_num = num;
1498    wd->display_item_num_by_api = EINA_TRUE;
1499 }
1500
1501 EAPI int
1502 elm_diskselector_display_item_num_get(const Evas_Object *item)
1503 {
1504    ELM_CHECK_WIDTYPE(item, widtype) (-1);
1505    Widget_Data *wd = elm_widget_data_get(item);
1506    if (!wd) return -1;
1507    return wd->display_item_num;
1508 }