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