Edje basics example

In this example, we illustrate how to start using the Edje library, with the very basic one needs to instantiate an Edje object.

We place, in the canvas, an Edje object along with a red border image to delimit its geometry. After we instantiate the Edje object, we have to set a file and a group, within that file, to bind to it. For this example, we're using an EDC file which declares two parts (blue and green rectangles) and an item data:

collections {
group {
name: "example_group";
max: 500 500;
min: 50 50;
data {
item: "example_data" "a string";
}
parts {
part {
name: "part_one";
type: RECT;
scale: 1;
description {
min: 50 50;
max: 50 50;
state: "default" 0.0;
color: 0 0 255 255; /* blue */
rel1.relative: 0.0 0.0;
rel2.relative: 1.0 1.0;
}
}
part {
name: "part_two";
type: RECT;
description {
state: "default" 0.0;
color: 0 255 0 255; /* green */
rel1.relative: -1.0 -1.0;
rel2.relative: 0.0 0.0;
}
}
}
}
}

We start by trying to access an unexistant group in the file, so that you can see the usefulness of edje_object_load_error_get() and edje_load_error_str(). Check that the error message will tell you just that – a group which didn't exist in the file was called for:

edje_obj = edje_object_add(evas);
/* exercising Edje loading error, on purpose */
if (!edje_object_file_set(edje_obj, edje_file, "unexistant_group"))
{
int err = edje_object_load_error_get(edje_obj);
const char *errmsg = edje_load_error_str(err);
fprintf(stderr, "Could not load 'unexistant_group' from basic.edj:"
" %s\n", errmsg);
}
edje_load_error_str
const char * edje_load_error_str(Edje_Load_Error error)
Converts the given Edje file load error code into a string describing it in English.
Definition: edje_load.c:108
edje_object_add
Evas_Object * edje_object_add(Evas *evas)
Instantiates a new Edje object.
Definition: edje_smart.c:22
edje_object_load_error_get
Edje_Load_Error edje_object_load_error_get(const Eo *obj)
Gets the (last) file loading error for a given Edje object.
Definition: edje_legacy.c:15
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

Than, we finally bind our Edje object to `"example_group"`, printing a message afterwards:

What follows is a series of Edje API calls which are of general use. The first of them is edje_object_data_get(), which we use to get the value we have put in the `"example_data"` data field, in our EDC object declaration:

printf("'example_data' data field in group 'example_group' has "
"the value: %s\n", edje_object_data_get(edje_obj,
"example_data"));

Than, we exemplify edje_object_part_exists():

printf("Testing if 'part_one' part exists: %s\n",
edje_object_part_exists(edje_obj, "part_one") ? "yes!" : "no");
edje_object_part_exists
Eina_Bool edje_object_part_exists(const Eo *obj, const char *part)
Checks if a part exists in a given Edje object's group definition.
Definition: edje_legacy.c:1163

The next call is to query `"part_one"'s` geometry, relative to the whole Edje object's area. The part will be situated in the middle of the Edje object's, because it has a restricted forced size (we set its minimum size equal to its maximum, for that) and, by default, parts are aligned to the center of their containers:

edje_object_part_geometry_get(edje_obj, "part_one", &x, &y, &w, &h);
printf("The geometry of that part inside the Edje object's area "
"is: x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
edje_object_part_geometry_get
Eina_Bool edje_object_part_geometry_get(const Edje_Object *obj, const char *part, int *x, int *y, int *w, int *h)
Retrieves the geometry of a given Edje part, in a given Edje object's group definition,...
Definition: edje_legacy.c:25

We can grab a direct pointer on the rectangle implementing `"part_one"`, by using edje_object_part_object_get(). Since we are not allowed to set properties on it, we just check its color, to assure its really blue, as declared in the EDC:

evas_object_color_get(edje_object_part_object_get(edje_obj, "part_one"),
&x, &y, &w, &h);
printf("That part's color components are: r = %d, g = %d, b = %d,"
" a = %d\n", x, y, w, h);
edje_object_part_object_get
const Efl_Canvas_Object * edje_object_part_object_get(const Evas_Object *obj, const char *part)
Gets a handle to the Evas object implementing a given Edje part, in an Edje object.
Definition: edje_util.c:2104
evas_object_color_get
EVAS_API void evas_object_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
Retrieves the general/main color of the given Evas object.
Definition: evas_object_main.c:2071

The `"min"` and `"max"` EDC properties can be queried with the following calls:

edje_object_size_max_get(edje_obj, &w, &h);
printf("The Edje object's max. size is: %d, %d\n", w, h);
edje_object_size_min_get(edje_obj, &w, &h);
printf("The Edje object's min. size is: %d, %d\n", w, h);
edje_object_size_max_get
void edje_object_size_max_get(const Edje_Object *obj, int *maxw, int *maxh)
Gets the maximum size specified – as an EDC property – for a given Edje object.
Definition: edje_legacy.c:1154
edje_object_size_min_get
void edje_object_size_min_get(const Edje_Object *obj, int *minw, int *minh)
Gets the minimum size specified – as an EDC property – for a given Edje object.
Definition: edje_legacy.c:1145

The next two calls are to make size calculations on our object. Because of the minimum size declared for `"part_one"` part's default state description, that will be our exact minimum size calculated for the group (remember the `"min"` declaration at group level is just a hint, not an enforcement). We then exercise the edje_object_size_min_restricted_calc() function, passing a minimum size of 500, in each axis. Since we have no object bigger than that, it will be the minimum size calculated, in the end:

edje_object_size_min_calc(edje_obj, &w, &h);
printf("The Edje object's min. size reported by min. size"
" calculation is: w = %d, h = %d\n", w, h);
edje_object_size_min_restricted_calc(edje_obj, &w, &h, 500, 500);
printf("The Edje object's min. size reported by *restricted* "
"min. size calculation is: w = %d, h = %d\n", w, h);
edje_object_size_min_restricted_calc
void edje_object_size_min_restricted_calc(Edje_Object *obj, int *minw, int *minh, int restrictedw, int restrictedh)
Calculates the minimum required size for a given Edje object.
Definition: edje_legacy.c:1065
edje_object_size_min_calc
void edje_object_size_min_calc(Edje_Object *obj, int *minw, int *minh)
Calculates the minimum required size for a given Edje object.
Definition: edje_legacy.c:1059

`"part_two"` part is there with a purpose: since it extrapolates the Edje object's boundaries, the edje_object_parts_extends_calc() function will report origin coordinates for the rectangle grouping both parts with negative values, indicating it extrapolates to the upper left of our group, just as we see it.

To interact with the last features exemplified in the program, there's a command line interface. A help string can be asked for with the 'h' key:

static const char commands[] = \
"commands are:\n"
"\ts - change Edje's global scaling factor\n"
"\tr - change center rectangle's scaling factor\n"
"\tEsc - exit\n"
"\th - print help\n";

Those commands will change the scaling factors of our Edje objects. The first of them, `'s'`, will change Edje's global scaling factor between `1.0` (no scaling) and `2.0` (double scale). Scaling will be applied to `"part_one"`, only, because that's the part flagged to be scaled at EDC level:

else if (strcmp(ev->key, "s") == 0) /* global scaling factor */
{
double scale = edje_scale_get();
printf("got scale %f\n", scale);
if (!EINA_DBL_EQ(scale, 1.0)) scale = 1.0;
else scale = 2.0;
edje_scale_set(scale);
printf("Setting global scaling factor to %f.\n", scale);
return;
}
edje_scale_get
double edje_scale_get(void)
Retrieves Edje's global scaling factor.
Definition: edje_util.c:401
edje_scale_set
void edje_scale_set(double scale)
Sets Edje's global scaling factor.
Definition: edje_util.c:391
EINA_DBL_EQ
#define EINA_DBL_EQ(a, b)
Safe comparison of double.
Definition: eina_util.h:100

Note, finally, that the `'s'` command will depend on the 'r' one to have its effects applied. The latter will change `"part_one"'s` individual scaling factor, which overrides Edje's global scaling factor. Only when the individual one is set to zero, will the global one take effect:

else if (strcmp(ev->key, "r") == 0) /* individual scaling factor */
{
double scale = edje_object_scale_get(edje_obj);
printf("got scale %f\n", scale);
if (EINA_DBL_EQ(scale, 0)) scale = 1.0;
else if (EINA_DBL_EQ(scale, 1.0)) scale = 2.0;
else scale = 0.0;
edje_object_scale_set(edje_obj, scale);
printf("Setting center rectangle's scaling factor to %f.\n",
scale);
return;
}
edje_object_scale_get
double edje_object_scale_get(const Edje_Object *obj)
Gets a given Edje object's scaling factor.
Definition: edje_legacy.c:215
edje_object_scale_set
Eina_Bool edje_object_scale_set(Edje_Object *obj, double scale)
Sets the scaling factor for a given Edje object.
Definition: edje_legacy.c:209

The example's window should look like this picture:

The full example follows.

#ifdef HAVE_CONFIG_H
# include "config.h"
#else
# define EINA_UNUSED
#endif
#ifndef PACKAGE_DATA_DIR
#define PACKAGE_DATA_DIR "."
#endif
#include <stdio.h>
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_Evas.h>
#include <Edje.h>
#define WIDTH (300)
#define HEIGHT (300)
static const char commands[] = \
"commands are:\n"
"\ts - change Edje's global scaling factor\n"
"\tr - change center rectangle's scaling factor\n"
"\tEsc - exit\n"
"\th - print help\n";
static void
_on_keydown(void *data,
Evas *evas EINA_UNUSED,
Evas_Object *o EINA_UNUSED,
void *einfo)
{
Evas_Event_Key_Down *ev;
Evas_Object *edje_obj;
ev = (Evas_Event_Key_Down *)einfo;
edje_obj = (Evas_Object *)data;
if (strcmp(ev->key, "h") == 0) /* print help */
{
printf(commands);
return;
}
else if (strcmp(ev->key, "s") == 0) /* global scaling factor */
{
double scale = edje_scale_get();
printf("got scale %f\n", scale);
if (!EINA_DBL_EQ(scale, 1.0)) scale = 1.0;
else scale = 2.0;
edje_scale_set(scale);
printf("Setting global scaling factor to %f.\n", scale);
return;
}
else if (strcmp(ev->key, "r") == 0) /* individual scaling factor */
{
double scale = edje_object_scale_get(edje_obj);
printf("got scale %f\n", scale);
if (EINA_DBL_EQ(scale, 0)) scale = 1.0;
else if (EINA_DBL_EQ(scale, 1.0)) scale = 2.0;
else scale = 0.0;
edje_object_scale_set(edje_obj, scale);
printf("Setting center rectangle's scaling factor to %f.\n",
scale);
return;
}
else if (!strcmp(ev->key, "Escape"))
ecore_main_loop_quit();
else
{
printf("unhandled key: %s\n", ev->key);
printf(commands);
}
}
static void
_on_delete(Ecore_Evas *ee EINA_UNUSED)
{
ecore_main_loop_quit();
}
int
main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
{
const char *img_file = PACKAGE_DATA_DIR"/red.png";
const char *edje_file = PACKAGE_DATA_DIR"/basic.edj";
Ecore_Evas *ee;
Evas *evas;
Evas_Object *bg;
Evas_Object *border;
Evas_Object *edje_obj;
int x;
int y;
int w;
int h;
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, WIDTH, HEIGHT, NULL);
if (!ee) goto shutdown_edje;
ecore_evas_callback_delete_request_set(ee, _on_delete);
ecore_evas_title_set(ee, "Edje Basics Example");
evas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(evas);
evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */
evas_object_move(bg, 0, 0); /* at canvas' origin */
evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */
evas_object_show(bg);
ecore_evas_object_associate(ee, bg, ECORE_EVAS_OBJECT_ASSOCIATE_BASE);
evas_object_focus_set(bg, EINA_TRUE);
edje_obj = edje_object_add(evas);
/* exercising Edje loading error, on purpose */
if (!edje_object_file_set(edje_obj, edje_file, "unexistant_group"))
{
int err = edje_object_load_error_get(edje_obj);
const char *errmsg = edje_load_error_str(err);
fprintf(stderr, "Could not load 'unexistant_group' from basic.edj:"
" %s\n", errmsg);
}
if (!edje_object_file_set(edje_obj, edje_file, "example_group"))
{
int err = edje_object_load_error_get(edje_obj);
const char *errmsg = edje_load_error_str(err);
fprintf(stderr, "Could not load 'example_group' from basic.edj: %s\n",
errmsg);
evas_object_del(edje_obj);
goto shutdown_edje;
}
printf("Loaded Edje object bound to group 'example_group' from"
" file basic.edj with success!\n");
evas_object_move(edje_obj, 20, 20);
evas_object_resize(edje_obj, WIDTH - 40, HEIGHT - 40);
evas_object_show(edje_obj);
evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, edje_obj);
/* this is a border around the Edje object above, here just to
* emphasize its geometry */
border = evas_object_image_filled_add(evas);
evas_object_image_file_set(border, img_file, NULL);
evas_object_image_border_set(border, 2, 2, 2, 2);
evas_object_image_border_center_fill_set(border, EVAS_BORDER_FILL_NONE);
evas_object_resize(border, WIDTH - 40 + 4, HEIGHT - 40 + 4);
evas_object_move(border, 20 - 2, 20 - 2);
evas_object_show(border);
printf("'example_data' data field in group 'example_group' has "
"the value: %s\n", edje_object_data_get(edje_obj,
"example_data"));
printf("Testing if 'part_one' part exists: %s\n",
edje_object_part_exists(edje_obj, "part_one") ? "yes!" : "no");
edje_object_part_geometry_get(edje_obj, "part_one", &x, &y, &w, &h);
printf("The geometry of that part inside the Edje object's area "
"is: x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
evas_object_color_get(edje_object_part_object_get(edje_obj, "part_one"),
&x, &y, &w, &h);
printf("That part's color components are: r = %d, g = %d, b = %d,"
" a = %d\n", x, y, w, h);
edje_object_size_max_get(edje_obj, &w, &h);
printf("The Edje object's max. size is: %d, %d\n", w, h);
edje_object_size_min_get(edje_obj, &w, &h);
printf("The Edje object's min. size is: %d, %d\n", w, h);
edje_object_size_min_calc(edje_obj, &w, &h);
printf("The Edje object's min. size reported by min. size"
" calculation is: w = %d, h = %d\n", w, h);
edje_object_size_min_restricted_calc(edje_obj, &w, &h, 500, 500);
printf("The Edje object's min. size reported by *restricted* "
"min. size calculation is: w = %d, h = %d\n", w, h);
edje_object_parts_extends_calc(edje_obj, &x, &y, &w, &h);
printf("The Edje object's \"extended\" geometry is: x = %d, "
"y = %d, w = %d, h = %d\n", x, y, w, h);
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.
Eina.h
Eina Utility 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:602
ecore_evas_title_set
EAPI void ecore_evas_title_set(Ecore_Evas *ee, const char *t)
Sets the title of an Ecore_Evas' window.
Definition: ecore_evas.c:1527
ecore_evas_callback_delete_request_set
EAPI void ecore_evas_callback_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
Sets a callback for Ecore_Evas delete request events.
Definition: ecore_evas.c:1176
ecore_evas_show
EAPI void ecore_evas_show(Ecore_Evas *ee)
Shows an Ecore_Evas' window.
Definition: ecore_evas.c:1480
ecore_evas_get
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition: ecore_evas.c:1300
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition: ecore_evas.c:666
ecore_evas_object_associate
EAPI Eina_Bool ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags)
Associates the given object to this ecore evas.
Definition: ecore_evas_util.c:223
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:1039
ecore_evas_free
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition: ecore_evas.c:1083
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_parts_extends_calc
Eina_Bool edje_object_parts_extends_calc(Edje_Object *obj, int *x, int *y, int *w, int *h)
Calculates the geometry of the region, relative to a given Edje object's area, occupied by all parts ...
Definition: edje_legacy.c:1083
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition: Evas_Common.h:163
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_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_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_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_image_border_set
EVAS_API void evas_object_image_border_set(Evas_Object *obj, int l, int r, int t, int b)
Dimensions of this image's border, a region that does not scale with the center area.
Definition: evas_image_legacy.c:117
evas_object_image_filled_add
EVAS_API Evas_Object * evas_object_image_filled_add(Evas *eo_e)
Creates a new image object that automatically scales its bound image to the object's area,...
Definition: evas_image_legacy.c:35
evas_object_image_border_center_fill_set
EVAS_API void evas_object_image_border_center_fill_set(Evas_Object *obj, Evas_Border_Fill_Mode fill)
Specifies how the center part of the object (not the borders) should be drawn when EFL is rendering i...
Definition: evas_image_legacy.c:145
evas_object_image_file_set
EVAS_API void evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
Set the source file from where an image object must fetch the real image data (it may be an Eet file,...
Definition: evas_image_legacy.c:194
EVAS_BORDER_FILL_NONE
@ EVAS_BORDER_FILL_NONE
Image's center region is not to be rendered.
Definition: Evas_Legacy.h:5721
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 press event.
Definition: Evas_Legacy.h:314
_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-basic edje-basic.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 basic.edc
    *