ecore: add an index property on Efl.Model_Composite and handle children_slice_get.

This will enable inheriting class to not have to implement as much code. This patch
fix also all class that use Efl.Model_Composite and its test.

Reviewed-by: SangHyeon Jade Lee <sh10233.lee@samsung.com>
Differential Revision: https://phab.enlightenment.org/D7654
This commit is contained in:
Cedric BAIL 2019-01-03 14:54:18 -08:00
parent 95a9cc90d1
commit 1dadeac05e
12 changed files with 341 additions and 437 deletions

View File

@ -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

View File

@ -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"
/**

View File

@ -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 *

View File

@ -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;
}
}

View File

@ -4,15 +4,14 @@
#include <Efl_Core.h>
#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"

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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"

View File

@ -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; }
}

View File

@ -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! */
}

View File

@ -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'
]

View File

@ -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();