From 89fa0bee810fa5269f21e010bee2630c8e202ab5 Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Mon, 27 Jun 2011 19:42:28 +0000 Subject: [PATCH] ecore/event_handler - Improve documentation and add an example. SVN revision: 60740 --- legacy/ecore/doc/examples.dox | 110 ++++++++++++++++++ legacy/ecore/src/examples/Makefile.am | 2 + .../ecore/src/examples/ecore_event_example.c | 86 ++++++++++++++ legacy/ecore/src/lib/ecore/ecore_events.c | 11 +- 4 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 legacy/ecore/src/examples/ecore_event_example.c diff --git a/legacy/ecore/doc/examples.dox b/legacy/ecore/doc/examples.dox index f455d9c27d..a4a97b1c59 100644 --- a/legacy/ecore/doc/examples.dox +++ b/legacy/ecore/doc/examples.dox @@ -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 * */ @@ -113,6 +115,108 @@ * @include ecore_job_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 @@ -132,6 +236,12 @@ * ecore_time_example_c "the example explained". */ +/** + * @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. diff --git a/legacy/ecore/src/examples/Makefile.am b/legacy/ecore/src/examples/Makefile.am index f909e353cb..1ad6c25520 100644 --- a/legacy/ecore/src/examples/Makefile.am +++ b/legacy/ecore/src/examples/Makefile.am @@ -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/legacy/ecore/src/examples/ecore_event_example.c b/legacy/ecore/src/examples/ecore_event_example.c new file mode 100644 index 0000000000..ef3f1871bd --- /dev/null +++ b/legacy/ecore/src/examples/ecore_event_example.c @@ -0,0 +1,86 @@ +#include +#include + +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; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_events.c b/legacy/ecore/src/lib/ecore/ecore_events.c index 2231b6e017..f2625a6cce 100644 --- a/legacy/ecore/src/lib/ecore/ecore_events.c +++ b/legacy/ecore/src/lib/ecore/ecore_events.c @@ -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)