ecore: refactor and migrate efl.model.composite.boolean to the new efl.model API.
This commit is contained in:
parent
2049c44c78
commit
9211fd73a7
|
@ -2,667 +2,303 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "Eina.h"
|
||||
#include "Efl.h"
|
||||
#include <Ecore.h>
|
||||
#include <Efl_Core.h>
|
||||
|
||||
#include "efl_model_composite_boolean_children.eo.h"
|
||||
|
||||
typedef struct _Efl_Model_Hash_Value
|
||||
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
|
||||
{
|
||||
Eina_Hash *values;
|
||||
};
|
||||
|
||||
struct _Efl_Model_Composite_Boolean_Value
|
||||
{
|
||||
Eina_Stringshare *property;
|
||||
|
||||
// This is not the best for supporting sparse bitfield with random insertion
|
||||
// but will do for now (Would be best to have a tree of fixed size array
|
||||
// or something along that line).
|
||||
unsigned char *buffer;
|
||||
unsigned int bits_count;
|
||||
Eina_Bool default_value : 1;
|
||||
} Efl_Model_Hash_Value;
|
||||
unsigned int buffer_count;
|
||||
|
||||
typedef struct _Efl_Model_Composite_Boolean_Data
|
||||
{
|
||||
Efl_Model *composite_model;
|
||||
Eina_Array *empty_properties;
|
||||
Eina_Hash *values; // [property_name, Efl_Model_Hash_Value*]
|
||||
} Efl_Model_Composite_Boolean_Data;
|
||||
Eina_Bool default_value;
|
||||
};
|
||||
|
||||
typedef struct _Efl_Model_Composite_Boolean_Children_Data
|
||||
struct _Efl_Model_Composite_Boolean_Children_Data
|
||||
{
|
||||
Efl_Model_Composite_Boolean_Data *parent_pd;
|
||||
Efl_Model *composite_child;
|
||||
Eina_Array *properties_names;
|
||||
Efl_Model_Composite_Boolean_Data *parent;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Eina_Bool b = (bitstream[idx / 8] >> (idx % 8)) & 1u;
|
||||
return b;
|
||||
}
|
||||
|
||||
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)
|
||||
_efl_model_composite_boolean_children_index_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Model_Composite_Boolean_Children_Data *pd,
|
||||
unsigned int index)
|
||||
{
|
||||
Eina_Array_Iterator it;
|
||||
void *name;
|
||||
unsigned int i;
|
||||
if (pd->parent) // This is set during finalize
|
||||
return ;
|
||||
|
||||
EINA_ARRAY_ITER_NEXT(properties_names, i, name, it)
|
||||
free(name);
|
||||
|
||||
eina_array_free(properties_names);
|
||||
pd->index = index;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_efl_model_composite_boolean_children_efl_object_destructor(Eo *obj,
|
||||
Efl_Model_Composite_Boolean_Children_Data *pd)
|
||||
static unsigned int
|
||||
_efl_model_composite_boolean_children_index_get(const Eo *obj EINA_UNUSED,
|
||||
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));
|
||||
return pd->index;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_properties_names_push(const Eina_Hash *hash EINA_UNUSED,
|
||||
const void *key, void *data EINA_UNUSED, void *fdata)
|
||||
static Efl_Object *
|
||||
_efl_model_composite_boolean_children_efl_object_finalize(Eo *obj,
|
||||
Efl_Model_Composite_Boolean_Children_Data *pd)
|
||||
{
|
||||
eina_array_push(fdata, key);
|
||||
return EINA_TRUE;
|
||||
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 const Eina_Array*
|
||||
_efl_model_composite_boolean_children_efl_model_properties_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Model_Composite_Boolean_Children_Data *pd)
|
||||
static Eina_Array *
|
||||
_efl_model_composite_boolean_children_efl_model_properties_get(const Eo *obj,
|
||||
Efl_Model_Composite_Boolean_Children_Data *pd)
|
||||
{
|
||||
Eina_Array const *composite_properties;
|
||||
unsigned int composite_count, self_count, i;
|
||||
Eina_Iterator *it;
|
||||
Eina_Stringshare *s;
|
||||
Eina_Array *r;
|
||||
|
||||
if (pd->properties_names)
|
||||
{
|
||||
_properties_names_array_free(pd->properties_names);
|
||||
pd->properties_names = NULL;
|
||||
}
|
||||
r = efl_model_properties_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS));
|
||||
if (!r) r = eina_array_new(1);
|
||||
|
||||
composite_properties = efl_model_properties_get(pd->composite_child);
|
||||
if (!composite_properties)
|
||||
return pd->properties_names = eina_array_new(1);
|
||||
it = eina_hash_iterator_key_new(pd->parent->values);
|
||||
EINA_ITERATOR_FOREACH(it, s)
|
||||
eina_array_push(r, s);
|
||||
eina_array_push(r, "child.index");
|
||||
|
||||
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;
|
||||
return r;
|
||||
}
|
||||
|
||||
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)
|
||||
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_Hash_Value *hv = eina_hash_find(pd->parent_pd->values, property);
|
||||
if (hv)
|
||||
{
|
||||
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, efl_main_loop_get());
|
||||
Efl_Future *rfuture = efl_promise_future_get(promise);
|
||||
Efl_Model_Composite_Boolean_Value *v;
|
||||
Eina_Stringshare *s;
|
||||
Eina_Bool flag;
|
||||
|
||||
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);
|
||||
if (property == NULL) return NULL;
|
||||
if (strcmp(property, "child.index") == 0)
|
||||
return eina_value_uint_new(pd->index);
|
||||
|
||||
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);
|
||||
|
||||
// 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)
|
||||
flag = v->default_value;
|
||||
else
|
||||
{
|
||||
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, efl_main_loop_get());
|
||||
Efl_Future *rfuture = efl_promise_future_get(promise);
|
||||
flag = v->buffer[pd->index >> 3] & (1 << pd->index & 0x7);
|
||||
|
||||
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
|
||||
return rfuture;
|
||||
}
|
||||
return eina_value_uchar_new(!!flag);
|
||||
}
|
||||
|
||||
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)
|
||||
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_Promise *promise = efl_add(EFL_PROMISE_CLASS, efl_main_loop_get());
|
||||
Efl_Future *rfuture = efl_promise_future_get(promise);
|
||||
Efl_Model_Composite_Boolean_Value *v;
|
||||
Eina_Stringshare *s;
|
||||
Eina_Value b = EINA_VALUE_EMPTY;
|
||||
Eina_Bool flag;
|
||||
|
||||
Efl_Model_Hash_Value *hv = eina_hash_find(pd->parent_pd->values, property);
|
||||
if (hv)
|
||||
if (!property)
|
||||
return eina_future_rejected(efl_loop_future_scheduler_get(obj),
|
||||
EFL_MODEL_ERROR_UNKNOWN);
|
||||
if (strcmp(property, "child.index") == 0)
|
||||
return eina_future_rejected(efl_loop_future_scheduler_get(obj),
|
||||
EFL_MODEL_ERROR_READ_ONLY);
|
||||
|
||||
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),
|
||||
property, value);
|
||||
|
||||
eina_value_setup(&b, EINA_VALUE_TYPE_UCHAR);
|
||||
if (!eina_value_convert(value, &b))
|
||||
return eina_future_rejected(efl_loop_future_scheduler_get(obj),
|
||||
EFL_MODEL_ERROR_UNKNOWN);
|
||||
if (!eina_value_get(value, &flag))
|
||||
return eina_future_rejected(efl_loop_future_scheduler_get(obj),
|
||||
EFL_MODEL_ERROR_UNKNOWN);
|
||||
|
||||
eina_value_flush(&b);
|
||||
|
||||
// We are optimistically allocating the boolean buffer now.
|
||||
// Aligning it on 64bits
|
||||
if (v->buffer_count < (((pd->index) >> 3) | 0x7) + 1)
|
||||
{
|
||||
Eina_Bool flag = EINA_FALSE;
|
||||
unsigned int rcount = (((pd->index | 0xF) >> 3) | 0x7) + 1;
|
||||
unsigned char *tmp;
|
||||
|
||||
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);
|
||||
tmp = realloc(v->buffer, rcount);
|
||||
if (!tmp) return eina_future_rejected(efl_loop_future_scheduler_get(obj), ENOMEM);
|
||||
v->buffer = tmp;
|
||||
memset(v->buffer + v->buffer_count, 0, rcount - v->buffer_count);
|
||||
v->buffer_count = rcount;
|
||||
}
|
||||
|
||||
// It is assumed that during slice get the buffer is properly sized
|
||||
if (flag)
|
||||
v->buffer[pd->index >> 3] |= 1 << (pd->index & 0x7);
|
||||
else
|
||||
v->buffer[pd->index >> 3] &= ~(1 << (pd->index & 0x7));
|
||||
|
||||
return eina_future_resolved(efl_loop_future_scheduler_get(obj),
|
||||
eina_value_uchar_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(void *data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
|
||||
{
|
||||
Efl_Model_Slice_Request *req = data;
|
||||
unsigned int i, len;
|
||||
Eina_Value r = EINA_VALUE_EMPTY;
|
||||
Eo *target = NULL;
|
||||
|
||||
if (eina_value_type_get(&v) != EINA_VALUE_TYPE_ARRAY)
|
||||
goto on_error;
|
||||
|
||||
eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4);
|
||||
|
||||
EINA_VALUE_ARRAY_FOREACH(&v, len, i, target)
|
||||
{
|
||||
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
|
||||
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 rfuture;
|
||||
}
|
||||
on_error:
|
||||
efl_unref(req->parent);
|
||||
free(req);
|
||||
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
|
||||
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)
|
||||
_boolean_value_free(void *data)
|
||||
{
|
||||
efl_model_child_del(pd->composite_child, child);
|
||||
Efl_Model_Composite_Boolean_Value *value = data;
|
||||
|
||||
eina_stringshare_del(value->property);
|
||||
value->property = NULL;
|
||||
|
||||
free(value->buffer);
|
||||
value->buffer = NULL;
|
||||
value->buffer_count = 0;
|
||||
}
|
||||
|
||||
/**************** efl_model_accessor_slice **************/
|
||||
|
||||
static void
|
||||
_bool_children_cache_array_free(Eina_Array *children_cache)
|
||||
static Eo *
|
||||
_efl_model_composite_boolean_efl_object_constructor(Eo *obj, Efl_Model_Composite_Boolean_Data *pd)
|
||||
{
|
||||
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);
|
||||
}
|
||||
obj = efl_constructor(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS));
|
||||
|
||||
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->bool_children_cache;
|
||||
if (!obj) return NULL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
pd->values = eina_hash_stringshared_new(_boolean_value_free);
|
||||
|
||||
child_bool = eina_array_data_get(children_cache, acc->index + 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 *cpd;
|
||||
child_bool = efl_add_ref(EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS, NULL);
|
||||
cpd = efl_data_scope_get(child_bool, EFL_MODEL_COMPOSITE_BOOLEAN_CHILDREN_CLASS);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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->bool_children_cache)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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, int start)
|
||||
{
|
||||
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;
|
||||
acc->index = start;
|
||||
}
|
||||
|
||||
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->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)
|
||||
{
|
||||
// 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->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->composite_model)
|
||||
{
|
||||
efl_unref(pd->composite_model);
|
||||
pd->composite_model = NULL;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
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);
|
||||
eina_hash_free(pd->values);
|
||||
|
||||
efl_destructor(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS));
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_model_composite_boolean_efl_ui_view_model_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Model_Composite_Boolean_Data *pd, Efl_Model *model)
|
||||
_efl_model_composite_boolean_boolean_add(Eo *obj EINA_UNUSED,
|
||||
Efl_Model_Composite_Boolean_Data *pd,
|
||||
const char *name, Eina_Bool default_value)
|
||||
{
|
||||
if (pd->composite_model)
|
||||
{
|
||||
_composite_model_data_reset(pd);
|
||||
}
|
||||
Efl_Model_Composite_Boolean_Value *value;
|
||||
|
||||
pd->composite_model = efl_ref(model);
|
||||
}
|
||||
if (!name) return ;
|
||||
|
||||
static Efl_Model *
|
||||
_efl_model_composite_boolean_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
|
||||
{
|
||||
return pd->composite_model;
|
||||
value = calloc(1, sizeof (Efl_Model_Composite_Boolean_Value));
|
||||
if (!value) return ;
|
||||
|
||||
value->property = eina_stringshare_add(name);
|
||||
value->default_value = default_value;
|
||||
|
||||
eina_hash_direct_add(pd->values, value->property, value);
|
||||
}
|
||||
|
||||
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)
|
||||
_efl_model_composite_boolean_boolean_del(Eo *obj EINA_UNUSED,
|
||||
Efl_Model_Composite_Boolean_Data *pd,
|
||||
const char *name)
|
||||
{
|
||||
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);
|
||||
Eina_Stringshare *s;
|
||||
|
||||
s = eina_stringshare_add(name);
|
||||
eina_hash_del(pd->values, s, NULL);
|
||||
eina_stringshare_del(s);
|
||||
}
|
||||
|
||||
static const Eina_Array *
|
||||
_efl_model_composite_boolean_efl_model_properties_get(const Eo *obj EINA_UNUSED, Efl_Model_Composite_Boolean_Data *pd)
|
||||
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)
|
||||
{
|
||||
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_Model_Slice_Request *req;
|
||||
Eina_Future *f;
|
||||
|
||||
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);
|
||||
f = efl_model_children_slice_get(efl_super(obj, EFL_MODEL_COMPOSITE_BOOLEAN_CLASS),
|
||||
start, count);
|
||||
|
||||
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, efl_main_loop_get());
|
||||
Efl_Future *rfuture = efl_promise_future_get(promise);
|
||||
req = malloc(sizeof (Efl_Model_Slice_Request));
|
||||
if (!req) return eina_future_rejected(efl_loop_future_scheduler_get(obj),
|
||||
ENOMEM);
|
||||
req->parent = efl_ref(obj);
|
||||
req->start = start;
|
||||
|
||||
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, efl_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, efl_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, start);
|
||||
|
||||
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, efl_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);
|
||||
}
|
||||
return efl_future_Eina_FutureXXX_then(obj,
|
||||
eina_future_then(f, _efl_model_composite_boolean_then, req));
|
||||
}
|
||||
|
||||
#include "efl_model_composite_boolean.eo.c"
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
class Efl.Model_Composite_Boolean (Efl.Object, Efl.Model, Efl.Ui.View)
|
||||
class Efl.Model_Composite_Boolean (Efl.Model_Composite)
|
||||
{
|
||||
[[Efl model composite boolean class]]
|
||||
methods {
|
||||
property_add {
|
||||
[[Adds property]]
|
||||
boolean_add {
|
||||
[[Add a new named boolean property with a defined default value.]]
|
||||
params {
|
||||
@in name: string; [[Property name]]
|
||||
@in initial_value: bool; [[Initial property value $bool]]
|
||||
}
|
||||
@in name: string;
|
||||
@in default_value: bool;
|
||||
}
|
||||
}
|
||||
boolean_del {
|
||||
[[Delete an existing named boolean property]]
|
||||
params {
|
||||
@in name: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
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;
|
||||
Efl.Ui.View.model { set; get; }
|
||||
}
|
||||
constructors {
|
||||
Efl.Ui.View.model;
|
||||
.property_add @optional;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
class Efl.Model_Composite_Boolean_Children (Efl.Object, Efl.Model)
|
||||
class Efl.Model_Composite_Boolean_Children (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.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;
|
||||
Efl.Model.property { get; set; }
|
||||
Efl.Object.finalize;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue