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