Progress bar widget example

This application is a thorough example of the progress bar widget, consisting of a window with various progress bars, each with a given look/style one can give to those widgets.

With two auxiliary buttons, one can start or stop a timer which will fill in the bars in synchrony, simulating an underlying task being completed.

We create seven progress bars, being three of them horizontal, three vertical and a final one under the "wheel" alternate style.

For the first one, we add a progress bar on total pristine state, with no other call than the elm_progressbar_add() one:

/* pb with no label, default unit label and no icon */
example_data.pb1 = pb;
#define EVAS_HINT_EXPAND
Use with evas_object_size_hint_weight_set(), evas_object_size_hint_weight_get(), evas_object_size_hin...
Definition: Evas_Common.h:297
#define EVAS_HINT_FILL
Use with evas_object_size_hint_align_set(), evas_object_size_hint_align_get(), evas_object_size_hint_...
Definition: Evas_Common.h:298
void elm_box_pack_end(Elm_Box *obj, Efl_Canvas_Object *subobj)
Add an object at the end of the pack list.
Definition: elm_box_eo.legacy.c:57
Evas_Object * elm_progressbar_add(Evas_Object *parent)
Add a new progress bar widget to the given parent Elementary (container) object.
Definition: efl_ui_progressbar.c:809
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
EVAS_API void evas_object_size_hint_weight_set(Evas_Object *obj, double x, double y)
Sets the hints for an object's weight.
Definition: evas_object_main.c:2638
EVAS_API void evas_object_size_hint_align_set(Evas_Object *obj, double x, double y)
Sets the hints for an object's alignment.
Definition: evas_object_main.c:2650

See, than, that the defaults of a progress bar are:

  • no primary label shown,
  • unit label set to "%.0f %%",
  • no icon set

The second progress bar is given a primary label, "Infinite bounce", and, besides, it's set to pulse. See how, after one starts the progress timer, with the "Start" button, it animates differently than the previous one. It won't account for the progress, itself, and just dumbly animate a small bar within its bar region.

/* pb with label, and set to pulse */
elm_object_text_set(pb, "Infinite bounce");
example_data.pb2 = pb;
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
void elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse)
Control whether a given progress bar widget is at "pulsing mode" or not.
Definition: efl_ui_progressbar.c:819

Next, comes a progress bar with an icon, a primary label and a unit label function set. It's also made to grow its bar in an inverted manner, so check that out during the timer's progression:

ic1 = elm_icon_add(win);
snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get());
elm_image_file_set(ic1, buf, NULL);
/* pb with label, icon, custom unit label function and span size set */
elm_object_text_set(pb, "Label");
elm_object_part_content_set(pb, "icon", ic1);
_progress_format_free);
example_data.pb3 = pb;
@ EVAS_ASPECT_CONTROL_VERTICAL
Use all vertical container space to place an object, using the given aspect.
Definition: Evas_Common.h:377
const char * elm_app_data_dir_get(void)
Get the application's run time data prefix directory, as set by elm_app_info_set() and the way (envir...
Definition: elm_main.c:586
void elm_object_part_content_set(Evas_Object *obj, const char *part, Evas_Object *content)
Set the content on part of a given container widget.
Definition: elm_main.c:1562
Evas_Object * elm_icon_add(Evas_Object *parent)
Add a new icon object to the parent.
Definition: elm_icon.c:613
Eina_Bool elm_image_file_set(Evas_Object *obj, const char *file, const char *group)
Set the file that will be used as the image's source.
Definition: efl_ui_image.c:2435
void elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size)
Control the (exact) length of the bar region of a given progress bar widget.
Definition: efl_ui_progressbar.c:1009
void elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted)
Invert a given progress bar widget's displaying values order.
Definition: efl_ui_progressbar.c:879
void elm_progressbar_unit_format_function_set(Evas_Object *obj, progressbar_func_type func, progressbar_freefunc_type free_func)
Set the format function pointer for the units label.
Definition: efl_ui_progressbar.c:944
EVAS_API void evas_object_size_hint_aspect_set(Evas_Object *obj, Evas_Aspect_Control aspect, Evas_Coord w, Evas_Coord h)
Sets the hints for an object's aspect ratio.
Definition: evas_object_main.c:2581

Another important thing in this one is the call to elm_progressbar_span_size_set() – this is how we forcefully set a minimum horizontal size to our whole window! We're not resizing it manually, as you can see in the complete code.

The format callback is a simple function that gets passed the progress value and returns a string. A free function should be provided as well, if the format callback allocates memory.

/* Format callback */
static char *
_progress_format_cb(double val)
{
static char buf[30];
int files = (1-val)*14000;
if (snprintf(buf, 30, "%i files left", files) > 0)
return strdup(buf);
return NULL;
}
static void
_progress_format_free(char *str)
{
free(str);
}

The last horizontal progress bar has a callback that gets called when its value is changed. This callback updates a label to provide an estimate when the operation finishes.

/* pb with label and changed trigger */
elm_object_text_set(pb, "Label");
label = elm_label_add(win);
elm_object_text_set(label, "ETA: N/A");
elm_box_pack_end(bx, label);
evas_object_smart_callback_add(pb, "changed", _on_changed, label);
example_data.pb4 = pb;
Evas_Object * elm_label_add(Evas_Object *parent)
Add a new label to the parent.
Definition: elm_label.c:421
EVAS_API void evas_object_smart_callback_add(Evas_Object *eo_obj, const char *event, Evas_Smart_Cb func, const void *data)
Add (register) a callback function to the smart event specified by event on the smart object obj.
Definition: evas_object_smart.c:1040

The "changed" signal is emitted every time the progressbar value is updated through elm_progressbar_value_set(). This callback calculates and displays the ETA based on the progress and time that has passed.

/* Callback for "changed" signal */
static void
_on_changed(void *data,
void *event_info EINA_UNUSED)
{
static char buf[30];
static time_t tstart = 0;
static double eta = 0;
time_t tdiff;
double val;
Evas_Object *label = (Evas_Object *)data;
if (EINA_DBL_EQ(val, 0))
{
tstart = 0;
elm_object_text_set(label, "ETA: N/A");
return;
}
#define EINA_DBL_EQ(a, b)
Safe comparison of double.
Definition: eina_util.h:100
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
double elm_progressbar_value_get(const Evas_Object *obj)
Get the progress value (in percentage) on a given progress bar widget.
Definition: efl_ui_progressbar.c:1046
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185
/* First invocation */
if (tstart == 0)
{
tstart = time(NULL);
}
/* Calculate ETA and update */
tdiff = time(NULL) - tstart;
eta = 0.3*eta + 0.7*(tdiff/val)*(1-val);
snprintf(buf, 30, "ETA: %.0fs", eta);
elm_object_text_set(label, buf);
}

The next three progress bars are just variants on the ones already shown, but now all being vertical. Another time we use one of than to give the window a minimum vertical size, with elm_progressbar_span_size_set(). To demonstrate this trick once more, the fifth one, which is also set to pulse, has a smaller hardcoded span size:

/* vertical pb, with pulse and custom (small) span size */
elm_object_text_set(pb, "Infinite bounce");
elm_box_pack_end(hbx, pb);
example_data.pb6 = pb;
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition: eina_types.h:533
void elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
Control the orientation of a given progress bar widget.
Definition: efl_ui_progressbar.c:899
void elm_progressbar_unit_format_set(Evas_Object *obj, const char *units)
Control the format string for a given progress bar widget's units label.
Definition: efl_ui_progressbar.c:1023

We end the widget demonstration by showing a progress bar with the special "wheel" progress bar style. One does not need to set it to pulse, with elm_progressbar_pulse_set(), explicitly, because its theme does not take it in account:

/* "wheel" style progress bar */
elm_object_style_set(pb, "wheel");
elm_object_text_set(pb, "Style: wheel");
example_data.pb8 = pb;
Eina_Bool elm_object_style_set(Evas_Object *obj, const char *style)
Set the style to used by a given widget.
Definition: elm_main.c:1583

The two buttons exercising the bars, the facto, follow:

bt = elm_button_add(win);
elm_object_text_set(bt, "Start");
evas_object_smart_callback_add(bt, "clicked", _progressbar_example_start,
NULL);
elm_box_pack_end(bt_bx, bt);
Evas_Object * elm_button_add(Evas_Object *parent)
Add a new button to the parent's canvas.
Definition: efl_ui_button.c:459
bt = elm_button_add(win);
elm_object_text_set(bt, "Stop");
evas_object_smart_callback_add(bt, "clicked", _progressbar_example_stop,
NULL);
elm_box_pack_end(bt_bx, bt);

The first of the callbacks will, for the progress bars set to pulse, start the pulsing animation at that time. For the others, a timer callback will take care of updating the values:

static Eina_Bool
_progressbar_example_value_set(void *data EINA_UNUSED)
{
double progress;
progress = elm_progressbar_value_get(example_data.pb1);
if (progress < 1.0) progress += 0.0123;
else progress = 0.0;
/* just the non-pulsing ones need an update */
elm_progressbar_value_set(example_data.pb1, progress);
elm_progressbar_value_set(example_data.pb3, progress);
elm_progressbar_value_set(example_data.pb4, progress);
elm_progressbar_value_set(example_data.pb5, progress);
elm_progressbar_value_set(example_data.pb7, progress);
if (progress < 1.0) return ECORE_CALLBACK_RENEW;
example_data.run = 0;
}
#define ECORE_CALLBACK_RENEW
Return value to keep a callback.
Definition: Ecore_Common.h:153
#define ECORE_CALLBACK_CANCEL
Return value to remove a callback.
Definition: Ecore_Common.h:152
unsigned char Eina_Bool
Type to mimic a boolean.
Definition: eina_types.h:527
void elm_progressbar_value_set(Evas_Object *obj, double val)
Control the progress value (in percentage) on a given progress bar widget.
Definition: efl_ui_progressbar.c:1040
static void
_progressbar_example_start(void *data EINA_UNUSED,
void *event_info EINA_UNUSED)
{
elm_progressbar_pulse(example_data.pb2, EINA_TRUE);
elm_progressbar_pulse(example_data.pb6, EINA_TRUE);
elm_progressbar_pulse(example_data.pb8, EINA_TRUE);
if (!example_data.run)
{
example_data.timer = ecore_timer_add(
0.1, _progressbar_example_value_set, NULL);
example_data.run = EINA_TRUE;
}
Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
Creates a timer to call the given function in the given period of time.
Definition: ecore_timer.c:189
void elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state)
Start/stop a given progress bar "pulsing" animation, if its under that mode.
Definition: efl_ui_progressbar.c:838
}

Finally, the callback to stop the progress timer will stop the pulsing on the pulsing progress bars and, for the others, to delete the timer which was acting on their values:

/* end of show */
static void
_progressbar_example_stop(void *data EINA_UNUSED,
void *event_info EINA_UNUSED)
{
elm_progressbar_pulse(example_data.pb2, EINA_FALSE);
elm_progressbar_pulse(example_data.pb6, EINA_FALSE);
elm_progressbar_pulse(example_data.pb8, EINA_FALSE);
if (example_data.run)
{
ecore_timer_del(example_data.timer);
example_data.run = EINA_FALSE;
}
void * ecore_timer_del(Ecore_Timer *timer)
Deletes the specified timer from the timer list.
Definition: ecore_timer.c:238
}

This is how the example program's window looks like:

See the full source code for this example.