Button - Complete example

A button is simple, you click on it and something happens. That said, we'll go through an example to show in detail the button API less commonly used.

In the end, we'll be presented with something that looks like this:

The full code of the example is here and we will follow here with a rundown of it.

#include <Elementary.h>
typedef struct
{
Evas_Object *mid;
Evas_Object *icon_still;
struct
{
Evas_Object *up;
Evas_Object *down;
Evas_Object *left;
Evas_Object *right;
} cursors;
} App_Data;
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185

We have several buttons to set different times for the autorepeat timeouts of the buttons that use it and a few more that we keep track of in our data struct. The mid button doesn't do much, just moves around according to what other buttons the user presses. Then four more buttons to move the central one, and we're also keeping track of the icon set in the middle button, since when this one moves, we change the icon, and when movement is finished (by releasing one of the four arrow buttons), we set back the normal icon.

static void
_btn_cursors_release_cb(void *data, Evas_Object *btn EINA_UNUSED,
void *ev EINA_UNUSED)
{
App_Data *app = data;
elm_object_part_content_set(app->mid, "icon", app->icon_still);
app->icon_still = NULL;
}
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
elm_object_part_content_set
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

Keeping any of those four buttons pressed will trigger their autorepeat callback, where we move the button doing some size hint magic. To understand how that works better, refer to the Elm_Box documentation. Also, the first time the function is called, we change the icon in the middle button, using elm_object_content_unset() first to keep the reference to the previous one, so we don't need to recreate it when we are done moving it.

static void
_btn_cursors_move_cb(void *data, Evas_Object *btn, void *ev EINA_UNUSED)
{
App_Data *app = data;
double ax, ay;
if (!app->icon_still)
{
Evas_Object *icon;
app->icon_still = elm_object_content_unset(app->mid);
evas_object_hide(app->icon_still);
icon = elm_icon_add(app->mid);
elm_icon_standard_set(icon, "chat");
elm_object_part_content_set(app->mid, "icon", icon);
}
elm_icon_add
Evas_Object * elm_icon_add(Evas_Object *parent)
Add a new icon object to the parent.
Definition: elm_icon.c:613
elm_icon_standard_set
Eina_Bool elm_icon_standard_set(Evas_Object *obj, const char *name)
Set the icon by icon standards names.
Definition: elm_icon.c:885
evas_object_hide
EVAS_API void evas_object_hide(Evas_Object *eo_obj)
Makes the given Evas object invisible.
Definition: evas_object_main.c:1823
evas_object_size_hint_align_get(app->mid, &ax, &ay);
if (btn == app->cursors.up)
{
ay -= 0.05;
if (ay < 0.0)
ay = 0.0;
}
else if (btn == app->cursors.down)
{
ay += 0.05;
if (ay > 1.0)
ay = 1.0;
}
else if (btn == app->cursors.left)
{
ax -= 0.05;
if (ax < 0.0)
ax = 0.0;
}
else if (btn == app->cursors.right)
{
ax += 0.05;
if (ax > 1.0)
ax = 1.0;
}
evas_object_size_hint_align_set(app->mid, ax, ay);
evas_object_size_hint_align_get
EVAS_API void evas_object_size_hint_align_get(const Evas_Object *obj, double *x, double *y)
Retrieves the hints for on object's alignment.
Definition: evas_object_main.c:2656
evas_object_size_hint_align_set
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
}

One more callback for the option buttons, that just sets the timeouts for the different autorepeat options.

static void
_btn_options_cb(void *data, Evas_Object *btn, void *ev EINA_UNUSED)
{
char *ptr;
double t;
App_Data *app = data;
const char *lbl = elm_object_text_get(btn);
ptr = strchr(lbl, ':');
ptr += 2;
t = strtod(ptr, NULL);
if (!strncmp(lbl, "Initial", 7))
{
elm_button_autorepeat_initial_timeout_set(app->cursors.up, t);
elm_button_autorepeat_initial_timeout_set(app->cursors.down, t);
elm_button_autorepeat_initial_timeout_set(app->cursors.left, t);
elm_button_autorepeat_initial_timeout_set(app->cursors.right, t);
}
elm_button_autorepeat_initial_timeout_set
void elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t)
The initial timeout before the autorepeat event is generated.
Definition: efl_ui_button.c:340
else if (!strncmp(lbl, "Gap", 3))
{
elm_button_autorepeat_gap_timeout_set(app->cursors.up, t);
elm_button_autorepeat_gap_timeout_set(app->cursors.down, t);
elm_button_autorepeat_gap_timeout_set(app->cursors.left, t);
elm_button_autorepeat_gap_timeout_set(app->cursors.right, t);
}
elm_button_autorepeat_gap_timeout_set
void elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
The interval between each generated autorepeat event.
Definition: efl_ui_button.c:352
}

And the main function, which does some setting up of the buttons in boxes to make things work. Here we'll go through some snippets only.

For the option buttons, it's just the button with its label and callback.

btn = elm_button_add(win);
elm_object_text_set(btn, "Initial: 0.0");
elm_box_pack_end(box2, btn);
evas_object_show(btn);
evas_object_smart_callback_add(btn, "clicked", _btn_options_cb, &data);
elm_box_pack_end
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
elm_button_add
Evas_Object * elm_button_add(Evas_Object *parent)
Add a new button to the parent's canvas.
Definition: efl_ui_button.c:459
evas_object_show
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
evas_object_smart_callback_add
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

For the ones that move the central button, we have no labels. There are icons instead, and the autorepeat option is toggled.

btn = elm_button_add(win);
elm_button_autorepeat_set(btn, EINA_TRUE);
elm_button_autorepeat_initial_timeout_set(btn, 1.0);
elm_button_autorepeat_gap_timeout_set(btn, 0.5);
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0.0);
elm_box_pack_end(box, btn);
evas_object_show(btn);
evas_object_smart_callback_add(btn, "repeated", _btn_cursors_move_cb, &data);
evas_object_smart_callback_add(btn, "unpressed", _btn_cursors_release_cb,
&data);
icon = elm_icon_add(win);
elm_icon_standard_set(icon, "arrow_up");
elm_object_part_content_set(btn, "icon", icon);
data.cursors.up = btn;
EVAS_HINT_EXPAND
#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
EVAS_HINT_FILL
#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
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
elm_button_autorepeat_set
void elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
Turn on/off the autorepeat event generated when the button is kept pressed.
Definition: efl_ui_button.c:364
evas_object_size_hint_weight_set
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

And just to show the mid button, which doesn't have anything special.

btn = elm_button_add(win);
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_box_pack_end(box2, btn);
evas_object_show(btn);
icon = elm_icon_add(win);
elm_icon_standard_set(icon, "close");
elm_object_part_content_set(btn, "icon", icon);
data.mid = btn;

And we are done.