Implement elm index sorted insert
authorBruno Dilly <bdilly@profusion.mobi>
Sun, 23 May 2010 23:41:32 +0000 (23:41 +0000)
committerBruno Dilly <bdilly@profusion.mobi>
Sun, 23 May 2010 23:41:32 +0000 (23:41 +0000)
 - 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

src/lib/Elementary.h.in
src/lib/elm_index.c

index 5ad9af4..f1de498 100644 (file)
@@ -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
index af2c1e2..fb601b8 100644 (file)
@@ -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)
      {
@@ -735,6 +734,62 @@ elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void
 }
 
 /**
+ * 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.
  *
  * @param obj The index object
@@ -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;
@@ -756,6 +811,24 @@ elm_index_item_del(Evas_Object *obj, const void *item)
 }
 
 /**
+ * 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.
  *
  * @param obj The index object.
@@ -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;
+}
+