send a signal to set theme according to orientation mode when a widget is created
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_container.h"
4 #include "elm_interface_scrollable.h"
5
6 static const char ELM_WIDGET_SMART_NAME[] = "elm_widget";
7
8 #define API_ENTRY                                               \
9   Elm_Widget_Smart_Data * sd = evas_object_smart_data_get(obj); \
10   if ((!sd) || (!_elm_widget_is(obj)))
11 #define INTERNAL_ENTRY                                          \
12   Elm_Widget_Smart_Data * sd = evas_object_smart_data_get(obj); \
13   if (!sd)                                                      \
14     return
15
16 #define ELM_WIDGET_FOCUS_GET(obj)                                    \
17   ((_elm_access_read_mode_get()) ? (elm_widget_highlight_get(obj)) : \
18                                   (elm_widget_focus_get(obj)))
19 typedef struct _Elm_Event_Cb_Data         Elm_Event_Cb_Data;
20 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
21
22 struct _Elm_Event_Cb_Data
23 {
24    Elm_Event_Cb func;
25    const void  *data;
26 };
27
28 struct _Elm_Translate_String_Data
29 {
30    const char *id;
31    const char *domain;
32    const char *string;
33 };
34
35 /* local subsystem globals */
36 static unsigned int focus_order = 0;
37
38 static inline Eina_Bool
39 _elm_widget_is(const Evas_Object *obj)
40 {
41    return evas_object_smart_type_check_ptr(obj, ELM_WIDGET_SMART_NAME);
42 }
43
44 static inline Eina_Bool
45 _is_focusable(Evas_Object *obj)
46 {
47    API_ENTRY return EINA_FALSE;
48    return sd->can_focus || (sd->child_can_focus);
49 }
50
51 static inline Eina_Bool
52 _elm_scrollable_is(const Evas_Object *obj)
53 {
54    INTERNAL_ENTRY EINA_FALSE;
55    return !!evas_object_smart_interface_get(obj, ELM_SCROLLABLE_IFACE_NAME);
56 }
57
58 /* what follows are basic (unimplemented) smart class functions */
59 #define UNIMPLEMENTED_MAKE(_prefix)                                         \
60   static Eina_Bool                                                          \
61   _elm_widget_##_prefix##_func_unimplemented(Evas_Object * obj)             \
62   {                                                                         \
63      WRN("The %s widget does not implement the \"" #_prefix "\" function.", \
64          elm_widget_type_get(obj));                                         \
65      return EINA_FALSE;                                                     \
66   }
67
68 UNIMPLEMENTED_MAKE(disable);
69 UNIMPLEMENTED_MAKE(translate);
70
71 #undef UNIMPLEMENTED_MAKE
72
73 /**
74  * @internal
75  * Resets the mirrored mode from the system mirror mode for widgets that are in
76  * automatic mirroring mode. This function does not call elm_widget_theme.
77  *
78  * @param obj The widget.
79  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
80  */
81 static void
82 _elm_widget_mirrored_reload(Evas_Object *obj)
83 {
84    API_ENTRY return;
85    Eina_Bool mirrored = elm_config_mirrored_get();
86
87    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
88      {
89         sd->is_mirrored = mirrored;
90      }
91 }
92
93 static Eina_Bool
94 _elm_widget_theme_func(Evas_Object *obj)
95 {
96    _elm_widget_mirrored_reload(obj);
97
98    elm_widget_disabled_set(obj, elm_widget_disabled_get(obj));
99
100    return EINA_TRUE;
101 }
102
103 static Eina_Bool
104 _elm_widget_on_focus_region_func_unimplemented(const Evas_Object *obj __UNUSED__,
105                                                Evas_Coord *x __UNUSED__,
106                                                Evas_Coord *y __UNUSED__,
107                                                Evas_Coord *w __UNUSED__,
108                                                Evas_Coord *h __UNUSED__)
109 {
110    WRN("The %s widget does not implement the \"on_focus_region\" function.",
111        elm_widget_type_get(obj));
112    return EINA_FALSE;
113 }
114
115 static Eina_Bool
116 _elm_widget_on_focus_func_unimplemented(Evas_Object *obj)
117 {
118    WRN("The %s widget does not implement the \"on_focus\" function.",
119        elm_widget_type_get(obj));
120    return EINA_FALSE;
121 }
122
123 static Eina_Bool
124 _elm_widget_event_func_unimplemented(Evas_Object *obj,
125                                      Evas_Object *source __UNUSED__,
126                                      Evas_Callback_Type type __UNUSED__,
127                                      void *event_info __UNUSED__)
128 {
129    WRN("The %s widget does not implement the \"event\" function.",
130        elm_widget_type_get(obj));
131    return EINA_FALSE;
132 }
133
134 static Eina_Bool
135 _elm_widget_focus_next_func_unimplemented(const Evas_Object *obj,
136                                           Elm_Focus_Direction dir __UNUSED__,
137                                           Evas_Object **next __UNUSED__)
138 {
139    WRN("The %s widget does not implement the \"focus_next\" function.",
140        elm_widget_type_get(obj));
141    return EINA_FALSE;
142 }
143
144 static Eina_Bool
145 _elm_widget_focus_direction_func_unimplemented(const Evas_Object *obj,
146                                                const Evas_Object *b __UNUSED__,
147                                                double degree __UNUSED__,
148                                                Evas_Object **target __UNUSED__,
149                                                double *weight __UNUSED__)
150 {
151    WRN("The %s widget does not implement the \"focus_direction\" function.",
152        elm_widget_type_get(obj));
153    return EINA_FALSE;
154 }
155
156 static void
157 _parents_focus(Evas_Object *obj)
158 {
159    for (; obj; obj = elm_widget_parent_get(obj))
160      {
161         INTERNAL_ENTRY;
162         if (sd->focused) return;
163         sd->focused = 1;
164      }
165 }
166
167 static void
168 _parents_unfocus(Evas_Object *obj)
169 {
170    for (; obj; obj = elm_widget_parent_get(obj))
171      {
172         INTERNAL_ENTRY;
173         if (!sd->focused) return;
174         sd->focused = 0;
175      }
176 }
177
178 static void
179 _on_sub_obj_hide(void *data __UNUSED__,
180               Evas *e __UNUSED__,
181               Evas_Object *obj,
182               void *event_info __UNUSED__)
183 {
184    elm_widget_focus_hide_handle(obj);
185 }
186
187 static void
188 _on_sub_obj_del(void *data,
189              Evas *e __UNUSED__,
190              Evas_Object *obj,
191              void *event_info __UNUSED__)
192 {
193    Elm_Widget_Smart_Data *sd = data;
194
195    if (_elm_widget_is(obj))
196      {
197         if (elm_widget_focus_get(obj)) _parents_unfocus(sd->obj);
198      }
199    if (obj == sd->resize_obj)
200      {
201         /* already dels sub object */
202         elm_widget_resize_object_set(sd->obj, NULL);
203         return;
204      }
205    else if (obj == sd->hover_obj)
206      {
207         sd->hover_obj = NULL;
208         return;
209      }
210    else
211      {
212         if (!elm_widget_sub_object_del(sd->obj, obj))
213           ERR("failed to remove sub object %p from %p\n", obj, sd->obj);
214      }
215 }
216
217 static Eina_Bool
218 _elm_widget_sub_object_add_func(Evas_Object *obj,
219                                 Evas_Object *sobj)
220 {
221    double scale, pscale = elm_widget_scale_get(sobj);
222    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
223    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
224
225    ELM_WIDGET_DATA_GET(obj, sd);
226    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
227
228    if (sobj == sd->parent_obj)
229      {
230         /* in this case, sobj must be an elm widget, or something
231          * very wrong is happening */
232         if (!_elm_widget_is(sobj)) return EINA_FALSE;
233
234         if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
235         WRN("You passed a parent object of obj = %p as the sub object = %p!",
236             obj, sobj);
237      }
238
239    if (_elm_widget_is(sobj))
240      {
241         ELM_WIDGET_DATA_GET(sobj, sdc);
242
243         if (sdc->parent_obj == obj) return EINA_TRUE;
244         if (sdc->parent_obj)
245           {
246              if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
247                return EINA_FALSE;
248           }
249         sdc->parent_obj = obj;
250         sdc->orient_mode = sd->orient_mode;
251         _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
252
253         /* update child focusable-ness on self and parents, now that a
254          * focusable child got in */
255         if (!sd->child_can_focus && (_is_focusable(sobj)))
256           {
257              Elm_Widget_Smart_Data *sdp = sd;
258
259              sdp->child_can_focus = EINA_TRUE;
260              while (sdp->parent_obj)
261                {
262                   sdp = evas_object_smart_data_get(sdp->parent_obj);
263
264                   if (sdp->child_can_focus) break;
265
266                   sdp->child_can_focus = EINA_TRUE;
267                }
268           }
269      }
270    else
271      {
272         void *data = evas_object_data_get(sobj, "elm-parent");
273
274         if (data)
275           {
276              if (data == obj) return EINA_TRUE;
277              if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
278           }
279      }
280
281    sd->subobjs = eina_list_append(sd->subobjs, sobj);
282    evas_object_data_set(sobj, "elm-parent", obj);
283    evas_object_event_callback_add
284      (sobj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
285    if (_elm_widget_is(sobj))
286      {
287         evas_object_event_callback_add
288           (sobj, EVAS_CALLBACK_HIDE, _on_sub_obj_hide, sd);
289
290         scale = elm_widget_scale_get(sobj);
291         th = elm_widget_theme_get(sobj);
292         mirrored = elm_widget_mirrored_get(sobj);
293
294         if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
295           elm_widget_theme(sobj);
296
297         if (elm_widget_focus_get(sobj)) _parents_focus(obj);
298      }
299
300    return EINA_TRUE;
301 }
302
303 static Eina_Bool
304 _elm_widget_sub_object_del_func(Evas_Object *obj,
305                                 Evas_Object *sobj)
306 {
307    Evas_Object *sobj_parent;
308
309    if (!sobj) return EINA_FALSE;
310
311    ELM_WIDGET_DATA_GET(obj, sd);
312    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
313
314    sobj_parent = evas_object_data_del(sobj, "elm-parent");
315    if (sobj_parent != obj)
316      {
317         static int abort_on_warn = -1;
318
319         ERR("removing sub object %p (%s) from parent %p (%s), "
320             "but elm-parent is different %p (%s)!",
321             sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
322             sobj_parent, elm_widget_type_get(sobj_parent));
323
324         if (EINA_UNLIKELY(abort_on_warn == -1))
325           {
326              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
327              else abort_on_warn = 0;
328           }
329         if (abort_on_warn == 1) abort();
330
331         return EINA_FALSE;
332      }
333
334    if (_elm_widget_is(sobj))
335      {
336         if (elm_widget_focus_get(sobj))
337           {
338              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
339              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
340           }
341         if ((sd->child_can_focus) && (_is_focusable(sobj)))
342           {
343              Evas_Object *parent = obj;
344
345              /* update child focusable-ness on self and parents, now that a
346               * focusable child is gone */
347              while (parent)
348                {
349                   const Eina_List *l;
350                   Evas_Object *subobj;
351
352                   ELM_WIDGET_DATA_GET(parent, sdp);
353
354                   sdp->child_can_focus = EINA_FALSE;
355                   EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
356                     {
357                        if ((subobj != sobj) && (_is_focusable(subobj)))
358                          {
359                             sdp->child_can_focus = EINA_TRUE;
360                             break;
361                          }
362                     }
363
364                   /* break again, child_can_focus went back to
365                    * original value */
366                   if (sdp->child_can_focus) break;
367                   parent = sdp->parent_obj;
368                }
369           }
370
371         ELM_WIDGET_DATA_GET(sobj, sdc);
372         sdc->parent_obj = NULL;
373      }
374
375    if (sd->resize_obj == sobj) sd->resize_obj = NULL;
376
377    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
378
379    evas_object_event_callback_del_full
380      (sobj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
381    if (_elm_widget_is(sobj))
382      evas_object_event_callback_del_full
383        (sobj, EVAS_CALLBACK_HIDE, _on_sub_obj_hide, sd);
384
385    return EINA_TRUE;
386 }
387
388 static const Evas_Smart_Cb_Description _smart_callbacks[] =
389 {
390    /* FIXME: complete later */
391    {NULL, NULL}
392 };
393
394 static void
395 _smart_add(Evas_Object *obj)
396 {
397    const Evas_Smart_Class *sc;
398    const Evas_Smart *smart;
399
400    EVAS_SMART_DATA_ALLOC(obj, Elm_Widget_Smart_Data);
401
402    smart = evas_object_smart_smart_get(obj);
403    sc = evas_smart_class_get(smart);
404    priv->api = (const Elm_Widget_Smart_Class *)sc;
405    priv->obj = obj;
406    priv->x = priv->y = priv->w = priv->h = 0;
407    priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
408                                           * settings */
409    elm_widget_can_focus_set(obj, EINA_TRUE);
410    elm_widget_mirrored_set(obj, elm_config_mirrored_get());
411
412    /* just a helper for inheriting classes */
413    if (priv->resize_obj)
414      {
415         Evas_Object *r_obj = priv->resize_obj;
416         priv->resize_obj = NULL;
417
418         elm_widget_resize_object_set(obj, r_obj);
419      }
420 }
421
422
423 static void
424 _if_focused_revert(Evas_Object *obj,
425                    Eina_Bool can_focus_only)
426 {
427    Evas_Object *top;
428    Evas_Object *newest = NULL;
429    unsigned int newest_focus_order = 0;
430
431    INTERNAL_ENTRY;
432
433    if (!sd->focused) return;
434    if (!sd->parent_obj) return;
435
436    top = elm_widget_top_get(sd->parent_obj);
437    if (top)
438      {
439         newest = elm_widget_newest_focus_order_get
440            (top, &newest_focus_order, can_focus_only);
441         if (newest)
442           {
443              elm_object_focus_set(newest, EINA_FALSE);
444              elm_object_focus_set(newest, EINA_TRUE);
445           }
446      }
447 }
448
449 static void
450 _smart_del(Evas_Object *obj)
451 {
452    Evas_Object *sobj;
453    Elm_Translate_String_Data *ts;
454    Elm_Event_Cb_Data *ecb;
455
456    ELM_WIDGET_DATA_GET(obj, sd);
457
458    if (sd->hover_obj)
459      {
460         /* detach it from us */
461         evas_object_event_callback_del_full
462           (sd->hover_obj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
463         sd->hover_obj = NULL;
464      }
465
466    while (sd->subobjs)
467      {
468         sobj = eina_list_data_get(sd->subobjs);
469
470         /* let the objects clean-up themselves and get rid of this list */
471         if (!elm_widget_sub_object_del(obj, sobj))
472           {
473              ERR("failed to remove sub object %p from %p\n", sobj, obj);
474              sd->subobjs = eina_list_remove_list
475                  (sd->subobjs, sd->subobjs);
476           }
477         evas_object_del(sobj);
478      }
479    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
480    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
481    EINA_LIST_FREE (sd->translate_strings, ts)
482      {
483         eina_stringshare_del(ts->id);
484         eina_stringshare_del(ts->domain);
485         eina_stringshare_del(ts->string);
486         free(ts);
487      }
488
489    EINA_LIST_FREE (sd->event_cb, ecb)
490      free(ecb);
491
492    if (sd->style) eina_stringshare_del(sd->style);
493    if (sd->theme) elm_theme_free(sd->theme);
494    _if_focused_revert(obj, EINA_TRUE);
495    if (sd->access_info) eina_stringshare_del(sd->access_info);
496    free(sd);
497    evas_object_smart_data_set(obj, NULL);
498 }
499
500 static void
501 _smart_reconfigure(Elm_Widget_Smart_Data *sd)
502 {
503    if (sd->resize_obj)
504      {
505         evas_object_move(sd->resize_obj, sd->x, sd->y);
506         evas_object_resize(sd->resize_obj, sd->w, sd->h);
507      }
508    if (sd->hover_obj)
509      {
510         evas_object_move(sd->hover_obj, sd->x, sd->y);
511         evas_object_resize(sd->hover_obj, sd->w, sd->h);
512      }
513 }
514
515 static void
516 _smart_move(Evas_Object *obj,
517             Evas_Coord x,
518             Evas_Coord y)
519 {
520    ELM_WIDGET_DATA_GET(obj, sd);
521
522    sd->x = x;
523    sd->y = y;
524
525    _smart_reconfigure(sd);
526 }
527
528 static void
529 _smart_resize(Evas_Object *obj,
530               Evas_Coord w,
531               Evas_Coord h)
532 {
533    ELM_WIDGET_DATA_GET(obj, sd);
534
535    sd->w = w;
536    sd->h = h;
537
538    _smart_reconfigure(sd);
539 }
540
541 static void
542 _smart_show(Evas_Object *obj)
543 {
544    Eina_List *list;
545    Evas_Object *o;
546
547    if ((list = evas_object_smart_members_get(obj)))
548      {
549         EINA_LIST_FREE (list, o)
550           {
551              if (evas_object_data_get(o, "_elm_leaveme")) continue;
552              evas_object_show(o);
553           }
554      }
555 }
556
557 static void
558 _smart_hide(Evas_Object *obj)
559 {
560    Eina_List *list;
561    Evas_Object *o;
562
563    list = evas_object_smart_members_get(obj);
564    EINA_LIST_FREE (list, o)
565      {
566         if (evas_object_data_get(o, "_elm_leaveme")) continue;
567         evas_object_hide(o);
568      }
569 }
570
571 static void
572 _smart_color_set(Evas_Object *obj,
573                  int r,
574                  int g,
575                  int b,
576                  int a)
577 {
578    Eina_List *list;
579    Evas_Object *o;
580
581    if ((list = evas_object_smart_members_get(obj)))
582      {
583         EINA_LIST_FREE (list, o)
584           {
585              if (evas_object_data_get(o, "_elm_leaveme")) continue;
586              evas_object_color_set(o, r, g, b, a);
587           }
588      }
589 }
590
591 static void
592 _smart_clip_set(Evas_Object *obj,
593                 Evas_Object *clip)
594 {
595    Eina_List *list;
596    Evas_Object *o;
597
598    if ((list = evas_object_smart_members_get(obj)))
599      {
600         EINA_LIST_FREE (list, o)
601           {
602              if (evas_object_data_get(o, "_elm_leaveme")) continue;
603              evas_object_clip_set(o, clip);
604           }
605      }
606 }
607
608 static void
609 _smart_clip_unset(Evas_Object *obj)
610 {
611    Eina_List *list;
612    Evas_Object *o;
613
614    if ((list = evas_object_smart_members_get(obj)))
615      {
616         EINA_LIST_FREE (list, o)
617           {
618              if (evas_object_data_get(o, "_elm_leaveme")) continue;
619              evas_object_clip_unset(o);
620           }
621      }
622 }
623
624 static void
625 _smart_calculate(Evas_Object *obj __UNUSED__)
626 {
627    /* a NO-OP, on the base */
628 }
629
630 static void
631 _smart_member_add(Evas_Object *obj,
632                   Evas_Object *child)
633 {
634    int r, g, b, a;
635
636    if (evas_object_data_get(child, "_elm_leaveme")) return;
637
638    evas_object_color_get(obj, &r, &g, &b, &a);
639    evas_object_color_set(child, r, g, b, a);
640
641    evas_object_clip_set(child, evas_object_clip_get(obj));
642
643    if (evas_object_visible_get(obj))
644      evas_object_show(child);
645    else
646      evas_object_hide(child);
647 }
648
649 static void
650 _smart_member_del(Evas_Object *obj __UNUSED__,
651                   Evas_Object *child)
652 {
653    if (evas_object_data_get(child, "_elm_leaveme")) return;
654    evas_object_clip_unset(child);
655 }
656
657 static void
658 _elm_widget_smart_set(Elm_Widget_Smart_Class *api)
659 {
660    Evas_Smart_Class *sc;
661
662    if (!(sc = (Evas_Smart_Class *)api))
663      return;
664
665    sc->add = _smart_add;
666    sc->del = _smart_del;
667    sc->move = _smart_move;
668    sc->resize = _smart_resize;
669    sc->show = _smart_show;
670    sc->hide = _smart_hide;
671    sc->color_set = _smart_color_set;
672    sc->clip_set = _smart_clip_set;
673    sc->clip_unset = _smart_clip_unset;
674    sc->calculate = _smart_calculate;
675    sc->member_add = _smart_member_add;
676    sc->member_del = _smart_member_del;
677
678 #define API_DEFAULT_SET_UNIMPLEMENTED(_prefix) \
679   api->_prefix = _elm_widget_##_prefix##_func_unimplemented;
680
681    /* NB: always remember to call these parent versions on children,
682     * except for the unimplemented ones and calculate, which is moot */
683
684 #define API_DEFAULT_SET(_prefix) \
685   api->_prefix = _elm_widget_##_prefix##_func;
686
687    /* base api */
688    API_DEFAULT_SET_UNIMPLEMENTED(on_focus);
689    API_DEFAULT_SET_UNIMPLEMENTED(disable);
690
691    API_DEFAULT_SET(theme);
692    API_DEFAULT_SET_UNIMPLEMENTED(on_focus_region);
693
694    API_DEFAULT_SET_UNIMPLEMENTED(translate);
695    API_DEFAULT_SET_UNIMPLEMENTED(event);
696    API_DEFAULT_SET_UNIMPLEMENTED(focus_next);
697    API_DEFAULT_SET_UNIMPLEMENTED(focus_direction);
698
699    /* NB: because those two weren't hooks before, translate the
700     * individual calls to them on the widgets as we bring them to the
701     * new class hierarchy. also, sub_object_{add,del} must be
702     * different than member_{add,del} here, because widget parenting
703     * on elm does not always imply parent and child will live on the
704     * same Evas layer */
705    API_DEFAULT_SET(sub_object_add);
706    API_DEFAULT_SET(sub_object_del);
707
708 #undef API_DEFAULT_SET
709 #undef API_DEFAULT_SET_UNIMPLEMENTED
710
711    sc->callbacks = _smart_callbacks;
712 }
713
714 // internal funcs
715 static inline Eina_Bool
716 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
717 {
718    API_ENTRY return EINA_FALSE;
719
720    if (!sd->api) return EINA_FALSE;
721    return sd->api->focus_next &&
722           (sd->api->focus_next != _elm_widget_focus_next_func_unimplemented);
723 }
724
725 static inline Eina_Bool
726 _elm_widget_focus_direction_manager_is(const Evas_Object *obj)
727 {
728    API_ENTRY return EINA_FALSE;
729
730    if (!sd->api) return EINA_FALSE;
731    return sd->api->focus_direction &&
732           (sd->api->focus_direction !=
733            _elm_widget_focus_direction_func_unimplemented);
734 }
735
736 static void
737 _obj_mouse_down(void *data,
738                 Evas *e __UNUSED__,
739                 Evas_Object *obj __UNUSED__,
740                 void *event_info)
741 {
742    Elm_Widget_Smart_Data *sd = data;
743    Evas_Event_Mouse_Down *ev = event_info;
744    if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
745      sd->still_in = EINA_TRUE;
746 }
747
748 static void
749 _obj_mouse_move(void *data,
750                 Evas *e __UNUSED__,
751                 Evas_Object *obj,
752                 void *event_info)
753 {
754    Elm_Widget_Smart_Data *sd = data;
755    Evas_Event_Mouse_Move *ev = event_info;
756    if (sd->still_in)
757      {
758         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
759           sd->still_in = EINA_FALSE;
760         else
761           {
762              Evas_Coord x, y, w, h;
763              evas_object_geometry_get(obj, &x, &y, &w, &h);
764              if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
765                  (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
766                sd->still_in = EINA_FALSE;
767           }
768      }
769 }
770
771 static void
772 _obj_mouse_up(void *data,
773               Evas *e __UNUSED__,
774               Evas_Object *obj,
775               void *event_info __UNUSED__)
776 {
777    Elm_Widget_Smart_Data *sd = data;
778    if (sd->still_in)
779      elm_widget_focus_mouse_up_handle(obj);
780    sd->still_in = EINA_FALSE;
781 }
782
783 static void
784 _propagate_x_drag_lock(Evas_Object *obj,
785                        int dir)
786 {
787    INTERNAL_ENTRY;
788    if (sd->parent_obj)
789      {
790         Elm_Widget_Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
791         if (sd2)
792           {
793              sd2->child_drag_x_locked += dir;
794              _propagate_x_drag_lock(sd->parent_obj, dir);
795           }
796      }
797 }
798
799 static void
800 _propagate_y_drag_lock(Evas_Object *obj,
801                        int dir)
802 {
803    INTERNAL_ENTRY;
804    if (sd->parent_obj)
805      {
806         Elm_Widget_Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
807         if (sd2)
808           {
809              sd2->child_drag_y_locked += dir;
810              _propagate_y_drag_lock(sd->parent_obj, dir);
811           }
812      }
813 }
814
815 static void
816 _propagate_event(void *data,
817                  Evas *e __UNUSED__,
818                  Evas_Object *obj,
819                  void *event_info)
820 {
821    INTERNAL_ENTRY;
822    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
823    Evas_Event_Flags *event_flags = NULL;
824
825    switch (type)
826      {
827       case EVAS_CALLBACK_KEY_DOWN:
828       {
829          Evas_Event_Key_Down *ev = event_info;
830          event_flags = &(ev->event_flags);
831       }
832       break;
833
834       case EVAS_CALLBACK_KEY_UP:
835       {
836          Evas_Event_Key_Up *ev = event_info;
837          event_flags = &(ev->event_flags);
838       }
839       break;
840
841       case EVAS_CALLBACK_MOUSE_WHEEL:
842       {
843          Evas_Event_Mouse_Wheel *ev = event_info;
844          event_flags = &(ev->event_flags);
845       }
846       break;
847
848       default:
849         break;
850      }
851
852    elm_widget_event_propagate(obj, type, event_info, event_flags);
853 }
854
855 /**
856  * If elm_widget_focus_region_get() returns EINA_FALSE, this function will
857  * ignore region show action.
858  */
859 static void
860 _elm_widget_focus_region_show(const Evas_Object *obj)
861 {
862    Evas_Coord x, y, ox, oy, w, h;
863    Evas_Object *o;
864
865    API_ENTRY return;
866
867    o = elm_widget_parent_get(obj);
868    if (!o) return;
869
870    if (!elm_widget_focus_region_get(obj, &x, &y, NULL, NULL))
871      return;
872
873    evas_object_geometry_get(obj, &ox, &oy, &w, &h);
874    if (w == 0 && h == 0) return;
875
876    while (o)
877      {
878         if (_elm_scrollable_is(o))
879           {
880              Evas_Coord px, py, pw, ph;
881              Evas_Coord rx, ry;
882
883              evas_object_geometry_get(o, &px, &py, &pw, &ph);
884
885              if ((px <= ox) && (px + pw) >= (ox + w) &&
886                  (py <= oy) && (py + ph) >= (oy + h))
887                {
888                   // if object is already shown
889                   o = elm_widget_parent_get(o);
890                   continue;
891                }
892              else if ((px < ox) && ((px + pw) < (ox + w)))
893                {
894                   // if object is over the viewport to the x axis.
895                   x += w - pw;
896                }
897              else if ((py < oy) && ((py + ph) < (oy + h)))
898                {
899                   // if object is over the viewport to the y axis.
900                   y += h - ph;
901                }
902
903              ELM_SCROLLABLE_IFACE_GET(o, s_iface);
904              s_iface->content_pos_get(o, &rx, &ry);
905              s_iface->content_viewport_size_get(o, &w, &h);
906
907              x += rx + ox - px;
908              y += ry + oy - py;
909
910              s_iface->content_region_show(o, x, y, w, h);
911              x = 0;
912              y = 0;
913           }
914         o = elm_widget_parent_get(o);
915      }
916 }
917
918 static void
919 _parent_focus(Evas_Object *obj)
920 {
921    API_ENTRY return;
922
923    if (sd->focused) return;
924
925    Evas_Object *o = elm_widget_parent_get(obj);
926    sd->focus_order_on_calc = EINA_TRUE;
927
928    if (o) _parent_focus(o);
929
930    if (!sd->focus_order_on_calc)
931      return;  /* we don't want to override it if by means of any of the
932                  callbacks below one gets to calculate our order
933                  first. */
934
935    focus_order++;
936    sd->focus_order = focus_order;
937    if (!sd->api) return;
938    if (sd->top_win_focused)
939      {
940         sd->focused = EINA_TRUE;
941         sd->api->on_focus(obj);
942      }
943    sd->focus_order_on_calc = EINA_FALSE;
944
945    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
946      _elm_access_highlight_set(obj);
947 }
948
949 static void
950 _elm_object_focus_chain_del_cb(void *data,
951                                Evas *e __UNUSED__,
952                                Evas_Object *obj,
953                                void *event_info __UNUSED__)
954 {
955    Elm_Widget_Smart_Data *sd = data;
956
957    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
958 }
959
960 EAPI const Elm_Widget_Smart_Class *
961 elm_widget_smart_class_get(void)
962 {
963    static Elm_Widget_Smart_Class _sc =
964      ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION(ELM_WIDGET_SMART_NAME);
965    static const Elm_Widget_Smart_Class *class = NULL;
966
967    if (class)
968      return class;
969
970    _elm_widget_smart_set(&_sc);
971    class = &_sc;
972
973    return class;
974 }
975
976 EAPI Evas_Object *
977 elm_widget_add(Evas_Smart *smart,
978                Evas_Object *parent)
979 {
980    Evas *e;
981    Evas_Object *o;
982
983    e = evas_object_evas_get(parent);
984    if (!e) return NULL;
985
986    o = evas_object_smart_add(e, smart);
987    elm_widget_parent_set(o, parent);
988
989    return o;
990 }
991
992 EAPI void
993 elm_widget_parent_set(Evas_Object *obj,
994                       Evas_Object *parent)
995 {
996    ELM_WIDGET_DATA_GET(obj, sd);
997
998    if (!sd->api->parent_set) return;
999
1000    sd->api->parent_set(obj, parent);
1001 }
1002
1003 EAPI Eina_Bool
1004 elm_widget_api_check(int ver)
1005 {
1006    if (ver != ELM_INTERNAL_API_VERSION)
1007      {
1008         CRITICAL("Elementary widget api versions do not match");
1009         return EINA_FALSE;
1010      }
1011    return EINA_TRUE;
1012 }
1013
1014 EAPI Eina_Bool
1015 elm_widget_access(Evas_Object *obj,
1016                   Eina_Bool is_access)
1017 {
1018    const Eina_List *l;
1019    Evas_Object *child;
1020    Eina_Bool ret = EINA_TRUE;
1021
1022    API_ENTRY return EINA_FALSE;
1023    EINA_LIST_FOREACH(sd->subobjs, l, child)
1024      ret &= elm_widget_access(child, is_access);
1025
1026    if (sd->api && sd->api->access)
1027      sd->api->access(obj, is_access);
1028    else
1029      return EINA_FALSE;
1030
1031    return ret;
1032 }
1033
1034 EAPI Eina_Bool
1035 elm_widget_theme(Evas_Object *obj)
1036 {
1037    const Eina_List *l;
1038    Evas_Object *child;
1039    Elm_Tooltip *tt;
1040    Elm_Cursor *cur;
1041    Eina_Bool ret = EINA_TRUE;
1042
1043    API_ENTRY return EINA_FALSE;
1044
1045    EINA_LIST_FOREACH(sd->subobjs, l, child)
1046      if (_elm_widget_is(child)) ret &= elm_widget_theme(child);
1047    if (sd->resize_obj && _elm_widget_is(sd->resize_obj))
1048      ret &= elm_widget_theme(sd->resize_obj);
1049    if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
1050
1051    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1052      elm_tooltip_theme(tt);
1053    EINA_LIST_FOREACH(sd->cursors, l, cur)
1054      elm_cursor_theme(cur);
1055
1056    if (!sd->api) return EINA_FALSE;
1057
1058    ret &= sd->api->theme(obj);
1059
1060    return ret;
1061 }
1062
1063 EAPI void
1064 elm_widget_theme_specific(Evas_Object *obj,
1065                           Elm_Theme *th,
1066                           Eina_Bool force)
1067 {
1068    const Eina_List *l;
1069    Evas_Object *child;
1070    Elm_Tooltip *tt;
1071    Elm_Cursor *cur;
1072    Elm_Theme *th2, *thdef;
1073
1074    API_ENTRY return;
1075
1076    thdef = elm_theme_default_get();
1077    if (!th) th = thdef;
1078    if (!force)
1079      {
1080         th2 = sd->theme;
1081         if (!th2) th2 = thdef;
1082         while (th2)
1083           {
1084              if (th2 == th)
1085                {
1086                   force = EINA_TRUE;
1087                   break;
1088                }
1089              if (th2 == thdef) break;
1090              th2 = th2->ref_theme;
1091              if (!th2) th2 = thdef;
1092           }
1093      }
1094    if (!force) return;
1095    EINA_LIST_FOREACH(sd->subobjs, l, child)
1096      elm_widget_theme_specific(child, th, force);
1097    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
1098    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1099    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1100      elm_tooltip_theme(tt);
1101    EINA_LIST_FOREACH(sd->cursors, l, cur)
1102      elm_cursor_theme(cur);
1103    if (!sd->api) return;
1104    sd->api->theme(obj);
1105 }
1106
1107 /**
1108  * Returns the widget's mirrored mode.
1109  *
1110  * @param obj The widget.
1111  * @return mirrored mode of the object.
1112  *
1113  **/
1114 EAPI Eina_Bool
1115 elm_widget_mirrored_get(const Evas_Object *obj)
1116 {
1117    API_ENTRY return EINA_FALSE;
1118    return sd->is_mirrored;
1119 }
1120
1121 /**
1122  * Sets the widget's mirrored mode.
1123  *
1124  * @param obj The widget.
1125  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1126  */
1127 EAPI void
1128 elm_widget_mirrored_set(Evas_Object *obj,
1129                         Eina_Bool mirrored)
1130 {
1131    API_ENTRY return;
1132
1133    mirrored = !!mirrored;
1134
1135    if (sd->is_mirrored == mirrored) return;
1136
1137    sd->is_mirrored = mirrored;
1138    elm_widget_theme(obj);
1139 }
1140
1141 /**
1142  * Returns the widget's mirrored mode setting.
1143  *
1144  * @param obj The widget.
1145  * @return mirrored mode setting of the object.
1146  *
1147  **/
1148 EAPI Eina_Bool
1149 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
1150 {
1151    API_ENTRY return EINA_FALSE;
1152    return sd->mirrored_auto_mode;
1153 }
1154
1155 /**
1156  * Sets the widget's mirrored mode setting.
1157  * When widget in automatic mode, it follows the system mirrored mode set by
1158  * elm_mirrored_set().
1159  * @param obj The widget.
1160  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1161  */
1162 EAPI void
1163 elm_widget_mirrored_automatic_set(Evas_Object *obj,
1164                                   Eina_Bool automatic)
1165 {
1166    API_ENTRY return;
1167    if (sd->mirrored_auto_mode != automatic)
1168      {
1169         sd->mirrored_auto_mode = automatic;
1170
1171         if (automatic)
1172           {
1173              elm_widget_mirrored_set(obj, elm_config_mirrored_get());
1174           }
1175      }
1176 }
1177
1178 EAPI void
1179 elm_widget_on_show_region_hook_set(Evas_Object *obj,
1180                                    void (*func)(void *data,
1181                                                 Evas_Object *obj),
1182                                    void *data)
1183 {
1184    API_ENTRY return;
1185
1186    sd->on_show_region = func;
1187    sd->on_show_region_data = data;
1188 }
1189
1190 EAPI Eina_Bool
1191 elm_widget_sub_object_add(Evas_Object *obj,
1192                           Evas_Object *sobj)
1193 {
1194    API_ENTRY return EINA_FALSE;
1195    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1196
1197    if (!sd->api) return EINA_FALSE;
1198    return sd->api->sub_object_add(obj, sobj);
1199 }
1200
1201 EAPI Eina_Bool
1202 elm_widget_sub_object_del(Evas_Object *obj,
1203                           Evas_Object *sobj)
1204 {
1205    API_ENTRY return EINA_FALSE;
1206    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1207
1208    if (!sobj) return EINA_FALSE;
1209
1210    if (!sd->api) return EINA_FALSE;
1211    return sd->api->sub_object_del(obj, sobj);
1212 }
1213
1214 //SHKWAK : Temp Function for Indicator Issue
1215 // THIS MUST BE REMOVED
1216
1217 EAPI const Eina_List *
1218 elm_widget_sub_object_list_get(const Evas_Object *obj)
1219 {
1220    API_ENTRY return NULL;
1221    return (const Eina_List *)sd->subobjs;
1222 }
1223
1224 //SHKWAK : END
1225
1226
1227 /* a resize object is a sub object with some more callbacks on it and
1228  * a smart member of the parent
1229  */
1230 EAPI void
1231 elm_widget_resize_object_set(Evas_Object *obj,
1232                              Evas_Object *sobj)
1233 {
1234    Evas_Object *parent;
1235
1236    API_ENTRY return;
1237
1238    if (sd->resize_obj == sobj) return;
1239
1240    // orphan previous resize obj
1241    if (sd->resize_obj)
1242      {
1243         evas_object_clip_unset(sd->resize_obj);
1244         evas_object_smart_member_del(sd->resize_obj);
1245
1246         if (_elm_widget_is(sd->resize_obj))
1247           {
1248              if (elm_widget_focus_get(sd->resize_obj)) _parents_unfocus(obj);
1249           }
1250
1251         elm_widget_sub_object_del(obj, sd->resize_obj);
1252      }
1253
1254    sd->resize_obj = sobj;
1255    if (!sobj)
1256      {
1257         evas_object_event_callback_del_full(obj,
1258                                             EVAS_CALLBACK_MOUSE_DOWN,
1259                                             _obj_mouse_down, sd);
1260         evas_object_event_callback_del_full(obj,
1261                                             EVAS_CALLBACK_MOUSE_MOVE,
1262                                             _obj_mouse_move, sd);
1263         evas_object_event_callback_del_full(obj,
1264                                             EVAS_CALLBACK_MOUSE_UP,
1265                                             _obj_mouse_up, sd);
1266         return;
1267      }
1268
1269    // orphan new resize obj
1270    parent = evas_object_data_get(sobj, "elm-parent");
1271    if (parent && parent != obj)
1272      {
1273         ELM_WIDGET_DATA_GET(parent, sdp);
1274
1275         /* should be there, just being paranoid */
1276         if (sdp)
1277           {
1278              if (sdp->resize_obj == sobj)
1279                elm_widget_resize_object_set(parent, NULL);
1280              else
1281                elm_widget_sub_object_del(parent, sobj);
1282           }
1283      }
1284
1285    elm_widget_sub_object_add(obj, sobj);
1286
1287    evas_object_smart_member_add(sobj, obj);
1288
1289    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1290                                   _obj_mouse_down, sd);
1291    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1292                                   _obj_mouse_move, sd);
1293    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1294                                   _obj_mouse_up, sd);
1295    _smart_reconfigure(sd);
1296 }
1297
1298 /* WARNING: the programmer is responsible, in the scenario of
1299  * exchanging a hover object, of cleaning the old hover "target"
1300  * before
1301  */
1302 EAPI void
1303 elm_widget_hover_object_set(Evas_Object *obj,
1304                             Evas_Object *sobj)
1305 {
1306    API_ENTRY return;
1307    if (sd->hover_obj)
1308      {
1309         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1310                                             _on_sub_obj_del, sd);
1311      }
1312    sd->hover_obj = sobj;
1313    if (sd->hover_obj)
1314      {
1315         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1316                                        _on_sub_obj_del, sd);
1317         _smart_reconfigure(sd);
1318      }
1319 }
1320
1321 EAPI void
1322 elm_widget_can_focus_set(Evas_Object *obj,
1323                          Eina_Bool can_focus)
1324 {
1325    API_ENTRY return;
1326
1327    can_focus = !!can_focus;
1328
1329    if (sd->can_focus == can_focus) return;
1330    sd->can_focus = can_focus;
1331    if (sd->can_focus)
1332      {
1333         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1334                                        _propagate_event,
1335                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1336         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1337                                        _propagate_event,
1338                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1339         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1340                                        _propagate_event,
1341                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1342      }
1343    else
1344      {
1345         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1346                                        _propagate_event);
1347         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1348                                        _propagate_event);
1349         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1350                                        _propagate_event);
1351      }
1352 }
1353
1354 EAPI Eina_Bool
1355 elm_widget_can_focus_get(const Evas_Object *obj)
1356 {
1357    API_ENTRY return EINA_FALSE;
1358    return sd->can_focus;
1359 }
1360
1361 EAPI Eina_Bool
1362 elm_widget_child_can_focus_get(const Evas_Object *obj)
1363 {
1364    API_ENTRY return EINA_FALSE;
1365    return sd->child_can_focus;
1366 }
1367
1368 /**
1369  * @internal
1370  *
1371  * This API makes the widget object and its children to be unfocusable.
1372  *
1373  * This API can be helpful for an object to be deleted.
1374  * When an object will be deleted soon, it and its children may not
1375  * want to get focus (by focus reverting or by other focus controls).
1376  * Then, just use this API before deleting.
1377  *
1378  * @param obj The widget root of sub-tree
1379  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1380  *
1381  * @ingroup Widget
1382  */
1383 EAPI void
1384 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1385                                 Eina_Bool tree_unfocusable)
1386 {
1387    API_ENTRY return;
1388
1389    tree_unfocusable = !!tree_unfocusable;
1390    if (sd->tree_unfocusable == tree_unfocusable) return;
1391    sd->tree_unfocusable = tree_unfocusable;
1392    elm_widget_focus_tree_unfocusable_handle(obj);
1393 }
1394
1395 /**
1396  * @internal
1397  *
1398  * This returns true, if the object sub-tree is unfocusable.
1399  *
1400  * @param obj The widget root of sub-tree
1401  * @return EINA_TRUE if the object sub-tree is unfocusable
1402  *
1403  * @ingroup Widget
1404  */
1405 EAPI Eina_Bool
1406 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1407 {
1408    API_ENTRY return EINA_FALSE;
1409    return sd->tree_unfocusable;
1410 }
1411
1412 /**
1413  * @internal
1414  *
1415  * Get the list of focusable child objects.
1416  *
1417  * This function retruns list of child objects which can get focus.
1418  *
1419  * @param obj The parent widget
1420  * @retrun list of focusable child objects.
1421  *
1422  * @ingroup Widget
1423  */
1424 EAPI Eina_List *
1425 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1426 {
1427    API_ENTRY return NULL;
1428
1429    const Eina_List *l;
1430    Eina_List *child_list = NULL;
1431    Evas_Object *child;
1432
1433    if (sd->subobjs)
1434      {
1435         EINA_LIST_FOREACH(sd->subobjs, l, child)
1436           {
1437              if ((elm_widget_can_focus_get(child)) &&
1438                  (evas_object_visible_get(child)) &&
1439                  (!elm_widget_disabled_get(child)))
1440                child_list = eina_list_append(child_list, child);
1441              else if (elm_widget_is(child))
1442                {
1443                   Eina_List *can_focus_list;
1444                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1445                   if (can_focus_list)
1446                     child_list = eina_list_merge(child_list, can_focus_list);
1447                }
1448           }
1449      }
1450    return child_list;
1451 }
1452
1453 EAPI void
1454 elm_widget_highlight_ignore_set(Evas_Object *obj,
1455                                 Eina_Bool ignore)
1456 {
1457    API_ENTRY return;
1458    sd->highlight_ignore = !!ignore;
1459 }
1460
1461 EAPI Eina_Bool
1462 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1463 {
1464    API_ENTRY return EINA_FALSE;
1465    return sd->highlight_ignore;
1466 }
1467
1468 EAPI void
1469 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1470                                   Eina_Bool highlight)
1471 {
1472    API_ENTRY return;
1473    sd->highlight_in_theme = !!highlight;
1474    /* FIXME: if focused, it should switch from one mode to the other */
1475 }
1476
1477 EAPI Eina_Bool
1478 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1479 {
1480    API_ENTRY return EINA_FALSE;
1481    return sd->highlight_in_theme;
1482 }
1483
1484 EAPI Eina_Bool
1485 elm_widget_focus_get(const Evas_Object *obj)
1486 {
1487    API_ENTRY return EINA_FALSE;
1488    return sd->focused;
1489 }
1490
1491 EAPI Evas_Object *
1492 elm_widget_focused_object_get(const Evas_Object *obj)
1493 {
1494    const Evas_Object *subobj;
1495    const Eina_List *l;
1496    API_ENTRY return NULL;
1497
1498    if (!sd->focused) return NULL;
1499    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1500      {
1501         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1502         if (fobj) return fobj;
1503      }
1504    return (Evas_Object *)obj;
1505 }
1506
1507 EAPI Evas_Object *
1508 elm_widget_top_get(const Evas_Object *obj)
1509 {
1510    API_ENTRY return NULL;
1511    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1512    return (Evas_Object *)obj;
1513 }
1514
1515 EAPI Eina_Bool
1516 elm_widget_is(const Evas_Object *obj)
1517 {
1518    return _elm_widget_is(obj);
1519 }
1520
1521 EAPI Evas_Object *
1522 elm_widget_parent_widget_get(const Evas_Object *obj)
1523 {
1524    Evas_Object *parent;
1525
1526    if (_elm_widget_is(obj))
1527      {
1528         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1529         if (!sd) return NULL;
1530         parent = sd->parent_obj;
1531      }
1532    else
1533      {
1534         parent = evas_object_data_get(obj, "elm-parent");
1535         if (!parent) parent = evas_object_smart_parent_get(obj);
1536      }
1537
1538    while (parent)
1539      {
1540         Evas_Object *elm_parent;
1541         if (_elm_widget_is(parent)) break;
1542         elm_parent = evas_object_data_get(parent, "elm-parent");
1543         if (elm_parent) parent = elm_parent;
1544         else parent = evas_object_smart_parent_get(parent);
1545      }
1546    return parent;
1547 }
1548
1549 EAPI Evas_Object *
1550 elm_widget_parent2_get(const Evas_Object *obj)
1551 {
1552    if (_elm_widget_is(obj))
1553      {
1554         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1555         if (sd) return sd->parent2;
1556      }
1557    return NULL;
1558 }
1559
1560 EAPI void
1561 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1562 {
1563    API_ENTRY return;
1564    sd->parent2 = parent;
1565 }
1566
1567 EAPI void
1568 elm_widget_event_callback_add(Evas_Object *obj,
1569                               Elm_Event_Cb func,
1570                               const void *data)
1571 {
1572    API_ENTRY return;
1573    EINA_SAFETY_ON_NULL_RETURN(func);
1574    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1575    ecb->func = func;
1576    ecb->data = data;
1577    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1578 }
1579
1580 EAPI void *
1581 elm_widget_event_callback_del(Evas_Object *obj,
1582                               Elm_Event_Cb func,
1583                               const void *data)
1584 {
1585    API_ENTRY return NULL;
1586    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1587    Eina_List *l;
1588    Elm_Event_Cb_Data *ecd;
1589    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1590      if ((ecd->func == func) && (ecd->data == data))
1591        {
1592           free(ecd);
1593           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1594           return (void *)data;
1595        }
1596    return NULL;
1597 }
1598
1599 EAPI Eina_Bool
1600 elm_widget_event_propagate(Evas_Object *obj,
1601                            Evas_Callback_Type type,
1602                            void *event_info,
1603                            Evas_Event_Flags *event_flags)
1604 {
1605    API_ENTRY return EINA_FALSE; //TODO reduce.
1606
1607    if (!_elm_widget_is(obj)) return EINA_FALSE;
1608    Evas_Object *parent = obj;
1609    Elm_Event_Cb_Data *ecd;
1610    Eina_List *l, *l_prev;
1611
1612    while (parent &&
1613           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1614      {
1615         sd = evas_object_smart_data_get(parent);
1616         if ((!sd) || (!_elm_widget_is(obj)))
1617           return EINA_FALSE;  //Not Elm Widget
1618         if (!sd->api) return EINA_FALSE;
1619
1620         if (sd->api->event(parent, obj, type, event_info))
1621           return EINA_TRUE;
1622
1623         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1624           {
1625              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1626                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1627                return EINA_TRUE;
1628           }
1629         parent = sd->parent_obj;
1630      }
1631
1632    return EINA_FALSE;
1633 }
1634
1635 /**
1636  * @internal
1637  *
1638  * Set custom focus chain.
1639  *
1640  * This function i set one new and overwrite any previous custom focus chain
1641  * with the list of objects. The previous list will be deleted and this list
1642  * will be managed. After setted, don't modity it.
1643  *
1644  * @note On focus cycle, only will be evaluated children of this container.
1645  *
1646  * @param obj The container widget
1647  * @param objs Chain of objects to pass focus
1648  * @ingroup Widget
1649  */
1650 EAPI void
1651 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1652                                   Eina_List *objs)
1653 {
1654    API_ENTRY return;
1655
1656    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1657
1658    elm_widget_focus_custom_chain_unset(obj);
1659
1660    Eina_List *l;
1661    Evas_Object *o;
1662
1663    EINA_LIST_FOREACH(objs, l, o)
1664      {
1665         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1666                                        _elm_object_focus_chain_del_cb, sd);
1667      }
1668
1669    sd->focus_chain = objs;
1670 }
1671
1672 /**
1673  * @internal
1674  *
1675  * Get custom focus chain
1676  *
1677  * @param obj The container widget
1678  * @ingroup Widget
1679  */
1680 EAPI const Eina_List *
1681 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1682 {
1683    API_ENTRY return NULL;
1684    return (const Eina_List *)sd->focus_chain;
1685 }
1686
1687 /**
1688  * @internal
1689  *
1690  * Unset custom focus chain
1691  *
1692  * @param obj The container widget
1693  * @ingroup Widget
1694  */
1695 EAPI void
1696 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1697 {
1698    API_ENTRY return;
1699    Eina_List *l, *l_next;
1700    Evas_Object *o;
1701
1702    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1703      {
1704         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1705                                             _elm_object_focus_chain_del_cb, sd);
1706         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1707      }
1708 }
1709
1710 /**
1711  * @internal
1712  *
1713  * Append object to custom focus chain.
1714  *
1715  * @note If relative_child equal to NULL or not in custom chain, the object
1716  * will be added in end.
1717  *
1718  * @note On focus cycle, only will be evaluated children of this container.
1719  *
1720  * @param obj The container widget
1721  * @param child The child to be added in custom chain
1722  * @param relative_child The relative object to position the child
1723  * @ingroup Widget
1724  */
1725 EAPI void
1726 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1727                                      Evas_Object *child,
1728                                      Evas_Object *relative_child)
1729 {
1730    API_ENTRY return;
1731    EINA_SAFETY_ON_NULL_RETURN(child);
1732
1733    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1734
1735    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1736                                        _elm_object_focus_chain_del_cb, sd);
1737
1738    if (!relative_child)
1739      sd->focus_chain = eina_list_append(sd->focus_chain, child);
1740    else
1741      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1742                                                  child, relative_child);
1743 }
1744
1745 /**
1746  * @internal
1747  *
1748  * Prepend object to custom focus chain.
1749  *
1750  * @note If relative_child equal to NULL or not in custom chain, the object
1751  * will be added in begin.
1752  *
1753  * @note On focus cycle, only will be evaluated children of this container.
1754  *
1755  * @param obj The container widget
1756  * @param child The child to be added in custom chain
1757  * @param relative_child The relative object to position the child
1758  * @ingroup Widget
1759  */
1760 EAPI void
1761 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1762                                       Evas_Object *child,
1763                                       Evas_Object *relative_child)
1764 {
1765    API_ENTRY return;
1766    EINA_SAFETY_ON_NULL_RETURN(child);
1767
1768    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1769
1770    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1771                                        _elm_object_focus_chain_del_cb, sd);
1772
1773    if (!relative_child)
1774      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1775    else
1776      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1777                                                   child, relative_child);
1778 }
1779
1780 /**
1781  * @internal
1782  *
1783  * Give focus to next object in object tree.
1784  *
1785  * Give focus to next object in focus chain of one object sub-tree.
1786  * If the last object of chain already have focus, the focus will go to the
1787  * first object of chain.
1788  *
1789  * @param obj The widget root of sub-tree
1790  * @param dir Direction to cycle the focus
1791  *
1792  * @ingroup Widget
1793  */
1794 EAPI void
1795 elm_widget_focus_cycle(Evas_Object *obj,
1796                        Elm_Focus_Direction dir)
1797 {
1798    Evas_Object *target = NULL;
1799    if (!_elm_widget_is(obj))
1800      return;
1801    elm_widget_focus_next_get(obj, dir, &target);
1802    if (target)
1803      {
1804         /* access */
1805         if (_elm_config->access_mode && _elm_access_read_mode_get())
1806           {
1807              _elm_access_highlight_set(target);
1808              _elm_widget_focus_region_show(target);
1809           }
1810         else elm_widget_focus_steal(target);
1811      }
1812 }
1813
1814 /**
1815  * @internal
1816  *
1817  * Give focus to near object(in object tree) in one direction.
1818  *
1819  * Give focus to near object(in object tree) in direction of current
1820  * focused object.  If none focusable object in given direction or
1821  * none focused object in object tree, the focus will not change.
1822  *
1823  * @param obj The reference widget
1824  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
1825  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
1826  * @return EINA_TRUE if focus is moved.
1827  *
1828  * @ingroup Widget
1829  */
1830 EAPI Eina_Bool
1831 elm_widget_focus_direction_go(Evas_Object *obj,
1832                               double degree)
1833 {
1834    Evas_Object *target = NULL;
1835    Evas_Object *current_focused = NULL;
1836    double weight = 0.0;
1837
1838    if (!_elm_widget_is(obj)) return EINA_FALSE;
1839    if (!elm_widget_focus_get(obj)) return EINA_FALSE;
1840
1841    current_focused = elm_widget_focused_object_get(obj);
1842
1843    if (elm_widget_focus_direction_get
1844          (obj, current_focused, degree, &target, &weight))
1845      {
1846         elm_widget_focus_steal(target);
1847         return EINA_TRUE;
1848      }
1849    return EINA_FALSE;
1850 }
1851
1852 static double
1853 _direction_weight_get(const Evas_Object *obj1,
1854                       const Evas_Object *obj2,
1855                       double degree)
1856 {
1857    Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
1858    double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
1859    double ax, ay, cx, cy;
1860    double weight = -1.0, g = 0.0;
1861
1862    if (obj1 == obj2) return 0.0;
1863
1864    degree -= 90.0;
1865    while (degree >= 360.0)
1866      degree -= 360.0;
1867    while (degree < 0.0)
1868      degree += 360.0;
1869
1870    evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
1871    cx = obj_x1 + (w1 / 2.0);
1872    cy = obj_y1 + (h1 / 2.0);
1873    evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
1874
1875    /* For overlapping cases. */
1876    if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
1877      return 0.0;
1878
1879    /* Change all points to relative one. */
1880    x1 = obj_x1 - cx;
1881    xx1 = x1 + w1;
1882    yy1 = obj_y1 - cy;
1883    yyy1 = yy1 + h1;
1884    x2 = obj_x2 - cx;
1885    xx2 = x2 + w2;
1886    yy2 = obj_y2 - cy;
1887    yyy2 = yy2 + h2;
1888
1889    /* Get crossing points (ax, ay) between obj1 and a line extending
1890     * to the direction of current degree. */
1891    if (degree == 0.0)
1892      {
1893         ax = xx1;
1894         ay = 0.0;
1895      }
1896    else if (degree == 90.0)
1897      {
1898         ax = 0.0;
1899         ay = yyy1;
1900      }
1901    else if (degree == 180.0)
1902      {
1903         ax = x1;
1904         ay = 0.0;
1905      }
1906    else if (degree == 270.0)
1907      {
1908         ax = 0.0;
1909         ay = yy1;
1910      }
1911    else
1912      {
1913         g = tan(degree * (M_PI / 180.0));
1914         if ((degree > 0.0) && (degree < 90.0))
1915           {
1916              ay = g * xx1;
1917              if (ay <= yyy1) ax = xx1;
1918              else
1919                {
1920                   ax = yyy1 / g;
1921                   ay = yyy1;
1922                }
1923           }
1924         else if ((degree > 90.0) && (degree < 180.0))
1925           {
1926              ay = g * x1;
1927              if (ay <= yyy1) ax = x1;
1928              else
1929                {
1930                   ax = yyy1 / g;
1931                   ay = yyy1;
1932                }
1933           }
1934         else if ((degree > 180.0) && (degree < 270.0))
1935           {
1936              ay = g * x1;
1937              if (ay >= yy1) ax = x1;
1938              else
1939                {
1940                   ax = yy1 / g;
1941                   ay = yy1;
1942                }
1943           }
1944         else
1945           {
1946              ay = g * xx1;
1947              if (ay >= yy1) ax = xx1;
1948              else
1949                {
1950                   ax = yy1 / g;
1951                   ay = yy1;
1952                }
1953           }
1954      }
1955
1956    /* Filter obj2, if it is not in the specific derection. */
1957    int i = 0;
1958    double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
1959    double t1, t2, u1, v1, u2, v2;
1960
1961    if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
1962        (degree == 315.0))
1963      {
1964         u1 = 1.0;
1965         v1 = 0.0;
1966         u2 = 0.0;
1967         v2 = 1.0;
1968      }
1969    else
1970      {
1971         double g2 = tan((degree + 45.0) * (M_PI / 180.0));
1972         u1 = (-1.0 * g2);
1973         u2 = (1.0 / g2);
1974         v1 = v2 = 1.0;
1975      }
1976    t1 = (u1 * ax) + (v1 * ay);
1977    t2 = (u2 * ax) + (v2 * ay);
1978
1979 #define _R(x) (int)((x + 0.05) * 10.0)
1980
1981    if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
1982                                                             (v2 * yy2))) > 0))
1983      {
1984         rx[i] = x2;
1985         ry[i++] = yy2;
1986      }
1987    if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
1988                                                              (v2 * yyy2))) > 0))
1989      {
1990         rx[i] = x2;
1991         ry[i++] = yyy2;
1992      }
1993    if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
1994                                                              (v2 * yy2))) > 0))
1995      {
1996         rx[i] = xx2;
1997         ry[i++] = yy2;
1998      }
1999    if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2000        (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2001      {
2002         rx[i] = xx2;
2003         ry[i++] = yyy2;
2004      }
2005    if (i == 0)
2006      {
2007         if (degree == 0.0)
2008           {
2009              if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2010           }
2011         else if (degree == 90.0)
2012           {
2013              if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2014           }
2015         else if (degree == 180.0)
2016           {
2017              if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2018           }
2019         else if (degree == 270.0)
2020           {
2021              if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2022           }
2023         else
2024           {
2025              if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2026                {
2027                   if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2028                     return 0.0;
2029                }
2030              else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2031                {
2032                   if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2033                     return 0.0;
2034                }
2035              else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2036                                                            <= _R(xx2)))
2037                {
2038                   if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2039                         && (_R(ay * yy2) > 0)))
2040                     return 0.0;
2041                }
2042              else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2043                       (_R((1.0 / g) * yyy2) <= _R(xx2)))
2044                {
2045                   if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2046                         && (_R(ay * yyy2) > 0))) return 0.0;
2047                }
2048              else return 0.0;
2049           }
2050      }
2051
2052    /* Calculate the weight for obj2. */
2053    if (degree == 0.0)
2054      {
2055         if (_R(xx1) > _R(x2)) weight = -1.0;
2056         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2057           weight = (x2 - xx1) * (x2 - xx1);
2058         else if (_R(yy2) > 0)
2059           weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2060         else if (_R(yyy2) < 0)
2061           weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2062         else weight = (x2 - xx1) * (x2 - xx1);
2063      }
2064    else if (degree == 90.0)
2065      {
2066         if (_R(yyy1) > _R(yy2)) weight = -1.0;
2067         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2068           weight = (yy2 - yyy1) * (yy2 - yyy1);
2069         else if (_R(x2) > 0)
2070           weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2071         else if (_R(xx2) < 0)
2072           weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2073         else weight = (yy2 - yyy1) * (yy2 - yyy1);
2074      }
2075    else if (degree == 180.0)
2076      {
2077         if (_R(x1) < _R(xx2)) weight = -1.0;
2078         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2079           weight = (x1 - xx2) * (x1 - xx2);
2080         else if (_R(yy2) > 0)
2081           weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2082         else if (_R(yyy2) < 0)
2083           weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2084         else weight = (x1 - xx2) * (x1 - xx2);
2085      }
2086    else if (degree == 270.0)
2087      {
2088         if (_R(yy1) < _R(yyy2)) weight = -1.0;
2089         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2090           weight = (yy1 - yyy2) * (yy1 - yyy2);
2091         else if (_R(x2) > 0)
2092           weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2093         else if (_R(xx2) < 0)
2094           weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2095         else weight = (yy1 - yyy2) * (yy1 - yyy2);
2096      }
2097    else
2098      {
2099         int j = 0, k = 0;
2100         double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2101         double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2102         if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2103           {
2104              sx[j] = x2;
2105              sy[j] = g * x2;
2106              t_weight[j++] = ((ax - x2) * (ax - x2)) +
2107                ((ay - (g * x2)) * (ay - (g * x2)));
2108           }
2109         if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2110           {
2111              sx[j] = xx2;
2112              sy[j] = g * xx2;
2113              t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2114                ((ay - (g * xx2)) * (ay - (g * xx2)));
2115           }
2116         if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2117           {
2118              sx[j] = (1.0 / g) * yy2;
2119              sy[j] = yy2;
2120              t_weight[j++] =
2121                ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2122                ((ay - yy2) * (ay - yy2));
2123           }
2124         if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2125                                                  <= _R(xx2)))
2126           {
2127              sx[j] = (1.0 / g) * yyy2;
2128              sy[j] = yyy2;
2129              t_weight[j++] =
2130                ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2131                ((ay - yyy2) * (ay - yyy2));
2132           }
2133
2134         if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2135                                      (_R(sy[0]) != _R(sy[1])))))
2136           {
2137              for (; k < j; k++)
2138                {
2139                   if (_R(t_weight[k]) == 0) return -1.0;
2140                   if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2141                }
2142           }
2143         else
2144           {
2145              for (; k < i; k++)
2146                {
2147                   double ccx, ccy, t1_weight, x_diff, y_diff;
2148                   ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2149                   ccy = g * ccx;
2150                   x_diff = rx[k] - ccx;
2151                   if (x_diff < 0) x_diff *= -1.0;
2152                   y_diff = ry[k] - ccy;
2153                   if (y_diff < 0) y_diff *= -1.0;
2154                   t1_weight =
2155                     (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2156                     ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2157                   if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2158                     weight = t1_weight;
2159                }
2160           }
2161      }
2162    /* Return the current object's weight. */
2163    if (weight == -1.0) return 0.0;
2164    if (_R(weight) == 0) return -1.0;
2165
2166 #undef _R
2167
2168    return 1.0 / weight;
2169 }
2170
2171 /**
2172  * @internal
2173  *
2174  * Get near object in one direction of base object.
2175  *
2176  * Get near object(in the object sub-tree) in one direction of
2177  * base object. Return the near object by reference.
2178  * By initializing weight, you can filter objects locating far
2179  * from base object. If object is in the specific direction,
2180  * weight is (1/(distance^2)). If object is not exactly in one
2181  * direction, some penalty will be added.
2182  *
2183  * @param obj The widget root of sub-tree
2184  * @param base The base object of the direction
2185  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2186  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2187  * @param direction The near object in one direction
2188  * @param weight The weight is bigger when the object is located near
2189  * @return EINA_TRUE if near object is updated.
2190  *
2191  * @ingroup Widget
2192  */
2193 EAPI Eina_Bool
2194 elm_widget_focus_direction_get(const Evas_Object *obj,
2195                                const Evas_Object *base,
2196                                double degree,
2197                                Evas_Object **direction,
2198                                double *weight)
2199 {
2200    double c_weight;
2201
2202    API_ENTRY return EINA_FALSE;
2203
2204    /* -1 means the best was already decided. Don't need any more searching. */
2205    if (!direction || !weight || !base || (obj == base))
2206      return EINA_FALSE;
2207
2208    /* Ignore if disabled */
2209    if ((!evas_object_visible_get(obj))
2210        || (elm_widget_disabled_get(obj))
2211        || (elm_widget_tree_unfocusable_get(obj)))
2212      return EINA_FALSE;
2213
2214    if (!sd->api) return EINA_FALSE;
2215
2216    /* Try use hook */
2217    if (_elm_widget_focus_direction_manager_is(obj))
2218      return sd->api->focus_direction(obj, base, degree, direction, weight);
2219
2220    if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
2221      return EINA_FALSE;
2222
2223    c_weight = _direction_weight_get(base, obj, degree);
2224    if ((c_weight == -1.0) ||
2225        ((c_weight != 0.0) && (*weight != -1.0) &&
2226         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2227      {
2228         if ((int)(*weight * 1000000) == (int)(c_weight * 1000000))
2229           {
2230              Elm_Widget_Smart_Data *sd1 =
2231                evas_object_smart_data_get(*direction);
2232              if (sd1)
2233                {
2234                   if (sd->focus_order <= sd1->focus_order)
2235                     return EINA_FALSE;
2236                }
2237           }
2238         *direction = (Evas_Object *)obj;
2239         *weight = c_weight;
2240         return EINA_TRUE;
2241      }
2242    return EINA_FALSE;
2243 }
2244
2245 /**
2246  * @internal
2247  *
2248  * Get near object in one direction of base object in list.
2249  *
2250  * Get near object in one direction of base object in the specific
2251  * object list. Return the near object by reference.
2252  * By initializing weight, you can filter objects locating far
2253  * from base object. If object is in the specific direction,
2254  * weight is (1/(distance^2)). If object is not exactly in one
2255  * direction, some penalty will be added.
2256  *
2257  * @param obj The widget root of sub-tree
2258  * @param base The base object of the direction
2259  * @param items list with ordered objects
2260  * @param list_data_get function to get the object from one item of list
2261  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2262  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2263  * @param direction The near object in one direction
2264  * @param weight The weight is bigger when the object is located near
2265  * @return EINA_TRUE if near object is updated.
2266  *
2267  * @ingroup Widget
2268  */
2269 EAPI Eina_Bool
2270 elm_widget_focus_list_direction_get(const Evas_Object *obj,
2271                                     const Evas_Object *base,
2272                                     const Eina_List *items,
2273                                     void *(*list_data_get)(const Eina_List *l),
2274                                     double degree,
2275                                     Evas_Object **direction,
2276                                     double *weight)
2277 {
2278    API_ENTRY return EINA_FALSE;
2279    if (!direction || !weight || !base || !items)
2280      return EINA_FALSE;
2281
2282    const Eina_List *l = items;
2283    Evas_Object *current_best = *direction;
2284
2285    for (; l; l = eina_list_next(l))
2286      {
2287         Evas_Object *cur = list_data_get(l);
2288         elm_widget_focus_direction_get(cur, base, degree, direction, weight);
2289      }
2290    if (current_best != *direction)
2291      return EINA_TRUE;
2292    else
2293      return EINA_FALSE;
2294 }
2295
2296 /**
2297  * @internal
2298  *
2299  * Get next object in focus chain of object tree.
2300  *
2301  * Get next object in focus chain of one object sub-tree.
2302  * Return the next object by reference. If don't have any candidate to receive
2303  * focus before chain end, the first candidate will be returned.
2304  *
2305  * @param obj The widget root of sub-tree
2306  * @param dir Direction os focus chain
2307  * @param next The next object in focus chain
2308  * @return EINA_TRUE if don't need focus chain restart/loop back
2309  *         to use 'next' obj.
2310  *
2311  * @ingroup Widget
2312  */
2313 EAPI Eina_Bool
2314 elm_widget_focus_next_get(const Evas_Object *obj,
2315                           Elm_Focus_Direction dir,
2316                           Evas_Object **next)
2317 {
2318    if (!next)
2319      return EINA_FALSE;
2320    *next = NULL;
2321
2322    API_ENTRY return EINA_FALSE;
2323
2324    /* Ignore if disabled */
2325    if ((!evas_object_visible_get(obj))
2326        || (elm_widget_disabled_get(obj))
2327        || (elm_widget_tree_unfocusable_get(obj)))
2328      return EINA_FALSE;
2329
2330    if (!sd->api) return EINA_FALSE;
2331
2332    /* Try use hook */
2333    if (_elm_widget_focus_chain_manager_is(obj))
2334      return sd->api->focus_next(obj, dir, next);
2335
2336    if (!elm_widget_can_focus_get(obj))
2337      return EINA_FALSE;
2338
2339    /* focusable object but does not have access info */
2340    if (_elm_config->access_mode)
2341      {
2342         if (!_elm_access_object_get(obj)) return EINA_FALSE;
2343      }
2344
2345    /* Return */
2346    *next = (Evas_Object *)obj;
2347    return !ELM_WIDGET_FOCUS_GET(obj);
2348 }
2349
2350 /**
2351  * @internal
2352  *
2353  * Get next object in focus chain of object tree in list.
2354  *
2355  * Get next object in focus chain of one object sub-tree ordered by one list.
2356  * Return the next object by reference. If don't have any candidate to receive
2357  * focus before list end, the first candidate will be returned.
2358  *
2359  * @param obj The widget root of sub-tree
2360  * @param dir Direction os focus chain
2361  * @param items list with ordered objects
2362  * @param list_data_get function to get the object from one item of list
2363  * @param next The next object in focus chain
2364  * @return EINA_TRUE if don't need focus chain restart/loop back
2365  *         to use 'next' obj.
2366  *
2367  * @ingroup Widget
2368  */
2369 EAPI Eina_Bool
2370 elm_widget_focus_list_next_get(const Evas_Object *obj,
2371                                const Eina_List *items,
2372                                void *(*list_data_get)(const Eina_List *list),
2373                                Elm_Focus_Direction dir,
2374                                Evas_Object **next)
2375 {
2376    Eina_List *(*list_next)(const Eina_List *list) = NULL;
2377
2378    if (!next)
2379      return EINA_FALSE;
2380    *next = NULL;
2381
2382    if (!_elm_widget_is(obj))
2383      return EINA_FALSE;
2384
2385    if (!items)
2386      return EINA_FALSE;
2387
2388    /* Direction */
2389    if (dir == ELM_FOCUS_PREVIOUS)
2390      {
2391         items = eina_list_last(items);
2392         list_next = eina_list_prev;
2393      }
2394    else if (dir == ELM_FOCUS_NEXT)
2395      list_next = eina_list_next;
2396    else
2397      return EINA_FALSE;
2398
2399    const Eina_List *l = items;
2400
2401    /* Recovery last focused sub item */
2402    if (ELM_WIDGET_FOCUS_GET(obj))
2403      {
2404         for (; l; l = list_next(l))
2405           {
2406              Evas_Object *cur = list_data_get(l);
2407              if (ELM_WIDGET_FOCUS_GET(cur)) break;
2408           }
2409
2410          /* Focused object, but no focused sub item */
2411          if (!l) l = items;
2412      }
2413
2414    const Eina_List *start = l;
2415    Evas_Object *to_focus = NULL;
2416
2417    /* Interate sub items */
2418    /* Go to end of list */
2419    for (; l; l = list_next(l))
2420      {
2421         Evas_Object *tmp = NULL;
2422         Evas_Object *cur = list_data_get(l);
2423
2424         if (elm_widget_parent_get(cur) != obj)
2425           continue;
2426
2427         /* Try Focus cycle in subitem */
2428         if (elm_widget_focus_next_get(cur, dir, &tmp))
2429           {
2430              *next = tmp;
2431              return EINA_TRUE;
2432           }
2433         else if ((tmp) && (!to_focus))
2434           to_focus = tmp;
2435      }
2436
2437    l = items;
2438
2439    /* Get First possible */
2440    for (; l != start; l = list_next(l))
2441      {
2442         Evas_Object *tmp = NULL;
2443         Evas_Object *cur = list_data_get(l);
2444
2445         if (elm_widget_parent_get(cur) != obj)
2446           continue;
2447
2448         /* Try Focus cycle in subitem */
2449         elm_widget_focus_next_get(cur, dir, &tmp);
2450         if (tmp)
2451           {
2452              *next = tmp;
2453              return EINA_FALSE;
2454           }
2455      }
2456
2457    *next = to_focus;
2458    return EINA_FALSE;
2459 }
2460
2461 EAPI Eina_Bool
2462 elm_widget_highlight_get(const Evas_Object *obj)
2463 {
2464    API_ENTRY return EINA_FALSE;
2465    return sd->highlighted;
2466 }
2467
2468 EAPI void
2469 elm_widget_parent_highlight_set(Evas_Object *obj,
2470                                 Eina_Bool highlighted)
2471 {
2472    API_ENTRY return;
2473
2474    highlighted = !!highlighted;
2475
2476    Evas_Object *o = elm_widget_parent_get(obj);
2477
2478    if (o) elm_widget_parent_highlight_set(o, highlighted);
2479
2480    sd->highlighted = highlighted;
2481 }
2482
2483 EAPI void
2484 elm_widget_signal_emit(Evas_Object *obj,
2485                        const char *emission,
2486                        const char *source)
2487 {
2488    API_ENTRY return;
2489
2490    if (evas_object_smart_type_check(obj, "elm_layout"))
2491      elm_layout_signal_emit(obj, emission, source);
2492    else if (evas_object_smart_type_check(obj, "elm_icon"))
2493      {
2494         WRN("Deprecated function. This functionality on icon objects"
2495             " will be dropped on a next release.");
2496         _elm_icon_signal_emit(obj, emission, source);
2497      }
2498 }
2499
2500 EAPI void
2501 elm_widget_signal_callback_add(Evas_Object *obj,
2502                                const char *emission,
2503                                const char *source,
2504                                Edje_Signal_Cb func,
2505                                void *data)
2506 {
2507    API_ENTRY return;
2508
2509    EINA_SAFETY_ON_NULL_RETURN(func);
2510
2511    if (evas_object_smart_type_check(obj, "elm_layout"))
2512      elm_layout_signal_callback_add(obj, emission, source, func, data);
2513    else if (evas_object_smart_type_check(obj, "elm_icon"))
2514      {
2515         WRN("Deprecated function. This functionality on icon objects"
2516             " will be dropped on a next release.");
2517
2518         _elm_icon_signal_callback_add(obj, emission, source, func, data);
2519      }
2520 }
2521
2522 EAPI void *
2523 elm_widget_signal_callback_del(Evas_Object *obj,
2524                                const char *emission,
2525                                const char *source,
2526                                Edje_Signal_Cb func)
2527 {
2528    void *data = NULL;
2529
2530    API_ENTRY return NULL;
2531
2532    if (evas_object_smart_type_check(obj, "elm_layout"))
2533      data = elm_layout_signal_callback_del(obj, emission, source, func);
2534    else if (evas_object_smart_type_check(obj, "elm_icon"))
2535      {
2536         WRN("Deprecated function. This functionality on icon objects"
2537             " will be dropped on a next release.");
2538
2539         data = _elm_icon_signal_callback_del(obj, emission, source, func);
2540      }
2541
2542    return data;
2543 }
2544
2545 EAPI void
2546 elm_widget_focus_set(Evas_Object *obj,
2547                      int first)
2548 {
2549    API_ENTRY return;
2550
2551    if (!sd->api) return;
2552
2553    if (!sd->focused)
2554      {
2555         focus_order++;
2556         sd->focus_order = focus_order;
2557         sd->focused = EINA_TRUE;
2558         sd->api->on_focus(obj);
2559      }
2560
2561    if (first)
2562      {
2563         if ((_is_focusable(sd->resize_obj)) &&
2564             (!elm_widget_disabled_get(sd->resize_obj)))
2565           {
2566              elm_widget_focus_set(sd->resize_obj, first);
2567           }
2568         else
2569           {
2570              const Eina_List *l;
2571              Evas_Object *child;
2572
2573              EINA_LIST_FOREACH(sd->subobjs, l, child)
2574                {
2575                   if ((_is_focusable(child)) &&
2576                       (!elm_widget_disabled_get(child)))
2577                     {
2578                        elm_widget_focus_set(child, first);
2579                        break;
2580                     }
2581                }
2582           }
2583      }
2584    else
2585      {
2586         const Eina_List *l;
2587         Evas_Object *child;
2588
2589         EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
2590           {
2591              if ((_is_focusable(child)) &&
2592                  (!elm_widget_disabled_get(child)))
2593                {
2594                   elm_widget_focus_set(child, first);
2595                   break;
2596                }
2597           }
2598         if (!l)
2599           {
2600              if ((_is_focusable(sd->resize_obj)) &&
2601                  (!elm_widget_disabled_get(sd->resize_obj)))
2602                {
2603                   elm_widget_focus_set(sd->resize_obj, first);
2604                }
2605           }
2606      }
2607 }
2608
2609 EAPI Evas_Object *
2610 elm_widget_parent_get(const Evas_Object *obj)
2611 {
2612    API_ENTRY return NULL;
2613    return sd->parent_obj;
2614 }
2615
2616 EAPI void
2617 elm_widget_focused_object_clear(Evas_Object *obj)
2618 {
2619    API_ENTRY return;
2620
2621    if (!sd->api) return;
2622
2623    if (!sd->focused) return;
2624
2625    // FIXME: evas_object_ref/unref is temporary code to fix logical issue.
2626    // After Eo is applied to elementary, remove these.
2627    evas_object_ref(obj);
2628    if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
2629      elm_widget_focused_object_clear(sd->resize_obj);
2630    else
2631      {
2632         const Eina_List *l;
2633         Evas_Object *child;
2634         EINA_LIST_FOREACH(sd->subobjs, l, child)
2635           {
2636              if (elm_widget_focus_get(child))
2637                {
2638                   elm_widget_focused_object_clear(child);
2639                   break;
2640                }
2641           }
2642      }
2643    sd->focused = EINA_FALSE;
2644    sd->api->on_focus(obj);
2645    evas_object_unref(obj);
2646 }
2647
2648 EAPI void
2649 elm_widget_focus_steal(Evas_Object *obj)
2650 {
2651    Evas_Object *parent, *parent2, *o;
2652    API_ENTRY return;
2653
2654    if (sd->focused) return;
2655    if (sd->disabled) return;
2656    if (!sd->can_focus) return;
2657    if (sd->tree_unfocusable) return;
2658    parent = obj;
2659    for (;; )
2660      {
2661         o = elm_widget_parent_get(parent);
2662         if (!o) break;
2663         sd = evas_object_smart_data_get(o);
2664         if (sd->disabled || sd->tree_unfocusable) return;
2665         if (sd->focused) break;
2666         parent = o;
2667      }
2668    if ((!elm_widget_parent_get(parent)) &&
2669        (!elm_widget_parent2_get(parent)))
2670      elm_widget_focused_object_clear(parent);
2671    else
2672      {
2673         parent2 = elm_widget_parent_get(parent);
2674         if (!parent2) parent2 = elm_widget_parent2_get(parent);
2675         parent = parent2;
2676         sd = evas_object_smart_data_get(parent);
2677         if (sd)
2678           {
2679              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2680                elm_widget_focused_object_clear(sd->resize_obj);
2681              else
2682                {
2683                   const Eina_List *l;
2684                   Evas_Object *child;
2685                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2686                     {
2687                        if (elm_widget_focus_get(child))
2688                          {
2689                             elm_widget_focused_object_clear(child);
2690                             break;
2691                          }
2692                     }
2693                }
2694           }
2695      }
2696    _parent_focus(obj);
2697    _elm_widget_focus_region_show(obj);
2698    return;
2699 }
2700
2701 EAPI void
2702 elm_widget_focus_restore(Evas_Object *obj)
2703 {
2704    Evas_Object *newest = NULL;
2705    unsigned int newest_focus_order = 0;
2706    API_ENTRY return;
2707
2708    newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2709    if (newest)
2710      {
2711         elm_object_focus_set(newest, EINA_FALSE);
2712         elm_object_focus_set(newest, EINA_TRUE);
2713      }
2714 }
2715
2716 void
2717 _elm_widget_top_win_focused_set(Evas_Object *obj,
2718                                 Eina_Bool top_win_focused)
2719 {
2720    const Eina_List *l;
2721    Evas_Object *child;
2722    API_ENTRY return;
2723
2724    if (sd->top_win_focused == top_win_focused) return;
2725    if (sd->resize_obj)
2726      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2727    EINA_LIST_FOREACH(sd->subobjs, l, child)
2728      {
2729         _elm_widget_top_win_focused_set(child, top_win_focused);
2730      }
2731    sd->top_win_focused = top_win_focused;
2732 }
2733
2734 Eina_Bool
2735 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2736 {
2737    API_ENTRY return EINA_FALSE;
2738    return sd->top_win_focused;
2739 }
2740
2741 EAPI void
2742 elm_widget_disabled_set(Evas_Object *obj,
2743                         Eina_Bool disabled)
2744 {
2745    API_ENTRY return;
2746
2747    if (sd->disabled == disabled) return;
2748    sd->disabled = !!disabled;
2749    elm_widget_focus_disabled_handle(obj);
2750    if (!sd->api) return;
2751    sd->api->disable(obj);
2752 }
2753
2754 EAPI Eina_Bool
2755 elm_widget_disabled_get(const Evas_Object *obj)
2756 {
2757    API_ENTRY return 0;
2758    return sd->disabled;
2759 }
2760
2761 EAPI void
2762 elm_widget_show_region_set(Evas_Object *obj,
2763                            Evas_Coord x,
2764                            Evas_Coord y,
2765                            Evas_Coord w,
2766                            Evas_Coord h,
2767                            Eina_Bool forceshow)
2768 {
2769    Evas_Object *parent_obj, *child_obj;
2770    Evas_Coord px, py, cx, cy;
2771
2772    API_ENTRY return;
2773
2774    evas_smart_objects_calculate(evas_object_evas_get(obj));
2775    ELM_WIDGET_CHECK_OR_RETURN(obj);
2776
2777    if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2778        (w == sd->rw) && (h == sd->rh)) return;
2779
2780    sd->rx = x;
2781    sd->ry = y;
2782    sd->rw = w;
2783    sd->rh = h;
2784    if (sd->on_show_region)
2785      sd->on_show_region
2786        (sd->on_show_region_data, obj);
2787
2788    do
2789      {
2790         parent_obj = sd->parent_obj;
2791         child_obj = sd->obj;
2792         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2793         sd = evas_object_smart_data_get(parent_obj);
2794         if (!sd) break;
2795
2796         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2797         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2798
2799         x += (cx - px);
2800         y += (cy - py);
2801         sd->rx = x;
2802         sd->ry = y;
2803         sd->rw = w;
2804         sd->rh = h;
2805
2806         if (sd->on_show_region)
2807           {
2808              sd->on_show_region
2809                (sd->on_show_region_data, parent_obj);
2810           }
2811      }
2812    while (parent_obj);
2813 }
2814
2815 EAPI void
2816 elm_widget_show_region_get(const Evas_Object *obj,
2817                            Evas_Coord *x,
2818                            Evas_Coord *y,
2819                            Evas_Coord *w,
2820                            Evas_Coord *h)
2821 {
2822    API_ENTRY return;
2823    if (x) *x = sd->rx;
2824    if (y) *y = sd->ry;
2825    if (w) *w = sd->rw;
2826    if (h) *h = sd->rh;
2827 }
2828
2829 /**
2830  * @internal
2831  *
2832  * Get the focus region of the given widget.
2833  *
2834  * @return show region or not
2835  * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
2836  *
2837  * The focus region is the area of a widget that should brought into the
2838  * visible area when the widget is focused. Mostly used to show the part of
2839  * an entry where the cursor is, for example. The area returned is relative
2840  * to the object @p obj.
2841  *
2842  * @param obj The widget object
2843  * @param x Where to store the x coordinate of the area
2844  * @param y Where to store the y coordinate of the area
2845  * @param w Where to store the width of the area
2846  * @param h Where to store the height of the area
2847  *
2848  * @ingroup Widget
2849  */
2850 EAPI Eina_Bool
2851 elm_widget_focus_region_get(const Evas_Object *obj,
2852                             Evas_Coord *x,
2853                             Evas_Coord *y,
2854                             Evas_Coord *w,
2855                             Evas_Coord *h)
2856 {
2857    API_ENTRY return EINA_FALSE;
2858    if (!sd->api->on_focus_region(obj, x, y, w, h))
2859      {
2860         evas_object_geometry_get(obj, NULL, NULL, w, h);
2861         if (x) *x = 0;
2862         if (y) *y = 0;
2863      }
2864    return EINA_TRUE;
2865 }
2866
2867 EAPI Eina_List *
2868 elm_widget_scrollable_children_get(Evas_Object *obj)
2869 {
2870    Eina_List *l, *ret = NULL;
2871    Evas_Object *child;
2872
2873    API_ENTRY return NULL;
2874
2875    EINA_LIST_FOREACH(sd->subobjs, l, child)
2876      {
2877         if (_elm_scrollable_is(child))
2878           ret = eina_list_append(ret, child);
2879      }
2880
2881    return ret;
2882 }
2883
2884 EAPI void
2885 elm_widget_scroll_hold_push(Evas_Object *obj)
2886 {
2887    API_ENTRY return;
2888    sd->scroll_hold++;
2889    if (sd->scroll_hold == 1)
2890      {
2891         if (_elm_scrollable_is(obj))
2892           {
2893              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
2894              s_iface->hold_set(obj, EINA_TRUE);
2895           }
2896         else
2897           {
2898              Eina_List *scr_children, *l;
2899              Evas_Object *child;
2900
2901              scr_children = elm_widget_scrollable_children_get(obj);
2902              EINA_LIST_FOREACH(scr_children, l, child)
2903                {
2904                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
2905                   s_iface->hold_set(child, EINA_TRUE);
2906                }
2907              eina_list_free(scr_children);
2908           }
2909      }
2910    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2911    // FIXME: on delete/reparent hold pop
2912 }
2913
2914 EAPI void
2915 elm_widget_scroll_hold_pop(Evas_Object *obj)
2916 {
2917    API_ENTRY return;
2918    sd->scroll_hold--;
2919    if (!sd->scroll_hold)
2920      {
2921         if (_elm_scrollable_is(obj))
2922           {
2923              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
2924              s_iface->hold_set(obj, EINA_FALSE);
2925           }
2926         else
2927           {
2928              Eina_List *scr_children, *l;
2929              Evas_Object *child;
2930
2931              scr_children = elm_widget_scrollable_children_get(obj);
2932              EINA_LIST_FOREACH(scr_children, l, child)
2933                {
2934                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
2935                   s_iface->hold_set(child, EINA_FALSE);
2936                }
2937              eina_list_free(scr_children);
2938           }
2939      }
2940    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2941    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2942 }
2943
2944 EAPI int
2945 elm_widget_scroll_hold_get(const Evas_Object *obj)
2946 {
2947    API_ENTRY return 0;
2948    return sd->scroll_hold;
2949 }
2950
2951 EAPI void
2952 elm_widget_scroll_freeze_push(Evas_Object *obj)
2953 {
2954    API_ENTRY return;
2955    sd->scroll_freeze++;
2956    if (sd->scroll_freeze == 1)
2957      {
2958         if (_elm_scrollable_is(obj))
2959           {
2960              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
2961              s_iface->freeze_set(obj, EINA_TRUE);
2962           }
2963         else
2964           {
2965              Eina_List *scr_children, *l;
2966              Evas_Object *child;
2967
2968              scr_children = elm_widget_scrollable_children_get(obj);
2969              EINA_LIST_FOREACH(scr_children, l, child)
2970                {
2971                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
2972                   s_iface->freeze_set(child, EINA_TRUE);
2973                }
2974              eina_list_free(scr_children);
2975           }
2976      }
2977    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2978    // FIXME: on delete/reparent freeze pop
2979 }
2980
2981 EAPI void
2982 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2983 {
2984    API_ENTRY return;
2985    sd->scroll_freeze--;
2986    if (!sd->scroll_freeze)
2987      {
2988         if (_elm_scrollable_is(obj))
2989           {
2990              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
2991              s_iface->freeze_set(obj, EINA_FALSE);
2992           }
2993         else
2994           {
2995              Eina_List *scr_children, *l;
2996              Evas_Object *child;
2997
2998              scr_children = elm_widget_scrollable_children_get(obj);
2999              EINA_LIST_FOREACH(scr_children, l, child)
3000                {
3001                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3002                   s_iface->freeze_set(child, EINA_FALSE);
3003                }
3004              eina_list_free(scr_children);
3005           }
3006      }
3007    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
3008    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3009 }
3010
3011 EAPI int
3012 elm_widget_scroll_freeze_get(const Evas_Object *obj)
3013 {
3014    API_ENTRY return 0;
3015    return sd->scroll_freeze;
3016 }
3017
3018 EAPI void
3019 elm_widget_scale_set(Evas_Object *obj,
3020                      double scale)
3021 {
3022    API_ENTRY return;
3023    if (scale <= 0.0) scale = 0.0;
3024    if (sd->scale != scale)
3025      {
3026         sd->scale = scale;
3027         elm_widget_theme(obj);
3028      }
3029 }
3030
3031 EAPI double
3032 elm_widget_scale_get(const Evas_Object *obj)
3033 {
3034    API_ENTRY return 1.0;
3035    // FIXME: save walking up the tree by storing/caching parent scale
3036    if (sd->scale == 0.0)
3037      {
3038         if (sd->parent_obj)
3039           return elm_widget_scale_get(sd->parent_obj);
3040         else
3041           return 1.0;
3042      }
3043    return sd->scale;
3044 }
3045
3046 EAPI void
3047 elm_widget_theme_set(Evas_Object *obj,
3048                      Elm_Theme *th)
3049 {
3050    API_ENTRY return;
3051    if (sd->theme != th)
3052      {
3053         if (sd->theme) elm_theme_free(sd->theme);
3054         sd->theme = th;
3055         if (th) th->ref++;
3056         elm_widget_theme(obj);
3057      }
3058 }
3059
3060 EAPI void
3061 elm_widget_text_part_set(Evas_Object *obj,
3062                          const char *part,
3063                          const char *label)
3064 {
3065    API_ENTRY return;
3066
3067    if (evas_object_smart_type_check(obj, "elm_layout"))
3068      elm_layout_text_set(obj, part, label);
3069 }
3070
3071 EAPI const char *
3072 elm_widget_text_part_get(const Evas_Object *obj,
3073                          const char *part)
3074 {
3075    API_ENTRY return NULL;
3076
3077    if (evas_object_smart_type_check(obj, "elm_layout"))
3078      return elm_layout_text_get(obj, part);
3079
3080    return NULL;
3081 }
3082
3083 EAPI void
3084 elm_widget_domain_translatable_text_part_set(Evas_Object *obj,
3085                                              const char *part,
3086                                              const char *domain,
3087                                              const char *label)
3088 {
3089    const char *str;
3090    Eina_List *l;
3091    Elm_Translate_String_Data *ts = NULL;
3092    API_ENTRY return;
3093
3094    str = eina_stringshare_add(part);
3095    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3096      if (ts->id == str)
3097        break;
3098      else
3099        ts = NULL;
3100
3101    if (!ts && !label)
3102      eina_stringshare_del(str);
3103    else if (!ts)
3104      {
3105         ts = malloc(sizeof(Elm_Translate_String_Data));
3106         if (!ts) return;
3107
3108         ts->id = str;
3109         ts->domain = eina_stringshare_add(domain);
3110         ts->string = eina_stringshare_add(label);
3111         sd->translate_strings = eina_list_append(sd->translate_strings, ts);
3112      }
3113    else
3114      {
3115         if (label)
3116           {
3117              eina_stringshare_replace(&ts->domain, domain);
3118              eina_stringshare_replace(&ts->string, label);
3119           }
3120         else
3121           {
3122              sd->translate_strings = eina_list_remove_list(
3123                  sd->translate_strings, l);
3124              eina_stringshare_del(ts->id);
3125              eina_stringshare_del(ts->domain);
3126              eina_stringshare_del(ts->string);
3127              free(ts);
3128           }
3129         eina_stringshare_del(str);
3130      }
3131
3132 #ifdef HAVE_GETTEXT
3133    if (label && label[0])
3134      label = dgettext(domain, label);
3135 #endif
3136    elm_widget_text_part_set(obj, part, label);
3137 }
3138
3139 EAPI const char *
3140 elm_widget_translatable_text_part_get(const Evas_Object *obj,
3141                                       const char *part)
3142 {
3143    const char *str, *ret = NULL;
3144    Eina_List *l;
3145    Elm_Translate_String_Data *ts;
3146    API_ENTRY return NULL;
3147
3148    str = eina_stringshare_add(part);
3149    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3150      if (ts->id == str)
3151        {
3152           ret = ts->string;
3153           break;
3154        }
3155    eina_stringshare_del(str);
3156    return ret;
3157 }
3158
3159 EAPI void
3160 elm_widget_translate(Evas_Object *obj)
3161 {
3162    const Eina_List *l;
3163    Evas_Object *child;
3164 #ifdef HAVE_GETTEXT
3165    Elm_Translate_String_Data *ts;
3166 #endif
3167
3168    API_ENTRY return;
3169
3170    EINA_LIST_FOREACH(sd->subobjs, l, child)
3171      elm_widget_translate(child);
3172    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
3173    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3174    if (!sd->api) return;
3175    sd->api->translate(obj);
3176
3177 #ifdef HAVE_GETTEXT
3178    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3179      {
3180         const char *s = dgettext(ts->domain, ts->string);
3181         elm_widget_text_part_set(obj, ts->id, s);
3182      }
3183 #endif
3184 }
3185
3186 EAPI void
3187 elm_widget_content_part_set(Evas_Object *obj,
3188                             const char *part,
3189                             Evas_Object *content)
3190 {
3191    API_ENTRY return;
3192
3193    if (!sd->api) return;
3194    if (evas_object_smart_type_check(obj, "elm_container"))
3195      ELM_CONTAINER_CLASS(sd->api)->content_set(obj, part, content);
3196 }
3197
3198 EAPI Evas_Object *
3199 elm_widget_content_part_get(const Evas_Object *obj,
3200                             const char *part)
3201 {
3202    API_ENTRY return NULL;
3203
3204    if (!sd->api) return NULL;
3205
3206    if (evas_object_smart_type_check(obj, "elm_container"))
3207      return ELM_CONTAINER_CLASS(sd->api)->content_get(obj, part);
3208
3209    return NULL;
3210 }
3211
3212 EAPI Evas_Object *
3213 elm_widget_content_part_unset(Evas_Object *obj,
3214                               const char *part)
3215 {
3216    API_ENTRY return NULL;
3217
3218    if (!sd->api) return NULL;
3219    if (evas_object_smart_type_check(obj, "elm_container"))
3220      return ELM_CONTAINER_CLASS(sd->api)->content_unset(obj, part);
3221
3222    return NULL;
3223 }
3224
3225 EAPI void
3226 elm_widget_access_info_set(Evas_Object *obj,
3227                            const char *txt)
3228 {
3229    API_ENTRY return;
3230    if (sd->access_info) eina_stringshare_del(sd->access_info);
3231    if (!txt) sd->access_info = NULL;
3232    else sd->access_info = eina_stringshare_add(txt);
3233 }
3234
3235 EAPI const char *
3236 elm_widget_access_info_get(const Evas_Object *obj)
3237 {
3238    API_ENTRY return NULL;
3239    return sd->access_info;
3240 }
3241
3242 EAPI Elm_Theme *
3243 elm_widget_theme_get(const Evas_Object *obj)
3244 {
3245    API_ENTRY return NULL;
3246    if (!sd->theme)
3247      {
3248         if (sd->parent_obj)
3249           return elm_widget_theme_get(sd->parent_obj);
3250         else
3251           return NULL;
3252      }
3253    return sd->theme;
3254 }
3255
3256 EAPI Eina_Bool
3257 elm_widget_style_set(Evas_Object *obj,
3258                      const char *style)
3259 {
3260    API_ENTRY return EINA_FALSE;
3261
3262    if (eina_stringshare_replace(&sd->style, style))
3263      return elm_widget_theme(obj);
3264
3265    return EINA_TRUE;
3266 }
3267
3268 EAPI const char *
3269 elm_widget_style_get(const Evas_Object *obj)
3270 {
3271    API_ENTRY return NULL;
3272    if (sd->style) return sd->style;
3273    return "default";
3274 }
3275
3276 EAPI void
3277 elm_widget_tooltip_add(Evas_Object *obj,
3278                        Elm_Tooltip *tt)
3279 {
3280    API_ENTRY return;
3281    sd->tooltips = eina_list_append(sd->tooltips, tt);
3282 }
3283
3284 EAPI void
3285 elm_widget_tooltip_del(Evas_Object *obj,
3286                        Elm_Tooltip *tt)
3287 {
3288    API_ENTRY return;
3289    sd->tooltips = eina_list_remove(sd->tooltips, tt);
3290 }
3291
3292 EAPI void
3293 elm_widget_cursor_add(Evas_Object *obj,
3294                       Elm_Cursor *cur)
3295 {
3296    API_ENTRY return;
3297    sd->cursors = eina_list_append(sd->cursors, cur);
3298 }
3299
3300 EAPI void
3301 elm_widget_cursor_del(Evas_Object *obj,
3302                       Elm_Cursor *cur)
3303 {
3304    API_ENTRY return;
3305    sd->cursors = eina_list_remove(sd->cursors, cur);
3306 }
3307
3308 EAPI void
3309 elm_widget_drag_lock_x_set(Evas_Object *obj,
3310                            Eina_Bool lock)
3311 {
3312    API_ENTRY return;
3313    if (sd->drag_x_locked == lock) return;
3314    sd->drag_x_locked = lock;
3315    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
3316    else _propagate_x_drag_lock(obj, -1);
3317 }
3318
3319 EAPI void
3320 elm_widget_drag_lock_y_set(Evas_Object *obj,
3321                            Eina_Bool lock)
3322 {
3323    API_ENTRY return;
3324    if (sd->drag_y_locked == lock) return;
3325    sd->drag_y_locked = lock;
3326    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
3327    else _propagate_y_drag_lock(obj, -1);
3328 }
3329
3330 EAPI Eina_Bool
3331 elm_widget_drag_lock_x_get(const Evas_Object *obj)
3332 {
3333    API_ENTRY return EINA_FALSE;
3334    return sd->drag_x_locked;
3335 }
3336
3337 EAPI Eina_Bool
3338 elm_widget_drag_lock_y_get(const Evas_Object *obj)
3339 {
3340    API_ENTRY return EINA_FALSE;
3341    return sd->drag_y_locked;
3342 }
3343
3344 EAPI int
3345 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
3346 {
3347    API_ENTRY return 0;
3348    return sd->child_drag_x_locked;
3349 }
3350
3351 EAPI int
3352 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
3353 {
3354    API_ENTRY return 0;
3355    return sd->child_drag_y_locked;
3356 }
3357
3358 EAPI Eina_Bool
3359 elm_widget_theme_object_set(Evas_Object *obj,
3360                             Evas_Object *edj,
3361                             const char *wname,
3362                             const char *welement,
3363                             const char *wstyle)
3364 {
3365    API_ENTRY return EINA_FALSE;
3366    char buf[128];
3367    int ret;
3368
3369    if (!_elm_theme_object_set(obj, edj, wname, welement, wstyle))
3370      return EINA_FALSE;
3371
3372    if (sd->orient_mode != -1)
3373      {
3374
3375         snprintf(buf, sizeof(buf), "elm,state,orient,%d", ret);
3376         elm_widget_signal_emit(obj, buf, "elm");
3377
3378      }
3379    return EINA_TRUE;
3380 }
3381
3382 EAPI Eina_Bool
3383 elm_widget_is_check(const Evas_Object *obj)
3384 {
3385    static int abort_on_warn = -1;
3386    if (elm_widget_is(obj))
3387      return EINA_TRUE;
3388
3389    ERR("Passing Object: %p.", obj);
3390    if (abort_on_warn == -1)
3391      {
3392         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3393         else abort_on_warn = 0;
3394      }
3395    if (abort_on_warn == 1) abort();
3396    return EINA_FALSE;
3397 }
3398
3399 EAPI const char *
3400 elm_widget_type_get(const Evas_Object *obj)
3401 {
3402    API_ENTRY return NULL;
3403
3404    return evas_object_type_get(obj);
3405 }
3406
3407 EAPI Eina_Bool
3408 elm_widget_type_check(const Evas_Object *obj,
3409                       const char *type,
3410                       const char *func)
3411 {
3412    const char *provided, *expected = "(unknown)";
3413    static int abort_on_warn = -1;
3414
3415    provided = elm_widget_type_get(obj);
3416    /* TODO: eventually migrate to check_ptr version */
3417    if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
3418    if (type) expected = type;
3419    if ((!provided) || (!provided[0]))
3420      {
3421         provided = evas_object_type_get(obj);
3422         if ((!provided) || (!provided[0]))
3423           provided = "(unknown)";
3424      }
3425    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
3426        " type: '%s'", obj, func, provided, expected);
3427    if (abort_on_warn == -1)
3428      {
3429         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3430         else abort_on_warn = 0;
3431      }
3432    if (abort_on_warn == 1) abort();
3433    return EINA_FALSE;
3434 }
3435
3436 static Evas_Object *
3437 _widget_name_find(const Evas_Object *obj,
3438                   const char *name,
3439                   int recurse)
3440 {
3441    Eina_List *l;
3442    Evas_Object *child;
3443    const char *s;
3444    INTERNAL_ENTRY NULL;
3445
3446    if (!_elm_widget_is(obj)) return NULL;
3447    if (sd->resize_obj)
3448      {
3449         s = evas_object_name_get(sd->resize_obj);
3450         if ((s) && (!strcmp(s, name))) return sd->resize_obj;
3451         if ((recurse != 0) &&
3452             ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
3453           return child;
3454      }
3455    EINA_LIST_FOREACH(sd->subobjs, l, child)
3456      {
3457         s = evas_object_name_get(child);
3458         if ((s) && (!strcmp(s, name))) return child;
3459         if ((recurse != 0) &&
3460             ((child = _widget_name_find(child, name, recurse - 1))))
3461           return child;
3462      }
3463    if (sd->hover_obj)
3464      {
3465         s = evas_object_name_get(sd->hover_obj);
3466         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
3467         if ((recurse != 0) &&
3468             ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
3469           return child;
3470      }
3471    return NULL;
3472 }
3473
3474 EAPI Evas_Object *
3475 elm_widget_name_find(const Evas_Object *obj,
3476                      const char *name,
3477                      int recurse)
3478 {
3479    API_ENTRY return NULL;
3480    if (!name) return NULL;
3481    return _widget_name_find(obj, name, recurse);
3482 }
3483
3484 EAPI void
3485 elm_widget_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3486 {
3487    int orient_mode = -1;
3488
3489    API_ENTRY return;
3490
3491    if (disabled && (sd->orient_mode == -1)) return;
3492    if (!disabled && (sd->orient_mode != -1)) return;
3493
3494    if (!disabled)
3495      {
3496         //Get current orient mode from it's parent otherwise, 0.
3497         sd->orient_mode = 0;
3498         ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
3499         if (!sd_parent) orient_mode = 0;
3500         else orient_mode = sd_parent->orient_mode;
3501      }
3502    elm_widget_orientation_set(obj, orient_mode);
3503 }
3504
3505 EAPI Eina_Bool
3506 elm_widget_orientation_mode_disabled_get(const Evas_Object *obj)
3507 {
3508    Eina_Bool ret;
3509
3510    API_ENTRY return EINA_FALSE;
3511
3512    if (sd->orient_mode == -1) ret = EINA_TRUE;
3513    else ret = EINA_FALSE;
3514    return ret;
3515 }
3516
3517 EAPI void
3518 elm_widget_orientation_set(Evas_Object *obj, int rotation)
3519 {
3520    Evas_Object *child;
3521    Eina_List *l;
3522
3523    API_ENTRY return;
3524
3525    if ((sd->orient_mode == rotation) || (sd->orient_mode == -1)) return;
3526
3527    sd->orient_mode = rotation;
3528
3529    EINA_LIST_FOREACH (sd->subobjs, l, child)
3530      elm_widget_orientation_set(child, rotation);
3531
3532    if (rotation != -1)
3533      {
3534         char buf[128];
3535         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3536         elm_widget_signal_emit(obj, buf, "elm");
3537      }
3538 }
3539
3540 /**
3541  * @internal
3542  *
3543  * Split string in words
3544  *
3545  * @param str Source string
3546  * @return List of const words
3547  *
3548  * @see elm_widget_stringlist_free()
3549  * @ingroup Widget
3550  */
3551 EAPI Eina_List *
3552 elm_widget_stringlist_get(const char *str)
3553 {
3554    Eina_List *list = NULL;
3555    const char *s, *b;
3556    if (!str) return NULL;
3557    for (b = s = str; 1; s++)
3558      {
3559         if ((*s == ' ') || (!*s))
3560           {
3561              char *t = malloc(s - b + 1);
3562              if (t)
3563                {
3564                   strncpy(t, b, s - b);
3565                   t[s - b] = 0;
3566                   list = eina_list_append(list, eina_stringshare_add(t));
3567                   free(t);
3568                }
3569              b = s + 1;
3570           }
3571         if (!*s) break;
3572      }
3573    return list;
3574 }
3575
3576 EAPI void
3577 elm_widget_stringlist_free(Eina_List *list)
3578 {
3579    const char *s;
3580    EINA_LIST_FREE (list, s)
3581      eina_stringshare_del(s);
3582 }
3583
3584 EAPI void
3585 elm_widget_focus_hide_handle(Evas_Object *obj)
3586 {
3587    if (!_elm_widget_is(obj))
3588      return;
3589    _if_focused_revert(obj, EINA_TRUE);
3590 }
3591
3592 EAPI void
3593 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
3594 {
3595    Evas_Object *o = obj;
3596    do
3597      {
3598         if (_elm_widget_is(o)) break;
3599         o = evas_object_smart_parent_get(o);
3600      }
3601    while (o);
3602    if (!o) return;
3603    if (!_is_focusable(o)) return;
3604    elm_widget_focus_steal(o);
3605 }
3606
3607 EAPI void
3608 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
3609 {
3610    API_ENTRY return;
3611
3612    //FIXME: Need to check whether the object is unfocusable or not.
3613
3614    if (!elm_widget_parent_get(obj))
3615      elm_widget_focused_object_clear(obj);
3616    else
3617      _if_focused_revert(obj, EINA_TRUE);
3618 }
3619
3620 EAPI void
3621 elm_widget_focus_disabled_handle(Evas_Object *obj)
3622 {
3623    API_ENTRY return;
3624
3625    elm_widget_focus_tree_unfocusable_handle(obj);
3626 }
3627
3628 EAPI unsigned int
3629 elm_widget_focus_order_get(const Evas_Object *obj)
3630 {
3631    API_ENTRY return 0;
3632    return sd->focus_order;
3633 }
3634
3635 EAPI Evas_Object *
3636 elm_widget_newest_focus_order_get(const Evas_Object *obj,
3637                                   unsigned int *newest_focus_order,
3638                                   Eina_Bool can_focus_only)
3639 {
3640    const Eina_List *l;
3641    Evas_Object *child, *ret, *best;
3642
3643    API_ENTRY return NULL;
3644
3645    if (!evas_object_visible_get(obj)
3646        || (elm_widget_disabled_get(obj))
3647        || (elm_widget_tree_unfocusable_get(obj)))
3648      return NULL;
3649
3650    best = NULL;
3651    if (*newest_focus_order < sd->focus_order)
3652      {
3653         *newest_focus_order = sd->focus_order;
3654         best = (Evas_Object *)obj;
3655      }
3656    EINA_LIST_FOREACH(sd->subobjs, l, child)
3657      {
3658         ret = elm_widget_newest_focus_order_get
3659            (child, newest_focus_order, can_focus_only);
3660         if (!ret) continue;
3661         best = ret;
3662      }
3663    if (can_focus_only)
3664      {
3665         if ((!best) || (!elm_widget_can_focus_get(best)))
3666           return NULL;
3667      }
3668    return best;
3669 }
3670
3671 EAPI void
3672 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
3673 {
3674    Evas_Object *parent;
3675    Eina_Bool ret;
3676
3677    API_ENTRY return;
3678
3679    ret = EINA_FALSE;
3680    if (sd->api->activate)
3681      ret = sd->api->activate(obj, act);
3682
3683    if (ret) return;
3684
3685    parent = elm_widget_parent_get(obj);
3686    if (parent)
3687      elm_widget_activate(parent, act);
3688
3689    return;
3690 }
3691
3692 /**
3693  * @internal
3694  *
3695  * Returns the widget's Evas_Display_Mode
3696  *
3697  * @param obj The widget.
3698  * @return Evas_Display_Mode of the object.
3699  *
3700  * @see elm_widget_display_mode_set().
3701  * @ingroup Widget
3702  **/
3703 EAPI Evas_Display_Mode
3704 elm_widget_display_mode_get(const Evas_Object *obj)
3705 {
3706    Evas_Display_Mode new_mode;
3707    Evas_Object *parent;
3708
3709    API_ENTRY return EVAS_DISPLAY_MODE_NONE;
3710
3711    new_mode = evas_object_size_hint_display_mode_get(obj);
3712    parent = elm_widget_parent_get(obj);
3713
3714    if ((new_mode == EVAS_DISPLAY_MODE_INHERIT) && parent)
3715      return elm_widget_display_mode_get(parent);
3716    return new_mode;
3717
3718 }
3719
3720 /**
3721  * @internal
3722  *
3723  * Sets the widget and child widget's Evas_Display_Mode.
3724  *
3725  * @param obj The widget.
3726  * @param dispmode Evas_Display_Mode to set widget's mode.
3727  *
3728  * Widgets are resized by several reasons.
3729  * Evas_Display_Mode can help for widgets to get one more reason of resize.
3730  * For example, elm conform widget resizes it's contents when keypad state changed.
3731  * After keypad showing, conform widget can change child's Evas_Display_Mode.
3732  * @ingroup Widget
3733  */
3734 EAPI void
3735 elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode)
3736 {
3737    Evas_Display_Mode child_mode;
3738    Evas_Object *child;
3739    Eina_List *l;
3740
3741    API_ENTRY return;
3742
3743    if (elm_widget_display_mode_get(obj) == dispmode) return;
3744    evas_object_size_hint_display_mode_set(obj, dispmode);
3745
3746    //TODO: Need to deal with EVAS_DISPLAY_MODE_INHERIT efficiently.
3747    EINA_LIST_FOREACH (sd->subobjs, l, child)
3748      {
3749         child_mode = evas_object_size_hint_display_mode_get(child);
3750         if (child_mode != EVAS_DISPLAY_MODE_DONT_CHANGE)
3751           {
3752              elm_widget_display_mode_set(child, dispmode);
3753           }
3754      }
3755
3756 }
3757
3758 // temporary code. should be removed after eo is applied.
3759 EAPI void
3760 _elm_widget_orient_signal_emit(Evas_Object *obj)
3761 {
3762    ELM_WIDGET_DATA_GET(obj, sd);
3763    char buf[128];
3764    if (sd->orient_mode > 0)
3765      {
3766         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3767         elm_widget_signal_emit(obj, buf, "elm");
3768      }
3769 }
3770
3771 /**
3772  * @internal
3773  *
3774  * Allocate a new Elm_Widget_Item-derived structure.
3775  *
3776  * The goal of this structure is to provide common ground for actions
3777  * that a widget item have, such as the owner widget, callback to
3778  * notify deletion, data pointer and maybe more.
3779  *
3780  * @param widget the owner widget that holds this item, must be an elm_widget!
3781  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
3782  *        be used to allocate memory.
3783  *
3784  * @return allocated memory that is already zeroed out, or NULL on errors.
3785  *
3786  * @see elm_widget_item_new() convenience macro.
3787  * @see elm_widget_item_del() to release memory.
3788  * @ingroup Widget
3789  */
3790 EAPI Elm_Widget_Item *
3791 _elm_widget_item_new(Evas_Object *widget,
3792                      size_t alloc_size)
3793 {
3794    if (!_elm_widget_is(widget))
3795      return NULL;
3796
3797    Elm_Widget_Item *item;
3798
3799    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
3800    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
3801
3802    item = calloc(1, alloc_size);
3803    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
3804
3805    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
3806    item->widget = widget;
3807    return item;
3808 }
3809
3810 EAPI void
3811 _elm_widget_item_free(Elm_Widget_Item *item)
3812 {
3813    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3814
3815    if (item->del_func)
3816      item->del_func((void *)item->data, item->widget, item);
3817
3818    if (item->view)
3819      evas_object_del(item->view);
3820
3821    if (item->access_info)
3822      eina_stringshare_del(item->access_info);
3823
3824    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
3825    free(item);
3826 }
3827
3828 /**
3829  * @internal
3830  *
3831  * Releases widget item memory, calling back del_cb() if it exists.
3832  *
3833  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
3834  * to memory release. Note that elm_widget_item_pre_notify_del() calls
3835  * this function and then unset it, thus being useful for 2 step
3836  * cleanup whenever the del_cb may use any of the data that must be
3837  * deleted from item.
3838  *
3839  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
3840  * is presented!
3841  *
3842  * @param item a valid #Elm_Widget_Item to be deleted.
3843  * @see elm_widget_item_del() convenience macro.
3844  * @ingroup Widget
3845  */
3846 EAPI void
3847 _elm_widget_item_del(Elm_Widget_Item *item)
3848 {
3849    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3850    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3851    item->on_deletion = EINA_TRUE;
3852
3853    //Widget item delete callback
3854    if (item->del_pre_func)
3855       if (item->del_pre_func((Elm_Object_Item *)item))
3856          _elm_widget_item_free(item);
3857  }
3858
3859 /**
3860  * @internal
3861  *
3862  * Set the function to notify to widgets when item is being deleted by user.
3863  *
3864  * @param item a valid #Elm_Widget_Item to be notified
3865  * @see elm_widget_item_del_pre_hook_set() convenience macro.
3866  * @ingroup Widget
3867  */
3868 EAPI void
3869 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item,
3870                                   Elm_Widget_Del_Pre_Cb func)
3871 {
3872    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3873    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3874    item->del_pre_func = func;
3875 }
3876
3877 /**
3878  * @internal
3879  *
3880  * Notify object will be deleted without actually deleting it.
3881  *
3882  * This function will callback Elm_Widget_Item::del_cb if it is set
3883  * and then unset it so it is not called twice (ie: from
3884  * elm_widget_item_del()).
3885  *
3886  * @param item a valid #Elm_Widget_Item to be notified
3887  * @see elm_widget_item_pre_notify_del() convenience macro.
3888  * @ingroup Widget
3889  */
3890 EAPI void
3891 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
3892 {
3893    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3894    if (!item->del_func) return;
3895    item->del_func((void *)item->data, item->widget, item);
3896    item->del_func = NULL;
3897 }
3898
3899 /**
3900  * @internal
3901  *
3902  * Set the function to notify when item is being deleted.
3903  *
3904  * This function will complain if there was a callback set already,
3905  * however it will set the new one.
3906  *
3907  * The callback will be called from elm_widget_item_pre_notify_del()
3908  * or elm_widget_item_del() will be called with:
3909  *   - data: the Elm_Widget_Item::data value.
3910  *   - obj: the Elm_Widget_Item::widget evas object.
3911  *   - event_info: the item being deleted.
3912  *
3913  * @param item a valid #Elm_Widget_Item to be notified
3914  * @see elm_widget_item_del_cb_set() convenience macro.
3915  * @ingroup Widget
3916  */
3917 EAPI void
3918 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
3919                             Evas_Smart_Cb func)
3920 {
3921    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3922    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3923
3924    if ((item->del_func) && (item->del_func != func))
3925      WRN("You're replacing a previously set del_cb %p of item %p with %p",
3926          item->del_func, item, func);
3927
3928    item->del_func = func;
3929 }
3930
3931 /**
3932  * @internal
3933  *
3934  * Retrieves owner widget of this item.
3935  *
3936  * @param item a valid #Elm_Widget_Item to get data from.
3937  * @return owner widget of this item.
3938  * @ingroup Widget
3939  */
3940 EAPI Evas_Object *
3941 _elm_widget_item_widget_get(const Elm_Widget_Item *item)
3942 {
3943    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3944    return item->widget;
3945 }
3946
3947 /**
3948  * @internal
3949  *
3950  * Set user-data in this item.
3951  *
3952  * User data may be used to identify this item or just store any
3953  * application data. It is automatically given as the first parameter
3954  * of the deletion notify callback.
3955  *
3956  * @param item a valid #Elm_Widget_Item to store data in.
3957  * @param data user data to store.
3958  * @see elm_widget_item_del_cb_set() convenience macro.
3959  * @ingroup Widget
3960  */
3961 EAPI void
3962 _elm_widget_item_data_set(Elm_Widget_Item *item,
3963                           const void *data)
3964 {
3965    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3966    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3967
3968    if ((item->data) && (item->data != data))
3969      DBG("Replacing item %p data %p with %p", item, item->data, data);
3970    item->data = data;
3971 }
3972
3973 /**
3974  * @internal
3975  *
3976  * Retrieves user-data of this item.
3977  *
3978  * @param item a valid #Elm_Widget_Item to get data from.
3979  * @see elm_widget_item_data_set()
3980  * @ingroup Widget
3981  */
3982 EAPI void *
3983 _elm_widget_item_data_get(const Elm_Widget_Item *item)
3984 {
3985    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3986    return (void *)item->data;
3987 }
3988
3989 EAPI void
3990 _elm_widget_item_disabled_set(Elm_Widget_Item *item,
3991                               Eina_Bool disabled)
3992 {
3993    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3994    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
3995
3996    if (item->disabled == disabled) return;
3997    item->disabled = !!disabled;
3998    if (item->disable_func) item->disable_func(item);
3999 }
4000
4001 EAPI Eina_Bool
4002 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
4003 {
4004    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4005    return item->disabled;
4006 }
4007
4008 EAPI void
4009 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
4010                                   Elm_Widget_Disable_Cb func)
4011 {
4012    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4013    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4014
4015    item->disable_func = func;
4016 }
4017
4018 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4019
4020 struct _Elm_Widget_Item_Tooltip
4021 {
4022    Elm_Widget_Item            *item;
4023    Elm_Tooltip_Item_Content_Cb func;
4024    Evas_Smart_Cb               del_cb;
4025    const void                 *data;
4026 };
4027
4028 static Evas_Object *
4029 _elm_widget_item_tooltip_label_create(void *data,
4030                                       Evas_Object *obj __UNUSED__,
4031                                       Evas_Object *tooltip,
4032                                       void *item __UNUSED__)
4033 {
4034    Evas_Object *label = elm_label_add(tooltip);
4035    if (!label)
4036      return NULL;
4037    elm_object_style_set(label, "tooltip");
4038    elm_object_text_set(label, data);
4039    return label;
4040 }
4041
4042 static Evas_Object *
4043 _elm_widget_item_tooltip_trans_label_create(void *data,
4044                                             Evas_Object *obj __UNUSED__,
4045                                             Evas_Object *tooltip,
4046                                             void *item __UNUSED__)
4047 {
4048    Evas_Object *label = elm_label_add(tooltip);
4049    if (!label)
4050      return NULL;
4051    elm_object_style_set(label, "tooltip");
4052    elm_object_translatable_text_set(label, data);
4053    return label;
4054 }
4055
4056 static void
4057 _elm_widget_item_tooltip_label_del_cb(void *data,
4058                                       Evas_Object *obj __UNUSED__,
4059                                       void *event_info __UNUSED__)
4060 {
4061    eina_stringshare_del(data);
4062 }
4063
4064 /**
4065  * @internal
4066  *
4067  * Set the text to be shown in the widget item.
4068  *
4069  * @param item Target item
4070  * @param text The text to set in the content
4071  *
4072  * Setup the text as tooltip to object. The item can have only one tooltip,
4073  * so any previous tooltip data is removed.
4074  *
4075  * @ingroup Widget
4076  */
4077 EAPI void
4078 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
4079                                   const char *text)
4080 {
4081    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4082    EINA_SAFETY_ON_NULL_RETURN(text);
4083    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4084
4085    text = eina_stringshare_add(text);
4086    _elm_widget_item_tooltip_content_cb_set
4087      (item, _elm_widget_item_tooltip_label_create, text,
4088      _elm_widget_item_tooltip_label_del_cb);
4089 }
4090
4091 EAPI void
4092 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
4093                                                const char *text)
4094 {
4095    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4096    EINA_SAFETY_ON_NULL_RETURN(text);
4097    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4098
4099    text = eina_stringshare_add(text);
4100    _elm_widget_item_tooltip_content_cb_set
4101      (item, _elm_widget_item_tooltip_trans_label_create, text,
4102      _elm_widget_item_tooltip_label_del_cb);
4103 }
4104
4105 static Evas_Object *
4106 _elm_widget_item_tooltip_create(void *data,
4107                                 Evas_Object *obj,
4108                                 Evas_Object *tooltip)
4109 {
4110    Elm_Widget_Item_Tooltip *wit = data;
4111    return wit->func((void *)wit->data, obj, tooltip, wit->item);
4112 }
4113
4114 static void
4115 _elm_widget_item_tooltip_del_cb(void *data,
4116                                 Evas_Object *obj,
4117                                 void *event_info __UNUSED__)
4118 {
4119    Elm_Widget_Item_Tooltip *wit = data;
4120    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
4121    free(wit);
4122 }
4123
4124 /**
4125  * @internal
4126  *
4127  * Set the content to be shown in the tooltip item
4128  *
4129  * Setup the tooltip to item. The item can have only one tooltip,
4130  * so any previous tooltip data is removed. @p func(with @p data) will
4131  * be called every time that need show the tooltip and it should
4132  * return a valid Evas_Object. This object is then managed fully by
4133  * tooltip system and is deleted when the tooltip is gone.
4134  *
4135  * @param item the widget item being attached a tooltip.
4136  * @param func the function used to create the tooltip contents.
4137  * @param data what to provide to @a func as callback data/context.
4138  * @param del_cb called when data is not needed anymore, either when
4139  *        another callback replaces @func, the tooltip is unset with
4140  *        elm_widget_item_tooltip_unset() or the owner @a item
4141  *        dies. This callback receives as the first parameter the
4142  *        given @a data, and @c event_info is the item.
4143  *
4144  * @ingroup Widget
4145  */
4146 EAPI void
4147 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
4148                                         Elm_Tooltip_Item_Content_Cb func,
4149                                         const void *data,
4150                                         Evas_Smart_Cb del_cb)
4151 {
4152    Elm_Widget_Item_Tooltip *wit;
4153
4154    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
4155    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4156    if (!func)
4157      {
4158         _elm_widget_item_tooltip_unset(item);
4159         return;
4160      }
4161
4162    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
4163    if (!wit) goto error;
4164    wit->item = item;
4165    wit->func = func;
4166    wit->data = data;
4167    wit->del_cb = del_cb;
4168
4169    elm_object_sub_tooltip_content_cb_set
4170      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
4171      _elm_widget_item_tooltip_del_cb);
4172
4173    return;
4174
4175 error_noitem:
4176    if (del_cb) del_cb((void *)data, NULL, item);
4177    return;
4178 error:
4179    if (del_cb) del_cb((void *)data, item->widget, item);
4180 }
4181
4182 /**
4183  * @internal
4184  *
4185  * Unset tooltip from item
4186  *
4187  * @param item widget item to remove previously set tooltip.
4188  *
4189  * Remove tooltip from item. The callback provided as del_cb to
4190  * elm_widget_item_tooltip_content_cb_set() will be called to notify
4191  * it is not used anymore.
4192  *
4193  * @see elm_widget_item_tooltip_content_cb_set()
4194  *
4195  * @ingroup Widget
4196  */
4197 EAPI void
4198 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
4199 {
4200    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4201    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4202
4203    elm_object_tooltip_unset(item->view);
4204 }
4205
4206 /**
4207  * @internal
4208  *
4209  * Sets a different style for this item tooltip.
4210  *
4211  * @note before you set a style you should define a tooltip with
4212  *       elm_widget_item_tooltip_content_cb_set() or
4213  *       elm_widget_item_tooltip_text_set()
4214  *
4215  * @param item widget item with tooltip already set.
4216  * @param style the theme style to use (default, transparent, ...)
4217  *
4218  * @ingroup Widget
4219  */
4220 EAPI void
4221 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
4222                                    const char *style)
4223 {
4224    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4225    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4226
4227    elm_object_tooltip_style_set(item->view, style);
4228 }
4229
4230 EAPI Eina_Bool
4231 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item,
4232                                          Eina_Bool disable)
4233 {
4234    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4235    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
4236
4237    return elm_object_tooltip_window_mode_set(item->view, disable);
4238 }
4239
4240 EAPI Eina_Bool
4241 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
4242 {
4243    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4244    return elm_object_tooltip_window_mode_get(item->view);
4245 }
4246
4247 /**
4248  * @internal
4249  *
4250  * Get the style for this item tooltip.
4251  *
4252  * @param item widget item with tooltip already set.
4253  * @return style the theme style in use, defaults to "default". If the
4254  *         object does not have a tooltip set, then NULL is returned.
4255  *
4256  * @ingroup Widget
4257  */
4258 EAPI const char *
4259 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
4260 {
4261    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4262    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4263
4264    return elm_object_tooltip_style_get(item->view);
4265 }
4266
4267 EAPI void
4268 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
4269                             const char *cursor)
4270 {
4271    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4272    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4273
4274    elm_object_sub_cursor_set(item->view, item->widget, cursor);
4275 }
4276
4277 EAPI const char *
4278 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
4279 {
4280    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4281    return elm_object_cursor_get(item->view);
4282 }
4283
4284 EAPI void
4285 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
4286 {
4287    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4288    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4289
4290    elm_object_cursor_unset(item->view);
4291 }
4292
4293 /**
4294  * @internal
4295  *
4296  * Sets a different style for this item cursor.
4297  *
4298  * @note before you set a style you should define a cursor with
4299  *       elm_widget_item_cursor_set()
4300  *
4301  * @param item widget item with cursor already set.
4302  * @param style the theme style to use (default, transparent, ...)
4303  *
4304  * @ingroup Widget
4305  */
4306 EAPI void
4307 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
4308                                   const char *style)
4309 {
4310    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4311    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4312
4313    elm_object_cursor_style_set(item->view, style);
4314 }
4315
4316 /**
4317  * @internal
4318  *
4319  * Get the style for this item cursor.
4320  *
4321  * @param item widget item with cursor already set.
4322  * @return style the theme style in use, defaults to "default". If the
4323  *         object does not have a cursor set, then NULL is returned.
4324  *
4325  * @ingroup Widget
4326  */
4327 EAPI const char *
4328 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
4329 {
4330    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4331    return elm_object_cursor_style_get(item->view);
4332 }
4333
4334 /**
4335  * @internal
4336  *
4337  * Set if the cursor set should be searched on the theme or should use
4338  * the provided by the engine, only.
4339  *
4340  * @note before you set if should look on theme you should define a cursor
4341  * with elm_object_cursor_set(). By default it will only look for cursors
4342  * provided by the engine.
4343  *
4344  * @param item widget item with cursor already set.
4345  * @param engine_only boolean to define it cursors should be looked only
4346  * between the provided by the engine or searched on widget's theme as well.
4347  *
4348  * @ingroup Widget
4349  */
4350 EAPI void
4351 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
4352                                         Eina_Bool engine_only)
4353 {
4354    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4355    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4356
4357    elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
4358 }
4359
4360 /**
4361  * @internal
4362  *
4363  * Get the cursor engine only usage for this item cursor.
4364  *
4365  * @param item widget item with cursor already set.
4366  * @return engine_only boolean to define it cursors should be looked only
4367  * between the provided by the engine or searched on widget's theme as well. If
4368  *         the object does not have a cursor set, then EINA_FALSE is returned.
4369  *
4370  * @ingroup Widget
4371  */
4372 EAPI Eina_Bool
4373 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
4374 {
4375    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4376    return elm_object_cursor_theme_search_enabled_get(item->view);
4377 }
4378
4379 EAPI void
4380 _elm_widget_item_part_content_set(Elm_Widget_Item *item,
4381                                   const char *part,
4382                                   Evas_Object *content)
4383 {
4384    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4385    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4386    if (!item->content_set_func)
4387      {
4388         ERR("%s does not support elm_object_item_part_content_set() API.",
4389             elm_widget_type_get(item->widget));
4390         return;
4391      }
4392    item->content_set_func((Elm_Object_Item *)item, part, content);
4393 }
4394
4395 EAPI Evas_Object *
4396 _elm_widget_item_part_content_get(const Elm_Widget_Item *item,
4397                                   const char *part)
4398 {
4399    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4400    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4401
4402    return item->content_get_func((Elm_Object_Item *)item, part);
4403 }
4404
4405 EAPI Evas_Object *
4406 _elm_widget_item_part_content_unset(Elm_Widget_Item *item,
4407                                     const char *part)
4408 {
4409    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4410    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4411    if (!item->content_unset_func)
4412      {
4413         ERR("%s does not support elm_object_item_part_content_unset() API.",
4414             elm_widget_type_get(item->widget));
4415         return NULL;
4416      }
4417
4418    return item->content_unset_func((Elm_Object_Item *)item, part);
4419 }
4420
4421 EAPI void
4422 _elm_widget_item_part_text_set(Elm_Widget_Item *item,
4423                                const char *part,
4424                                const char *label)
4425 {
4426    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4427    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4428    if (!item->text_set_func)
4429      {
4430         ERR("%s does not support elm_object_item_part_text_set() API.",
4431             elm_widget_type_get(item->widget));
4432         return;
4433      }
4434
4435    item->text_set_func((Elm_Object_Item *)item, part, label);
4436 }
4437
4438 EAPI const char *
4439 _elm_widget_item_part_text_get(const Elm_Widget_Item *item,
4440                                const char *part)
4441 {
4442    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4443    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4444    if (!item->text_get_func)
4445      {
4446         ERR("%s does not support elm_object_item_part_text_get() API.",
4447             elm_widget_type_get(item->widget));
4448         return NULL;
4449      }
4450
4451    return item->text_get_func((Elm_Object_Item *)item, part);
4452 }
4453
4454 EAPI void
4455 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
4456                                       Elm_Widget_Content_Set_Cb func)
4457 {
4458    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4459    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4460
4461    item->content_set_func = func;
4462 }
4463
4464 EAPI void
4465 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
4466                                       Elm_Widget_Content_Get_Cb func)
4467 {
4468    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4469    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4470
4471    item->content_get_func = func;
4472 }
4473
4474 EAPI void
4475 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
4476                                         Elm_Widget_Content_Unset_Cb func)
4477 {
4478    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4479    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4480
4481    item->content_unset_func = func;
4482 }
4483
4484 EAPI void
4485 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
4486                                    Elm_Widget_Text_Set_Cb func)
4487 {
4488    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4489    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4490
4491    item->text_set_func = func;
4492 }
4493
4494 EAPI void
4495 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
4496                                    Elm_Widget_Text_Get_Cb func)
4497 {
4498    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4499    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4500
4501    item->text_get_func = func;
4502 }
4503
4504 EAPI void
4505 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
4506                              const char *emission,
4507                              const char *source)
4508 {
4509    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4510    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4511
4512    if (item->signal_emit_func)
4513      item->signal_emit_func((Elm_Object_Item *)item, emission, source);
4514 }
4515
4516 EAPI void
4517 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
4518                                       Elm_Widget_Signal_Emit_Cb func)
4519 {
4520    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4521    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4522
4523    item->signal_emit_func = func;
4524 }
4525
4526 EAPI void
4527 _elm_widget_item_access_info_set(Elm_Widget_Item *item,
4528                                  const char *txt)
4529 {
4530    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4531    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4532
4533    if (item->access_info) eina_stringshare_del(item->access_info);
4534    if (!txt) item->access_info = NULL;
4535    else item->access_info = eina_stringshare_add(txt);
4536 }
4537
4538 /* happy debug functions */
4539 #ifdef ELM_DEBUG
4540 static void
4541 _sub_obj_tree_dump(const Evas_Object *obj,
4542                    int lvl)
4543 {
4544    int i;
4545
4546    for (i = 0; i < lvl * 3; i++)
4547      putchar(' ');
4548
4549    if (_elm_widget_is(obj))
4550      {
4551         Eina_List *l;
4552         INTERNAL_ENTRY;
4553         printf("+ %s(%p)\n",
4554                elm_widget_type_get(obj),
4555                obj);
4556         if (sd->resize_obj)
4557           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
4558         EINA_LIST_FOREACH(sd->subobjs, l, obj)
4559           {
4560              if (obj != sd->resize_obj)
4561                _sub_obj_tree_dump(obj, lvl + 1);
4562           }
4563      }
4564    else
4565      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
4566 }
4567
4568 static void
4569 _sub_obj_tree_dot_dump(const Evas_Object *obj,
4570                        FILE *output)
4571 {
4572    if (!_elm_widget_is(obj))
4573      return;
4574    INTERNAL_ENTRY;
4575
4576    Eina_Bool visible = evas_object_visible_get(obj);
4577    Eina_Bool disabled = elm_widget_disabled_get(obj);
4578    Eina_Bool focused = elm_widget_focus_get(obj);
4579    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
4580
4581    if (sd->parent_obj)
4582      {
4583         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
4584
4585         if (focused)
4586           fprintf(output, ", style=bold");
4587
4588         if (!visible)
4589           fprintf(output, ", color=gray28");
4590
4591         fprintf(output, " ];\n");
4592      }
4593
4594    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
4595                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
4596            obj, obj, elm_widget_type_get(obj),
4597            evas_object_name_get(obj), visible, disabled, focused, can_focus,
4598            sd->focus_order);
4599
4600    if (focused)
4601      fprintf(output, ", style=bold");
4602
4603    if (!visible)
4604      fprintf(output, ", fontcolor=gray28");
4605
4606    if ((disabled) || (!visible))
4607      fprintf(output, ", color=gray");
4608
4609    fprintf(output, " ];\n");
4610
4611    Eina_List *l;
4612    Evas_Object *o;
4613    EINA_LIST_FOREACH(sd->subobjs, l, o)
4614      _sub_obj_tree_dot_dump(o, output);
4615 }
4616
4617 #endif
4618
4619 EAPI void
4620 elm_widget_tree_dump(const Evas_Object *top)
4621 {
4622 #ifdef ELM_DEBUG
4623    if (!_elm_widget_is(top))
4624      return;
4625    _sub_obj_tree_dump(top, 0);
4626 #else
4627    (void)top;
4628    return;
4629 #endif
4630 }
4631
4632 EAPI void
4633 elm_widget_tree_dot_dump(const Evas_Object *top,
4634                          FILE *output)
4635 {
4636 #ifdef ELM_DEBUG
4637    if (!_elm_widget_is(top))
4638      return;
4639    fprintf(output, "graph " " { node [shape=record];\n");
4640    _sub_obj_tree_dot_dump(top, output);
4641    fprintf(output, "}\n");
4642 #else
4643    (void)top;
4644    (void)output;
4645    return;
4646 #endif
4647 }