ecore/event_handler - Improve documentation and add an example.
authorantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 27 Jun 2011 19:42:28 +0000 (19:42 +0000)
committerantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 27 Jun 2011 19:42:28 +0000 (19:42 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@60740 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

doc/examples.dox
src/examples/Makefile.am
src/examples/ecore_event_example.c [new file with mode: 0644]
src/lib/ecore/ecore_events.c

index f455d9c..a4a97b1 100644 (file)
@@ -5,6 +5,8 @@
  *
  * @li @ref ecore_time_example_c
  * @li @ref ecore_idler_example_c
+ * @li @ref ecore_job_example_c
+ * @li @ref ecore_event_example_c
  *
  */
 
  */
 
 /**
+ * @page ecore_event_example_c ecore events and handlers - Setup and use
+ * This example shows how to create a new type of event, setup some event
+ * handlers to it, fire the event and have the callbacks called. After
+ * finishing, we delete the event handlers so no memory will leak.
+ *
+ * See the full source code for this example @ref ecore_event_example.c "here".
+ *
+ * Let's start the example from the beginning:
+ *
+ * @dontinclude ecore_event_example.c
+ * @until _event_type
+ *
+ * First thing is to declare a struct that will be passed as context to the
+ * event handlers. In this structure we will store the event handler pointers,
+ * and two strings that will be used by the first event handler. We also will
+ * use a global integer to store the event type used for our event. It is
+ * initialized with 0 in the beginning because the event wasn't created yet.
+ * Later, in the main function we will use ecore_event_type_new() to associate
+ * another value to it. Now the event handler callbacks:
+ *
+ * @until }
+ *
+ * This is the first event handler callback. It prints the event data received
+ * by the event, and the data passed to this handler when it was added.  Notice
+ * that this callback already knows that the event data is an integer pointer,
+ * and that the handler data is a string. It knows about the first one because
+ * this is based on the type of event that is going to be handled, and the
+ * second because it was passed to the ecore_event_handler_add() function when
+ * registering the event handler.
+ *
+ * Another interesting point about this callback is that it returns @ref
+ * ECORE_CALLBACK_DONE (0) if the event data is even, swallowing the event and
+ * don't allowing any other callback to be called after this one for this event.
+ * Otherwise it returns @ref ECORE_CALLBACK_PASS_ON, allowing the event to be
+ * handled by other event handlers registered for this event. This makes the
+ * second event handler be called just for "odd" events.
+ *
+ * @until ECORE_CALLBACK_DONE
+ * @until }
+ *
+ * The second event handler will check if the event data is equal to 5, and if
+ * that's the case, it will change the event handler data of the first event
+ * handler to another string. Then it checks if the event data is higher than
+ * 10, and if so, it will request the main loop to quit.
+ *
+ * An interesting point of this example is that although the second event
+ * handler requests the main loop to finish after the 11th event being received,
+ * it will process all the events that were already fired, and call their
+ * respective event handlers, before the main loop stops. If we didn't want
+ * these event handlers to be called after the 11th event, we would need to
+ * unregister them with ecore_event_handler_del() at this point.
+ *
+ * Now some basic initialization of the context, and the Ecore library itself:
+ *
+ * @until type_new
+ *
+ * This last line is interesting. It creates a new type of event and returns a
+ * unique ID for this event inside Ecore. This ID can be used anywhere else in
+ * your program to reference this specific type of event, and to add callbacks
+ * to it.
+ *
+ * It's common if you are implementing a library that declares new types of
+ * events to export their respective types as extern in the header files. This
+ * way, when the library is initialized and the new type is created, it will be
+ * available through the header file to an application using it add some
+ * callbacks to it. Since our example is self-contained, we are just putting it
+ * as a global variable.
+ *
+ * Now we add some callbacks:
+ *
+ * @until ctxt);
+ *
+ * This is very simple. Just need to call ecore_event_handler_add() with the
+ * respective event type, the callback function to be called, and a data pointer
+ * that will be passed to the callback when it is called by the event.
+ *
+ * Then we start firing events:
+ *
+ * @until }
+ *
+ * This @c for will fire 16 events of this type. Notice that the events will be
+ * fired consecutively, but any callback will be called yet. They are just
+ * called by the main loop, and since it wasn't even started, nothing happens
+ * yet. For each event fired, we allocate an integer that will hold the number
+ * of the event (we are arbitrarily creating these numbers just for
+ * demonstration purposes). It's up to the event creator to decide which type of
+ * information it wants to give to the event handler, and the event handler must
+ * know what is the event info structure for that type of event.
+ *
+ * Since we are not allocating any complex structure, just a simple integer, we
+ * don't need to pass any special free function to ecore_event_add(), and it
+ * will use a simple @c free on our data. That's the default behavior.
+ *
+ * Now finishing our example:
+ *
+ * @until }
+ *
+ * We just start the main loop and watch things happen, waiting to shutdown
+ * Ecore when the main loop exits and return.
+ */
+
+/**
  * @example ecore_idler_example.c
  * This example shows when @ref Ecore_Idler, @ref Ecore_Idle_Enterer and @ref
  * Ecore_Idle_Exiter are called. See
  */
 
 /**
+ * @example ecore_event_example.c
+ * This example shows how to setup, change, and delete event handlers. See
+ * @ref ecore_event_example_c "the explanation here".
+ */
+
+/**
  * @example ecore_fd_handler_example.c
  * Shows how to use fd handlers.
 */
index f909e35..1ad6c25 100644 (file)
@@ -12,6 +12,7 @@ LDADD = \
        @dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ @rt_libs@ -lm
 
 SRCS = \
+       ecore_event_example.c \
        ecore_idler_example.c \
        ecore_time_example.c \
        ecore_job_example.c \
@@ -33,6 +34,7 @@ endif
 
 if EFL_BUILD_EXAMPLES
 pkglib_PROGRAMS += \
+       ecore_event_example \
        ecore_idler_example \
        ecore_job_example \
        ecore_time_example
diff --git a/src/examples/ecore_event_example.c b/src/examples/ecore_event_example.c
new file mode 100644 (file)
index 0000000..ef3f187
--- /dev/null
@@ -0,0 +1,86 @@
+#include <Ecore.h>
+#include <unistd.h>
+
+struct context { // helper struct to give some context to the callbacks
+     const char *str1, *str2;
+     Ecore_Event_Handler *handler1;
+     Ecore_Event_Handler *handler2;
+};
+
+static _event_type = 0; // a new type of event will be defined and stored here
+
+static Eina_Bool
+_event_handler1_cb(void *data, int type, void *event)
+{
+   int *number = event;
+   const char *str = data;
+
+   printf("event_handler1: number=%d, data=\"%s\".\n", *number, str);
+
+   if ((*number % 2) == 0)
+     return ECORE_CALLBACK_DONE;
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_event_handler2_cb(void *data, int type, void *event) // event callback
+{
+   struct context *ctxt = data;
+   int *number = event;
+
+   printf("event_handler2: number=%d.\n", *number);
+
+   if (*number == 5)
+     {
+       const char *old = NULL;
+       old = ecore_event_handler_data_set(ctxt->handler1, (void *)ctxt->str2);
+       printf("changed handler1 data from \"%s\" to \"%s\".\n",
+              old, ctxt->str2);
+     }
+   else if (*number >= 10)
+     {
+       printf("finish main loop.\n");
+       ecore_main_loop_quit();
+     }
+
+   return ECORE_CALLBACK_DONE; // same as EINA_FALSE
+}
+
+int main(int argc, char **argv)
+{
+   struct context ctxt = {0};
+   int i;
+   ctxt.str1 = "dataone";
+   ctxt.str2 = "datatwo";
+
+   if (!ecore_init())
+     {
+       printf("ERROR: Cannot init Ecore!\n");
+       return -1;
+     }
+
+   _event_type = ecore_event_type_new();
+
+   ctxt.handler1 = ecore_event_handler_add(_event_type,
+                                          _event_handler1_cb,
+                                          ctxt.str1);
+   ctxt.handler2 = ecore_event_handler_add(_event_type,
+                                          _event_handler2_cb,
+                                          &ctxt);
+
+   for (i = 0; i <= 15; i++)
+     {
+       int *event_data = malloc(sizeof(*event_data));
+       *event_data = i;
+       ecore_event_add(_event_type, event_data, NULL, NULL);
+     }
+
+   printf("start the main loop.\n");
+
+   ecore_main_loop_begin();
+
+   ecore_shutdown();
+
+   return 0;
+}
index 2231b6e..f2625a6 100644 (file)
@@ -101,9 +101,9 @@ static void *_ecore_event_del(Ecore_Event *event);
  * provided in this call as the @p data parameter.
  *
  * When the callback @p func is called, it must return 1 or 0. If it returns
- * 1 (or ECORE_CALLBACK_RENEW), It will keep being called as per normal, for
+ * 1 (or ECORE_CALLBACK_PASS_ON), It will keep being called as per normal, for
  * each handler set up for that event type. If it returns 0 (or
- * ECORE_CALLBACK_CANCEL), it will cease processing handlers for that particular
+ * ECORE_CALLBACK_DONE), it will cease processing handlers for that particular
  * event, so all handler set to handle that event type that have not already
  * been called, will not be.
  */
@@ -179,7 +179,9 @@ ecore_event_handler_del(Ecore_Event_Handler *event_handler)
  * @brief Get the data associated with an #Ecore_Event_Handler
  * @param eh The event handler
  * @return The data
- * This function returns the data previously associated with @p eh.
+ *
+ * This function returns the data previously associated with @p eh by
+ * ecore_event_handler_add().
  */
 EAPI void *
 ecore_event_handler_data_get(Ecore_Event_Handler *eh)
@@ -197,8 +199,9 @@ ecore_event_handler_data_get(Ecore_Event_Handler *eh)
  * @param eh The event handler
  * @param data The data to associate
  * @return The previous data
+ *
  * This function sets @p data to @p eh and returns the old data pointer
- * which was previously associated with @p eh.
+ * which was previously associated with @p eh by ecore_event_handler_add().
  */
 EAPI void *
 ecore_event_handler_data_set(Ecore_Event_Handler *eh, void *data)