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
This commit is contained in:
Gustavo Sverzut Barbieri 2010-03-26 00:58:14 +00:00
parent ed5cb0e7f3
commit 439a3bd492
4 changed files with 88 additions and 9 deletions

View File

@ -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)
{

View File

@ -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)

View File

@ -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

View File

@ -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;
}