1 #include <Elementary.h>
4 static const char SMART_NAME[] = "elm_widget";
7 Smart_Data * sd = evas_object_smart_data_get(obj); \
8 if ((!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY \
10 Smart_Data * sd = evas_object_smart_data_get(obj); \
13 #undef elm_widget_text_set_hook_set
14 #undef elm_widget_text_get_hook_set
15 #undef elm_widget_content_set_hook_set
16 #undef elm_widget_content_get_hook_set
17 #undef elm_widget_content_unset_hook_set
19 typedef struct _Smart_Data Smart_Data;
20 typedef struct _Edje_Signal_Data Edje_Signal_Data;
21 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
28 Evas_Object *parent_obj;
30 Evas_Coord x, y, w, h;
32 Evas_Object *resize_obj;
33 Evas_Object *hover_obj;
34 Eina_List *tooltips, *cursors;
35 void (*del_func)(Evas_Object *obj);
36 void (*del_pre_func)(Evas_Object *obj);
37 void (*focus_func)(Evas_Object *obj);
38 void (*activate_func)(Evas_Object *obj);
39 void (*disable_func)(Evas_Object *obj);
40 void (*theme_func)(Evas_Object *obj);
41 void (*translate_func)(Evas_Object *obj);
42 Eina_Bool (*event_func)(Evas_Object *obj,
44 Evas_Callback_Type type,
46 void (*signal_func)(Evas_Object *obj,
49 void (*callback_add_func)(Evas_Object *obj,
54 void (*callback_del_func)(Evas_Object *obj,
59 void (*changed_func)(Evas_Object *obj);
60 Eina_Bool (*focus_next_func)(const Evas_Object *obj,
61 Elm_Focus_Direction dir,
63 void (*on_focus_func)(void *data,
66 void (*on_change_func)(void *data,
69 void (*on_show_region_func)(void *data,
71 void *on_show_region_data;
72 void (*focus_region_func)(Evas_Object *obj,
77 void (*on_focus_region_func)(const Evas_Object *obj,
82 Elm_Widget_Text_Set_Cb text_set_func;
83 Elm_Widget_Text_Get_Cb text_get_func;
84 Elm_Widget_Content_Set_Cb content_set_func;
85 Elm_Widget_Content_Get_Cb content_get_func;
86 Elm_Widget_Content_Unset_Cb content_unset_func;
88 Evas_Coord rx, ry, rw, rh;
94 const char *access_info;
95 unsigned int focus_order;
96 Eina_Bool focus_order_on_calc;
98 int child_drag_x_locked;
99 int child_drag_y_locked;
101 Eina_List *edje_signals;
102 Eina_List *translate_strings;
104 Eina_Bool drag_x_locked : 1;
105 Eina_Bool drag_y_locked : 1;
107 Eina_Bool can_focus : 1;
108 Eina_Bool child_can_focus : 1;
109 Eina_Bool focused : 1;
110 Eina_Bool top_win_focused : 1;
111 Eina_Bool tree_unfocusable : 1;
112 Eina_Bool highlight_ignore : 1;
113 Eina_Bool highlight_in_theme : 1;
114 Eina_Bool disabled : 1;
115 Eina_Bool is_mirrored : 1;
116 Eina_Bool mirrored_auto_mode : 1; /* This is TRUE by default */
117 Eina_Bool still_in : 1;
119 Eina_List *focus_chain;
123 struct _Edje_Signal_Data
127 const char *emission;
132 struct _Elm_Event_Cb_Data
138 struct _Elm_Translate_String_Data
145 /* local subsystem functions */
146 static void _smart_reconfigure(Smart_Data *sd);
147 static void _smart_add(Evas_Object *obj);
148 static void _smart_del(Evas_Object *obj);
149 static void _smart_move(Evas_Object *obj,
152 static void _smart_resize(Evas_Object *obj,
155 static void _smart_show(Evas_Object *obj);
156 static void _smart_hide(Evas_Object *obj);
157 static void _smart_color_set(Evas_Object *obj,
162 static void _smart_clip_set(Evas_Object *obj,
164 static void _smart_clip_unset(Evas_Object *obj);
165 static void _smart_calculate(Evas_Object *obj);
166 static void _smart_member_add(Evas_Object *obj, Evas_Object *child);
167 static void _smart_member_del(Evas_Object *obj, Evas_Object *child);
168 static void _smart_init(void);
170 static void _if_focused_revert(Evas_Object *obj,
171 Eina_Bool can_focus_only);
172 static Evas_Object *_newest_focus_order_get(Evas_Object *obj,
173 unsigned int *newest_focus_order,
174 Eina_Bool can_focus_only);
176 /* local subsystem globals */
177 static Evas_Smart *_e_smart = NULL;
178 static Eina_List *widtypes = NULL;
180 static unsigned int focus_order = 0;
183 static inline Eina_Bool
184 _elm_widget_is(const Evas_Object *obj)
186 const char *type = evas_object_type_get(obj);
187 return type == SMART_NAME;
190 static inline Eina_Bool
191 _is_focusable(Evas_Object *obj)
193 API_ENTRY return EINA_FALSE;
194 return sd->can_focus || (sd->child_can_focus);
198 _unfocus_parents(Evas_Object *obj)
200 for (; obj; obj = elm_widget_parent_get(obj))
203 if (!sd->focused) return;
209 _focus_parents(Evas_Object *obj)
211 for (; obj; obj = elm_widget_parent_get(obj))
214 if (sd->focused) return;
220 _sub_obj_del(void *data,
223 void *event_info __UNUSED__)
225 Smart_Data *sd = data;
227 if (_elm_widget_is(obj))
229 if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
231 if (obj == sd->resize_obj)
232 sd->resize_obj = NULL;
233 else if (obj == sd->hover_obj)
234 sd->hover_obj = NULL;
236 sd->subobjs = eina_list_remove(sd->subobjs, obj);
237 evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
241 _sub_obj_hide(void *data __UNUSED__,
244 void *event_info __UNUSED__)
246 elm_widget_focus_hide_handle(obj);
250 _sub_obj_mouse_down(void *data,
252 Evas_Object *obj __UNUSED__,
255 Smart_Data *sd = data;
256 Evas_Event_Mouse_Down *ev = event_info;
257 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
258 sd->still_in = EINA_TRUE;
262 _sub_obj_mouse_move(void *data,
267 Smart_Data *sd = data;
268 Evas_Event_Mouse_Move *ev = event_info;
271 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
272 sd->still_in = EINA_FALSE;
275 Evas_Coord x, y, w, h;
276 evas_object_geometry_get(obj, &x, &y, &w, &h);
277 if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
278 (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
279 sd->still_in = EINA_FALSE;
285 _sub_obj_mouse_up(void *data,
288 void *event_info __UNUSED__)
290 Smart_Data *sd = data;
292 elm_widget_focus_mouse_up_handle(obj);
293 sd->still_in = EINA_FALSE;
297 _propagate_x_drag_lock(Evas_Object *obj,
303 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
306 sd2->child_drag_x_locked += dir;
307 _propagate_x_drag_lock(sd->parent_obj, dir);
313 _propagate_y_drag_lock(Evas_Object *obj,
319 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
322 sd2->child_drag_y_locked += dir;
323 _propagate_y_drag_lock(sd->parent_obj, dir);
329 _propagate_event(void *data,
335 Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
336 Evas_Event_Flags *event_flags = NULL;
340 case EVAS_CALLBACK_KEY_DOWN:
342 Evas_Event_Key_Down *ev = event_info;
343 event_flags = &(ev->event_flags);
347 case EVAS_CALLBACK_KEY_UP:
349 Evas_Event_Key_Up *ev = event_info;
350 event_flags = &(ev->event_flags);
354 case EVAS_CALLBACK_MOUSE_WHEEL:
356 Evas_Event_Mouse_Wheel *ev = event_info;
357 event_flags = &(ev->event_flags);
365 elm_widget_event_propagate(obj, type, event_info, event_flags);
369 _parent_focus(Evas_Object *obj)
372 if (sd->focused) return;
374 Evas_Object *o = elm_widget_parent_get(obj);
375 sd->focus_order_on_calc = EINA_TRUE;
377 if (o) _parent_focus(o);
379 if (!sd->focus_order_on_calc)
380 return; /* we don't want to override it if by means of any of the
381 callbacks below one gets to calculate our order
385 sd->focus_order = focus_order;
386 if (sd->top_win_focused)
388 sd->focused = EINA_TRUE;
389 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
390 if (sd->focus_func) sd->focus_func(obj);
391 _elm_widget_focus_region_show(obj);
393 sd->focus_order_on_calc = EINA_FALSE;
397 _elm_object_focus_chain_del_cb(void *data,
400 void *event_info __UNUSED__)
402 Smart_Data *sd = data;
404 sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
407 // exposed util funcs to elm
409 _elm_widget_type_clear(void)
413 EINA_LIST_FREE(widtypes, ptr)
415 eina_stringshare_del(*ptr);
421 _elm_widget_focus_region_show(const Evas_Object *obj)
423 Evas_Coord x, y, w, h, ox, oy;
429 o = elm_widget_parent_get(obj);
432 elm_widget_focus_region_get(obj, &x, &y, &w, &h);
433 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
437 sd2 = evas_object_smart_data_get(o);
438 if (sd2->focus_region_func)
440 sd2->focus_region_func(o, x, y, w, h);
441 elm_widget_focus_region_get(o, &x, &y, &w, &h);
445 evas_object_geometry_get(o, &px, &py, NULL, NULL);
451 o = elm_widget_parent_get(o);
456 * @defgroup Widget Widget
459 * Exposed api for making widgets
462 elm_widget_type_register(const char **ptr)
464 widtypes = eina_list_append(widtypes, (void *)ptr);
468 * @defgroup Widget Widget
471 * Disposed api for making widgets
474 elm_widget_type_unregister(const char **ptr)
476 widtypes = eina_list_remove(widtypes, (void *)ptr);
480 elm_widget_api_check(int ver)
482 if (ver != ELM_INTERNAL_API_VERSION)
484 CRITICAL("Elementary widget api versions do not match");
491 elm_widget_add(Evas *evas)
495 obj = evas_object_smart_add(evas, _e_smart);
496 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
501 elm_widget_del_hook_set(Evas_Object *obj,
502 void (*func)(Evas_Object *obj))
509 elm_widget_del_pre_hook_set(Evas_Object *obj,
510 void (*func)(Evas_Object *obj))
513 sd->del_pre_func = func;
517 elm_widget_focus_hook_set(Evas_Object *obj,
518 void (*func)(Evas_Object *obj))
521 sd->focus_func = func;
525 elm_widget_activate_hook_set(Evas_Object *obj,
526 void (*func)(Evas_Object *obj))
529 sd->activate_func = func;
533 elm_widget_disable_hook_set(Evas_Object *obj,
534 void (*func)(Evas_Object *obj))
537 sd->disable_func = func;
541 elm_widget_theme_hook_set(Evas_Object *obj,
542 void (*func)(Evas_Object *obj))
545 sd->theme_func = func;
549 elm_widget_translate_hook_set(Evas_Object *obj,
550 void (*func)(Evas_Object *obj))
553 sd->translate_func = func;
557 elm_widget_event_hook_set(Evas_Object *obj,
558 Eina_Bool (*func)(Evas_Object *obj,
560 Evas_Callback_Type type,
564 sd->event_func = func;
568 elm_widget_text_set_hook_set(Evas_Object *obj,
569 Elm_Widget_Text_Set_Cb func)
572 sd->text_set_func = func;
576 elm_widget_text_get_hook_set(Evas_Object *obj,
577 Elm_Widget_Text_Get_Cb func)
580 sd->text_get_func = func;
584 elm_widget_content_set_hook_set(Evas_Object *obj,
585 Elm_Widget_Content_Set_Cb func)
588 sd->content_set_func = func;
592 elm_widget_content_get_hook_set(Evas_Object *obj,
593 Elm_Widget_Content_Get_Cb func)
596 sd->content_get_func = func;
600 elm_widget_content_unset_hook_set(Evas_Object *obj,
601 Elm_Widget_Content_Unset_Cb func)
604 sd->content_unset_func = func;
608 elm_widget_changed_hook_set(Evas_Object *obj,
609 void (*func)(Evas_Object *obj))
612 sd->changed_func = func;
616 elm_widget_signal_emit_hook_set(Evas_Object *obj,
617 void (*func)(Evas_Object *obj,
618 const char *emission,
622 sd->signal_func = func;
626 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
627 void (*func)(Evas_Object *obj,
628 const char *emission,
630 Edje_Signal_Cb func_cb,
634 sd->callback_add_func = func;
638 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
639 void (*func)(Evas_Object *obj,
640 const char *emission,
642 Edje_Signal_Cb func_cb,
646 sd->callback_del_func = func;
650 elm_widget_theme(Evas_Object *obj)
656 Eina_Bool ret = EINA_TRUE;
658 API_ENTRY return EINA_FALSE;
659 EINA_LIST_FOREACH(sd->subobjs, l, child) ret &= elm_widget_theme(child);
660 if (sd->resize_obj && _elm_widget_is(sd->resize_obj))
661 ret &= elm_widget_theme(sd->resize_obj);
662 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
663 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
664 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
665 if (sd->theme_func) sd->theme_func(obj);
671 elm_widget_theme_specific(Evas_Object *obj,
679 Elm_Theme *th2, *thdef;
682 thdef = elm_theme_default_get();
687 if (!th2) th2 = thdef;
695 if (th2 == thdef) break;
696 th2 = th2->ref_theme;
697 if (!th2) th2 = thdef;
701 EINA_LIST_FOREACH(sd->subobjs, l, child)
702 elm_widget_theme_specific(child, th, force);
703 if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
704 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
705 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
706 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
707 if (sd->theme_func) sd->theme_func(obj);
713 * Set hook to get next object in object focus chain.
715 * @param obj The widget object.
716 * @param func The hook to be used with this widget.
721 elm_widget_focus_next_hook_set(Evas_Object *obj,
722 Eina_Bool (*func)(const Evas_Object *obj,
723 Elm_Focus_Direction dir,
727 sd->focus_next_func = func;
731 * Returns the widget's mirrored mode.
733 * @param obj The widget.
734 * @return mirrored mode of the object.
738 elm_widget_mirrored_get(const Evas_Object *obj)
740 API_ENTRY return EINA_FALSE;
741 return sd->is_mirrored;
745 * Sets the widget's mirrored mode.
747 * @param obj The widget.
748 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
751 elm_widget_mirrored_set(Evas_Object *obj,
755 if (sd->is_mirrored != mirrored)
757 sd->is_mirrored = mirrored;
758 elm_widget_theme(obj);
764 * Resets the mirrored mode from the system mirror mode for widgets that are in
765 * automatic mirroring mode. This function does not call elm_widget_theme.
767 * @param obj The widget.
768 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
771 _elm_widget_mirrored_reload(Evas_Object *obj)
774 Eina_Bool mirrored = elm_config_mirrored_get();
775 if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
777 sd->is_mirrored = mirrored;
782 * Returns the widget's mirrored mode setting.
784 * @param obj The widget.
785 * @return mirrored mode setting of the object.
789 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
791 API_ENTRY return EINA_FALSE;
792 return sd->mirrored_auto_mode;
796 * Sets the widget's mirrored mode setting.
797 * When widget in automatic mode, it follows the system mirrored mode set by
798 * elm_mirrored_set().
799 * @param obj The widget.
800 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
803 elm_widget_mirrored_automatic_set(Evas_Object *obj,
807 if (sd->mirrored_auto_mode != automatic)
809 sd->mirrored_auto_mode = automatic;
813 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
819 elm_widget_on_focus_hook_set(Evas_Object *obj,
820 void (*func)(void *data,
825 sd->on_focus_func = func;
826 sd->on_focus_data = data;
830 elm_widget_on_change_hook_set(Evas_Object *obj,
831 void (*func)(void *data,
836 sd->on_change_func = func;
837 sd->on_change_data = data;
841 elm_widget_on_show_region_hook_set(Evas_Object *obj,
842 void (*func)(void *data,
847 sd->on_show_region_func = func;
848 sd->on_show_region_data = data;
854 * Set the hook to use to show the focused region.
856 * Whenever a new widget gets focused or it's needed to show the focused
857 * area of the current one, this hook will be called on objects that may
858 * want to move their children into their visible area.
859 * The area given in the hook function is relative to the @p obj widget.
861 * @param obj The widget object
862 * @param func The function to call to show the specified area.
867 elm_widget_focus_region_hook_set(Evas_Object *obj,
868 void (*func)(Evas_Object *obj,
875 sd->focus_region_func = func;
881 * Set the hook to retrieve the focused region of a widget.
883 * This hook will be called by elm_widget_focus_region_get() whenever
884 * it's needed to get the focused area of a widget. The area must be relative
885 * to the widget itself and if no hook is set, it will default to the entire
888 * @param obj The widget object
889 * @param func The function used to retrieve the focus region.
894 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
895 void (*func)(const Evas_Object *obj,
902 sd->on_focus_region_func = func;
906 elm_widget_data_set(Evas_Object *obj,
914 elm_widget_data_get(const Evas_Object *obj)
916 API_ENTRY return NULL;
921 elm_widget_sub_object_add(Evas_Object *obj,
925 EINA_SAFETY_ON_TRUE_RETURN(obj == sobj);
926 double scale, pscale = elm_widget_scale_get(sobj);
927 Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
928 Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
930 if (sobj == sd->parent_obj)
932 elm_widget_sub_object_del(sobj, obj);
933 WRN("You passed a parent object of obj = %p as the sub object = %p!", obj, sobj);
936 if (_elm_widget_is(sobj))
938 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
941 if (sd2->parent_obj == obj)
944 elm_widget_sub_object_del(sd2->parent_obj, sobj);
945 sd2->parent_obj = obj;
946 _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
947 if (!sd->child_can_focus && (_is_focusable(sobj)))
948 sd->child_can_focus = EINA_TRUE;
953 void *data = evas_object_data_get(sobj, "elm-parent");
956 if (data == obj) return;
957 evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
961 sd->subobjs = eina_list_append(sd->subobjs, sobj);
962 evas_object_data_set(sobj, "elm-parent", obj);
963 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
964 if (_elm_widget_is(sobj))
965 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
966 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
967 scale = elm_widget_scale_get(sobj);
968 th = elm_widget_theme_get(sobj);
969 mirrored = elm_widget_mirrored_get(sobj);
970 if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
971 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
975 elm_widget_sub_object_del(Evas_Object *obj,
978 Evas_Object *sobj_parent;
982 sobj_parent = evas_object_data_del(sobj, "elm-parent");
983 if (sobj_parent != obj)
985 static int abort_on_warn = -1;
986 ERR("removing sub object %p (%s) from parent %p (%s), "
987 "but elm-parent is different %p (%s)!",
988 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
989 sobj_parent, elm_widget_type_get(sobj_parent));
990 if (EINA_UNLIKELY(abort_on_warn == -1))
992 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
993 else abort_on_warn = 0;
995 if (abort_on_warn == 1) abort();
997 if (_elm_widget_is(sobj))
999 if (elm_widget_focus_get(sobj))
1001 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1002 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1004 if ((sd->child_can_focus) && (_is_focusable(sobj)))
1006 Evas_Object *subobj;
1008 sd->child_can_focus = EINA_FALSE;
1009 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1011 if (_is_focusable(subobj))
1013 sd->child_can_focus = EINA_TRUE;
1018 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1021 sd2->parent_obj = NULL;
1022 if (sd2->resize_obj == sobj)
1023 sd2->resize_obj = NULL;
1025 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1028 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1031 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1032 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1034 if (_elm_widget_is(sobj))
1035 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1037 evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1040 EAPI const Eina_List *
1041 elm_widget_sub_object_list_get(const Evas_Object *obj)
1043 API_ENTRY return NULL;
1044 return (const Eina_List *)sd->subobjs;
1048 elm_widget_resize_object_set(Evas_Object *obj,
1052 // orphan previous resize obj
1055 evas_object_clip_unset(sd->resize_obj);
1056 evas_object_data_del(sd->resize_obj, "elm-parent");
1057 if (_elm_widget_is(sd->resize_obj))
1059 Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1060 if (sd2) sd2->parent_obj = NULL;
1061 evas_object_event_callback_del_full(sd->resize_obj,
1065 evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1067 evas_object_event_callback_del_full(sd->resize_obj,
1068 EVAS_CALLBACK_MOUSE_DOWN,
1069 _sub_obj_mouse_down, sd);
1070 evas_object_event_callback_del_full(sd->resize_obj,
1071 EVAS_CALLBACK_MOUSE_MOVE,
1072 _sub_obj_mouse_move, sd);
1073 evas_object_event_callback_del_full(sd->resize_obj,
1074 EVAS_CALLBACK_MOUSE_UP,
1075 _sub_obj_mouse_up, sd);
1076 evas_object_smart_member_del(sd->resize_obj);
1078 if (_elm_widget_is(sd->resize_obj))
1080 if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1084 sd->resize_obj = sobj;
1087 // orphan new resize obj
1088 evas_object_data_del(sobj, "elm-parent");
1089 if (_elm_widget_is(sobj))
1091 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1092 if (sd2) sd2->parent_obj = NULL;
1093 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1096 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1098 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1099 _sub_obj_mouse_down, sd);
1100 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1101 _sub_obj_mouse_move, sd);
1102 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1103 _sub_obj_mouse_up, sd);
1104 evas_object_smart_member_del(sobj);
1105 if (_elm_widget_is(sobj))
1107 if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1110 // set the resize obj up
1111 if (_elm_widget_is(sobj))
1113 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1116 sd2->parent_obj = obj;
1117 sd2->top_win_focused = sd->top_win_focused;
1119 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1122 evas_object_smart_member_add(sobj, obj);
1123 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1125 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1126 _sub_obj_mouse_down, sd);
1127 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1128 _sub_obj_mouse_move, sd);
1129 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1130 _sub_obj_mouse_up, sd);
1131 _smart_reconfigure(sd);
1132 evas_object_data_set(sobj, "elm-parent", obj);
1133 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1134 if (_elm_widget_is(sobj))
1136 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1141 elm_widget_hover_object_set(Evas_Object *obj,
1147 evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1150 sd->hover_obj = sobj;
1153 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1155 _smart_reconfigure(sd);
1160 elm_widget_can_focus_set(Evas_Object *obj,
1161 Eina_Bool can_focus)
1165 can_focus = !!can_focus;
1167 if (sd->can_focus == can_focus) return;
1168 sd->can_focus = can_focus;
1171 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1173 (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1174 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1176 (void *)(long)EVAS_CALLBACK_KEY_UP);
1177 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1179 (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1183 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1185 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1187 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1193 elm_widget_can_focus_get(const Evas_Object *obj)
1195 API_ENTRY return EINA_FALSE;
1196 return sd->can_focus;
1200 elm_widget_child_can_focus_get(const Evas_Object *obj)
1202 API_ENTRY return EINA_FALSE;
1203 return sd->child_can_focus;
1209 * This API makes the widget object and its children to be unfocusable.
1211 * This API can be helpful for an object to be deleted.
1212 * When an object will be deleted soon, it and its children may not
1213 * want to get focus (by focus reverting or by other focus controls).
1214 * Then, just use this API before deleting.
1216 * @param obj The widget root of sub-tree
1217 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1222 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1223 Eina_Bool tree_unfocusable)
1227 tree_unfocusable = !!tree_unfocusable;
1228 if (sd->tree_unfocusable == tree_unfocusable) return;
1229 sd->tree_unfocusable = tree_unfocusable;
1230 elm_widget_focus_tree_unfocusable_handle(obj);
1236 * This returns true, if the object sub-tree is unfocusable.
1238 * @param obj The widget root of sub-tree
1239 * @return EINA_TRUE if the object sub-tree is unfocusable
1244 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1246 API_ENTRY return EINA_FALSE;
1247 return sd->tree_unfocusable;
1253 * Get the list of focusable child objects.
1255 * This function retruns list of child objects which can get focus.
1257 * @param obj The parent widget
1258 * @retrun list of focusable child objects.
1263 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1265 API_ENTRY return NULL;
1268 Eina_List *child_list = NULL;
1273 EINA_LIST_FOREACH(sd->subobjs, l, child)
1275 if ((elm_widget_can_focus_get(child)) &&
1276 (evas_object_visible_get(child)) &&
1277 (!elm_widget_disabled_get(child)))
1278 child_list = eina_list_append(child_list, child);
1279 else if (elm_widget_is(child))
1281 Eina_List *can_focus_list;
1282 can_focus_list = elm_widget_can_focus_child_list_get(child);
1284 child_list = eina_list_merge(child_list, can_focus_list);
1292 elm_widget_highlight_ignore_set(Evas_Object *obj,
1296 sd->highlight_ignore = !!ignore;
1300 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1302 API_ENTRY return EINA_FALSE;
1303 return sd->highlight_ignore;
1307 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1308 Eina_Bool highlight)
1311 sd->highlight_in_theme = !!highlight;
1312 /* FIXME: if focused, it should switch from one mode to the other */
1316 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1318 API_ENTRY return EINA_FALSE;
1319 return sd->highlight_in_theme;
1323 elm_widget_focus_get(const Evas_Object *obj)
1325 API_ENTRY return EINA_FALSE;
1330 elm_widget_focused_object_get(const Evas_Object *obj)
1332 const Evas_Object *subobj;
1334 API_ENTRY return NULL;
1336 if (!sd->focused) return NULL;
1337 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1339 Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1340 if (fobj) return fobj;
1342 return (Evas_Object *)obj;
1346 elm_widget_top_get(const Evas_Object *obj)
1348 API_ENTRY return NULL;
1349 if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1350 return (Evas_Object *)obj;
1354 elm_widget_is(const Evas_Object *obj)
1356 return _elm_widget_is(obj);
1360 elm_widget_parent_widget_get(const Evas_Object *obj)
1362 Evas_Object *parent;
1364 if (_elm_widget_is(obj))
1366 Smart_Data *sd = evas_object_smart_data_get(obj);
1367 if (!sd) return NULL;
1368 parent = sd->parent_obj;
1372 parent = evas_object_data_get(obj, "elm-parent");
1373 if (!parent) parent = evas_object_smart_parent_get(obj);
1378 Evas_Object *elm_parent;
1379 if (_elm_widget_is(parent)) break;
1380 elm_parent = evas_object_data_get(parent, "elm-parent");
1381 if (elm_parent) parent = elm_parent;
1382 else parent = evas_object_smart_parent_get(parent);
1388 elm_widget_parent2_get(const Evas_Object *obj)
1390 if (_elm_widget_is(obj))
1392 Smart_Data *sd = evas_object_smart_data_get(obj);
1393 if (sd) return sd->parent2;
1399 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1402 sd->parent2 = parent;
1406 elm_widget_event_callback_add(Evas_Object *obj,
1411 EINA_SAFETY_ON_NULL_RETURN(func);
1412 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1415 sd->event_cb = eina_list_append(sd->event_cb, ecb);
1419 elm_widget_event_callback_del(Evas_Object *obj,
1423 API_ENTRY return NULL;
1424 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1426 Elm_Event_Cb_Data *ecd;
1427 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1428 if ((ecd->func == func) && (ecd->data == data))
1431 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1432 return (void *)data;
1438 elm_widget_event_propagate(Evas_Object *obj,
1439 Evas_Callback_Type type,
1441 Evas_Event_Flags *event_flags)
1443 API_ENTRY return EINA_FALSE; //TODO reduce.
1444 if (!_elm_widget_is(obj)) return EINA_FALSE;
1445 Evas_Object *parent = obj;
1446 Elm_Event_Cb_Data *ecd;
1447 Eina_List *l, *l_prev;
1450 (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1452 sd = evas_object_smart_data_get(parent);
1453 if ((!sd) || (!_elm_widget_is(obj)))
1454 return EINA_FALSE; //Not Elm Widget
1456 if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1459 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1461 if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1462 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1465 parent = sd->parent_obj;
1474 * Set custom focus chain.
1476 * This function i set one new and overwrite any previous custom focus chain
1477 * with the list of objects. The previous list will be deleted and this list
1478 * will be managed. After setted, don't modity it.
1480 * @note On focus cycle, only will be evaluated children of this container.
1482 * @param obj The container widget
1483 * @param objs Chain of objects to pass focus
1487 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1491 if (!sd->focus_next_func)
1494 elm_widget_focus_custom_chain_unset(obj);
1499 EINA_LIST_FOREACH(objs, l, o)
1501 evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1502 _elm_object_focus_chain_del_cb, sd);
1505 sd->focus_chain = objs;
1511 * Get custom focus chain
1513 * @param obj The container widget
1516 EAPI const Eina_List *
1517 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1519 API_ENTRY return NULL;
1520 return (const Eina_List *)sd->focus_chain;
1526 * Unset custom focus chain
1528 * @param obj The container widget
1532 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1535 Eina_List *l, *l_next;
1538 EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1540 evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1541 _elm_object_focus_chain_del_cb, sd);
1542 sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1549 * Append object to custom focus chain.
1551 * @note If relative_child equal to NULL or not in custom chain, the object
1552 * will be added in end.
1554 * @note On focus cycle, only will be evaluated children of this container.
1556 * @param obj The container widget
1557 * @param child The child to be added in custom chain
1558 * @param relative_child The relative object to position the child
1562 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1564 Evas_Object *relative_child)
1567 EINA_SAFETY_ON_NULL_RETURN(child);
1568 if (!sd->focus_next_func) return;
1570 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1571 _elm_object_focus_chain_del_cb, sd);
1573 if (!relative_child)
1574 sd->focus_chain = eina_list_append(sd->focus_chain, child);
1576 sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1577 child, relative_child);
1583 * Prepend object to custom focus chain.
1585 * @note If relative_child equal to NULL or not in custom chain, the object
1586 * will be added in begin.
1588 * @note On focus cycle, only will be evaluated children of this container.
1590 * @param obj The container widget
1591 * @param child The child to be added in custom chain
1592 * @param relative_child The relative object to position the child
1596 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1598 Evas_Object *relative_child)
1601 EINA_SAFETY_ON_NULL_RETURN(child);
1603 if (!sd->focus_next_func) return;
1605 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1606 _elm_object_focus_chain_del_cb, sd);
1608 if (!relative_child)
1609 sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1611 sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1612 child, relative_child);
1618 * Give focus to next object in object tree.
1620 * Give focus to next object in focus chain of one object sub-tree.
1621 * If the last object of chain already have focus, the focus will go to the
1622 * first object of chain.
1624 * @param obj The widget root of sub-tree
1625 * @param dir Direction to cycle the focus
1630 elm_widget_focus_cycle(Evas_Object *obj,
1631 Elm_Focus_Direction dir)
1633 Evas_Object *target = NULL;
1634 if (!_elm_widget_is(obj))
1636 elm_widget_focus_next_get(obj, dir, &target);
1638 elm_widget_focus_steal(target);
1644 * Give focus to near object in one direction.
1646 * Give focus to near object in direction of one object.
1647 * If none focusable object in given direction, the focus will not change.
1649 * @param obj The reference widget
1650 * @param x Horizontal component of direction to focus
1651 * @param y Vertical component of direction to focus
1655 //FIXME: If x, y indicates the elements of the directional vector,
1656 //It would be better if these values are the normalized value(float x, float y)
1658 EINA_DEPRECATED EAPI void
1659 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1669 * Get next object in focus chain of object tree.
1671 * Get next object in focus chain of one object sub-tree.
1672 * Return the next object by reference. If don't have any candidate to receive
1673 * focus before chain end, the first candidate will be returned.
1675 * @param obj The widget root of sub-tree
1676 * @param dir Direction os focus chain
1677 * @param next The next object in focus chain
1678 * @return EINA_TRUE if don't need focus chain restart/loop back
1679 * to use 'next' obj.
1684 elm_widget_focus_next_get(const Evas_Object *obj,
1685 Elm_Focus_Direction dir,
1692 API_ENTRY return EINA_FALSE;
1694 /* Ignore if disabled */
1695 if ((!evas_object_visible_get(obj))
1696 || (elm_widget_disabled_get(obj))
1697 || (elm_widget_tree_unfocusable_get(obj)))
1701 if (sd->focus_next_func)
1702 return sd->focus_next_func(obj, dir, next);
1704 if (!elm_widget_can_focus_get(obj))
1708 *next = (Evas_Object *)obj;
1709 return !elm_widget_focus_get(obj);
1715 * Get next object in focus chain of object tree in list.
1717 * Get next object in focus chain of one object sub-tree ordered by one list.
1718 * Return the next object by reference. If don't have any candidate to receive
1719 * focus before list end, the first candidate will be returned.
1721 * @param obj The widget root of sub-tree
1722 * @param dir Direction os focus chain
1723 * @param items list with ordered objects
1724 * @param list_data_get function to get the object from one item of list
1725 * @param next The next object in focus chain
1726 * @return EINA_TRUE if don't need focus chain restart/loop back
1727 * to use 'next' obj.
1732 elm_widget_focus_list_next_get(const Evas_Object *obj,
1733 const Eina_List *items,
1734 void *(*list_data_get)(const Eina_List * list),
1735 Elm_Focus_Direction dir,
1738 Eina_List *(*list_next)(const Eina_List * list) = NULL;
1744 if (!_elm_widget_is(obj))
1751 if (dir == ELM_FOCUS_PREVIOUS)
1753 items = eina_list_last(items);
1754 list_next = eina_list_prev;
1756 else if (dir == ELM_FOCUS_NEXT)
1757 list_next = eina_list_next;
1761 const Eina_List *l = items;
1763 /* Recovery last focused sub item */
1764 if (elm_widget_focus_get(obj))
1765 for (; l; l = list_next(l))
1767 Evas_Object *cur = list_data_get(l);
1768 if (elm_widget_focus_get(cur)) break;
1771 const Eina_List *start = l;
1772 Evas_Object *to_focus = NULL;
1774 /* Interate sub items */
1775 /* Go to end of list */
1776 for (; l; l = list_next(l))
1778 Evas_Object *tmp = NULL;
1779 Evas_Object *cur = list_data_get(l);
1781 if (elm_widget_parent_get(cur) != obj)
1784 /* Try Focus cycle in subitem */
1785 if (elm_widget_focus_next_get(cur, dir, &tmp))
1790 else if ((tmp) && (!to_focus))
1796 /* Get First possible */
1797 for (; l != start; l = list_next(l))
1799 Evas_Object *tmp = NULL;
1800 Evas_Object *cur = list_data_get(l);
1802 if (elm_widget_parent_get(cur) != obj)
1805 /* Try Focus cycle in subitem */
1806 elm_widget_focus_next_get(cur, dir, &tmp);
1819 elm_widget_signal_emit(Evas_Object *obj,
1820 const char *emission,
1824 if (!sd->signal_func) return;
1825 sd->signal_func(obj, emission, source);
1829 _edje_signal_callback(void *data,
1830 Evas_Object *obj __UNUSED__,
1831 const char *emission,
1834 Edje_Signal_Data *esd = data;
1835 esd->func(esd->data, esd->obj, emission, source);
1839 elm_widget_signal_callback_add(Evas_Object *obj,
1840 const char *emission,
1842 Edje_Signal_Cb func,
1845 Edje_Signal_Data *esd;
1847 if (!sd->callback_add_func) return;
1848 EINA_SAFETY_ON_NULL_RETURN(func);
1850 esd = ELM_NEW(Edje_Signal_Data);
1855 esd->emission = eina_stringshare_add(emission);
1856 esd->source = eina_stringshare_add(source);
1858 sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1859 sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1863 elm_widget_signal_callback_del(Evas_Object *obj,
1864 const char *emission,
1866 Edje_Signal_Cb func)
1868 Edje_Signal_Data *esd;
1871 API_ENTRY return NULL;
1872 if (!sd->callback_del_func) return NULL;
1874 EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1876 if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1877 (!strcmp(esd->source, source)))
1879 sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1880 eina_stringshare_del(esd->emission);
1881 eina_stringshare_del(esd->source);
1885 sd->callback_del_func
1886 (obj, emission, source, _edje_signal_callback, esd);
1895 elm_widget_focus_set(Evas_Object *obj,
1902 sd->focus_order = focus_order;
1903 sd->focused = EINA_TRUE;
1904 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1908 sd->focus_func(obj);
1915 if ((_is_focusable(sd->resize_obj)) &&
1916 (!elm_widget_disabled_get(sd->resize_obj)))
1918 elm_widget_focus_set(sd->resize_obj, first);
1924 EINA_LIST_FOREACH(sd->subobjs, l, child)
1926 if ((_is_focusable(child)) &&
1927 (!elm_widget_disabled_get(child)))
1929 elm_widget_focus_set(child, first);
1939 EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1941 if ((_is_focusable(child)) &&
1942 (!elm_widget_disabled_get(child)))
1944 elm_widget_focus_set(child, first);
1950 if ((_is_focusable(sd->resize_obj)) &&
1951 (!elm_widget_disabled_get(sd->resize_obj)))
1953 elm_widget_focus_set(sd->resize_obj, first);
1961 elm_widget_parent_get(const Evas_Object *obj)
1963 API_ENTRY return NULL;
1964 return sd->parent_obj;
1968 elm_widget_focused_object_clear(Evas_Object *obj)
1971 if (!sd->focused) return;
1972 if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
1973 elm_widget_focused_object_clear(sd->resize_obj);
1978 EINA_LIST_FOREACH(sd->subobjs, l, child)
1980 if (elm_widget_focus_get(child))
1982 elm_widget_focused_object_clear(child);
1987 sd->focused = EINA_FALSE;
1988 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1989 if (sd->focus_func) sd->focus_func(obj);
1993 elm_widget_focus_steal(Evas_Object *obj)
1995 Evas_Object *parent, *parent2, *o;
1998 if (sd->focused) return;
1999 if (sd->disabled) return;
2000 if (!sd->can_focus) return;
2001 if (sd->tree_unfocusable) return;
2005 o = elm_widget_parent_get(parent);
2007 sd = evas_object_smart_data_get(o);
2008 if (sd->disabled || sd->tree_unfocusable) return;
2009 if (sd->focused) break;
2012 if ((!elm_widget_parent_get(parent)) &&
2013 (!elm_widget_parent2_get(parent)))
2014 elm_widget_focused_object_clear(parent);
2017 parent2 = elm_widget_parent_get(parent);
2018 if (!parent2) parent2 = elm_widget_parent2_get(parent);
2020 sd = evas_object_smart_data_get(parent);
2023 if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2024 elm_widget_focused_object_clear(sd->resize_obj);
2029 EINA_LIST_FOREACH(sd->subobjs, l, child)
2031 if (elm_widget_focus_get(child))
2033 elm_widget_focused_object_clear(child);
2045 elm_widget_focus_restore(Evas_Object *obj)
2047 Evas_Object *newest = NULL;
2048 unsigned int newest_focus_order = 0;
2051 newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2054 elm_object_focus_set(newest, EINA_FALSE);
2055 elm_object_focus_set(newest, EINA_TRUE);
2060 _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2066 if (sd->top_win_focused == top_win_focused) return;
2068 _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2069 EINA_LIST_FOREACH(sd->subobjs, l, child)
2071 _elm_widget_top_win_focused_set(child, top_win_focused);
2073 sd->top_win_focused = top_win_focused;
2077 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2079 API_ENTRY return EINA_FALSE;
2080 return sd->top_win_focused;
2084 elm_widget_activate(Evas_Object *obj)
2087 elm_widget_change(obj);
2088 if (sd->activate_func) sd->activate_func(obj);
2092 elm_widget_change(Evas_Object *obj)
2095 elm_widget_change(elm_widget_parent_get(obj));
2096 if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2100 elm_widget_disabled_set(Evas_Object *obj,
2105 if (sd->disabled == disabled) return;
2106 sd->disabled = !!disabled;
2107 elm_widget_focus_disabled_handle(obj);
2108 if (sd->disable_func) sd->disable_func(obj);
2112 elm_widget_disabled_get(const Evas_Object *obj)
2115 return sd->disabled;
2119 elm_widget_show_region_set(Evas_Object *obj,
2124 Eina_Bool forceshow)
2126 Evas_Object *parent_obj, *child_obj;
2127 Evas_Coord px, py, cx, cy;
2131 evas_smart_objects_calculate(evas_object_evas_get(obj));
2133 if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2134 (w == sd->rw) && (h == sd->rh)) return;
2139 if (sd->on_show_region_func)
2140 sd->on_show_region_func(sd->on_show_region_data, obj);
2144 parent_obj = sd->parent_obj;
2145 child_obj = sd->obj;
2146 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2147 sd = evas_object_smart_data_get(parent_obj);
2150 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2151 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2160 if (sd->on_show_region_func)
2162 sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2169 elm_widget_show_region_get(const Evas_Object *obj,
2185 * Get the focus region of the given widget.
2187 * The focus region is the area of a widget that should brought into the
2188 * visible area when the widget is focused. Mostly used to show the part of
2189 * an entry where the cursor is, for example. The area returned is relative
2190 * to the object @p obj.
2191 * If the @p obj doesn't have the proper on_focus_region_hook set, this
2192 * function will return the full size of the object.
2194 * @param obj The widget object
2195 * @param x Where to store the x coordinate of the area
2196 * @param y Where to store the y coordinate of the area
2197 * @param w Where to store the width of the area
2198 * @param h Where to store the height of the area
2203 elm_widget_focus_region_get(const Evas_Object *obj,
2213 sd = evas_object_smart_data_get(obj);
2214 if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2216 evas_object_geometry_get(obj, NULL, NULL, w, h);
2221 sd->on_focus_region_func(obj, x, y, w, h);
2225 elm_widget_scroll_hold_push(Evas_Object *obj)
2229 if (sd->scroll_hold == 1)
2230 evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2231 if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2232 // FIXME: on delete/reparent hold pop
2236 elm_widget_scroll_hold_pop(Evas_Object *obj)
2240 if (!sd->scroll_hold)
2241 evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2242 if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2243 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2247 elm_widget_scroll_hold_get(const Evas_Object *obj)
2250 return sd->scroll_hold;
2254 elm_widget_scroll_freeze_push(Evas_Object *obj)
2257 sd->scroll_freeze++;
2258 if (sd->scroll_freeze == 1)
2259 evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2260 if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2261 // FIXME: on delete/reparent freeze pop
2265 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2268 sd->scroll_freeze--;
2269 if (!sd->scroll_freeze)
2270 evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2271 if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2272 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2276 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2279 return sd->scroll_freeze;
2283 elm_widget_scale_set(Evas_Object *obj,
2287 if (scale <= 0.0) scale = 0.0;
2288 if (sd->scale != scale)
2291 elm_widget_theme(obj);
2296 elm_widget_scale_get(const Evas_Object *obj)
2298 API_ENTRY return 1.0;
2299 // FIXME: save walking up the tree by storing/caching parent scale
2300 if (sd->scale == 0.0)
2303 return elm_widget_scale_get(sd->parent_obj);
2311 elm_widget_theme_set(Evas_Object *obj,
2315 if (sd->theme != th)
2317 if (sd->theme) elm_theme_free(sd->theme);
2320 elm_widget_theme(obj);
2325 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2329 if (!sd->text_set_func)
2332 sd->text_set_func(obj, part, label);
2336 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2338 API_ENTRY return NULL;
2340 if (!sd->text_get_func)
2343 return sd->text_get_func(obj, part);
2347 elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2351 Elm_Translate_String_Data *ts = NULL;
2354 str = eina_stringshare_add(part);
2355 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2362 eina_stringshare_del(str);
2365 ts = malloc(sizeof(Elm_Translate_String_Data));
2369 ts->domain = eina_stringshare_add(domain);
2370 ts->string = eina_stringshare_add(label);
2371 sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2377 eina_stringshare_replace(&ts->domain, domain);
2378 eina_stringshare_replace(&ts->string, label);
2382 sd->translate_strings = eina_list_remove_list(
2383 sd->translate_strings, l);
2384 eina_stringshare_del(ts->id);
2385 eina_stringshare_del(ts->domain);
2386 eina_stringshare_del(ts->string);
2389 eina_stringshare_del(str);
2393 if (label && label[0])
2394 label = dgettext(domain, label);
2396 elm_widget_text_part_set(obj, part, label);
2400 elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2402 const char *str, *ret = NULL;
2404 Elm_Translate_String_Data *ts;
2405 API_ENTRY return NULL;
2407 str = eina_stringshare_add(part);
2408 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2414 eina_stringshare_del(str);
2419 elm_widget_translate(Evas_Object *obj)
2424 Elm_Translate_String_Data *ts;
2428 EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2429 if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2430 if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2431 if (sd->translate_func) sd->translate_func(obj);
2434 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2436 const char *s = dgettext(ts->domain, ts->string);
2437 elm_widget_text_part_set(obj, ts->id, s);
2443 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2447 if (!sd->content_set_func) return;
2448 sd->content_set_func(obj, part, content);
2452 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2454 API_ENTRY return NULL;
2456 if (!sd->content_get_func) return NULL;
2457 return sd->content_get_func(obj, part);
2461 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2463 API_ENTRY return NULL;
2465 if (!sd->content_unset_func) return NULL;
2466 return sd->content_unset_func(obj, part);
2470 elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2473 if (sd->access_info) eina_stringshare_del(sd->access_info);
2474 if (!txt) sd->access_info = NULL;
2475 else sd->access_info = eina_stringshare_add(txt);
2479 elm_widget_access_info_get(const Evas_Object *obj)
2481 API_ENTRY return NULL;
2482 return sd->access_info;
2486 elm_widget_theme_get(const Evas_Object *obj)
2488 API_ENTRY return NULL;
2492 return elm_widget_theme_get(sd->parent_obj);
2500 elm_widget_style_set(Evas_Object *obj,
2503 API_ENTRY return EINA_FALSE;
2505 if (eina_stringshare_replace(&sd->style, style))
2506 return elm_widget_theme(obj);
2512 elm_widget_style_get(const Evas_Object *obj)
2514 API_ENTRY return NULL;
2515 if (sd->style) return sd->style;
2520 elm_widget_type_set(Evas_Object *obj,
2524 eina_stringshare_replace(&sd->type, type);
2528 elm_widget_type_get(const Evas_Object *obj)
2530 API_ENTRY return NULL;
2531 if (sd->type) return sd->type;
2536 elm_widget_tooltip_add(Evas_Object *obj,
2540 sd->tooltips = eina_list_append(sd->tooltips, tt);
2544 elm_widget_tooltip_del(Evas_Object *obj,
2548 sd->tooltips = eina_list_remove(sd->tooltips, tt);
2552 elm_widget_cursor_add(Evas_Object *obj,
2556 sd->cursors = eina_list_append(sd->cursors, cur);
2560 elm_widget_cursor_del(Evas_Object *obj,
2564 sd->cursors = eina_list_remove(sd->cursors, cur);
2568 elm_widget_drag_lock_x_set(Evas_Object *obj,
2572 if (sd->drag_x_locked == lock) return;
2573 sd->drag_x_locked = lock;
2574 if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2575 else _propagate_x_drag_lock(obj, -1);
2579 elm_widget_drag_lock_y_set(Evas_Object *obj,
2583 if (sd->drag_y_locked == lock) return;
2584 sd->drag_y_locked = lock;
2585 if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2586 else _propagate_y_drag_lock(obj, -1);
2590 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2592 API_ENTRY return EINA_FALSE;
2593 return sd->drag_x_locked;
2597 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2599 API_ENTRY return EINA_FALSE;
2600 return sd->drag_y_locked;
2604 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2607 return sd->child_drag_x_locked;
2611 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2614 return sd->child_drag_y_locked;
2618 elm_widget_theme_object_set(Evas_Object *obj,
2621 const char *welement,
2624 API_ENTRY return EINA_FALSE;
2625 return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2629 elm_widget_is_check(const Evas_Object *obj)
2631 static int abort_on_warn = -1;
2632 if (elm_widget_is(obj))
2635 ERR("Passing Object: %p.", obj);
2636 if (abort_on_warn == -1)
2638 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2639 else abort_on_warn = 0;
2641 if (abort_on_warn == 1) abort();
2646 elm_widget_type_check(const Evas_Object *obj,
2650 const char *provided, *expected = "(unknown)";
2651 static int abort_on_warn = -1;
2652 provided = elm_widget_type_get(obj);
2653 if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2654 if (type) expected = type;
2655 if ((!provided) || (!provided[0]))
2657 provided = evas_object_type_get(obj);
2658 if ((!provided) || (!provided[0]))
2659 provided = "(unknown)";
2661 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2662 if (abort_on_warn == -1)
2664 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2665 else abort_on_warn = 0;
2667 if (abort_on_warn == 1) abort();
2671 static Evas_Object *
2672 _widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2677 INTERNAL_ENTRY NULL;
2679 if (!_elm_widget_is(obj)) return NULL;
2682 s = evas_object_name_get(sd->resize_obj);
2683 if ((s) && (!strcmp(s, name))) return sd->resize_obj;
2684 if ((recurse != 0) &&
2685 ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
2688 EINA_LIST_FOREACH(sd->subobjs, l, child)
2690 s = evas_object_name_get(child);
2691 if ((s) && (!strcmp(s, name))) return child;
2692 if ((recurse != 0) &&
2693 ((child = _widget_name_find(child, name, recurse - 1))))
2698 s = evas_object_name_get(sd->hover_obj);
2699 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
2700 if ((recurse != 0) &&
2701 ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
2708 elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2710 API_ENTRY return NULL;
2711 if (!name) return NULL;
2712 return _widget_name_find(obj, name, recurse);
2718 * Split string in words
2720 * @param str Source string
2721 * @return List of const words
2723 * @see elm_widget_stringlist_free()
2727 elm_widget_stringlist_get(const char *str)
2729 Eina_List *list = NULL;
2731 if (!str) return NULL;
2732 for (b = s = str; 1; s++)
2734 if ((*s == ' ') || (!*s))
2736 char *t = malloc(s - b + 1);
2739 strncpy(t, b, s - b);
2741 list = eina_list_append(list, eina_stringshare_add(t));
2752 elm_widget_stringlist_free(Eina_List *list)
2755 EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2759 elm_widget_focus_hide_handle(Evas_Object *obj)
2761 if (!_elm_widget_is(obj))
2763 _if_focused_revert(obj, EINA_TRUE);
2767 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2769 Evas_Object *o = obj;
2772 if (_elm_widget_is(o)) break;
2773 o = evas_object_smart_parent_get(o);
2777 if (!_is_focusable(o)) return;
2778 elm_widget_focus_steal(o);
2782 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2786 //FIXME: Need to check whether the object is unfocusable or not.
2788 if (!elm_widget_parent_get(obj))
2789 elm_widget_focused_object_clear(obj);
2791 _if_focused_revert(obj, EINA_TRUE);
2795 elm_widget_focus_disabled_handle(Evas_Object *obj)
2799 elm_widget_focus_tree_unfocusable_handle(obj);
2803 elm_widget_focus_order_get(const Evas_Object *obj)
2806 return sd->focus_order;
2812 * Allocate a new Elm_Widget_Item-derived structure.
2814 * The goal of this structure is to provide common ground for actions
2815 * that a widget item have, such as the owner widget, callback to
2816 * notify deletion, data pointer and maybe more.
2818 * @param widget the owner widget that holds this item, must be an elm_widget!
2819 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2820 * be used to allocate memory.
2822 * @return allocated memory that is already zeroed out, or NULL on errors.
2824 * @see elm_widget_item_new() convenience macro.
2825 * @see elm_widget_item_del() to release memory.
2828 EAPI Elm_Widget_Item *
2829 _elm_widget_item_new(Evas_Object *widget,
2832 if (!_elm_widget_is(widget))
2835 Elm_Widget_Item *item;
2837 EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2838 EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2840 item = calloc(1, alloc_size);
2841 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2843 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2844 item->widget = widget;
2849 _elm_widget_item_free(Elm_Widget_Item *item)
2851 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2853 _elm_access_item_unregister(item);
2856 item->del_func((void *)item->data, item->widget, item);
2859 evas_object_del(item->view);
2863 _elm_access_clear(item->access);
2867 if (item->access_info)
2868 eina_stringshare_del(item->access_info);
2870 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2877 * Releases widget item memory, calling back del_cb() if it exists.
2879 * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2880 * to memory release. Note that elm_widget_item_pre_notify_del() calls
2881 * this function and then unset it, thus being useful for 2 step
2882 * cleanup whenever the del_cb may use any of the data that must be
2883 * deleted from item.
2885 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2888 * @param item a valid #Elm_Widget_Item to be deleted.
2889 * @see elm_widget_item_del() convenience macro.
2893 _elm_widget_item_del(Elm_Widget_Item *item)
2895 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2897 //Widget item delete callback
2898 if (item->del_pre_func)
2900 if (item->del_pre_func((Elm_Object_Item *)item))
2901 _elm_widget_item_free(item);
2904 _elm_widget_item_free(item);
2910 * Set the function to notify to widgets when item is being deleted by user.
2912 * @param item a valid #Elm_Widget_Item to be notified
2913 * @see elm_widget_item_del_pre_hook_set() convenience macro.
2917 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func)
2919 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2920 item->del_pre_func = func;
2926 * Notify object will be deleted without actually deleting it.
2928 * This function will callback Elm_Widget_Item::del_cb if it is set
2929 * and then unset it so it is not called twice (ie: from
2930 * elm_widget_item_del()).
2932 * @param item a valid #Elm_Widget_Item to be notified
2933 * @see elm_widget_item_pre_notify_del() convenience macro.
2937 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2939 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2940 if (!item->del_func) return;
2941 item->del_func((void *)item->data, item->widget, item);
2942 item->del_func = NULL;
2948 * Set the function to notify when item is being deleted.
2950 * This function will complain if there was a callback set already,
2951 * however it will set the new one.
2953 * The callback will be called from elm_widget_item_pre_notify_del()
2954 * or elm_widget_item_del() will be called with:
2955 * - data: the Elm_Widget_Item::data value.
2956 * - obj: the Elm_Widget_Item::widget evas object.
2957 * - event_info: the item being deleted.
2959 * @param item a valid #Elm_Widget_Item to be notified
2960 * @see elm_widget_item_del_cb_set() convenience macro.
2964 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2967 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2969 if ((item->del_func) && (item->del_func != func))
2970 WRN("You're replacing a previously set del_cb %p of item %p with %p",
2971 item->del_func, item, func);
2973 item->del_func = func;
2979 * Set user-data in this item.
2981 * User data may be used to identify this item or just store any
2982 * application data. It is automatically given as the first parameter
2983 * of the deletion notify callback.
2985 * @param item a valid #Elm_Widget_Item to store data in.
2986 * @param data user data to store.
2987 * @see elm_widget_item_del_cb_set() convenience macro.
2991 _elm_widget_item_data_set(Elm_Widget_Item *item,
2994 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2995 if ((item->data) && (item->data != data))
2996 DBG("Replacing item %p data %p with %p", item, item->data, data);
3003 * Retrieves user-data of this item.
3005 * @param item a valid #Elm_Widget_Item to get data from.
3006 * @see elm_widget_item_data_set()
3010 _elm_widget_item_data_get(const Elm_Widget_Item *item)
3012 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3013 return (void *)item->data;
3017 _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
3019 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3021 if (item->disabled == disabled) return;
3022 item->disabled = !!disabled;
3023 if (item->disable_func) item->disable_func(item);
3027 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
3029 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3030 return item->disabled;
3034 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
3035 Elm_Widget_Disable_Cb func)
3037 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3038 item->disable_func = func;
3041 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
3043 struct _Elm_Widget_Item_Tooltip
3045 Elm_Widget_Item *item;
3046 Elm_Tooltip_Item_Content_Cb func;
3047 Evas_Smart_Cb del_cb;
3051 static Evas_Object *
3052 _elm_widget_item_tooltip_label_create(void *data,
3053 Evas_Object *obj __UNUSED__,
3054 Evas_Object *tooltip,
3055 void *item __UNUSED__)
3057 Evas_Object *label = elm_label_add(tooltip);
3060 elm_object_style_set(label, "tooltip");
3061 elm_object_text_set(label, data);
3065 static Evas_Object *
3066 _elm_widget_item_tooltip_trans_label_create(void *data,
3067 Evas_Object *obj __UNUSED__,
3068 Evas_Object *tooltip,
3069 void *item __UNUSED__)
3071 Evas_Object *label = elm_label_add(tooltip);
3074 elm_object_style_set(label, "tooltip");
3075 elm_object_translatable_text_set(label, data);
3080 _elm_widget_item_tooltip_label_del_cb(void *data,
3081 Evas_Object *obj __UNUSED__,
3082 void *event_info __UNUSED__)
3084 eina_stringshare_del(data);
3090 * Set the text to be shown in the widget item.
3092 * @param item Target item
3093 * @param text The text to set in the content
3095 * Setup the text as tooltip to object. The item can have only one tooltip,
3096 * so any previous tooltip data is removed.
3101 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
3104 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3105 EINA_SAFETY_ON_NULL_RETURN(text);
3107 text = eina_stringshare_add(text);
3108 _elm_widget_item_tooltip_content_cb_set
3109 (item, _elm_widget_item_tooltip_label_create, text,
3110 _elm_widget_item_tooltip_label_del_cb);
3114 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
3117 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3118 EINA_SAFETY_ON_NULL_RETURN(text);
3120 text = eina_stringshare_add(text);
3121 _elm_widget_item_tooltip_content_cb_set
3122 (item, _elm_widget_item_tooltip_trans_label_create, text,
3123 _elm_widget_item_tooltip_label_del_cb);
3126 static Evas_Object *
3127 _elm_widget_item_tooltip_create(void *data,
3129 Evas_Object *tooltip)
3131 Elm_Widget_Item_Tooltip *wit = data;
3132 return wit->func((void *)wit->data, obj, tooltip, wit->item);
3136 _elm_widget_item_tooltip_del_cb(void *data,
3138 void *event_info __UNUSED__)
3140 Elm_Widget_Item_Tooltip *wit = data;
3141 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3148 * Set the content to be shown in the tooltip item
3150 * Setup the tooltip to item. The item can have only one tooltip,
3151 * so any previous tooltip data is removed. @p func(with @p data) will
3152 * be called every time that need show the tooltip and it should
3153 * return a valid Evas_Object. This object is then managed fully by
3154 * tooltip system and is deleted when the tooltip is gone.
3156 * @param item the widget item being attached a tooltip.
3157 * @param func the function used to create the tooltip contents.
3158 * @param data what to provide to @a func as callback data/context.
3159 * @param del_cb called when data is not needed anymore, either when
3160 * another callback replaces @func, the tooltip is unset with
3161 * elm_widget_item_tooltip_unset() or the owner @a item
3162 * dies. This callback receives as the first parameter the
3163 * given @a data, and @c event_info is the item.
3168 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
3169 Elm_Tooltip_Item_Content_Cb func,
3171 Evas_Smart_Cb del_cb)
3173 Elm_Widget_Item_Tooltip *wit;
3175 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3179 _elm_widget_item_tooltip_unset(item);
3183 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3184 if (!wit) goto error;
3188 wit->del_cb = del_cb;
3190 elm_object_sub_tooltip_content_cb_set
3191 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3192 _elm_widget_item_tooltip_del_cb);
3197 if (del_cb) del_cb((void *)data, NULL, item);
3200 if (del_cb) del_cb((void *)data, item->widget, item);
3206 * Unset tooltip from item
3208 * @param item widget item to remove previously set tooltip.
3210 * Remove tooltip from item. The callback provided as del_cb to
3211 * elm_widget_item_tooltip_content_cb_set() will be called to notify
3212 * it is not used anymore.
3214 * @see elm_widget_item_tooltip_content_cb_set()
3219 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3221 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3222 elm_object_tooltip_unset(item->view);
3228 * Sets a different style for this item tooltip.
3230 * @note before you set a style you should define a tooltip with
3231 * elm_widget_item_tooltip_content_cb_set() or
3232 * elm_widget_item_tooltip_text_set()
3234 * @param item widget item with tooltip already set.
3235 * @param style the theme style to use (default, transparent, ...)
3240 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3243 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3244 elm_object_tooltip_style_set(item->view, style);
3248 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item, Eina_Bool disable)
3250 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3251 return elm_object_tooltip_window_mode_set(item->view, disable);
3255 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
3257 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3258 return elm_object_tooltip_window_mode_get(item->view);
3264 * Get the style for this item tooltip.
3266 * @param item widget item with tooltip already set.
3267 * @return style the theme style in use, defaults to "default". If the
3268 * object does not have a tooltip set, then NULL is returned.
3273 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3275 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3276 return elm_object_tooltip_style_get(item->view);
3280 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
3283 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3284 elm_object_sub_cursor_set(item->view, item->widget, cursor);
3288 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3290 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3291 return elm_object_cursor_get(item->view);
3295 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3297 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3298 elm_object_cursor_unset(item->view);
3304 * Sets a different style for this item cursor.
3306 * @note before you set a style you should define a cursor with
3307 * elm_widget_item_cursor_set()
3309 * @param item widget item with cursor already set.
3310 * @param style the theme style to use (default, transparent, ...)
3315 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3318 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3319 elm_object_cursor_style_set(item->view, style);
3325 * Get the style for this item cursor.
3327 * @param item widget item with cursor already set.
3328 * @return style the theme style in use, defaults to "default". If the
3329 * object does not have a cursor set, then NULL is returned.
3334 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3336 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3337 return elm_object_cursor_style_get(item->view);
3343 * Set if the cursor set should be searched on the theme or should use
3344 * the provided by the engine, only.
3346 * @note before you set if should look on theme you should define a cursor
3347 * with elm_object_cursor_set(). By default it will only look for cursors
3348 * provided by the engine.
3350 * @param item widget item with cursor already set.
3351 * @param engine_only boolean to define it cursors should be looked only
3352 * between the provided by the engine or searched on widget's theme as well.
3357 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3358 Eina_Bool engine_only)
3360 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3361 elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
3367 * Get the cursor engine only usage for this item cursor.
3369 * @param item widget item with cursor already set.
3370 * @return engine_only boolean to define it cursors should be looked only
3371 * between the provided by the engine or searched on widget's theme as well. If
3372 * the object does not have a cursor set, then EINA_FALSE is returned.
3377 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3379 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3380 return elm_object_cursor_theme_search_enabled_get(item->view);
3383 // smart object funcs
3385 _smart_reconfigure(Smart_Data *sd)
3389 evas_object_move(sd->resize_obj, sd->x, sd->y);
3390 evas_object_resize(sd->resize_obj, sd->w, sd->h);
3394 evas_object_move(sd->hover_obj, sd->x, sd->y);
3395 evas_object_resize(sd->hover_obj, sd->w, sd->h);
3400 _elm_widget_item_part_content_set(Elm_Widget_Item *item,
3402 Evas_Object *content)
3404 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3405 if (!item->content_set_func)
3407 ERR("%s does not support elm_object_item_part_content_set() API.",
3408 elm_widget_type_get(item->widget));
3411 item->content_set_func((Elm_Object_Item *)item, part, content);
3415 _elm_widget_item_part_content_get(const Elm_Widget_Item *item,
3418 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3419 if (!item->content_get_func)
3421 ERR("%s does not support elm_object_item_part_content_get() API.",
3422 elm_widget_type_get(item->widget));
3425 return item->content_get_func((Elm_Object_Item *)item, part);
3429 _elm_widget_item_part_content_unset(Elm_Widget_Item *item,
3432 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3433 if (!item->content_unset_func)
3435 ERR("%s does not support elm_object_item_part_content_unset() API.",
3436 elm_widget_type_get(item->widget));
3439 return item->content_unset_func((Elm_Object_Item *)item, part);
3443 _elm_widget_item_part_text_set(Elm_Widget_Item *item,
3447 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3448 if (!item->text_set_func)
3450 ERR("%s does not support elm_object_item_part_text_set() API.",
3451 elm_widget_type_get(item->widget));
3454 item->text_set_func((Elm_Object_Item *)item, part, label);
3458 _elm_widget_item_part_text_get(const Elm_Widget_Item *item,
3461 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3462 if (!item->text_get_func)
3464 ERR("%s does not support elm_object_item_part_text_get() API.",
3465 elm_widget_type_get(item->widget));
3468 return item->text_get_func((Elm_Object_Item *)item, part);
3472 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3473 Elm_Widget_Content_Set_Cb func)
3475 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3476 item->content_set_func = func;
3480 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3481 Elm_Widget_Content_Get_Cb func)
3483 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3484 item->content_get_func = func;
3488 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3489 Elm_Widget_Content_Unset_Cb func)
3491 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3492 item->content_unset_func = func;
3496 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3497 Elm_Widget_Text_Set_Cb func)
3499 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3500 item->text_set_func = func;
3504 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3505 Elm_Widget_Text_Get_Cb func)
3507 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3508 item->text_get_func = func;
3512 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3513 const char *emission,
3516 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3517 if (item->signal_emit_func)
3518 item->signal_emit_func((Elm_Object_Item *)item, emission, source);
3522 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3523 Elm_Widget_Signal_Emit_Cb func)
3525 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3526 item->signal_emit_func = func;
3530 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3532 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3533 if (item->access_info) eina_stringshare_del(item->access_info);
3534 if (!txt) item->access_info = NULL;
3535 else item->access_info = eina_stringshare_add(txt);
3539 _smart_add(Evas_Object *obj)
3543 sd = calloc(1, sizeof(Smart_Data));
3546 sd->x = sd->y = sd->w = sd->h = 0;
3547 sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3548 evas_object_smart_data_set(obj, sd);
3549 elm_widget_can_focus_set(obj, EINA_TRUE);
3552 static Evas_Object *
3553 _newest_focus_order_get(Evas_Object *obj,
3554 unsigned int *newest_focus_order,
3555 Eina_Bool can_focus_only)
3558 Evas_Object *child, *ret, *best;
3560 API_ENTRY return NULL;
3562 if (!evas_object_visible_get(obj)
3563 || (elm_widget_disabled_get(obj))
3564 || (elm_widget_tree_unfocusable_get(obj)))
3568 if (*newest_focus_order < sd->focus_order)
3570 *newest_focus_order = sd->focus_order;
3573 EINA_LIST_FOREACH(sd->subobjs, l, child)
3575 ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3581 if ((!best) || (!elm_widget_can_focus_get(best)))
3588 _if_focused_revert(Evas_Object *obj,
3589 Eina_Bool can_focus_only)
3592 Evas_Object *newest = NULL;
3593 unsigned int newest_focus_order = 0;
3597 if (!sd->focused) return;
3598 if (!sd->parent_obj) return;
3600 top = elm_widget_top_get(sd->parent_obj);
3603 newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3606 elm_object_focus_set(newest, EINA_FALSE);
3607 elm_object_focus_set(newest, EINA_TRUE);
3613 _smart_del(Evas_Object *obj)
3616 Edje_Signal_Data *esd;
3617 Elm_Translate_String_Data *ts;
3621 if (sd->del_pre_func) sd->del_pre_func(obj);
3624 sobj = sd->resize_obj;
3625 sd->resize_obj = NULL;
3626 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3627 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3628 evas_object_del(sobj);
3629 sd->resize_obj = NULL;
3633 sobj = sd->hover_obj;
3634 sd->hover_obj = NULL;
3635 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3636 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3637 evas_object_del(sobj);
3638 sd->hover_obj = NULL;
3640 EINA_LIST_FREE(sd->subobjs, sobj)
3642 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3643 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3644 evas_object_del(sobj);
3646 sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
3647 sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
3648 EINA_LIST_FREE(sd->edje_signals, esd)
3650 eina_stringshare_del(esd->emission);
3651 eina_stringshare_del(esd->source);
3654 EINA_LIST_FREE(sd->translate_strings, ts)
3656 eina_stringshare_del(ts->id);
3657 eina_stringshare_del(ts->domain);
3658 eina_stringshare_del(ts->string);
3661 sd->event_cb = eina_list_free(sd->event_cb); /* should be empty anyway */
3662 if (sd->del_func) sd->del_func(obj);
3663 if (sd->style) eina_stringshare_del(sd->style);
3664 if (sd->type) eina_stringshare_del(sd->type);
3665 if (sd->theme) elm_theme_free(sd->theme);
3667 _if_focused_revert(obj, EINA_TRUE);
3668 if (sd->access_info) eina_stringshare_del(sd->access_info);
3670 evas_object_smart_data_set(obj, NULL);
3674 _smart_move(Evas_Object *obj,
3681 _smart_reconfigure(sd);
3685 _smart_resize(Evas_Object *obj,
3692 _smart_reconfigure(sd);
3696 _smart_show(Evas_Object *obj)
3701 if ((list = evas_object_smart_members_get(obj)))
3703 EINA_LIST_FREE(list, o)
3705 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3706 evas_object_show(o);
3712 _smart_hide(Evas_Object *obj)
3718 list = evas_object_smart_members_get(obj);
3719 EINA_LIST_FREE(list, o)
3721 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3722 evas_object_hide(o);
3727 _smart_color_set(Evas_Object *obj,
3736 if ((list = evas_object_smart_members_get(obj)))
3738 EINA_LIST_FREE(list, o)
3740 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3741 evas_object_color_set(o, r, g, b, a);
3747 _smart_clip_set(Evas_Object *obj,
3753 if ((list = evas_object_smart_members_get(obj)))
3755 EINA_LIST_FREE(list, o)
3757 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3758 evas_object_clip_set(o, clip);
3764 _smart_clip_unset(Evas_Object *obj)
3769 if ((list = evas_object_smart_members_get(obj)))
3771 EINA_LIST_FREE(list, o)
3773 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3774 evas_object_clip_unset(o);
3780 _smart_calculate(Evas_Object *obj)
3783 if (sd->changed_func) sd->changed_func(obj);
3787 _smart_member_add(Evas_Object *obj, Evas_Object *child)
3791 if (evas_object_data_get(child, "_elm_leaveme")) return;
3793 evas_object_color_get(obj, &r, &g, &b, &a);
3794 evas_object_color_set(child, r, g, b, a);
3796 evas_object_clip_set(child, evas_object_clip_get(obj));
3798 if (evas_object_visible_get(obj))
3799 evas_object_show(child);
3801 evas_object_hide(child);
3805 _smart_member_del(Evas_Object *obj __UNUSED__, Evas_Object *child)
3807 if (evas_object_data_get(child, "_elm_leaveme")) return;
3808 evas_object_clip_unset(child);
3811 /* never need to touch this */
3815 if (_e_smart) return;
3817 static const Evas_Smart_Class sc =
3820 EVAS_SMART_CLASS_VERSION,
3838 _e_smart = evas_smart_class_new(&sc);
3842 /* happy debug functions */
3845 _sub_obj_tree_dump(const Evas_Object *obj,
3850 for (i = 0; i < lvl * 3; i++)
3853 if (_elm_widget_is(obj))
3857 printf("+ %s(%p)\n",
3861 _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3862 EINA_LIST_FOREACH(sd->subobjs, l, obj)
3864 if (obj != sd->resize_obj)
3865 _sub_obj_tree_dump(obj, lvl + 1);
3869 printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3873 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3876 if (!_elm_widget_is(obj))
3880 Eina_Bool visible = evas_object_visible_get(obj);
3881 Eina_Bool disabled = elm_widget_disabled_get(obj);
3882 Eina_Bool focused = elm_widget_focus_get(obj);
3883 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3887 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3890 fprintf(output, ", style=bold");
3893 fprintf(output, ", color=gray28");
3895 fprintf(output, " ];\n");
3898 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3899 "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3900 evas_object_name_get(obj), visible, disabled, focused, can_focus,
3904 fprintf(output, ", style=bold");
3907 fprintf(output, ", fontcolor=gray28");
3909 if ((disabled) || (!visible))
3910 fprintf(output, ", color=gray");
3912 fprintf(output, " ];\n");
3916 EINA_LIST_FOREACH(sd->subobjs, l, o)
3917 _sub_obj_tree_dot_dump(o, output);
3922 elm_widget_tree_dump(const Evas_Object *top)
3925 if (!_elm_widget_is(top))
3927 _sub_obj_tree_dump(top, 0);
3935 elm_widget_tree_dot_dump(const Evas_Object *top,
3939 if (!_elm_widget_is(top))
3941 fprintf(output, "graph " " { node [shape=record];\n");
3942 _sub_obj_tree_dot_dump(top, output);
3943 fprintf(output, "}\n");