[access] call a callback function with information
[framework/uifw/elementary.git] / src / lib / elc_fileselector_entry.c
1 //FIXME this widget should inherit from file selector button
2
3 #include <Elementary.h>
4 #include "elm_priv.h"
5 #include "elm_widget_fileselector_entry.h"
6
7 EAPI const char ELM_FILESELECTOR_ENTRY_SMART_NAME[] = "elm_fileselector_entry";
8
9 static const char SIG_CHANGED[] = "changed";
10 static const char SIG_ACTIVATED[] = "activated";
11 static const char SIG_PRESS[] = "press";
12 static const char SIG_LONGPRESSED[] = "longpressed";
13 static const char SIG_CLICKED[] = "clicked";
14 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
15 static const char SIG_FOCUSED[] = "focused";
16 static const char SIG_UNFOCUSED[] = "unfocused";
17 static const char SIG_SELECTION_PASTE[] = "selection,paste";
18 static const char SIG_SELECTION_COPY[] = "selection,copy";
19 static const char SIG_SELECTION_CUT[] = "selection,cut";
20 static const char SIG_UNPRESSED[] = "unpressed";
21 static const char SIG_FILE_CHOSEN[] = "file,chosen";
22 static const Evas_Smart_Cb_Description _smart_callbacks[] =
23 {
24    {SIG_CHANGED, ""},
25    {SIG_ACTIVATED, ""},
26    {SIG_PRESS, ""},
27    {SIG_LONGPRESSED, ""},
28    {SIG_CLICKED, ""},
29    {SIG_CLICKED_DOUBLE, ""},
30    {SIG_FOCUSED, ""},
31    {SIG_UNFOCUSED, ""},
32    {SIG_SELECTION_PASTE, ""},
33    {SIG_SELECTION_COPY, ""},
34    {SIG_SELECTION_CUT, ""},
35    {SIG_UNPRESSED, ""},
36    {SIG_FILE_CHOSEN, "s"},
37    {NULL, NULL}
38 };
39
40 #define SIG_FWD(name)                                                       \
41   static void                                                               \
42   _##name##_fwd(void *data, Evas_Object * obj __UNUSED__, void *event_info) \
43   {                                                                         \
44      evas_object_smart_callback_call(data, SIG_##name, event_info);         \
45   }
46 SIG_FWD(CHANGED)
47 SIG_FWD(PRESS)
48 SIG_FWD(LONGPRESSED)
49 SIG_FWD(CLICKED)
50 SIG_FWD(CLICKED_DOUBLE)
51 SIG_FWD(FOCUSED)
52 SIG_FWD(UNFOCUSED)
53 SIG_FWD(SELECTION_PASTE)
54 SIG_FWD(SELECTION_COPY)
55 SIG_FWD(SELECTION_CUT)
56 SIG_FWD(UNPRESSED)
57 #undef SIG_FWD
58
59 EVAS_SMART_SUBCLASS_NEW
60   (ELM_FILESELECTOR_ENTRY_SMART_NAME, _elm_fileselector_entry,
61   Elm_Fileselector_Entry_Smart_Class, Elm_Layout_Smart_Class,
62   elm_layout_smart_class_get, _smart_callbacks);
63
64 static void
65 _FILE_CHOSEN_fwd(void *data,
66                  Evas_Object *obj __UNUSED__,
67                  void *event_info)
68 {
69    const char *file = event_info;
70    char *s;
71
72    ELM_FILESELECTOR_ENTRY_DATA_GET(data, sd);
73
74    s = elm_entry_utf8_to_markup(file);
75    if (!s) return;
76    elm_object_text_set(sd->entry, s);
77    free(s);
78    evas_object_smart_callback_call(data, SIG_FILE_CHOSEN, event_info);
79 }
80
81 static void
82 _ACTIVATED_fwd(void *data,
83                Evas_Object *obj __UNUSED__,
84                void *event_info)
85 {
86    const char *file;
87
88    ELM_FILESELECTOR_ENTRY_DATA_GET(data, sd);
89
90    file = elm_object_text_get(sd->entry);
91    elm_fileselector_button_path_set(sd->button, file);
92    evas_object_smart_callback_call(data, SIG_ACTIVATED, event_info);
93 }
94
95 static void
96 _elm_fileselector_entry_smart_sizing_eval(Evas_Object *obj)
97 {
98    Evas_Coord minw = -1, minh = -1;
99
100    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
101
102    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
103    evas_object_size_hint_min_set(obj, minw, minh);
104    evas_object_size_hint_max_set(obj, -1, -1);
105 }
106
107 static Eina_Bool
108 _elm_fileselector_entry_smart_focus_next(const Evas_Object *obj,
109                                          Elm_Focus_Direction dir,
110                                          Evas_Object **next)
111 {
112    Evas_Object *chain[2];
113    Evas_Object *to_focus;
114    unsigned char i;
115
116    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
117
118    /* Direction */
119    if (dir == ELM_FOCUS_PREVIOUS)
120      {
121         chain[0] = sd->button;
122         chain[1] = sd->entry;
123      }
124    else if (dir == ELM_FOCUS_NEXT)
125      {
126         chain[0] = sd->entry;
127         chain[1] = sd->button;
128      }
129    else
130      return EINA_FALSE;
131
132    i = elm_widget_focus_get(chain[1]);
133
134    if (elm_widget_focus_next_get(chain[i], dir, next))
135      return EINA_TRUE;
136
137    i = !i;
138
139    if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
140      {
141         *next = to_focus;
142         return !!i;
143      }
144
145    return EINA_FALSE;
146 }
147
148 static void
149 _mirrored_set(Evas_Object *obj,
150               Eina_Bool rtl)
151 {
152    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
153
154    elm_widget_mirrored_set(sd->button, rtl);
155 }
156
157 static Eina_Bool
158 _elm_fileselector_entry_smart_theme(Evas_Object *obj)
159 {
160    const char *style;
161    char buf[1024];
162
163    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
164
165    if (!ELM_WIDGET_CLASS(_elm_fileselector_entry_parent_sc)->theme(obj))
166      return EINA_FALSE;
167
168    style = elm_widget_style_get(obj);
169
170    _mirrored_set(obj, elm_widget_mirrored_get(obj));
171
172    if (elm_object_disabled_get(obj))
173      elm_layout_signal_emit(obj, "elm,state,disabled", "elm");
174
175    if (!style) style = "default";
176    snprintf(buf, sizeof(buf), "fileselector_entry/%s", style);
177    elm_widget_style_set(sd->button, buf);
178    elm_widget_style_set(sd->entry, buf);
179
180    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
181
182    elm_layout_sizing_eval(obj);
183
184    return EINA_TRUE;
185 }
186
187 static Eina_Bool
188 _elm_fileselector_entry_smart_disable(Evas_Object *obj)
189 {
190    Eina_Bool val;
191
192    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
193
194    if (!ELM_WIDGET_CLASS(_elm_fileselector_entry_parent_sc)->disable(obj))
195      return EINA_FALSE;
196
197    val = elm_widget_disabled_get(obj);
198
199    elm_widget_disabled_set(sd->button, val);
200    elm_widget_disabled_set(sd->entry, val);
201
202    return EINA_TRUE;
203 }
204
205 static Eina_Bool
206 _elm_fileselector_entry_smart_text_set(Evas_Object *obj,
207                                        const char *item,
208                                        const char *label)
209 {
210    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
211
212    if (item && strcmp(item, "default"))
213      return _elm_fileselector_entry_parent_sc->text_set(obj, item, label);
214
215    elm_object_text_set(sd->button, label);
216
217    return EINA_TRUE;
218 }
219
220 static const char *
221 _elm_fileselector_entry_smart_text_get(const Evas_Object *obj,
222                                        const char *item)
223 {
224    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
225
226    if (item && strcmp(item, "default"))
227      return _elm_fileselector_entry_parent_sc->text_get(obj, item);
228
229    return elm_object_text_get(sd->button);
230 }
231
232 static Eina_Bool
233 _elm_fileselector_entry_smart_content_set(Evas_Object *obj,
234                                           const char *part,
235                                           Evas_Object *content)
236 {
237    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
238
239    if (part && strcmp(part, "button icon"))
240      return ELM_CONTAINER_CLASS(_elm_fileselector_entry_parent_sc)->content_set
241               (obj, part, content);
242
243    elm_layout_content_set(sd->button, NULL, content);
244
245    return EINA_TRUE;
246 }
247
248 static Evas_Object *
249 _elm_fileselector_entry_smart_content_get(const Evas_Object *obj,
250                                           const char *part)
251 {
252    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
253
254    if (part && strcmp(part, "button icon"))
255      return ELM_CONTAINER_CLASS(_elm_fileselector_entry_parent_sc)->
256             content_get(obj, part);
257
258    return elm_layout_content_get(sd->button, NULL);
259 }
260
261 static Evas_Object *
262 _elm_fileselector_entry_smart_content_unset(Evas_Object *obj,
263                                             const char *part)
264 {
265    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
266    if (part && strcmp(part, "button icon"))
267      return ELM_CONTAINER_CLASS(_elm_fileselector_entry_parent_sc)->
268             content_unset(obj, part);
269
270    return elm_layout_content_unset(sd->button, NULL);
271 }
272
273 static void
274 _elm_fileselector_entry_smart_add(Evas_Object *obj)
275 {
276    EVAS_SMART_DATA_ALLOC(obj, Elm_Fileselector_Entry_Smart_Data);
277
278    ELM_WIDGET_CLASS(_elm_fileselector_entry_parent_sc)->base.add(obj);
279
280    elm_layout_theme_set
281      (obj, "fileselector_entry", "base", elm_widget_style_get(obj));
282
283    priv->button = elm_fileselector_button_add(obj);
284    elm_widget_mirrored_automatic_set(priv->button, EINA_FALSE);
285    elm_widget_style_set(priv->button, "fileselector_entry/default");
286
287    elm_layout_content_set(obj, "elm.swallow.button", priv->button);
288    elm_fileselector_button_expandable_set
289      (priv->button, _elm_config->fileselector_expand_enable);
290
291 #define SIG_FWD(name) \
292   evas_object_smart_callback_add(priv->button, SIG_##name, _##name##_fwd, obj)
293    SIG_FWD(CLICKED);
294    SIG_FWD(UNPRESSED);
295    SIG_FWD(FILE_CHOSEN);
296 #undef SIG_FWD
297
298    priv->entry = elm_entry_add(obj);
299    elm_entry_scrollable_set(priv->entry, EINA_TRUE);
300    elm_widget_mirrored_automatic_set(priv->entry, EINA_FALSE);
301    elm_widget_style_set(priv->entry, "fileselector_entry/default");
302    elm_entry_single_line_set(priv->entry, EINA_TRUE);
303    elm_entry_editable_set(priv->entry, EINA_TRUE);
304    elm_layout_content_set(obj, "elm.swallow.entry", priv->entry);
305
306 #define SIG_FWD(name) \
307   evas_object_smart_callback_add(priv->entry, SIG_##name, _##name##_fwd, obj)
308    SIG_FWD(CHANGED);
309    SIG_FWD(ACTIVATED);
310    SIG_FWD(PRESS);
311    SIG_FWD(LONGPRESSED);
312    SIG_FWD(CLICKED);
313    SIG_FWD(CLICKED_DOUBLE);
314    SIG_FWD(FOCUSED);
315    SIG_FWD(UNFOCUSED);
316    SIG_FWD(SELECTION_PASTE);
317    SIG_FWD(SELECTION_COPY);
318    SIG_FWD(SELECTION_CUT);
319 #undef SIG_FWD
320
321    elm_widget_can_focus_set(obj, EINA_FALSE);
322
323    _mirrored_set(obj, elm_widget_mirrored_get(obj));
324    elm_layout_sizing_eval(obj);
325 }
326
327 static void
328 _elm_fileselector_entry_smart_del(Evas_Object *obj)
329 {
330    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
331
332    if (sd->path) free(sd->path);
333
334    ELM_WIDGET_CLASS(_elm_fileselector_entry_parent_sc)->base.del(obj);
335 }
336
337 static void
338 _elm_fileselector_entry_smart_set_user(Elm_Fileselector_Entry_Smart_Class *sc)
339 {
340    ELM_WIDGET_CLASS(sc)->base.add = _elm_fileselector_entry_smart_add;
341    ELM_WIDGET_CLASS(sc)->base.del = _elm_fileselector_entry_smart_del;
342
343    ELM_WIDGET_CLASS(sc)->disable = _elm_fileselector_entry_smart_disable;
344    ELM_WIDGET_CLASS(sc)->theme = _elm_fileselector_entry_smart_theme;
345
346    ELM_WIDGET_CLASS(sc)->focus_next = _elm_fileselector_entry_smart_focus_next;
347    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
348
349    ELM_CONTAINER_CLASS(sc)->content_set =
350      _elm_fileselector_entry_smart_content_set;
351    ELM_CONTAINER_CLASS(sc)->content_get =
352      _elm_fileselector_entry_smart_content_get;
353    ELM_CONTAINER_CLASS(sc)->content_unset =
354      _elm_fileselector_entry_smart_content_unset;
355
356    ELM_LAYOUT_CLASS(sc)->text_set = _elm_fileselector_entry_smart_text_set;
357    ELM_LAYOUT_CLASS(sc)->text_get = _elm_fileselector_entry_smart_text_get;
358    ELM_LAYOUT_CLASS(sc)->sizing_eval =
359      _elm_fileselector_entry_smart_sizing_eval;
360 }
361
362 EAPI const Elm_Fileselector_Entry_Smart_Class *
363 elm_fileselector_entry_smart_class_get(void)
364 {
365    static Elm_Fileselector_Entry_Smart_Class _sc =
366      ELM_FILESELECTOR_ENTRY_SMART_CLASS_INIT_NAME_VERSION
367        (ELM_FILESELECTOR_ENTRY_SMART_NAME);
368    static const Elm_Fileselector_Entry_Smart_Class *class = NULL;
369    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
370
371    if (class)
372      return class;
373
374    _elm_fileselector_entry_smart_set(&_sc);
375    esc->callbacks = _smart_callbacks;
376    class = &_sc;
377
378    return class;
379 }
380
381 EAPI Evas_Object *
382 elm_fileselector_entry_add(Evas_Object *parent)
383 {
384    Evas_Object *obj;
385
386    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
387
388    obj = elm_widget_add(_elm_fileselector_entry_smart_class_new(), parent);
389    if (!obj) return NULL;
390
391    if (!elm_widget_sub_object_add(parent, obj))
392      ERR("could not add %p as sub object of %p", obj, parent);
393
394    return obj;
395 }
396
397 EAPI void
398 elm_fileselector_entry_selected_set(Evas_Object *obj,
399                                     const char *path)
400 {
401    ELM_FILESELECTOR_ENTRY_CHECK(obj);
402    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
403
404    elm_fileselector_button_path_set(sd->button, path);
405 }
406
407 EAPI const char *
408 elm_fileselector_entry_selected_get(const Evas_Object *obj)
409 {
410    ELM_FILESELECTOR_ENTRY_CHECK(obj) NULL;
411    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
412
413    return elm_fileselector_button_path_get(sd->button);
414 }
415
416 EAPI void
417 elm_fileselector_entry_window_title_set(Evas_Object *obj,
418                                         const char *title)
419 {
420    ELM_FILESELECTOR_ENTRY_CHECK(obj);
421    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
422
423    elm_fileselector_button_window_title_set(sd->button, title);
424 }
425
426 EAPI const char *
427 elm_fileselector_entry_window_title_get(const Evas_Object *obj)
428 {
429    ELM_FILESELECTOR_ENTRY_CHECK(obj) NULL;
430    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
431
432    return elm_fileselector_button_window_title_get(sd->button);
433 }
434
435 EAPI void
436 elm_fileselector_entry_window_size_set(Evas_Object *obj,
437                                        Evas_Coord width,
438                                        Evas_Coord height)
439 {
440    ELM_FILESELECTOR_ENTRY_CHECK(obj);
441    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
442
443    elm_fileselector_button_window_size_set(sd->button, width, height);
444 }
445
446 EAPI void
447 elm_fileselector_entry_window_size_get(const Evas_Object *obj,
448                                        Evas_Coord *width,
449                                        Evas_Coord *height)
450 {
451    ELM_FILESELECTOR_ENTRY_CHECK(obj);
452    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
453
454    elm_fileselector_button_window_size_get(sd->button, width, height);
455 }
456
457 EAPI void
458 elm_fileselector_entry_path_set(Evas_Object *obj,
459                                 const char *path)
460 {
461    char *s;
462
463    ELM_FILESELECTOR_ENTRY_CHECK(obj);
464    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
465
466    elm_fileselector_button_path_set(sd->button, path);
467    s = elm_entry_utf8_to_markup(path);
468    if (s)
469      {
470         elm_object_text_set(sd->entry, s);
471         free(s);
472      }
473 }
474
475 EAPI const char *
476 elm_fileselector_entry_path_get(const Evas_Object *obj)
477 {
478    ELM_FILESELECTOR_ENTRY_CHECK(obj) NULL;
479    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
480
481    if (sd->path) free(sd->path);
482    sd->path = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry));
483    return sd->path;
484 }
485
486 EAPI void
487 elm_fileselector_entry_expandable_set(Evas_Object *obj,
488                                       Eina_Bool value)
489 {
490    ELM_FILESELECTOR_ENTRY_CHECK(obj);
491    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
492
493    elm_fileselector_button_expandable_set(sd->button, value);
494 }
495
496 EAPI Eina_Bool
497 elm_fileselector_entry_expandable_get(const Evas_Object *obj)
498 {
499    ELM_FILESELECTOR_ENTRY_CHECK(obj) EINA_FALSE;
500    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
501
502    return elm_fileselector_button_expandable_get(sd->button);
503 }
504
505 EAPI void
506 elm_fileselector_entry_folder_only_set(Evas_Object *obj,
507                                        Eina_Bool value)
508 {
509    ELM_FILESELECTOR_ENTRY_CHECK(obj);
510    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
511
512    elm_fileselector_button_folder_only_set(sd->button, value);
513 }
514
515 EAPI Eina_Bool
516 elm_fileselector_entry_folder_only_get(const Evas_Object *obj)
517 {
518    ELM_FILESELECTOR_ENTRY_CHECK(obj) EINA_FALSE;
519    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
520
521    return elm_fileselector_button_folder_only_get(sd->button);
522 }
523
524 EAPI void
525 elm_fileselector_entry_is_save_set(Evas_Object *obj,
526                                    Eina_Bool value)
527 {
528    ELM_FILESELECTOR_ENTRY_CHECK(obj);
529    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
530
531    elm_fileselector_button_is_save_set(sd->button, value);
532 }
533
534 EAPI Eina_Bool
535 elm_fileselector_entry_is_save_get(const Evas_Object *obj)
536 {
537    ELM_FILESELECTOR_ENTRY_CHECK(obj) EINA_FALSE;
538    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
539
540    return elm_fileselector_button_is_save_get(sd->button);
541 }
542
543 EAPI void
544 elm_fileselector_entry_inwin_mode_set(Evas_Object *obj,
545                                       Eina_Bool value)
546 {
547    ELM_FILESELECTOR_ENTRY_CHECK(obj);
548    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
549
550    elm_fileselector_button_inwin_mode_set(sd->button, value);
551 }
552
553 EAPI Eina_Bool
554 elm_fileselector_entry_inwin_mode_get(const Evas_Object *obj)
555 {
556    ELM_FILESELECTOR_ENTRY_CHECK(obj) EINA_FALSE;
557    ELM_FILESELECTOR_ENTRY_DATA_GET(obj, sd);
558
559    return elm_fileselector_button_inwin_mode_get(sd->button);
560 }