elementary/map - map supports language,changed
[framework/uifw/elementary.git] / src / lib / elm_progressbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_progressbar.h"
4
5 EAPI const char ELM_PROGRESSBAR_SMART_NAME[] = "elm_progressbar";
6
7 static const char SIG_CHANGED[] = "changed";
8
9 #define MIN_RATIO_LVL 0.0
10 #define MAX_RATIO_LVL 1.0
11
12 /* smart callbacks coming from elm progressbar objects (besides the
13  * ones coming from elm layout): */
14 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
15    {SIG_CHANGED, ""},
16    {NULL, NULL}
17 };
18
19 EVAS_SMART_SUBCLASS_NEW
20   (ELM_PROGRESSBAR_SMART_NAME, _elm_progressbar, Elm_Progressbar_Smart_Class,
21   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
22
23 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
24 {
25    {"icon", "elm.swallow.content"},
26    {NULL, NULL}
27 };
28
29 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
30 {
31    {"default", "elm.text"},
32    {NULL, NULL}
33 };
34
35 static void
36 _units_set(Evas_Object *obj)
37 {
38    ELM_PROGRESSBAR_DATA_GET(obj, sd);
39
40    if (sd->unit_format_func)
41      {
42         char *buf;
43
44         buf = sd->unit_format_func(sd->val);
45         elm_layout_text_set(obj, "elm.text.status", buf);
46         if (sd->unit_format_free) sd->unit_format_free(buf);
47      }
48    else if (sd->units)
49      {
50         char buf[1024];
51
52         snprintf(buf, sizeof(buf), sd->units, 100 * sd->val);
53         elm_layout_text_set(obj, "elm.text.status", buf);
54      }
55    else elm_layout_text_set(obj, "elm.text.status", NULL);
56 }
57
58 static void
59 _val_set(Evas_Object *obj)
60 {
61    Eina_Bool rtl;
62    double pos;
63
64    ELM_PROGRESSBAR_DATA_GET(obj, sd);
65
66    pos = sd->val;
67    rtl = elm_widget_mirrored_get(obj);
68
69    if ((!rtl && sd->inverted) ||
70        (rtl && ((!sd->horizontal && sd->inverted) ||
71                 (sd->horizontal && !sd->inverted))))
72      pos = MAX_RATIO_LVL - pos;
73
74    edje_object_part_drag_value_set
75      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.cur.progressbar", pos, pos);
76
77    elm_layout_signal_emit(obj, "elm,state,change", "elm");
78 }
79
80 static void
81 _elm_progressbar_smart_sizing_eval(Evas_Object *obj)
82 {
83    Evas_Coord minw = -1, minh = -1;
84
85    ELM_PROGRESSBAR_DATA_GET(obj, sd);
86
87    edje_object_size_min_restricted_calc
88      (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh);
89    evas_object_size_hint_min_set(obj, minw, minh);
90    evas_object_size_hint_max_set(obj, -1, -1);
91 }
92
93 /* FIXME: replicated from elm_layout just because progressbar's icon
94  * spot is elm.swallow.content, not elm.swallow.icon. Fix that
95  * whenever we can changed the theme API */
96 static void
97 _icon_signal_emit(Evas_Object *obj)
98 {
99    char buf[64];
100
101    snprintf(buf, sizeof(buf), "elm,state,icon,%s",
102             elm_layout_content_get(obj, "icon") ? "visible" : "hidden");
103
104    elm_layout_signal_emit(obj, buf, "elm");
105 }
106
107 /* FIXME: replicated from elm_layout just because progressbar's icon
108  * spot is elm.swallow.content, not elm.swallow.icon. Fix that
109  * whenever we can changed the theme API */
110 static Eina_Bool
111 _elm_progressbar_smart_sub_object_del(Evas_Object *obj,
112                                       Evas_Object *sobj)
113 {
114    if (!ELM_WIDGET_CLASS(_elm_progressbar_parent_sc)->sub_object_del
115          (obj, sobj))
116      return EINA_FALSE;
117
118    _icon_signal_emit(obj);
119
120    return EINA_TRUE;
121 }
122
123 /* FIXME: replicated from elm_layout just because progressbar's icon
124  * spot is elm.swallow.content, not elm.swallow.icon. Fix that
125  * whenever we can changed the theme API */
126 static Eina_Bool
127 _elm_progressbar_smart_content_set(Evas_Object *obj,
128                                    const char *part,
129                                    Evas_Object *content)
130 {
131    if (!ELM_CONTAINER_CLASS(_elm_progressbar_parent_sc)->content_set
132          (obj, part, content))
133      return EINA_FALSE;
134
135    _icon_signal_emit(obj);
136
137    return EINA_TRUE;
138 }
139
140 static Eina_Bool
141 _elm_progressbar_smart_theme(Evas_Object *obj)
142 {
143    ELM_PROGRESSBAR_DATA_GET(obj, sd);
144
145    if (sd->horizontal)
146      eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "horizontal");
147    else eina_stringshare_replace(&ELM_LAYOUT_DATA(sd)->group, "vertical");
148
149    if (!ELM_WIDGET_CLASS(_elm_progressbar_parent_sc)->theme(obj))
150      return EINA_FALSE;
151
152    if (sd->pulse)
153      elm_layout_signal_emit(obj, "elm,state,pulse", "elm");
154    else
155      elm_layout_signal_emit(obj, "elm,state,fraction", "elm");
156
157    if (sd->pulse_state)
158      elm_layout_signal_emit(obj, "elm,state,pulse,start", "elm");
159
160    if ((sd->units) && (!sd->pulse))
161      elm_layout_signal_emit(obj, "elm,state,units,visible", "elm");
162
163    if (sd->horizontal)
164      evas_object_size_hint_min_set
165        (sd->spacer, (double)sd->size * elm_widget_scale_get(obj) *
166        elm_config_scale_get(), 1);
167    else
168      evas_object_size_hint_min_set
169        (sd->spacer, 1, (double)sd->size * elm_widget_scale_get(obj) *
170        elm_config_scale_get());
171
172    if (sd->inverted)
173      elm_layout_signal_emit(obj, "elm,state,inverted,on", "elm");
174
175    _units_set(obj);
176    _val_set(obj);
177
178    /* FIXME: replicated from elm_layout just because progressbar's
179     * icon spot is elm.swallow.content, not elm.swallow.icon. Fix that
180     * whenever we can changed the theme API */
181    _icon_signal_emit(obj);
182
183    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
184
185    elm_layout_sizing_eval(obj);
186
187    return EINA_TRUE;
188 }
189
190 static char *
191 _access_info_cb(void *data __UNUSED__, Evas_Object *obj)
192 {
193    const char *txt = elm_widget_access_info_get(obj);
194
195    if (!txt) txt = elm_layout_text_get(obj, NULL);
196    if (txt) return strdup(txt);
197
198    return NULL;
199 }
200
201 static char *
202 _access_state_cb(void *data __UNUSED__, Evas_Object *obj)
203 {
204    char *ret;
205    Eina_Strbuf *buf;
206    buf = eina_strbuf_new();
207
208    const char *txt = elm_layout_text_get(obj, "elm.text.status");
209    if (txt) eina_strbuf_append(buf, txt);
210
211    if (elm_widget_disabled_get(obj))
212      eina_strbuf_append(buf, " state: disabled");
213
214    if (eina_strbuf_length_get(buf))
215      {
216         ret = eina_strbuf_string_steal(buf);
217         eina_strbuf_free(buf);
218         return ret;
219      }
220
221    eina_strbuf_free(buf);
222    return NULL;
223 }
224
225 static void
226 _elm_progressbar_smart_add(Evas_Object *obj)
227 {
228    EVAS_SMART_DATA_ALLOC(obj, Elm_Progressbar_Smart_Data);
229
230    ELM_WIDGET_CLASS(_elm_progressbar_parent_sc)->base.add(obj);
231
232    priv->horizontal = EINA_TRUE;
233    priv->inverted = EINA_FALSE;
234    priv->pulse = EINA_FALSE;
235    priv->pulse_state = EINA_FALSE;
236    priv->units = eina_stringshare_add("%.0f %%");
237    priv->val = MIN_RATIO_LVL;
238
239    elm_layout_theme_set
240      (obj, "progressbar", "horizontal", elm_widget_style_get(obj));
241
242    priv->spacer = evas_object_rectangle_add(evas_object_evas_get(obj));
243    evas_object_color_set(priv->spacer, 0, 0, 0, 0);
244    evas_object_pass_events_set(priv->spacer, EINA_TRUE);
245
246    elm_layout_content_set(obj, "elm.swallow.bar", priv->spacer);
247
248    _units_set(obj);
249    _val_set(obj);
250
251    elm_layout_sizing_eval(obj);
252
253    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
254      elm_widget_can_focus_set(obj, EINA_TRUE);
255
256    _elm_access_object_register(obj, ELM_WIDGET_DATA(priv)->resize_obj);
257    _elm_access_text_set
258      (_elm_access_object_get(obj), ELM_ACCESS_TYPE, E_("progressbar"));
259    _elm_access_callback_set
260      (_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
261    _elm_access_callback_set
262      (_elm_access_object_get(obj), ELM_ACCESS_STATE, _access_state_cb, priv);
263 }
264
265 static void
266 _elm_progressbar_smart_del(Evas_Object *obj)
267 {
268    ELM_PROGRESSBAR_DATA_GET(obj, sd);
269
270    if (sd->units) eina_stringshare_del(sd->units);
271
272    ELM_WIDGET_CLASS(_elm_progressbar_parent_sc)->base.del(obj);
273 }
274
275 static void
276 _elm_progressbar_smart_set_user(Elm_Progressbar_Smart_Class *sc)
277 {
278    ELM_WIDGET_CLASS(sc)->base.add = _elm_progressbar_smart_add;
279    ELM_WIDGET_CLASS(sc)->base.del = _elm_progressbar_smart_del;
280
281    ELM_WIDGET_CLASS(sc)->theme = _elm_progressbar_smart_theme;
282    ELM_WIDGET_CLASS(sc)->sub_object_del =
283      _elm_progressbar_smart_sub_object_del;
284
285    /* not a 'focus chain manager' */
286    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
287    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
288
289    ELM_CONTAINER_CLASS(sc)->content_set = _elm_progressbar_smart_content_set;
290
291    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_progressbar_smart_sizing_eval;
292
293    ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
294    ELM_LAYOUT_CLASS(sc)->text_aliases = _text_aliases;
295 }
296
297 EAPI const Elm_Progressbar_Smart_Class *
298 elm_progressbar_smart_class_get(void)
299 {
300    static Elm_Progressbar_Smart_Class _sc =
301      ELM_PROGRESSBAR_SMART_CLASS_INIT_NAME_VERSION(ELM_PROGRESSBAR_SMART_NAME);
302    static const Elm_Progressbar_Smart_Class *class = NULL;
303    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
304
305    if (class)
306      return class;
307
308    _elm_progressbar_smart_set(&_sc);
309    esc->callbacks = _smart_callbacks;
310    class = &_sc;
311
312    return class;
313 }
314
315 EAPI Evas_Object *
316 elm_progressbar_add(Evas_Object *parent)
317 {
318    Evas_Object *obj;
319
320    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
321
322    obj = elm_widget_add(_elm_progressbar_smart_class_new(), parent);
323    if (!obj) return NULL;
324
325    if (!elm_widget_sub_object_add(parent, obj))
326      ERR("could not add %p as sub object of %p", obj, parent);
327
328    return obj;
329 }
330
331 EAPI void
332 elm_progressbar_pulse_set(Evas_Object *obj,
333                           Eina_Bool pulse)
334 {
335    ELM_PROGRESSBAR_CHECK(obj);
336    ELM_PROGRESSBAR_DATA_GET(obj, sd);
337
338    pulse = !!pulse;
339    if (sd->pulse == pulse) return;
340
341    sd->pulse = pulse;
342
343    _elm_progressbar_smart_theme(obj);
344 }
345
346 EAPI Eina_Bool
347 elm_progressbar_pulse_get(const Evas_Object *obj)
348 {
349    ELM_PROGRESSBAR_CHECK(obj) EINA_FALSE;
350    ELM_PROGRESSBAR_DATA_GET(obj, sd);
351
352    return sd->pulse;
353 }
354
355 EAPI void
356 elm_progressbar_pulse(Evas_Object *obj,
357                       Eina_Bool state)
358 {
359    ELM_PROGRESSBAR_CHECK(obj);
360    ELM_PROGRESSBAR_DATA_GET(obj, sd);
361
362    state = !!state;
363    if ((!sd->pulse) && (sd->pulse_state == state)) return;
364
365    sd->pulse_state = state;
366
367    if (sd->pulse_state)
368      elm_layout_signal_emit(obj, "elm,state,pulse,start", "elm");
369    else
370      elm_layout_signal_emit(obj, "elm,state,pulse,stop", "elm");
371 }
372
373 EAPI void
374 elm_progressbar_value_set(Evas_Object *obj,
375                           double val)
376 {
377    ELM_PROGRESSBAR_CHECK(obj);
378    ELM_PROGRESSBAR_DATA_GET(obj, sd);
379
380    if (sd->val == val) return;
381
382    sd->val = val;
383    if (sd->val < MIN_RATIO_LVL) sd->val = MIN_RATIO_LVL;
384    if (sd->val > MAX_RATIO_LVL) sd->val = MAX_RATIO_LVL;
385
386    _val_set(obj);
387    _units_set(obj);
388    evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
389 }
390
391 EAPI double
392 elm_progressbar_value_get(const Evas_Object *obj)
393 {
394    ELM_PROGRESSBAR_CHECK(obj) 0.0;
395    ELM_PROGRESSBAR_DATA_GET(obj, sd);
396
397    return sd->val;
398 }
399
400 EAPI void
401 elm_progressbar_span_size_set(Evas_Object *obj,
402                               Evas_Coord size)
403 {
404    ELM_PROGRESSBAR_CHECK(obj);
405    ELM_PROGRESSBAR_DATA_GET(obj, sd);
406
407    if (sd->size == size) return;
408
409    sd->size = size;
410
411    if (sd->horizontal)
412      evas_object_size_hint_min_set
413        (sd->spacer, (double)sd->size * elm_widget_scale_get(obj) *
414        elm_config_scale_get(), 1);
415    else
416      evas_object_size_hint_min_set
417        (sd->spacer, 1, (double)sd->size * elm_widget_scale_get(obj) *
418        elm_config_scale_get());
419
420    elm_layout_sizing_eval(obj);
421 }
422
423 EAPI Evas_Coord
424 elm_progressbar_span_size_get(const Evas_Object *obj)
425 {
426    ELM_PROGRESSBAR_CHECK(obj) 0;
427    ELM_PROGRESSBAR_DATA_GET(obj, sd);
428
429    return sd->size;
430 }
431
432 EAPI void
433 elm_progressbar_unit_format_set(Evas_Object *obj,
434                                 const char *units)
435 {
436    ELM_PROGRESSBAR_CHECK(obj);
437    ELM_PROGRESSBAR_DATA_GET(obj, sd);
438
439    eina_stringshare_replace(&sd->units, units);
440    if (units)
441      {
442         elm_layout_signal_emit(obj, "elm,state,units,visible", "elm");
443         edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
444      }
445    else
446      {
447         elm_layout_signal_emit(obj, "elm,state,units,hidden", "elm");
448         edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
449      }
450
451    _units_set(obj);
452    elm_layout_sizing_eval(obj);
453 }
454
455 EAPI const char *
456 elm_progressbar_unit_format_get(const Evas_Object *obj)
457 {
458    ELM_PROGRESSBAR_CHECK(obj) NULL;
459    ELM_PROGRESSBAR_DATA_GET(obj, sd);
460
461    return sd->units;
462 }
463
464 EAPI void
465 elm_progressbar_unit_format_function_set(Evas_Object *obj, char *(func)(double), void (*free_func) (char *))
466 {
467    ELM_PROGRESSBAR_CHECK(obj);
468    ELM_PROGRESSBAR_DATA_GET(obj, sd);
469
470    sd->unit_format_func = func;
471    sd->unit_format_free = free_func;
472
473    _units_set(obj);
474    elm_layout_sizing_eval(obj);
475 }
476
477 EAPI void
478 elm_progressbar_horizontal_set(Evas_Object *obj,
479                                Eina_Bool horizontal)
480 {
481    ELM_PROGRESSBAR_CHECK(obj);
482    ELM_PROGRESSBAR_DATA_GET(obj, sd);
483
484    horizontal = !!horizontal;
485    if (sd->horizontal == horizontal) return;
486
487    sd->horizontal = horizontal;
488    _elm_progressbar_smart_theme(obj);
489 }
490
491 EAPI Eina_Bool
492 elm_progressbar_horizontal_get(const Evas_Object *obj)
493 {
494    ELM_PROGRESSBAR_CHECK(obj) EINA_FALSE;
495    ELM_PROGRESSBAR_DATA_GET(obj, sd);
496
497    return sd->horizontal;
498 }
499
500 EAPI void
501 elm_progressbar_inverted_set(Evas_Object *obj,
502                              Eina_Bool inverted)
503 {
504    ELM_PROGRESSBAR_CHECK(obj);
505    ELM_PROGRESSBAR_DATA_GET(obj, sd);
506
507    inverted = !!inverted;
508    if (sd->inverted == inverted) return;
509
510    sd->inverted = inverted;
511    if (sd->inverted)
512      elm_layout_signal_emit(obj, "elm,state,inverted,on", "elm");
513    else
514      elm_layout_signal_emit(obj, "elm,state,inverted,off", "elm");
515
516    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
517
518    _val_set(obj);
519    _units_set(obj);
520 }
521
522 EAPI Eina_Bool
523 elm_progressbar_inverted_get(const Evas_Object *obj)
524 {
525    ELM_PROGRESSBAR_CHECK(obj) EINA_FALSE;
526    ELM_PROGRESSBAR_DATA_GET(obj, sd);
527
528    return sd->inverted;
529 }