So... this breaks Smarts ABI, rebuild everything after updating Evas.

This patch adds some stuff for smart callback description/instropection, which
is still untested but doesn't break anything that's out there now. Should help
with bindings later on.

Also some parenting guidelines for smart objects, so it's easier to spawn a
subclass out of another. Look at Box and Table for an example on this.

And again, rebuild everything that uses smart objects after this update, or
the world will turn into a happy place where lawyers are no longer needed...
and we don't want to upset the lawyers.


SVN revision: 45043
This commit is contained in:
Iván Briano 2010-01-11 14:24:41 +00:00
parent a4c6892258
commit 3b160b4354
6 changed files with 684 additions and 150 deletions

View File

@ -104,6 +104,7 @@ typedef enum _Evas_Object_Table_Homogeneous_Mode
typedef struct _Evas_Transform Evas_Transform; /**< An Evas projective or affine transform */
typedef struct _Evas_Coord_Rectangle Evas_Coord_Rectangle; /**< A generic rectangle handle */
typedef struct _Evas_Smart_Class Evas_Smart_Class; /**< A smart object base class */
typedef struct _Evas_Smart_Cb_Description Evas_Smart_Cb_Description; /**< A smart object callback description, used to provide introspection */
typedef struct _Evas_Map Evas_Map; /**< An array of map points */
typedef struct _Evas Evas; /**< An Evas canvas handle */
@ -144,7 +145,7 @@ typedef enum _Evas_Aspect_Control
} Evas_Aspect_Control;
#define EVAS_SMART_CLASS_VERSION 3 /** the version you have to put into the version field in the smart class struct */
#define EVAS_SMART_CLASS_VERSION 4 /** the version you have to put into the version field in the smart class struct */
struct _Evas_Smart_Class /** a smart object class */
{
const char *name; /** the string name of the class */
@ -164,16 +165,55 @@ struct _Evas_Smart_Class /** a smart object class */
void (*member_add) (Evas_Object *o, Evas_Object *child);
void (*member_del) (Evas_Object *o, Evas_Object *child);
const Evas_Smart_Class *parent; /**< this class inherits from this parent */
const Evas_Smart_Cb_Description *callbacks; /**< callbacks at this level, NULL terminated */
const void *data;
};
struct _Evas_Smart_Cb_Description
{
const char *name; /**< callback name, ie: "changed" */
/**
* @brief Hint type of @c event_info parameter of Evas_Smart_Cb.
*
* The type string uses the pattern similar to
*
* http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures
*
* but extended to optionally include variable names within
* brackets preceding types. Example:
*
* @li Structure with two integers:
* @c "(ii)"
*
* @li Structure called 'x' with two integers named 'a' and 'b':
* @c "[x]([a]i[b]i)"
*
* @li Array of integers:
* @c "ai"
*
* @li Array called 'x' of struct with two integers:
* @c "[x]a(ii)"
*
* @note This type string is used as a hint and is @b not validated
* or enforced anyhow. Implementors should make the best use
* of it to help bindings, documentation and other users of
* introspection features.
*/
const char *type;
};
/**
* Initializer to zero a whole Evas_Smart_Class structure.
*
* @see EVAS_SMART_CLASS_INIT_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT_CALLBACKS
*/
#define EVAS_SMART_CLASS_INIT_NULL {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define EVAS_SMART_CLASS_INIT_NULL {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
/**
* Initializer to zero a whole Evas_Smart_Class structure and set version.
@ -183,8 +223,10 @@ struct _Evas_Smart_Class /** a smart object class */
*
* @see EVAS_SMART_CLASS_INIT_NULL
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT_CALLBACKS
*/
#define EVAS_SMART_CLASS_INIT_VERSION {NULL, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define EVAS_SMART_CLASS_INIT_VERSION {NULL, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
/**
* Initializer to zero a whole Evas_Smart_Class structure and set name
@ -199,10 +241,133 @@ struct _Evas_Smart_Class /** a smart object class */
*
* @see EVAS_SMART_CLASS_INIT_NULL
* @see EVAS_SMART_CLASS_INIT_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT_CALLBACKS
*/
#define EVAS_SMART_CLASS_INIT_NAME_VERSION(name) {name, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define EVAS_SMART_CLASS_INIT_NAME_VERSION(name) {name, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
/**
* Initializer to zero a whole Evas_Smart_Class structure and set name,
* version and parent class.
*
* Similar to EVAS_SMART_CLASS_INIT_NULL, but will set version field to
* latest EVAS_SMART_CLASS_VERSION, name to the specified value and
* parent class.
*
* It will keep a reference to name field as a "const char *", that is,
* name must be available while the structure is used (hint: static or global!)
* and will not be modified. Similarly, parent reference will be kept.
*
* @see EVAS_SMART_CLASS_INIT_NULL
* @see EVAS_SMART_CLASS_INIT_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT_CALLBACKS
*/
#define EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT(name, parent) {name, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, parent, NULL}
/**
* Initializer to zero a whole Evas_Smart_Class structure and set name,
* version, parent class and callbacks definition.
*
* Similar to EVAS_SMART_CLASS_INIT_NULL, but will set version field to
* latest EVAS_SMART_CLASS_VERSION, name to the specified value, parent
* class and callbacks at this level.
*
* It will keep a reference to name field as a "const char *", that is,
* name must be available while the structure is used (hint: static or global!)
* and will not be modified. Similarly, parent and callbacks reference
* will be kept.
*
* @see EVAS_SMART_CLASS_INIT_NULL
* @see EVAS_SMART_CLASS_INIT_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION
* @see EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT
*/
#define EVAS_SMART_CLASS_INIT_NAME_VERSION_PARENT_CALLBACKS(name, parent, callbacks) {name, EVAS_SMART_CLASS_VERSION, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, parent, callbacks}
/**
* Convenience macro to subclass a Smart Class.
*
* This macro saves some typing when writing a Smart Class derived from
* another one. In order to work, the user needs to provide some functions
* adhering to the following guidelines.
* - <prefix>_smart_set_user(): the internal _smart_set function will call
* this one provided by the user after inheriting everything from the
* parent, which should take care of setting the right member functions
* for the class.
* - <prefix>_parent_sc: smart class of the parent. When calling parent
* functions from overloaded ones, use this global variable.
* - <prefix>_smart_class_new(): this function returns the Evas_Smart needed
* to create smart objects with this class, should be called by the public
* _add() function.
* - If this new class should be subclassable as well, a public _smart_set()
* function is desirable to fill the class used as parent by the children.
* It's up to the user to provide this interface, which will most likely
* call <prefix>_smart_set() to get the job done.
*
* @param smart_name The name used for the Smart Class. e.g: "Evas_Object_Box".
* @param prefix Prefix used for all variables and functions defined.
* @param api_type Type of the structure used as API for the Smart Class. Either Evas_Smart_Class or something derived from it.
* @param parent_type Type of the parent class API.
* @param parent_func Function that sets up the parent class. e.g: evas_object_box_smart_set().
* @param cb_desc Array of callback descriptions for this Smart Class.
*/
#define EVAS_SMART_SUBCLASS_NEW(smart_name, prefix, api_type, parent_type, parent_func, cb_desc) \
static parent_type prefix##_parent_sc; \
static Eina_Bool prefix##_parent_init = 0; \
static void prefix##_smart_set_user(api_type *api); \
static void prefix##_smart_set(api_type *api) \
{ \
Evas_Smart_Class *sc; \
if (!(sc = (Evas_Smart_Class *)api)) \
return; \
if (!prefix##_parent_init) \
{ \
memset(&prefix##_parent_sc, 0, sizeof(parent_type)); \
((Evas_Smart_Class)prefix##_parent_sc).version = EVAS_SMART_CLASS_VERSION; \
parent_func(&prefix##_parent_sc); \
prefix##_parent_init = 1; \
} \
evas_smart_class_inherit(sc, &prefix##_parent_sc); \
prefix##_smart_set_user(api); \
} \
static Evas_Smart * prefix##_smart_class_new(void) \
{ \
static Evas_Smart *smart = NULL; \
static api_type api; \
if (!smart) \
{ \
Evas_Smart_Class *sc = (Evas_Smart_Class *)&api; \
memset(&api, 0, sizeof(api_type)); \
sc->version = EVAS_SMART_CLASS_VERSION; \
sc->name = smart_name; \
sc->callbacks = cb_desc; \
prefix##_smart_set(&api); \
smart = evas_smart_class_new(sc); \
} \
return smart; \
}
/**
* Convenience macro to allocate smart data only if needed.
*
* When writing a subclassable smart object, the .add function will need
* to check if the smart private data was already allocated by some child
* object or not. This macro makes it easier to do it.
*
* @param o Evas object passed to the .add function
* @param priv_type The type of the data to allocate
*/
#define EVAS_SMART_DATA_ALLOC(o, priv_type) \
priv_type *priv; \
priv = evas_object_smart_data_get(o); \
if (!priv) \
{ \
priv = (priv_type *)calloc(1, sizeof(priv_type)); \
if (!priv) \
return; \
evas_object_smart_data_set(o, priv); \
}
typedef struct _Evas_Pixel_Import_Source Evas_Pixel_Import_Source; /**< A source description of pixels for importing pixels */
typedef struct _Evas_Engine_Info Evas_Engine_Info; /**< A generic Evas Engine information structure */
@ -898,6 +1063,20 @@ extern "C" {
EAPI const Evas_Smart_Class *evas_smart_class_get (const Evas_Smart *s) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void *evas_smart_data_get (const Evas_Smart *s) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI const Evas_Smart_Cb_Description *evas_smart_callback_description_find(const Evas_Smart *s, const char *name) EINA_ARG_NONNULL(1, 2) EINA_PURE;
EAPI Eina_Bool evas_smart_class_inherit_full (Evas_Smart_Class *sc, const Evas_Smart_Class *parent_sc, unsigned int parent_sc_size) EINA_ARG_NONNULL(1, 2);
/**
* Easy to use version of evas_smart_class_inherit_full().
*
* This version will use sizeof(parent_sc), copying everything.
*
* @param sc child class, will have methods copied from @a parent_sc
* @param parent_sc parent class, will provide contents to be copied.
* @return 1 on success, 0 on failure.
*/
#define evas_smart_class_inherit(sc, parent_sc) evas_smart_class_inherit_full(sc, parent_sc, sizeof(*parent_sc))
EAPI Evas_Object *evas_object_smart_add (Evas *e, Evas_Smart *s) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_MALLOC;
EAPI void evas_object_smart_member_add (Evas_Object *obj, Evas_Object *smart_obj) EINA_ARG_NONNULL(1, 2);
@ -910,6 +1089,11 @@ extern "C" {
EAPI void evas_object_smart_callback_add (Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1, 2, 3);
EAPI void *evas_object_smart_callback_del (Evas_Object *obj, const char *event, Evas_Smart_Cb func) EINA_ARG_NONNULL(1, 2, 3);
EAPI void evas_object_smart_callback_call (Evas_Object *obj, const char *event, void *event_info) EINA_ARG_NONNULL(1, 2);
EAPI Eina_Bool evas_object_smart_callbacks_descriptions_set(Evas_Object *obj, const Evas_Smart_Cb_Description *descriptions) EINA_ARG_NONNULL(1);
EAPI void evas_object_smart_callbacks_descriptions_get(const Evas_Object *obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count) EINA_ARG_NONNULL(1);
EAPI void evas_object_smart_callback_description_find(const Evas_Object *obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description) EINA_ARG_NONNULL(1, 2);
EAPI void evas_object_smart_changed (Evas_Object *obj) EINA_ARG_NONNULL(1);
EAPI void evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value) EINA_ARG_NONNULL(1);
EAPI Eina_Bool evas_object_smart_need_recalculate_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;

View File

@ -50,7 +50,9 @@ struct _Evas_Object_Box_Accessor
return val; \
}
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
EVAS_SMART_SUBCLASS_NEW("Evas_Object_Box", _evas_object_box,
Evas_Object_Box_Api, Evas_Smart_Class,
evas_object_smart_clipped_smart_set, NULL)
static Eina_Bool
_evas_object_box_iterator_next(Evas_Object_Box_Iterator *it, void **data)
@ -420,7 +422,7 @@ _evas_object_box_smart_add(Evas_Object *o)
evas_object_smart_data_set(o, priv);
}
_parent_sc.add(o);
_evas_object_box_parent_sc.add(o);
priv->children = NULL;
priv->align.h = 0.5;
@ -461,7 +463,7 @@ _evas_object_box_smart_del(Evas_Object *o)
if (priv->layout.data && priv->layout.free_data)
priv->layout.free_data(priv->layout.data);
_parent_sc.del(o);
_evas_object_box_parent_sc.del(o);
}
static void
@ -487,15 +489,23 @@ _evas_object_box_smart_calculate(Evas_Object *o)
ERR("No layout function set for %p box.", o);
}
static Evas_Smart *
_evas_object_box_smart_class_new(void)
static void
_evas_object_box_smart_set_user(Evas_Object_Box_Api *api)
{
static Evas_Object_Box_Api api = EVAS_OBJECT_BOX_API_INIT_NAME_VERSION("Evas_Object_Box");
api->base.add = _evas_object_box_smart_add;
api->base.del = _evas_object_box_smart_del;
api->base.resize = _evas_object_box_smart_resize;
api->base.calculate = _evas_object_box_smart_calculate;
if (!_parent_sc.name)
evas_object_box_smart_set(&api);
return evas_smart_class_new(&api.base);
api->append = _evas_object_box_append_default;
api->prepend = _evas_object_box_prepend_default;
api->insert_before = _evas_object_box_insert_before_default;
api->insert_after = _evas_object_box_insert_after_default;
api->insert_at = _evas_object_box_insert_at_default;
api->remove = _evas_object_box_remove_default;
api->remove_at = _evas_object_box_remove_at_default;
api->option_new = _evas_object_box_option_new_default;
api->option_free = _evas_object_box_option_free_default;
}
/**
@ -506,17 +516,10 @@ _evas_object_box_smart_class_new(void)
* properties of the box must be set/retrieved via
* evas_object_box_{h,v}_{align,padding}_{get,set)().
*/
Evas_Object *
EAPI Evas_Object *
evas_object_box_add(Evas *evas)
{
static Evas_Smart *smart = NULL;
Evas_Object *o;
if (!smart)
smart = _evas_object_box_smart_class_new();
o = evas_object_smart_add(evas, smart);
return o;
return evas_object_smart_add(evas, _evas_object_box_smart_class_new());
}
/**
@ -524,7 +527,7 @@ evas_object_box_add(Evas *evas)
*
* @see evas_object_box_add()
*/
Evas_Object *
EAPI Evas_Object *
evas_object_box_add_to(Evas_Object *parent)
{
Evas *evas;
@ -540,41 +543,12 @@ evas_object_box_add_to(Evas_Object *parent)
* Set the default box @a api struct (Evas_Object_Box_Api)
* with the default values. May be used to extend that API.
*/
void
EAPI void
evas_object_box_smart_set(Evas_Object_Box_Api *api)
{
if (!api)
return;
if (!_parent_sc.name)
evas_object_smart_clipped_smart_set(&_parent_sc);
api->base.add = _evas_object_box_smart_add;
api->base.del = _evas_object_box_smart_del;
api->base.move = _parent_sc.move;
api->base.resize = _evas_object_box_smart_resize;
api->base.show = _parent_sc.show;
api->base.hide = _parent_sc.hide;
api->base.color_set = _parent_sc.color_set;
api->base.clip_set = _parent_sc.clip_set;
api->base.clip_unset = _parent_sc.clip_unset;
api->base.calculate = _evas_object_box_smart_calculate;
api->base.member_add = _parent_sc.member_add;
api->base.member_del = _parent_sc.member_del;
api->append = _evas_object_box_append_default;
api->prepend = _evas_object_box_prepend_default;
api->insert_before = _evas_object_box_insert_before_default;
api->insert_after = _evas_object_box_insert_after_default;
api->insert_at = _evas_object_box_insert_at_default;
api->remove = _evas_object_box_remove_default;
api->remove_at = _evas_object_box_remove_at_default;
api->property_set = NULL;
api->property_get = NULL;
api->property_name_get = NULL;
api->property_id_get = NULL;
api->option_new = _evas_object_box_option_new_default;
api->option_free = _evas_object_box_option_free_default;
_evas_object_box_smart_set(api);
}
/**
@ -582,7 +556,7 @@ evas_object_box_smart_set(Evas_Object_Box_Api *api)
* which here defines its genre (horizontal, vertical, homogeneous,
* etc.).
*/
void
EAPI void
evas_object_box_layout_set(Evas_Object *o, Evas_Object_Box_Layout cb, const void *data, void (*free_data)(void *data))
{
EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
@ -789,7 +763,7 @@ _evas_object_box_layout_horizontal_weight_apply(Evas_Object_Box_Data *priv, Evas
* properties must be set (by the
* evas_object_size_hint_{min,max}_set() functions.
*/
void
EAPI void
evas_object_box_layout_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int pad_inc = 0, sub_pixel = 0;
@ -955,7 +929,7 @@ _evas_object_box_layout_vertical_weight_apply(Evas_Object_Box_Data *priv, Evas_O
* evas_object_box_layout_horizontal(). The description of its
* behaviour can be derived from that function's documentation.
*/
void
EAPI void
evas_object_box_layout_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int pad_inc = 0, sub_pixel = 0;
@ -1092,7 +1066,7 @@ evas_object_box_layout_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void
* element to the exact height of its parent (respecting the max hint
* on the child's height).
*/
void
EAPI void
evas_object_box_layout_homogeneous_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int cell_sz, share, inc;
@ -1161,7 +1135,7 @@ evas_object_box_layout_homogeneous_horizontal(Evas_Object *o, Evas_Object_Box_Da
* evas_object_box_layout_homogeneous_horizontal(). The description
* of its behaviour can be derived from that function's documentation.
*/
void
EAPI void
evas_object_box_layout_homogeneous_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int cell_sz, share, inc;
@ -1262,7 +1236,7 @@ evas_object_box_layout_homogeneous_vertical(Evas_Object *o, Evas_Object_Box_Data
* element to the exact height of its parent (respecting the max hint
* on the child's height).
*/
void
EAPI void
evas_object_box_layout_homogeneous_max_size_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
@ -1355,7 +1329,7 @@ evas_object_box_layout_homogeneous_max_size_horizontal(Evas_Object *o, Evas_Obje
* description of its behaviour can be derived from that function's
* documentation.
*/
void
EAPI void
evas_object_box_layout_homogeneous_max_size_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
@ -1538,7 +1512,7 @@ _evas_object_box_layout_flow_horizontal_row_info_collect(Evas_Object_Box_Data *p
* @c align_y dictates positioning relative to the *largest height*
* required by a child object in the actual row.
*/
void
EAPI void
evas_object_box_layout_flow_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int n_children, v_justify;
@ -1727,7 +1701,7 @@ _evas_object_box_layout_flow_vertical_col_info_collect(Evas_Object_Box_Data *pri
* evas_object_box_layout_flow_horizontal(). The description of its
* behaviour can be derived from that function's documentation.
*/
void
EAPI void
evas_object_box_layout_flow_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
int n_children;
@ -1863,7 +1837,7 @@ evas_object_box_layout_flow_vertical(Evas_Object *o, Evas_Object_Box_Data *priv,
* accounting its horizontal padding properties). Same applies to
* vertical axis.
*/
void
EAPI void
evas_object_box_layout_stack(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
{
Eina_List *l;
@ -1914,7 +1888,7 @@ evas_object_box_layout_stack(Evas_Object *o, Evas_Object_Box_Data *priv, void *d
/**
* Set the alignment of the whole bounding box of contents.
*/
void
EAPI void
evas_object_box_align_set(Evas_Object *o, double horizontal, double vertical)
{
EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
@ -1928,7 +1902,7 @@ evas_object_box_align_set(Evas_Object *o, double horizontal, double vertical)
/**
* Get alignment of the whole bounding box of contents.
*/
void
EAPI void
evas_object_box_align_get(const Evas_Object *o, double *horizontal, double *vertical)
{
EVAS_OBJECT_BOX_DATA_GET(o, priv);
@ -1947,7 +1921,7 @@ evas_object_box_align_get(const Evas_Object *o, double *horizontal, double *vert
/**
* Set the space (padding) between cells.
*/
void
EAPI void
evas_object_box_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord vertical)
{
EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
@ -1961,7 +1935,7 @@ evas_object_box_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord ve
/**
* Get the (space) padding between cells.
*/
void
EAPI void
evas_object_box_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical)
{
EVAS_OBJECT_BOX_DATA_GET(o, priv);
@ -1981,7 +1955,7 @@ evas_object_box_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_C
* Append a new object @a child to the box @a o. On error, @c NULL is
* returned.
*/
Evas_Object_Box_Option *
EAPI Evas_Object_Box_Option *
evas_object_box_append(Evas_Object *o, Evas_Object *child)
{
Evas_Object_Box_Option *opt;
@ -2011,7 +1985,7 @@ evas_object_box_append(Evas_Object *o, Evas_Object *child)
* Prepend a new object @a child to the box @a o. On error, @c NULL is
* returned.
*/
Evas_Object_Box_Option *
EAPI Evas_Object_Box_Option *
evas_object_box_prepend(Evas_Object *o, Evas_Object *child)
{
Evas_Object_Box_Option *opt;
@ -2042,7 +2016,7 @@ evas_object_box_prepend(Evas_Object *o, Evas_Object *child)
* reference. If @a reference is not contained in the box or any other
* error occurs, @c NULL is returned.
*/
Evas_Object_Box_Option *
EAPI Evas_Object_Box_Option *
evas_object_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
{
Evas_Object_Box_Option *opt;
@ -2073,7 +2047,7 @@ evas_object_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Obj
* reference. If @a reference is not contained in the box or any other
* error occurs, @c NULL is returend.
*/
Evas_Object_Box_Option *
EAPI Evas_Object_Box_Option *
evas_object_box_insert_after(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
{
Evas_Object_Box_Option *opt;
@ -2103,7 +2077,7 @@ evas_object_box_insert_after(Evas_Object *o, Evas_Object *child, const Evas_Obje
* Insert a new object @a child to the box @a o at position @a pos. On
* error, @c NULL is returned.
*/
Evas_Object_Box_Option *
EAPI Evas_Object_Box_Option *
evas_object_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
{
Evas_Object_Box_Option *opt;
@ -2133,7 +2107,7 @@ evas_object_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
* Remove an object @a child from the box @a o. On error, @c 0 is
* returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_remove(Evas_Object *o, Evas_Object *child)
{
const Evas_Object_Box_Api *api;
@ -2163,7 +2137,7 @@ evas_object_box_remove(Evas_Object *o, Evas_Object *child)
* Remove an object from the box @a o which occupies position @a
* pos. On error, @c 0 is returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_remove_at(Evas_Object *o, unsigned int pos)
{
const Evas_Object_Box_Api *api;
@ -2190,7 +2164,7 @@ evas_object_box_remove_at(Evas_Object *o, unsigned int pos)
* Remove all child objects.
* @return 0 on errors
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_remove_all(Evas_Object *o, Eina_Bool clear)
{
const Evas_Object_Box_Api *api;
@ -2226,7 +2200,7 @@ evas_object_box_remove_all(Evas_Object *o, Eina_Bool clear)
*
* @note Do not remove or delete objects while walking the list.
*/
Eina_Iterator *
EAPI Eina_Iterator *
evas_object_box_iterator_new(const Evas_Object *o)
{
Evas_Object_Box_Iterator *it;
@ -2255,7 +2229,7 @@ evas_object_box_iterator_new(const Evas_Object *o)
*
* @note Do not remove or delete objects while walking the list.
*/
Eina_Accessor *
EAPI Eina_Accessor *
evas_object_box_accessor_new(const Evas_Object *o)
{
Evas_Object_Box_Accessor *it;
@ -2287,7 +2261,7 @@ evas_object_box_accessor_new(const Evas_Object *o)
* It's possible to remove objects from the box when walking this
* list, but these removals won't be reflected on it.
*/
Eina_List *
EAPI Eina_List *
evas_object_box_children_get(const Evas_Object *o)
{
Eina_List *new_list = NULL, *l;
@ -2305,7 +2279,7 @@ evas_object_box_children_get(const Evas_Object *o)
* Get the name of the property of the child elements of the box @a o
* whose id is @a property. On error, @c NULL is returned.
*/
const char *
EAPI const char *
evas_object_box_option_property_name_get(Evas_Object *o, int property)
{
const Evas_Object_Box_Api *api;
@ -2326,7 +2300,7 @@ evas_object_box_option_property_name_get(Evas_Object *o, int property)
* Get the id of the property of the child elements of the box @a o
* whose name is @a name. On error, @c -1 is returned.
*/
int
EAPI int
evas_object_box_option_property_id_get(Evas_Object *o, const char *name)
{
const Evas_Object_Box_Api *api;
@ -2349,7 +2323,7 @@ evas_object_box_option_property_id_get(Evas_Object *o, const char *name)
* must be the last arguments and their type *must* match that of the
* property itself. On error, @c 0 is returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_option_property_set(Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
{
Eina_Bool ret;
@ -2370,7 +2344,7 @@ evas_object_box_option_property_set(Evas_Object *o, Evas_Object_Box_Option *opt,
* is returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_option_property_vset(Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
{
const Evas_Object_Box_Api *api;
@ -2396,7 +2370,7 @@ evas_object_box_option_property_vset(Evas_Object *o, Evas_Object_Box_Option *opt
* be addresses of variables with the same type of that property. On
* error, @c 0 is returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_option_property_get(Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
{
Eina_Bool ret;
@ -2415,7 +2389,7 @@ evas_object_box_option_property_get(Evas_Object *o, Evas_Object_Box_Option *opt,
* va_list @a args is initialized with must be addresses of variables
* with the same type of that property. On error, @c 0 is returned.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_box_option_property_vget(Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
{
const Evas_Object_Box_Api *api;

View File

@ -11,6 +11,7 @@ struct _Evas_Object_Smart
void *data;
Eina_List *callbacks;
Eina_Inlist *contained;
Evas_Smart_Cb_Description_Array callbacks_descriptions;
int walking_list;
Eina_Bool deletions_waiting : 1;
Eina_Bool need_recalculate : 1;
@ -467,6 +468,174 @@ evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event
evas_object_smart_callbacks_clear(obj);
}
/**
* Set smart object instance callbacks descriptions.
*
* These descriptions are hints to be used by introspection and are
* not enforced in any way.
*
* It will not be checked if instance callbacks descriptions have the
* same name as another in class. Both are kept in different arrays
* and users of evas_object_smart_callbacks_descriptions_get() should
* handle this case as they wish.
*
* @param obj The smart object
* @param descriptions NULL terminated (name != NULL) array with
* descriptions. Array elements will not be modified, but
* reference to them and their contents will be made, so this
* array should be kept alive during object lifetime.
* @return 1 on success, 0 on failure.
* @ingroup Evas_Smart_Object_Group
*
* @note while instance callbacks descriptions are possible, they are
* not recommended. Use class callbacks descriptions instead as they
* make user's life simpler and will use less memory as descriptions
* and arrays will be shared among all instances.
*/
EAPI Eina_Bool
evas_object_smart_callbacks_descriptions_set(Evas_Object *obj, const Evas_Smart_Cb_Description *descriptions)
{
const Evas_Smart_Cb_Description *d;
const Evas_Smart_Cb_Description_Array *sa;
Evas_Object_Smart *o;
unsigned int i, count;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return 0;
MAGIC_CHECK_END();
o = (Evas_Object_Smart *)(obj->object_data);
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
return 0;
MAGIC_CHECK_END();
if ((!descriptions) || (!descriptions->name))
{
evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
return 1;
}
for (count = 0, d = descriptions; d->name != NULL; d++)
count++;
evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, count);
for (i = 0, d = descriptions; i < count; d++, i++)
o->callbacks_descriptions.array[i] = d;
evas_smart_cb_descriptions_fix(&o->callbacks_descriptions);
return 1;
}
/**
* Get the callbacks descriptions known by this smart object.
*
* This call retrieves processed callbacks descriptions for both
* instance and class. These arrays are sorted by description's name
* and are @c NULL terminated, so both @a class_count and
* @a instance_count can be ignored, the terminator @c NULL is not
* counted in these values.
*
* @param s the smart object.
* @param class_descriptions where to store class callbacks
* descriptions array, if any is known. If no descriptions are
* known, @c NULL is returned. This parameter may be @c NULL if
* it is not of interest.
* @param class_count returns how many class callbacks descriptions
* are known.
* @param instance_descriptions where to store instance callbacks
* descriptions array, if any is known. If no descriptions are
* known, @c NULL is returned. This parameter may be @c NULL if
* it is not of interest.
* @param instance_count returns how many instance callbacks
* descriptions are known.
*
* @note if just class descriptions are of interest, try
* evas_smart_callbacks_descriptions_get() instead.
*
* @see evas_smart_callbacks_descriptions_get()
* @ingroup Evas_Smart_Object_Group
*/
EAPI void
evas_object_smart_callbacks_descriptions_get(const Evas_Object *obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count)
{
Evas_Object_Smart *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
if (class_descriptions) *class_descriptions = NULL;
if (class_count) *class_count = 0;
if (instance_descriptions) *instance_descriptions = NULL;
if (instance_count) *instance_count = 0;
return;
MAGIC_CHECK_END();
o = (Evas_Object_Smart *)(obj->object_data);
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
if (class_descriptions) *class_descriptions = NULL;
if (class_count) *class_count = 0;
if (instance_descriptions) *instance_descriptions = NULL;
if (instance_count) *instance_count = 0;
return;
MAGIC_CHECK_END();
if (class_descriptions)
*class_descriptions = obj->smart.smart->callbacks.array;
if (class_count)
*class_count = obj->smart.smart->callbacks.size;
if (instance_descriptions)
*instance_descriptions = o->callbacks_descriptions.array;
if (instance_count)
*instance_count = o->callbacks_descriptions.size;
}
/**
* Find callback description for callback called @a name.
*
* @param obj the smart object.
* @param name name of desired callback, must @b not be @c NULL. The
* search have a special case for @a name being the same
* pointer as registered with Evas_Smart_Cb_Description, one
* can use it to avoid excessive use of strcmp().
* @param class_description pointer to return class description or @c
* NULL if not found. If parameter is @c NULL, no search will
* be done on class descriptions.
* @param instance_description pointer to return instance description
* or @c NULL if not found. If parameter is @c NULL, no search
* will be done on instance descriptions.
* @return reference to description if found, @c NULL if not found.
*/
EAPI void
evas_object_smart_callback_description_find(const Evas_Object *obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description)
{
Evas_Object_Smart *o;
if (!name)
{
if (class_description) *class_description = NULL;
if (instance_description) *instance_description = NULL;
return;
}
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
if (class_description) *class_description = NULL;
if (instance_description) *instance_description = NULL;
return;
MAGIC_CHECK_END();
o = (Evas_Object_Smart *)(obj->object_data);
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
if (class_description) *class_description = NULL;
if (instance_description) *instance_description = NULL;
return;
MAGIC_CHECK_END();
if (class_description)
*class_description = evas_smart_cb_description_find
(&obj->smart.smart->callbacks, name);
if (instance_description)
*instance_description = evas_smart_cb_description_find
(&o->callbacks_descriptions, name);
}
/**
* Set the need_recalculate flag of given smart object.
*

View File

@ -813,24 +813,15 @@ _evas_object_table_smart_calculate_regular(Evas_Object *o, Evas_Object_Table_Dat
_evas_object_table_calculate_layout_regular(o, priv);
}
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
EVAS_SMART_SUBCLASS_NEW("Evas_Object_Table", _evas_object_table,
Evas_Smart_Class, Evas_Smart_Class,
evas_object_smart_clipped_smart_set, NULL)
static void
_evas_object_table_smart_add(Evas_Object *o)
{
Evas_Object_Table_Data *priv;
EVAS_SMART_DATA_ALLOC(o, Evas_Object_Table_Data)
priv = evas_object_smart_data_get(o);
if (!priv)
{
priv = calloc(1, sizeof(*priv));
if (!priv)
{
ERR("could not allocate object private data.");
return;
}
evas_object_smart_data_set(o, priv);
}
priv->pad.h = 0;
priv->pad.v = 0;
priv->align.h = 0.5;
@ -843,7 +834,7 @@ _evas_object_table_smart_add(Evas_Object *o)
priv->expand_h = 0;
priv->expand_v = 0;
_parent_sc.add(o);
_evas_object_table_parent_sc.add(o);
}
static void
@ -865,7 +856,7 @@ _evas_object_table_smart_del(Evas_Object *o)
if (priv->cache)
_evas_object_table_cache_free(priv->cache);
_parent_sc.del(o);
_evas_object_table_parent_sc.del(o);
}
static void
@ -896,37 +887,12 @@ _evas_object_table_smart_calculate(Evas_Object *o)
}
static void
_evas_object_table_smart_set(Evas_Smart_Class *sc)
_evas_object_table_smart_set_user(Evas_Smart_Class *sc)
{
if (!sc)
return;
if (!_parent_sc.name)
evas_object_smart_clipped_smart_set(&_parent_sc);
sc->add = _evas_object_table_smart_add;
sc->del = _evas_object_table_smart_del;
sc->move = _parent_sc.move;
sc->resize = _evas_object_table_smart_resize;
sc->show = _parent_sc.show;
sc->hide = _parent_sc.hide;
sc->color_set = _parent_sc.color_set;
sc->clip_set = _parent_sc.clip_set;
sc->clip_unset = _parent_sc.clip_unset;
sc->calculate = _evas_object_table_smart_calculate;
sc->member_add = _parent_sc.member_add;
sc->member_del = _parent_sc.member_del;
}
static Evas_Smart *
_evas_object_table_smart_class_new(void)
{
static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("Evas_Object_Table");
if (!_parent_sc.name)
_evas_object_table_smart_set(&sc);
return evas_smart_class_new(&sc);
}
/**
@ -935,17 +901,10 @@ _evas_object_table_smart_class_new(void)
* It's set to non-homogeneous by default, add children with
* evas_object_table_pack().
*/
Evas_Object *
EAPI Evas_Object *
evas_object_table_add(Evas *evas)
{
static Evas_Smart *smart = NULL;
Evas_Object *o;
if (!smart)
smart = _evas_object_table_smart_class_new();
o = evas_object_smart_add(evas, smart);
return o;
return evas_object_smart_add(evas, _evas_object_table_smart_class_new());
}
/**
@ -953,7 +912,7 @@ evas_object_table_add(Evas *evas)
*
* @see evas_object_table_add()
*/
Evas_Object *
EAPI Evas_Object *
evas_object_table_add_to(Evas_Object *parent)
{
Evas *evas;
@ -1007,7 +966,7 @@ evas_object_table_add_to(Evas_Object *parent)
* no minimum size is provided at all then the table will fallback to
* expand mode as well.
*/
void
EAPI void
evas_object_table_homogeneous_set(Evas_Object *o, Evas_Object_Table_Homogeneous_Mode homogeneous)
{
EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
@ -1023,7 +982,7 @@ evas_object_table_homogeneous_set(Evas_Object *o, Evas_Object_Table_Homogeneous_
*
* @see evas_object_table_homogeneous_set()
*/
Evas_Object_Table_Homogeneous_Mode
EAPI Evas_Object_Table_Homogeneous_Mode
evas_object_table_homogeneous_get(const Evas_Object *o)
{
EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
@ -1033,7 +992,7 @@ evas_object_table_homogeneous_get(const Evas_Object *o)
/**
* Set the alignment of the whole bounding box of contents.
*/
void
EAPI void
evas_object_table_align_set(Evas_Object *o, double horizontal, double vertical)
{
EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
@ -1047,7 +1006,7 @@ evas_object_table_align_set(Evas_Object *o, double horizontal, double vertical)
/**
* Get alignment of the whole bounding box of contents.
*/
void
EAPI void
evas_object_table_align_get(const Evas_Object *o, double *horizontal, double *vertical)
{
EVAS_OBJECT_TABLE_DATA_GET(o, priv);
@ -1066,7 +1025,7 @@ evas_object_table_align_get(const Evas_Object *o, double *horizontal, double *ve
/**
* Set padding between cells.
*/
void
EAPI void
evas_object_table_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord vertical)
{
EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
@ -1081,7 +1040,7 @@ evas_object_table_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord
/**
* Get padding between cells.
*/
void
EAPI void
evas_object_table_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical)
{
EVAS_OBJECT_TABLE_DATA_GET(o, priv);
@ -1109,7 +1068,7 @@ evas_object_table_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas
*
* @return 1 on success, 0 on failure.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
{
Evas_Object_Table_Option *opt;
@ -1232,7 +1191,7 @@ _evas_object_table_remove_opt(Evas_Object_Table_Data *priv, Evas_Object_Table_Op
*
* @return 1 on success, 0 on failure.
*/
Eina_Bool
EAPI Eina_Bool
evas_object_table_unpack(Evas_Object *o, Evas_Object *child)
{
Evas_Object_Table_Option *opt;
@ -1268,7 +1227,7 @@ evas_object_table_unpack(Evas_Object *o, Evas_Object *child)
* @param o The given table object.
* @param clear if true, it will delete just removed children.
*/
void
EAPI void
evas_object_table_clear(Evas_Object *o, Eina_Bool clear)
{
Evas_Object_Table_Option *opt;
@ -1298,7 +1257,7 @@ evas_object_table_clear(Evas_Object *o, Eina_Bool clear)
* difference for a single cell table is that paddings will be
* accounted proportionally.
*/
void
EAPI void
evas_object_table_col_row_size_get(const Evas_Object *o, int *cols, int *rows)
{
EVAS_OBJECT_TABLE_DATA_GET(o, priv);
@ -1319,7 +1278,7 @@ evas_object_table_col_row_size_get(const Evas_Object *o, int *cols, int *rows)
*
* @note Do not remove or delete objects while walking the list.
*/
Eina_Iterator *
EAPI Eina_Iterator *
evas_object_table_iterator_new(const Evas_Object *o)
{
Evas_Object_Table_Iterator *it;
@ -1348,7 +1307,7 @@ evas_object_table_iterator_new(const Evas_Object *o)
*
* @note Do not remove or delete objects while walking the list.
*/
Eina_Accessor *
EAPI Eina_Accessor *
evas_object_table_accessor_new(const Evas_Object *o)
{
Evas_Object_Table_Accessor *it;
@ -1380,7 +1339,7 @@ evas_object_table_accessor_new(const Evas_Object *o)
* It's possible to remove objects from the table when walking this
* list, but these removals won't be reflected on it.
*/
Eina_List *
EAPI Eina_List *
evas_object_table_children_get(const Evas_Object *o)
{
Eina_List *new_list = NULL, *l;

View File

@ -1,6 +1,9 @@
#include "evas_common.h"
#include "evas_private.h"
static void _evas_smart_class_callbacks_create(Evas_Smart *s);
/* all public */
/**
@ -142,6 +145,7 @@ evas_smart_class_new(const Evas_Smart_Class *sc)
s->magic = MAGIC_SMART;
s->smart_class = sc;
_evas_smart_class_callbacks_create(s);
return s;
}
@ -179,6 +183,118 @@ evas_smart_data_get(const Evas_Smart *s)
return (void *)s->smart_class->data;
}
/**
* Get the callbacks known by this Evas_Smart.
*
* This is likely different from Evas_Smart_Class::callbacks as it
* will contain the callbacks of all class hierarchy sorted, while the
* direct smart class member refers only to that specific class and
* should not include parent's.
*
* If no callbacks are known, this function returns @c NULL.
*
* The array elements and thus their contents will be reference to
* original values given to evas_smart_new() as
* Evas_Smart_Class::callbacks.
*
* The array is sorted by name. The last array element is the @c NULL
* pointer and is not counted in @a count. Loop iterations can check
* any of these cases.
*
* @param s the Evas_Smart.
* @param count returns the number of elements in returned array.
* @return the array with callback descriptions known by this class,
* its size is returned in @a count parameter. It should not
* be modified anyhow. If no callbacks are known, @c NULL is
* returned. The array is sorted by name and elements refer to
* the original value given to evas_smart_new().
*
* @note objects may provide per-instance callbacks, use
* evas_object_smart_callbacks_descriptions_get() to get those
* as well.
* @see evas_object_smart_callbacks_descriptions_get()
*/
EAPI const Evas_Smart_Cb_Description **
evas_smart_callbacks_descriptions_get(const Evas_Smart *s, unsigned int *count)
{
MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
if (count) *count = 0;
return NULL;
MAGIC_CHECK_END();
if (count) *count = s->callbacks.size;
return s->callbacks.array;
}
/**
* Find callback description for callback called @a name.
*
* @param s the Evas_Smart.
* @param name name of desired callback, must @b not be @c NULL. The
* search have a special case for @a name being the same
* pointer as registered with Evas_Smart_Cb_Description, one
* can use it to avoid excessive use of strcmp().
* @return reference to description if found, @c NULL if not found.
*/
EAPI const Evas_Smart_Cb_Description *
evas_smart_callback_description_find(const Evas_Smart *s, const char *name)
{
if (!name) return NULL;
MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
return NULL;
MAGIC_CHECK_END();
return evas_smart_cb_description_find(&s->callbacks, name);
}
/**
* Sets one class to inherit from the other.
*
* Copy all function pointers, set @c parent to @a parent_sc and copy
* everything after sizeof(Evas_Smart_Class) present in @a parent_sc,
* using @a parent_sc_size as reference.
*
* This is recommended instead of a single memcpy() since it will take
* care to not modify @a sc name, version, callbacks and possible
* other members.
*
* @param sc child class.
* @param parent_sc parent class, will provide attributes.
* @param parent_sc_size size of parent_sc structure, child should be at least
* this size. Everything after @c Evas_Smart_Class size is copied
* using regular memcpy().
*/
EAPI Eina_Bool
evas_smart_class_inherit_full(Evas_Smart_Class *sc, const Evas_Smart_Class *parent_sc, unsigned int parent_sc_size)
{
unsigned int off;
/* api does not match abi! for now refuse as we only have 1 version */
if (parent_sc->version != EVAS_SMART_CLASS_VERSION) return 0;
#define _CP(m) sc->m = parent_sc->m
_CP(add);
_CP(del);
_CP(move);
_CP(resize);
_CP(show);
_CP(hide);
_CP(color_set);
_CP(clip_set);
_CP(clip_unset);
_CP(calculate);
_CP(member_add);
_CP(member_del);
#undef _CP
sc->parent = parent_sc;
off = sizeof(Evas_Smart_Class);
if (parent_sc_size == off) return 1;
memcpy(((char *)sc) + off, ((char *)parent_sc) + off, parent_sc_size - off);
return 1;
}
/**
* @}
*/
@ -196,3 +312,122 @@ evas_object_smart_unuse(Evas_Smart *s)
s->usage--;
if ((s->usage <= 0) && (s->delete_me)) evas_smart_free(s);
}
Eina_Bool
evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size)
{
void *tmp;
if (size == a->size)
return 1;
if (size == 0)
{
free(a->array);
a->array = NULL;
a->size = 0;
return 1;
}
tmp = realloc(a->array, (size + 1) * sizeof(Evas_Smart_Cb_Description *));
if (tmp)
{
a->array = tmp;
a->size = size;
a->array[size] = NULL;
return 1;
}
else
{
fprintf(stderr, "ERROR: realloc failed!\n");
return 0;
}
}
static int
_evas_smart_cb_description_cmp_sort(const void *p1, const void *p2)
{
const Evas_Smart_Cb_Description * const*a = p1, * const*b = p2;
return strcmp((*a)->name, (*b)->name);
}
void
evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a)
{
unsigned int i, j;
qsort(a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
_evas_smart_cb_description_cmp_sort);
fprintf(stderr, "\nDEBUG: %u callbacks\n", a->size);
if (a->size)
fprintf(stderr, "DEBUG: %20.20s [%s]\n", a->array[0]->name, a->array[1]->type);
for (i = 0, j = 1; j < a->size; j++)
{
const Evas_Smart_Cb_Description *cur, *prev;
cur = a->array[j];
prev = a->array[i];
fprintf(stderr, "DEBUG: %20.20s [%s]\n", cur->name, cur->type);
if (strcmp(cur->name, prev->name) != 0)
{
i++;
if (i != j)
a->array[i] = a->array[j];
}
else
{
if (strcmp(cur->type, prev->type) == 0)
fprintf(stderr, "WARNING: duplicated smart callback description name '%s', type '%s'\n", cur->name, cur->type);
else
fprintf(stderr, "ERROR: callback description named '%s' differ, keep '%s', ignore '%s'\n", cur->name, prev->type, cur->type);
}
}
evas_smart_cb_descriptions_resize(a, a->size - (j - i));
}
static void
_evas_smart_class_callbacks_create(Evas_Smart *s)
{
const Evas_Smart_Class *sc;
unsigned int n = 0;
for (sc = s->smart_class; sc != NULL; sc = sc->parent)
{
const Evas_Smart_Cb_Description *d;
for (d = sc->callbacks; d && d->name != NULL; d++)
n++;
}
if (n == 0) return;
if (!evas_smart_cb_descriptions_resize(&s->callbacks, n)) return;
for (n = 0, sc = s->smart_class; sc != NULL; sc = sc->parent)
{
const Evas_Smart_Cb_Description *d;
for (d = sc->callbacks; d->name != NULL; d++)
s->callbacks.array[n++] = d;
}
evas_smart_cb_descriptions_fix(&s->callbacks);
}
static int
_evas_smart_cb_description_cmp_search(const void *p1, const void *p2)
{
const char *name = p1;
const Evas_Smart_Cb_Description * const*v = p2;
/* speed up string shares searches (same pointers) */
if (name == (*v)->name) return 0;
return strcmp(name, (*v)->name);
}
const Evas_Smart_Cb_Description *
evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name)
{
if (!a->array) return NULL;
return bsearch(name, a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
_evas_smart_cb_description_cmp_search);
}

View File

@ -49,6 +49,7 @@ typedef struct _Evas_Key_Grab Evas_Key_Grab;
typedef struct _Evas_Callbacks Evas_Callbacks;
typedef struct _Evas_Format Evas_Format;
typedef struct _Evas_Map_Point Evas_Map_Point;
typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array;
#define MAGIC_EVAS 0x70777770
#define MAGIC_OBJ 0x71777770
@ -173,6 +174,12 @@ struct _Evas_Intercept_Func
Evas_Intercept_Func_Basic clip_unset;
};
struct _Evas_Smart_Cb_Description_Array
{
unsigned int size;
const Evas_Smart_Cb_Description **array;
};
struct _Evas_Smart
{
DATA32 magic;
@ -181,6 +188,8 @@ struct _Evas_Smart
const Evas_Smart_Class *smart_class;
Evas_Smart_Cb_Description_Array callbacks;
unsigned char delete_me : 1;
unsigned char class_allocated : 1;
@ -761,6 +770,10 @@ void evas_debug_generic(const char *str);
const char *evas_debug_magic_string_get(DATA32 magic);
void evas_object_smart_use(Evas_Smart *s);
void evas_object_smart_unuse(Evas_Smart *s);
void evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a) EINA_ARG_NONNULL(1);
Eina_Bool evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size) EINA_ARG_NONNULL(1);
const Evas_Smart_Cb_Description *evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name) EINA_ARG_NONNULL(1, 2) EINA_PURE;
void evas_object_smart_del(Evas_Object *obj);
void evas_object_smart_cleanup(Evas_Object *obj);
void evas_object_smart_member_raise(Evas_Object *member);