From cfecbc912b9103bf99a2896061ff74065c6a720c Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Thu, 25 Mar 2010 18:05:42 +0000 Subject: [PATCH] Edje EXTERNAL API break, for good. I'm now introducing a couple of goodies to make externals more useful, they are: * add: extra parameter with the part name. This may be used by external objects to emit signals in the name of that part. * param_set/param_get: set parameters at runtime, given their names and types. This avoids requiring users to get the actual object and call methods. This abstraction is also good because it let one uses Elementary without even linking to it ;-) (this have limits, like complex types are not supported). Right now this is just exposed to C, but goal is to have it exposed in Embryo and Lua as well. * translate: new method to translate previously strings that are specified statically, such as the parameters names. Four new functions got added to the Edje API: * edje_object_part_external_object_get() so we don't have to abuse edje_object_part_swallow_get() * edje_object_part_external_param_set() and edje_object_part_external_param_get() that call the external type's functions. * edje_external_param_type_str() to convert types to string and provide nicer debugs :-) TODO: * expose external_param_set()/external_param_get() to Embryo and Lua. SVN revision: 47456 --- legacy/edje/src/lib/Edje.h | 22 ++- legacy/edje/src/lib/edje_edit.c | 12 +- legacy/edje/src/lib/edje_external.c | 206 +++++++++++++++++++++++++++- legacy/edje/src/lib/edje_load.c | 4 +- legacy/edje/src/lib/edje_private.h | 4 +- 5 files changed, 230 insertions(+), 18 deletions(-) diff --git a/legacy/edje/src/lib/Edje.h b/legacy/edje/src/lib/Edje.h index 497e256645..c7c5207934 100644 --- a/legacy/edje/src/lib/Edje.h +++ b/legacy/edje/src/lib/Edje.h @@ -250,6 +250,8 @@ enum _Edje_External_Param_Type }; typedef enum _Edje_External_Param_Type Edje_External_Param_Type; +EAPI const char *edje_external_param_type_str(Edje_External_Param_Type type) EINA_PURE; + struct _Edje_External_Param { const char *name; @@ -325,7 +327,7 @@ typedef struct _Edje_External_Param_Info Edje_External_Param_Info; struct _Edje_External_Type { -#define EDJE_EXTERNAL_TYPE_ABI_VERSION (1) +#define EDJE_EXTERNAL_TYPE_ABI_VERSION (2) unsigned int abi_version; /**< always use: * - #EDJE_EXTERNAL_TYPE_ABI_VERSION to declare. * - edje_external_type_abi_version_get() to check. @@ -333,11 +335,13 @@ struct _Edje_External_Type const char *module; const char *module_name; - Evas_Object *(*add) (void *data, Evas *evas, Evas_Object *parent, const Eina_List *params); - void (*state_set) (void *data, Evas_Object *obj, const void *from_params, const void *to_params, float pos); - void (*signal_emit) (void *data, Evas_Object *obj, const char *emission, const char *source); - void *(*params_parse) (void *data, Evas_Object *obj, const Eina_List *params); - void (*params_free) (void *params); + Evas_Object *(*add) (void *data, Evas *evas, Evas_Object *parent, const Eina_List *params, const char *part_name); /**< creates the object to be used by Edje as the part */ + void (*state_set) (void *data, Evas_Object *obj, const void *from_params, const void *to_params, float pos); /**< called upon state changes, including the initial "default" 0.0 state. Parameters are the value returned by params_parse() */ + void (*signal_emit) (void *data, Evas_Object *obj, const char *emission, const char *source); /**< Feed a signal emitted with emission originally set as part_name:signal to this object (without the "part_name:" prefix) */ + Eina_Bool (*param_set) (void *data, Evas_Object *obj, const Edje_External_Param *param); /**< dynamically change a parameter of this external, called by scripts and user code. Returns @c EINA_TRUE on success */ + Eina_Bool (*param_get) (void *data, const Evas_Object *obj, Edje_External_Param *param); /**< dynamically fetch a parameter of this external, called by scripts and user code. Returns @c EINA_TRUE on success. (Must check parameter name and type!) */ + void *(*params_parse) (void *data, Evas_Object *obj, const Eina_List *params); /**< parses the list of parameters, converting into a friendly representation. Used with state_set() */ + void (*params_free) (void *params); /**< free parameters parsed with params_parse() */ /* The following callbacks aren't used by Edje itself, but by UI design tools instead */ @@ -345,6 +349,7 @@ struct _Edje_External_Type const char *(*description_get) (void *data); Evas_Object *(*icon_add) (void *data, Evas *e); Evas_Object *(*preview_add) (void *data, Evas *e); + const char *(*translate) (void *data, const char *orig); /**< called to translate parameters_info name properties for use in user interfaces that support internationalization (i18n) */ Edje_External_Param_Info *parameters_info; @@ -500,6 +505,11 @@ extern "C" { EAPI Eina_Bool edje_object_part_drag_page_get (const Evas_Object *obj, const char *part, double *dx, double *dy); EAPI Eina_Bool edje_object_part_drag_step (Evas_Object *obj, const char *part, double dx, double dy); EAPI Eina_Bool edje_object_part_drag_page (Evas_Object *obj, const char *part, double dx, double dy); + + EAPI Evas_Object *edje_object_part_external_object_get(const Evas_Object *obj, const char *part); + EAPI Eina_Bool edje_object_part_external_param_set(Evas_Object *obj, const char *part, const Edje_External_Param *param); + EAPI Eina_Bool edje_object_part_external_param_get(const Evas_Object *obj, const char *part, Edje_External_Param *param); + EAPI Eina_Bool edje_object_part_box_append (Evas_Object *obj, const char *part, Evas_Object *child); EAPI Eina_Bool edje_object_part_box_prepend (Evas_Object *obj, const char *part, Evas_Object *child); EAPI Eina_Bool edje_object_part_box_insert_before (Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference); diff --git a/legacy/edje/src/lib/edje_edit.c b/legacy/edje/src/lib/edje_edit.c index 3ee8a97a57..854d4e6f8b 100644 --- a/legacy/edje/src/lib/edje_edit.c +++ b/legacy/edje/src/lib/edje_edit.c @@ -1782,7 +1782,7 @@ _edje_edit_real_part_add(Evas_Object *obj, const char *name, Edje_Part_Type type else if (ep->type == EDJE_PART_TYPE_GRADIENT) rp->object = evas_object_gradient_add(ed->evas); else - printf("EDJE ERROR: wrong part type %i!\n", ep->type); + ERR("wrong part type %i!", ep->type); if (rp->object) { evas_object_show(rp->object); @@ -1811,7 +1811,7 @@ _edje_edit_real_part_add(Evas_Object *obj, const char *name, Edje_Part_Type type if (ep->type == EDJE_PART_TYPE_EXTERNAL) { Evas_Object *child; - child = _edje_external_type_add(source, evas_object_evas_get(ed->obj), ed->obj, NULL); + child = _edje_external_type_add(source, evas_object_evas_get(ed->obj), ed->obj, NULL, name); if (child) _edje_real_part_swallow(rp, child); } @@ -2665,8 +2665,7 @@ edje_edit_state_add(Evas_Object *obj, const char *part, const char *name) p->s = eina_stringshare_add(pi->info.s.def); break; default: - printf("ERROR: unknown external parameter type '%d'\n", - p->type); + ERR("unknown external parameter type '%d'", p->type); } pd->external_params = eina_list_append(pd->external_params, p); pi++; @@ -3626,8 +3625,7 @@ edje_edit_state_external_param_get(Evas_Object *obj, const char *part, const cha *value = (void *)p->s; break; default: - printf("ERROR: unknown external parameter type '%d'\n", - p->type); + ERR("unknown external parameter type '%d'", p->type); } return EINA_TRUE; } @@ -3754,7 +3752,7 @@ edje_edit_state_external_param_set(Evas_Object *obj, const char *part, const cha p->s = eina_stringshare_add((const char *)va_arg(ap, char *)); break; default: - printf("ERROR: unknown external parameter type '%d'\n", type); + ERR("unknown external parameter type '%d'", type); } va_end(ap); diff --git a/legacy/edje/src/lib/edje_external.c b/legacy/edje/src/lib/edje_external.c index 019ef387fc..92ee40c3d9 100644 --- a/legacy/edje/src/lib/edje_external.c +++ b/legacy/edje/src/lib/edje_external.c @@ -7,6 +7,172 @@ static Eina_Hash *type_registry = NULL; static int init_count = 0; +/** + * @brief Converts type identifier to string nicer representation. + * + * This may be used to debug or other informational purposes. + * + * @param type the identifier to convert. + * @return the string with the string representation, or @c "(unknown)". + */ +EAPI const char * +edje_external_param_type_str(Edje_External_Param_Type type) +{ + switch (type) + { + case EDJE_EXTERNAL_PARAM_TYPE_INT: + return "INT"; + case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE: + return "DOUBLE"; + case EDJE_EXTERNAL_PARAM_TYPE_STRING: + return "STRING"; + case EDJE_EXTERNAL_PARAM_TYPE_BOOL: + return "BOOL"; + default: + return "(unknown)"; + } +} + +/** + * @brief Get the object created by this external part. + * + * Parts of type external creates the part object using information + * provided by external plugins. It's somehow like "swallow" + * (edje_object_part_swallow()), but it's all set automatically. + * + * This function returns the part created by such external plugins and + * being currently managed by this Edje. + * + * @note Almost all swallow rules apply: you should not move, resize, + * hide, show, set the color or clipper of such part. It's a bit + * more restrictive as one must @b never delete this object! + * + * @param obj A valid Evas_Object handle + * @param part The part name + * @return The externally created object, or NULL if there is none or + * part is not an external. + */ +EAPI Evas_Object * +edje_object_part_external_object_get(const Evas_Object *obj, const char *part) +{ + Edje *ed; + Edje_Real_Part *rp; + + ed = _edje_fetch(obj); + if ((!ed) || (!part)) return NULL; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + + rp = _edje_real_part_recursive_get(ed, (char *)part); + if (!rp) + { + ERR("no part '%s'", part); + return EINA_FALSE; + } + if (rp->part->type != EDJE_PART_TYPE_EXTERNAL) + { + ERR("cannot get external object of a part '%s' that is not EXTERNAL", + rp->part->name); + return NULL; + } + return rp->swallowed_object; +} + +/** + * @brief Set the parameter for the external part. + * + * Parts of type external may carry extra properties that have + * meanings defined by the external plugin. For instance, it may be a + * string that defines a button label and setting this property will + * change that label on the fly. + * + * @note external parts have parameters set when they change + * states. Those parameters will never be changed by this + * function. The interpretation of how state_set parameters and + * param_set will interact is up to the external plugin. + * + * @param obj A valid Evas_Object handle + * @param part The part name + * @param param the parameter details, including its name, type and + * actual value. This pointer should be valid, and the + * parameter must exist in + * #Edje_External_Type::parameters_info, with the exact type, + * otherwise the operation will fail and @c EINA_FALSE will be + * returned. + * + * @return @c EINA_TRUE if everything went fine, @c EINA_FALSE on errors. + */ +EAPI Eina_Bool +edje_object_part_external_param_set(Evas_Object *obj, const char *part, const Edje_External_Param *param) +{ + Edje *ed; + Edje_Real_Part *rp; + + if ((!param) || (!param->name)) return EINA_FALSE; + + ed = _edje_fetch(obj); + if ((!ed) || (!part)) return EINA_FALSE; + + rp = _edje_real_part_recursive_get(ed, (char *)part); + if (!rp) + { + ERR("no part '%s'", part); + return EINA_FALSE; + } + + return _edje_external_param_set(rp->swallowed_object, param); +} + +/** + * @brief Get the parameter for the external part. + * + * Parts of type external may carry extra properties that have + * meanings defined by the external plugin. For instance, it may be a + * string that defines a button label. This property can be modifed by + * state parameters, by explicit calls to + * edje_object_part_external_param_set() or getting the actual object + * with edje_object_part_external_object_get() and calling native + * functions. + * + * This function asks the external plugin what is the current value, + * independent on how it was set. + * + * @param obj A valid Evas_Object handle + * @param part The part name + + * @param param the parameter details. It is used as both input and + * output variable. This pointer should be valid, and the + * parameter must exist in + * #Edje_External_Type::parameters_info, with the exact type, + * otherwise the operation will fail and @c EINA_FALSE will be + * returned. + * + * @return @c EINA_TRUE if everything went fine and @p param members + * are filled with information, @c EINA_FALSE on errors and @p + * param member values are not set or valid. + */ +EAPI Eina_Bool +edje_object_part_external_param_get(const Evas_Object *obj, const char *part, Edje_External_Param *param) +{ + Edje *ed; + Edje_Real_Part *rp; + + if ((!param) || (!param->name)) return EINA_FALSE; + + ed = _edje_fetch(obj); + if ((!ed) || (!part)) return EINA_FALSE; + + rp = _edje_real_part_recursive_get(ed, (char *)part); + if (!rp) + { + ERR("no part '%s'", part); + return EINA_FALSE; + } + + return _edje_external_param_get(rp->swallowed_object, param); +} + /** * Register given type name to return the given information. * @@ -269,7 +435,7 @@ _edje_external_shutdown() } Evas_Object * -_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params) +_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params, const char *part_name) { Edje_External_Type *type; Evas_Object *obj; @@ -281,7 +447,7 @@ _edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, return NULL; } - obj = type->add(type->data, evas, parent, params); + obj = type->add(type->data, evas, parent, params, part_name); if (!obj) { ERR("External type '%s' returned NULL from constructor", type_name); @@ -308,6 +474,42 @@ _edje_external_signal_emit(Evas_Object *obj, const char *emission, const char *s type->signal_emit(type->data, obj, emission, source); } +Eina_Bool +_edje_external_param_set(Evas_Object *obj, const Edje_External_Param *param) +{ + Edje_External_Type *type = evas_object_data_get(obj, "Edje_External_Type"); + if (!type) + { + ERR("no external type for object %p", obj); + return EINA_FALSE; + } + if (!type->param_set) + { + ERR("external type '%s' from module '%s' does not provide param_set()", + type->module_name, type->module); + return EINA_FALSE; + } + return type->param_set(type->data, obj, param); +} + +Eina_Bool +_edje_external_param_get(const Evas_Object *obj, Edje_External_Param *param) +{ + Edje_External_Type *type = evas_object_data_get(obj, "Edje_External_Type"); + if (!type) + { + ERR("no external type for object %p", obj); + return EINA_FALSE; + } + if (!type->param_get) + { + ERR("external type '%s' from module '%s' does not provide param_set()", + type->module_name, type->module); + return EINA_FALSE; + } + return type->param_get(type->data, obj, param); +} + void _edje_external_params_free(Eina_List *external_params, Eina_Bool free_strings) { diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index 60897d8221..68a3eb0431 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -428,7 +428,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g rp->object = evas_object_table_add(ed->evas); break; default: - printf("EDJE ERROR: wrong part type %i!\n", ep->type); + ERR("wrong part type %i!", ep->type); break; } @@ -610,7 +610,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g case EDJE_PART_TYPE_EXTERNAL: { Evas_Object *child_obj; - child_obj = _edje_external_type_add(rp->part->source, evas_object_evas_get(ed->obj), ed->obj, rp->part->default_desc->external_params); + child_obj = _edje_external_type_add(rp->part->source, evas_object_evas_get(ed->obj), ed->obj, rp->part->default_desc->external_params, rp->part->name); if (child_obj) { _edje_real_part_swallow(rp, child_obj); diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 4c2aee86ca..4bdea783e5 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -1523,8 +1523,10 @@ const char *_edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur); void _edje_external_init(); void _edje_external_shutdown(); -Evas_Object *_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params); +Evas_Object *_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params, const char *part_name); void _edje_external_signal_emit(Evas_Object *obj, const char *emission, const char *source); +Eina_Bool _edje_external_param_set(Evas_Object *obj, const Edje_External_Param *param) EINA_ARG_NONNULL(1, 2); +Eina_Bool _edje_external_param_get(const Evas_Object *obj, Edje_External_Param *param) EINA_ARG_NONNULL(1, 2); void _edje_external_params_free(Eina_List *params, Eina_Bool free_strings); void _edje_external_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *params, Edje_Part_Description *chosen_desc); void *_edje_external_params_parse(Evas_Object *obj, const Eina_List *params);