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