forked from enlightenment/efl
ecore: correctly handle children removal in Efl.Composite_Model by updating all required index.
Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de> Differential Revision: https://phab.enlightenment.org/D10032
This commit is contained in:
parent
06d328ffd1
commit
6e49752712
|
@ -40,7 +40,26 @@ static int
|
||||||
_children_indexed_key(const Efl_Composite_Model_Data *node,
|
_children_indexed_key(const Efl_Composite_Model_Data *node,
|
||||||
const int *key, int length EINA_UNUSED, void *data EINA_UNUSED)
|
const int *key, int length EINA_UNUSED, void *data EINA_UNUSED)
|
||||||
{
|
{
|
||||||
return node->index - *key;
|
if (node->index > (unsigned int) *key) return 1;
|
||||||
|
if (node->index < (unsigned int) *key) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_mark_greater(Efl_Composite_Model_Data *root, Eina_Array *mark, const unsigned int upper)
|
||||||
|
{
|
||||||
|
if (!root) return ;
|
||||||
|
|
||||||
|
if (root->index > upper)
|
||||||
|
{
|
||||||
|
eina_array_push(mark, root);
|
||||||
|
_mark_greater((void*) EINA_RBTREE_GET(root)->son[0], mark, upper);
|
||||||
|
_mark_greater((void*) EINA_RBTREE_GET(root)->son[1], mark, upper);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_mark_greater((void*) EINA_RBTREE_GET(root)->son[0], mark, upper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -136,20 +155,75 @@ _efl_composite_model_index_get(const Eo *obj, Efl_Composite_Model_Data *pd)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_efl_composite_model_child_event(Efl_Composite_Model_Data *pd,
|
||||||
|
const Efl_Model_Children_Event *ev,
|
||||||
|
const Efl_Event_Description *description)
|
||||||
|
{
|
||||||
|
Efl_Composite_Model_Data *cpd;
|
||||||
|
Efl_Model_Children_Event cev = { 0 };
|
||||||
|
Eina_Array mark;
|
||||||
|
Eina_Array_Iterator iterator;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
cev.index = ev->index;
|
||||||
|
if (ev->child)
|
||||||
|
{
|
||||||
|
cev.child = _efl_composite_lookup(efl_class_get(pd->self),
|
||||||
|
pd->self, ev->child, ev->index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpd = (void*) eina_rbtree_inline_lookup(pd->indexed, &cev.index, sizeof (unsigned int),
|
||||||
|
EINA_RBTREE_CMP_KEY_CB(_children_indexed_key), NULL);
|
||||||
|
if (cpd) cev.child = efl_ref(cpd->self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cev.child && description == EFL_MODEL_EVENT_CHILD_REMOVED)
|
||||||
|
{
|
||||||
|
cpd = efl_data_scope_get(cev.child, EFL_COMPOSITE_MODEL_CLASS);
|
||||||
|
|
||||||
|
// Remove child from lookup tree if it exist before triggering anything further
|
||||||
|
pd->indexed = eina_rbtree_inline_remove(pd->indexed, EINA_RBTREE_GET(cpd),
|
||||||
|
EINA_RBTREE_CMP_NODE_CB(_children_indexed_cmp), NULL);
|
||||||
|
cpd->inserted = EINA_FALSE;
|
||||||
|
efl_replace(&cpd->source, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all index above this one if necessaryy
|
||||||
|
eina_array_step_set(&mark, sizeof (Eina_Array), 8);
|
||||||
|
_mark_greater((void*) pd->indexed, &mark, cev.index);
|
||||||
|
|
||||||
|
// Correct index of the object stored that need to
|
||||||
|
// There is no need to remove and reinsert them as their relative order will not change.
|
||||||
|
EINA_ARRAY_ITER_NEXT(&mark, i, cpd, iterator)
|
||||||
|
{
|
||||||
|
if (description == EFL_MODEL_EVENT_CHILD_REMOVED) cpd->index--;
|
||||||
|
else cpd->index++;
|
||||||
|
|
||||||
|
efl_ref(cpd->self);
|
||||||
|
}
|
||||||
|
|
||||||
|
efl_event_callback_call(pd->self, description, &cev);
|
||||||
|
|
||||||
|
// Notify of the index change only after notifying of the removal top avoid overlap
|
||||||
|
EINA_ARRAY_ITER_NEXT(&mark, i, cpd, iterator)
|
||||||
|
{
|
||||||
|
efl_model_properties_changed(cpd->self, EFL_COMPOSITE_MODEL_CHILD_INDEX);
|
||||||
|
efl_unref(cpd->self);
|
||||||
|
}
|
||||||
|
eina_array_flush(&mark);
|
||||||
|
|
||||||
|
efl_unref(cev.child);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_efl_composite_model_child_added(void *data, const Efl_Event *event)
|
_efl_composite_model_child_added(void *data, const Efl_Event *event)
|
||||||
{
|
{
|
||||||
Efl_Composite_Model_Data *pd = data;
|
Efl_Composite_Model_Data *pd = data;
|
||||||
Efl_Model_Children_Event *ev = event->info;
|
Efl_Model_Children_Event *ev = event->info;
|
||||||
Efl_Model_Children_Event cev = { 0 };
|
|
||||||
|
|
||||||
cev.index = ev->index;
|
_efl_composite_model_child_event(pd, ev, EFL_MODEL_EVENT_CHILD_ADDED);
|
||||||
if (ev->child)
|
|
||||||
cev.child = _efl_composite_lookup(efl_class_get(pd->self),
|
|
||||||
pd->self, ev->child, ev->index);
|
|
||||||
efl_event_callback_call(pd->self, EFL_MODEL_EVENT_CHILD_ADDED, &cev);
|
|
||||||
|
|
||||||
efl_unref(cev.child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -157,16 +231,8 @@ _efl_composite_model_child_removed(void *data, const Efl_Event *event)
|
||||||
{
|
{
|
||||||
Efl_Composite_Model_Data *pd = data;
|
Efl_Composite_Model_Data *pd = data;
|
||||||
Efl_Model_Children_Event *ev = event->info;
|
Efl_Model_Children_Event *ev = event->info;
|
||||||
Efl_Model_Children_Event cev = { 0 };
|
|
||||||
|
|
||||||
cev.index = ev->index;
|
_efl_composite_model_child_event(pd, ev, EFL_MODEL_EVENT_CHILD_REMOVED);
|
||||||
if (ev->child)
|
|
||||||
cev.child = _efl_composite_lookup(efl_class_get(pd->self),
|
|
||||||
pd->self, ev->child, ev->index);
|
|
||||||
|
|
||||||
efl_event_callback_call(pd->self, EFL_MODEL_EVENT_CHILD_REMOVED, &cev);
|
|
||||||
|
|
||||||
efl_unref(cev.child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EFL_CALLBACKS_ARRAY_DEFINE(composite_callbacks,
|
EFL_CALLBACKS_ARRAY_DEFINE(composite_callbacks,
|
||||||
|
@ -427,8 +493,7 @@ _efl_composite_model_efl_object_destructor(Eo *obj, Efl_Composite_Model_Data *pd
|
||||||
efl_event_callback_forwarder_del(pd->source, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, obj);
|
efl_event_callback_forwarder_del(pd->source, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, obj);
|
||||||
efl_event_callback_forwarder_del(pd->source, EFL_MODEL_EVENT_PROPERTIES_CHANGED, obj);
|
efl_event_callback_forwarder_del(pd->source, EFL_MODEL_EVENT_PROPERTIES_CHANGED, obj);
|
||||||
|
|
||||||
efl_unref(pd->source);
|
efl_replace(&pd->source, NULL);
|
||||||
pd->source = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
efl_destructor(efl_super(obj, EFL_COMPOSITE_MODEL_CLASS));
|
efl_destructor(efl_super(obj, EFL_COMPOSITE_MODEL_CLASS));
|
||||||
|
|
Loading…
Reference in New Issue