#include "elm_widget.h"
#include "elm_priv.h"
-#define MY_CLASS EFL_UI_ITEM_CONTAINER_CLASS
-
-#define MY_DATA_GET(obj, pd) \
- Efl_Ui_Item_Container_Data *pd = efl_data_scope_get(obj, MY_CLASS);
-
typedef struct {
- Efl_Ui_Scroll_Manager *smanager;
- Efl_Ui_Pan *pan;
- Eina_List *selected;
- Eina_List *items;
- Efl_Ui_Select_Mode mode;
- Efl_Ui_Layout_Orientation dir;
- Eina_Size2D content_min_size;
- Efl_Ui_Position_Manager_Entity *pos_man;
- struct {
- Eina_Accessor pass_on;
- unsigned int last_index;
- const Eina_List *current;
- } obj_accessor;
- struct {
- Eina_Bool w;
- Eina_Bool h;
- } match_content;
- Eina_Accessor size_accessor;
- Efl_Gfx_Entity *sizer;
-} Efl_Ui_Item_Container_Data;
-
-static Eina_Bool register_item(Eo *obj, Efl_Ui_Item_Container_Data *pd, Efl_Ui_Item *item);
-static Eina_Bool unregister_item(Eo *obj, Efl_Ui_Item_Container_Data *pd, Efl_Ui_Item *item);
-
-static void
-flush_min_size(Eo *obj, Efl_Ui_Item_Container_Data *pd)
-{
- Eina_Size2D tmp = pd->content_min_size;
-
- if (!pd->match_content.w)
- tmp.w = -1;
-
- if (!pd->match_content.h)
- tmp.h = -1;
-
- efl_gfx_hint_size_min_set(obj, tmp);
-}
-
-static int
-clamp_index(Efl_Ui_Item_Container_Data *pd, int index)
-{
- if (index < ((int)eina_list_count(pd->items)) * -1)
- return -1;
- else if (index > (int)eina_list_count(pd->items) - 1)
- return 1;
- return 0;
-}
-
-static int
-index_adjust(Efl_Ui_Item_Container_Data *pd, int index)
-{
- int c = eina_list_count(pd->items);
- if (index < c * -1)
- return 0;
- else if (index > c - 1)
- return c - 1;
- else if (index < 0)
- return index + c;
- return index;
-}
+ Eina_Accessor acc;
+ unsigned int last_index;
+ const Eina_List *current;
+ Eina_List **items;
+} Fast_Accessor;
static Eina_Bool
-_obj_accessor_get_at(Eina_Accessor *accessor, unsigned int idx, void **data)
+_fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data)
{
- ptrdiff_t offset = offsetof(Efl_Ui_Item_Container_Data, obj_accessor);
- Efl_Ui_Item_Container_Data *pd = (void*)accessor - offset;
const Eina_List *over;
unsigned int middle;
unsigned int i;
- if (idx >= eina_list_count(pd->items))
+ if (idx >= eina_list_count(*accessor->items))
return EINA_FALSE;
- if (pd->obj_accessor.last_index == idx)
- over = pd->obj_accessor.current;
- else if (idx > pd->obj_accessor.last_index)
+ if (accessor->last_index == idx)
+ over = accessor->current;
+ else if (idx > accessor->last_index)
{
/* After current position. */
- middle = ((eina_list_count(pd->items) - pd->obj_accessor.last_index))/2;
+ middle = ((eina_list_count(*accessor->items) - accessor->last_index))/2;
if (idx > middle)
/* Go backward from the end. */
- for (i = eina_list_count(pd->items) - 1,
- over = eina_list_last(pd->items);
+ for (i = eina_list_count(*accessor->items) - 1,
+ over = eina_list_last(*accessor->items);
i > idx && over;
--i, over = eina_list_prev(over))
;
else
/* Go forward from current. */
- for (i = pd->obj_accessor.last_index, over = pd->obj_accessor.current;
+ for (i = accessor->last_index, over = accessor->current;
i < idx && over;
++i, over = eina_list_next(over))
;
else
{
/* Before current position. */
- middle = pd->obj_accessor.last_index/2;
+ middle = accessor->last_index/2;
if (idx > middle)
/* Go backward from current. */
- for (i = pd->obj_accessor.last_index, over = pd->obj_accessor.current;
+ for (i = accessor->last_index, over = accessor->current;
i > idx && over;
--i, over = eina_list_prev(over))
;
else
/* Go forward from start. */
- for (i = 0, over = pd->items;
+ for (i = 0, over = *accessor->items;
i < idx && over;
++i, over = eina_list_next(over))
;
if (!over)
return EINA_FALSE;
- pd->obj_accessor.last_index = idx;
- pd->obj_accessor.current = over;
+ accessor->last_index = idx;
+ accessor->current = over;
*data = eina_list_data_get(over);
return EINA_TRUE;
}
+
static Eina_Accessor*
-_obj_clone(Eina_Accessor *accessor)
+_fast_accessor_clone(Fast_Accessor *accessor)
{
- ptrdiff_t offset = offsetof(Efl_Ui_Item_Container_Data, obj_accessor);
- Efl_Ui_Item_Container_Data *pd = (void*)accessor - offset;
-
- return eina_list_accessor_new(pd->items);
+ return eina_list_accessor_new(*accessor->items);
}
static Eina_List *
-_null_container(Eina_Accessor *accessor EINA_UNUSED)
+_fast_accessor_get_container(Fast_Accessor *accessor EINA_UNUSED)
{
ERR("Not allowed to get a container!");
return NULL;
}
static void
-_free(Eina_Accessor *accessor EINA_UNUSED)
+_fast_accessor_free(Fast_Accessor *accessor EINA_UNUSED)
{
ERR("Freeing this accessor is not supported");
}
static void
-_obj_accessor_init(Eina_Accessor *accessor)
+_fast_accessor_init(Fast_Accessor *accessor, Eina_List **items)
{
//this is the accessor for accessing the items
//we have to workarround here the problem that
//no accessor can be created for a not yet created list.
- accessor->version = EINA_ACCESSOR_VERSION;
- accessor->get_at = FUNC_ACCESSOR_GET_AT(_obj_accessor_get_at);
- accessor->clone = FUNC_ACCESSOR_CLONE(_obj_clone);
- accessor->get_container = FUNC_ACCESSOR_GET_CONTAINER(_null_container);
- accessor->free = FUNC_ACCESSOR_FREE(_free);
- EINA_MAGIC_SET(accessor, EINA_MAGIC_ACCESSOR);
+ accessor->acc.version = EINA_ACCESSOR_VERSION;
+ accessor->acc.get_at = FUNC_ACCESSOR_GET_AT(_fast_accessor_get_at);
+ accessor->acc.clone = FUNC_ACCESSOR_CLONE(_fast_accessor_clone);
+ accessor->acc.get_container = FUNC_ACCESSOR_GET_CONTAINER(_fast_accessor_get_container);
+ accessor->acc.free = FUNC_ACCESSOR_FREE(_fast_accessor_free);
+ EINA_MAGIC_SET(&accessor->acc, EINA_MAGIC_ACCESSOR);
+ accessor->items = items;
}
-static Eina_Bool
-_size_accessor_get_at(Eina_Accessor *accessor, unsigned int idx, void **data)
+static void
+_fast_accessor_remove(Fast_Accessor *accessor, const Eina_List *removed_elem)
{
- Eina_Size2D *size = (Eina_Size2D*)data;
- ptrdiff_t offset = offsetof(Efl_Ui_Item_Container_Data, size_accessor);
- Efl_Ui_Item_Container_Data *pd = (void*)accessor - offset;
+ if (accessor->current == removed_elem)
+ {
+ Eina_List *next;
+ Eina_List *prev;
- if (idx > eina_list_count(pd->items))
- return EINA_FALSE;
+ next = eina_list_next(removed_elem);
+ prev = eina_list_prev(removed_elem);
+ if (next)
+ {
+ accessor->current = next;
+ accessor->last_index ++;
+ }
+ else if (prev)
+ {
+ accessor->current = prev;
+ accessor->last_index --;
+ }
+ else
+ {
+ //everything >= length is invalid, and we need that.
+ accessor->last_index = eina_list_count(*accessor->items);
+ accessor->current = NULL;
+ }
- Eo *subobj = eina_list_nth(pd->items, idx);
+ }
- *size = efl_gfx_hint_size_combined_min_get(subobj);
+}
- return EINA_TRUE;
+#define MY_CLASS EFL_UI_ITEM_CONTAINER_CLASS
+
+#define MY_DATA_GET(obj, pd) \
+ Efl_Ui_Item_Container_Data *pd = efl_data_scope_get(obj, MY_CLASS);
+
+typedef struct {
+ Efl_Ui_Scroll_Manager *smanager;
+ Efl_Ui_Pan *pan;
+ Eina_List *selected;
+ Eina_List *items;
+ Efl_Ui_Select_Mode mode;
+ Efl_Ui_Layout_Orientation dir;
+ Eina_Size2D content_min_size;
+ Efl_Ui_Position_Manager_Entity *pos_man;
+ struct {
+ Eina_Bool w;
+ Eina_Bool h;
+ } match_content;
+ Fast_Accessor obj_accessor;
+ Fast_Accessor size_accessor;
+ Efl_Gfx_Entity *sizer;
+} Efl_Ui_Item_Container_Data;
+
+static Eina_Bool register_item(Eo *obj, Efl_Ui_Item_Container_Data *pd, Efl_Ui_Item *item);
+static Eina_Bool unregister_item(Eo *obj, Efl_Ui_Item_Container_Data *pd, Efl_Ui_Item *item);
+
+static void
+flush_min_size(Eo *obj, Efl_Ui_Item_Container_Data *pd)
+{
+ Eina_Size2D tmp = pd->content_min_size;
+
+ if (!pd->match_content.w)
+ tmp.w = -1;
+
+ if (!pd->match_content.h)
+ tmp.h = -1;
+
+ efl_gfx_hint_size_min_set(obj, tmp);
}
-static Eina_Accessor*
-_size_clone(Eina_Accessor *accessor EINA_UNUSED)
+static int
+clamp_index(Efl_Ui_Item_Container_Data *pd, int index)
{
- return NULL;
+ if (index < ((int)eina_list_count(pd->items)) * -1)
+ return -1;
+ else if (index > (int)eina_list_count(pd->items) - 1)
+ return 1;
+ return 0;
}
-static void
-_size_accessor_init(Eina_Accessor *accessor)
+static int
+index_adjust(Efl_Ui_Item_Container_Data *pd, int index)
{
- accessor->version = EINA_ACCESSOR_VERSION;
- accessor->get_at = FUNC_ACCESSOR_GET_AT(_size_accessor_get_at);
- accessor->clone = FUNC_ACCESSOR_CLONE(_size_clone);
- accessor->get_container = FUNC_ACCESSOR_GET_CONTAINER(_null_container);
- accessor->free = FUNC_ACCESSOR_FREE(_free);
- EINA_MAGIC_SET(accessor, EINA_MAGIC_ACCESSOR);
+ int c = eina_list_count(pd->items);
+ if (index < c * -1)
+ return 0;
+ else if (index > c - 1)
+ return c - 1;
+ else if (index < 0)
+ return index + c;
+ return index;
}
static void
return eina_list_iterator_new(pd->selected);
}
+static Eina_Bool
+_size_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data)
+{
+ Eina_Bool res = EINA_FALSE;
+ Efl_Gfx_Entity *geom;
+ Eina_Size2D *size = (void*)data;
+
+ res = _fast_accessor_get_at(accessor, idx,(void*) &geom);
+
+ if (!res) return EINA_FALSE;
+
+ *size = efl_gfx_hint_size_min_get(geom);
+
+ return res;
+}
+
+
EOLIAN static Efl_Object*
_efl_ui_item_container_efl_object_constructor(Eo *obj, Efl_Ui_Item_Container_Data *pd EINA_UNUSED)
{
pd->dir = EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
- _obj_accessor_init(&pd->obj_accessor.pass_on);
- _size_accessor_init(&pd->size_accessor);
+ _fast_accessor_init(&pd->obj_accessor, &pd->items);
+ _fast_accessor_init(&pd->size_accessor, &pd->items);
+ pd->size_accessor.acc.get_at = FUNC_ACCESSOR_GET_AT(_size_accessor_get_at);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "item_container");
return EINA_FALSE;
unsigned int id = eina_list_data_idx(pd->items, item);
- if (pd->obj_accessor.last_index == id)
- {
- if (eina_list_next(elem))
- {
- pd->obj_accessor.current = eina_list_next(elem);
- }
- else if (eina_list_prev(elem))
- {
- pd->obj_accessor.last_index = id-1;
- pd->obj_accessor.current = eina_list_prev(elem);
- }
- else
- {
- //everything >= length is invalid, and we need that.
- pd->obj_accessor.last_index = eina_list_count(pd->items);
- pd->obj_accessor.current = NULL;
- }
- }
+ _fast_accessor_remove(&pd->obj_accessor, elem);
+ _fast_accessor_remove(&pd->size_accessor, elem);
pd->items = eina_list_remove(pd->items, item);
pd->selected = eina_list_remove(pd->selected, item);
{
pd->obj_accessor.last_index = id;
pd->obj_accessor.current = pd->items;
+ pd->size_accessor.last_index = id;
+ pd->size_accessor.current = pd->items;
}
efl_ui_position_manager_entity_item_added(pd->pos_man, id, subobj);
}
{
efl_parent_set(pd->pos_man, obj);
efl_event_callback_array_add(pd->pos_man, pos_manager_cbs(), obj);
- efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.pass_on, &pd->size_accessor, eina_list_count(pd->items));
+ efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items));
efl_ui_position_manager_entity_viewport_set(pd->pos_man, efl_ui_scrollable_viewport_geometry_get(obj));
efl_ui_layout_orientation_set(pd->pos_man, pd->dir);
}