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)
{
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;
}

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);

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:

edje-box2-example.png

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)
{
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_resize(o, 10, 10);
evas_object_color_set(o, 0, 255, 0, 255);
return o;
}
static void
on_keydown(void *data, Evas *evas, Evas_Object *o EINA_UNUSED, void *einfo)
{
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)
return;
}
if (evas_key_modifier_is_set(mods, "Control"))
{
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"))
}
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;
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 *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)
{
}
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 *edje_obj;
Evas_Object *last;
int w;
int h;
int i;
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_geometry_get(ee, NULL, NULL, &w, &h);
evas = ecore_evas_get(ee);
evas_object_resize(bg, w, h);
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);
for (i = 1; i <= 5; i++)
{
o = last = evas_object_rectangle_add(evas);
evas_object_resize(o, 50, 50);
evas_object_color_set(o, 128, 0, 0, 128);
if (!edje_object_part_box_append(edje_obj, "example/box", o))
{
fprintf(stderr, "error appending child object!\n");
return 1;
}
}
printf(commands);
return EXIT_SUCCESS;
shutdown_edje:
shutdown_ecore_evas:
return EXIT_FAILURE;
}

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
*