[entry] hide copypaste ctxpopup when a non-editable entry is unfocused
[framework/uifw/elementary.git] / src / lib / elm_progressbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define MIN_RATIO_LVL 0.0
5 #define MAX_RATIO_LVL 1.0
6
7 typedef struct _Widget_Data Widget_Data;
8
9 struct _Widget_Data
10 {
11    Evas_Object *progressbar;
12    Evas_Object *spacer;
13    Evas_Object *icon;
14    Evas_Coord size;
15    Eina_Bool horizontal : 1;
16    Eina_Bool inverted : 1;
17    Eina_Bool pulse : 1;
18    Eina_Bool pulse_state : 1;
19    const char *units;
20    const char *label;
21    double val;
22 };
23
24 static const char *widtype = NULL;
25 static void _del_hook(Evas_Object *obj);
26 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
27 static void _theme_hook(Evas_Object *obj);
28 static void _sizing_eval(Evas_Object *obj);
29 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
30 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
31 static void _units_set(Evas_Object *obj);
32 static void _val_set(Evas_Object *obj);
33
34 static void
35 _del_hook(Evas_Object *obj)
36 {
37    Widget_Data *wd = elm_widget_data_get(obj);
38    if (!wd) return;
39    if (wd->label) eina_stringshare_del(wd->label);
40    if (wd->units) eina_stringshare_del(wd->units);
41    free(wd);
42 }
43
44 static void
45 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
46 {
47    Widget_Data *wd = elm_widget_data_get(obj);
48    if (!wd) return;
49    edje_object_mirrored_set(wd->progressbar, rtl);
50 }
51
52 static void
53 _theme_hook(Evas_Object *obj)
54 {
55    Widget_Data *wd = elm_widget_data_get(obj);
56    if (!wd) return;
57    _elm_widget_mirrored_reload(obj);
58    _mirrored_set(obj, elm_widget_mirrored_get(obj));
59    if (wd->horizontal)
60      _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", elm_widget_style_get(obj));
61    else
62      _elm_theme_object_set(obj, wd->progressbar, "progressbar", "vertical", elm_widget_style_get(obj));
63
64    if (wd->icon)
65      {
66         edje_object_part_swallow(wd->progressbar, "elm.swallow.content", wd->icon);
67         edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
68      }
69    if (wd->label)
70      {
71         edje_object_part_text_set(wd->progressbar, "elm.text", wd->label);
72         edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
73      }
74    if (wd->pulse)
75      edje_object_signal_emit(wd->progressbar, "elm,state,pulse", "elm");
76    else
77      edje_object_signal_emit(wd->progressbar, "elm,state,fraction", "elm");
78    if (wd->pulse_state)
79      edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
80
81    if ((wd->units) && (!wd->pulse))
82      edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
83
84    if (wd->horizontal)
85      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
86    else
87      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
88
89    edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
90
91    if (wd->inverted)
92      edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
93
94    _units_set(obj);
95    edje_object_message_signal_process(wd->progressbar);
96    edje_object_scale_set(wd->progressbar, elm_widget_scale_get(obj) * _elm_config->scale);
97    _val_set(obj);
98    _sizing_eval(obj);
99 }
100
101 static void
102 _sizing_eval(Evas_Object *obj)
103 {
104    Widget_Data *wd = elm_widget_data_get(obj);
105    Evas_Coord minw = -1, minh = -1;
106    if (!wd) return;
107    edje_object_size_min_restricted_calc(wd->progressbar, &minw, &minh, minw, minh);
108    evas_object_size_hint_min_set(obj, minw, minh);
109    evas_object_size_hint_max_set(obj, -1, -1);
110 }
111
112 static void
113 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
114 {
115    Widget_Data *wd = elm_widget_data_get(data);
116    if (!wd) return;
117    if (obj != wd->icon) return;
118    _sizing_eval(data);
119 }
120
121 static void
122 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
123 {
124    Widget_Data *wd = elm_widget_data_get(obj);
125    Evas_Object *sub = event_info;
126    if (!wd) return;
127    if (sub == wd->icon)
128      {
129         edje_object_signal_emit(wd->progressbar, "elm,state,icon,hidden", "elm");
130         evas_object_event_callback_del_full
131            (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
132         wd->icon = NULL;
133         edje_object_message_signal_process(wd->progressbar);
134         _sizing_eval(obj);
135      }
136 }
137
138 static void
139 _val_set(Evas_Object *obj)
140 {
141    Widget_Data *wd = elm_widget_data_get(obj);
142    Eina_Bool rtl;
143    double pos;
144    if (!wd) return;
145    pos = wd->val;
146    rtl = elm_widget_mirrored_get(obj);
147    if ((!rtl && wd->inverted) || (rtl &&
148                                   ((!wd->horizontal && wd->inverted) ||
149                                    (wd->horizontal && !wd->inverted)))) pos = MAX_RATIO_LVL - pos;
150    edje_object_part_drag_value_set(wd->progressbar, "elm.cur.progressbar", pos, pos);
151 }
152
153 static void
154 _units_set(Evas_Object *obj)
155 {
156    Widget_Data *wd = elm_widget_data_get(obj);
157    if (!wd) return;
158    if (wd->units)
159      {
160         char buf[1024];
161         snprintf(buf, sizeof(buf), wd->units, 100 * wd->val);
162         edje_object_part_text_set(wd->progressbar, "elm.text.status", buf);
163      }
164    else
165      edje_object_part_text_set(wd->progressbar, "elm.text.status", NULL);
166 }
167
168 static void
169 _elm_progressbar_label_set(Evas_Object *obj, const char *item, const char *label)
170 {
171    ELM_CHECK_WIDTYPE(obj, widtype);
172    Widget_Data *wd = elm_widget_data_get(obj);
173    if (item && strcmp(item, "default")) return;
174    if (!wd) return;
175    eina_stringshare_replace(&wd->label, label);
176    if (label)
177      {
178         edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
179         edje_object_message_signal_process(wd->progressbar);
180      }
181    else
182      {
183         edje_object_signal_emit(wd->progressbar, "elm,state,text,hidden", "elm");
184         edje_object_message_signal_process(wd->progressbar);
185      }
186    edje_object_part_text_set(wd->progressbar, "elm.text", label);
187    _sizing_eval(obj);
188 }
189
190 static const char *
191 _elm_progressbar_label_get(const Evas_Object *obj, const char *item)
192 {
193    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
194    Widget_Data *wd = elm_widget_data_get(obj);
195    if (item && strcmp(item, "default")) return NULL;
196    if (!wd) return NULL;
197    return wd->label;
198 }
199
200 static void
201 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
202 {
203    ELM_CHECK_WIDTYPE(obj, widtype);
204    Widget_Data *wd;
205    if (part && strcmp(part, "icon")) return;
206    wd = elm_widget_data_get(obj);
207    if (!wd) return;
208    if (wd->icon == content) return;
209    if (wd->icon) evas_object_del(wd->icon);
210    wd->icon = content;
211    if (content)
212      {
213         elm_widget_sub_object_add(obj, content);
214         evas_object_event_callback_add(content,
215                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
216                                        _changed_size_hints, obj);
217         edje_object_part_swallow(wd->progressbar, "elm.swallow.content", content);
218         edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
219         edje_object_message_signal_process(wd->progressbar);
220      }
221    _sizing_eval(obj);
222 }
223
224 static Evas_Object *
225 _content_get_hook(const Evas_Object *obj, const char *part)
226 {
227    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
228    Widget_Data *wd;
229    if (part && strcmp(part, "icon")) return NULL;
230    wd = elm_widget_data_get(obj);
231    if (!wd) return NULL;
232    return wd->icon;
233 }
234
235 static Evas_Object *
236 _content_unset_hook(Evas_Object *obj, const char *part)
237 {
238    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
239    Widget_Data *wd;
240    Evas_Object *icon;
241    if (part && strcmp(part, "icon")) return NULL;
242    wd = elm_widget_data_get(obj);
243    if (!wd) return NULL;
244    if (!wd->icon) return NULL;
245    icon = wd->icon;
246    elm_widget_sub_object_del(obj, wd->icon);
247    evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
248                                   _changed_size_hints, obj);
249    edje_object_part_unswallow(wd->progressbar, wd->icon);
250    wd->icon = NULL;
251    return icon;
252 }
253
254
255 EAPI Evas_Object *
256 elm_progressbar_add(Evas_Object *parent)
257 {
258    Evas_Object *obj;
259    Evas *e;
260    Widget_Data *wd;
261
262    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
263
264    ELM_SET_WIDTYPE(widtype, "progressbar");
265    elm_widget_type_set(obj, "progressbar");
266    elm_widget_sub_object_add(parent, obj);
267    elm_widget_data_set(obj, wd);
268    elm_widget_del_hook_set(obj, _del_hook);
269    elm_widget_theme_hook_set(obj, _theme_hook);
270    elm_widget_can_focus_set(obj, EINA_FALSE);
271    elm_widget_text_set_hook_set(obj, _elm_progressbar_label_set);
272    elm_widget_text_get_hook_set(obj, _elm_progressbar_label_get);
273    elm_widget_content_set_hook_set(obj, _content_set_hook);
274    elm_widget_content_get_hook_set(obj, _content_get_hook);
275    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
276
277    wd->horizontal = EINA_TRUE;
278    wd->inverted = EINA_FALSE;
279    wd->pulse = EINA_FALSE;
280    wd->pulse_state = EINA_FALSE;
281    wd->units = eina_stringshare_add("%.0f %%");
282    wd->val = MIN_RATIO_LVL;
283
284    wd->progressbar = edje_object_add(e);
285    _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", "default");
286    elm_widget_resize_object_set(obj, wd->progressbar);
287
288    wd->spacer = evas_object_rectangle_add(e);
289    evas_object_color_set(wd->spacer, 0, 0, 0, 0);
290    evas_object_pass_events_set(wd->spacer, EINA_TRUE);
291    elm_widget_sub_object_add(obj, wd->spacer);
292    edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
293
294    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
295    _units_set(obj);
296    _val_set(obj);
297    _mirrored_set(obj, elm_widget_mirrored_get(obj));
298    _sizing_eval(obj);
299    return obj;
300 }
301
302 EAPI void
303 elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse)
304 {
305    ELM_CHECK_WIDTYPE(obj, widtype);
306    Widget_Data *wd = elm_widget_data_get(obj);
307    if (!wd) return;
308    pulse = !!pulse;
309    if (wd->pulse == pulse) return;
310    wd->pulse = pulse;
311    _theme_hook(obj);
312 }
313
314 EAPI Eina_Bool
315 elm_progressbar_pulse_get(const Evas_Object *obj)
316 {
317    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
318    Widget_Data *wd = elm_widget_data_get(obj);
319    if (!wd) return EINA_FALSE;
320    return wd->pulse;
321 }
322
323 EAPI void
324 elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state)
325 {
326    ELM_CHECK_WIDTYPE(obj, widtype);
327    Widget_Data *wd = elm_widget_data_get(obj);
328    if (!wd) return;
329    state = !!state;
330    if ((!wd->pulse) && (wd->pulse_state == state)) return;
331    wd->pulse_state = state;
332    if (wd->pulse_state)
333      edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
334    else
335      edje_object_signal_emit(wd->progressbar, "elm,state,pulse,stop", "elm");
336 }
337
338 EAPI void
339 elm_progressbar_value_set(Evas_Object *obj, double val)
340 {
341    ELM_CHECK_WIDTYPE(obj, widtype);
342    Widget_Data *wd = elm_widget_data_get(obj);
343    if (!wd) return;
344    if (wd->val == val) return;
345    wd->val = val;
346    if (wd->val < MIN_RATIO_LVL) wd->val = MIN_RATIO_LVL;
347    if (wd->val > MAX_RATIO_LVL) wd->val = MAX_RATIO_LVL;
348    _val_set(obj);
349    _units_set(obj);
350 }
351
352 EAPI double
353 elm_progressbar_value_get(const Evas_Object *obj)
354 {
355    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
356    Widget_Data *wd = elm_widget_data_get(obj);
357    if (!wd) return 0.0;
358    return wd->val;
359 }
360
361 EAPI void
362 elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size)
363 {
364    ELM_CHECK_WIDTYPE(obj, widtype);
365    Widget_Data *wd = elm_widget_data_get(obj);
366    if (!wd) return;
367    if (wd->size == size) return;
368    wd->size = size;
369    if (wd->horizontal)
370      evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
371    else
372      evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
373    edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
374    _sizing_eval(obj);
375 }
376
377 EAPI Evas_Coord
378 elm_progressbar_span_size_get(const Evas_Object *obj)
379 {
380    ELM_CHECK_WIDTYPE(obj, widtype) 0;
381    Widget_Data *wd = elm_widget_data_get(obj);
382    if (!wd) return 0;
383    return wd->size;
384 }
385
386 EAPI void
387 elm_progressbar_unit_format_set(Evas_Object *obj, const char *units)
388 {
389    ELM_CHECK_WIDTYPE(obj, widtype);
390    Widget_Data *wd = elm_widget_data_get(obj);
391    if (!wd) return;
392    eina_stringshare_replace(&wd->units, units);
393    if (units)
394      {
395         edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
396         edje_object_message_signal_process(wd->progressbar);
397      }
398    else
399      {
400         edje_object_signal_emit(wd->progressbar, "elm,state,units,hidden", "elm");
401         edje_object_message_signal_process(wd->progressbar);
402      }
403    _units_set(obj);
404    _sizing_eval(obj);
405 }
406
407 EAPI const char *
408 elm_progressbar_unit_format_get(const Evas_Object *obj)
409 {
410    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
411    Widget_Data *wd = elm_widget_data_get(obj);
412    if (!wd) return NULL;
413    return wd->units;
414 }
415
416 EAPI void
417 elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
418 {
419    ELM_CHECK_WIDTYPE(obj, widtype);
420    Widget_Data *wd = elm_widget_data_get(obj);
421    if (!wd) return;
422    horizontal = !!horizontal;
423    if (wd->horizontal == horizontal) return;
424    wd->horizontal = horizontal;
425    _theme_hook(obj);
426 }
427
428 EAPI Eina_Bool
429 elm_progressbar_horizontal_get(const Evas_Object *obj)
430 {
431    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
432    Widget_Data *wd = elm_widget_data_get(obj);
433    if (!wd) return EINA_FALSE;
434    return wd->horizontal;
435 }
436
437 EAPI void
438 elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted)
439 {
440    ELM_CHECK_WIDTYPE(obj, widtype);
441    Widget_Data *wd = elm_widget_data_get(obj);
442    if (!wd) return;
443    inverted = !!inverted;
444    if (wd->inverted == inverted) return;
445    wd->inverted = inverted;
446    if (wd->inverted)
447      edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
448    else
449      edje_object_signal_emit(wd->progressbar, "elm,state,inverted,off", "elm");
450    edje_object_message_signal_process(wd->progressbar);
451    _val_set(obj);
452    _units_set(obj);
453 }
454
455 EAPI Eina_Bool
456 elm_progressbar_inverted_get(const Evas_Object *obj)
457 {
458    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
459    Widget_Data *wd = elm_widget_data_get(obj);
460    if (!wd) return EINA_FALSE;
461    return wd->inverted;
462 }