2 # include "elementary_config.h"
5 #include <Elementary.h>
11 # define STUPID(X) STR(X)
12 # define TTDBG(x...) fprintf(stderr, STUPID(__LINE__)": " x)
17 static const char _tooltip_key[] = "_elm_tooltip";
19 #define ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ...) \
25 CRI("Null pointer: " #obj); \
28 tt = evas_object_data_get((obj), _tooltip_key); \
31 ERR("Object does not have tooltip: " #obj); \
39 Elm_Tooltip_Content_Cb func;
44 Evas_Object *eventarea, *owner;
45 Evas_Object *tooltip, *content;
47 Ecore_Timer *show_timer;
48 Ecore_Timer *hide_timer;
49 Ecore_Job *reconfigure_job;
50 Evas_Coord mouse_x, mouse_y;
53 Evas_Coord x, y, bx, by;
59 Elm_Tooltip_Orient orient; /** orientation for tooltip */
62 double hide_timeout; /* from theme */
63 Eina_Bool visible_lock:1;
64 Eina_Bool changed_style:1;
65 Eina_Bool free_size : 1;
68 static void _elm_tooltip_reconfigure(Elm_Tooltip *tt);
69 static void _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt);
70 static void _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt);
71 static void _elm_tooltip_hide_anim_start(Elm_Tooltip *tt);
72 static void _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt);
73 static void _elm_tooltip_show_timer_stop(Elm_Tooltip *tt);
74 static void _elm_tooltip_hide(Elm_Tooltip *tt);
75 static void _elm_tooltip_data_clean(Elm_Tooltip *tt);
78 _elm_tooltip_content_changed_hints_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
80 _elm_tooltip_reconfigure_job_start(data);
81 TTDBG("HINTS CHANGED\n");
85 _elm_tooltip_content_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
87 Elm_Tooltip *tt = data;
89 tt->visible_lock = EINA_FALSE;
90 if (tt->tooltip) _elm_tooltip_hide(tt);
94 _elm_tooltip_obj_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
96 Elm_Tooltip *tt = data;
97 _elm_tooltip_reconfigure_job_start(tt);
102 _elm_tooltip_obj_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
104 Elm_Tooltip *tt = data;
105 _elm_tooltip_reconfigure_job_start(tt);
106 TTDBG("TT RESIZE\n");
110 _elm_tooltip_obj_mouse_move_cb(void *data, Evas *e EINA_UNUSED,
111 Evas_Object *obj EINA_UNUSED, void *event_info)
113 Elm_Tooltip *tt = data;
114 Evas_Event_Mouse_Move *ev = event_info;
116 if (tt->mouse_x || tt->mouse_y)
118 if ((abs(ev->cur.output.x - tt->mouse_x) < 3) &&
119 (abs(ev->cur.output.y - tt->mouse_y) < 3))
121 TTDBG("MOUSE MOVE REJECTED!\n");
125 tt->mouse_x = ev->cur.output.x;
126 tt->mouse_y = ev->cur.output.y;
127 TTDBG("MOUSE MOVED\n");
128 _elm_tooltip_reconfigure_job_start(tt);
132 _elm_tooltip_show(Elm_Tooltip *tt)
134 _elm_tooltip_show_timer_stop(tt);
135 _elm_tooltip_hide_anim_stop(tt);
140 _elm_tooltip_reconfigure_job_start(tt);
141 TTDBG("RECURSIVE JOB\n");
146 tt->tt_win = elm_win_add(NULL, "tooltip", ELM_WIN_TOOLTIP);
147 elm_win_override_set(tt->tt_win, EINA_TRUE);
148 tt->tt_evas = evas_object_evas_get(tt->tt_win);
149 tt->tooltip = edje_object_add(tt->tt_evas);
150 evas_object_size_hint_weight_set(tt->tooltip, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
151 evas_object_size_hint_align_set(tt->tooltip, EVAS_HINT_FILL, EVAS_HINT_FILL);
152 elm_win_resize_object_add(tt->tt_win, tt->tooltip);
155 tt->tooltip = edje_object_add(tt->evas);
156 if (!tt->tooltip) return;
159 evas_object_layer_set(tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
161 evas_object_event_callback_add
162 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
163 evas_object_event_callback_add
164 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
166 if (tt->move_freeze == 0)
168 //No movement of tooltip upon mouse move if orientation set
169 if ((tt->orient <= ELM_TOOLTIP_ORIENT_NONE) || (tt->orient >= ELM_TOOLTIP_ORIENT_LAST))
171 evas_object_event_callback_add(tt->eventarea,
172 EVAS_CALLBACK_MOUSE_MOVE,
173 _elm_tooltip_obj_mouse_move_cb, tt);
176 tt->changed_style = EINA_TRUE;
177 _elm_tooltip_reconfigure_job_start(tt);
181 _elm_tooltip_content_del(Elm_Tooltip *tt)
183 if (!tt->content) return;
185 TTDBG("CONTENT DEL\n");
186 evas_object_event_callback_del_full
187 (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
188 _elm_tooltip_content_changed_hints_cb, tt);
189 evas_object_event_callback_del_full
190 (tt->content, EVAS_CALLBACK_DEL,
191 _elm_tooltip_content_del_cb, tt);
192 evas_object_hide(tt->content);
193 ELM_SAFE_FREE(tt->content, evas_object_del);
197 _elm_tooltip_hide(Elm_Tooltip *tt)
201 _elm_tooltip_show_timer_stop(tt);
202 _elm_tooltip_hide_anim_stop(tt);
203 _elm_tooltip_reconfigure_job_stop(tt);
205 if (!tt->tooltip) return;
206 if (tt->visible_lock) return;
208 _elm_tooltip_content_del(tt);
210 evas_object_event_callback_del_full
211 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
212 evas_object_event_callback_del_full
213 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
214 evas_object_event_callback_del_full
215 (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_move_cb, tt);
217 del = tt->tt_win ?: tt->tooltip;
222 evas_object_del(del);
226 _elm_tooltip_reconfigure_job(void *data)
228 Elm_Tooltip *tt = data;
229 tt->reconfigure_job = NULL;
230 _elm_tooltip_reconfigure(data);
234 _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt)
236 ELM_SAFE_FREE(tt->reconfigure_job, ecore_job_del);
240 _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt)
242 ecore_job_del(tt->reconfigure_job);
243 tt->reconfigure_job = ecore_job_add(_elm_tooltip_reconfigure_job, tt);
247 _elm_tooltip_hide_anim_cb(void *data)
249 Elm_Tooltip *tt = data;
250 tt->hide_timer = NULL;
251 _elm_tooltip_hide(tt);
256 _elm_tooltip_hide_anim_start(Elm_Tooltip *tt)
259 if (tt->hide_timer) return;
260 TTDBG("HIDE START\n");
261 /* hide slightly faster when in window mode to look less stupid */
262 if ((tt->hide_timeout > 0) && tt->tt_win) extra = 0.1;
263 edje_object_signal_emit(tt->tooltip, "elm,action,hide", "elm");
264 tt->hide_timer = ecore_timer_add
265 (tt->hide_timeout - extra, _elm_tooltip_hide_anim_cb, tt);
269 _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt)
271 if (!tt->hide_timer) return;
273 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
275 ELM_SAFE_FREE(tt->hide_timer, ecore_timer_del);
279 _elm_tooltip_reconfigure(Elm_Tooltip *tt)
281 Evas_Coord ox, oy, ow, oh, px = 0, py = 0, tx, ty, tw, th, cw = 0, ch = 0;
282 Evas_Coord eminw, eminh, ominw, ominh;
284 Eina_Bool inside_eventarea;
286 _elm_tooltip_reconfigure_job_stop(tt);
288 if (tt->hide_timer) return;
289 if (!tt->tooltip) return;
290 if (tt->changed_style)
292 const char *style = tt->style ? tt->style : "default";
294 if (!_elm_theme_object_set(tt->tt_win ? NULL : tt->owner, tt->tooltip,
295 "tooltip", "base", style))
297 ERR("Could not apply the theme to the tooltip! style=%s", style);
298 if (tt->tt_win) evas_object_del(tt->tt_win);
299 else evas_object_del(tt->tooltip);
313 tt->hide_timeout = 0.0;
315 str = edje_object_data_get(tt->tooltip, "transparent");
317 { /* FIXME: hardcoded here is bad */
318 if (str && (!strcmp(str, "enabled")))
320 evas_object_hide(tt->tt_win);
321 elm_win_alpha_set(tt->tt_win, EINA_TRUE);
325 evas_object_hide(tt->tt_win);
326 elm_win_alpha_set(tt->tt_win, EINA_FALSE);
330 str = edje_object_data_get(tt->tooltip, "pad_x");
331 if (str) tt->pad.x = atoi(str);
332 str = edje_object_data_get(tt->tooltip, "pad_y");
333 if (str) tt->pad.y = atoi(str);
335 str = edje_object_data_get(tt->tooltip, "pad_border_x");
336 if (str) tt->pad.bx = atoi(str);
337 str = edje_object_data_get(tt->tooltip, "pad_border_y");
338 if (str) tt->pad.by = atoi(str);
340 str = edje_object_data_get(tt->tooltip, "hide_timeout");
343 tt->hide_timeout = _elm_atof(str);
344 if (tt->hide_timeout < 0.0) tt->hide_timeout = 0.0;
347 evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
348 tt->changed_style = EINA_FALSE;
350 edje_object_part_swallow(tt->tooltip, "elm.swallow.content",
353 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
358 tt->content = tt->func((void *)tt->data, tt->owner, tt->tt_win ? : tt->owner);
361 WRN("could not create tooltip content!");
362 if (tt->tt_win) evas_object_del(tt->tt_win);
363 else evas_object_del(tt->tooltip);
370 evas_object_pass_events_set(tt->content, EINA_TRUE);
371 edje_object_part_swallow
372 (tt->tooltip, "elm.swallow.content", tt->content);
373 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
374 _elm_tooltip_content_changed_hints_cb, tt);
375 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_DEL,
376 _elm_tooltip_content_del_cb, tt);
378 /* tooltip has to use layer tooltip */
379 evas_object_layer_set(tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
381 TTDBG("*******RECALC\n");
382 evas_object_size_hint_min_get(tt->content, &ominw, &ominh);
383 edje_object_size_min_get(tt->tooltip, &eminw, &eminh);
385 if (eminw && (ominw < eminw)) ominw = eminw;
386 if (eminh && (ominh < eminh)) ominh = eminh;
388 if ((ominw < 1) || (ominh < 1))
390 evas_object_move(tt->tt_win ? : tt->tooltip, -9999, -9999);
391 evas_object_resize(tt->tt_win ? : tt->tooltip, 1, 1);
392 TTDBG("FAKE: tx=%d,ty=%d,tw=%d,th=%d\n", -9999, -9999, 1, 1);
393 evas_object_show(tt->tooltip);
394 if (tt->tt_win) evas_object_show(tt->tt_win);
395 _elm_tooltip_reconfigure_job_start(tt);
399 edje_object_size_min_restricted_calc(tt->tooltip, &tw, &th, ominw, ominh);
400 TTDBG("TTSIZE: tw=%d,th=%d,ominw=%d,ominh=%d\n", tw, th, ominw, ominh);
404 #ifdef HAVE_ELEMENTARY_X
405 Evas_Object *win = elm_widget_top_get(tt->owner);
406 Ecore_X_Window xwin = elm_win_xwindow_get(win);
408 ecore_x_window_size_get(ecore_x_window_root_get(xwin), &cw, &ch);
411 elm_win_screen_size_get(elm_widget_top_get(tt->owner), NULL, NULL, &cw, &ch);
414 evas_output_size_get(tt->tt_evas ?: tt->evas, &cw, &ch);
415 TTDBG("SCREEN: cw=%d,ch=%d\n", cw, ch);
417 evas_object_geometry_get(tt->eventarea, &ox, &oy, &ow, &oh);
418 TTDBG("EVENTAREA: ox=%d,oy=%d,ow=%d,oh=%d\n", ox, oy, ow, oh);
423 Evas_Object *win = elm_widget_top_get(tt->owner);
424 #ifdef HAVE_ELEMENTARY_X
425 Ecore_X_Window xwin = elm_win_xwindow_get(win);
427 ecore_x_pointer_xy_get(xwin, &px, &py);
429 elm_win_screen_position_get(win, &x, &y);
436 evas_pointer_canvas_xy_get(tt->evas, &px, &py);
437 TTDBG("POINTER: px=%d,py=%d\n", px, py);
438 inside_eventarea = ((px >= ox) && (py >= oy) &&
439 (px <= ox + ow) && (py <= oy + oh));
440 if (inside_eventarea)
442 /* try to position bottom right corner at pointer */
445 TTDBG("INIT (EVENTAREA)\n");
449 /* try centered on middle of eventarea */
450 tx = ox + (ow / 2) - (tw / 2);
451 if (0 > (th - oy - oh)) ty = oy + th;
453 TTDBG("INIT (INTERPRETED)\n");
455 TTDBG("ADJUST (POINTER): tx=%d,ty=%d\n", tx, ty);
456 if ((tx < 0) || (tx + tw > cw))
460 /* if we're offscreen to the left, try to flip over the Y axis */
461 if (abs((tx + 2 * tw) - cw) < abs(tx))
466 else if (tx + tw > cw)
468 int test_x = tx - tw;
470 /* if we're offscreen to the right, try to flip over the Y axis */
471 if ((test_x >= 0) || (tx + tw - cw > abs(test_x)))
477 else if ((tx > px) && (px > tw))
482 if ((ty < 0) || (ty + th > ch))
486 /* if we're offscreen to the top, try to flip over the X axis */
487 if (abs((ty + 2 * th) - ch) < abs(ty))
492 else if (ty + th > ch)
494 int test_y = ty - th;
496 /* if we're offscreen to the bottom, try to flip over the X axis */
497 if ((test_y >= 0) || (ty + th - ch > abs(test_y)))
503 else if ((ty > py) && (py > th))
508 TTDBG("ADJUST (FLIP): tx=%d,ty=%d\n", tx, ty);
509 if (inside_eventarea)
511 if ((tx == px) && ((tx + tw + tt->pad.x < cw) || (tx + tw > cw))) tx += tt->pad.x;
512 else if ((tx - tt->pad.x > 0) || (tx < 0)) tx -= tt->pad.x;
513 if ((ty == py) && ((ty + th + tt->pad.y < ch) || (ty + th > ch))) ty += tt->pad.y;
514 else if ((ty - tt->pad.y > 0) || (ty < 0)) ty -= tt->pad.y;
516 TTDBG("PAD: tx=%d,ty=%d\n", tx, ty);
517 if (tt->pad.bx * 2 + tw < cw)
519 if (tx < tt->pad.bx) tx = tt->pad.bx;
520 else if ((tx >= tw) && (tx + tt->pad.bx <= cw)) tx += tt->pad.bx;
521 else if (tx - tt->pad.bx >= 0) tx -= tt->pad.bx;
523 else if (tx < 0) tx -= tt->pad.bx;
524 else if (tx > cw) tx += tt->pad.bx;
525 if (tt->pad.by * 2 + th < ch)
527 if (ty < tt->pad.by) ty = tt->pad.by;
528 else if ((ty >= th) && (ty + tt->pad.by <= ch)) ty += tt->pad.by;
529 else if (ty - tt->pad.by >= 0) ty -= tt->pad.by;
531 else if (ty < 0) ty -= tt->pad.by;
532 else if (ty > ch) ty += tt->pad.by;
533 TTDBG("PAD (BORDER): tx=%d,ty=%d\n", tx, ty);
536 #define INSIDE(x, y, xx, yy, ww, hh) \
537 (((x) < ((xx) + (ww))) && ((y) < ((yy) + (hh))) && ((x) >= (xx)) && ((y) >= (yy)))
538 /* attempt to ensure no overlap with pointer */
539 if (INSIDE(px, py, tx, ty, tw, th))
545 if (!INSIDE(px, py, tx, ty + (py - ty) + ay, tw, th))
547 else if (!INSIDE(px, py, tx + (px - tx) + ax, ty, tw, th))
549 else if (!INSIDE(px, py, tx + (px - tx) + ax, ty + (py - ty) + ay, tw, th))
550 tx += px - tx + ax, ty += py - ty + ay;
554 if (((tx < 0) && (tw < cw)) || ((ty < 0) && (th < ch)))
556 TTDBG("POSITIONING FAILED! THIS IS A BUG SOMEWHERE!\n");
560 evas_object_move(tt->tt_win ? : tt->tooltip, tx, ty);
561 evas_object_resize(tt->tt_win ? : tt->tooltip, tw, th);
562 TTDBG("FINAL: tx=%d,ty=%d,tw=%d,th=%d\n", tx, ty, tw, th);
563 evas_object_show(tt->tooltip);
565 if (inside_eventarea)
567 rel_x = (px - tx) / (double)tw;
568 rel_y = (py - ty) / (double)th;
572 rel_x = (ox + (ow / 2) - tx) / (double)tw;
573 rel_y = (oy + (oh / 2) - ty) / (double)th;
576 #define FDIF(a, b) (fabs((a) - (b)) > 0.0001)
577 if ((FDIF(rel_x, tt->rel_pos.x)) || (FDIF(rel_y, tt->rel_pos.y)))
579 Edje_Message_Float_Set *msg;
581 msg = alloca(sizeof(Edje_Message_Float_Set) + sizeof(double));
583 //Orient calculations if orient set
586 case ELM_TOOLTIP_ORIENT_TOP_LEFT:
587 evas_object_move(tt->tooltip, ox - tw, oy - th);
591 case ELM_TOOLTIP_ORIENT_TOP:
592 evas_object_move(tt->tooltip, ox + ((ow - tw) / 2), oy - th);
596 case ELM_TOOLTIP_ORIENT_TOP_RIGHT:
597 evas_object_move(tt->tooltip, ox + ow, oy - th);
601 case ELM_TOOLTIP_ORIENT_LEFT:
602 evas_object_move(tt->tooltip, ox - tw, oy + ((oh - th) / 2));
606 case ELM_TOOLTIP_ORIENT_CENTER:
607 evas_object_move(tt->tooltip, ox + ((ow - tw) / 2), oy + ((oh - th) / 2));
611 case ELM_TOOLTIP_ORIENT_RIGHT:
612 evas_object_move(tt->tooltip, ox + ow, oy + ((oh - th) / 2));
616 case ELM_TOOLTIP_ORIENT_BOTTOM_LEFT:
617 evas_object_move(tt->tooltip, ox - tw, oy + oh);
621 case ELM_TOOLTIP_ORIENT_BOTTOM:
622 evas_object_move(tt->tooltip, ox + ((ow - tw) / 2), oy + oh);
626 case ELM_TOOLTIP_ORIENT_BOTTOM_RIGHT:
627 evas_object_move(tt->tooltip, ox + ow, oy + oh);
635 evas_object_show(tt->tooltip);
639 tt->rel_pos.x = rel_x;
640 tt->rel_pos.y = rel_y;
642 edje_object_message_send(tt->tooltip, EDJE_MESSAGE_FLOAT_SET, 1, msg);
645 if (tt->tt_win) evas_object_show(tt->tt_win);
649 _elm_tooltip_show_timer_stop(Elm_Tooltip *tt)
651 if (!tt->show_timer) return;
652 ELM_SAFE_FREE(tt->show_timer, ecore_timer_del);
656 _elm_tooltip_timer_show_cb(void *data)
658 Elm_Tooltip *tt = data;
659 tt->show_timer = NULL;
660 _elm_tooltip_show(tt);
661 return ECORE_CALLBACK_CANCEL;
665 _elm_tooltip_obj_mouse_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
667 Elm_Tooltip *tt = data;
669 _elm_tooltip_hide_anim_stop(tt);
671 if ((tt->show_timer) || (tt->tooltip)) return;
673 tt->show_timer = ecore_timer_add(_elm_config->tooltip_delay, _elm_tooltip_timer_show_cb, tt);
678 _elm_tooltip_obj_mouse_out_cb(Elm_Tooltip *tt, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Evas_Event_Mouse_Out *event EINA_UNUSED)
680 if (tt->visible_lock) return;
684 _elm_tooltip_show_timer_stop(tt);
687 _elm_tooltip_hide_anim_start(tt);
688 TTDBG("MOUSE OUT\n");
691 static void _elm_tooltip_obj_free_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
694 _elm_tooltip_unset(Elm_Tooltip *tt)
696 tt->visible_lock = EINA_FALSE;
697 _elm_tooltip_hide(tt);
698 _elm_tooltip_data_clean(tt);
702 evas_object_event_callback_del_full
703 (tt->eventarea, EVAS_CALLBACK_MOUSE_IN,
704 _elm_tooltip_obj_mouse_in_cb, tt);
705 evas_object_event_callback_del_full
706 (tt->eventarea, EVAS_CALLBACK_MOUSE_OUT,
707 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
708 evas_object_event_callback_del_full
709 (tt->eventarea, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
711 evas_object_data_del(tt->eventarea, _tooltip_key);
715 evas_object_event_callback_del_full
716 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
717 elm_widget_tooltip_del(tt->owner, tt);
720 eina_stringshare_del(tt->style);
725 _elm_tooltip_obj_free_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
727 Elm_Tooltip *tt = data;
728 if (tt->eventarea == obj) tt->eventarea = NULL;
729 if (tt->owner == obj) tt->owner = NULL;
730 _elm_tooltip_unset(tt);
734 _tooltip_label_style_set(Evas_Object *obj, Evas_Object *label)
736 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
738 const char *style = tt->style ? tt->style : "default";
740 sprintf(buf, "tooltip/%s", style);
741 if (!elm_object_style_set(label, buf))
743 WRN("Failed to set tooltip label style: %s, reverting to old style",
745 elm_object_style_set(label, "tooltip"); //XXX: remove it in EFL 2.0
750 _elm_tooltip_label_create(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object *tooltip)
752 Evas_Object *label = elm_label_add(tooltip);
755 _tooltip_label_style_set(obj, label);
756 elm_object_text_set(label, data);
761 _elm_tooltip_trans_label_create(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object *tooltip)
763 Evas_Object *label = elm_label_add(tooltip);
764 const char **text = data;
767 _tooltip_label_style_set(obj, label);
768 elm_object_domain_translatable_text_set(label, text[0], text[1]);
773 _elm_tooltip_label_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
775 eina_stringshare_del(data);
779 _elm_tooltip_trans_label_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
781 const char **text = data;
782 eina_stringshare_del(text[0]);
783 eina_stringshare_del(text[1]);
788 _elm_tooltip_data_clean(Elm_Tooltip *tt)
790 if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
792 _elm_tooltip_content_del(tt);
799 elm_object_tooltip_move_freeze_push(Evas_Object *obj)
801 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
807 elm_object_tooltip_move_freeze_pop(Evas_Object *obj)
809 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
812 if (tt->move_freeze < 0) tt->move_freeze = 0;
816 elm_object_tooltip_move_freeze_get(const Evas_Object *obj)
818 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, 0);
820 return tt->move_freeze;
824 elm_object_tooltip_orient_set(Evas_Object *obj, Elm_Tooltip_Orient orient)
826 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
828 if ((orient > ELM_TOOLTIP_ORIENT_NONE) && (orient < ELM_TOOLTIP_ORIENT_LAST))
831 tt->orient = ELM_TOOLTIP_ORIENT_NONE;
834 EAPI Elm_Tooltip_Orient
835 elm_object_tooltip_orient_get(const Evas_Object *obj)
837 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ELM_TOOLTIP_ORIENT_NONE);
839 Elm_Tooltip_Orient orient = ELM_TOOLTIP_ORIENT_NONE;
846 * Notify tooltip should recalculate its theme.
850 elm_tooltip_theme(Elm_Tooltip *tt)
852 if (!tt->tooltip) return;
853 tt->changed_style = EINA_TRUE;
854 _elm_tooltip_reconfigure_job_start(tt);
858 * Set the content to be shown in the tooltip object for specific event area.
860 * Setup the tooltip to object. The object @a eventarea can have only
861 * one tooltip, so any previous tooltip data is removed. @p func(with
862 * @p data) will be called every time that need show the tooltip and
863 * it should return a valid Evas_Object. This object is then managed
864 * fully by tooltip system and is deleted when the tooltip is gone.
866 * This is an internal function that is used by objects with sub-items
867 * that want to provide different tooltips for each of them. The @a
868 * owner object should be an elm_widget and will be used to track
869 * theme changes and to feed @a func and @a del_cb. The @a eventarea
870 * may be any object and is the one that should be used later on with
871 * elm_object_tooltip apis, such as elm_object_tooltip_hide(),
872 * elm_object_tooltip_show() or elm_object_tooltip_unset().
874 * @param eventarea the object being attached a tooltip.
875 * @param owner the elm_widget that owns this object, will be used to
876 * track theme changes and to be used in @a func or @a del_cb.
877 * @param func the function used to create the tooltip contents. The
878 * @a Evas_Object parameters will receive @a owner as value.
879 * @param data what to provide to @a func as callback data/context.
880 * @param del_cb called when data is not needed anymore, either when
881 * another callback replaces @p func, the tooltip is unset with
882 * elm_object_tooltip_unset() or the owner object @a obj
883 * dies. This callback receives as the first parameter the
884 * given @a data, and @c event_info is NULL.
890 elm_object_sub_tooltip_content_cb_set(Evas_Object *eventarea, Evas_Object *owner, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
892 Elm_Tooltip *tt = NULL;
893 Eina_Bool just_created;
895 EINA_SAFETY_ON_NULL_GOTO(owner, error);
896 EINA_SAFETY_ON_NULL_GOTO(eventarea, error);
900 elm_object_tooltip_unset(eventarea);
904 tt = evas_object_data_get(eventarea, _tooltip_key);
907 if (tt->owner != owner)
909 if (tt->owner != eventarea)
910 evas_object_event_callback_del_full
911 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
913 elm_widget_tooltip_del(tt->owner, tt);
915 if (owner != eventarea)
916 evas_object_event_callback_add
917 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
919 elm_widget_tooltip_add(tt->owner, tt);
922 if ((tt->func == func) && (tt->data == data) &&
923 (tt->del_cb == del_cb))
925 _elm_tooltip_data_clean(tt);
926 just_created = EINA_FALSE;
930 tt = ELM_NEW(Elm_Tooltip);
934 tt->eventarea = eventarea;
935 tt->evas = evas_object_evas_get(eventarea);
936 evas_object_data_set(eventarea, _tooltip_key, tt);
938 just_created = EINA_TRUE;
940 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
941 _elm_tooltip_obj_mouse_in_cb, tt);
942 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
943 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
944 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_FREE,
945 _elm_tooltip_obj_free_cb, tt);
947 if (owner != eventarea)
948 evas_object_event_callback_add
949 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
951 elm_widget_tooltip_add(tt->owner, tt);
958 if (!just_created) _elm_tooltip_reconfigure_job_start(tt);
962 if (del_cb) del_cb((void *)data, owner, NULL);
966 elm_object_tooltip_show(Evas_Object *obj)
968 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
969 tt->visible_lock = EINA_TRUE;
970 _elm_tooltip_show(tt);
974 elm_object_tooltip_hide(Evas_Object *obj)
976 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
977 tt->visible_lock = EINA_FALSE;
978 _elm_tooltip_hide_anim_start(tt);
982 elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
984 EINA_SAFETY_ON_NULL_RETURN(obj);
985 EINA_SAFETY_ON_NULL_RETURN(text);
987 text = eina_stringshare_add(text);
988 elm_object_tooltip_content_cb_set
989 (obj, _elm_tooltip_label_create, text, _elm_tooltip_label_del_cb);
993 elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text)
996 EINA_SAFETY_ON_NULL_RETURN(obj);
997 EINA_SAFETY_ON_NULL_RETURN(text);
999 data = malloc(2 * sizeof(char *));
1001 data[0] = eina_stringshare_add(domain);
1002 data[1] = eina_stringshare_add(text);
1003 elm_object_tooltip_content_cb_set
1004 (obj, _elm_tooltip_trans_label_create, data,
1005 _elm_tooltip_trans_label_del_cb);
1009 elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
1011 elm_object_sub_tooltip_content_cb_set(obj, obj, func, data, del_cb);
1015 elm_object_tooltip_unset(Evas_Object *obj)
1017 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
1018 _elm_tooltip_unset(tt);
1022 elm_object_tooltip_style_set(Evas_Object *obj, const char *style)
1024 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
1025 if (!eina_stringshare_replace(&tt->style, style)) return;
1026 elm_tooltip_theme(tt);
1030 elm_object_tooltip_style_get(const Evas_Object *obj)
1032 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, NULL);
1033 return tt->style ? tt->style : "default";
1037 elm_object_tooltip_window_mode_set(Evas_Object *obj, Eina_Bool disable)
1039 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
1040 return tt->free_size = disable;
1044 elm_object_tooltip_window_mode_get(const Evas_Object *obj)
1046 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
1047 return tt->free_size;