Merge "[ctxpopup] apply dragable area"
[framework/uifw/elementary.git] / src / lib / elm_button.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Button Button
6  * @ingroup Elementary
7  *
8  * This is a push-button. Press it and run some function. It can contain
9  * a simple label and icon object.
10  *
11  * Signals that you can add callbacks for are:
12  *
13  * "clicked" - the user clicked the button
14  * "repeated" - the user pressed the button without releasing it
15  * "unpressed" - when the button is unpressed (released)
16  */
17
18 typedef struct _Widget_Data Widget_Data;
19
20 enum
21 {
22    DEFAULT = 0,
23    HIGHLIGHTED,
24    FOCUSED,
25    DISABLED,
26 };
27
28 struct _Widget_Data
29 {
30    Evas_Object *btn, *icon;
31    const char *label;
32    Eina_Bool autorepeat;
33    Eina_Bool repeating;
34    double ar_threshold;
35    double ar_interval;
36    Ecore_Timer *timer;
37    const char *statelabel[4];
38    int statetype[4];
39 };
40
41 static const char *widtype = NULL;
42 static void _del_hook(Evas_Object *obj);
43 static void _theme_hook(Evas_Object *obj);
44 static void _disable_hook(Evas_Object *obj);
45 static void _sizing_eval(Evas_Object *obj);
46 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
47 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
48 static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
49 static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source);
50 static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source);
51 static void _on_focus_hook(void *data, Evas_Object *obj);
52 static void _activate(Evas_Object *obj);
53 static void _activate_hook(Evas_Object *obj);
54 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
55                              Evas_Callback_Type type, void *event_info);
56
57 static void _set_label(Evas_Object *obj, const char *label);
58 static void _signal_default_text_set(void *data, Evas_Object *obj, const char *emission, const char *source);
59
60 static const char SIG_CLICKED[] = "clicked";
61 static const char SIG_REPEATED[] = "repeated";
62 static const char SIG_UNPRESSED[] = "unpressed";
63 static const Evas_Smart_Cb_Description _signals[] = {
64        {SIG_CLICKED, ""},
65        {SIG_REPEATED, ""},
66        {SIG_UNPRESSED, ""},
67        {NULL, NULL}
68 };
69
70 static Eina_Bool
71 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
72 {
73    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
74    Evas_Event_Key_Down *ev = event_info;
75    Widget_Data *wd = elm_widget_data_get(obj);
76    if (!wd) return EINA_FALSE;
77    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
78    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
79    if ((strcmp(ev->keyname, "Return")) &&
80        (strcmp(ev->keyname, "KP_Enter")) &&
81        (strcmp(ev->keyname, "space")))
82      return EINA_FALSE;
83    _activate(obj);
84    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
85    edje_object_signal_emit(wd->btn, "elm,anim,activate", "elm");
86    return EINA_TRUE;
87 }
88
89 static void
90 _del_hook(Evas_Object *obj)
91 {
92    Widget_Data *wd = elm_widget_data_get(obj);
93    if (!wd) return;
94    if (wd->label) eina_stringshare_del(wd->label);
95    if (wd->statelabel[DEFAULT]) eina_stringshare_del(wd->statelabel[DEFAULT]);
96    if (wd->statelabel[HIGHLIGHTED]) eina_stringshare_del(wd->statelabel[HIGHLIGHTED]);
97    if (wd->statelabel[FOCUSED]) eina_stringshare_del(wd->statelabel[FOCUSED]);
98    if (wd->statelabel[DISABLED]) eina_stringshare_del(wd->statelabel[DISABLED]);
99    free(wd);
100 }
101
102 static void
103 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
104 {
105    Widget_Data *wd = elm_widget_data_get(obj);
106    if (!wd) return;
107    if (elm_widget_focus_get(obj))
108      {
109         if (wd->statelabel[FOCUSED])
110           {
111              _set_label(obj, wd->statelabel[FOCUSED]);
112           }
113         edje_object_signal_emit(wd->btn, "elm,action,focus", "elm");
114         evas_object_focus_set(wd->btn, EINA_TRUE);
115      }
116    else
117      {
118         if (wd->statelabel[DEFAULT])
119           _set_label(obj, wd->statelabel[DEFAULT]);
120         #if 0
121         else
122           _set_label(obj, wd->label);
123         #endif
124         edje_object_signal_emit(wd->btn, "elm,action,unfocus", "elm");
125         evas_object_focus_set(wd->btn, EINA_FALSE);
126      }
127 }
128
129 static void
130 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
131 {
132    Widget_Data *wd = elm_widget_data_get(obj);
133    if (!wd) return;
134    edje_object_mirrored_set(wd->btn, rtl);
135 }
136
137 static void
138 _theme_hook(Evas_Object *obj)
139 {
140    Widget_Data *wd = elm_widget_data_get(obj);
141    const char *str;
142    if (!wd) return;
143    _elm_widget_mirrored_reload(obj);
144    _mirrored_set(obj, elm_widget_mirrored_get(obj));
145    _elm_theme_object_set(obj, wd->btn, "button", "base", elm_widget_style_get(obj));
146    if (elm_object_disabled_get(obj))
147      edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
148    if (wd->icon)
149      edje_object_part_swallow(wd->btn, "elm.swallow.content", wd->icon);
150    if (wd->label)
151      edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
152    else
153      edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
154    if (wd->icon)
155      edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
156    else
157      edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
158    edje_object_part_text_set(wd->btn, "elm.text", wd->label);
159    edje_object_message_signal_process(wd->btn);
160    edje_object_scale_set(wd->btn, elm_widget_scale_get(obj) * _elm_config->scale);
161    str = edje_object_data_get(wd->btn, "focus_highlight");
162    if ((str) && (!strcmp(str, "on")))
163      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
164    else
165      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
166    _sizing_eval(obj);
167 }
168
169 static void
170 _disable_hook(Evas_Object *obj)
171 {
172    Widget_Data *wd = elm_widget_data_get(obj);
173    if (!wd) return;
174    if (elm_widget_disabled_get(obj))
175      {
176         if (wd->statelabel[DISABLED] )
177           {
178              _set_label(obj, wd->statelabel[DISABLED]);
179           }
180         edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
181      }
182    else
183      {
184         if (wd->statelabel[DEFAULT])
185           _set_label(obj, wd->statelabel[DEFAULT]);
186         #if 0
187         else
188           _set_label(obj, wd->label);
189         #endif
190         edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm");
191      }
192 }
193
194 static void
195 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
196 {
197    Widget_Data *wd = elm_widget_data_get(obj);
198    if (!wd) return;
199    edje_object_signal_emit(wd->btn, emission, source);
200 }
201
202 static void
203 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
204 {
205    Widget_Data *wd = elm_widget_data_get(obj);
206    if (!wd) return;
207    edje_object_signal_callback_add(wd->btn, emission, source, func_cb, data);
208 }
209
210 static void
211 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
212 {
213    Widget_Data *wd = elm_widget_data_get(obj);
214    edje_object_signal_callback_del_full(wd->btn, emission, source, func_cb,
215                                         data);
216 }
217
218 static void
219 _sizing_eval(Evas_Object *obj)
220 {
221    Widget_Data *wd = elm_widget_data_get(obj);
222    Evas_Coord minw = -1, minh = -1;
223    Evas_Coord w, h;
224
225    if (!wd) return;
226    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
227    edje_object_size_min_restricted_calc(wd->btn, &minw, &minh, minw, minh);
228    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
229    //Commenting to sync with open source and able to resize based on text change
230    evas_object_size_hint_min_get(obj, &w, &h);
231    //if (w > minw) minw = w;
232    if (h > minh) minh = h;
233
234    evas_object_size_hint_min_set(obj, minw, minh);
235 }
236
237 static void
238 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
239 {
240    Widget_Data *wd = elm_widget_data_get(data);
241    if (!wd) return;
242    if (obj != wd->icon) return;
243    _sizing_eval(data);
244 }
245
246 static void
247 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
248 {
249    Widget_Data *wd = elm_widget_data_get(obj);
250    Evas_Object *sub = event_info;
251    if (!wd) return;
252    if (sub == wd->icon)
253      {
254         edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
255         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
256                                             _changed_size_hints, obj);
257         wd->icon = NULL;
258         edje_object_message_signal_process(wd->btn);
259         _sizing_eval(obj);
260      }
261 }
262
263 static void
264 _activate(Evas_Object *obj)
265 {
266    Widget_Data *wd = elm_widget_data_get(obj);
267    if (!wd) return;
268    if (wd->timer)
269      {
270         ecore_timer_del(wd->timer);
271         wd->timer = NULL;
272      }
273    wd->repeating = EINA_FALSE;
274    evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
275 }
276
277 static void
278 _activate_hook(Evas_Object *obj)
279 {
280    _activate(obj);
281 }
282
283 static void
284 _signal_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
285 {
286    _activate(data);
287 }
288
289 static Eina_Bool
290 _autorepeat_send(void *data)
291 {
292    Widget_Data *wd = elm_widget_data_get(data);
293    if (!wd) return ECORE_CALLBACK_CANCEL;
294
295    evas_object_smart_callback_call(data, SIG_REPEATED, NULL);
296    if (!wd->repeating)
297      {
298         wd->timer = NULL;
299         return ECORE_CALLBACK_CANCEL;
300      }
301
302    return ECORE_CALLBACK_RENEW;
303 }
304
305 static Eina_Bool
306 _autorepeat_initial_send(void *data)
307 {
308    Widget_Data *wd = elm_widget_data_get(data);
309    if (!wd) return ECORE_CALLBACK_CANCEL;
310
311    if (wd->timer) ecore_timer_del(wd->timer);
312    wd->repeating = EINA_TRUE;
313    _autorepeat_send(data);
314    wd->timer = ecore_timer_add(wd->ar_interval, _autorepeat_send, data);
315
316    return ECORE_CALLBACK_CANCEL;
317 }
318
319 static void
320 _signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
321 {
322    Widget_Data *wd = elm_widget_data_get(data);
323    if (!wd) return;
324
325    if (wd->statelabel[HIGHLIGHTED])
326      {
327         _set_label(data, wd->statelabel[HIGHLIGHTED]);
328      }
329    if ((wd->autorepeat) && (!wd->repeating))
330      {
331         if (wd->ar_threshold <= 0.0)
332           _autorepeat_initial_send(data); /* call immediately */
333         else
334           wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data);
335      }
336 }
337
338 static void
339 _signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
340 {
341    Widget_Data *wd = elm_widget_data_get(data);
342    if (!wd) return;
343    if (wd->statelabel[DEFAULT])
344      _set_label(data, wd->statelabel[DEFAULT]);
345    #if 0
346    else
347      _set_label(data, wd->label);
348    #endif
349
350    if (wd->timer)
351      {
352         ecore_timer_del(wd->timer);
353         wd->timer = NULL;
354      }
355    wd->repeating = EINA_FALSE;
356    evas_object_smart_callback_call(data, SIG_UNPRESSED, NULL);
357 }
358
359 static void
360 _signal_default_text_set(void *data, Evas_Object *obj, const char *emission, const char *source)
361 {
362    Widget_Data *wd = elm_widget_data_get(data);
363    if (!wd) return;
364    if (wd->statelabel[DEFAULT])
365      _set_label(data, wd->statelabel[DEFAULT]);
366    #if 0
367    else
368      _set_label(data, wd->label);
369    #endif
370 }
371 /**
372  * Add a new button to the parent
373  * @param[in] parent The parent object
374  * @return The new object or NULL if it cannot be created
375  *
376  * @ingroup Button
377  */
378 EAPI Evas_Object *
379 elm_button_add(Evas_Object *parent)
380 {
381    Evas_Object *obj;
382    Evas *e;
383    Widget_Data *wd;
384
385    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
386
387    ELM_SET_WIDTYPE(widtype, "button");
388    elm_widget_type_set(obj, "button");
389    elm_widget_sub_object_add(parent, obj);
390    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
391    elm_widget_data_set(obj, wd);
392    elm_widget_del_hook_set(obj, _del_hook);
393    elm_widget_theme_hook_set(obj, _theme_hook);
394    elm_widget_disable_hook_set(obj, _disable_hook);
395    elm_widget_can_focus_set(obj, EINA_TRUE);
396    elm_widget_activate_hook_set(obj, _activate_hook);
397    elm_widget_event_hook_set(obj, _event_hook);
398    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
399    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
400    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
401
402    wd->btn = edje_object_add(e);
403    _elm_theme_object_set(obj, wd->btn, "button", "base", "default");
404    wd->statetype[DEFAULT] = 0;
405    wd->statetype[HIGHLIGHTED] = 0;
406    wd->statetype[FOCUSED] = 0;
407    wd->statetype[DISABLED] = 0;
408    wd->statelabel[DEFAULT] = 0;
409    wd->statelabel[HIGHLIGHTED] = 0;
410    wd->statelabel[FOCUSED] = 0;
411    wd->statelabel[DISABLED] = 0;
412    edje_object_signal_callback_add(wd->btn, "elm,action,click", "",
413                                    _signal_clicked, obj);
414    edje_object_signal_callback_add(wd->btn, "elm,action,press", "",
415                                    _signal_pressed, obj);
416    edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "",
417                                    _signal_unpressed, obj);
418    edje_object_signal_callback_add(wd->btn, "elm,action,default,text,set", "",
419                                    _signal_default_text_set, obj);
420    elm_widget_resize_object_set(obj, wd->btn);
421
422    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
423
424    _theme_hook(obj);
425
426    // TODO: convert Elementary to subclassing of Evas_Smart_Class
427    // TODO: and save some bytes, making descriptions per-class and not instance!
428    evas_object_smart_callbacks_descriptions_set(obj, _signals);
429    return obj;
430 }
431
432 /**
433  * Set the label used in the button
434  *
435  * @param[in] obj The button object
436  * @param[in] label The text will be written on the button
437  *
438  * @ingroup Button
439  */
440 EAPI void
441 elm_button_label_set(Evas_Object *obj, const char *label)
442 {
443    ELM_CHECK_WIDTYPE(obj, widtype);
444    Widget_Data *wd = elm_widget_data_get(obj);
445    if (!wd) return;
446    eina_stringshare_replace(&wd->label, label);
447    if (label)
448      edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
449    else
450      edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
451    edje_object_message_signal_process(wd->btn);
452    edje_object_part_text_set(wd->btn, "elm.text", label);
453    _sizing_eval(obj);
454 }
455
456 static void
457 _set_label(Evas_Object *obj, const char *label)
458 {
459    Widget_Data *wd = elm_widget_data_get(obj);
460
461    edje_object_part_text_set(wd->btn, "elm.text", label);
462    _sizing_eval(obj);
463 }
464 /**
465  * Set the label for each state of button
466  *
467  * @param[in] obj The button object
468  * @param[in] label The text will be written on the button
469  * @param[in] state The state of button
470  *
471  * @ingroup Button
472  */
473 EAPI void
474 elm_button_label_set_for_state(Evas_Object *obj, const char *label, UIControlState state)
475 {
476    Widget_Data *wd = elm_widget_data_get(obj);
477
478    if (!wd) return;
479    if (label == NULL) return;
480
481    if (state == UIControlStateDefault)
482      {
483         wd->statetype[DEFAULT] = UIControlStateDefault;
484         eina_stringshare_replace(&wd->statelabel[DEFAULT], label);
485         return;
486      }
487    if (state == UIControlStateHighlighted)
488      {
489         wd->statetype[HIGHLIGHTED] = UIControlStateHighlighted;
490         eina_stringshare_replace(&wd->statelabel[HIGHLIGHTED], label);
491         return;
492      }
493    if (state == UIControlStateFocused)
494      {
495         wd->statetype[FOCUSED] = UIControlStateFocused;
496         eina_stringshare_replace(&wd->statelabel[FOCUSED], label);
497         return;
498      }
499    if (state == UIControlStateDisabled)
500      {
501         wd->statetype[DISABLED] = UIControlStateDisabled;
502         eina_stringshare_replace(&wd->statelabel[DISABLED], label);
503         return;
504      }
505 }
506
507 /**
508  * Get the label of button
509  *
510  * @param[in] obj The button object
511  * @return The title of button
512  *
513  * @ingroup Button
514  */
515 EAPI const char *
516 elm_button_label_get(const Evas_Object *obj)
517 {
518    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
519    Widget_Data *wd = elm_widget_data_get(obj);
520    if (!wd) return NULL;
521    return wd->label;
522 }
523 /**
524  * Get the label of button for each state
525  *
526  * @param[in] obj The button object
527  * @param[in] state The state of button
528  * @return The title of button for state
529  *
530  * @ingroup Button
531  */
532 EAPI const char*
533 elm_button_label_get_for_state(const Evas_Object *obj, UIControlState state)
534 {
535    Widget_Data *wd = elm_widget_data_get(obj);
536    if (!wd) return NULL;
537
538    if (state == UIControlStateDefault)
539      return wd->statelabel[DEFAULT];
540    else if (state == UIControlStateHighlighted)
541      return wd->statelabel[HIGHLIGHTED];
542    else if (state == UIControlStateFocused)
543      return wd->statelabel[FOCUSED];
544    else if (state == UIControlStateDisabled)
545      return wd->statelabel[DISABLED];
546    else
547      return NULL;
548 }
549
550 /**
551  * Set the icon used for the button
552  *
553  * Once the icon object is set, a previously set one will be deleted
554  * If you want to keep that old content object, use the
555  * elm_button_icon_unset() function.
556  *
557  * @param[in] obj The button object
558  * @param[in] icon The icon object for the button
559  *
560  * @ingroup Button
561  */
562 EAPI void
563 elm_button_icon_set(Evas_Object *obj, Evas_Object *icon)
564 {
565    ELM_CHECK_WIDTYPE(obj, widtype);
566    Widget_Data *wd = elm_widget_data_get(obj);
567    if (!wd) return;
568    if (wd->icon == icon) return;
569    if (wd->icon) evas_object_del(wd->icon);
570    wd->icon = icon;
571    if (icon)
572      {
573         elm_widget_sub_object_add(obj, icon);
574         evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
575                                        _changed_size_hints, obj);
576         edje_object_part_swallow(wd->btn, "elm.swallow.content", icon);
577         edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
578         edje_object_message_signal_process(wd->btn);
579      }
580    _sizing_eval(obj);
581 }
582
583 /**
584  * Get the icon used for the button
585  *
586  * Return the icon object which is set for this widget.
587  *
588  * @param[in] obj The button object
589  * @return The icon object that is being used
590  *
591  * @ingroup Button
592  */
593 EAPI Evas_Object *
594 elm_button_icon_get(const Evas_Object *obj)
595 {
596    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
597    Widget_Data *wd = elm_widget_data_get(obj);
598    if (!wd) return NULL;
599    return wd->icon;
600 }
601
602 /**
603  * Unset the icon used for the button
604  *
605  * Unparent and return the icon object which was set for this widget.
606  *
607  * @param[in] obj The button object
608  * @return The icon object that was being used
609  *
610  * @ingroup Button
611  */
612 EAPI Evas_Object *
613 elm_button_icon_unset(Evas_Object *obj)
614 {
615    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
616    Widget_Data *wd = elm_widget_data_get(obj);
617    if (!wd) return NULL;
618    if (!wd->icon) return NULL;
619    Evas_Object *icon = wd->icon;
620    elm_widget_sub_object_del(obj, wd->icon);
621    edje_object_part_unswallow(wd->btn, wd->icon);
622    wd->icon = NULL;
623    return icon;
624 }
625
626 /**
627  * Turn on/off the autorepeat event generated when the user keeps pressing on the button
628  *
629  * @param[in] obj The button object
630  * @param[in] on  A bool to turn on/off the event
631  *
632  * @ingroup Button
633  */
634 EAPI void
635 elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
636 {
637    ELM_CHECK_WIDTYPE(obj, widtype);
638    Widget_Data *wd = elm_widget_data_get(obj);
639    if (!wd) return;
640    if (wd->timer)
641      {
642         ecore_timer_del(wd->timer);
643         wd->timer = NULL;
644      }
645    wd->autorepeat = on;
646    wd->repeating = EINA_FALSE;
647 }
648
649 /**
650  * Get if autorepeat event is on
651  *
652  * @param[in] obj The button object
653  * @return If autorepeat is on
654  *
655  * @ingroup Button
656  */
657 EAPI Eina_Bool
658 elm_button_autorepeat_get(const Evas_Object *obj)
659 {
660    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
661    Widget_Data *wd = elm_widget_data_get(obj);
662    if (!wd) return EINA_FALSE;
663    return wd->autorepeat;
664 }
665
666 /**
667  * Set the initial timeout before the autorepeat event is generated
668  *
669  * @param[in] obj The button object
670  * @param[in] t   Timeout
671  *
672  * @ingroup Button
673  */
674 EAPI void
675 elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t)
676 {
677    ELM_CHECK_WIDTYPE(obj, widtype);
678    Widget_Data *wd = elm_widget_data_get(obj);
679    if (!wd) return;
680    if (wd->ar_threshold == t) return;
681    if (wd->timer)
682      {
683         ecore_timer_del(wd->timer);
684         wd->timer = NULL;
685      }
686    wd->ar_threshold = t;
687 }
688
689 /**
690  * Get the initial timeout before the autorepeat event is generated
691  *
692  * @param[in] obj The button object
693  * @return Timeout
694  *
695  * @ingroup Button
696  */
697 EAPI double
698 elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj)
699 {
700    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
701    Widget_Data *wd = elm_widget_data_get(obj);
702    if (!wd) return 0.0;
703    return wd->ar_threshold;
704 }
705
706 /**
707  * Set the interval between each generated autorepeat event
708  *
709  * @param[in] obj The button object
710  * @param[in] t   Interval
711  *
712  * @ingroup Button
713  */
714 EAPI void
715 elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
716 {
717    ELM_CHECK_WIDTYPE(obj, widtype);
718    Widget_Data *wd = elm_widget_data_get(obj);
719    if (!wd) return;
720    if (wd->ar_interval == t) return;
721
722    wd->ar_interval = t;
723    if ((wd->repeating) && (wd->timer)) ecore_timer_interval_set(wd->timer, t);
724 }
725
726 /**
727  * Get the interval between each generated autorepeat event
728  *
729  * @param[in] obj The button object
730  * @return Interval
731  *
732  * @ingroup Button
733  */
734 EAPI double
735 elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj)
736 {
737    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
738    Widget_Data *wd = elm_widget_data_get(obj);
739    if (!wd) return 0.0;
740    return wd->ar_interval;
741 }