From 0fa8bd1b3d6180bfcecb9269041a0dd6efd9ca60 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Fri, 26 Mar 2010 00:58:14 +0000 Subject: [PATCH] Proxy Elementary widget signals to Edje. Add support to automatic proxy events from Elementary to Edje using callbacks described with Evas_Smart_Cb_Description and set to Evas_Smart_Class or per-instance with evas_object_smart_callbacks_descriptions_set(). Right now elm_widget is not subclassable, so there is no way to define class signals, just instance signals. Just doing it for button, lots of widgets to do... If you can help, please follow the process: * see example at src/lib/elm_button.c, copy it. * read your widget documentation at Elementary.h * grep for evas_object_smart_callback_call(), see if they are all documented in Elementary.h, or if there are some missing. Fix Elementary.h * paste and change based on fixed Elementary.h My recommendation is to create "static const char []" variables and replace all evas_object_smart_callback_call() with that, to force sync. With callback descriptions pre-defined and using the same pointer with a custom variation evas_object_smart_callback_call_ptr() we may later optimize signal calling heavily, removing the requirement to call eina_stringshare_add()/eina_stringshare_del() and also not mixing all the callbacks in teh same list, instead having an array for defined signals, and a list from there. These optimizations are not in, but they are easily added later without breaking the API/ABI. SVN revision: 47461 --- src/edje_externals/elm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ src/edje_externals/private.h | 16 +++++++----- src/lib/Elementary.h.in | 1 + src/lib/elm_button.c | 20 ++++++++++++--- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/edje_externals/elm.c b/src/edje_externals/elm.c index 2aa8c81..520a4dd 100644 --- a/src/edje_externals/elm.c +++ b/src/edje_externals/elm.c @@ -15,6 +15,66 @@ external_translate(void *data __UNUSED__, const char *orig) return orig; } +typedef struct { + const char *emission; + const char *source; + Evas_Object *edje; +} Elm_External_Signals_Proxy_Context; + +static void +_external_signal_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Elm_External_Signals_Proxy_Context *ctxt = data; + free(ctxt); +} + +static void +_external_signal_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Elm_External_Signals_Proxy_Context *ctxt = data; + // TODO: Is it worth to check Evas_Smart_Cb_Description and do something + // TODO: with event_info given its description? + edje_object_signal_emit(ctxt->edje, ctxt->emission, ctxt->source); +} + +void +external_signals_proxy(Evas_Object *obj, Evas_Object *edje, const char *part_name) +{ + const Evas_Smart_Cb_Description **cls_descs, **inst_descs; + unsigned int cls_count, inst_count, total; + Elm_External_Signals_Proxy_Context *ctxt; + + evas_object_smart_callbacks_descriptions_get + (obj, &cls_descs, &cls_count, &inst_descs, &inst_count); + + total = cls_count + inst_count; + if (!total) return; + ctxt = malloc(sizeof(Elm_External_Signals_Proxy_Context) * total); + if (!ctxt) return; + evas_object_event_callback_add + (obj, EVAS_CALLBACK_DEL, _external_signal_proxy_free_cb, ctxt); + + for (; cls_count > 0; cls_count--, cls_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *cls_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_signal_proxy_cb, ctxt); + } + + for (; inst_count > 0; inst_count--, inst_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *inst_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_signal_proxy_cb, ctxt); + } +} + void * external_common_params_parse_internal(size_t params_size, void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params) { diff --git a/src/edje_externals/private.h b/src/edje_externals/private.h index b03538a..4bdc26d 100644 --- a/src/edje_externals/private.h +++ b/src/edje_externals/private.h @@ -8,12 +8,13 @@ typedef struct { const char *label; } Elm_Params; -void external_signal(void *data, Evas_Object *obj, const char *signal, const char *source); +void external_signal(void *data, Evas_Object *obj, const char *signal, const char *source); +void external_signals_proxy(Evas_Object *obj, Evas_Object *edje, const char *part_name); const char *external_translate(void *data, const char *orig); -void external_common_params_free(void *params); +void external_common_params_free(void *params); void *external_common_params_parse_internal(size_t params_size, void *data, Evas_Object *obj, const Eina_List *params); Evas_Object *external_common_param_icon_get(Evas_Object *obj, const Edje_External_Param *param); -void external_common_icon_param_parse(Evas_Object **icon, Evas_Object *obj, const Eina_List *params); +void external_common_icon_param_parse(Evas_Object **icon, Evas_Object *obj, const Eina_List *params); #define external_common_params_parse(type, data, obj, params) \ external_common_params_parse_internal(sizeof(type), data, obj, params) @@ -47,11 +48,14 @@ const Edje_External_Type external_##type_name##_type = {\ #define DEFINE_EXTERNAL_TYPE_SIMPLE(type_name, name) \ static Evas_Object * \ -external_##type_name##_add(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *edje, const Eina_List *params __UNUSED__, const char *part_name __UNUSED__) \ +external_##type_name##_add(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *edje, const Eina_List *params __UNUSED__, const char *part_name) \ { \ - Evas_Object *parent = elm_widget_parent_widget_get(edje); \ + Evas_Object *parent, *obj; \ + parent = elm_widget_parent_widget_get(edje); \ if (!parent) parent = edje; \ - return elm_##type_name##_add(parent); \ + obj = elm_##type_name##_add(parent); \ + external_signals_proxy(obj, edje, part_name); \ + return obj; \ } \ \ DEFINE_EXTERNAL_TYPE(type_name, name) diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 2a670d1..c78b57b 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -411,6 +411,7 @@ extern "C" { /* smart callbacks called: * "clicked" - the user clicked the button * "repeated" - the user pressed the button without releasing it + * "unpressed" - when the button is unpressed (released) */ typedef enum _Elm_Scroller_Policy diff --git a/src/lib/elm_button.c b/src/lib/elm_button.c index 5ee3b04..8da3ffd 100644 --- a/src/lib/elm_button.c +++ b/src/lib/elm_button.c @@ -38,6 +38,16 @@ static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source); static void _on_focus_hook(void *data, Evas_Object *obj); +static const char SIG_CLICKED[] = "clicked"; +static const char SIG_REPEATED[] = "repeated"; +static const char SIG_UNPRESSED[] = "unpressed"; +static const Evas_Smart_Cb_Description _signals[] = { + {SIG_CLICKED, ""}, + {SIG_REPEATED, ""}, + {SIG_UNPRESSED, ""}, + {NULL, NULL} +}; + static void _del_hook(Evas_Object *obj) { @@ -136,7 +146,7 @@ _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char * { Widget_Data *wd = elm_widget_data_get(data); if (!wd) return; - evas_object_smart_callback_call(data, "clicked", NULL); + evas_object_smart_callback_call(data, SIG_CLICKED, NULL); _signal_unpressed(data, obj, emission, source); /* safe guard when the theme does not emit the 'unpress' signal */ } @@ -146,7 +156,7 @@ _autorepeat_send(void *data) Widget_Data *wd = elm_widget_data_get(data); if (!wd) return ECORE_CALLBACK_CANCEL; - evas_object_smart_callback_call(data, "repeated", NULL); + evas_object_smart_callback_call(data, SIG_REPEATED, NULL); return ECORE_CALLBACK_RENEW; } @@ -184,7 +194,7 @@ _signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission { Widget_Data *wd = elm_widget_data_get(data); if (!wd) return; - evas_object_smart_callback_call(data, "unpressed", NULL); + evas_object_smart_callback_call(data, SIG_UNPRESSED, NULL); if (wd->timer) { @@ -234,6 +244,10 @@ elm_button_add(Evas_Object *parent) evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); _sizing_eval(obj); + + // TODO: convert Elementary to subclassing of Evas_Smart_Class + // TODO: and save some bytes, making descriptions per-class and not instance! + evas_object_smart_callbacks_descriptions_set(obj, _signals); return obj; } -- 2.7.4