Merge branch 'master' of wh0705.jung@165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL...
[framework/uifw/elementary.git] / src / lib / elm_slider.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Slider Slider
6  * @ingroup Elementary
7  *
8  * The slider adds a dragable “slider” widget for selecting the value of
9  * something within a range.
10  *
11  * Signals that you can add callbacks for are:
12  *
13  * changed - Whenever the slider value is changed by the user.
14  *
15  * delay,changed - A short time after the value is changed by the user.
16  * This will be called only when the user stops dragging for a very short
17  * period or when they release their finger/mouse, so it avoids possibly
18  * expensive reactions to the value change.
19  *
20  * slider,drag,start - dragging the slider indicator around has started
21  *
22  * slider,drag,stop - dragging the slider indicator around has stopped
23  *
24  * A slider can be horizontal or vertical. It can contain an Icon and has a
25  * primary label as well as a units label (that is formatted with floating
26  * point values and thus accepts a printf-style format string, like
27  * “%1.2f units”. There is also an indicator string that may be somewhere
28  * else (like on the slider itself) that also accepts a format string like
29  * units. Label, Icon Unit and Indicator strings/objects are optional.
30  *
31  * A slider may be inverted which means values invert, with high vales being
32  * on the left or top and low values on the right or bottom (as opposed to
33  * normally being low on the left or top and high on the bottom and right).
34  *
35  * The slider should have its minimum and maximum values set by the
36  * application with  elm_slider_min_max_set() and value should also be set by
37  * the application before use with  elm_slider_value_set(). The span of the
38  * slider is its length (horizontally or vertically). This will be scaled by
39  * the object or applications scaling factor. At any point code can query the
40  * slider for its value with elm_slider_value_get().
41  */
42
43 typedef struct _Widget_Data Widget_Data;
44
45 struct _Widget_Data
46 {
47         Evas_Object *slider;
48         Evas_Object *icon;      
49         Evas_Object *spacer;
50         const char *label;
51         const char *e_label;
52         const char *units;
53         const char *indicator;
54         const char *(*indicator_format_func)(double val);
55         Eina_Bool horizontal : 1;
56         Eina_Bool inverted : 1;
57         double val, val_min, val_max;
58         Ecore_Timer *delay;
59         Evas_Coord size;
60         /* for supporting aqua feature */
61         Ecore_Timer *mv_timer;
62         Evas_Object *e_icon;
63         double src_val;
64         double des_val;
65         double mv_step;
66 };
67
68 #define SLIDER_THUMB_MOVE_STEP 100
69
70 static void _del_hook(Evas_Object *obj);
71 static void _theme_hook(Evas_Object *obj);
72 static void _sizing_eval(Evas_Object *obj);
73 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
74 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
75 static void _units_set(Evas_Object *obj);
76 static void _indicator_set(Evas_Object *obj);
77
78 /* supporting aqua feature */
79 static _mv_timer_cb(void *data);
80
81 static const char SIG_CHANGED[] = "changed";
82 static const char SIG_DELAY_CHANGED[] = "delay,changed";
83 static const char SIG_DRAG_START[] = "slider,drag,start";
84 static const char SIG_DRAG_STOP[] = "slider,drag,stop";
85 static const Evas_Smart_Cb_Description _signals[] = {
86   {SIG_CHANGED, ""},
87   {SIG_DELAY_CHANGED, ""},
88   {SIG_DRAG_START, ""},
89   {SIG_DRAG_STOP, ""},
90   {NULL, NULL}
91 };
92
93 static void
94 _del_hook(Evas_Object *obj)
95 {
96    Widget_Data *wd = elm_widget_data_get(obj);
97    if (!wd) return;
98    if (wd->label) eina_stringshare_del(wd->label);
99    if (wd->e_label) eina_stringshare_del(wd->label);
100    if (wd->indicator) eina_stringshare_del(wd->units);
101    if (wd->delay) ecore_timer_del(wd->delay);
102    free(wd);
103 }
104
105 static void
106 _theme_hook(Evas_Object *obj)
107 {
108    Widget_Data *wd = elm_widget_data_get(obj);
109    if (!wd) return;
110    if (wd->horizontal)
111      _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", elm_widget_style_get(obj));
112    else
113      _elm_theme_object_set(obj, wd->slider, "slider", "vertical", elm_widget_style_get(obj));
114    if (wd->inverted)
115      edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
116    else
117      edje_object_signal_emit(wd->slider, "elm,state,inverted,off", "elm");
118    if (wd->icon)
119      edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
120    else
121      edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
122    if (wd->e_icon)
123      edje_object_signal_emit(wd->slider, "elm,state,eicon,visible", "elm");
124    else
125      edje_object_signal_emit(wd->slider, "elm,state,eicon,hidden", "elm");
126    if (wd->label)
127      edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
128    else
129      edje_object_signal_emit(wd->slider, "elm,state,text,hidden", "elm");
130    edje_object_part_text_set(wd->slider, "elm.text", wd->label);
131    if (wd->e_label)
132      edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
133    else
134      edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
135    edje_object_part_text_set(wd->slider, "elm.text", wd->e_label);
136    if (wd->units)
137      edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
138    else
139      edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
140    if (wd->horizontal)
141      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
142    else
143      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
144    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
145    _units_set(obj);
146    edje_object_message_signal_process(wd->slider);
147    edje_object_scale_set(wd->slider, elm_widget_scale_get(obj) * _elm_config->scale);
148    _sizing_eval(obj);
149 }
150
151 static void
152 _sizing_eval(Evas_Object *obj)
153 {   
154    Widget_Data *wd = elm_widget_data_get(obj);
155    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
156    if (!wd) return;
157    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
158    edje_object_size_min_restricted_calc(wd->slider, &minw, &minh, minw, minh);
159    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
160    evas_object_size_hint_min_set(obj, minw, minh);
161    evas_object_size_hint_max_set(obj, maxw, maxh);
162 }
163
164 static void
165 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
166 {
167    Widget_Data *wd = elm_widget_data_get(data);
168    if (!wd) return;
169
170    // if (obj != wd->icon) return;
171   /*supporting aqua feature*/
172    if (obj != wd->icon && obj != wd->e_icon) return;
173
174    _sizing_eval(data);
175 }
176
177 static void
178 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
179 {
180    Widget_Data *wd = elm_widget_data_get(obj);
181    Evas_Object *sub = event_info;
182    if (!wd) return;
183    if (sub == wd->icon)
184     {
185         edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
186         evas_object_event_callback_del_full
187           (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
188         wd->icon = NULL;
189         _sizing_eval(obj);
190      }
191     /*supporting aqua feature*/
192     if (sub == wd->e_icon)
193     {
194         edje_object_signal_emit(wd->slider, "elm,state,eicon,hidden", "elm");
195         evas_object_event_callback_del_full
196          (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
197          wd->e_icon = NULL;
198         _sizing_eval(obj);
199     }
200 }
201
202 static int
203 _delay_change(void *data)
204 {
205    Widget_Data *wd = elm_widget_data_get(data);
206    if (!wd) return 0;
207    wd->delay = NULL;
208    evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, NULL);
209    return 0;
210 }
211
212 static void
213 _val_fetch(Evas_Object *obj)
214 {
215    Widget_Data *wd = elm_widget_data_get(obj);
216    double posx = 0.0, posy = 0.0, pos = 0.0, val;
217    if (!wd) return;
218    edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider",
219                                    &posx, &posy);
220    if (wd->horizontal) pos = posx;
221    else pos = posy;
222    if (wd->inverted) pos = 1.0 - pos;
223    val = (pos * (wd->val_max - wd->val_min)) + wd->val_min;
224    if (val != wd->val)
225      {
226         wd->val = val;
227         evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
228         if (wd->delay) ecore_timer_del(wd->delay);
229         wd->delay = ecore_timer_add(0.2, _delay_change, obj);
230      }
231 }
232
233 static void
234 _val_set(Evas_Object *obj)
235 {
236    Widget_Data *wd = elm_widget_data_get(obj);
237    double pos;
238    if (!wd) return;
239    if (wd->val_max > wd->val_min)
240      pos = (wd->val - wd->val_min) / (wd->val_max - wd->val_min);
241    else
242      pos = 0.0;
243    if (pos < 0.0) pos = 0.0;
244    else if (pos > 1.0) pos = 1.0;
245    if (wd->inverted) pos = 1.0 - pos;
246    edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", pos, pos);
247 }
248
249 static void
250 _units_set(Evas_Object *obj)
251 {
252    Widget_Data *wd = elm_widget_data_get(obj);
253    if (!wd) return;
254    if (wd->units)
255      {
256         char buf[1024];
257
258         snprintf(buf, sizeof(buf), wd->units, wd->val);
259         edje_object_part_text_set(wd->slider, "elm.units", buf);
260      }
261    else if (wd->e_label)
262      edje_object_part_text_set(wd->slider, "elm.units", wd->e_label);
263    else
264      edje_object_part_text_set(wd->slider, "elm.units", NULL);
265 }
266
267 static void
268 _indicator_set(Evas_Object *obj)
269 {
270    Widget_Data *wd = elm_widget_data_get(obj);
271    if (!wd) return;
272    if (wd->indicator_format_func)
273      {
274         const char *buf;
275         buf = wd->indicator_format_func(wd->val);
276         edje_object_part_text_set(wd->slider, "elm.indicator", buf);
277      }
278    else if (wd->indicator)
279      {
280         char buf[1024];
281         snprintf(buf, sizeof(buf), wd->indicator, wd->val);
282         edje_object_part_text_set(wd->slider, "elm.indicator", buf);
283      }
284    else
285      edje_object_part_text_set(wd->slider, "elm.indicator", NULL);
286 }
287
288 static void
289 _drag(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
290 {
291     Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
292     /* supporting aqua feature : delete thumb move timer when drag event occured to the moving thumb */
293     if(wd->mv_timer){
294         ecore_timer_del(wd->mv_timer);
295           wd->mv_timer = NULL;
296     }
297    _val_fetch(data);
298    _units_set(data);
299    _indicator_set(data);
300 }
301
302 static void
303 _drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
304 {
305         Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
306         /* supporting aqua feature : delete thumb move timer when drag event occured to the moving thumb */
307         if(wd->mv_timer){
308                 ecore_timer_del(wd->mv_timer);
309                 wd->mv_timer = NULL;
310         }
311    _val_fetch(data);
312    evas_object_smart_callback_call(data, SIG_DRAG_START, NULL);
313    _units_set(data);
314    _indicator_set(data);
315 }
316
317 static void
318 _drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
319 {
320    _val_fetch(data);
321    evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
322    _units_set(data);
323    _indicator_set(data);
324 }
325
326 static void
327 _drag_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
328 {
329    Widget_Data *wd = elm_widget_data_get(data);
330    edje_object_part_drag_step(wd->slider, "elm.dragable.slider", -0.05, -0.05);
331 }
332
333 static void
334 _drag_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
335 {
336    Widget_Data *wd = elm_widget_data_get(data);
337    edje_object_part_drag_step(wd->slider, "elm.dragable.slider", 0.05, 0.05);
338 }
339
340 static const char*widtype = NULL;
341
342 /**
343  * Add a new slider to the parent
344  *
345  * @param parent The parent object
346  * @return The new object or NULL if it cannot be created
347  *
348  * @ingroup Slider
349  */
350 EAPI Evas_Object *
351 elm_slider_add(Evas_Object *parent)
352 {
353    Evas_Object *obj;
354    Evas *e;
355    Widget_Data *wd;
356
357    wd = ELM_NEW(Widget_Data);
358    e = evas_object_evas_get(parent);
359    obj = elm_widget_add(e);
360    ELM_SET_WIDTYPE(widtype, "slider");
361    elm_widget_type_set(obj, "slider");
362    elm_widget_sub_object_add(parent, obj);
363    elm_widget_data_set(obj, wd);
364    elm_widget_del_hook_set(obj, _del_hook);
365    elm_widget_theme_hook_set(obj, _theme_hook);
366
367    wd->horizontal = EINA_TRUE;
368    wd->val = 0.0;
369    wd->val_min = 0.0;
370    wd->val_max = 1.0;
371
372     /* supporting aqua feature */
373     wd->mv_step = (double)((wd->val_max - wd->val_min) / (double)SLIDER_THUMB_MOVE_STEP);
374
375    wd->slider = edje_object_add(e);
376    _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", "default");
377    elm_widget_resize_object_set(obj, wd->slider);
378    edje_object_signal_callback_add(wd->slider, "drag", "*", _drag, obj);
379    edje_object_signal_callback_add(wd->slider, "drag,start", "*", _drag_start, obj);
380    edje_object_signal_callback_add(wd->slider, "drag,stop", "*", _drag_stop, obj);
381    edje_object_signal_callback_add(wd->slider, "drag,step", "*", _drag_stop, obj);
382    edje_object_signal_callback_add(wd->slider, "drag,page", "*", _drag_stop, obj);
383 //   edje_object_signal_callback_add(wd->slider, "drag,set", "*", _drag_stop, obj);
384    edje_object_signal_callback_add(wd->slider, "mouse,wheel,0,-1", "*", _drag_up, obj);
385    edje_object_signal_callback_add(wd->slider, "mouse,wheel,0,1", "*", _drag_down, obj);
386    edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", 0.0, 0.0);
387
388    wd->spacer = evas_object_rectangle_add(e);
389    evas_object_color_set(wd->spacer, 0, 0, 0, 0);
390    evas_object_pass_events_set(wd->spacer, 1);
391    elm_widget_sub_object_add(obj, wd->spacer);
392    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
393
394    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
395
396    _sizing_eval(obj);
397
398    // TODO: convert Elementary to subclassing of Evas_Smart_Class
399    // TODO: and save some bytes, making descriptions per-class and not instance!
400    evas_object_smart_callbacks_descriptions_set(obj, _signals);
401    return obj;
402 }
403
404 /**
405  * Set the label of the slider
406  *
407  * @param obj The slider object
408  * @param label The text label string in UTF-8
409  *
410  * @ingroup Slider
411  */
412 EAPI void
413 elm_slider_label_set(Evas_Object *obj, const char *label)
414 {
415    ELM_CHECK_WIDTYPE(obj, widtype);
416    Widget_Data *wd = elm_widget_data_get(obj);
417    if (!wd) return;
418    eina_stringshare_replace(&wd->label, label);
419    if (label)
420      {
421         edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
422         edje_object_message_signal_process(wd->slider);
423      }
424    else
425      {
426         edje_object_signal_emit(wd->slider, "elm,state,text,hidden", "elm");
427         edje_object_message_signal_process(wd->slider);
428      }
429    edje_object_part_text_set(wd->slider, "elm.text", label);
430    _sizing_eval(obj);
431 }
432
433 /**
434  * Get the label of the slider
435  *
436  * @param obj The slider object
437  * @return The text label string in UTF-8
438  *
439  * @ingroup Slider
440  */
441 EAPI const char *
442 elm_slider_label_get(const Evas_Object *obj)
443 {
444    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
445    Widget_Data *wd = elm_widget_data_get(obj);
446    if (!wd) return NULL;
447    return wd->label;
448 }
449
450 /**
451  * Set the icon object of the slider object
452  *
453  * Once the icon object is set, it will become a child of the slider object and
454  * be deleted when the slider object is deleted. If another icon object is set
455  * then the previous one becomes orophaned and will no longer be deleted along
456  * with the slider.
457  *
458  * @param obj The slider object
459  * @param icon The icon object
460  *
461  * @ingroup Slider
462  */
463 EAPI void
464 elm_slider_icon_set(Evas_Object *obj, Evas_Object *icon)
465 {
466    ELM_CHECK_WIDTYPE(obj, widtype);
467    Widget_Data *wd = elm_widget_data_get(obj);
468    if (!wd) return;
469    if ((wd->icon != icon) && (wd->icon))
470      elm_widget_sub_object_del(obj, wd->icon);
471    wd->icon = icon;
472    if (icon)
473      {
474         elm_widget_sub_object_add(obj, icon);
475         evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
476                                        _changed_size_hints, obj);
477         edje_object_part_swallow(wd->slider, "elm.swallow.content", icon);
478         edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
479         _sizing_eval(obj);
480      }
481 }
482
483 /**
484  * Get the icon object of the slider object
485  *
486  * @param obj The slider object
487  * @return The icon object
488  *
489  * @ingroup Slider
490  */
491 EAPI Evas_Object *
492 elm_slider_icon_get(const Evas_Object *obj)
493 {
494    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
495    Widget_Data *wd = elm_widget_data_get(obj);
496    if (!wd) return NULL;
497    return wd->icon;
498 }
499
500 /**
501  * Set the length of the dragable region of the slider
502  *
503  * This sets the minimum width or height (depending on orientation) of the
504  * area of the slider that allows the slider to be dragged around. This in
505  * turn affects the objects minimum size (along with icon label and unit
506  * text). Note that this will also get multiplied by the scale factor.
507  *
508  * @param obj The slider object
509  * @param size The length of the slider area
510  *
511  * @ingroup Slider
512  */
513 EAPI void
514 elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size)
515 {
516    ELM_CHECK_WIDTYPE(obj, widtype);
517    Widget_Data *wd = elm_widget_data_get(obj);
518    if (!wd) return;
519    if (wd->size == size) return;
520    wd->size = size;
521    if (wd->horizontal)
522      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
523    else
524      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
525    edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
526    _sizing_eval(obj);
527 }
528
529 /**
530  * Get the length of the dragable region of the slider
531  *
532  * This gets the minimum width or height (depending on orientation) of
533  * the area of the slider that allows the slider to be dragged
534  * around. Note that this will also get multiplied by the scale
535  * factor.
536  *
537  * @param obj The slider object
538  * @return The length of the slider area
539  *
540  * @ingroup Slider
541  */
542 EAPI Evas_Coord
543 elm_slider_span_size_get(const Evas_Object *obj)
544 {
545    ELM_CHECK_WIDTYPE(obj, widtype) 0;
546    Widget_Data *wd = elm_widget_data_get(obj);
547    if (!wd) return 0;
548    return wd->size;
549 }
550
551 /**
552  * Set the format string of the unit area
553  *
554  * If NULL, this disabls the unit area display. If not it sets the format
555  * string for the unit text. The unit text is provided a floating point
556  * value, so the unit text can display up to 1 floating point value. Note that
557  * this is optional. Use a format string such as "%1.2f meters" for example.
558  *
559  * @param obj The slider object
560  * @param units The format string for the units display
561  *
562  * @ingroup Slider
563  */
564 EAPI void
565 elm_slider_unit_format_set(Evas_Object *obj, const char *units)
566 {
567    ELM_CHECK_WIDTYPE(obj, widtype);
568    Widget_Data *wd = elm_widget_data_get(obj);
569    if (!wd) return;
570    eina_stringshare_replace(&wd->units, units);
571    if (units)
572      {
573         edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
574         edje_object_message_signal_process(wd->slider);
575      }
576    else
577      {
578         edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
579         edje_object_message_signal_process(wd->slider);
580      }
581    _units_set(obj);
582    _sizing_eval(obj);
583 }
584
585 /**
586  * Get the format string for the unit area
587  *
588  * The slider may also display a value (the value of the slider) somewhere
589  * (for example above the slider knob that is dragged around). This sets the
590  * format string for this. See elm_slider_unit_format_set() for more
591  * information on how this works.
592  *
593  * @param obj The slider object
594  * @return The format string for the unit display.
595  *
596  * @ingroup Slider
597  */
598 EAPI const char *
599 elm_slider_unit_format_get(const Evas_Object *obj)
600 {
601    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
602    Widget_Data *wd = elm_widget_data_get(obj);
603    if (!wd) return NULL;
604    return wd->units;
605 }
606
607 /**
608  * Set the format string for the indicator area
609  *
610  * The slider may also display a value (the value of the slider) somewhere
611  * (for example above the slider knob that is dragged around). This sets the
612  * format string for this. See elm_slider_unit_format_set() for more
613  * information on how this works.
614  *
615  * @param obj The slider object
616  * @param indicator The format string for the indicator display
617  *
618  * @ingroup Slider
619  */
620 EAPI void
621 elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator)
622 {
623    ELM_CHECK_WIDTYPE(obj, widtype);
624    Widget_Data *wd = elm_widget_data_get(obj);
625    if (!wd) return;
626    eina_stringshare_replace(&wd->indicator, indicator);
627    _indicator_set(obj);
628 }
629
630 /**
631  * Get the format string for the indicator area
632  *
633  * The slider may also display a value (the value of the slider) somewhere
634  * (for example above the slider knob that is dragged around). This sets the
635  * format string for this. See elm_slider_indicator_format_set() for more
636  * information on how this works.
637  *
638  * @param obj The slider object
639  * @return The format string for the indicator display.
640  *
641  * @ingroup Slider
642  */
643 EAPI const char *
644 elm_slider_indicator_format_get(const Evas_Object *obj)
645 {
646    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
647    Widget_Data *wd = elm_widget_data_get(obj);
648    if (!wd) return NULL;
649    return wd->indicator;
650 }
651
652 /**
653  * Set orientation of the slider
654  *
655  * @param obj The slider object
656  * @param horizontal If set, the slider will be horizontal
657  *
658  * @ingroup Slider
659  */
660 EAPI void
661 elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
662 {
663    ELM_CHECK_WIDTYPE(obj, widtype);
664    Widget_Data *wd = elm_widget_data_get(obj);
665    if (!wd) return;
666    horizontal = !!horizontal;
667    if (wd->horizontal == horizontal) return;
668    wd->horizontal = horizontal;
669    _theme_hook(obj);
670 }
671
672 /**
673  * Get orientation of the slider
674  *
675  * @param obj The slider object
676  * @return If @c EINA_TRUE the slider will be horizontal, else it is
677  *         vertical.
678  * @ingroup Slider
679  */
680 EAPI Eina_Bool
681 elm_slider_horizontal_get(const Evas_Object *obj)
682 {
683    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
684    Widget_Data *wd = elm_widget_data_get(obj);
685    if (!wd) return EINA_FALSE;
686    return wd->horizontal;
687 }
688
689 /**
690  * Set the minimum and maximum values for the slider
691  *
692  * Maximum mut be greater than minimum.
693  *
694  * @param obj The slider object
695  * @param min The minimum value
696  * @param max The maximum value
697  *
698  * @ingroup Slider
699  */
700 EAPI void
701 elm_slider_min_max_set(Evas_Object *obj, double min, double max)
702 {
703    ELM_CHECK_WIDTYPE(obj, widtype);
704    Widget_Data *wd = elm_widget_data_get(obj);
705    if (!wd) return;
706    if ((wd->val_min == min) && (wd->val_max == max)) return;
707    wd->val_min = min;
708    wd->val_max = max;
709
710         /* supporting aqua feature */
711         wd->mv_step = (double)((wd->val_max - wd->val_min) / (double)SLIDER_THUMB_MOVE_STEP);
712
713    if (wd->val < wd->val_min) wd->val = wd->val_min;
714    if (wd->val > wd->val_max) wd->val = wd->val_max;
715    _val_set(obj);
716    _units_set(obj);
717    _indicator_set(obj);
718 }
719
720 /**
721  * Get the minimum and maximum values for the slider
722  *
723  * @param obj The slider object
724  * @param min The pointer to store minimum value, may be @c NULL.
725  * @param max The pointer to store maximum value, may be @c NULL.
726  *
727  * @ingroup Slider
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 /**
742  * Set the value the slider indicates
743  *
744  * @param obj The slider object
745  * @param val The value (must be beween min and max for the slider)
746  *
747  * @ingroup Slider
748  */
749 EAPI void
750 elm_slider_value_set(Evas_Object *obj, double val)
751 {
752    ELM_CHECK_WIDTYPE(obj, widtype);
753    Widget_Data *wd = elm_widget_data_get(obj);
754    if (!wd) return;
755    if (wd->val == val) return;
756    wd->val = val;
757    if (wd->val < wd->val_min) wd->val = wd->val_min;
758    if (wd->val > wd->val_max) wd->val = wd->val_max;
759    _val_set(obj);
760    _units_set(obj);
761    _indicator_set(obj);
762 }
763
764 /**
765  * Get the value the slider has
766  *
767  * @param obj The slider object
768  * @return The value of the slider
769  *
770  * @ingroup Slider
771  */
772 EAPI double
773 elm_slider_value_get(const Evas_Object *obj)
774 {
775    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
776    Widget_Data *wd = elm_widget_data_get(obj);
777    if (!wd) return 0.0;
778    return wd->val;
779 }
780
781 /**
782  * Invert the slider display
783  *
784  * Normally the slider will display and interpret values from low to high
785  * and when horizontal that is left to right. When vertical that is top
786  * to bottom. This inverts this (so from right to left or bottom to top) if
787  * inverted is set to 1.
788  *
789  * @param obj The slider object
790  * @param inverted The inverted flag. 1 == inverted, 0 == normal
791  *
792  * @ingroup Slider
793  */
794 EAPI void
795 elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted)
796 {
797    ELM_CHECK_WIDTYPE(obj, widtype);
798    Widget_Data *wd = elm_widget_data_get(obj);
799    if (!wd) return;
800    inverted = !!inverted;
801    if (wd->inverted == inverted) return;
802    wd->inverted = inverted;
803    if (wd->inverted)
804      edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
805    else
806      edje_object_signal_emit(wd->slider, "elm,state,inverted,off", "elm");
807    edje_object_message_signal_process(wd->slider);
808    _val_set(obj);
809    _units_set(obj);
810    _indicator_set(obj);
811 }
812
813 /**
814  * Get if the slider display is inverted (backwards)
815  *
816  * @param obj The slider object
817  * @return If @c EINA_TRUE the slider will be inverted.
818  * @ingroup Slider
819  */
820 EAPI Eina_Bool
821 elm_slider_inverted_get(const Evas_Object *obj)
822 {
823    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
824    Widget_Data *wd = elm_widget_data_get(obj);
825    if (!wd) return EINA_FALSE;
826    return wd->inverted;
827 }
828
829 /**
830  * Set the format function pointer for the inducator area
831  *
832  * Set the callback function to format the indicator string.
833  * See elm_slider_indicator_format_set() for more info on how this works.
834  *
835  * @param obj The slider object
836  * @param indicator The format string for the indicator display
837  * @param func The indicator format function
838  *
839  * @ingroup Slider
840  */
841 EAPI void
842 elm_slider_indicator_format_function_set(Evas_Object *obj, const char *(*func)(double val))
843 {
844    ELM_CHECK_WIDTYPE(obj, widtype);
845    Widget_Data *wd = elm_widget_data_get(obj);
846    if (!wd) return;
847    wd->indicator_format_func = func;
848    _indicator_set(obj);
849 }
850
851
852 //////////////////////////////////////////////////////////////////////////////////////////////////////
853 ////////////////////////  supporting beat feature  ///////////////////////////////////////////////////
854 //////////////////////////////////////////////////////////////////////////////////////////////////////
855
856
857
858 /**
859  * Set the right icon object of the slider object
860  *
861  * Once the right icon object is set, it will become a child of the slider object and
862  * be deleted when the slider object is deleted. If another icon object is set
863  * then the previous one becomes orophaned and will no longer be deleted along
864  * with the slider.
865  *
866  * @param obj The slider object
867  * @param icon The icon object
868  * 
869  * @return 1 if icon set succeed, 0 if there is no part for right icon 
870  * 
871  * @ingroup Slider
872  */
873 EAPI Eina_Bool 
874 elm_slider_end_icon_set(Evas_Object *obj, Evas_Object *icon)
875 {
876         Widget_Data *wd = elm_widget_data_get(obj);
877         
878         if ((wd->e_icon != icon) && (wd->e_icon))
879                 elm_widget_sub_object_del(obj, wd->e_icon);
880         
881         if (icon)
882         {
883                 if ( !(edje_object_part_swallow(wd->slider, "end_icon", icon)) )
884                         return EINA_FALSE;              
885                 wd->e_icon = icon;
886                 elm_widget_sub_object_add(obj, icon);
887                 evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
888                                 _changed_size_hints, obj);
889                 edje_object_signal_emit(wd->slider, "elm,state,eicon,visible", "elm");
890                 _sizing_eval(obj);
891         }
892         
893         return EINA_TRUE;
894 }
895
896
897 /**
898  * Get the right icon object of the slider object
899  *
900  * @param obj The slider object
901  * @return The right icon object
902  *
903  * @ingroup Slider
904  */
905 EAPI Evas_Object *
906 elm_slider_end_icon_get(Evas_Object *obj)
907 {
908         Widget_Data *wd = elm_widget_data_get(obj);
909         if (!wd) return NULL;
910         return wd->e_icon;
911 }
912
913
914 /**
915  * Set whether showing the number(indicator) or not.
916  *
917  * @param obj The slider object
918  * @param show 1 will show the number, 0 will not.
919  *
920  * @ingroup Slider
921  */
922 EAPI void
923 elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show)
924 {
925         Widget_Data *wd = elm_widget_data_get(obj);
926         if(show)
927                 edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
928         else
929                 edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");                       
930 }
931
932
933
934 static _mv_timer_cb(void *data)
935 {
936         Evas_Object* obj = (Evas_Object*)data;
937         Widget_Data *wd = elm_widget_data_get(obj);
938         
939         if (!wd) return EINA_TRUE;
940         
941         if(wd->src_val < wd->des_val) {
942                 wd->src_val += wd->mv_step;
943                 if(wd-> src_val > wd->des_val)  
944                         wd->src_val = wd->des_val;
945         }       
946         
947         else if (wd->src_val > wd->des_val) {
948                 wd->src_val -= wd->mv_step;
949                 if(wd->src_val < wd->des_val)   
950                         wd->src_val = wd->des_val;
951         }       
952                 
953         elm_slider_value_set(obj, wd->src_val);
954         evas_object_smart_callback_call(obj, "changed", NULL);
955
956         if (wd->val == wd->des_val ) {
957                 if(wd->mv_timer){
958                         ecore_timer_del(wd->mv_timer);
959                         wd->mv_timer = NULL;
960                 }       
961                 return EINA_FALSE;
962         }
963         else
964                 return EINA_TRUE;
965 }
966
967
968 /**
969  * Move the thumb to the specified value.
970  *
971  * This is different with elm_slider_value_set() in animated moving. 
972  * 
973  * @param obj The slider object
974  * @param val thumb's destination value.
975  *
976  * @ingroup Slider
977  */
978 EAPI void
979 elm_slider_value_animated_set(Evas_Object *obj, double val)
980 {
981         Widget_Data *wd = elm_widget_data_get(obj);
982         
983         if (wd->val == val) return;
984         
985         wd->src_val = wd->val;
986         wd->des_val = val;
987         if (wd->des_val < wd->val_min) wd->des_val = wd->val_min;       
988         if (wd->des_val > wd->val_max) wd->des_val = wd->val_max;
989
990         if(wd->mv_timer){
991                 ecore_timer_del(wd->mv_timer);
992                 wd->mv_timer = NULL;
993         }
994         
995         wd->mv_timer = ecore_timer_add(0.005, _mv_timer_cb, obj);       
996 }
997
998
999 /**
1000  * Set the label of the slider
1001  *
1002  * @param obj The slider object
1003  * @param label The text label string in UTF-8
1004  *
1005  * @ingroup Slider
1006  */
1007 EAPI void
1008 elm_slider_end_label_set(Evas_Object *obj, const char *label)
1009 {
1010    ELM_CHECK_WIDTYPE(obj, widtype);
1011    Widget_Data *wd = elm_widget_data_get(obj);
1012    if (!wd) return;
1013    eina_stringshare_replace(&wd->e_label, label);
1014    if (label)
1015      {
1016         edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
1017         edje_object_message_signal_process(wd->slider);
1018      }
1019    else
1020      {
1021         edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
1022         edje_object_message_signal_process(wd->slider);
1023      }
1024    edje_object_part_text_set(wd->slider, "elm.units", label);
1025    if(wd->units)
1026            wd->units = NULL;
1027    _sizing_eval(obj);
1028 }
1029
1030 /**
1031  * Get the label of the slider
1032  *
1033  * @param obj The slider object
1034  * @return The text label string in UTF-8
1035  *
1036  * @ingroup Slider
1037  */
1038 EAPI const char *
1039 elm_slider_end_label_get(const Evas_Object *obj)
1040 {
1041    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1042    Widget_Data *wd = elm_widget_data_get(obj);
1043    if (!wd) return NULL;
1044    return wd->e_label;
1045 }