1 #include <Elementary.h>
5 * @defgroup File_Selector_Button File Selector Button
7 * A button that, when clicked, creates an Elementary window (or inner
8 * window) with an Elementary File Selector within. When a file is
9 * chosen, the (inner) window is closed and the selected file is
10 * exposed as an evas_object_smart_callback_call() of the button.
13 typedef struct _Widget_Data Widget_Data;
17 Evas_Object *self, *btn, *fs, *fsw;
18 const char *window_title;
23 Eina_Bool expandable : 1;
24 Eina_Bool folder_only : 1;
25 Eina_Bool is_save : 1;
27 Eina_Bool inwin_mode : 1;
30 #define DEFAULT_WINDOW_TITLE "Select a file"
32 static const char *widtype = NULL;
34 static void _del_hook(Evas_Object *obj);
35 static void _theme_hook(Evas_Object *obj);
36 static void _disable_hook(Evas_Object *obj);
37 static void _sizing_eval(Evas_Object *obj);
38 static void _changed_size_hints(void *data,
42 static void _on_focus_hook(void *data,
44 static void _selection_done(void *data,
47 static void _activate(Widget_Data *wd);
49 static const char SIG_FILE_CHOSEN[] = "file,chosen";
50 static const Evas_Smart_Cb_Description _signals[] = {
51 {SIG_FILE_CHOSEN, "s"},
56 _del_hook(Evas_Object *obj)
61 wd = elm_widget_data_get(obj);
64 if (wd->window_title) eina_stringshare_del(wd->window_title);
65 if (wd->fsd.path) eina_stringshare_del(wd->fsd.path);
68 win = evas_object_data_del(obj, "win");
75 _on_focus_hook(void *data __UNUSED__,
78 Widget_Data *wd = elm_widget_data_get(obj);
80 if (elm_widget_focus_get(obj))
81 elm_widget_focus_steal(wd->btn);
85 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
87 Widget_Data *wd = elm_widget_data_get(obj);
89 elm_widget_mirrored_set(wd->btn, rtl);
90 elm_widget_mirrored_set(wd->fs, rtl);
94 _theme_hook(Evas_Object *obj)
96 Widget_Data *wd = elm_widget_data_get(obj);
99 _mirrored_set(obj, elm_widget_mirrored_get(obj));
100 snprintf(buf, sizeof(buf), "fileselector_button/%s",
101 elm_widget_style_get(obj));
102 elm_object_style_set(wd->btn, buf);
107 _disable_hook(Evas_Object *obj)
109 Widget_Data *wd = elm_widget_data_get(obj);
111 elm_widget_disabled_set(wd->btn, elm_widget_disabled_get(obj));
115 _sizing_eval(Evas_Object *obj)
117 Widget_Data *wd = elm_widget_data_get(obj);
118 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
120 evas_object_size_hint_min_get(wd->btn, &minw, &minh);
121 evas_object_size_hint_max_get(wd->btn, &maxw, &maxh);
122 evas_object_size_hint_min_set(obj, minw, minh);
123 evas_object_size_hint_max_set(obj, maxw, maxh);
127 _changed_size_hints(void *data,
129 Evas_Object *obj __UNUSED__,
130 void *event_info __UNUSED__)
132 Widget_Data *wd = elm_widget_data_get(data);
138 _activate_hook(Evas_Object *obj)
141 wd = elm_widget_data_get(obj);
147 _button_clicked(void *data,
148 Evas_Object *obj __UNUSED__,
149 void *event_info __UNUSED__)
155 _parent_win_get(Evas_Object *obj)
157 while ((obj) && (strcmp(elm_widget_type_get(obj), "win")))
158 obj = elm_object_parent_widget_get(obj);
164 _new_window_add(Widget_Data *wd)
166 Evas_Object *win, *bg;
168 win = elm_win_add(NULL, "fileselector_button", ELM_WIN_DIALOG_BASIC);
169 elm_win_title_set(win, wd->window_title);
170 elm_win_autodel_set(win, EINA_TRUE);
172 bg = elm_bg_add(win);
173 elm_win_resize_object_add(win, bg);
174 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
175 evas_object_show(bg);
177 evas_object_resize(win, wd->w, wd->h);
182 _activate(Widget_Data *wd)
184 Eina_Bool is_inwin = EINA_FALSE;
190 wd->fsw = _parent_win_get(wd->self);
193 wd->fsw = _new_window_add(wd);
196 wd->fsw = elm_win_inwin_add(wd->fsw);
197 is_inwin = EINA_TRUE;
201 wd->fsw = _new_window_add(wd);
203 wd->fs = elm_fileselector_add(wd->fsw);
204 elm_widget_mirrored_set(wd->fs, elm_widget_mirrored_get(wd->self));
205 elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
206 elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
207 elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
208 elm_fileselector_selected_set(wd->fs, wd->fsd.path);
209 evas_object_size_hint_weight_set(wd->fs, EVAS_HINT_EXPAND,
211 evas_object_size_hint_align_set(wd->fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
212 evas_object_smart_callback_add(wd->fs, "done", _selection_done, wd);
213 evas_object_show(wd->fs);
217 elm_win_inwin_content_set(wd->fsw, wd->fs);
218 elm_win_inwin_activate(wd->fsw);
222 elm_win_resize_object_add(wd->fsw, wd->fs);
223 evas_object_show(wd->fsw);
228 _selection_done(void *data,
229 Evas_Object *obj __UNUSED__,
232 const char *file = event_info;
233 Widget_Data *wd = data;
237 if (file) eina_stringshare_replace(&wd->fsd.path, file);
242 evas_object_del(del);
244 evas_object_smart_callback_call(wd->self, SIG_FILE_CHOSEN,
245 (void *)wd->fsd.path);
249 * Add a new file selector button into the parent object.
251 * @param parent The parent object
252 * @return The new object or NULL if it cannot be created
254 * @ingroup File_Selector_Button
257 elm_fileselector_button_add(Evas_Object *parent)
263 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
265 wd = ELM_NEW(Widget_Data);
266 wd->window_title = eina_stringshare_add(DEFAULT_WINDOW_TITLE);
267 wd->fsd.path = eina_stringshare_add(getenv("HOME"));
268 wd->fsd.expandable = _elm_config->fileselector_expand_enable;
269 wd->inwin_mode = _elm_config->inwin_dialogs_enable;
273 e = evas_object_evas_get(parent);
275 obj = elm_widget_add(e);
276 ELM_SET_WIDTYPE(widtype, "fileselector_button");
277 elm_widget_type_set(obj, "fileselector_button");
278 elm_widget_sub_object_add(parent, obj);
280 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
281 elm_widget_data_set(obj, wd);
282 elm_widget_del_hook_set(obj, _del_hook);
283 elm_widget_theme_hook_set(obj, _theme_hook);
284 elm_widget_disable_hook_set(obj, _disable_hook);
285 elm_widget_can_focus_set(obj, EINA_TRUE);
286 elm_widget_activate_hook_set(obj, _activate_hook);
288 wd->btn = elm_button_add(parent);
289 elm_widget_resize_object_set(obj, wd->btn);
290 evas_object_event_callback_add(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
291 _changed_size_hints, obj);
292 evas_object_smart_callback_add(wd->btn, "clicked", _button_clicked, wd);
293 elm_widget_sub_object_add(obj, wd->btn);
296 evas_object_smart_callbacks_descriptions_set(obj, _signals);
301 * Set the label used in the file selector button.
303 * @param obj The button object
304 * @param label The text label text to be displayed on the button
306 * @ingroup File_Selector_Button
309 elm_fileselector_button_label_set(Evas_Object *obj,
312 ELM_CHECK_WIDTYPE(obj, widtype);
313 Widget_Data *wd = elm_widget_data_get(obj);
315 elm_button_label_set(wd->btn, label);
319 * Get the label used in the file selector button.
321 * @param obj The button object
322 * @return The button label
324 * @ingroup File_Selector_Button
327 elm_fileselector_button_label_get(const Evas_Object *obj)
329 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
330 Widget_Data *wd = elm_widget_data_get(obj);
331 if (!wd) return NULL;
332 return elm_button_label_get(wd->btn);
336 * Set the title of the file selector button's window.
338 * @param obj The button object
339 * @param title The title string
341 * Note that it will only take any effect if the fileselector button
342 * not at "inwin mode".
344 * @ingroup File_Selector_Button
347 elm_fileselector_button_window_title_set(Evas_Object *obj,
350 ELM_CHECK_WIDTYPE(obj, widtype);
351 Widget_Data *wd = elm_widget_data_get(obj);
354 eina_stringshare_replace(&wd->window_title, title);
357 elm_win_title_set(wd->fsw, wd->window_title);
361 * Get the title of the file selector button's window.
363 * @param obj The button object
364 * @return Title of the file selector button's window
366 * @ingroup File_Selector_Button
369 elm_fileselector_button_window_title_get(const Evas_Object *obj)
371 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
372 Widget_Data *wd = elm_widget_data_get(obj);
374 if (!wd) return NULL;
375 return wd->window_title;
379 * Set the size of the file selector button's window.
381 * @param obj The button object
382 * @param width The width
383 * @param height The height
385 * Note that it will only take any effect if the fileselector button not at
386 * "inwin mode". Default size for the window (when applicable) is 400x400.
388 * @ingroup File_Selector_Button
391 elm_fileselector_button_window_size_set(Evas_Object *obj,
395 ELM_CHECK_WIDTYPE(obj, widtype);
396 Widget_Data *wd = elm_widget_data_get(obj);
403 evas_object_resize(wd->fsw, wd->w, wd->h);
407 * Get the size of the file selector button's window.
409 * @param obj The button object
410 * @param width Pointer into which to store the width value
411 * @param height Pointer into which to store the height value
413 * @ingroup File_Selector_Button
416 elm_fileselector_button_window_size_get(const Evas_Object *obj,
420 ELM_CHECK_WIDTYPE(obj, widtype);
421 Widget_Data *wd = elm_widget_data_get(obj);
424 if (width) *width = wd->w;
425 if (height) *height = wd->h;
429 * Set the starting path of the file selector button's window.
431 * @param obj The button object
432 * @param path The path string
434 * It must be a <b>directory</b> path.
435 * Default path is "HOME" environment variable's value.
437 * @ingroup File_Selector_Button
440 elm_fileselector_button_path_set(Evas_Object *obj,
443 ELM_CHECK_WIDTYPE(obj, widtype);
444 Widget_Data *wd = elm_widget_data_get(obj);
447 eina_stringshare_replace(&wd->fsd.path, path);
450 elm_fileselector_selected_set(wd->fs, wd->fsd.path);
454 * Get the <b>last</b> path of the file selector button's window.
456 * @param obj The button object
458 * @ingroup File_Selector_Button
461 elm_fileselector_button_path_get(const Evas_Object *obj)
463 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
464 Widget_Data *wd = elm_widget_data_get(obj);
465 if (!wd) return NULL;
470 * Set whether the button's file selector is to present itself as an
471 * Elementary Generic List (which will expand its entries for nested
472 * directories) or as canonical list, which will be rendered again
473 * with the contents of each selected directory.
475 * @param obj The button object
476 * @param value The expandable flag
478 * @ingroup File_Selector_Button
481 elm_fileselector_button_expandable_set(Evas_Object *obj,
484 ELM_CHECK_WIDTYPE(obj, widtype);
485 Widget_Data *wd = elm_widget_data_get(obj);
488 wd->fsd.expandable = value;
491 elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
495 * Get the button's file selector expandable flag.
497 * @param obj The button object
498 * @return value The expandable flag
500 * @ingroup File_Selector_Button
503 elm_fileselector_button_expandable_get(const Evas_Object *obj)
505 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
506 Widget_Data *wd = elm_widget_data_get(obj);
508 if (!wd) return EINA_FALSE;
509 return wd->fsd.expandable;
513 * Set whether the button's file selector list is to display folders
514 * only or the directory contents, as well.
516 * @param obj The button object
517 * @param value The "folder only" flag
519 * @ingroup File_Selector_Button
522 elm_fileselector_button_folder_only_set(Evas_Object *obj,
525 ELM_CHECK_WIDTYPE(obj, widtype);
526 Widget_Data *wd = elm_widget_data_get(obj);
529 wd->fsd.folder_only = value;
532 elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
536 * Get the button's file selector "folder only" flag.
538 * @param obj The button object
539 * @return value The "folder only" flag
541 * @ingroup File_Selector_Button
544 elm_fileselector_button_folder_only_get(const Evas_Object *obj)
546 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
547 Widget_Data *wd = elm_widget_data_get(obj);
549 if (!wd) return EINA_FALSE;
550 return wd->fsd.folder_only;
554 * Set whether the button's file selector has an editable text entry
555 * which will hold its current selection.
557 * @param obj The button object
558 * @param value The "is save" flag
560 * @ingroup File_Selector_Button
563 elm_fileselector_button_is_save_set(Evas_Object *obj,
566 ELM_CHECK_WIDTYPE(obj, widtype);
567 Widget_Data *wd = elm_widget_data_get(obj);
570 wd->fsd.is_save = value;
573 elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
577 * Get the button's file selector "is save" flag.
579 * @param obj The button object
580 * @return value The "is save" flag
582 * @ingroup File_Selector_Button
585 elm_fileselector_button_is_save_get(const Evas_Object *obj)
587 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
588 Widget_Data *wd = elm_widget_data_get(obj);
590 if (!wd) return EINA_FALSE;
591 return wd->fsd.is_save;
595 * Set whether the button's file selector will raise an Elementary
596 * Inner Window, instead of a dedicated Elementary Window. By default,
599 * @param obj The button object
600 * @param value The "inwin mode" flag
602 * @ingroup File_Selector_Button
605 elm_fileselector_button_inwin_mode_set(Evas_Object *obj,
608 ELM_CHECK_WIDTYPE(obj, widtype);
609 Widget_Data *wd = elm_widget_data_get(obj);
612 wd->inwin_mode = value;
616 * Get the button's file selector "inwin mode" flag.
618 * @param obj The button object
619 * @return value The "inwin mode" flag
621 * @ingroup File_Selector_Button
624 elm_fileselector_button_inwin_mode_get(const Evas_Object *obj)
626 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
627 Widget_Data *wd = elm_widget_data_get(obj);
629 if (!wd) return EINA_FALSE;
630 return wd->inwin_mode;
634 * Set the icon used for the button
636 * Once the icon object is set, a previously set one will be deleted.
637 * If you want to keep that old content object, use the
638 * elm_fileselector_button_icon_unset() function.
640 * @param obj The button object
641 * @param icon The icon object for the button
643 * @ingroup File_Selector_Button
646 elm_fileselector_button_icon_set(Evas_Object *obj,
649 ELM_CHECK_WIDTYPE(obj, widtype);
650 Widget_Data *wd = elm_widget_data_get(obj);
653 evas_object_del(icon);
656 elm_button_icon_set(wd->btn, icon);
660 * Get the icon used for the button
662 * @param obj The button object
663 * @return The icon object that is being used
665 * @ingroup File_Selector_Button
668 elm_fileselector_button_icon_get(const Evas_Object *obj)
670 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
671 Widget_Data *wd = elm_widget_data_get(obj);
672 if (!wd) return NULL;
673 return elm_button_icon_get(wd->btn);
677 * Unset the icon used for the button
679 * Unparent and return the icon object which was set for this widget.
681 * @param obj The button object
682 * @return The icon object that was being used
684 * @ingroup File_Selector_Button
687 elm_fileselector_button_icon_unset(Evas_Object *obj)
689 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
690 Widget_Data *wd = elm_widget_data_get(obj);
691 if (!wd) return NULL;
692 return elm_button_icon_unset(wd->btn);