check, colorselector, calendar, diskselector: apply key binding
[platform/upstream/elementary.git] / src / lib / elm_diskselector.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #include <Elementary.h>
6 #include "elm_priv.h"
7 #include "elm_widget_diskselector.h"
8 #include "elm_interface_scrollable.h"
9
10 #define DISPLAY_ITEM_NUM_MIN 3
11
12 #define MY_CLASS ELM_OBJ_DISKSELECTOR_CLASS
13
14 #define MY_CLASS_NAME "Elm_Diskselector"
15 #define MY_CLASS_NAME_LEGACY "elm_diskselector"
16
17 static const char SIG_SELECTED[] = "selected";
18 static const char SIG_CLICKED[] = "clicked";
19 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
20 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
21 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
22 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
23
24 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
25    {SIG_SELECTED, ""},
26    {SIG_CLICKED, ""},
27    {SIG_SCROLL_ANIM_START, ""},
28    {SIG_SCROLL_ANIM_STOP, ""},
29    {SIG_SCROLL_DRAG_START, ""},
30    {SIG_SCROLL_DRAG_STOP, ""},
31    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
32    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
33    {SIG_WIDGET_FOCUSED, ""}, /**< handled by elm_widget */
34    {SIG_WIDGET_UNFOCUSED, ""}, /**< handled by elm_widget */
35    {NULL, NULL}
36 };
37
38 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
39
40 static const Elm_Action key_actions[] = {
41    {"move", _key_action_move},
42    {NULL, NULL}
43 };
44
45 EOLIAN static Eina_Bool
46 _elm_diskselector_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
47 {
48    Elm_Diskselector_Item *it;
49    Eina_List *l;
50
51    EINA_LIST_FOREACH(sd->items, l, it)
52      elm_widget_item_translate(it);
53
54    return EINA_TRUE;
55 }
56
57 static void
58 _selected_item_indicate(Elm_Diskselector_Item *item)
59 {
60    Eina_List *l;
61    Elm_Diskselector_Item *it;
62
63    ELM_DISKSELECTOR_DATA_GET(WIDGET(item), sd);
64
65    if (!item->label) return;
66
67    EINA_LIST_FOREACH(sd->r_items, l, it)
68      {
69         if (it->label && !strcmp(it->label, item->label))
70           edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
71         else
72           edje_object_signal_emit(VIEW(it), "elm,state,default", "elm");
73      }
74 }
75
76 static void
77 _item_select(Elm_Diskselector_Item *it)
78 {
79    if (!it) return;
80
81    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
82
83    sd->selected_item = it;
84    _selected_item_indicate(sd->selected_item);
85
86    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
87    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
88 }
89
90 static int
91 _letters_count(const char *str)
92 {
93    int pos = 0;
94    int code = 0, chnum;
95
96    for (chnum = 0;; chnum++)
97      {
98         pos = evas_string_char_next_get(str, pos, &code);
99         if (code == 0) break;
100      }
101
102    return chnum;
103 }
104
105 static int
106 _letters_check(const char *str,
107                int length)
108 {
109    int pos = 0;
110    int code = 0, chnum;
111
112    for (chnum = 0;; chnum++)
113      {
114         if (chnum == length) break;
115         pos = evas_string_char_next_get(str, pos, &code);
116         if (code == 0) break;
117      }
118
119    return pos;
120 }
121 static void
122 _item_signal_emit(Elm_Diskselector_Item *it)
123 {
124    if ((it->icon) && (!it->label))
125      edje_object_signal_emit(VIEW(it), "elm,state,icon,only", "elm");
126    else if ((!it->icon) && (it->label))
127      edje_object_signal_emit(VIEW(it), "elm,state,text,only", "elm");
128    else
129      edje_object_signal_emit(VIEW(it), "elm,state,text,icon", "elm");
130 }
131
132 static Eina_Bool
133 _string_check_idle_enterer_cb(void *data)
134 {
135    Evas_Object *obj = data;
136    ELM_DISKSELECTOR_DATA_GET(obj, sd);
137
138    int mid, steps, length, diff;
139    Elm_Diskselector_Item *it;
140    Eina_List *list, *l;
141    Evas_Coord ox, ow;
142    char buf[1024];
143
144    evas_object_geometry_get(obj, &ox, NULL, &ow, NULL);
145
146    if (ow <= 0)
147      {
148         sd->string_check_idle_enterer = NULL;
149         return ECORE_CALLBACK_CANCEL;
150      }
151
152    if (!sd->init)
153      {
154         sd->string_check_idle_enterer = NULL;
155         return ECORE_CALLBACK_CANCEL;
156      }
157
158    if (!sd->round)
159      list = sd->items;
160    else
161      list = sd->r_items;
162
163    EINA_LIST_FOREACH(list, l, it)
164      {
165         Evas_Coord x, w;
166         int len;
167
168         if (it->icon && !it->label)
169           continue;
170
171         evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
172         /* item not visible */
173         if ((x + w <= ox) || (x >= ox + ow))
174           continue;
175
176         len = _letters_count(it->label);
177         // FIXME: len should be # of ut8f letters. ie count using utf8
178         // string walk, not stringshare len
179         //len = eina_stringshare_strlen(it->label);
180
181         if (x <= ox + 5)
182           edje_object_signal_emit(VIEW(it), "elm,state,left_side", "elm");
183         else if (x + w >= ox + ow - 5)
184           edje_object_signal_emit(VIEW(it), "elm,state,right_side", "elm");
185         else
186           {
187              if ((sd->len_threshold) && (len > sd->len_threshold))
188                edje_object_signal_emit
189                  (VIEW(it), "elm,state,center_small", "elm");
190              else
191                edje_object_signal_emit(VIEW(it), "elm,state,center", "elm");
192           }
193
194         // if len is les that the limit len, skip anyway
195         if (len <= sd->len_side)
196           continue;
197
198         steps = len - sd->len_side + 1;
199         mid = x + w / 2;
200         if (mid <= ox + ow / 2)
201           diff = (ox + ow / 2) - mid;
202         else
203           diff = mid - (ox + ow / 2);
204
205         length = len - (int)(diff * steps / (ow / 3));
206         length = MAX(length, sd->len_side);
207         // limit string len to "length" ut8f chars
208         length = _letters_check(it->label, length);
209         // cut it off at byte mark returned form _letters_check
210         strncpy(buf, it->label, length);
211         buf[length] = '\0';
212         edje_object_part_text_escaped_set(VIEW(it), "elm.text", buf);
213      }
214
215    sd->string_check_idle_enterer = NULL;
216
217    return ECORE_CALLBACK_CANCEL;
218 }
219
220 static void
221 _string_check(void *data)
222 {
223    Evas_Object *obj = data;
224    ELM_DISKSELECTOR_DATA_GET(obj, sd);
225
226    ELM_SAFE_FREE(sd->string_check_idle_enterer, ecore_idle_enterer_del);
227
228    // call string check idle enterer directly
229    _string_check_idle_enterer_cb(data);
230 }
231
232 static Eina_Bool
233 _scroller_move(void *data)
234 {
235    Evas_Object *obj = data;
236    Elm_Diskselector_Item *dit;
237    Eina_List *list, *l;
238    Evas_Coord y, w, h;
239    int i;
240
241    ELM_DISKSELECTOR_DATA_GET(obj, sd);
242
243    if (!sd->round)
244      {
245         i = 0;
246         list = sd->items;
247      }
248    else
249      {
250         i = 1;
251         list = sd->r_items;
252      }
253
254    EINA_LIST_FOREACH(list, l, dit)
255      {
256         if (sd->selected_item == dit)
257           break;
258         i++;
259      }
260
261    if (sd->round) i -= CEIL(sd->display_item_num);
262
263    if (!dit)
264      {
265         sd->selected_item =
266           (Elm_Diskselector_Item *)eina_list_nth(sd->items, 0);
267         goto end;
268      }
269
270    evas_object_geometry_get(obj, NULL, &y, &w, &h);
271    eo_do(obj, elm_interface_scrollable_content_region_show(w / sd->display_item_num * i, y, w, h));
272    _item_select(dit);
273
274    sd->init = EINA_TRUE;
275    _string_check(obj);
276
277 end:
278    sd->scroller_move_idle_enterer = NULL;
279    return ECORE_CALLBACK_CANCEL;
280 }
281
282 static void
283 _resize_cb(void *data EINA_UNUSED,
284            Evas *e EINA_UNUSED,
285            Evas_Object *obj,
286            void *event_info EINA_UNUSED)
287 {
288    Evas_Coord w, h, vw = 0, vh = 0, mw = 0, mh = 0;
289    ELM_DISKSELECTOR_DATA_GET(obj, sd);
290    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
291
292    if ((sd->minw == -1) && (sd->minh == -1))
293      elm_coords_finger_size_adjust(6, &sd->minw, 1, &sd->minh);
294
295    eo_do(obj, elm_interface_scrollable_content_viewport_size_get(&vw, &vh));
296    if (sd->items)
297      {
298         Elm_Diskselector_Item *it = sd->items->data;
299         evas_object_size_hint_min_get(VIEW(it), &mw, &mh);
300      }
301    if (sd->minh < mh) sd->minh = mh;
302    edje_object_size_min_restricted_calc
303      (wd->resize_obj, &sd->minw, &sd->minh, sd->minw,
304      sd->minh);
305
306    evas_object_size_hint_min_set(obj, sd->minw, sd->minh);
307    evas_object_size_hint_max_set(obj, -1, -1);
308
309    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
310    if (sd->round)
311      evas_object_resize(sd->main_box, (w / sd->display_item_num)
312                         * (sd->item_count + (CEIL(sd->display_item_num) * 2)),
313                         h);
314    else
315      evas_object_resize(sd->main_box, (w / sd->display_item_num)
316                         * (sd->item_count + eina_list_count(sd->left_blanks)
317                            + eina_list_count(sd->right_blanks)), h);
318
319    eo_do(obj, elm_interface_scrollable_paging_set(0, 0, (int)(w / sd->display_item_num), 0));
320
321    if (!sd->scroller_move_idle_enterer)
322      sd->scroller_move_idle_enterer = ecore_idle_enterer_before_add(_scroller_move, obj);
323 }
324
325 static void
326 _item_del(Elm_Diskselector_Item *item)
327 {
328    if (!item) return;
329
330    ELM_DISKSELECTOR_DATA_GET(WIDGET(item), sd);
331    sd->item_count -= 1;
332    eina_stringshare_del(item->label);
333    evas_object_del(item->icon);
334 }
335
336 static void
337 _sizing_eval(Evas_Object *obj)
338 {
339    _resize_cb(NULL, NULL, obj, NULL);
340 }
341
342 static Eina_Bool
343 _item_del_pre_hook(Elm_Object_Item *item)
344 {
345    Elm_Diskselector_Item *it, *item2, *dit;
346    Eina_List *l;
347    int i = 0;
348
349    it = (Elm_Diskselector_Item *)item;
350    Evas_Object *obj = WIDGET(it);
351
352    ELM_DISKSELECTOR_DATA_GET(obj, sd);
353
354    elm_box_unpack(sd->main_box, VIEW(it));
355
356    if (sd->round)
357      sd->r_items = eina_list_remove(sd->r_items, it);
358
359    sd->items = eina_list_remove(sd->items, it);
360
361    if (sd->selected_item == it)
362      {
363         if (sd->items)
364           {
365              sd->selected_item = (Elm_Diskselector_Item *)eina_list_nth(sd->items, 0);
366              _selected_item_indicate(sd->selected_item);
367           }
368         else
369           sd->selected_item = NULL;
370      }
371
372    _item_del(it);
373
374    if (sd->round)
375      {
376         if (!sd->item_count)
377           {
378              evas_object_hide(sd->VIEW(first));
379              evas_object_hide(sd->VIEW(second));
380              evas_object_hide(sd->VIEW(last));
381              evas_object_hide(sd->VIEW(s_last));
382
383              EINA_LIST_FOREACH(sd->under_items, l, item2)
384                evas_object_hide(VIEW(item2));
385
386              EINA_LIST_FOREACH(sd->over_items, l, item2)
387                evas_object_hide(VIEW(item2));
388           }
389         else
390           {
391              dit = eina_list_nth(sd->items, 0);
392              if (dit)
393                {
394                   eina_stringshare_replace(&sd->first->label, dit->label);
395                   edje_object_part_text_escaped_set
396                     (sd->VIEW(first), "elm.text", sd->first->label);
397                }
398
399              dit = eina_list_nth(sd->items, 1);
400              if (dit)
401                {
402                   eina_stringshare_replace(&sd->second->label, dit->label);
403                   edje_object_part_text_escaped_set
404                     (sd->VIEW(second), "elm.text", sd->second->label);
405                }
406              // if more than 3 itmes should be displayed
407              for (i = 2; i < CEIL(sd->display_item_num); i++)
408                {
409                   dit = eina_list_nth(sd->items, i);
410                   item2 = eina_list_nth(sd->over_items, i - 2);
411                   eina_stringshare_replace(&item2->label, dit->label);
412                   edje_object_part_text_escaped_set
413                     (VIEW(item2), "elm.text", item2->label);
414                }
415
416              dit = eina_list_nth(sd->items, eina_list_count(sd->items) - 1);
417              if (dit)
418                {
419                   eina_stringshare_replace(&sd->last->label, dit->label);
420                   edje_object_part_text_escaped_set
421                     (sd->VIEW(last), "elm.text", sd->last->label);
422                }
423
424              dit = eina_list_nth(sd->items, eina_list_count(sd->items) - 2);
425              if (dit)
426                {
427                   eina_stringshare_replace(&sd->s_last->label, dit->label);
428                   edje_object_part_text_escaped_set
429                     (sd->VIEW(s_last), "elm.text", sd->s_last->label);
430                }
431              // if more than 3 itmes should be displayed
432              for (i = 3; i <= CEIL(sd->display_item_num); i++)
433                {
434                   dit = eina_list_nth(sd->items, sd->item_count - i);
435                   item2 = eina_list_nth(sd->under_items, i - 3);
436                   eina_stringshare_replace(&item2->label, dit->label);
437                   edje_object_part_text_escaped_set
438                     (VIEW(item2), "elm.text", item2->label);
439                }
440           }
441      }
442
443    sd->string_check_idle_enterer =
444       ecore_idle_enterer_before_add(_string_check_idle_enterer_cb,
445                                     obj);
446
447    _sizing_eval(obj);
448
449    return EINA_TRUE;
450 }
451
452 static void
453 _item_text_set_hook(Elm_Object_Item *item,
454                     const char *part,
455                     const char *label)
456 {
457    Elm_Diskselector_Item *it;
458    Evas_Coord mw, mh;
459
460    if (part && strcmp(part, "default")) return;
461
462    it = (Elm_Diskselector_Item *)item;
463    eina_stringshare_replace(&it->label, label);
464    edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
465    _item_signal_emit(it);
466    edje_object_size_min_calc(VIEW(it), &mw, &mh);
467    evas_object_size_hint_min_set(VIEW(it), 0, mh);
468 }
469
470 static const char *
471 _item_text_get_hook(const Elm_Object_Item *it,
472                     const char *part)
473 {
474    if (part && strcmp(part, "default")) return NULL;
475
476    return ((Elm_Diskselector_Item *)it)->label;
477 }
478
479 static void
480 _item_icon_set(Elm_Diskselector_Item *it,
481                Evas_Object *icon)
482 {
483    if (it->icon == icon) return;
484
485    evas_object_del(it->icon);
486    it->icon = icon;
487
488    if (VIEW(it))
489      {
490         evas_object_size_hint_min_set(it->icon, 24, 24);
491         evas_object_size_hint_max_set(it->icon, 40, 40);
492         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
493         evas_object_show(it->icon);
494         elm_widget_sub_object_add(WIDGET(it), it->icon);
495      }
496
497    _item_signal_emit(it);
498 }
499
500 static void
501 _identical_item_check(Elm_Diskselector_Item *it,
502                       Evas_Object *icon)
503 {
504    Elm_Diskselector_Item *dit;
505    Eina_List *l;
506    int idx = 0;
507    int ic = 0;
508    int ac = 0;
509
510    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
511
512    if (sd->round)
513      {
514         // Get index from indentical item from round items
515         EINA_LIST_FOREACH(sd->r_items, l, dit)
516           {
517              if (it == dit) break;
518              idx++;
519           }
520
521         // No item to match
522         ic = eina_list_count(sd->r_items);
523
524         if (idx >= ic) return;
525         dit = NULL;
526
527         // Number of added items: CEIL(sd->display_item_num)
528         ac = CEIL(sd->display_item_num);
529
530         if (((idx >= 0) && (idx < ac)) ||
531             ((idx >= ac) && (idx < (2 * ac))))
532           {
533              // Selected item: under, low region
534              dit = eina_list_nth(sd->r_items,
535                                  idx + ic - (2 * ac));
536           }
537         else if (((idx >= (ic - ac)) && (idx < ic)) ||
538                  ((idx >= (ic - (2 * ac))) && (idx < ic - ac)))
539           {
540              // Selected item: over, high region
541              dit = eina_list_nth(sd->r_items,
542                                  idx - ic + (2 * ac));
543           }
544
545         if (dit) _item_icon_set(dit, icon);
546         _sizing_eval(WIDGET(it));
547      }
548 }
549
550 static void
551 _item_content_set_hook(Elm_Object_Item *it,
552                        const char *part,
553                        Evas_Object *content)
554 {
555    if (part && strcmp(part, "icon")) return;
556
557    _item_icon_set((Elm_Diskselector_Item *)it, content);
558    _identical_item_check((Elm_Diskselector_Item *)it, content);
559 }
560
561 static Evas_Object *
562 _item_content_get_hook(const Elm_Object_Item *it,
563                        const char *part)
564 {
565    if (part && strcmp(part, "icon")) return NULL;
566
567    return ((Elm_Diskselector_Item *)it)->icon;
568 }
569
570 static void
571 _item_click_cb(void *data,
572                Evas_Object *obj EINA_UNUSED,
573                const char *emission EINA_UNUSED,
574                const char *source EINA_UNUSED)
575 {
576    Elm_Diskselector_Item *it = data;
577
578    if (!it) return;
579    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
580
581    if (sd->selected_item != it)
582      {
583         sd->selected_item = it;
584         _selected_item_indicate(sd->selected_item);
585      }
586
587    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
588    evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED, it);
589 }
590
591 static char *
592 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
593 {
594    Elm_Diskselector_Item *it = (Elm_Diskselector_Item *)data;
595    const char *txt = NULL;
596    if (!it) return NULL;
597
598    if (!txt) txt = it->label;
599    if (txt) return strdup(txt);
600
601    return NULL;
602 }
603
604 static void
605 _access_on_highlight_cb(void *data)
606 {
607    Evas_Coord bx, by, bw, bh;
608    Evas_Coord x, y, w, h;
609
610    Elm_Diskselector_Item *it = (Elm_Diskselector_Item *)data;
611
612    ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
613    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
614
615    evas_smart_objects_calculate(evas_object_evas_get(sd->main_box));
616    evas_object_geometry_get(sd->main_box, &bx, &by, &bw, &bh);
617    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
618
619    x -= bx;
620    y -= by;
621
622    eo_do(WIDGET(it), elm_interface_scrollable_region_bring_in(x, y, w, h));
623 }
624
625 static Elm_Diskselector_Item *
626 _item_new(Evas_Object *obj,
627           Evas_Object *icon,
628           const char *label,
629           Evas_Smart_Cb func,
630           const void *data)
631 {
632    Elm_Diskselector_Item *it;
633
634    it = elm_widget_item_new(obj, Elm_Diskselector_Item);
635    if (!it) return NULL;
636
637    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
638    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
639    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
640    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
641    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
642
643    it->label = eina_stringshare_add(label);
644    it->func = func;
645    it->base.data = data;
646    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
647    elm_widget_theme_object_set(obj, VIEW(it), "diskselector", "item",
648                                elm_widget_style_get(obj));
649
650    evas_object_size_hint_weight_set
651      (VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
652    evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
653    evas_object_show(VIEW(it));
654
655    if (icon)
656      _item_content_set_hook((Elm_Object_Item *)it, "icon", icon);
657
658    if (it->label)
659      {
660         _item_text_set_hook((Elm_Object_Item *)it, "default", it->label);
661         edje_object_signal_callback_add
662           (VIEW(it), "elm,action,click", "*", _item_click_cb, it);
663      }
664
665    //XXX: ACCESS
666    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
667      {
668         _elm_access_widget_item_register((Elm_Widget_Item *)it);
669
670         _elm_access_text_set(_elm_access_info_get(it->base.access_obj),
671                              ELM_ACCESS_TYPE, E_("diskselector item"));
672         _elm_access_callback_set(_elm_access_info_get(it->base.access_obj),
673                                  ELM_ACCESS_INFO,
674                                  _access_info_cb, it);
675         _elm_access_on_highlight_hook_set(
676            _elm_access_info_get(it->base.access_obj), _access_on_highlight_cb,
677            it);
678      }
679
680    return it;
681 }
682
683 static Evas_Object *
684 _blank_add(Evas_Object *obj)
685 {
686    Evas_Object *blank;
687    blank = edje_object_add(evas_object_evas_get(obj));
688    elm_widget_theme_object_set(obj, blank, "diskselector", "item", "default");
689    evas_object_size_hint_weight_set(blank, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
690    evas_object_size_hint_align_set(blank, EVAS_HINT_FILL, EVAS_HINT_FILL);
691
692    return blank;
693 }
694
695 static void
696 _blank_item_check(Evas_Object *obj, int item_num)
697 {
698    Evas_Object *blank;
699    Eina_List *last;
700    int diff, i;
701
702    ELM_DISKSELECTOR_DATA_GET(obj, sd);
703
704    diff = (item_num / 2) - eina_list_count(sd->left_blanks);
705    if (!diff) return;
706
707    /* left blank */
708    for (i = 0; i < ((diff > 0) ? (diff) : (-diff)); i++)
709      {
710         if (diff > 0)
711           {
712              blank = _blank_add(obj);
713              elm_box_pack_start(sd->main_box, blank);
714              evas_object_show(blank);
715              sd->left_blanks = eina_list_append(sd->left_blanks, blank);
716           }
717         else
718           {
719              last = eina_list_last(sd->left_blanks);
720              blank = eina_list_data_get(last);
721              elm_box_unpack(sd->main_box, blank);
722              evas_object_del(blank);
723              sd->left_blanks = eina_list_remove_list(sd->left_blanks, last);
724           }
725      }
726
727    /* right blank */
728    for (i = 0; i < ((diff > 0) ? (diff) : (-diff)); i++)
729      {
730         if (diff > 0)
731           {
732              blank = _blank_add(obj);
733              elm_box_pack_end(sd->main_box, blank);
734              evas_object_show(blank);
735              sd->right_blanks = eina_list_append(sd->right_blanks, blank);
736           }
737         else
738           {
739              last = eina_list_last(sd->right_blanks);
740              blank = eina_list_data_get(last);
741              elm_box_unpack(sd->main_box, blank);
742              evas_object_del(blank);
743              sd->right_blanks = eina_list_remove_list(sd->right_blanks, last);
744           }
745      }
746 }
747
748 static void
749 _theme_data_get(Evas_Object *obj)
750 {
751    const char *str;
752    Evas_Object *blank;
753
754    ELM_DISKSELECTOR_DATA_GET(obj, sd);
755
756    blank = eina_list_data_get(sd->right_blanks);
757    if (blank) return;
758
759    str = edje_object_data_get(blank, "len_threshold");
760    if (str) sd->len_threshold = MAX(0, atoi(str));
761    else sd->len_threshold = 0;
762
763    if (!sd->display_item_num_by_api)
764      {
765         str = edje_object_data_get(blank, "display_item_num");
766         if (str)
767           {
768              sd->display_item_num = MAX(DISPLAY_ITEM_NUM_MIN, atoi(str));
769              if (!sd->round) _blank_item_check(obj, sd->display_item_num);
770           }
771
772         else sd->display_item_num = DISPLAY_ITEM_NUM_MIN;
773      }
774
775    str = edje_object_data_get(blank, "min_width");
776    if (str) sd->minw = MAX(-1, atoi(str));
777    else sd->minw = -1;
778
779    str = edje_object_data_get(blank, "min_height");
780    if (str) sd->minh = MAX(-1, atoi(str));
781    else sd->minh = -1;
782 }
783
784 EOLIAN static Eina_Bool
785 _elm_diskselector_elm_widget_theme_apply(Eo *obj, Elm_Diskselector_Data *sd)
786 {
787    Eina_List *l;
788    Elm_Diskselector_Item *it;
789    Evas_Object *blank;
790    Eina_Bool int_ret = EINA_FALSE;
791    Evas *evas;
792    const char *style = elm_widget_style_get(obj);
793
794    eo_do_super(obj, MY_CLASS, elm_obj_widget_theme_apply(&int_ret));
795    if (!int_ret) return EINA_FALSE;
796
797    evas = evas_object_evas_get(obj);
798    evas_event_freeze(evas);
799
800    if (sd->round)
801      {
802         EINA_LIST_FOREACH(sd->r_items, l, it)
803           {
804              elm_widget_theme_object_set(obj, VIEW(it),
805                                          "diskselector", "item", style);
806              edje_object_part_text_escaped_set
807                (VIEW(it), "elm.text", it->label);
808           }
809      }
810    else
811      {
812         EINA_LIST_FOREACH(sd->items, l, it)
813           {
814              elm_widget_theme_object_set(obj, VIEW(it),
815                                          "diskselector","item", style);
816              edje_object_part_text_escaped_set
817                (VIEW(it), "elm.text", it->label);
818           }
819
820         /* left blank */
821         EINA_LIST_FOREACH (sd->left_blanks, l, blank)
822           {
823              elm_widget_theme_object_set(obj, blank,
824                                          "diskselector", "item", style);
825           }
826
827         /* right blank */
828         EINA_LIST_FOREACH (sd->right_blanks, l, blank)
829           {
830              elm_widget_theme_object_set(obj, blank,
831                                          "diskselector", "item", style);
832           }
833      }
834
835    _theme_data_get(obj);
836    _sizing_eval(obj);
837
838    evas_event_thaw(evas);
839    evas_event_thaw_eval(evas);
840
841    return EINA_TRUE;
842 }
843
844 EOLIAN static Eina_Bool
845 _elm_diskselector_elm_widget_sub_object_del(Eo *obj, Elm_Diskselector_Data *sd, Evas_Object *sobj)
846 {
847    Eina_Bool int_ret = EINA_FALSE;
848
849    Elm_Diskselector_Item *it;
850    const Eina_List *l;
851
852    eo_do_super(obj, MY_CLASS, elm_obj_widget_sub_object_del(sobj, &int_ret));
853    if (!int_ret) return EINA_FALSE;
854
855    EINA_LIST_FOREACH(sd->items, l, it)
856      {
857         if (sobj == it->icon)
858           {
859              it->icon = NULL;
860
861              _sizing_eval(obj);
862              break;
863           }
864      }
865
866    return EINA_TRUE;
867 }
868
869 EOLIAN static Eina_Bool
870 _elm_diskselector_elm_widget_on_focus(Eo *obj, Elm_Diskselector_Data *_pd EINA_UNUSED)
871 {
872    Eina_Bool int_ret = EINA_FALSE;
873    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
874
875    eo_do_super(obj, MY_CLASS, elm_obj_widget_on_focus(&int_ret));
876    if (!int_ret) return EINA_FALSE;
877
878    if (elm_widget_focus_get(obj))
879      {
880         edje_object_signal_emit
881           (wd->resize_obj, "elm,action,focus", "elm");
882         evas_object_focus_set(wd->resize_obj, EINA_TRUE);
883      }
884    else
885      {
886         edje_object_signal_emit
887           (wd->resize_obj, "elm,action,unfocus", "elm");
888         evas_object_focus_set(wd->resize_obj, EINA_FALSE);
889      }
890
891    return EINA_TRUE;
892 }
893
894 static Eina_Bool _elm_diskselector_smart_focus_next_enable = EINA_FALSE;
895
896 EOLIAN static Eina_Bool
897 _elm_diskselector_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *_pd EINA_UNUSED)
898 {
899    return _elm_diskselector_smart_focus_next_enable;
900 }
901
902 EOLIAN static Eina_Bool
903 _elm_diskselector_elm_widget_focus_next(Eo *obj, Elm_Diskselector_Data *sd, Elm_Focus_Direction dir, Evas_Object **next)
904 {
905    Eina_List *items = NULL;
906    Eina_List *elist = NULL;
907    Elm_Diskselector_Item *it;
908
909    EINA_LIST_FOREACH(sd->items, elist, it)
910      items = eina_list_append(items, it->base.access_obj);
911
912    if (!sd->round)
913      {
914         return elm_widget_focus_list_next_get
915               (obj, items, eina_list_data_get, dir, next);
916      }
917
918    if (!elm_widget_focus_list_next_get
919           (obj, items, eina_list_data_get, dir, next))
920      {
921         elm_widget_focused_object_clear((Evas_Object *)obj);
922         elm_widget_focus_list_next_get
923           (obj, items, eina_list_data_get, dir, next);
924      }
925    return EINA_TRUE;
926 }
927
928 static Eina_Bool
929 _key_action_move(Evas_Object *obj, const char *params)
930 {
931    ELM_DISKSELECTOR_DATA_GET(obj, sd);
932    Elm_Diskselector_Item *it = NULL;
933    Eina_List *l = NULL;
934    char *dir = params;
935
936    if (!strcmp(dir, "prev"))
937      {
938         l = sd->selected_item->node->prev;
939         if ((!l) && (sd->round))
940           l = eina_list_last(sd->items);
941      }
942    else if (!strcmp(dir, "next"))
943      {
944         l = sd->selected_item->node->next;
945         if ((!l) && (sd->round))
946           l = sd->items;
947      }
948    else if (!strcmp(dir, "first"))
949      l = sd->items;
950    else if (!strcmp(dir, "last"))
951      l = eina_list_last(sd->items);
952    else return EINA_FALSE;
953
954    if (l)
955      it = eina_list_data_get(l);
956
957    if (it)
958      {
959         sd->selected_item = it;
960         if (!sd->scroller_move_idle_enterer)
961           sd->scroller_move_idle_enterer = ecore_idle_enterer_before_add(_scroller_move, obj);
962      }
963
964    return EINA_TRUE;
965 }
966
967 EOLIAN static Eina_Bool
968 _elm_diskselector_elm_widget_event(Eo *obj, Elm_Diskselector_Data *sd, Evas_Object *src, Evas_Callback_Type type, void *event_info)
969 {
970    Evas_Event_Key_Down  *ev = event_info;
971
972    (void) src;
973
974    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
975    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
976    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
977
978    if (!sd->selected_item)
979      {
980         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
981         return EINA_TRUE;
982      }
983
984    if (!_elm_config_key_binding_call(obj, ev, key_actions))
985      return EINA_FALSE;
986
987    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
988    return EINA_TRUE;
989 }
990
991 static void
992 _scroll_cb(Evas_Object *obj,
993            void *data EINA_UNUSED)
994 {
995    Evas_Coord x, y, w, h, bw, x_boundary;
996    unsigned int adjust_pixels;
997    Eina_Bool h_bounce;
998
999    ELM_DISKSELECTOR_DATA_GET(obj, sd);
1000
1001    _string_check(obj);
1002    eo_do(obj,
1003          elm_interface_scrollable_content_pos_get(&x, &y),
1004          elm_interface_scrollable_content_viewport_size_get(&w, &h));
1005    if (sd->round)
1006      {
1007         evas_object_geometry_get(sd->main_box, NULL, NULL, &bw, NULL);
1008         x_boundary = bw - w;
1009
1010         if (x >= x_boundary)
1011           {
1012               if (sd->left_boundary_reached) return;
1013
1014               sd->right_boundary_reached = EINA_TRUE;
1015               eo_do(obj, elm_interface_scrollable_bounce_allow_get(&h_bounce, NULL));
1016               /* If scroller's bounce effect is disabled, add 1 pixel
1017                *  to provide circular effect */
1018               adjust_pixels = (_elm_config->thumbscroll_bounce_enable
1019                                && h_bounce) ? 0 : 1;
1020               eo_do(obj, elm_interface_scrollable_content_region_show
1021                  (x - x_boundary + adjust_pixels, y, w, h));
1022               sd->left_boundary_reached = EINA_FALSE;
1023           }
1024         else if (x <= 0)
1025           {
1026               if (sd->right_boundary_reached) return;
1027
1028               sd->left_boundary_reached = EINA_TRUE;
1029               eo_do(obj, elm_interface_scrollable_bounce_allow_get(&h_bounce, NULL));
1030               /* If scroller's bounce effect is disabled, subtract 1 pixel
1031                *  to provide circular effect */
1032               adjust_pixels = (_elm_config->thumbscroll_bounce_enable
1033                                && h_bounce) ? 0 : 1;
1034               eo_do(obj, elm_interface_scrollable_content_region_show
1035                  (x + x_boundary - adjust_pixels, y, w, h));
1036               sd->right_boundary_reached = EINA_FALSE;
1037           }
1038         else
1039           {
1040               sd->left_boundary_reached = EINA_FALSE;
1041               sd->right_boundary_reached = EINA_FALSE;
1042           }
1043      }
1044 }
1045
1046 static void
1047 _scroll_animate_stop_cb(Evas_Object *obj,
1048                         void *data EINA_UNUSED)
1049 {
1050    Elm_Diskselector_Item *it;
1051    Evas_Coord x, w, ox, ow;
1052    Eina_List *l, *list;
1053
1054    ELM_DISKSELECTOR_DATA_GET(obj, sd);
1055
1056    if (sd->scroller_move_idle_enterer) return;
1057
1058    if (!sd->round)
1059      list = sd->items;
1060    else
1061      list = sd->r_items;
1062
1063    evas_object_geometry_get(obj, &ox, NULL, &ow, NULL);
1064    EINA_LIST_FOREACH(list, l, it)
1065      {
1066         evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
1067         if (abs((int)(ox + (ow / 2)) - (int)(x + (w / 2))) < 10) break;
1068      }
1069
1070    if (!it) return;
1071    _item_select(it);
1072    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, it);
1073 }
1074
1075 static void
1076 _scroll_animate_start_cb(Evas_Object *obj,
1077                          void *data EINA_UNUSED)
1078 {
1079    evas_object_smart_callback_call
1080      (obj, SIG_SCROLL_ANIM_START, elm_diskselector_selected_item_get(obj));
1081 }
1082
1083 static void
1084 _scroll_drag_start_cb(Evas_Object *obj,
1085                       void *data EINA_UNUSED)
1086 {
1087    evas_object_smart_callback_call
1088      (obj, SIG_SCROLL_DRAG_START, elm_diskselector_selected_item_get(obj));
1089 }
1090
1091 static void
1092 _scroll_drag_stop_cb(Evas_Object *obj,
1093                      void *data EINA_UNUSED)
1094 {
1095    evas_object_smart_callback_call
1096      (obj, SIG_SCROLL_DRAG_STOP, elm_diskselector_selected_item_get(obj));
1097 }
1098
1099 static void
1100 _round_item_del(Elm_Diskselector_Data *sd,
1101                 Elm_Diskselector_Item *it)
1102 {
1103    if (!it) return;
1104
1105    elm_box_unpack(sd->main_box, VIEW(it));
1106    sd->r_items = eina_list_remove(sd->r_items, it);
1107    eina_stringshare_del(it->label);
1108    elm_widget_item_free(it);
1109 }
1110
1111 static void
1112 _round_items_del(Elm_Diskselector_Data *sd)
1113 {
1114    Eina_List *l;
1115    Elm_Diskselector_Item *it;
1116
1117    _round_item_del(sd, sd->last);
1118    sd->last = NULL;
1119    _round_item_del(sd, sd->s_last);
1120    sd->s_last = NULL;
1121    _round_item_del(sd, sd->second);
1122    sd->second = NULL;
1123    _round_item_del(sd, sd->first);
1124    sd->first = NULL;
1125
1126    EINA_LIST_FOREACH(sd->under_items, l, it)
1127      {
1128         _round_item_del(sd, it);
1129      }
1130    sd->under_items = eina_list_free(sd->under_items);
1131
1132    EINA_LIST_FOREACH(sd->over_items, l, it)
1133      {
1134         _round_item_del(sd, it);
1135      }
1136    sd->over_items = eina_list_free(sd->over_items);
1137 }
1138
1139 static Evas_Object *
1140 _icon_duplicate(Evas_Object *icon)
1141 {
1142    Evas_Object *ic;
1143    const char *file;
1144    const char *group;
1145
1146    if (!icon) return NULL;
1147
1148    elm_image_file_get(icon, &file, &group);
1149    ic = elm_icon_add(icon);
1150    elm_image_file_set(ic, file, group);
1151    elm_image_resizable_set(ic, EINA_TRUE, EINA_TRUE);
1152
1153    return ic;
1154 }
1155
1156 static void
1157 _round_items_add(Elm_Diskselector_Data *sd)
1158 {
1159    Elm_Diskselector_Item *temp_it;
1160    Elm_Diskselector_Item *dit;
1161    Elm_Diskselector_Item *it;
1162    int i = 0;
1163
1164    dit = it = eina_list_nth(sd->items, 0);
1165    if (!dit) return;
1166
1167    if (!sd->first)
1168      {
1169         sd->first = _item_new
1170             (WIDGET(it), _icon_duplicate(it->icon), it->label, it->func,
1171             it->base.data);
1172         sd->first->node = it->node;
1173         sd->r_items = eina_list_append(sd->r_items, sd->first);
1174      }
1175
1176    it = eina_list_nth(sd->items, 1);
1177    if (!it)
1178      it = dit;
1179
1180    if (!sd->second)
1181      {
1182         sd->second = _item_new
1183             (WIDGET(it), _icon_duplicate(it->icon), it->label, it->func,
1184             it->base.data);
1185         sd->second->node = it->node;
1186         sd->r_items = eina_list_append(sd->r_items, sd->second);
1187      }
1188
1189    // if more than 3 itmes should be displayed
1190    for (i = 2; i < CEIL(sd->display_item_num); i++)
1191      {
1192         it = eina_list_nth(sd->items, i);
1193
1194         if (!it) it = dit;
1195         temp_it = _item_new
1196             (WIDGET(it), _icon_duplicate
1197               (it->icon), it->label, it->func, it->base.data);
1198         sd->over_items = eina_list_append(sd->over_items, temp_it);
1199         sd->r_items = eina_list_append(sd->r_items, temp_it);
1200      }
1201
1202    it = eina_list_nth(sd->items, sd->item_count - 1);
1203    if (!it)
1204      it = dit;
1205    if (!sd->last)
1206      {
1207         sd->last = _item_new
1208             (WIDGET(it), _icon_duplicate(it->icon), it->label, it->func,
1209             it->base.data);
1210         sd->last->node = it->node;
1211         sd->r_items = eina_list_prepend(sd->r_items, sd->last);
1212      }
1213
1214    it = eina_list_nth(sd->items, sd->item_count - 2);
1215    if (!it)
1216      it = dit;
1217    if (!sd->s_last)
1218      {
1219         sd->s_last = _item_new
1220             (WIDGET(it), _icon_duplicate(it->icon), it->label, it->func,
1221             it->base.data);
1222         sd->s_last->node = it->node;
1223         sd->r_items = eina_list_prepend(sd->r_items, sd->s_last);
1224      }
1225
1226    // if more than 3 itmes should be displayed
1227    for (i = 3; i <= CEIL(sd->display_item_num); i++)
1228      {
1229         it = eina_list_nth(sd->items, sd->item_count - i);
1230         if (!it) it = dit;
1231         temp_it = _item_new
1232             (WIDGET(it), _icon_duplicate
1233               (it->icon), it->label, it->func, it->base.data);
1234         sd->under_items = eina_list_append(sd->under_items, temp_it);
1235         sd->r_items = eina_list_prepend(sd->r_items, temp_it);
1236      }
1237 }
1238
1239 EOLIAN static void
1240 _elm_diskselector_evas_smart_add(Eo *obj, Elm_Diskselector_Data *priv)
1241 {
1242    Evas *evas;
1243    Evas_Object *blank, *edje;
1244
1245    elm_widget_sub_object_parent_add(obj);
1246
1247    evas = evas_object_evas_get(obj);
1248    evas_event_freeze(evas);
1249
1250    edje = edje_object_add(evas);
1251    elm_widget_resize_object_set(obj, edje, EINA_TRUE);
1252
1253    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1254
1255    elm_widget_theme_object_set
1256      (obj, edje, "diskselector", "base", elm_widget_style_get(obj));
1257
1258    priv->hit_rect = evas_object_rectangle_add(evas);
1259    evas_object_smart_member_add(priv->hit_rect, obj);
1260    elm_widget_sub_object_add(obj, priv->hit_rect);
1261
1262    /* common scroller hit rectangle setup */
1263    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
1264    evas_object_show(priv->hit_rect);
1265    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
1266
1267    elm_widget_can_focus_set(obj, EINA_TRUE);
1268
1269    priv->len_side = 3;
1270
1271    eo_do(obj,
1272          elm_interface_scrollable_objects_set(edje, priv->hit_rect),
1273          elm_obj_widget_theme_apply(NULL),
1274          elm_interface_scrollable_policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF),
1275          elm_interface_scrollable_bounce_allow_set(EINA_TRUE, EINA_FALSE),
1276          elm_interface_scrollable_animate_start_cb_set(_scroll_animate_start_cb),
1277          elm_interface_scrollable_animate_stop_cb_set(_scroll_animate_stop_cb),
1278          elm_interface_scrollable_drag_start_cb_set(_scroll_drag_start_cb),
1279          elm_interface_scrollable_drag_stop_cb_set(_scroll_drag_stop_cb),
1280          elm_interface_scrollable_scroll_cb_set(_scroll_cb));
1281
1282    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, NULL);
1283
1284    priv->main_box = elm_box_add(obj);
1285    elm_box_horizontal_set(priv->main_box, EINA_TRUE);
1286    elm_box_homogeneous_set(priv->main_box, EINA_TRUE);
1287    evas_object_size_hint_weight_set
1288      (priv->main_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1289    evas_object_size_hint_align_set
1290      (priv->main_box, EVAS_HINT_FILL, EVAS_HINT_FILL);
1291    elm_widget_theme_set(priv->main_box, elm_widget_theme_get(obj));
1292
1293    elm_widget_sub_object_add(obj, priv->main_box);
1294
1295    eo_do(obj, elm_interface_scrollable_content_set(priv->main_box));
1296
1297    /* left blank */
1298    blank = _blank_add(obj);
1299    elm_box_pack_start(priv->main_box, blank);
1300    evas_object_show(blank);
1301    priv->left_blanks = eina_list_append(priv->left_blanks, blank);
1302
1303    /* right blank */
1304    blank = _blank_add(obj);
1305    elm_box_pack_end(priv->main_box, blank);
1306    evas_object_show(blank);
1307    priv->right_blanks = eina_list_append(priv->right_blanks, blank);
1308
1309    _theme_data_get(obj);
1310    _sizing_eval(obj);
1311
1312    evas_event_thaw(evas);
1313    evas_event_thaw_eval(evas);
1314 }
1315
1316 EOLIAN static void
1317 _elm_diskselector_evas_smart_del(Eo *obj, Elm_Diskselector_Data *sd)
1318 {
1319    Elm_Diskselector_Item *it;
1320    Eina_List *l;
1321    Evas_Object *blank;
1322
1323    /* left blank */
1324    EINA_LIST_FOREACH (sd->left_blanks, l, blank)
1325      evas_object_del(blank);
1326
1327    /* right blank */
1328    EINA_LIST_FOREACH (sd->right_blanks, l, blank)
1329      evas_object_del(blank);
1330
1331    if (sd->last)
1332      {
1333         eina_stringshare_del(sd->last->label);
1334         evas_object_del(sd->VIEW(last));
1335         free(sd->last);
1336      }
1337
1338    if (sd->s_last)
1339      {
1340         eina_stringshare_del(sd->s_last->label);
1341         evas_object_del(sd->VIEW(s_last));
1342         free(sd->s_last);
1343      }
1344
1345    if (sd->second)
1346      {
1347         eina_stringshare_del(sd->second->label);
1348         evas_object_del(sd->VIEW(second));
1349         free(sd->second);
1350      }
1351
1352    if (sd->first)
1353      {
1354         eina_stringshare_del(sd->first->label);
1355         evas_object_del(sd->VIEW(first));
1356         free(sd->first);
1357      }
1358
1359    EINA_LIST_FOREACH(sd->under_items, l, it)
1360      {
1361         if (it)
1362           {
1363              eina_stringshare_del(it->label);
1364              evas_object_del(VIEW(it));
1365              free(it);
1366           }
1367      }
1368
1369    EINA_LIST_FOREACH(sd->over_items, l, it)
1370      {
1371         if (it)
1372           {
1373              eina_stringshare_del(it->label);
1374              evas_object_del(VIEW(it));
1375              free(it);
1376           }
1377      }
1378
1379    EINA_LIST_FREE(sd->items, it)
1380      {
1381         _item_del(it);
1382         elm_widget_item_free(it);
1383      }
1384    sd->r_items = eina_list_free(sd->r_items);
1385
1386    ELM_SAFE_FREE(sd->scroller_move_idle_enterer, ecore_idle_enterer_del);
1387    ELM_SAFE_FREE(sd->string_check_idle_enterer, ecore_idle_enterer_del);
1388
1389    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1390 }
1391
1392 EOLIAN static void
1393 _elm_diskselector_evas_smart_move(Eo *obj, Elm_Diskselector_Data *sd, Evas_Coord x, Evas_Coord y)
1394 {
1395    eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
1396
1397    evas_object_move(sd->hit_rect, x, y);
1398 }
1399
1400 EOLIAN static void
1401 _elm_diskselector_evas_smart_resize(Eo *obj, Elm_Diskselector_Data *sd, Evas_Coord w, Evas_Coord h)
1402 {
1403    eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
1404
1405    evas_object_resize(sd->hit_rect, w, h);
1406 }
1407
1408 EOLIAN static void
1409 _elm_diskselector_evas_smart_member_add(Eo *obj, Elm_Diskselector_Data *sd, Evas_Object *member)
1410 {
1411    eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
1412
1413    if (sd->hit_rect)
1414      evas_object_raise(sd->hit_rect);
1415 }
1416
1417 EOLIAN static void
1418 _elm_diskselector_elm_widget_access(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *_pd EINA_UNUSED, Eina_Bool acs)
1419 {
1420    _elm_diskselector_smart_focus_next_enable = acs;
1421 }
1422
1423 EAPI Evas_Object *
1424 elm_diskselector_add(Evas_Object *parent)
1425 {
1426    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1427    Evas_Object *obj = eo_add(MY_CLASS, parent);
1428    eo_unref(obj);
1429    return obj;
1430 }
1431
1432 EOLIAN static void
1433 _elm_diskselector_eo_base_constructor(Eo *obj, Elm_Diskselector_Data *_pd EINA_UNUSED)
1434 {
1435    eo_do_super(obj, MY_CLASS, eo_constructor());
1436    eo_do(obj,
1437          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1438          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks, NULL));
1439 }
1440
1441 EOLIAN static Eina_Bool
1442 _elm_diskselector_round_enabled_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1443 {
1444    return sd->round;
1445 }
1446
1447 EOLIAN static void
1448 _elm_diskselector_round_enabled_set(Eo *obj, Elm_Diskselector_Data *sd, Eina_Bool enabled)
1449 {
1450    Eina_List *elist;
1451    Elm_Diskselector_Item *it;
1452    Evas_Object *blank;
1453
1454    if (sd->round == enabled)
1455      return;
1456
1457    sd->round = !!enabled;
1458    if (enabled)
1459      {
1460         sd->r_items = eina_list_clone(sd->items);
1461         _blank_item_check(obj, DISPLAY_ITEM_NUM_MIN);
1462
1463         /* left blank */
1464         EINA_LIST_FOREACH (sd->left_blanks, elist, blank)
1465           {
1466              elm_box_unpack(sd->main_box, blank);
1467              evas_object_hide(blank);
1468           }
1469
1470         /* right blank */
1471         EINA_LIST_FOREACH (sd->right_blanks, elist, blank)
1472           {
1473              elm_box_unpack(sd->main_box, blank);
1474              evas_object_hide(blank);
1475           }
1476
1477         if (!sd->items)
1478           return;
1479
1480         _round_items_add(sd);
1481
1482         if (sd->last)
1483           elm_box_pack_start(sd->main_box, sd->VIEW(last));
1484         if (sd->s_last)
1485           elm_box_pack_start(sd->main_box, sd->VIEW(s_last));
1486
1487         // if more than 3 items should be displayed
1488         EINA_LIST_FOREACH(sd->under_items, elist, it)
1489           elm_box_pack_start(sd->main_box, VIEW(it));
1490
1491         if (sd->first)
1492           elm_box_pack_end(sd->main_box, sd->VIEW(first));
1493         if (sd->second)
1494           elm_box_pack_end(sd->main_box, sd->VIEW(second));
1495
1496         // if more than 3 items should be displayed
1497         EINA_LIST_FOREACH(sd->over_items, elist, it)
1498           elm_box_pack_end(sd->main_box, VIEW(it));
1499      }
1500    else
1501      {
1502         _round_items_del(sd);
1503
1504         /* left blank */
1505         EINA_LIST_FOREACH (sd->left_blanks, elist, blank)
1506           {
1507              elm_box_pack_start(sd->main_box, blank);
1508              evas_object_show(blank);
1509           }
1510
1511         /* right blank */
1512         EINA_LIST_FOREACH (sd->right_blanks, elist, blank)
1513           {
1514              elm_box_pack_end(sd->main_box, blank);
1515              evas_object_show(blank);
1516           }
1517
1518         _blank_item_check(obj, sd->display_item_num);
1519
1520         sd->r_items = eina_list_free(sd->r_items);
1521      }
1522
1523    if (sd->selected_item) _selected_item_indicate(sd->selected_item);
1524    _sizing_eval(obj);
1525 }
1526
1527 EOLIAN static int
1528 _elm_diskselector_side_text_max_length_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1529 {
1530    return sd->len_side;
1531 }
1532
1533 EOLIAN static void
1534 _elm_diskselector_side_text_max_length_set(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd, int len)
1535 {
1536    sd->len_side = len;
1537 }
1538
1539 EAPI void
1540 elm_diskselector_bounce_set(Evas_Object *obj,
1541                             Eina_Bool h_bounce,
1542                             Eina_Bool v_bounce)
1543 {
1544    ELM_DISKSELECTOR_CHECK(obj);
1545
1546    eo_do(obj, elm_interface_scrollable_bounce_allow_set(h_bounce, v_bounce));
1547 }
1548
1549 EAPI void
1550 elm_diskselector_bounce_get(const Evas_Object *obj,
1551                             Eina_Bool *h_bounce,
1552                             Eina_Bool *v_bounce)
1553 {
1554    ELM_DISKSELECTOR_CHECK(obj);
1555
1556    eo_do((Eo *) obj, elm_interface_scrollable_bounce_allow_get(h_bounce, v_bounce));
1557 }
1558
1559 EAPI void
1560 elm_diskselector_scroller_policy_get(const Evas_Object *obj,
1561                                      Elm_Scroller_Policy *policy_h,
1562                                      Elm_Scroller_Policy *policy_v)
1563 {
1564    ELM_DISKSELECTOR_CHECK(obj);
1565    eo_do((Eo *) obj, elm_interface_scrollable_policy_get(policy_h, policy_v));
1566 }
1567
1568 EOLIAN static void
1569 _elm_diskselector_elm_interface_scrollable_policy_get(Eo *obj, Elm_Diskselector_Data *sd EINA_UNUSED, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
1570 {
1571    Elm_Scroller_Policy s_policy_h, s_policy_v;
1572
1573    eo_do_super((Eo *)obj, MY_CLASS, elm_interface_scrollable_policy_get(&s_policy_h, &s_policy_v));
1574    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
1575    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
1576 }
1577
1578 EAPI void
1579 elm_diskselector_scroller_policy_set(Evas_Object *obj,
1580                                      Elm_Scroller_Policy policy_h,
1581                                      Elm_Scroller_Policy policy_v)
1582 {
1583    ELM_DISKSELECTOR_CHECK(obj);
1584    eo_do(obj, elm_interface_scrollable_policy_set(policy_h, policy_v));
1585 }
1586
1587 EOLIAN static void
1588 _elm_diskselector_elm_interface_scrollable_policy_set(Eo *obj, Elm_Diskselector_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
1589 {
1590    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1591        (policy_v >= ELM_SCROLLER_POLICY_LAST))
1592      return;
1593
1594    eo_do_super(obj, MY_CLASS, elm_interface_scrollable_policy_set(policy_h, policy_v));
1595 }
1596
1597 EOLIAN static void
1598 _elm_diskselector_clear(Eo *obj, Elm_Diskselector_Data *sd)
1599 {
1600    Elm_Diskselector_Item *it;
1601
1602    if (!sd->items) return;
1603
1604    sd->selected_item = NULL;
1605    EINA_LIST_FREE(sd->items, it)
1606      {
1607         _item_del(it);
1608         elm_widget_item_free(it);
1609      }
1610
1611    _round_items_del(sd);
1612    sd->r_items = eina_list_free(sd->r_items);
1613    _sizing_eval(obj);
1614 }
1615
1616 EOLIAN static const Eina_List*
1617 _elm_diskselector_items_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1618 {
1619    return sd->items;
1620 }
1621
1622 EOLIAN static Elm_Object_Item*
1623 _elm_diskselector_item_append(Eo *obj, Elm_Diskselector_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
1624 {
1625    Elm_Diskselector_Item *it, *dit;
1626    Eina_List *elist;
1627
1628    Evas *evas;
1629
1630    evas = evas_object_evas_get(obj);
1631    evas_event_freeze(evas);
1632
1633    it = _item_new(obj, icon, label, func, data);
1634    sd->items = eina_list_append(sd->items, it);
1635    it->node = eina_list_last(sd->items);
1636    sd->item_count++;
1637    if (sd->round)
1638      {
1639         _round_items_del(sd);
1640         sd->r_items = eina_list_append(sd->r_items, it);
1641         _round_items_add(sd);
1642
1643         if (sd->last)
1644           elm_box_pack_start(sd->main_box, sd->VIEW(last));
1645         if (sd->s_last)
1646           elm_box_pack_start(sd->main_box, sd->VIEW(s_last));
1647
1648         // if more than 3 items should be displayed
1649          EINA_LIST_FOREACH (sd->under_items, elist, dit)
1650            elm_box_pack_start(sd->main_box, VIEW(dit));
1651
1652         elm_box_pack_end(sd->main_box, VIEW(it));
1653
1654         if (sd->first)
1655           elm_box_pack_end(sd->main_box, sd->VIEW(first));
1656         if (sd->second)
1657           elm_box_pack_end(sd->main_box, sd->VIEW(second));
1658
1659         // if more than 3 items should be displayed
1660          EINA_LIST_FOREACH (sd->over_items, elist, dit)
1661            elm_box_pack_end(sd->main_box, VIEW(dit));
1662      }
1663    else
1664      {
1665         Evas_Object *blank;
1666         blank = eina_list_data_get(sd->right_blanks);
1667         elm_box_pack_before(sd->main_box, VIEW(it), blank);
1668      }
1669
1670    if (!sd->selected_item)
1671      sd->selected_item = it;
1672
1673    if (!sd->scroller_move_idle_enterer)
1674      sd->scroller_move_idle_enterer = ecore_idle_enterer_before_add(_scroller_move, obj);
1675
1676    _sizing_eval(obj);
1677
1678    evas_event_thaw(evas);
1679    evas_event_thaw_eval(evas);
1680
1681    return (Elm_Object_Item *)it;
1682 }
1683
1684 EOLIAN static Elm_Object_Item*
1685 _elm_diskselector_selected_item_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1686 {
1687    return (Elm_Object_Item *)sd->selected_item;
1688 }
1689
1690 EAPI void
1691 elm_diskselector_item_selected_set(Elm_Object_Item *item,
1692                                    Eina_Bool selected)
1693 {
1694    Elm_Diskselector_Item *it = (Elm_Diskselector_Item *)item;
1695
1696    ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it);
1697    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
1698
1699    if ((sd->selected_item == it) && (selected))
1700      return;
1701
1702    if ((sd->selected_item == it) && (!selected))
1703      sd->selected_item = eina_list_data_get(sd->items);
1704    else
1705      {
1706         sd->selected_item = it;
1707         _selected_item_indicate(sd->selected_item);
1708      }
1709
1710    if (!sd->scroller_move_idle_enterer)
1711      sd->scroller_move_idle_enterer = ecore_idle_enterer_before_add(_scroller_move, WIDGET(item));
1712 }
1713
1714 EAPI Eina_Bool
1715 elm_diskselector_item_selected_get(const Elm_Object_Item *it)
1716 {
1717    ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1718    ELM_DISKSELECTOR_DATA_GET(WIDGET(it), sd);
1719
1720    return sd->selected_item == ((Elm_Diskselector_Item *)it);
1721 }
1722
1723 EAPI Elm_Object_Item *
1724 elm_diskselector_item_prev_get(const Elm_Object_Item *item)
1725 {
1726    Elm_Diskselector_Item *it = (Elm_Diskselector_Item *)item;
1727
1728    ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
1729
1730    if (it->node->prev) return it->node->prev->data;
1731    else return NULL;
1732 }
1733
1734 EAPI Elm_Object_Item *
1735 elm_diskselector_item_next_get(const Elm_Object_Item *item)
1736 {
1737    Elm_Diskselector_Item *it = (Elm_Diskselector_Item *)item;
1738
1739    ELM_DISKSELECTOR_ITEM_CHECK_OR_RETURN(it, NULL);
1740
1741    if (it->node->next) return it->node->next->data;
1742    else return NULL;
1743 }
1744
1745 EOLIAN static Elm_Object_Item*
1746 _elm_diskselector_first_item_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1747 {
1748    if (!sd || !sd->items) return NULL;
1749    else return eina_list_data_get(sd->items);
1750 }
1751
1752 EOLIAN static Elm_Object_Item*
1753 _elm_diskselector_last_item_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1754 {
1755    if (!sd->items) return NULL;
1756    else return eina_list_data_get(eina_list_last(sd->items));
1757 }
1758
1759 EOLIAN static void
1760 _elm_diskselector_display_item_num_set(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd, int num)
1761 {
1762    if (num < DISPLAY_ITEM_NUM_MIN) num = DISPLAY_ITEM_NUM_MIN;
1763    sd->display_item_num = num;
1764    sd->display_item_num_by_api = EINA_TRUE;
1765
1766    if (!sd->round) _blank_item_check(obj, num);
1767 }
1768
1769 EOLIAN static int
1770 _elm_diskselector_display_item_num_get(Eo *obj EINA_UNUSED, Elm_Diskselector_Data *sd)
1771 {
1772    return sd->display_item_num;
1773 }
1774
1775 static void
1776 _elm_diskselector_class_constructor(Eo_Class *klass)
1777 {
1778    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1779
1780    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1781       _elm_diskselector_smart_focus_next_enable = EINA_TRUE;
1782 }
1783
1784 #include "elm_diskselector.eo.c"