elementary/elm_object_item - added smart callback feature.
authorChunEon Park <hermet@hermet.pe.kr>
Fri, 24 Feb 2012 04:31:03 +0000 (04:31 +0000)
committerChunEon Park <hermet@hermet.pe.kr>
Fri, 24 Feb 2012 04:31:03 +0000 (04:31 +0000)
SVN revision: 68377

src/lib/elm_main.c
src/lib/elm_object_item.h
src/lib/elm_widget.c
src/lib/elm_widget.h

index 372dcc8..1248b79 100644 (file)
@@ -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);
+}
index c360048..0a3f8ba 100644 (file)
@@ -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 <b>the first</b> 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);
index 1a4f70e..b493d0e 100644 (file)
@@ -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)
 {
index 721d653..2d9c6ee 100644 (file)
@@ -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 {                                                       \