diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index 364bac41d6..2cbc5a13d2 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -47,9 +47,7 @@ ecore_eolian_files_public = \ lib/ecore/efl_model_container.eo \ lib/ecore/efl_model_container_item.eo \ lib/ecore/efl_model_composite_boolean.eo \ - lib/ecore/efl_model_composite_boolean_children.eo \ lib/ecore/efl_model_composite_selection.eo \ - lib/ecore/efl_model_composite_selection_children.eo \ lib/ecore/efl_model_composite.eo \ lib/ecore/efl_model_view.eo diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index f8d8626848..d0a6bc0b9f 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -115,9 +115,7 @@ EAPI Eo *efl_main_loop_get(void); #include "efl_model_container_item.eo.h" #include "efl_model_composite.eo.h" #include "efl_model_composite_boolean.eo.h" -#include "efl_model_composite_boolean_children.eo.h" #include "efl_model_composite_selection.eo.h" -#include "efl_model_composite_selection_children.eo.h" #include "efl_model_view.eo.h" /** diff --git a/src/lib/ecore/efl_model_composite.c b/src/lib/ecore/efl_model_composite.c index 2803675b36..9beb6ac3fd 100644 --- a/src/lib/ecore/efl_model_composite.c +++ b/src/lib/ecore/efl_model_composite.c @@ -10,11 +10,18 @@ #include "efl_model_composite.eo.h" +#define _CHILD_INDEX "child.index" + typedef struct _Efl_Model_Composite_Data Efl_Model_Composite_Data; struct _Efl_Model_Composite_Data { Efl_Model *source; + + unsigned int index; + + Eina_Bool need_index : 1; + Eina_Bool set_index : 1; }; static void @@ -46,9 +53,40 @@ _efl_model_composite_efl_object_finalize(Eo *obj, Efl_Model_Composite_Data *pd) return obj; } +static void +_efl_model_composite_index_set(Eo *obj EINA_UNUSED, Efl_Model_Composite_Data *pd, unsigned int index) +{ + if (pd->set_index || !pd->source) + return ; + pd->index = index; + pd->set_index = EINA_TRUE; +} + +static unsigned int +_efl_model_composite_index_get(const Eo *obj, Efl_Model_Composite_Data *pd) +{ + Eina_Value *fetch = NULL; + unsigned int r = 0xFFFFFFFF; + + if (pd->set_index) + return pd->index; + if (pd->need_index) + return 0xFFFFFFFF; + + fetch = efl_model_property_get(obj, _CHILD_INDEX); + if (!eina_value_uint_convert(fetch, &r)) + return 0xFFFFFFFF; + eina_value_free(fetch); + + return r; +} + static void _efl_model_composite_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Model_Composite_Data *pd, Efl_Model *model) { + Eina_Iterator *properties; + const char *property; + if (pd->source != NULL) { ERR("Source already set for composite model. It can only be set once."); @@ -60,6 +98,19 @@ _efl_model_composite_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Model_Compos efl_event_callback_forwarder_priority_add(model, EFL_MODEL_EVENT_CHILD_REMOVED, EFL_CALLBACK_PRIORITY_BEFORE, obj); efl_event_callback_forwarder_priority_add(model, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, obj); efl_event_callback_forwarder_priority_add(model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, obj); + + pd->need_index = EINA_TRUE; + + properties = efl_model_properties_get(pd->source); + EINA_ITERATOR_FOREACH(properties, property) + { + if (!strcmp(property, _CHILD_INDEX)) + { + pd->need_index = EINA_FALSE; + break; + } + } + eina_iterator_free(properties); } static Efl_Model * @@ -69,9 +120,18 @@ _efl_model_composite_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Model_ } static Eina_Future * -_efl_model_composite_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Composite_Data *pd, +_efl_model_composite_efl_model_property_set(Eo *obj, Efl_Model_Composite_Data *pd, const char *property, Eina_Value *value) { + if (pd->need_index && !strcmp(property, _CHILD_INDEX)) + { + if (pd->set_index || !pd->source) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_READ_ONLY); + if (!eina_value_uint_convert(value, &pd->index)) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_UNKNOWN); + pd->set_index = EINA_TRUE; + return efl_loop_future_resolved(obj, eina_value_uint_init(pd->index)); + } return efl_model_property_set(pd->source, property, value); } @@ -79,12 +139,27 @@ static Eina_Value * _efl_model_composite_efl_model_property_get(const Eo *obj EINA_UNUSED, Efl_Model_Composite_Data *pd, const char *property) { + if (pd->need_index && !strcmp(property, _CHILD_INDEX)) + { + if (pd->set_index) + return eina_value_uint_new(pd->index); + return eina_value_error_new(EAGAIN); + } return efl_model_property_get(pd->source, property); } static Eina_Iterator * _efl_model_composite_efl_model_properties_get(const Eo *obj EINA_UNUSED, Efl_Model_Composite_Data *pd) { + if (pd->need_index) + { + static const char *composite_properties[] = { + _CHILD_INDEX + }; + + return eina_multi_iterator_new(efl_model_properties_get(pd->source), + EINA_C_ARRAY_ITERATOR_NEW(composite_properties)); + } return efl_model_properties_get(pd->source); } @@ -94,13 +169,72 @@ _efl_model_composite_efl_model_children_count_get(const Eo *obj EINA_UNUSED, Efl return efl_model_children_count_get(pd->source); } +typedef struct _Efl_Model_Composite_Slice_Request Efl_Model_Composite_Slice_Request; +struct _Efl_Model_Composite_Slice_Request +{ + const Efl_Class *self; + Eo *parent; + unsigned int start; +}; + +static Eina_Value +_efl_model_composite_then(Eo *o EINA_UNUSED, void *data, const Eina_Value v) +{ + Efl_Model_Composite_Slice_Request *req = data; + unsigned int i, len; + Eina_Value r = EINA_VALUE_EMPTY; + Eo *target = NULL; + + eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4); + + EINA_VALUE_ARRAY_FOREACH(&v, len, i, target) + { + Eo *composite; + + // First set the Model to be used as a source so that we the newly object + // can know if it needs to retain the information regarding its index. + composite = efl_add(req->self, req->parent, + efl_ui_view_model_set(efl_added, target), + efl_model_composite_index_set(efl_added, req->start + i)); + + eina_value_array_append(&r, composite); + } + + return r; +} + +static void +_efl_model_composite_clean(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED) +{ + Efl_Model_Composite_Slice_Request *req = data; + + efl_unref(req->parent); + free(data); +} + static Eina_Future * -_efl_model_composite_efl_model_children_slice_get(Eo *obj EINA_UNUSED, +_efl_model_composite_efl_model_children_slice_get(Eo *obj, Efl_Model_Composite_Data *pd, unsigned int start, unsigned int count) { - return efl_model_children_slice_get(pd->source, start, count); + Efl_Model_Composite_Slice_Request *req; + Eina_Future *f; + + f = efl_model_children_slice_get(pd->source, start, count); + if (!f) return NULL; + + req = malloc(sizeof (Efl_Model_Composite_Slice_Request)); + if (!req) return efl_loop_future_rejected(obj, ENOMEM); + + req->self = efl_class_get(obj); + req->parent = efl_ref(obj); + req->start = start; + + return efl_future_then(obj, f, .success_type = EINA_VALUE_TYPE_ARRAY, + .success = _efl_model_composite_then, + .free = _efl_model_composite_clean, + .data = req); } static Efl_Object * diff --git a/src/lib/ecore/efl_model_composite.eo b/src/lib/ecore/efl_model_composite.eo index d353a2e9f4..a1baad1b99 100644 --- a/src/lib/ecore/efl_model_composite.eo +++ b/src/lib/ecore/efl_model_composite.eo @@ -1,6 +1,24 @@ class Efl.Model_Composite extends Efl.Model_Loop implements Efl.Ui.View { - [[Efl model for all composite class which provide a unified API to set source of data]] + [[Efl model for all composite class which provide a unified API to set source of data. + + This class also provide an @Efl.Model.property "$child.index" that match the value of @.index.]] + methods { + @property index { + [[Position of this object in the parent model.]] + set { + [[Set the index. It can only be set before the object is finalized, + but after the Model it compose is set and only if that Model does + not provide an index already.]] + } + get { + [[Get the index. It will only work after the object has been finalized.]] + } + values { + index: uint; [[Index of the object in the parent model. The index is uniq and start from zero.]] + } + } + } implements { Efl.Object.destructor; Efl.Object.finalize; @@ -12,4 +30,7 @@ class Efl.Model_Composite extends Efl.Model_Loop implements Efl.Ui.View Efl.Model.child_add; Efl.Model.child_del; } + constructors { + .index; + } } diff --git a/src/lib/ecore/efl_model_composite_boolean.c b/src/lib/ecore/efl_model_composite_boolean.c index 2db0bc768e..5cfa96150a 100644 --- a/src/lib/ecore/efl_model_composite_boolean.c +++ b/src/lib/ecore/efl_model_composite_boolean.c @@ -4,15 +4,14 @@ #include -#include "efl_model_composite_boolean_children.eo.h" #include "efl_model_composite_private.h" typedef struct _Efl_Model_Composite_Boolean_Data Efl_Model_Composite_Boolean_Data; -typedef struct _Efl_Model_Composite_Boolean_Children_Data Efl_Model_Composite_Boolean_Children_Data; typedef struct _Efl_Model_Composite_Boolean_Value Efl_Model_Composite_Boolean_Value; struct _Efl_Model_Composite_Boolean_Data { + Efl_Model_Composite_Boolean_Data *parent; Eina_Hash *values; }; @@ -29,127 +28,92 @@ struct _Efl_Model_Composite_Boolean_Value Eina_Bool default_value; }; -struct _Efl_Model_Composite_Boolean_Children_Data -{ - Efl_Model_Composite_Boolean_Data *parent; - unsigned int index; -}; - -/**************** efl_mmodel_composite_boolean_children **************/ - -static void -_efl_model_composite_boolean_children_index_set(Eo *obj EINA_UNUSED, - Efl_Model_Composite_Boolean_Children_Data *pd, - unsigned int index) -{ - if (pd->parent) // This is set during finalize - return ; - - pd->index = index; -} - -static unsigned int -_efl_model_composite_boolean_children_index_get(const Eo *obj EINA_UNUSED, - Efl_Model_Composite_Boolean_Children_Data *pd) -{ - return pd->index; -} - -static Efl_Object * -_efl_model_composite_boolean_children_efl_object_finalize(Eo *obj, - Efl_Model_Composite_Boolean_Children_Data *pd) -{ - Eo *parent; - - parent = efl_parent_get(obj); - if (!parent) return NULL; - pd->parent = efl_data_scope_get(parent, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS); - - return obj; -} - static Eina_Iterator * -_efl_model_composite_boolean_children_efl_model_properties_get(const Eo *obj, - Efl_Model_Composite_Boolean_Children_Data *pd) +_efl_model_composite_boolean_efl_model_properties_get(const Eo *obj, + Efl_Model_Composite_Boolean_Data *pd) { EFL_MODEL_COMPOSITE_PROPERTIES_SUPER(props, - obj, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, - eina_hash_iterator_key_new(pd->parent->values), - "child.index"); + obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS, + eina_hash_iterator_key_new(pd->parent->values)); return props; } static Eina_Value * -_efl_model_composite_boolean_children_efl_model_property_get(const Eo *obj, - Efl_Model_Composite_Boolean_Children_Data *pd, - const char *property) +_efl_model_composite_boolean_efl_model_property_get(const Eo *obj, + Efl_Model_Composite_Boolean_Data *pd, + const char *property) { Efl_Model_Composite_Boolean_Value *v; Eina_Stringshare *s; Eina_Bool flag; + unsigned int index; if (property == NULL) return NULL; - if (strcmp(property, "child.index") == 0) - return eina_value_uint_new(pd->index); + // If we do not have a parent set that his a COMPOSITE_BOOLEAN, then we should just forward up the call + if (!pd->parent) + return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), property); + + // Check if this is requesting a defined boolean property + // Property are defined and their value are stored on the parent COMPOSITE_BOOLEAN s = eina_stringshare_add(property); v = eina_hash_find(pd->parent->values, s); eina_stringshare_del(s); - if (!v) - return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS), - property); + if (!v) // Not a property handle by this object, forward + return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), property); + + index = efl_model_composite_index_get(obj); // As an optimization we do optimistically allocate the boolean array // Better would be to have a sparse boolean array - if ((pd->index >> 3) >= v->buffer_count) + if ((index >> 3) >= v->buffer_count) flag = v->default_value; else - flag = v->buffer[pd->index >> 3] & (((unsigned char)1) << (pd->index & 0x7)); + flag = v->buffer[index >> 3] & (((unsigned char)1) << (index & 0x7)); return eina_value_bool_new(!!flag); } static Eina_Future * -_efl_model_composite_boolean_children_efl_model_property_set(Eo *obj, - Efl_Model_Composite_Boolean_Children_Data *pd, - const char *property, Eina_Value *value) +_efl_model_composite_boolean_efl_model_property_set(Eo *obj, + Efl_Model_Composite_Boolean_Data *pd, + const char *property, Eina_Value *value) { Efl_Model_Composite_Boolean_Value *v; Eina_Stringshare *s; - Eina_Value b = EINA_VALUE_EMPTY; Eina_Bool flag; + unsigned int index; if (!property) return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_UNKNOWN); - if (strcmp(property, "child.index") == 0) - return efl_loop_future_rejected(obj, - EFL_MODEL_ERROR_READ_ONLY); + // If we do not have a parent set that his a COMPOSITE_BOOLEAN, then we should just forward up the call + if (!pd->parent) + return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), + property, value); + + // Check if this is requesting a defined boolean property + // Property are defined and their value are stored on the parent COMPOSITE_BOOLEAN s = eina_stringshare_add(property); v = eina_hash_find(pd->parent->values, s); eina_stringshare_del(s); if (!v) - return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS), + return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), property, value); - eina_value_setup(&b, EINA_VALUE_TYPE_BOOL); - if (!eina_value_convert(value, &b)) - return efl_loop_future_rejected(obj, - EFL_MODEL_ERROR_UNKNOWN); - if (!eina_value_get(value, &flag)) - return efl_loop_future_rejected(obj, - EFL_MODEL_ERROR_UNKNOWN); + if (!eina_value_bool_convert(value, &flag)) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_UNKNOWN); - eina_value_flush(&b); + index = efl_model_composite_index_get(obj); // We are optimistically allocating the boolean buffer now. // Aligning it on 64bits - if (v->buffer_count < (((pd->index) >> 3) | 0x7) + 1) + if (v->buffer_count < (((index) >> 3) | 0x7) + 1) { - unsigned int rcount = (((pd->index | 0xF) >> 3) | 0x7) + 1; + unsigned int rcount = (((index | 0xF) >> 3) | 0x7) + 1; unsigned char *tmp; tmp = realloc(v->buffer, rcount); @@ -161,9 +125,9 @@ _efl_model_composite_boolean_children_efl_model_property_set(Eo *obj, // It is assumed that during slice get the buffer is properly sized if (flag) - v->buffer[pd->index >> 3] |= ((unsigned char)1) << (pd->index & 0x7); + v->buffer[index >> 3] |= ((unsigned char)1) << (index & 0x7); else - v->buffer[pd->index >> 3] &= ~(((unsigned char)1) << (pd->index & 0x7)); + v->buffer[index >> 3] &= ~(((unsigned char)1) << (index & 0x7)); // Calling "properties,changed" event efl_model_properties_changed(obj, property); @@ -172,49 +136,6 @@ _efl_model_composite_boolean_children_efl_model_property_set(Eo *obj, return efl_loop_future_resolved(obj, eina_value_bool_init(!!flag)); } -/**************** efl_model_composite_boolean **************/ -typedef struct _Efl_Model_Slice_Request Efl_Model_Slice_Request; -struct _Efl_Model_Slice_Request -{ - Eo *parent; - unsigned int start; -}; - -static Eina_Value -_efl_model_composite_boolean_then(Eo *o EINA_UNUSED, void *data, const Eina_Value v) -{ - Efl_Model_Slice_Request *req = data; - unsigned int i, len; - Eina_Value r = EINA_VALUE_EMPTY; - Eo *target = NULL; - - eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4); - - EINA_VALUE_ARRAY_FOREACH(&v, len, i, target) - { - Eo *composite; - - // It would have been nice if I could have just overriden the object - // function, but this would allow only one composite model - composite = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, req->parent, - efl_model_composite_boolean_children_index_set(efl_added, req->start + i), - efl_ui_view_model_set(efl_added, target)); - - eina_value_array_append(&r, composite); - } - - return r; -} - -static void -_efl_model_composite_boolean_clean(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED) -{ - Efl_Model_Slice_Request *req = data; - - efl_unref(req->parent); - free(req); -} - static void _boolean_value_free(void *data) { @@ -233,11 +154,17 @@ _boolean_value_free(void *data) static Eo * _efl_model_composite_boolean_efl_object_constructor(Eo *obj, Efl_Model_Composite_Boolean_Data *pd) { + Eo *parent; obj = efl_constructor(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS)); if (!obj) return NULL; pd->values = eina_hash_stringshared_new(_boolean_value_free); + // Only add a reference to the parent if it is actually a COMPOSITE_BOOLEAN_CLASS + // The root typically doesn't have any boolean property, only its child do + parent = efl_parent_get(obj); + if (efl_isa(parent, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS)) + pd->parent = efl_data_scope_get(parent, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS); return obj; } @@ -280,28 +207,4 @@ _efl_model_composite_boolean_boolean_del(Eo *obj EINA_UNUSED, eina_stringshare_del(s); } -static Eina_Future * -_efl_model_composite_boolean_efl_model_children_slice_get(Eo *obj, - Efl_Model_Composite_Boolean_Data *pd EINA_UNUSED, - unsigned int start, unsigned int count) -{ - Efl_Model_Slice_Request *req; - Eina_Future *f; - - f = efl_model_children_slice_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), - start, count); - - req = malloc(sizeof (Efl_Model_Slice_Request)); - if (!req) return efl_loop_future_rejected(obj, - ENOMEM); - req->parent = efl_ref(obj); - req->start = start; - - return efl_future_then(obj, f, .success_type = EINA_VALUE_TYPE_ARRAY, - .success = _efl_model_composite_boolean_then, - .free = _efl_model_composite_boolean_clean, - .data = req); -} - #include "efl_model_composite_boolean.eo.c" -#include "efl_model_composite_boolean_children.eo.c" diff --git a/src/lib/ecore/efl_model_composite_boolean.eo b/src/lib/ecore/efl_model_composite_boolean.eo index 47c7e3cfb6..8bbc664b52 100644 --- a/src/lib/ecore/efl_model_composite_boolean.eo +++ b/src/lib/ecore/efl_model_composite_boolean.eo @@ -17,8 +17,9 @@ class Efl.Model_Composite_Boolean extends Efl.Model_Composite } } implements { + Efl.Model.properties { get; } + Efl.Model.property { get; set; } Efl.Object.constructor; Efl.Object.destructor; - Efl.Model.children_slice_get; } } diff --git a/src/lib/ecore/efl_model_composite_boolean_children.eo b/src/lib/ecore/efl_model_composite_boolean_children.eo deleted file mode 100644 index d06a9cc424..0000000000 --- a/src/lib/ecore/efl_model_composite_boolean_children.eo +++ /dev/null @@ -1,23 +0,0 @@ -class Efl.Model_Composite_Boolean_Children extends Efl.Model_Composite -{ - [[Efl model composite boolean children class]] - methods { - @property index { - [[Position of children in the parent model.]] - set { - [[Set the index. It can only be set before the object is finalized.]] - } - get { - [[Get the index.]] - } - values { - index: uint; [[The index of the child in the parent model.]] - } - } - } - implements { - Efl.Model.properties { get; } - Efl.Model.property { get; set; } - Efl.Object.finalize; - } -} diff --git a/src/lib/ecore/efl_model_composite_selection.c b/src/lib/ecore/efl_model_composite_selection.c index 18db24cfc3..3bcd7b4829 100644 --- a/src/lib/ecore/efl_model_composite_selection.c +++ b/src/lib/ecore/efl_model_composite_selection.c @@ -12,30 +12,32 @@ #include "efl_model_composite_private.h" typedef struct _Efl_Model_Composite_Selection_Data Efl_Model_Composite_Selection_Data; -typedef struct _Efl_Model_Composite_Selection_Children_Data Efl_Model_Composite_Selection_Children_Data; struct _Efl_Model_Composite_Selection_Data { + Efl_Model_Composite_Selection_Data *parent; unsigned long last; Eina_Bool exclusive : 1; Eina_Bool none : 1; }; -struct _Efl_Model_Composite_Selection_Children_Data -{ -}; - static Eo* _efl_model_composite_selection_efl_object_constructor(Eo *obj, - Efl_Model_Composite_Selection_Data *pd EINA_UNUSED) + Efl_Model_Composite_Selection_Data *pd) { + Eo *parent; + obj = efl_constructor(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS)); efl_model_composite_boolean_add(obj, "selected", EINA_FALSE); pd->last = -1; + parent = efl_parent_get(obj); + if (efl_isa(parent, EFL_MODEL_COMPOSITE_SELECTION_CLASS)) + pd->parent = efl_data_scope_get(parent, EFL_MODEL_COMPOSITE_SELECTION_CLASS); + return obj; } @@ -43,14 +45,12 @@ static Eina_Value _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) { Efl_Model_Composite_Selection_Data *pd; - Eina_Value *vc = NULL; Eina_Value *selected = NULL; Eina_Bool selflag = EINA_FALSE; if (v.type == EINA_VALUE_TYPE_ERROR) goto on_error; - vc = efl_model_property_get(child, "Child.index"); selected = efl_model_property_get(child, "selected"); pd = efl_data_scope_get(efl_parent_get(child), EFL_MODEL_COMPOSITE_SELECTION_CLASS); @@ -61,7 +61,7 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) { // select case pd->none = EINA_FALSE; - eina_value_ulong_get(vc, &pd->last); + pd->last = efl_model_composite_index_get(child); efl_event_callback_call(child, EFL_MODEL_COMPOSITE_SELECTION_EVENT_SELECTED, child); } else @@ -69,7 +69,7 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) // unselect case unsigned long last; - eina_value_ulong_get(vc, &last); + last = efl_model_composite_index_get(child); if (pd->last == last) { pd->last = 0; @@ -79,7 +79,6 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) } on_error: - eina_value_free(vc); eina_value_free(selected); return v; } @@ -180,78 +179,6 @@ _unselect_slice_then(Eo *obj EINA_UNUSED, return v; } -static Eina_Iterator * -_efl_model_composite_selection_efl_model_properties_get(const Eo *obj, - Efl_Model_Composite_Selection_Data *pd EINA_UNUSED) -{ - EFL_MODEL_COMPOSITE_PROPERTIES_SUPER(props, - obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS, - NULL, - "selected", "exclusive"); - return props; -} - -static Eina_Future * -_efl_model_composite_selection_efl_model_property_set(Eo *obj, - Efl_Model_Composite_Selection_Data *pd, - const char *property, Eina_Value *value) -{ - Eina_Value vf = EINA_VALUE_EMPTY; - - if (!strcmp("exclusive", property)) - { - Eina_Bool exclusive = pd->exclusive; - Eina_Bool changed; - - vf = eina_value_bool_init(exclusive); - eina_value_convert(value, &vf); - eina_value_bool_get(&vf, &exclusive); - - changed = (!pd->exclusive != !exclusive); - pd->exclusive = !!exclusive; - - if (changed) efl_model_properties_changed(obj, "exclusive"); - - return efl_loop_future_resolved(obj, vf); - } - - if (!strcmp("selected", property)) - { - Eina_Value vl = EINA_VALUE_EMPTY; - unsigned long l = 0; - Eina_Bool success = EINA_TRUE; - - vl = eina_value_ulong_init(0); - success &= eina_value_convert(value, &vl); - success &= eina_value_ulong_get(&vl, &l); - if (!success) - return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); - - return efl_future_then(obj, efl_model_children_slice_get(obj, l, 1), - .success = _select_slice_then, - .success_type = EINA_VALUE_TYPE_ARRAY); - } - - return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), - property, value); -} - -static Eina_Value * -_efl_model_composite_selection_efl_model_property_get(const Eo *obj, Efl_Model_Composite_Selection_Data *pd, const char *property) -{ - if (!strcmp("exclusive", property)) - return eina_value_bool_new(pd->exclusive); - if (!strcmp("selected", property)) - { - if (pd->none) - return eina_value_error_new(EFL_MODEL_ERROR_INCORRECT_VALUE); - else - return eina_value_ulong_new(pd->last); - } - - return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), property); -} - static Eina_Value _regenerate_error(void *data, const Eina_Value v, @@ -282,17 +209,6 @@ _untangle_array(void *data EINA_UNUSED, return va; } -static Eina_Iterator * -_efl_model_composite_selection_children_efl_model_properties_get(const Eo *obj, - Efl_Model_Composite_Selection_Children_Data *pd EINA_UNUSED) -{ - EFL_MODEL_COMPOSITE_PROPERTIES_SUPER(props, - obj, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS, - NULL, - "selected"); - return props; -} - static Eina_Value _untangle_error(void *data, Eina_Error err) { @@ -304,7 +220,7 @@ _untangle_error(void *data, Eina_Error err) // where we could end up here. Eina_Error *error = calloc(1, sizeof (Eina_Error)); - f = efl_model_property_set(efl_super(child, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS), + f = efl_model_property_set(efl_super(child, EFL_MODEL_COMPOSITE_SELECTION_CLASS), "selected", eina_value_bool_new(EINA_FALSE)); // Once this is done, we need to repropagate the error *error = err; @@ -313,178 +229,141 @@ _untangle_error(void *data, Eina_Error err) return eina_future_as_value(f); } -static Eina_Future * -_efl_model_composite_selection_children_efl_model_property_set(Eo *obj, - Efl_Model_Composite_Selection_Children_Data *pd EINA_UNUSED, - const char *property, Eina_Value *value) +static Eina_Iterator * +_efl_model_composite_selection_efl_model_properties_get(const Eo *obj, + Efl_Model_Composite_Selection_Data *pd EINA_UNUSED) { - Eina_Value *ve = NULL; - Eina_Value *vb = NULL; - Eina_Value lvb = EINA_VALUE_EMPTY; - Eina_Bool success = EINA_TRUE; - Eina_Bool exclusive = EINA_FALSE; - Eina_Bool prevflag = EINA_FALSE, newflag = EINA_FALSE; - Eina_Future *chain; + EFL_MODEL_COMPOSITE_PROPERTIES_SUPER(props, + obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS, + NULL, + "self.selected", "child.selected", "exclusive"); + return props; +} - if (strcmp("selected", property)) - return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS), - property, value); +static Eina_Future * +_efl_model_composite_selection_efl_model_property_set(Eo *obj, + Efl_Model_Composite_Selection_Data *pd, + const char *property, Eina_Value *value) +{ + Eina_Value vf = EINA_VALUE_EMPTY; - vb = efl_model_property_get(obj, "selected"); - success &= eina_value_bool_get(vb, &prevflag); - eina_value_free(vb); - - lvb = eina_value_bool_init(prevflag); - success &= eina_value_convert(value, &lvb); - success &= eina_value_bool_get(&lvb, &newflag); - eina_value_flush(&lvb); - - if (!success) - return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); - - // Nothing changed - if (newflag == prevflag) - return efl_loop_future_resolved(obj, - eina_value_bool_init(newflag)); - - ve = efl_model_property_get(efl_parent_get(obj), "exclusive"); - eina_value_bool_get(ve, &exclusive); - eina_value_free(ve); - - // First store the new value in the boolean model we inherit from - chain = efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS), - "selected", value); - - // Now act ! - if (exclusive) + if (!strcmp("exclusive", property)) { - // We are here either, because we weren't and are after this call - // or because we were selected and are not anymore. In the later case, - // there is nothing special to do, just normal commit change will do. - if (!newflag) + Eina_Bool exclusive = pd->exclusive; + Eina_Bool changed; + + vf = eina_value_bool_init(exclusive); + eina_value_convert(value, &vf); + eina_value_bool_get(&vf, &exclusive); + + changed = (!pd->exclusive != !exclusive); + pd->exclusive = !!exclusive; + + if (changed) efl_model_properties_changed(obj, "exclusive"); + + return efl_loop_future_resolved(obj, vf); + } + + if (!strcmp("child.selected", property)) + { + unsigned long l = 0; + + if (!eina_value_ulong_convert(value, &l)) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); + + return efl_future_then(obj, efl_model_children_slice_get(obj, l, 1), + .success = _select_slice_then, + .success_type = EINA_VALUE_TYPE_ARRAY); + } + + if (pd->parent && !strcmp("self.selected", property)) + { + Eina_Bool prevflag = EINA_FALSE, newflag = EINA_FALSE; + Eina_Bool exclusive = EINA_FALSE; + Eina_Bool success; + Eina_Value *prev; + Eina_Future *chain; + + prev = efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), "selected"); + success = eina_value_bool_get(prev, &prevflag); + success &= eina_value_bool_convert(value, &newflag); + + if (!success) return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); + + // Nothing changed + if (newflag == prevflag) + return efl_loop_future_resolved(obj, eina_value_bool_init(newflag)); + + exclusive = pd->parent->exclusive; + + // First store the new value in the boolean model we inherit from + chain = efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), + "selected", value); + + // Now act ! + if (exclusive) { - Efl_Model_Composite_Selection_Data *ppd; - Eina_Value *index; - unsigned int i = 0; - - index = efl_model_property_get(obj, "child.index"); - if (!eina_value_uint_get(index, &i)) - goto commit_change; - - ppd = efl_data_scope_get(efl_parent_get(obj), EFL_MODEL_COMPOSITE_SELECTION_CLASS); - if (ppd->last == i && !newflag) - ppd->none = EINA_TRUE; - } - else - { - Eo *parent; - Eina_Value *vs; - unsigned long selected = 0; - - // In this case we need to first unselect the previously selected one - // and then commit the change to this one. - - // Fetch the one to unselect - vs = efl_model_property_get(efl_parent_get(obj), "selected"); - // Check if there was any selected - if (eina_value_type_get(vs) == EINA_VALUE_TYPE_ERROR) + // We are here either, because we weren't and are after this call + // or because we were selected and are not anymore. In the later case, + // there is nothing special to do, just normal commit change will do. + if (!newflag) { - eina_value_free(vs); - goto commit_change; + unsigned int i; + + i = efl_model_composite_index_get(obj); + if (pd->parent->last == i && !newflag) + pd->parent->none = EINA_TRUE; } - success = eina_value_ulong_get(vs, &selected); - eina_value_free(vs); + else + { + Eo *parent; + unsigned long selected = 0; - if (!success) - return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); + // In this case we need to first unselect the previously selected one + // and then commit the change to this one. + selected = pd->parent->last; - // There was, need to unselect the previous one along setting the new value - parent = efl_parent_get(obj); - chain = eina_future_all(chain, - efl_future_then(parent, efl_model_children_slice_get(parent, selected, 1), - .success = _unselect_slice_then, - .success_type = EINA_VALUE_TYPE_ARRAY)); - - chain = eina_future_then_easy(chain, - .success_type = EINA_VALUE_TYPE_ARRAY, - .success = _untangle_array, - .data = obj, - .error = _untangle_error); + // There was, need to unselect the previous one along setting the new value + parent = efl_parent_get(obj); + chain = eina_future_all(chain, + efl_future_then(parent, efl_model_children_slice_get(parent, selected, 1), + .success = _unselect_slice_then, + .success_type = EINA_VALUE_TYPE_ARRAY)); + chain = eina_future_then_easy(chain, + .success_type = EINA_VALUE_TYPE_ARRAY, + .success = _untangle_array, + .data = obj, + .error = _untangle_error); + } } + + return efl_future_then(obj, chain, .success = _commit_change); } - commit_change: - return efl_future_then(obj, chain, - .success = _commit_change); + return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), + property, value); } -typedef struct _Selection_Children_Request Selection_Children_Request; -struct _Selection_Children_Request +static Eina_Value * +_efl_model_composite_selection_efl_model_property_get(const Eo *obj, Efl_Model_Composite_Selection_Data *pd, const char *property) { - Efl_Model *parent; - - unsigned int start; -}; - -static Eina_Value -_slice_get(Eo *o EINA_UNUSED, - void *data, - const Eina_Value v) -{ - Selection_Children_Request *req = data; - unsigned int length, it; - Eo *composited = NULL; - Eina_Value r = EINA_VALUE_EMPTY; - - eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4); - - EINA_VALUE_ARRAY_FOREACH(&v, length, it, composited) + if (!strcmp("exclusive", property)) + return eina_value_bool_new(pd->exclusive); + // Last selected child + if (!strcmp("child.selected", property)) { - Eo *compositing; - - compositing = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS, req->parent, - efl_model_composite_boolean_children_index_set(efl_added, req->start + it), - efl_ui_view_model_set(efl_added, composited)); - eina_value_array_append(&r, compositing); + if (pd->none) + return eina_value_error_new(EFL_MODEL_ERROR_INCORRECT_VALUE); + else + return eina_value_ulong_new(pd->last); + } + // Redirect to are we ourself selected + if (pd->parent && !strcmp("self.selected", property)) + { + return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), "selected"); } - return r; -} - -static void -_slice_clean(Eo *o EINA_UNUSED, - void *data, - const Eina_Future *dead_future EINA_UNUSED) -{ - Selection_Children_Request *req = data; - - efl_unref(req->parent); - free(req); -} - -static Eina_Future * -_efl_model_composite_selection_efl_model_children_slice_get(Eo *obj, - Efl_Model_Composite_Selection_Data *pd EINA_UNUSED, - unsigned int start, unsigned int count) -{ - Selection_Children_Request *req; - Eina_Future *f; - - req = calloc(1, sizeof (Selection_Children_Request)); - if (!req) return efl_loop_future_rejected(obj, ENOMEM); - req->parent = efl_ref(obj); - req->start = start; - - // NOTE: We do jump on purpose EFL_MODEL_COMPOSITE_BOOLEAN_CLASS here - f = efl_model_children_slice_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS), - start, count); - - return efl_future_then(obj, f, - .success_type = EINA_VALUE_TYPE_ARRAY, - .success = _slice_get, - .free = _slice_clean, - .data = req); + return efl_model_property_get(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS), property); } #include "efl_model_composite_selection.eo.c" -#include "efl_model_composite_selection_children.eo.c" diff --git a/src/lib/ecore/efl_model_composite_selection.eo b/src/lib/ecore/efl_model_composite_selection.eo index 35ecc270af..699154a78b 100644 --- a/src/lib/ecore/efl_model_composite_selection.eo +++ b/src/lib/ecore/efl_model_composite_selection.eo @@ -3,7 +3,6 @@ class Efl.Model_Composite_Selection extends Efl.Model_Composite_Boolean [[Efl model composite selection class]] implements { Efl.Object.constructor; - Efl.Model.children_slice_get; Efl.Model.property { get; set; } Efl.Model.properties { get; } } diff --git a/src/lib/ecore/efl_model_composite_selection_children.eo b/src/lib/ecore/efl_model_composite_selection_children.eo deleted file mode 100644 index ce59ea2b16..0000000000 --- a/src/lib/ecore/efl_model_composite_selection_children.eo +++ /dev/null @@ -1,9 +0,0 @@ -class Efl.Model_Composite_Selection_Children extends Efl.Model_Composite_Boolean_Children -{ - [[Efl model composite selection children class]] - implements { - Efl.Model.property { set; } - Efl.Model.properties { get; } - } - /* FIXME: emitting Efl.Model_Composite_Selection.Selected. Use a default selection event! */ -} diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 6fc4b2c38f..537a16dbc6 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -72,9 +72,7 @@ pub_eo_files = [ 'efl_model_container.eo', 'efl_model_container_item.eo', 'efl_model_composite_boolean.eo', - 'efl_model_composite_boolean_children.eo', 'efl_model_composite_selection.eo', - 'efl_model_composite_selection_children.eo', 'efl_model_composite.eo', 'efl_model_view.eo' ] diff --git a/src/tests/efl/efl_test_model_composite.c b/src/tests/efl/efl_test_model_composite.c index 315c34ac5f..f48127acb4 100644 --- a/src/tests/efl/efl_test_model_composite.c +++ b/src/tests/efl/efl_test_model_composite.c @@ -80,17 +80,22 @@ _selection_children_slice_get_then(void *data EINA_UNUSED, { Eina_Value *p_int = NULL; Eina_Value *p_bool = NULL; + Eina_Value *p_index = NULL; int v_int = 0; + unsigned int index = 0; Eina_Bool v_bool = EINA_FALSE; p_bool = efl_model_property_get(child, "selected"); p_int = efl_model_property_get(child, "test_p_int"); + p_index = efl_model_property_get(child, "child.index"); eina_value_get(p_bool, &v_bool); eina_value_get(p_int, &v_int); + fail_if(!eina_value_uint_convert(p_index, &index)); fail_if(v_bool != base_selections[i]); fail_if(v_int != base_ints[i]); + ck_assert_int_eq(i, index); } ecore_main_loop_quit(); @@ -165,7 +170,7 @@ EFL_START_TEST(efl_test_model_composite_selection) model = efl_add_ref(EFL_MODEL_COMPOSITE_SELECTION_CLASS, efl_main_loop_get(), efl_ui_view_model_set(efl_added, base_model)); ck_assert(!!model); - future = efl_model_property_set(model, "selected", eina_value_int_new(2)); + future = efl_model_property_set(model, "child.selected", eina_value_int_new(2)); eina_future_then(future, _wait_propagate, NULL, NULL); ecore_main_loop_begin();