[evas] Documenting and exemplifying the following:
authorglima <glima@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 5 Jul 2011 21:10:19 +0000 (21:10 +0000)
committerglima <glima@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 5 Jul 2011 21:10:19 +0000 (21:10 +0000)
 - 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
src/examples/Makefile.am
src/examples/evas-smart-object.c [new file with mode: 0644]
src/lib/Evas.h

index 96d65b7..4e7e1f2 100644 (file)
@@ -20,6 +20,8 @@
  * @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
+ */
index ff3eca1..7a2b10a 100644 (file)
@@ -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 (file)
index 0000000..85ab3b3
--- /dev/null
@@ -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 <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;
+}
index fdb056b..52b85b3 100644 (file)
@@ -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.
- *  - @<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
  */
@@ -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 <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;
@@ -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: <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.