fileselector: apply key binding
[platform/upstream/elementary.git] / src / lib / elc_fileselector.c
1 /*
2  * TODO:
3  *  - child elements focusing support
4  *  - user defined icon/label cb
5  *  - show/hide/add buttons ???
6  *  - Pattern Filter support
7  */
8 #ifdef HAVE_CONFIG_H
9 # include "elementary_config.h"
10 #endif
11
12 #include <Elementary.h>
13 #include "elm_priv.h"
14 #include "elm_interface_fileselector.h"
15 #include "elm_widget_fileselector.h"
16
17 #define MY_CLASS ELM_OBJ_FILESELECTOR_CLASS
18
19 #define MY_CLASS_NAME "Elm_Fileselector"
20 #define MY_CLASS_NAME_LEGACY "elm_fileselector"
21
22 /* FIXME: need a way to find a gap between the size of item and thumbnail */
23 #define GENGRID_PADDING 16
24
25 static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST];
26 static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
27
28 #define ELM_PRIV_FILESELECTOR_SIGNALS(cmd) \
29    cmd(SIG_ACTIVATED, "activated", "s") \
30    cmd(SIG_DIRECTORY_OPEN, "directory,open", "s") \
31    cmd(SIG_DONE, "done", "s") \
32    cmd(SIG_SELECTED, "selected", "s") \
33    cmd(SIG_SELECTED_INVALID, "selected,invalid", "s")
34
35 ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
36
37 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
38    ELM_PRIV_FILESELECTOR_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
39    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
40    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
41    {NULL, NULL}
42 };
43 #undef ELM_PRIV_FILESELECTOR_SIGNALS
44
45 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
46 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
47
48 static const Elm_Action key_actions[] = {
49    {"select", _key_action_select},
50    {"escape", _key_action_escape},
51    {NULL, NULL}
52 };
53
54 static void _ok(void *data, Evas_Object *obj, void *event_info);
55 static void _canc(void *data, Evas_Object *obj, void *event_info);
56
57 /* final routine on deletion */
58 static void
59 _elm_fileselector_smart_del_do(Elc_Fileselector_Data *sd)
60 {
61    eina_stringshare_del(sd->path);
62    eina_stringshare_del(sd->selection);
63    free(ecore_idler_del(sd->populate_idler));
64
65    eo_do_super(sd->obj, MY_CLASS, evas_obj_smart_del());
66 }
67
68 EOLIAN static void
69 _elc_fileselector_elm_layout_sizing_eval(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED)
70 {
71    Evas_Coord minw = -1, minh = -1;
72
73    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
74
75    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
76    edje_object_size_min_restricted_calc
77      (wd->resize_obj, &minw, &minh, minw, minh);
78    evas_object_size_hint_min_set(obj, minw, minh);
79 }
80
81 static void
82 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
83 {
84    ELM_FILESELECTOR_DATA_GET(obj, sd);
85
86    elm_widget_mirrored_set(sd->cancel_button, rtl);
87    elm_widget_mirrored_set(sd->ok_button, rtl);
88    elm_widget_mirrored_set(sd->files_view, rtl);
89    elm_widget_mirrored_set(sd->up_button, rtl);
90    elm_widget_mirrored_set(sd->home_button, rtl);
91 }
92
93 EOLIAN static Eina_Bool
94 _elc_fileselector_elm_widget_theme_apply(Eo *obj, Elc_Fileselector_Data *sd)
95 {
96    const char *style;
97    const char *data;
98    char buf[1024];
99
100    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
101
102    Eina_Bool int_ret = EINA_FALSE;
103    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
104    if (!int_ret) return EINA_FALSE;
105
106    style = elm_widget_style_get(obj);
107    _mirrored_set(obj, elm_widget_mirrored_get(obj));
108
109    data = edje_object_data_get
110        (wd->resize_obj, "path_separator");
111    if (data) sd->path_separator = data;
112    else sd->path_separator = "/";
113
114    snprintf(buf, sizeof(buf), "fileselector/%s", style);
115
116 #define SWALLOW(part_name, object_ptn)                          \
117   if (object_ptn)                                               \
118     {                                                           \
119        elm_widget_style_set(object_ptn, buf);                   \
120        if (!elm_layout_content_set(obj, part_name, object_ptn)) \
121          evas_object_hide(object_ptn);                          \
122     }
123
124    SWALLOW("elm.swallow.up", sd->up_button);
125    SWALLOW("elm.swallow.home", sd->home_button);
126    SWALLOW("elm.swallow.spinner", sd->spinner);
127    elm_object_style_set(sd->spinner, "wheel");
128
129    if (!elm_layout_content_set(obj, "elm.swallow.files", sd->files_view))
130      evas_object_hide(sd->files_view);
131
132    SWALLOW("elm.swallow.path", sd->path_entry);
133    SWALLOW("elm.swallow.filename", sd->name_entry);
134
135    snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
136    SWALLOW("elm.swallow.filters", sd->filter_hoversel);
137    SWALLOW("elm.swallow.cancel", sd->cancel_button);
138    SWALLOW("elm.swallow.ok", sd->ok_button);
139
140 #undef SWALLOW
141
142    edje_object_message_signal_process(wd->resize_obj);
143
144    elm_layout_sizing_eval(obj);
145
146    return EINA_TRUE;
147 }
148
149 static Eina_Bool
150 _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED)
151 {
152    _ok(obj, NULL, NULL);
153    return EINA_TRUE;
154 }
155
156 static Eina_Bool
157 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
158 {
159    _canc(obj, NULL, NULL);
160    return EINA_TRUE;
161 }
162
163 EOLIAN static Eina_Bool
164 _elc_fileselector_elm_widget_event(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info)
165 {
166    Evas_Event_Key_Down *ev = event_info;
167    (void) src;
168
169    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
170    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
171    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
172
173    if (!_elm_config_key_binding_call(obj, ev, key_actions))
174      return EINA_FALSE;
175
176    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
177    return EINA_TRUE;
178 }
179
180 /***  GENLIST/GENGRID "MODEL"  ***/
181 static char *
182 _itc_text_get(void *data,
183               Evas_Object *obj   EINA_UNUSED,
184               const char *source EINA_UNUSED)
185 {
186    return elm_entry_utf8_to_markup
187             (ecore_file_file_get(data)); /* NOTE this will be free()'d by
188                                           * the caller */
189 }
190
191 static Evas_Object *
192 _itc_icon_folder_get(void *data EINA_UNUSED,
193                      Evas_Object *obj,
194                      const char *source)
195 {
196    Evas_Object *ic, *grid, *f;
197
198    if (strcmp(source, "elm.swallow.icon")) return NULL;
199
200    f = evas_object_data_get(obj, "parent");
201    ELM_FILESELECTOR_DATA_GET(f, sd);
202
203    ic = elm_icon_add(obj);
204    elm_icon_standard_set(ic, "folder");
205    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
206    evas_object_show(ic);
207
208    grid = elm_grid_add(obj);
209    elm_grid_size_set(grid, 1, 1);
210    elm_grid_pack(grid, ic, 0, 0, 1, 1);
211    evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
212    evas_object_show(grid);
213
214    return grid;
215 }
216
217 static Evas_Object *
218 _itc_icon_image_get(void *data,
219                     Evas_Object *obj,
220                     const char *source)
221 {
222    const char *filename = data;
223    Evas_Object *ic, *grid, *f;
224
225    if (strcmp(source, "elm.swallow.icon")) return NULL;
226
227    f = evas_object_data_get(obj, "parent");
228    ELM_FILESELECTOR_DATA_GET(f, sd);
229
230    ic = elm_icon_add(obj);
231    elm_icon_standard_set(ic, "image");
232    elm_icon_thumb_set(ic, filename, NULL);
233    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
234    evas_object_show(ic);
235
236    grid = elm_grid_add(obj);
237    elm_grid_size_set(grid, 1, 1);
238    elm_grid_pack(grid, ic, 0, 0, 1, 1);
239    evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
240    evas_object_show(grid);
241
242    return grid;
243 }
244
245 static Evas_Object *
246 _itc_icon_file_get(void *data EINA_UNUSED,
247                    Evas_Object *obj,
248                    const char *source)
249 {
250    Evas_Object *ic, *grid, *f;
251
252    if (strcmp(source, "elm.swallow.icon")) return NULL;
253
254    f = evas_object_data_get(obj, "parent");
255    ELM_FILESELECTOR_DATA_GET(f, sd);
256
257    ic = elm_icon_add(obj);
258    elm_icon_standard_set(ic, "file");
259    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
260    evas_object_show(ic);
261
262    grid = elm_grid_add(obj);
263    elm_grid_size_set(grid, 1, 1);
264    elm_grid_pack(grid, ic, 0, 0, 1, 1);
265    evas_object_size_hint_min_set(grid, sd->thumbnail_size.w, sd->thumbnail_size.h);
266    evas_object_show(grid);
267
268    return grid;
269 }
270
271 static Eina_Bool
272 _itc_state_get(void *data         EINA_UNUSED,
273                Evas_Object *obj   EINA_UNUSED,
274                const char *source EINA_UNUSED)
275 {
276    return EINA_FALSE;
277 }
278
279 static void
280 _itc_del(void *data,
281          Evas_Object *obj EINA_UNUSED)
282 {
283    eina_stringshare_del(data);
284 }
285
286 static void
287 _anchors_do(Evas_Object *obj,
288             const char *path)
289 {
290    char **tok, buf[PATH_MAX * 3], *s;
291    int i, j;
292
293    ELM_FILESELECTOR_DATA_GET(obj, sd);
294
295    s = elm_entry_utf8_to_markup(path);
296    if (!s) return;
297
298    buf[0] = '\0';
299    tok = eina_str_split(s, "/", 0);
300    free(s);
301
302    eina_strlcat(buf, "<a href='/'>root</a>", sizeof(buf));
303    for (i = 0; tok[i]; i++)
304      {
305         if ((!tok[i]) || (!tok[i][0])) continue;
306         eina_strlcat(buf, sd->path_separator, sizeof(buf));
307         eina_strlcat(buf, "<a href=", sizeof(buf));
308         for (j = 0; j <= i; j++)
309           {
310              if (strlen(tok[j]) < 1) continue;
311              eina_strlcat(buf, "/", sizeof(buf));
312              eina_strlcat(buf, tok[j], sizeof(buf));
313           }
314         eina_strlcat(buf, ">", sizeof(buf));
315         eina_strlcat(buf, tok[i], sizeof(buf));
316         eina_strlcat(buf, "</a>", sizeof(buf));
317      }
318    free(tok[0]);
319    free(tok);
320
321    elm_object_text_set(sd->path_entry, buf);
322 }
323
324 static Eina_Bool
325 _mime_type_matched(const char *mime_filter, const char *mime_type)
326 {
327    int i = 0;
328
329    while (mime_filter[i] != '\0')
330      {
331         if (mime_filter[i] != mime_type[i])
332           {
333              if (mime_filter[i] == '*' && mime_filter[i + 1] == '\0')
334                return EINA_TRUE;
335
336              return EINA_FALSE;
337           }
338         i++;
339      }
340
341    if (mime_type[i] != '\0') return EINA_FALSE;
342
343    return EINA_TRUE;
344 }
345
346 static Eina_Bool
347 _check_mime_type_filter(const Elm_Fileselector_Filter *filter,
348                         const char *file_name)
349 {
350    const char *mime_type = NULL;
351    int i;
352
353    mime_type = efreet_mime_type_get(file_name);
354
355    if (!mime_type) return EINA_FALSE;
356
357    for (i = 0; filter->filter.mime_types[i]; ++i)
358      {
359         if (_mime_type_matched(filter->filter.mime_types[i], mime_type))
360           return EINA_TRUE;
361      }
362    return EINA_FALSE;
363 }
364
365 static Eina_Bool
366 _ls_filter_cb(void *data,
367               Eio_File *handler EINA_UNUSED,
368               const Eina_File_Direct_Info *info)
369 {
370    Listing_Request *lreq = data;
371    Elm_Fileselector_Filter *cf;
372    Eina_Bool dir = EINA_FALSE;
373
374    if (!lreq->sd->hidden_visible && info->path[info->name_start] == '.')
375      return EINA_FALSE;
376
377    if (info->type == EINA_FILE_DIR)
378      dir = EINA_TRUE;
379
380    if (lreq->sd->only_folder && !dir)
381      return EINA_FALSE;
382
383    cf = lreq->sd->current_filter;
384    if (!cf)
385      return EINA_TRUE;
386
387    switch (cf->filter_type)
388      {
389       case ELM_FILESELECTOR_MIME_FILTER:
390          return dir || _check_mime_type_filter(cf, info->path);
391       case ELM_FILESELECTOR_CUSTOM_FILTER:
392          return cf->filter.custom->func(info->path, dir,
393                                         cf->filter.custom->data);
394       default:
395          return EINA_FALSE;
396      }
397
398    return EINA_FALSE;
399 }
400
401 static const char *
402 _file_type(const char *a)
403 {
404    char *p = strrchr(a, '.');
405    if (!p) return "";
406
407    return p;
408 }
409
410 static int
411 _strcoll_rev(const char *a, const char *b)
412 {
413    return strcoll(b, a);
414 }
415
416 static int
417 _strcoll_type(const char *a, const char *b)
418 {
419    return strcoll(_file_type(a), _file_type(b));
420 }
421
422 static int
423 _strcoll_type_rev(const char *a, const char *b)
424 {
425    return _strcoll_type(b, a);
426 }
427
428 static int
429 _size_cmp(const char *a, const char *b)
430 {
431    return ecore_file_size(a) - ecore_file_size(b);
432 }
433
434 static int
435 _size_cmp_rev(const char *a, const char *b)
436 {
437    return _size_cmp(b, a);
438 }
439
440 static int
441 _modified_cmp(const char *a, const char *b)
442 {
443    if (ecore_file_mod_time(a) > ecore_file_mod_time(b))
444      return 1;
445
446    return -1;
447 }
448
449 static int
450 _modified_cmp_rev(const char *a, const char *b)
451 {
452    return _modified_cmp(b, a);
453 }
454
455 static int
456 _file_grid_cmp(const void *a, const void *b)
457 {
458    Evas_Object *f;
459
460    const Elm_Object_Item *ga = a;
461    const Elm_Object_Item *gb = b;
462    const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga);
463    const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb);
464
465    if (ca == grid_itc[ELM_DIRECTORY])
466      {
467         if (cb != grid_itc[ELM_DIRECTORY])
468           return -1;
469      }
470    else if (cb == grid_itc[ELM_DIRECTORY])
471      {
472         return 1;
473      }
474
475    f = evas_object_data_get(elm_object_item_widget_get(ga), "parent");
476    ELM_FILESELECTOR_DATA_GET(f, sd);
477    return sd->sort_method(elm_object_item_data_get(ga),
478                           elm_object_item_data_get(gb));
479 }
480
481 static int
482 _file_list_cmp(const void *a, const void *b)
483 {
484    Evas_Object *f;
485
486    const Elm_Object_Item *la = a;
487    const Elm_Object_Item *lb = b;
488    const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la);
489    const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb);
490
491    if (ca == list_itc[ELM_DIRECTORY])
492      {
493         if (cb != list_itc[ELM_DIRECTORY])
494           return -1;
495      }
496    else if (cb == list_itc[ELM_DIRECTORY])
497      {
498         return 1;
499      }
500
501    f = evas_object_data_get(elm_object_item_widget_get(la), "parent");
502    ELM_FILESELECTOR_DATA_GET(f, sd);
503    return sd->sort_method(elm_object_item_data_get(la),
504                           elm_object_item_data_get(lb));
505 }
506
507 static void
508 _signal_first(Listing_Request *lreq)
509 {
510    if (!lreq->first) return;
511
512    if (lreq->sd->multi)
513      {
514         char *path;
515         EINA_LIST_FREE(lreq->sd->paths, path)
516           free(path);
517      }
518
519    evas_object_smart_callback_call
520      (lreq->obj, SIG_DIRECTORY_OPEN, (void *)lreq->path);
521
522    if (!lreq->parent_it)
523      {
524         if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
525           elm_genlist_clear(lreq->sd->files_view);
526         else
527           elm_gengrid_clear(lreq->sd->files_view);
528         eina_stringshare_replace(&lreq->sd->path, lreq->path);
529         _anchors_do(lreq->obj, lreq->path);
530         elm_object_text_set(lreq->sd->name_entry, "");
531      }
532
533    lreq->first = EINA_FALSE;
534 }
535
536 static void
537 _ls_main_cb(void *data,
538             Eio_File *handler,
539             const Eina_File_Direct_Info *info)
540 {
541    Listing_Request *lreq = data;
542    Elm_Object_Item *item;
543    int itcn = ELM_FILE_UNKNOW;
544
545    if (eio_file_check(handler)) return;
546
547    if (!lreq->sd->files_view || lreq->sd->current != handler)
548      {
549         eio_file_cancel(handler);
550         return;
551      }
552
553    _signal_first(lreq);
554
555    if (info->type == EINA_FILE_DIR)
556      itcn = ELM_DIRECTORY;
557    else
558      {
559         if (evas_object_image_extension_can_load_get
560               (info->path + info->name_start))
561           itcn = ELM_FILE_IMAGE;
562      }
563
564    if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
565      {
566         item = elm_genlist_item_sorted_insert(lreq->sd->files_view, list_itc[itcn],
567                                               eina_stringshare_add(info->path),
568                                               lreq->parent_it,
569                                               ((lreq->sd->expand) && (itcn == ELM_DIRECTORY))
570                                               ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
571                                               _file_list_cmp, NULL, NULL);
572
573         if (lreq->selected && !strcmp(info->path, lreq->selected))
574           {
575              elm_genlist_item_selected_set(item, EINA_TRUE);
576              elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
577           }
578      }
579    else if (lreq->sd->mode == ELM_FILESELECTOR_GRID)
580      {
581         item = elm_gengrid_item_sorted_insert(lreq->sd->files_view, grid_itc[itcn],
582                                               eina_stringshare_add(info->path),
583                                               _file_grid_cmp, NULL, NULL);
584
585         if (lreq->selected && !strcmp(info->path, lreq->selected))
586           {
587              elm_gengrid_item_selected_set(item, EINA_TRUE);
588              elm_object_text_set(lreq->sd->name_entry, ecore_file_file_get(info->path));
589           }
590      }
591 }
592
593 static void
594 _listing_request_cleanup(Listing_Request *lreq)
595 {
596    EINA_REFCOUNT_UNREF(lreq->sd) _elm_fileselector_smart_del_do(lreq->sd);
597
598    eina_stringshare_del(lreq->path);
599    eina_stringshare_del(lreq->selected);
600    free(lreq);
601 }
602
603 static void
604 _ls_done_cb(void *data, Eio_File *handler EINA_UNUSED)
605 {
606    Listing_Request *lreq = data;
607
608    _signal_first(lreq);
609    elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
610    elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
611
612    lreq->sd->current = NULL;
613    _listing_request_cleanup(lreq);
614 }
615
616 static void
617 _ls_error_cb(void *data, Eio_File *handler, int error EINA_UNUSED)
618 {
619    Listing_Request *lreq = data;
620
621    elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
622    elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
623
624    if (lreq->sd->current == handler)
625      lreq->sd->current = NULL;
626    _listing_request_cleanup(lreq);
627 }
628
629 static void
630 _populate(Evas_Object *obj,
631           const char *path,
632           Elm_Object_Item *parent_it,
633           const char *selected)
634 {
635    ELM_FILESELECTOR_DATA_GET(obj, sd);
636    if (!path) return;
637
638    Listing_Request *lreq;
639
640    if (sd->expand && sd->current) return;
641
642    if (sd->monitor) eio_monitor_del(sd->monitor);
643    if (sd->current) eio_file_cancel(sd->current);
644
645    lreq = malloc(sizeof (Listing_Request));
646    if (!lreq) return;
647
648    lreq->sd = sd;
649    EINA_REFCOUNT_REF(lreq->sd);
650
651    lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */
652    lreq->obj = obj;
653    lreq->path = eina_stringshare_add(path);
654    lreq->first = EINA_TRUE;
655
656    if (selected)
657      lreq->selected = eina_stringshare_add(selected);
658    else
659      lreq->selected = NULL;
660
661    /* TODO: sub directory should be monitored for expand mode */
662    sd->monitor = eio_monitor_add(path);
663    sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb,
664                                   _ls_done_cb, _ls_error_cb, lreq);
665    elm_progressbar_pulse(sd->spinner, EINA_TRUE);
666    elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm");
667 }
668
669 static void
670 _on_list_expanded(void *data,
671                   Evas_Object *obj EINA_UNUSED,
672                   void *event_info)
673 {
674    Elm_Object_Item *it = event_info;
675    const char *path = elm_object_item_data_get(it);
676
677    _populate(data, path, it, NULL);
678 }
679
680 static void
681 _on_list_contracted(void *data       EINA_UNUSED,
682                     Evas_Object *obj EINA_UNUSED,
683                     void *event_info)
684 {
685    Elm_Object_Item *it = event_info;
686
687    elm_genlist_item_subitems_clear(it);
688 }
689
690 static void
691 _on_list_expand_req(void *data       EINA_UNUSED,
692                     Evas_Object *obj EINA_UNUSED,
693                     void *event_info)
694 {
695    Elm_Object_Item *it = event_info;
696
697    elm_genlist_item_expanded_set(it, EINA_TRUE);
698 }
699
700 static void
701 _on_list_contract_req(void *data       EINA_UNUSED,
702                       Evas_Object *obj EINA_UNUSED,
703                       void *event_info)
704 {
705    Elm_Object_Item *it = event_info;
706
707    elm_genlist_item_expanded_set(it, EINA_FALSE);
708 }
709
710 static Eina_Bool
711 _populate_do(void *data)
712 {
713    struct sel_data *sdata = data;
714    const char *p;
715
716    ELM_FILESELECTOR_DATA_GET(sdata->fs, sd);
717
718    /* keep a ref to path 'couse it will be destroyed by _populate */
719    p = eina_stringshare_add(sdata->path);
720    _populate(sdata->fs, p, NULL, NULL);
721    eina_stringshare_del(p);
722
723    sd->populate_idler = NULL;
724    free(sdata);
725    return ECORE_CALLBACK_CANCEL;
726 }
727
728 static void
729 _on_item_activated(void *data,
730                    Evas_Object *obj EINA_UNUSED,
731                    void *event_info)
732 {
733    //This event_info could be a list or gengrid item
734    Elm_Object_Item *it = event_info;
735    struct sel_data *sdata;
736    void *old_sdata;
737    const char *path;
738    Eina_Bool is_dir;
739
740    ELM_FILESELECTOR_DATA_GET(data, sd);
741
742    path = elm_object_item_data_get(it);
743    if (!path) return;
744
745    is_dir = ecore_file_is_dir(path);
746    if (!is_dir)
747      {
748         evas_object_smart_callback_call(data, SIG_ACTIVATED, (void *)path);
749         return;
750      }
751
752    if (!sd->double_tap_navigation) return;
753
754    sdata = malloc(sizeof(*sdata));
755    if (!sdata) return;
756
757    sdata->fs = data;
758    sdata->path = path;
759
760    if (sd->populate_idler)
761      {
762         old_sdata = ecore_idler_del(sd->populate_idler);
763         free(old_sdata);
764      }
765    sd->populate_idler = ecore_idler_add(_populate_do, sdata);
766 }
767
768 static void
769 _clear_selections(Elc_Fileselector_Data *sd, Elm_Object_Item *last_selected)
770 {
771    Eina_List *items;
772    Elm_Object_Item *sel;
773
774    if (sd->mode == ELM_FILESELECTOR_LIST)
775      {
776         items = eina_list_clone(elm_genlist_selected_items_get(sd->files_view));
777
778         EINA_LIST_FREE(items, sel)
779           {
780             if (sel == last_selected) continue;
781             elm_genlist_item_selected_set(sel, EINA_FALSE);
782           }
783      }
784    else if (sd->mode == ELM_FILESELECTOR_GRID)
785      {
786         items = eina_list_clone(elm_gengrid_selected_items_get(sd->files_view));
787
788         EINA_LIST_FREE(items, sel)
789           {
790             if (sel == last_selected) continue;
791             elm_gengrid_item_selected_set(sel, EINA_FALSE);
792           }
793      }
794 }
795
796 static void
797 _on_item_selected(void *data,
798                   Evas_Object *obj EINA_UNUSED,
799                   void *event_info)
800 {
801    //This event_info could be a list or gengrid item
802    Elm_Object_Item *it = event_info;
803    struct sel_data *sdata;
804    void *old_sdata;
805    const char *path;
806    char *parent_path;
807    Eina_Bool is_dir;
808
809    ELM_FILESELECTOR_DATA_GET(data, sd);
810
811    path = elm_object_item_data_get(it);
812    if (!path) return;
813
814    is_dir = ecore_file_is_dir(path);
815
816    /* We need to send callback when:
817     * - path is dir and mode is ONLY FOLDER
818     * - path is file and mode is NOT ONLY FOLDER */
819    if (is_dir == sd->only_folder)
820      {
821         if (sd->multi)
822           {
823              Eina_List *li;
824              const char *p;
825              Eina_Strbuf *buf;
826
827              if (sd->dir_selected)
828                {
829                   _clear_selections(sd, it);
830                   sd->dir_selected = EINA_FALSE;
831                }
832
833              buf = eina_strbuf_new();
834              EINA_LIST_FOREACH(sd->paths, li, p)
835                {
836                   eina_strbuf_append(buf, ecore_file_file_get(p));
837                   eina_strbuf_append_length(buf, ", ", 2);
838                }
839
840              sd->paths = eina_list_append(sd->paths, strdup(path));
841              eina_strbuf_append(buf, ecore_file_file_get(path));
842
843              elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
844              eina_strbuf_free(buf);
845           }
846         else
847           elm_object_text_set(sd->name_entry, ecore_file_file_get(path));
848
849         evas_object_smart_callback_call(data, SIG_SELECTED, (void *)path);
850      }
851    else
852      {
853         if (sd->multi && is_dir && sd->double_tap_navigation)
854           {
855              _clear_selections(sd, it);
856              sd->dir_selected = EINA_TRUE;
857           }
858
859         elm_object_text_set(sd->name_entry, "");
860      }
861
862    /* We need to populate, if path is directory and:
863     * - mode is GRID;
864     * - mode is LIST and 'not expand mode';
865     *   in other cases update anchors. */
866    if (!is_dir) return;
867
868    if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
869      {
870         if (sd->only_folder)
871           {
872              parent_path = ecore_file_dir_get(path);
873              eina_stringshare_replace(&sd->path, parent_path);
874              _anchors_do(data, parent_path);
875              free(parent_path);
876           }
877         else
878           {
879              eina_stringshare_replace(&sd->path, path);
880              _anchors_do(data, path);
881           }
882        return;
883      }
884
885    if (sd->double_tap_navigation) return;
886
887    sdata = malloc(sizeof(*sdata));
888    if (!sdata) return;
889
890    sdata->fs = data;
891    sdata->path = path;
892
893    if (sd->populate_idler)
894      {
895         old_sdata = ecore_idler_del(sd->populate_idler);
896         free(old_sdata);
897      }
898    sd->populate_idler = ecore_idler_add(_populate_do, sdata);
899 }
900
901 static void
902 _on_item_unselected(void *data,
903                     Evas_Object *obj EINA_UNUSED,
904                     void *event_info)
905 {
906    Eina_List *li, *l;
907    char *path;
908    const char *unselected_path;
909    Eina_Strbuf *buf;
910    Elm_Object_Item *it = event_info;
911    Eina_Bool first = EINA_TRUE;
912
913    ELM_FILESELECTOR_DATA_GET(data, sd);
914
915    if (!sd->multi) return;
916
917    unselected_path = elm_object_item_data_get(it);
918    if (!unselected_path) return;
919
920    buf = eina_strbuf_new();
921    EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
922      {
923         if (!strcmp(path, unselected_path))
924           {
925              sd->paths = eina_list_remove_list(sd->paths, li);
926              free(path);
927           }
928         else
929           {
930              if (!first)
931                eina_strbuf_append_length(buf, ", ", 2);
932              else
933                first = EINA_FALSE;
934
935              eina_strbuf_append(buf, ecore_file_file_get(path));
936           }
937      }
938
939    elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
940    eina_strbuf_free(buf);
941 }
942
943 static void
944 _on_dir_up(void *data,
945            Evas_Object *obj EINA_UNUSED,
946            void *event_info EINA_UNUSED)
947 {
948    Evas_Object *fs = data;
949    char *parent;
950
951    ELM_FILESELECTOR_DATA_GET(fs, sd);
952
953    parent = ecore_file_dir_get(sd->path);
954    _populate(fs, parent, NULL, NULL);
955    free(parent);
956 }
957
958 static void
959 _home(void *data,
960       Evas_Object *obj EINA_UNUSED,
961       void *event_info EINA_UNUSED)
962 {
963    Evas_Object *fs = data;
964
965    _populate(fs, getenv("HOME"), NULL, NULL);
966 }
967
968 static void
969 _current_filter_changed(void *data,
970                         Evas_Object *obj,
971                         void *event_info EINA_UNUSED)
972 {
973    Elm_Fileselector_Filter *filter = data;
974
975    if (filter->sd->current_filter == filter) return;
976
977    elm_object_text_set(obj, filter->filter_name);
978    filter->sd->current_filter = filter;
979
980    _populate(filter->sd->obj, filter->sd->path, NULL, NULL);
981 }
982
983 static void
984 _ok(void *data,
985     Evas_Object *obj EINA_UNUSED,
986     void *event_info EINA_UNUSED)
987 {
988    const char *name;
989    const char *selection = NULL;
990    Evas_Object *fs = data;
991    ELM_FILESELECTOR_DATA_GET(fs, sd);
992
993    if (!sd->path)
994      {
995         evas_object_smart_callback_call(fs, SIG_DONE, NULL);
996         return;
997      }
998
999    name = elm_object_text_get(sd->name_entry);
1000    if (name && name[0] != '\0')
1001      {
1002         int len = eina_stringshare_strlen(sd->path);
1003         if (sd->path[len - 1] == '/')
1004           selection = eina_stringshare_printf("%s%s", sd->path, name);
1005         else
1006           selection = eina_stringshare_printf("%s/%s", sd->path, name);
1007      }
1008    else
1009      selection = eina_stringshare_add(elm_fileselector_selected_get(fs));
1010
1011    evas_object_smart_callback_call(fs, SIG_DONE, (void *)selection);
1012    eina_stringshare_del(selection);
1013 }
1014
1015 static void
1016 _canc(void *data,
1017       Evas_Object *obj EINA_UNUSED,
1018       void *event_info EINA_UNUSED)
1019 {
1020    Evas_Object *fs = data;
1021
1022    evas_object_smart_callback_call(fs, SIG_DONE, NULL);
1023 }
1024
1025 static void
1026 _on_text_clicked(void *data EINA_UNUSED,
1027                  Evas_Object *obj,
1028                  void *event_info EINA_UNUSED)
1029 {
1030    ELM_FILESELECTOR_DATA_GET(data, sd);
1031
1032    /* FIXME: When anchor is clicked, current callback is also called.
1033     * But when it is "anchor,clicked" entry should be unfocused, so we remove
1034     * focus in achor_clicked.
1035     *
1036     * Check if entry is focused.
1037     * It will be so if empty place (not anchor) was clicked. */
1038    if (!elm_object_focus_get(obj)) return;
1039
1040    elm_entry_entry_set(obj, sd->path);
1041    elm_entry_cursor_pos_set(obj, eina_stringshare_strlen(sd->path));
1042 }
1043
1044 static void
1045 _on_text_activated(void *data,
1046                    Evas_Object *obj,
1047                    void *event_info EINA_UNUSED)
1048 {
1049    Evas_Object *fs = data;
1050    const char *p, *path;
1051    char *dir;
1052
1053    ELM_FILESELECTOR_DATA_GET(fs, sd);
1054
1055    path = elm_widget_part_text_get(obj, NULL);
1056
1057    if (!ecore_file_exists(path))
1058      {
1059         evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1060         evas_object_smart_callback_call(fs, SIG_SELECTED_INVALID, (void *)path);
1061         goto end;
1062      }
1063
1064    if (ecore_file_is_dir(path))
1065      {
1066         // keep a ref to path 'couse it will be destroyed by _populate
1067         p = eina_stringshare_add(path);
1068         _populate(fs, p, NULL, NULL);
1069         eina_stringshare_del(p);
1070
1071         if (sd->only_folder)
1072           evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1073
1074         goto end;
1075      }
1076
1077    dir = ecore_file_dir_get(path);
1078    if (!dir) goto end;
1079
1080    if (strcmp(dir, sd->path))
1081      {
1082         _populate(fs, dir, NULL, path);
1083
1084         if (sd->only_folder)
1085           evas_object_smart_callback_call(fs, SIG_SELECTED, (void *)path);
1086      }
1087    else
1088      {
1089         if (sd->mode == ELM_FILESELECTOR_LIST)
1090           {
1091              Elm_Object_Item *item = elm_genlist_first_item_get(sd->files_view);
1092              while (item)
1093                {
1094                   const char *item_path = elm_widget_item_data_get(item);
1095                   if (!strcmp(item_path, path))
1096                     {
1097                        elm_genlist_item_selected_set(item, EINA_TRUE);
1098                        elm_widget_part_text_set(sd->name_entry, NULL,
1099                                                 ecore_file_file_get(path));
1100                        break;
1101                     }
1102                   item = elm_genlist_item_next_get(item);
1103                }
1104           }
1105         else
1106           {
1107              Elm_Object_Item *item = elm_gengrid_first_item_get(sd->files_view);
1108              while (item)
1109                {
1110                   const char *item_path = elm_object_item_data_get(item);
1111                   if (!strcmp(item_path, path))
1112                     {
1113                        elm_gengrid_item_selected_set(item, EINA_TRUE);
1114                        elm_widget_part_text_set(sd->name_entry, NULL,
1115                                                 ecore_file_file_get(path));
1116                        break;
1117                     }
1118                   item = elm_gengrid_item_next_get(item);
1119                }
1120           }
1121      }
1122    free(dir);
1123
1124 end:
1125    elm_object_focus_set(obj, EINA_FALSE);
1126 }
1127
1128 static void
1129 _on_text_unfocused(void *data,
1130                    Evas_Object *obj EINA_UNUSED,
1131                    void *event_info EINA_UNUSED)
1132 {
1133    ELM_FILESELECTOR_DATA_GET(data, sd);
1134    _anchors_do(data, sd->path);
1135 }
1136
1137 static void
1138 _anchor_clicked(void *data,
1139                 Evas_Object *obj EINA_UNUSED,
1140                 void *event_info)
1141 {
1142    Elm_Entry_Anchor_Info *info = event_info;
1143    Evas_Object *fs = data;
1144    const char *p;
1145
1146    // keep a ref to path 'couse it will be destroyed by _populate
1147    p = eina_stringshare_add(info->name);
1148    _populate(fs, p, NULL, NULL);
1149    eina_stringshare_del(p);
1150    /* After anchor was clicked, entry will be focused, and will be editable.
1151     * It's wrong. So remove focus. */
1152    elm_object_focus_set(obj, EINA_FALSE);
1153 }
1154
1155 static Evas_Object *
1156 _files_list_add(Evas_Object *obj)
1157 {
1158    Evas_Object *li;
1159
1160    li = elm_genlist_add(obj);
1161    evas_object_data_set(li, "parent", obj);
1162    elm_widget_mirrored_automatic_set(li, EINA_FALSE);
1163    evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
1164    evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1165    evas_object_size_hint_min_set(li, 100, 100);
1166
1167    evas_object_smart_callback_add(li, "selected", _on_item_selected, obj);
1168    evas_object_smart_callback_add(li, "unselected", _on_item_unselected, obj);
1169    evas_object_smart_callback_add(li, "activated", _on_item_activated, obj);
1170    evas_object_smart_callback_add
1171      (li, "expand,request", _on_list_expand_req, obj);
1172    evas_object_smart_callback_add
1173      (li, "contract,request", _on_list_contract_req, obj);
1174    evas_object_smart_callback_add(li, "expanded", _on_list_expanded, obj);
1175    evas_object_smart_callback_add(li, "contracted", _on_list_contracted, obj);
1176
1177    elm_widget_sub_object_add(obj, li);
1178
1179    return li;
1180 }
1181
1182 static Evas_Object *
1183 _files_grid_add(Evas_Object *obj)
1184 {
1185    Evas_Object *grid;
1186
1187    ELM_FILESELECTOR_DATA_GET(obj, sd);
1188
1189    grid = elm_gengrid_add(obj);
1190    evas_object_data_set(grid, "parent", obj);
1191    elm_widget_mirrored_automatic_set(grid, EINA_FALSE);
1192    evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
1193    evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1194
1195    elm_gengrid_item_size_set(grid, sd->thumbnail_size.w + GENGRID_PADDING, sd->thumbnail_size.h + GENGRID_PADDING);
1196
1197    elm_gengrid_align_set(grid, 0.0, 0.0);
1198
1199    evas_object_smart_callback_add(grid, "selected", _on_item_selected, obj);
1200    evas_object_smart_callback_add(grid, "unselected", _on_item_unselected, obj);
1201    evas_object_smart_callback_add(grid, "activated", _on_item_activated, obj);
1202
1203    elm_widget_sub_object_add(obj, grid);
1204
1205    return grid;
1206 }
1207
1208 static Eina_Bool
1209 _resource_created(void *data, int type, void *ev)
1210 {
1211    Evas_Object *obj = data;
1212    Eio_Monitor_Event *event = ev;
1213    int itcn = ELM_FILE_UNKNOW;
1214    Eina_Bool dir = EINA_FALSE;
1215
1216    ELM_FILESELECTOR_DATA_GET(obj, sd);
1217
1218    if (type == EIO_MONITOR_DIRECTORY_CREATED)
1219      dir = EINA_TRUE;
1220
1221    Elm_Fileselector_Filter *cf = sd->current_filter;
1222    if (cf)
1223      {
1224         switch (cf->filter_type)
1225           {
1226            case ELM_FILESELECTOR_MIME_FILTER:
1227               if (!dir && !_check_mime_type_filter(cf, event->filename))
1228                 return ECORE_CALLBACK_PASS_ON;
1229               break;
1230            case ELM_FILESELECTOR_CUSTOM_FILTER:
1231               if (!cf->filter.custom->func(event->filename, dir, cf->filter.custom->data))
1232                 return ECORE_CALLBACK_PASS_ON;
1233               break;
1234            default:
1235               break;
1236           }
1237      }
1238
1239    if (dir)
1240      itcn = ELM_DIRECTORY;
1241    else
1242      {
1243         if (evas_object_image_extension_can_load_get(event->filename))
1244           itcn = ELM_FILE_IMAGE;
1245      }
1246
1247    if (sd->mode == ELM_FILESELECTOR_LIST)
1248      elm_genlist_item_sorted_insert(sd->files_view, list_itc[itcn],
1249                                     eina_stringshare_add(event->filename),
1250                                     NULL,
1251                                     (sd->expand && itcn == ELM_DIRECTORY)
1252                                     ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
1253                                     _file_list_cmp, NULL, NULL);
1254    else
1255      elm_gengrid_item_sorted_insert(sd->files_view, grid_itc[itcn],
1256                                     eina_stringshare_add(event->filename),
1257                                     _file_grid_cmp, NULL, NULL);
1258
1259    return ECORE_CALLBACK_PASS_ON;
1260 }
1261
1262 static Eina_Bool
1263 _resource_deleted(void *data, int type EINA_UNUSED, void *ev)
1264 {
1265    Evas_Object *obj = data;
1266    Eio_Monitor_Event *event = ev;
1267    Elm_Object_Item *it = NULL;
1268    Eina_Bool selected = EINA_FALSE;
1269
1270    ELM_FILESELECTOR_DATA_GET(obj, sd);
1271
1272    if (sd->mode == ELM_FILESELECTOR_LIST)
1273      {
1274         it = elm_genlist_first_item_get(sd->files_view);
1275         while(it)
1276           {
1277              if (!strcmp(elm_object_item_data_get(it), event->filename))
1278                {
1279                   selected = elm_genlist_item_selected_get(it);
1280                   break;
1281                }
1282              it = elm_genlist_item_next_get(it);
1283           }
1284      }
1285    else
1286      {
1287         it = elm_gengrid_first_item_get(sd->files_view);
1288         while(it)
1289           {
1290              if (!strcmp(elm_object_item_data_get(it), event->filename))
1291                {
1292                   selected = elm_genlist_item_selected_get(it);
1293                   break;
1294                }
1295              it = elm_gengrid_item_next_get(it);
1296           }
1297      }
1298
1299    if (it) elm_object_item_del(it);
1300
1301    if (selected)
1302      {
1303         if (sd->multi)
1304           {
1305              Eina_List *li, *l;
1306              char *path;
1307              Eina_Strbuf *buf;
1308              Eina_Bool first = EINA_TRUE;
1309
1310              buf = eina_strbuf_new();
1311              EINA_LIST_FOREACH_SAFE(sd->paths, li, l, path)
1312                {
1313                   if (!strcmp(path, event->filename))
1314                     {
1315                        sd->paths = eina_list_remove_list(sd->paths, li);
1316                        free(path);
1317                     }
1318                   else
1319                     {
1320                        if (!first)
1321                          eina_strbuf_append_length(buf, ", ", 2);
1322                        else
1323                          first = EINA_FALSE;
1324
1325                        eina_strbuf_append(buf, ecore_file_file_get(path));
1326                     }
1327                }
1328
1329              elm_object_text_set(sd->name_entry, eina_strbuf_string_get(buf));
1330              eina_strbuf_free(buf);
1331           }
1332         else
1333           elm_object_text_set(sd->name_entry, "");
1334      }
1335
1336    return ECORE_CALLBACK_PASS_ON;
1337 }
1338
1339 static void
1340 _name_entry_activated_cb(void *data, Evas_Object *obj EINA_UNUSED,
1341                          void *event_info EINA_UNUSED)
1342 {
1343    _ok(data, NULL, NULL);
1344 }
1345
1346 EOLIAN static void
1347 _elc_fileselector_evas_smart_add(Eo *obj, Elc_Fileselector_Data *priv)
1348 {
1349    Evas_Object *ic, *bt, *en, *pb;
1350
1351    EINA_REFCOUNT_INIT(priv);
1352
1353    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1354    elm_widget_sub_object_parent_add(obj);
1355    elm_widget_can_focus_set(obj, EINA_TRUE);
1356
1357    priv->expand = !!_elm_config->fileselector_expand_enable;
1358    priv->double_tap_navigation = !!_elm_config->fileselector_double_tap_navigation_enable;
1359
1360    if (!elm_layout_theme_set
1361        (obj, "fileselector", "base", elm_widget_style_get(obj)))
1362      CRI("Failed to set layout!");
1363
1364    // up btn
1365    ic = elm_icon_add(obj);
1366    elm_icon_standard_set(ic, "arrow_up");
1367    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1368    bt = elm_button_add(obj);
1369    elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1370    elm_object_part_content_set(bt, "icon", ic);
1371    elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
1372    evas_object_size_hint_align_set(bt, 0.0, 0.0);
1373    evas_object_smart_callback_add(bt, "clicked", _on_dir_up, obj);
1374
1375    elm_widget_sub_object_add(obj, bt);
1376
1377    priv->up_button = bt;
1378
1379    // home btn
1380    ic = elm_icon_add(obj);
1381    elm_icon_standard_set(ic, "home");
1382    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1383    bt = elm_button_add(obj);
1384    elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1385    elm_object_part_content_set(bt, "icon", ic);
1386    elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
1387    evas_object_size_hint_align_set(bt, 0.0, 0.0);
1388    evas_object_smart_callback_add(bt, "clicked", _home, obj);
1389
1390    elm_widget_sub_object_add(obj, bt);
1391    priv->home_button = bt;
1392
1393    // spinner
1394    pb = elm_progressbar_add(obj);
1395    elm_widget_sub_object_add(obj, pb);
1396    priv->spinner = pb;
1397
1398    // XXX: will fail for dynamic finger size changing
1399    priv->thumbnail_size.w = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
1400    priv->thumbnail_size.h = priv->thumbnail_size.w;
1401
1402    priv->sort_type = ELM_FILESELECTOR_SORT_BY_FILENAME_ASC;
1403    priv->sort_method = strcoll;
1404
1405    // files_view
1406    priv->files_view = _files_list_add(obj);
1407
1408    // path entry
1409    en = elm_entry_add(obj);
1410    elm_entry_scrollable_set(en, EINA_TRUE);
1411    elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1412    elm_entry_single_line_set(en, EINA_TRUE);
1413    elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
1414    evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1415    evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
1416
1417    evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
1418    evas_object_smart_callback_add(en, "clicked", _on_text_clicked, obj);
1419    evas_object_smart_callback_add(en, "unfocused", _on_text_unfocused, obj);
1420    evas_object_smart_callback_add(en, "activated", _on_text_activated, obj);
1421
1422    elm_widget_sub_object_add(obj, en);
1423    priv->path_entry = en;
1424
1425    // name entry
1426    en = elm_entry_add(obj);
1427    elm_entry_scrollable_set(en, EINA_TRUE);
1428    elm_widget_mirrored_automatic_set(en, EINA_FALSE);
1429    elm_entry_editable_set(en, EINA_TRUE);
1430    elm_entry_single_line_set(en, EINA_TRUE);
1431    elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
1432    evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1433    evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
1434    evas_object_smart_callback_add(en, "activated",
1435                                   _name_entry_activated_cb, obj);
1436
1437    elm_widget_sub_object_add(obj, en);
1438    priv->name_entry = en;
1439
1440    elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
1441    elm_fileselector_is_save_set(obj, EINA_FALSE);
1442
1443 #define HANDLER_ADD(e, fn) \
1444    priv->handlers = eina_list_append(priv->handlers, \
1445                                      ecore_event_handler_add(e, fn, obj));
1446
1447    HANDLER_ADD(EIO_MONITOR_FILE_CREATED, _resource_created);
1448    HANDLER_ADD(EIO_MONITOR_DIRECTORY_CREATED, _resource_created);
1449
1450    HANDLER_ADD(EIO_MONITOR_FILE_DELETED, _resource_deleted);
1451    HANDLER_ADD(EIO_MONITOR_DIRECTORY_DELETED, _resource_deleted);
1452 #undef HANDLER_ADD
1453
1454    eo_do(obj, elm_obj_widget_theme_apply());
1455 }
1456
1457 EOLIAN static void
1458 _elc_fileselector_evas_smart_del(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1459 {
1460    Elm_Fileselector_Filter *filter;
1461    char *path;
1462    Ecore_Event_Handler *h;
1463
1464    if (sd->monitor) eio_monitor_del(sd->monitor);
1465    if (sd->current) eio_file_cancel(sd->current);
1466
1467    EINA_LIST_FREE(sd->handlers, h)
1468      {
1469         ecore_event_handler_del(h);
1470      }
1471
1472    EINA_LIST_FREE(sd->filter_list, filter)
1473      {
1474         eina_stringshare_del(filter->filter_name);
1475
1476         if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
1477           {
1478              free(filter->filter.mime_types[0]);
1479              free(filter->filter.mime_types);
1480           }
1481         else
1482           free(filter->filter.custom);
1483
1484         free(filter);
1485      }
1486
1487    EINA_LIST_FREE(sd->paths, path)
1488      free(path);
1489
1490    sd->files_view = NULL;
1491
1492    /* this one matching EINA_REFCOUNT_INIT() */
1493    EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd);
1494 }
1495
1496 EAPI Evas_Object *
1497 elm_fileselector_add(Evas_Object *parent)
1498 {
1499    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1500    Evas_Object *obj = eo_add(MY_CLASS, parent);
1501    eo_unref(obj);
1502    return obj;
1503 }
1504
1505 EOLIAN static void
1506 _elc_fileselector_eo_base_constructor(Eo *obj, Elc_Fileselector_Data *sd)
1507 {
1508    sd->obj = obj;
1509    eo_do_super(obj, MY_CLASS, eo_constructor());
1510    eo_do(obj,
1511          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1512          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks));
1513 }
1514
1515 EAPI void
1516 elm_fileselector_is_save_set(Evas_Object *obj,
1517                              Eina_Bool is_save)
1518 {
1519    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1520    eo_do(obj, elm_interface_fileselector_is_save_set(is_save));
1521 }
1522
1523 EOLIAN static void
1524 _elc_fileselector_elm_interface_fileselector_is_save_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool is_save)
1525 {
1526    elm_object_disabled_set(sd->name_entry, !is_save);
1527
1528    if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm");
1529    else elm_layout_signal_emit(obj, "elm,state,save,off", "elm");
1530 }
1531
1532 EAPI Eina_Bool
1533 elm_fileselector_is_save_get(const Evas_Object *obj)
1534 {
1535    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1536    Eina_Bool ret = EINA_FALSE;
1537    eo_do((Eo *) obj, ret = elm_interface_fileselector_is_save_get());
1538    return ret;
1539 }
1540
1541 EOLIAN static Eina_Bool
1542 _elc_fileselector_elm_interface_fileselector_is_save_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1543 {
1544    return !elm_object_disabled_get(sd->name_entry);
1545 }
1546
1547 EAPI void
1548 elm_fileselector_folder_only_set(Evas_Object *obj,
1549                                  Eina_Bool only)
1550 {
1551    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1552    eo_do(obj, elm_interface_fileselector_folder_only_set(only));
1553 }
1554
1555 EOLIAN static void
1556 _elc_fileselector_elm_interface_fileselector_folder_only_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool only)
1557 {
1558    if (sd->only_folder == only) return;
1559
1560    sd->only_folder = !!only;
1561    if (sd->path) _populate(obj, sd->path, NULL, NULL);
1562 }
1563
1564 EAPI Eina_Bool
1565 elm_fileselector_folder_only_get(const Evas_Object *obj)
1566 {
1567    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1568    Eina_Bool ret = EINA_FALSE;
1569    eo_do((Eo *) obj, ret = elm_interface_fileselector_folder_only_get());
1570    return ret;
1571 }
1572
1573 EOLIAN static Eina_Bool
1574 _elc_fileselector_elm_interface_fileselector_folder_only_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1575 {
1576    return sd->only_folder;
1577 }
1578
1579 EOLIAN static void
1580 _elc_fileselector_buttons_ok_cancel_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool visible)
1581 {
1582    Evas_Object *bt;
1583
1584    if (visible && (!sd->ok_button))
1585      {
1586         // cancel btn
1587         bt = elm_button_add(obj);
1588         elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1589         elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
1590
1591         evas_object_smart_callback_add(bt, "clicked", _canc, obj);
1592
1593         sd->cancel_button = bt;
1594
1595         // ok btn
1596         bt = elm_button_add(obj);
1597         elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1598         elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
1599
1600         evas_object_smart_callback_add(bt, "clicked", _ok, obj);
1601
1602         sd->ok_button = bt;
1603
1604         eo_do(obj, elm_obj_widget_theme_apply());
1605      }
1606    else if (!visible)
1607      {
1608         ELM_SAFE_FREE(sd->cancel_button, evas_object_del);
1609         ELM_SAFE_FREE(sd->ok_button, evas_object_del);
1610      }
1611 }
1612
1613 EOLIAN static Eina_Bool
1614 _elc_fileselector_buttons_ok_cancel_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1615 {
1616    return sd->ok_button ? EINA_TRUE : EINA_FALSE;
1617 }
1618
1619 EAPI void
1620 elm_fileselector_expandable_set(Evas_Object *obj,
1621                                 Eina_Bool expand)
1622 {
1623    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1624    eo_do(obj, elm_interface_fileselector_expandable_set(expand));
1625 }
1626
1627 EOLIAN static void
1628 _elc_fileselector_elm_interface_fileselector_expandable_set(Eo *obj, Elc_Fileselector_Data *sd, Eina_Bool expand)
1629 {
1630    sd->expand = !!expand;
1631
1632    if (sd->path) _populate(obj, sd->path, NULL, NULL);
1633 }
1634
1635 EAPI Eina_Bool
1636 elm_fileselector_expandable_get(const Evas_Object *obj)
1637 {
1638    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1639    Eina_Bool ret = EINA_FALSE;
1640    eo_do((Eo *) obj, ret = elm_interface_fileselector_expandable_get());
1641    return ret;
1642 }
1643
1644 EOLIAN static Eina_Bool
1645 _elc_fileselector_elm_interface_fileselector_expandable_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1646 {
1647    return sd->expand;
1648 }
1649
1650 EAPI void
1651 elm_fileselector_path_set(Evas_Object *obj,
1652                           const char *_path)
1653 {
1654    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1655    eo_do(obj, elm_interface_fileselector_path_set(_path));
1656 }
1657
1658 EOLIAN static void
1659 _elc_fileselector_elm_interface_fileselector_path_set(Eo *obj, Elc_Fileselector_Data *sd EINA_UNUSED, const char *_path)
1660 {
1661    char *path;
1662
1663    path = ecore_file_realpath(_path);
1664    _populate(obj, path, NULL, NULL);
1665    free(path);
1666 }
1667
1668 EAPI const char *
1669 elm_fileselector_path_get(const Evas_Object *obj)
1670 {
1671    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1672    const char *ret = NULL;
1673    eo_do((Eo *) obj, ret = elm_interface_fileselector_path_get());
1674    return ret;
1675 }
1676
1677 EOLIAN static const char*
1678 _elc_fileselector_elm_interface_fileselector_path_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1679 {
1680    return sd->path;
1681 }
1682
1683 EAPI void
1684 elm_fileselector_mode_set(Evas_Object *obj,
1685                           Elm_Fileselector_Mode mode)
1686 {
1687    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1688    eo_do(obj, elm_interface_fileselector_mode_set(mode));
1689 }
1690
1691 EOLIAN static void
1692 _elc_fileselector_elm_interface_fileselector_mode_set(Eo *obj, Elc_Fileselector_Data *sd, Elm_Fileselector_Mode mode)
1693 {
1694    Evas_Object *old;
1695
1696    if (mode == sd->mode) return;
1697
1698    old = elm_layout_content_unset(obj, "elm.swallow.files");
1699
1700    if (mode == ELM_FILESELECTOR_LIST)
1701      {
1702         sd->files_view = _files_list_add(obj);
1703         if (sd->multi)
1704           elm_genlist_multi_select_set(sd->files_view, EINA_TRUE);
1705      }
1706    else
1707      {
1708         sd->files_view = _files_grid_add(obj);
1709         if (sd->multi)
1710           elm_gengrid_multi_select_set(sd->files_view, EINA_TRUE);
1711      }
1712
1713    elm_layout_content_set(obj, "elm.swallow.files", sd->files_view);
1714
1715    evas_object_del(old);
1716
1717    sd->mode = mode;
1718
1719    _populate(obj, sd->path, NULL, NULL);
1720 }
1721
1722 EAPI Elm_Fileselector_Mode
1723 elm_fileselector_mode_get(const Evas_Object *obj)
1724 {
1725    ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_LAST);
1726    Elm_Fileselector_Mode ret = ELM_FILESELECTOR_LAST;
1727    eo_do((Eo *) obj, ret = elm_interface_fileselector_mode_get());
1728    return ret;
1729 }
1730
1731 EOLIAN static Elm_Fileselector_Mode
1732 _elc_fileselector_elm_interface_fileselector_mode_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1733 {
1734    return sd->mode;
1735 }
1736
1737 EAPI void
1738 elm_fileselector_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1739 {
1740    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1741    eo_do(obj, elm_interface_fileselector_multi_select_set(multi));
1742 }
1743
1744 EOLIAN static void
1745 _elc_fileselector_elm_interface_fileselector_multi_select_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool multi)
1746 {
1747    char *path;
1748
1749    multi = !!multi;
1750    if (sd->multi == multi) return;
1751    sd->multi = multi;
1752
1753    if (sd->mode == ELM_FILESELECTOR_LIST)
1754      elm_genlist_multi_select_set(sd->files_view, multi);
1755    else
1756      elm_gengrid_multi_select_set(sd->files_view, multi);
1757
1758    if (!sd->multi)
1759      {
1760         _clear_selections(sd, NULL);
1761
1762         EINA_LIST_FREE(sd->paths, path)
1763           free(path);
1764      }
1765    else
1766      {
1767         const Eina_List *selected_items, *li;
1768         const Elm_Object_Item *it;
1769
1770         if (sd->mode == ELM_FILESELECTOR_LIST)
1771           selected_items = elm_genlist_selected_items_get(sd->files_view);
1772         else
1773           selected_items = elm_gengrid_selected_items_get(sd->files_view);
1774
1775         EINA_LIST_FOREACH(selected_items, li, it)
1776           {
1777              path = elm_object_item_data_get(it);
1778              sd->paths = eina_list_append(sd->paths, strdup(path));
1779           }
1780      }
1781 }
1782
1783 EAPI Eina_Bool
1784 elm_fileselector_multi_select_get(const Evas_Object *obj)
1785 {
1786    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1787    Eina_Bool ret = EINA_FALSE;
1788    eo_do((Eo *) obj, ret = elm_interface_fileselector_multi_select_get());
1789    return ret;
1790 }
1791
1792 EOLIAN static Eina_Bool
1793 _elc_fileselector_elm_interface_fileselector_multi_select_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1794 {
1795    return sd->multi;
1796 }
1797
1798 EAPI const char *
1799 elm_fileselector_selected_get(const Evas_Object *obj)
1800 {
1801    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1802    const char *ret = NULL;
1803    eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_get());
1804    return ret;
1805 }
1806
1807 EOLIAN static const char*
1808 _elc_fileselector_elm_interface_fileselector_selected_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1809 {
1810    const char *fp;
1811    if (!sd->path) return NULL;
1812
1813    fp = elm_object_text_get(sd->path_entry);
1814    if (ecore_file_exists(fp))
1815      {
1816         eina_stringshare_replace(&sd->selection, fp);
1817
1818         return sd->selection;
1819      }
1820
1821    if (sd->mode == ELM_FILESELECTOR_LIST)
1822      {
1823         Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_view);
1824
1825         if (gl_it) return elm_object_item_data_get(gl_it);
1826      }
1827    else
1828      {
1829         Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_view);
1830
1831         if (gg_it) return elm_object_item_data_get(gg_it);
1832      }
1833
1834
1835    return sd->path;
1836 }
1837
1838 EAPI Eina_Bool
1839 elm_fileselector_selected_set(Evas_Object *obj,
1840                               const char *_path)
1841 {
1842    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1843    Eina_Bool ret = EINA_FALSE;
1844    eo_do(obj, ret = elm_interface_fileselector_selected_set(_path));
1845    return ret;
1846 }
1847
1848 EOLIAN static Eina_Bool
1849 _elc_fileselector_elm_interface_fileselector_selected_set(Eo *obj, Elc_Fileselector_Data *sd, const char *_path)
1850 {
1851    Eina_Bool ret = EINA_TRUE;
1852    char *selected;
1853    char *path;
1854
1855    path = ecore_file_realpath(_path);
1856
1857    if (ecore_file_is_dir(path)) _populate(obj, path, NULL, NULL);
1858    else
1859      {
1860         if (!ecore_file_exists(path))
1861           {
1862              ret = EINA_FALSE;
1863              goto clean_up;
1864           }
1865
1866         selected = ecore_file_dir_get(path);
1867         _populate(obj, selected, NULL, NULL);
1868         eina_stringshare_replace(&sd->selection, path);
1869         free(selected);
1870      }
1871
1872 clean_up:
1873    free(path);
1874
1875    return ret;
1876 }
1877
1878 EAPI const Eina_List *
1879 elm_fileselector_selected_paths_get(const Evas_Object* obj)
1880 {
1881    ELM_FILESELECTOR_INTERFACE_CHECK(obj, NULL);
1882    const Eina_List *ret = NULL;
1883    eo_do((Eo *) obj, ret = elm_interface_fileselector_selected_paths_get());
1884    return ret;
1885 }
1886
1887 EOLIAN static const Eina_List*
1888 _elc_fileselector_elm_interface_fileselector_selected_paths_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
1889 {
1890    if (sd->multi)
1891      return sd->paths;
1892    else
1893      return NULL;
1894 }
1895
1896 static Elm_Fileselector_Filter *
1897 _filter_add(Elc_Fileselector_Data *sd, const char *filter_name)
1898 {
1899    Elm_Fileselector_Filter *ff;
1900    ff = malloc(sizeof(Elm_Fileselector_Filter));
1901
1902    ff->filter_name = eina_stringshare_add(filter_name);
1903    ff->sd = sd;
1904
1905    return ff;
1906 }
1907
1908 EAPI Eina_Bool
1909 elm_fileselector_mime_types_filter_append(Evas_Object *obj, const char *mime_type, const char *filter_name)
1910 {
1911    ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1912    Eina_Bool ret = EINA_FALSE;
1913    eo_do(obj, ret = elm_interface_fileselector_mime_types_filter_append(mime_type, filter_name));
1914    return ret;
1915 }
1916
1917 EOLIAN static Eina_Bool
1918 _elc_fileselector_elm_interface_fileselector_mime_types_filter_append(Eo *obj, Elc_Fileselector_Data *sd, const char *mime_types, const char *filter_name)
1919 {
1920    Elm_Fileselector_Filter *ff;
1921    Eina_Bool need_theme = EINA_FALSE;
1922
1923    if (!mime_types) return EINA_FALSE;
1924
1925    ff = _filter_add(sd, filter_name ? filter_name : mime_types);
1926    ff->filter_type = ELM_FILESELECTOR_MIME_FILTER;
1927
1928    ff->filter.mime_types = eina_str_split(mime_types, ",", 0);
1929
1930    if (!sd->filter_list)
1931      {
1932         sd->current_filter = ff;
1933         sd->filter_hoversel = elm_hoversel_add(obj);
1934         elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1935         need_theme = EINA_TRUE;
1936      }
1937    elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1938
1939    sd->filter_list = eina_list_append(sd->filter_list, ff);
1940
1941    _populate(obj, sd->path, NULL, NULL);
1942
1943    if (need_theme)
1944      eo_do(obj, elm_obj_widget_theme_apply());
1945
1946    return EINA_TRUE;
1947 }
1948
1949 EAPI Eina_Bool
1950 elm_fileselector_custom_filter_append(Evas_Object *obj, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
1951 {
1952    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
1953    Eina_Bool ret = EINA_FALSE;
1954    eo_do(obj, ret = elm_interface_fileselector_custom_filter_append(func, data, filter_name));
1955    return ret;
1956 }
1957
1958 EOLIAN static Eina_Bool
1959 _elc_fileselector_elm_interface_fileselector_custom_filter_append(Eo *obj, Elc_Fileselector_Data *sd, Elm_Fileselector_Filter_Func func, void *data, const char *filter_name)
1960 {
1961    Elm_Fileselector_Filter *ff;
1962    Eina_Bool need_theme = EINA_FALSE;
1963
1964    if (!func) return EINA_FALSE;
1965
1966    ff = _filter_add(sd, filter_name ? filter_name : "custom");
1967    ff->filter_type = ELM_FILESELECTOR_CUSTOM_FILTER;
1968
1969    ff->filter.custom = malloc(sizeof(Elm_Fileselector_Custom_Filter));
1970    ff->filter.custom->func = func;
1971    ff->filter.custom->data = data;
1972
1973    if (!sd->filter_list)
1974      {
1975         sd->current_filter = ff;
1976         sd->filter_hoversel = elm_hoversel_add(obj);
1977         elm_object_text_set(sd->filter_hoversel, ff->filter_name);
1978         need_theme = EINA_TRUE;
1979      }
1980    elm_hoversel_item_add(sd->filter_hoversel, ff->filter_name, NULL, ELM_ICON_NONE, _current_filter_changed, ff);
1981
1982    sd->filter_list = eina_list_append(sd->filter_list, ff);
1983
1984    _populate(obj, sd->path, NULL, NULL);
1985
1986    if (need_theme)
1987      eo_do(obj, elm_obj_widget_theme_apply());
1988
1989    return EINA_TRUE;
1990 }
1991
1992 EAPI void
1993 elm_fileselector_filters_clear(Evas_Object *obj)
1994 {
1995    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
1996    eo_do(obj, elm_interface_fileselector_filters_clear());
1997 }
1998
1999 EOLIAN static void
2000 _elc_fileselector_elm_interface_fileselector_filters_clear(Eo *obj, Elc_Fileselector_Data *sd)
2001 {
2002    Elm_Fileselector_Filter *filter;
2003
2004    EINA_LIST_FREE(sd->filter_list, filter)
2005      {
2006         eina_stringshare_del(filter->filter_name);
2007
2008         if (filter->filter_type == ELM_FILESELECTOR_MIME_FILTER)
2009           {
2010              free(filter->filter.mime_types[0]);
2011              free(filter->filter.mime_types);
2012           }
2013         else
2014           free(filter->filter.custom);
2015
2016         free(filter);
2017      }
2018
2019    ELM_SAFE_FREE(sd->filter_hoversel, evas_object_del);
2020
2021    _populate(obj, sd->path, NULL, NULL);
2022 }
2023
2024 EAPI void
2025 elm_fileselector_hidden_visible_set(Evas_Object *obj, Eina_Bool visible)
2026 {
2027    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2028    eo_do(obj, elm_interface_fileselector_hidden_visible_set(visible));
2029 }
2030
2031 EOLIAN static void
2032 _elc_fileselector_elm_interface_fileselector_hidden_visible_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Eina_Bool visible)
2033 {
2034    visible = !!visible;
2035    if (sd->hidden_visible == visible) return;
2036    sd->hidden_visible = visible;
2037
2038    _clear_selections(sd, NULL);
2039    _populate(obj, sd->path, NULL, NULL);
2040 }
2041
2042 EAPI Eina_Bool
2043 elm_fileselector_hidden_visible_get(const Evas_Object *obj)
2044 {
2045    ELM_FILESELECTOR_INTERFACE_CHECK(obj, EINA_FALSE);
2046    Eina_Bool ret = EINA_FALSE;
2047    eo_do((Eo *) obj, ret = elm_interface_fileselector_hidden_visible_get());
2048    return ret;
2049 }
2050
2051 EOLIAN static Eina_Bool
2052 _elc_fileselector_elm_interface_fileselector_hidden_visible_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2053 {
2054    return sd->hidden_visible;
2055 }
2056
2057 EAPI void
2058 elm_fileselector_thumbnail_size_set(Evas_Object *obj,
2059                                     Evas_Coord w,
2060                                     Evas_Coord h)
2061 {
2062    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2063    eo_do(obj, elm_interface_fileselector_thumbnail_size_set(w, h));
2064 }
2065
2066 EOLIAN static void
2067 _elc_fileselector_elm_interface_fileselector_thumbnail_size_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord w, Evas_Coord h)
2068 {
2069    if (sd->thumbnail_size.w == w && sd->thumbnail_size.h == h) return;
2070
2071    if (!w || !h)
2072      w = h = elm_config_finger_size_get() * 2 - GENGRID_PADDING;
2073
2074    sd->thumbnail_size.w = w;
2075    sd->thumbnail_size.h = h;
2076
2077    if (sd->mode == ELM_FILESELECTOR_GRID)
2078      elm_gengrid_item_size_set(sd->files_view, w + GENGRID_PADDING, h + GENGRID_PADDING);
2079
2080    _populate(obj, sd->path, NULL, NULL);
2081 }
2082
2083 EAPI void
2084 elm_fileselector_thumbnail_size_get(const Evas_Object *obj,
2085                                     Evas_Coord *w,
2086                                     Evas_Coord *h)
2087 {
2088    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2089    eo_do((Eo *) obj, elm_interface_fileselector_thumbnail_size_get(w, h));
2090 }
2091
2092 EOLIAN static void
2093 _elc_fileselector_elm_interface_fileselector_thumbnail_size_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Evas_Coord *w, Evas_Coord *h)
2094 {
2095    if (w) *w = sd->thumbnail_size.w;
2096    if (h) *h = sd->thumbnail_size.h;
2097 }
2098
2099 EAPI void
2100 elm_fileselector_sort_method_set(Evas_Object *obj, Elm_Fileselector_Sort sort)
2101 {
2102    ELM_FILESELECTOR_INTERFACE_CHECK(obj);
2103    eo_do(obj, elm_interface_fileselector_sort_method_set(sort));
2104 }
2105
2106 EOLIAN static void
2107 _elc_fileselector_elm_interface_fileselector_sort_method_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, Elm_Fileselector_Sort sort)
2108 {
2109    if (sd->sort_type == sort) return;
2110    sd->sort_type = sort;
2111
2112    switch (sd->sort_type)
2113      {
2114       case ELM_FILESELECTOR_SORT_BY_FILENAME_ASC:
2115          sd->sort_method = strcoll;
2116          break;
2117       case ELM_FILESELECTOR_SORT_BY_FILENAME_DESC:
2118          sd->sort_method = _strcoll_rev;
2119          break;
2120       case ELM_FILESELECTOR_SORT_BY_TYPE_ASC:
2121          sd->sort_method = _strcoll_type;
2122          break;
2123       case ELM_FILESELECTOR_SORT_BY_TYPE_DESC:
2124          sd->sort_method = _strcoll_type_rev;
2125          break;
2126       case ELM_FILESELECTOR_SORT_BY_SIZE_ASC:
2127          sd->sort_method = _size_cmp;
2128          break;
2129       case ELM_FILESELECTOR_SORT_BY_SIZE_DESC:
2130          sd->sort_method = _size_cmp_rev;
2131          break;
2132       case ELM_FILESELECTOR_SORT_BY_MODIFIED_ASC:
2133          sd->sort_method = _modified_cmp;
2134          break;
2135       case ELM_FILESELECTOR_SORT_BY_MODIFIED_DESC:
2136          sd->sort_method = _modified_cmp_rev;
2137          break;
2138       case ELM_FILESELECTOR_SORT_LAST:
2139       default:
2140          sd->sort_method = strcoll;
2141      }
2142
2143    _populate(obj, sd->path, NULL, NULL);
2144 }
2145
2146 EAPI Elm_Fileselector_Sort
2147 elm_fileselector_sort_method_get(const Evas_Object *obj)
2148 {
2149    ELM_FILESELECTOR_INTERFACE_CHECK(obj, ELM_FILESELECTOR_SORT_LAST);
2150    Elm_Fileselector_Sort ret = ELM_FILESELECTOR_SORT_LAST;
2151    eo_do((Eo *) obj, ret = elm_interface_fileselector_sort_method_get());
2152
2153    return ret;
2154 }
2155
2156 EOLIAN static Elm_Fileselector_Sort
2157 _elc_fileselector_elm_interface_fileselector_sort_method_get(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd)
2158 {
2159    return sd->sort_type;
2160 }
2161
2162 EOLIAN static Eina_Bool
2163 _elc_fileselector_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2164 {
2165    return EINA_FALSE;
2166 }
2167
2168 EOLIAN static Eina_Bool
2169 _elc_fileselector_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd EINA_UNUSED)
2170 {
2171    return EINA_FALSE;
2172 }
2173
2174 EOLIAN static Eina_Bool
2175 _elc_fileselector_elm_layout_text_set(Eo *obj EINA_UNUSED, Elc_Fileselector_Data *sd, const char *part, const char *label)
2176 {
2177    if (!part) return EINA_FALSE;
2178
2179    if (sd->ok_button && !strcmp(part, "ok"))
2180      {
2181         elm_object_text_set(sd->ok_button, label);
2182         return EINA_TRUE;
2183      }
2184    else if (sd->cancel_button && !strcmp(part, "cancel"))
2185      {
2186         elm_object_text_set(sd->cancel_button, label);
2187         return EINA_TRUE;
2188      }
2189    else
2190      {
2191         Eina_Bool int_ret = EINA_FALSE;
2192         eo_do_super(obj, MY_CLASS, int_ret = elm_obj_layout_text_set(part, label));
2193         return int_ret;
2194      }
2195
2196    return EINA_FALSE;
2197 }
2198
2199 EOLIAN static void
2200 _elc_fileselector_class_constructor(Eo_Class *klass)
2201 {
2202    unsigned int i;
2203
2204    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2205
2206    for (i = 0; i < ELM_FILE_LAST; ++i)
2207      {
2208         list_itc[i] = elm_genlist_item_class_new();
2209         grid_itc[i] = elm_gengrid_item_class_new();
2210
2211         list_itc[i]->item_style = "default";
2212         list_itc[i]->func.text_get = grid_itc[i]->func.text_get =
2213             _itc_text_get;
2214         list_itc[i]->func.state_get = grid_itc[i]->func.state_get =
2215             _itc_state_get;
2216         list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del;
2217      }
2218
2219    list_itc[ELM_DIRECTORY]->func.content_get =
2220      grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get;
2221    list_itc[ELM_FILE_IMAGE]->func.content_get =
2222      grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get;
2223    list_itc[ELM_FILE_UNKNOW]->func.content_get =
2224      grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get;
2225
2226 }
2227
2228 EOLIAN static void
2229 _elc_fileselector_class_destructor(Eo_Class *klass EINA_UNUSED)
2230 {
2231    unsigned int i;
2232
2233    for (i = 0; i < ELM_FILE_LAST; ++i)
2234      {
2235         elm_genlist_item_class_free(list_itc[i]);
2236         elm_gengrid_item_class_free(grid_itc[i]);
2237      }
2238 }
2239
2240 #include "elc_fileselector.eo.c"