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:
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
elm_box_pack_end(bx, pb);
evas_object_show(pb);
example_data.pb1 = pb;
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.
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_text_set(pb, "Infinite bounce");
elm_box_pack_end(bx, pb);
evas_object_show(pb);
example_data.pb2 = pb;
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:
evas_object_size_hint_aspect_set(ic1, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
elm_object_text_set(pb, "Label");
_progress_format_free);
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(bx, pb);
evas_object_show(ic1);
evas_object_show(pb);
example_data.pb3 = pb;
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.
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.
elm_object_text_set(pb, "Label");
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(bx, pb);
evas_object_show(pb);
elm_object_text_set(label, "ETA: N/A");
evas_object_size_hint_align_set(label, 0.5, 0.5);
evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(bx, label);
evas_object_show(label);
evas_object_smart_callback_add(pb, "changed", _on_changed, label);
example_data.pb4 = pb;
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.
static void
_on_changed(void *data,
Evas_Object *obj,
void *event_info)
{
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 (val == 0)
{
tstart = 0;
elm_object_text_set(label, "ETA: N/A");
return;
}
if (tstart == 0)
{
tstart = time(NULL);
}
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:
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_text_set(pb, "Infinite bounce");
elm_box_pack_end(hbx, pb);
evas_object_show(pb);
example_data.pb6 = pb;
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:
elm_object_text_set(pb, "Style: wheel");
evas_object_size_hint_align_set(pb, EVAS_HINT_FILL, 0.5);
evas_object_size_hint_weight_set(pb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(bx, pb);
evas_object_show(pb);
example_data.pb8 = pb;
The two buttons exercising the bars, the facto, follow:
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_show(bt);
elm_object_text_set(bt, "Stop");
evas_object_smart_callback_add(bt, "clicked", _progressbar_example_stop,
NULL);
elm_box_pack_end(bt_bx, bt);
evas_object_show(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)
{
double progress;
if (progress < 1.0) progress += 0.0123;
else progress = 0.0;
if (progress < 1.0) return ECORE_CALLBACK_RENEW;
example_data.run = 0;
return ECORE_CALLBACK_CANCEL;
}
static void
_progressbar_example_start(void *data,
Evas_Object *obj,
void *event_info)
{
if (!example_data.run)
{
example_data.timer = ecore_timer_add(
0.1, _progressbar_example_value_set, NULL);
example_data.run = EINA_TRUE;
}
}
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:
static void
_progressbar_example_stop(void *data,
Evas_Object *obj,
void *event_info)
{
if (example_data.run)
{
ecore_timer_del(example_data.timer);
example_data.run = EINA_FALSE;
}
}
This is how the example program's window looks like:
See the full source code for this example.