From b64eb106207241982e39fe33f27669541b102110 Mon Sep 17 00:00:00 2001 From: glima Date: Tue, 5 Jul 2011 21:10:19 +0000 Subject: [PATCH] [evas] Documenting and exemplifying the following: - evas_object_smart_add - evas_object_smart_calculate - evas_object_smart_changed - evas_object_smart_clipped_class_get - evas_object_smart_clipped_clipper_get - evas_object_smart_clipped_smart_set - evas_object_smart_data_get - evas_object_smart_data_set git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@61062 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- doc/examples.dox | 148 ++++++++++ src/examples/Makefile.am | 8 +- src/examples/evas-smart-object.c | 610 +++++++++++++++++++++++++++++++++++++++ src/lib/Evas.h | 286 +++++++++++------- 4 files changed, 954 insertions(+), 98 deletions(-) create mode 100644 src/examples/evas-smart-object.c diff --git a/doc/examples.dox b/doc/examples.dox index 96d65b7..4e7e1f2 100644 --- a/doc/examples.dox +++ b/doc/examples.dox @@ -20,6 +20,8 @@ * @ref Example_Evas_Size_Hints * * @ref Example_Evas_Stacking + * + * @ref Example_Evas_Smart_Objects */ /** @@ -486,3 +488,149 @@ * * @example evas-map-utils.c */ + +/** + * @page Example_Evas_Smart_Objects Evas object smart objects + * @dontinclude evas-smart-object.c + * + * In this example, we illustrate how to create and handle Evas smart objects. + * + * A smart object is one that provides custom functions to handle + * clipping, hiding, moving, resizing, color setting and more on @b + * child elements, automatically, for the smart object's user. They + * could be as simple as a group of objects that move together (see + * @ref Evas_Smart_Object_Clipped) or implementations of whole complex + * UI widgets, providing some intelligence (thus the name) and + * extension to simple Evas objects. + * + * Here, we create one as an example. What it does is to control (at + * maximum) 2 child objects, with regard to their geometries and + * colors. There can be a "left" child and a "right" one. The former + * will always occupy the top left quadrant of the smart object's + * area, while the latter will occupy the bottom right. The smart + * object will also contain an @b internal decorative border object, + * which will also be controlled by it, naturally. + * + * Here is where we add it to the canvas: + * @skip d.smt = evas_smart_example_add(d.evas); + * @until show + * + * The magic starts to happen in the @c evas_smart_example_add() + * function, which is one in the example smart object's defined @b + * interface. These should be the functions you would export to the + * users of your smart object. We made three for this one: + * - @c evas_smart_example_add(): add a new instance of the example + * smart object to a canvas + * - @c evas_smart_example_remove(): remove a given child of the smart + * object from it + * - @c evas_smart_example_set_left(): set the left child of the smart + * object + * - @c evas_smart_example_set_right(): set the right child of the + * smart object + * + * The object's creation takes place as: + * @dontinclude evas-smart-object.c + * @skip add a new example smart object to a canvas + * @until } + * + * Smart objects are define by smart classes, which are structs + * defining their interfaces, or smart functions (see + * #Evas_Smart_Class, the base class for any smart object). As you + * see, one has to use the evas_object_smart_add() function to + * instantiate smart objects. Its second parameter is what matters -- + * an #Evas_Smart struct, which contains all the smart class + * definitions (smart functions, smart callbacks, and the like). Note, + * however, that @c _evas_smart_example_smart_class_new() seems not to + * be defined in our example's code. That's because it came from a very + * handy helper macro: + * @dontinclude evas-smart-object.c + * @skip EVAS_SMART_SUBCLASS_NEW + * @until _signals + * What it does is to @b subclass a given existing smart class, thus + * specializing it. This is very common and useful in Evas. There is a + * built-in smart object, the "clipped smart object", whose behavior is + * mostly desired by many other smart object implementors: it will clip + * its children to its area and move them along with it, on + * evas_object_resize() calls. Then, our example smart object will get + * that behavior for free. + * + * The first argument to the macro, + * @dontinclude evas-smart-object.c + * @skip _evas_smart_example_type + * @until _evas_smart_example_type + * will define the new smart class' name. The second tells the macro + * what is the @b prefix of the function it will be declaring with a @c + * _smart_set_user() suffix. On this function, we may override/extend + * any desired method from our parent smart class: + * @dontinclude evas-smart-object.c + * @skip setting our smart interface + * @until } + * + * The first function pointer's code will take place at an example + * smart object's @b creation time: + * @dontinclude evas-smart-object.c + * @skip create and setup + * @until } + * + * The #EVAS_SMART_DATA_ALLOC macro will take care of allocating our + * smart object data, which will be available on other contexts for us + * (mainly in our interface functions): + * @dontinclude evas-smart-object.c + * @skip typedef struct _Evas_Smart_Example_Data + * @until }; + * + * + * See that, as we're inheriting from the clipped smart object's + * class, we @b must have their data struct as our first member. Other + * data of interest for us is a child members array and the border + * object's handle. The latter is what is created in the last + * mentioned function. Note how to tell Evas the border will be + * managed by our smart object from that time on: + * evas_object_smart_member_add(priv->border, o);. + * + * At the end of that function we make use of an constant defined by + * the #EVAS_SMART_SUBCLASS_NEW: @c _evas_smart_example_parent_sc. It + * has the same prefix we passed to the macro, as you can see, and it + * holds a pointer to our @b parent smart class. Then, we can call the + * specialized method, itself, after our code. The @c del, @c hide, @c + * show and @c resize specializations are straightforward, we let the + * reader take a look at them below to check their behavior. What's + * interesting is the @c calculate one: + * @dontinclude evas-smart-object.c + * @skip act on child objects' properties + * @until setting + * + * This code will take place whenever the smart object itself is + * flagged "dirty", i.e., must be recalculated for rendering (that + * could come from changes on its clipper, resizing, moving, + * etc). There, we make sure the decorative border lies on the edges of + * the smart object and the children, if any, lie on their respective + * quadrants. + * + * As in other examples, to interact with this one there's a command + * line interface, whose help string can be asked for with the 'h' key: + * + * @dontinclude evas-smart-object.c + * @skip static const char *commands = + * @until ; + * Use 'l' and 'r' keys, to create new rectangles and place them on the + * left (@c evas_smart_example_set_left()) or right + * (@c evas_smart_example_set_right()) spots of our smart object, + * respectively. The keyboard arrows will move the smart object along + * the canvas. See how it takes any child objects with it during its + * movement. The 'd' and 'i' keys will increase or decrease the smart + * object's size -- see how it affects the children's sizes, + * too. Finally, 'c' will change the color of the smart object's + * clipper (which is the exact internal clipper coming from a clipped + * smart object): + * @dontinclude evas-smart-object.c + * @skip d.clipper = + * @until .a); + * + * "Real life" examples of smart objects are Edje and Emotion objects: + * they both have independent libraries implementing their + * behavior. The full example follows. + * + * @include evas-smart-object.c + * @example evas-smart-object.c + */ diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index ff3eca1..7a2b10a 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am @@ -73,6 +73,10 @@ pkglib_PROGRAMS += evas_text evas_text_SOURCES = evas-text.c evas_text_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@ +pkglib_PROGRAMS += evas_smart_object +evas_smart_object_SOURCES = evas-smart-object.c +evas_smart_object_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@ + #the ones using ecore_evas and edje follow AM_CPPFLAGS += @EDJE_CFLAGS@ @@ -116,7 +120,8 @@ files_DATA += \ $(srcdir)/evas-hints.c \ $(srcdir)/evas-stacking.c \ $(srcdir)/evas-map-utils.c \ - $(srcdir)/evas-text.c + $(srcdir)/evas-text.c \ + $(srcdir)/evas-smart-object.c endif EXTRA_DIST = $(EDCS) \ @@ -131,6 +136,7 @@ EXTRA_DIST = $(EDCS) \ $(srcdir)/evas-stacking.c \ $(srcdir)/evas-map-utils.c \ $(srcdir)/evas-text.c \ + $(srcdir)/evas-smart-object.c $(srcdir)/enlightenment.png \ $(srcdir)/red.png \ $(srcdir)/im1.png \ diff --git a/src/examples/evas-smart-object.c b/src/examples/evas-smart-object.c new file mode 100644 index 0000000..85ab3b3 --- /dev/null +++ b/src/examples/evas-smart-object.c @@ -0,0 +1,610 @@ +/** + * Simple Evas example illustrating a custom Evas smart object + * + * You'll need at least one engine built for it (excluding the buffer + * one). See stdout/stderr for output. + * + * @verbatim + * gcc -o evas-smart-object evas-smart-object.c `pkg-config --libs --cflags evas ecore ecore-evas` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H + +#include "config.h" +#else + +#define PACKAGE_EXAMPLES_DIR "." +#define __UNUSED__ + +#endif + +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static const char *commands = \ + "commands are:\n" + "\tl - insert child rectangle on the left\n" + "\tr - insert child rectangle on the right\n" + "\tright arrow - move smart object to the right\n" + "\tleft arrow - move smart object to the left\n" + "\tup arrow - move smart object up\n" + "\tdown arrow - move smart object down\n" + "\td - decrease smart object's size\n" + "\ti - increase smart object's size\n" + "\tc - change smart object's clipper color\n" + "\th - print help\n"; + +#define WHITE {255, 255, 255, 255} +#define RED {255, 0, 0, 255} +#define GREEN {0, 255, 0, 255} +#define BLUE {0, 0, 255, 255} + +struct test_data +{ + Ecore_Evas *ee; + Evas *evas; + Evas_Object *smt, *bg, *clipper; +}; + +struct color_tuple +{ + int r, g, b, a; +} clipper_colors[4] = {WHITE, RED, GREEN, BLUE}; +int cur_color = 0; + +static const char * +_index_to_color(int i) +{ + switch (i) + { + case 0: + return "WHITE (default)"; + + case 1: + return "RED"; + + case 2: + return "GREEN"; + + case 3: + return "BLUE"; + + default: + return "other"; + } +} + +static struct test_data d = {0}; +static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png"; + +#define _evas_smart_example_type "Evas_Smart_Example" +#define SIG_CHILD_ADDED "child,added" +#define SIG_CHILD_REMOVED "child,removed" + +static const Evas_Smart_Cb_Description _signals[] = +{ + {SIG_CHILD_ADDED, ""}, + {SIG_CHILD_REMOVED, ""}, + {NULL, NULL} +}; + +typedef struct _Evas_Smart_Example_Data Evas_Smart_Example_Data; +/* + * This structure augments clipped smart object's instance data, + * providing extra members required by our example smart object's + * implementation. + */ +struct _Evas_Smart_Example_Data +{ + Evas_Object_Smart_Clipped_Data base; + Evas_Object *children[2], *border; +}; + +#define EVAS_SMART_EXAMPLE_DATA_GET(o, ptr) \ + Evas_Smart_Example_Data * ptr = evas_object_smart_data_get(o) + +#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, ptr) \ + EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + fprintf(stderr, "No widget data for object %p (%s)!", \ + o, evas_object_type_get(o)); \ + fflush(stderr); \ + abort(); \ + return; \ + } + +#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + fprintf(stderr, "No widget data for object %p (%s)!", \ + o, evas_object_type_get(o)); \ + fflush(stderr); \ + abort(); \ + return val; \ + } + +EVAS_SMART_SUBCLASS_NEW(_evas_smart_example_type, _evas_smart_example, + Evas_Smart_Class, Evas_Smart_Class, + evas_object_smart_clipped_class_get, _signals); + +static void +_on_destroy(Ecore_Evas *ee __UNUSED__) +{ + ecore_main_loop_quit(); +} + +/* here just to keep our example's window size and background image's + * size in synchrony */ +static void +_canvas_resize_cb(Ecore_Evas *ee) +{ + int w, h; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(d.bg, w, h); +} + +static void +_on_child_del(void *data, + Evas *evas __UNUSED__, + Evas_Object *o, + void *einfo __UNUSED__) +{ + Evas_Object *example_smart = data; + int index; + + EVAS_SMART_EXAMPLE_DATA_GET(example_smart, priv); + + index = (int)evas_object_data_get(o, "index"); + index--; + + priv->children[index] = NULL; + + evas_object_smart_member_del(o); + evas_object_smart_changed(example_smart); +} + +static void +_evas_smart_example_child_callbacks_unregister(Evas_Object *obj) +{ + evas_object_data_set(obj, "index", NULL); + evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE, _on_child_del); +} + +static void +_evas_smart_example_child_callbacks_register(Evas_Object *o, + Evas_Object *child, + int index) +{ + evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _on_child_del, o); + evas_object_data_set(child, "index", (void *)(++index)); +} + +/* create and setup a new example smart object's internals */ +static void +_evas_smart_example_smart_add(Evas_Object *o) +{ + EVAS_SMART_DATA_ALLOC(o, Evas_Smart_Example_Data); + + /* this is a border around the smart object's area, delimiting it */ + priv->border = evas_object_image_filled_add(evas_object_evas_get(o)); + evas_object_image_file_set(priv->border, border_img_path, NULL); + evas_object_image_border_set(priv->border, 3, 3, 3, 3); + evas_object_image_border_center_fill_set( + priv->border, EVAS_BORDER_FILL_NONE); + evas_object_smart_member_add(priv->border, o); + + _evas_smart_example_parent_sc->add(o); +} + +static void +_evas_smart_example_smart_del(Evas_Object *o) +{ + EVAS_SMART_EXAMPLE_DATA_GET(o, priv); + + if (priv->children[0]) + { + _evas_smart_example_child_callbacks_unregister(priv->children[0]); + priv->children[0] = NULL; + } + + if (priv->children[1]) + { + _evas_smart_example_child_callbacks_unregister(priv->children[1]); + priv->children[1] = NULL; + } + + _evas_smart_example_parent_sc->del(o); +} + +static void +_evas_smart_example_smart_show(Evas_Object *o) +{ + EVAS_SMART_EXAMPLE_DATA_GET(o, priv); + + if (priv->children[0]) evas_object_show(priv->children[0]); + if (priv->children[1]) evas_object_show(priv->children[1]); + evas_object_show(priv->border); + + _evas_smart_example_parent_sc->show(o); +} + +static void +_evas_smart_example_smart_hide(Evas_Object *o) +{ + EVAS_SMART_EXAMPLE_DATA_GET(o, priv); + + if (priv->children[0]) evas_object_hide(priv->children[0]); + if (priv->children[1]) evas_object_hide(priv->children[1]); + evas_object_hide(priv->border); + + _evas_smart_example_parent_sc->hide(o); +} + +static void +_evas_smart_example_smart_resize(Evas_Object *o, + Evas_Coord w, + Evas_Coord h) +{ + Evas_Coord ow, oh; + evas_object_geometry_get(o, NULL, NULL, &ow, &oh); + if ((ow == w) && (oh == h)) return; + + /* this will trigger recalculation */ + evas_object_smart_changed(o); +} + +/* act on child objects' properties, before rendering */ +static void +_evas_smart_example_smart_calculate(Evas_Object *o) +{ + Evas_Coord x, y, w, h; + + EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, priv); + evas_object_geometry_get(o, &x, &y, &w, &h); + + evas_object_resize(priv->border, w, h); + evas_object_move(priv->border, x, y); + + if (priv->children[0]) + { + evas_object_move(priv->children[0], x + 3, y + 3); + evas_object_resize(priv->children[0], (w / 2) - 3, (h / 2) - 3); + } + + if (priv->children[1]) + { + evas_object_move(priv->children[1], x + (w / 2), y + (h / 2)); + evas_object_resize(priv->children[1], (w / 2) - 3, (h / 2) - 3); + } +} + +/* setting our smart interface */ +static void +_evas_smart_example_smart_set_user(Evas_Smart_Class *sc) +{ + /* specializing these two */ + sc->add = _evas_smart_example_smart_add; + sc->del = _evas_smart_example_smart_del; + sc->show = _evas_smart_example_smart_show; + sc->hide = _evas_smart_example_smart_hide; + + /* clipped smart object has no hook on resizes or calculations */ + sc->resize = _evas_smart_example_smart_resize; + sc->calculate = _evas_smart_example_smart_calculate; +} + +/* BEGINS example smart object's own interface */ + +/* add a new example smart object to a canvas */ +Evas_Object * +evas_smart_example_add(Evas *evas) +{ + return evas_object_smart_add(evas, _evas_smart_example_smart_class_new()); +} + +/* remove a child element, return its pointer (or NULL on errors) */ +Evas_Object * +evas_smart_example_remove(Evas_Object *o, + Evas_Object *child) +{ + int index; + + EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL); + + if (priv->children[0] != child && priv->children[1] != child) + { + fprintf(stderr, "You are trying to remove something not belonging to" + " the example smart object!\n"); + return NULL; + } + + index = (int)evas_object_data_get(child, "index"); + index--; + + priv->children[index] = NULL; + + evas_object_smart_callback_call(o, SIG_CHILD_REMOVED, child); + _evas_smart_example_child_callbacks_unregister(child); + evas_object_smart_member_del(child); + evas_object_smart_changed(o); + + return child; +} + +/* set to return any previous object set to the left position of the + * smart object or NULL, if any (or on errors) */ +Evas_Object * +evas_smart_example_set_left(Evas_Object *o, + Evas_Object *child) +{ + Evas_Object *ret = NULL; + + EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL); + if (!child) + return NULL; + + if (priv->children[1] == child) + { + fprintf(stderr, "You mustn't place a child on both slots of" + " the example smart object!\n"); + return NULL; + } + + if (priv->children[0]) + { + if (priv->children[0] != child) + ret = evas_smart_example_remove(o, priv->children[0]); + else return child; + } + + priv->children[0] = child; + evas_object_smart_callback_call(o, SIG_CHILD_ADDED, child); + + _evas_smart_example_child_callbacks_register(o, child, 0); + evas_object_smart_member_add(child, o); + evas_object_smart_changed(o); + + return ret; +} + +/* set to return any previous object set to the right position of the + * smart object or NULL, if any (or on errors) */ +Evas_Object * +evas_smart_example_set_right(Evas_Object *o, + Evas_Object *child) +{ + Evas_Object *ret = NULL; + + EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL); + if (!child) + return NULL; + + if (priv->children[0] == child) + { + fprintf(stderr, "You mustn't place a child on both slots of" + " the example smart object!\n"); + return NULL; + } + + if (priv->children[1]) + { + if (priv->children[1] != child) + ret = evas_smart_example_remove(o, priv->children[1]); + else return child; + } + + priv->children[1] = child; + evas_object_smart_callback_call(o, SIG_CHILD_ADDED, child); + + _evas_smart_example_child_callbacks_register(o, child, 1); + evas_object_smart_member_add(child, o); + evas_object_smart_changed(o); + + return ret; +} + +/* END OF example smart object's own interface */ + +static void +_on_keydown(void *data __UNUSED__, + Evas *evas __UNUSED__, + Evas_Object *o __UNUSED__, + void *einfo) +{ + Evas_Event_Key_Down *ev = einfo; + + if (strcmp(ev->keyname, "h") == 0) /* print help */ + { + fprintf(stdout, commands); + return; + } + + if (strcmp(ev->keyname, "l") == 0) /* insert random colored + * rectangle on the left */ + { + Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev; + evas_object_color_set( + rect, rand() % 255, rand() % 255, rand() % 255, 255); + evas_object_show(rect); + + prev = evas_smart_example_set_left(d.smt, rect); + fprintf(stdout, "Setting smart object's left spot with a new" + " rectangle.\n"); + if (prev) + { + int r, g, b; + + evas_object_color_get(prev, &r, &g, &b, NULL); + fprintf(stdout, "Deleting previous left child," + " which had colors (%d, %d, %d)\n", r, g, b); + evas_object_del(prev); + } + + return; + } + + if (strcmp(ev->keyname, "r") == 0) /* insert random colored + * rectangle on the right */ + { + Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev; + evas_object_color_set( + rect, rand() % 255, rand() % 255, rand() % 255, 255); + evas_object_show(rect); + + prev = evas_smart_example_set_right(d.smt, rect); + fprintf(stdout, "Setting smart object's right spot with a new" + " rectangle.\n"); + if (prev) + { + int r, g, b; + + evas_object_color_get(prev, &r, &g, &b, NULL); + fprintf(stdout, "Deleting previous right child," + " which had colors (%d, %d, %d)\n", r, g, b); + evas_object_del(prev); + } + + return; + } + + /* move smart object along the canvas */ + if (strcmp(ev->keyname, "Right") == 0 || strcmp(ev->keyname, "Left") == 0 || + strcmp(ev->keyname, "Up") == 0 || strcmp(ev->keyname, "Down") == 0) + { + Evas_Coord x, y; + + evas_object_geometry_get(d.smt, &x, &y, NULL, NULL); + + switch (ev->keyname[0]) + { + case 'R': + x += 20; + break; + + case 'L': + x -= 20; + break; + + case 'U': + y -= 20; + break; + + case 'D': + y += 20; + break; + } + + evas_object_move(d.smt, x, y); + + return; + } + + /* increase smart object's size */ + if (strcmp(ev->keyname, "i") == 0) + { + Evas_Coord w, h; + + evas_object_geometry_get(d.smt, NULL, NULL, &w, &h); + + w *= 1.1; + h *= 1.1; + + evas_object_resize(d.smt, w, h); + + return; + } + + /* decrease smart object's size */ + if (strcmp(ev->keyname, "d") == 0) + { + Evas_Coord w, h; + + evas_object_geometry_get(d.smt, NULL, NULL, &w, &h); + + w *= 0.9; + h *= 0.9; + + evas_object_resize(d.smt, w, h); + + return; + } + + /* change smart object's clipper color */ + if (strcmp(ev->keyname, "c") == 0) + { + cur_color = (cur_color + 1) % 4; + + evas_object_color_set( + d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g, + clipper_colors[cur_color].b, clipper_colors[cur_color].a); + + fprintf (stderr, "Changing clipper's color to %s\n", + _index_to_color(cur_color)); + + return; + } +} + +int +main(void) +{ + srand(time(NULL)); + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!d.ee) + goto error; + + ecore_evas_callback_destroy_set(d.ee, _on_destroy); + ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb); + ecore_evas_show(d.ee); + + /* the canvas pointer, de facto */ + d.evas = ecore_evas_get(d.ee); + + d.bg = evas_object_rectangle_add(d.evas); + evas_object_color_set(d.bg, 255, 255, 255, 255); + evas_object_move(d.bg, 0, 0); + evas_object_resize(d.bg, WIDTH, HEIGHT); + evas_object_show(d.bg); + + d.smt = evas_smart_example_add(d.evas); + evas_object_move(d.smt, WIDTH / 4, HEIGHT / 4); + evas_object_resize(d.smt, WIDTH / 2, HEIGHT / 2); + evas_object_show(d.smt); + + d.clipper = evas_object_smart_clipped_clipper_get(d.smt); + evas_object_color_set( + d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g, + clipper_colors[cur_color].b, clipper_colors[cur_color].a); + + evas_object_focus_set(d.bg, EINA_TRUE); + evas_object_event_callback_add( + d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL); + + fprintf(stdout, commands); + ecore_main_loop_begin(); + + ecore_evas_free(d.ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + ecore_evas_shutdown(); + return -1; +} diff --git a/src/lib/Evas.h b/src/lib/Evas.h index fdb056b..52b85b3 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -467,7 +467,9 @@ typedef struct _Evas_Precision_Position Evas_Precision_Position; /**< assoc /** * @typedef Evas_Smart_Class - * A smart object base class + * + * A smart object's @b base class definition + * * @ingroup Evas_Smart_Group */ typedef struct _Evas_Smart_Class Evas_Smart_Class; @@ -7755,35 +7757,40 @@ EAPI void evas_object_polygon_points_clear (Evas_Object *obj) EINA /** * @def EVAS_SMART_CLASS_VERSION - * The version you have to put into the version field in the smart - * class struct + * + * The version you have to put into the version field in the + * #Evas_Smart_Class struct. Used to safeguard from binaries with old + * smart object intefaces running with newer ones. + * * @ingroup Evas_Smart_Group */ #define EVAS_SMART_CLASS_VERSION 4 /** * @struct _Evas_Smart_Class - * a smart object class + * + * A smart object's @b base class definition + * * @ingroup Evas_Smart_Group */ struct _Evas_Smart_Class { - const char *name; /**< the string name of the class */ + const char *name; /**< the name string of the class */ int version; - void (*add) (Evas_Object *o); - void (*del) (Evas_Object *o); - void (*move) (Evas_Object *o, Evas_Coord x, Evas_Coord y); - void (*resize) (Evas_Object *o, Evas_Coord w, Evas_Coord h); - void (*show) (Evas_Object *o); - void (*hide) (Evas_Object *o); - void (*color_set) (Evas_Object *o, int r, int g, int b, int a); - void (*clip_set) (Evas_Object *o, Evas_Object *clip); - void (*clip_unset) (Evas_Object *o); - void (*calculate) (Evas_Object *o); - void (*member_add) (Evas_Object *o, Evas_Object *child); - void (*member_del) (Evas_Object *o, Evas_Object *child); + void (*add) (Evas_Object *o); /**< code to be run when adding object to a canvas */ + void (*del) (Evas_Object *o); /**< code to be run when removing object to a canvas */ + void (*move) (Evas_Object *o, Evas_Coord x, Evas_Coord y); /**< code to be run when moving object on a canvas */ + void (*resize) (Evas_Object *o, Evas_Coord w, Evas_Coord h); /**< code to be run when resizing object on a canvas */ + void (*show) (Evas_Object *o); /**< code to be run when showing object on a canvas */ + void (*hide) (Evas_Object *o); /**< code to be run when hiding object on a canvas */ + void (*color_set) (Evas_Object *o, int r, int g, int b, int a); /**< code to be run when setting color of object on a canvas */ + void (*clip_set) (Evas_Object *o, Evas_Object *clip); /**< code to be run when setting clipper of object on a canvas */ + void (*clip_unset) (Evas_Object *o); /**< code to be run when unsetting clipper of object on a canvas */ + void (*calculate) (Evas_Object *o); /**< code to be run when object has rendering updates on a canvas */ + void (*member_add) (Evas_Object *o, Evas_Object *child); /**< code to be run when child member is added to object */ + void (*member_del) (Evas_Object *o, Evas_Object *child); /**< code to be run when child member is removed from object */ const Evas_Smart_Class *parent; /**< this class inherits from this parent */ - const Evas_Smart_Cb_Description *callbacks; /**< callbacks at this level, NULL terminated */ + const Evas_Smart_Cb_Description *callbacks; /**< callbacks at this level, @c NULL terminated */ void *interfaces; /**< to be used in a future near you */ const void *data; }; @@ -7925,31 +7932,40 @@ struct _Evas_Smart_Cb_Description /** * @def EVAS_SMART_SUBCLASS_NEW * - * Convenience macro to subclass a Smart Class. - * - * This macro saves some typing when writing a Smart Class derived from - * another one. In order to work, the user needs to provide some functions - * adhering to the following guidelines. - * - @_smart_set_user(): the internal _smart_set function will call - * this one provided by the user after inheriting everything from the - * parent, which should take care of setting the right member functions - * for the class. - * - @_parent_sc: pointer to the smart class of the parent. When calling - * parent functions from overloaded ones, use this global variable. - * - @_smart_class_new(): this function returns the Evas_Smart needed - * to create smart objects with this class, should be called by the public - * _add() function. - * - If this new class should be subclassable as well, a public _smart_set() - * function is desirable to fill the class used as parent by the children. - * It's up to the user to provide this interface, which will most likely - * call @_smart_set() to get the job done. - * - * @param smart_name The name used for the Smart Class. e.g: "Evas_Object_Box". - * @param prefix Prefix used for all variables and functions defined. - * @param api_type Type of the structure used as API for the Smart Class. Either Evas_Smart_Class or something derived from it. + * Convenience macro to subclass a given Evas smart class. + * + * @param smart_name The name used for the smart class. e.g: + * @c "Evas_Object_Box". + * @param prefix Prefix used for all variables and functions defined + * and referenced by this macro. + * @param api_type Type of the structure used as API for the smart + * class. Either #Evas_Smart_Class or something derived from it. * @param parent_type Type of the parent class API. - * @param parent_func Function that gets the parent class. e.g: evas_object_box_smart_class_get(). - * @param cb_desc Array of callback descriptions for this Smart Class. + * @param parent_func Function that gets the parent class. e.g: + * evas_object_box_smart_class_get(). + * @param cb_desc Array of callback descriptions for this smart class. + * + * This macro saves some typing when writing a smart class derived + * from another one. In order to work, the user @b must provide some + * functions adhering to the following guidelines: + * - @_smart_set_user(): the @b internal @c _smart_set + * function (defined by this macro) will call this one, provided by + * the user, after inheriting everything from the parent, which + * should take care of setting the right member functions for + * the class, both overrides and extensions, if any. + * - If this new class should be subclassable as well, a @b public @c + * _smart_set() function is desirable to fill in the class used as + * parent by the children. It's up to the user to provide this + * interface, which will most likely call @_smart_set() to + * get the job done. + * + * After the macro's usage, the following will be defined for use: + * - @_parent_sc: A pointer to the @b parent smart + * class. When calling parent functions from overloaded ones, use + * this global variable. + * - @_smart_class_new(): this function returns the + * #Evas_Smart needed to create smart objects with this class, + * which should be passed to evas_object_smart_add(). * * @ingroup Evas_Smart_Group */ @@ -7985,14 +8001,21 @@ struct _Evas_Smart_Cb_Description /** * @def EVAS_SMART_DATA_ALLOC + * * Convenience macro to allocate smart data only if needed. * - * When writing a subclassable smart object, the .add function will need - * to check if the smart private data was already allocated by some child - * object or not. This macro makes it easier to do it. + * When writing a subclassable smart object, the @c .add() function + * will need to check if the smart private data was already allocated + * by some child object or not. This macro makes it easier to do it. * - * @param o Evas object passed to the .add function + * @note This is an idiom used when one calls the parent's @c. add() + * after the specialized code. Naturally, the parent's base smart data + * has to be contemplated as the specialized one's first member, for + * things to work. + * + * @param o Evas object passed to the @c .add() function * @param priv_type The type of the data to allocate + * * @ingroup Evas_Smart_Group */ #define EVAS_SMART_DATA_ALLOC(o, priv_type) \ @@ -8147,23 +8170,39 @@ EAPI int evas_smart_usage_get(const Evas_Smart *s); /** * @defgroup Evas_Smart_Object_Group Smart Object Functions * - * Functions dealing with evas smart objects (instances). + * Functions dealing with Evas smart objects (instances). * - * Smart objects are groupings of primitive Evas objects that behave as a - * cohesive group. For instance, a file manager icon may be a smart object - * composed of an image object, a text label and two rectangles that appear - * behind the image and text when the icon is selected. As a smart object, - * the normal evas api could be used on the icon object. + * Smart objects are groupings of primitive Evas objects that behave + * as a cohesive group. For instance, a file manager icon may be a + * smart object composed of an image object, a text label and two + * rectangles that appear behind the image and text when the icon is + * selected. As a smart object, the normal Evas object API could be + * used on the icon object. + * + * See some @ref Example_Evas_Smart_Objects "examples" of this group + * of functions. * * @see @ref Evas_Smart_Group for class definitions. */ /** + * @addtogroup Evas_Smart_Object_Group + * @{ + */ + +/** * Instantiates a new smart object described by @p s. * - * @param e the evas on which to add the object - * @param s the Evas_Smart describing the smart object - * @return a new Evas_Object + * @param e the canvas on which to add the object + * @param s the #Evas_Smart describing the smart object + * @return a new #Evas_Object handle + * + * This is the function one should use when defining the public + * function @b adding an instance of the new smart object to a given + * canvas. It will take care of setting all of its internals to work + * as they should, if the user set things properly, as seem on the + * #EVAS_SMART_SUBCLASS_NEW, for example. + * * @ingroup Evas_Smart_Object_Group */ EAPI Evas_Object *evas_object_smart_add (Evas *e, Evas_Smart *s) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_MALLOC; @@ -8241,20 +8280,30 @@ EAPI Eina_List *evas_object_smart_members_get (const Evas_Object *obj EAPI Evas_Smart *evas_object_smart_smart_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Retrieve user data stored on a smart object. + * Retrieve user data stored on a given smart object. + * + * @param obj The smart object's handle + * @return A pointer to data stored using + * evas_object_smart_data_set(), or @c NULL, if none has been + * set. + * + * @see evas_object_smart_data_set() * - * @param obj The smart object - * @return A pointer to data stored using evas_object_smart_data_set(), or - * NULL if none has been set. * @ingroup Evas_Smart_Object_Group */ EAPI void *evas_object_smart_data_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Store a pointer to user data for a smart object. + * Store a pointer to user data for a given smart object. * - * @param obj The smart object + * @param obj The smart object's handle * @param data A pointer to user data + * + * This data is stored @b independently of the one set by + * evas_object_data_set(), naturally. + * + * @see evas_object_smart_data_get() + * * @ingroup Evas_Smart_Object_Group */ EAPI void evas_object_smart_data_set (Evas_Object *obj, void *data) EINA_ARG_NONNULL(1); @@ -8378,10 +8427,14 @@ EAPI void evas_object_smart_callback_description_find(const Evas_Ob /** * Mark smart object as changed, dirty. * - * This will inform the scene that it changed and needs to be redraw, also - * setting need_recalculate on the given object. + * @param obj The given Evas smart object + * + * This will flag the given object as needing recalculation, + * forcefully. As an effect, on the next rendering cycle it's @b + * calculate() (see #Evas_Smart_Class) smart function will be called. * * @see evas_object_smart_need_recalculate_set(). + * @see evas_object_smart_calculate(). * * @ingroup Evas_Smart_Object_Group */ @@ -8423,15 +8476,20 @@ EAPI void evas_object_smart_need_recalculate_set(Evas_Object *obj, EAPI Eina_Bool evas_object_smart_need_recalculate_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Call user provided calculate() and unset need_calculate. + * Call the @b calculate() smart function immediataly on a given smart + * object. * - * @param obj the smart object + * @param obj the smart object's handle + * + * This will force immediate calculations (see #Evas_Smart_Class) + * needed for renderization of this object and, besides, unset the + * flag on it telling it needs recalculation for the next rendering + * phase. * * @ingroup Evas_Smart_Object_Group */ EAPI void evas_object_smart_calculate (Evas_Object *obj) EINA_ARG_NONNULL(1); - /** * Call user provided calculate() and unset need_calculate on all objects. * @@ -8441,17 +8499,34 @@ EAPI void evas_object_smart_calculate (Evas_Object *obj) EINA */ EAPI void evas_smart_objects_calculate (Evas *e); + +/** + * Moves all children objects relative to given offset. + * + * @param obj the smart Evas object to use. + * @param dx horizontal offset. + * @param dy vertical offset. + */ +EAPI void evas_object_smart_move_children_relative(Evas_Object *obj, Evas_Coord dx, Evas_Coord dy) EINA_ARG_NONNULL(1); + +/** + * @} + */ + /** * @defgroup Evas_Smart_Object_Clipped Clipped Smart Object * * Clipped smart object is a base to construct other smart objects - * that based on the concept of having an internal clipper that is - * applied to all its other children. This clipper will control the - * visibility, clipping and color of sibling objects (remember that - * the clipping is recursive, and clipper color modulates the color of - * its clippees). By default, this base will also move children - * relatively to the parent, and delete them when parent is - * deleted. In other words, it is the base for simple object grouping. + * based on the concept of having an internal clipper that is applied + * to all children objects. This clipper will control the visibility, + * clipping and color of sibling objects (remember that the clipping + * is recursive, and clipper color modulates the color of its + * clippees). By default, this base will also move children relatively + * to the parent, and delete them when parent is deleted. In other + * words, it is the base for simple object grouping. + * + * See some @ref Example_Evas_Smart_Objects "examples" of this group + * of functions. * * @see evas_object_smart_clipped_smart_set() * @@ -8459,6 +8534,11 @@ EAPI void evas_smart_objects_calculate (Evas *e); */ /** + * @addtogroup Evas_Smart_Object_Clipped + * @{ + */ + +/** * Every subclass should provide this at the beginning of their own * data set with evas_object_smart_data_set(). */ @@ -8473,20 +8553,28 @@ EAPI void evas_smart_objects_calculate (Evas *e); /** * Get the clipper object for the given clipped smart object. * - * @param obj the clipped smart object to retrieve the associated clipper. + * @param obj the clipped smart object to retrieve associated clipper + * from. * @return the clipper object. * + * Use this function if you want to change any of this clipper's + * properties, like colors. + * * @see evas_object_smart_clipped_smart_add() */ EAPI Evas_Object *evas_object_smart_clipped_clipper_get (Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Set smart class callbacks so it implements the "Clipped Smart Object". + * Set a given smart class' callbacks so it implements the clipped smart + * object"'s interface. * - * This call will assign all the required methods of Evas_Smart_Class, - * if one wants to "subclass" it, call this function and later - * override values, if one wants to call the original method, save it - * somewhere, example: + * @param sc The smart class handle to operate on + * + * This call will assign all the required methods of the @p sc + * #Evas_Smart_Class instance to the implementations set for clipped + * smart objects. If one wants to "subclass" it, call this function + * and then override desired values. If one wants to call any original + * method, save it somewhere. Example: * * @code * static Evas_Smart_Class parent_sc = EVAS_SMART_CLASS_INIT_NULL; @@ -8511,33 +8599,37 @@ EAPI Evas_Object *evas_object_smart_clipped_clipper_get (Evas_Objec * } * @endcode * - * Default behavior is: - * - add: creates a hidden clipper with "infinite" size; - * - del: delete all children objects; - * - move: move all objects relative relatively; - * - resize: not defined; - * - show: if there are children objects, show clipper; - * - hide: hides clipper; - * - color_set: set the color of clipper; - * - clip_set: set clipper of clipper; - * - clip_unset: unset the clipper of clipper; + * Default behavior for each of #Evas_Smart_Class functions on a + * clipped smart object are: + * - @c add: creates a hidden clipper with "infinite" size, to clip + * any incoming members; + * - @c del: delete all children objects; + * - @c move: move all objects relative relatively; + * - @c resize: not defined; + * - @c show: if there are children objects, show clipper; + * - @c hide: hides clipper; + * - @c color_set: set the color of clipper; + * - @c clip_set: set clipper of clipper; + * - @c clip_unset: unset the clipper of clipper; + * + * @note There are other means of assigning parent smart classes to + * child ones, like the #EVAS_SMART_SUBCLASS_NEW macro or the + * evas_smart_class_inherit_full() function. */ EAPI void evas_object_smart_clipped_smart_set (Evas_Smart_Class *sc) EINA_ARG_NONNULL(1); /** - * Get a pointer to the Clipped Smart Class to use for proper inheritance + * Get a pointer to the clipped smart object's class, to use + * for proper inheritance + * + * @see #Evas_Smart_Object_Clipped for more information on this smart + * class */ EAPI const Evas_Smart_Class *evas_object_smart_clipped_class_get (void) EINA_CONST; - /** - * Moves all children objects relative to given offset. - * - * @param obj the smart Evas object to use. - * @param dx horizontal offset. - * @param dy vertical offset. + * @} */ -EAPI void evas_object_smart_move_children_relative(Evas_Object *obj, Evas_Coord dx, Evas_Coord dy) EINA_ARG_NONNULL(1); /** * @defgroup Evas_Object_Box Box (Sequence) Smart Object. -- 2.7.4