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