3 * - child elements focusing support
4 * - user defined icon/label cb
5 * - show/hide/add buttons ???
6 * - show/hide hidden files
7 * - double click to choose a file
9 * - make variable/function names that are sensible
13 #include <Elementary.h>
15 #include "elm_widget_fileselector.h"
17 EAPI const char ELM_FILESELECTOR_SMART_NAME[] = "elm_fileselector";
19 static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST];
20 static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
22 static const char SIG_DIRECTORY_OPEN[] = "directory,open";
23 static const char SIG_DONE[] = "done";
24 static const char SIG_SELECTED[] = "selected";
25 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
26 {SIG_DIRECTORY_OPEN, "s"},
32 EVAS_SMART_SUBCLASS_NEW
33 (ELM_FILESELECTOR_SMART_NAME, _elm_fileselector,
34 Elm_Fileselector_Smart_Class, Elm_Layout_Smart_Class,
35 elm_layout_smart_class_get, _smart_callbacks);
37 /* final routine on deletion */
39 _elm_fileselector_smart_del_do(Elm_Fileselector_Smart_Data *sd)
41 if (sd->path) eina_stringshare_del(sd->path);
42 if (sd->selection) eina_stringshare_del(sd->selection);
43 if (sd->sel_idler) free(ecore_idler_del(sd->sel_idler));
45 ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->base.del
46 (ELM_WIDGET_DATA(sd)->obj);
50 _elm_fileselector_smart_sizing_eval(Evas_Object *obj)
52 Evas_Coord minw = -1, minh = -1;
54 ELM_FILESELECTOR_DATA_GET(obj, sd);
56 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
57 edje_object_size_min_restricted_calc
58 (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh);
59 evas_object_size_hint_min_set(obj, minw, minh);
63 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
65 ELM_FILESELECTOR_DATA_GET(obj, sd);
67 elm_widget_mirrored_set(sd->cancel_button, rtl);
68 elm_widget_mirrored_set(sd->ok_button, rtl);
69 elm_widget_mirrored_set(sd->files_list, rtl);
70 elm_widget_mirrored_set(sd->up_button, rtl);
71 elm_widget_mirrored_set(sd->home_button, rtl);
75 _elm_fileselector_smart_theme(Evas_Object *obj)
81 ELM_FILESELECTOR_DATA_GET(obj, sd);
83 if (!ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->theme(obj))
86 style = elm_widget_style_get(obj);
87 _mirrored_set(obj, elm_widget_mirrored_get(obj));
89 data = edje_object_data_get
90 (ELM_WIDGET_DATA(sd)->resize_obj, "path_separator");
91 if (data) sd->path_separator = data;
92 else sd->path_separator = "/";
94 snprintf(buf, sizeof(buf), "fileselector/%s", style);
96 #define SWALLOW(part_name, object_ptn) \
99 elm_widget_style_set(object_ptn, buf); \
100 if (!elm_layout_content_set(obj, part_name, object_ptn)) \
101 evas_object_hide(object_ptn); \
104 SWALLOW("elm.swallow.up", sd->up_button);
105 SWALLOW("elm.swallow.home", sd->home_button);
106 SWALLOW("elm.swallow.spinner", sd->spinner);
107 elm_object_style_set(sd->spinner, "wheel");
109 if (sd->mode == ELM_FILESELECTOR_LIST)
111 if (elm_layout_content_set(obj, "elm.swallow.files", sd->files_list))
112 evas_object_hide(sd->files_grid);
113 else evas_object_hide(sd->files_list);
117 if (elm_layout_content_set(obj, "elm.swallow.files", sd->files_grid))
118 evas_object_hide(sd->files_list);
119 else evas_object_hide(sd->files_grid);
122 SWALLOW("elm.swallow.filename", sd->filename_entry);
123 SWALLOW("elm.swallow.path", sd->path_entry);
125 snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
126 SWALLOW("elm.swallow.cancel", sd->cancel_button);
127 SWALLOW("elm.swallow.ok", sd->ok_button);
131 edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
133 elm_layout_sizing_eval(obj);
138 /*** GENLIST/GENGRID "MODEL" ***/
140 _itc_text_get(void *data,
141 Evas_Object *obj __UNUSED__,
142 const char *source __UNUSED__)
144 return elm_entry_utf8_to_markup
145 (ecore_file_file_get(data)); /* NOTE this will be free()'d by
150 _itc_icon_folder_get(void *data __UNUSED__,
156 if (strcmp(source, "elm.swallow.icon")) return NULL;
158 ic = elm_icon_add(obj);
159 elm_icon_standard_set(ic, "folder");
161 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
166 _itc_icon_image_get(void *data,
170 const char *filename = data;
173 if (strcmp(source, "elm.swallow.icon")) return NULL;
175 ic = elm_icon_add(obj);
176 elm_icon_standard_set(ic, "image");
177 elm_icon_thumb_set(ic, filename, NULL);
179 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
184 _itc_icon_file_get(void *data __UNUSED__,
190 if (strcmp(source, "elm.swallow.icon")) return NULL;
192 ic = elm_icon_add(obj);
193 elm_icon_standard_set(ic, "file");
195 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
200 _itc_state_get(void *data __UNUSED__,
201 Evas_Object *obj __UNUSED__,
202 const char *source __UNUSED__)
209 Evas_Object *obj __UNUSED__)
211 eina_stringshare_del(data);
215 _anchors_do(Evas_Object *obj,
218 char **tok, buf[PATH_MAX * 3], *s;
221 ELM_FILESELECTOR_DATA_GET(obj, sd);
223 s = elm_entry_utf8_to_markup(path);
227 tok = eina_str_split(s, "/", 0);
230 eina_strlcat(buf, "<a href=/>root</a>", sizeof(buf));
231 for (i = 0; tok[i]; i++)
233 if ((!tok[i]) || (!tok[i][0])) continue;
234 eina_strlcat(buf, sd->path_separator, sizeof(buf));
235 eina_strlcat(buf, "<a href=", sizeof(buf));
236 for (j = 0; j <= i; j++)
238 if (strlen(tok[j]) < 1) continue;
239 eina_strlcat(buf, "/", sizeof(buf));
240 eina_strlcat(buf, tok[j], sizeof(buf));
242 eina_strlcat(buf, ">", sizeof(buf));
243 eina_strlcat(buf, tok[i], sizeof(buf));
244 eina_strlcat(buf, "</a>", sizeof(buf));
249 elm_object_text_set(sd->path_entry, buf);
254 _ls_filter_cb(void *data,
255 Eio_File *handler __UNUSED__,
256 const Eina_File_Direct_Info *info)
258 Listing_Request *lreq = data;
260 if (info->path[info->name_start] == '.')
263 if (lreq->sd->only_folder && info->type != EINA_FILE_DIR)
270 _file_grid_cmp(const void *a,
273 const Elm_Object_Item *ga = a;
274 const Elm_Object_Item *gb = b;
275 const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga);
276 const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb);
278 if (ca == grid_itc[ELM_DIRECTORY])
280 if (cb != grid_itc[ELM_DIRECTORY])
283 else if (cb == grid_itc[ELM_DIRECTORY])
288 return strcoll(elm_object_item_data_get(ga), elm_object_item_data_get(gb));
292 _file_list_cmp(const void *a,
295 const Elm_Object_Item *la = a;
296 const Elm_Object_Item *lb = b;
297 const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la);
298 const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb);
300 if (ca == list_itc[ELM_DIRECTORY])
302 if (cb != list_itc[ELM_DIRECTORY])
305 else if (cb == list_itc[ELM_DIRECTORY])
310 return strcoll(elm_object_item_data_get(la), elm_object_item_data_get(lb));
314 _signal_first(Listing_Request *lreq)
316 if (!lreq->first) return;
318 evas_object_smart_callback_call
319 (lreq->obj, SIG_DIRECTORY_OPEN, (void *)lreq->path);
321 if (!lreq->parent_it)
323 elm_genlist_clear(lreq->sd->files_list);
324 elm_gengrid_clear(lreq->sd->files_grid);
325 eina_stringshare_replace(&lreq->sd->path, lreq->path);
326 _anchors_do(lreq->obj, lreq->path);
329 if (lreq->sd->filename_entry)
330 elm_object_text_set(lreq->sd->filename_entry, "");
332 lreq->first = EINA_FALSE;
336 _ls_main_cb(void *data,
338 const Eina_File_Direct_Info *info)
340 Listing_Request *lreq = data;
341 int itcn = ELM_FILE_UNKNOW;
343 if (eio_file_check(handler)) return;
345 if (!lreq->sd->files_list || !lreq->sd->files_grid
346 || lreq->sd->current != handler)
348 eio_file_cancel(handler);
354 if (info->type == EINA_FILE_DIR)
355 itcn = ELM_DIRECTORY;
358 if (evas_object_image_extension_can_load_get
359 (info->path + info->name_start))
360 itcn = ELM_FILE_IMAGE;
363 if (lreq->sd->mode == ELM_FILESELECTOR_LIST)
364 elm_genlist_item_sorted_insert(lreq->sd->files_list, list_itc[itcn],
365 eina_stringshare_add(info->path),
367 ((lreq->sd->expand) && (itcn == ELM_DIRECTORY))
368 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
369 _file_list_cmp, NULL, NULL);
370 else if (lreq->sd->mode == ELM_FILESELECTOR_GRID)
371 elm_gengrid_item_sorted_insert(lreq->sd->files_grid, grid_itc[itcn],
372 eina_stringshare_add(info->path),
373 _file_grid_cmp, NULL, NULL);
377 _listing_request_cleanup(Listing_Request *lreq)
379 EINA_REFCOUNT_UNREF(lreq->sd) _elm_fileselector_smart_del_do(lreq->sd);
381 eina_stringshare_del(lreq->path);
386 _ls_done_cb(void *data, Eio_File *handler __UNUSED__)
388 Listing_Request *lreq = data;
391 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
392 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
394 lreq->sd->current = NULL;
395 _listing_request_cleanup(lreq);
399 _ls_error_cb(void *data, Eio_File *handler, int error __UNUSED__)
401 Listing_Request *lreq = data;
403 elm_progressbar_pulse(lreq->sd->spinner, EINA_FALSE);
404 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,hide", "elm");
406 if (lreq->sd->current == handler)
407 lreq->sd->current = NULL;
408 _listing_request_cleanup(lreq);
414 _populate(Evas_Object *obj,
416 Elm_Object_Item *parent_it)
418 ELM_FILESELECTOR_DATA_GET(obj, sd);
421 Listing_Request *lreq;
423 Eina_List *files = NULL, *dirs = NULL;
424 Eina_File_Direct_Info *file;
429 #ifndef HAVE_EIO /* synchronous listing path */
430 if (!ecore_file_is_dir(path)) return;
432 it = eina_file_stat_ls(path);
435 evas_object_smart_callback_call(obj, SIG_DIRECTORY_OPEN, (void *)path);
438 elm_genlist_clear(sd->files_list);
439 elm_gengrid_clear(sd->files_grid);
440 eina_stringshare_replace(&sd->path, path);
441 _anchors_do(obj, path);
444 if (sd->filename_entry) elm_object_text_set(sd->filename_entry, "");
445 EINA_ITERATOR_FOREACH(it, file)
447 const char *filename;
449 if (file->path[file->name_start] == '.') continue;
451 filename = eina_stringshare_add(file->path);
452 if (file->type == EINA_FILE_DIR)
453 dirs = eina_list_append(dirs, filename);
454 else if (!sd->only_folder)
455 files = eina_list_append(files, filename);
457 eina_iterator_free(it);
459 files = eina_list_sort
460 (files, eina_list_count(files), EINA_COMPARE_CB(strcoll));
462 dirs = eina_list_sort
463 (dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll));
464 EINA_LIST_FREE (dirs, entry)
466 if (sd->mode == ELM_FILESELECTOR_LIST)
467 elm_genlist_item_append(sd->files_list, list_itc[ELM_DIRECTORY],
468 entry, /* item data */
471 ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
473 else if (sd->mode == ELM_FILESELECTOR_GRID)
474 elm_gengrid_item_append(sd->files_grid, grid_itc[ELM_DIRECTORY],
475 entry, /* item data */
479 EINA_LIST_FREE (files, entry)
481 Elm_Fileselector_Type type =
482 evas_object_image_extension_can_load_fast_get(entry) ?
483 ELM_FILE_IMAGE : ELM_FILE_UNKNOW;
485 if (sd->mode == ELM_FILESELECTOR_LIST)
486 elm_genlist_item_append(sd->files_list, list_itc[type],
487 entry, /* item data */
488 parent_it, ELM_GENLIST_ITEM_NONE,
490 else if (sd->mode == ELM_FILESELECTOR_GRID)
491 elm_gengrid_item_append(sd->files_grid, grid_itc[type],
492 entry, /* item data */
496 #else /* asynchronous listing path */
497 if (sd->expand && sd->current) return;
499 if (sd->current) eio_file_cancel(sd->current);
501 lreq = malloc(sizeof (Listing_Request));
505 EINA_REFCOUNT_REF(lreq->sd);
507 lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */
509 lreq->path = eina_stringshare_add(path);
510 lreq->first = EINA_TRUE;
512 sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb,
513 _ls_done_cb, _ls_error_cb, lreq);
514 elm_progressbar_pulse(sd->spinner, EINA_TRUE);
515 elm_layout_signal_emit(lreq->obj, "elm,action,spinner,show", "elm");
520 _on_list_expanded(void *data,
521 Evas_Object *obj __UNUSED__,
524 Elm_Object_Item *it = event_info;
525 const char *path = elm_object_item_data_get(it);
527 _populate(data, path, it);
531 _on_list_contracted(void *data __UNUSED__,
532 Evas_Object *obj __UNUSED__,
535 Elm_Object_Item *it = event_info;
537 elm_genlist_item_subitems_clear(it);
541 _on_list_expand_req(void *data __UNUSED__,
542 Evas_Object *obj __UNUSED__,
545 Elm_Object_Item *it = event_info;
547 elm_genlist_item_expanded_set(it, EINA_TRUE);
551 _on_list_contract_req(void *data __UNUSED__,
552 Evas_Object *obj __UNUSED__,
555 Elm_Object_Item *it = event_info;
557 elm_genlist_item_expanded_set(it, EINA_FALSE);
563 struct sel_data *sdata = data;
567 ELM_FILESELECTOR_DATA_GET(sdata->fs, sd);
570 if ((!sd->only_folder) && ecore_file_is_dir(path))
572 if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
574 _anchors_do(sdata->fs, path);
575 elm_object_text_set(sd->filename_entry, "");
579 /* keep a ref to path 'couse it will be destroyed by _populate */
580 p = eina_stringshare_add(path);
581 _populate(sdata->fs, p, NULL);
582 eina_stringshare_del(p);
586 else /* navigating through folders only or file is not a dir. */
590 if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST)
591 _anchors_do(sdata->fs, path);
592 else if (sd->only_folder)
594 /* keep a ref to path 'couse it will be destroyed by _populate */
595 p = eina_stringshare_add(path);
596 _populate(sdata->fs, p, NULL);
597 eina_stringshare_del(p);
600 s = elm_entry_utf8_to_markup(ecore_file_file_get(path));
603 elm_object_text_set(sd->filename_entry, s);
606 else elm_object_text_set(sd->filename_entry, "");
609 evas_object_smart_callback_call(sdata->fs, SIG_SELECTED, (void *)path);
612 sd->sel_idler = NULL;
614 return ECORE_CALLBACK_CANCEL;
618 _on_item_selected(void *data,
619 Evas_Object *obj __UNUSED__,
622 //This event_info could be a list or gengrid item
623 Elm_Object_Item *it = event_info;
624 struct sel_data *sdata;
628 ELM_FILESELECTOR_DATA_GET(data, sd);
630 sdata = malloc(sizeof(*sdata));
632 sdata->path = elm_object_item_data_get(it);
636 eina_stringshare_replace(&sd->path, "");
640 dir = sd->only_folder ? strdup(sdata->path) :
641 ecore_file_dir_get(sdata->path);
644 eina_stringshare_replace(&sd->path, dir);
649 eina_stringshare_replace(&sd->path, "");
655 old_sd = ecore_idler_del(sd->sel_idler);
658 sd->sel_idler = ecore_idler_add(_sel_do, sdata);
662 _on_dir_up(void *data,
663 Evas_Object *obj __UNUSED__,
664 void *event_info __UNUSED__)
666 Evas_Object *fs = data;
669 ELM_FILESELECTOR_DATA_GET(fs, sd);
671 parent = ecore_file_dir_get(sd->path);
672 _populate(fs, parent, NULL);
678 Evas_Object *obj __UNUSED__,
679 void *event_info __UNUSED__)
681 Evas_Object *fs = data;
683 _populate(fs, getenv("HOME"), NULL);
688 Evas_Object *obj __UNUSED__,
689 void *event_info __UNUSED__)
691 Evas_Object *fs = data;
693 evas_object_smart_callback_call
694 (fs, SIG_DONE, (void *)elm_fileselector_selected_get(fs));
699 Evas_Object *obj __UNUSED__,
700 void *event_info __UNUSED__)
702 Evas_Object *fs = data;
704 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
708 _anchor_clicked(void *data,
709 Evas_Object *obj __UNUSED__,
712 Elm_Entry_Anchor_Info *info = event_info;
713 Evas_Object *fs = data;
716 // keep a ref to path 'couse it will be destroyed by _populate
717 p = eina_stringshare_add(info->name);
718 _populate(fs, p, NULL);
719 evas_object_smart_callback_call(data, SIG_SELECTED, (void *)p);
720 eina_stringshare_del(p);
724 _elm_fileselector_smart_add(Evas_Object *obj)
726 Evas_Object *ic, *bt, *li, *en, *grid, *pb;
730 EVAS_SMART_DATA_ALLOC(obj, Elm_Fileselector_Smart_Data);
731 EINA_REFCOUNT_INIT(priv);
733 ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->base.add(obj);
735 elm_widget_can_focus_set(obj, EINA_FALSE);
737 priv->expand = !!_elm_config->fileselector_expand_enable;
740 (obj, "fileselector", "base", elm_widget_style_get(obj));
743 ic = elm_icon_add(obj);
744 elm_icon_standard_set(ic, "arrow_up");
745 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
746 bt = elm_button_add(obj);
747 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
748 elm_object_part_content_set(bt, "icon", ic);
749 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
750 evas_object_size_hint_align_set(bt, 0.0, 0.0);
751 evas_object_smart_callback_add(bt, "clicked", _on_dir_up, obj);
753 elm_widget_sub_object_add(obj, bt);
755 priv->up_button = bt;
758 ic = elm_icon_add(obj);
759 elm_icon_standard_set(ic, "home");
760 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
761 bt = elm_button_add(obj);
762 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
763 elm_object_part_content_set(bt, "icon", ic);
764 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
765 evas_object_size_hint_align_set(bt, 0.0, 0.0);
766 evas_object_smart_callback_add(bt, "clicked", _home, obj);
768 elm_widget_sub_object_add(obj, bt);
769 priv->home_button = bt;
772 pb = elm_progressbar_add(obj);
773 elm_widget_sub_object_add(obj, pb);
776 for (i = 0; i < ELM_FILE_LAST; ++i)
778 list_itc[i] = elm_genlist_item_class_new();
779 grid_itc[i] = elm_gengrid_item_class_new();
781 list_itc[i]->item_style = "default";
782 list_itc[i]->func.text_get = grid_itc[i]->func.text_get =
784 list_itc[i]->func.state_get = grid_itc[i]->func.state_get =
786 list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del;
789 list_itc[ELM_DIRECTORY]->func.content_get =
790 grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get;
791 list_itc[ELM_FILE_IMAGE]->func.content_get =
792 grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get;
793 list_itc[ELM_FILE_UNKNOW]->func.content_get =
794 grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get;
796 li = elm_genlist_add(obj);
797 elm_widget_mirrored_automatic_set(li, EINA_FALSE);
798 evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
799 evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
800 evas_object_size_hint_min_set(li, 100, 100);
802 grid = elm_gengrid_add(obj);
803 elm_widget_mirrored_automatic_set(grid, EINA_FALSE);
804 evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
805 evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
807 // XXX: will fail for dynamic finger size changing
808 s = elm_config_finger_size_get() * 2;
809 elm_gengrid_item_size_set(grid, s, s);
810 elm_gengrid_align_set(grid, 0.0, 0.0);
812 evas_object_smart_callback_add(li, "selected", _on_item_selected, obj);
813 evas_object_smart_callback_add
814 (li, "expand,request", _on_list_expand_req, obj);
815 evas_object_smart_callback_add
816 (li, "contract,request", _on_list_contract_req, obj);
817 evas_object_smart_callback_add(li, "expanded", _on_list_expanded, obj);
818 evas_object_smart_callback_add(li, "contracted", _on_list_contracted, obj);
819 evas_object_smart_callback_add(grid, "selected", _on_item_selected, obj);
821 elm_widget_sub_object_add(obj, li);
822 elm_widget_sub_object_add(obj, grid);
823 priv->files_list = li;
824 priv->files_grid = grid;
827 en = elm_entry_add(obj);
828 elm_entry_scrollable_set(en, EINA_TRUE);
829 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
830 elm_entry_editable_set(en, EINA_FALSE);
831 elm_entry_single_line_set(en, EINA_TRUE);
832 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
833 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
834 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
836 evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
838 elm_widget_sub_object_add(obj, en);
839 priv->path_entry = en;
842 en = elm_entry_add(obj);
843 elm_entry_scrollable_set(en, EINA_TRUE);
844 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
845 elm_entry_editable_set(en, EINA_TRUE);
846 elm_entry_single_line_set(en, EINA_TRUE);
847 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
848 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
849 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
851 elm_widget_sub_object_add(obj, en);
852 priv->filename_entry = en;
854 elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
855 elm_fileselector_is_save_set(obj, EINA_FALSE);
857 _elm_fileselector_smart_theme(obj);
861 _elm_fileselector_smart_del(Evas_Object *obj)
865 ELM_FILESELECTOR_DATA_GET(obj, sd);
867 for (i = 0; i < ELM_FILE_LAST; ++i)
869 elm_genlist_item_class_free(list_itc[i]);
870 elm_gengrid_item_class_free(grid_itc[i]);
874 if (sd->current) eio_file_cancel(sd->current);
877 sd->files_list = NULL;
878 sd->files_grid = NULL;
880 /* this one matching EINA_REFCOUNT_INIT() */
881 EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd);
885 _elm_fileselector_smart_set_user(Elm_Fileselector_Smart_Class *sc)
887 ELM_WIDGET_CLASS(sc)->base.add = _elm_fileselector_smart_add;
888 ELM_WIDGET_CLASS(sc)->base.del = _elm_fileselector_smart_del;
890 ELM_WIDGET_CLASS(sc)->theme = _elm_fileselector_smart_theme;
892 /* not a 'focus chain manager' */
893 ELM_WIDGET_CLASS(sc)->focus_next = NULL;
894 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
896 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_fileselector_smart_sizing_eval;
899 EAPI const Elm_Fileselector_Smart_Class *
900 elm_fileselector_smart_class_get(void)
902 static Elm_Fileselector_Smart_Class _sc =
903 ELM_FILESELECTOR_SMART_CLASS_INIT_NAME_VERSION
904 (ELM_FILESELECTOR_SMART_NAME);
905 static const Elm_Fileselector_Smart_Class *class = NULL;
906 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
911 _elm_fileselector_smart_set(&_sc);
912 esc->callbacks = _smart_callbacks;
919 elm_fileselector_add(Evas_Object *parent)
923 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
925 obj = elm_widget_add(_elm_fileselector_smart_class_new(), parent);
926 if (!obj) return NULL;
928 if (!elm_widget_sub_object_add(parent, obj))
929 ERR("could not add %p as sub object of %p", obj, parent);
935 elm_fileselector_is_save_set(Evas_Object *obj,
938 ELM_FILESELECTOR_CHECK(obj);
939 ELM_FILESELECTOR_DATA_GET(obj, sd);
941 elm_object_disabled_set(sd->filename_entry, !is_save);
943 if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm");
944 else elm_layout_signal_emit(obj, "elm,state,save,off", "elm");
948 elm_fileselector_is_save_get(const Evas_Object *obj)
950 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
951 ELM_FILESELECTOR_DATA_GET(obj, sd);
953 return !elm_object_disabled_get(sd->filename_entry);
957 elm_fileselector_folder_only_set(Evas_Object *obj,
960 ELM_FILESELECTOR_CHECK(obj);
961 ELM_FILESELECTOR_DATA_GET(obj, sd);
963 if (sd->only_folder == only) return;
965 sd->only_folder = !!only;
966 if (sd->path) _populate(obj, sd->path, NULL);
970 elm_fileselector_folder_only_get(const Evas_Object *obj)
972 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
973 ELM_FILESELECTOR_DATA_GET(obj, sd);
975 return sd->only_folder;
979 elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj,
984 ELM_FILESELECTOR_CHECK(obj);
985 ELM_FILESELECTOR_DATA_GET(obj, sd);
990 bt = elm_button_add(obj);
991 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
992 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
994 evas_object_smart_callback_add(bt, "clicked", _canc, obj);
996 sd->cancel_button = bt;
999 bt = elm_button_add(obj);
1000 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1001 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
1003 evas_object_smart_callback_add(bt, "clicked", _ok, obj);
1007 _elm_fileselector_smart_theme(obj);
1011 evas_object_del(sd->cancel_button);
1012 sd->cancel_button = NULL;
1013 evas_object_del(sd->ok_button);
1014 sd->ok_button = NULL;
1019 elm_fileselector_buttons_ok_cancel_get(const Evas_Object *obj)
1021 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1022 ELM_FILESELECTOR_DATA_GET(obj, sd);
1024 return sd->ok_button ? EINA_TRUE : EINA_FALSE;
1028 elm_fileselector_expandable_set(Evas_Object *obj,
1031 ELM_FILESELECTOR_CHECK(obj);
1032 ELM_FILESELECTOR_DATA_GET(obj, sd);
1034 sd->expand = !!expand;
1036 if (sd->path) _populate(obj, sd->path, NULL);
1040 elm_fileselector_expandable_get(const Evas_Object *obj)
1042 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1043 ELM_FILESELECTOR_DATA_GET(obj, sd);
1049 elm_fileselector_path_set(Evas_Object *obj,
1054 ELM_FILESELECTOR_CHECK(obj);
1056 path = ecore_file_realpath(_path);
1057 _populate(obj, path, NULL);
1062 elm_fileselector_path_get(const Evas_Object *obj)
1064 ELM_FILESELECTOR_CHECK(obj) NULL;
1065 ELM_FILESELECTOR_DATA_GET(obj, sd);
1071 elm_fileselector_mode_set(Evas_Object *obj,
1072 Elm_Fileselector_Mode mode)
1074 ELM_FILESELECTOR_CHECK(obj);
1076 ELM_FILESELECTOR_DATA_GET(obj, sd);
1078 if (mode == sd->mode) return;
1080 evas_object_hide(elm_layout_content_unset(obj, "elm.swallow.files"));
1082 if (mode == ELM_FILESELECTOR_LIST)
1083 elm_layout_content_set(obj, "elm.swallow.files", sd->files_list);
1084 else elm_layout_content_set(obj, "elm.swallow.files", sd->files_grid);
1088 _populate(obj, sd->path, NULL);
1091 EAPI Elm_Fileselector_Mode
1092 elm_fileselector_mode_get(const Evas_Object *obj)
1094 ELM_FILESELECTOR_CHECK(obj) ELM_FILESELECTOR_LAST;
1095 ELM_FILESELECTOR_DATA_GET(obj, sd);
1101 elm_fileselector_selected_get(const Evas_Object *obj)
1103 ELM_FILESELECTOR_CHECK(obj) NULL;
1104 ELM_FILESELECTOR_DATA_GET(obj, sd);
1106 if (!sd->path) return NULL;
1108 if (sd->filename_entry)
1114 if (ecore_file_is_dir(sd->path))
1115 dir = strdup(sd->path);
1117 dir = ecore_file_dir_get(sd->path);
1118 name = elm_object_text_get(sd->filename_entry);
1121 s = elm_entry_markup_to_utf8(name);
1124 snprintf(buf, sizeof(buf), "%s/%s", dir, s);
1127 else snprintf(buf, sizeof(buf), "%s", dir);
1129 else snprintf(buf, sizeof(buf), "%s", dir);
1131 eina_stringshare_replace(&sd->selection, buf);
1134 return sd->selection;
1137 if (sd->mode == ELM_FILESELECTOR_LIST)
1139 Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_list);
1141 if (gl_it) return elm_object_item_data_get(gl_it);
1145 Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_grid);
1147 if (gg_it) return elm_object_item_data_get(gg_it);
1154 elm_fileselector_selected_set(Evas_Object *obj,
1157 Eina_Bool ret = EINA_TRUE;
1160 ELM_FILESELECTOR_CHECK(obj) EINA_FALSE;
1161 ELM_FILESELECTOR_DATA_GET(obj, sd);
1163 path = ecore_file_realpath(_path);
1165 if (ecore_file_is_dir(path)) _populate(obj, path, NULL);
1168 if (!ecore_file_exists(path))
1174 _populate(obj, ecore_file_dir_get(path), NULL);
1175 if (sd->filename_entry)
1179 s = elm_entry_utf8_to_markup(ecore_file_file_get(path));
1182 elm_object_text_set(sd->filename_entry, s);
1185 else elm_object_text_set(sd->filename_entry, "");
1187 eina_stringshare_replace(&sd->selection, path);