From c1075327a3d77c83c6daaae4fdafab53cf28f287 Mon Sep 17 00:00:00 2001 From: Gustavo Lima Chaves Date: Thu, 3 May 2012 22:44:26 +0000 Subject: [PATCH] [Elm] File selector now a layout. SVN revision: 70742 --- src/lib/elc_fileselector.c | 1406 ++++++++++++++++++++++---------------------- src/lib/elc_fileselector.h | 5 +- 2 files changed, 721 insertions(+), 690 deletions(-) diff --git a/src/lib/elc_fileselector.c b/src/lib/elc_fileselector.c index 148c73d..c2a2d89 100644 --- a/src/lib/elc_fileselector.c +++ b/src/lib/elc_fileselector.c @@ -10,48 +10,47 @@ * - Filter support */ -#ifdef HAVE_CONFIG_H -# include "elementary_config.h" -#endif +#include +#include "elm_priv.h" +#include "elm_widget_layout.h" #ifdef HAVE_EIO # include #endif -#include -#include "elm_priv.h" +static const char FILESELECTOR_SMART_NAME[] = "elm_fileselector"; -typedef struct _Widget_Data Widget_Data; +typedef struct _Elm_Fileselector_Smart_Data Elm_Fileselector_Smart_Data; -struct _Widget_Data +struct _Elm_Fileselector_Smart_Data { - EINA_REFCOUNT; + Elm_Layout_Smart_Data base; - Evas_Object *edje; - Evas_Object *filename_entry; - Evas_Object *path_entry; - Evas_Object *files_list; - Evas_Object *files_grid; - Evas_Object *up_button; - Evas_Object *home_button; + EINA_REFCOUNT; - Evas_Object *ok_button; - Evas_Object *cancel_button; + Evas_Object *filename_entry; + Evas_Object *path_entry; + Evas_Object *files_list; + Evas_Object *files_grid; + Evas_Object *up_button; + Evas_Object *home_button; + Evas_Object *ok_button; + Evas_Object *cancel_button; - const char *path; - const char *selection; - Ecore_Idler *sel_idler; + const char *path; + const char *selection; + Ecore_Idler *sel_idler; - const char *path_separator; + const char *path_separator; #ifdef HAVE_EIO - Eio_File *current; + Eio_File *current; #endif Elm_Fileselector_Mode mode; - Eina_Bool only_folder : 1; - Eina_Bool expand : 1; + Eina_Bool only_folder : 1; + Eina_Bool expand : 1; }; struct sel_data @@ -60,202 +59,182 @@ struct sel_data const char *path; }; -typedef struct _Widget_Request Widget_Request; -struct _Widget_Request +typedef struct _Listing_Request Listing_Request; +struct _Listing_Request { - Widget_Data *wd; - Elm_Object_Item *parent; + Elm_Fileselector_Smart_Data *sd; + Elm_Object_Item *parent_it; - Evas_Object *obj; - const char *path; - Eina_Bool first : 1; + Evas_Object *obj; + const char *path; + Eina_Bool first : 1; }; typedef enum { - ELM_DIRECTORY = 0, - ELM_FILE_IMAGE = 1, - ELM_FILE_UNKNOW = 2, - ELM_FILE_LAST + ELM_DIRECTORY = 0, + ELM_FILE_IMAGE = 1, + ELM_FILE_UNKNOW = 2, + ELM_FILE_LAST } Elm_Fileselector_Type; static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST]; static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST]; -static const char *widtype = NULL; - static const char SIG_DIRECTORY_OPEN[] = "directory,open"; static const char SIG_DONE[] = "done"; static const char SIG_SELECTED[] = "selected"; -static const Evas_Smart_Cb_Description _signals[] = { +static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_DIRECTORY_OPEN, "s"}, {SIG_DONE, "s"}, {SIG_SELECTED, "s"}, {NULL, NULL} }; -static void _populate(Evas_Object *obj, - const char *path, - Elm_Object_Item *parent); -static void _do_anchors(Evas_Object *obj, - const char *path); - -/*** ELEMENTARY WIDGET ***/ -static void -_widget_data_free(Widget_Data *wd) -{ - if (wd->path) eina_stringshare_del(wd->path); - if (wd->selection) eina_stringshare_del(wd->selection); - if (wd->sel_idler) - { - void *sd; - - sd = ecore_idler_del(wd->sel_idler); - free(sd); - } - free(wd); -} +#define ELM_FILESELECTOR_DATA_GET(o, sd) \ + Elm_Fileselector_Smart_Data * sd = evas_object_smart_data_get(o) -static void -_del_hook(Evas_Object *obj) -{ - Widget_Data *wd; - int i; +#define ELM_FILESELECTOR_DATA_GET_OR_RETURN(o, ptr) \ + ELM_FILESELECTOR_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } - wd = elm_widget_data_get(obj); - if (!wd) return; +#define ELM_FILESELECTOR_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + ELM_FILESELECTOR_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } - for (i = 0; i < ELM_FILE_LAST; ++i) - { - elm_genlist_item_class_free(list_itc[i]); - elm_gengrid_item_class_free(grid_itc[i]); - } +#define ELM_FILESELECTOR_CHECK(obj) \ + if (!obj || !elm_widget_type_check \ + ((obj), FILESELECTOR_SMART_NAME, __func__)) \ + return -#ifdef HAVE_EIO - if (wd->current) - eio_file_cancel(wd->current); -#endif +/* Inheriting from elm_layout. Besides, we need no more than what is + * there */ +EVAS_SMART_SUBCLASS_NEW + (FILESELECTOR_SMART_NAME, _elm_fileselector, Elm_Layout_Smart_Class, + Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks); - wd->files_list = NULL; - wd->files_grid = NULL; +/* final routine on deletion */ +static void +_elm_fileselector_smart_del_do(Elm_Fileselector_Smart_Data *sd) +{ + if (sd->path) eina_stringshare_del(sd->path); + if (sd->selection) eina_stringshare_del(sd->selection); + if (sd->sel_idler) free(ecore_idler_del(sd->sel_idler)); - EINA_REFCOUNT_UNREF(wd) - _widget_data_free(wd); + ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->base.del + (ELM_WIDGET_DATA(sd)->obj); } static void -_sizing_eval(Evas_Object *obj) +_elm_fileselector_smart_sizing_eval(Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(obj); Evas_Coord minw = -1, minh = -1; - if (!wd) return; + + ELM_FILESELECTOR_DATA_GET(obj, sd); + elm_coords_finger_size_adjust(1, &minw, 1, &minh); - edje_object_size_min_restricted_calc(wd->edje, &minw, &minh, minw, minh); + edje_object_size_min_restricted_calc + (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh); evas_object_size_hint_min_set(obj, minw, minh); } static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl) { - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - elm_widget_mirrored_set(wd->cancel_button, rtl); - elm_widget_mirrored_set(wd->ok_button, rtl); - elm_widget_mirrored_set(wd->files_list, rtl); - elm_widget_mirrored_set(wd->up_button, rtl); - elm_widget_mirrored_set(wd->home_button, rtl); - edje_object_mirrored_set(wd->edje, rtl); + ELM_FILESELECTOR_DATA_GET(obj, sd); + + elm_widget_mirrored_set(sd->cancel_button, rtl); + elm_widget_mirrored_set(sd->ok_button, rtl); + elm_widget_mirrored_set(sd->files_list, rtl); + elm_widget_mirrored_set(sd->up_button, rtl); + elm_widget_mirrored_set(sd->home_button, rtl); } -static void -_theme_hook(Evas_Object *obj) +static Eina_Bool +_elm_fileselector_smart_theme(Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(obj); - const char *style = elm_widget_style_get(obj); + const char *style; const char *data; char buf[1024]; - if (!wd) return; - _elm_widget_mirrored_reload(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); - _elm_theme_object_set(obj, wd->edje, "fileselector", "base", style); + if (!ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->theme(obj)) return EINA_FALSE; - if (elm_object_disabled_get(obj)) - edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm"); + style = elm_widget_style_get(obj); + _mirrored_set(obj, elm_widget_mirrored_get(obj)); - data = edje_object_data_get(wd->edje, "path_separator"); - if (data) - wd->path_separator = data; - else - wd->path_separator = "/"; + data = edje_object_data_get + (ELM_WIDGET_DATA(sd)->resize_obj, "path_separator"); + if (data) sd->path_separator = data; + else sd->path_separator = "/"; - if (!style) style = "default"; snprintf(buf, sizeof(buf), "fileselector/%s", style); -#define SWALLOW(part_name, object_ptn) \ - if (object_ptn) \ - { \ - elm_widget_style_set(object_ptn, buf); \ - if (edje_object_part_swallow(wd->edje, part_name, object_ptn)) \ - evas_object_show(object_ptn); \ - else \ - evas_object_hide(object_ptn); \ +#define SWALLOW(part_name, object_ptn) \ + if (object_ptn) \ + { \ + elm_widget_style_set(object_ptn, buf); \ + if (!elm_layout_content_set(obj, part_name, object_ptn)) \ + evas_object_hide(object_ptn); \ } - SWALLOW("elm.swallow.up", wd->up_button); - SWALLOW("elm.swallow.home", wd->home_button); - if (wd->mode == ELM_FILESELECTOR_LIST) + SWALLOW("elm.swallow.up", sd->up_button); + SWALLOW("elm.swallow.home", sd->home_button); + + if (sd->mode == ELM_FILESELECTOR_LIST) { - if (edje_object_part_swallow(wd->edje, "elm.swallow.files", - wd->files_list)) - { - evas_object_show(wd->files_list); - evas_object_hide(wd->files_grid); - } - else - evas_object_hide(wd->files_list); + if (elm_layout_content_set(obj, "elm.swallow.files", sd->files_list)) + evas_object_hide(sd->files_grid); + else evas_object_hide(sd->files_list); } else { - if (edje_object_part_swallow(wd->edje, "elm.swallow.files", - wd->files_grid)) - { - evas_object_show(wd->files_grid); - evas_object_hide(wd->files_list); - } - else - evas_object_hide(wd->files_grid); + if (elm_layout_content_set(obj, "elm.swallow.files", sd->files_grid)) + evas_object_hide(sd->files_list); + else evas_object_hide(sd->files_grid); } - SWALLOW("elm.swallow.filename", wd->filename_entry); - SWALLOW("elm.swallow.path", wd->path_entry); + SWALLOW("elm.swallow.filename", sd->filename_entry); + SWALLOW("elm.swallow.path", sd->path_entry); snprintf(buf, sizeof(buf), "fileselector/actions/%s", style); - SWALLOW("elm.swallow.cancel", wd->cancel_button); - SWALLOW("elm.swallow.ok", wd->ok_button); + SWALLOW("elm.swallow.cancel", sd->cancel_button); + SWALLOW("elm.swallow.ok", sd->ok_button); + #undef SWALLOW - edje_object_message_signal_process(wd->edje); - _mirrored_set(obj, elm_widget_mirrored_get(obj)); - edje_object_scale_set - (wd->edje, elm_widget_scale_get(obj) * _elm_config->scale); - _sizing_eval(obj); + edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj); + + elm_layout_sizing_eval(obj); + + return EINA_TRUE; } -/*** GENLIST "MODEL" ***/ +/*** GENLIST/GENGRID "MODEL" ***/ static char * -_itc_text_get(void *data, - Evas_Object *obj __UNUSED__, - const char *source __UNUSED__) +_itc_text_get(void *data, + Evas_Object *obj __UNUSED__, + const char *source __UNUSED__) { - return elm_entry_utf8_to_markup(ecore_file_file_get(data)); /* NOTE this will be - * free() by the - * caller */ + return elm_entry_utf8_to_markup + (ecore_file_file_get(data)); /* NOTE this will be free()'d by + * the caller */ } static Evas_Object * -_itc_icon_folder_get(void *data __UNUSED__, +_itc_icon_folder_get(void *data __UNUSED__, Evas_Object *obj, - const char *source) + const char *source) { Evas_Object *ic; @@ -264,15 +243,14 @@ _itc_icon_folder_get(void *data __UNUSED__, ic = elm_icon_add(obj); elm_icon_standard_set(ic, "folder"); - evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, - 1, 1); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); return ic; } static Evas_Object * -_itc_icon_image_get(void *data, +_itc_icon_image_get(void *data, Evas_Object *obj, - const char *source) + const char *source) { const char *filename = data; Evas_Object *ic; @@ -283,15 +261,14 @@ _itc_icon_image_get(void *data, elm_icon_standard_set(ic, "image"); elm_icon_thumb_set(ic, filename, NULL); - evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, - 1, 1); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); return ic; } static Evas_Object * -_itc_icon_file_get(void *data __UNUSED__, +_itc_icon_file_get(void *data __UNUSED__, Evas_Object *obj, - const char *source) + const char *source) { Evas_Object *ic; @@ -300,8 +277,7 @@ _itc_icon_file_get(void *data __UNUSED__, ic = elm_icon_add(obj); elm_icon_standard_set(ic, "file"); - evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, - 1, 1); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); return ic; } @@ -314,253 +290,17 @@ _itc_state_get(void *data __UNUSED__, } static void -_itc_del(void *data, +_itc_del(void *data, Evas_Object *obj __UNUSED__) { eina_stringshare_del(data); } -static void -_expand_done(void *data, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - Elm_Object_Item *it = event_info; - const char *path = elm_object_item_data_get(it); - _populate(data, path, it); -} - -static void -_contract_done(void *data __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - Elm_Object_Item *it = event_info; - elm_genlist_item_subitems_clear(it); -} - -static void -_expand_req(void *data __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - Elm_Object_Item *it = event_info; - elm_genlist_item_expanded_set(it, EINA_TRUE); -} - -static void -_contract_req(void *data __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - Elm_Object_Item *it = event_info; - elm_genlist_item_expanded_set(it, EINA_FALSE); -} - -/*** PRIVATES ***/ -static Eina_Bool -_sel_do(void *data) -{ - struct sel_data *sd; - const char *path; - Widget_Data *wd; - const char *p; - - sd = data; - wd = elm_widget_data_get(sd->fs); - path = sd->path; - - if ((!wd->only_folder) && ecore_file_is_dir(path)) - { - if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST) - { - _do_anchors(sd->fs, path); - elm_object_text_set(wd->filename_entry, ""); - } - else - { - /* keep a ref to path 'couse it will be destroyed by _populate */ - p = eina_stringshare_add(path); - _populate(sd->fs, p, NULL); - eina_stringshare_del(p); - } - goto end; - } - else /* navigating through folders only or file is not a dir. */ - { - char *s; - - if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST) - _do_anchors(sd->fs, path); - else if (wd->only_folder) - { - /* keep a ref to path 'couse it will be destroyed by _populate */ - p = eina_stringshare_add(path); - _populate(sd->fs, p, NULL); - eina_stringshare_del(p); - } - s = elm_entry_utf8_to_markup(ecore_file_file_get(path)); - if (s) - { - elm_object_text_set(wd->filename_entry, s); - free(s); - } - else - elm_object_text_set(wd->filename_entry, ""); - } - - evas_object_smart_callback_call(sd->fs, SIG_SELECTED, (void *)path); - -end: - wd->sel_idler = NULL; - free(sd); - return ECORE_CALLBACK_CANCEL; -} - -static void -_sel(void *data, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - struct sel_data *sd; - Widget_Data *wd; - void *old_sd; - char *dir; - //This event_info could be a list or gengrid item - Elm_Object_Item *it = event_info; - - wd = elm_widget_data_get(data); - if (!wd) return; - - sd = malloc(sizeof(*sd)); - sd->fs = data; - sd->path = elm_object_item_data_get(it); - - if (!sd->path) - { - eina_stringshare_replace(&wd->path, ""); - goto end; - } - - dir = wd->only_folder ? strdup(sd->path) : ecore_file_dir_get(sd->path); - if (dir) - { - eina_stringshare_replace(&wd->path, dir); - free(dir); - } - else - { - eina_stringshare_replace(&wd->path, ""); - } - -end: - if (wd->sel_idler) - { - old_sd = ecore_idler_del(wd->sel_idler); - free(old_sd); - } - wd->sel_idler = ecore_idler_add(_sel_do, sd); -} - -static void -_up(void *data, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) -{ - Evas_Object *fs = data; - char *parent; - - Widget_Data *wd = elm_widget_data_get(fs); - if (!wd) return; - parent = ecore_file_dir_get(wd->path); - _populate(fs, parent, NULL); - free(parent); -} - -static void -_home(void *data, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) -{ - Evas_Object *fs = data; - _populate(fs, getenv("HOME"), NULL); -} - -static void -_ok(void *data, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) -{ - Evas_Object *fs = data; - evas_object_smart_callback_call(fs, SIG_DONE, - (void *)elm_fileselector_selected_get(fs)); -} - -static void -_canc(void *data, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) -{ - Evas_Object *fs = data; - evas_object_smart_callback_call(fs, SIG_DONE, NULL); -} - -static void -_anchor_clicked(void *data, - Evas_Object *obj __UNUSED__, - void *event_info) -{ - Evas_Object *fs = data; - Widget_Data *wd = elm_widget_data_get(fs); - Elm_Entry_Anchor_Info *info = event_info; - const char *p; - if (!wd) return; - // keep a ref to path 'couse it will be destroyed by _populate - p = eina_stringshare_add(info->name); - _populate(fs, p, NULL); - evas_object_smart_callback_call(data, SIG_SELECTED, (void *)p); - eina_stringshare_del(p); -} - -static void -_do_anchors(Evas_Object *obj, - const char *path) -{ - Widget_Data *wd = elm_widget_data_get(obj); - char **tok, buf[PATH_MAX * 3], *s; - int i, j; - - if (!wd) return; - s = elm_entry_utf8_to_markup(path); - if (!s) return; - buf[0] = '\0'; - tok = eina_str_split(s, "/", 0); - free(s); - eina_strlcat(buf, "root", sizeof(buf)); - for (i = 0; tok[i]; i++) - { - if ((!tok[i]) || (!tok[i][0])) continue; - eina_strlcat(buf, wd->path_separator, sizeof(buf)); - eina_strlcat(buf, "", sizeof(buf)); - eina_strlcat(buf, tok[i], sizeof(buf)); - eina_strlcat(buf, "", sizeof(buf)); - } - free(tok[0]); - free(tok); - - elm_object_text_set(wd->path_entry, buf); -} - #ifdef HAVE_EIO static Eina_Bool -_filter_cb(void *data __UNUSED__, Eio_File *handler, const Eina_File_Direct_Info *info) +_ls_filter_cb(void *data __UNUSED__, + Eio_File *handler, + const Eina_File_Direct_Info *info) { const char *filename; @@ -568,24 +308,32 @@ _filter_cb(void *data __UNUSED__, Eio_File *handler, const Eina_File_Direct_Info return EINA_FALSE; filename = eina_stringshare_add(info->path); - eio_file_associate_direct_add(handler, "filename", filename, EINA_FREE_CB(eina_stringshare_del)); + eio_file_associate_direct_add + (handler, "filename", filename, EINA_FREE_CB(eina_stringshare_del)); if (info->type == EINA_FILE_DIR) { - eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_DIRECTORY], NULL); - eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_DIRECTORY], NULL); + eio_file_associate_direct_add + (handler, "type/grid", grid_itc[ELM_DIRECTORY], NULL); + eio_file_associate_direct_add + (handler, "type/list", list_itc[ELM_DIRECTORY], NULL); } else { - if (evas_object_image_extension_can_load_get(info->path + info->name_start)) + if (evas_object_image_extension_can_load_get + (info->path + info->name_start)) { - eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_FILE_IMAGE], NULL); - eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_FILE_IMAGE], NULL); + eio_file_associate_direct_add + (handler, "type/grid", grid_itc[ELM_FILE_IMAGE], NULL); + eio_file_associate_direct_add + (handler, "type/list", list_itc[ELM_FILE_IMAGE], NULL); } else { - eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_FILE_UNKNOW], NULL); - eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_FILE_UNKNOW], NULL); + eio_file_associate_direct_add + (handler, "type/grid", grid_itc[ELM_FILE_UNKNOW], NULL); + eio_file_associate_direct_add + (handler, "type/list", list_itc[ELM_FILE_UNKNOW], NULL); } } @@ -593,7 +341,8 @@ _filter_cb(void *data __UNUSED__, Eio_File *handler, const Eina_File_Direct_Info } static int -_file_grid_cmp(const void *a, const void *b) +_file_grid_cmp(const void *a, + const void *b) { const Elm_Object_Item *ga = a; const Elm_Object_Item *gb = b; @@ -614,7 +363,8 @@ _file_grid_cmp(const void *a, const void *b) } static int -_file_list_cmp(const void *a, const void *b) +_file_list_cmp(const void *a, + const void *b) { const Elm_Object_Item *la = a; const Elm_Object_Item *lb = b; @@ -635,244 +385,489 @@ _file_list_cmp(const void *a, const void *b) } static void -_signal_first(Widget_Request *wr) +_anchors_do(Evas_Object *obj, + const char *path) +{ + char **tok, buf[PATH_MAX * 3], *s; + int i, j; + + ELM_FILESELECTOR_DATA_GET(obj, sd); + + s = elm_entry_utf8_to_markup(path); + if (!s) return; + + buf[0] = '\0'; + tok = eina_str_split(s, "/", 0); + free(s); + + eina_strlcat(buf, "root", sizeof(buf)); + for (i = 0; tok[i]; i++) + { + if ((!tok[i]) || (!tok[i][0])) continue; + eina_strlcat(buf, sd->path_separator, sizeof(buf)); + eina_strlcat(buf, "", sizeof(buf)); + eina_strlcat(buf, tok[i], sizeof(buf)); + eina_strlcat(buf, "", sizeof(buf)); + } + free(tok[0]); + free(tok); + + elm_object_text_set(sd->path_entry, buf); +} + +static void +_signal_first(Listing_Request *lreq) { - if (!wr->first) return ; - evas_object_smart_callback_call(wr->obj, SIG_DIRECTORY_OPEN, (void *)wr->path); - if (!wr->parent) + if (!lreq->first) return; + + evas_object_smart_callback_call + (lreq->obj, SIG_DIRECTORY_OPEN, (void *)lreq->path); + + if (!lreq->parent_it) { - elm_genlist_clear(wr->wd->files_list); - elm_gengrid_clear(wr->wd->files_grid); - eina_stringshare_replace(&wr->wd->path, wr->path); - _do_anchors(wr->obj, wr->path); + elm_genlist_clear(lreq->sd->files_list); + elm_gengrid_clear(lreq->sd->files_grid); + eina_stringshare_replace(&lreq->sd->path, lreq->path); + _anchors_do(lreq->obj, lreq->path); } - if (wr->wd->filename_entry) elm_object_text_set(wr->wd->filename_entry, ""); + if (lreq->sd->filename_entry) + elm_object_text_set(lreq->sd->filename_entry, ""); - wr->first = EINA_FALSE; + lreq->first = EINA_FALSE; } static void -_main_cb(void *data, Eio_File *handler, const Eina_File_Direct_Info *info __UNUSED__) +_ls_main_cb(void *data, + Eio_File *handler, + const Eina_File_Direct_Info *info __UNUSED__) { - Widget_Request *wr = data; + Listing_Request *lreq = data; - if (eio_file_check(handler)) - return ; - if (!wr->wd->files_list || !wr->wd->files_grid || wr->wd->current != handler) + if (eio_file_check(handler)) return; + + if (!lreq->sd->files_list || !lreq->sd->files_grid + || lreq->sd->current != handler) { eio_file_cancel(handler); - return ; + return; } - _signal_first(wr); + _signal_first(lreq); - if (wr->wd->mode == ELM_FILESELECTOR_LIST) + if (lreq->sd->mode == ELM_FILESELECTOR_LIST) { - Eina_Bool is_dir = (eio_file_associate_find(handler, "type/list") == list_itc[ELM_DIRECTORY]); - - elm_genlist_item_sorted_insert(wr->wd->files_list, eio_file_associate_find(handler, "type/list"), - eina_stringshare_ref(eio_file_associate_find(handler, "filename")), - wr->parent, wr->wd->expand && is_dir ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE, - _file_list_cmp, NULL, NULL); + Eina_Bool is_dir = (eio_file_associate_find(handler, "type/list") + == list_itc[ELM_DIRECTORY]); + + elm_genlist_item_sorted_insert + (lreq->sd->files_list, eio_file_associate_find(handler, "type/list"), + eina_stringshare_ref(eio_file_associate_find + (handler, "filename")), + lreq->parent_it, lreq->sd->expand && is_dir ? ELM_GENLIST_ITEM_TREE + : ELM_GENLIST_ITEM_NONE, _file_list_cmp, NULL, NULL); } - else if (wr->wd->mode == ELM_FILESELECTOR_GRID) - elm_gengrid_item_sorted_insert(wr->wd->files_grid, eio_file_associate_find(handler, "type/grid"), - eina_stringshare_ref(eio_file_associate_find(handler, "filename")), - _file_grid_cmp, NULL, NULL); + else if (lreq->sd->mode == ELM_FILESELECTOR_GRID) + elm_gengrid_item_sorted_insert + (lreq->sd->files_grid, eio_file_associate_find(handler, "type/grid"), + eina_stringshare_ref(eio_file_associate_find(handler, "filename")), + _file_grid_cmp, NULL, NULL); } static void -_widget_request_cleanup(Widget_Request *wr) +_listing_request_cleanup(Listing_Request *lreq) { - EINA_REFCOUNT_UNREF(wr->wd) - _widget_data_free(wr->wd); + EINA_REFCOUNT_UNREF(lreq->sd) _elm_fileselector_smart_del_do(lreq->sd); - eina_stringshare_del(wr->path); - free(wr); + eina_stringshare_del(lreq->path); + free(lreq); } static void -_done_cb(void *data, Eio_File *handler __UNUSED__) +_ls_done_cb(void *data, Eio_File *handler __UNUSED__) { - Widget_Request *wr = data; + Listing_Request *lreq = data; - _signal_first(wr); + _signal_first(lreq); - wr->wd->current = NULL; - _widget_request_cleanup(wr); + lreq->sd->current = NULL; + _listing_request_cleanup(lreq); } static void -_error_cb(void *data, Eio_File *handler, int error __UNUSED__) +_ls_error_cb(void *data, Eio_File *handler, int error __UNUSED__) { - Widget_Request *wr = data; + Listing_Request *lreq = data; - if (wr->wd->current == handler) - wr->wd->current = NULL; - _widget_request_cleanup(wr); + if (lreq->sd->current == handler) + lreq->sd->current = NULL; + _listing_request_cleanup(lreq); } #endif static void -_populate(Evas_Object *obj, - const char *path, - Elm_Object_Item *parent) +_populate(Evas_Object *obj, + const char *path, + Elm_Object_Item *parent_it) { - Widget_Data *wd = elm_widget_data_get(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); + #ifdef HAVE_EIO - Widget_Request *wr; + Listing_Request *lreq; #else + Eina_List *files = NULL, *dirs = NULL; Eina_File_Direct_Info *file; Eina_Iterator *it; - const char *real; - Eina_List *files = NULL, *dirs = NULL; + const char *entry; #endif - if (!wd) return; -#ifndef HAVE_EIO - if (!ecore_file_is_dir(path)) return ; +#ifndef HAVE_EIO /* synchronous listing path */ + if (!ecore_file_is_dir(path)) return; + it = eina_file_stat_ls(path); - if (!it) return ; + if (!it) return; + evas_object_smart_callback_call(obj, SIG_DIRECTORY_OPEN, (void *)path); - if (!parent) + if (!parent_it) { - elm_genlist_clear(wd->files_list); - elm_gengrid_clear(wd->files_grid); - eina_stringshare_replace(&wd->path, path); - _do_anchors(obj, path); + elm_genlist_clear(sd->files_list); + elm_gengrid_clear(sd->files_grid); + eina_stringshare_replace(&sd->path, path); + _anchors_do(obj, path); } - if (wd->filename_entry) elm_object_text_set(wd->filename_entry, ""); - EINA_ITERATOR_FOREACH(it, file) + if (sd->filename_entry) elm_object_text_set(sd->filename_entry, ""); + EINA_ITERATOR_FOREACH (it, file) { const char *filename; - if (file->path[file->name_start] == '.') - continue ; + if (file->path[file->name_start] == '.') continue; filename = eina_stringshare_add(file->path); if (file->type == EINA_FILE_DIR) dirs = eina_list_append(dirs, filename); - else if (!wd->only_folder) + else if (!sd->only_folder) files = eina_list_append(files, filename); } eina_iterator_free(it); - files = eina_list_sort(files, eina_list_count(files), - EINA_COMPARE_CB(strcoll)); - dirs = eina_list_sort(dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll)); - EINA_LIST_FREE(dirs, real) + files = eina_list_sort + (files, eina_list_count(files), EINA_COMPARE_CB(strcoll)); + + dirs = eina_list_sort + (dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll)); + EINA_LIST_FREE (dirs, entry) { - if (wd->mode == ELM_FILESELECTOR_LIST) - elm_genlist_item_append(wd->files_list, list_itc[ELM_DIRECTORY], - real, /* item data */ - parent, - wd->expand ? ELM_GENLIST_ITEM_TREE : + if (sd->mode == ELM_FILESELECTOR_LIST) + elm_genlist_item_append(sd->files_list, list_itc[ELM_DIRECTORY], + entry, /* item data */ + parent_it, + sd->expand ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE, NULL, NULL); - else if (wd->mode == ELM_FILESELECTOR_GRID) - elm_gengrid_item_append(wd->files_grid, grid_itc[ELM_DIRECTORY], - real, /* item data */ + else if (sd->mode == ELM_FILESELECTOR_GRID) + elm_gengrid_item_append(sd->files_grid, grid_itc[ELM_DIRECTORY], + entry, /* item data */ NULL, NULL); } - EINA_LIST_FREE(files, real) + EINA_LIST_FREE (files, entry) { - Elm_Fileselector_Type type = evas_object_image_extension_can_load_fast_get(real) ? + Elm_Fileselector_Type type = + evas_object_image_extension_can_load_fast_get(entry) ? ELM_FILE_IMAGE : ELM_FILE_UNKNOW; - if (wd->mode == ELM_FILESELECTOR_LIST) - elm_genlist_item_append(wd->files_list, list_itc[type], - real, /* item data */ - parent, ELM_GENLIST_ITEM_NONE, + if (sd->mode == ELM_FILESELECTOR_LIST) + elm_genlist_item_append(sd->files_list, list_itc[type], + entry, /* item data */ + parent_it, ELM_GENLIST_ITEM_NONE, NULL, NULL); - else if (wd->mode == ELM_FILESELECTOR_GRID) - elm_gengrid_item_append(wd->files_grid, grid_itc[type], - real, /* item data */ + else if (sd->mode == ELM_FILESELECTOR_GRID) + elm_gengrid_item_append(sd->files_grid, grid_itc[type], + entry, /* item data */ NULL, NULL); } -#else - if (wd->expand && wd->current) return ; - if (wd->current) - eio_file_cancel(wd->current); - wr = malloc(sizeof (Widget_Request)); - if (!wr) return ; - wr->wd = wd; - EINA_REFCOUNT_REF(wr->wd); - wr->parent = parent; /* FIXME: should we refcount the parent ? */ - wr->obj = obj; - wr->path = eina_stringshare_add(path); - wr->first = EINA_TRUE; - - wd->current = eio_file_stat_ls(path, - _filter_cb, - _main_cb, - _done_cb, - _error_cb, - wr); + +#else /* asynchronous listing path */ + if (sd->expand && sd->current) return; + + if (sd->current) eio_file_cancel(sd->current); + + lreq = malloc(sizeof (Listing_Request)); + if (!lreq) return; + + lreq->sd = sd; + EINA_REFCOUNT_REF(lreq->sd); + + lreq->parent_it = parent_it; /* FIXME: should we refcount the parent_it ? */ + lreq->obj = obj; + lreq->path = eina_stringshare_add(path); + lreq->first = EINA_TRUE; + + sd->current = eio_file_stat_ls(path, _ls_filter_cb, _ls_main_cb, + _ls_done_cb, _ls_error_cb, lreq); #endif } -/*** API ***/ +static void +_on_list_expanded(void *data, + Evas_Object *obj __UNUSED__, + void *event_info) +{ + Elm_Object_Item *it = event_info; + const char *path = elm_object_item_data_get(it); + + _populate(data, path, it); +} -EAPI Evas_Object * -elm_fileselector_add(Evas_Object *parent) +static void +_on_list_contracted(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info) { - Evas *e; - Evas_Object *obj, *ic, *bt, *li, *en, *grid; - Widget_Data *wd; + Elm_Object_Item *it = event_info; + + elm_genlist_item_subitems_clear(it); +} + +static void +_on_list_expand_req(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info) +{ + Elm_Object_Item *it = event_info; + + elm_genlist_item_expanded_set(it, EINA_TRUE); +} + +static void +_on_list_contract_req(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info) +{ + Elm_Object_Item *it = event_info; + + elm_genlist_item_expanded_set(it, EINA_FALSE); +} + +static Eina_Bool +_sel_do(void *data) +{ + struct sel_data *sdata = data; + const char *path; + const char *p; + + ELM_FILESELECTOR_DATA_GET(sdata->fs, sd); + path = sdata->path; + + if ((!sd->only_folder) && ecore_file_is_dir(path)) + { + if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST) + { + _anchors_do(sdata->fs, path); + elm_object_text_set(sd->filename_entry, ""); + } + else + { + /* keep a ref to path 'couse it will be destroyed by _populate */ + p = eina_stringshare_add(path); + _populate(sdata->fs, p, NULL); + eina_stringshare_del(p); + } + goto end; + } + else /* navigating through folders only or file is not a dir. */ + { + char *s; + + if (sd->expand && sd->mode == ELM_FILESELECTOR_LIST) + _anchors_do(sdata->fs, path); + else if (sd->only_folder) + { + /* keep a ref to path 'couse it will be destroyed by _populate */ + p = eina_stringshare_add(path); + _populate(sdata->fs, p, NULL); + eina_stringshare_del(p); + } + + s = elm_entry_utf8_to_markup(ecore_file_file_get(path)); + if (s) + { + elm_object_text_set(sd->filename_entry, s); + free(s); + } + else elm_object_text_set(sd->filename_entry, ""); + } + + evas_object_smart_callback_call(sdata->fs, SIG_SELECTED, (void *)path); + +end: + sd->sel_idler = NULL; + free(sdata); + return ECORE_CALLBACK_CANCEL; +} + +static void +_on_item_selected(void *data, + Evas_Object *obj __UNUSED__, + void *event_info) +{ + //This event_info could be a list or gengrid item + Elm_Object_Item *it = event_info; + struct sel_data *sdata; + void *old_sd; + char *dir; + + ELM_FILESELECTOR_DATA_GET(data, sd); + + sdata = malloc(sizeof(*sdata)); + sdata->fs = data; + sdata->path = elm_object_item_data_get(it); + + if (!sdata->path) + { + eina_stringshare_replace(&sd->path, ""); + goto end; + } + + dir = sd->only_folder ? strdup(sdata->path) : + ecore_file_dir_get(sdata->path); + if (dir) + { + eina_stringshare_replace(&sd->path, dir); + free(dir); + } + else + { + eina_stringshare_replace(&sd->path, ""); + } + +end: + if (sd->sel_idler) + { + old_sd = ecore_idler_del(sd->sel_idler); + free(old_sd); + } + sd->sel_idler = ecore_idler_add(_sel_do, sdata); +} + +static void +_on_dir_up(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Evas_Object *fs = data; + char *parent; + + ELM_FILESELECTOR_DATA_GET(fs, sd); + + parent = ecore_file_dir_get(sd->path); + _populate(fs, parent, NULL); + free(parent); +} + +static void +_home(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Evas_Object *fs = data; + + _populate(fs, getenv("HOME"), NULL); +} + +static void +_ok(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Evas_Object *fs = data; + + evas_object_smart_callback_call + (fs, SIG_DONE, (void *)elm_fileselector_selected_get(fs)); +} + +static void +_canc(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Evas_Object *fs = data; + + evas_object_smart_callback_call(fs, SIG_DONE, NULL); +} + +static void +_anchor_clicked(void *data, + Evas_Object *obj __UNUSED__, + void *event_info) +{ + Elm_Entry_Anchor_Info *info = event_info; + Evas_Object *fs = data; + const char *p; + + // keep a ref to path 'couse it will be destroyed by _populate + p = eina_stringshare_add(info->name); + _populate(fs, p, NULL); + evas_object_smart_callback_call(data, SIG_SELECTED, (void *)p); + eina_stringshare_del(p); +} + +static void +_elm_fileselector_smart_add(Evas_Object *obj) +{ + Evas_Object *ic, *bt, *li, *en, *grid; unsigned int i; int s; - ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); + EVAS_SMART_DATA_ALLOC(obj, Elm_Fileselector_Smart_Data); + EINA_REFCOUNT_INIT(priv); - EINA_REFCOUNT_INIT(wd); + ELM_WIDGET_CLASS(_elm_fileselector_parent_sc)->base.add(obj); - ELM_SET_WIDTYPE(widtype, "fileselector"); - elm_widget_type_set(obj, "fileselector"); - elm_widget_sub_object_add(parent, obj); - elm_widget_data_set(obj, wd); - elm_widget_del_hook_set(obj, _del_hook); - elm_widget_theme_hook_set(obj, _theme_hook); elm_widget_can_focus_set(obj, EINA_FALSE); - wd->expand = !!_elm_config->fileselector_expand_enable; + priv->expand = !!_elm_config->fileselector_expand_enable; - wd->edje = edje_object_add(e); - _elm_theme_object_set(obj, wd->edje, "fileselector", "base", "default"); - elm_widget_resize_object_set(obj, wd->edje); + elm_layout_theme_set + (obj, "fileselector", "base", elm_widget_style_get(obj)); // up btn - ic = elm_icon_add(parent); + ic = elm_icon_add(obj); elm_icon_standard_set(ic, "arrow_up"); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); - bt = elm_button_add(parent); + bt = elm_button_add(obj); elm_widget_mirrored_automatic_set(bt, EINA_FALSE); elm_object_part_content_set(bt, "icon", ic); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up")); evas_object_size_hint_align_set(bt, 0.0, 0.0); - - evas_object_smart_callback_add(bt, "clicked", _up, obj); + evas_object_smart_callback_add(bt, "clicked", _on_dir_up, obj); elm_widget_sub_object_add(obj, bt); - wd->up_button = bt; + + priv->up_button = bt; // home btn - ic = elm_icon_add(parent); + ic = elm_icon_add(obj); elm_icon_standard_set(ic, "home"); evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); - bt = elm_button_add(parent); + bt = elm_button_add(obj); elm_widget_mirrored_automatic_set(bt, EINA_FALSE); elm_object_part_content_set(bt, "icon", ic); elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home")); evas_object_size_hint_align_set(bt, 0.0, 0.0); - evas_object_smart_callback_add(bt, "clicked", _home, obj); elm_widget_sub_object_add(obj, bt); - wd->home_button = bt; + priv->home_button = bt; for (i = 0; i < ELM_FILE_LAST; ++i) { @@ -880,8 +875,10 @@ elm_fileselector_add(Evas_Object *parent) grid_itc[i] = elm_gengrid_item_class_new(); list_itc[i]->item_style = "default"; - list_itc[i]->func.text_get = grid_itc[i]->func.text_get = _itc_text_get; - list_itc[i]->func.state_get = grid_itc[i]->func.state_get = _itc_state_get; + list_itc[i]->func.text_get = grid_itc[i]->func.text_get = + _itc_text_get; + list_itc[i]->func.state_get = grid_itc[i]->func.state_get = + _itc_state_get; list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del; } @@ -892,37 +889,39 @@ elm_fileselector_add(Evas_Object *parent) list_itc[ELM_FILE_UNKNOW]->func.content_get = grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get; - li = elm_genlist_add(parent); + li = elm_genlist_add(obj); elm_widget_mirrored_automatic_set(li, EINA_FALSE); evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_min_set(li, 100, 100); - grid = elm_gengrid_add(parent); + grid = elm_gengrid_add(obj); elm_widget_mirrored_automatic_set(grid, EINA_FALSE); evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); // XXX: will fail for dynamic finger size changing - s = _elm_config->finger_size * 2; + s = elm_config_finger_size_get() * 2; elm_gengrid_item_size_set(grid, s, s); elm_gengrid_align_set(grid, 0.0, 0.0); - evas_object_smart_callback_add(li, "selected", _sel, obj); - evas_object_smart_callback_add(li, "expand,request", _expand_req, obj); - evas_object_smart_callback_add(li, "contract,request", _contract_req, obj); - evas_object_smart_callback_add(li, "expanded", _expand_done, obj); - evas_object_smart_callback_add(li, "contracted", _contract_done, obj); + evas_object_smart_callback_add(li, "selected", _on_item_selected, obj); + evas_object_smart_callback_add + (li, "expand,request", _on_list_expand_req, obj); + evas_object_smart_callback_add + (li, "contract,request", _on_list_contract_req, obj); + evas_object_smart_callback_add(li, "expanded", _on_list_expanded, obj); + evas_object_smart_callback_add(li, "contracted", _on_list_contracted, obj); - evas_object_smart_callback_add(grid, "selected", _sel, obj); + evas_object_smart_callback_add(grid, "selected", _on_item_selected, obj); elm_widget_sub_object_add(obj, li); elm_widget_sub_object_add(obj, grid); - wd->files_list = li; - wd->files_grid = grid; + priv->files_list = li; + priv->files_grid = grid; // path entry - en = elm_entry_add(parent); + en = elm_entry_add(obj); elm_entry_scrollable_set(en, EINA_TRUE); elm_widget_mirrored_automatic_set(en, EINA_FALSE); elm_entry_editable_set(en, EINA_FALSE); @@ -934,10 +933,10 @@ elm_fileselector_add(Evas_Object *parent) evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj); elm_widget_sub_object_add(obj, en); - wd->path_entry = en; + priv->path_entry = en; // filename entry - en = elm_entry_add(parent); + en = elm_entry_add(obj); elm_entry_scrollable_set(en, EINA_TRUE); elm_widget_mirrored_automatic_set(en, EINA_FALSE); elm_entry_editable_set(en, EINA_TRUE); @@ -947,71 +946,124 @@ elm_fileselector_add(Evas_Object *parent) evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_widget_sub_object_add(obj, en); - wd->filename_entry = en; + priv->filename_entry = en; elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE); elm_fileselector_is_save_set(obj, EINA_FALSE); - _theme_hook(obj); + _elm_fileselector_smart_theme(obj); +} + +static void +_elm_fileselector_smart_del(Evas_Object *obj) +{ + int i; + + ELM_FILESELECTOR_DATA_GET(obj, sd); + + for (i = 0; i < ELM_FILE_LAST; ++i) + { + elm_genlist_item_class_free(list_itc[i]); + elm_gengrid_item_class_free(grid_itc[i]); + } + +#ifdef HAVE_EIO + if (sd->current) eio_file_cancel(sd->current); +#endif + + sd->files_list = NULL; + sd->files_grid = NULL; + + /* this one matching EINA_REFCOUNT_INIT() */ + EINA_REFCOUNT_UNREF(sd) _elm_fileselector_smart_del_do(sd); +} + +static void +_elm_fileselector_smart_set_user(Elm_Layout_Smart_Class *sc) +{ + ELM_WIDGET_CLASS(sc)->base.add = _elm_fileselector_smart_add; + ELM_WIDGET_CLASS(sc)->base.del = _elm_fileselector_smart_del; + + ELM_WIDGET_CLASS(sc)->theme = _elm_fileselector_smart_theme; + + /* not a 'focus chain manager' */ + ELM_WIDGET_CLASS(sc)->focus_next = NULL; + ELM_WIDGET_CLASS(sc)->focus_direction = NULL; + + sc->sizing_eval = _elm_fileselector_smart_sizing_eval; +} + +EAPI Evas_Object * +elm_fileselector_add(Evas_Object *parent) +{ + Evas *e; + Evas_Object *obj; + + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + + e = evas_object_evas_get(parent); + if (!e) return NULL; + + obj = evas_object_smart_add(e, _elm_fileselector_smart_class_new()); + + if (!elm_widget_sub_object_add(parent, obj)) + ERR("could not add %p as sub object of %p", obj, parent); - evas_object_smart_callbacks_descriptions_set(obj, _signals); return obj; } EAPI void elm_fileselector_is_save_set(Evas_Object *obj, - Eina_Bool is_save) + Eina_Bool is_save) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; + ELM_FILESELECTOR_CHECK(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); - elm_object_disabled_set(wd->filename_entry, !is_save); + elm_object_disabled_set(sd->filename_entry, !is_save); - if (is_save) - edje_object_signal_emit(wd->edje, "elm,state,save,on", "elm"); - else - edje_object_signal_emit(wd->edje, "elm,state,save,off", "elm"); + if (is_save) elm_layout_signal_emit(obj, "elm,state,save,on", "elm"); + else elm_layout_signal_emit(obj, "elm,state,save,off", "elm"); } EAPI Eina_Bool elm_fileselector_is_save_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return !elm_object_disabled_get(wd->filename_entry); + ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; + ELM_FILESELECTOR_DATA_GET(obj, sd); + + return !elm_object_disabled_get(sd->filename_entry); } EAPI void elm_fileselector_folder_only_set(Evas_Object *obj, - Eina_Bool only) + Eina_Bool only) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->only_folder == only) return; - wd->only_folder = !!only; - if (wd->path) _populate(obj, wd->path, NULL); + ELM_FILESELECTOR_CHECK(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); + + if (sd->only_folder == only) return; + + sd->only_folder = !!only; + if (sd->path) _populate(obj, sd->path, NULL); } EAPI Eina_Bool elm_fileselector_folder_only_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->only_folder; + ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; + ELM_FILESELECTOR_DATA_GET(obj, sd); + + return sd->only_folder; } EAPI void elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj, - Eina_Bool visible) + Eina_Bool visible) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); Evas_Object *bt; - if (!wd) return; + + ELM_FILESELECTOR_CHECK(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); if (visible) { @@ -1023,7 +1075,7 @@ elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj, evas_object_smart_callback_add(bt, "clicked", _canc, obj); elm_widget_sub_object_add(obj, bt); - wd->cancel_button = bt; + sd->cancel_button = bt; // ok btn bt = elm_button_add(obj); @@ -1033,58 +1085,57 @@ elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj, evas_object_smart_callback_add(bt, "clicked", _ok, obj); elm_widget_sub_object_add(obj, bt); - wd->ok_button = bt; + sd->ok_button = bt; - _theme_hook(obj); + _elm_fileselector_smart_theme(obj); } else { - evas_object_del(wd->cancel_button); - wd->cancel_button = NULL; - evas_object_del(wd->ok_button); - wd->ok_button = NULL; + evas_object_del(sd->cancel_button); + sd->cancel_button = NULL; + evas_object_del(sd->ok_button); + sd->ok_button = NULL; } } EAPI Eina_Bool elm_fileselector_buttons_ok_cancel_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->ok_button ? EINA_TRUE : EINA_FALSE; + ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; + ELM_FILESELECTOR_DATA_GET(obj, sd); + + return sd->ok_button ? EINA_TRUE : EINA_FALSE; } EAPI void elm_fileselector_expandable_set(Evas_Object *obj, - Eina_Bool expand) + Eina_Bool expand) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd; + ELM_FILESELECTOR_CHECK(obj); + ELM_FILESELECTOR_DATA_GET(obj, sd); - wd = elm_widget_data_get(obj); - if (!wd) return; + sd->expand = !!expand; - wd->expand = !!expand; - - if (wd->path) _populate(obj, wd->path, NULL); + if (sd->path) _populate(obj, sd->path, NULL); } EAPI Eina_Bool elm_fileselector_expandable_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->expand; + ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; + ELM_FILESELECTOR_DATA_GET(obj, sd); + + return sd->expand; } EAPI void elm_fileselector_path_set(Evas_Object *obj, - const char *_path) + const char *_path) { - ELM_CHECK_WIDTYPE(obj, widtype); char *path; + + ELM_FILESELECTOR_CHECK(obj); + path = ecore_file_realpath(_path); _populate(obj, path, NULL); free(path); @@ -1093,79 +1144,59 @@ elm_fileselector_path_set(Evas_Object *obj, EAPI const char * elm_fileselector_path_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - return wd->path; + ELM_FILESELECTOR_CHECK(obj) NULL; + ELM_FILESELECTOR_DATA_GET(obj, sd); + + return sd->path; } EAPI void -elm_fileselector_mode_set(Evas_Object *obj, +elm_fileselector_mode_set(Evas_Object *obj, Elm_Fileselector_Mode mode) { - ELM_CHECK_WIDTYPE(obj, widtype); + ELM_FILESELECTOR_CHECK(obj); + + ELM_FILESELECTOR_DATA_GET(obj, sd); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; + if (mode == sd->mode) return; - if (mode == wd->mode) return; + evas_object_hide(elm_layout_content_unset(obj, "elm.swallow.files")); if (mode == ELM_FILESELECTOR_LIST) - { - if (edje_object_part_swallow(wd->edje, "elm.swallow.files", - wd->files_list)) - { - evas_object_show(wd->files_list); - evas_object_hide(wd->files_grid); - } - else - evas_object_hide(wd->files_list); - } - else - { - if (edje_object_part_swallow(wd->edje, "elm.swallow.files", - wd->files_grid)) - { - evas_object_show(wd->files_grid); - evas_object_hide(wd->files_list); - } - else - evas_object_hide(wd->files_grid); - } + elm_layout_content_set(obj, "elm.swallow.files", sd->files_list); + else elm_layout_content_set(obj, "elm.swallow.files", sd->files_grid); - wd->mode = mode; + sd->mode = mode; - _populate(obj, wd->path, NULL); + _populate(obj, sd->path, NULL); } EAPI Elm_Fileselector_Mode elm_fileselector_mode_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) ELM_FILESELECTOR_LAST; - - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return ELM_FILESELECTOR_LAST; + ELM_FILESELECTOR_CHECK(obj) ELM_FILESELECTOR_LAST; + ELM_FILESELECTOR_DATA_GET(obj, sd); - return wd->mode; + return sd->mode; } EAPI const char * elm_fileselector_selected_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; + ELM_FILESELECTOR_CHECK(obj) NULL; + ELM_FILESELECTOR_DATA_GET(obj, sd); - if (!wd->path) return NULL; - - if (wd->filename_entry) + if (!sd->path) return NULL; + + if (sd->filename_entry) { - const char *name; char buf[PATH_MAX]; + const char *name; char *dir, *s; - dir = wd->only_folder ? ecore_file_dir_get(wd->path) : strdup(wd->path); - name = elm_object_text_get(wd->filename_entry); + dir = sd->only_folder ? ecore_file_dir_get(sd->path) + : strdup(sd->path); + name = elm_object_text_get(sd->filename_entry); if (name) { s = elm_entry_markup_to_utf8(name); @@ -1174,49 +1205,47 @@ elm_fileselector_selected_get(const Evas_Object *obj) snprintf(buf, sizeof(buf), "%s/%s", dir, s); free(s); } - else - snprintf(buf, sizeof(buf), "%s", dir); - } - else - { - snprintf(buf, sizeof(buf), "%s", dir); + else snprintf(buf, sizeof(buf), "%s", dir); } - if (wd->only_folder && !ecore_file_is_dir(buf)) - eina_stringshare_replace(&wd->selection, ecore_file_dir_get(buf)); - else - eina_stringshare_replace(&wd->selection, buf); + else snprintf(buf, sizeof(buf), "%s", dir); + + if (sd->only_folder && !ecore_file_is_dir(buf)) + eina_stringshare_replace(&sd->selection, ecore_file_dir_get(buf)); + else eina_stringshare_replace(&sd->selection, buf); + if (dir) free(dir); - return wd->selection; + return sd->selection; } - if (wd->mode == ELM_FILESELECTOR_LIST) + if (sd->mode == ELM_FILESELECTOR_LIST) { - Elm_Object_Item *gl_it = elm_genlist_selected_item_get(wd->files_list); + Elm_Object_Item *gl_it = elm_genlist_selected_item_get(sd->files_list); + if (gl_it) return elm_object_item_data_get(gl_it); } else { - Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(wd->files_grid); + Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(sd->files_grid); + if (gg_it) return elm_object_item_data_get(gg_it); } - return wd->path; + return sd->path; } EAPI Eina_Bool elm_fileselector_selected_set(Evas_Object *obj, - const char *_path) + const char *_path) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - Eina_Bool ret = EINA_TRUE; char *path; + + ELM_FILESELECTOR_CHECK(obj) EINA_FALSE; + ELM_FILESELECTOR_DATA_GET(obj, sd); + path = ecore_file_realpath(_path); - if (ecore_file_is_dir(path)) - _populate(obj, path, NULL); + if (ecore_file_is_dir(path)) _populate(obj, path, NULL); else { if (!ecore_file_exists(path)) @@ -1226,19 +1255,19 @@ elm_fileselector_selected_set(Evas_Object *obj, } _populate(obj, ecore_file_dir_get(path), NULL); - if (wd->filename_entry) + if (sd->filename_entry) { char *s; - + s = elm_entry_utf8_to_markup(ecore_file_file_get(path)); if (s) { - elm_object_text_set(wd->filename_entry, s); + elm_object_text_set(sd->filename_entry, s); free(s); } - else - elm_object_text_set(wd->filename_entry, ""); - eina_stringshare_replace(&wd->selection, path); + else elm_object_text_set(sd->filename_entry, ""); + + eina_stringshare_replace(&sd->selection, path); } } @@ -1246,4 +1275,3 @@ clean_up: free(path); return ret; } - diff --git a/src/lib/elc_fileselector.h b/src/lib/elc_fileselector.h index bf11c67..7e0a4e8 100644 --- a/src/lib/elc_fileselector.h +++ b/src/lib/elc_fileselector.h @@ -31,8 +31,11 @@ * library, the second form of view will display preview thumbnails * of files which it supports. * - * Smart callbacks one can register to: + * This widget inherits from the @ref Layout one, so that all the + * functions acting on it also work for file selector objects. * + * This widget emits the following signals, besides the ones sent from + * @ref Layout: * - @c "selected" - the user has clicked on a file (when not in * folders-only mode) or directory (when in folders-only mode) * - @c "directory,open" - the list has been populated with new -- 2.7.4