Elementary: Slider documentation
[framework/uifw/elementary.git] / src / lib / elm_slider.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Widget_Data Widget_Data;
5
6 struct _Widget_Data
7 {
8    Evas_Object *slider;
9    Evas_Object *icon;
10    Evas_Object *end;
11    Evas_Object *spacer;
12
13    Ecore_Timer *delay;
14
15    const char *label;
16    const char *units;
17    const char *indicator;
18
19    const char *(*indicator_format_func)(double val);
20    void (*indicator_format_free)(const char *str);
21
22    const char *(*units_format_func)(double val);
23    void (*units_format_free)(const char *str);
24
25    double val, val_min, val_max;
26    Evas_Coord size;
27
28    Eina_Bool horizontal : 1;
29    Eina_Bool inverted : 1;
30    Eina_Bool indicator_show : 1;
31 };
32
33 #define ELM_SLIDER_INVERTED_FACTOR (-1.0)
34
35 static const char *widtype = NULL;
36 static void _del_hook(Evas_Object *obj);
37 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
38 static void _theme_hook(Evas_Object *obj);
39 static void _disable_hook(Evas_Object *obj);
40 static void _sizing_eval(Evas_Object *obj);
41 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
42 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
43 static void _units_set(Evas_Object *obj);
44 static void _val_set(Evas_Object *obj);
45 static void _indicator_set(Evas_Object *obj);
46 static void _on_focus_hook(void *data, Evas_Object *obj);
47 static void _drag_up(void *data, Evas_Object *obj,
48                     const char *emission, const char *source);
49 static void _drag_down(void *data, Evas_Object *obj,
50                     const char *emission, const char *source);
51 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
52                              Evas_Callback_Type type, void *event_info);
53 static void _spacer_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
54
55 static const char SIG_CHANGED[] = "changed";
56 static const char SIG_DELAY_CHANGED[] = "delay,changed";
57 static const char SIG_DRAG_START[] = "slider,drag,start";
58 static const char SIG_DRAG_STOP[] = "slider,drag,stop";
59 static const Evas_Smart_Cb_Description _signals[] = {
60   {SIG_CHANGED, ""},
61   {SIG_DELAY_CHANGED, ""},
62   {SIG_DRAG_START, ""},
63   {SIG_DRAG_STOP, ""},
64   {NULL, NULL}
65 };
66
67 static Eina_Bool
68 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
69 {
70    Evas_Event_Mouse_Wheel *mev;
71    Evas_Event_Key_Down *ev;
72    Widget_Data *wd;
73
74    wd = elm_widget_data_get(obj);
75    if (!wd) return EINA_FALSE;
76
77    if (type == EVAS_CALLBACK_KEY_DOWN) goto key_down;
78    else if (type != EVAS_CALLBACK_MOUSE_WHEEL) return EINA_FALSE;
79
80    mev = event_info;
81    if (mev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
82    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
83
84    if (mev->z < 0) _drag_up(obj, NULL, NULL, NULL);
85    else _drag_down(obj, NULL, NULL, NULL);
86    mev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
87    return EINA_TRUE;
88
89   key_down:
90    ev = event_info;
91    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
92    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
93    if ((!strcmp(ev->keyname, "Left"))
94        || (!strcmp(ev->keyname, "KP_Left")))
95      {
96         if (!wd->horizontal) return EINA_FALSE;
97         if (!wd->inverted) _drag_down(obj, NULL, NULL, NULL);
98         else _drag_up(obj, NULL, NULL, NULL);
99         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
100         return EINA_TRUE;
101      }
102    else if ((!strcmp(ev->keyname, "Right"))
103             || (!strcmp(ev->keyname, "KP_Right")))
104      {
105         if (!wd->horizontal) return EINA_FALSE;
106         if (!wd->inverted) _drag_up(obj, NULL, NULL, NULL);
107         else _drag_down(obj, NULL, NULL, NULL);
108         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
109         return EINA_TRUE;
110      }
111    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
112      {
113         if (wd->horizontal) return EINA_FALSE;
114         if (wd->inverted) _drag_up(obj, NULL, NULL, NULL);
115         else _drag_down(obj, NULL, NULL, NULL);
116         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
117         return EINA_TRUE;
118      }
119    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
120      {
121         if (wd->horizontal) return EINA_FALSE;
122         if (wd->inverted) _drag_down(obj, NULL, NULL, NULL);
123         else _drag_up(obj, NULL, NULL, NULL);
124         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
125         return EINA_TRUE;
126      }
127    else return EINA_FALSE;
128 }
129
130 static void
131 _del_hook(Evas_Object *obj)
132 {
133    Widget_Data *wd = elm_widget_data_get(obj);
134    if (!wd) return;
135    if (wd->label) eina_stringshare_del(wd->label);
136    if (wd->indicator) eina_stringshare_del(wd->units);
137    if (wd->delay) ecore_timer_del(wd->delay);
138    free(wd);
139 }
140
141 static void
142 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
143 {
144    Widget_Data *wd = elm_widget_data_get(obj);
145    if (!wd) return;
146    if (elm_widget_focus_get(obj))
147      {
148         edje_object_signal_emit(wd->slider, "elm,action,focus", "elm");
149         evas_object_focus_set(wd->slider, EINA_TRUE);
150      }
151    else
152      {
153         edje_object_signal_emit(wd->slider, "elm,action,unfocus", "elm");
154         evas_object_focus_set(wd->slider, EINA_FALSE);
155      }
156 }
157
158 static void
159 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
160 {
161    Widget_Data *wd = elm_widget_data_get(obj);
162    if (!wd) return;
163    edje_object_mirrored_set(wd->slider, rtl);
164 }
165
166 static void
167 _theme_hook(Evas_Object *obj)
168 {
169    Widget_Data *wd = elm_widget_data_get(obj);
170    if (!wd) return;
171    _elm_widget_mirrored_reload(obj);
172    _mirrored_set(obj, elm_widget_mirrored_get(obj));
173    if (wd->horizontal)
174      _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", elm_widget_style_get(obj));
175    else
176      _elm_theme_object_set(obj, wd->slider, "slider", "vertical", elm_widget_style_get(obj));
177    if (wd->icon)
178      {
179         edje_object_part_swallow(wd->slider, "elm.swallow.content", wd->icon);
180         edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
181      }
182    if (wd->end)
183      edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
184    else
185      edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
186    if (wd->label)
187      {
188         edje_object_part_text_set(wd->slider, "elm.text", wd->label);
189         edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
190      }
191
192    if (wd->units)
193      edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
194
195    if (wd->horizontal)
196      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
197    else
198      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
199
200    if (wd->inverted)
201      edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
202
203    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
204    _units_set(obj);
205    _indicator_set(obj);
206    edje_object_message_signal_process(wd->slider);
207    edje_object_scale_set(wd->slider, elm_widget_scale_get(obj) * _elm_config->scale);
208    _val_set(obj);
209    _sizing_eval(obj);
210 }
211
212 static void
213 _disable_hook(Evas_Object *obj)
214 {
215    Widget_Data *wd = elm_widget_data_get(obj);
216    if (!wd) return;
217    if (elm_widget_disabled_get(obj))
218      edje_object_signal_emit(wd->slider, "elm,state,disabled", "elm");
219    else
220      edje_object_signal_emit(wd->slider, "elm,state,enabled", "elm");
221 }
222
223 static void
224 _sizing_eval(Evas_Object *obj)
225 {
226    Widget_Data *wd = elm_widget_data_get(obj);
227    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
228    if (!wd) return;
229    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
230    edje_object_size_min_restricted_calc(wd->slider, &minw, &minh, minw, minh);
231    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
232    evas_object_size_hint_min_set(obj, minw, minh);
233    evas_object_size_hint_max_set(obj, maxw, maxh);
234 }
235
236 static void
237 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
238 {
239    Widget_Data *wd = elm_widget_data_get(data);
240    if (!wd) return;
241    if ((obj != wd->icon) && (obj != wd->end)) return;
242    _sizing_eval(data);
243 }
244
245 static void
246 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
247 {
248    Widget_Data *wd = elm_widget_data_get(obj);
249    Evas_Object *sub = event_info;
250    if (!wd) return;
251    if (sub == wd->icon)
252      {
253         edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
254         evas_object_event_callback_del_full
255            (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
256         wd->icon = NULL;
257         edje_object_message_signal_process(wd->slider);
258         _sizing_eval(obj);
259      }
260    if (sub == wd->end)
261      {
262         edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
263         evas_object_event_callback_del_full(sub,
264                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
265                                             _changed_size_hints, obj);
266         wd->end = NULL;
267         edje_object_message_signal_process(wd->slider);
268         _sizing_eval(obj);
269      }
270 }
271
272 static Eina_Bool
273 _delay_change(void *data)
274 {
275    Widget_Data *wd = elm_widget_data_get(data);
276    if (!wd) return ECORE_CALLBACK_CANCEL;
277    wd->delay = NULL;
278    evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, NULL);
279    return ECORE_CALLBACK_CANCEL;
280 }
281
282 static void
283 _val_fetch(Evas_Object *obj)
284 {
285    Eina_Bool rtl;
286    Widget_Data *wd = elm_widget_data_get(obj);
287    double posx = 0.0, posy = 0.0, pos = 0.0, val;
288    if (!wd) return;
289    edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider",
290                                    &posx, &posy);
291    if (wd->horizontal) pos = posx;
292    else pos = posy;
293
294    rtl = elm_widget_mirrored_get(obj);
295    if ((!rtl && wd->inverted) || (rtl &&
296                                   ((!wd->horizontal && wd->inverted) ||
297                                    (wd->horizontal && !wd->inverted)))) pos = 1.0 - pos;
298    val = (pos * (wd->val_max - wd->val_min)) + wd->val_min;
299    if (val != wd->val)
300      {
301         wd->val = val;
302         evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
303         if (wd->delay) ecore_timer_del(wd->delay);
304         wd->delay = ecore_timer_add(0.2, _delay_change, obj);
305      }
306 }
307
308 static void
309 _val_set(Evas_Object *obj)
310 {
311    Eina_Bool rtl;
312    Widget_Data *wd = elm_widget_data_get(obj);
313    double pos;
314    if (!wd) return;
315    if (wd->val_max > wd->val_min)
316      pos = (wd->val - wd->val_min) / (wd->val_max - wd->val_min);
317    else
318      pos = 0.0;
319    if (pos < 0.0) pos = 0.0;
320    else if (pos > 1.0) pos = 1.0;
321
322    rtl = elm_widget_mirrored_get(obj);
323    if ((!rtl && wd->inverted) || (rtl &&
324                                   ((!wd->horizontal && wd->inverted) ||
325                                    (wd->horizontal && !wd->inverted)))) pos = 1.0 - pos;
326    edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", pos, pos);
327 }
328
329 static void
330 _units_set(Evas_Object *obj)
331 {
332    Widget_Data *wd = elm_widget_data_get(obj);
333    if (!wd) return;
334    if (wd->units_format_func)
335      {
336         const char *buf;
337         buf = wd->units_format_func(wd->val);
338         edje_object_part_text_set(wd->slider, "elm.units", buf);
339         if (wd->units_format_free) wd->units_format_free(buf);
340      }
341    else if (wd->units)
342      {
343         char buf[1024];
344
345         snprintf(buf, sizeof(buf), wd->units, wd->val);
346         edje_object_part_text_set(wd->slider, "elm.units", buf);
347      }
348    else
349      edje_object_part_text_set(wd->slider, "elm.units", NULL);
350 }
351
352 static void
353 _indicator_set(Evas_Object *obj)
354 {
355    Widget_Data *wd = elm_widget_data_get(obj);
356    if (!wd) return;
357    if (wd->indicator_format_func)
358      {
359         const char *buf;
360         buf = wd->indicator_format_func(wd->val);
361         edje_object_part_text_set(wd->slider, "elm.dragable.slider:elm.indicator", buf);
362         if (wd->indicator_format_free) wd->indicator_format_free(buf);
363      }
364    else if (wd->indicator)
365      {
366         char buf[1024];
367         snprintf(buf, sizeof(buf), wd->indicator, wd->val);
368         edje_object_part_text_set(wd->slider, "elm.dragable.slider:elm.indicator", buf);
369      }
370    else
371      edje_object_part_text_set(wd->slider, "elm.dragable.slider:elm.indicator", NULL);
372 }
373
374 static void
375 _drag(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
376 {
377    _val_fetch(data);
378    _units_set(data);
379    _indicator_set(data);
380 }
381
382 static void
383 _drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
384 {
385    _val_fetch(data);
386    evas_object_smart_callback_call(data, SIG_DRAG_START, NULL);
387    _units_set(data);
388    _indicator_set(data);
389    elm_widget_scroll_freeze_push(data);
390 }
391
392 static void
393 _drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
394 {
395    _val_fetch(data);
396    evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
397    _units_set(data);
398    _indicator_set(data);
399    elm_widget_scroll_freeze_pop(data);
400 }
401
402 static void
403 _drag_step(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
404 {
405    _val_fetch(data);
406    _units_set(data);
407    _indicator_set(data);
408 }
409
410 static void
411 _drag_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
412 {
413    double step;
414    Widget_Data *wd;
415
416    wd = elm_widget_data_get(data);
417    step = 0.05;
418
419    if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
420
421    edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
422 }
423
424 static void
425 _drag_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
426 {
427    double step;
428    Widget_Data *wd;
429
430    wd = elm_widget_data_get(data);
431    step = -0.05;
432
433    if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
434
435    edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
436 }
437
438 static void
439 _spacer_cb(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
440 {
441    Widget_Data *wd = elm_widget_data_get(data);
442    Evas_Event_Mouse_Down *ev = event_info;
443    Evas_Coord x, y, w, h;
444    double button_x, button_y;
445
446    evas_object_geometry_get(wd->spacer, &x, &y, &w, &h);
447    edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider", &button_x, &button_y);
448    if (wd->horizontal)
449      {
450         button_x = ((double)ev->canvas.x - (double)x) / (double)w;
451         if (button_x > 1) button_x = 1;
452         if (button_x < 0) button_x = 0;
453      }
454    else
455      {
456         button_y = ((double)ev->canvas.y - (double)y) / (double)h;
457         if (button_y > 1) button_y = 1;
458         if (button_y < 0) button_y = 0;
459      }
460    edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", button_x, button_y);
461    evas_event_feed_mouse_cancel(e, 0, NULL);
462    evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, 0, NULL);
463 }
464
465 static void
466 _elm_slider_label_set(Evas_Object *obj, const char *item, const char *label)
467 {
468    ELM_CHECK_WIDTYPE(obj, widtype);
469    Widget_Data *wd = elm_widget_data_get(obj);
470    if (item && strcmp(item, "default")) return;
471    if (!wd) return;
472    eina_stringshare_replace(&wd->label, label);
473    if (label)
474      {
475         edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
476         edje_object_message_signal_process(wd->slider);
477      }
478    else
479      {
480         edje_object_signal_emit(wd->slider, "elm,state,text,hidden", "elm");
481         edje_object_message_signal_process(wd->slider);
482      }
483    edje_object_part_text_set(wd->slider, "elm.text", label);
484    _sizing_eval(obj);
485 }
486
487 static const char *
488 _elm_slider_label_get(const Evas_Object *obj, const char *item)
489 {
490    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
491    Widget_Data *wd = elm_widget_data_get(obj);
492    if (item && strcmp(item, "default")) return NULL;
493    if (!wd) return NULL;
494    return wd->label;
495 }
496
497 EAPI Evas_Object *
498 elm_slider_add(Evas_Object *parent)
499 {
500    Evas_Object *obj;
501    Evas *e;
502    Widget_Data *wd;
503
504    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
505
506    ELM_SET_WIDTYPE(widtype, "slider");
507    elm_widget_type_set(obj, "slider");
508    elm_widget_sub_object_add(parent, obj);
509    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
510    elm_widget_data_set(obj, wd);
511    elm_widget_del_hook_set(obj, _del_hook);
512    elm_widget_theme_hook_set(obj, _theme_hook);
513    elm_widget_disable_hook_set(obj, _disable_hook);
514    elm_widget_can_focus_set(obj, EINA_TRUE);
515    elm_widget_event_hook_set(obj, _event_hook);
516    elm_widget_text_set_hook_set(obj, _elm_slider_label_set);
517    elm_widget_text_get_hook_set(obj, _elm_slider_label_get);
518
519    wd->horizontal = EINA_TRUE;
520    wd->indicator_show = EINA_TRUE;
521    wd->val = 0.0;
522    wd->val_min = 0.0;
523    wd->val_max = 1.0;
524
525    wd->slider = edje_object_add(e);
526    _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", "default");
527    elm_widget_resize_object_set(obj, wd->slider);
528    edje_object_signal_callback_add(wd->slider, "drag", "*", _drag, obj);
529    edje_object_signal_callback_add(wd->slider, "drag,start", "*", _drag_start, obj);
530    edje_object_signal_callback_add(wd->slider, "drag,stop", "*", _drag_stop, obj);
531    edje_object_signal_callback_add(wd->slider, "drag,step", "*", _drag_step, obj);
532    edje_object_signal_callback_add(wd->slider, "drag,page", "*", _drag_stop, obj);
533    //   edje_object_signal_callback_add(wd->slider, "drag,set", "*", _drag_stop, obj);
534    edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", 0.0, 0.0);
535
536    wd->spacer = evas_object_rectangle_add(e);
537    evas_object_color_set(wd->spacer, 0, 0, 0, 0);
538    evas_object_pass_events_set(wd->spacer, EINA_TRUE);
539    elm_widget_sub_object_add(obj, wd->spacer);
540    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
541    evas_object_event_callback_add(wd->spacer, EVAS_CALLBACK_MOUSE_DOWN, _spacer_cb, obj);
542    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
543
544    _mirrored_set(obj, elm_widget_mirrored_get(obj));
545    _sizing_eval(obj);
546
547    // TODO: convert Elementary to subclassing of Evas_Smart_Class
548    // TODO: and save some bytes, making descriptions per-class and not instance!
549    evas_object_smart_callbacks_descriptions_set(obj, _signals);
550    return obj;
551 }
552
553 EAPI void
554 elm_slider_label_set(Evas_Object *obj, const char *label)
555 {
556    _elm_slider_label_set(obj, NULL, label);
557 }
558
559 EAPI const char *
560 elm_slider_label_get(const Evas_Object *obj)
561 {
562    return _elm_slider_label_get(obj, NULL);
563 }
564
565 EAPI void
566 elm_slider_icon_set(Evas_Object *obj, Evas_Object *icon)
567 {
568    ELM_CHECK_WIDTYPE(obj, widtype);
569    Widget_Data *wd = elm_widget_data_get(obj);
570    if (!wd) return;
571    if (wd->icon == icon) return;
572    if (wd->icon) evas_object_del(wd->icon);
573    wd->icon = icon;
574    if (icon)
575      {
576         elm_widget_sub_object_add(obj, icon);
577         evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
578                                        _changed_size_hints, obj);
579         edje_object_part_swallow(wd->slider, "elm.swallow.icon", icon);
580         edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
581         edje_object_message_signal_process(wd->slider);
582      }
583    _sizing_eval(obj);
584 }
585
586 EAPI Evas_Object *
587 elm_slider_icon_unset(Evas_Object *obj)
588 {
589    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
590    Widget_Data *wd = elm_widget_data_get(obj);
591    Evas_Object *ret = NULL;
592    if (!wd) return NULL;
593    if (wd->icon)
594      {
595         elm_widget_sub_object_del(obj, wd->icon);
596         ret = wd->icon;
597         edje_object_part_unswallow(wd->slider, wd->icon);
598         edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
599         wd->icon = NULL;
600         _sizing_eval(obj);
601      }
602    return ret;
603 }
604
605 EAPI Evas_Object *
606 elm_slider_icon_get(const Evas_Object *obj)
607 {
608    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
609    Widget_Data *wd = elm_widget_data_get(obj);
610    if (!wd) return NULL;
611    return wd->icon;
612 }
613
614 EAPI void
615 elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size)
616 {
617    ELM_CHECK_WIDTYPE(obj, widtype);
618    Widget_Data *wd = elm_widget_data_get(obj);
619    if (!wd) return;
620    if (wd->size == size) return;
621    wd->size = size;
622    if (wd->horizontal)
623      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
624    else
625      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
626    if (wd->indicator_show)
627      edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
628    else
629      edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
630    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
631    _sizing_eval(obj);
632 }
633
634 EAPI Evas_Coord
635 elm_slider_span_size_get(const Evas_Object *obj)
636 {
637    ELM_CHECK_WIDTYPE(obj, widtype) 0;
638    Widget_Data *wd = elm_widget_data_get(obj);
639    if (!wd) return 0;
640    return wd->size;
641 }
642
643 EAPI void
644 elm_slider_unit_format_set(Evas_Object *obj, const char *units)
645 {
646    ELM_CHECK_WIDTYPE(obj, widtype);
647    Widget_Data *wd = elm_widget_data_get(obj);
648    if (!wd) return;
649    eina_stringshare_replace(&wd->units, units);
650    if (units)
651      {
652         edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
653         edje_object_message_signal_process(wd->slider);
654      }
655    else
656      {
657         edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
658         edje_object_message_signal_process(wd->slider);
659      }
660    _units_set(obj);
661    _sizing_eval(obj);
662 }
663
664 EAPI const char *
665 elm_slider_unit_format_get(const Evas_Object *obj)
666 {
667    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
668    Widget_Data *wd = elm_widget_data_get(obj);
669    if (!wd) return NULL;
670    return wd->units;
671 }
672
673 EAPI void
674 elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator)
675 {
676    ELM_CHECK_WIDTYPE(obj, widtype);
677    Widget_Data *wd = elm_widget_data_get(obj);
678    if (!wd) return;
679    eina_stringshare_replace(&wd->indicator, indicator);
680    _indicator_set(obj);
681 }
682
683 EAPI const char *
684 elm_slider_indicator_format_get(const Evas_Object *obj)
685 {
686    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
687    Widget_Data *wd = elm_widget_data_get(obj);
688    if (!wd) return NULL;
689    return wd->indicator;
690 }
691
692 EAPI void
693 elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
694 {
695    ELM_CHECK_WIDTYPE(obj, widtype);
696    Widget_Data *wd = elm_widget_data_get(obj);
697    if (!wd) return;
698    horizontal = !!horizontal;
699    if (wd->horizontal == horizontal) return;
700    wd->horizontal = horizontal;
701    _theme_hook(obj);
702 }
703
704 EAPI Eina_Bool
705 elm_slider_horizontal_get(const Evas_Object *obj)
706 {
707    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
708    Widget_Data *wd = elm_widget_data_get(obj);
709    if (!wd) return EINA_FALSE;
710    return wd->horizontal;
711 }
712
713 EAPI void
714 elm_slider_min_max_set(Evas_Object *obj, double min, double max)
715 {
716    ELM_CHECK_WIDTYPE(obj, widtype);
717    Widget_Data *wd = elm_widget_data_get(obj);
718    if (!wd) return;
719    if ((wd->val_min == min) && (wd->val_max == max)) return;
720    wd->val_min = min;
721    wd->val_max = max;
722    if (wd->val < wd->val_min) wd->val = wd->val_min;
723    if (wd->val > wd->val_max) wd->val = wd->val_max;
724    _val_set(obj);
725    _units_set(obj);
726    _indicator_set(obj);
727 }
728
729 EAPI void
730 elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max)
731 {
732    if (min) *min = 0.0;
733    if (max) *max = 0.0;
734    ELM_CHECK_WIDTYPE(obj, widtype);
735    Widget_Data *wd = elm_widget_data_get(obj);
736    if (!wd) return;
737    if (min) *min = wd->val_min;
738    if (max) *max = wd->val_max;
739 }
740
741 EAPI void
742 elm_slider_value_set(Evas_Object *obj, double val)
743 {
744    ELM_CHECK_WIDTYPE(obj, widtype);
745    Widget_Data *wd = elm_widget_data_get(obj);
746    if (!wd) return;
747    if (wd->val == val) return;
748    wd->val = val;
749    if (wd->val < wd->val_min) wd->val = wd->val_min;
750    if (wd->val > wd->val_max) wd->val = wd->val_max;
751    _val_set(obj);
752    _units_set(obj);
753    _indicator_set(obj);
754 }
755
756 EAPI double
757 elm_slider_value_get(const Evas_Object *obj)
758 {
759    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
760    Widget_Data *wd = elm_widget_data_get(obj);
761    if (!wd) return 0.0;
762    return wd->val;
763 }
764
765 EAPI void
766 elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted)
767 {
768    ELM_CHECK_WIDTYPE(obj, widtype);
769    Widget_Data *wd = elm_widget_data_get(obj);
770    if (!wd) return;
771    inverted = !!inverted;
772    if (wd->inverted == inverted) return;
773    wd->inverted = inverted;
774    if (wd->inverted)
775      edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
776    else
777      edje_object_signal_emit(wd->slider, "elm,state,inverted,off", "elm");
778    edje_object_message_signal_process(wd->slider);
779    _val_set(obj);
780    _units_set(obj);
781    _indicator_set(obj);
782 }
783
784 EAPI Eina_Bool
785 elm_slider_inverted_get(const Evas_Object *obj)
786 {
787    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
788    Widget_Data *wd = elm_widget_data_get(obj);
789    if (!wd) return EINA_FALSE;
790    return wd->inverted;
791 }
792
793 EAPI void
794 elm_slider_indicator_format_function_set(Evas_Object *obj, const char *(*func)(double val), void (*free_func)(const char *str))
795 {
796    ELM_CHECK_WIDTYPE(obj, widtype);
797    Widget_Data *wd = elm_widget_data_get(obj);
798    if (!wd) return;
799    wd->indicator_format_func = func;
800    wd->indicator_format_free = free_func;
801    _indicator_set(obj);
802 }
803
804 EAPI void
805 elm_slider_units_format_function_set(Evas_Object *obj, const char *(*func)(double val), void (*free_func)(const char *str))
806 {
807    ELM_CHECK_WIDTYPE(obj, widtype);
808    Widget_Data *wd = elm_widget_data_get(obj);
809    if (!wd) return;
810    wd->units_format_func = func;
811    wd->units_format_free = free_func;
812    _indicator_set(obj);
813 }
814
815 EAPI void
816 elm_slider_end_set(Evas_Object *obj, Evas_Object *end)
817 {
818    ELM_CHECK_WIDTYPE(obj, widtype);
819    Widget_Data *wd = elm_widget_data_get(obj);
820    if (!wd) return;
821    if (wd->end == end) return;
822    if (wd->end) evas_object_del(wd->end);
823    wd->end = end;
824    if (end)
825      {
826         elm_widget_sub_object_add(obj, end);
827         evas_object_event_callback_add(end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
828                                        _changed_size_hints, obj);
829         edje_object_part_swallow(wd->slider, "elm.swallow.end", end);
830         edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
831         edje_object_message_signal_process(wd->slider);
832      }
833    _sizing_eval(obj);
834 }
835
836 EAPI Evas_Object *
837 elm_slider_end_unset(Evas_Object *obj)
838 {
839    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
840    Widget_Data *wd = elm_widget_data_get(obj);
841    Evas_Object *ret = NULL;
842    if (!wd) return NULL;
843    if (wd->end)
844      {
845         elm_widget_sub_object_del(obj, wd->end);
846         ret = wd->end;
847         edje_object_part_unswallow(wd->slider, wd->end);
848         edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
849         wd->end = NULL;
850         _sizing_eval(obj);
851      }
852    return ret;
853 }
854
855 EAPI Evas_Object *
856 elm_slider_end_get(const Evas_Object *obj)
857 {
858    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
859    Widget_Data *wd = elm_widget_data_get(obj);
860    if (!wd) return NULL;
861    return wd->end;
862 }
863
864 EAPI void
865 elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show)
866 {
867    ELM_CHECK_WIDTYPE(obj, widtype);
868    Widget_Data *wd = elm_widget_data_get(obj);
869    if (show) {
870         wd->indicator_show = EINA_TRUE;
871         edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
872    }
873    else {
874         wd->indicator_show = EINA_FALSE;
875         edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
876    }
877 }
878
879 EAPI Eina_Bool
880 elm_slider_indicator_show_get(const Evas_Object *obj)
881 {
882    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
883    Widget_Data *wd = elm_widget_data_get(obj);
884    if (!wd) return EINA_FALSE;
885    return wd->indicator_show;
886 }
887