From df9f2e07722fa384cba09e934351e90f0d237009 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Thu, 7 Sep 2017 12:06:17 +0900 Subject: [PATCH] ecore: Add efl_model_copmosite_selection model --- src/Makefile_Ecore.am | 4 + src/Makefile_Efl.am | 2 +- src/lib/ecore/Ecore_Eo.h | 2 + src/lib/ecore/efl_model_accessor_view.c | 133 ++++++++++ .../ecore/efl_model_accessor_view_private.h | 5 + src/lib/ecore/efl_model_composite_boolean.c | 81 ++++-- src/lib/ecore/efl_model_composite_boolean.eo | 15 +- src/lib/ecore/efl_model_composite_selection.c | 237 ++++++++++++++++++ .../ecore/efl_model_composite_selection.eo | 21 ++ .../efl_model_composite_selection_children.eo | 7 + src/lib/ecore/efl_model_item.c | 2 +- ...e_boolean.c => efl_test_model_composite.c} | 111 +++++++- 12 files changed, 577 insertions(+), 43 deletions(-) create mode 100644 src/lib/ecore/efl_model_accessor_view.c create mode 100644 src/lib/ecore/efl_model_accessor_view_private.h create mode 100644 src/lib/ecore/efl_model_composite_selection.c create mode 100644 src/lib/ecore/efl_model_composite_selection.eo create mode 100644 src/lib/ecore/efl_model_composite_selection_children.eo rename src/tests/efl/{efl_test_model_composite_boolean.c => efl_test_model_composite.c} (56%) diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index 4158ae5185..755d4bb0f8 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -30,6 +30,8 @@ ecore_eolian_files = \ 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 \ $(ecore_eolian_files_legacy) ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c) @@ -90,6 +92,8 @@ lib/ecore/efl_model_container.c \ lib/ecore/efl_model_container_item.c \ lib/ecore/efl_model_container_private.h \ lib/ecore/efl_model_composite_boolean.c \ +lib/ecore/efl_model_composite_selection.c \ +lib/ecore/efl_model_accessor_view.c \ lib/ecore/ecore_pipe.c \ lib/ecore/ecore_poller.c \ lib/ecore/ecore_time.c \ diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am index 58601aabdd..25dde93a7c 100644 --- a/src/Makefile_Efl.am +++ b/src/Makefile_Efl.am @@ -193,7 +193,7 @@ TESTS += tests/efl/efl_suite tests_efl_efl_suite_SOURCES = \ tests/efl/efl_suite.c \ tests/efl/efl_test_model_container.c \ -tests/efl/efl_test_model_composite_boolean.c \ +tests/efl/efl_test_model_composite.c \ tests/efl/efl_suite.h tests_efl_efl_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index 502f6419ec..aadd2ba136 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -115,6 +115,8 @@ EAPI Efl_Future *efl_future_iterator_race(Eina_Iterator *it); #include "efl_model_container_item.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" /** * @} diff --git a/src/lib/ecore/efl_model_accessor_view.c b/src/lib/ecore/efl_model_accessor_view.c new file mode 100644 index 0000000000..2afe1dc8f3 --- /dev/null +++ b/src/lib/ecore/efl_model_accessor_view.c @@ -0,0 +1,133 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Eina.h" +#include "Eo.h" + +#include "efl_model_accessor_view_private.h" + +typedef struct _Efl_Model_Accessor +{ + Eina_Accessor vtable; + Eina_Accessor *real_accessor; + void *pdata; + Efl_Model_Accessor_View_Constructor_Cb cb; + Eina_Array *children; +} Efl_Model_Accessor; + +static void +_efl_model_accessor_setup(Efl_Model_Accessor *acc, + Eina_Accessor* real_accessor, + Efl_Model_Accessor_View_Constructor_Cb ctor, + void* pdata); + +static Eina_Bool +_efl_model_acessor_get_at(Efl_Model_Accessor *acc, unsigned int idx, void **data) +{ + void* eo; + Eo *p; + Eo *child; + + if(eina_accessor_data_get(acc->real_accessor, idx, &eo)) + { + p = eo; + child = acc->cb(acc->pdata, p); + if(!acc->children) + { + acc->children = eina_array_new(32); + } + eina_array_push(acc->children, child); + *data = child; + return !!*data; + } + else + return EINA_FALSE; +} + +static void * +_efl_model_acessor_get_container(Efl_Model_Accessor *acc) +{ + return eina_accessor_container_get(acc->real_accessor); +} + +static void +_efl_model_acessor_free(Efl_Model_Accessor *acc) +{ + if (acc->real_accessor) + { + eina_accessor_free(acc->real_accessor); + acc->real_accessor = NULL; + } + + if(acc->children) + { + unsigned i; + Eina_Array_Iterator iterator; + Eo* item; + + EINA_ARRAY_ITER_NEXT(acc->children, i, item, iterator) + { + efl_del(item); + } + eina_array_free(acc->children); + acc->children = NULL; + } + + free(acc); +} + +static Eina_Bool +_efl_model_acessor_lock(Efl_Model_Accessor *acc) +{ + return eina_accessor_lock(acc->real_accessor); +} + +static Eina_Bool +_efl_model_acessor_unlock(Efl_Model_Accessor *acc) +{ + return eina_accessor_unlock(acc->real_accessor); +} + +static Efl_Model_Accessor * +_efl_model_acessor_clone(Efl_Model_Accessor *acc EINA_UNUSED) +{ + Efl_Model_Accessor* accessor = calloc(1, sizeof(Efl_Model_Accessor)); + _efl_model_accessor_setup(accessor, eina_accessor_clone(acc->real_accessor), + acc->cb, acc->pdata); + return accessor; +} + +static void +_efl_model_accessor_setup(Efl_Model_Accessor *acc, + Eina_Accessor* real_accessor, + Efl_Model_Accessor_View_Constructor_Cb ctor, + void* pdata) +{ + acc->vtable.version = EINA_ACCESSOR_VERSION; + acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_model_acessor_get_at); + acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_model_acessor_get_container); + acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_model_acessor_free); + + acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_model_acessor_lock); + acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_model_acessor_unlock); + + acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_model_acessor_clone); + + EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR); + + acc->real_accessor = real_accessor; + acc->cb = ctor; + acc->pdata = pdata; +} + +Eina_Accessor* efl_model_accessor_view_new(Eina_Accessor* accessor, + Efl_Model_Accessor_View_Constructor_Cb ctor, + void* data) +{ + Efl_Model_Accessor* acc = calloc(1, sizeof(Efl_Model_Accessor)); + _efl_model_accessor_setup(acc, accessor, ctor, data); + return &acc->vtable; +} + + diff --git a/src/lib/ecore/efl_model_accessor_view_private.h b/src/lib/ecore/efl_model_accessor_view_private.h new file mode 100644 index 0000000000..c44f2ec3cb --- /dev/null +++ b/src/lib/ecore/efl_model_accessor_view_private.h @@ -0,0 +1,5 @@ + +typedef Eo*(*Efl_Model_Accessor_View_Constructor_Cb)(void* data, Eo* child); + +Eina_Accessor* efl_model_accessor_view_new(Eina_Accessor* accessor, + Efl_Model_Accessor_View_Constructor_Cb constructor, void* data); diff --git a/src/lib/ecore/efl_model_composite_boolean.c b/src/lib/ecore/efl_model_composite_boolean.c index 7ec344d05c..62107bbffc 100644 --- a/src/lib/ecore/efl_model_composite_boolean.c +++ b/src/lib/ecore/efl_model_composite_boolean.c @@ -18,7 +18,6 @@ typedef struct _Efl_Model_Hash_Value typedef struct _Efl_Model_Composite_Boolean_Data { Efl_Model *composite_model; - Eina_Array *bool_children_cache; Eina_Array *empty_properties; Eina_Hash *values; // [property_name, Efl_Model_Hash_Value*] } Efl_Model_Composite_Boolean_Data; @@ -39,8 +38,14 @@ typedef struct _Efl_Model_Accessor_Slice Efl_Model_Composite_Boolean_Data *parent_pd; Efl_Promise *promise; unsigned int index; + Eina_Array *bool_children_cache; } Efl_Model_Accessor_Slice; +static void +efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice *acc, + Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise *promise, int start); + + static Eina_Value * _value_clone(const Eina_Value *value) { @@ -66,7 +71,8 @@ _future_error_forward_cb(void *data, Efl_Event const *event) static Eina_Bool _bit_get(const unsigned char *bitstream, unsigned int idx) { - return (bitstream[idx / 8] >> (idx % 8)) & 1u; + Eina_Bool b = (bitstream[idx / 8] >> (idx % 8)) & 1u; + return b; } static void @@ -160,8 +166,8 @@ _efl_model_composite_boolean_children_efl_model_property_get(Eo *obj EINA_UNUSED Eina_Value *eina_value = eina_value_new(EINA_VALUE_TYPE_UCHAR); if (hv->bits_count <= pd->index) { - unsigned char f = hv->default_value; - eina_value_set(eina_value, f); + unsigned char f = hv->default_value; + eina_value_set(eina_value, f); } else { @@ -194,7 +200,7 @@ _efl_model_composite_boolean_children_efl_model_property_set(Eo *obj EINA_UNUSED { Eina_Bool flag = EINA_FALSE; - if (eina_value_type_get(value) == EINA_VALUE_TYPE_UCHAR) + if (eina_value_type_get(value) != EINA_VALUE_TYPE_UCHAR) { efl_promise_failed_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE); return rfuture; @@ -285,7 +291,7 @@ static Eina_Bool efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice *acc, unsigned int idx, void **data) { Efl_Model *child_bool; - Eina_Array *children_cache = acc->parent_pd->bool_children_cache; + Eina_Array *children_cache = acc->bool_children_cache; /* NOTE: Efl.Model.Composite.Boolean must alloc the cache with the correct size and NULL initialized. */ @@ -295,7 +301,7 @@ efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice *acc, unsigned int idx, return EINA_FALSE; } - child_bool = eina_array_data_get(children_cache, idx); + child_bool = eina_array_data_get(children_cache, acc->index + idx); if (!child_bool) { @@ -306,13 +312,13 @@ efl_model_acessor_slice_get_at(Efl_Model_Accessor_Slice *acc, unsigned int idx, if (child) { - Efl_Model_Composite_Boolean_Children_Data *pd; + Efl_Model_Composite_Boolean_Children_Data *cpd; child_bool = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, NULL); - pd = efl_data_scope_get(child_bool, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS); + cpd = efl_data_scope_get(child_bool, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS); - pd->parent_pd = acc->parent_pd; - pd->composite_child = efl_ref(child); - pd->index = acc->index++; + cpd->parent_pd = acc->parent_pd; + cpd->composite_child = efl_ref(child); + cpd->index = acc->index + idx; eina_array_data_set(children_cache, idx, child_bool); } @@ -331,9 +337,15 @@ efl_model_acessor_slice_get_container(Efl_Model_Accessor_Slice *acc) static void efl_model_acessor_slice_free(Efl_Model_Accessor_Slice *acc) { - if (acc->real_accessor) + if (acc->bool_children_cache) { - eina_accessor_free(acc->real_accessor); + _bool_children_cache_array_free(acc->bool_children_cache); + acc->bool_children_cache = NULL; + } + + if (acc->real_accessor) + { + /* eina_accessor_free(acc->real_accessor); */ acc->real_accessor = NULL; } @@ -364,12 +376,31 @@ efl_model_acessor_slice_unlock(Efl_Model_Accessor_Slice *acc) static Efl_Model_Accessor_Slice * efl_model_acessor_slice_clone(Efl_Model_Accessor_Slice *acc EINA_UNUSED) { - return NULL; + Efl_Model_Accessor_Slice* new_accessor = calloc(1, sizeof(Efl_Model_Accessor_Slice)); + Eina_Array* children_cache; + unsigned i; + unsigned children_count = eina_array_count(acc->bool_children_cache); + + efl_model_accessor_slice_setup(new_accessor, acc->parent, acc->parent_pd, NULL + , acc->index); + new_accessor->real_accessor = eina_accessor_clone(acc->real_accessor); + + children_cache = eina_array_new(children_count); + for (i = 0 ; i < children_count; ++i) + { + // NOTE: eina_array_push do not accept NULL + eina_array_push(children_cache, (void*)0x01); + eina_array_data_set(children_cache, i, NULL); + } + + new_accessor->bool_children_cache = children_cache; + + return new_accessor; } static void efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice *acc, - Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise *promise) + Efl_Model *parent, Efl_Model_Composite_Boolean_Data *parent_pd, Efl_Promise *promise, int start) { acc->vtable.version = EINA_ACCESSOR_VERSION; acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(efl_model_acessor_slice_get_at); @@ -386,6 +417,7 @@ efl_model_accessor_slice_setup(Efl_Model_Accessor_Slice *acc, acc->parent = efl_ref(parent); acc->parent_pd = parent_pd; acc->promise = promise; + acc->index = start; } static void @@ -413,8 +445,8 @@ _efl_model_composite_boolean_slice_then_cb(void *data, Efl_Event const *event) Eina_Array *children_cache; unsigned int i; - if (slice_acc->parent_pd->bool_children_cache) - _bool_children_cache_array_free(slice_acc->parent_pd->bool_children_cache); + if (slice_acc->bool_children_cache) + _bool_children_cache_array_free(slice_acc->bool_children_cache); children_cache = eina_array_new(*children_count); for (i = 0 ; i < *children_count; ++i) @@ -424,7 +456,7 @@ _efl_model_composite_boolean_slice_then_cb(void *data, Efl_Event const *event) eina_array_data_set(children_cache, i, NULL); } - slice_acc->parent_pd->bool_children_cache = children_cache; + slice_acc->bool_children_cache = children_cache; efl_promise_value_set(slice_acc->promise, slice_acc, (Eina_Free_Cb)&eina_accessor_free); } @@ -460,11 +492,6 @@ efl_model_hash_value_free(void *p) static void _composite_model_data_reset(Efl_Model_Composite_Boolean_Data *pd) { - if (pd->bool_children_cache) - { - _bool_children_cache_array_free(pd->bool_children_cache); - pd->bool_children_cache = NULL; - } if (pd->composite_model) { @@ -494,7 +521,7 @@ _efl_model_composite_boolean_efl_object_destructor(Eo *obj, Efl_Model_Composite_ } static void -_efl_model_composite_boolean_composite_model_set(Eo *obj EINA_UNUSED, +_efl_model_composite_boolean_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd, Efl_Model *model) { if (pd->composite_model) @@ -506,7 +533,7 @@ _efl_model_composite_boolean_composite_model_set(Eo *obj EINA_UNUSED, } static Efl_Model * -_efl_model_composite_boolean_composite_model_get(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd) +_efl_model_composite_boolean_efl_ui_view_model_get(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd) { return pd->composite_model; } @@ -586,7 +613,7 @@ _efl_model_composite_boolean_efl_model_children_slice_get(Eo *obj, Efl_Model_Com composite_future = efl_future_all(futures[0], futures[1]); accessor = calloc(1, sizeof(Efl_Model_Accessor_Slice)); - efl_model_accessor_slice_setup(accessor, obj, pd, promise); + efl_model_accessor_slice_setup(accessor, obj, pd, promise, start); efl_future_then(composite_future, &_efl_model_composite_boolean_slice_then_cb, &_efl_model_composite_boolean_slice_error_cb, NULL, accessor); diff --git a/src/lib/ecore/efl_model_composite_boolean.eo b/src/lib/ecore/efl_model_composite_boolean.eo index cdca17e998..bb7eacbb11 100644 --- a/src/lib/ecore/efl_model_composite_boolean.eo +++ b/src/lib/ecore/efl_model_composite_boolean.eo @@ -1,17 +1,7 @@ -class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model) +class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model, Efl.Ui.View) { [[Efl model composite boolean class]] methods { - @property composite_model { - [[Composite model]] - set { - } - get { - } - values { - model: Efl.Model; [[Efl model]] - } - } property_add { [[Adds property]] params { @@ -29,9 +19,10 @@ class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model) Efl.Model.children_count_get; Efl.Model.child_add; Efl.Model.child_del; + Efl.Ui.View.model { set; get; } } constructors { - .composite_model; + Efl.Ui.View.model; .property_add @optional; } } diff --git a/src/lib/ecore/efl_model_composite_selection.c b/src/lib/ecore/efl_model_composite_selection.c new file mode 100644 index 0000000000..8311f1c7b5 --- /dev/null +++ b/src/lib/ecore/efl_model_composite_selection.c @@ -0,0 +1,237 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Eina.h" +#include "Efl.h" +#include +#include "Eo.h" + +#include "efl_model_composite_selection.eo.h" +#include "efl_model_accessor_view_private.h" + +typedef struct _Efl_Model_Composite_Selection_Data +{ + Efl_Model_Composite_Selection* obj; + struct { + Efl_Model* selected_child; + } exclusive_data; + Eina_Bool is_exclusive; + +} Efl_Model_Composite_Selection_Data; + +typedef struct _Efl_Model_Composite_Selection_Children_Data +{ + Efl_Model_Composite_Selection_Data* pd; +} 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_constructor(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS)); + efl_model_composite_boolean_property_add(obj, "selected", EINA_FALSE); + pd->obj = obj; + return obj; +} + +/***************************/ +static void _select_property_failed(void* data, Efl_Event const* event) +{ + Efl_Promise* promise = data; + Efl_Future_Event_Failure* fail = event->info; + efl_promise_failed_set(promise, fail->error); + efl_unref(promise); +} + +static void _select_property_then(void* data, Efl_Event const* event EINA_UNUSED) +{ + Efl_Promise* promise = data; + Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_UCHAR); + eina_value_set(v, EINA_TRUE); + efl_promise_value_set(promise, v, (Eina_Free_Cb)&eina_value_free); + efl_unref(promise); +} + +static void _select_slice_then(void* data EINA_UNUSED, Efl_Event const* event) +{ + Efl_Future_Event_Success* success = event->info; + Eina_Accessor* accessor = eina_accessor_clone(success->value); + Eina_Value value; + Efl_Model* child; + + eina_accessor_data_get(accessor, 0, (void**)&child); + + eina_value_setup(&value, EINA_VALUE_TYPE_UCHAR); + eina_value_set(&value, EINA_TRUE); + + efl_future_then(efl_model_property_set(child, "selected", &value), + _select_property_then, _select_property_failed, NULL, efl_ref(success->next)); +} + +static void _select_error(void* data EINA_UNUSED, Efl_Event const* event) +{ + Efl_Future_Event_Failure* fail = event->info; + efl_promise_failed_set(fail->next, fail->error); +} + +/***************************/ + +static Efl_Future* +_efl_model_composite_selection_select(Eo *obj, + Efl_Model_Composite_Selection_Data *pd, int idx) +{ + return efl_future_then(efl_model_children_slice_get(obj, idx, 1), + &_select_slice_then, + &_select_error, + NULL, pd); +} + +static void +_efl_model_composite_selection_exclusive_selection_set(Eo *obj EINA_UNUSED, + Efl_Model_Composite_Selection_Data *pd, Eina_Bool exclusive) +{ + pd->is_exclusive = exclusive; +} + +static Eina_Bool +_efl_model_composite_selection_exclusive_selection_get(Eo *obj EINA_UNUSED, + Efl_Model_Composite_Selection_Data *pd) +{ + return pd->is_exclusive; +} + +static void +_exclusive_future_link_then_cb(void* data, Efl_Event const* event) +{ + Efl_Future_Event_Success *success = event->info; + efl_promise_value_set(data, success->value, NULL); // We would need to move the value + // Needs to set exclusive_child + efl_unref(data); +} + +static void +_exclusive_future_link_failed(void* data, Efl_Event const* event) +{ + Efl_Future_Event_Failure *failed = event->info; + efl_promise_failed_set(data, failed->error); + efl_unref(data); +} + +static void +_exclusive_unselected_then_cb(void* data, Efl_Event const* event) +{ + Efl_Future_Event_Success *success = event->info; + Eina_Value* true_value = eina_value_new(EINA_VALUE_TYPE_UCHAR); + eina_value_set(true_value, EINA_TRUE); + efl_future_then(efl_model_property_set(data, "selected", true_value), + _exclusive_future_link_then_cb, _exclusive_future_link_failed, + NULL, efl_ref(success->next)); + efl_unref(data); +} + +static void +_exclusive_unselected_failed(void* data, Efl_Event const* event) +{ + Efl_Future_Event_Failure *failed = event->info; + efl_promise_failed_set(data, failed->error); + efl_unref(data); +} + +static Efl_Future * +_efl_model_composite_selection_children_efl_model_property_set(Eo *obj EINA_UNUSED, + Efl_Model_Composite_Selection_Children_Data *pd, const char *property, const Eina_Value *value) +{ + if(!strcmp("selected", property)) + { + unsigned long v = EINA_FALSE; + if(eina_value_type_get(value) != EINA_VALUE_TYPE_ULONG) + { + Eina_Value to; + eina_value_setup(&to, EINA_VALUE_TYPE_ULONG); + if(eina_value_convert(value, &to)) + eina_value_get(&to, &v); + eina_value_flush(&to); + } + else + eina_value_get(value, &v); + + if(v && pd->pd->is_exclusive) + { + if(pd->pd->exclusive_data.selected_child) + { + // unset current selected + // set this child as current + // bookkeep this child as current selection + // return with future for this asynchronous task + Eina_Value* false_value = eina_value_new(EINA_VALUE_TYPE_UCHAR); + eina_value_set(false_value, EINA_FALSE); + return + efl_future_then(efl_model_property_set + (pd->pd->exclusive_data.selected_child, + property, false_value), + _exclusive_unselected_then_cb, + _exclusive_unselected_failed, NULL, + efl_ref(obj)); + } + else + { + Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); + Efl_Future *rfuture = efl_promise_future_get(promise); + Eina_Value* true_value = eina_value_new(EINA_VALUE_TYPE_UCHAR); + eina_value_set(true_value, EINA_TRUE); + efl_future_then(efl_model_property_set + (efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS), + "selected", true_value), + _exclusive_future_link_then_cb, _exclusive_future_link_failed, + NULL, efl_ref(promise)); + return rfuture; + } + } + else + { + + } + } + + return efl_model_property_set(efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS), + property, value); +} + +static Eo* _construct_children(void* pdata, Eo* child) +{ + Efl_Model_Composite_Selection_Data* pd = pdata; + Eo* new_child = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS, NULL); + Efl_Model_Composite_Selection_Children_Data* data = efl_data_scope_get + (new_child, EFL_MODEL_COMPOSITE_SELECTION_CHILDREN_CLASS); + data->pd = pd; + efl_composite_attach(new_child, efl_ref(child)); + return new_child; +} + +static void _composited_children_slice_get_then(void* data, Efl_Event const* event) +{ + Efl_Future_Event_Success* success = event->info; + Eina_Accessor* accessor = success->value; + efl_promise_value_set(success->next, + efl_model_accessor_view_new(eina_accessor_clone(accessor), &_construct_children, + data), + (Eina_Free_Cb)&eina_accessor_free); +} +static void _composited_children_slice_get_fail(void* data EINA_UNUSED, Efl_Event const* event) +{ + Efl_Future_Event_Failure* failure = event->info; + efl_promise_failed_set(failure->next, failure->error); +} + +static Efl_Future * +_efl_model_composite_selection_efl_model_children_slice_get(Eo *obj, Efl_Model_Composite_Selection_Data *pd, unsigned int start, unsigned int count) +{ + Efl_Future* composited_future = efl_model_children_slice_get + (efl_super(obj, EFL_MODEL_COMPOSITE_SELECTION_CLASS),start, count); + return efl_future_then(composited_future, &_composited_children_slice_get_then, + &_composited_children_slice_get_fail, NULL, pd); +} + +#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 new file mode 100644 index 0000000000..bccf0070ad --- /dev/null +++ b/src/lib/ecore/efl_model_composite_selection.eo @@ -0,0 +1,21 @@ +class Efl.Model.Composite.Selection (Efl.Model.Composite.Boolean) +{ + [[Efl model composite selection class]] + methods { + select { + params { + idx: int; + } + return: future; + } + @property exclusive_selection { + values { + exclusive: bool; + } + } + } + implements { + Efl.Object.constructor; + Efl.Model.children_slice_get; + } +} diff --git a/src/lib/ecore/efl_model_composite_selection_children.eo b/src/lib/ecore/efl_model_composite_selection_children.eo new file mode 100644 index 0000000000..2ea5c950ef --- /dev/null +++ b/src/lib/ecore/efl_model_composite_selection_children.eo @@ -0,0 +1,7 @@ +class Efl.Model.Composite.Selection.Children (Efl.Object, Efl.Model) +{ + [[Efl model composite selection children class]] + implements { + Efl.Model.property_set; + } +} diff --git a/src/lib/ecore/efl_model_item.c b/src/lib/ecore/efl_model_item.c index 5f61ee79e9..8afc0a77a4 100644 --- a/src/lib/ecore/efl_model_item.c +++ b/src/lib/ecore/efl_model_item.c @@ -169,9 +169,9 @@ _efl_model_item_efl_model_child_add(Eo *obj, Efl_Model_Item_Data *sd) eina_error_set(EFL_MODEL_ERROR_UNKNOWN); return NULL; } + cevt.index = eina_list_count(sd->children); sd->children = eina_list_append(sd->children, child); cevt.child = child; - cevt.index = eina_list_count(sd->children); efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt); efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &cevt.index); return child; diff --git a/src/tests/efl/efl_test_model_composite_boolean.c b/src/tests/efl/efl_test_model_composite.c similarity index 56% rename from src/tests/efl/efl_test_model_composite_boolean.c rename to src/tests/efl/efl_test_model_composite.c index 2b94fa7aa0..a38e776746 100644 --- a/src/tests/efl/efl_test_model_composite_boolean.c +++ b/src/tests/efl/efl_test_model_composite.c @@ -39,6 +39,7 @@ typedef struct _Test_Child_Data const int child_number = 3; const int base_ints[] = { 41, 42, 43 }; +const Eina_Bool base_selections[] = { EINA_FALSE, EINA_FALSE, EINA_TRUE }; static void _future_error_then(void *data EINA_UNUSED, Efl_Event const* event EINA_UNUSED) @@ -78,6 +79,45 @@ _property_get_then(void *data, Efl_Event const *event) #undef _value_get_and_compare } +static void +_selection_property_get_then(void *data, Efl_Event const *event) +{ + Test_Child_Data *t = data; + Eina_Accessor *value_itt = (Eina_Accessor*)((Efl_Future_Event_Success*)event->info)->value; + int v_int = 0; + Eina_Bool v_bool = EINA_FALSE; + + +#define EFL_TEST_value_get_and_compare(it, i, var, cmp) \ + do { \ + Eina_Value *vvv = NULL; \ + if (!eina_accessor_data_get(it, i, (void **)&vvv) || !vvv || \ + !eina_value_get(vvv, &var)) \ + { \ + fprintf(stderr, "Could not get value!\n"); fflush(stderr); \ + ck_abort_msg("Could not get value"); \ + return; \ + } \ + else if(var != cmp) \ + { \ + fprintf(stderr, "Value did not match!\n"); fflush(stderr); \ + ck_abort_msg("Value did not match"); \ + return; \ + } \ + else \ + fprintf(stderr, "Value matched\n"); fflush(stderr); \ + } while(0) + + EFL_TEST_value_get_and_compare(value_itt, 0, v_bool, base_selections[t->idx]); + EFL_TEST_value_get_and_compare(value_itt, 1, v_int, base_ints[t->idx]); + + t->tdata->child_count++; + if (t->tdata->child_count == 3) + t->tdata->success_flag = EINA_TRUE; + +#undef EFL_TEST_value_get_and_compare +} + static void _children_slice_get_then(void *data, Efl_Event const* event) { @@ -86,7 +126,6 @@ _children_slice_get_then(void *data, Efl_Event const* event) Test_Child_Data *t; unsigned int i = 0; - fprintf(stderr, "OPAAAAAAa\n"); EINA_ACCESSOR_FOREACH(children, i, child) { Efl_Future *futures[3] = {NULL,}; @@ -105,6 +144,31 @@ _children_slice_get_then(void *data, Efl_Event const* event) } } +static void +_selection_children_slice_get_then(void *data, Efl_Event const* event) +{ + Eina_Accessor *children = (Eina_Accessor *)((Efl_Future_Event_Success*)event->info)->value; + Efl_Model *child; + Test_Child_Data *t; + unsigned int i = 0; + + EINA_ACCESSOR_FOREACH(children, i, child) + { + Efl_Future *futures[2] = {NULL,}; + Efl_Future *future_all = NULL; + + futures[0] = efl_model_property_get(child, "selected"); + futures[1] = efl_model_property_get(child, "test_p_int"); + + future_all = efl_future_all(futures[0], futures[1]); + + t = calloc(1, sizeof(Test_Child_Data)); + t->tdata = data; + t->idx = i; + efl_future_then(future_all, _selection_property_get_then, _future_error_then, NULL, t); + } +} + START_TEST(efl_test_model_composite_boolean) { Efl_Model_Item *base_model, *child; @@ -131,7 +195,7 @@ START_TEST(efl_test_model_composite_boolean) } model = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CLASS, NULL, - efl_model_composite_boolean_composite_model_set(efl_added, base_model), + efl_ui_view_model_set(efl_added, base_model), efl_model_composite_boolean_property_add(efl_added, "test_p_true", EINA_TRUE), efl_model_composite_boolean_property_add(efl_added, "test_p_false", EINA_FALSE)); ck_assert(!!model); @@ -148,8 +212,51 @@ START_TEST(efl_test_model_composite_boolean) } END_TEST +START_TEST(efl_test_model_composite_selection) +{ + Efl_Model_Item *base_model, *child; + int i; + Eina_Value v; + Efl_Model_Composite_Selection *model; + Test_Data *tdata; + Efl_Future *future; + + fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n"); + fail_if(!efl_object_init(), "ERROR: Cannot init EO!\n"); + + eina_value_setup(&v, EINA_VALUE_TYPE_INT); + + base_model = efl_add(EFL_MODEL_ITEM_CLASS, NULL); + ck_assert(!!base_model); + + for (i = 0; i < child_number; ++i) + { + child = efl_model_child_add(base_model); + ck_assert(!!child); + ck_assert(eina_value_set(&v, base_ints[i])); + efl_model_property_set(child, "test_p_int", &v); + } + + model = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CLASS, NULL, + efl_ui_view_model_set(efl_added, base_model)); + ck_assert(!!model); + efl_model_composite_selection_select(model, 2); + + tdata = calloc(1, sizeof(Test_Data)); + future = efl_model_children_slice_get(model, 0, 0); + efl_future_then(future, _selection_children_slice_get_then, _future_error_then, NULL, tdata); + + ecore_main_loop_iterate(); + + ck_assert(tdata->success_flag); + + ecore_shutdown(); +} +END_TEST + void efl_test_case_model_composite_boolean(TCase *tc) { tcase_add_test(tc, efl_test_model_composite_boolean); + tcase_add_test(tc, efl_test_model_composite_selection); }