6f7ce0ab0e241e0ec2cf2bb3195d96579950af4e
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char SMART_NAME[] = "elm_widget";
5
6 #define API_ENTRY                                    \
7   Smart_Data * sd = evas_object_smart_data_get(obj); \
8   if ((!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY                               \
10   Smart_Data * sd = evas_object_smart_data_get(obj); \
11   if (!sd) return
12
13 #undef elm_widget_text_set_hook_set
14 #undef elm_widget_text_get_hook_set
15 #undef elm_widget_content_set_hook_set
16 #undef elm_widget_content_get_hook_set
17 #undef elm_widget_content_unset_hook_set
18
19 typedef struct _Smart_Data        Smart_Data;
20 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
21 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
23 typedef struct _Elm_Widget_Item_Callback Elm_Widget_Item_Callback;
24
25 struct _Smart_Data
26 {
27    Evas_Object *obj;
28    const char  *type;
29    Evas_Object *parent_obj;
30    Evas_Object *parent2;
31    Evas_Coord   x, y, w, h;
32    Eina_List   *subobjs;
33    Evas_Object *resize_obj;
34    Evas_Object *hover_obj;
35    Eina_List   *tooltips, *cursors;
36    void       (*del_func)(Evas_Object *obj);
37    void       (*del_pre_func)(Evas_Object *obj);
38    void       (*focus_func)(Evas_Object *obj);
39    void       (*activate_func)(Evas_Object *obj);
40    void       (*disable_func)(Evas_Object *obj);
41    void       (*theme_func)(Evas_Object *obj);
42    void       (*translate_func)(Evas_Object *obj);
43    Eina_Bool  (*event_func)(Evas_Object       *obj,
44                             Evas_Object       *source,
45                             Evas_Callback_Type type,
46                             void              *event_info);
47    void       (*signal_func)(Evas_Object *obj,
48                              const char  *emission,
49                              const char  *source);
50    void       (*callback_add_func)(Evas_Object   *obj,
51                                    const char    *emission,
52                                    const char    *source,
53                                    Edje_Signal_Cb func,
54                                    void          *data);
55    void       (*callback_del_func)(Evas_Object   *obj,
56                                    const char    *emission,
57                                    const char    *source,
58                                    Edje_Signal_Cb func,
59                                    void          *data);
60    void       (*changed_func)(Evas_Object *obj);
61    Eina_Bool  (*focus_next_func)(const Evas_Object  *obj,
62                                  Elm_Focus_Direction dir,
63                                  Evas_Object       **next);
64    void       (*on_focus_func)(void        *data,
65                                Evas_Object *obj);
66    void        *on_focus_data;
67    void       (*on_change_func)(void        *data,
68                                 Evas_Object *obj);
69    void        *on_change_data;
70    void       (*on_show_region_func)(void        *data,
71                                      Evas_Object *obj);
72    void        *on_show_region_data;
73    void       (*focus_region_func)(Evas_Object *obj,
74                                    Evas_Coord   x,
75                                    Evas_Coord   y,
76                                    Evas_Coord   w,
77                                    Evas_Coord   h);
78    void       (*on_focus_region_func)(const Evas_Object *obj,
79                                       Evas_Coord        *x,
80                                       Evas_Coord        *y,
81                                       Evas_Coord        *w,
82                                       Evas_Coord        *h);
83    Elm_Widget_Text_Set_Cb text_set_func;
84    Elm_Widget_Text_Get_Cb text_get_func;
85    Elm_Widget_Content_Set_Cb content_set_func;
86    Elm_Widget_Content_Get_Cb content_get_func;
87    Elm_Widget_Content_Unset_Cb content_unset_func;
88    void        *data;
89    Evas_Coord   rx, ry, rw, rh;
90    int          scroll_hold;
91    int          scroll_freeze;
92    double       scale;
93    Elm_Theme   *theme;
94    const char  *style;
95    const char  *access_info;
96    unsigned int focus_order;
97    Eina_Bool    focus_order_on_calc;
98
99    int          child_drag_x_locked;
100    int          child_drag_y_locked;
101
102    Eina_List   *edje_signals;
103    Eina_List   *translate_strings;
104
105    Eina_Bool    drag_x_locked : 1;
106    Eina_Bool    drag_y_locked : 1;
107
108    Eina_Bool    can_focus : 1;
109    Eina_Bool    child_can_focus : 1;
110    Eina_Bool    focused : 1;
111    Eina_Bool    top_win_focused : 1;
112    Eina_Bool    tree_unfocusable : 1;
113    Eina_Bool    highlight_ignore : 1;
114    Eina_Bool    highlight_in_theme : 1;
115    Eina_Bool    disabled : 1;
116    Eina_Bool    is_mirrored : 1;
117    Eina_Bool    mirrored_auto_mode : 1;   /* This is TRUE by default */
118    Eina_Bool    still_in : 1;
119
120    Eina_List   *focus_chain;
121    Eina_List   *event_cb;
122 };
123
124 struct _Edje_Signal_Data
125 {
126    Evas_Object   *obj;
127    Edje_Signal_Cb func;
128    const char    *emission;
129    const char    *source;
130    void          *data;
131 };
132
133 struct _Elm_Event_Cb_Data
134 {
135    Elm_Event_Cb func;
136    const void  *data;
137 };
138
139 struct _Elm_Translate_String_Data
140 {
141    const char *id;
142    const char *domain;
143    const char *string;
144 };
145
146 struct _Elm_Widget_Item_Callback
147 {
148    const char *event;
149    Elm_Object_Item_Smart_Cb func;
150    void *data;
151    int walking : 1;
152    Eina_Bool delete_me : 1;
153 };
154
155
156 /* local subsystem functions */
157 static void _smart_reconfigure(Smart_Data *sd);
158 static void _smart_add(Evas_Object *obj);
159 static void _smart_del(Evas_Object *obj);
160 static void _smart_move(Evas_Object *obj,
161                         Evas_Coord   x,
162                         Evas_Coord   y);
163 static void _smart_resize(Evas_Object *obj,
164                           Evas_Coord   w,
165                           Evas_Coord   h);
166 static void _smart_show(Evas_Object *obj);
167 static void _smart_hide(Evas_Object *obj);
168 static void _smart_color_set(Evas_Object *obj,
169                              int          r,
170                              int          g,
171                              int          b,
172                              int          a);
173 static void _smart_clip_set(Evas_Object *obj,
174                             Evas_Object *clip);
175 static void _smart_clip_unset(Evas_Object *obj);
176 static void _smart_calculate(Evas_Object *obj);
177 static void _smart_init(void);
178
179 static void _if_focused_revert(Evas_Object *obj,
180                                Eina_Bool    can_focus_only);
181 static Evas_Object *_newest_focus_order_get(Evas_Object  *obj,
182                                             unsigned int *newest_focus_order,
183                                             Eina_Bool     can_focus_only);
184
185 /* local subsystem globals */
186 static Evas_Smart *_e_smart = NULL;
187 static Eina_List  *widtypes = NULL;
188
189 static unsigned int focus_order = 0;
190
191 // internal funcs
192 static inline Eina_Bool
193 _elm_widget_is(const Evas_Object *obj)
194 {
195    const char *type = evas_object_type_get(obj);
196    return type == SMART_NAME;
197 }
198
199 static inline Eina_Bool
200 _is_focusable(Evas_Object *obj)
201 {
202    API_ENTRY return EINA_FALSE;
203    return sd->can_focus || (sd->child_can_focus);
204 }
205
206 static void
207 _unfocus_parents(Evas_Object *obj)
208 {
209    for (; obj; obj = elm_widget_parent_get(obj))
210      {
211         INTERNAL_ENTRY;
212         if (!sd->focused) return;
213         sd->focused = 0;
214      }
215 }
216
217 static void
218 _focus_parents(Evas_Object *obj)
219 {
220    for (; obj; obj = elm_widget_parent_get(obj))
221      {
222         INTERNAL_ENTRY;
223         if (sd->focused) return;
224         sd->focused = 1;
225      }
226 }
227
228 static void
229 _sub_obj_del(void        *data,
230              Evas        *e __UNUSED__,
231              Evas_Object *obj,
232              void        *event_info __UNUSED__)
233 {
234    Smart_Data *sd = data;
235
236    if (_elm_widget_is(obj))
237      {
238         if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
239      }
240    if (obj == sd->resize_obj)
241      sd->resize_obj = NULL;
242    else if (obj == sd->hover_obj)
243      sd->hover_obj = NULL;
244    else
245      sd->subobjs = eina_list_remove(sd->subobjs, obj);
246    evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
247 }
248
249 static void
250 _sub_obj_hide(void        *data __UNUSED__,
251               Evas        *e __UNUSED__,
252               Evas_Object *obj,
253               void        *event_info __UNUSED__)
254 {
255    elm_widget_focus_hide_handle(obj);
256 }
257
258 static void
259 _sub_obj_mouse_down(void        *data,
260                     Evas        *e __UNUSED__,
261                     Evas_Object *obj __UNUSED__,
262                     void        *event_info)
263 {
264    Smart_Data *sd = data;
265    Evas_Event_Mouse_Down *ev = event_info;
266    if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
267      sd->still_in = EINA_TRUE;
268 }
269
270 static void
271 _sub_obj_mouse_move(void        *data,
272                     Evas        *e __UNUSED__,
273                     Evas_Object *obj,
274                     void        *event_info)
275 {
276    Smart_Data *sd = data;
277    Evas_Event_Mouse_Move *ev = event_info;
278    if (sd->still_in)
279      {
280         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
281           sd->still_in = EINA_FALSE;
282         else
283           {
284              Evas_Coord x, y, w, h;
285              evas_object_geometry_get(obj, &x, &y, &w, &h);
286              if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
287                  (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
288                sd->still_in = EINA_FALSE;
289           }
290      }
291 }
292
293 static void
294 _sub_obj_mouse_up(void        *data,
295                   Evas        *e __UNUSED__,
296                   Evas_Object *obj,
297                   void        *event_info __UNUSED__)
298 {
299    Smart_Data *sd = data;
300    if (sd->still_in)
301      elm_widget_focus_mouse_up_handle(obj);
302    sd->still_in = EINA_FALSE;
303 }
304
305 static void
306 _propagate_x_drag_lock(Evas_Object *obj,
307                        int          dir)
308 {
309    INTERNAL_ENTRY;
310    if (sd->parent_obj)
311      {
312         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
313         if (sd2)
314           {
315              sd2->child_drag_x_locked += dir;
316              _propagate_x_drag_lock(sd->parent_obj, dir);
317           }
318      }
319 }
320
321 static void
322 _propagate_y_drag_lock(Evas_Object *obj,
323                        int          dir)
324 {
325    INTERNAL_ENTRY;
326    if (sd->parent_obj)
327      {
328         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
329         if (sd2)
330           {
331              sd2->child_drag_y_locked += dir;
332              _propagate_y_drag_lock(sd->parent_obj, dir);
333           }
334      }
335 }
336
337 static void
338 _propagate_event(void        *data,
339                  Evas        *e __UNUSED__,
340                  Evas_Object *obj,
341                  void        *event_info)
342 {
343    INTERNAL_ENTRY;
344    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
345    Evas_Event_Flags *event_flags = NULL;
346
347    switch (type)
348      {
349       case EVAS_CALLBACK_KEY_DOWN:
350           {
351             Evas_Event_Key_Down *ev = event_info;
352             event_flags = &(ev->event_flags);
353           }
354         break;
355
356       case EVAS_CALLBACK_KEY_UP:
357           {
358              Evas_Event_Key_Up *ev = event_info;
359              event_flags = &(ev->event_flags);
360           }
361         break;
362
363       case EVAS_CALLBACK_MOUSE_WHEEL:
364           {
365             Evas_Event_Mouse_Wheel *ev = event_info;
366             event_flags = &(ev->event_flags);
367           }
368         break;
369
370       default:
371         break;
372      }
373
374    elm_widget_event_propagate(obj, type, event_info, event_flags);
375 }
376
377 static void
378 _parent_focus(Evas_Object *obj)
379 {
380    API_ENTRY return;
381    if (sd->focused) return;
382
383    Evas_Object *o = elm_widget_parent_get(obj);
384    sd->focus_order_on_calc = EINA_TRUE;
385
386    if (o) _parent_focus(o);
387
388    if (!sd->focus_order_on_calc)
389      return; /* we don't want to override it if by means of any of the
390                 callbacks below one gets to calculate our order
391                 first. */
392
393    focus_order++;
394    sd->focus_order = focus_order;
395    if (sd->top_win_focused)
396      {
397         sd->focused = EINA_TRUE;
398         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
399         if (sd->focus_func) sd->focus_func(obj);
400         _elm_widget_focus_region_show(obj);
401      }
402    sd->focus_order_on_calc = EINA_FALSE;
403 }
404
405 static void
406 _elm_object_focus_chain_del_cb(void        *data,
407                                Evas        *e __UNUSED__,
408                                Evas_Object *obj,
409                                void        *event_info __UNUSED__)
410 {
411    Smart_Data *sd = data;
412
413    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
414 }
415
416 // exposed util funcs to elm
417 void
418 _elm_widget_type_clear(void)
419 {
420    const char **ptr;
421
422    EINA_LIST_FREE(widtypes, ptr)
423      {
424         eina_stringshare_del(*ptr);
425         *ptr = NULL;
426      }
427 }
428
429 void
430 _elm_widget_focus_region_show(const Evas_Object *obj)
431 {
432    Evas_Coord x, y, w, h, ox, oy;
433    Smart_Data *sd2;
434    Evas_Object *o;
435
436    API_ENTRY return;
437
438    o = elm_widget_parent_get(obj);
439    if (!o) return;
440
441    elm_widget_focus_region_get(obj, &x, &y, &w, &h);
442    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
443    while (o)
444      {
445         Evas_Coord px, py;
446         sd2 = evas_object_smart_data_get(o);
447         if (sd2->focus_region_func)
448           {
449              sd2->focus_region_func(o, x, y, w, h);
450              elm_widget_focus_region_get(o, &x, &y, &w, &h);
451           }
452         else
453           {
454              evas_object_geometry_get(o, &px, &py, NULL, NULL);
455              x += ox - px;
456              y += oy - py;
457              ox = px;
458              oy = py;
459           }
460         o = elm_widget_parent_get(o);
461      }
462 }
463
464 /**
465  * @defgroup Widget Widget
466  *
467  * @internal
468  * Exposed api for making widgets
469  */
470 EAPI void
471 elm_widget_type_register(const char **ptr)
472 {
473    widtypes = eina_list_append(widtypes, (void *)ptr);
474 }
475
476 /**
477  * @defgroup Widget Widget
478  *
479  * @internal
480  * Disposed api for making widgets
481  */
482 EAPI void
483 elm_widget_type_unregister(const char **ptr)
484 {
485    widtypes = eina_list_remove(widtypes, (void *)ptr);
486 }
487
488 EAPI Eina_Bool
489 elm_widget_api_check(int ver)
490 {
491    if (ver != ELM_INTERNAL_API_VERSION)
492      {
493         CRITICAL("Elementary widget api versions do not match");
494         return EINA_FALSE;
495      }
496    return EINA_TRUE;
497 }
498
499 EAPI Evas_Object *
500 elm_widget_add(Evas *evas)
501 {
502    Evas_Object *obj;
503    _smart_init();
504    obj = evas_object_smart_add(evas, _e_smart);
505    elm_widget_mirrored_set(obj, elm_config_mirrored_get());
506    return obj;
507 }
508
509 EAPI void
510 elm_widget_del_hook_set(Evas_Object *obj,
511                         void       (*func)(Evas_Object *obj))
512 {
513    API_ENTRY return;
514    sd->del_func = func;
515 }
516
517 EAPI void
518 elm_widget_del_pre_hook_set(Evas_Object *obj,
519                             void       (*func)(Evas_Object *obj))
520 {
521    API_ENTRY return;
522    sd->del_pre_func = func;
523 }
524
525 EAPI void
526 elm_widget_focus_hook_set(Evas_Object *obj,
527                           void       (*func)(Evas_Object *obj))
528 {
529    API_ENTRY return;
530    sd->focus_func = func;
531 }
532
533 EAPI void
534 elm_widget_activate_hook_set(Evas_Object *obj,
535                              void       (*func)(Evas_Object *obj))
536 {
537    API_ENTRY return;
538    sd->activate_func = func;
539 }
540
541 EAPI void
542 elm_widget_disable_hook_set(Evas_Object *obj,
543                             void       (*func)(Evas_Object *obj))
544 {
545    API_ENTRY return;
546    sd->disable_func = func;
547 }
548
549 EAPI void
550 elm_widget_theme_hook_set(Evas_Object *obj,
551                           void       (*func)(Evas_Object *obj))
552 {
553    API_ENTRY return;
554    sd->theme_func = func;
555 }
556
557 EAPI void
558 elm_widget_translate_hook_set(Evas_Object *obj,
559                               void       (*func)(Evas_Object *obj))
560 {
561    API_ENTRY return;
562    sd->translate_func = func;
563 }
564
565 EAPI void
566 elm_widget_event_hook_set(Evas_Object *obj,
567                           Eina_Bool  (*func)(Evas_Object       *obj,
568                                              Evas_Object       *source,
569                                              Evas_Callback_Type type,
570                                              void              *event_info))
571 {
572    API_ENTRY return;
573    sd->event_func = func;
574 }
575
576 EAPI void
577 elm_widget_text_set_hook_set(Evas_Object *obj,
578                              Elm_Widget_Text_Set_Cb func)
579 {
580    API_ENTRY return;
581    sd->text_set_func = func;
582 }
583
584 EAPI void
585 elm_widget_text_get_hook_set(Evas_Object *obj,
586                              Elm_Widget_Text_Get_Cb func)
587 {
588    API_ENTRY return;
589    sd->text_get_func = func;
590 }
591
592 EAPI void
593 elm_widget_content_set_hook_set(Evas_Object *obj,
594                                 Elm_Widget_Content_Set_Cb func)
595 {
596    API_ENTRY return;
597    sd->content_set_func = func;
598 }
599
600 EAPI void
601 elm_widget_content_get_hook_set(Evas_Object *obj,
602                                 Elm_Widget_Content_Get_Cb func)
603 {
604    API_ENTRY return;
605    sd->content_get_func = func;
606 }
607
608 EAPI void
609 elm_widget_content_unset_hook_set(Evas_Object *obj,
610                                   Elm_Widget_Content_Unset_Cb func)
611 {
612    API_ENTRY return;
613    sd->content_unset_func = func;
614 }
615
616 EAPI void
617 elm_widget_changed_hook_set(Evas_Object *obj,
618                             void       (*func)(Evas_Object *obj))
619 {
620    API_ENTRY return;
621    sd->changed_func = func;
622 }
623
624 EAPI void
625 elm_widget_signal_emit_hook_set(Evas_Object *obj,
626                                 void       (*func)(Evas_Object *obj,
627                                                    const char *emission,
628                                                    const char *source))
629 {
630    API_ENTRY return;
631    sd->signal_func = func;
632 }
633
634 EAPI void
635 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
636                                         void       (*func)(Evas_Object   *obj,
637                                                            const char    *emission,
638                                                            const char    *source,
639                                                            Edje_Signal_Cb func_cb,
640                                                            void          *data))
641 {
642    API_ENTRY return;
643    sd->callback_add_func = func;
644 }
645
646 EAPI void
647 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
648                                         void       (*func)(Evas_Object   *obj,
649                                                            const char    *emission,
650                                                            const char    *source,
651                                                            Edje_Signal_Cb func_cb,
652                                                            void          *data))
653 {
654    API_ENTRY return;
655    sd->callback_del_func = func;
656 }
657
658 EAPI Eina_Bool
659 elm_widget_theme(Evas_Object *obj)
660 {
661    const Eina_List *l;
662    Evas_Object *child;
663    Elm_Tooltip *tt;
664    Elm_Cursor *cur;
665    Eina_Bool ret = EINA_TRUE;
666
667    API_ENTRY return EINA_FALSE;
668    EINA_LIST_FOREACH(sd->subobjs, l, child) ret &= elm_widget_theme(child);
669    if (sd->resize_obj) ret &= elm_widget_theme(sd->resize_obj);
670    if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
671    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
672    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
673    if (sd->theme_func) sd->theme_func(obj);
674
675    return ret;
676 }
677
678 EAPI void
679 elm_widget_theme_specific(Evas_Object *obj,
680                           Elm_Theme   *th,
681                           Eina_Bool    force)
682 {
683    const Eina_List *l;
684    Evas_Object *child;
685    Elm_Tooltip *tt;
686    Elm_Cursor *cur;
687    Elm_Theme *th2, *thdef;
688
689    API_ENTRY return;
690    thdef = elm_theme_default_get();
691    if (!th) th = thdef;
692    if (!force)
693      {
694         th2 = sd->theme;
695         if (!th2) th2 = thdef;
696         while (th2)
697           {
698              if (th2 == th)
699                {
700                   force = EINA_TRUE;
701                   break;
702                }
703              if (th2 == thdef) break;
704              th2 = th2->ref_theme;
705              if (!th2) th2 = thdef;
706           }
707      }
708    if (!force) return;
709    EINA_LIST_FOREACH(sd->subobjs, l, child)
710      elm_widget_theme_specific(child, th, force);
711    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
712    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
713    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
714    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
715    if (sd->theme_func) sd->theme_func(obj);
716 }
717
718 /**
719  * @internal
720  *
721  * Set hook to get next object in object focus chain.
722  *
723  * @param obj The widget object.
724  * @param func The hook to be used with this widget.
725  *
726  * @ingroup Widget
727  */
728 EAPI void
729 elm_widget_focus_next_hook_set(Evas_Object *obj,
730                                Eina_Bool  (*func)(const Evas_Object   *obj,
731                                                    Elm_Focus_Direction dir,
732                                                    Evas_Object       **next))
733 {
734    API_ENTRY return;
735    sd->focus_next_func = func;
736 }
737
738 /**
739  * Returns the widget's mirrored mode.
740  *
741  * @param obj The widget.
742  * @return mirrored mode of the object.
743  *
744  **/
745 EAPI Eina_Bool
746 elm_widget_mirrored_get(const Evas_Object *obj)
747 {
748    API_ENTRY return EINA_FALSE;
749    return sd->is_mirrored;
750 }
751
752 /**
753  * Sets the widget's mirrored mode.
754  *
755  * @param obj The widget.
756  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
757  */
758 EAPI void
759 elm_widget_mirrored_set(Evas_Object *obj,
760                         Eina_Bool    mirrored)
761 {
762    API_ENTRY return;
763    if (sd->is_mirrored != mirrored)
764      {
765         sd->is_mirrored = mirrored;
766         elm_widget_theme(obj);
767      }
768 }
769
770 /**
771  * @internal
772  * Resets the mirrored mode from the system mirror mode for widgets that are in
773  * automatic mirroring mode. This function does not call elm_widget_theme.
774  *
775  * @param obj The widget.
776  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
777  */
778 void
779 _elm_widget_mirrored_reload(Evas_Object *obj)
780 {
781    API_ENTRY return;
782    Eina_Bool mirrored = elm_config_mirrored_get();
783    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
784      {
785         sd->is_mirrored = mirrored;
786      }
787 }
788
789 /**
790  * Returns the widget's mirrored mode setting.
791  *
792  * @param obj The widget.
793  * @return mirrored mode setting of the object.
794  *
795  **/
796 EAPI Eina_Bool
797 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
798 {
799    API_ENTRY return EINA_FALSE;
800    return sd->mirrored_auto_mode;
801 }
802
803 /**
804  * Sets the widget's mirrored mode setting.
805  * When widget in automatic mode, it follows the system mirrored mode set by
806  * elm_mirrored_set().
807  * @param obj The widget.
808  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
809  */
810 EAPI void
811 elm_widget_mirrored_automatic_set(Evas_Object *obj,
812                                   Eina_Bool    automatic)
813 {
814    API_ENTRY return;
815    if (sd->mirrored_auto_mode != automatic)
816      {
817         sd->mirrored_auto_mode = automatic;
818
819         if (automatic)
820           {
821              elm_widget_mirrored_set(obj, elm_config_mirrored_get());
822           }
823      }
824 }
825
826 EAPI void
827 elm_widget_on_focus_hook_set(Evas_Object *obj,
828                              void       (*func)(void *data,
829                                                 Evas_Object *obj),
830                              void        *data)
831 {
832    API_ENTRY return;
833    sd->on_focus_func = func;
834    sd->on_focus_data = data;
835 }
836
837 EAPI void
838 elm_widget_on_change_hook_set(Evas_Object *obj,
839                               void       (*func)(void *data,
840                                                  Evas_Object *obj),
841                               void        *data)
842 {
843    API_ENTRY return;
844    sd->on_change_func = func;
845    sd->on_change_data = data;
846 }
847
848 EAPI void
849 elm_widget_on_show_region_hook_set(Evas_Object *obj,
850                                    void       (*func)(void *data,
851                                                       Evas_Object *obj),
852                                    void        *data)
853 {
854    API_ENTRY return;
855    sd->on_show_region_func = func;
856    sd->on_show_region_data = data;
857 }
858
859 /**
860  * @internal
861  *
862  * Set the hook to use to show the focused region.
863  *
864  * Whenever a new widget gets focused or it's needed to show the focused
865  * area of the current one, this hook will be called on objects that may
866  * want to move their children into their visible area.
867  * The area given in the hook function is relative to the @p obj widget.
868  *
869  * @param obj The widget object
870  * @param func The function to call to show the specified area.
871  *
872  * @ingroup Widget
873  */
874 EAPI void
875 elm_widget_focus_region_hook_set(Evas_Object *obj,
876                                  void       (*func)(Evas_Object *obj,
877                                                     Evas_Coord x,
878                                                     Evas_Coord y,
879                                                     Evas_Coord w,
880                                                     Evas_Coord h))
881 {
882    API_ENTRY return;
883    sd->focus_region_func = func;
884 }
885
886 /**
887  * @internal
888  *
889  * Set the hook to retrieve the focused region of a widget.
890  *
891  * This hook will be called by elm_widget_focus_region_get() whenever
892  * it's needed to get the focused area of a widget. The area must be relative
893  * to the widget itself and if no hook is set, it will default to the entire
894  * object.
895  *
896  * @param obj The widget object
897  * @param func The function used to retrieve the focus region.
898  *
899  * @ingroup Widget
900  */
901 EAPI void
902 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
903                                     void       (*func)(const Evas_Object *obj,
904                                                        Evas_Coord *x,
905                                                        Evas_Coord *y,
906                                                        Evas_Coord *w,
907                                                        Evas_Coord *h))
908 {
909    API_ENTRY return;
910    sd->on_focus_region_func = func;
911 }
912
913 EAPI void
914 elm_widget_data_set(Evas_Object *obj,
915                     void        *data)
916 {
917    API_ENTRY return;
918    sd->data = data;
919 }
920
921 EAPI void *
922 elm_widget_data_get(const Evas_Object *obj)
923 {
924    API_ENTRY return NULL;
925    return sd->data;
926 }
927
928 EAPI void
929 elm_widget_sub_object_add(Evas_Object *obj,
930                           Evas_Object *sobj)
931 {
932    API_ENTRY return;
933    double scale, pscale = elm_widget_scale_get(sobj);
934    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
935    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
936
937    if (sobj == sd->parent_obj)
938      {
939         elm_widget_sub_object_del(sobj, obj);
940         WRN("You passed a parent object of obj = %p as the sub object = %p!", obj, sobj);
941      }
942
943    if (_elm_widget_is(sobj))
944      {
945         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
946         if (sd2)
947           {
948              if (sd2->parent_obj == obj)
949                return;
950              if (sd2->parent_obj)
951                elm_widget_sub_object_del(sd2->parent_obj, sobj);
952              sd2->parent_obj = obj;
953              sd2->top_win_focused = sd->top_win_focused;
954              if (!sd->child_can_focus && (_is_focusable(sobj)))
955                sd->child_can_focus = EINA_TRUE;
956           }
957      }
958    else
959      {
960         void *data = evas_object_data_get(sobj, "elm-parent");
961         if (data)
962           {
963              if (data == obj) return;
964              evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
965                                             _sub_obj_del);
966           }
967      }
968    sd->subobjs = eina_list_append(sd->subobjs, sobj);
969    evas_object_data_set(sobj, "elm-parent", obj);
970    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
971    if (_elm_widget_is(sobj))
972      evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
973    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
974    scale = elm_widget_scale_get(sobj);
975    th = elm_widget_theme_get(sobj);
976    mirrored = elm_widget_mirrored_get(sobj);
977    if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
978    if (elm_widget_focus_get(sobj)) _focus_parents(obj);
979 }
980
981 EAPI void
982 elm_widget_sub_object_del(Evas_Object *obj,
983                           Evas_Object *sobj)
984 {
985    Evas_Object *sobj_parent;
986    API_ENTRY return;
987    if (!sobj) return;
988
989    sobj_parent = evas_object_data_del(sobj, "elm-parent");
990    if (sobj_parent != obj)
991      {
992         static int abort_on_warn = -1;
993         ERR("removing sub object %p (%s) from parent %p (%s), "
994             "but elm-parent is different %p (%s)!",
995             sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
996             sobj_parent, elm_widget_type_get(sobj_parent));
997         if (EINA_UNLIKELY(abort_on_warn == -1))
998           {
999              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1000              else abort_on_warn = 0;
1001           }
1002         if (abort_on_warn == 1) abort();
1003      }
1004    if (_elm_widget_is(sobj))
1005      {
1006         if (elm_widget_focus_get(sobj))
1007           {
1008              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1009              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1010           }
1011         if ((sd->child_can_focus) && (_is_focusable(sobj)))
1012           {
1013              Evas_Object *subobj;
1014              const Eina_List *l;
1015              sd->child_can_focus = EINA_FALSE;
1016              EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1017                {
1018                   if (_is_focusable(subobj))
1019                     {
1020                        sd->child_can_focus = EINA_TRUE;
1021                        break;
1022                     }
1023                }
1024           }
1025         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1026         if (sd2)
1027           {
1028              sd2->parent_obj = NULL;
1029              if (sd2->resize_obj == sobj)
1030                sd2->resize_obj = NULL;
1031              else
1032                sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1033           }
1034         else
1035           sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1036      }
1037    else
1038      sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1039    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1040                                        _sub_obj_del, sd);
1041    if (_elm_widget_is(sobj))
1042      evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1043                                          _sub_obj_hide, sd);
1044    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1045 }
1046
1047 EAPI void
1048 elm_widget_resize_object_set(Evas_Object *obj,
1049                              Evas_Object *sobj)
1050 {
1051    API_ENTRY return;
1052    // orphan previous resize obj
1053    if (sd->resize_obj)
1054      {
1055         evas_object_clip_unset(sd->resize_obj);
1056         evas_object_data_del(sd->resize_obj, "elm-parent");
1057         if (_elm_widget_is(sd->resize_obj))
1058           {
1059              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1060              if (sd2) sd2->parent_obj = NULL;
1061              evas_object_event_callback_del_full(sd->resize_obj,
1062                                                  EVAS_CALLBACK_HIDE,
1063                                                  _sub_obj_hide, sd);
1064           }
1065         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1066                                             _sub_obj_del, sd);
1067         evas_object_event_callback_del_full(sd->resize_obj,
1068                                             EVAS_CALLBACK_MOUSE_DOWN,
1069                                             _sub_obj_mouse_down, sd);
1070         evas_object_event_callback_del_full(sd->resize_obj,
1071                                             EVAS_CALLBACK_MOUSE_MOVE,
1072                                             _sub_obj_mouse_move, sd);
1073         evas_object_event_callback_del_full(sd->resize_obj,
1074                                             EVAS_CALLBACK_MOUSE_UP,
1075                                             _sub_obj_mouse_up, sd);
1076         evas_object_smart_member_del(sd->resize_obj);
1077
1078         if (_elm_widget_is(sd->resize_obj))
1079           {
1080              if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1081           }
1082      }
1083
1084    sd->resize_obj = sobj;
1085    if (!sobj) return;
1086
1087    // orphan new resize obj
1088    evas_object_data_del(sobj, "elm-parent");
1089    if (_elm_widget_is(sobj))
1090      {
1091         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1092         if (sd2) sd2->parent_obj = NULL;
1093         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1094                                             _sub_obj_hide, sd);
1095      }
1096    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1097                                        _sub_obj_del, sd);
1098    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1099                                        _sub_obj_mouse_down, sd);
1100    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1101                                        _sub_obj_mouse_move, sd);
1102    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1103                                        _sub_obj_mouse_up, sd);
1104    evas_object_smart_member_del(sobj);
1105    if (_elm_widget_is(sobj))
1106      {
1107         if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1108      }
1109
1110    // set the resize obj up
1111    if (_elm_widget_is(sobj))
1112      {
1113         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1114         if (sd2)
1115           {
1116              sd2->parent_obj = obj;
1117              sd2->top_win_focused = sd->top_win_focused;
1118           }
1119         evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1120                                        _sub_obj_hide, sd);
1121      }
1122    evas_object_clip_set(sobj, evas_object_clip_get(obj));
1123    evas_object_smart_member_add(sobj, obj);
1124    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1125                                   _sub_obj_del, sd);
1126    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1127                                   _sub_obj_mouse_down, sd);
1128    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1129                                   _sub_obj_mouse_move, sd);
1130    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1131                                   _sub_obj_mouse_up, sd);
1132    _smart_reconfigure(sd);
1133    evas_object_data_set(sobj, "elm-parent", obj);
1134    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1135    if (_elm_widget_is(sobj))
1136      {
1137         if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1138      }
1139 }
1140
1141 EAPI void
1142 elm_widget_hover_object_set(Evas_Object *obj,
1143                             Evas_Object *sobj)
1144 {
1145    API_ENTRY return;
1146    if (sd->hover_obj)
1147      {
1148         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1149                                             _sub_obj_del, sd);
1150      }
1151    sd->hover_obj = sobj;
1152    if (sd->hover_obj)
1153      {
1154         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1155                                        _sub_obj_del, sd);
1156         _smart_reconfigure(sd);
1157      }
1158 }
1159
1160 EAPI void
1161 elm_widget_can_focus_set(Evas_Object *obj,
1162                          Eina_Bool    can_focus)
1163 {
1164    API_ENTRY return;
1165
1166    can_focus = !!can_focus;
1167
1168    if (sd->can_focus == can_focus) return;
1169    sd->can_focus = can_focus;
1170    if (sd->can_focus)
1171      {
1172         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1173                                        _propagate_event,
1174                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1175         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1176                                        _propagate_event,
1177                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1178         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1179                                        _propagate_event,
1180                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1181      }
1182    else
1183      {
1184         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1185                                        _propagate_event);
1186         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1187                                        _propagate_event);
1188         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1189                                        _propagate_event);
1190      }
1191 }
1192
1193 EAPI Eina_Bool
1194 elm_widget_can_focus_get(const Evas_Object *obj)
1195 {
1196    API_ENTRY return EINA_FALSE;
1197    return sd->can_focus;
1198 }
1199
1200 EAPI Eina_Bool
1201 elm_widget_child_can_focus_get(const Evas_Object *obj)
1202 {
1203    API_ENTRY return EINA_FALSE;
1204    return sd->child_can_focus;
1205 }
1206
1207 /**
1208  * @internal
1209  *
1210  * This API makes the widget object and its children to be unfocusable.
1211  *
1212  * This API can be helpful for an object to be deleted.
1213  * When an object will be deleted soon, it and its children may not
1214  * want to get focus (by focus reverting or by other focus controls).
1215  * Then, just use this API before deleting.
1216  *
1217  * @param obj The widget root of sub-tree
1218  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1219  *
1220  * @ingroup Widget
1221  */
1222 EAPI void
1223 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1224                                 Eina_Bool    tree_unfocusable)
1225 {
1226    API_ENTRY return;
1227
1228    tree_unfocusable = !!tree_unfocusable;
1229    if (sd->tree_unfocusable == tree_unfocusable) return;
1230    sd->tree_unfocusable = tree_unfocusable;
1231    elm_widget_focus_tree_unfocusable_handle(obj);
1232 }
1233
1234 /**
1235  * @internal
1236  *
1237  * This returns true, if the object sub-tree is unfocusable.
1238  *
1239  * @param obj The widget root of sub-tree
1240  * @return EINA_TRUE if the object sub-tree is unfocusable
1241  *
1242  * @ingroup Widget
1243  */
1244 EAPI Eina_Bool
1245 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1246 {
1247    API_ENTRY return EINA_FALSE;
1248    return sd->tree_unfocusable;
1249 }
1250
1251 /**
1252  * @internal
1253  *
1254  * Get the list of focusable child objects.
1255  *
1256  * This function retruns list of child objects which can get focus.
1257  *
1258  * @param obj The parent widget
1259  * @retrun list of focusable child objects.
1260  *
1261  * @ingroup Widget
1262  */
1263 EAPI Eina_List *
1264 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1265 {
1266    API_ENTRY return NULL;
1267
1268    const Eina_List *l;
1269    Eina_List *child_list = NULL;
1270    Evas_Object *child;
1271
1272    if (sd->subobjs)
1273      {
1274         EINA_LIST_FOREACH(sd->subobjs, l, child)
1275           {
1276              if ((elm_widget_can_focus_get(child)) &&
1277                  (evas_object_visible_get(child)) &&
1278                  (!elm_widget_disabled_get(child)))
1279                child_list = eina_list_append(child_list, child);
1280              else if (elm_widget_is(child))
1281                {
1282                   Eina_List *can_focus_list;
1283                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1284                   if (can_focus_list)
1285                     child_list = eina_list_merge(child_list, can_focus_list);
1286                }
1287           }
1288      }
1289    return child_list;
1290 }
1291
1292 EAPI void
1293 elm_widget_highlight_ignore_set(Evas_Object *obj,
1294                                 Eina_Bool    ignore)
1295 {
1296    API_ENTRY return;
1297    sd->highlight_ignore = !!ignore;
1298 }
1299
1300 EAPI Eina_Bool
1301 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1302 {
1303    API_ENTRY return EINA_FALSE;
1304    return sd->highlight_ignore;
1305 }
1306
1307 EAPI void
1308 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1309                                   Eina_Bool    highlight)
1310 {
1311    API_ENTRY return;
1312    sd->highlight_in_theme = !!highlight;
1313    /* FIXME: if focused, it should switch from one mode to the other */
1314 }
1315
1316 EAPI Eina_Bool
1317 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1318 {
1319    API_ENTRY return EINA_FALSE;
1320    return sd->highlight_in_theme;
1321 }
1322
1323 EAPI Eina_Bool
1324 elm_widget_focus_get(const Evas_Object *obj)
1325 {
1326    API_ENTRY return EINA_FALSE;
1327    return sd->focused;
1328 }
1329
1330 EAPI Evas_Object *
1331 elm_widget_focused_object_get(const Evas_Object *obj)
1332 {
1333    const Evas_Object *subobj;
1334    const Eina_List *l;
1335    API_ENTRY return NULL;
1336
1337    if (!sd->focused) return NULL;
1338    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1339      {
1340         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1341         if (fobj) return fobj;
1342      }
1343    return (Evas_Object *)obj;
1344 }
1345
1346 EAPI Evas_Object *
1347 elm_widget_top_get(const Evas_Object *obj)
1348 {
1349    API_ENTRY return NULL;
1350    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1351    return (Evas_Object *)obj;
1352 }
1353
1354 EAPI Eina_Bool
1355 elm_widget_is(const Evas_Object *obj)
1356 {
1357    return _elm_widget_is(obj);
1358 }
1359
1360 EAPI Evas_Object *
1361 elm_widget_parent_widget_get(const Evas_Object *obj)
1362 {
1363    Evas_Object *parent;
1364
1365    if (_elm_widget_is(obj))
1366      {
1367         Smart_Data *sd = evas_object_smart_data_get(obj);
1368         if (!sd) return NULL;
1369         parent = sd->parent_obj;
1370      }
1371    else
1372      {
1373         parent = evas_object_data_get(obj, "elm-parent");
1374         if (!parent) parent = evas_object_smart_parent_get(obj);
1375      }
1376
1377    while (parent)
1378      {
1379         Evas_Object *elm_parent;
1380         if (_elm_widget_is(parent)) break;
1381         elm_parent = evas_object_data_get(parent, "elm-parent");
1382         if (elm_parent) parent = elm_parent;
1383         else parent = evas_object_smart_parent_get(parent);
1384      }
1385    return parent;
1386 }
1387
1388 EAPI Evas_Object *
1389 elm_widget_parent2_get(const Evas_Object *obj)
1390 {
1391    if (_elm_widget_is(obj))
1392      {
1393         Smart_Data *sd = evas_object_smart_data_get(obj);
1394         if (sd) return sd->parent2;
1395      }
1396    return NULL;
1397 }
1398
1399 EAPI void
1400 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1401 {
1402    API_ENTRY return;
1403    sd->parent2 = parent;
1404 }
1405
1406 EAPI void
1407 elm_widget_event_callback_add(Evas_Object *obj,
1408                               Elm_Event_Cb func,
1409                               const void  *data)
1410 {
1411    API_ENTRY return;
1412    EINA_SAFETY_ON_NULL_RETURN(func);
1413    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1414    ecb->func = func;
1415    ecb->data = data;
1416    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1417 }
1418
1419 EAPI void *
1420 elm_widget_event_callback_del(Evas_Object *obj,
1421                               Elm_Event_Cb func,
1422                               const void  *data)
1423 {
1424    API_ENTRY return NULL;
1425    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1426    Eina_List *l;
1427    Elm_Event_Cb_Data *ecd;
1428    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1429      if ((ecd->func == func) && (ecd->data == data))
1430        {
1431           free(ecd);
1432           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1433           return (void *)data;
1434        }
1435    return NULL;
1436 }
1437
1438 EAPI Eina_Bool
1439 elm_widget_event_propagate(Evas_Object       *obj,
1440                            Evas_Callback_Type type,
1441                            void              *event_info,
1442                            Evas_Event_Flags  *event_flags)
1443 {
1444    API_ENTRY return EINA_FALSE; //TODO reduce.
1445    if (!_elm_widget_is(obj)) return EINA_FALSE;
1446    Evas_Object *parent = obj;
1447    Elm_Event_Cb_Data *ecd;
1448    Eina_List *l, *l_prev;
1449
1450    while (parent &&
1451           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1452      {
1453         sd = evas_object_smart_data_get(parent);
1454         if ((!sd) || (!_elm_widget_is(obj)))
1455           return EINA_FALSE; //Not Elm Widget
1456
1457         if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1458           return EINA_TRUE;
1459
1460         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1461           {
1462              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1463                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1464                return EINA_TRUE;
1465           }
1466         parent = sd->parent_obj;
1467      }
1468
1469    return EINA_FALSE;
1470 }
1471
1472 /**
1473  * @internal
1474  *
1475  * Set custom focus chain.
1476  *
1477  * This function i set one new and overwrite any previous custom focus chain
1478  * with the list of objects. The previous list will be deleted and this list
1479  * will be managed. After setted, don't modity it.
1480  *
1481  * @note On focus cycle, only will be evaluated children of this container.
1482  *
1483  * @param obj The container widget
1484  * @param objs Chain of objects to pass focus
1485  * @ingroup Widget
1486  */
1487 EAPI void
1488 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1489                                   Eina_List   *objs)
1490 {
1491    API_ENTRY return;
1492    if (!sd->focus_next_func)
1493      return;
1494
1495    elm_widget_focus_custom_chain_unset(obj);
1496
1497    Eina_List *l;
1498    Evas_Object *o;
1499
1500    EINA_LIST_FOREACH(objs, l, o)
1501      {
1502         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1503                                        _elm_object_focus_chain_del_cb, sd);
1504      }
1505
1506    sd->focus_chain = objs;
1507 }
1508
1509 /**
1510  * @internal
1511  *
1512  * Get custom focus chain
1513  *
1514  * @param obj The container widget
1515  * @ingroup Widget
1516  */
1517 EAPI const Eina_List *
1518 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1519 {
1520    API_ENTRY return NULL;
1521    return (const Eina_List *)sd->focus_chain;
1522 }
1523
1524 /**
1525  * @internal
1526  *
1527  * Unset custom focus chain
1528  *
1529  * @param obj The container widget
1530  * @ingroup Widget
1531  */
1532 EAPI void
1533 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1534 {
1535    API_ENTRY return;
1536    Eina_List *l, *l_next;
1537    Evas_Object *o;
1538
1539    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1540      {
1541         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1542                                             _elm_object_focus_chain_del_cb, sd);
1543         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1544      }
1545 }
1546
1547 /**
1548  * @internal
1549  *
1550  * Append object to custom focus chain.
1551  *
1552  * @note If relative_child equal to NULL or not in custom chain, the object
1553  * will be added in end.
1554  *
1555  * @note On focus cycle, only will be evaluated children of this container.
1556  *
1557  * @param obj The container widget
1558  * @param child The child to be added in custom chain
1559  * @param relative_child The relative object to position the child
1560  * @ingroup Widget
1561  */
1562 EAPI void
1563 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1564                                      Evas_Object *child,
1565                                      Evas_Object *relative_child)
1566 {
1567    API_ENTRY return;
1568    EINA_SAFETY_ON_NULL_RETURN(child);
1569    if (!sd->focus_next_func) return;
1570
1571    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1572                                        _elm_object_focus_chain_del_cb, sd);
1573
1574    if (!relative_child)
1575      sd->focus_chain = eina_list_append(sd->focus_chain, child);
1576    else
1577      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1578                                                  child, relative_child);
1579 }
1580
1581 /**
1582  * @internal
1583  *
1584  * Prepend object to custom focus chain.
1585  *
1586  * @note If relative_child equal to NULL or not in custom chain, the object
1587  * will be added in begin.
1588  *
1589  * @note On focus cycle, only will be evaluated children of this container.
1590  *
1591  * @param obj The container widget
1592  * @param child The child to be added in custom chain
1593  * @param relative_child The relative object to position the child
1594  * @ingroup Widget
1595  */
1596 EAPI void
1597 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1598                                       Evas_Object *child,
1599                                       Evas_Object *relative_child)
1600 {
1601    API_ENTRY return;
1602    EINA_SAFETY_ON_NULL_RETURN(child);
1603
1604    if (!sd->focus_next_func) return;
1605
1606    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1607                                        _elm_object_focus_chain_del_cb, sd);
1608
1609    if (!relative_child)
1610      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1611    else
1612      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1613                                                   child, relative_child);
1614 }
1615
1616 /**
1617  * @internal
1618  *
1619  * Give focus to next object in object tree.
1620  *
1621  * Give focus to next object in focus chain of one object sub-tree.
1622  * If the last object of chain already have focus, the focus will go to the
1623  * first object of chain.
1624  *
1625  * @param obj The widget root of sub-tree
1626  * @param dir Direction to cycle the focus
1627  *
1628  * @ingroup Widget
1629  */
1630 EAPI void
1631 elm_widget_focus_cycle(Evas_Object        *obj,
1632                        Elm_Focus_Direction dir)
1633 {
1634    Evas_Object *target = NULL;
1635    if (!_elm_widget_is(obj))
1636      return;
1637    elm_widget_focus_next_get(obj, dir, &target);
1638    if (target)
1639      elm_widget_focus_steal(target);
1640 }
1641
1642 /**
1643  * @internal
1644  *
1645  * Give focus to near object in one direction.
1646  *
1647  * Give focus to near object in direction of one object.
1648  * If none focusable object in given direction, the focus will not change.
1649  *
1650  * @param obj The reference widget
1651  * @param x Horizontal component of direction to focus
1652  * @param y Vertical component of direction to focus
1653  *
1654  * @ingroup Widget
1655  */
1656 //XXX: If x, y indicates the elements of the directional vector,
1657 //It would be better if these values are the normalized value(float x, float y)
1658 //or degree.
1659 EINA_DEPRECATED EAPI void
1660 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1661                               int          x __UNUSED__,
1662                               int          y __UNUSED__)
1663 {
1664    return; /* TODO */
1665 }
1666
1667 /**
1668  * @internal
1669  *
1670  * Get next object in focus chain of object tree.
1671  *
1672  * Get next object in focus chain of one object sub-tree.
1673  * Return the next object by reference. If don't have any candidate to receive
1674  * focus before chain end, the first candidate will be returned.
1675  *
1676  * @param obj The widget root of sub-tree
1677  * @param dir Direction os focus chain
1678  * @param next The next object in focus chain
1679  * @return EINA_TRUE if don't need focus chain restart/loop back
1680  *         to use 'next' obj.
1681  *
1682  * @ingroup Widget
1683  */
1684 EAPI Eina_Bool
1685 elm_widget_focus_next_get(const Evas_Object  *obj,
1686                           Elm_Focus_Direction dir,
1687                           Evas_Object       **next)
1688 {
1689    if (!next)
1690      return EINA_FALSE;
1691    *next = NULL;
1692
1693    API_ENTRY return EINA_FALSE;
1694
1695    /* Ignore if disabled */
1696    if ((!evas_object_visible_get(obj))
1697        || (elm_widget_disabled_get(obj))
1698        || (elm_widget_tree_unfocusable_get(obj)))
1699      return EINA_FALSE;
1700
1701    /* Try use hook */
1702    if (sd->focus_next_func)
1703      return sd->focus_next_func(obj, dir, next);
1704
1705    if (!elm_widget_can_focus_get(obj))
1706      return EINA_FALSE;
1707
1708    /* Return */
1709    *next = (Evas_Object *)obj;
1710    return !elm_widget_focus_get(obj);
1711 }
1712
1713 /**
1714  * @internal
1715  *
1716  * Get next object in focus chain of object tree in list.
1717  *
1718  * Get next object in focus chain of one object sub-tree ordered by one list.
1719  * Return the next object by reference. If don't have any candidate to receive
1720  * focus before list end, the first candidate will be returned.
1721  *
1722  * @param obj The widget root of sub-tree
1723  * @param dir Direction os focus chain
1724  * @param items list with ordered objects
1725  * @param list_data_get function to get the object from one item of list
1726  * @param next The next object in focus chain
1727  * @return EINA_TRUE if don't need focus chain restart/loop back
1728  *         to use 'next' obj.
1729  *
1730  * @ingroup Widget
1731  */
1732 EAPI Eina_Bool
1733 elm_widget_focus_list_next_get(const Evas_Object  *obj,
1734                                const Eina_List    *items,
1735                                void *(*list_data_get)(const Eina_List * list),
1736                                Elm_Focus_Direction dir,
1737                                Evas_Object       **next)
1738 {
1739    Eina_List *(*list_next)(const Eina_List * list) = NULL;
1740
1741    if (!next)
1742      return EINA_FALSE;
1743    *next = NULL;
1744
1745    if (!_elm_widget_is(obj))
1746      return EINA_FALSE;
1747
1748    if (!items)
1749      return EINA_FALSE;
1750
1751    /* Direction */
1752    if (dir == ELM_FOCUS_PREVIOUS)
1753      {
1754         items = eina_list_last(items);
1755         list_next = eina_list_prev;
1756      }
1757    else if (dir == ELM_FOCUS_NEXT)
1758      list_next = eina_list_next;
1759    else
1760      return EINA_FALSE;
1761
1762    const Eina_List *l = items;
1763
1764    /* Recovery last focused sub item */
1765    if (elm_widget_focus_get(obj))
1766      for (; l; l = list_next(l))
1767        {
1768           Evas_Object *cur = list_data_get(l);
1769           if (elm_widget_focus_get(cur)) break;
1770        }
1771
1772    const Eina_List *start = l;
1773    Evas_Object *to_focus = NULL;
1774
1775    /* Interate sub items */
1776    /* Go to end of list */
1777    for (; l; l = list_next(l))
1778      {
1779         Evas_Object *tmp = NULL;
1780         Evas_Object *cur = list_data_get(l);
1781
1782         if (elm_widget_parent_get(cur) != obj)
1783           continue;
1784
1785         /* Try Focus cycle in subitem */
1786         if (elm_widget_focus_next_get(cur, dir, &tmp))
1787           {
1788              *next = tmp;
1789              return EINA_TRUE;
1790           }
1791         else if ((tmp) && (!to_focus))
1792           to_focus = tmp;
1793      }
1794
1795    l = items;
1796
1797    /* Get First possible */
1798    for (; l != start; l = list_next(l))
1799      {
1800         Evas_Object *tmp = NULL;
1801         Evas_Object *cur = list_data_get(l);
1802
1803         if (elm_widget_parent_get(cur) != obj)
1804           continue;
1805
1806         /* Try Focus cycle in subitem */
1807         elm_widget_focus_next_get(cur, dir, &tmp);
1808         if (tmp)
1809           {
1810              *next = tmp;
1811              return EINA_FALSE;
1812           }
1813      }
1814
1815    *next = to_focus;
1816    return EINA_FALSE;
1817 }
1818
1819 EAPI void
1820 elm_widget_signal_emit(Evas_Object *obj,
1821                        const char  *emission,
1822                        const char  *source)
1823 {
1824    API_ENTRY return;
1825    if (!sd->signal_func) return;
1826    sd->signal_func(obj, emission, source);
1827 }
1828
1829 static void
1830 _edje_signal_callback(void        *data,
1831                       Evas_Object *obj __UNUSED__,
1832                       const char  *emission,
1833                       const char  *source)
1834 {
1835    Edje_Signal_Data *esd = data;
1836    esd->func(esd->data, esd->obj, emission, source);
1837 }
1838
1839 EAPI void
1840 elm_widget_signal_callback_add(Evas_Object   *obj,
1841                                const char    *emission,
1842                                const char    *source,
1843                                Edje_Signal_Cb func,
1844                                void          *data)
1845 {
1846    Edje_Signal_Data *esd;
1847    API_ENTRY return;
1848    if (!sd->callback_add_func) return;
1849    EINA_SAFETY_ON_NULL_RETURN(func);
1850
1851    esd = ELM_NEW(Edje_Signal_Data);
1852    if (!esd) return;
1853
1854    esd->obj = obj;
1855    esd->func = func;
1856    esd->emission = eina_stringshare_add(emission);
1857    esd->source = eina_stringshare_add(source);
1858    esd->data = data;
1859    sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1860    sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1861 }
1862
1863 EAPI void *
1864 elm_widget_signal_callback_del(Evas_Object   *obj,
1865                                const char    *emission,
1866                                const char    *source,
1867                                Edje_Signal_Cb func)
1868 {
1869    Edje_Signal_Data *esd;
1870    Eina_List *l;
1871    void *data = NULL;
1872    API_ENTRY return NULL;
1873    if (!sd->callback_del_func) return NULL;
1874
1875    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1876      {
1877         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1878             (!strcmp(esd->source, source)))
1879           {
1880              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1881              eina_stringshare_del(esd->emission);
1882              eina_stringshare_del(esd->source);
1883              data = esd->data;
1884              free(esd);
1885              break;
1886           }
1887      }
1888    sd->callback_del_func(obj, emission, source, _edje_signal_callback, esd);
1889    return data;
1890 }
1891
1892 EAPI void
1893 elm_widget_focus_set(Evas_Object *obj,
1894                      int          first)
1895 {
1896    API_ENTRY return;
1897    if (!sd->focused)
1898      {
1899         focus_order++;
1900         sd->focus_order = focus_order;
1901         sd->focused = EINA_TRUE;
1902         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1903      }
1904    if (sd->focus_func)
1905      {
1906         sd->focus_func(obj);
1907         return;
1908      }
1909    else
1910      {
1911         if (first)
1912           {
1913              if ((_is_focusable(sd->resize_obj)) &&
1914                  (!elm_widget_disabled_get(sd->resize_obj)))
1915                {
1916                   elm_widget_focus_set(sd->resize_obj, first);
1917                }
1918              else
1919                {
1920                   const Eina_List *l;
1921                   Evas_Object *child;
1922                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1923                     {
1924                        if ((_is_focusable(child)) &&
1925                            (!elm_widget_disabled_get(child)))
1926                          {
1927                             elm_widget_focus_set(child, first);
1928                             break;
1929                          }
1930                     }
1931                }
1932           }
1933         else
1934           {
1935              const Eina_List *l;
1936              Evas_Object *child;
1937              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1938                {
1939                   if ((_is_focusable(child)) &&
1940                       (!elm_widget_disabled_get(child)))
1941                     {
1942                        elm_widget_focus_set(child, first);
1943                        break;
1944                     }
1945                }
1946              if (!l)
1947                {
1948                   if ((_is_focusable(sd->resize_obj)) &&
1949                       (!elm_widget_disabled_get(sd->resize_obj)))
1950                     {
1951                        elm_widget_focus_set(sd->resize_obj, first);
1952                     }
1953                }
1954           }
1955      }
1956 }
1957
1958 EAPI Evas_Object *
1959 elm_widget_parent_get(const Evas_Object *obj)
1960 {
1961    API_ENTRY return NULL;
1962    return sd->parent_obj;
1963 }
1964
1965 EAPI void
1966 elm_widget_focused_object_clear(Evas_Object *obj)
1967 {
1968    API_ENTRY return;
1969    if (!sd->focused) return;
1970    if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
1971      elm_widget_focused_object_clear(sd->resize_obj);
1972    else
1973      {
1974         const Eina_List *l;
1975         Evas_Object *child;
1976         EINA_LIST_FOREACH(sd->subobjs, l, child)
1977           {
1978              if (elm_widget_focus_get(child))
1979                {
1980                   elm_widget_focused_object_clear(child);
1981                   break;
1982                }
1983           }
1984      }
1985    sd->focused = EINA_FALSE;
1986    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1987    if (sd->focus_func) sd->focus_func(obj);
1988 }
1989
1990 EAPI void
1991 elm_widget_focus_steal(Evas_Object *obj)
1992 {
1993    Evas_Object *parent, *parent2, *o;
1994    API_ENTRY return;
1995
1996    if (sd->focused) return;
1997    if (sd->disabled) return;
1998    if (!sd->can_focus) return;
1999    if (sd->tree_unfocusable) return;
2000    parent = obj;
2001    for (;;)
2002      {
2003         o = elm_widget_parent_get(parent);
2004         if (!o) break;
2005         sd = evas_object_smart_data_get(o);
2006         if (sd->disabled || sd->tree_unfocusable) return;
2007         if (sd->focused) break;
2008         parent = o;
2009      }
2010    if ((!elm_widget_parent_get(parent)) &&
2011        (!elm_widget_parent2_get(parent)))
2012       elm_widget_focused_object_clear(parent);
2013    else
2014      {
2015         parent2 = elm_widget_parent_get(parent);
2016         if (!parent2) parent2 = elm_widget_parent2_get(parent);
2017         parent = parent2;
2018         sd = evas_object_smart_data_get(parent);
2019         if (sd)
2020           {
2021              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2022                 elm_widget_focused_object_clear(sd->resize_obj);
2023              else
2024                {
2025                   const Eina_List *l;
2026                   Evas_Object *child;
2027                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2028                     {
2029                        if (elm_widget_focus_get(child))
2030                          {
2031                             elm_widget_focused_object_clear(child);
2032                             break;
2033                          }
2034                     }
2035                }
2036           }
2037      }
2038    _parent_focus(obj);
2039    return;
2040 }
2041
2042 EAPI void
2043 elm_widget_focus_restore(Evas_Object *obj)
2044 {
2045    Evas_Object *newest = NULL;
2046    unsigned int newest_focus_order = 0;
2047    API_ENTRY return;
2048
2049    newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2050    if (newest)
2051      {
2052         elm_object_focus_set(newest, EINA_FALSE);
2053         elm_object_focus_set(newest, EINA_TRUE);
2054      }
2055 }
2056
2057 void
2058 _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2059 {
2060    const Eina_List *l;
2061    Evas_Object *child;
2062    API_ENTRY return;
2063
2064    if (sd->top_win_focused == top_win_focused) return;
2065    if (sd->resize_obj)
2066      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2067    EINA_LIST_FOREACH(sd->subobjs, l, child)
2068      {
2069         _elm_widget_top_win_focused_set(child, top_win_focused);
2070      }
2071    sd->top_win_focused = top_win_focused;
2072 }
2073
2074 Eina_Bool
2075 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2076 {
2077    API_ENTRY return EINA_FALSE;
2078    return sd->top_win_focused;
2079 }
2080
2081 EAPI void
2082 elm_widget_activate(Evas_Object *obj)
2083 {
2084    API_ENTRY return;
2085    elm_widget_change(obj);
2086    if (sd->activate_func) sd->activate_func(obj);
2087 }
2088
2089 EAPI void
2090 elm_widget_change(Evas_Object *obj)
2091 {
2092    API_ENTRY return;
2093    elm_widget_change(elm_widget_parent_get(obj));
2094    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2095 }
2096
2097 EAPI void
2098 elm_widget_disabled_set(Evas_Object *obj,
2099                         Eina_Bool    disabled)
2100 {
2101    API_ENTRY return;
2102
2103    if (sd->disabled == disabled) return;
2104    sd->disabled = !!disabled;
2105    elm_widget_focus_disabled_handle(obj);
2106    if (sd->disable_func) sd->disable_func(obj);
2107 }
2108
2109 EAPI Eina_Bool
2110 elm_widget_disabled_get(const Evas_Object *obj)
2111 {
2112    API_ENTRY return 0;
2113    return sd->disabled;
2114 }
2115
2116 EAPI void
2117 elm_widget_show_region_set(Evas_Object *obj,
2118                            Evas_Coord   x,
2119                            Evas_Coord   y,
2120                            Evas_Coord   w,
2121                            Evas_Coord   h,
2122                            Eina_Bool    forceshow)
2123 {
2124    Evas_Object *parent_obj, *child_obj;
2125    Evas_Coord px, py, cx, cy;
2126
2127    API_ENTRY return;
2128    
2129    evas_smart_objects_calculate(evas_object_evas_get(obj));
2130    
2131    if (!forceshow && (x == sd->rx) && (y == sd->ry) && 
2132        (w == sd->rw) && (h == sd->rh)) return;
2133    sd->rx = x;
2134    sd->ry = y;
2135    sd->rw = w;
2136    sd->rh = h;
2137    if (sd->on_show_region_func)
2138      sd->on_show_region_func(sd->on_show_region_data, obj);
2139
2140    do
2141      {
2142         parent_obj = sd->parent_obj;
2143         child_obj = sd->obj;
2144         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2145         sd = evas_object_smart_data_get(parent_obj);
2146         if (!sd) break;
2147
2148         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2149         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2150
2151         x += (cx - px);
2152         y += (cy - py);
2153         sd->rx = x;
2154         sd->ry = y;
2155         sd->rw = w;
2156         sd->rh = h;
2157
2158         if (sd->on_show_region_func)
2159           {
2160              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2161           }
2162      }
2163    while (parent_obj);
2164 }
2165
2166 EAPI void
2167 elm_widget_show_region_get(const Evas_Object *obj,
2168                            Evas_Coord        *x,
2169                            Evas_Coord        *y,
2170                            Evas_Coord        *w,
2171                            Evas_Coord        *h)
2172 {
2173    API_ENTRY return;
2174    if (x) *x = sd->rx;
2175    if (y) *y = sd->ry;
2176    if (w) *w = sd->rw;
2177    if (h) *h = sd->rh;
2178 }
2179
2180 /**
2181  * @internal
2182  *
2183  * Get the focus region of the given widget.
2184  *
2185  * The focus region is the area of a widget that should brought into the
2186  * visible area when the widget is focused. Mostly used to show the part of
2187  * an entry where the cursor is, for example. The area returned is relative
2188  * to the object @p obj.
2189  * If the @p obj doesn't have the proper on_focus_region_hook set, this
2190  * function will return the full size of the object.
2191  *
2192  * @param obj The widget object
2193  * @param x Where to store the x coordinate of the area
2194  * @param y Where to store the y coordinate of the area
2195  * @param w Where to store the width of the area
2196  * @param h Where to store the height of the area
2197  *
2198  * @ingroup Widget
2199  */
2200 EAPI void
2201 elm_widget_focus_region_get(const Evas_Object *obj,
2202                             Evas_Coord        *x,
2203                             Evas_Coord        *y,
2204                             Evas_Coord        *w,
2205                             Evas_Coord        *h)
2206 {
2207    Smart_Data *sd;
2208
2209    if (!obj) return;
2210
2211    sd = evas_object_smart_data_get(obj);
2212    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2213      {
2214         evas_object_geometry_get(obj, NULL, NULL, w, h);
2215         if (x) *x = 0;
2216         if (y) *y = 0;
2217         return;
2218      }
2219    sd->on_focus_region_func(obj, x, y, w, h);
2220 }
2221
2222 EAPI void
2223 elm_widget_scroll_hold_push(Evas_Object *obj)
2224 {
2225    API_ENTRY return;
2226    sd->scroll_hold++;
2227    if (sd->scroll_hold == 1)
2228      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2229    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2230    // FIXME: on delete/reparent hold pop
2231 }
2232
2233 EAPI void
2234 elm_widget_scroll_hold_pop(Evas_Object *obj)
2235 {
2236    API_ENTRY return;
2237    sd->scroll_hold--;
2238    if (!sd->scroll_hold)
2239      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2240    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2241    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2242 }
2243
2244 EAPI int
2245 elm_widget_scroll_hold_get(const Evas_Object *obj)
2246 {
2247    API_ENTRY return 0;
2248    return sd->scroll_hold;
2249 }
2250
2251 EAPI void
2252 elm_widget_scroll_freeze_push(Evas_Object *obj)
2253 {
2254    API_ENTRY return;
2255    sd->scroll_freeze++;
2256    if (sd->scroll_freeze == 1)
2257      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2258    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2259    // FIXME: on delete/reparent freeze pop
2260 }
2261
2262 EAPI void
2263 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2264 {
2265    API_ENTRY return;
2266    sd->scroll_freeze--;
2267    if (!sd->scroll_freeze)
2268      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2269    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2270    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2271 }
2272
2273 EAPI int
2274 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2275 {
2276    API_ENTRY return 0;
2277    return sd->scroll_freeze;
2278 }
2279
2280 EAPI void
2281 elm_widget_scale_set(Evas_Object *obj,
2282                      double       scale)
2283 {
2284    API_ENTRY return;
2285    if (scale <= 0.0) scale = 0.0;
2286    if (sd->scale != scale)
2287      {
2288         sd->scale = scale;
2289         elm_widget_theme(obj);
2290      }
2291 }
2292
2293 EAPI double
2294 elm_widget_scale_get(const Evas_Object *obj)
2295 {
2296    API_ENTRY return 1.0;
2297    // FIXME: save walking up the tree by storing/caching parent scale
2298    if (sd->scale == 0.0)
2299      {
2300         if (sd->parent_obj)
2301           return elm_widget_scale_get(sd->parent_obj);
2302         else
2303           return 1.0;
2304      }
2305    return sd->scale;
2306 }
2307
2308 EAPI void
2309 elm_widget_theme_set(Evas_Object *obj,
2310                      Elm_Theme   *th)
2311 {
2312    API_ENTRY return;
2313    if (sd->theme != th)
2314      {
2315         if (sd->theme) elm_theme_free(sd->theme);
2316         sd->theme = th;
2317         if (th) th->ref++;
2318         elm_widget_theme(obj);
2319      }
2320 }
2321
2322 EAPI void
2323 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2324 {
2325    API_ENTRY return;
2326
2327    if (!sd->text_set_func)
2328      return;
2329
2330    sd->text_set_func(obj, part, label);
2331 }
2332
2333 EAPI const char *
2334 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2335 {
2336    API_ENTRY return NULL;
2337
2338    if (!sd->text_get_func)
2339      return NULL;
2340
2341    return sd->text_get_func(obj, part);
2342 }
2343
2344 EAPI void
2345 elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2346 {
2347    const char *str;
2348    Eina_List *l;
2349    Elm_Translate_String_Data *ts = NULL;
2350    API_ENTRY return;
2351
2352    str = eina_stringshare_add(part);
2353    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2354       if (ts->id == str)
2355         break;
2356       else
2357         ts = NULL;
2358
2359    if (!ts && !label)
2360      eina_stringshare_del(str);
2361    else if (!ts)
2362      {
2363         ts = malloc(sizeof(Elm_Translate_String_Data));
2364         if (!ts) return;
2365
2366         ts->id = str;
2367         ts->domain = eina_stringshare_add(domain);
2368         ts->string = eina_stringshare_add(label);
2369         sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2370      }
2371    else
2372      {
2373         if (label)
2374           {
2375              eina_stringshare_replace(&ts->domain, domain);
2376              eina_stringshare_replace(&ts->string, label);
2377           }
2378         else
2379           {
2380              sd->translate_strings = eina_list_remove_list(
2381                                                 sd->translate_strings, l);
2382              eina_stringshare_del(ts->id);
2383              eina_stringshare_del(ts->domain);
2384              eina_stringshare_del(ts->string);
2385              free(ts);
2386           }
2387         eina_stringshare_del(str);
2388      }
2389
2390 #ifdef HAVE_GETTEXT
2391    if (label && label[0])
2392      label = dgettext(domain, label);
2393 #endif
2394    elm_widget_text_part_set(obj, part, label);
2395 }
2396
2397 EAPI const char *
2398 elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2399 {
2400    const char *str, *ret = NULL;
2401    Eina_List *l;
2402    Elm_Translate_String_Data *ts;
2403    API_ENTRY return NULL;
2404
2405    str = eina_stringshare_add(part);
2406    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2407       if (ts->id == str)
2408         {
2409            ret = ts->string;
2410            break;
2411         }
2412    eina_stringshare_del(str);
2413    return ret;
2414 }
2415
2416 EAPI void
2417 elm_widget_translate(Evas_Object *obj)
2418 {
2419    const Eina_List *l;
2420    Evas_Object *child;
2421 #ifdef HAVE_GETTEXT
2422    Elm_Translate_String_Data *ts;
2423 #endif
2424
2425    API_ENTRY return;
2426    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2427    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2428    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2429    if (sd->translate_func) sd->translate_func(obj);
2430
2431 #ifdef HAVE_GETTEXT
2432    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2433      {
2434         const char *s = dgettext(ts->domain, ts->string);
2435         elm_widget_text_part_set(obj, ts->id, s);
2436      }
2437 #endif
2438 }
2439
2440 EAPI void
2441 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2442 {
2443    API_ENTRY return;
2444
2445    if (!sd->content_set_func)  return;
2446    sd->content_set_func(obj, part, content);
2447 }
2448
2449 EAPI Evas_Object *
2450 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2451 {
2452    API_ENTRY return NULL;
2453
2454    if (!sd->content_get_func) return NULL;
2455    return sd->content_get_func(obj, part);
2456 }
2457
2458 EAPI Evas_Object *
2459 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2460 {
2461    API_ENTRY return NULL;
2462
2463    if (!sd->content_unset_func) return NULL;
2464    return sd->content_unset_func(obj, part);
2465 }
2466
2467 EAPI void
2468 elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2469 {
2470    API_ENTRY return;
2471    if (sd->access_info) eina_stringshare_del(sd->access_info);
2472    if (!txt) sd->access_info = NULL;
2473    else sd->access_info = eina_stringshare_add(txt);
2474 }
2475
2476 EAPI const char *
2477 elm_widget_access_info_get(const Evas_Object *obj)
2478 {
2479    API_ENTRY return NULL;
2480    return sd->access_info;
2481 }
2482
2483 EAPI Elm_Theme *
2484 elm_widget_theme_get(const Evas_Object *obj)
2485 {
2486    API_ENTRY return NULL;
2487    if (!sd->theme)
2488      {
2489         if (sd->parent_obj)
2490           return elm_widget_theme_get(sd->parent_obj);
2491         else
2492           return NULL;
2493      }
2494    return sd->theme;
2495 }
2496
2497 EAPI Eina_Bool
2498 elm_widget_style_set(Evas_Object *obj,
2499                      const char  *style)
2500 {
2501    API_ENTRY return EINA_FALSE;
2502
2503    if (eina_stringshare_replace(&sd->style, style))
2504      return elm_widget_theme(obj);
2505
2506    return EINA_TRUE;
2507 }
2508
2509 EAPI const char *
2510 elm_widget_style_get(const Evas_Object *obj)
2511 {
2512    API_ENTRY return NULL;
2513    if (sd->style) return sd->style;
2514    return "default";
2515 }
2516
2517 EAPI void
2518 elm_widget_type_set(Evas_Object *obj,
2519                     const char  *type)
2520 {
2521    API_ENTRY return;
2522    eina_stringshare_replace(&sd->type, type);
2523 }
2524
2525 EAPI const char *
2526 elm_widget_type_get(const Evas_Object *obj)
2527 {
2528    API_ENTRY return NULL;
2529    if (sd->type) return sd->type;
2530    return "";
2531 }
2532
2533 EAPI void
2534 elm_widget_tooltip_add(Evas_Object *obj,
2535                        Elm_Tooltip *tt)
2536 {
2537    API_ENTRY return;
2538    sd->tooltips = eina_list_append(sd->tooltips, tt);
2539 }
2540
2541 EAPI void
2542 elm_widget_tooltip_del(Evas_Object *obj,
2543                        Elm_Tooltip *tt)
2544 {
2545    API_ENTRY return;
2546    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2547 }
2548
2549 EAPI void
2550 elm_widget_cursor_add(Evas_Object *obj,
2551                       Elm_Cursor  *cur)
2552 {
2553    API_ENTRY return;
2554    sd->cursors = eina_list_append(sd->cursors, cur);
2555 }
2556
2557 EAPI void
2558 elm_widget_cursor_del(Evas_Object *obj,
2559                       Elm_Cursor  *cur)
2560 {
2561    API_ENTRY return;
2562    sd->cursors = eina_list_remove(sd->cursors, cur);
2563 }
2564
2565 EAPI void
2566 elm_widget_drag_lock_x_set(Evas_Object *obj,
2567                            Eina_Bool    lock)
2568 {
2569    API_ENTRY return;
2570    if (sd->drag_x_locked == lock) return;
2571    sd->drag_x_locked = lock;
2572    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2573    else _propagate_x_drag_lock(obj, -1);
2574 }
2575
2576 EAPI void
2577 elm_widget_drag_lock_y_set(Evas_Object *obj,
2578                            Eina_Bool    lock)
2579 {
2580    API_ENTRY return;
2581    if (sd->drag_y_locked == lock) return;
2582    sd->drag_y_locked = lock;
2583    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2584    else _propagate_y_drag_lock(obj, -1);
2585 }
2586
2587 EAPI Eina_Bool
2588 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2589 {
2590    API_ENTRY return EINA_FALSE;
2591    return sd->drag_x_locked;
2592 }
2593
2594 EAPI Eina_Bool
2595 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2596 {
2597    API_ENTRY return EINA_FALSE;
2598    return sd->drag_y_locked;
2599 }
2600
2601 EAPI int
2602 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2603 {
2604    API_ENTRY return 0;
2605    return sd->child_drag_x_locked;
2606 }
2607
2608 EAPI int
2609 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2610 {
2611    API_ENTRY return 0;
2612    return sd->child_drag_y_locked;
2613 }
2614
2615 EAPI Eina_Bool
2616 elm_widget_theme_object_set(Evas_Object *obj,
2617                             Evas_Object *edj,
2618                             const char  *wname,
2619                             const char  *welement,
2620                             const char  *wstyle)
2621 {
2622    API_ENTRY return EINA_FALSE;
2623    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2624 }
2625
2626 EAPI Eina_Bool
2627 elm_widget_is_check(const Evas_Object *obj)
2628 {
2629    static int abort_on_warn = -1;
2630    if (elm_widget_is(obj))
2631       return EINA_TRUE;
2632
2633    ERR("Passing Object: %p.", obj);
2634    if (abort_on_warn == -1)
2635      {
2636         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2637         else abort_on_warn = 0;
2638      }
2639    if (abort_on_warn == 1) abort();
2640    return EINA_FALSE;
2641 }
2642
2643 EAPI Eina_Bool
2644 elm_widget_type_check(const Evas_Object *obj,
2645                       const char        *type,
2646                       const char        *func)
2647 {
2648    const char *provided, *expected = "(unknown)";
2649    static int abort_on_warn = -1;
2650    provided = elm_widget_type_get(obj);
2651    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2652    if (type) expected = type;
2653    if ((!provided) || (!provided[0]))
2654      {
2655         provided = evas_object_type_get(obj);
2656         if ((!provided) || (!provided[0]))
2657           provided = "(unknown)";
2658      }
2659    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2660    if (abort_on_warn == -1)
2661      {
2662         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2663         else abort_on_warn = 0;
2664      }
2665    if (abort_on_warn == 1) abort();
2666    return EINA_FALSE;
2667 }
2668
2669 static Evas_Object *
2670 _widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2671 {
2672    Eina_List *l;
2673    Evas_Object *child;
2674    const char *s;
2675    INTERNAL_ENTRY NULL;
2676    
2677    if (!_elm_widget_is(obj)) return NULL;
2678    if (sd->resize_obj)
2679      {
2680         s = evas_object_name_get(sd->resize_obj);
2681         if ((s) && (!strcmp(s, name))) return sd->resize_obj;
2682         if ((recurse != 0) && 
2683             ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
2684           return child;
2685      }
2686    EINA_LIST_FOREACH(sd->subobjs, l, child)
2687      {
2688         s = evas_object_name_get(child);
2689         if ((s) && (!strcmp(s, name))) return child;
2690         if ((recurse != 0) && 
2691             ((child = _widget_name_find(child, name, recurse - 1))))
2692           return child;
2693      }
2694    if (sd->hover_obj)
2695      {
2696         s = evas_object_name_get(sd->hover_obj);
2697         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
2698         if ((recurse != 0) && 
2699             ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
2700           return child;
2701      }
2702    return NULL;
2703 }
2704
2705 EAPI Evas_Object *
2706 elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2707 {
2708    API_ENTRY return NULL;
2709    if (!name) return NULL;
2710    return _widget_name_find(obj, name, recurse);
2711 }
2712
2713 /**
2714  * @internal
2715  *
2716  * Split string in words
2717  *
2718  * @param str Source string
2719  * @return List of const words
2720  *
2721  * @see elm_widget_stringlist_free()
2722  * @ingroup Widget
2723  */
2724 EAPI Eina_List *
2725 elm_widget_stringlist_get(const char *str)
2726 {
2727    Eina_List *list = NULL;
2728    const char *s, *b;
2729    if (!str) return NULL;
2730    for (b = s = str; 1; s++)
2731      {
2732         if ((*s == ' ') || (!*s))
2733           {
2734              char *t = malloc(s - b + 1);
2735              if (t)
2736                {
2737                   strncpy(t, b, s - b);
2738                   t[s - b] = 0;
2739                   list = eina_list_append(list, eina_stringshare_add(t));
2740                   free(t);
2741                }
2742              b = s + 1;
2743           }
2744         if (!*s) break;
2745      }
2746    return list;
2747 }
2748
2749 EAPI void
2750 elm_widget_stringlist_free(Eina_List *list)
2751 {
2752    const char *s;
2753    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2754 }
2755
2756 EAPI void
2757 elm_widget_focus_hide_handle(Evas_Object *obj)
2758 {
2759    if (!_elm_widget_is(obj))
2760      return;
2761    _if_focused_revert(obj, EINA_TRUE);
2762 }
2763
2764 EAPI void
2765 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2766 {
2767    Evas_Object *o = obj;
2768    do
2769      {
2770         if (_elm_widget_is(o)) break;
2771         o = evas_object_smart_parent_get(o);
2772      }
2773    while (o);
2774    if (!o) return;
2775    if (!_is_focusable(o)) return;
2776    elm_widget_focus_steal(o);
2777 }
2778
2779 EAPI void
2780 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2781 {
2782    API_ENTRY return;
2783
2784    //FIXME: Need to check whether the object is unfocusable or not.
2785
2786    if (!elm_widget_parent_get(obj))
2787      elm_widget_focused_object_clear(obj);
2788    else
2789      _if_focused_revert(obj, EINA_TRUE);
2790 }
2791
2792 EAPI void
2793 elm_widget_focus_disabled_handle(Evas_Object *obj)
2794 {
2795    API_ENTRY return;
2796
2797    elm_widget_focus_tree_unfocusable_handle(obj);
2798 }
2799
2800 EAPI unsigned int
2801 elm_widget_focus_order_get(const Evas_Object *obj)
2802 {
2803    API_ENTRY return 0;
2804    return sd->focus_order;
2805 }
2806
2807 /**
2808  * @internal
2809  *
2810  * Allocate a new Elm_Widget_Item-derived structure.
2811  *
2812  * The goal of this structure is to provide common ground for actions
2813  * that a widget item have, such as the owner widget, callback to
2814  * notify deletion, data pointer and maybe more.
2815  *
2816  * @param widget the owner widget that holds this item, must be an elm_widget!
2817  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2818  *        be used to allocate memory.
2819  *
2820  * @return allocated memory that is already zeroed out, or NULL on errors.
2821  *
2822  * @see elm_widget_item_new() convenience macro.
2823  * @see elm_widget_item_del() to release memory.
2824  * @ingroup Widget
2825  */
2826 EAPI Elm_Widget_Item *
2827 _elm_widget_item_new(Evas_Object *widget,
2828                      size_t       alloc_size)
2829 {
2830    if (!_elm_widget_is(widget))
2831      return NULL;
2832
2833    Elm_Widget_Item *item;
2834
2835    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2836    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2837
2838    item = calloc(1, alloc_size);
2839    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2840
2841    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2842    item->widget = widget;
2843    return item;
2844 }
2845
2846 EAPI void
2847 _elm_widget_item_free(Elm_Widget_Item *item)
2848 {
2849    ELM_WIDGET_ITEM_FREE_OR_RETURN(item);
2850    Elm_Object_Item_Smart_Cb cb;
2851
2852    if (item->walking > 0)
2853      {
2854         item->delete_me = EINA_TRUE;
2855         return;
2856      }
2857
2858    EINA_LIST_FREE(item->callbacks, cb) free(cb);
2859
2860    if (item->del_func)
2861      item->del_func((void *)item->data, item->widget, item);
2862
2863    if (item->view)
2864      evas_object_del(item->view);
2865
2866    if (item->access)
2867      {
2868         _elm_access_clear(item->access);
2869         free(item->access);
2870      }
2871
2872    if (item->access_info)
2873      eina_stringshare_del(item->access_info);
2874
2875    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2876    free(item);
2877 }
2878
2879 /**
2880  * @internal
2881  *
2882  * Releases widget item memory, calling back del_cb() if it exists.
2883  *
2884  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2885  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2886  * this function and then unset it, thus being useful for 2 step
2887  * cleanup whenever the del_cb may use any of the data that must be
2888  * deleted from item.
2889  *
2890  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2891  * is presented!
2892  *
2893  * @param item a valid #Elm_Widget_Item to be deleted.
2894  * @see elm_widget_item_del() convenience macro.
2895  * @ingroup Widget
2896  */
2897 EAPI void
2898 _elm_widget_item_del(Elm_Widget_Item *item)
2899 {
2900    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2901
2902    //Widget item delete callback
2903    if (item->del_pre_func)
2904      {
2905         if (item->del_pre_func((Elm_Object_Item *)item))
2906           _elm_widget_item_free(item);
2907      }
2908    else
2909      _elm_widget_item_free(item);
2910 }
2911
2912 /**
2913  * @internal
2914  *
2915  * Set the function to notify to widgets when item is being deleted by user.
2916  *
2917  * @param item a valid #Elm_Widget_Item to be notified
2918  * @see elm_widget_item_del_pre_hook_set() convenience macro.
2919  * @ingroup Widget
2920  */
2921 EAPI void
2922 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func)
2923 {
2924    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2925    item->del_pre_func = func;
2926 }
2927
2928 /**
2929  * @internal
2930  *
2931  * Notify object will be deleted without actually deleting it.
2932  *
2933  * This function will callback Elm_Widget_Item::del_cb if it is set
2934  * and then unset it so it is not called twice (ie: from
2935  * elm_widget_item_del()).
2936  *
2937  * @param item a valid #Elm_Widget_Item to be notified
2938  * @see elm_widget_item_pre_notify_del() convenience macro.
2939  * @ingroup Widget
2940  */
2941 EAPI void
2942 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2943 {
2944    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2945    if (!item->del_func) return;
2946    item->del_func((void *)item->data, item->widget, item);
2947    item->del_func = NULL;
2948 }
2949
2950 /**
2951  * @internal
2952  *
2953  * Set the function to notify when item is being deleted.
2954  *
2955  * This function will complain if there was a callback set already,
2956  * however it will set the new one.
2957  *
2958  * The callback will be called from elm_widget_item_pre_notify_del()
2959  * or elm_widget_item_del() will be called with:
2960  *   - data: the Elm_Widget_Item::data value.
2961  *   - obj: the Elm_Widget_Item::widget evas object.
2962  *   - event_info: the item being deleted.
2963  *
2964  * @param item a valid #Elm_Widget_Item to be notified
2965  * @see elm_widget_item_del_cb_set() convenience macro.
2966  * @ingroup Widget
2967  */
2968 EAPI void
2969 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2970                             Evas_Smart_Cb    func)
2971 {
2972    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2973
2974    if ((item->del_func) && (item->del_func != func))
2975      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2976          item->del_func, item, func);
2977
2978    item->del_func = func;
2979 }
2980
2981 /**
2982  * @internal
2983  *
2984  * Set user-data in this item.
2985  *
2986  * User data may be used to identify this item or just store any
2987  * application data. It is automatically given as the first parameter
2988  * of the deletion notify callback.
2989  *
2990  * @param item a valid #Elm_Widget_Item to store data in.
2991  * @param data user data to store.
2992  * @see elm_widget_item_del_cb_set() convenience macro.
2993  * @ingroup Widget
2994  */
2995 EAPI void
2996 _elm_widget_item_data_set(Elm_Widget_Item *item,
2997                           const void      *data)
2998 {
2999    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3000    if ((item->data) && (item->data != data))
3001      DBG("Replacing item %p data %p with %p", item, item->data, data);
3002    item->data = data;
3003 }
3004
3005 /**
3006  * @internal
3007  *
3008  * Retrieves user-data of this item.
3009  *
3010  * @param item a valid #Elm_Widget_Item to get data from.
3011  * @see elm_widget_item_data_set()
3012  * @ingroup Widget
3013  */
3014 EAPI void *
3015 _elm_widget_item_data_get(const Elm_Widget_Item *item)
3016 {
3017    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3018    return (void *)item->data;
3019 }
3020
3021 EAPI void
3022 _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
3023 {
3024    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3025
3026    if (item->disabled == disabled) return;
3027    item->disabled = !!disabled;
3028    if (item->disable_func) item->disable_func(item);
3029 }
3030
3031 EAPI Eina_Bool
3032 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
3033 {
3034    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3035    return item->disabled;
3036 }
3037
3038 EAPI void
3039 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
3040                                   Elm_Widget_Disable_Cb func)
3041 {
3042    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3043    item->disable_func = func;
3044 }
3045
3046 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
3047
3048 struct _Elm_Widget_Item_Tooltip
3049 {
3050    Elm_Widget_Item            *item;
3051    Elm_Tooltip_Item_Content_Cb func;
3052    Evas_Smart_Cb               del_cb;
3053    const void                 *data;
3054 };
3055
3056 static Evas_Object *
3057 _elm_widget_item_tooltip_label_create(void        *data,
3058                                       Evas_Object *obj __UNUSED__,
3059                                       Evas_Object *tooltip,
3060                                       void        *item __UNUSED__)
3061 {
3062    Evas_Object *label = elm_label_add(tooltip);
3063    if (!label)
3064      return NULL;
3065    elm_object_style_set(label, "tooltip");
3066    elm_object_text_set(label, data);
3067    return label;
3068 }
3069
3070 static Evas_Object *
3071 _elm_widget_item_tooltip_trans_label_create(void        *data,
3072                                             Evas_Object *obj __UNUSED__,
3073                                             Evas_Object *tooltip,
3074                                             void        *item __UNUSED__)
3075 {
3076    Evas_Object *label = elm_label_add(tooltip);
3077    if (!label)
3078      return NULL;
3079    elm_object_style_set(label, "tooltip");
3080    elm_object_translatable_text_set(label, data);
3081    return label;
3082 }
3083
3084 static void
3085 _elm_widget_item_tooltip_label_del_cb(void        *data,
3086                                       Evas_Object *obj __UNUSED__,
3087                                       void        *event_info __UNUSED__)
3088 {
3089    eina_stringshare_del(data);
3090 }
3091
3092 /**
3093  * @internal
3094  *
3095  * Set the text to be shown in the widget item.
3096  *
3097  * @param item Target item
3098  * @param text The text to set in the content
3099  *
3100  * Setup the text as tooltip to object. The item can have only one tooltip,
3101  * so any previous tooltip data is removed.
3102  *
3103  * @ingroup Widget
3104  */
3105 EAPI void
3106 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
3107                                   const char      *text)
3108 {
3109    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3110    EINA_SAFETY_ON_NULL_RETURN(text);
3111
3112    text = eina_stringshare_add(text);
3113    _elm_widget_item_tooltip_content_cb_set
3114      (item, _elm_widget_item_tooltip_label_create, text,
3115      _elm_widget_item_tooltip_label_del_cb);
3116 }
3117
3118 EAPI void
3119 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
3120                                                const char      *text)
3121 {
3122    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3123    EINA_SAFETY_ON_NULL_RETURN(text);
3124
3125    text = eina_stringshare_add(text);
3126    _elm_widget_item_tooltip_content_cb_set
3127      (item, _elm_widget_item_tooltip_trans_label_create, text,
3128      _elm_widget_item_tooltip_label_del_cb);
3129 }
3130
3131 static Evas_Object *
3132 _elm_widget_item_tooltip_create(void        *data,
3133                                 Evas_Object *obj,
3134                                 Evas_Object *tooltip)
3135 {
3136    Elm_Widget_Item_Tooltip *wit = data;
3137    return wit->func((void *)wit->data, obj, tooltip, wit->item);
3138 }
3139
3140 static void
3141 _elm_widget_item_tooltip_del_cb(void        *data,
3142                                 Evas_Object *obj,
3143                                 void        *event_info __UNUSED__)
3144 {
3145    Elm_Widget_Item_Tooltip *wit = data;
3146    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3147    free(wit);
3148 }
3149
3150 /**
3151  * @internal
3152  *
3153  * Set the content to be shown in the tooltip item
3154  *
3155  * Setup the tooltip to item. The item can have only one tooltip,
3156  * so any previous tooltip data is removed. @p func(with @p data) will
3157  * be called every time that need show the tooltip and it should
3158  * return a valid Evas_Object. This object is then managed fully by
3159  * tooltip system and is deleted when the tooltip is gone.
3160  *
3161  * @param item the widget item being attached a tooltip.
3162  * @param func the function used to create the tooltip contents.
3163  * @param data what to provide to @a func as callback data/context.
3164  * @param del_cb called when data is not needed anymore, either when
3165  *        another callback replaces @func, the tooltip is unset with
3166  *        elm_widget_item_tooltip_unset() or the owner @a item
3167  *        dies. This callback receives as the first parameter the
3168  *        given @a data, and @c event_info is the item.
3169  *
3170  * @ingroup Widget
3171  */
3172 EAPI void
3173 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
3174                                         Elm_Tooltip_Item_Content_Cb func,
3175                                         const void                 *data,
3176                                         Evas_Smart_Cb               del_cb)
3177 {
3178    Elm_Widget_Item_Tooltip *wit;
3179
3180    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3181
3182    if (!func)
3183      {
3184         _elm_widget_item_tooltip_unset(item);
3185         return;
3186      }
3187
3188    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3189    if (!wit) goto error;
3190    wit->item = item;
3191    wit->func = func;
3192    wit->data = data;
3193    wit->del_cb = del_cb;
3194
3195    elm_object_sub_tooltip_content_cb_set
3196      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3197      _elm_widget_item_tooltip_del_cb);
3198
3199    return;
3200
3201 error_noitem:
3202    if (del_cb) del_cb((void *)data, NULL, item);
3203    return;
3204 error:
3205    if (del_cb) del_cb((void *)data, item->widget, item);
3206 }
3207
3208 /**
3209  * @internal
3210  *
3211  * Unset tooltip from item
3212  *
3213  * @param item widget item to remove previously set tooltip.
3214  *
3215  * Remove tooltip from item. The callback provided as del_cb to
3216  * elm_widget_item_tooltip_content_cb_set() will be called to notify
3217  * it is not used anymore.
3218  *
3219  * @see elm_widget_item_tooltip_content_cb_set()
3220  *
3221  * @ingroup Widget
3222  */
3223 EAPI void
3224 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3225 {
3226    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3227    elm_object_tooltip_unset(item->view);
3228 }
3229
3230 /**
3231  * @internal
3232  *
3233  * Sets a different style for this item tooltip.
3234  *
3235  * @note before you set a style you should define a tooltip with
3236  *       elm_widget_item_tooltip_content_cb_set() or
3237  *       elm_widget_item_tooltip_text_set()
3238  *
3239  * @param item widget item with tooltip already set.
3240  * @param style the theme style to use (default, transparent, ...)
3241  *
3242  * @ingroup Widget
3243  */
3244 EAPI void
3245 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3246                                    const char      *style)
3247 {
3248    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3249    elm_object_tooltip_style_set(item->view, style);
3250 }
3251
3252 EAPI Eina_Bool
3253 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item, Eina_Bool disable)
3254 {
3255    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3256    return elm_object_tooltip_window_mode_set(item->view, disable);
3257 }
3258
3259 EAPI Eina_Bool
3260 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
3261 {
3262    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3263    return elm_object_tooltip_window_mode_get(item->view);
3264 }
3265
3266 /**
3267  * @internal
3268  *
3269  * Get the style for this item tooltip.
3270  *
3271  * @param item widget item with tooltip already set.
3272  * @return style the theme style in use, defaults to "default". If the
3273  *         object does not have a tooltip set, then NULL is returned.
3274  *
3275  * @ingroup Widget
3276  */
3277 EAPI const char *
3278 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3279 {
3280    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3281    return elm_object_tooltip_style_get(item->view);
3282 }
3283
3284 EAPI void
3285 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
3286                             const char      *cursor)
3287 {
3288    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3289    elm_object_sub_cursor_set(item->view, item->widget, cursor);
3290 }
3291
3292 EAPI const char *
3293 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3294 {
3295    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3296    return elm_object_cursor_get(item->view);
3297 }
3298
3299 EAPI void
3300 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3301 {
3302    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3303    elm_object_cursor_unset(item->view);
3304 }
3305
3306 /**
3307  * @internal
3308  *
3309  * Sets a different style for this item cursor.
3310  *
3311  * @note before you set a style you should define a cursor with
3312  *       elm_widget_item_cursor_set()
3313  *
3314  * @param item widget item with cursor already set.
3315  * @param style the theme style to use (default, transparent, ...)
3316  *
3317  * @ingroup Widget
3318  */
3319 EAPI void
3320 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3321                                   const char      *style)
3322 {
3323    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3324    elm_object_cursor_style_set(item->view, style);
3325 }
3326
3327 /**
3328  * @internal
3329  *
3330  * Get the style for this item cursor.
3331  *
3332  * @param item widget item with cursor already set.
3333  * @return style the theme style in use, defaults to "default". If the
3334  *         object does not have a cursor set, then NULL is returned.
3335  *
3336  * @ingroup Widget
3337  */
3338 EAPI const char *
3339 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3340 {
3341    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3342    return elm_object_cursor_style_get(item->view);
3343 }
3344
3345 /**
3346  * @internal
3347  *
3348  * Set if the cursor set should be searched on the theme or should use
3349  * the provided by the engine, only.
3350  *
3351  * @note before you set if should look on theme you should define a cursor
3352  * with elm_object_cursor_set(). By default it will only look for cursors
3353  * provided by the engine.
3354  *
3355  * @param item widget item with cursor already set.
3356  * @param engine_only boolean to define it cursors should be looked only
3357  * between the provided by the engine or searched on widget's theme as well.
3358  *
3359  * @ingroup Widget
3360  */
3361 EAPI void
3362 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3363                                         Eina_Bool        engine_only)
3364 {
3365    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3366    elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
3367 }
3368
3369 /**
3370  * @internal
3371  *
3372  * Get the cursor engine only usage for this item cursor.
3373  *
3374  * @param item widget item with cursor already set.
3375  * @return engine_only boolean to define it cursors should be looked only
3376  * between the provided by the engine or searched on widget's theme as well. If
3377  *         the object does not have a cursor set, then EINA_FALSE is returned.
3378  *
3379  * @ingroup Widget
3380  */
3381 EAPI Eina_Bool
3382 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3383 {
3384    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3385    return elm_object_cursor_theme_search_enabled_get(item->view);
3386 }
3387
3388 // smart object funcs
3389 static void
3390 _smart_reconfigure(Smart_Data *sd)
3391 {
3392    if (sd->resize_obj)
3393      {
3394         evas_object_move(sd->resize_obj, sd->x, sd->y);
3395         evas_object_resize(sd->resize_obj, sd->w, sd->h);
3396      }
3397    if (sd->hover_obj)
3398      {
3399         evas_object_move(sd->hover_obj, sd->x, sd->y);
3400         evas_object_resize(sd->hover_obj, sd->w, sd->h);
3401      }
3402 }
3403
3404 EAPI void
3405 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
3406                                  const char *part,
3407                                  Evas_Object *content)
3408 {
3409    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3410    if (!item->content_set_func) return;
3411    item->content_set_func((Elm_Object_Item *)item, part, content);
3412 }
3413
3414 EAPI Evas_Object *
3415 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
3416                                   const char *part)
3417 {
3418    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3419    if (!item->content_get_func) return NULL;
3420    return item->content_get_func((Elm_Object_Item *)item, part);
3421 }
3422
3423 EAPI Evas_Object *
3424 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3425                                     const char *part)
3426 {
3427    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3428    if (!item->content_unset_func) return NULL;
3429    return item->content_unset_func((Elm_Object_Item *)item, part);
3430 }
3431
3432 EAPI void
3433 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3434                               const char *part,
3435                               const char *label)
3436 {
3437    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3438    if (!item->text_set_func) return;
3439    item->text_set_func((Elm_Object_Item *)item, part, label);
3440 }
3441
3442 EAPI void
3443 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3444                              const char *emission,
3445                              const char *source)
3446 {
3447    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3448    if (item->signal_emit_func)
3449      item->signal_emit_func((Elm_Object_Item *)item, emission, source);
3450 }
3451
3452 EAPI const char *
3453 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3454                                const char *part)
3455 {
3456    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3457    if (!item->text_get_func) return NULL;
3458    return item->text_get_func((Elm_Object_Item *)item, part);
3459 }
3460
3461 EAPI void
3462 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3463                                       Elm_Widget_Content_Set_Cb func)
3464 {
3465    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3466    item->content_set_func = func;
3467 }
3468
3469 EAPI void
3470 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3471                                       Elm_Widget_Content_Get_Cb func)
3472 {
3473    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3474    item->content_get_func = func;
3475 }
3476
3477 EAPI void
3478 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3479                                         Elm_Widget_Content_Unset_Cb func)
3480 {
3481    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3482    item->content_unset_func = func;
3483 }
3484
3485 EAPI void
3486 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3487                                    Elm_Widget_Text_Set_Cb func)
3488 {
3489    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3490    item->text_set_func = func;
3491 }
3492
3493 EAPI void
3494 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3495                                    Elm_Widget_Text_Get_Cb func)
3496 {
3497    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3498    item->text_get_func = func;
3499 }
3500
3501 EAPI void
3502 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3503                                       Elm_Widget_Signal_Emit_Cb func)
3504 {
3505    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3506    item->signal_emit_func = func;
3507 }
3508
3509 EAPI void
3510 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3511 {
3512    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3513    if (item->access_info) eina_stringshare_del(item->access_info);
3514    if (!txt) item->access_info = NULL;
3515    else item->access_info = eina_stringshare_add(txt);
3516 }
3517
3518 EAPI void
3519 elm_widget_item_smart_callback_add(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func, const void *data)
3520 {
3521    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3522    if ((!event) || (!func)) return;
3523
3524    Elm_Widget_Item_Callback *cb = ELM_NEW(Elm_Widget_Item_Callback);
3525    if (!cb) return;
3526
3527    //TODO: apply MEMPOOL?
3528    cb->event = eina_stringshare_add(event);
3529    cb->func = func;
3530    cb->data = (void *)data;
3531    item->callbacks = eina_list_append(item->callbacks, cb);
3532 }
3533
3534 EAPI void*
3535 elm_widget_item_smart_callback_del(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func)
3536 {
3537    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3538
3539    Eina_List *l, *l_next;
3540    Elm_Widget_Item_Callback *cb;
3541
3542    if ((!event) || (!func)) return NULL;
3543
3544    EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb)
3545      {
3546         if ((!strcmp(cb->event, event)) && (cb->func == func))
3547           {
3548              void *data = cb->data;
3549              if (!cb->walking)
3550                {
3551                   item->callbacks = eina_list_remove_list(item->callbacks, l);
3552                   free(cb);
3553                }
3554              else
3555                cb->delete_me = EINA_TRUE;
3556              return data;
3557           }
3558      }
3559    return NULL;
3560 }
3561
3562 EAPI void
3563 _elm_widget_item_smart_callback_call(Elm_Widget_Item *item, const char *event, void *event_info)
3564 {
3565    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3566
3567    Eina_List *l, *l_next;
3568    Elm_Widget_Item_Callback *cb;
3569    const char *strshare;
3570
3571    if (!event) return;
3572
3573    strshare = eina_stringshare_add(event);
3574
3575    EINA_LIST_FOREACH(item->callbacks, l, cb)
3576      {
3577         if (strcmp(cb->event, strshare)) continue;
3578         if (cb->delete_me) continue;
3579         cb->walking++;
3580         item->walking++;
3581         cb->func(cb->data, (Elm_Object_Item *)item, event_info);
3582         item->walking--;
3583         cb->walking--;
3584         if (item->delete_me) break;
3585      }
3586
3587    //Clear callbacks
3588    EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb)
3589      {
3590         if (!cb->delete_me) continue;
3591         item->callbacks = eina_list_remove_list(item->callbacks, l);
3592         free(cb);
3593      }
3594
3595    if (item->delete_me && !item->walking)
3596      elm_widget_item_free(item);
3597 }
3598
3599 static void
3600 _smart_add(Evas_Object *obj)
3601 {
3602    Smart_Data *sd;
3603
3604    sd = calloc(1, sizeof(Smart_Data));
3605    if (!sd) return;
3606    sd->obj = obj;
3607    sd->x = sd->y = sd->w = sd->h = 0;
3608    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3609    evas_object_smart_data_set(obj, sd);
3610    elm_widget_can_focus_set(obj, EINA_TRUE);
3611 }
3612
3613 static Evas_Object *
3614 _newest_focus_order_get(Evas_Object  *obj,
3615                         unsigned int *newest_focus_order,
3616                         Eina_Bool     can_focus_only)
3617 {
3618    const Eina_List *l;
3619    Evas_Object *child, *ret, *best;
3620
3621    API_ENTRY return NULL;
3622
3623    if (!evas_object_visible_get(obj)
3624        || (elm_widget_disabled_get(obj))
3625        || (elm_widget_tree_unfocusable_get(obj)))
3626      return NULL;
3627
3628    best = NULL;
3629    if (*newest_focus_order < sd->focus_order)
3630      {
3631         *newest_focus_order = sd->focus_order;
3632         best = obj;
3633      }
3634    EINA_LIST_FOREACH(sd->subobjs, l, child)
3635      {
3636         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3637         if (!ret) continue;
3638         best = ret;
3639      }
3640    if (can_focus_only)
3641      {
3642         if ((!best) || (!elm_widget_can_focus_get(best)))
3643           return NULL;
3644      }
3645    return best;
3646 }
3647
3648 static void
3649 _if_focused_revert(Evas_Object *obj,
3650                    Eina_Bool    can_focus_only)
3651 {
3652    Evas_Object *top;
3653    Evas_Object *newest = NULL;
3654    unsigned int newest_focus_order = 0;
3655
3656    INTERNAL_ENTRY;
3657
3658    if (!sd->focused) return;
3659    if (!sd->parent_obj) return;
3660
3661    top = elm_widget_top_get(sd->parent_obj);
3662    if (top)
3663      {
3664         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3665         if (newest)
3666           {
3667              elm_object_focus_set(newest, EINA_FALSE);
3668              elm_object_focus_set(newest, EINA_TRUE);
3669           }
3670      }
3671 }
3672
3673 static void
3674 _smart_del(Evas_Object *obj)
3675 {
3676    Evas_Object *sobj;
3677    Edje_Signal_Data *esd;
3678    Elm_Translate_String_Data *ts;
3679
3680    INTERNAL_ENTRY;
3681
3682    if (sd->del_pre_func) sd->del_pre_func(obj);
3683    if (sd->resize_obj)
3684      {
3685         sobj = sd->resize_obj;
3686         sd->resize_obj = NULL;
3687         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3688         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3689         evas_object_del(sobj);
3690         sd->resize_obj = NULL;
3691      }
3692    if (sd->hover_obj)
3693      {
3694         sobj = sd->hover_obj;
3695         sd->hover_obj = NULL;
3696         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3697         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3698         evas_object_del(sobj);
3699         sd->hover_obj = NULL;
3700      }
3701    EINA_LIST_FREE(sd->subobjs, sobj)
3702      {
3703         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3704         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3705         evas_object_del(sobj);
3706      }
3707    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
3708    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
3709    EINA_LIST_FREE(sd->edje_signals, esd)
3710      {
3711         eina_stringshare_del(esd->emission);
3712         eina_stringshare_del(esd->source);
3713         free(esd);
3714      }
3715    EINA_LIST_FREE(sd->translate_strings, ts)
3716      {
3717         eina_stringshare_del(ts->id);
3718         eina_stringshare_del(ts->domain);
3719         eina_stringshare_del(ts->string);
3720         free(ts);
3721      }
3722    sd->event_cb = eina_list_free(sd->event_cb); /* should be empty anyway */
3723    if (sd->del_func) sd->del_func(obj);
3724    if (sd->style) eina_stringshare_del(sd->style);
3725    if (sd->type) eina_stringshare_del(sd->type);
3726    if (sd->theme) elm_theme_free(sd->theme);
3727    sd->data = NULL;
3728    _if_focused_revert(obj, EINA_TRUE);
3729    if (sd->access_info) eina_stringshare_del(sd->access_info);
3730    free(sd);
3731    evas_object_smart_data_set(obj, NULL);
3732 }
3733
3734 static void
3735 _smart_move(Evas_Object *obj,
3736             Evas_Coord   x,
3737             Evas_Coord   y)
3738 {
3739    INTERNAL_ENTRY;
3740    sd->x = x;
3741    sd->y = y;
3742    _smart_reconfigure(sd);
3743 }
3744
3745 static void
3746 _smart_resize(Evas_Object *obj,
3747               Evas_Coord   w,
3748               Evas_Coord   h)
3749 {
3750    INTERNAL_ENTRY;
3751    sd->w = w;
3752    sd->h = h;
3753    _smart_reconfigure(sd);
3754 }
3755
3756 static void
3757 _smart_show(Evas_Object *obj)
3758 {
3759    Eina_List *list;
3760    Evas_Object *o;
3761    INTERNAL_ENTRY;
3762    if ((list = evas_object_smart_members_get(obj)))
3763      {
3764         EINA_LIST_FREE(list, o)
3765           {
3766              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3767              evas_object_show(o);
3768           }
3769      }
3770 }
3771
3772 static void
3773 _smart_hide(Evas_Object *obj)
3774 {
3775    Eina_List *list;
3776    Evas_Object *o;
3777    INTERNAL_ENTRY;
3778
3779    list = evas_object_smart_members_get(obj);
3780    EINA_LIST_FREE(list, o)
3781      {
3782         if (evas_object_data_get(o, "_elm_leaveme")) continue;
3783         evas_object_hide(o);
3784      }
3785 }
3786
3787 static void
3788 _smart_color_set(Evas_Object *obj,
3789                  int          r,
3790                  int          g,
3791                  int          b,
3792                  int          a)
3793 {
3794    Eina_List *list;
3795    Evas_Object *o;
3796    INTERNAL_ENTRY;
3797    if ((list = evas_object_smart_members_get(obj)))
3798      {
3799         EINA_LIST_FREE(list, o)
3800           {
3801              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3802              evas_object_color_set(o, r, g, b, a);
3803           }
3804      }
3805 }
3806
3807 static void
3808 _smart_clip_set(Evas_Object *obj,
3809                 Evas_Object *clip)
3810 {
3811    Eina_List *list;
3812    Evas_Object *o;
3813    INTERNAL_ENTRY;
3814    if ((list = evas_object_smart_members_get(obj)))
3815      {
3816         EINA_LIST_FREE(list, o)
3817           {
3818              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3819              evas_object_clip_set(o, clip);
3820           }
3821      }
3822 }
3823
3824 static void
3825 _smart_clip_unset(Evas_Object *obj)
3826 {
3827    Eina_List *list;
3828    Evas_Object *o;
3829    INTERNAL_ENTRY;
3830    if ((list = evas_object_smart_members_get(obj)))
3831      {
3832         EINA_LIST_FREE(list, o)
3833           {
3834              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3835              evas_object_clip_unset(o);
3836           }
3837      }
3838 }
3839
3840 static void
3841 _smart_calculate(Evas_Object *obj)
3842 {
3843    INTERNAL_ENTRY;
3844    if (sd->changed_func) sd->changed_func(obj);
3845 }
3846
3847 /* never need to touch this */
3848 static void
3849 _smart_init(void)
3850 {
3851    if (_e_smart) return;
3852      {
3853         static const Evas_Smart_Class sc =
3854           {
3855              SMART_NAME,
3856              EVAS_SMART_CLASS_VERSION,
3857              _smart_add,
3858              _smart_del,
3859              _smart_move,
3860              _smart_resize,
3861              _smart_show,
3862              _smart_hide,
3863              _smart_color_set,
3864              _smart_clip_set,
3865              _smart_clip_unset,
3866              _smart_calculate,
3867              NULL,
3868              NULL,
3869              NULL,
3870              NULL,
3871              NULL,
3872              NULL
3873           };
3874         _e_smart = evas_smart_class_new(&sc);
3875      }
3876 }
3877
3878 /* happy debug functions */
3879 #ifdef ELM_DEBUG
3880 static void
3881 _sub_obj_tree_dump(const Evas_Object *obj,
3882                    int                lvl)
3883 {
3884    int i;
3885
3886    for (i = 0; i < lvl * 3; i++)
3887      putchar(' ');
3888
3889    if (_elm_widget_is(obj))
3890      {
3891         Eina_List *l;
3892         INTERNAL_ENTRY;
3893         printf("+ %s(%p)\n",
3894                sd->type,
3895                obj);
3896         if (sd->resize_obj)
3897           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3898         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3899           {
3900              if (obj != sd->resize_obj)
3901                _sub_obj_tree_dump(obj, lvl + 1);
3902           }
3903      }
3904    else
3905      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3906 }
3907
3908 static void
3909 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3910                        FILE              *output)
3911 {
3912    if (!_elm_widget_is(obj))
3913      return;
3914    INTERNAL_ENTRY;
3915
3916    Eina_Bool visible = evas_object_visible_get(obj);
3917    Eina_Bool disabled = elm_widget_disabled_get(obj);
3918    Eina_Bool focused = elm_widget_focus_get(obj);
3919    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3920
3921    if (sd->parent_obj)
3922      {
3923         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3924
3925         if (focused)
3926           fprintf(output, ", style=bold");
3927
3928         if (!visible)
3929           fprintf(output, ", color=gray28");
3930
3931         fprintf(output, " ];\n");
3932      }
3933
3934    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3935                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3936            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3937            sd->focus_order);
3938
3939    if (focused)
3940      fprintf(output, ", style=bold");
3941
3942    if (!visible)
3943      fprintf(output, ", fontcolor=gray28");
3944
3945    if ((disabled) || (!visible))
3946      fprintf(output, ", color=gray");
3947
3948    fprintf(output, " ];\n");
3949
3950    Eina_List *l;
3951    Evas_Object *o;
3952    EINA_LIST_FOREACH(sd->subobjs, l, o)
3953      _sub_obj_tree_dot_dump(o, output);
3954 }
3955 #endif
3956
3957 EAPI void
3958 elm_widget_tree_dump(const Evas_Object *top)
3959 {
3960 #ifdef ELM_DEBUG
3961    if (!_elm_widget_is(top))
3962      return;
3963    _sub_obj_tree_dump(top, 0);
3964 #else
3965    return;
3966    (void)top;
3967 #endif
3968 }
3969
3970 EAPI void
3971 elm_widget_tree_dot_dump(const Evas_Object *top,
3972                          FILE              *output)
3973 {
3974 #ifdef ELM_DEBUG
3975    if (!_elm_widget_is(top))
3976      return;
3977    fprintf(output, "graph " " { node [shape=record];\n");
3978    _sub_obj_tree_dot_dump(top, output);
3979    fprintf(output, "}\n");
3980 #else
3981    return;
3982    (void)top;
3983    (void)output;
3984 #endif
3985 }