Merge "[Password]: New design based changes, a new style removed password mode contro...
[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 ((!obj) || (!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 typedef struct _Smart_Data        Smart_Data;
14 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
15 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
16
17 struct _Smart_Data
18 {
19    Evas_Object *obj;
20    const char  *type;
21    Evas_Object *parent_obj;
22    Evas_Coord   x, y, w, h;
23    Eina_List   *subobjs;
24    Evas_Object *resize_obj;
25    Evas_Object *hover_obj;
26    Eina_List   *tooltips, *cursors;
27    void       (*del_func)(Evas_Object *obj);
28    void       (*del_pre_func)(Evas_Object *obj);
29    void       (*focus_func)(Evas_Object *obj);
30    void       (*activate_func)(Evas_Object *obj);
31    void       (*disable_func)(Evas_Object *obj);
32    void       (*theme_func)(Evas_Object *obj);
33    Eina_Bool  (*event_func)(Evas_Object       *obj,
34                             Evas_Object       *source,
35                             Evas_Callback_Type type,
36                             void              *event_info);
37    void       (*signal_func)(Evas_Object *obj,
38                              const char  *emission,
39                              const char  *source);
40    void       (*callback_add_func)(Evas_Object   *obj,
41                                    const char    *emission,
42                                    const char    *source,
43                                    Edje_Signal_Cb func,
44                                    void          *data);
45    void       (*callback_del_func)(Evas_Object   *obj,
46                                    const char    *emission,
47                                    const char    *source,
48                                    Edje_Signal_Cb func,
49                                    void          *data);
50    void       (*changed_func)(Evas_Object *obj);
51    Eina_Bool  (*focus_next_func)(const Evas_Object  *obj,
52                                  Elm_Focus_Direction dir,
53                                  Evas_Object       **next);
54    void       (*on_focus_func)(void        *data,
55                                Evas_Object *obj);
56    void        *on_focus_data;
57    void       (*on_change_func)(void        *data,
58                                 Evas_Object *obj);
59    void        *on_change_data;
60    void       (*on_show_region_func)(void        *data,
61                                      Evas_Object *obj);
62    void        *on_show_region_data;
63    void       (*focus_region_func)(Evas_Object *obj,
64                                    Evas_Coord   x,
65                                    Evas_Coord   y,
66                                    Evas_Coord   w,
67                                    Evas_Coord   h);
68    void       (*on_focus_region_func)(const Evas_Object *obj,
69                                       Evas_Coord        *x,
70                                       Evas_Coord        *y,
71                                       Evas_Coord        *w,
72                                       Evas_Coord        *h);
73    void        *data;
74    Evas_Coord   rx, ry, rw, rh;
75    int          scroll_hold;
76    int          scroll_freeze;
77    double       scale;
78    Elm_Theme   *theme;
79    const char  *style;
80    unsigned int focus_order;
81    Eina_Bool    focus_order_on_calc;
82
83    int          child_drag_x_locked;
84    int          child_drag_y_locked;
85
86    Eina_List   *edje_signals;
87
88    Eina_Bool    drag_x_locked : 1;
89    Eina_Bool    drag_y_locked : 1;
90
91    Eina_Bool    can_focus : 1;
92    Eina_Bool    child_can_focus : 1;
93    Eina_Bool    focused : 1;
94    Eina_Bool    highlight_ignore : 1;
95    Eina_Bool    highlight_in_theme : 1;
96    Eina_Bool    disabled : 1;
97    Eina_Bool    is_mirrored : 1;
98    Eina_Bool    mirrored_auto_mode : 1;   /* This is TRUE by default */
99
100    Eina_List   *focus_chain;
101    Eina_List   *event_cb;
102 };
103
104 struct _Edje_Signal_Data
105 {
106    Evas_Object   *obj;
107    Edje_Signal_Cb func;
108    const char    *emission;
109    const char    *source;
110    void          *data;
111 };
112
113 struct _Elm_Event_Cb_Data
114 {
115    Elm_Event_Cb func;
116    const void  *data;
117 };
118
119 /* local subsystem functions */
120 static void _smart_reconfigure(Smart_Data *sd);
121 static void _smart_add(Evas_Object *obj);
122 static void _smart_del(Evas_Object *obj);
123 static void _smart_move(Evas_Object *obj,
124                         Evas_Coord   x,
125                         Evas_Coord   y);
126 static void _smart_resize(Evas_Object *obj,
127                           Evas_Coord   w,
128                           Evas_Coord   h);
129 static void _smart_show(Evas_Object *obj);
130 static void _smart_hide(Evas_Object *obj);
131 static void _smart_color_set(Evas_Object *obj,
132                              int          r,
133                              int          g,
134                              int          b,
135                              int          a);
136 static void _smart_clip_set(Evas_Object *obj,
137                             Evas_Object *clip);
138 static void _smart_clip_unset(Evas_Object *obj);
139 static void _smart_calculate(Evas_Object *obj);
140 static void _smart_init(void);
141
142 static void _if_focused_revert(Evas_Object *obj,
143                                Eina_Bool    can_focus_only);
144 static Evas_Object *_newest_focus_order_get(Evas_Object  *obj,
145                                             unsigned int *newest_focus_order,
146                                             Eina_Bool     can_focus_only);
147
148 /* local subsystem globals */
149 static Evas_Smart *_e_smart = NULL;
150 static Eina_List  *widtypes = NULL;
151
152 static unsigned int focus_order = 0;
153
154 // internal funcs
155 static inline Eina_Bool
156 _elm_widget_is(const Evas_Object *obj)
157 {
158    const char *type = evas_object_type_get(obj);
159    return type == SMART_NAME;
160 }
161
162 static inline Eina_Bool
163 _is_focusable(Evas_Object *obj)
164 {
165    API_ENTRY return EINA_FALSE;
166    return sd->can_focus || (sd->child_can_focus);
167 }
168
169 static void
170 _unfocus_parents(Evas_Object *obj)
171 {
172    for (; obj; obj = elm_widget_parent_get(obj))
173      {
174         INTERNAL_ENTRY
175         if (!sd->focused) return;
176         sd->focused = 0;
177      }
178 }
179
180 static void
181 _focus_parents(Evas_Object *obj)
182 {
183    for (; obj; obj = elm_widget_parent_get(obj))
184      {
185         INTERNAL_ENTRY
186         if (sd->focused) return;
187         sd->focused = 1;
188      }
189 }
190
191 static void
192 _sub_obj_del(void        *data,
193              Evas        *e __UNUSED__,
194              Evas_Object *obj,
195              void        *event_info __UNUSED__)
196 {
197    Smart_Data *sd = data;
198
199    if (_elm_widget_is(obj))
200      {
201         if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
202      }
203    if (obj == sd->resize_obj)
204      sd->resize_obj = NULL;
205    else if (obj == sd->hover_obj)
206      sd->hover_obj = NULL;
207    else
208      sd->subobjs = eina_list_remove(sd->subobjs, obj);
209    evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
210 }
211
212 static void
213 _sub_obj_hide(void        *data __UNUSED__,
214               Evas        *e __UNUSED__,
215               Evas_Object *obj,
216               void        *event_info __UNUSED__)
217 {
218    _if_focused_revert(obj, EINA_TRUE);
219 }
220
221 static void
222 _sub_obj_mouse_down(void        *data __UNUSED__,
223                     Evas        *e __UNUSED__,
224                     Evas_Object *obj,
225                     void        *event_info __UNUSED__)
226 {
227    Evas_Object *o = obj;
228    do
229      {
230         if (_elm_widget_is(o)) break;
231         o = evas_object_smart_parent_get(o);
232      }
233    while (o);
234    if (!o) return;
235    if (!_is_focusable(o)) return;
236    elm_widget_focus_steal(o);
237 }
238
239 static void
240 _propagate_x_drag_lock(Evas_Object *obj,
241                        int          dir)
242 {
243    INTERNAL_ENTRY
244    if (sd->parent_obj)
245      {
246         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
247         if (sd2)
248           {
249              sd2->child_drag_x_locked += dir;
250              _propagate_x_drag_lock(sd->parent_obj, dir);
251           }
252      }
253 }
254
255 static void
256 _propagate_y_drag_lock(Evas_Object *obj,
257                        int          dir)
258 {
259    INTERNAL_ENTRY
260    if (sd->parent_obj)
261      {
262         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
263         if (sd2)
264           {
265              sd2->child_drag_y_locked += dir;
266              _propagate_y_drag_lock(sd->parent_obj, dir);
267           }
268      }
269 }
270
271 static void
272 _propagate_event(void        *data,
273                  Evas        *e __UNUSED__,
274                  Evas_Object *obj,
275                  void        *event_info)
276 {
277    INTERNAL_ENTRY
278    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
279    Evas_Event_Flags *event_flags = NULL;
280
281    switch (type)
282      {
283       case EVAS_CALLBACK_KEY_DOWN:
284           {
285             Evas_Event_Key_Down *ev = event_info;
286             event_flags = &(ev->event_flags);
287           }
288         break;
289
290       case EVAS_CALLBACK_KEY_UP:
291           {
292              Evas_Event_Key_Up *ev = event_info;
293              event_flags = &(ev->event_flags);
294           }
295         break;
296
297       case EVAS_CALLBACK_MOUSE_WHEEL:
298           {
299             Evas_Event_Mouse_Wheel *ev = event_info;
300             event_flags = &(ev->event_flags);
301           }
302         break;
303
304       default:
305         break;
306      }
307
308    elm_widget_event_propagate(obj, type, event_info, event_flags);
309 }
310
311 static void
312 _parent_focus(Evas_Object *obj)
313 {
314    API_ENTRY return;
315    if (sd->focused) return;
316
317    Evas_Object *o = elm_widget_parent_get(obj);
318    sd->focus_order_on_calc = EINA_TRUE;
319
320    if (o) _parent_focus(o);
321
322    if (!sd->focus_order_on_calc)
323      return; /* we don't want to override it if by means of any of the
324                 callbacks below one gets to calculate our order
325                 first. */
326
327    focus_order++;
328    sd->focus_order = focus_order;
329    sd->focused = EINA_TRUE;
330    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
331    if (sd->focus_func) sd->focus_func(obj);
332
333    _elm_widget_focus_region_show(obj);
334
335    sd->focus_order_on_calc = EINA_FALSE;
336 }
337
338 static void
339 _elm_object_focus_chain_del_cb(void        *data,
340                                Evas        *e __UNUSED__,
341                                Evas_Object *obj,
342                                void        *event_info __UNUSED__)
343 {
344    Smart_Data *sd = data;
345
346    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
347 }
348
349 // exposed util funcs to elm
350 void
351 _elm_widget_type_clear(void)
352 {
353    const char **ptr;
354
355    EINA_LIST_FREE(widtypes, ptr)
356      {
357         eina_stringshare_del(*ptr);
358         *ptr = NULL;
359      }
360 }
361
362 void
363 _elm_widget_focus_region_show(const Evas_Object *obj)
364 {
365    Evas_Coord x, y, w, h, ox, oy;
366    Smart_Data *sd2;
367    Evas_Object *o;
368
369    API_ENTRY return;
370
371    o = elm_widget_parent_get(obj);
372    if (!o) return;
373
374    elm_widget_focus_region_get(obj, &x, &y, &w, &h);
375    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
376    while (o)
377      {
378         Evas_Coord px, py;
379         sd2 = evas_object_smart_data_get(o);
380         if (sd2->focus_region_func)
381           {
382              sd2->focus_region_func(o, x, y, w, h);
383              elm_widget_focus_region_get(o, &x, &y, &w, &h);
384           }
385         else
386           {
387              evas_object_geometry_get(o, &px, &py, NULL, NULL);
388              x += ox - px;
389              y += oy - py;
390              ox = px;
391              oy = py;
392           }
393         o = elm_widget_parent_get(o);
394      }
395 }
396
397 /**
398  * @defgroup Widget Widget
399  *
400  * @internal
401  * Exposed api for making widgets
402  */
403 EAPI void
404 elm_widget_type_register(const char **ptr)
405 {
406    widtypes = eina_list_append(widtypes, (void *)ptr);
407 }
408
409 EAPI Eina_Bool
410 elm_widget_api_check(int ver)
411 {
412    if (ver != ELM_INTERNAL_API_VERSION)
413      {
414         CRITICAL("Elementary widget api versions do not match");
415         return EINA_FALSE;
416      }
417    return EINA_TRUE;
418 }
419
420 EAPI Evas_Object *
421 elm_widget_add(Evas *evas)
422 {
423    Evas_Object *obj;
424    _smart_init();
425    obj = evas_object_smart_add(evas, _e_smart);
426    elm_widget_mirrored_set(obj, elm_mirrored_get());
427    return obj;
428 }
429
430 EAPI void
431 elm_widget_del_hook_set(Evas_Object *obj,
432                         void       (*func)(Evas_Object *obj))
433 {
434    API_ENTRY return;
435    sd->del_func = func;
436 }
437
438 EAPI void
439 elm_widget_del_pre_hook_set(Evas_Object *obj,
440                             void       (*func)(Evas_Object *obj))
441 {
442    API_ENTRY return;
443    sd->del_pre_func = func;
444 }
445
446 EAPI void
447 elm_widget_focus_hook_set(Evas_Object *obj,
448                           void       (*func)(Evas_Object *obj))
449 {
450    API_ENTRY return;
451    sd->focus_func = func;
452 }
453
454 EAPI void
455 elm_widget_activate_hook_set(Evas_Object *obj,
456                              void       (*func)(Evas_Object *obj))
457 {
458    API_ENTRY return;
459    sd->activate_func = func;
460 }
461
462 EAPI void
463 elm_widget_disable_hook_set(Evas_Object *obj,
464                             void       (*func)(Evas_Object *obj))
465 {
466    API_ENTRY return;
467    sd->disable_func = func;
468 }
469
470 EAPI void
471 elm_widget_theme_hook_set(Evas_Object *obj,
472                           void       (*func)(Evas_Object *obj))
473 {
474    API_ENTRY return;
475    sd->theme_func = func;
476 }
477
478 EAPI void
479 elm_widget_event_hook_set(Evas_Object *obj,
480                           Eina_Bool  (*func)(Evas_Object       *obj,
481                                              Evas_Object       *source,
482                                              Evas_Callback_Type type,
483                                              void              *event_info))
484 {
485    API_ENTRY return;
486    sd->event_func = func;
487 }
488
489 EAPI void
490 elm_widget_changed_hook_set(Evas_Object *obj,
491                             void       (*func)(Evas_Object *obj))
492 {
493    API_ENTRY return;
494    sd->changed_func = func;
495 }
496
497 EAPI void
498 elm_widget_signal_emit_hook_set(Evas_Object *obj,
499                                 void       (*func)(Evas_Object *obj,
500                                                    const char *emission,
501                                                    const char *source))
502 {
503    API_ENTRY return;
504    sd->signal_func = func;
505 }
506
507 EAPI void
508 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
509                                         void       (*func)(Evas_Object   *obj,
510                                                            const char    *emission,
511                                                            const char    *source,
512                                                            Edje_Signal_Cb func_cb,
513                                                            void          *data))
514 {
515    API_ENTRY return;
516    sd->callback_add_func = func;
517 }
518
519 EAPI void
520 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
521                                         void       (*func)(Evas_Object   *obj,
522                                                            const char    *emission,
523                                                            const char    *source,
524                                                            Edje_Signal_Cb func_cb,
525                                                            void          *data))
526 {
527    API_ENTRY return;
528    sd->callback_del_func = func;
529 }
530
531 EAPI void
532 elm_widget_theme(Evas_Object *obj)
533 {
534    const Eina_List *l;
535    Evas_Object *child;
536    Elm_Tooltip *tt;
537    Elm_Cursor *cur;
538
539    API_ENTRY return;
540    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_theme(child);
541    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
542    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
543    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
544    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
545    if (sd->theme_func) sd->theme_func(obj);
546 }
547
548 EAPI void
549 elm_widget_theme_specific(Evas_Object *obj,
550                           Elm_Theme   *th,
551                           Eina_Bool    force)
552 {
553    const Eina_List *l;
554    Evas_Object *child;
555    Elm_Tooltip *tt;
556    Elm_Cursor *cur;
557    Elm_Theme *th2, *thdef;
558
559    API_ENTRY return;
560    thdef = elm_theme_default_get();
561    if (!th) th = thdef;
562    if (!force)
563      {
564         th2 = sd->theme;
565         if (!th2) th2 = thdef;
566         while (th2)
567           {
568              if (th2 == th)
569                {
570                   force = EINA_TRUE;
571                   break;
572                }
573              if (th2 == thdef) break;
574              th2 = th2->ref_theme;
575              if (!th2) th2 = thdef;
576           }
577      }
578    if (!force) return;
579    EINA_LIST_FOREACH(sd->subobjs, l, child)
580      elm_widget_theme_specific(child, th, force);
581    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
582    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
583    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
584    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
585    if (sd->theme_func) sd->theme_func(obj);
586 }
587
588 /**
589  * @internal
590  *
591  * Set hook to get next object in object focus chain.
592  *
593  * @param obj The widget object.
594  * @param func The hook to be used with this widget.
595  *
596  * @ingroup Widget
597  */
598 EAPI void
599 elm_widget_focus_next_hook_set(Evas_Object *obj,
600                                Eina_Bool  (*func)(const Evas_Object   *obj,
601                                                    Elm_Focus_Direction dir,
602                                                    Evas_Object       **next))
603 {
604    API_ENTRY return;
605    sd->focus_next_func = func;
606 }
607
608 /**
609  * Returns the widget's mirrored mode.
610  *
611  * @param obj The widget.
612  * @return mirrored mode of the object.
613  *
614  **/
615 EAPI Eina_Bool
616 elm_widget_mirrored_get(const Evas_Object *obj)
617 {
618    API_ENTRY return EINA_FALSE;
619    return sd->is_mirrored;
620 }
621
622 /**
623  * Sets the widget's mirrored mode.
624  *
625  * @param obj The widget.
626  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
627  */
628 EAPI void
629 elm_widget_mirrored_set(Evas_Object *obj,
630                         Eina_Bool    mirrored)
631 {
632    API_ENTRY return;
633    if (sd->is_mirrored != mirrored)
634      {
635         sd->is_mirrored = mirrored;
636         elm_widget_theme(obj);
637      }
638 }
639
640 /**
641  * @internal
642  * Resets the mirrored mode from the system mirror mode for widgets that are in
643  * automatic mirroring mode. This function does not call elm_widget_theme.
644  *
645  * @param obj The widget.
646  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
647  */
648 void
649 _elm_widget_mirrored_reload(Evas_Object *obj)
650 {
651    API_ENTRY return;
652    Eina_Bool mirrored = elm_mirrored_get();
653    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
654      {
655         sd->is_mirrored = mirrored;
656      }
657 }
658
659 /**
660  * Returns the widget's mirrored mode setting.
661  *
662  * @param obj The widget.
663  * @return mirrored mode setting of the object.
664  *
665  **/
666 EAPI Eina_Bool
667 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
668 {
669    API_ENTRY return EINA_FALSE;
670    return sd->mirrored_auto_mode;
671 }
672
673 /**
674  * Sets the widget's mirrored mode setting.
675  * When widget in automatic mode, it follows the system mirrored mode set by
676  * elm_mirrored_set().
677  * @param obj The widget.
678  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
679  */
680 EAPI void
681 elm_widget_mirrored_automatic_set(Evas_Object *obj,
682                                   Eina_Bool    automatic)
683 {
684    API_ENTRY return;
685    if (sd->mirrored_auto_mode != automatic)
686      {
687         sd->mirrored_auto_mode = automatic;
688
689         if (automatic)
690           {
691              elm_widget_mirrored_set(obj, elm_mirrored_get());
692           }
693      }
694 }
695
696 EAPI void
697 elm_widget_on_focus_hook_set(Evas_Object *obj,
698                              void       (*func)(void *data,
699                                                 Evas_Object *obj),
700                              void        *data)
701 {
702    API_ENTRY return;
703    sd->on_focus_func = func;
704    sd->on_focus_data = data;
705 }
706
707 EAPI void
708 elm_widget_on_change_hook_set(Evas_Object *obj,
709                               void       (*func)(void *data,
710                                                  Evas_Object *obj),
711                               void        *data)
712 {
713    API_ENTRY return;
714    sd->on_change_func = func;
715    sd->on_change_data = data;
716 }
717
718 EAPI void
719 elm_widget_on_show_region_hook_set(Evas_Object *obj,
720                                    void       (*func)(void *data,
721                                                       Evas_Object *obj),
722                                    void        *data)
723 {
724    API_ENTRY return;
725    sd->on_show_region_func = func;
726    sd->on_show_region_data = data;
727 }
728
729 /**
730  * @internal
731  *
732  * Set the hook to use to show the focused region.
733  *
734  * Whenever a new widget gets focused or it's needed to show the focused
735  * area of the current one, this hook will be called on objects that may
736  * want to move their children into their visible area.
737  * The area given in the hook function is relative to the @p obj widget.
738  *
739  * @param obj The widget object
740  * @param func The function to call to show the specified area.
741  *
742  * @ingroup Widget
743  */
744 EAPI void
745 elm_widget_focus_region_hook_set(Evas_Object *obj,
746                                  void       (*func)(Evas_Object *obj,
747                                                     Evas_Coord x,
748                                                     Evas_Coord y,
749                                                     Evas_Coord w,
750                                                     Evas_Coord h))
751 {
752    API_ENTRY return;
753    sd->focus_region_func = func;
754 }
755
756 /**
757  * @internal
758  *
759  * Set the hook to retrieve the focused region of a widget.
760  *
761  * This hook will be called by elm_widget_focus_region_get() whenever
762  * it's needed to get the focused area of a widget. The area must be relative
763  * to the widget itself and if no hook is set, it will default to the entire
764  * object.
765  *
766  * @param obj The widget object
767  * @param func The function used to retrieve the focus region.
768  *
769  * @ingroup Widget
770  */
771 EAPI void
772 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
773                                     void       (*func)(const Evas_Object *obj,
774                                                        Evas_Coord *x,
775                                                        Evas_Coord *y,
776                                                        Evas_Coord *w,
777                                                        Evas_Coord *h))
778 {
779    API_ENTRY return;
780    sd->on_focus_region_func = func;
781 }
782
783 EAPI void
784 elm_widget_data_set(Evas_Object *obj,
785                     void        *data)
786 {
787    API_ENTRY return;
788    sd->data = data;
789 }
790
791 EAPI void *
792 elm_widget_data_get(const Evas_Object *obj)
793 {
794    API_ENTRY return NULL;
795    return sd->data;
796 }
797
798 EAPI void
799 elm_widget_sub_object_add(Evas_Object *obj,
800                           Evas_Object *sobj)
801 {
802    API_ENTRY return;
803    double scale, pscale = elm_widget_scale_get(sobj);
804    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
805    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
806
807    if (_elm_widget_is(sobj))
808      {
809         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
810         if (sd2)
811           {
812              if (sd2->parent_obj == obj)
813                return;
814              if (sd2->parent_obj)
815                elm_widget_sub_object_del(sd2->parent_obj, sobj);
816              sd2->parent_obj = obj;
817              if (!sd->child_can_focus && (_is_focusable(sobj)))
818                sd->child_can_focus = EINA_TRUE;
819           }
820      }
821    else
822      {
823         void *data = evas_object_data_get(sobj, "elm-parent");
824         if (data)
825           {
826              if (data == obj) return;
827              evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
828                                             _sub_obj_del);
829           }
830      }
831
832    sd->subobjs = eina_list_append(sd->subobjs, sobj);
833    evas_object_data_set(sobj, "elm-parent", obj);
834    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
835    if (_elm_widget_is(sobj))
836      evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
837    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
838    scale = elm_widget_scale_get(sobj);
839    th = elm_widget_theme_get(sobj);
840    mirrored = elm_widget_mirrored_get(sobj);
841    if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
842    if (elm_widget_focus_get(sobj)) _focus_parents(obj);
843 }
844
845 EAPI void
846 elm_widget_sub_object_del(Evas_Object *obj,
847                           Evas_Object *sobj)
848 {
849    Evas_Object *sobj_parent;
850    API_ENTRY return;
851    if (!sobj) return;
852
853    sobj_parent = evas_object_data_del(sobj, "elm-parent");
854    if (sobj_parent != obj)
855      {
856         static int abort_on_warn = -1;
857         ERR("removing sub object %p from parent %p, "
858             "but elm-parent is different %p!",
859             sobj, obj, sobj_parent);
860         if (EINA_UNLIKELY(abort_on_warn == -1))
861           {
862              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
863              else abort_on_warn = 0;
864           }
865         if (abort_on_warn == 1) abort();
866      }
867    if (_elm_widget_is(sobj))
868      {
869         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
870         if (sd2)
871           {
872              sd2->parent_obj = NULL;
873              if (sd2->resize_obj == sobj)
874                sd2->resize_obj = NULL;
875              else
876                sd->subobjs = eina_list_remove(sd->subobjs, sobj);
877           }
878         else
879           sd->subobjs = eina_list_remove(sd->subobjs, sobj);
880         if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
881         if ((sd->child_can_focus) && (_is_focusable(sobj)))
882           {
883              Evas_Object *subobj;
884              const Eina_List *l;
885              sd->child_can_focus = EINA_FALSE;
886              EINA_LIST_FOREACH(sd->subobjs, l, subobj)
887                {
888                   if (_is_focusable(subobj))
889                     {
890                        sd->child_can_focus = EINA_TRUE;
891                        break;
892                     }
893                }
894           }
895      }
896    else
897      sd->subobjs = eina_list_remove(sd->subobjs, sobj);
898    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
899                                        _sub_obj_del, sd);
900    if (_elm_widget_is(sobj))
901      evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
902                                          _sub_obj_hide, sd);
903    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
904 }
905
906 EAPI void
907 elm_widget_resize_object_set(Evas_Object *obj,
908                              Evas_Object *sobj)
909 {
910    API_ENTRY return;
911    // orphan previous resize obj
912    if (sd->resize_obj)
913      {
914         evas_object_clip_unset(sd->resize_obj);
915         evas_object_data_del(sd->resize_obj, "elm-parent");
916         if (_elm_widget_is(sd->resize_obj))
917           {
918              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
919              if (sd2) sd2->parent_obj = NULL;
920              evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_HIDE,
921                                                  _sub_obj_hide, sd);
922           }
923         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
924                                             _sub_obj_del, sd);
925         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_DOWN,
926                                             _sub_obj_mouse_down, sd);
927         evas_object_smart_member_del(sd->resize_obj);
928         if (_elm_widget_is(sd->resize_obj))
929           {
930              if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
931           }
932      }
933    // orphan new resize obj
934    if (sobj)
935      {
936         evas_object_data_del(sobj, "elm-parent");
937         if (_elm_widget_is(sobj))
938           {
939              Smart_Data *sd2 = evas_object_smart_data_get(sobj);
940              if (sd2) sd2->parent_obj = NULL;
941              evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
942                                                  _sub_obj_hide, sd);
943           }
944         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
945                                             _sub_obj_del, sd);
946         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
947                                             _sub_obj_mouse_down, sd);
948         evas_object_smart_member_del(sobj);
949         if (_elm_widget_is(sobj))
950           {
951              if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
952           }
953      }
954    // set the resize obj up
955    sd->resize_obj = sobj;
956    if (sd->resize_obj)
957      {
958         if (_elm_widget_is(sd->resize_obj))
959           {
960              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
961              if (sd2) sd2->parent_obj = obj;
962              evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
963                                             _sub_obj_hide, sd);
964           }
965         evas_object_clip_set(sobj, evas_object_clip_get(obj));
966         evas_object_smart_member_add(sobj, obj);
967         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
968                                        _sub_obj_del, sd);
969         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
970                                        _sub_obj_mouse_down, sd);
971         _smart_reconfigure(sd);
972         evas_object_data_set(sobj, "elm-parent", obj);
973         evas_object_smart_callback_call(obj, "sub-object-add", sobj);
974         if (_elm_widget_is(sobj))
975           {
976              if (elm_widget_focus_get(sobj)) _focus_parents(obj);
977           }
978      }
979 }
980
981 EAPI void
982 elm_widget_hover_object_set(Evas_Object *obj,
983                             Evas_Object *sobj)
984 {
985    API_ENTRY return;
986    if (sd->hover_obj)
987      {
988         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
989                                             _sub_obj_del, sd);
990      }
991    sd->hover_obj = sobj;
992    if (sd->hover_obj)
993      {
994         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
995                                        _sub_obj_del, sd);
996         _smart_reconfigure(sd);
997      }
998 }
999
1000 EAPI void
1001 elm_widget_can_focus_set(Evas_Object *obj,
1002                          Eina_Bool    can_focus)
1003 {
1004    API_ENTRY return;
1005    sd->can_focus = can_focus;
1006    if (can_focus)
1007      {
1008         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1009                                        _propagate_event,
1010                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1011         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1012                                        _propagate_event,
1013                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1014         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1015                                        _propagate_event,
1016                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1017      }
1018    else
1019      {
1020         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1021                                        _propagate_event);
1022         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1023                                        _propagate_event);
1024         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1025                                        _propagate_event);
1026      }
1027 }
1028
1029 EAPI Eina_Bool
1030 elm_widget_can_focus_get(const Evas_Object *obj)
1031 {
1032    API_ENTRY return EINA_FALSE;
1033    return sd->can_focus;
1034 }
1035
1036 EAPI Eina_Bool
1037 elm_widget_child_can_focus_get(const Evas_Object *obj)
1038 {
1039    API_ENTRY return EINA_FALSE;
1040    return sd->child_can_focus;
1041 }
1042
1043 EAPI void
1044 elm_widget_highlight_ignore_set(Evas_Object *obj,
1045                                 Eina_Bool    ignore)
1046 {
1047    API_ENTRY return;
1048    sd->highlight_ignore = !!ignore;
1049 }
1050
1051 EAPI Eina_Bool
1052 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1053 {
1054    API_ENTRY return EINA_FALSE;
1055    return sd->highlight_ignore;
1056 }
1057
1058 EAPI void
1059 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1060                                   Eina_Bool    highlight)
1061 {
1062    API_ENTRY return;
1063    sd->highlight_in_theme = !!highlight;
1064    /* FIXME: if focused, it should switch from one mode to the other */
1065 }
1066
1067 EAPI Eina_Bool
1068 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1069 {
1070    API_ENTRY return EINA_FALSE;
1071    return sd->highlight_in_theme;
1072 }
1073
1074 EAPI Eina_Bool
1075 elm_widget_focus_get(const Evas_Object *obj)
1076 {
1077    API_ENTRY return EINA_FALSE;
1078    return sd->focused;
1079 }
1080
1081 EAPI Evas_Object *
1082 elm_widget_focused_object_get(const Evas_Object *obj)
1083 {
1084    const Evas_Object *subobj;
1085    const Eina_List *l;
1086    API_ENTRY return NULL;
1087
1088    if (!sd->focused) return NULL;
1089    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1090      {
1091         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1092         if (fobj) return fobj;
1093      }
1094    return (Evas_Object *)obj;
1095 }
1096
1097 EAPI Evas_Object *
1098 elm_widget_top_get(const Evas_Object *obj)
1099 {
1100    API_ENTRY return NULL;
1101    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1102    return (Evas_Object *)obj;
1103 }
1104
1105 EAPI Eina_Bool
1106 elm_widget_is(const Evas_Object *obj)
1107 {
1108    return _elm_widget_is(obj);
1109 }
1110
1111 EAPI Evas_Object *
1112 elm_widget_parent_widget_get(const Evas_Object *obj)
1113 {
1114    Evas_Object *parent;
1115
1116    if (_elm_widget_is(obj))
1117      {
1118         Smart_Data *sd = evas_object_smart_data_get(obj);
1119         if (!sd) return NULL;
1120         parent = sd->parent_obj;
1121      }
1122    else
1123      {
1124         parent = evas_object_data_get(obj, "elm-parent");
1125         if (!parent) parent = evas_object_smart_parent_get(obj);
1126      }
1127
1128    while (parent)
1129      {
1130         Evas_Object *elm_parent;
1131         if (_elm_widget_is(parent)) break;
1132         elm_parent = evas_object_data_get(parent, "elm-parent");
1133         if (elm_parent) parent = elm_parent;
1134         else parent = evas_object_smart_parent_get(parent);
1135      }
1136    return parent;
1137 }
1138
1139 EAPI void
1140 elm_widget_event_callback_add(Evas_Object *obj,
1141                               Elm_Event_Cb func,
1142                               const void  *data)
1143 {
1144    API_ENTRY return;
1145    EINA_SAFETY_ON_NULL_RETURN(func);
1146    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1147    ecb->func = func;
1148    ecb->data = data;
1149    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1150 }
1151
1152 EAPI void *
1153 elm_widget_event_callback_del(Evas_Object *obj,
1154                               Elm_Event_Cb func,
1155                               const void  *data)
1156 {
1157    API_ENTRY return NULL;
1158    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1159    Eina_List *l;
1160    Elm_Event_Cb_Data *ecd;
1161    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1162      if ((ecd->func == func) && (ecd->data == data))
1163        {
1164           free(ecd);
1165           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1166           return (void *)data;
1167        }
1168    return NULL;
1169 }
1170
1171 EAPI Eina_Bool
1172 elm_widget_event_propagate(Evas_Object       *obj,
1173                            Evas_Callback_Type type,
1174                            void              *event_info,
1175                            Evas_Event_Flags  *event_flags)
1176 {
1177    API_ENTRY return EINA_FALSE; //TODO reduce.
1178    if (!_elm_widget_is(obj)) return EINA_FALSE;
1179    Evas_Object *parent = obj;
1180    Elm_Event_Cb_Data *ecd;
1181    Eina_List *l, *l_prev;
1182
1183    while (parent &&
1184           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1185      {
1186         sd = evas_object_smart_data_get(parent);
1187         if ((!sd) || (!_elm_widget_is(obj)))
1188           return EINA_FALSE; //Not Elm Widget
1189
1190         if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1191           return EINA_TRUE;
1192
1193         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1194           {
1195              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1196                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1197                return EINA_TRUE;
1198           }
1199         parent = sd->parent_obj;
1200      }
1201
1202    return EINA_FALSE;
1203 }
1204
1205 /**
1206  * @internal
1207  *
1208  * Set custom focus chain.
1209  *
1210  * This function i set one new and overwrite any previous custom focus chain
1211  * with the list of objects. The previous list will be deleted and this list
1212  * will be managed. After setted, don't modity it.
1213  *
1214  * @note On focus cycle, only will be evaluated children of this container.
1215  *
1216  * @param obj The container widget
1217  * @param objs Chain of objects to pass focus
1218  * @ingroup Widget
1219  */
1220 EAPI void
1221 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1222                                   Eina_List   *objs)
1223 {
1224    API_ENTRY return;
1225    if (!sd->focus_next_func)
1226      return;
1227
1228    elm_widget_focus_custom_chain_unset(obj);
1229
1230    Eina_List *l;
1231    Evas_Object *o;
1232
1233    EINA_LIST_FOREACH(objs, l, o)
1234      {
1235         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1236                                        _elm_object_focus_chain_del_cb, sd);
1237      }
1238
1239    sd->focus_chain = objs;
1240 }
1241
1242 /**
1243  * @internal
1244  *
1245  * Get custom focus chain
1246  *
1247  * @param obj The container widget
1248  * @ingroup Widget
1249  */
1250 EAPI const Eina_List *
1251 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1252 {
1253    API_ENTRY return NULL;
1254    return (const Eina_List *)sd->focus_chain;
1255 }
1256
1257 /**
1258  * @internal
1259  *
1260  * Unset custom focus chain
1261  *
1262  * @param obj The container widget
1263  * @ingroup Widget
1264  */
1265 EAPI void
1266 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1267 {
1268    API_ENTRY return;
1269    Eina_List *l, *l_next;
1270    Evas_Object *o;
1271
1272    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1273      {
1274         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1275                                             _elm_object_focus_chain_del_cb, sd);
1276         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1277      }
1278 }
1279
1280 /**
1281  * @internal
1282  *
1283  * Append object to custom focus chain.
1284  *
1285  * @note If relative_child equal to NULL or not in custom chain, the object
1286  * will be added in end.
1287  *
1288  * @note On focus cycle, only will be evaluated children of this container.
1289  *
1290  * @param obj The container widget
1291  * @param child The child to be added in custom chain
1292  * @param relative_child The relative object to position the child
1293  * @ingroup Widget
1294  */
1295 EAPI void
1296 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1297                                      Evas_Object *child,
1298                                      Evas_Object *relative_child)
1299 {
1300    API_ENTRY return;
1301    EINA_SAFETY_ON_NULL_RETURN(child);
1302    if (!sd->focus_next_func)
1303      return;
1304
1305    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1306                                        _elm_object_focus_chain_del_cb, sd);
1307
1308    if (!relative_child)
1309      {
1310         sd->focus_chain = eina_list_append(sd->focus_chain, child);
1311         return;
1312      }
1313
1314    sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child);
1315    return;
1316 }
1317
1318 /**
1319  * @internal
1320  *
1321  * Prepend object to custom focus chain.
1322  *
1323  * @note If relative_child equal to NULL or not in custom chain, the object
1324  * will be added in begin.
1325  *
1326  * @note On focus cycle, only will be evaluated children of this container.
1327  *
1328  * @param obj The container widget
1329  * @param child The child to be added in custom chain
1330  * @param relative_child The relative object to position the child
1331  * @ingroup Widget
1332  */
1333 EAPI void
1334 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1335                                       Evas_Object *child,
1336                                       Evas_Object *relative_child)
1337 {
1338    API_ENTRY return;
1339    EINA_SAFETY_ON_NULL_RETURN(child);
1340    if (!sd->focus_next_func)
1341      return;
1342
1343    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1344                                        _elm_object_focus_chain_del_cb, sd);
1345
1346    if (!relative_child)
1347      {
1348         sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1349         return;
1350      }
1351
1352    sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child);
1353    return;
1354 }
1355
1356 /**
1357  * @internal
1358  *
1359  * Give focus to next object in object tree.
1360  *
1361  * Give focus to next object in focus chain of one object sub-tree.
1362  * If the last object of chain already have focus, the focus will go to the
1363  * first object of chain.
1364  *
1365  * @param obj The widget root of sub-tree
1366  * @param dir Direction to cycle the focus
1367  *
1368  * @ingroup Widget
1369  */
1370 EAPI void
1371 elm_widget_focus_cycle(Evas_Object        *obj,
1372                        Elm_Focus_Direction dir)
1373 {
1374    Evas_Object *target = NULL;
1375    if (!_elm_widget_is(obj))
1376      return;
1377    elm_widget_focus_next_get(obj, dir, &target);
1378    if (target)
1379      elm_widget_focus_steal(target);
1380 }
1381
1382 /**
1383  * @internal
1384  *
1385  * Give focus to near object in one direction.
1386  *
1387  * Give focus to near object in direction of one object.
1388  * If none focusable object in given direction, the focus will not change.
1389  *
1390  * @param obj The reference widget
1391  * @param x Horizontal component of direction to focus
1392  * @param y Vertical component of direction to focus
1393  *
1394  * @ingroup Widget
1395  */
1396 EAPI void
1397 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1398                               int          x __UNUSED__,
1399                               int          y __UNUSED__)
1400 {
1401    return; /* TODO */
1402 }
1403
1404 /**
1405  * @internal
1406  *
1407  * Get next object in focus chain of object tree.
1408  *
1409  * Get next object in focus chain of one object sub-tree.
1410  * Return the next object by reference. If don't have any candidate to receive
1411  * focus before chain end, the first candidate will be returned.
1412  *
1413  * @param obj The widget root of sub-tree
1414  * @param dir Direction os focus chain
1415  * @param next The next object in focus chain
1416  * @return EINA_TRUE if don't need focus chain restart/loop back
1417  *         to use 'next' obj.
1418  *
1419  * @ingroup Widget
1420  */
1421 EAPI Eina_Bool
1422 elm_widget_focus_next_get(const Evas_Object  *obj,
1423                           Elm_Focus_Direction dir,
1424                           Evas_Object       **next)
1425 {
1426    if (!next)
1427      return EINA_FALSE;
1428    *next = NULL;
1429
1430    API_ENTRY return EINA_FALSE;
1431
1432    /* Ignore if disabled */
1433    if ((!evas_object_visible_get(obj)) || (elm_widget_disabled_get(obj)))
1434      return EINA_FALSE;
1435
1436    /* Try use hook */
1437    if (sd->focus_next_func)
1438      return sd->focus_next_func(obj, dir, next);
1439
1440    if (!elm_widget_can_focus_get(obj))
1441      return EINA_FALSE;
1442
1443    /* Return */
1444    *next = (Evas_Object *)obj;
1445    return !elm_widget_focus_get(obj);
1446 }
1447
1448 /**
1449  * @internal
1450  *
1451  * Get next object in focus chain of object tree in list.
1452  *
1453  * Get next object in focus chain of one object sub-tree ordered by one list.
1454  * Return the next object by reference. If don't have any candidate to receive
1455  * focus before list end, the first candidate will be returned.
1456  *
1457  * @param obj The widget root of sub-tree
1458  * @param dir Direction os focus chain
1459  * @param items list with ordered objects
1460  * @param list_data_get function to get the object from one item of list
1461  * @param next The next object in focus chain
1462  * @return EINA_TRUE if don't need focus chain restart/loop back
1463  *         to use 'next' obj.
1464  *
1465  * @ingroup Widget
1466  */
1467 EAPI Eina_Bool
1468 elm_widget_focus_list_next_get(const Evas_Object  *obj,
1469                                const Eina_List    *items,
1470                                void *(*list_data_get)(const Eina_List * list),
1471                                Elm_Focus_Direction dir,
1472                                Evas_Object       **next)
1473 {
1474    Eina_List *(*list_next)(const Eina_List * list);
1475
1476    if (!next)
1477      return EINA_FALSE;
1478    *next = NULL;
1479
1480    if (!_elm_widget_is(obj))
1481      return EINA_FALSE;
1482
1483    if (!items)
1484      return EINA_FALSE;
1485
1486    /* Direction */
1487    if (dir == ELM_FOCUS_PREVIOUS)
1488      {
1489         items = eina_list_last(items);
1490         list_next = eina_list_prev;
1491      }
1492    else if (dir == ELM_FOCUS_NEXT)
1493      list_next = eina_list_next;
1494    else
1495      return EINA_FALSE;
1496
1497    const Eina_List *l = items;
1498
1499    /* Recovery last focused sub item */
1500    if (elm_widget_focus_get(obj))
1501      for (; l; l = list_next(l))
1502        {
1503           Evas_Object *cur = list_data_get(l);
1504           if (elm_widget_focus_get(cur)) break;
1505        }
1506
1507    const Eina_List *start = l;
1508    Evas_Object *to_focus = NULL;
1509
1510    /* Interate sub items */
1511    /* Go to end of list */
1512    for (; l; l = list_next(l))
1513      {
1514         Evas_Object *tmp = NULL;
1515         Evas_Object *cur = list_data_get(l);
1516
1517         if (elm_widget_parent_get(cur) != obj)
1518           continue;
1519
1520         /* Try Focus cycle in subitem */
1521         if (elm_widget_focus_next_get(cur, dir, &tmp))
1522           {
1523              *next = tmp;
1524              return EINA_TRUE;
1525           }
1526         else if ((tmp) && (!to_focus))
1527           to_focus = tmp;
1528      }
1529
1530    l = items;
1531
1532    /* Get First possible */
1533    for (; l != start; l = list_next(l))
1534      {
1535         Evas_Object *tmp = NULL;
1536         Evas_Object *cur = list_data_get(l);
1537
1538         if (elm_widget_parent_get(cur) != obj)
1539           continue;
1540
1541         /* Try Focus cycle in subitem */
1542         elm_widget_focus_next_get(cur, dir, &tmp);
1543         if (tmp)
1544           {
1545              *next = tmp;
1546              return EINA_FALSE;
1547           }
1548      }
1549
1550    *next = to_focus;
1551    return EINA_FALSE;
1552 }
1553
1554 EAPI void
1555 elm_widget_signal_emit(Evas_Object *obj,
1556                        const char  *emission,
1557                        const char  *source)
1558 {
1559    API_ENTRY return;
1560    if (!sd->signal_func) return;
1561    sd->signal_func(obj, emission, source);
1562 }
1563
1564 static void
1565 _edje_signal_callback(void        *data,
1566                       Evas_Object *obj __UNUSED__,
1567                       const char  *emission,
1568                       const char  *source)
1569 {
1570    Edje_Signal_Data *esd = data;
1571    esd->func(esd->data, esd->obj, emission, source);
1572 }
1573
1574 EAPI void
1575 elm_widget_signal_callback_add(Evas_Object   *obj,
1576                                const char    *emission,
1577                                const char    *source,
1578                                Edje_Signal_Cb func,
1579                                void          *data)
1580 {
1581    Edje_Signal_Data *esd;
1582    API_ENTRY return;
1583    if (!sd->callback_add_func) return;
1584    EINA_SAFETY_ON_NULL_RETURN(func);
1585
1586    esd = ELM_NEW(Edje_Signal_Data);
1587    if (!esd) return;
1588
1589    esd->obj = obj;
1590    esd->func = func;
1591    esd->emission = eina_stringshare_add(emission);
1592    esd->source = eina_stringshare_add(source);
1593    esd->data = data;
1594    sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1595    sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1596 }
1597
1598 EAPI void *
1599 elm_widget_signal_callback_del(Evas_Object   *obj,
1600                                const char    *emission,
1601                                const char    *source,
1602                                Edje_Signal_Cb func)
1603 {
1604    Edje_Signal_Data *esd;
1605    Eina_List *l;
1606    void *data = NULL;
1607    API_ENTRY return NULL;
1608    if (!sd->callback_del_func) return NULL;
1609
1610    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1611      {
1612         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1613             (!strcmp(esd->source, source)))
1614           {
1615              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1616              eina_stringshare_del(esd->emission);
1617              eina_stringshare_del(esd->source);
1618              data = esd->data;
1619              free(esd);
1620              break;
1621           }
1622      }
1623    sd->callback_del_func(obj, emission, source, _edje_signal_callback, esd);
1624    return data;
1625 }
1626
1627 EAPI void
1628 elm_widget_focus_set(Evas_Object *obj,
1629                      int          first)
1630 {
1631    API_ENTRY return;
1632    if (!sd->focused)
1633      {
1634         focus_order++;
1635         sd->focus_order = focus_order;
1636         sd->focused = EINA_TRUE;
1637         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1638      }
1639    if (sd->focus_func)
1640      {
1641         sd->focus_func(obj);
1642         return;
1643      }
1644    else
1645      {
1646         if (first)
1647           {
1648              if ((_is_focusable(sd->resize_obj)) &&
1649                  (!elm_widget_disabled_get(sd->resize_obj)))
1650                {
1651                   elm_widget_focus_set(sd->resize_obj, first);
1652                }
1653              else
1654                {
1655                   const Eina_List *l;
1656                   Evas_Object *child;
1657                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1658                     {
1659                        if ((_is_focusable(child)) &&
1660                            (!elm_widget_disabled_get(child)))
1661                          {
1662                             elm_widget_focus_set(child, first);
1663                             break;
1664                          }
1665                     }
1666                }
1667           }
1668         else
1669           {
1670              const Eina_List *l;
1671              Evas_Object *child;
1672              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1673                {
1674                   if ((_is_focusable(child)) &&
1675                       (!elm_widget_disabled_get(child)))
1676                     {
1677                        elm_widget_focus_set(child, first);
1678                        break;
1679                     }
1680                }
1681              if (!l)
1682                {
1683                   if ((_is_focusable(sd->resize_obj)) &&
1684                       (!elm_widget_disabled_get(sd->resize_obj)))
1685                     {
1686                        elm_widget_focus_set(sd->resize_obj, first);
1687                     }
1688                }
1689           }
1690      }
1691 }
1692
1693 EAPI Evas_Object *
1694 elm_widget_parent_get(const Evas_Object *obj)
1695 {
1696    API_ENTRY return NULL;
1697    return sd->parent_obj;
1698 }
1699
1700 EAPI void
1701 elm_widget_focused_object_clear(Evas_Object *obj)
1702 {
1703    API_ENTRY return;
1704    if (!sd->focused) return;
1705    if (elm_widget_focus_get(sd->resize_obj))
1706      elm_widget_focused_object_clear(sd->resize_obj);
1707    else
1708      {
1709         const Eina_List *l;
1710         Evas_Object *child;
1711         EINA_LIST_FOREACH(sd->subobjs, l, child)
1712           {
1713              if (elm_widget_focus_get(child))
1714                {
1715                   elm_widget_focused_object_clear(child);
1716                   break;
1717                }
1718           }
1719      }
1720    sd->focused = EINA_FALSE;
1721    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1722    if (sd->focus_func) sd->focus_func(obj);
1723 }
1724
1725 EAPI void
1726 elm_widget_focus_steal(Evas_Object *obj)
1727 {
1728    Evas_Object *parent, *o;
1729    API_ENTRY return;
1730
1731    if (sd->focused) return;
1732    if (sd->disabled) return;
1733    if (!sd->can_focus) return;
1734    parent = obj;
1735    for (;;)
1736      {
1737         o = elm_widget_parent_get(parent);
1738         if (!o) break;
1739         sd = evas_object_smart_data_get(o);
1740         if (sd->focused) break;
1741         parent = o;
1742      }
1743    if (!elm_widget_parent_get(parent))
1744      elm_widget_focused_object_clear(parent);
1745    else
1746      {
1747         parent = elm_widget_parent_get(parent);
1748         sd = evas_object_smart_data_get(parent);
1749         if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1750           elm_widget_focused_object_clear(sd->resize_obj);
1751         else
1752           {
1753              const Eina_List *l;
1754              Evas_Object *child;
1755              EINA_LIST_FOREACH(sd->subobjs, l, child)
1756                {
1757                   if (elm_widget_focus_get(child))
1758                     {
1759                        elm_widget_focused_object_clear(child);
1760                        break;
1761                     }
1762                }
1763           }
1764      }
1765    _parent_focus(obj);
1766    return;
1767 }
1768
1769 EAPI void
1770 elm_widget_activate(Evas_Object *obj)
1771 {
1772    API_ENTRY return;
1773    elm_widget_change(obj);
1774    if (sd->activate_func) sd->activate_func(obj);
1775 }
1776
1777 EAPI void
1778 elm_widget_change(Evas_Object *obj)
1779 {
1780    API_ENTRY return;
1781    elm_widget_change(elm_widget_parent_get(obj));
1782    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
1783 }
1784
1785 EAPI void
1786 elm_widget_disabled_set(Evas_Object *obj,
1787                         int          disabled)
1788 {
1789    API_ENTRY return;
1790
1791    if (sd->disabled == disabled) return;
1792    sd->disabled = disabled;
1793    if (sd->focused)
1794      {
1795         Evas_Object *o, *parent;
1796
1797         parent = obj;
1798         for (;;)
1799           {
1800              o = elm_widget_parent_get(parent);
1801              if (!o) break;
1802              parent = o;
1803           }
1804         if (elm_widget_focus_get(obj))
1805           elm_widget_focus_cycle(parent, ELM_FOCUS_NEXT);
1806      }
1807    if (sd->disable_func) sd->disable_func(obj);
1808 }
1809
1810 EAPI int
1811 elm_widget_disabled_get(const Evas_Object *obj)
1812 {
1813    API_ENTRY return 0;
1814    return sd->disabled;
1815 }
1816
1817 EAPI void
1818 elm_widget_show_region_set(Evas_Object *obj,
1819                            Evas_Coord   x,
1820                            Evas_Coord   y,
1821                            Evas_Coord   w,
1822                            Evas_Coord   h,
1823                            Eina_Bool forceshow)
1824 {
1825    Evas_Object *parent_obj, *child_obj;
1826    Evas_Coord px, py, cx, cy;
1827
1828    API_ENTRY return;
1829    if (!forceshow && (x == sd->rx) && (y == sd->ry)
1830             && (w == sd->rw) && (h == sd->rh)) return;
1831    sd->rx = x;
1832    sd->ry = y;
1833    sd->rw = w;
1834    sd->rh = h;
1835    if (sd->on_show_region_func)
1836      sd->on_show_region_func(sd->on_show_region_data, obj);
1837
1838    do
1839      {
1840         parent_obj = sd->parent_obj;
1841         child_obj = sd->obj;
1842         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
1843         sd = evas_object_smart_data_get(parent_obj);
1844         if (!sd) break;
1845
1846         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
1847         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
1848
1849         x += (cx - px);
1850         y += (cy - py);
1851         sd->rx = x;
1852         sd->ry = y;
1853         sd->rw = w;
1854         sd->rh = h;
1855
1856         if (sd->on_show_region_func)
1857           {
1858              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
1859           }
1860      }
1861    while (parent_obj);
1862 }
1863
1864 EAPI void
1865 elm_widget_show_region_get(const Evas_Object *obj,
1866                            Evas_Coord        *x,
1867                            Evas_Coord        *y,
1868                            Evas_Coord        *w,
1869                            Evas_Coord        *h)
1870 {
1871    API_ENTRY return;
1872    if (x) *x = sd->rx;
1873    if (y) *y = sd->ry;
1874    if (w) *w = sd->rw;
1875    if (h) *h = sd->rh;
1876 }
1877
1878 /**
1879  * @internal
1880  *
1881  * Get the focus region of the given widget.
1882  *
1883  * The focus region is the area of a widget that should brought into the
1884  * visible area when the widget is focused. Mostly used to show the part of
1885  * an entry where the cursor is, for example. The area returned is relative
1886  * to the object @p obj.
1887  * If the @p obj doesn't have the proper on_focus_region_hook set, this
1888  * function will return the full size of the object.
1889  *
1890  * @param obj The widget object
1891  * @param x Where to store the x coordinate of the area
1892  * @param y Where to store the y coordinate of the area
1893  * @param w Where to store the width of the area
1894  * @param h Where to store the height of the area
1895  *
1896  * @ingroup Widget
1897  */
1898 EAPI void
1899 elm_widget_focus_region_get(const Evas_Object *obj,
1900                             Evas_Coord        *x,
1901                             Evas_Coord        *y,
1902                             Evas_Coord        *w,
1903                             Evas_Coord        *h)
1904 {
1905    Smart_Data *sd;
1906
1907    if (!obj) return;
1908
1909    sd = evas_object_smart_data_get(obj);
1910    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
1911      {
1912         evas_object_geometry_get(obj, NULL, NULL, w, h);
1913         if (x) *x = 0;
1914         if (y) *y = 0;
1915         return;
1916      }
1917    sd->on_focus_region_func(obj, x, y, w, h);
1918 }
1919
1920 EAPI void
1921 elm_widget_scroll_hold_push(Evas_Object *obj)
1922 {
1923    API_ENTRY return;
1924    sd->scroll_hold++;
1925    if (sd->scroll_hold == 1)
1926      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
1927    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
1928    // FIXME: on delete/reparent hold pop
1929 }
1930
1931 EAPI void
1932 elm_widget_scroll_hold_pop(Evas_Object *obj)
1933 {
1934    API_ENTRY return;
1935    sd->scroll_hold--;
1936    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
1937    if (!sd->scroll_hold)
1938      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
1939    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
1940 }
1941
1942 EAPI int
1943 elm_widget_scroll_hold_get(const Evas_Object *obj)
1944 {
1945    API_ENTRY return 0;
1946    return sd->scroll_hold;
1947 }
1948
1949 EAPI void
1950 elm_widget_scroll_freeze_push(Evas_Object *obj)
1951 {
1952    API_ENTRY return;
1953    sd->scroll_freeze++;
1954    if (sd->scroll_freeze == 1)
1955      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
1956    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
1957    // FIXME: on delete/reparent freeze pop
1958 }
1959
1960 EAPI void
1961 elm_widget_scroll_freeze_pop(Evas_Object *obj)
1962 {
1963    API_ENTRY return;
1964    sd->scroll_freeze--;
1965    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
1966    if (!sd->scroll_freeze)
1967      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
1968    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
1969 }
1970
1971 EAPI int
1972 elm_widget_scroll_freeze_get(const Evas_Object *obj)
1973 {
1974    API_ENTRY return 0;
1975    return sd->scroll_freeze;
1976 }
1977
1978 EAPI void
1979 elm_widget_scale_set(Evas_Object *obj,
1980                      double       scale)
1981 {
1982    API_ENTRY return;
1983    if (scale <= 0.0) scale = 0.0;
1984    if (sd->scale != scale)
1985      {
1986         sd->scale = scale;
1987         elm_widget_theme(obj);
1988      }
1989 }
1990
1991 EAPI double
1992 elm_widget_scale_get(const Evas_Object *obj)
1993 {
1994    API_ENTRY return 1.0;
1995    // FIXME: save walking up the tree by storing/caching parent scale
1996    if (sd->scale == 0.0)
1997      {
1998         if (sd->parent_obj)
1999           return elm_widget_scale_get(sd->parent_obj);
2000         else
2001           return 1.0;
2002      }
2003    return sd->scale;
2004 }
2005
2006 EAPI void
2007 elm_widget_theme_set(Evas_Object *obj,
2008                      Elm_Theme   *th)
2009 {
2010    API_ENTRY return;
2011    if (sd->theme != th)
2012      {
2013         if (sd->theme) elm_theme_free(sd->theme);
2014         sd->theme = th;
2015         if (th) th->ref++;
2016         elm_widget_theme(obj);
2017      }
2018 }
2019
2020 EAPI Elm_Theme *
2021 elm_widget_theme_get(const Evas_Object *obj)
2022 {
2023    API_ENTRY return NULL;
2024    if (!sd->theme)
2025      {
2026         if (sd->parent_obj)
2027           return elm_widget_theme_get(sd->parent_obj);
2028         else
2029           return NULL;
2030      }
2031    return sd->theme;
2032 }
2033
2034 EAPI void
2035 elm_widget_style_set(Evas_Object *obj,
2036                      const char  *style)
2037 {
2038    API_ENTRY return;
2039
2040    if (eina_stringshare_replace(&sd->style, style))
2041      elm_widget_theme(obj);
2042 }
2043
2044 EAPI const char *
2045 elm_widget_style_get(const Evas_Object *obj)
2046 {
2047    API_ENTRY return NULL;
2048    if (sd->style) return sd->style;
2049    return "default";
2050 }
2051
2052 EAPI void
2053 elm_widget_type_set(Evas_Object *obj,
2054                     const char  *type)
2055 {
2056    API_ENTRY return;
2057    eina_stringshare_replace(&sd->type, type);
2058 }
2059
2060 EAPI const char *
2061 elm_widget_type_get(const Evas_Object *obj)
2062 {
2063    API_ENTRY return NULL;
2064    if (sd->type) return sd->type;
2065    return "";
2066 }
2067
2068 EAPI void
2069 elm_widget_tooltip_add(Evas_Object *obj,
2070                        Elm_Tooltip *tt)
2071 {
2072    API_ENTRY return;
2073    sd->tooltips = eina_list_append(sd->tooltips, tt);
2074 }
2075
2076 EAPI void
2077 elm_widget_tooltip_del(Evas_Object *obj,
2078                        Elm_Tooltip *tt)
2079 {
2080    API_ENTRY return;
2081    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2082 }
2083
2084 EAPI void
2085 elm_widget_cursor_add(Evas_Object *obj,
2086                       Elm_Cursor  *cur)
2087 {
2088    API_ENTRY return;
2089    sd->cursors = eina_list_append(sd->cursors, cur);
2090 }
2091
2092 EAPI void
2093 elm_widget_cursor_del(Evas_Object *obj,
2094                       Elm_Cursor  *cur)
2095 {
2096    API_ENTRY return;
2097    sd->cursors = eina_list_remove(sd->cursors, cur);
2098 }
2099
2100 EAPI void
2101 elm_widget_drag_lock_x_set(Evas_Object *obj,
2102                            Eina_Bool    lock)
2103 {
2104    API_ENTRY return;
2105    if (sd->drag_x_locked == lock) return;
2106    sd->drag_x_locked = lock;
2107    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2108    else _propagate_x_drag_lock(obj, -1);
2109 }
2110
2111 EAPI void
2112 elm_widget_drag_lock_y_set(Evas_Object *obj,
2113                            Eina_Bool    lock)
2114 {
2115    API_ENTRY return;
2116    if (sd->drag_y_locked == lock) return;
2117    sd->drag_y_locked = lock;
2118    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2119    else _propagate_y_drag_lock(obj, -1);
2120 }
2121
2122 EAPI Eina_Bool
2123 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2124 {
2125    API_ENTRY return EINA_FALSE;
2126    return sd->drag_x_locked;
2127 }
2128
2129 EAPI Eina_Bool
2130 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2131 {
2132    API_ENTRY return EINA_FALSE;
2133    return sd->drag_y_locked;
2134 }
2135
2136 EAPI int
2137 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2138 {
2139    API_ENTRY return 0;
2140    return sd->child_drag_x_locked;
2141 }
2142
2143 EAPI int
2144 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2145 {
2146    API_ENTRY return 0;
2147    return sd->child_drag_y_locked;
2148 }
2149
2150 EAPI Eina_Bool
2151 elm_widget_theme_object_set(Evas_Object *obj,
2152                             Evas_Object *edj,
2153                             const char  *wname,
2154                             const char  *welement,
2155                             const char  *wstyle)
2156 {
2157    API_ENTRY return EINA_FALSE;
2158    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2159 }
2160
2161 EAPI Eina_Bool
2162 elm_widget_type_check(const Evas_Object *obj,
2163                       const char        *type)
2164 {
2165    const char *provided, *expected = "(unknown)";
2166    static int abort_on_warn = -1;
2167    provided = elm_widget_type_get(obj);
2168    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2169    if (type) expected = type;
2170    if ((!provided) || (!provided[0]))
2171      {
2172         provided = evas_object_type_get(obj);
2173         if ((!provided) || (!provided[0]))
2174           provided = "(unknown)";
2175      }
2176    ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
2177    if (abort_on_warn == -1)
2178      {
2179         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2180         else abort_on_warn = 0;
2181      }
2182    if (abort_on_warn == 1) abort();
2183    return EINA_FALSE;
2184 }
2185
2186 /**
2187  * @internal
2188  *
2189  * Split string in words
2190  *
2191  * @param str Source string
2192  * @return List of const words
2193  *
2194  * @see elm_widget_stringlist_free()
2195  * @ingroup Widget
2196  */
2197 EAPI Eina_List *
2198 elm_widget_stringlist_get(const char *str)
2199 {
2200    Eina_List *list = NULL;
2201    const char *s, *b;
2202    if (!str) return NULL;
2203    for (b = s = str; 1; s++)
2204      {
2205         if ((*s == ' ') || (!*s))
2206           {
2207              char *t = malloc(s - b + 1);
2208              if (t)
2209                {
2210                   strncpy(t, b, s - b);
2211                   t[s - b] = 0;
2212                   list = eina_list_append(list, eina_stringshare_add(t));
2213                   free(t);
2214                }
2215              b = s + 1;
2216           }
2217         if (!*s) break;
2218      }
2219    return list;
2220 }
2221
2222 EAPI void
2223 elm_widget_stringlist_free(Eina_List *list)
2224 {
2225    const char *s;
2226    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2227 }
2228
2229 /**
2230  * @internal
2231  *
2232  * Allocate a new Elm_Widget_Item-derived structure.
2233  *
2234  * The goal of this structure is to provide common ground for actions
2235  * that a widget item have, such as the owner widget, callback to
2236  * notify deletion, data pointer and maybe more.
2237  *
2238  * @param widget the owner widget that holds this item, must be an elm_widget!
2239  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2240  *        be used to allocate memory.
2241  *
2242  * @return allocated memory that is already zeroed out, or NULL on errors.
2243  *
2244  * @see elm_widget_item_new() convenience macro.
2245  * @see elm_widget_item_del() to release memory.
2246  * @ingroup Widget
2247  */
2248 EAPI Elm_Widget_Item *
2249 _elm_widget_item_new(Evas_Object *widget,
2250                      size_t       alloc_size)
2251 {
2252    if (!_elm_widget_is(widget))
2253      return NULL;
2254
2255    Elm_Widget_Item *item;
2256
2257    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2258    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2259
2260    item = calloc(1, alloc_size);
2261    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2262
2263    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2264    item->widget = widget;
2265    return item;
2266 }
2267
2268 /**
2269  * @internal
2270  *
2271  * Releases widget item memory, calling back del_cb() if it exists.
2272  *
2273  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2274  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2275  * this function and then unset it, thus being useful for 2 step
2276  * cleanup whenever the del_cb may use any of the data that must be
2277  * deleted from item.
2278  *
2279  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2280  * is presented!
2281  *
2282  * @param item a valid #Elm_Widget_Item to be deleted.
2283  * @see elm_widget_item_del() convenience macro.
2284  * @ingroup Widget
2285  */
2286 EAPI void
2287 _elm_widget_item_del(Elm_Widget_Item *item)
2288 {
2289    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2290
2291    if (item->del_cb)
2292      item->del_cb((void *)item->data, item->widget, item);
2293
2294    if (item->view)
2295      evas_object_del(item->view);
2296
2297    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2298    free(item);
2299 }
2300
2301 /**
2302  * @internal
2303  *
2304  * Notify object will be deleted without actually deleting it.
2305  *
2306  * This function will callback Elm_Widget_Item::del_cb if it is set
2307  * and then unset it so it is not called twice (ie: from
2308  * elm_widget_item_del()).
2309  *
2310  * @param item a valid #Elm_Widget_Item to be notified
2311  * @see elm_widget_item_pre_notify_del() convenience macro.
2312  * @ingroup Widget
2313  */
2314 EAPI void
2315 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2316 {
2317    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2318    if (!item->del_cb) return;
2319    item->del_cb((void *)item->data, item->widget, item);
2320    item->del_cb = NULL;
2321 }
2322
2323 /**
2324  * @internal
2325  *
2326  * Set the function to notify when item is being deleted.
2327  *
2328  * This function will complain if there was a callback set already,
2329  * however it will set the new one.
2330  *
2331  * The callback will be called from elm_widget_item_pre_notify_del()
2332  * or elm_widget_item_del() will be called with:
2333  *   - data: the Elm_Widget_Item::data value.
2334  *   - obj: the Elm_Widget_Item::widget evas object.
2335  *   - event_info: the item being deleted.
2336  *
2337  * @param item a valid #Elm_Widget_Item to be notified
2338  * @see elm_widget_item_del_cb_set() convenience macro.
2339  * @ingroup Widget
2340  */
2341 EAPI void
2342 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2343                             Evas_Smart_Cb    del_cb)
2344 {
2345    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2346
2347    if ((item->del_cb) && (item->del_cb != del_cb))
2348      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2349          item->del_cb, item, del_cb);
2350
2351    item->del_cb = del_cb;
2352 }
2353
2354 /**
2355  * @internal
2356  *
2357  * Set user-data in this item.
2358  *
2359  * User data may be used to identify this item or just store any
2360  * application data. It is automatically given as the first parameter
2361  * of the deletion notify callback.
2362  *
2363  * @param item a valid #Elm_Widget_Item to store data in.
2364  * @param data user data to store.
2365  * @see elm_widget_item_del_cb_set() convenience macro.
2366  * @ingroup Widget
2367  */
2368 EAPI void
2369 _elm_widget_item_data_set(Elm_Widget_Item *item,
2370                           const void      *data)
2371 {
2372    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2373    if ((item->data) && (item->data != data))
2374      DBG("Replacing item %p data %p with %p", item, item->data, data);
2375    item->data = data;
2376 }
2377
2378 /**
2379  * @internal
2380  *
2381  * Retrieves user-data of this item.
2382  *
2383  * @param item a valid #Elm_Widget_Item to get data from.
2384  * @see elm_widget_item_data_set()
2385  * @ingroup Widget
2386  */
2387 EAPI void *
2388 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2389 {
2390    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2391    return (void *)item->data;
2392 }
2393
2394 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2395
2396 struct _Elm_Widget_Item_Tooltip
2397 {
2398    Elm_Widget_Item            *item;
2399    Elm_Tooltip_Item_Content_Cb func;
2400    Evas_Smart_Cb               del_cb;
2401    const void                 *data;
2402 };
2403
2404 static Evas_Object *
2405 _elm_widget_item_tooltip_label_create(void        *data,
2406                                       Evas_Object *obj,
2407                                       void        *item __UNUSED__)
2408 {
2409    Evas_Object *label = elm_label_add(obj);
2410    if (!label)
2411      return NULL;
2412    elm_object_style_set(label, "tooltip");
2413    elm_label_label_set(label, data);
2414    return label;
2415 }
2416
2417 static void
2418 _elm_widget_item_tooltip_label_del_cb(void        *data,
2419                                       Evas_Object *obj __UNUSED__,
2420                                       void        *event_info __UNUSED__)
2421 {
2422    eina_stringshare_del(data);
2423 }
2424
2425 /**
2426  * @internal
2427  *
2428  * Set the text to be shown in the widget item.
2429  *
2430  * @param item Target item
2431  * @param text The text to set in the content
2432  *
2433  * Setup the text as tooltip to object. The item can have only one tooltip,
2434  * so any previous tooltip data is removed.
2435  *
2436  * @ingroup Widget
2437  */
2438 EAPI void
2439 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2440                                   const char      *text)
2441 {
2442    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2443    EINA_SAFETY_ON_NULL_RETURN(text);
2444
2445    text = eina_stringshare_add(text);
2446    _elm_widget_item_tooltip_content_cb_set
2447      (item, _elm_widget_item_tooltip_label_create, text,
2448      _elm_widget_item_tooltip_label_del_cb);
2449 }
2450
2451 static Evas_Object *
2452 _elm_widget_item_tooltip_create(void        *data,
2453                                 Evas_Object *obj)
2454 {
2455    Elm_Widget_Item_Tooltip *wit = data;
2456    return wit->func((void *)wit->data, obj, wit->item);
2457 }
2458
2459 static void
2460 _elm_widget_item_tooltip_del_cb(void        *data,
2461                                 Evas_Object *obj,
2462                                 void        *event_info __UNUSED__)
2463 {
2464    Elm_Widget_Item_Tooltip *wit = data;
2465    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
2466    free(wit);
2467 }
2468
2469 /**
2470  * @internal
2471  *
2472  * Set the content to be shown in the tooltip item
2473  *
2474  * Setup the tooltip to item. The item can have only one tooltip,
2475  * so any previous tooltip data is removed. @p func(with @p data) will
2476  * be called every time that need show the tooltip and it should
2477  * return a valid Evas_Object. This object is then managed fully by
2478  * tooltip system and is deleted when the tooltip is gone.
2479  *
2480  * @param item the widget item being attached a tooltip.
2481  * @param func the function used to create the tooltip contents.
2482  * @param data what to provide to @a func as callback data/context.
2483  * @param del_cb called when data is not needed anymore, either when
2484  *        another callback replaces @func, the tooltip is unset with
2485  *        elm_widget_item_tooltip_unset() or the owner @a item
2486  *        dies. This callback receives as the first parameter the
2487  *        given @a data, and @c event_info is the item.
2488  *
2489  * @ingroup Widget
2490  */
2491 EAPI void
2492 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
2493                                         Elm_Tooltip_Item_Content_Cb func,
2494                                         const void                 *data,
2495                                         Evas_Smart_Cb               del_cb)
2496 {
2497    Elm_Widget_Item_Tooltip *wit;
2498
2499    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
2500
2501    if (!func)
2502      {
2503         _elm_widget_item_tooltip_unset(item);
2504         return;
2505      }
2506
2507    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
2508    if (!wit) goto error;
2509    wit->item = item;
2510    wit->func = func;
2511    wit->data = data;
2512    wit->del_cb = del_cb;
2513
2514    elm_object_sub_tooltip_content_cb_set
2515      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
2516      _elm_widget_item_tooltip_del_cb);
2517
2518    return;
2519
2520 error_noitem:
2521    if (del_cb) del_cb((void *)data, NULL, item);
2522    return;
2523 error:
2524    if (del_cb) del_cb((void *)data, item->widget, item);
2525 }
2526
2527 /**
2528  * @internal
2529  *
2530  * Unset tooltip from item
2531  *
2532  * @param item widget item to remove previously set tooltip.
2533  *
2534  * Remove tooltip from item. The callback provided as del_cb to
2535  * elm_widget_item_tooltip_content_cb_set() will be called to notify
2536  * it is not used anymore.
2537  *
2538  * @see elm_widget_item_tooltip_content_cb_set()
2539  *
2540  * @ingroup Widget
2541  */
2542 EAPI void
2543 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
2544 {
2545    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2546    elm_object_tooltip_unset(item->view);
2547 }
2548
2549 /**
2550  * @internal
2551  *
2552  * Sets a different style for this item tooltip.
2553  *
2554  * @note before you set a style you should define a tooltip with
2555  *       elm_widget_item_tooltip_content_cb_set() or
2556  *       elm_widget_item_tooltip_text_set()
2557  *
2558  * @param item widget item with tooltip already set.
2559  * @param style the theme style to use (default, transparent, ...)
2560  *
2561  * @ingroup Widget
2562  */
2563 EAPI void
2564 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
2565                                    const char      *style)
2566 {
2567    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2568    elm_object_tooltip_style_set(item->view, style);
2569 }
2570
2571 /**
2572  * @internal
2573  *
2574  * Get the style for this item tooltip.
2575  *
2576  * @param item widget item with tooltip already set.
2577  * @return style the theme style in use, defaults to "default". If the
2578  *         object does not have a tooltip set, then NULL is returned.
2579  *
2580  * @ingroup Widget
2581  */
2582 EAPI const char *
2583 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
2584 {
2585    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2586    return elm_object_tooltip_style_get(item->view);
2587 }
2588
2589 EAPI void
2590 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
2591                             const char      *cursor)
2592 {
2593    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2594    elm_object_sub_cursor_set(item->view, item->widget, cursor);
2595 }
2596
2597 EAPI const char *
2598 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
2599 {
2600    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2601    return elm_object_cursor_get(item->view);
2602 }
2603
2604 EAPI void
2605 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
2606 {
2607    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2608    elm_object_cursor_unset(item->view);
2609 }
2610
2611 /**
2612  * @internal
2613  *
2614  * Sets a different style for this item cursor.
2615  *
2616  * @note before you set a style you should define a cursor with
2617  *       elm_widget_item_cursor_set()
2618  *
2619  * @param item widget item with cursor already set.
2620  * @param style the theme style to use (default, transparent, ...)
2621  *
2622  * @ingroup Widget
2623  */
2624 EAPI void
2625 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
2626                                   const char      *style)
2627 {
2628    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2629    elm_object_cursor_style_set(item->view, style);
2630 }
2631
2632 /**
2633  * @internal
2634  *
2635  * Get the style for this item cursor.
2636  *
2637  * @param item widget item with cursor already set.
2638  * @return style the theme style in use, defaults to "default". If the
2639  *         object does not have a cursor set, then NULL is returned.
2640  *
2641  * @ingroup Widget
2642  */
2643 EAPI const char *
2644 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
2645 {
2646    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2647    return elm_object_cursor_style_get(item->view);
2648 }
2649
2650 /**
2651  * @internal
2652  *
2653  * Set if the cursor set should be searched on the theme or should use
2654  * the provided by the engine, only.
2655  *
2656  * @note before you set if should look on theme you should define a cursor
2657  * with elm_object_cursor_set(). By default it will only look for cursors
2658  * provided by the engine.
2659  *
2660  * @param item widget item with cursor already set.
2661  * @param engine_only boolean to define it cursors should be looked only
2662  * between the provided by the engine or searched on widget's theme as well.
2663  *
2664  * @ingroup Widget
2665  */
2666 EAPI void
2667 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
2668                                         Eina_Bool        engine_only)
2669 {
2670    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2671    elm_object_cursor_engine_only_set(item->view, engine_only);
2672 }
2673
2674 /**
2675  * @internal
2676  *
2677  * Get the cursor engine only usage for this item cursor.
2678  *
2679  * @param item widget item with cursor already set.
2680  * @return engine_only boolean to define it cursors should be looked only
2681  * between the provided by the engine or searched on widget's theme as well. If
2682  *         the object does not have a cursor set, then EINA_FALSE is returned.
2683  *
2684  * @ingroup Widget
2685  */
2686 EAPI Eina_Bool
2687 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
2688 {
2689    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2690    return elm_object_cursor_engine_only_get(item->view);
2691 }
2692
2693 // smart object funcs
2694 static void
2695 _smart_reconfigure(Smart_Data *sd)
2696 {
2697    if (sd->resize_obj)
2698      {
2699         evas_object_move(sd->resize_obj, sd->x, sd->y);
2700         evas_object_resize(sd->resize_obj, sd->w, sd->h);
2701      }
2702    if (sd->hover_obj)
2703      {
2704         evas_object_move(sd->hover_obj, sd->x, sd->y);
2705         evas_object_resize(sd->hover_obj, sd->w, sd->h);
2706      }
2707 }
2708
2709 static void
2710 _smart_add(Evas_Object *obj)
2711 {
2712    Smart_Data *sd;
2713
2714    sd = calloc(1, sizeof(Smart_Data));
2715    if (!sd) return;
2716    sd->obj = obj;
2717    sd->x = sd->y = sd->w = sd->h = 0;
2718    sd->can_focus = 1;
2719    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
2720    evas_object_smart_data_set(obj, sd);
2721 }
2722
2723 static Evas_Object *
2724 _newest_focus_order_get(Evas_Object  *obj,
2725                         unsigned int *newest_focus_order,
2726                         Eina_Bool     can_focus_only)
2727 {
2728    const Eina_List *l;
2729    Evas_Object *child, *ret, *best;
2730
2731    API_ENTRY return NULL;
2732    if (!evas_object_visible_get(obj)) return NULL;
2733    best = NULL;
2734    if (*newest_focus_order < sd->focus_order)
2735      {
2736         *newest_focus_order = sd->focus_order;
2737         best = obj;
2738      }
2739    EINA_LIST_FOREACH(sd->subobjs, l, child)
2740      {
2741         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
2742         if (!ret) continue;
2743         best = ret;
2744      }
2745    if (can_focus_only)
2746      {
2747         if ((!best) || (!elm_widget_can_focus_get(best)))
2748           return NULL;
2749      }
2750    return best;
2751 }
2752
2753 static void
2754 _if_focused_revert(Evas_Object *obj,
2755                    Eina_Bool    can_focus_only)
2756 {
2757    Evas_Object *top;
2758    Evas_Object *newest = NULL;
2759    unsigned int newest_focus_order = 0;
2760
2761    INTERNAL_ENTRY
2762
2763    if (!sd->focused) return;
2764    if (!sd->parent_obj) return;
2765
2766    top = elm_widget_top_get(sd->parent_obj);
2767    if (top)
2768      {
2769         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
2770         if (newest)
2771           {
2772              elm_object_unfocus(newest);
2773              elm_object_focus(newest);
2774           }
2775      }
2776 }
2777
2778 static void
2779 _smart_del(Evas_Object *obj)
2780 {
2781    Evas_Object *sobj;
2782    Edje_Signal_Data *esd;
2783
2784    INTERNAL_ENTRY
2785
2786    if (sd->del_pre_func) sd->del_pre_func(obj);
2787    if (sd->resize_obj)
2788      {
2789         sobj = sd->resize_obj;
2790         sd->resize_obj = NULL;
2791         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2792         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2793         evas_object_del(sobj);
2794      }
2795    if (sd->hover_obj)
2796      {
2797         sobj = sd->hover_obj;
2798         sd->hover_obj = NULL;
2799         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2800         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2801         evas_object_del(sobj);
2802      }
2803    EINA_LIST_FREE(sd->subobjs, sobj)
2804      {
2805         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2806         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2807         evas_object_del(sobj);
2808      }
2809    eina_list_free(sd->tooltips); /* should be empty anyway */
2810    eina_list_free(sd->cursors); /* should be empty anyway */
2811    EINA_LIST_FREE(sd->edje_signals, esd)
2812      {
2813         eina_stringshare_del(esd->emission);
2814         eina_stringshare_del(esd->source);
2815         free(esd);
2816      }
2817    eina_list_free(sd->event_cb); /* should be empty anyway */
2818    if (sd->del_func) sd->del_func(obj);
2819    if (sd->style) eina_stringshare_del(sd->style);
2820    if (sd->type) eina_stringshare_del(sd->type);
2821    if (sd->theme) elm_theme_free(sd->theme);
2822    _if_focused_revert(obj, EINA_TRUE);
2823    free(sd);
2824 }
2825
2826 static void
2827 _smart_move(Evas_Object *obj,
2828             Evas_Coord   x,
2829             Evas_Coord   y)
2830 {
2831    INTERNAL_ENTRY
2832    sd->x = x;
2833    sd->y = y;
2834    _smart_reconfigure(sd);
2835 }
2836
2837 static void
2838 _smart_resize(Evas_Object *obj,
2839               Evas_Coord   w,
2840               Evas_Coord   h)
2841 {
2842    INTERNAL_ENTRY
2843    sd->w = w;
2844    sd->h = h;
2845    _smart_reconfigure(sd);
2846 }
2847
2848 static void
2849 _smart_show(Evas_Object *obj)
2850 {
2851    Eina_List *list;
2852    Evas_Object *o;
2853    INTERNAL_ENTRY
2854    if ((list = evas_object_smart_members_get(obj)))
2855      {
2856         EINA_LIST_FREE(list, o)
2857           {
2858              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2859              evas_object_show(o);
2860           }
2861      }
2862 }
2863
2864 static void
2865 _smart_hide(Evas_Object *obj)
2866 {
2867    Eina_List *list;
2868    Evas_Object *o;
2869    INTERNAL_ENTRY
2870      list = evas_object_smart_members_get(obj);
2871    EINA_LIST_FREE(list, o)
2872      {
2873         if (evas_object_data_get(o, "_elm_leaveme")) continue;
2874         evas_object_hide(o);
2875      }
2876 }
2877
2878 static void
2879 _smart_color_set(Evas_Object *obj,
2880                  int          r,
2881                  int          g,
2882                  int          b,
2883                  int          a)
2884 {
2885    Eina_List *list;
2886    Evas_Object *o;
2887    INTERNAL_ENTRY
2888    if ((list = evas_object_smart_members_get(obj)))
2889      {
2890         EINA_LIST_FREE(list, o)
2891           {
2892              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2893              evas_object_color_set(o, r, g, b, a);
2894           }
2895      }
2896 }
2897
2898 static void
2899 _smart_clip_set(Evas_Object *obj,
2900                 Evas_Object *clip)
2901 {
2902    Eina_List *list;
2903    Evas_Object *o;
2904    INTERNAL_ENTRY
2905    if ((list = evas_object_smart_members_get(obj)))
2906      {
2907         EINA_LIST_FREE(list, o)
2908           {
2909              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2910              evas_object_clip_set(o, clip);
2911           }
2912      }
2913 }
2914
2915 static void
2916 _smart_clip_unset(Evas_Object *obj)
2917 {
2918    Eina_List *list;
2919    Evas_Object *o;
2920    INTERNAL_ENTRY
2921    if ((list = evas_object_smart_members_get(obj)))
2922      {
2923         EINA_LIST_FREE(list, o)
2924           {
2925              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2926              evas_object_clip_unset(o);
2927           }
2928      }
2929 }
2930
2931 static void
2932 _smart_calculate(Evas_Object *obj)
2933 {
2934    INTERNAL_ENTRY
2935    if (sd->changed_func) sd->changed_func(obj);
2936 }
2937
2938 /* never need to touch this */
2939 static void
2940 _smart_init(void)
2941 {
2942    if (_e_smart) return;
2943    {
2944       static const Evas_Smart_Class sc =
2945       {
2946          SMART_NAME,
2947          EVAS_SMART_CLASS_VERSION,
2948          _smart_add,
2949          _smart_del,
2950          _smart_move,
2951          _smart_resize,
2952          _smart_show,
2953          _smart_hide,
2954          _smart_color_set,
2955          _smart_clip_set,
2956          _smart_clip_unset,
2957          _smart_calculate,
2958          NULL,
2959          NULL,
2960          NULL,
2961          NULL,
2962          NULL,
2963          NULL
2964       };
2965       _e_smart = evas_smart_class_new(&sc);
2966    }
2967 }
2968
2969 /* happy debug functions */
2970 #ifdef ELM_DEBUG
2971 static void
2972 _sub_obj_tree_dump(const Evas_Object *obj,
2973                    int                lvl)
2974 {
2975    int i;
2976
2977    for (i = 0; i < lvl * 3; i++)
2978      putchar(' ');
2979
2980    if (_elm_widget_is(obj))
2981      {
2982         Eina_List *l;
2983         INTERNAL_ENTRY
2984         printf("+ %s(%p)\n",
2985                sd->type,
2986                obj);
2987         if (sd->resize_obj)
2988           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
2989         EINA_LIST_FOREACH(sd->subobjs, l, obj)
2990           {
2991              if (obj != sd->resize_obj)
2992                _sub_obj_tree_dump(obj, lvl + 1);
2993           }
2994      }
2995    else
2996      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
2997 }
2998
2999 static void
3000 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3001                        FILE              *output)
3002 {
3003    if (!_elm_widget_is(obj))
3004      return;
3005    INTERNAL_ENTRY
3006
3007    Eina_Bool visible = evas_object_visible_get(obj);
3008    Eina_Bool disabled = elm_widget_disabled_get(obj);
3009    Eina_Bool focused = elm_widget_focus_get(obj);
3010    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3011
3012    if (sd->parent_obj)
3013      {
3014         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3015
3016         if (focused)
3017           fprintf(output, ", style=bold");
3018
3019         if (!visible)
3020           fprintf(output, ", color=gray28");
3021
3022         fprintf(output, " ];\n");
3023      }
3024
3025    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3026                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3027            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3028            sd->focus_order);
3029
3030    if (focused)
3031      fprintf(output, ", style=bold");
3032
3033    if (!visible)
3034      fprintf(output, ", fontcolor=gray28");
3035
3036    if ((disabled) || (!visible))
3037      fprintf(output, ", color=gray");
3038
3039    fprintf(output, " ];\n");
3040
3041    Eina_List *l;
3042    Evas_Object *o;
3043    EINA_LIST_FOREACH(sd->subobjs, l, o)
3044      _sub_obj_tree_dot_dump(o, output);
3045 }
3046 #endif
3047
3048 EAPI void
3049 elm_widget_tree_dump(const Evas_Object *top)
3050 {
3051 #ifdef ELM_DEBUG
3052    _sub_obj_tree_dump(top, 0);
3053 #else
3054    return;
3055    (void)top;
3056 #endif
3057 }
3058
3059 EAPI void
3060 elm_widget_tree_dot_dump(const Evas_Object *top,
3061                          FILE              *output)
3062 {
3063 #ifdef ELM_DEBUG
3064    if (!_elm_widget_is(top))
3065      return;
3066    fprintf(output, "graph " " { node [shape=record];\n");
3067    _sub_obj_tree_dot_dump(top, output);
3068    fprintf(output, "}\n");
3069 #else
3070    return;
3071    (void)top;
3072    (void)output;
3073 #endif
3074 }