82fd15c8ae92e8c23c67496381fe102163f5f4c6
[framework/uifw/elementary.git] / src / lib / els_tooltip.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Tooltips Tooltips
6  *
7  * The Tooltip is an (internal, for now) smart object used to show a
8  * content in a frame on mouse hover of objects(or widgets), with
9  * tips/information about them.
10  */
11
12 static const char _tooltip_key[] = "_elm_tooltip";
13
14 #define ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ...)         \
15   Elm_Tooltip *tt;                                      \
16   do                                                    \
17     {                                                   \
18        if (!(obj))                                      \
19          {                                              \
20             CRITICAL("Null pointer: " #obj);            \
21             return __VA_ARGS__;                         \
22          }                                              \
23        tt = evas_object_data_get((obj), _tooltip_key);  \
24        if (!tt)                                         \
25          {                                              \
26             ERR("Object does not have tooltip: " #obj); \
27             return __VA_ARGS__;                         \
28          }                                              \
29     }                                                   \
30   while (0)
31
32 struct _Elm_Tooltip
33 {
34    Elm_Tooltip_Content_Cb   func;
35    Evas_Smart_Cb            del_cb;
36    const void              *data;
37    const char              *style;
38    Evas                    *evas;
39    Evas_Object             *eventarea, *owner;
40    Evas_Object             *tooltip, *content;
41    Ecore_Timer             *show_timer;
42    Ecore_Timer             *hide_timer;
43    Ecore_Job               *reconfigure_job;
44    struct {
45       Evas_Coord            x, y, bx, by;
46    } pad;
47    struct {
48       double                x, y;
49    } rel_pos;
50    double                   hide_timeout; /* from theme */
51    Eina_Bool                visible_lock:1;
52    Eina_Bool                changed_style:1;
53 };
54
55 static void _elm_tooltip_reconfigure(Elm_Tooltip *tt);
56 static void _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt);
57 static void _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt);
58 static void _elm_tooltip_hide_anim_start(Elm_Tooltip *tt);
59 static void _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt);
60 static void _elm_tooltip_show_timer_stop(Elm_Tooltip *tt);
61 static void _elm_tooltip_hide(Elm_Tooltip *tt);
62 static void _elm_tooltip_data_clean(Elm_Tooltip *tt);
63
64
65 static void
66 _elm_tooltip_content_changed_hints_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
67 {
68    _elm_tooltip_reconfigure_job_start(data);
69 }
70
71 static void
72 _elm_tooltip_content_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
73 {
74    Elm_Tooltip *tt = data;
75    tt->content = NULL;
76    tt->visible_lock = EINA_FALSE;
77    _elm_tooltip_hide(tt);
78 }
79
80 static void
81 _elm_tooltip_obj_move_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
82 {
83    Elm_Tooltip *tt = data;
84    _elm_tooltip_reconfigure_job_start(tt);
85 }
86
87 static void
88 _elm_tooltip_obj_resize_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
89 {
90    Elm_Tooltip *tt = data;
91    _elm_tooltip_reconfigure_job_start(tt);
92 }
93
94 static void
95 _elm_tooltip_obj_mouse_move_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
96 {
97    Elm_Tooltip *tt = data;
98    _elm_tooltip_reconfigure_job_start(tt);
99 }
100
101 static void
102 _elm_tooltip_show(Elm_Tooltip *tt)
103 {
104    _elm_tooltip_show_timer_stop(tt);
105    _elm_tooltip_hide_anim_stop(tt);
106
107    if (tt->tooltip)
108      {
109         _elm_tooltip_reconfigure_job_start(tt);
110         return;
111      }
112    tt->tooltip = edje_object_add(tt->evas);
113    if (!tt->tooltip) return;
114
115    evas_object_layer_set(tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
116
117    evas_object_event_callback_add
118      (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
119    evas_object_event_callback_add
120      (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
121    evas_object_event_callback_add
122      (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, _elm_tooltip_obj_mouse_move_cb, tt);
123
124    evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
125    tt->changed_style = EINA_TRUE;
126    _elm_tooltip_reconfigure_job_start(tt);
127 }
128
129 static void
130 _elm_tooltip_content_del(Elm_Tooltip *tt)
131 {
132    if (!tt->content) return;
133
134    evas_object_event_callback_del_full
135      (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
136       _elm_tooltip_content_changed_hints_cb, tt);
137    evas_object_event_callback_del_full
138      (tt->content, EVAS_CALLBACK_DEL,
139       _elm_tooltip_content_del_cb, tt);
140    evas_object_hide(tt->content);
141    evas_object_del(tt->content);
142    tt->content = NULL;
143 }
144
145
146 static void
147 _elm_tooltip_hide(Elm_Tooltip *tt)
148 {
149    _elm_tooltip_show_timer_stop(tt);
150    _elm_tooltip_hide_anim_stop(tt);
151    _elm_tooltip_reconfigure_job_stop(tt);
152
153    if (!tt->tooltip) return;
154    if (tt->visible_lock) return;
155
156    _elm_tooltip_content_del(tt);
157
158    evas_object_event_callback_del_full
159      (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
160    evas_object_event_callback_del_full
161      (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
162    evas_object_event_callback_del_full
163      (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, _elm_tooltip_obj_mouse_move_cb, tt);
164
165    evas_object_del(tt->tooltip);
166    tt->tooltip = NULL;
167 }
168
169 static void
170 _elm_tooltip_reconfigure_job(void *data)
171 {
172    Elm_Tooltip *tt = data;
173    tt->reconfigure_job = NULL;
174    _elm_tooltip_reconfigure(data);
175 }
176
177 static void
178 _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt)
179 {
180    if (!tt->reconfigure_job) return;
181    ecore_job_del(tt->reconfigure_job);
182    tt->reconfigure_job = NULL;
183 }
184
185 static void
186 _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt)
187 {
188    if (tt->reconfigure_job) ecore_job_del(tt->reconfigure_job);
189    tt->reconfigure_job = ecore_job_add
190      (_elm_tooltip_reconfigure_job, tt);
191 }
192
193 static Eina_Bool
194 _elm_tooltip_hide_anim_cb(void *data)
195 {
196    Elm_Tooltip *tt = data;
197    tt->hide_timer = NULL;
198    _elm_tooltip_hide(tt);
199    return EINA_FALSE;
200 }
201
202 static void
203 _elm_tooltip_hide_anim_start(Elm_Tooltip *tt)
204 {
205    if (tt->hide_timer) return;
206    edje_object_signal_emit(tt->tooltip, "elm,action,hide", "elm");
207    tt->hide_timer = ecore_timer_add
208      (tt->hide_timeout, _elm_tooltip_hide_anim_cb, tt);
209 }
210
211 static void
212 _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt)
213 {
214    if (!tt->hide_timer) return;
215    if (tt->tooltip)
216      edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
217    ecore_timer_del(tt->hide_timer);
218    tt->hide_timer = NULL;
219 }
220
221 static void
222 _elm_tooltip_reconfigure(Elm_Tooltip *tt)
223 {
224    Evas_Coord ox, oy, ow, oh, px, py, tx, ty, tw, th, cw, ch;
225    Evas_Coord eminw, eminh, ominw, ominh;
226    double rel_x, rel_y;
227    Eina_Bool inside_eventarea;
228
229    _elm_tooltip_reconfigure_job_stop(tt);
230
231    if (tt->hide_timer) return;
232    if (!tt->tooltip) return;
233    if (tt->changed_style)
234      {
235         const char *style = tt->style ? tt->style : "default";
236         const char *str;
237         if (!_elm_theme_object_set
238             (tt->owner, tt->tooltip, "tooltip", "base", style))
239           {
240              ERR("Could not apply the theme to the tooltip! style=%s", style);
241              evas_object_del(tt->tooltip);
242              tt->tooltip = NULL;
243              return;
244           }
245
246         tt->rel_pos.x = 0;
247         tt->rel_pos.y = 0;
248
249         tt->pad.x = 0;
250         tt->pad.y = 0;
251         tt->pad.bx = 0;
252         tt->pad.by = 0;
253         tt->hide_timeout = 0.0;
254
255         str = edje_object_data_get(tt->tooltip, "pad_x");
256         if (str) tt->pad.x = atoi(str);
257         str = edje_object_data_get(tt->tooltip, "pad_y");
258         if (str) tt->pad.y = atoi(str);
259
260         str = edje_object_data_get(tt->tooltip, "pad_border_x");
261         if (str) tt->pad.bx = atoi(str);
262         str = edje_object_data_get(tt->tooltip, "pad_border_y");
263         if (str) tt->pad.by = atoi(str);
264
265         str = edje_object_data_get(tt->tooltip, "hide_timeout");
266         if (str)
267           {
268              tt->hide_timeout = atof(str);
269              if (tt->hide_timeout < 0.0) tt->hide_timeout = 0.0;
270           }
271
272         evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
273         tt->changed_style = EINA_FALSE;
274         if (tt->tooltip)
275           edje_object_part_swallow
276             (tt->tooltip, "elm.swallow.content", tt->content);
277
278         edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
279      }
280
281    if (!tt->content)
282      {
283         tt->content = tt->func((void *)tt->data, tt->owner);
284         if (!tt->content)
285           {
286              WRN("could not create tooltip content!");
287              evas_object_del(tt->tooltip);
288              tt->tooltip = NULL;
289              return;
290           }
291         evas_object_layer_set(tt->content, ELM_OBJECT_LAYER_TOOLTIP);
292         evas_object_pass_events_set(tt->content, EINA_TRUE);
293         edje_object_part_swallow
294           (tt->tooltip, "elm.swallow.content", tt->content);
295         evas_object_event_callback_add
296           (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
297            _elm_tooltip_content_changed_hints_cb, tt);
298         evas_object_event_callback_add
299           (tt->content, EVAS_CALLBACK_DEL,
300            _elm_tooltip_content_del_cb, tt);
301
302      }
303
304    evas_object_size_hint_min_get(tt->content, &ominw, &ominh);
305    edje_object_size_min_get(tt->tooltip, &eminw, &eminh);
306
307    if (ominw < eminw) ominw = eminw;
308    if (ominh < eminh) ominh = eminh;
309
310    if (ominw < 1) ominw = 10; /* at least it is noticeable */
311    if (ominh < 1) ominh = 10; /* at least it is noticeable */
312
313    edje_object_size_min_restricted_calc
314      (tt->tooltip, &tw, &th, ominw, ominh);
315
316    evas_output_size_get(tt->evas, &cw, &ch);
317    evas_pointer_canvas_xy_get(tt->evas, &px, &py);
318
319    evas_object_geometry_get(tt->eventarea, &ox, &oy, &ow, &oh);
320
321    inside_eventarea = ((px >= ox) && (py >= oy) &&
322                        (px <= ox + ow) && (py <= oy + oh));
323    if (inside_eventarea)
324      {
325         tx = px;
326         ty = py;
327
328         if (tx + tw + tt->pad.x < cw) tx += tt->pad.x;
329         if (ty + th + tt->pad.y < ch) ty += tt->pad.y;
330      }
331    else
332      {
333         tx = ox + (ow / 2) - (tw / 2);
334         if (ch < (th + oy + oh)) ty = oy - th;
335         else ty = oy + oh;
336      }
337
338    if (tt->pad.bx * 2 + tw < cw)
339      {
340         if (tx < tt->pad.bx) tx = tt->pad.bx;
341         else if (tx + tw >= cw - tt->pad.bx) tx = cw - tw - tt->pad.bx;
342      }
343
344    if (tt->pad.by * 2 + th < ch)
345      {
346         if (ty < tt->pad.by) ty = tt->pad.by;
347         else if (ty + th >= ch - tt->pad.by) ty = ch - th - tt->pad.by;
348      }
349
350    evas_object_move(tt->tooltip, tx, ty);
351    evas_object_resize(tt->tooltip, tw, th);
352    evas_object_show(tt->tooltip);
353
354    if (inside_eventarea)
355      {
356         rel_x = (px - tx) / (double)tw;
357         rel_y = (py - ty) / (double)th;
358      }
359    else
360      {
361         rel_x = (ox + (ow / 2) - tx) / (double)tw;
362         rel_y = (oy + (oh / 2) - ty) / (double)th;
363      }
364
365 #define FDIF(a, b) (fabs((a) - (b)) > 0.0001)
366    if ((FDIF(rel_x, tt->rel_pos.x)) || (FDIF(rel_y, tt->rel_pos.y)))
367      {
368         Edje_Message_Float_Set *msg;
369
370         msg = alloca(sizeof(Edje_Message_Float_Set) + sizeof(double));
371         msg->count = 2;
372         msg->val[0] = rel_x;
373         msg->val[1] = rel_y;
374         tt->rel_pos.x = rel_x;
375         tt->rel_pos.y = rel_y;
376
377         edje_object_message_send(tt->tooltip, EDJE_MESSAGE_FLOAT_SET, 1, msg);
378      }
379 #undef FDIF
380 }
381
382 static void
383 _elm_tooltip_show_timer_stop(Elm_Tooltip *tt)
384 {
385    if (!tt->show_timer) return;
386    ecore_timer_del(tt->show_timer);
387    tt->show_timer = NULL;
388 }
389
390 static Eina_Bool
391 _elm_tooltip_timer_show_cb(void *data)
392 {
393    Elm_Tooltip *tt = data;
394    tt->show_timer = NULL;
395    _elm_tooltip_show(tt);
396    return ECORE_CALLBACK_CANCEL;
397 }
398
399 static void
400 _elm_tooltip_obj_mouse_in_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
401 {
402    Elm_Tooltip *tt = data;
403
404    _elm_tooltip_hide_anim_stop(tt);
405
406    if ((tt->show_timer) || (tt->tooltip)) return;
407
408    tt->show_timer = ecore_timer_add
409      (_elm_config->tooltip_delay, _elm_tooltip_timer_show_cb, tt);
410 }
411
412 static void
413 _elm_tooltip_obj_mouse_out_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
414 {
415    Elm_Tooltip *tt = data;
416
417    if (tt->visible_lock) return;
418
419    if (!tt->tooltip)
420      {
421         _elm_tooltip_show_timer_stop(tt);
422         return;
423      }
424
425    _elm_tooltip_hide_anim_start(tt);
426 }
427
428 static void _elm_tooltip_obj_free_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj, void *event_info  __UNUSED__);
429
430 static void
431 _elm_tooltip_unset(Elm_Tooltip *tt)
432 {
433    tt->visible_lock = EINA_FALSE;
434    _elm_tooltip_hide(tt);
435    _elm_tooltip_data_clean(tt);
436
437    if (tt->eventarea)
438      {
439         evas_object_event_callback_del_full
440           (tt->eventarea, EVAS_CALLBACK_MOUSE_IN,
441            _elm_tooltip_obj_mouse_in_cb, tt);
442         evas_object_event_callback_del_full
443           (tt->eventarea, EVAS_CALLBACK_MOUSE_OUT,
444            _elm_tooltip_obj_mouse_out_cb, tt);
445         evas_object_event_callback_del_full
446           (tt->eventarea, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
447
448         evas_object_data_del(tt->eventarea, _tooltip_key);
449      }
450    if (tt->owner)
451      {
452         evas_object_event_callback_del_full
453           (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
454         elm_widget_tooltip_del(tt->owner, tt);
455      }
456
457    eina_stringshare_del(tt->style);
458    free(tt);
459 }
460
461 static void
462 _elm_tooltip_obj_free_cb(void *data, Evas *e  __UNUSED__, Evas_Object *obj, void *event_info  __UNUSED__)
463 {
464    Elm_Tooltip *tt = data;
465    if (tt->eventarea == obj) tt->eventarea = NULL;
466    if (tt->owner == obj) tt->owner = NULL;
467    _elm_tooltip_unset(tt);
468 }
469
470 static Evas_Object *
471 _elm_tooltip_label_create(void *data, Evas_Object *obj)
472 {
473    Evas_Object *label = elm_label_add(obj);
474    if (!label)
475      return NULL;
476    elm_object_style_set(label, "tooltip");
477    elm_object_text_set(label, data);
478    return label;
479 }
480
481 static void
482 _elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
483 {
484    eina_stringshare_del(data);
485 }
486
487 static void
488 _elm_tooltip_data_clean(Elm_Tooltip *tt)
489 {
490    if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
491
492    _elm_tooltip_content_del(tt);
493
494    tt->data = NULL;
495    tt->del_cb = NULL;
496 }
497
498 /**
499  * Notify tooltip should recalculate its theme.
500  * @internal
501  */
502 void
503 elm_tooltip_theme(Elm_Tooltip *tt)
504 {
505    if (!tt->tooltip) return;
506    tt->changed_style = EINA_TRUE;
507    _elm_tooltip_reconfigure_job_start(tt);
508 }
509
510
511 /**
512  * Set the content to be shown in the tooltip object for specific event area.
513  *
514  * Setup the tooltip to object. The object @a eventarea can have only
515  * one tooltip, so any previous tooltip data is removed. @p func(with
516  * @p data) will be called every time that need show the tooltip and
517  * it should return a valid Evas_Object. This object is then managed
518  * fully by tooltip system and is deleted when the tooltip is gone.
519  *
520  * This is an internal function that is used by objects with sub-items
521  * that want to provide different tooltips for each of them. The @a
522  * owner object should be an elm_widget and will be used to track
523  * theme changes and to feed @a func and @a del_cb. The @a eventarea
524  * may be any object and is the one that should be used later on with
525  * elm_object_tooltip apis, such as elm_object_tooltip_hide(),
526  * elm_object_tooltip_show() or elm_object_tooltip_unset().
527  *
528  * @param eventarea the object being attached a tooltip.
529  * @param owner the elm_widget that owns this object, will be used to
530  *        track theme changes and to be used in @a func or @a del_cb.
531  * @param func the function used to create the tooltip contents. The
532  *        @a Evas_Object parameters will receive @a owner as value.
533  * @param data what to provide to @a func as callback data/context.
534  * @param del_cb called when data is not needed anymore, either when
535  *        another callback replaces @func, the tooltip is unset with
536  *        elm_object_tooltip_unset() or the owner object @a obj
537  *        dies. This callback receives as the first parameter the
538  *        given @a data, and @c event_info is NULL.
539  *
540  * @internal
541  * @ingroup Tooltips
542  */
543 void
544 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)
545 {
546    Elm_Tooltip *tt = NULL;
547    Eina_Bool just_created;
548
549    EINA_SAFETY_ON_NULL_GOTO(owner, error);
550    EINA_SAFETY_ON_NULL_GOTO(eventarea, error);
551
552    if (!func)
553      {
554         elm_object_tooltip_unset(eventarea);
555         return;
556      }
557
558    tt = evas_object_data_get(eventarea, _tooltip_key);
559    if (tt)
560      {
561         if (tt->owner != owner)
562           {
563              if (tt->owner != eventarea)
564                evas_object_event_callback_del_full
565                  (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
566
567              elm_widget_tooltip_del(tt->owner, tt);
568
569              if (owner != eventarea)
570                evas_object_event_callback_add
571                  (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
572
573              elm_widget_tooltip_add(tt->owner, tt);
574           }
575
576         if ((tt->func == func) && (tt->data == data) &&
577             (tt->del_cb == del_cb))
578           return;
579         _elm_tooltip_data_clean(tt);
580         just_created = EINA_FALSE;
581      }
582    else
583      {
584         tt = ELM_NEW(Elm_Tooltip);
585         if (!tt) goto error;
586
587         tt->owner = owner;
588         tt->eventarea = eventarea;
589         tt->evas = evas_object_evas_get(eventarea);
590         evas_object_data_set(eventarea, _tooltip_key, tt);
591
592         just_created = EINA_TRUE;
593
594         evas_object_event_callback_add
595           (eventarea, EVAS_CALLBACK_MOUSE_IN,
596            _elm_tooltip_obj_mouse_in_cb, tt);
597         evas_object_event_callback_add
598           (eventarea, EVAS_CALLBACK_MOUSE_OUT,
599            _elm_tooltip_obj_mouse_out_cb, tt);
600         evas_object_event_callback_add
601           (eventarea, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
602
603         if (owner != eventarea)
604           evas_object_event_callback_add
605             (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
606
607         elm_widget_tooltip_add(tt->owner, tt);
608      }
609
610    tt->func = func;
611    tt->data = data;
612    tt->del_cb = del_cb;
613
614    if (!just_created) _elm_tooltip_reconfigure_job_start(tt);
615    return;
616
617  error:
618    if (del_cb) del_cb((void *)data, owner, NULL);
619 }
620
621 /**
622  * Force show tooltip of object
623  *
624  * @param obj Target object
625  *
626  * Force show the tooltip and disable hide on mouse_out.
627  * If another content is set as tooltip, the visible tooltip will hididen and
628  * showed again with new content.
629  * This can force show more than one tooltip at a time.
630  *
631  * @ingroup Tooltips
632  */
633 EAPI void
634 elm_object_tooltip_show(Evas_Object *obj)
635 {
636    ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
637    tt->visible_lock = EINA_TRUE;
638    _elm_tooltip_show(tt);
639 }
640
641 /**
642  * Force hide tooltip of object
643  *
644  * @param obj Target object
645  *
646  * Force hide the tooltip and (re)enable future mouse interations.
647  *
648  * @ingroup Tooltips
649  */
650 EAPI void
651 elm_object_tooltip_hide(Evas_Object *obj)
652 {
653    ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
654    tt->visible_lock = EINA_FALSE;
655    _elm_tooltip_hide_anim_start(tt);
656 }
657
658 /**
659  * Set the text to be shown in the tooltip object
660  *
661  * @param obj Target object
662  * @param text The text to set in the content
663  *
664  * Setup the text as tooltip to object. The object can have only one tooltip,
665  * so any previous tooltip data is removed.
666  * This method call internaly the elm_tooltip_content_cb_set().
667  *
668  * @ingroup Tooltips
669  */
670 EAPI void
671 elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
672 {
673    EINA_SAFETY_ON_NULL_RETURN(obj);
674    EINA_SAFETY_ON_NULL_RETURN(text);
675
676    text = eina_stringshare_add(text);
677    elm_object_tooltip_content_cb_set
678      (obj, _elm_tooltip_label_create, text, _elm_tooltip_label_del_cb);
679 }
680
681 /**
682  * Set the content to be shown in the tooltip object
683  *
684  * Setup the tooltip to object. The object can have only one tooltip,
685  * so any previous tooltip data is removed. @p func(with @p data) will
686  * be called every time that need show the tooltip and it should
687  * return a valid Evas_Object. This object is then managed fully by
688  * tooltip system and is deleted when the tooltip is gone.
689  *
690  * @param obj the object being attached a tooltip.
691  * @param func the function used to create the tooltip contents.
692  * @param data what to provide to @a func as callback data/context.
693  * @param del_cb called when data is not needed anymore, either when
694  *        another callback replaces @func, the tooltip is unset with
695  *        elm_object_tooltip_unset() or the owner object @a obj
696  *        dies. This callback receives as the first parameter the
697  *        given @a data, and @c event_info is NULL.
698  *
699  * @ingroup Tooltips
700  */
701 EAPI void
702 elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
703 {
704    elm_object_sub_tooltip_content_cb_set(obj, obj, func, data, del_cb);
705 }
706
707 /**
708  * Unset tooltip from object
709  *
710  * @param obj Target object
711  *
712  * Remove tooltip from object. The callback provided as del_cb to
713  * elm_object_tooltip_content_cb_set() will be called to notify it is
714  * not used anymore.
715  *
716  * @see elm_object_tooltip_content_cb_set()
717  *
718  * @ingroup Tooltips
719  */
720 EAPI void
721 elm_object_tooltip_unset(Evas_Object *obj)
722 {
723    ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
724    _elm_tooltip_unset(tt);
725 }
726
727 /**
728  * Sets a different style for this object tooltip.
729  *
730  * @note before you set a style you should define a tooltip with
731  *       elm_object_tooltip_content_cb_set() or
732  *       elm_object_tooltip_text_set().
733  *
734  * @param obj an object with tooltip already set.
735  * @param style the theme style to use (default, transparent, ...)
736  */
737 EAPI void
738 elm_object_tooltip_style_set(Evas_Object *obj, const char *style)
739 {
740    ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
741    if (!eina_stringshare_replace(&tt->style, style)) return;
742    elm_tooltip_theme(tt);
743 }
744
745 /**
746  * Get the style for this object tooltip.
747  *
748  * @param obj an object with tooltip already set.
749  * @return style the theme style in use, defaults to "default". If the
750  *         object does not have a tooltip set, then NULL is returned.
751  */
752 EAPI const char *
753 elm_object_tooltip_style_get(const Evas_Object *obj)
754 {
755    ELM_TOOLTIP_GET_OR_RETURN(tt, obj, NULL);
756    return tt->style ? tt->style : "default";
757 }
758
759 /**
760  * Get the configured tooltip delay
761  *
762  * This gets the globally configured tooltip delay in seconds
763  *
764  * @return The tooltip delay
765  * @ingroup Tooltips
766  */
767 EAPI double
768 elm_tooltip_delay_get(void)
769 {
770    return _elm_config->tooltip_delay;
771 }
772
773 /**
774  * Set the configured tooltip delay
775  *
776  * This sets the globally configured delay to tooltip
777  *
778  * @param delay The delay to show the tooltip
779  * @return EINA_TRUE if value is valid and setted
780  * @ingroup Tooltips
781  */
782 EAPI Eina_Bool
783 elm_tooltip_delay_set(double delay)
784 {
785    if (delay < 0.0) return EINA_FALSE;
786    _elm_config->tooltip_delay = delay;
787    return EINA_TRUE;
788 }