* @ref Example_Evas_Size_Hints
*
* @ref Example_Evas_Stacking
+ *
+ * @ref Example_Evas_Smart_Objects
*/
/**
*
* @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 <b>smart classes</b>, which are structs
+ * defining their interfaces, or <b>smart functions</b> (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 <b>helper macro</b>:
+ * @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:
+ * <code>evas_object_smart_member_add(priv->border, o);</code>.
+ *
+ * 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
+ */
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@
$(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) \
$(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 \
--- /dev/null
+/**
+ * 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 <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#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;
+}
/**
* @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;
/**
* @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;
};
/**
* @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.
- * - @<prefix@>_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.
- * - @<prefix@>_parent_sc: pointer to the smart class of the parent. When calling
- * parent functions from overloaded ones, use this global variable.
- * - @<prefix@>_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 @<prefix@>_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:
+ * - @<prefix@>_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 <b>take care of setting the right member functions for
+ * the class</b>, 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 @<prefix@>_smart_set() to
+ * get the job done.
+ *
+ * After the macro's usage, the following will be defined for use:
+ * - @<prefix@>_parent_sc: A pointer to the @b parent smart
+ * class. When calling parent functions from overloaded ones, use
+ * this global variable.
+ * - @<prefix@>_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
*/
/**
* @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) \
/**
* @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;
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);
/**
* 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
*/
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.
*
*/
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()
*
*/
/**
+ * @addtogroup Evas_Smart_Object_Clipped
+ * @{
+ */
+
+/**
* Every subclass should provide this at the beginning of their own
* data set with evas_object_smart_data_set().
*/
/**
* 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 <b>clipped smart
+ * object"</b>'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;
* }
* @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: <b>not defined</b>;
+ * - @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 <b>clipped smart object's</b> 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.