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