forked from enlightenment/efl
Implement elm index sorted insert
- Name index item as Elm_Index_Item - Add some other index functions: + Item find + Data get/set + Letter get I think this stuff will make easier to create index for dynamically created lists. SVN revision: 49171
This commit is contained in:
parent
de41ec04e3
commit
0fa431bcc0
|
@ -1266,6 +1266,7 @@ extern "C" {
|
|||
* vertical (two up/down buttons at the right side and text left aligned)
|
||||
*/
|
||||
|
||||
typedef struct _Elm_Index_Item Elm_Index_Item;
|
||||
EAPI Evas_Object *elm_index_add(Evas_Object *parent);
|
||||
EAPI void elm_index_active_set(Evas_Object *obj, Eina_Bool active);
|
||||
EAPI void elm_index_item_level_set(Evas_Object *obj, int level);
|
||||
|
@ -1275,9 +1276,14 @@ extern "C" {
|
|||
EAPI void elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item);
|
||||
EAPI void elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative);
|
||||
EAPI void elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative);
|
||||
EAPI void elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func);
|
||||
EAPI void elm_index_item_del(Evas_Object *obj, const void *item);
|
||||
EAPI Elm_Index_Item *elm_index_item_find(Evas_Object *obj, const void *item);
|
||||
EAPI void elm_index_item_clear(Evas_Object *obj);
|
||||
EAPI void elm_index_item_go(Evas_Object *obj, int level);
|
||||
EAPI void *elm_index_item_data_get(const Elm_Index_Item *item);
|
||||
EAPI void elm_index_item_data_set(Elm_Index_Item *it, const void *data);
|
||||
EAPI const char *elm_index_item_letter_get(const Elm_Index_Item *item);
|
||||
/* smart callbacks called:
|
||||
* "changed" - when the selected index item changes
|
||||
* "delay,changed" - when the selected index item changes, but after some small idle period
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
*/
|
||||
|
||||
typedef struct _Widget_Data Widget_Data;
|
||||
typedef struct _Item Item;
|
||||
|
||||
struct _Widget_Data
|
||||
{
|
||||
|
@ -26,7 +25,7 @@ struct _Widget_Data
|
|||
Eina_Bool down : 1;
|
||||
};
|
||||
|
||||
struct _Item
|
||||
struct _Elm_Index_Item
|
||||
{
|
||||
Evas_Object *obj;
|
||||
const char *letter;
|
||||
|
@ -42,13 +41,13 @@ static void _theme_hook(Evas_Object *obj);
|
|||
static void _sizing_eval(Evas_Object *obj);
|
||||
static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
|
||||
static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
|
||||
static void _item_free(Item *it);
|
||||
static void _item_free(Elm_Index_Item *it);
|
||||
|
||||
static void
|
||||
_del_hook(Evas_Object *obj)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
Eina_List *l, *clear = NULL;
|
||||
if (!wd) return;
|
||||
_index_box_clear(obj, wd->bx[wd->level], wd->level);
|
||||
|
@ -138,13 +137,13 @@ _sizing_eval(Evas_Object *obj)
|
|||
evas_object_size_hint_max_set(obj, maxw, maxh);
|
||||
}
|
||||
|
||||
static Item *
|
||||
static Elm_Index_Item *
|
||||
_item_new(Evas_Object *obj, const char *letter, const void *item)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return NULL;
|
||||
it = calloc(1, sizeof(Item));
|
||||
it = calloc(1, sizeof(Elm_Index_Item));
|
||||
if (!it) return NULL;
|
||||
it->obj = obj;
|
||||
it->letter = eina_stringshare_add(letter);
|
||||
|
@ -153,12 +152,12 @@ _item_new(Evas_Object *obj, const char *letter, const void *item)
|
|||
return it;
|
||||
}
|
||||
|
||||
static Item *
|
||||
static Elm_Index_Item *
|
||||
_item_find(Evas_Object *obj, const void *item)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *l;
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return NULL;
|
||||
EINA_LIST_FOREACH(wd->items, l, it)
|
||||
if (it->data == item) return it;
|
||||
|
@ -166,7 +165,7 @@ _item_find(Evas_Object *obj, const void *item)
|
|||
}
|
||||
|
||||
static void
|
||||
_item_free(Item *it)
|
||||
_item_free(Elm_Index_Item *it)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(it->obj);
|
||||
if (!wd) return;
|
||||
|
@ -182,7 +181,7 @@ _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
|
|||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *l;
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
Evas_Coord mw, mh, w, h;
|
||||
int i = 0;
|
||||
if (!wd) return;
|
||||
|
@ -235,7 +234,7 @@ _index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
|
|||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *l;
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return;
|
||||
if (!wd->level_active[level]) return;
|
||||
EINA_LIST_FOREACH(wd->items, l, it)
|
||||
|
@ -264,7 +263,7 @@ static void
|
|||
_sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it, *it_closest, *it_last;
|
||||
Elm_Index_Item *it, *it_closest, *it_last;
|
||||
Eina_List *l;
|
||||
Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
|
||||
double cdv = 0.5;
|
||||
|
@ -614,7 +613,7 @@ elm_index_item_selected_get(const Evas_Object *obj, int level)
|
|||
ELM_CHECK_WIDTYPE(obj, widtype) NULL;
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *l;
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return NULL;
|
||||
EINA_LIST_FOREACH(wd->items, l, it)
|
||||
if ((it->selected) && (it->level == level)) return it->data;
|
||||
|
@ -635,7 +634,7 @@ elm_index_item_append(Evas_Object *obj, const char *letter, const void *item)
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return;
|
||||
it = _item_new(obj, letter, item);
|
||||
if (!it) return;
|
||||
|
@ -657,7 +656,7 @@ elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item)
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
|
||||
if (!wd) return;
|
||||
it = _item_new(obj, letter, item);
|
||||
|
@ -681,7 +680,7 @@ elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it, *it_rel;
|
||||
Elm_Index_Item *it, *it_rel;
|
||||
if (!wd) return;
|
||||
if (!relative)
|
||||
{
|
||||
|
@ -715,7 +714,7 @@ elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it, *it_rel;
|
||||
Elm_Index_Item *it, *it_rel;
|
||||
if (!wd) return;
|
||||
if (!relative)
|
||||
{
|
||||
|
@ -734,6 +733,62 @@ elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void
|
|||
_index_box_clear(obj, wd->bx[wd->level], wd->level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new @p item into the sorted index @p obj in @p letter.
|
||||
*
|
||||
* @param obj The index object
|
||||
* @param letter Letter under which the item should be indexed
|
||||
* @param item The item to put in the index
|
||||
* @param cmp_func The function called for the sort of index items.
|
||||
* @param cmp_data_func The function called for the sort of the data. It will
|
||||
* be used when cmp_func return 0. It means the index item already exists.
|
||||
* So, to decide which data item should be pointed by the index item, a function
|
||||
* to compare them is needed. If this function is not provided, index items
|
||||
* will be duplicated.
|
||||
*
|
||||
* @ingroup Index
|
||||
*/
|
||||
EAPI void
|
||||
elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, const void *item, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func)
|
||||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *lnear;
|
||||
Elm_Index_Item *it;
|
||||
int cmp;
|
||||
|
||||
if (!wd) return;
|
||||
if (!(wd->items))
|
||||
{
|
||||
elm_index_item_append(obj, letter, item);
|
||||
return;
|
||||
}
|
||||
|
||||
it = _item_new(obj, letter, item);
|
||||
if (!it) return;
|
||||
|
||||
lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
|
||||
if (cmp < 0)
|
||||
wd->items = eina_list_append_relative_list(wd->items, it, lnear);
|
||||
else if (cmp > 0)
|
||||
wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
|
||||
else
|
||||
{
|
||||
/* If cmp_data_func is not provided, append a duplicated item */
|
||||
if (!cmp_data_func)
|
||||
wd->items = eina_list_append_relative_list(wd->items, it, lnear);
|
||||
else
|
||||
{
|
||||
Elm_Index_Item *p_it = eina_list_data_get(lnear);
|
||||
if (cmp_data_func(p_it->data, it->data) >= 0)
|
||||
p_it->data = it->data;
|
||||
_item_free(it);
|
||||
}
|
||||
}
|
||||
|
||||
_index_box_clear(obj, wd->bx[wd->level], wd->level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the index.
|
||||
*
|
||||
|
@ -747,7 +802,7 @@ elm_index_item_del(Evas_Object *obj, const void *item)
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
if (!wd) return;
|
||||
it = _item_find(obj, item);
|
||||
if (!it) return;
|
||||
|
@ -755,6 +810,24 @@ elm_index_item_del(Evas_Object *obj, const void *item)
|
|||
_index_box_clear(obj, wd->bx[wd->level], wd->level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an index item using item data.
|
||||
*
|
||||
* @param obj The index object
|
||||
* @param item The item pointed by index item
|
||||
* @return The index item pointing to @p item
|
||||
*
|
||||
* @ingroup Index
|
||||
*/
|
||||
EAPI Elm_Index_Item *
|
||||
elm_index_item_find(Evas_Object *obj, const void *item)
|
||||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
if (!wd) return NULL;
|
||||
return _item_find(obj, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears an index of its items.
|
||||
*
|
||||
|
@ -767,7 +840,7 @@ elm_index_item_clear(Evas_Object *obj)
|
|||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Item *it;
|
||||
Elm_Index_Item *it;
|
||||
Eina_List *l, *clear = NULL;
|
||||
if (!wd) return;
|
||||
_index_box_clear(obj, wd->bx[wd->level], wd->level);
|
||||
|
@ -796,3 +869,51 @@ elm_index_item_go(Evas_Object *obj, int level __UNUSED__)
|
|||
_index_box_auto_fill(obj, wd->bx[0], 0);
|
||||
if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated with the item.
|
||||
*
|
||||
* @param it The list item
|
||||
* @return The data associated with @p it
|
||||
*
|
||||
* @ingroup Index
|
||||
*/
|
||||
EAPI void *
|
||||
elm_index_item_data_get(const Elm_Index_Item *it)
|
||||
{
|
||||
if (!it) return NULL;
|
||||
return (void *)it->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data item from the index item
|
||||
*
|
||||
* This set a new data value.
|
||||
*
|
||||
* @param it The item
|
||||
* @param data The new data pointer to set
|
||||
*
|
||||
* @ingroup Index
|
||||
*/
|
||||
EAPI void
|
||||
elm_index_item_data_set(Elm_Index_Item *it, const void *data)
|
||||
{
|
||||
if (!it) return;
|
||||
it->data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the letter of the item.
|
||||
*
|
||||
* @param it The list item
|
||||
* @return The letter of @p it
|
||||
*
|
||||
* @ingroup Index
|
||||
*/
|
||||
EAPI const char *
|
||||
elm_index_item_letter_get(const Elm_Index_Item *it)
|
||||
{
|
||||
if (!it) return NULL;
|
||||
return it->letter;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue