From 9536b08c366e7ab10348695d854661f3c0bd77fc Mon Sep 17 00:00:00 2001 From: ChunEon Park Date: Fri, 24 Feb 2012 04:31:03 +0000 Subject: [PATCH] elementary/elm_object_item - added smart callback feature. SVN revision: 68377 --- legacy/elementary/src/lib/elm_main.c | 13 +++ legacy/elementary/src/lib/elm_object_item.h | 56 ++++++++++- legacy/elementary/src/lib/elm_widget.c | 104 ++++++++++++++++++++ legacy/elementary/src/lib/elm_widget.h | 15 ++- 4 files changed, 184 insertions(+), 4 deletions(-) diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index 372dcc83a4..1248b79cc0 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -2095,3 +2095,16 @@ elm_object_item_cursor_engine_only_get(const Elm_Object_Item *it) { return elm_widget_item_cursor_engine_only_get(it); } + +EAPI void +elm_object_item_smart_callback_add(Elm_Object_Item *it, const char *event, Elm_Object_Item_Smart_Cb func, const void *data) +{ + elm_widget_item_smart_callback_add((Elm_Widget_Item *)it, event, func, data); +} + +EAPI void * +elm_object_item_smart_callback_del(Elm_Object_Item *it, const char *event, Elm_Object_Item_Smart_Cb func) +{ + return elm_widget_item_smart_callback_del((Elm_Widget_Item *)it, event, + func); +} diff --git a/legacy/elementary/src/lib/elm_object_item.h b/legacy/elementary/src/lib/elm_object_item.h index c360048a21..0a3f8ba7f3 100644 --- a/legacy/elementary/src/lib/elm_object_item.h +++ b/legacy/elementary/src/lib/elm_object_item.h @@ -1,3 +1,5 @@ +typedef void (*Elm_Object_Item_Smart_Cb) (void *data, Elm_Object_Item *it, void *event_info); + /** * Get the widget object's handle which contains a given item * @@ -418,7 +420,7 @@ EAPI void elm_object_item_cursor_engine_only_set(Elm_Obj * searched in its theme, also, or is only relying on the rendering * engine. * - * @param item an item + * @param it an object item * @return @c EINA_TRUE, if cursors are being looked for only on * those provided by the rendering engine, @c EINA_FALSE if they * are being searched on the widget's theme, as well. @@ -427,4 +429,54 @@ EAPI void elm_object_item_cursor_engine_only_set(Elm_Obj * * @ingroup General */ -EAPI Eina_Bool elm_object_item_cursor_engine_only_get(const Elm_Object_Item *item); +EAPI Eina_Bool elm_object_item_cursor_engine_only_get(const Elm_Object_Item *it); + +/** + * Add (register) a callback function to the smart event specified by @p event + * on the elm_object_item @p it. + * + * @param it an object item + * @param event the event's name string + * @param func the callback function + * @param data user data to be passed to the callback function + * + * Smart callbacks look very similar to Evas Smart callbacks, but are + * implemented as elementary object item's custom ones. + * + * This function adds a function callback to an elementary object item when the + * event named @p event occurs in it. The function is @p func. + * + * A smart callback function must have the Elm_Object_Item_Smart_Cb prototype + * definition. The first parameter (@p data) in this definition will be a user + * specific data. The second parameter @p it is a handle to the object item on + * which event occurred. The third parameter, @p event_info, is a pointer to + * data which is totally dependent on the elementary object item's + * implementation and semantic for the given event. + * + * @see elm_object_item_smart_callback_del() + * + * @ingroup General + */ +EAPI void elm_object_item_smart_callback_add(Elm_Object_Item *it, const char *event, Elm_Object_Item_Smart_Cb func, const void *data); + +/** + * Delete (unregister) a callback function from the smart event specified by @p + * event on the elementary object item @p it. + * + * @param it an object item + * @param event the event's name string + * @param func the callback function + * @return data user data. + * + * This function removes the first added smart callback on the item @p it + * matching the event name @p event and the registered function pointer @p func. + * If the removal is successful it will also return the data pointer that was + * passed to elm_object_item_smart_callback_add() (that will be the same as the + * parameter) when the callback(s) was(were) added to the item. If not + * successful @c NULL will be returned. + * + * @see elm_object_item_smart_callback_add() + * + * @ingroup General + */ +EAPI void *elm_object_item_smart_callback_del(Elm_Object_Item *it, const char *event, Elm_Object_Item_Smart_Cb func); diff --git a/legacy/elementary/src/lib/elm_widget.c b/legacy/elementary/src/lib/elm_widget.c index 1a4f70ed69..b493d0eeec 100644 --- a/legacy/elementary/src/lib/elm_widget.c +++ b/legacy/elementary/src/lib/elm_widget.c @@ -20,6 +20,7 @@ typedef struct _Smart_Data Smart_Data; typedef struct _Edje_Signal_Data Edje_Signal_Data; typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data; typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data; +typedef struct _Elm_Widget_Item_Callback Elm_Widget_Item_Callback; struct _Smart_Data { @@ -142,6 +143,16 @@ struct _Elm_Translate_String_Data const char *string; }; +struct _Elm_Widget_Item_Callback +{ + const char *event; + Elm_Object_Item_Smart_Cb func; + void *data; + int walking : 1; + Eina_Bool delete_me : 1; +}; + + /* local subsystem functions */ static void _smart_reconfigure(Smart_Data *sd); static void _smart_add(Evas_Object *obj); @@ -2832,6 +2843,16 @@ _elm_widget_item_free(Elm_Widget_Item *item) { ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); + Elm_Object_Item_Smart_Cb cb; + + if (item->walking > 0) + { + item->delete_me = EINA_TRUE; + return; + } + + EINA_LIST_FREE(item->callbacks, cb) free(cb); + if (item->del_func) item->del_func((void *)item->data, item->widget, item); @@ -2880,6 +2901,8 @@ _elm_widget_item_del(Elm_Widget_Item *item) if (item->del_pre_func((Elm_Object_Item *) item)) _elm_widget_item_free(item); } + else + _elm_widget_item_free(item); } /** @@ -3488,6 +3511,87 @@ _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt) else item->access_info = eina_stringshare_add(txt); } +EAPI void +elm_widget_item_smart_callback_add(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func, const void *data) +{ + ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); + if ((!event) || (!func)) return; + + Elm_Widget_Item_Callback *cb = ELM_NEW(Elm_Widget_Item_Callback); + if (!cb) return; + + //TODO: apply MEMPOOL? + cb->event = eina_stringshare_add(event); + cb->func = func; + cb->data = (void *)data; + item->callbacks = eina_list_append(item->callbacks, cb); +} + +EAPI void* +elm_widget_item_smart_callback_del(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func) +{ + ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL); + + Eina_List *l, *l_next; + Elm_Widget_Item_Callback *cb; + + if ((!event) || (!func)) return NULL; + + EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb) + { + if ((!strcmp(cb->event, event)) && (cb->func == func)) + { + void *data = cb->data; + if (!cb->walking) + { + item->callbacks = eina_list_remove_list(item->callbacks, l); + free(cb); + } + else + cb->delete_me = EINA_TRUE; + return data; + } + } + return NULL; +} + +EAPI void +_elm_widget_item_smart_callback_call(Elm_Widget_Item *item, const char *event, void *event_info) +{ + ELM_WIDGET_ITEM_CHECK_OR_RETURN(item); + + Eina_List *l, *l_next; + Elm_Widget_Item_Callback *cb; + const char *strshare; + + if (!event) return; + + strshare = eina_stringshare_add(event); + + EINA_LIST_FOREACH(item->callbacks, l, cb) + { + if (strcmp(cb->event, strshare)) continue; + if (cb->delete_me) continue; + cb->walking++; + item->walking++; + cb->func(cb->data, (Elm_Object_Item *) item, event_info); + item->walking--; + cb->walking--; + if (item->delete_me) break; + } + + //Clear callbacks + EINA_LIST_FOREACH_SAFE(item->callbacks, l, l_next, cb) + { + if (!cb->delete_me) continue; + item->callbacks = eina_list_remove_list(item->callbacks, l); + free(cb); + } + + if (item->delete_me && !item->walking) + elm_widget_item_free(item); +} + static void _smart_add(Evas_Object *obj) { diff --git a/legacy/elementary/src/lib/elm_widget.h b/legacy/elementary/src/lib/elm_widget.h index 721d6530c1..2d9c6ee62b 100644 --- a/legacy/elementary/src/lib/elm_widget.h +++ b/legacy/elementary/src/lib/elm_widget.h @@ -268,6 +268,7 @@ struct _Elm_Widget_Item Evas_Smart_Cb del_func; /**< widget delete callback function. don't expose this callback call */ Elm_Widget_Del_Pre_Cb del_pre_func; + Eina_List *callbacks; Elm_Widget_Content_Set_Cb content_set_func; Elm_Widget_Content_Get_Cb content_get_func; @@ -278,9 +279,10 @@ struct _Elm_Widget_Item Elm_Widget_Disable_Cb disable_func; Elm_Access_Info *access; const char *access_info; + Eina_Bool disabled : 1; - /* widget variations should have data from here and on */ - /* @todo: TODO check if this is enough for 1.0 release, maybe add padding! */ + Eina_Bool walking : 1; + Eina_Bool delete_me : 1; }; struct _Elm_Object_Item @@ -477,6 +479,9 @@ EAPI void _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_ EAPI Eina_Bool _elm_widget_item_disabled_get(const Elm_Widget_Item *item); EAPI void _elm_widget_item_disable_hook_set(Elm_Widget_Item *item, Elm_Widget_Disable_Cb func); EAPI void _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func); +EAPI void elm_widget_item_smart_callback_add(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func, const void *data); +EAPI void *elm_widget_item_smart_callback_del(Elm_Widget_Item *item, const char *event, Elm_Object_Item_Smart_Cb func); +EAPI void _elm_widget_item_smart_callback_call(Elm_Widget_Item *item, const char *event, void *event_info); /* debug function. don't use it unless you are tracking parenting issues */ EAPI void elm_widget_tree_dump(const Evas_Object *top); @@ -670,6 +675,12 @@ EAPI void elm_widget_tree_dot_dump(const Evas_Object *top, FILE *out */ #define elm_widget_item_del_pre_hook_set(item, func) \ _elm_widget_item_del_pre_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Del_Pre_Cb)func) +/** + * Convenience function to query callback call hook + * @see _elm_widget_item_smart_callback_call() + */ +#define elm_widget_item_smart_callback_call(item, event, event_info) \ + _elm_widget_item_smart_callback_call((Elm_Widget_Item *) item, event, event_info) #define ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, ...) \ do { \