remove deprecated calls (been deprecated for a while now)
[platform/upstream/elementary.git] / src / lib / elm_button.c
1 /*
2  *
3  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4  */
5 #include <Elementary.h>
6 #include "elm_priv.h"
7
8 /**
9  * @defgroup Button Button
10  *
11  * This is a push-button. Press it and run some function. It can contain
12  * a simple label and icon object.
13  */
14
15 typedef struct _Widget_Data Widget_Data;
16
17 struct _Widget_Data
18 {
19    Evas_Object *btn, *icon;
20    const char *label;
21
22    Eina_Bool autorepeat;
23    Eina_Bool repeating;
24    double ar_threshold;
25    double ar_interval;
26    Ecore_Timer *timer;
27 };
28
29 static const char *widtype = NULL;
30 static void _del_hook(Evas_Object *obj);
31 static void _theme_hook(Evas_Object *obj);
32 static void _disable_hook(Evas_Object *obj);
33 static void _sizing_eval(Evas_Object *obj);
34 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
35 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
36 static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
37 static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source);
38 static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source);
39 static void _on_focus_hook(void *data, Evas_Object *obj);
40
41 static void
42 _del_hook(Evas_Object *obj)
43 {
44    Widget_Data *wd = elm_widget_data_get(obj);
45    if (!wd) return;
46    if (wd->label) eina_stringshare_del(wd->label);
47    free(wd);
48 }
49
50 static void
51 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
52 {
53    Widget_Data *wd = elm_widget_data_get(obj);
54    if (!wd) return;
55    if (elm_widget_focus_get(obj))
56      edje_object_signal_emit(wd->btn, "elm,action,focus", "elm");
57    else
58      edje_object_signal_emit(wd->btn, "elm,action,unfocus", "elm");
59 }
60
61 static void
62 _theme_hook(Evas_Object *obj)
63 {
64    Widget_Data *wd = elm_widget_data_get(obj);
65    if (!wd) return;
66    _elm_theme_set(wd->btn, "button", "base", elm_widget_style_get(obj));
67    if (wd->icon)
68      edje_object_part_swallow(wd->btn, "elm.swallow.content", wd->icon);
69    if (wd->label)
70      edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
71    else
72      edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
73    if (wd->icon)
74      edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
75    else
76      edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
77    edje_object_part_text_set(wd->btn, "elm.text", wd->label);
78    edje_object_message_signal_process(wd->btn);
79    edje_object_scale_set(wd->btn, elm_widget_scale_get(obj) * _elm_config->scale);
80    _sizing_eval(obj);
81 }
82
83 static void
84 _disable_hook(Evas_Object *obj)
85 {
86    Widget_Data *wd = elm_widget_data_get(obj);
87    if (!wd) return;
88    if (elm_widget_disabled_get(obj))
89      edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
90    else
91      edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm");
92 }
93
94 static void
95 _sizing_eval(Evas_Object *obj)
96 {
97    Widget_Data *wd = elm_widget_data_get(obj);
98    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
99
100    if (!wd) return;
101    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
102    edje_object_size_min_restricted_calc(wd->btn, &minw, &minh, minw, minh);
103    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
104    evas_object_size_hint_min_set(obj, minw, minh);
105    evas_object_size_hint_max_set(obj, maxw, maxh);
106 }
107
108 static void
109 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
110 {
111    Widget_Data *wd = elm_widget_data_get(data);
112    if (!wd) return;
113    if (obj != wd->icon) return;
114    _sizing_eval(data);
115 }
116
117 static void
118 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
119 {
120    Widget_Data *wd = elm_widget_data_get(obj);
121    Evas_Object *sub = event_info;
122    if (!wd) return;
123    if (sub == wd->icon)
124      {
125         edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
126         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
127                                        _changed_size_hints, obj);
128         wd->icon = NULL;
129         edje_object_message_signal_process(wd->btn);
130         _sizing_eval(obj);
131      }
132 }
133
134 static void
135 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
136 {
137    Widget_Data *wd = elm_widget_data_get(data);
138    if (!wd) return;
139    evas_object_smart_callback_call(data, "clicked", NULL);
140    _signal_unpressed(data, obj, emission, source); /* safe guard when the theme does not emit the 'unpress' signal */
141 }
142
143 static int
144 _autorepeat_send(void *data)
145 {
146    Widget_Data *wd = elm_widget_data_get(data);
147    if (!wd) return ECORE_CALLBACK_CANCEL;
148
149    evas_object_smart_callback_call(data, "repeated", NULL);
150
151    return ECORE_CALLBACK_RENEW;
152 }
153
154 static int
155 _autorepeat_initial_send(void *data)
156 {
157    Widget_Data *wd = elm_widget_data_get(data);
158    if (!wd) return ECORE_CALLBACK_CANCEL;
159
160    _autorepeat_send(data);
161    wd->timer = ecore_timer_add(wd->ar_interval, _autorepeat_send, data);
162    wd->repeating = 1;
163
164    return ECORE_CALLBACK_CANCEL;
165 }
166
167 static void
168 _signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
169 {
170    Widget_Data *wd = elm_widget_data_get(data);
171    if (!wd) return;
172
173    if (wd->autorepeat)
174      {
175         if (wd->ar_threshold <= 0.0)
176           _autorepeat_initial_send(data); /* call immediately */
177         else
178           wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data);
179      }
180 }
181
182 static void
183 _signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
184 {
185    Widget_Data *wd = elm_widget_data_get(data);
186    if (!wd) return;
187    evas_object_smart_callback_call(data, "unpressed", NULL);
188
189    if (wd->timer)
190      {
191         ecore_timer_del(wd->timer);
192         wd->timer = NULL;
193      }
194    wd->repeating = 0;
195 }
196
197 /**
198  * Add a new button to the parent
199  * @param parent The parent object
200  * @return The new object or NULL if it cannot be created
201  *
202  * @ingroup Button
203  */
204 EAPI Evas_Object *
205 elm_button_add(Evas_Object *parent)
206 {
207    Evas_Object *obj;
208    Evas *e;
209    Widget_Data *wd;
210
211    wd = ELM_NEW(Widget_Data);
212    e = evas_object_evas_get(parent);
213    obj = elm_widget_add(e);
214    ELM_SET_WIDTYPE(widtype, "button");
215    elm_widget_type_set(obj, "button");
216    elm_widget_sub_object_add(parent, obj);
217    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
218    elm_widget_data_set(obj, wd);
219    elm_widget_del_hook_set(obj, _del_hook);
220    elm_widget_theme_hook_set(obj, _theme_hook);
221    elm_widget_disable_hook_set(obj, _disable_hook);
222    elm_widget_can_focus_set(obj, 1 );                 
223
224    wd->btn = edje_object_add(e);
225    _elm_theme_set(wd->btn, "button", "base", "default");
226    edje_object_signal_callback_add(wd->btn, "elm,action,click", "",
227                                    _signal_clicked, obj);
228    edje_object_signal_callback_add(wd->btn, "elm,action,press", "",
229                                    _signal_pressed, obj);
230    edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "",
231                                    _signal_unpressed, obj);
232    elm_widget_resize_object_set(obj, wd->btn);
233
234    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
235
236    _sizing_eval(obj);
237    return obj;
238 }
239
240 /**
241  * Set the label used in the button
242  *
243  * @param obj The button object
244  * @param label The text will be written on the button
245  *
246  * @ingroup Button
247  */
248 EAPI void
249 elm_button_label_set(Evas_Object *obj, const char *label)
250 {
251    ELM_CHECK_WIDTYPE(obj, widtype);
252    Widget_Data *wd = elm_widget_data_get(obj);
253    if (!wd) return;
254    if (wd->label) eina_stringshare_del(wd->label);
255    if (label)
256      {
257         wd->label = eina_stringshare_add(label);
258         edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
259      }
260    else
261      {
262         wd->label = NULL;
263         edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
264      }
265    edje_object_message_signal_process(wd->btn);
266    edje_object_part_text_set(wd->btn, "elm.text", label);
267    _sizing_eval(obj);
268 }
269
270 EAPI const char *
271 elm_button_label_get(Evas_Object *obj)
272 {
273    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
274    Widget_Data *wd = elm_widget_data_get(obj);
275    if (!wd) return NULL;
276    return wd->label;
277 }
278
279 /**
280  * Set the icon used for the button
281  *
282  * @param obj The button object
283  * @param icon  The image for the button
284  *
285  * @ingroup Button
286  */
287 EAPI void
288 elm_button_icon_set(Evas_Object *obj, Evas_Object *icon)
289 {
290    ELM_CHECK_WIDTYPE(obj, widtype);
291    Widget_Data *wd = elm_widget_data_get(obj);
292    if (!wd) return;
293    if ((wd->icon != icon) && (wd->icon))
294      elm_widget_sub_object_del(obj, wd->icon);
295    if ((icon) && (wd->icon != icon))
296      {
297         wd->icon = icon;
298         elm_widget_sub_object_add(obj, icon);
299         evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
300                                        _changed_size_hints, obj);
301         edje_object_part_swallow(wd->btn, "elm.swallow.content", icon);
302         edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
303         edje_object_message_signal_process(wd->btn);
304         _sizing_eval(obj);
305      }
306    else
307      wd->icon = icon;
308 }
309
310 /**
311  * Get the icon used for the button
312  *
313  * @param obj The button object
314  * @return The image for the button
315  *
316  * @ingroup Button
317  */
318 EAPI Evas_Object *
319 elm_button_icon_get(Evas_Object *obj)
320 {
321    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
322    Widget_Data *wd = elm_widget_data_get(obj);
323    if (!wd) return NULL;
324    return wd->icon;
325 }
326
327 /**
328  * Turn on/off the autorepeat event generated when the user keeps pressing on the button
329  *
330  * @param obj The button object
331  * @param on  A bool to turn on/off the event
332  *
333  * @ingroup Button
334  */
335 EAPI void
336 elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
337 {
338    ELM_CHECK_WIDTYPE(obj, widtype);
339    Widget_Data *wd = elm_widget_data_get(obj);
340    if (!wd) return;
341    if (wd->timer)
342      {
343         ecore_timer_del(wd->timer);
344         wd->timer = NULL;
345      }
346    wd->autorepeat = on;
347 }
348
349 /**
350  * Set the initial timeout before the autorepeat event is generated
351  *
352  * @param obj The button object
353  * @param t   Timeout
354  *
355  * @ingroup Button
356  */
357 EAPI void
358 elm_button_autorepeat_initital_timeout_set(Evas_Object *obj, double t)
359 {
360    ELM_CHECK_WIDTYPE(obj, widtype);
361    Widget_Data *wd = elm_widget_data_get(obj);
362    if (!wd) return;
363    if (wd->ar_threshold == t) return;
364    if (wd->timer)
365      {
366         ecore_timer_del(wd->timer);
367         wd->timer = NULL;
368      }
369    wd->ar_threshold = t;
370 }
371
372 /**
373  * Set the interval between each generated autorepeat event
374  *
375  * @param obj The button object
376  * @param t   Interval
377  *
378  * @ingroup Button
379  */
380 EAPI void         
381 elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
382 {
383    ELM_CHECK_WIDTYPE(obj, widtype);
384    Widget_Data *wd = elm_widget_data_get(obj);
385    if (!wd) return;
386    if (wd->ar_interval == t) return;
387    if (wd->timer)
388      {
389         ecore_timer_del(wd->timer);
390         wd->timer = NULL;
391      }
392    wd->ar_interval = t;
393    if (wd->repeating)
394      wd->timer = ecore_timer_add(t, _autorepeat_send, obj);
395 }
396