Dragable parts example

This example shows how to manipulate a dragable part through the edje_object_part_drag API.

First, in the edc code, we are declaring a part which will be our movable part, called "knob". It is a normal rectangle, which contains a block called "dragable", that will define the area where this rectangle can be moved, and in which axis it can be moved.

This is our part:

part {
name: "example/knob";
type: RECT;
mouse_events: 1;
dragable {
confine: "drag_area";
x: 0 0 0;
y: 1 1 0;
}
description {
state: "default" 0.0;
min: 10 10;
color: 255 0 0 200;
}
} // example/knob

Notice that it defines, through its `"x:"` and `"y:'` properties, that the part will be only moved on the y axis (vertical). Check the edc reference docs for more info about this.

Now, in our example C code, we just do the same as on the other examples, setting some global data on a structure, load the edje file and so:

static const char *PARTNAME = "example/knob";

We want to use the drag_page and drag_step functions, and in order to do so we need to define the step size and page size of our dragable part. They are defined as float values which represent a portion of the entire size of the dragable area:

We are going to use the keyboard to move the `knob` part, through the key down callback `_bg_key_down`, but we also want to know when the user has moved the knob by using the mouse (which is possible, since we defined that this part will receive mouse events). Thus, we set a callback for the signal "drag", which comes from the dragable part:

evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_bg_key_down, ee);
EVAS_CALLBACK_KEY_DOWN
@ EVAS_CALLBACK_KEY_DOWN
Key Press Event.
Definition: Evas_Common.h:430
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
edje_object_signal_callback_add(edje_obj, "drag", PARTNAME, _on_knob_moved, NULL);
edje_object_signal_callback_add
void edje_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
Adds a callback for an arriving Edje signal, emitted by a given Edje object.
Definition: edje_legacy.c:85

Now, let's take a look at our key down callback:

_on_bg_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info)
{
Ecore_Evas *ee;
Evas_Event_Key_Down *ev;
Evas_Object *edje_obj;
ee = (Ecore_Evas *)data;
ev = (Evas_Event_Key_Down *)event_info;
edje_obj = ecore_evas_data_get(ee, "edje_obj");
if (!strcmp(ev->key, "h"))
{
printf(commands);
return;
}
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:1092
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
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185
_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
else if (!strcmp(ev->key, "Down"))
{
edje_object_part_drag_step(edje_obj, PARTNAME, 0, 1.0);
}
edje_object_part_drag_step
Eina_Bool edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double dy)
Steps the dragable x,y steps.
Definition: edje_legacy.c:276
else if (!strcmp(ev->key, "Up"))
{
edje_object_part_drag_step(edje_obj, PARTNAME, 0, -1.0);
}
else if (!strcmp(ev->key, "m"))
{
edje_object_part_drag_value_set(edje_obj, PARTNAME, 0.0, 0.5);
}
edje_object_part_drag_value_set
Eina_Bool edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, double dy)
Sets the dragable object location.
Definition: edje_legacy.c:228
else if (!strcmp(ev->key, "Prior"))
{
edje_object_part_drag_page(edje_obj, PARTNAME, 0.0, -1.0);
}
edje_object_part_drag_page
Eina_Bool edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double dy)
Pages x,y steps.
Definition: edje_legacy.c:282
else if (!strcmp(ev->key, "Next"))
{
edje_object_part_drag_page(edje_obj, PARTNAME, 0.0, 1.0);
}
else if (!strcmp(ev->key, "Escape"))
ecore_main_loop_quit();
else
{
printf("unhandled key: %s\n", ev->key);
printf(commands);
}
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
}

On this callback we define that the user will use the "up" and "down" arrows to move the dragable part, respectively, -1.0 and 1.0 times the step size. And that the "Page Up" (Prior) and "Page Down" (Next) keys will move -1.0 and 1.0 times the page size. Both of these will occur on the vertical axis, since we pass 0.0 as value to the respective horizontal axis parameters. And our dragable part also only supports being moved in the vertical axis (defined in the edc).

We also define that the "m" key will be used to explicitly position the knob part in the middle of the dragable area.

And here is the callback for the `"drag"` signal that is received from the theme:

_on_knob_moved(void *data EINA_UNUSED, Evas_Object *o, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
double val;
edje_object_part_drag_value_get(o, PARTNAME, NULL, &val);
printf("value changed to: %0.3f\n", val);
}
edje_object_part_drag_value_get
Eina_Bool edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
Gets the dragable object location.
Definition: edje_legacy.c:234

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 <Ecore.h>
#include <Ecore_Evas.h>
#include <Edje.h>
#define WIDTH 300
#define HEIGHT 300
static const char commands[] = \
"commands are:\n"
"\tDown - set drag step to 1\n"
"\tUp - set drag step to -1\n"
"\tm - set drag value to 0.5\n"
"\tPrior - set drag page to -1\n"
"\tNext - set drag page to -1\n"
"\tEsc - exit\n"
"\th - print help\n";
static const char *PARTNAME = "example/knob";
static void
_on_destroy(Ecore_Evas *ee EINA_UNUSED)
{
ecore_main_loop_quit();
}
/* here just to keep our example's window size and background image's
* size in synchrony */
static void
_on_canvas_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_bg_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info)
{
Ecore_Evas *ee;
Evas_Event_Key_Down *ev;
Evas_Object *edje_obj;
ee = (Ecore_Evas *)data;
ev = (Evas_Event_Key_Down *)event_info;
edje_obj = ecore_evas_data_get(ee, "edje_obj");
if (!strcmp(ev->key, "h"))
{
printf(commands);
return;
}
else if (!strcmp(ev->key, "Down"))
{
edje_object_part_drag_step(edje_obj, PARTNAME, 0, 1.0);
}
else if (!strcmp(ev->key, "Up"))
{
edje_object_part_drag_step(edje_obj, PARTNAME, 0, -1.0);
}
else if (!strcmp(ev->key, "m"))
{
edje_object_part_drag_value_set(edje_obj, PARTNAME, 0.0, 0.5);
}
else if (!strcmp(ev->key, "Prior"))
{
edje_object_part_drag_page(edje_obj, PARTNAME, 0.0, -1.0);
}
else if (!strcmp(ev->key, "Next"))
{
edje_object_part_drag_page(edje_obj, PARTNAME, 0.0, 1.0);
}
else if (!strcmp(ev->key, "Escape"))
ecore_main_loop_quit();
else
{
printf("unhandled key: %s\n", ev->key);
printf(commands);
}
}
static void
_on_knob_moved(void *data EINA_UNUSED, Evas_Object *o, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
double val;
edje_object_part_drag_value_get(o, PARTNAME, NULL, &val);
printf("value changed to: %0.3f\n", val);
}
int
main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
{
const char *edje_file = PACKAGE_DATA_DIR"/drag.edj";
Ecore_Evas *ee;
Evas *evas;
Evas_Object *bg;
Evas_Object *edje_obj;
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_destroy_set(ee, _on_destroy);
ecore_evas_callback_resize_set(ee, _on_canvas_resize);
ecore_evas_title_set(ee, "Edje Drag Example");
evas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(evas);
evas_object_color_set(bg, 255, 255, 255, 255);
evas_object_resize(bg, WIDTH, HEIGHT);
evas_object_focus_set(bg, EINA_TRUE);
evas_object_show(bg);
ecore_evas_data_set(ee, "background", bg);
evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_bg_key_down, ee);
edje_obj = edje_object_add(evas);
if (!edje_object_file_set(edje_obj, edje_file, "example/group"))
printf("failed to set file %s.\n", edje_file);
evas_object_move(edje_obj, 0, 0);
evas_object_resize(edje_obj, WIDTH, HEIGHT);
evas_object_show(edje_obj);
ecore_evas_data_set(ee, "edje_obj", edje_obj);
edje_object_part_drag_size_set(edje_obj, PARTNAME, 1.0, 0.4);
if (!edje_object_part_drag_step_set(edje_obj, PARTNAME, 0.0, 0.1))
printf("error when setting drag step size.\n");
if (!edje_object_part_drag_page_set(edje_obj, PARTNAME, 0.0, 0.3))
printf("error when setting drag page step size.\n");
edje_object_signal_callback_add(edje_obj, "drag", PARTNAME, _on_knob_moved, NULL);
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.
ecore_evas_init
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition: ecore_evas.c:602
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:1185
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_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_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:1362
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:1103
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:1140
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition: ecore_evas.c:666
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_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_drag_size_set
Eina_Bool edje_object_part_drag_size_set(Evas_Object *obj, const char *part, double dw, double dh)
Sets the dragable object size.
Definition: edje_legacy.c:240
edje_object_part_drag_page_set
Eina_Bool edje_object_part_drag_page_set(Evas_Object *obj, const char *part, double dx, double dy)
Sets the page step increments.
Definition: edje_legacy.c:264
edje_object_part_drag_step_set
Eina_Bool edje_object_part_drag_step_set(Evas_Object *obj, const char *part, double dx, double dy)
Sets the drag step increment.
Definition: edje_legacy.c:252
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
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_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_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_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_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

To compile use this command:

    * gcc -o edje-drag edje-drag.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 drag.edc
    *