Spinner widget example with C++ Binding

This code places seven Elementary spinner widgets on a window, each of them exemplifying a part of the widget's API.

The first part consists of including the headers. In this case we are only working with the Elementary C++ binding and thus we need only to include him.

#include <Elementary.hh>

Attention
If necessary the C and/or the C++ headers should be include here as well.

Now we need to actually start the code and set the elm_policy, which defines for a given policy group/identifier a new policy's value, respectively. In this example the only policy we need to set a value for is ELM_POLICY_QUIT, possibles values for it are:

EAPI_MAIN int
elm_main (int argc, char *argv[])
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);

As you can see, the policy we chose was to quit when the last win is hidden as opose to examples with the C bindings where we perpetually set it to quit when last win was closed. This changed was necessary because in C++ binding as the elm mainloop stop running all object are destroyed, references are unreferenced and events are stopped at ELM_MAIN().

See also
For more details consult elm_policy_set

Next step is creating an Elementary window, in this example we use the C++ binding method with the elm_win_util_standard_add that is a elm_win_legacy function, better explained below. And then we set the autohide state for it.

elm_win_util_standard_add (const char *name, const char *tittle) Adds a window object with standard setup.

Parameters:

This creates a window but also puts in a standard background with elm_bg_add(), as well as setting the window title to title. The window type created is of type ELM_WIN_BASIC, with the NULL as the parent widget. Returns the created object or NULL on failure.

The autohide works similarly to autodel, automatically handling "delete,request" signals when set to true, with the difference that it will hide the window, instead of destroying it.

It is specially designed to work together with ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN which allows exiting Elementary's main loop when all the windows are hidden.

::elm::win win(elm_win_util_standard_add("spinner", "Spinner Example"));
win.autohide_set(true);

Note
autodel and autohide are not mutually exclusive. The window will be destructed if both autodel and autohide is set to EINA_TRUE or true.

A box arranges objects in a linear fashion, governed by a layout function that defines the details of this arrangement. The box will use an internal function to set the layout to a single row, vertical by default.

Now let's create the box with the C++ binding method, passing our window object as parent.

::elm::box bx(efl::eo::parent = win);

To better understand, the function size_hint_weight_set for C++ bindings originated from C bindings function evas_object_size_hint_weight_set, that is EFL Evas type function. With this function we set the hints for an object's weight. The parameters are:

This is not a size enforcement in any way, it's just a hint that should be used whenever appropriate. This is a hint on how a container object should resize a given child within its area.

Containers may adhere to the simpler logic of just expanding the child object's dimensions to fit its own (see the EVAS_HINT_EXPAND helper weight macro in the EFL Evas Documentation) or the complete one of taking each child's weight hint as real weights to how much of its size to allocate for them in each axis. A container is supposed to, after normalizing the weights of its children (with weight hints), distribute the space it has to layout them by those factors – most weighted children get larger in this process than the least ones.

bx.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);

Note
Default weight hint values are 0.0, for both axis.

Now we add the box as a resize_object to win informing that when the size of the win changes so should the box's size. And finally we make it visible.

Now we create our spinner with the C++ method, this first one will the default spinner.

As you see, the defaults for a spinner are:

The function size_hint_weight_set works with spinner the same way as with box, as seem above.

The function size_hint_align_set for C++ bindings originated from C bindings function evas_object_size_hint_align_set, that is EFL Evas type function. With this function we set the hints for an object's alignment. The parameters are:

These are hints on how to align an object inside the boundaries of a container/manager. Accepted values are in the 0.0 to 1.0 range, with the special value EVAS_HINT_FILL used to specify "justify" or "fill" by some users. In this case, maximum size hints should be enforced with higher priority, if they are set. Also, any padding hint set on objects should add up to the alignment space on the final scene composition.

For the horizontal component, 0.0 means to the left, 1.0 means to the right. Analogously, for the vertical component, 0.0 to the top, 1.0 means to the bottom.

This is not a size enforcement in any way, it's just a hint that should be used whenever appropriate.

Note
Default alignment hint values are 0.5, for both axis.

When using the elm::box the packing method of the subobj - spinner in this case - should be defined. There are four possible methods:

In this and most examples we use pack_end by choice and practicality. In this part of the code we also make spinner visible.

In our second spinner we are altering the format. It will put a text before and after the value, and also format value to display two decimals. As with the first spinner, we create the second with the same C++ method, set the alignment and the weight, choose the packing method and make it visible.

The third one will use a customized step, define new minimum and maximum values and enable wrap, so when value reaches minimum it jumps to maximum, or jumps to minimum after maximum value is reached. Format is set to display a decimal:

The fourth uses vertical style, so instead of left and right arrows, top and bottom are displayed. Also the change interval is reduced, so user can change value faster.

In the fifth the user won't be allowed to set value directly, i.e., will be obligate change value only using arrows:

The sixth widget will receive a lot of special values, so instead of reading numeric values, user will see labels for each one. Also direct edition is disabled, otherwise users would see the numeric value on edition mode. User will be able to select a month in this widget:

Finally the last widget will exemplify how to listen to widget's signals, changed and delay_changed .

We start the same way as previously, creating spinner, setting alignment and weight, choosing the packing method, making it visible and editable.

Our spinner will output it's value or delay value every time the std::function object is called. In this example we are using std::bind to bind the parameters of each lambda function, that captures sp7 by reference and then get it's value or delay value to finally output it.

The first function changed, that was declare as auto, will output the new value. For this we need to add it to the callback_changed

The second function changed, that was also declare as auto, will output the new delay value. For this we need to add it to the callback_delay_changed.

To learn more consult Lambda Functions with Elementary - C++11.

The first callback function should be called everytime value changes, the second one only after user stops to increment or decrement. Try to keep arrows pressed and check the difference.

Finally we just have to make our window visible. Then run the elm mainloop, starting to handle events and drawing operations.

See the full code for this example at spinner_cxx_example.cc .

This example will look like this:

spinner_cxx_example.png