summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-06-20 18:50:38 -0300
committerLarry Jr <larry.olj@gmail.com>2017-02-01 14:45:50 -0200
commitb7d1a1c688558d340715b76952b2b6b4d423a1a5 (patch)
tree5dafc5fcf06bdd14ad31f92e642e19357e8a7105
parent2b044b9bc20bcb78f89f459fbda72e298196bf9b (diff)
downloadefl-devs/felipealmeida/efl_ui_connect.tar.gz
efl: Add composite model for boolean propertiesdevs/felipealmeida/efl_ui_connect
Add Efl.Model.Composite.Boolean, a model for wrapping another Efl.Model and adding boolean properties to its children. Children of the given composite model will have the boolean properties specified in Efl.Model.Composite.Boolean with the specified default value. A call to Efl.Model.Property_set can change the property value for a child.
-rw-r--r--src/Makefile_Ecore.am3
-rw-r--r--src/Makefile_Efl.am1
-rw-r--r--src/lib/ecore/Ecore_Eo.h2
-rw-r--r--src/lib/ecore/efl_model_composite_boolean.c642
-rw-r--r--src/lib/ecore/efl_model_composite_boolean.eo34
-rw-r--r--src/lib/ecore/efl_model_composite_boolean_children.eo13
-rw-r--r--src/tests/efl/efl_suite.c1
-rw-r--r--src/tests/efl/efl_suite.h1
-rw-r--r--src/tests/efl/efl_test_model_composite_boolean.c155
9 files changed, 852 insertions, 0 deletions
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 3cb58b6b43..97b91f0c89 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -29,6 +29,8 @@ ecore_eolian_files = \
lib/ecore/efl_model_item.eo \
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 \
$(ecore_eolian_files_legacy)
ecore_eolian_type_files = \
@@ -93,6 +95,7 @@ lib/ecore/efl_model_item.c \
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/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 faccdf5bac..a8fbf038c7 100644
--- a/src/Makefile_Efl.am
+++ b/src/Makefile_Efl.am
@@ -184,6 +184,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_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 1c29de392c..2a250fca29 100644
--- a/src/lib/ecore/Ecore_Eo.h
+++ b/src/lib/ecore/Ecore_Eo.h
@@ -125,6 +125,8 @@ EAPI Efl_Future *efl_future_iterator_race(Eina_Iterator *it);
#include "efl_model_item.eo.h"
#include "efl_model_container.eo.h"
#include "efl_model_container_item.eo.h"
+#include "efl_model_composite_boolean.eo.h"
+#include "efl_model_composite_boolean_children.eo.h"
/**
* @}
diff --git a/src/lib/ecore/efl_model_composite_boolean.c b/src/lib/ecore/efl_model_composite_boolean.c
new file mode 100644
index 0000000000..7ec344d05c
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_boolean.c
@@ -0,0 +1,642 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eina.h"
+#include "Efl.h"
+#include <Ecore.h>
+
+#include "efl_model_composite_boolean_children.eo.h"
+
+typedef struct _Efl_Model_Hash_Value
+{
+ unsigned char *buffer;
+ unsigned int bits_count;
+ Eina_Bool default_value : 1;
+} 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;
+
+typedef struct _Efl_Model_Composite_Boolean_Children_Data
+{
+ Efl_Model_Composite_Boolean_Data *parent_pd;
+ Efl_Model *composite_child;
+ Eina_Array *properties_names;
+ unsigned int index;
+} Efl_Model_Composite_Boolean_Children_Data;
+
+typedef struct _Efl_Model_Accessor_Slice
+{
+ Eina_Accessor vtable;
+ Eina_Accessor *real_accessor;
+ Efl_Model *parent;
+ Efl_Model_Composite_Boolean_Data *parent_pd;
+ Efl_Promise *promise;
+ unsigned int index;
+} Efl_Model_Accessor_Slice;
+
+static Eina_Value *
+_value_clone(const Eina_Value *value)
+{
+ Eina_Value *copy = eina_value_new(eina_value_type_get(value));
+ eina_value_copy(value, copy);
+ return copy;
+}
+
+static void
+_future_forward_cb(void *data, Efl_Event const *event)
+{
+ efl_promise_value_set(
+ data, _value_clone(((Efl_Future_Event_Success*)event->info)->value), (Eina_Free_Cb)eina_value_free);
+}
+
+static void
+_future_error_forward_cb(void *data, Efl_Event const *event)
+{
+ Eina_Error err = ((Efl_Future_Event_Failure*)event->info)->error;
+ efl_promise_failed_set(data, err);
+}
+
+static Eina_Bool
+_bit_get(const unsigned char *bitstream, unsigned int idx)
+{
+ return (bitstream[idx / 8] >> (idx % 8)) & 1u;
+}
+
+static void
+_bit_set(unsigned char *bitstream, unsigned int idx, Eina_Bool v)
+{
+ if (v)
+ bitstream[idx / 8] |= 1u << (idx % 8);
+ else
+ bitstream[idx / 8] &= ~(1u << (idx % 8));
+}
+
+/**************** efl_mmodel_composite_boolean_children **************/
+
+static void
+_properties_names_array_free(Eina_Array *properties_names)
+{
+ Eina_Array_Iterator it;
+ void *name;
+ unsigned int i;
+
+ EINA_ARRAY_ITER_NEXT(properties_names, i, name, it)
+ free(name);
+
+ eina_array_free(properties_names);
+}
+
+
+static void
+_efl_model_composite_boolean_children_efl_object_destructor(Eo *obj,
+ Efl_Model_Composite_Boolean_Children_Data *pd)
+{
+ if (pd->properties_names)
+ _properties_names_array_free(pd->properties_names);
+
+ if (pd->composite_child)
+ efl_unref(pd->composite_child);
+
+ efl_destructor(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS));
+}
+
+static Eina_Bool
+_properties_names_push(const Eina_Hash *hash EINA_UNUSED,
+ const void *key, void *data EINA_UNUSED, void *fdata)
+{
+ eina_array_push(fdata, key);
+ return EINA_TRUE;
+}
+
+static const Eina_Array*
+_efl_model_composite_boolean_children_efl_model_properties_get(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd)
+{
+ Eina_Array const *composite_properties;
+ unsigned int composite_count, self_count, i;
+
+ if (pd->properties_names)
+ {
+ _properties_names_array_free(pd->properties_names);
+ pd->properties_names = NULL;
+ }
+
+ composite_properties = efl_model_properties_get(pd->composite_child);
+ if (!composite_properties)
+ return pd->properties_names = eina_array_new(1);
+
+ composite_count = eina_array_count_get(composite_properties);
+ self_count = eina_hash_population(pd->parent_pd->values);
+
+ pd->properties_names = eina_array_new(composite_count + self_count);
+ for (i = 0; i != composite_count; ++i)
+ {
+ const char *name = strdup(eina_array_data_get(composite_properties, i));
+ eina_array_push(pd->properties_names, name);
+ }
+
+ eina_hash_foreach(pd->parent_pd->values, _properties_names_push, pd->properties_names);
+
+ return pd->properties_names;
+}
+
+static Efl_Future *
+_efl_model_composite_boolean_children_efl_model_property_get(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd, const char *property)
+{
+ Efl_Model_Hash_Value *hv = eina_hash_find(pd->parent_pd->values, property);
+ if (hv)
+ {
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ 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);
+ }
+ else
+ {
+ eina_value_set(eina_value, _bit_get(hv->buffer, pd->index));
+ }
+ efl_promise_value_set(promise, eina_value, (Eina_Free_Cb)eina_value_free);
+ return rfuture;
+ }
+ else if (pd->composite_child)
+ return efl_model_property_get(pd->composite_child, property);
+ else
+ {
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+ return rfuture;
+ }
+}
+
+static Efl_Future *
+_efl_model_composite_boolean_children_efl_model_property_set(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd, const char *property, const Eina_Value *value)
+{
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ Efl_Model_Hash_Value *hv = eina_hash_find(pd->parent_pd->values, property);
+ if (hv)
+ {
+ Eina_Bool flag = EINA_FALSE;
+
+ if (eina_value_type_get(value) == EINA_VALUE_TYPE_UCHAR)
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
+ return rfuture;
+ }
+ if (!eina_value_get(value, &flag))
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
+ return rfuture;
+ }
+
+ if (pd->index >= hv->bits_count)
+ {
+ unsigned int bytes = (pd->index / 8) + 1;
+ unsigned int buff_size = (hv->bits_count / 8) + (hv->bits_count % 8 ? 1 : 0);
+ unsigned char *buff = realloc(hv->buffer, bytes);
+ if (!buff)
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
+ return rfuture;
+ }
+ memset(
+ buff + buff_size,
+ hv->default_value ? -1 : 0,
+ bytes - buff_size);
+
+ hv->buffer = buff;
+ hv->bits_count = bytes * 8;
+ }
+
+ _bit_set(hv->buffer, pd->index, flag);
+
+ efl_promise_value_set(
+ promise, _value_clone(value), (Eina_Free_Cb)eina_value_free);
+ }
+ else if (pd->composite_child)
+ {
+ Efl_Future *f_forward = efl_model_property_set(pd->composite_child, property, value);
+ efl_future_then(f_forward, _future_forward_cb, _future_error_forward_cb, NULL, promise);
+ }
+ else
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+ }
+
+ return rfuture;
+}
+
+static Efl_Future*
+_efl_model_composite_boolean_children_efl_model_children_slice_get(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd, unsigned int start, unsigned int count)
+{
+ return efl_model_children_slice_get(pd->composite_child, start, count);
+}
+
+static Efl_Future*
+_efl_model_composite_boolean_children_efl_model_children_count_get(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd)
+{
+ return efl_model_children_count_get(pd->composite_child);
+}
+
+static Efl_Object*
+_efl_model_composite_boolean_children_efl_model_child_add(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd)
+{
+ return efl_model_child_add(pd->composite_child);
+}
+
+static void
+_efl_model_composite_boolean_children_efl_model_child_del(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Children_Data *pd, Efl_Object *child)
+{
+ efl_model_child_del(pd->composite_child, child);
+}
+
+/**************** efl_model_accessor_slice **************/
+
+static void
+_bool_children_cache_array_free(Eina_Array *children_cache)
+{
+ int i, count = eina_array_count_get(children_cache);
+ for (i = 0; i < count; ++i)
+ efl_unref(eina_array_data_get(children_cache, i));
+ eina_array_free(children_cache);
+}
+
+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;
+
+ /* NOTE: Efl.Model.Composite.Boolean must alloc the cache with the correct size
+ and NULL initialized. */
+ if (idx >= eina_array_count(children_cache))
+ {
+ EINA_LOG_WARN("Index bigger than size");
+ return EINA_FALSE;
+ }
+
+ child_bool = eina_array_data_get(children_cache, idx);
+
+ if (!child_bool)
+ {
+ Efl_Model *child = NULL;
+
+ if (!eina_accessor_data_get(acc->real_accessor, idx, (void *)&child))
+ return EINA_FALSE;
+
+ if (child)
+ {
+ Efl_Model_Composite_Boolean_Children_Data *pd;
+ child_bool = efl_add(EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, NULL);
+ pd = 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++;
+
+ eina_array_data_set(children_cache, idx, child_bool);
+ }
+ }
+
+ if (data) *data = child_bool;
+ return EINA_TRUE;
+}
+
+static void *
+efl_model_acessor_slice_get_container(Efl_Model_Accessor_Slice *acc)
+{
+ return eina_accessor_container_get(acc->real_accessor);
+}
+
+static void
+efl_model_acessor_slice_free(Efl_Model_Accessor_Slice *acc)
+{
+ if (acc->real_accessor)
+ {
+ eina_accessor_free(acc->real_accessor);
+ acc->real_accessor = NULL;
+ }
+
+ if (acc->parent)
+ {
+ efl_unref(acc->parent);
+ acc->parent = NULL;
+ }
+
+ acc->parent_pd = NULL;
+ acc->promise = NULL;
+
+ free(acc);
+}
+
+static Eina_Bool
+efl_model_acessor_slice_lock(Efl_Model_Accessor_Slice *acc)
+{
+ return eina_accessor_lock(acc->real_accessor);
+}
+
+static Eina_Bool
+efl_model_acessor_slice_unlock(Efl_Model_Accessor_Slice *acc)
+{
+ return eina_accessor_unlock(acc->real_accessor);
+}
+
+static Efl_Model_Accessor_Slice *
+efl_model_acessor_slice_clone(Efl_Model_Accessor_Slice *acc EINA_UNUSED)
+{
+ return NULL;
+}
+
+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)
+{
+ acc->vtable.version = EINA_ACCESSOR_VERSION;
+ acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(efl_model_acessor_slice_get_at);
+ acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(efl_model_acessor_slice_get_container);
+ acc->vtable.free = FUNC_ACCESSOR_FREE(efl_model_acessor_slice_free);
+
+ acc->vtable.lock = FUNC_ACCESSOR_LOCK(efl_model_acessor_slice_lock);
+ acc->vtable.unlock = FUNC_ACCESSOR_LOCK(efl_model_acessor_slice_unlock);
+
+ acc->vtable.clone = FUNC_ACCESSOR_CLONE(efl_model_acessor_slice_clone);
+
+ EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR);
+
+ acc->parent = efl_ref(parent);
+ acc->parent_pd = parent_pd;
+ acc->promise = promise;
+}
+
+static void
+_efl_model_composite_boolean_slice_then_cb(void *data, Efl_Event const *event)
+{
+ Efl_Model_Accessor_Slice *slice_acc = data;
+ Eina_Accessor *value_itt = (Eina_Accessor *)((Efl_Future_Event_Success*)event->info)->value;
+ unsigned int *children_count = NULL;
+ Eina_Accessor *children_accessor = NULL;
+
+ if (!eina_accessor_data_get(value_itt, 0, (void**)&children_count) ||
+ !children_count ||
+ !eina_accessor_data_get(value_itt, 1, (void**)&children_accessor) ||
+ !children_accessor)
+ {
+ EINA_LOG_WARN("missing Efl.Model information");
+ efl_promise_failed_set(slice_acc->promise, EFL_MODEL_ERROR_UNKNOWN);
+ efl_model_acessor_slice_free(slice_acc);
+ return;
+ }
+
+ slice_acc->real_accessor = eina_accessor_clone(children_accessor);
+ if (slice_acc->real_accessor)
+ {
+ 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);
+
+ 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);
+ }
+
+ slice_acc->parent_pd->bool_children_cache = children_cache;
+
+ efl_promise_value_set(slice_acc->promise, slice_acc, (Eina_Free_Cb)&eina_accessor_free);
+ }
+ else
+ {
+ efl_promise_failed_set(slice_acc->promise, EFL_MODEL_ERROR_NOT_SUPPORTED);
+ efl_model_acessor_slice_free(slice_acc);
+ }
+}
+
+static void
+_efl_model_composite_boolean_slice_error_cb(void *data, Efl_Event const*event)
+{
+ Efl_Model_Accessor_Slice *slice_acc = data;
+ Eina_Error error = ((Efl_Future_Event_Failure*)event->info)->error;
+ efl_promise_failed_set(slice_acc->promise, error);
+ efl_model_acessor_slice_free(slice_acc);
+}
+
+/**************** efl_mmodel_composite_boolean **************/
+
+static void
+efl_model_hash_value_free(void *p)
+{
+ Efl_Model_Hash_Value *value = p;
+ if (value)
+ {
+ free(value->buffer);
+ free(value);
+ }
+}
+
+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)
+ {
+ efl_unref(pd->composite_model);
+ pd->composite_model = NULL;
+ }
+}
+
+static void
+_efl_model_composite_boolean_efl_object_destructor(Eo *obj, Efl_Model_Composite_Boolean_Data *pd)
+{
+ if (pd->empty_properties)
+ {
+ eina_array_free(pd->empty_properties);
+ pd->empty_properties = NULL;
+ }
+
+ if (pd->values)
+ {
+ eina_hash_free(pd->values);
+ pd->values = NULL;
+ }
+
+ _composite_model_data_reset(pd);
+
+ efl_destructor(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS));
+}
+
+static void
+_efl_model_composite_boolean_composite_model_set(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Data *pd, Efl_Model *model)
+{
+ if (pd->composite_model)
+ {
+ _composite_model_data_reset(pd);
+ }
+
+ pd->composite_model = efl_ref(model);
+}
+
+static Efl_Model *
+_efl_model_composite_boolean_composite_model_get(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
+{
+ return pd->composite_model;
+}
+
+static void
+_efl_model_composite_boolean_property_add(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd,
+ const char *name, Eina_Bool initial_value)
+{
+ if (!pd->values)
+ pd->values = eina_hash_string_small_new(&efl_model_hash_value_free);
+ Efl_Model_Hash_Value *value = calloc(1, sizeof(Efl_Model_Hash_Value));
+ value->default_value = initial_value;
+ eina_hash_add(pd->values, name, value);
+}
+
+static const Eina_Array *
+_efl_model_composite_boolean_efl_model_properties_get(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
+{
+ if (pd->composite_model)
+ return efl_model_properties_get(pd->composite_model);
+ else if (pd->empty_properties)
+ return pd->empty_properties;
+ else
+ return pd->empty_properties = eina_array_new(1);
+}
+
+Efl_Future *
+_efl_model_composite_boolean_efl_model_property_get(Eo *obj EINA_UNUSED,
+ Efl_Model_Composite_Boolean_Data *pd, const char *property)
+{
+ if (pd->composite_model)
+ return efl_model_property_get(pd->composite_model, property);
+
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+ return rfuture;
+}
+
+Efl_Future *
+_efl_model_composite_boolean_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd,
+ const char *property, const Eina_Value *value)
+{
+
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ if (pd->composite_model)
+ {
+ Efl_Future *f_forward = efl_model_property_set(pd->composite_model, property, value);
+ efl_future_then(f_forward, _future_forward_cb, _future_error_forward_cb, NULL, promise);
+ }
+ else
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
+ }
+
+ return rfuture;
+}
+
+static Efl_Future *
+_efl_model_composite_boolean_efl_model_children_slice_get(Eo *obj, Efl_Model_Composite_Boolean_Data *pd, unsigned int start, unsigned int count)
+{
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ if (pd->composite_model)
+ {
+ Efl_Model_Accessor_Slice *accessor;
+ Efl_Future *composite_future;
+ Efl_Future *futures[2] = {NULL,};
+
+ futures[0] = efl_model_children_count_get(pd->composite_model);
+ futures[1] = efl_model_children_slice_get(pd->composite_model, start, count);
+
+ 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_future_then(composite_future, &_efl_model_composite_boolean_slice_then_cb,
+ &_efl_model_composite_boolean_slice_error_cb, NULL, accessor);
+ }
+ else
+ {
+ efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_SUPPORTED);
+ }
+ return rfuture;
+}
+
+static Efl_Future *
+_efl_model_composite_boolean_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
+{
+ if (pd->composite_model)
+ return efl_model_children_count_get(pd->composite_model);
+ else
+ {
+ Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+ Efl_Future *rfuture = efl_promise_future_get(promise);
+
+ unsigned int *count = malloc(sizeof(unsigned int));
+ *count = 0;
+ efl_promise_value_set(promise, count, free);
+ return rfuture;
+ }
+}
+
+static Efl_Object*
+_efl_model_composite_boolean_efl_model_child_add(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
+{
+ if (pd->composite_model)
+ return efl_model_child_add(pd->composite_model);
+ else
+ {
+ eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
+ return NULL;
+ }
+}
+
+static void
+_efl_model_composite_boolean_efl_model_child_del(Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd, Efl_Object *child)
+{
+ if (pd->composite_model)
+ return efl_model_child_del(pd->composite_model, child);
+ else
+ {
+ eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
+ }
+}
+
+#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
new file mode 100644
index 0000000000..4384e20017
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_boolean.eo
@@ -0,0 +1,34 @@
+class Efl.Model.Composite.Boolean (Efl.Object, Efl.Model)
+{
+ methods {
+ @property composite_model {
+ set {
+ }
+ get {
+ }
+ values {
+ model: Efl.Model;
+ }
+ }
+ property_add {
+ params {
+ @in name: string;
+ @in initial_value: bool;
+ }
+ }
+ }
+ implements {
+ Efl.Object.destructor;
+ Efl.Model.properties { get; }
+ Efl.Model.property_get;
+ Efl.Model.property_set;
+ Efl.Model.children_slice_get;
+ Efl.Model.children_count_get;
+ Efl.Model.child_add;
+ Efl.Model.child_del;
+ }
+ constructors {
+ .composite_model;
+ .property_add @optional;
+ }
+}
diff --git a/src/lib/ecore/efl_model_composite_boolean_children.eo b/src/lib/ecore/efl_model_composite_boolean_children.eo
new file mode 100644
index 0000000000..d2668c745f
--- /dev/null
+++ b/src/lib/ecore/efl_model_composite_boolean_children.eo
@@ -0,0 +1,13 @@
+class Efl.Model.Composite.Boolean.Children (Efl.Object, Efl.Model)
+{
+ implements {
+ Efl.Object.destructor;
+ Efl.Model.properties { get; }
+ Efl.Model.property_get;
+ Efl.Model.property_set;
+ Efl.Model.children_slice_get;
+ Efl.Model.children_count_get;
+ Efl.Model.child_add;
+ Efl.Model.child_del;
+ }
+}
diff --git a/src/tests/efl/efl_suite.c b/src/tests/efl/efl_suite.c
index 653aac2201..82cc6dfb32 100644
--- a/src/tests/efl/efl_suite.c
+++ b/src/tests/efl/efl_suite.c
@@ -27,6 +27,7 @@
static const Efl_Test_Case etc[] = {
{ "Efl_Model_Container", efl_test_case_model_container },
+ { "Efl_Model_Composite_Boolean", efl_test_case_model_composite_boolean },
{ NULL, NULL }
};
diff --git a/src/tests/efl/efl_suite.h b/src/tests/efl/efl_suite.h
index d5a7caa9ec..b142037425 100644
--- a/src/tests/efl/efl_suite.h
+++ b/src/tests/efl/efl_suite.h
@@ -22,5 +22,6 @@
#include <check.h>
void efl_test_case_model_container(TCase *tc);
+void efl_test_case_model_composite_boolean(TCase *tc);
#endif /* EFL_SUITE_H_ */
diff --git a/src/tests/efl/efl_test_model_composite_boolean.c b/src/tests/efl/efl_test_model_composite_boolean.c
new file mode 100644
index 0000000000..2b94fa7aa0
--- /dev/null
+++ b/src/tests/efl/efl_test_model_composite_boolean.c
@@ -0,0 +1,155 @@
+/* EFL - EFL library
+ * Copyright (C) 2013 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "efl_suite.h"
+
+#include <Efl.h>
+#include <Ecore.h>
+
+typedef struct _Test_Data
+{
+ Eina_Bool success_flag;
+ unsigned int child_count;
+} Test_Data;
+
+typedef struct _Test_Child_Data
+{
+ Test_Data *tdata;
+ unsigned int idx;
+} Test_Child_Data;
+
+const int child_number = 3;
+const int base_ints[] = { 41, 42, 43 };
+
+static void
+_future_error_then(void *data EINA_UNUSED, Efl_Event const* event EINA_UNUSED)
+{
+ fprintf(stderr, "Promise failed!\n"); fflush(stderr);
+ ck_abort_msg("Promise failed");
+}
+
+static void
+_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 _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) || var != cmp) \
+ { \
+ fprintf(stderr, "Could not get value!\n"); fflush(stderr); \
+ ck_abort_msg("Could not get value"); \
+ return; \
+ } \
+ } while(0)
+
+ _value_get_and_compare(value_itt, 0, v_int, base_ints[t->idx]);
+ _value_get_and_compare(value_itt, 1, v_bool, EINA_TRUE);
+ _value_get_and_compare(value_itt, 2, v_bool, EINA_FALSE);
+
+ t->tdata->child_count++;
+ if (t->tdata->child_count == 3)
+ t->tdata->success_flag = EINA_TRUE;
+
+#undef _value_get_and_compare
+}
+
+static void
+_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;
+
+ fprintf(stderr, "OPAAAAAAa\n");
+ EINA_ACCESSOR_FOREACH(children, i, child)
+ {
+ Efl_Future *futures[3] = {NULL,};
+ Efl_Future *future_all = NULL;
+
+ futures[0] = efl_model_property_get(child, "test_p_int");
+ futures[1] = efl_model_property_get(child, "test_p_true");
+ futures[2] = efl_model_property_get(child, "test_p_false");
+
+ future_all = efl_future_all(futures[0], futures[1], futures[2]);
+
+ t = calloc(1, sizeof(Test_Child_Data));
+ t->tdata = data;
+ t->idx = i;
+ efl_future_then(future_all, _property_get_then, _future_error_then, NULL, t);
+ }
+}
+
+START_TEST(efl_test_model_composite_boolean)
+{
+ Efl_Model_Item *base_model, *child;
+ int i;
+ Eina_Value v;
+ Efl_Model_Composite_Boolean *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_BOOLEAN_CLASS, NULL,
+ efl_model_composite_boolean_composite_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);
+
+ tdata = calloc(1, sizeof(Test_Data));
+ future = efl_model_children_slice_get(model, 0, 0);
+ efl_future_then(future, _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);
+}