elementary: elm_label_label_ -> elm_object_text
[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_label_set_func)(Evas_Object *obj,
74                                    const char  *item,
75                                    const char  *text);
76    const char *(*on_label_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_label_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_label_set_func = func;
493 }
494
495 EAPI void
496 elm_widget_label_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_label_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->focused) break;
1756         parent = o;
1757      }
1758    if (!elm_widget_parent_get(parent))
1759      elm_widget_focused_object_clear(parent);
1760    else
1761      {
1762         parent = elm_widget_parent_get(parent);
1763         sd = evas_object_smart_data_get(parent);
1764         if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1765           elm_widget_focused_object_clear(sd->resize_obj);
1766         else
1767           {
1768              const Eina_List *l;
1769              Evas_Object *child;
1770              EINA_LIST_FOREACH(sd->subobjs, l, child)
1771                {
1772                   if (elm_widget_focus_get(child))
1773                     {
1774                        elm_widget_focused_object_clear(child);
1775                        break;
1776                     }
1777                }
1778           }
1779      }
1780    _parent_focus(obj);
1781    return;
1782 }
1783
1784 EAPI void
1785 elm_widget_activate(Evas_Object *obj)
1786 {
1787    API_ENTRY return;
1788    elm_widget_change(obj);
1789    if (sd->activate_func) sd->activate_func(obj);
1790 }
1791
1792 EAPI void
1793 elm_widget_change(Evas_Object *obj)
1794 {
1795    API_ENTRY return;
1796    elm_widget_change(elm_widget_parent_get(obj));
1797    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
1798 }
1799
1800 EAPI void
1801 elm_widget_disabled_set(Evas_Object *obj,
1802                         Eina_Bool    disabled)
1803 {
1804    API_ENTRY return;
1805
1806    if (sd->disabled == disabled) return;
1807    sd->disabled = !!disabled;
1808    if (sd->focused)
1809      {
1810         Evas_Object *o, *parent;
1811
1812         parent = obj;
1813         for (;;)
1814           {
1815              o = elm_widget_parent_get(parent);
1816              if (!o) break;
1817              parent = o;
1818           }
1819         if (elm_widget_focus_get(obj))
1820           elm_widget_focus_cycle(parent, ELM_FOCUS_NEXT);
1821      }
1822    if (sd->disable_func) sd->disable_func(obj);
1823 }
1824
1825 EAPI Eina_Bool
1826 elm_widget_disabled_get(const Evas_Object *obj)
1827 {
1828    API_ENTRY return 0;
1829    return sd->disabled;
1830 }
1831
1832 EAPI void
1833 elm_widget_show_region_set(Evas_Object *obj,
1834                            Evas_Coord   x,
1835                            Evas_Coord   y,
1836                            Evas_Coord   w,
1837                            Evas_Coord   h)
1838 {
1839    Evas_Object *parent_obj, *child_obj;
1840    Evas_Coord px, py, cx, cy;
1841
1842    API_ENTRY return;
1843    if ((x == sd->rx) && (y == sd->ry) && (w == sd->rw) && (h == sd->rh)) return;
1844    sd->rx = x;
1845    sd->ry = y;
1846    sd->rw = w;
1847    sd->rh = h;
1848    if (sd->on_show_region_func)
1849      sd->on_show_region_func(sd->on_show_region_data, obj);
1850
1851    do
1852      {
1853         parent_obj = sd->parent_obj;
1854         child_obj = sd->obj;
1855         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
1856         sd = evas_object_smart_data_get(parent_obj);
1857         if (!sd) break;
1858
1859         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
1860         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
1861
1862         x += (cx - px);
1863         y += (cy - py);
1864         sd->rx = x;
1865         sd->ry = y;
1866         sd->rw = w;
1867         sd->rh = h;
1868
1869         if (sd->on_show_region_func)
1870           {
1871              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
1872           }
1873      }
1874    while (parent_obj);
1875 }
1876
1877 EAPI void
1878 elm_widget_show_region_get(const Evas_Object *obj,
1879                            Evas_Coord        *x,
1880                            Evas_Coord        *y,
1881                            Evas_Coord        *w,
1882                            Evas_Coord        *h)
1883 {
1884    API_ENTRY return;
1885    if (x) *x = sd->rx;
1886    if (y) *y = sd->ry;
1887    if (w) *w = sd->rw;
1888    if (h) *h = sd->rh;
1889 }
1890
1891 /**
1892  * @internal
1893  *
1894  * Get the focus region of the given widget.
1895  *
1896  * The focus region is the area of a widget that should brought into the
1897  * visible area when the widget is focused. Mostly used to show the part of
1898  * an entry where the cursor is, for example. The area returned is relative
1899  * to the object @p obj.
1900  * If the @p obj doesn't have the proper on_focus_region_hook set, this
1901  * function will return the full size of the object.
1902  *
1903  * @param obj The widget object
1904  * @param x Where to store the x coordinate of the area
1905  * @param y Where to store the y coordinate of the area
1906  * @param w Where to store the width of the area
1907  * @param h Where to store the height of the area
1908  *
1909  * @ingroup Widget
1910  */
1911 EAPI void
1912 elm_widget_focus_region_get(const Evas_Object *obj,
1913                             Evas_Coord        *x,
1914                             Evas_Coord        *y,
1915                             Evas_Coord        *w,
1916                             Evas_Coord        *h)
1917 {
1918    Smart_Data *sd;
1919
1920    if (!obj) return;
1921
1922    sd = evas_object_smart_data_get(obj);
1923    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
1924      {
1925         evas_object_geometry_get(obj, NULL, NULL, w, h);
1926         if (x) *x = 0;
1927         if (y) *y = 0;
1928         return;
1929      }
1930    sd->on_focus_region_func(obj, x, y, w, h);
1931 }
1932
1933 EAPI void
1934 elm_widget_scroll_hold_push(Evas_Object *obj)
1935 {
1936    API_ENTRY return;
1937    sd->scroll_hold++;
1938    if (sd->scroll_hold == 1)
1939      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
1940    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
1941    // FIXME: on delete/reparent hold pop
1942 }
1943
1944 EAPI void
1945 elm_widget_scroll_hold_pop(Evas_Object *obj)
1946 {
1947    API_ENTRY return;
1948    sd->scroll_hold--;
1949    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
1950    if (!sd->scroll_hold)
1951      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
1952    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
1953 }
1954
1955 EAPI int
1956 elm_widget_scroll_hold_get(const Evas_Object *obj)
1957 {
1958    API_ENTRY return 0;
1959    return sd->scroll_hold;
1960 }
1961
1962 EAPI void
1963 elm_widget_scroll_freeze_push(Evas_Object *obj)
1964 {
1965    API_ENTRY return;
1966    sd->scroll_freeze++;
1967    if (sd->scroll_freeze == 1)
1968      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
1969    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
1970    // FIXME: on delete/reparent freeze pop
1971 }
1972
1973 EAPI void
1974 elm_widget_scroll_freeze_pop(Evas_Object *obj)
1975 {
1976    API_ENTRY return;
1977    sd->scroll_freeze--;
1978    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
1979    if (!sd->scroll_freeze)
1980      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
1981    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
1982 }
1983
1984 EAPI int
1985 elm_widget_scroll_freeze_get(const Evas_Object *obj)
1986 {
1987    API_ENTRY return 0;
1988    return sd->scroll_freeze;
1989 }
1990
1991 EAPI void
1992 elm_widget_scale_set(Evas_Object *obj,
1993                      double       scale)
1994 {
1995    API_ENTRY return;
1996    if (scale <= 0.0) scale = 0.0;
1997    if (sd->scale != scale)
1998      {
1999         sd->scale = scale;
2000         elm_widget_theme(obj);
2001      }
2002 }
2003
2004 EAPI double
2005 elm_widget_scale_get(const Evas_Object *obj)
2006 {
2007    API_ENTRY return 1.0;
2008    // FIXME: save walking up the tree by storing/caching parent scale
2009    if (sd->scale == 0.0)
2010      {
2011         if (sd->parent_obj)
2012           return elm_widget_scale_get(sd->parent_obj);
2013         else
2014           return 1.0;
2015      }
2016    return sd->scale;
2017 }
2018
2019 EAPI void
2020 elm_widget_theme_set(Evas_Object *obj,
2021                      Elm_Theme   *th)
2022 {
2023    API_ENTRY return;
2024    if (sd->theme != th)
2025      {
2026         if (sd->theme) elm_theme_free(sd->theme);
2027         sd->theme = th;
2028         if (th) th->ref++;
2029         elm_widget_theme(obj);
2030      }
2031 }
2032
2033 EAPI void
2034 elm_widget_label_set(Evas_Object *obj, const char *item, const char *label)
2035 {
2036    API_ENTRY return;
2037
2038    if (!sd->on_label_set_func)
2039      return;
2040
2041    sd->on_label_set_func(obj, item, label);
2042 }
2043
2044 EAPI const char *
2045 elm_widget_label_get(const Evas_Object *obj, const char *item)
2046 {
2047    API_ENTRY return NULL;
2048
2049    if (!sd->on_label_get_func)
2050      return NULL;
2051
2052    return sd->on_label_get_func(obj, item);
2053 }
2054
2055 EAPI Elm_Theme *
2056 elm_widget_theme_get(const Evas_Object *obj)
2057 {
2058    API_ENTRY return NULL;
2059    if (!sd->theme)
2060      {
2061         if (sd->parent_obj)
2062           return elm_widget_theme_get(sd->parent_obj);
2063         else
2064           return NULL;
2065      }
2066    return sd->theme;
2067 }
2068
2069 EAPI void
2070 elm_widget_style_set(Evas_Object *obj,
2071                      const char  *style)
2072 {
2073    API_ENTRY return;
2074
2075    if (eina_stringshare_replace(&sd->style, style))
2076      elm_widget_theme(obj);
2077 }
2078
2079 EAPI const char *
2080 elm_widget_style_get(const Evas_Object *obj)
2081 {
2082    API_ENTRY return NULL;
2083    if (sd->style) return sd->style;
2084    return "default";
2085 }
2086
2087 EAPI void
2088 elm_widget_type_set(Evas_Object *obj,
2089                     const char  *type)
2090 {
2091    API_ENTRY return;
2092    eina_stringshare_replace(&sd->type, type);
2093 }
2094
2095 EAPI const char *
2096 elm_widget_type_get(const Evas_Object *obj)
2097 {
2098    API_ENTRY return NULL;
2099    if (sd->type) return sd->type;
2100    return "";
2101 }
2102
2103 EAPI void
2104 elm_widget_tooltip_add(Evas_Object *obj,
2105                        Elm_Tooltip *tt)
2106 {
2107    API_ENTRY return;
2108    sd->tooltips = eina_list_append(sd->tooltips, tt);
2109 }
2110
2111 EAPI void
2112 elm_widget_tooltip_del(Evas_Object *obj,
2113                        Elm_Tooltip *tt)
2114 {
2115    API_ENTRY return;
2116    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2117 }
2118
2119 EAPI void
2120 elm_widget_cursor_add(Evas_Object *obj,
2121                       Elm_Cursor  *cur)
2122 {
2123    API_ENTRY return;
2124    sd->cursors = eina_list_append(sd->cursors, cur);
2125 }
2126
2127 EAPI void
2128 elm_widget_cursor_del(Evas_Object *obj,
2129                       Elm_Cursor  *cur)
2130 {
2131    API_ENTRY return;
2132    sd->cursors = eina_list_remove(sd->cursors, cur);
2133 }
2134
2135 EAPI void
2136 elm_widget_drag_lock_x_set(Evas_Object *obj,
2137                            Eina_Bool    lock)
2138 {
2139    API_ENTRY return;
2140    if (sd->drag_x_locked == lock) return;
2141    sd->drag_x_locked = lock;
2142    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2143    else _propagate_x_drag_lock(obj, -1);
2144 }
2145
2146 EAPI void
2147 elm_widget_drag_lock_y_set(Evas_Object *obj,
2148                            Eina_Bool    lock)
2149 {
2150    API_ENTRY return;
2151    if (sd->drag_y_locked == lock) return;
2152    sd->drag_y_locked = lock;
2153    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2154    else _propagate_y_drag_lock(obj, -1);
2155 }
2156
2157 EAPI Eina_Bool
2158 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2159 {
2160    API_ENTRY return EINA_FALSE;
2161    return sd->drag_x_locked;
2162 }
2163
2164 EAPI Eina_Bool
2165 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2166 {
2167    API_ENTRY return EINA_FALSE;
2168    return sd->drag_y_locked;
2169 }
2170
2171 EAPI int
2172 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2173 {
2174    API_ENTRY return 0;
2175    return sd->child_drag_x_locked;
2176 }
2177
2178 EAPI int
2179 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2180 {
2181    API_ENTRY return 0;
2182    return sd->child_drag_y_locked;
2183 }
2184
2185 EAPI Eina_Bool
2186 elm_widget_theme_object_set(Evas_Object *obj,
2187                             Evas_Object *edj,
2188                             const char  *wname,
2189                             const char  *welement,
2190                             const char  *wstyle)
2191 {
2192    API_ENTRY return EINA_FALSE;
2193    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2194 }
2195
2196 EAPI Eina_Bool
2197 elm_widget_type_check(const Evas_Object *obj,
2198                       const char        *type)
2199 {
2200    const char *provided, *expected = "(unknown)";
2201    static int abort_on_warn = -1;
2202    provided = elm_widget_type_get(obj);
2203    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2204    if (type) expected = type;
2205    if ((!provided) || (!provided[0]))
2206      {
2207         provided = evas_object_type_get(obj);
2208         if ((!provided) || (!provided[0]))
2209           provided = "(unknown)";
2210      }
2211    ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
2212    if (abort_on_warn == -1)
2213      {
2214         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2215         else abort_on_warn = 0;
2216      }
2217    if (abort_on_warn == 1) abort();
2218    return EINA_FALSE;
2219 }
2220
2221 /**
2222  * @internal
2223  *
2224  * Split string in words
2225  *
2226  * @param str Source string
2227  * @return List of const words
2228  *
2229  * @see elm_widget_stringlist_free()
2230  * @ingroup Widget
2231  */
2232 EAPI Eina_List *
2233 elm_widget_stringlist_get(const char *str)
2234 {
2235    Eina_List *list = NULL;
2236    const char *s, *b;
2237    if (!str) return NULL;
2238    for (b = s = str; 1; s++)
2239      {
2240         if ((*s == ' ') || (!*s))
2241           {
2242              char *t = malloc(s - b + 1);
2243              if (t)
2244                {
2245                   strncpy(t, b, s - b);
2246                   t[s - b] = 0;
2247                   list = eina_list_append(list, eina_stringshare_add(t));
2248                   free(t);
2249                }
2250              b = s + 1;
2251           }
2252         if (!*s) break;
2253      }
2254    return list;
2255 }
2256
2257 EAPI void
2258 elm_widget_stringlist_free(Eina_List *list)
2259 {
2260    const char *s;
2261    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2262 }
2263
2264 EAPI void
2265 elm_widget_focus_hide_handle(Evas_Object *obj)
2266 {
2267    _if_focused_revert(obj, EINA_TRUE);
2268 }
2269
2270 EAPI void
2271 elm_widget_focus_mouse_down_handle(Evas_Object *obj)
2272 {
2273    Evas_Object *o = obj;
2274    do
2275      {
2276         if (_elm_widget_is(o)) break;
2277         o = evas_object_smart_parent_get(o);
2278      }
2279    while (o);
2280    if (!o) return;
2281    if (!_is_focusable(o)) return;
2282    elm_widget_focus_steal(o);
2283 }
2284
2285 /**
2286  * @internal
2287  *
2288  * Allocate a new Elm_Widget_Item-derived structure.
2289  *
2290  * The goal of this structure is to provide common ground for actions
2291  * that a widget item have, such as the owner widget, callback to
2292  * notify deletion, data pointer and maybe more.
2293  *
2294  * @param widget the owner widget that holds this item, must be an elm_widget!
2295  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2296  *        be used to allocate memory.
2297  *
2298  * @return allocated memory that is already zeroed out, or NULL on errors.
2299  *
2300  * @see elm_widget_item_new() convenience macro.
2301  * @see elm_widget_item_del() to release memory.
2302  * @ingroup Widget
2303  */
2304 EAPI Elm_Widget_Item *
2305 _elm_widget_item_new(Evas_Object *widget,
2306                      size_t       alloc_size)
2307 {
2308    if (!_elm_widget_is(widget))
2309      return NULL;
2310
2311    Elm_Widget_Item *item;
2312
2313    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2314    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2315
2316    item = calloc(1, alloc_size);
2317    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2318
2319    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2320    item->widget = widget;
2321    return item;
2322 }
2323
2324 /**
2325  * @internal
2326  *
2327  * Releases widget item memory, calling back del_cb() if it exists.
2328  *
2329  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2330  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2331  * this function and then unset it, thus being useful for 2 step
2332  * cleanup whenever the del_cb may use any of the data that must be
2333  * deleted from item.
2334  *
2335  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2336  * is presented!
2337  *
2338  * @param item a valid #Elm_Widget_Item to be deleted.
2339  * @see elm_widget_item_del() convenience macro.
2340  * @ingroup Widget
2341  */
2342 EAPI void
2343 _elm_widget_item_del(Elm_Widget_Item *item)
2344 {
2345    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2346
2347    if (item->del_cb)
2348      item->del_cb((void *)item->data, item->widget, item);
2349
2350    if (item->view)
2351      evas_object_del(item->view);
2352
2353    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2354    free(item);
2355 }
2356
2357 /**
2358  * @internal
2359  *
2360  * Notify object will be deleted without actually deleting it.
2361  *
2362  * This function will callback Elm_Widget_Item::del_cb if it is set
2363  * and then unset it so it is not called twice (ie: from
2364  * elm_widget_item_del()).
2365  *
2366  * @param item a valid #Elm_Widget_Item to be notified
2367  * @see elm_widget_item_pre_notify_del() convenience macro.
2368  * @ingroup Widget
2369  */
2370 EAPI void
2371 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2372 {
2373    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2374    if (!item->del_cb) return;
2375    item->del_cb((void *)item->data, item->widget, item);
2376    item->del_cb = NULL;
2377 }
2378
2379 /**
2380  * @internal
2381  *
2382  * Set the function to notify when item is being deleted.
2383  *
2384  * This function will complain if there was a callback set already,
2385  * however it will set the new one.
2386  *
2387  * The callback will be called from elm_widget_item_pre_notify_del()
2388  * or elm_widget_item_del() will be called with:
2389  *   - data: the Elm_Widget_Item::data value.
2390  *   - obj: the Elm_Widget_Item::widget evas object.
2391  *   - event_info: the item being deleted.
2392  *
2393  * @param item a valid #Elm_Widget_Item to be notified
2394  * @see elm_widget_item_del_cb_set() convenience macro.
2395  * @ingroup Widget
2396  */
2397 EAPI void
2398 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2399                             Evas_Smart_Cb    del_cb)
2400 {
2401    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2402
2403    if ((item->del_cb) && (item->del_cb != del_cb))
2404      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2405          item->del_cb, item, del_cb);
2406
2407    item->del_cb = del_cb;
2408 }
2409
2410 /**
2411  * @internal
2412  *
2413  * Set user-data in this item.
2414  *
2415  * User data may be used to identify this item or just store any
2416  * application data. It is automatically given as the first parameter
2417  * of the deletion notify callback.
2418  *
2419  * @param item a valid #Elm_Widget_Item to store data in.
2420  * @param data user data to store.
2421  * @see elm_widget_item_del_cb_set() convenience macro.
2422  * @ingroup Widget
2423  */
2424 EAPI void
2425 _elm_widget_item_data_set(Elm_Widget_Item *item,
2426                           const void      *data)
2427 {
2428    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2429    if ((item->data) && (item->data != data))
2430      DBG("Replacing item %p data %p with %p", item, item->data, data);
2431    item->data = data;
2432 }
2433
2434 /**
2435  * @internal
2436  *
2437  * Retrieves user-data of this item.
2438  *
2439  * @param item a valid #Elm_Widget_Item to get data from.
2440  * @see elm_widget_item_data_set()
2441  * @ingroup Widget
2442  */
2443 EAPI void *
2444 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2445 {
2446    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2447    return (void *)item->data;
2448 }
2449
2450 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2451
2452 struct _Elm_Widget_Item_Tooltip
2453 {
2454    Elm_Widget_Item            *item;
2455    Elm_Tooltip_Item_Content_Cb func;
2456    Evas_Smart_Cb               del_cb;
2457    const void                 *data;
2458 };
2459
2460 static Evas_Object *
2461 _elm_widget_item_tooltip_label_create(void        *data,
2462                                       Evas_Object *obj,
2463                                       void        *item __UNUSED__)
2464 {
2465    Evas_Object *label = elm_label_add(obj);
2466    if (!label)
2467      return NULL;
2468    elm_object_style_set(label, "tooltip");
2469    elm_object_text_set(label, data);
2470    return label;
2471 }
2472
2473 static void
2474 _elm_widget_item_tooltip_label_del_cb(void        *data,
2475                                       Evas_Object *obj __UNUSED__,
2476                                       void        *event_info __UNUSED__)
2477 {
2478    eina_stringshare_del(data);
2479 }
2480
2481 /**
2482  * @internal
2483  *
2484  * Set the text to be shown in the widget item.
2485  *
2486  * @param item Target item
2487  * @param text The text to set in the content
2488  *
2489  * Setup the text as tooltip to object. The item can have only one tooltip,
2490  * so any previous tooltip data is removed.
2491  *
2492  * @ingroup Widget
2493  */
2494 EAPI void
2495 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2496                                   const char      *text)
2497 {
2498    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2499    EINA_SAFETY_ON_NULL_RETURN(text);
2500
2501    text = eina_stringshare_add(text);
2502    _elm_widget_item_tooltip_content_cb_set
2503      (item, _elm_widget_item_tooltip_label_create, text,
2504      _elm_widget_item_tooltip_label_del_cb);
2505 }
2506
2507 static Evas_Object *
2508 _elm_widget_item_tooltip_create(void        *data,
2509                                 Evas_Object *obj)
2510 {
2511    Elm_Widget_Item_Tooltip *wit = data;
2512    return wit->func((void *)wit->data, obj, wit->item);
2513 }
2514
2515 static void
2516 _elm_widget_item_tooltip_del_cb(void        *data,
2517                                 Evas_Object *obj,
2518                                 void        *event_info __UNUSED__)
2519 {
2520    Elm_Widget_Item_Tooltip *wit = data;
2521    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
2522    free(wit);
2523 }
2524
2525 /**
2526  * @internal
2527  *
2528  * Set the content to be shown in the tooltip item
2529  *
2530  * Setup the tooltip to item. The item can have only one tooltip,
2531  * so any previous tooltip data is removed. @p func(with @p data) will
2532  * be called every time that need show the tooltip and it should
2533  * return a valid Evas_Object. This object is then managed fully by
2534  * tooltip system and is deleted when the tooltip is gone.
2535  *
2536  * @param item the widget item being attached a tooltip.
2537  * @param func the function used to create the tooltip contents.
2538  * @param data what to provide to @a func as callback data/context.
2539  * @param del_cb called when data is not needed anymore, either when
2540  *        another callback replaces @func, the tooltip is unset with
2541  *        elm_widget_item_tooltip_unset() or the owner @a item
2542  *        dies. This callback receives as the first parameter the
2543  *        given @a data, and @c event_info is the item.
2544  *
2545  * @ingroup Widget
2546  */
2547 EAPI void
2548 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
2549                                         Elm_Tooltip_Item_Content_Cb func,
2550                                         const void                 *data,
2551                                         Evas_Smart_Cb               del_cb)
2552 {
2553    Elm_Widget_Item_Tooltip *wit;
2554
2555    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
2556
2557    if (!func)
2558      {
2559         _elm_widget_item_tooltip_unset(item);
2560         return;
2561      }
2562
2563    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
2564    if (!wit) goto error;
2565    wit->item = item;
2566    wit->func = func;
2567    wit->data = data;
2568    wit->del_cb = del_cb;
2569
2570    elm_object_sub_tooltip_content_cb_set
2571      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
2572      _elm_widget_item_tooltip_del_cb);
2573
2574    return;
2575
2576 error_noitem:
2577    if (del_cb) del_cb((void *)data, NULL, item);
2578    return;
2579 error:
2580    if (del_cb) del_cb((void *)data, item->widget, item);
2581 }
2582
2583 /**
2584  * @internal
2585  *
2586  * Unset tooltip from item
2587  *
2588  * @param item widget item to remove previously set tooltip.
2589  *
2590  * Remove tooltip from item. The callback provided as del_cb to
2591  * elm_widget_item_tooltip_content_cb_set() will be called to notify
2592  * it is not used anymore.
2593  *
2594  * @see elm_widget_item_tooltip_content_cb_set()
2595  *
2596  * @ingroup Widget
2597  */
2598 EAPI void
2599 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
2600 {
2601    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2602    elm_object_tooltip_unset(item->view);
2603 }
2604
2605 /**
2606  * @internal
2607  *
2608  * Sets a different style for this item tooltip.
2609  *
2610  * @note before you set a style you should define a tooltip with
2611  *       elm_widget_item_tooltip_content_cb_set() or
2612  *       elm_widget_item_tooltip_text_set()
2613  *
2614  * @param item widget item with tooltip already set.
2615  * @param style the theme style to use (default, transparent, ...)
2616  *
2617  * @ingroup Widget
2618  */
2619 EAPI void
2620 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
2621                                    const char      *style)
2622 {
2623    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2624    elm_object_tooltip_style_set(item->view, style);
2625 }
2626
2627 /**
2628  * @internal
2629  *
2630  * Get the style for this item tooltip.
2631  *
2632  * @param item widget item with tooltip already set.
2633  * @return style the theme style in use, defaults to "default". If the
2634  *         object does not have a tooltip set, then NULL is returned.
2635  *
2636  * @ingroup Widget
2637  */
2638 EAPI const char *
2639 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
2640 {
2641    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2642    return elm_object_tooltip_style_get(item->view);
2643 }
2644
2645 EAPI void
2646 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
2647                             const char      *cursor)
2648 {
2649    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2650    elm_object_sub_cursor_set(item->view, item->widget, cursor);
2651 }
2652
2653 EAPI const char *
2654 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
2655 {
2656    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2657    return elm_object_cursor_get(item->view);
2658 }
2659
2660 EAPI void
2661 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
2662 {
2663    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2664    elm_object_cursor_unset(item->view);
2665 }
2666
2667 /**
2668  * @internal
2669  *
2670  * Sets a different style for this item cursor.
2671  *
2672  * @note before you set a style you should define a cursor with
2673  *       elm_widget_item_cursor_set()
2674  *
2675  * @param item widget item with cursor already set.
2676  * @param style the theme style to use (default, transparent, ...)
2677  *
2678  * @ingroup Widget
2679  */
2680 EAPI void
2681 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
2682                                   const char      *style)
2683 {
2684    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2685    elm_object_cursor_style_set(item->view, style);
2686 }
2687
2688 /**
2689  * @internal
2690  *
2691  * Get the style for this item cursor.
2692  *
2693  * @param item widget item with cursor already set.
2694  * @return style the theme style in use, defaults to "default". If the
2695  *         object does not have a cursor set, then NULL is returned.
2696  *
2697  * @ingroup Widget
2698  */
2699 EAPI const char *
2700 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
2701 {
2702    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2703    return elm_object_cursor_style_get(item->view);
2704 }
2705
2706 /**
2707  * @internal
2708  *
2709  * Set if the cursor set should be searched on the theme or should use
2710  * the provided by the engine, only.
2711  *
2712  * @note before you set if should look on theme you should define a cursor
2713  * with elm_object_cursor_set(). By default it will only look for cursors
2714  * provided by the engine.
2715  *
2716  * @param item widget item with cursor already set.
2717  * @param engine_only boolean to define it cursors should be looked only
2718  * between the provided by the engine or searched on widget's theme as well.
2719  *
2720  * @ingroup Widget
2721  */
2722 EAPI void
2723 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
2724                                         Eina_Bool        engine_only)
2725 {
2726    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2727    elm_object_cursor_engine_only_set(item->view, engine_only);
2728 }
2729
2730 /**
2731  * @internal
2732  *
2733  * Get the cursor engine only usage for this item cursor.
2734  *
2735  * @param item widget item with cursor already set.
2736  * @return engine_only boolean to define it cursors should be looked only
2737  * between the provided by the engine or searched on widget's theme as well. If
2738  *         the object does not have a cursor set, then EINA_FALSE is returned.
2739  *
2740  * @ingroup Widget
2741  */
2742 EAPI Eina_Bool
2743 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
2744 {
2745    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2746    return elm_object_cursor_engine_only_get(item->view);
2747 }
2748
2749 // smart object funcs
2750 static void
2751 _smart_reconfigure(Smart_Data *sd)
2752 {
2753    if (sd->resize_obj)
2754      {
2755         evas_object_move(sd->resize_obj, sd->x, sd->y);
2756         evas_object_resize(sd->resize_obj, sd->w, sd->h);
2757      }
2758    if (sd->hover_obj)
2759      {
2760         evas_object_move(sd->hover_obj, sd->x, sd->y);
2761         evas_object_resize(sd->hover_obj, sd->w, sd->h);
2762      }
2763 }
2764
2765 static void
2766 _smart_add(Evas_Object *obj)
2767 {
2768    Smart_Data *sd;
2769
2770    sd = calloc(1, sizeof(Smart_Data));
2771    if (!sd) return;
2772    sd->obj = obj;
2773    sd->x = sd->y = sd->w = sd->h = 0;
2774    sd->can_focus = 1;
2775    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
2776    evas_object_smart_data_set(obj, sd);
2777 }
2778
2779 static Evas_Object *
2780 _newest_focus_order_get(Evas_Object  *obj,
2781                         unsigned int *newest_focus_order,
2782                         Eina_Bool     can_focus_only)
2783 {
2784    const Eina_List *l;
2785    Evas_Object *child, *ret, *best;
2786
2787    API_ENTRY return NULL;
2788    if (!evas_object_visible_get(obj)) return NULL;
2789    best = NULL;
2790    if (*newest_focus_order < sd->focus_order)
2791      {
2792         *newest_focus_order = sd->focus_order;
2793         best = obj;
2794      }
2795    EINA_LIST_FOREACH(sd->subobjs, l, child)
2796      {
2797         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
2798         if (!ret) continue;
2799         best = ret;
2800      }
2801    if (can_focus_only)
2802      {
2803         if ((!best) || (!elm_widget_can_focus_get(best)))
2804           return NULL;
2805      }
2806    return best;
2807 }
2808
2809 static void
2810 _if_focused_revert(Evas_Object *obj,
2811                    Eina_Bool    can_focus_only)
2812 {
2813    Evas_Object *top;
2814    Evas_Object *newest = NULL;
2815    unsigned int newest_focus_order = 0;
2816
2817    INTERNAL_ENTRY
2818
2819    if (!sd->focused) return;
2820    if (!sd->parent_obj) return;
2821
2822    top = elm_widget_top_get(sd->parent_obj);
2823    if (top)
2824      {
2825         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
2826         if (newest)
2827           {
2828              elm_object_unfocus(newest);
2829              elm_object_focus(newest);
2830           }
2831      }
2832 }
2833
2834 static void
2835 _smart_del(Evas_Object *obj)
2836 {
2837    Evas_Object *sobj;
2838    Edje_Signal_Data *esd;
2839
2840    INTERNAL_ENTRY
2841
2842    if (sd->del_pre_func) sd->del_pre_func(obj);
2843    if (sd->resize_obj)
2844      {
2845         sobj = sd->resize_obj;
2846         sd->resize_obj = NULL;
2847         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2848         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2849         evas_object_del(sobj);
2850      }
2851    if (sd->hover_obj)
2852      {
2853         sobj = sd->hover_obj;
2854         sd->hover_obj = NULL;
2855         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2856         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2857         evas_object_del(sobj);
2858      }
2859    EINA_LIST_FREE(sd->subobjs, sobj)
2860      {
2861         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2862         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2863         evas_object_del(sobj);
2864      }
2865    eina_list_free(sd->tooltips); /* should be empty anyway */
2866    eina_list_free(sd->cursors); /* should be empty anyway */
2867    EINA_LIST_FREE(sd->edje_signals, esd)
2868      {
2869         eina_stringshare_del(esd->emission);
2870         eina_stringshare_del(esd->source);
2871         free(esd);
2872      }
2873    eina_list_free(sd->event_cb); /* should be empty anyway */
2874    if (sd->del_func) sd->del_func(obj);
2875    if (sd->style) eina_stringshare_del(sd->style);
2876    if (sd->type) eina_stringshare_del(sd->type);
2877    if (sd->theme) elm_theme_free(sd->theme);
2878    _if_focused_revert(obj, EINA_TRUE);
2879    free(sd);
2880 }
2881
2882 static void
2883 _smart_move(Evas_Object *obj,
2884             Evas_Coord   x,
2885             Evas_Coord   y)
2886 {
2887    INTERNAL_ENTRY
2888    sd->x = x;
2889    sd->y = y;
2890    _smart_reconfigure(sd);
2891 }
2892
2893 static void
2894 _smart_resize(Evas_Object *obj,
2895               Evas_Coord   w,
2896               Evas_Coord   h)
2897 {
2898    INTERNAL_ENTRY
2899    sd->w = w;
2900    sd->h = h;
2901    _smart_reconfigure(sd);
2902 }
2903
2904 static void
2905 _smart_show(Evas_Object *obj)
2906 {
2907    Eina_List *list;
2908    Evas_Object *o;
2909    INTERNAL_ENTRY
2910    if ((list = evas_object_smart_members_get(obj)))
2911      {
2912         EINA_LIST_FREE(list, o)
2913           {
2914              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2915              evas_object_show(o);
2916           }
2917      }
2918 }
2919
2920 static void
2921 _smart_hide(Evas_Object *obj)
2922 {
2923    Eina_List *list;
2924    Evas_Object *o;
2925    INTERNAL_ENTRY
2926
2927    list = evas_object_smart_members_get(obj);
2928    EINA_LIST_FREE(list, o)
2929      {
2930         if (evas_object_data_get(o, "_elm_leaveme")) continue;
2931         evas_object_hide(o);
2932      }
2933 }
2934
2935 static void
2936 _smart_color_set(Evas_Object *obj,
2937                  int          r,
2938                  int          g,
2939                  int          b,
2940                  int          a)
2941 {
2942    Eina_List *list;
2943    Evas_Object *o;
2944    INTERNAL_ENTRY
2945    if ((list = evas_object_smart_members_get(obj)))
2946      {
2947         EINA_LIST_FREE(list, o)
2948           {
2949              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2950              evas_object_color_set(o, r, g, b, a);
2951           }
2952      }
2953 }
2954
2955 static void
2956 _smart_clip_set(Evas_Object *obj,
2957                 Evas_Object *clip)
2958 {
2959    Eina_List *list;
2960    Evas_Object *o;
2961    INTERNAL_ENTRY
2962    if ((list = evas_object_smart_members_get(obj)))
2963      {
2964         EINA_LIST_FREE(list, o)
2965           {
2966              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2967              evas_object_clip_set(o, clip);
2968           }
2969      }
2970 }
2971
2972 static void
2973 _smart_clip_unset(Evas_Object *obj)
2974 {
2975    Eina_List *list;
2976    Evas_Object *o;
2977    INTERNAL_ENTRY
2978    if ((list = evas_object_smart_members_get(obj)))
2979      {
2980         EINA_LIST_FREE(list, o)
2981           {
2982              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2983              evas_object_clip_unset(o);
2984           }
2985      }
2986 }
2987
2988 static void
2989 _smart_calculate(Evas_Object *obj)
2990 {
2991    INTERNAL_ENTRY
2992    if (sd->changed_func) sd->changed_func(obj);
2993 }
2994
2995 /* never need to touch this */
2996 static void
2997 _smart_init(void)
2998 {
2999    if (_e_smart) return;
3000    {
3001       static const Evas_Smart_Class sc =
3002       {
3003          SMART_NAME,
3004          EVAS_SMART_CLASS_VERSION,
3005          _smart_add,
3006          _smart_del,
3007          _smart_move,
3008          _smart_resize,
3009          _smart_show,
3010          _smart_hide,
3011          _smart_color_set,
3012          _smart_clip_set,
3013          _smart_clip_unset,
3014          _smart_calculate,
3015          NULL,
3016          NULL,
3017          NULL,
3018          NULL,
3019          NULL,
3020          NULL
3021       };
3022       _e_smart = evas_smart_class_new(&sc);
3023    }
3024 }
3025
3026 /* happy debug functions */
3027 #ifdef ELM_DEBUG
3028 static void
3029 _sub_obj_tree_dump(const Evas_Object *obj,
3030                    int                lvl)
3031 {
3032    int i;
3033
3034    for (i = 0; i < lvl * 3; i++)
3035      putchar(' ');
3036
3037    if (_elm_widget_is(obj))
3038      {
3039         Eina_List *l;
3040         INTERNAL_ENTRY
3041         printf("+ %s(%p)\n",
3042                sd->type,
3043                obj);
3044         if (sd->resize_obj)
3045           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3046         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3047           {
3048              if (obj != sd->resize_obj)
3049                _sub_obj_tree_dump(obj, lvl + 1);
3050           }
3051      }
3052    else
3053      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3054 }
3055
3056 static void
3057 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3058                        FILE              *output)
3059 {
3060    if (!_elm_widget_is(obj))
3061      return;
3062    INTERNAL_ENTRY
3063
3064    Eina_Bool visible = evas_object_visible_get(obj);
3065    Eina_Bool disabled = elm_widget_disabled_get(obj);
3066    Eina_Bool focused = elm_widget_focus_get(obj);
3067    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3068
3069    if (sd->parent_obj)
3070      {
3071         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3072
3073         if (focused)
3074           fprintf(output, ", style=bold");
3075
3076         if (!visible)
3077           fprintf(output, ", color=gray28");
3078
3079         fprintf(output, " ];\n");
3080      }
3081
3082    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3083                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3084            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3085            sd->focus_order);
3086
3087    if (focused)
3088      fprintf(output, ", style=bold");
3089
3090    if (!visible)
3091      fprintf(output, ", fontcolor=gray28");
3092
3093    if ((disabled) || (!visible))
3094      fprintf(output, ", color=gray");
3095
3096    fprintf(output, " ];\n");
3097
3098    Eina_List *l;
3099    Evas_Object *o;
3100    EINA_LIST_FOREACH(sd->subobjs, l, o)
3101      _sub_obj_tree_dot_dump(o, output);
3102 }
3103 #endif
3104
3105 EAPI void
3106 elm_widget_tree_dump(const Evas_Object *top)
3107 {
3108 #ifdef ELM_DEBUG
3109    _sub_obj_tree_dump(top, 0);
3110 #else
3111    return;
3112    (void)top;
3113 #endif
3114 }
3115
3116 EAPI void
3117 elm_widget_tree_dot_dump(const Evas_Object *top,
3118                          FILE              *output)
3119 {
3120 #ifdef ELM_DEBUG
3121    if (!_elm_widget_is(top))
3122      return;
3123    fprintf(output, "graph " " { node [shape=record];\n");
3124    _sub_obj_tree_dot_dump(top, output);
3125    fprintf(output, "}\n");
3126 #else
3127    return;
3128    (void)top;
3129    (void)output;
3130 #endif
3131 }