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