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