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