[elm_navigationbar]: check added if the button being added is same then dont delete it.
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char SMART_NAME[] = "elm_widget";
5
6 #define API_ENTRY \
7    Smart_Data *sd = evas_object_smart_data_get(obj); \
8    if ((!obj) || (!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY \
10    Smart_Data *sd = evas_object_smart_data_get(obj); \
11    if (!sd) return;
12
13 typedef struct _Smart_Data Smart_Data;
14
15 struct _Smart_Data
16 {
17    Evas_Object   *obj;
18    const char    *type;
19    Evas_Object   *parent_obj;
20    Evas_Coord     x, y, w, h;
21    Eina_List     *subobjs;
22    Evas_Object   *resize_obj;
23    Evas_Object   *hover_obj;
24    void         (*del_func) (Evas_Object *obj);
25    void         (*del_pre_func) (Evas_Object *obj);
26    void         (*focus_func) (Evas_Object *obj);
27    void         (*activate_func) (Evas_Object *obj);
28    void         (*disable_func) (Evas_Object *obj);
29    void         (*theme_func) (Evas_Object *obj);
30    void         (*signal_func) (Evas_Object *obj, const char *emission,
31                                 const char *source);
32    void         (*callback_add_func) (Evas_Object *obj, const char *emission,
33                                 const char *source, void (*func) (void *data,
34                                    Evas_Object *o, const char *emission,
35                                    const char *source), void *data);
36    void         *(*callback_del_func) (Evas_Object *obj, const char *emission,
37                                   const char *source, void (*func) (void *data,
38                                      Evas_Object *o, const char *emission,
39                                      const char *source));
40    void         (*changed_func) (Evas_Object *obj);
41    void         (*on_focus_func) (void *data, Evas_Object *obj);
42    void          *on_focus_data;
43    void         (*on_change_func) (void *data, Evas_Object *obj);
44    void          *on_change_data;
45 #ifdef HAVE_CONFORMANT_AUTOSCROLL
46    Evas_Object * (*imp_region_get_func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); 
47 #endif
48    void         (*on_show_region_func) (void *data, Evas_Object *obj);
49    void          *on_show_region_data;
50    void          *data;
51    Evas_Coord     rx, ry, rw, rh;
52    int            scroll_hold;
53    int            scroll_freeze;
54    double         scale;
55    Elm_Theme     *theme;
56    const char    *style;
57    unsigned int   focus_order;
58    
59    int            child_drag_x_locked;
60    int            child_drag_y_locked;
61    Eina_Bool      drag_x_locked : 1;
62    Eina_Bool      drag_y_locked : 1;
63    
64    Eina_Bool      can_focus : 1;
65    Eina_Bool      child_can_focus : 1;
66    Eina_Bool      focused : 1;
67    Eina_Bool      disabled : 1;
68 };
69
70 /* local subsystem functions */
71 static void _smart_reconfigure(Smart_Data *sd);
72 static void _smart_add(Evas_Object *obj);
73 static void _smart_del(Evas_Object *obj);
74 static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
75 static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
76 static void _smart_show(Evas_Object *obj);
77 static void _smart_hide(Evas_Object *obj);
78 static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
79 static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
80 static void _smart_clip_unset(Evas_Object *obj);
81 static void _smart_calculate(Evas_Object *obj);
82 static void _smart_init(void);
83 static inline Eina_Bool _elm_widget_is(const Evas_Object *obj);
84
85 static void _if_focused_revert(Evas_Object *obj);
86
87 /* local subsystem globals */
88 static Evas_Smart *_e_smart = NULL;
89
90 static unsigned int focus_order = 0;
91
92 static void  
93 _unfocus_parents(Evas_Object *obj)  
94 {  
95         for (; obj; obj = elm_widget_parent_get(obj))  
96         {  
97                 Smart_Data *sd = evas_object_smart_data_get(obj);  
98                 if (!sd) return;  
99                 if (!sd->focused) return;  
100                 sd->focused = 0;  
101         }  
102 }  
103
104 static void  
105 _focus_parents(Evas_Object *obj)  
106 {  
107         for (; obj; obj = elm_widget_parent_get(obj))  
108         {  
109                 Smart_Data *sd = evas_object_smart_data_get(obj);  
110                 if (!sd) return;  
111                 if (sd->focused) return;  
112                 sd->focused = 1;  
113         }  
114 }  
115
116 static void
117 _sub_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
118 {
119    Smart_Data *sd = data;
120
121    if (_elm_widget_is(obj))  
122       {  
123          if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);  
124       }     
125    if (obj == sd->resize_obj)
126      sd->resize_obj = NULL;
127    else if (obj == sd->hover_obj)
128      sd->hover_obj = NULL;
129    else
130      sd->subobjs = eina_list_remove(sd->subobjs, obj);
131    evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
132 }
133
134 static void
135 _sub_obj_mouse_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
136 {
137    Evas_Object *o = obj;
138    do 
139      {
140         if (_elm_widget_is(o)) break;
141         o = evas_object_smart_parent_get(o);
142      }
143    while (o);
144    if (!o) return;
145    if (!elm_widget_can_focus_get(o)) return;
146    elm_widget_focus_steal(o);
147 }
148
149 EAPI Evas_Object *
150 elm_widget_add(Evas *evas)
151 {
152    _smart_init();
153    return evas_object_smart_add(evas, _e_smart);
154 }
155
156 EAPI void
157 elm_widget_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
158 {
159    API_ENTRY return;
160    sd->del_func = func;
161 }
162
163 EAPI void
164 elm_widget_del_pre_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
165 {
166    API_ENTRY return;
167    sd->del_pre_func = func;
168 }
169
170 EAPI void
171 elm_widget_focus_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
172 {
173    API_ENTRY return;
174    sd->focus_func = func;
175 }
176
177 EAPI void
178 elm_widget_activate_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
179 {
180    API_ENTRY return;
181    sd->activate_func = func;
182 }
183
184 EAPI void
185 elm_widget_disable_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
186 {
187    API_ENTRY return;
188    sd->disable_func = func;
189 }
190
191 EAPI void
192 elm_widget_theme_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
193 {
194    API_ENTRY return;
195    sd->theme_func = func;
196 }
197
198 EAPI void
199 elm_widget_changed_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj))
200 {
201    API_ENTRY return;
202    sd->changed_func = func;
203 }
204
205 EAPI void
206 elm_widget_signal_emit_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source))
207 {
208    API_ENTRY return;
209    sd->signal_func = func;
210 }
211
212 EAPI void
213 elm_widget_signal_callback_add_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data))
214 {
215    API_ENTRY return;
216    sd->callback_add_func = func;
217 }
218
219 EAPI void
220 elm_widget_signal_callback_del_hook_set(Evas_Object *obj, void *(*func) (Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source)))
221 {
222    API_ENTRY return;
223    sd->callback_del_func = func;
224 }
225
226 EAPI void
227 elm_widget_theme(Evas_Object *obj)
228 {
229    const Eina_List *l;
230    Evas_Object *child;
231
232    API_ENTRY return;
233    EINA_LIST_FOREACH(sd->subobjs, l, child)
234      elm_widget_theme(child);
235    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
236    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
237    if (sd->theme_func) sd->theme_func(obj);
238 }
239
240 EAPI void
241 elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
242 {
243    API_ENTRY return;
244    sd->on_focus_func = func;
245    sd->on_focus_data = data;
246 }
247
248 EAPI void
249 elm_widget_on_change_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
250 {
251    API_ENTRY return;
252    sd->on_change_func = func;
253    sd->on_change_data = data;
254 }
255
256 #ifdef HAVE_CONFORMANT_AUTOSCROLL
257 EAPI void
258 elm_widget_imp_region_get_hook_set(Evas_Object *obj, Evas_Object * (*func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h), void *data)
259 {
260    API_ENTRY return;
261    sd->imp_region_get_func = func;
262 }
263 #endif
264
265 EAPI void
266 elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data)
267 {
268    API_ENTRY return;
269    sd->on_show_region_func = func;
270    sd->on_show_region_data = data;
271 }
272
273 EAPI void
274 elm_widget_data_set(Evas_Object *obj, void *data)
275 {
276    API_ENTRY return;
277    sd->data = data;
278 }
279
280 EAPI void *
281 elm_widget_data_get(const Evas_Object *obj)
282 {
283    API_ENTRY return NULL;
284    return sd->data;
285 }
286
287 EAPI void
288 elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj)
289 {
290    API_ENTRY return;
291    double scale, pscale = elm_widget_scale_get(sobj);
292    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
293
294    sd->subobjs = eina_list_append(sd->subobjs, sobj);
295    if (!sd->child_can_focus)
296      {
297         if (elm_widget_can_focus_get(sobj)) sd->child_can_focus = 1;
298      }
299    if (_elm_widget_is(sobj))
300      {
301         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
302         if (sd2)
303           {
304              if (sd2->parent_obj)
305                elm_widget_sub_object_del(sd2->parent_obj, sobj);
306              sd2->parent_obj = obj;
307           }
308      }
309    evas_object_data_set(sobj, "elm-parent", obj);
310    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
311    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
312    scale = elm_widget_scale_get(sobj);
313    th = elm_widget_theme_get(sobj);
314    if ((scale != pscale) || (th != pth)) elm_widget_theme(sobj);
315    if (_elm_widget_is(sobj))  
316       {  
317          if (elm_widget_focus_get(sobj)) _focus_parents(obj);  
318       }
319 }
320
321 EAPI void
322 elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj)
323 {
324    Evas_Object *sobj_parent;
325    API_ENTRY return;
326    if (!sobj) return;
327
328    sobj_parent = evas_object_data_del(sobj, "elm-parent");
329    if (sobj_parent != obj)
330      {
331         static int abort_on_warn = -1;
332         ERR("removing sub object %p from parent %p, "
333             "but elm-parent is different %p!",
334             sobj, obj, sobj_parent);
335         if (EINA_UNLIKELY(abort_on_warn == -1))
336           {
337              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
338              else abort_on_warn = 0;
339           }
340         if (abort_on_warn == 1) abort();
341      }
342    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
343    if (!sd->child_can_focus)
344      {
345         if (elm_widget_can_focus_get(sobj)) sd->child_can_focus = 0;
346      }
347    if (_elm_widget_is(sobj))
348      {
349         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
350         if (sd2) sd2->parent_obj = NULL;
351         if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
352      }
353    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
354    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
355 }
356
357 EAPI void
358 elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj)
359 {
360    API_ENTRY return;
361    if (sd->resize_obj)
362      {
363         evas_object_data_del(sd->resize_obj, "elm-parent");
364         if (_elm_widget_is(sd->resize_obj))
365           {
366              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
367              if (sd2) sd2->parent_obj = NULL;
368           }
369         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
370            _sub_obj_del, sd);
371         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_DOWN,
372            _sub_obj_mouse_down, sd);
373         evas_object_smart_member_del(sd->resize_obj);
374         if (_elm_widget_is(sd->resize_obj))  
375            {  
376               if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);  
377            }
378      }
379    sd->resize_obj = sobj;
380    if (sd->resize_obj)
381      {
382         if (_elm_widget_is(sd->resize_obj))
383           {
384              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
385              if (sd2) sd2->parent_obj = obj;
386           }
387         evas_object_clip_set(sobj, evas_object_clip_get(obj));
388         evas_object_smart_member_add(sobj, obj);
389         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
390         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
391                                        _sub_obj_mouse_down, sd);
392         _smart_reconfigure(sd);
393         evas_object_data_set(sobj, "elm-parent", obj);
394         evas_object_smart_callback_call(obj, "sub-object-add", sobj);
395         if (_elm_widget_is(sobj))  
396            {  
397               if (elm_widget_focus_get(sobj)) _focus_parents(obj);  
398            }                          
399      }
400 }
401
402 EAPI void
403 elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj)
404 {
405    API_ENTRY return;
406    if (sd->hover_obj)
407      {
408         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
409            _sub_obj_del, sd);
410      }
411    sd->hover_obj = sobj;
412    if (sd->hover_obj)
413      {
414         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
415         _smart_reconfigure(sd);
416      }
417 }
418
419 EAPI void
420 elm_widget_can_focus_set(Evas_Object *obj, int can_focus)
421 {
422    API_ENTRY return;
423    sd->can_focus = can_focus;
424 }
425
426 EAPI int
427 elm_widget_can_focus_get(const Evas_Object *obj)
428 {
429    API_ENTRY return 0;
430    if (sd->can_focus) return 1;
431    if (sd->child_can_focus) return 1;
432    return 0;
433 }
434
435 EAPI int
436 elm_widget_focus_get(const Evas_Object *obj)
437 {
438    API_ENTRY return 0;
439    return sd->focused;
440 }
441
442 EAPI Evas_Object *
443 elm_widget_focused_object_get(const Evas_Object *obj)
444 {
445    const Evas_Object *subobj;
446    const Eina_List *l;
447    API_ENTRY return NULL;
448
449    if (!sd->focused) return NULL;
450    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
451      {
452         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
453         if (fobj) return fobj;
454      }
455    return (Evas_Object *)obj;
456 }
457
458 EAPI Evas_Object *
459 elm_widget_top_get(const Evas_Object *obj)
460 {
461 #if 1 // strict way  
462    API_ENTRY return NULL;
463    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
464    return (Evas_Object *)obj;
465 #else // loose way
466    Smart_Data *sd = evas_object_smart_data_get(obj);
467    Evas_Object *par;
468    
469    if (!obj) return NULL;
470    if ((sd) && _elm_widget_is(obj))
471      {
472         if ((sd->type) && (!strcmp(sd->type, "win"))) 
473           return (Evas_Object *)obj;
474         if (sd->parent_obj)
475           return elm_widget_top_get(sd->parent_obj);
476      }
477    par = evas_object_smart_parent_get(obj);
478    if (!par) return (Evas_Object *)obj;
479    return elm_widget_top_get(par);
480 #endif   
481 }
482
483 EAPI Eina_Bool
484 elm_widget_is(const Evas_Object *obj)
485 {
486    return _elm_widget_is(obj);
487 }
488
489 EAPI Evas_Object *
490 elm_widget_parent_widget_get(const Evas_Object *obj)
491 {
492    Evas_Object *parent;
493
494    if (_elm_widget_is(obj))
495      {
496         Smart_Data *sd = evas_object_smart_data_get(obj);
497         if (!sd) return NULL;
498         parent = sd->parent_obj;
499      }
500    else
501      {
502         parent = evas_object_data_get(obj, "elm-parent");
503         if (!parent)
504           parent = evas_object_smart_data_get(obj);
505      }
506
507    while (parent)
508      {
509         Evas_Object *elm_parent;
510         if (_elm_widget_is(parent)) break;
511         elm_parent = evas_object_data_get(parent, "elm-parent");
512         if (elm_parent)
513           parent = elm_parent;
514         else
515           parent = evas_object_smart_parent_get(parent);
516      }
517    return parent;
518 }
519
520 EAPI int
521 elm_widget_focus_jump(Evas_Object *obj, int forward)
522 {
523    API_ENTRY return 0;
524    if (!elm_widget_can_focus_get(obj)) return 0;
525
526    /* if it has a focus func its an end-point widget like a button */
527    if (sd->focus_func)
528      {
529         if (!sd->focused)
530           {
531              focus_order++;
532              sd->focus_order = focus_order;
533              sd->focused = 1;
534           }
535         else sd->focused = 0;
536         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
537         sd->focus_func(obj);
538         return sd->focused;
539      }
540    /* its some container */
541    else
542      {
543         int focus_next;
544         int noloop = 0;
545
546         focus_next = 0;
547         if (!sd->focused)
548           {
549              elm_widget_focus_set(obj, forward);
550              return 1;
551           }
552         else
553           {
554              if (forward)
555                {
556                   if (elm_widget_can_focus_get(sd->resize_obj))
557                     {
558                        if ((focus_next) &&
559                            (!elm_widget_disabled_get(sd->resize_obj)))
560                          {
561                             /* the previous focused item was unfocused - so focus
562                              * the next one (that can be focused) */
563                             if (elm_widget_focus_jump(sd->resize_obj, forward))
564                               return 1;
565                             else noloop = 1;
566                          }
567                        else
568                          {
569                             if (elm_widget_focus_get(sd->resize_obj))
570                               {
571                                  /* jump to the next focused item or focus this item */
572                                  if (elm_widget_focus_jump(sd->resize_obj, forward))
573                                    return 1;
574                                  /* it returned 0 - it got to the last item and is past it */
575                                  focus_next = 1;
576                               }
577                          }
578                     }
579                   if (!noloop)
580                     {
581                        const Eina_List *l;
582                        Evas_Object *child;
583                        EINA_LIST_FOREACH(sd->subobjs, l, child)
584                          {
585                             if (elm_widget_can_focus_get(child))
586                               {
587                                  if ((focus_next) &&
588                                      (!elm_widget_disabled_get(child)))
589                                    {
590                                       /* the previous focused item was unfocused - so focus
591                                        * the next one (that can be focused) */
592                                       if (elm_widget_focus_jump(child, forward))
593                                         return 1;
594                                       else break;
595                                    }
596                                  else
597                                    {
598                                       if (elm_widget_focus_get(child))
599                                         {
600                                            /* jump to the next focused item or focus this item */
601                                            if (elm_widget_focus_jump(child, forward))
602                                              return 1;
603                                            /* it returned 0 - it got to the last item and is past it */
604                                            focus_next = 1;
605                                         }
606                                    }
607                               }
608                          }
609                     }
610                }
611              else
612                {
613                   const Eina_List *l;
614                   Evas_Object *child;
615
616                   EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
617                     {
618                        if (elm_widget_can_focus_get(child))
619                          {
620                             if ((focus_next) &&
621                                 (!elm_widget_disabled_get(child)))
622                               {
623                                  /* the previous focused item was unfocused - so focus
624                                   * the next one (that can be focused) */
625                                  if (elm_widget_focus_jump(child, forward))
626                                    return 1;
627                                  else break;
628                               }
629                             else
630                               {
631                                  if (elm_widget_focus_get(child))
632                                    {
633                                       /* jump to the next focused item or focus this item */
634                                       if (elm_widget_focus_jump(child, forward))
635                                         return 1;
636                                       /* it returned 0 - it got to the last item and is past it */
637                                       focus_next = 1;
638                                    }
639                               }
640                          }
641                     }
642                   if (!l)
643                     {
644                        if (elm_widget_can_focus_get(sd->resize_obj))
645                          {
646                             if ((focus_next) &&
647                                 (!elm_widget_disabled_get(sd->resize_obj)))
648                               {
649                                  /* the previous focused item was unfocused - so focus
650                                   * the next one (that can be focused) */
651                                  if (elm_widget_focus_jump(sd->resize_obj, forward))
652                                    return 1;
653                               }
654                             else
655                               {
656                                  if (elm_widget_focus_get(sd->resize_obj))
657                                    {
658                                       /* jump to the next focused item or focus this item */
659                                       if (elm_widget_focus_jump(sd->resize_obj, forward))
660                                         return 1;
661                                       /* it returned 0 - it got to the last item and is past it */
662                                       focus_next = 1;
663                                    }
664                               }
665                          }
666                     }
667                }
668           }
669      }
670    /* no next item can be focused */
671    if (sd->focused)
672      {
673         sd->focused = 0;
674         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
675      }
676    return 0;
677 }
678
679 EAPI void
680 elm_widget_signal_emit(Evas_Object *obj, const char *emission, const char *source)
681 {
682    API_ENTRY return;
683    if (!sd->signal_func) return;
684    sd->signal_func(obj, emission, source);
685 }
686
687 EAPI void
688 elm_widget_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
689 {
690    API_ENTRY return;
691    if (!sd->callback_add_func) return;
692    sd->callback_add_func(obj, emission, source, func, data);
693 }
694
695 EAPI void *
696 elm_widget_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
697 {
698    API_ENTRY return NULL;
699    if (!sd->callback_del_func) return NULL;
700    return sd->callback_del_func(obj, emission, source, func);
701 }
702
703 EAPI void
704 elm_widget_focus_set(Evas_Object *obj, int first)
705 {
706    API_ENTRY return;
707    if (!sd->focused)
708      {
709         focus_order++;
710         sd->focus_order = focus_order;
711         sd->focused = 1;
712         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
713      }
714    if (sd->focus_func)
715      {
716         sd->focus_func(obj);
717         return;
718      }
719    else
720      {
721         if (first)
722           {
723              if ((elm_widget_can_focus_get(sd->resize_obj)) &&
724                  (!elm_widget_disabled_get(sd->resize_obj)))
725                {
726                   elm_widget_focus_set(sd->resize_obj, first);
727                }
728              else
729                {
730                   const Eina_List *l;
731                   Evas_Object *child;
732                   EINA_LIST_FOREACH(sd->subobjs, l, child)
733                     {
734                        if ((elm_widget_can_focus_get(child)) &&
735                            (!elm_widget_disabled_get(child)))
736                          {
737                             elm_widget_focus_set(child, first);
738                             break;
739                          }
740                     }
741                }
742           }
743         else
744           {
745              const Eina_List *l;
746              Evas_Object *child;
747              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
748                {
749                   if ((elm_widget_can_focus_get(child)) &&
750                       (!elm_widget_disabled_get(child)))
751                     {
752                        elm_widget_focus_set(child, first);
753                        break;
754                     }
755                }
756              if (!l)
757                {
758                   if ((elm_widget_can_focus_get(sd->resize_obj)) &&
759                       (!elm_widget_disabled_get(sd->resize_obj)))
760                     {
761                        elm_widget_focus_set(sd->resize_obj, first);
762                     }
763                }
764           }
765      }
766 }
767
768 EAPI Evas_Object *
769 elm_widget_parent_get(const Evas_Object *obj)
770 {
771    API_ENTRY return NULL;
772    return sd->parent_obj;
773 }
774
775 EAPI void
776 elm_widget_focused_object_clear(Evas_Object *obj)
777 {
778    API_ENTRY return;
779    if (!sd->focused) return;
780    if (elm_widget_focus_get(sd->resize_obj))
781      elm_widget_focused_object_clear(sd->resize_obj);
782    else
783      {
784         const Eina_List *l;
785         Evas_Object *child;
786         EINA_LIST_FOREACH(sd->subobjs, l, child)
787           {
788              if (elm_widget_focus_get(child))
789                {
790                   elm_widget_focused_object_clear(child);
791                   break;
792                }
793           }
794      }
795    sd->focused = 0;
796    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
797    if (sd->focus_func) sd->focus_func(obj);
798 }
799
800 static void
801 _elm_widget_parent_focus(Evas_Object *obj)
802 {
803    API_ENTRY return;
804    Evas_Object *o = elm_widget_parent_get(obj);
805
806    if (sd->focused) return;
807    if (o) _elm_widget_parent_focus(o);
808    focus_order++;
809    sd->focus_order = focus_order;
810    sd->focused = 1;
811    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
812    if (sd->focus_func) sd->focus_func(obj);
813 }
814
815 EAPI void
816 elm_widget_focus_steal(Evas_Object *obj)
817 {
818    Evas_Object *parent, *o;
819    API_ENTRY return;
820
821    if (sd->focused) return;
822    if (sd->disabled) return;
823    parent = obj;
824    for (;;)
825      {
826         o = elm_widget_parent_get(parent);
827         if (!o) break;
828         sd = evas_object_smart_data_get(o);
829         if (sd->focused) break;
830         parent = o;
831      }
832    if (!elm_widget_parent_get(parent))
833      elm_widget_focused_object_clear(parent);
834    else
835      {
836         parent = elm_widget_parent_get(parent);
837         sd = evas_object_smart_data_get(parent);
838         if (elm_widget_focus_get(sd->resize_obj))
839           {
840              elm_widget_focused_object_clear(sd->resize_obj);
841           }
842         else
843           {
844              const Eina_List *l;
845              Evas_Object *child;
846              EINA_LIST_FOREACH(sd->subobjs, l, child)
847                {
848                   if (elm_widget_focus_get(child))
849                     {
850                        elm_widget_focused_object_clear(child);
851                        break;
852                     }
853                }
854           }
855      }
856    _elm_widget_parent_focus(obj);
857    return;
858 }
859
860 EAPI void
861 elm_widget_activate(Evas_Object *obj)
862 {
863    API_ENTRY return;
864    elm_widget_change(obj);
865    if (sd->activate_func) sd->activate_func(obj);
866 }
867
868 EAPI void
869 elm_widget_change(Evas_Object *obj)
870 {
871    API_ENTRY return;
872    elm_widget_change(elm_widget_parent_get(obj));
873    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
874 }
875
876 EAPI void
877 elm_widget_disabled_set(Evas_Object *obj, int disabled)
878 {
879    API_ENTRY return;
880
881    if (sd->disabled == disabled) return;
882    sd->disabled = disabled;
883    if (sd->focused)
884      {
885         Evas_Object *o, *parent;
886
887         parent = obj;
888         for (;;)
889           {
890              o = elm_widget_parent_get(parent);
891              if (!o) break;
892              parent = o;
893           }
894         elm_widget_focus_jump(parent, 1);
895      }
896    if (sd->disable_func) sd->disable_func(obj);
897 }
898
899 EAPI int
900 elm_widget_disabled_get(const Evas_Object *obj)
901 {
902    API_ENTRY return 0;
903    return sd->disabled;
904 }
905
906 #ifdef HAVE_CONFORMANT_AUTOSCROLL
907 EAPI Evas_Object *
908 elm_widget_imp_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
909 {
910    API_ENTRY return;
911    if (sd->imp_region_get_func)
912      return sd->imp_region_get_func(obj, x, y, w, h);
913    else
914      return NULL;
915 }
916 #endif
917
918 EAPI void
919 elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
920 {
921    API_ENTRY return;
922    if ((x == sd->rx) && (y == sd->ry) && (w == sd->rw) && (h == sd->rh)) return;
923    sd->rx = x;
924    sd->ry = y;
925    sd->rw = w;
926    sd->rh = h;
927    if (sd->on_show_region_func)
928      sd->on_show_region_func(sd->on_show_region_data, obj);
929      
930         Evas_Object *parent_obj, *child_obj;
931         Evas_Coord px, py, cx, cy;
932         do
933           {
934              parent_obj = sd->parent_obj; 
935                  child_obj = sd->obj;
936              sd = evas_object_smart_data_get(parent_obj);
937
938              if ((!parent_obj) || (!sd) || (!_elm_widget_is(parent_obj))) break;
939
940                  evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
941                  evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
942
943                  x += (cx - px);
944                  y += (cy - py);
945                  sd->rx = x;
946                  sd->ry = y;
947                  sd->rw = w;
948                  sd->rh = h;
949
950              if (sd->on_show_region_func)
951                {
952                   sd->on_show_region_func(sd->on_show_region_data, parent_obj);
953                }
954           }
955         while (parent_obj);
956 }
957
958 EAPI void
959 elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
960 {
961    API_ENTRY return;
962    if (x) *x = sd->rx;
963    if (y) *y = sd->ry;
964    if (w) *w = sd->rw;
965    if (h) *h = sd->rh;
966 }
967
968 EAPI void
969 elm_widget_scroll_hold_push(Evas_Object *obj)
970 {
971    API_ENTRY return;
972    sd->scroll_hold++;
973    if (sd->scroll_hold == 1)
974      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
975    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
976    // FIXME: on delete/reparent hold pop
977 }
978
979 EAPI void
980 elm_widget_scroll_hold_pop(Evas_Object *obj)
981 {
982    API_ENTRY return;
983    sd->scroll_hold--;
984    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
985    if (sd->scroll_hold == 0)
986      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
987    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
988 }
989
990 EAPI int
991 elm_widget_scroll_hold_get(const Evas_Object *obj)
992 {
993    API_ENTRY return 0;
994    return sd->scroll_hold;
995 }
996
997 EAPI void
998 elm_widget_scroll_freeze_push(Evas_Object *obj)
999 {
1000    API_ENTRY return;
1001    sd->scroll_freeze++;
1002    if (sd->scroll_freeze == 1)
1003      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
1004    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
1005    // FIXME: on delete/reparent freeze pop
1006 }
1007
1008 EAPI void
1009 elm_widget_scroll_freeze_pop(Evas_Object *obj)
1010 {
1011    API_ENTRY return;
1012    sd->scroll_freeze--;
1013    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
1014    if (sd->scroll_freeze == 0)
1015      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
1016    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
1017 }
1018
1019 EAPI int
1020 elm_widget_scroll_freeze_get(const Evas_Object *obj)
1021 {
1022    API_ENTRY return 0;
1023    return sd->scroll_freeze;
1024 }
1025
1026 EAPI void
1027 elm_widget_scale_set(Evas_Object *obj, double scale)
1028 {
1029    API_ENTRY return;
1030    if (scale <= 0.0) scale = 0.0;
1031    if (sd->scale != scale)
1032      {
1033         sd->scale = scale;
1034         elm_widget_theme(obj);
1035      }
1036 }
1037
1038 EAPI double
1039 elm_widget_scale_get(const Evas_Object *obj)
1040 {
1041    API_ENTRY return 1.0;
1042    // FIXME: save walking up the tree by storing/caching parent scale
1043    if (sd->scale == 0.0)
1044      {
1045         if (sd->parent_obj)
1046           return elm_widget_scale_get(sd->parent_obj);
1047         else
1048           return 1.0;
1049      }
1050    return sd->scale;
1051 }
1052
1053 EAPI void
1054 elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th)
1055 {
1056    API_ENTRY return;
1057    if (sd->theme != th)
1058      {
1059         if (sd->theme) elm_theme_free(sd->theme);
1060         sd->theme = th;
1061         if (th) th->ref++;
1062         elm_widget_theme(obj);
1063      }
1064 }
1065
1066 EAPI Elm_Theme *
1067 elm_widget_theme_get(const Evas_Object *obj)
1068 {
1069    API_ENTRY return NULL;
1070    if (!sd->theme)
1071      {
1072         if (sd->parent_obj)
1073           return elm_widget_theme_get(sd->parent_obj);
1074         else
1075           return NULL;
1076      }
1077    return sd->theme;
1078 }
1079
1080 EAPI void
1081 elm_widget_style_set(Evas_Object *obj, const char *style)
1082 {
1083    API_ENTRY return;
1084
1085    if (eina_stringshare_replace(&sd->style, style))
1086      elm_widget_theme(obj);
1087 }
1088
1089 EAPI const char *
1090 elm_widget_style_get(const Evas_Object *obj)
1091 {
1092    API_ENTRY return "";
1093    if (sd->style) return sd->style;
1094    return "default";
1095 }
1096
1097 EAPI void
1098 elm_widget_type_set(Evas_Object *obj, const char *type)
1099 {
1100    API_ENTRY return;
1101    eina_stringshare_replace(&sd->type, type);
1102 }
1103
1104 EAPI const char *
1105 elm_widget_type_get(const Evas_Object *obj)
1106 {
1107    API_ENTRY return "";
1108    if (sd->type) return sd->type;
1109    return "";
1110 }
1111
1112 static void
1113 _propagate_x_drag_lock(Evas_Object *obj, int dir)
1114 {
1115    Smart_Data *sd = evas_object_smart_data_get(obj);
1116    if (sd->parent_obj)
1117      {
1118         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
1119         if (sd2)
1120           {
1121              sd2->child_drag_x_locked += dir;
1122              _propagate_x_drag_lock(sd->parent_obj, dir);
1123           }
1124      }
1125 }
1126
1127 static void
1128 _propagate_y_drag_lock(Evas_Object *obj, int dir)
1129 {
1130    Smart_Data *sd = evas_object_smart_data_get(obj);
1131    if (sd->parent_obj)
1132      {
1133         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
1134         if (sd2)
1135           {
1136              sd2->child_drag_y_locked += dir;
1137              _propagate_y_drag_lock(sd->parent_obj, dir);
1138           }
1139      }
1140 }
1141 EAPI void
1142 elm_widget_drag_lock_x_set(Evas_Object *obj, Eina_Bool lock)
1143 {
1144    API_ENTRY return;
1145    if (sd->drag_x_locked == lock) return;
1146    sd->drag_x_locked = lock;
1147    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
1148    else _propagate_x_drag_lock(obj, -1);
1149 }
1150
1151 EAPI void
1152 elm_widget_drag_lock_y_set(Evas_Object *obj, Eina_Bool lock)
1153 {
1154    API_ENTRY return;
1155    if (sd->drag_y_locked == lock) return;
1156    sd->drag_y_locked = lock;
1157    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
1158    else _propagate_y_drag_lock(obj, -1);
1159 }
1160
1161 EAPI Eina_Bool
1162 elm_widget_drag_lock_x_get(const Evas_Object *obj)
1163 {
1164    API_ENTRY return EINA_FALSE;
1165    return sd->drag_x_locked;
1166 }
1167
1168 EAPI Eina_Bool
1169 elm_widget_drag_lock_y_get(const Evas_Object *obj)
1170 {
1171    API_ENTRY return EINA_FALSE;
1172    return sd->drag_y_locked;
1173 }
1174
1175 EAPI int
1176 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
1177 {
1178    API_ENTRY return 0;
1179    return sd->child_drag_x_locked;
1180 }
1181
1182 EAPI int
1183 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
1184 {
1185    API_ENTRY return 0;
1186    return sd->child_drag_y_locked;
1187 }
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199 /* local subsystem functions */
1200 static void
1201 _smart_reconfigure(Smart_Data *sd)
1202 {
1203    if (sd->resize_obj)
1204      {
1205         evas_object_move(sd->resize_obj, sd->x, sd->y);
1206         evas_object_resize(sd->resize_obj, sd->w, sd->h);
1207      }
1208    if (sd->hover_obj)
1209      {
1210         evas_object_move(sd->hover_obj, sd->x, sd->y);
1211         evas_object_resize(sd->hover_obj, sd->w, sd->h);
1212      }
1213 }
1214
1215 static void
1216 _smart_add(Evas_Object *obj)
1217 {
1218    Smart_Data *sd;
1219
1220    sd = calloc(1, sizeof(Smart_Data));
1221    if (!sd) return;
1222    sd->obj = obj;
1223    sd->x = 0;
1224    sd->y = 0;
1225    sd->w = 0;
1226    sd->h = 0;
1227    sd->can_focus = 1;
1228    evas_object_smart_data_set(obj, sd);
1229 }
1230
1231 static Evas_Object *
1232 _newest_focus_order_get(Evas_Object *obj, unsigned int *newest_focus_order)
1233 {
1234    const Eina_List *l;
1235    Evas_Object *child, *ret, *best;
1236    
1237    API_ENTRY return NULL;
1238    if (!evas_object_visible_get(obj)) return NULL;
1239    best = NULL;
1240    if (*newest_focus_order < sd->focus_order)
1241      {
1242         *newest_focus_order = sd->focus_order;
1243         best = obj;
1244      }
1245    EINA_LIST_FOREACH(sd->subobjs, l, child)
1246      {
1247         ret = _newest_focus_order_get(child, newest_focus_order);
1248         if (!ret) continue;
1249         best = ret;
1250      }
1251    return best;
1252 }
1253
1254 static void
1255 _if_focused_revert(Evas_Object *obj)
1256 {
1257    Evas_Object *top;
1258    Evas_Object *newest = NULL;
1259    unsigned int newest_focus_order = 0;
1260    
1261    INTERNAL_ENTRY;
1262    
1263    if (!sd->focused) return;
1264    if (!sd->parent_obj) return;
1265
1266    top = elm_widget_top_get(sd->parent_obj);
1267    if (top)
1268      {
1269         newest = _newest_focus_order_get(top, &newest_focus_order);
1270         if (newest)
1271           {
1272              elm_object_unfocus(newest);
1273              elm_object_focus(newest);
1274           }
1275      }
1276 }
1277
1278 static void
1279 _smart_del(Evas_Object *obj)
1280 {
1281    Evas_Object *sobj;
1282
1283    INTERNAL_ENTRY;
1284    if (sd->del_pre_func) sd->del_pre_func(obj);
1285    if (sd->resize_obj)
1286      {
1287         sobj = sd->resize_obj;
1288         sd->resize_obj = NULL;
1289         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
1290         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
1291         evas_object_del(sobj);
1292      }
1293    if (sd->hover_obj)
1294      {
1295         sobj = sd->hover_obj;
1296         sd->hover_obj = NULL;
1297         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
1298         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
1299         evas_object_del(sobj);
1300      }
1301    EINA_LIST_FREE(sd->subobjs, sobj)
1302      {
1303         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
1304         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
1305         evas_object_del(sobj);
1306      }
1307    if (sd->del_func) sd->del_func(obj);
1308    if (sd->style) eina_stringshare_del(sd->style);
1309    if (sd->type) eina_stringshare_del(sd->type);
1310    if (sd->theme) elm_theme_free(sd->theme);
1311    _if_focused_revert(obj);
1312    free(sd);
1313 }
1314
1315 static void
1316 _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1317 {
1318    INTERNAL_ENTRY;
1319    sd->x = x;
1320    sd->y = y;
1321    _smart_reconfigure(sd);
1322 }
1323
1324 static void
1325 _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
1326 {
1327    INTERNAL_ENTRY;
1328    sd->w = w;
1329    sd->h = h;
1330    _smart_reconfigure(sd);
1331 }
1332
1333 static void
1334 _smart_show(Evas_Object *obj)
1335 {
1336    Eina_List *list, *l;
1337    Evas_Object *o;
1338    INTERNAL_ENTRY;
1339    list = evas_object_smart_members_get(obj);
1340    EINA_LIST_FOREACH(list, l, o)
1341      {
1342         if (evas_object_data_get(o, "_elm_leaveme")) continue;
1343         evas_object_show(o);
1344      }
1345 }
1346
1347 static void
1348 _smart_hide(Evas_Object *obj)
1349 {
1350    Eina_List *list, *l;
1351    Evas_Object *o;
1352    INTERNAL_ENTRY;
1353    list = evas_object_smart_members_get(obj);
1354    EINA_LIST_FOREACH(list, l, o)
1355      {
1356         if (evas_object_data_get(o, "_elm_leaveme")) continue;
1357         evas_object_hide(o);
1358      }
1359    _if_focused_revert(obj);
1360 }
1361
1362 static void
1363 _smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
1364 {
1365    Eina_List *list, *l;
1366    Evas_Object *o;
1367    INTERNAL_ENTRY;
1368    list = evas_object_smart_members_get(obj);
1369    EINA_LIST_FOREACH(list, l, o)
1370      {
1371         if (evas_object_data_get(o, "_elm_leaveme")) continue;
1372         evas_object_color_set(o, r, g, b, a);
1373      }
1374 }
1375
1376 static void
1377 _smart_clip_set(Evas_Object *obj, Evas_Object *clip)
1378 {
1379    Eina_List *list, *l;
1380    Evas_Object *o;
1381    INTERNAL_ENTRY;
1382    list = evas_object_smart_members_get(obj);
1383    EINA_LIST_FOREACH(list, l, o)
1384      {
1385         if (evas_object_data_get(o, "_elm_leaveme")) continue;
1386         evas_object_clip_set(o, clip);
1387      }
1388 }
1389
1390 static void
1391 _smart_clip_unset(Evas_Object *obj)
1392 {
1393    Eina_List *list, *l;
1394    Evas_Object *o;
1395    INTERNAL_ENTRY;
1396    list = evas_object_smart_members_get(obj);
1397    EINA_LIST_FOREACH(list, l, o)
1398      {
1399         if (evas_object_data_get(o, "_elm_leaveme")) continue;
1400         evas_object_clip_unset(o);
1401      }
1402 }
1403
1404 static void
1405 _smart_calculate(Evas_Object *obj)
1406 {
1407    INTERNAL_ENTRY;
1408    if (sd->changed_func) sd->changed_func(obj);
1409 }
1410
1411 /* never need to touch this */
1412
1413 static void
1414 _smart_init(void)
1415 {
1416    if (_e_smart) return;
1417      {
1418         static const Evas_Smart_Class sc =
1419           {
1420              SMART_NAME,
1421                EVAS_SMART_CLASS_VERSION,
1422                _smart_add,
1423                _smart_del,
1424                _smart_move,
1425                _smart_resize,
1426                _smart_show,
1427                _smart_hide,
1428                _smart_color_set,
1429                _smart_clip_set,
1430                _smart_clip_unset,
1431                _smart_calculate,
1432                NULL,
1433                NULL,
1434                NULL,
1435                NULL,
1436                NULL,
1437                NULL
1438           };
1439         _e_smart = evas_smart_class_new(&sc);
1440      }
1441 }
1442
1443 /* utilities */
1444
1445 Eina_List *
1446 _elm_stringlist_get(const char *str)
1447 {
1448    Eina_List *list = NULL;
1449    const char *s, *b;
1450    if (!str) return NULL;
1451    for (b = s = str; 1; s++)
1452      {
1453         if ((*s == ' ') || (*s == 0))
1454           {
1455              char *t = malloc(s - b + 1);
1456              if (t)
1457                {
1458                   strncpy(t, b, s - b);
1459                   t[s - b] = 0;
1460                   list = eina_list_append(list, eina_stringshare_add(t));
1461                   free(t);
1462                }
1463              b = s + 1;
1464           }
1465         if (*s == 0) break;
1466      }
1467    return list;
1468 }
1469
1470 void
1471 _elm_stringlist_free(Eina_List *list)
1472 {
1473    const char *s;
1474    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
1475 }
1476
1477 Eina_Bool
1478 _elm_widget_type_check(const Evas_Object *obj, const char *type)
1479 {
1480    const char *provided, *expected = "(unknown)";
1481    static int abort_on_warn = -1;
1482    provided = elm_widget_type_get(obj);
1483    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
1484    if (type) expected = type;
1485    if ((!provided) || (provided[0] == 0))
1486      {
1487         provided = evas_object_type_get(obj);
1488         if ((!provided) || (provided[0] == 0))
1489           provided = "(unknown)";
1490      }
1491    ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
1492    if (abort_on_warn == -1)
1493      {
1494         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1495         else abort_on_warn = 0;
1496      }
1497    if (abort_on_warn == 1) abort();
1498    return EINA_FALSE;
1499 }
1500
1501 static inline Eina_Bool
1502 _elm_widget_is(const Evas_Object *obj)
1503 {
1504    const char *type = evas_object_type_get(obj);
1505    return type == SMART_NAME;
1506 }