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;
23 typedef struct _Elm_Widget_Item_Callback Elm_Widget_Item_Callback;
29 Evas_Object *parent_obj;
31 Evas_Coord x, y, w, h;
33 Evas_Object *resize_obj;
34 Evas_Object *hover_obj;
35 Eina_List *tooltips, *cursors;
36 void (*del_func)(Evas_Object *obj);
37 void (*del_pre_func)(Evas_Object *obj);
38 void (*focus_func)(Evas_Object *obj);
39 void (*activate_func)(Evas_Object *obj);
40 void (*disable_func)(Evas_Object *obj);
41 void (*theme_func)(Evas_Object *obj);
42 void (*translate_func)(Evas_Object *obj);
43 Eina_Bool (*event_func)(Evas_Object *obj,
45 Evas_Callback_Type type,
47 void (*signal_func)(Evas_Object *obj,
50 void (*callback_add_func)(Evas_Object *obj,
55 void (*callback_del_func)(Evas_Object *obj,
60 void (*changed_func)(Evas_Object *obj);
61 Eina_Bool (*focus_next_func)(const Evas_Object *obj,
62 Elm_Focus_Direction dir,
64 void (*on_focus_func)(void *data,
67 void (*on_change_func)(void *data,
70 void (*on_show_region_func)(void *data,
72 void *on_show_region_data;
73 void (*focus_region_func)(Evas_Object *obj,
78 void (*on_focus_region_func)(const Evas_Object *obj,
83 Elm_Widget_Text_Set_Cb text_set_func;
84 Elm_Widget_Text_Get_Cb text_get_func;
85 Elm_Widget_Content_Set_Cb content_set_func;
86 Elm_Widget_Content_Get_Cb content_get_func;
87 Elm_Widget_Content_Unset_Cb content_unset_func;
89 Evas_Coord rx, ry, rw, rh;
95 const char *access_info;
96 unsigned int focus_order;
97 Eina_Bool focus_order_on_calc;
99 int child_drag_x_locked;
100 int child_drag_y_locked;
102 Eina_List *edje_signals;
103 Eina_List *translate_strings;
105 Eina_Bool drag_x_locked : 1;
106 Eina_Bool drag_y_locked : 1;
108 Eina_Bool can_focus : 1;
109 Eina_Bool child_can_focus : 1;
110 Eina_Bool focused : 1;
111 Eina_Bool top_win_focused : 1;
112 Eina_Bool tree_unfocusable : 1;
113 Eina_Bool highlight_ignore : 1;
114 Eina_Bool highlight_in_theme : 1;
115 Eina_Bool disabled : 1;
116 Eina_Bool is_mirrored : 1;
117 Eina_Bool mirrored_auto_mode : 1; /* This is TRUE by default */
118 Eina_Bool still_in : 1;
120 Eina_List *focus_chain;
124 struct _Edje_Signal_Data
128 const char *emission;
133 struct _Elm_Event_Cb_Data
139 struct _Elm_Translate_String_Data
146 struct _Elm_Widget_Item_Callback
149 Elm_Object_Item_Smart_Cb func;
152 Eina_Bool delete_me : 1;
156 /* local subsystem functions */
157 static void _smart_reconfigure(Smart_Data *sd);
158 static void _smart_add(Evas_Object *obj);
159 static void _smart_del(Evas_Object *obj);
160 static void _smart_move(Evas_Object *obj,
163 static void _smart_resize(Evas_Object *obj,
166 static void _smart_show(Evas_Object *obj);
167 static void _smart_hide(Evas_Object *obj);
168 static void _smart_color_set(Evas_Object *obj,
173 static void _smart_clip_set(Evas_Object *obj,
175 static void _smart_clip_unset(Evas_Object *obj);
176 static void _smart_calculate(Evas_Object *obj);
177 static void _smart_member_add(Evas_Object *obj, Evas_Object *child);
178 static void _smart_init(void);
180 static void _if_focused_revert(Evas_Object *obj,
181 Eina_Bool can_focus_only);
182 static Evas_Object *_newest_focus_order_get(Evas_Object *obj,
183 unsigned int *newest_focus_order,
184 Eina_Bool can_focus_only);
186 /* local subsystem globals */
187 static Evas_Smart *_e_smart = NULL;
188 static Eina_List *widtypes = NULL;
190 static unsigned int focus_order = 0;
193 static inline Eina_Bool
194 _elm_widget_is(const Evas_Object *obj)
196 const char *type = evas_object_type_get(obj);
197 return type == SMART_NAME;
200 static inline Eina_Bool
201 _is_focusable(Evas_Object *obj)
203 API_ENTRY return EINA_FALSE;
204 return sd->can_focus || (sd->child_can_focus);
208 _unfocus_parents(Evas_Object *obj)
210 for (; obj; obj = elm_widget_parent_get(obj))
213 if (!sd->focused) return;
219 _focus_parents(Evas_Object *obj)
221 for (; obj; obj = elm_widget_parent_get(obj))
224 if (sd->focused) return;
230 _sub_obj_del(void *data,
233 void *event_info __UNUSED__)
235 Smart_Data *sd = data;
237 if (_elm_widget_is(obj))
239 if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
241 if (obj == sd->resize_obj)
242 sd->resize_obj = NULL;
243 else if (obj == sd->hover_obj)
244 sd->hover_obj = NULL;
246 sd->subobjs = eina_list_remove(sd->subobjs, obj);
247 evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
251 _sub_obj_hide(void *data __UNUSED__,
254 void *event_info __UNUSED__)
256 elm_widget_focus_hide_handle(obj);
260 _sub_obj_mouse_down(void *data,
262 Evas_Object *obj __UNUSED__,
265 Smart_Data *sd = data;
266 Evas_Event_Mouse_Down *ev = event_info;
267 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
268 sd->still_in = EINA_TRUE;
272 _sub_obj_mouse_move(void *data,
277 Smart_Data *sd = data;
278 Evas_Event_Mouse_Move *ev = event_info;
281 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
282 sd->still_in = EINA_FALSE;
285 Evas_Coord x, y, w, h;
286 evas_object_geometry_get(obj, &x, &y, &w, &h);
287 if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
288 (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
289 sd->still_in = EINA_FALSE;
295 _sub_obj_mouse_up(void *data,
298 void *event_info __UNUSED__)
300 Smart_Data *sd = data;
302 elm_widget_focus_mouse_up_handle(obj);
303 sd->still_in = EINA_FALSE;
307 _propagate_x_drag_lock(Evas_Object *obj,
313 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
316 sd2->child_drag_x_locked += dir;
317 _propagate_x_drag_lock(sd->parent_obj, dir);
323 _propagate_y_drag_lock(Evas_Object *obj,
329 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
332 sd2->child_drag_y_locked += dir;
333 _propagate_y_drag_lock(sd->parent_obj, dir);
339 _propagate_event(void *data,
345 Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
346 Evas_Event_Flags *event_flags = NULL;
350 case EVAS_CALLBACK_KEY_DOWN:
352 Evas_Event_Key_Down *ev = event_info;
353 event_flags = &(ev->event_flags);
357 case EVAS_CALLBACK_KEY_UP:
359 Evas_Event_Key_Up *ev = event_info;
360 event_flags = &(ev->event_flags);
364 case EVAS_CALLBACK_MOUSE_WHEEL:
366 Evas_Event_Mouse_Wheel *ev = event_info;
367 event_flags = &(ev->event_flags);
375 elm_widget_event_propagate(obj, type, event_info, event_flags);
379 _parent_focus(Evas_Object *obj)
382 if (sd->focused) return;
384 Evas_Object *o = elm_widget_parent_get(obj);
385 sd->focus_order_on_calc = EINA_TRUE;
387 if (o) _parent_focus(o);
389 if (!sd->focus_order_on_calc)
390 return; /* we don't want to override it if by means of any of the
391 callbacks below one gets to calculate our order
395 sd->focus_order = focus_order;
396 if (sd->top_win_focused)
398 sd->focused = EINA_TRUE;
399 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
400 if (sd->focus_func) sd->focus_func(obj);
401 _elm_widget_focus_region_show(obj);
403 sd->focus_order_on_calc = EINA_FALSE;
407 _elm_object_focus_chain_del_cb(void *data,
410 void *event_info __UNUSED__)
412 Smart_Data *sd = data;
414 sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
417 // exposed util funcs to elm
419 _elm_widget_type_clear(void)
423 EINA_LIST_FREE(widtypes, ptr)
425 eina_stringshare_del(*ptr);
431 _elm_widget_focus_region_show(const Evas_Object *obj)
433 Evas_Coord x, y, w, h, ox, oy;
439 o = elm_widget_parent_get(obj);
442 elm_widget_focus_region_get(obj, &x, &y, &w, &h);
443 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
447 sd2 = evas_object_smart_data_get(o);
448 if (sd2->focus_region_func)
450 sd2->focus_region_func(o, x, y, w, h);
451 elm_widget_focus_region_get(o, &x, &y, &w, &h);
455 evas_object_geometry_get(o, &px, &py, NULL, NULL);
461 o = elm_widget_parent_get(o);
466 * @defgroup Widget Widget
469 * Exposed api for making widgets
472 elm_widget_type_register(const char **ptr)
474 widtypes = eina_list_append(widtypes, (void *)ptr);
478 * @defgroup Widget Widget
481 * Disposed api for making widgets
484 elm_widget_type_unregister(const char **ptr)
486 widtypes = eina_list_remove(widtypes, (void *)ptr);
490 elm_widget_api_check(int ver)
492 if (ver != ELM_INTERNAL_API_VERSION)
494 CRITICAL("Elementary widget api versions do not match");
501 elm_widget_add(Evas *evas)
505 obj = evas_object_smart_add(evas, _e_smart);
506 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
511 elm_widget_del_hook_set(Evas_Object *obj,
512 void (*func)(Evas_Object *obj))
519 elm_widget_del_pre_hook_set(Evas_Object *obj,
520 void (*func)(Evas_Object *obj))
523 sd->del_pre_func = func;
527 elm_widget_focus_hook_set(Evas_Object *obj,
528 void (*func)(Evas_Object *obj))
531 sd->focus_func = func;
535 elm_widget_activate_hook_set(Evas_Object *obj,
536 void (*func)(Evas_Object *obj))
539 sd->activate_func = func;
543 elm_widget_disable_hook_set(Evas_Object *obj,
544 void (*func)(Evas_Object *obj))
547 sd->disable_func = func;
551 elm_widget_theme_hook_set(Evas_Object *obj,
552 void (*func)(Evas_Object *obj))
555 sd->theme_func = func;
559 elm_widget_translate_hook_set(Evas_Object *obj,
560 void (*func)(Evas_Object *obj))
563 sd->translate_func = func;
567 elm_widget_event_hook_set(Evas_Object *obj,
568 Eina_Bool (*func)(Evas_Object *obj,
570 Evas_Callback_Type type,
574 sd->event_func = func;
578 elm_widget_text_set_hook_set(Evas_Object *obj,
579 Elm_Widget_Text_Set_Cb func)
582 sd->text_set_func = func;
586 elm_widget_text_get_hook_set(Evas_Object *obj,
587 Elm_Widget_Text_Get_Cb func)
590 sd->text_get_func = func;
594 elm_widget_content_set_hook_set(Evas_Object *obj,
595 Elm_Widget_Content_Set_Cb func)
598 sd->content_set_func = func;
602 elm_widget_content_get_hook_set(Evas_Object *obj,
603 Elm_Widget_Content_Get_Cb func)
606 sd->content_get_func = func;
610 elm_widget_content_unset_hook_set(Evas_Object *obj,
611 Elm_Widget_Content_Unset_Cb func)
614 sd->content_unset_func = func;
618 elm_widget_changed_hook_set(Evas_Object *obj,
619 void (*func)(Evas_Object *obj))
622 sd->changed_func = func;
626 elm_widget_signal_emit_hook_set(Evas_Object *obj,
627 void (*func)(Evas_Object *obj,
628 const char *emission,
632 sd->signal_func = func;
636 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
637 void (*func)(Evas_Object *obj,
638 const char *emission,
640 Edje_Signal_Cb func_cb,
644 sd->callback_add_func = func;
648 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
649 void (*func)(Evas_Object *obj,
650 const char *emission,
652 Edje_Signal_Cb func_cb,
656 sd->callback_del_func = func;
660 elm_widget_theme(Evas_Object *obj)
666 Eina_Bool ret = EINA_TRUE;
668 API_ENTRY return EINA_FALSE;
669 EINA_LIST_FOREACH(sd->subobjs, l, child) ret &= elm_widget_theme(child);
670 if (sd->resize_obj && _elm_widget_is(sd->resize_obj))
671 ret &= elm_widget_theme(sd->resize_obj);
672 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
673 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
674 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
675 if (sd->theme_func) sd->theme_func(obj);
681 elm_widget_theme_specific(Evas_Object *obj,
689 Elm_Theme *th2, *thdef;
692 thdef = elm_theme_default_get();
697 if (!th2) th2 = thdef;
705 if (th2 == thdef) break;
706 th2 = th2->ref_theme;
707 if (!th2) th2 = thdef;
711 EINA_LIST_FOREACH(sd->subobjs, l, child)
712 elm_widget_theme_specific(child, th, force);
713 if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
714 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
715 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
716 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
717 if (sd->theme_func) sd->theme_func(obj);
723 * Set hook to get next object in object focus chain.
725 * @param obj The widget object.
726 * @param func The hook to be used with this widget.
731 elm_widget_focus_next_hook_set(Evas_Object *obj,
732 Eina_Bool (*func)(const Evas_Object *obj,
733 Elm_Focus_Direction dir,
737 sd->focus_next_func = func;
741 * Returns the widget's mirrored mode.
743 * @param obj The widget.
744 * @return mirrored mode of the object.
748 elm_widget_mirrored_get(const Evas_Object *obj)
750 API_ENTRY return EINA_FALSE;
751 return sd->is_mirrored;
755 * Sets the widget's mirrored mode.
757 * @param obj The widget.
758 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
761 elm_widget_mirrored_set(Evas_Object *obj,
765 if (sd->is_mirrored != mirrored)
767 sd->is_mirrored = mirrored;
768 elm_widget_theme(obj);
774 * Resets the mirrored mode from the system mirror mode for widgets that are in
775 * automatic mirroring mode. This function does not call elm_widget_theme.
777 * @param obj The widget.
778 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
781 _elm_widget_mirrored_reload(Evas_Object *obj)
784 Eina_Bool mirrored = elm_config_mirrored_get();
785 if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
787 sd->is_mirrored = mirrored;
792 * Returns the widget's mirrored mode setting.
794 * @param obj The widget.
795 * @return mirrored mode setting of the object.
799 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
801 API_ENTRY return EINA_FALSE;
802 return sd->mirrored_auto_mode;
806 * Sets the widget's mirrored mode setting.
807 * When widget in automatic mode, it follows the system mirrored mode set by
808 * elm_mirrored_set().
809 * @param obj The widget.
810 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
813 elm_widget_mirrored_automatic_set(Evas_Object *obj,
817 if (sd->mirrored_auto_mode != automatic)
819 sd->mirrored_auto_mode = automatic;
823 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
829 elm_widget_on_focus_hook_set(Evas_Object *obj,
830 void (*func)(void *data,
835 sd->on_focus_func = func;
836 sd->on_focus_data = data;
840 elm_widget_on_change_hook_set(Evas_Object *obj,
841 void (*func)(void *data,
846 sd->on_change_func = func;
847 sd->on_change_data = data;
851 elm_widget_on_show_region_hook_set(Evas_Object *obj,
852 void (*func)(void *data,
857 sd->on_show_region_func = func;
858 sd->on_show_region_data = data;
864 * Set the hook to use to show the focused region.
866 * Whenever a new widget gets focused or it's needed to show the focused
867 * area of the current one, this hook will be called on objects that may
868 * want to move their children into their visible area.
869 * The area given in the hook function is relative to the @p obj widget.
871 * @param obj The widget object
872 * @param func The function to call to show the specified area.
877 elm_widget_focus_region_hook_set(Evas_Object *obj,
878 void (*func)(Evas_Object *obj,
885 sd->focus_region_func = func;
891 * Set the hook to retrieve the focused region of a widget.
893 * This hook will be called by elm_widget_focus_region_get() whenever
894 * it's needed to get the focused area of a widget. The area must be relative
895 * to the widget itself and if no hook is set, it will default to the entire
898 * @param obj The widget object
899 * @param func The function used to retrieve the focus region.
904 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
905 void (*func)(const Evas_Object *obj,
912 sd->on_focus_region_func = func;
916 elm_widget_data_set(Evas_Object *obj,
924 elm_widget_data_get(const Evas_Object *obj)
926 API_ENTRY return NULL;
931 elm_widget_sub_object_add(Evas_Object *obj,
935 double scale, pscale = elm_widget_scale_get(sobj);
936 Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
937 Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
939 if (sobj == sd->parent_obj)
941 elm_widget_sub_object_del(sobj, obj);
942 WRN("You passed a parent object of obj = %p as the sub object = %p!", obj, sobj);
945 if (_elm_widget_is(sobj))
947 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
950 if (sd2->parent_obj == obj)
953 elm_widget_sub_object_del(sd2->parent_obj, sobj);
954 sd2->parent_obj = obj;
955 _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
956 if (!sd->child_can_focus && (_is_focusable(sobj)))
957 sd->child_can_focus = EINA_TRUE;
962 void *data = evas_object_data_get(sobj, "elm-parent");
965 if (data == obj) return;
966 evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
970 sd->subobjs = eina_list_append(sd->subobjs, sobj);
971 evas_object_data_set(sobj, "elm-parent", obj);
972 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
973 if (_elm_widget_is(sobj))
974 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
975 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
976 scale = elm_widget_scale_get(sobj);
977 th = elm_widget_theme_get(sobj);
978 mirrored = elm_widget_mirrored_get(sobj);
979 if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
980 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
984 elm_widget_sub_object_del(Evas_Object *obj,
987 Evas_Object *sobj_parent;
991 sobj_parent = evas_object_data_del(sobj, "elm-parent");
992 if (sobj_parent != obj)
994 static int abort_on_warn = -1;
995 ERR("removing sub object %p (%s) from parent %p (%s), "
996 "but elm-parent is different %p (%s)!",
997 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
998 sobj_parent, elm_widget_type_get(sobj_parent));
999 if (EINA_UNLIKELY(abort_on_warn == -1))
1001 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1002 else abort_on_warn = 0;
1004 if (abort_on_warn == 1) abort();
1006 if (_elm_widget_is(sobj))
1008 if (elm_widget_focus_get(sobj))
1010 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1011 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1013 if ((sd->child_can_focus) && (_is_focusable(sobj)))
1015 Evas_Object *subobj;
1017 sd->child_can_focus = EINA_FALSE;
1018 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1020 if (_is_focusable(subobj))
1022 sd->child_can_focus = EINA_TRUE;
1027 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1030 sd2->parent_obj = NULL;
1031 if (sd2->resize_obj == sobj)
1032 sd2->resize_obj = NULL;
1034 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1037 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1040 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1041 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1043 if (_elm_widget_is(sobj))
1044 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1046 evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1050 elm_widget_resize_object_set(Evas_Object *obj,
1054 // orphan previous resize obj
1057 evas_object_clip_unset(sd->resize_obj);
1058 evas_object_data_del(sd->resize_obj, "elm-parent");
1059 if (_elm_widget_is(sd->resize_obj))
1061 Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1062 if (sd2) sd2->parent_obj = NULL;
1063 evas_object_event_callback_del_full(sd->resize_obj,
1067 evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1069 evas_object_event_callback_del_full(sd->resize_obj,
1070 EVAS_CALLBACK_MOUSE_DOWN,
1071 _sub_obj_mouse_down, sd);
1072 evas_object_event_callback_del_full(sd->resize_obj,
1073 EVAS_CALLBACK_MOUSE_MOVE,
1074 _sub_obj_mouse_move, sd);
1075 evas_object_event_callback_del_full(sd->resize_obj,
1076 EVAS_CALLBACK_MOUSE_UP,
1077 _sub_obj_mouse_up, sd);
1078 evas_object_smart_member_del(sd->resize_obj);
1080 if (_elm_widget_is(sd->resize_obj))
1082 if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1086 sd->resize_obj = sobj;
1089 // orphan new resize obj
1090 evas_object_data_del(sobj, "elm-parent");
1091 if (_elm_widget_is(sobj))
1093 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1094 if (sd2) sd2->parent_obj = NULL;
1095 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1098 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1100 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1101 _sub_obj_mouse_down, sd);
1102 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1103 _sub_obj_mouse_move, sd);
1104 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1105 _sub_obj_mouse_up, sd);
1106 evas_object_smart_member_del(sobj);
1107 if (_elm_widget_is(sobj))
1109 if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1112 // set the resize obj up
1113 if (_elm_widget_is(sobj))
1115 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1118 sd2->parent_obj = obj;
1119 sd2->top_win_focused = sd->top_win_focused;
1121 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1124 evas_object_smart_member_add(sobj, obj);
1125 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1127 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1128 _sub_obj_mouse_down, sd);
1129 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1130 _sub_obj_mouse_move, sd);
1131 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1132 _sub_obj_mouse_up, sd);
1133 _smart_reconfigure(sd);
1134 evas_object_data_set(sobj, "elm-parent", obj);
1135 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1136 if (_elm_widget_is(sobj))
1138 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1143 elm_widget_hover_object_set(Evas_Object *obj,
1149 evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1152 sd->hover_obj = sobj;
1155 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1157 _smart_reconfigure(sd);
1162 elm_widget_can_focus_set(Evas_Object *obj,
1163 Eina_Bool can_focus)
1167 can_focus = !!can_focus;
1169 if (sd->can_focus == can_focus) return;
1170 sd->can_focus = can_focus;
1173 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1175 (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1176 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1178 (void *)(long)EVAS_CALLBACK_KEY_UP);
1179 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1181 (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1185 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1187 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1189 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1195 elm_widget_can_focus_get(const Evas_Object *obj)
1197 API_ENTRY return EINA_FALSE;
1198 return sd->can_focus;
1202 elm_widget_child_can_focus_get(const Evas_Object *obj)
1204 API_ENTRY return EINA_FALSE;
1205 return sd->child_can_focus;
1211 * This API makes the widget object and its children to be unfocusable.
1213 * This API can be helpful for an object to be deleted.
1214 * When an object will be deleted soon, it and its children may not
1215 * want to get focus (by focus reverting or by other focus controls).
1216 * Then, just use this API before deleting.
1218 * @param obj The widget root of sub-tree
1219 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1224 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1225 Eina_Bool tree_unfocusable)
1229 tree_unfocusable = !!tree_unfocusable;
1230 if (sd->tree_unfocusable == tree_unfocusable) return;
1231 sd->tree_unfocusable = tree_unfocusable;
1232 elm_widget_focus_tree_unfocusable_handle(obj);
1238 * This returns true, if the object sub-tree is unfocusable.
1240 * @param obj The widget root of sub-tree
1241 * @return EINA_TRUE if the object sub-tree is unfocusable
1246 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1248 API_ENTRY return EINA_FALSE;
1249 return sd->tree_unfocusable;
1255 * Get the list of focusable child objects.
1257 * This function retruns list of child objects which can get focus.
1259 * @param obj The parent widget
1260 * @retrun list of focusable child objects.
1265 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1267 API_ENTRY return NULL;
1270 Eina_List *child_list = NULL;
1275 EINA_LIST_FOREACH(sd->subobjs, l, child)
1277 if ((elm_widget_can_focus_get(child)) &&
1278 (evas_object_visible_get(child)) &&
1279 (!elm_widget_disabled_get(child)))
1280 child_list = eina_list_append(child_list, child);
1281 else if (elm_widget_is(child))
1283 Eina_List *can_focus_list;
1284 can_focus_list = elm_widget_can_focus_child_list_get(child);
1286 child_list = eina_list_merge(child_list, can_focus_list);
1294 elm_widget_highlight_ignore_set(Evas_Object *obj,
1298 sd->highlight_ignore = !!ignore;
1302 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1304 API_ENTRY return EINA_FALSE;
1305 return sd->highlight_ignore;
1309 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1310 Eina_Bool highlight)
1313 sd->highlight_in_theme = !!highlight;
1314 /* FIXME: if focused, it should switch from one mode to the other */
1318 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1320 API_ENTRY return EINA_FALSE;
1321 return sd->highlight_in_theme;
1325 elm_widget_focus_get(const Evas_Object *obj)
1327 API_ENTRY return EINA_FALSE;
1332 elm_widget_focused_object_get(const Evas_Object *obj)
1334 const Evas_Object *subobj;
1336 API_ENTRY return NULL;
1338 if (!sd->focused) return NULL;
1339 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1341 Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1342 if (fobj) return fobj;
1344 return (Evas_Object *)obj;
1348 elm_widget_top_get(const Evas_Object *obj)
1350 API_ENTRY return NULL;
1351 if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1352 return (Evas_Object *)obj;
1356 elm_widget_is(const Evas_Object *obj)
1358 return _elm_widget_is(obj);
1362 elm_widget_parent_widget_get(const Evas_Object *obj)
1364 Evas_Object *parent;
1366 if (_elm_widget_is(obj))
1368 Smart_Data *sd = evas_object_smart_data_get(obj);
1369 if (!sd) return NULL;
1370 parent = sd->parent_obj;
1374 parent = evas_object_data_get(obj, "elm-parent");
1375 if (!parent) parent = evas_object_smart_parent_get(obj);
1380 Evas_Object *elm_parent;
1381 if (_elm_widget_is(parent)) break;
1382 elm_parent = evas_object_data_get(parent, "elm-parent");
1383 if (elm_parent) parent = elm_parent;
1384 else parent = evas_object_smart_parent_get(parent);
1390 elm_widget_parent2_get(const Evas_Object *obj)
1392 if (_elm_widget_is(obj))
1394 Smart_Data *sd = evas_object_smart_data_get(obj);
1395 if (sd) return sd->parent2;
1401 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1404 sd->parent2 = parent;
1408 elm_widget_event_callback_add(Evas_Object *obj,
1413 EINA_SAFETY_ON_NULL_RETURN(func);
1414 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1417 sd->event_cb = eina_list_append(sd->event_cb, ecb);
1421 elm_widget_event_callback_del(Evas_Object *obj,
1425 API_ENTRY return NULL;
1426 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1428 Elm_Event_Cb_Data *ecd;
1429 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1430 if ((ecd->func == func) && (ecd->data == data))
1433 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1434 return (void *)data;
1440 elm_widget_event_propagate(Evas_Object *obj,
1441 Evas_Callback_Type type,
1443 Evas_Event_Flags *event_flags)
1445 API_ENTRY return EINA_FALSE; //TODO reduce.
1446 if (!_elm_widget_is(obj)) return EINA_FALSE;
1447 Evas_Object *parent = obj;
1448 Elm_Event_Cb_Data *ecd;
1449 Eina_List *l, *l_prev;
1452 (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1454 sd = evas_object_smart_data_get(parent);
1455 if ((!sd) || (!_elm_widget_is(obj)))
1456 return EINA_FALSE; //Not Elm Widget
1458 if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1461 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1463 if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1464 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1467 parent = sd->parent_obj;
1476 * Set custom focus chain.
1478 * This function i set one new and overwrite any previous custom focus chain
1479 * with the list of objects. The previous list will be deleted and this list
1480 * will be managed. After setted, don't modity it.
1482 * @note On focus cycle, only will be evaluated children of this container.
1484 * @param obj The container widget
1485 * @param objs Chain of objects to pass focus
1489 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1493 if (!sd->focus_next_func)
1496 elm_widget_focus_custom_chain_unset(obj);
1501 EINA_LIST_FOREACH(objs, l, o)
1503 evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1504 _elm_object_focus_chain_del_cb, sd);
1507 sd->focus_chain = objs;
1513 * Get custom focus chain
1515 * @param obj The container widget
1518 EAPI const Eina_List *
1519 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1521 API_ENTRY return NULL;
1522 return (const Eina_List *)sd->focus_chain;
1528 * Unset custom focus chain
1530 * @param obj The container widget
1534 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1537 Eina_List *l, *l_next;
1540 EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1542 evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1543 _elm_object_focus_chain_del_cb, sd);
1544 sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1551 * Append object to custom focus chain.
1553 * @note If relative_child equal to NULL or not in custom chain, the object
1554 * will be added in end.
1556 * @note On focus cycle, only will be evaluated children of this container.
1558 * @param obj The container widget
1559 * @param child The child to be added in custom chain
1560 * @param relative_child The relative object to position the child
1564 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1566 Evas_Object *relative_child)
1569 EINA_SAFETY_ON_NULL_RETURN(child);
1570 if (!sd->focus_next_func) return;
1572 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1573 _elm_object_focus_chain_del_cb, sd);
1575 if (!relative_child)
1576 sd->focus_chain = eina_list_append(sd->focus_chain, child);
1578 sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1579 child, relative_child);
1585 * Prepend object to custom focus chain.
1587 * @note If relative_child equal to NULL or not in custom chain, the object
1588 * will be added in begin.
1590 * @note On focus cycle, only will be evaluated children of this container.
1592 * @param obj The container widget
1593 * @param child The child to be added in custom chain
1594 * @param relative_child The relative object to position the child
1598 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1600 Evas_Object *relative_child)
1603 EINA_SAFETY_ON_NULL_RETURN(child);
1605 if (!sd->focus_next_func) return;
1607 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1608 _elm_object_focus_chain_del_cb, sd);
1610 if (!relative_child)
1611 sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1613 sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1614 child, relative_child);
1620 * Give focus to next object in object tree.
1622 * Give focus to next object in focus chain of one object sub-tree.
1623 * If the last object of chain already have focus, the focus will go to the
1624 * first object of chain.
1626 * @param obj The widget root of sub-tree
1627 * @param dir Direction to cycle the focus
1632 elm_widget_focus_cycle(Evas_Object *obj,
1633 Elm_Focus_Direction dir)
1635 Evas_Object *target = NULL;
1636 if (!_elm_widget_is(obj))
1638 elm_widget_focus_next_get(obj, dir, &target);
1640 elm_widget_focus_steal(target);
1646 * Give focus to near object in one direction.
1648 * Give focus to near object in direction of one object.
1649 * If none focusable object in given direction, the focus will not change.
1651 * @param obj The reference widget
1652 * @param x Horizontal component of direction to focus
1653 * @param y Vertical component of direction to focus
1657 //FIXME: If x, y indicates the elements of the directional vector,
1658 //It would be better if these values are the normalized value(float x, float y)
1660 EINA_DEPRECATED EAPI void
1661 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1671 * Get next object in focus chain of object tree.
1673 * Get next object in focus chain of one object sub-tree.
1674 * Return the next object by reference. If don't have any candidate to receive
1675 * focus before chain end, the first candidate will be returned.
1677 * @param obj The widget root of sub-tree
1678 * @param dir Direction os focus chain
1679 * @param next The next object in focus chain
1680 * @return EINA_TRUE if don't need focus chain restart/loop back
1681 * to use 'next' obj.
1686 elm_widget_focus_next_get(const Evas_Object *obj,
1687 Elm_Focus_Direction dir,
1694 API_ENTRY return EINA_FALSE;
1696 /* Ignore if disabled */
1697 if ((!evas_object_visible_get(obj))
1698 || (elm_widget_disabled_get(obj))
1699 || (elm_widget_tree_unfocusable_get(obj)))
1703 if (sd->focus_next_func)
1704 return sd->focus_next_func(obj, dir, next);
1706 if (!elm_widget_can_focus_get(obj))
1710 *next = (Evas_Object *)obj;
1711 return !elm_widget_focus_get(obj);
1717 * Get next object in focus chain of object tree in list.
1719 * Get next object in focus chain of one object sub-tree ordered by one list.
1720 * Return the next object by reference. If don't have any candidate to receive
1721 * focus before list end, the first candidate will be returned.
1723 * @param obj The widget root of sub-tree
1724 * @param dir Direction os focus chain
1725 * @param items list with ordered objects
1726 * @param list_data_get function to get the object from one item of list
1727 * @param next The next object in focus chain
1728 * @return EINA_TRUE if don't need focus chain restart/loop back
1729 * to use 'next' obj.
1734 elm_widget_focus_list_next_get(const Evas_Object *obj,
1735 const Eina_List *items,
1736 void *(*list_data_get)(const Eina_List * list),
1737 Elm_Focus_Direction dir,
1740 Eina_List *(*list_next)(const Eina_List * list) = NULL;
1746 if (!_elm_widget_is(obj))
1753 if (dir == ELM_FOCUS_PREVIOUS)
1755 items = eina_list_last(items);
1756 list_next = eina_list_prev;
1758 else if (dir == ELM_FOCUS_NEXT)
1759 list_next = eina_list_next;
1763 const Eina_List *l = items;
1765 /* Recovery last focused sub item */
1766 if (elm_widget_focus_get(obj))
1767 for (; l; l = list_next(l))
1769 Evas_Object *cur = list_data_get(l);
1770 if (elm_widget_focus_get(cur)) break;
1773 const Eina_List *start = l;
1774 Evas_Object *to_focus = NULL;
1776 /* Interate sub items */
1777 /* Go to end of list */
1778 for (; l; l = list_next(l))
1780 Evas_Object *tmp = NULL;
1781 Evas_Object *cur = list_data_get(l);
1783 if (elm_widget_parent_get(cur) != obj)
1786 /* Try Focus cycle in subitem */
1787 if (elm_widget_focus_next_get(cur, dir, &tmp))
1792 else if ((tmp) && (!to_focus))
1798 /* Get First possible */
1799 for (; l != start; l = list_next(l))
1801 Evas_Object *tmp = NULL;
1802 Evas_Object *cur = list_data_get(l);
1804 if (elm_widget_parent_get(cur) != obj)
1807 /* Try Focus cycle in subitem */
1808 elm_widget_focus_next_get(cur, dir, &tmp);
1821 elm_widget_signal_emit(Evas_Object *obj,
1822 const char *emission,
1826 if (!sd->signal_func) return;
1827 sd->signal_func(obj, emission, source);
1831 _edje_signal_callback(void *data,
1832 Evas_Object *obj __UNUSED__,
1833 const char *emission,
1836 Edje_Signal_Data *esd = data;
1837 esd->func(esd->data, esd->obj, emission, source);
1841 elm_widget_signal_callback_add(Evas_Object *obj,
1842 const char *emission,
1844 Edje_Signal_Cb func,
1847 Edje_Signal_Data *esd;
1849 if (!sd->callback_add_func) return;
1850 EINA_SAFETY_ON_NULL_RETURN(func);
1852 esd = ELM_NEW(Edje_Signal_Data);
1857 esd->emission = eina_stringshare_add(emission);
1858 esd->source = eina_stringshare_add(source);
1860 sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1861 sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1865 elm_widget_signal_callback_del(Evas_Object *obj,
1866 const char *emission,
1868 Edje_Signal_Cb func)
1870 Edje_Signal_Data *esd;
1873 API_ENTRY return NULL;
1874 if (!sd->callback_del_func) return NULL;
1876 EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1878 if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1879 (!strcmp(esd->source, source)))
1881 sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1882 eina_stringshare_del(esd->emission);
1883 eina_stringshare_del(esd->source);
1887 sd->callback_del_func
1888 (obj, emission, source, _edje_signal_callback, esd);
1897 elm_widget_focus_set(Evas_Object *obj,
1904 sd->focus_order = focus_order;
1905 sd->focused = EINA_TRUE;
1906 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1910 sd->focus_func(obj);
1917 if ((_is_focusable(sd->resize_obj)) &&
1918 (!elm_widget_disabled_get(sd->resize_obj)))
1920 elm_widget_focus_set(sd->resize_obj, first);
1926 EINA_LIST_FOREACH(sd->subobjs, l, child)
1928 if ((_is_focusable(child)) &&
1929 (!elm_widget_disabled_get(child)))
1931 elm_widget_focus_set(child, first);
1941 EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1943 if ((_is_focusable(child)) &&
1944 (!elm_widget_disabled_get(child)))
1946 elm_widget_focus_set(child, first);
1952 if ((_is_focusable(sd->resize_obj)) &&
1953 (!elm_widget_disabled_get(sd->resize_obj)))
1955 elm_widget_focus_set(sd->resize_obj, first);
1963 elm_widget_parent_get(const Evas_Object *obj)
1965 API_ENTRY return NULL;
1966 return sd->parent_obj;
1970 elm_widget_focused_object_clear(Evas_Object *obj)
1973 if (!sd->focused) return;
1974 if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
1975 elm_widget_focused_object_clear(sd->resize_obj);
1980 EINA_LIST_FOREACH(sd->subobjs, l, child)
1982 if (elm_widget_focus_get(child))
1984 elm_widget_focused_object_clear(child);
1989 sd->focused = EINA_FALSE;
1990 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1991 if (sd->focus_func) sd->focus_func(obj);
1995 elm_widget_focus_steal(Evas_Object *obj)
1997 Evas_Object *parent, *parent2, *o;
2000 if (sd->focused) return;
2001 if (sd->disabled) return;
2002 if (!sd->can_focus) return;
2003 if (sd->tree_unfocusable) return;
2007 o = elm_widget_parent_get(parent);
2009 sd = evas_object_smart_data_get(o);
2010 if (sd->disabled || sd->tree_unfocusable) return;
2011 if (sd->focused) break;
2014 if ((!elm_widget_parent_get(parent)) &&
2015 (!elm_widget_parent2_get(parent)))
2016 elm_widget_focused_object_clear(parent);
2019 parent2 = elm_widget_parent_get(parent);
2020 if (!parent2) parent2 = elm_widget_parent2_get(parent);
2022 sd = evas_object_smart_data_get(parent);
2025 if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2026 elm_widget_focused_object_clear(sd->resize_obj);
2031 EINA_LIST_FOREACH(sd->subobjs, l, child)
2033 if (elm_widget_focus_get(child))
2035 elm_widget_focused_object_clear(child);
2047 elm_widget_focus_restore(Evas_Object *obj)
2049 Evas_Object *newest = NULL;
2050 unsigned int newest_focus_order = 0;
2053 newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2056 elm_object_focus_set(newest, EINA_FALSE);
2057 elm_object_focus_set(newest, EINA_TRUE);
2062 _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2068 if (sd->top_win_focused == top_win_focused) return;
2070 _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2071 EINA_LIST_FOREACH(sd->subobjs, l, child)
2073 _elm_widget_top_win_focused_set(child, top_win_focused);
2075 sd->top_win_focused = top_win_focused;
2079 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2081 API_ENTRY return EINA_FALSE;
2082 return sd->top_win_focused;
2086 elm_widget_activate(Evas_Object *obj)
2089 elm_widget_change(obj);
2090 if (sd->activate_func) sd->activate_func(obj);
2094 elm_widget_change(Evas_Object *obj)
2097 elm_widget_change(elm_widget_parent_get(obj));
2098 if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2102 elm_widget_disabled_set(Evas_Object *obj,
2107 if (sd->disabled == disabled) return;
2108 sd->disabled = !!disabled;
2109 elm_widget_focus_disabled_handle(obj);
2110 if (sd->disable_func) sd->disable_func(obj);
2114 elm_widget_disabled_get(const Evas_Object *obj)
2117 return sd->disabled;
2121 elm_widget_show_region_set(Evas_Object *obj,
2126 Eina_Bool forceshow)
2128 Evas_Object *parent_obj, *child_obj;
2129 Evas_Coord px, py, cx, cy;
2133 evas_smart_objects_calculate(evas_object_evas_get(obj));
2135 if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2136 (w == sd->rw) && (h == sd->rh)) return;
2141 if (sd->on_show_region_func)
2142 sd->on_show_region_func(sd->on_show_region_data, obj);
2146 parent_obj = sd->parent_obj;
2147 child_obj = sd->obj;
2148 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2149 sd = evas_object_smart_data_get(parent_obj);
2152 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2153 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2162 if (sd->on_show_region_func)
2164 sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2171 elm_widget_show_region_get(const Evas_Object *obj,
2187 * Get the focus region of the given widget.
2189 * The focus region is the area of a widget that should brought into the
2190 * visible area when the widget is focused. Mostly used to show the part of
2191 * an entry where the cursor is, for example. The area returned is relative
2192 * to the object @p obj.
2193 * If the @p obj doesn't have the proper on_focus_region_hook set, this
2194 * function will return the full size of the object.
2196 * @param obj The widget object
2197 * @param x Where to store the x coordinate of the area
2198 * @param y Where to store the y coordinate of the area
2199 * @param w Where to store the width of the area
2200 * @param h Where to store the height of the area
2205 elm_widget_focus_region_get(const Evas_Object *obj,
2215 sd = evas_object_smart_data_get(obj);
2216 if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2218 evas_object_geometry_get(obj, NULL, NULL, w, h);
2223 sd->on_focus_region_func(obj, x, y, w, h);
2227 elm_widget_scroll_hold_push(Evas_Object *obj)
2231 if (sd->scroll_hold == 1)
2232 evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2233 if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2234 // FIXME: on delete/reparent hold pop
2238 elm_widget_scroll_hold_pop(Evas_Object *obj)
2242 if (!sd->scroll_hold)
2243 evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2244 if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2245 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2249 elm_widget_scroll_hold_get(const Evas_Object *obj)
2252 return sd->scroll_hold;
2256 elm_widget_scroll_freeze_push(Evas_Object *obj)
2259 sd->scroll_freeze++;
2260 if (sd->scroll_freeze == 1)
2261 evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2262 if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2263 // FIXME: on delete/reparent freeze pop
2267 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2270 sd->scroll_freeze--;
2271 if (!sd->scroll_freeze)
2272 evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2273 if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2274 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2278 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2281 return sd->scroll_freeze;
2285 elm_widget_scale_set(Evas_Object *obj,
2289 if (scale <= 0.0) scale = 0.0;
2290 if (sd->scale != scale)
2293 elm_widget_theme(obj);
2298 elm_widget_scale_get(const Evas_Object *obj)
2300 API_ENTRY return 1.0;
2301 // FIXME: save walking up the tree by storing/caching parent scale
2302 if (sd->scale == 0.0)
2305 return elm_widget_scale_get(sd->parent_obj);
2313 elm_widget_theme_set(Evas_Object *obj,
2317 if (sd->theme != th)
2319 if (sd->theme) elm_theme_free(sd->theme);
2322 elm_widget_theme(obj);
2327 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2331 if (!sd->text_set_func)
2334 sd->text_set_func(obj, part, label);
2338 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2340 API_ENTRY return NULL;
2342 if (!sd->text_get_func)
2345 return sd->text_get_func(obj, part);
2349 elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2353 Elm_Translate_String_Data *ts = NULL;
2356 str = eina_stringshare_add(part);
2357 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2364 eina_stringshare_del(str);
2367 ts = malloc(sizeof(Elm_Translate_String_Data));
2371 ts->domain = eina_stringshare_add(domain);
2372 ts->string = eina_stringshare_add(label);
2373 sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2379 eina_stringshare_replace(&ts->domain, domain);
2380 eina_stringshare_replace(&ts->string, label);
2384 sd->translate_strings = eina_list_remove_list(
2385 sd->translate_strings, l);
2386 eina_stringshare_del(ts->id);
2387 eina_stringshare_del(ts->domain);
2388 eina_stringshare_del(ts->string);
2391 eina_stringshare_del(str);
2395 if (label && label[0])
2396 label = dgettext(domain, label);
2398 elm_widget_text_part_set(obj, part, label);
2402 elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2404 const char *str, *ret = NULL;
2406 Elm_Translate_String_Data *ts;
2407 API_ENTRY return NULL;
2409 str = eina_stringshare_add(part);
2410 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2416 eina_stringshare_del(str);
2421 elm_widget_translate(Evas_Object *obj)
2426 Elm_Translate_String_Data *ts;
2430 EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2431 if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2432 if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2433 if (sd->translate_func) sd->translate_func(obj);
2436 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2438 const char *s = dgettext(ts->domain, ts->string);
2439 elm_widget_text_part_set(obj, ts->id, s);
2445 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2449 if (!sd->content_set_func) return;
2450 sd->content_set_func(obj, part, content);
2454 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2456 API_ENTRY return NULL;
2458 if (!sd->content_get_func) return NULL;
2459 return sd->content_get_func(obj, part);
2463 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2465 API_ENTRY return NULL;
2467 if (!sd->content_unset_func) return NULL;
2468 return sd->content_unset_func(obj, part);
2472 elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2475 if (sd->access_info) eina_stringshare_del(sd->access_info);
2476 if (!txt) sd->access_info = NULL;
2477 else sd->access_info = eina_stringshare_add(txt);
2481 elm_widget_access_info_get(const Evas_Object *obj)
2483 API_ENTRY return NULL;
2484 return sd->access_info;
2488 elm_widget_theme_get(const Evas_Object *obj)
2490 API_ENTRY return NULL;
2494 return elm_widget_theme_get(sd->parent_obj);
2502 elm_widget_style_set(Evas_Object *obj,
2505 API_ENTRY return EINA_FALSE;
2507 if (eina_stringshare_replace(&sd->style, style))
2508 return elm_widget_theme(obj);
2514 elm_widget_style_get(const Evas_Object *obj)
2516 API_ENTRY return NULL;
2517 if (sd->style) return sd->style;
2522 elm_widget_type_set(Evas_Object *obj,
2526 eina_stringshare_replace(&sd->type, type);
2530 elm_widget_type_get(const Evas_Object *obj)
2532 API_ENTRY return NULL;
2533 if (sd->type) return sd->type;
2538 elm_widget_tooltip_add(Evas_Object *obj,
2542 sd->tooltips = eina_list_append(sd->tooltips, tt);
2546 elm_widget_tooltip_del(Evas_Object *obj,
2550 sd->tooltips = eina_list_remove(sd->tooltips, tt);
2554 elm_widget_cursor_add(Evas_Object *obj,
2558 sd->cursors = eina_list_append(sd->cursors, cur);
2562 elm_widget_cursor_del(Evas_Object *obj,
2566 sd->cursors = eina_list_remove(sd->cursors, cur);
2570 elm_widget_drag_lock_x_set(Evas_Object *obj,
2574 if (sd->drag_x_locked == lock) return;
2575 sd->drag_x_locked = lock;
2576 if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2577 else _propagate_x_drag_lock(obj, -1);
2581 elm_widget_drag_lock_y_set(Evas_Object *obj,
2585 if (sd->drag_y_locked == lock) return;
2586 sd->drag_y_locked = lock;
2587 if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2588 else _propagate_y_drag_lock(obj, -1);
2592 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2594 API_ENTRY return EINA_FALSE;
2595 return sd->drag_x_locked;
2599 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2601 API_ENTRY return EINA_FALSE;
2602 return sd->drag_y_locked;
2606 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2609 return sd->child_drag_x_locked;
2613 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2616 return sd->child_drag_y_locked;
2620 elm_widget_theme_object_set(Evas_Object *obj,
2623 const char *welement,
2626 API_ENTRY return EINA_FALSE;
2627 return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2631 elm_widget_is_check(const Evas_Object *obj)
2633 static int abort_on_warn = -1;
2634 if (elm_widget_is(obj))
2637 ERR("Passing Object: %p.", obj);
2638 if (abort_on_warn == -1)
2640 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2641 else abort_on_warn = 0;
2643 if (abort_on_warn == 1) abort();
2648 elm_widget_type_check(const Evas_Object *obj,
2652 const char *provided, *expected = "(unknown)";
2653 static int abort_on_warn = -1;
2654 provided = elm_widget_type_get(obj);
2655 if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2656 if (type) expected = type;
2657 if ((!provided) || (!provided[0]))
2659 provided = evas_object_type_get(obj);
2660 if ((!provided) || (!provided[0]))
2661 provided = "(unknown)";
2663 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2664 if (abort_on_warn == -1)
2666 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2667 else abort_on_warn = 0;
2669 if (abort_on_warn == 1) abort();
2673 static Evas_Object *
2674 _widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2679 INTERNAL_ENTRY NULL;
2681 if (!_elm_widget_is(obj)) return NULL;
2684 s = evas_object_name_get(sd->resize_obj);
2685 if ((s) && (!strcmp(s, name))) return sd->resize_obj;
2686 if ((recurse != 0) &&
2687 ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
2690 EINA_LIST_FOREACH(sd->subobjs, l, child)
2692 s = evas_object_name_get(child);
2693 if ((s) && (!strcmp(s, name))) return child;
2694 if ((recurse != 0) &&
2695 ((child = _widget_name_find(child, name, recurse - 1))))
2700 s = evas_object_name_get(sd->hover_obj);
2701 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
2702 if ((recurse != 0) &&
2703 ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
2710 elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2712 API_ENTRY return NULL;
2713 if (!name) return NULL;
2714 return _widget_name_find(obj, name, recurse);
2720 * Split string in words
2722 * @param str Source string
2723 * @return List of const words
2725 * @see elm_widget_stringlist_free()
2729 elm_widget_stringlist_get(const char *str)
2731 Eina_List *list = NULL;
2733 if (!str) return NULL;
2734 for (b = s = str; 1; s++)
2736 if ((*s == ' ') || (!*s))
2738 char *t = malloc(s - b + 1);
2741 strncpy(t, b, s - b);
2743 list = eina_list_append(list, eina_stringshare_add(t));
2754 elm_widget_stringlist_free(Eina_List *list)
2757 EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2761 elm_widget_focus_hide_handle(Evas_Object *obj)
2763 if (!_elm_widget_is(obj))
2765 _if_focused_revert(obj, EINA_TRUE);
2769 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2771 Evas_Object *o = obj;
2774 if (_elm_widget_is(o)) break;
2775 o = evas_object_smart_parent_get(o);
2779 if (!_is_focusable(o)) return;
2780 elm_widget_focus_steal(o);
2784 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2788 //FIXME: Need to check whether the object is unfocusable or not.
2790 if (!elm_widget_parent_get(obj))
2791 elm_widget_focused_object_clear(obj);
2793 _if_focused_revert(obj, EINA_TRUE);
2797 elm_widget_focus_disabled_handle(Evas_Object *obj)
2801 elm_widget_focus_tree_unfocusable_handle(obj);
2805 elm_widget_focus_order_get(const Evas_Object *obj)
2808 return sd->focus_order;
2814 * Allocate a new Elm_Widget_Item-derived structure.
2816 * The goal of this structure is to provide common ground for actions
2817 * that a widget item have, such as the owner widget, callback to
2818 * notify deletion, data pointer and maybe more.
2820 * @param widget the owner widget that holds this item, must be an elm_widget!
2821 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2822 * be used to allocate memory.
2824 * @return allocated memory that is already zeroed out, or NULL on errors.
2826 * @see elm_widget_item_new() convenience macro.
2827 * @see elm_widget_item_del() to release memory.
2830 EAPI Elm_Widget_Item *
2831 _elm_widget_item_new(Evas_Object *widget,
2834 if (!_elm_widget_is(widget))
2837 Elm_Widget_Item *item;
2839 EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2840 EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2842 item = calloc(1, alloc_size);
2843 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2845 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2846 item->widget = widget;
2851 _elm_widget_item_free(Elm_Widget_Item *item)
2853 ELM_WIDGET_ITEM_FREE_OR_RETURN(item);
2854 Elm_Object_Item_Smart_Cb cb;
2856 if (item->walking > 0)
2858 item->delete_me = EINA_TRUE;
2862 EINA_LIST_FREE(item->callbacks, cb) free(cb);
2865 item->del_func((void *)item->data, item->widget, item);
2868 evas_object_del(item->view);
2872 _elm_access_clear(item->access);
2876 if (item->access_info)
2877 eina_stringshare_del(item->access_info);
2879 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2886 * Releases widget item memory, calling back del_cb() if it exists.
2888 * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2889 * to memory release. Note that elm_widget_item_pre_notify_del() calls
2890 * this function and then unset it, thus being useful for 2 step
2891 * cleanup whenever the del_cb may use any of the data that must be
2892 * deleted from item.
2894 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2897 * @param item a valid #Elm_Widget_Item to be deleted.
2898 * @see elm_widget_item_del() convenience macro.
2902 _elm_widget_item_del(Elm_Widget_Item *item)
2904 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2906 //Widget item delete callback
2907 if (item->del_pre_func)
2909 if (item->del_pre_func((Elm_Object_Item *)item))
2910 _elm_widget_item_free(item);
2913 _elm_widget_item_free(item);
2919 * Set the function to notify to widgets when item is being deleted by user.
2921 * @param item a valid #Elm_Widget_Item to be notified
2922 * @see elm_widget_item_del_pre_hook_set() convenience macro.
2926 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func)
2928 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2929 item->del_pre_func = func;
2935 * Notify object will be deleted without actually deleting it.
2937 * This function will callback Elm_Widget_Item::del_cb if it is set
2938 * and then unset it so it is not called twice (ie: from
2939 * elm_widget_item_del()).
2941 * @param item a valid #Elm_Widget_Item to be notified
2942 * @see elm_widget_item_pre_notify_del() convenience macro.
2946 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2948 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2949 if (!item->del_func) return;
2950 item->del_func((void *)item->data, item->widget, item);
2951 item->del_func = NULL;
2957 * Set the function to notify when item is being deleted.
2959 * This function will complain if there was a callback set already,
2960 * however it will set the new one.
2962 * The callback will be called from elm_widget_item_pre_notify_del()
2963 * or elm_widget_item_del() will be called with:
2964 * - data: the Elm_Widget_Item::data value.
2965 * - obj: the Elm_Widget_Item::widget evas object.
2966 * - event_info: the item being deleted.
2968 * @param item a valid #Elm_Widget_Item to be notified
2969 * @see elm_widget_item_del_cb_set() convenience macro.
2973 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2976 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2978 if ((item->del_func) && (item->del_func != func))
2979 WRN("You're replacing a previously set del_cb %p of item %p with %p",
2980 item->del_func, item, func);
2982 item->del_func = func;
2988 * Set user-data in this item.
2990 * User data may be used to identify this item or just store any
2991 * application data. It is automatically given as the first parameter
2992 * of the deletion notify callback.
2994 * @param item a valid #Elm_Widget_Item to store data in.
2995 * @param data user data to store.
2996 * @see elm_widget_item_del_cb_set() convenience macro.
3000 _elm_widget_item_data_set(Elm_Widget_Item *item,
3003 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3004 if ((item->data) && (item->data != data))
3005 DBG("Replacing item %p data %p with %p", item, item->data, data);
3012 * Retrieves user-data of this item.
3014 * @param item a valid #Elm_Widget_Item to get data from.
3015 * @see elm_widget_item_data_set()
3019 _elm_widget_item_data_get(const Elm_Widget_Item *item)
3021 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3022 return (void *)item->data;
3026 _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
3028 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3030 if (item->disabled == disabled) return;
3031 item->disabled = !!disabled;
3032 if (item->disable_func) item->disable_func(item);
3036 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
3038 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3039 return item->disabled;
3043 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
3044 Elm_Widget_Disable_Cb func)
3046 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3047 item->disable_func = func;
3050 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
3052 struct _Elm_Widget_Item_Tooltip
3054 Elm_Widget_Item *item;
3055 Elm_Tooltip_Item_Content_Cb func;
3056 Evas_Smart_Cb del_cb;
3060 static Evas_Object *
3061 _elm_widget_item_tooltip_label_create(void *data,
3062 Evas_Object *obj __UNUSED__,
3063 Evas_Object *tooltip,
3064 void *item __UNUSED__)
3066 Evas_Object *label = elm_label_add(tooltip);
3069 elm_object_style_set(label, "tooltip");
3070 elm_object_text_set(label, data);
3074 static Evas_Object *
3075 _elm_widget_item_tooltip_trans_label_create(void *data,
3076 Evas_Object *obj __UNUSED__,
3077 Evas_Object *tooltip,
3078 void *item __UNUSED__)
3080 Evas_Object *label = elm_label_add(tooltip);
3083 elm_object_style_set(label, "tooltip");
3084 elm_object_translatable_text_set(label, data);
3089 _elm_widget_item_tooltip_label_del_cb(void *data,
3090 Evas_Object *obj __UNUSED__,
3091 void *event_info __UNUSED__)
3093 eina_stringshare_del(data);
3099 * Set the text to be shown in the widget item.
3101 * @param item Target item
3102 * @param text The text to set in the content
3104 * Setup the text as tooltip to object. The item can have only one tooltip,
3105 * so any previous tooltip data is removed.
3110 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
3113 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3114 EINA_SAFETY_ON_NULL_RETURN(text);
3116 text = eina_stringshare_add(text);
3117 _elm_widget_item_tooltip_content_cb_set
3118 (item, _elm_widget_item_tooltip_label_create, text,
3119 _elm_widget_item_tooltip_label_del_cb);
3123 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
3126 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3127 EINA_SAFETY_ON_NULL_RETURN(text);
3129 text = eina_stringshare_add(text);
3130 _elm_widget_item_tooltip_content_cb_set
3131 (item, _elm_widget_item_tooltip_trans_label_create, text,
3132 _elm_widget_item_tooltip_label_del_cb);
3135 static Evas_Object *
3136 _elm_widget_item_tooltip_create(void *data,
3138 Evas_Object *tooltip)
3140 Elm_Widget_Item_Tooltip *wit = data;
3141 return wit->func((void *)wit->data, obj, tooltip, wit->item);
3145 _elm_widget_item_tooltip_del_cb(void *data,
3147 void *event_info __UNUSED__)
3149 Elm_Widget_Item_Tooltip *wit = data;
3150 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3157 * Set the content to be shown in the tooltip item
3159 * Setup the tooltip to item. The item can have only one tooltip,
3160 * so any previous tooltip data is removed. @p func(with @p data) will
3161 * be called every time that need show the tooltip and it should
3162 * return a valid Evas_Object. This object is then managed fully by
3163 * tooltip system and is deleted when the tooltip is gone.
3165 * @param item the widget item being attached a tooltip.
3166 * @param func the function used to create the tooltip contents.
3167 * @param data what to provide to @a func as callback data/context.
3168 * @param del_cb called when data is not needed anymore, either when
3169 * another callback replaces @func, the tooltip is unset with
3170 * elm_widget_item_tooltip_unset() or the owner @a item
3171 * dies. This callback receives as the first parameter the
3172 * given @a data, and @c event_info is the item.
3177 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
3178 Elm_Tooltip_Item_Content_Cb func,
3180 Evas_Smart_Cb del_cb)
3182 Elm_Widget_Item_Tooltip *wit;
3184 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3188 _elm_widget_item_tooltip_unset(item);
3192 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3193 if (!wit) goto error;
3197 wit->del_cb = del_cb;
3199 elm_object_sub_tooltip_content_cb_set
3200 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3201 _elm_widget_item_tooltip_del_cb);
3206 if (del_cb) del_cb((void *)data, NULL, item);
3209 if (del_cb) del_cb((void *)data, item->widget, item);
3215 * Unset tooltip from item
3217 * @param item widget item to remove previously set tooltip.
3219 * Remove tooltip from item. The callback provided as del_cb to
3220 * elm_widget_item_tooltip_content_cb_set() will be called to notify
3221 * it is not used anymore.
3223 * @see elm_widget_item_tooltip_content_cb_set()
3228 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3230 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3231 elm_object_tooltip_unset(item->view);
3237 * Sets a different style for this item tooltip.
3239 * @note before you set a style you should define a tooltip with
3240 * elm_widget_item_tooltip_content_cb_set() or
3241 * elm_widget_item_tooltip_text_set()
3243 * @param item widget item with tooltip already set.
3244 * @param style the theme style to use (default, transparent, ...)
3249 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3252 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3253 elm_object_tooltip_style_set(item->view, style);
3257 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item, Eina_Bool disable)
3259 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3260 return elm_object_tooltip_window_mode_set(item->view, disable);
3264 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
3266 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3267 return elm_object_tooltip_window_mode_get(item->view);
3273 * Get the style for this item tooltip.
3275 * @param item widget item with tooltip already set.
3276 * @return style the theme style in use, defaults to "default". If the
3277 * object does not have a tooltip set, then NULL is returned.
3282 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3284 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3285 return elm_object_tooltip_style_get(item->view);
3289 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
3292 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3293 elm_object_sub_cursor_set(item->view, item->widget, cursor);
3297 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3299 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3300 return elm_object_cursor_get(item->view);
3304 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3306 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3307 elm_object_cursor_unset(item->view);
3313 * Sets a different style for this item cursor.
3315 * @note before you set a style you should define a cursor with
3316 * elm_widget_item_cursor_set()
3318 * @param item widget item with cursor already set.
3319 * @param style the theme style to use (default, transparent, ...)
3324 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3327 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3328 elm_object_cursor_style_set(item->view, style);
3334 * Get the style for this item cursor.
3336 * @param item widget item with cursor already set.
3337 * @return style the theme style in use, defaults to "default". If the
3338 * object does not have a cursor set, then NULL is returned.
3343 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3345 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3346 return elm_object_cursor_style_get(item->view);
3352 * Set if the cursor set should be searched on the theme or should use
3353 * the provided by the engine, only.
3355 * @note before you set if should look on theme you should define a cursor
3356 * with elm_object_cursor_set(). By default it will only look for cursors
3357 * provided by the engine.
3359 * @param item widget item with cursor already set.
3360 * @param engine_only boolean to define it cursors should be looked only
3361 * between the provided by the engine or searched on widget's theme as well.
3366 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3367 Eina_Bool engine_only)
3369 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3370 elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
3376 * Get the cursor engine only usage for this item cursor.
3378 * @param item widget item with cursor already set.
3379 * @return engine_only boolean to define it cursors should be looked only
3380 * between the provided by the engine or searched on widget's theme as well. If
3381 * the object does not have a cursor set, then EINA_FALSE is returned.
3386 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3388 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3389 return elm_object_cursor_theme_search_enabled_get(item->view);
3392 // smart object funcs
3394 _smart_reconfigure(Smart_Data *sd)
3398 evas_object_move(sd->resize_obj, sd->x, sd->y);
3399 evas_object_resize(sd->resize_obj, sd->w, sd->h);
3403 evas_object_move(sd->hover_obj, sd->x, sd->y);
3404 evas_object_resize(sd->hover_obj, sd->w, sd->h);
3409 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
3411 Evas_Object *content)
3413 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3414 if (!item->content_set_func) return;
3415 item->content_set_func((Elm_Object_Item *)item, part, content);
3419 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
3422 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3423 if (!item->content_get_func) return NULL;
3424 return item->content_get_func((Elm_Object_Item *)item, part);
3428 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3431 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3432 if (!item->content_unset_func) return NULL;
3433 return item->content_unset_func((Elm_Object_Item *)item, part);
3437 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3441 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3442 if (!item->text_set_func) return;
3443 item->text_set_func((Elm_Object_Item *)item, part, label);
3447 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3448 const char *emission,
3451 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3452 if (item->signal_emit_func)
3453 item->signal_emit_func((Elm_Object_Item *)item, emission, source);
3457 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3460 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3461 if (!item->text_get_func) return NULL;
3462 return item->text_get_func((Elm_Object_Item *)item, part);
3466 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3467 Elm_Widget_Content_Set_Cb func)
3469 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3470 item->content_set_func = func;
3474 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3475 Elm_Widget_Content_Get_Cb func)
3477 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3478 item->content_get_func = func;
3482 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3483 Elm_Widget_Content_Unset_Cb func)
3485 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3486 item->content_unset_func = func;
3490 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3491 Elm_Widget_Text_Set_Cb func)
3493 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3494 item->text_set_func = func;
3498 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3499 Elm_Widget_Text_Get_Cb func)
3501 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3502 item->text_get_func = func;
3506 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3507 Elm_Widget_Signal_Emit_Cb func)
3509 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3510 item->signal_emit_func = func;
3514 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3516 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3517 if (item->access_info) eina_stringshare_del(item->access_info);
3518 if (!txt) item->access_info = NULL;
3519 else item->access_info = eina_stringshare_add(txt);
3523 elm_widget_item_smart_callback_add(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func, const void *data)
3525 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3526 if ((!event) || (!func)) return;
3528 Elm_Widget_Item_Callback *cb = ELM_NEW(Elm_Widget_Item_Callback);
3531 //TODO: apply MEMPOOL?
3532 cb->event = eina_stringshare_add(event);
3534 cb->data = (void *)data;
3535 item->callbacks = eina_list_append(item->callbacks, cb);
3539 elm_widget_item_smart_callback_del(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func)
3541 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3543 Eina_List *l, *l_next;
3544 Elm_Widget_Item_Callback *cb;
3546 if ((!event) || (!func)) return NULL;
3548 EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb)
3550 if ((!strcmp(cb->event, event)) && (cb->func == func))
3552 void *data = cb->data;
3555 item->callbacks = eina_list_remove_list(item->callbacks, l);
3559 cb->delete_me = EINA_TRUE;
3567 _elm_widget_item_smart_callback_call(Elm_Widget_Item *item, const char *event, void *event_info)
3569 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3571 Eina_List *l, *l_next;
3572 Elm_Widget_Item_Callback *cb;
3573 const char *strshare;
3577 strshare = eina_stringshare_add(event);
3579 EINA_LIST_FOREACH(item->callbacks, l, cb)
3581 if (strcmp(cb->event, strshare)) continue;
3582 if (cb->delete_me) continue;
3585 cb->func(cb->data, (Elm_Object_Item *)item, event_info);
3588 if (item->delete_me) break;
3592 EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb)
3594 if (!cb->delete_me) continue;
3595 item->callbacks = eina_list_remove_list(item->callbacks, l);
3599 if (item->delete_me && !item->walking)
3600 elm_widget_item_free(item);
3604 _smart_add(Evas_Object *obj)
3608 sd = calloc(1, sizeof(Smart_Data));
3611 sd->x = sd->y = sd->w = sd->h = 0;
3612 sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3613 evas_object_smart_data_set(obj, sd);
3614 elm_widget_can_focus_set(obj, EINA_TRUE);
3617 static Evas_Object *
3618 _newest_focus_order_get(Evas_Object *obj,
3619 unsigned int *newest_focus_order,
3620 Eina_Bool can_focus_only)
3623 Evas_Object *child, *ret, *best;
3625 API_ENTRY return NULL;
3627 if (!evas_object_visible_get(obj)
3628 || (elm_widget_disabled_get(obj))
3629 || (elm_widget_tree_unfocusable_get(obj)))
3633 if (*newest_focus_order < sd->focus_order)
3635 *newest_focus_order = sd->focus_order;
3638 EINA_LIST_FOREACH(sd->subobjs, l, child)
3640 ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3646 if ((!best) || (!elm_widget_can_focus_get(best)))
3653 _if_focused_revert(Evas_Object *obj,
3654 Eina_Bool can_focus_only)
3657 Evas_Object *newest = NULL;
3658 unsigned int newest_focus_order = 0;
3662 if (!sd->focused) return;
3663 if (!sd->parent_obj) return;
3665 top = elm_widget_top_get(sd->parent_obj);
3668 newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3671 elm_object_focus_set(newest, EINA_FALSE);
3672 elm_object_focus_set(newest, EINA_TRUE);
3678 _smart_del(Evas_Object *obj)
3681 Edje_Signal_Data *esd;
3682 Elm_Translate_String_Data *ts;
3686 if (sd->del_pre_func) sd->del_pre_func(obj);
3689 sobj = sd->resize_obj;
3690 sd->resize_obj = NULL;
3691 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3692 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3693 evas_object_del(sobj);
3694 sd->resize_obj = NULL;
3698 sobj = sd->hover_obj;
3699 sd->hover_obj = NULL;
3700 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3701 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3702 evas_object_del(sobj);
3703 sd->hover_obj = NULL;
3705 EINA_LIST_FREE(sd->subobjs, sobj)
3707 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3708 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3709 evas_object_del(sobj);
3711 sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
3712 sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
3713 EINA_LIST_FREE(sd->edje_signals, esd)
3715 eina_stringshare_del(esd->emission);
3716 eina_stringshare_del(esd->source);
3719 EINA_LIST_FREE(sd->translate_strings, ts)
3721 eina_stringshare_del(ts->id);
3722 eina_stringshare_del(ts->domain);
3723 eina_stringshare_del(ts->string);
3726 sd->event_cb = eina_list_free(sd->event_cb); /* should be empty anyway */
3727 if (sd->del_func) sd->del_func(obj);
3728 if (sd->style) eina_stringshare_del(sd->style);
3729 if (sd->type) eina_stringshare_del(sd->type);
3730 if (sd->theme) elm_theme_free(sd->theme);
3732 _if_focused_revert(obj, EINA_TRUE);
3733 if (sd->access_info) eina_stringshare_del(sd->access_info);
3735 evas_object_smart_data_set(obj, NULL);
3739 _smart_move(Evas_Object *obj,
3746 _smart_reconfigure(sd);
3750 _smart_resize(Evas_Object *obj,
3757 _smart_reconfigure(sd);
3761 _smart_show(Evas_Object *obj)
3766 if ((list = evas_object_smart_members_get(obj)))
3768 EINA_LIST_FREE(list, o)
3770 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3771 evas_object_show(o);
3777 _smart_hide(Evas_Object *obj)
3783 list = evas_object_smart_members_get(obj);
3784 EINA_LIST_FREE(list, o)
3786 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3787 evas_object_hide(o);
3792 _smart_color_set(Evas_Object *obj,
3801 if ((list = evas_object_smart_members_get(obj)))
3803 EINA_LIST_FREE(list, o)
3805 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3806 evas_object_color_set(o, r, g, b, a);
3812 _smart_clip_set(Evas_Object *obj,
3818 if ((list = evas_object_smart_members_get(obj)))
3820 EINA_LIST_FREE(list, o)
3822 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3823 evas_object_clip_set(o, clip);
3829 _smart_clip_unset(Evas_Object *obj)
3834 if ((list = evas_object_smart_members_get(obj)))
3836 EINA_LIST_FREE(list, o)
3838 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3839 evas_object_clip_unset(o);
3845 _smart_calculate(Evas_Object *obj)
3848 if (sd->changed_func) sd->changed_func(obj);
3852 _smart_member_add(Evas_Object *obj, Evas_Object *child)
3856 if (evas_object_data_get(child, "_elm_leaveme")) return;
3858 evas_object_color_get(obj, &r, &g, &b, &a);
3859 evas_object_color_set(child, r, g, b, a);
3861 evas_object_clip_set(child, evas_object_clip_get(obj));
3863 if (evas_object_visible_get(obj))
3864 evas_object_show(child);
3866 evas_object_hide(child);
3869 /* never need to touch this */
3873 if (_e_smart) return;
3875 static const Evas_Smart_Class sc =
3878 EVAS_SMART_CLASS_VERSION,
3896 _e_smart = evas_smart_class_new(&sc);
3900 /* happy debug functions */
3903 _sub_obj_tree_dump(const Evas_Object *obj,
3908 for (i = 0; i < lvl * 3; i++)
3911 if (_elm_widget_is(obj))
3915 printf("+ %s(%p)\n",
3919 _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3920 EINA_LIST_FOREACH(sd->subobjs, l, obj)
3922 if (obj != sd->resize_obj)
3923 _sub_obj_tree_dump(obj, lvl + 1);
3927 printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3931 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3934 if (!_elm_widget_is(obj))
3938 Eina_Bool visible = evas_object_visible_get(obj);
3939 Eina_Bool disabled = elm_widget_disabled_get(obj);
3940 Eina_Bool focused = elm_widget_focus_get(obj);
3941 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3945 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3948 fprintf(output, ", style=bold");
3951 fprintf(output, ", color=gray28");
3953 fprintf(output, " ];\n");
3956 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3957 "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3958 evas_object_name_get(obj), visible, disabled, focused, can_focus,
3962 fprintf(output, ", style=bold");
3965 fprintf(output, ", fontcolor=gray28");
3967 if ((disabled) || (!visible))
3968 fprintf(output, ", color=gray");
3970 fprintf(output, " ];\n");
3974 EINA_LIST_FOREACH(sd->subobjs, l, o)
3975 _sub_obj_tree_dot_dump(o, output);
3980 elm_widget_tree_dump(const Evas_Object *top)
3983 if (!_elm_widget_is(top))
3985 _sub_obj_tree_dump(top, 0);
3993 elm_widget_tree_dot_dump(const Evas_Object *top,
3997 if (!_elm_widget_is(top))
3999 fprintf(output, "graph " " { node [shape=record];\n");
4000 _sub_obj_tree_dot_dump(top, output);
4001 fprintf(output, "}\n");