[evas] Example of Evas interfaces.
authorglima <glima@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 Jul 2012 21:25:57 +0000 (21:25 +0000)
committerglima <glima@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 Jul 2012 21:25:57 +0000 (21:25 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@73304 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

doc/examples.dox
src/examples/Makefile.am
src/examples/evas-smart-interface.c [new file with mode: 0644]
src/lib/Evas.h

index 2276c48..65dd513 100644 (file)
  */
 
 /**
+ * @page Example_Evas_Smart_Interfaces Evas object smart interfaces
+ * @dontinclude evas-smart-interface.c
+ *
+ * In this example, we illustrate how to create and handle Evas smart
+ * @b interfaces. Note that we use the same code base of the @ref
+ * Example_Evas_Smart_Objects example, here. We just augment it with
+ * an interfaces demonstration.
+ *
+ * A smart interface is just a functions interface a given smart
+ * objcet is declaring to support and or use. In Evas, interfaces are
+ * very simple: no interface inheritance, no interface
+ * overriding. Their purpose is to extend an object's capabilities and
+ * behaviour beyound the sub-classing schema.
+ *
+ * Here, together with a custom smart object, we create and declare
+ * the object as using an Evas interface. It'll have a custom
+ * function, too, besides the @c add() and del() obligatory ones. To
+ * demonstrate interface data, which is bound to object @b instances,
+ * we'll have a string as this data.
+ *
+ * Here is where we declare our interface:
+ * @skip static const char iface1_data[]
+ * @until (Evas_Smart_Interface *)&iface1, NULL
+ * @until };
+ *
+ * Note that there's error checking for interfaces creation, by means of
+ * the @c add() method's return value (@c _iface1_add(), here).
+ *
+ * Now note that here we are filling in the interface's fields dinamically.
+ * Let's move on to that code region:
+ *
+ * @dontinclude evas-smart-interface.c
+ * @skip iface = (Evas_Smart_Example_Interface *)&iface1;
+ * @until d.smt = evas_smart_example_add(d.evas);
+ *
+ * As important as setting the function pointers, is declaring the @c
+ * private_size as to match exactly the size of the data blob we want
+ * to have allocated for us by Evas. This will happen automatically
+ * inside @c evas_smart_example_add().  Later, on this code, we deal
+ * exactly with that data blob, more specifically writing on it (as
+ * it's not done inside @c _iface1_add(), here:
+ *
+ * @dontinclude evas-smart-interface.c
+ * @skip iface = (Evas_Smart_Example_Interface *)evas_object_smart_interface_get
+ * @until }
+ *
+ * Before accessing the interface data, we exercise the interface
+ * fetching call evas_object_smart_interface_get(), with the name
+ * string we used to be interface's name. With that handle in hands,
+ * we issue evas_object_smart_interface_data_get() and write the
+ * string we want as data on that memory region. That will make up for
+ * the string you get on @c _iface1_del().
+ *
+ * The full example follows.
+ *
+ * @include evas-smart-interface.c
+ * @example evas-smart-interface.c
+ */
+
+/**
  * @page Example_Evas_Text Evas text object example
  *
  * In this example, we illustrate how to use text objects in various
index 757ca54..e03ff9e 100644 (file)
@@ -79,6 +79,10 @@ examples_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@
 
+examples_PROGRAMS += evas_smart_interface
+evas_smart_interface_SOURCES = evas-smart-interface.c
+evas_smart_interface_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@
+
 examples_PROGRAMS += evas_box
 evas_box_SOURCES = evas-box.c
 evas_box_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@ @EINA_LIBS@
@@ -129,6 +133,7 @@ files_DATA += \
        $(srcdir)/evas-map-utils.c \
        $(srcdir)/evas-text.c \
        $(srcdir)/evas-smart-object.c \
+       $(srcdir)/evas-smart-interface.c \
        $(srcdir)/evas-box.c
 endif
 
@@ -146,6 +151,7 @@ EXTRA_DIST = $(EDCS) \
        $(srcdir)/evas-map-utils.c \
        $(srcdir)/evas-text.c \
        $(srcdir)/evas-smart-object.c \
+       $(srcdir)/evas-smart-interface.c \
        $(srcdir)/evas-box.c \
        $(srcdir)/evas-table.c \
        $(srcdir)/enlightenment.png \
diff --git a/src/examples/evas-smart-interface.c b/src/examples/evas-smart-interface.c
new file mode 100644 (file)
index 0000000..97b9a9e
--- /dev/null
@@ -0,0 +1,790 @@
+/**
+ * Simple Evas example illustrating Evas smart interfaces
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * gcc -o evas-smart-interface evas-smart-interface.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"
+  "\tw - remove and delete all members from the smart object\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"
+  "\tq - quit\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, *rects[2];
+};
+
+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"
+
+static const char iface1_data[] = "iface1_data";
+static const char IFACE1_NAME[] = "iface1";
+
+static Eina_Bool _iface1_add(Evas_Object *);
+static void      _iface1_del(Evas_Object *);
+static void      _iface1_custom_fn(Evas_Object *);
+
+typedef struct _Evas_Smart_Example_Interface Evas_Smart_Example_Interface;
+struct _Evas_Smart_Example_Interface
+{
+   Evas_Smart_Interface base;
+   void                 (*example_func)(Evas_Object *obj);
+};
+
+static Evas_Smart_Example_Interface iface1;
+
+static Eina_Bool
+_iface1_add(Evas_Object *obj)
+{
+   printf("iface1's add()!\n");
+
+   return EINA_TRUE;
+}
+
+static void
+_iface1_del(Evas_Object *obj)
+{
+   printf("iface1's del()! Data is %s\n",
+          (char *)evas_object_smart_interface_data_get
+            (obj, (Evas_Smart_Interface *)&iface1));
+}
+
+static void
+_iface1_custom_fn(Evas_Object *obj)
+{
+   printf("iface1's custom_fn()!\n");
+}
+
+static const Evas_Smart_Interface *_smart_interfaces[] =
+{
+   (Evas_Smart_Interface *)&iface1, NULL
+};
+
+#define EVT_CHILDREN_NUMBER_CHANGED "children,changed"
+
+static const Evas_Smart_Cb_Description _smart_callbacks[] =
+{
+   {EVT_CHILDREN_NUMBER_CHANGED, "i"},
+   {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;
+   int                            child_count;
+};
+
+#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_IFACE_NEW
+  (_evas_smart_example_type, _evas_smart_example, Evas_Smart_Class,
+  Evas_Smart_Class, evas_object_smart_clipped_class_get, _smart_callbacks,
+  _smart_interfaces);
+
+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;
+   long idx;
+
+   EVAS_SMART_EXAMPLE_DATA_GET(example_smart, priv);
+
+   idx = (long)evas_object_data_get(o, "index");
+   idx--;
+
+   priv->children[idx] = 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,
+                                             long idx)
+{
+   evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _on_child_del, o);
+   evas_object_data_set(child, "index", (void *)(++idx));
+}
+
+/* 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());
+}
+
+static void
+_evas_smart_example_remove_do(Evas_Smart_Example_Data *priv,
+                              Evas_Object *child,
+                              int idx)
+{
+   priv->children[idx] = NULL;
+   priv->child_count--;
+   _evas_smart_example_child_callbacks_unregister(child);
+   evas_object_smart_member_del(child);
+}
+
+/* remove a child element, return its pointer (or NULL on errors) */
+Evas_Object *
+evas_smart_example_remove(Evas_Object *o,
+                          Evas_Object *child)
+{
+   long idx;
+
+   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;
+     }
+
+   idx = (long)evas_object_data_get(child, "index");
+   idx--;
+
+   _evas_smart_example_remove_do(priv, child, idx);
+
+   evas_object_smart_callback_call(
+     o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+   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 = priv->children[0];
+             _evas_smart_example_remove_do(priv, priv->children[0], 0);
+          }
+        else return child;
+     }
+
+   priv->children[0] = child;
+   _evas_smart_example_child_callbacks_register(o, child, 0);
+   evas_object_smart_member_add(child, o);
+   evas_object_smart_changed(o);
+
+   priv->child_count++;
+   if (!ret)
+     {
+        evas_object_smart_callback_call(
+          o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+     }
+
+   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 = priv->children[1];
+             _evas_smart_example_remove_do(priv, priv->children[1], 1);
+          }
+        else return child;
+     }
+
+   priv->children[1] = child;
+   _evas_smart_example_child_callbacks_register(o, child, 1);
+   evas_object_smart_member_add(child, o);
+   evas_object_smart_changed(o);
+
+   priv->child_count++;
+   if (!ret)
+     {
+        evas_object_smart_callback_call(
+          o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+     }
+
+   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, "q") == 0) /* print help */
+     {
+        _on_destroy(NULL);
+        return;
+     }
+
+   if (strcmp(ev->keyname, "h") == 0) /* print help */
+     {
+        fprintf(stdout, commands);
+        return;
+     }
+
+   if (strcmp(ev->keyname, "w") == 0) /* clear out smart object (WRT
+                                       * members) */
+     {
+        if (d.rects[0])
+          {
+             evas_smart_example_remove(d.smt, d.rects[0]);
+             evas_object_del(d.rects[0]);
+          }
+        if (d.rects[1])
+          {
+             evas_smart_example_remove(d.smt, d.rects[1]);
+             evas_object_del(d.rects[1]);
+          }
+
+        memset(d.rects, 0, sizeof(d.rects));
+
+        fprintf(stdout, "Deleting all members of the smart object.\n");
+
+        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);
+        d.rects[0] = rect;
+
+        fprintf(stdout, "Setting smart object's left spot with a new"
+                        " rectangle.\n");
+        fprintf(stdout, "Checking its new smart object parent: %s\n",
+                evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+                "Failure!");
+        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);
+        d.rects[1] = rect;
+
+        fprintf(stdout, "Setting smart object's right spot with a new"
+                        " rectangle.\n");
+        fprintf(stdout, "Checking its new smart object parent: %s\n",
+                evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+                "Failure!");
+        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;
+     }
+}
+
+static void
+/* callback on number of member objects changed */
+_on_example_smart_object_child_num_change(void *data __UNUSED__,
+                                          Evas_Object *obj __UNUSED__,
+                                          void *event_info)
+{
+   fprintf(stdout, "Number of child members on our example smart"
+                   " object changed to %lu\n", (long)event_info);
+}
+
+int
+main(void)
+{
+   const Evas_Smart_Cb_Description **descriptions;
+   Evas_Smart_Example_Interface *iface;
+   unsigned int count;
+   Eina_Bool ret;
+
+   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);
+
+   iface = (Evas_Smart_Example_Interface *)&iface1;
+   iface->base.name = IFACE1_NAME;
+   iface->base.private_size = sizeof(iface1_data);
+   iface->base.add = _iface1_add;
+   iface->base.del = _iface1_del;
+   iface->example_func = _iface1_custom_fn;
+
+   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);
+
+   ret = evas_object_smart_type_check(d.smt, _evas_smart_example_type);
+   fprintf(stdout, "Adding smart object of type \"%s\" to the canvas: %s.\n",
+           _evas_smart_example_type, ret ? "success" : "failure");
+
+   d.clipper = evas_object_smart_clipped_clipper_get(d.smt);
+   fprintf(stdout, "Checking if clipped smart object's clipper is a "
+                   "\"static\" one: %s\n", evas_object_static_clip_get(
+             d.clipper) ? "yes" : "no");
+
+   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_smart_callbacks_descriptions_get(
+     d.smt, &descriptions, &count, NULL, NULL);
+
+   for (; *descriptions; descriptions++)
+     {
+        fprintf(stdout, "We've found a smart callback on the smart object!"
+                        "\n\tname: %s\n\ttype: %s\n", (*descriptions)->name,
+                (*descriptions)->type);
+
+        if (strcmp((*descriptions)->type, "i")) continue;
+        /* we know we don't have other types of smart callbacks
+         * here, just playing with it */
+
+        /* for now, we know the only one callback is the one
+         * reporting number of member objects changed on the
+         * example smart object */
+        evas_object_smart_callback_add(
+          d.smt, (*descriptions)->name,
+          _on_example_smart_object_child_num_change, NULL);
+     }
+
+   evas_object_focus_set(d.bg, EINA_TRUE);
+   evas_object_event_callback_add(
+     d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+   iface = (Evas_Smart_Example_Interface *)evas_object_smart_interface_get
+       (d.smt, IFACE1_NAME);
+   if (iface)
+     {
+        char *data;
+
+        fprintf(stdout, "We've found a smart interface on the smart object!"
+                        "\n\tname: %s\n", iface->base.name);
+
+        fprintf(stdout, "Setting its interface data...\n");
+        data = evas_object_smart_interface_data_get
+            (d.smt, (Evas_Smart_Interface *)iface);
+        memcpy(data, iface1_data, sizeof(iface1_data));
+
+        fprintf(stdout, "Calling an interface's function...\n");
+        iface->example_func(d.smt);
+     }
+
+   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 9f15764..6c22f40 100644 (file)
@@ -9664,6 +9664,9 @@ struct _Evas_Smart_Class
  * function pointers must be defined, too, which will be called at
  * object creation and deletion times.
  *
+ * See also some @ref Example_Evas_Smart_Interfaces "examples" on
+ * smart interfaces.
+ *
  * @since 1.3
  *
  * @ingroup Evas_Smart_Group