Box example - custom layout

This example shows how to register a custom layout to be used by the Edje box part.

It will use edje_box_layout_register() for that.

To play with this example, use the keyboard modifier keys and number keys together. The Ctrl key is used for adding elements, and Shift is used for removing them. For instance, Ctrl + 3 will insert a new rectangle object in the 3rd position of the box, while Shift + 6 will try to remove the 6th element of the box.

This example is very similar to the other box example, has a structure with global data, a callback for key down events where we create or delete rectangle objects and add or remove them to/from the box part.

But the important part is the next one:

static void
custom_layout(Evas_Object *o, Evas_Object_Box_Data *p, void *data EINA_UNUSED)
{
Evas_Object_Box_Option *opt;
Eina_List *l;
int x, y, w, h;
int xx, yy, ww, hh;
int count;
evas_object_geometry_get(o, &x, &y, &w, &h);
count = eina_list_count(p->children);
ww = w / (count ? count : 1);
hh = h / (count ? count : 1);
if (ww < 1) ww = 1;
if (hh < 1) hh = 1;
xx = x;
yy = y;
EINA_LIST_FOREACH(p->children, l, opt)
{
evas_object_move(opt->obj, xx, yy);
xx += ww;
yy += hh;
}
Eina_List
struct _Eina_List Eina_List
Type for a generic double linked list.
Definition eina_list.h:304
EINA_LIST_FOREACH
#define EINA_LIST_FOREACH(list, l, _data)
Definition for the macro to iterate over a list.
Definition eina_list.h:1415
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition eina_types.h:339
Evas_Object_Box_Option
struct _Evas_Object_Box_Option Evas_Object_Box_Option
The base structure for a box option.
Definition Evas_Common.h:2713
Evas_Object_Box_Data
struct _Evas_Object_Box_Data Evas_Object_Box_Data
Smart object instance data, providing box object requirements.
Definition Evas_Common.h:2687
evas_object_geometry_get
EVAS_API void evas_object_geometry_get(const Evas_Object *eo_obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
Retrieves the position and (rectangular) size of the given Evas object.
Definition evas_object_main.c:1335
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition evas_object_main.c:1171
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition Evas_Common.h:185
_Evas_Object_Box_Option::obj
Evas_Object * obj
Pointer to the box child object, itself.
Definition Evas_Common.h:2873

This code implements our custom layout, which will position every object added to the box in a diagonal through the size of the box part. Notice that it just calculates the position and offset based on the size of the box and number of children, and then moves each child to the respective position.

Later on the `main` function, everything we need to do is to register this custom layout function with edje:

edje_box_layout_register("custom_layout", custom_layout, NULL, NULL, NULL, NULL);
edje_box_layout_register
void edje_box_layout_register(const char *name, Evas_Object_Box_Layout func, void *(*layout_data_get)(void *), void(*layout_data_free)(void *), void(*free_data)(void *), void *data)
Registers a custom layout to be used in edje boxes.
Definition edje_util.c:3478

And use it inside the box.edc file:

part {
name: "example/box";
type: BOX;
description {
state: "default" 0.0;
box {
layout: "custom_layout";
padding: 2 2;
align: 0.5 0.5;
min: 1 1;
}
rel1 {
relative: 0.0 0.2;
offset: 0 0;
to: "bg";
}
rel2 {
relative: 1.0 1.0;
offset: -1 -61;
to: "bg";
}
}
} // example/box

The example's window should look like this picture:

The full source code follows:

#ifdef HAVE_CONFIG_H
# include "config.h"
#else
# define EINA_UNUSED
#endif
#ifndef PACKAGE_DATA_DIR
#define PACKAGE_DATA_DIR "."
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Ecore.h>
#include <Evas.h>
#include <Ecore_Evas.h>
#include <Edje.h>
static const char commands[] = \
"commands are:\n"
"\tShift + any key - remove box\n"
"\tCtrl + any key - insert box\n"
"\tEsc - exit\n"
"\th - print help\n";
static void
custom_layout(Evas_Object *o, Evas_Object_Box_Data *p, void *data EINA_UNUSED)
{
Evas_Object_Box_Option *opt;
Eina_List *l;
int x, y, w, h;
int xx, yy, ww, hh;
int count;
evas_object_geometry_get(o, &x, &y, &w, &h);
count = eina_list_count(p->children);
ww = w / (count ? count : 1);
hh = h / (count ? count : 1);
if (ww < 1) ww = 1;
if (hh < 1) hh = 1;
xx = x;
yy = y;
EINA_LIST_FOREACH(p->children, l, opt)
{
evas_object_move(opt->obj, xx, yy);
xx += ww;
yy += hh;
}
}
static Evas_Object *
new_greenie_block(Evas *e)
{
Evas_Object *o;
o = evas_object_rectangle_add(e);
evas_object_resize(o, 10, 10);
evas_object_color_set(o, 0, 255, 0, 255);
evas_object_show(o);
return o;
}
static void
on_keydown(void *data, Evas *evas, Evas_Object *o EINA_UNUSED, void *einfo)
{
Evas_Event_Key_Down *ev;
Evas_Object *edje_obj;
const Evas_Modifier *mods;
ev = (Evas_Event_Key_Down *)einfo;
edje_obj = (Evas_Object *)data;
mods = evas_key_modifier_get(evas);
if (!strcmp(ev->key, "h"))
{
printf(commands);
return;
}
if (evas_key_modifier_is_set(mods, "Shift"))
{
int pos;
Evas_Object *obj = NULL;
pos = atoi(ev->key);
obj = edje_object_part_box_remove_at(edje_obj, "example/box", pos);
if (obj)
evas_object_del(obj);
return;
}
if (evas_key_modifier_is_set(mods, "Control"))
{
Evas_Object *obj;
int pos;
pos = atoi(ev->key);
obj = new_greenie_block(evas);
if (!edje_object_part_box_insert_at(edje_obj, "example/box", obj, pos))
edje_object_part_box_append(edje_obj, "example/box", obj);
return;
}
if (!strcmp(ev->key, "Escape"))
ecore_main_loop_quit();
}
static Evas_Object *
box_new(Ecore_Evas *ee, const char *edje_file_path, const char *name, int x, int y, int w, int h)
{
Evas_Object *edje_obj;
edje_obj = edje_object_add(ecore_evas_get(ee));
evas_object_move(edje_obj, x, y);
evas_object_resize(edje_obj, w, h);
if (!edje_object_file_set(edje_obj, edje_file_path, "example/group2"))
{
printf("error: could not load file object.\n");
}
evas_object_show(edje_obj);
evas_object_name_set(edje_obj, name);
ecore_evas_data_set(ee, "edje_obj", edje_obj);
return edje_obj;
}
static void
on_resize(Ecore_Evas *ee)
{
Evas_Object *bg;
Evas_Object *edje_obj;
int w;
int h;
bg = ecore_evas_data_get(ee, "background");
edje_obj = ecore_evas_data_get(ee, "edje_obj");
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
evas_object_resize(bg, w, h);
evas_object_resize(edje_obj, w, h);
}
static void
on_destroy(Ecore_Evas *ee EINA_UNUSED)
{
ecore_main_loop_quit();
}
int
main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
{
const char *edje_file = PACKAGE_DATA_DIR"/box.edj";
Ecore_Evas *ee;
Evas *evas;
Evas_Object *bg;
Evas_Object *edje_obj;
Evas_Object *last;
Evas_Object *o;
int w;
int h;
int i;
if (!ecore_evas_init())
return EXIT_FAILURE;
if (!edje_init())
goto shutdown_ecore_evas;
/* this will give you a window with an Evas canvas under the first
* engine available */
ee = ecore_evas_new(NULL, 0, 0, 640, 480, NULL);
if (!ee) goto shutdown_edje;
ecore_evas_callback_resize_set(ee, on_resize);
ecore_evas_callback_destroy_set(ee, on_destroy);
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
evas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(evas);
evas_object_resize(bg, w, h);
evas_object_show(bg);
evas_object_focus_set(bg, 1);
ecore_evas_data_set(ee, "background", bg);
edje_box_layout_register("custom_layout", custom_layout, NULL, NULL, NULL, NULL);
edje_obj = box_new(ee, edje_file, "box", 0, 0, w, h);
evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, on_keydown, edje_obj);
for (i = 1; i <= 5; i++)
{
o = last = evas_object_rectangle_add(evas);
evas_object_size_hint_min_set(o, 50, 50);
evas_object_resize(o, 50, 50);
evas_object_color_set(o, 128, 0, 0, 128);
evas_object_show(o);
if (!edje_object_part_box_append(edje_obj, "example/box", o))
{
fprintf(stderr, "error appending child object!\n");
return 1;
}
}
printf(commands);
ecore_evas_show(ee);
ecore_main_loop_begin();
ecore_evas_free(ee);
ecore_evas_shutdown();
edje_shutdown();
return EXIT_SUCCESS;
shutdown_edje:
edje_shutdown();
shutdown_ecore_evas:
ecore_evas_shutdown();
return EXIT_FAILURE;
}
Ecore_Evas.h
Evas wrapper functions.
Edje.h
Edje Graphical Design Library.
EVAS_CALLBACK_KEY_DOWN
@ EVAS_CALLBACK_KEY_DOWN
Key Press Event.
Definition Evas_Common.h:430
ecore_evas_init
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition ecore_evas.c:608
ecore_evas_callback_destroy_set
EAPI void ecore_evas_callback_destroy_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
Sets a callback for Ecore_Evas destroy events.
Definition ecore_evas.c:1199
ecore_evas_show
EAPI void ecore_evas_show(Ecore_Evas *ee)
Shows an Ecore_Evas' window.
Definition ecore_evas.c:1494
ecore_evas_get
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition ecore_evas.c:1314
ecore_evas_data_get
EAPI void * ecore_evas_data_get(const Ecore_Evas *ee, const char *key)
Retrieves user data associated with an Ecore_Evas.
Definition ecore_evas.c:1106
ecore_evas_geometry_get
EAPI void ecore_evas_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h)
Gets the geometry of an Ecore_Evas.
Definition ecore_evas.c:1376
ecore_evas_data_set
EAPI void ecore_evas_data_set(Ecore_Evas *ee, const char *key, const void *data)
Stores user data in an Ecore_Evas structure.
Definition ecore_evas.c:1117
ecore_evas_new
EAPI Ecore_Evas * ecore_evas_new(const char *engine_name, int x, int y, int w, int h, const char *extra_options)
Creates a new Ecore_Evas based on engine name and common parameters.
Definition ecore_evas.c:1053
ecore_evas_callback_resize_set
EAPI void ecore_evas_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
Sets a callback for Ecore_Evas resize events.
Definition ecore_evas.c:1154
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition ecore_evas.c:672
ecore_evas_free
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition ecore_evas.c:1097
ecore_main_loop_quit
void ecore_main_loop_quit(void)
Quits the main loop once all the events currently on the queue have been processed.
Definition ecore_main.c:1321
ecore_main_loop_begin
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition ecore_main.c:1311
edje_shutdown
int edje_shutdown(void)
Shuts down the Edje library.
Definition edje_main.c:262
edje_init
int edje_init(void)
Initializes the Edje library.
Definition edje_main.c:35
edje_object_add
Evas_Object * edje_object_add(Evas *evas)
Instantiates a new Edje object.
Definition edje_smart.c:22
edje_object_file_set
Eina_Bool edje_object_file_set(Evas_Object *obj, const char *file, const char *group)
Sets the EDJ file (and group within it) to load an Edje object's contents from.
Definition edje_smart.c:467
edje_object_part_box_insert_at
Eina_Bool edje_object_part_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos)
Inserts an object to the box.
Definition edje_part_table.c:260
edje_object_part_box_remove_at
Evas_Object * edje_object_part_box_remove_at(Evas_Object *obj, const char *part, unsigned int pos)
Removes an object from the box.
Definition edje_part_table.c:267
edje_object_part_box_append
Eina_Bool edje_object_part_box_append(Evas_Object *obj, const char *part, Evas_Object *child)
Appends an object to the box.
Definition edje_part_table.c:232
Evas_Event_Key_Down
struct _Evas_Event_Key_Down Evas_Event_Key_Down
Event structure for EVAS_CALLBACK_KEY_DOWN event callbacks.
Definition Evas_Legacy.h:154
evas_key_modifier_get
EVAS_API const Evas_Modifier * evas_key_modifier_get(const Evas *eo_e)
Returns a handle to the list of modifier keys registered in the canvas e.
Definition evas_key.c:35
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition Evas_Common.h:163
Evas_Modifier
struct _Evas_Modifier Evas_Modifier
An opaque type containing information on which modifier keys are registered in an Evas canvas.
Definition Evas_Internal.h:36
evas_key_modifier_is_set
EVAS_API Eina_Bool evas_key_modifier_is_set(const Evas_Modifier *m, const char *keyname)
Checks the state of a given modifier of the default seat, at the time of the call.
Definition evas_key.c:76
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_name_set
EVAS_API void evas_object_name_set(Evas_Object *eo_obj, const char *name)
Sets the name of the given Evas object to the given name.
Definition evas_name.c:5
evas_object_del
EVAS_API void evas_object_del(Evas_Object *obj)
Marks the given Evas object for deletion (when Evas will free its memory).
Definition evas_object_main.c:928
evas_object_color_set
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition evas_object_main.c:2024
evas_object_event_callback_add
EVAS_API void evas_object_event_callback_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
Add (register) a callback function to a given Evas object event.
Definition evas_callbacks.c:478
evas_object_focus_set
EVAS_API void evas_object_focus_set(Efl_Canvas_Object *obj, Eina_Bool focus)
Indicates that this object is the keyboard event receiver on its canvas.
Definition efl_canvas_object_eo.legacy.c:39
evas_object_resize
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition evas_object_main.c:1236
evas_object_size_hint_min_set
EVAS_API void evas_object_size_hint_min_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Sets the hints for an object's minimum size.
Definition evas_object_main.c:2611
evas_object_rectangle_add
EVAS_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition evas_object_rectangle.c:78
_Evas_Event_Key_Down::key
const char * key
The logical key : (eg shift+1 == exclamation).
Definition Evas_Legacy.h:320

To compile use this command:

    * gcc -o edje-box2 edje-box2.c -DPACKAGE_BIN_DIR=\"/Where/enlightenment/is/installed/bin\" -DPACKAGE_LIB_DIR=\"/Where/enlightenment/is/installed/lib\"
    * -DPACKAGE_DATA_DIR=\"/Where/enlightenment/is/installed/share\"
    * `pkg-config --cflags --libs evas ecore ecore-evas edje`
    *
    * edje_cc box.edc
    *