Moin,

I wrote a (not yet finished) patch to filter and search in gengrids. If
you like this feature I would step up to implement it for the other
grids/lists/...

But there are some questions in current stage:
* to allow the user to show a widget with the current searchstring:
  should i emit a signal or allow him to set a methods to
  start,hide,delete,update his widgets?
* should i add a default indicator?

current BUGS:
* item not shown after cancel: press w -> scroll -> backspace
* Your bug here

Any additional ideas I should implement, too?
Maybe sort by rating of the compare callback?

If you want to test it: the patch includes some addional lines for
elementary_test-> Gengrid in filter mode. If you want to test search
mode: replace elm_gengrid_filter_set by elm_gengrid_search_set.

Regards, Frederik

P.S.: Yes. the patch is not ecrustified, but it's not finished yet.
-- 
IRC: playya @ Freenode, Gimpnet
xmpp: [email protected]
identi.ca: playya
Index: src/lib/Elementary.h.in
===================================================================
--- src/lib/Elementary.h.in	(Revision 57300)
+++ src/lib/Elementary.h.in	(Arbeitskopie)
@@ -960,6 +960,11 @@
    EAPI void	           elm_gengrid_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI Elm_Gengrid_Item  *elm_gengrid_selected_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI const Eina_List   *elm_gengrid_selected_items_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_item_match_func_set(Evas_Object *obj, Eina_Compare_Cb cb) EINA_ARG_NONNULL(1,2);
+   EAPI void               elm_gengrid_search_set(Evas_Object *obj, Eina_Bool search) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_search_stop(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_filter_stop(Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI void               elm_gengrid_filter_set(Evas_Object *obj, Eina_Bool filter) EINA_ARG_NONNULL(1);
 
    EAPI Elm_Gengrid_Item  *elm_gengrid_item_append(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic,  const void *data, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
    EAPI Elm_Gengrid_Item  *elm_gengrid_item_prepend(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Evas_Smart_Cb func, const void *func_data) EINA_ARG_NONNULL(1);
Index: src/lib/elm_gengrid.c
===================================================================
--- src/lib/elm_gengrid.c	(Revision 57300)
+++ src/lib/elm_gengrid.c	(Arbeitskopie)
@@ -210,6 +210,7 @@
    Ecore_Job        *calc_job;
    Eina_List        *selected;
    Elm_Gengrid_Item *last_selected_item;
+   Elm_Gengrid_Item *last_search_item;
    double            align_x, align_y;
 
    Evas_Coord        pan_x, pan_y;
@@ -219,6 +220,12 @@
    long              count;
    int               walking;
 
+   struct
+   {
+        Eina_Compare_Cb   func;
+        char*             buf;
+   }match;
+
    Eina_Bool         horizontal : 1;
    Eina_Bool         on_hold : 1;
    Eina_Bool         longpressed : 1;
@@ -227,6 +234,8 @@
    Eina_Bool         wasselected : 1;
    Eina_Bool         always_select : 1;
    Eina_Bool         clear_me : 1;
+   Eina_Bool         search : 1;
+   Eina_Bool         filter : 1;
 };
 
 #define ELM_GENGRID_ITEM_FROM_INLIST(item) \
@@ -240,6 +249,7 @@
 
 static const char *widtype = NULL;
 static void      _item_hilight(Elm_Gengrid_Item *item);
+static void      _item_unhilight(Elm_Gengrid_Item *item);
 static void      _item_unrealize(Elm_Gengrid_Item *item);
 static void      _item_select(Elm_Gengrid_Item *item);
 static void      _item_unselect(Elm_Gengrid_Item *item);
@@ -262,6 +272,12 @@
 
 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
+static void _search_next(Evas_Object *obj, Eina_Bool cont);
+static void _search_prev(Evas_Object *obj);
+static void _search_finish(Evas_Object *obj);
+static void _filter_finish(Evas_Object *obj);
+static void _filter(Evas_Object *obj);
+static Eina_Bool _is_filtered(Elm_Gengrid_Item *i);
 
 static Eina_Bool
 _event_hook(Evas_Object       *obj,
@@ -294,7 +310,13 @@
 
    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
      {
-        if ((wd->horizontal) &&
+        if(wd->match.buf && wd->search)
+        {
+             _search_prev(obj);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+        }
+        else if ((wd->horizontal) &&
             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
               (_item_multi_select_up(wd)))
              || (_item_single_select_up(wd))))
@@ -315,7 +337,13 @@
      }
    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
      {
-        if ((wd->horizontal) &&
+        if(wd->match.buf && wd->search)
+        {
+            _search_next(obj, EINA_TRUE);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+        }
+        else if ((wd->horizontal) &&
             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
               (_item_multi_select_down(wd)))
              || (_item_single_select_down(wd))))
@@ -336,7 +364,13 @@
      }
    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
      {
-        if ((wd->horizontal) &&
+        if(wd->match.buf && wd->search)
+        {
+             _search_prev(obj);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+        }
+        else if ((wd->horizontal) &&
             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
               (_item_multi_select_left(wd)))
              || (_item_single_select_left(wd))))
@@ -357,7 +391,13 @@
      }
    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
      {
-        if ((wd->horizontal) &&
+        if(wd->match.buf && wd->search)
+        {
+            _search_next(obj, EINA_TRUE);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+        }
+        else if ((wd->horizontal) &&
             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
               (_item_multi_select_right(wd)))
              || (_item_single_select_right(wd))))
@@ -427,7 +467,12 @@
      }
    else if (!strcmp(ev->keyname, "Escape"))
      {
-        if (!_deselect_all_items(wd)) return EINA_FALSE;
+        if(wd->search && wd->match.buf)
+                _search_finish(obj);
+        else if(wd->filter && wd->match.buf)
+           _filter_finish(obj);
+        else
+                if (!_deselect_all_items(wd)) return EINA_FALSE;
         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
         return EINA_TRUE;
      }
@@ -436,6 +481,51 @@
         item = elm_gengrid_selected_item_get(obj);
         evas_object_smart_callback_call(item->wd->self, "clicked", item);
      }
+   else if(((wd->search || wd->filter) && (strlen(ev->key)) == 1))
+   {
+           int len = 0;
+           char* buf = wd->match.buf;
+           if(buf)
+                    len = strlen(buf);
+           wd->match.buf = calloc(len + 1 + 1, sizeof(char));
+           if(!wd->match.buf)
+                return EINA_FALSE;
+           if(buf)
+           {
+                memcpy(wd->match.buf, buf, len);
+                free(buf);
+           }
+           wd->match.buf[len] = ev->keyname[0];
+
+           if(wd->search)
+                _search_next(obj,EINA_FALSE);
+           else if(wd->filter)
+                    _filter(obj);
+   }
+   else if((wd->search || wd->filter) && wd->match.buf && !strcmp(ev->keyname, "BackSpace"))
+   {
+        if(strlen(wd->match.buf) == 1)
+        {
+            free(wd->match.buf);
+            wd->match.buf = NULL;
+            if(wd->search)
+                     _search_finish(obj);
+            else
+                     _filter_finish(obj);
+        }
+        else
+        {
+            int len = strlen(wd->match.buf);
+            wd->match.buf[len-1] = '\0';
+            if(wd->search)
+                     _search_next(obj, EINA_FALSE);
+            else
+                     _filter(obj);
+
+        }
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+        return EINA_TRUE;
+   }
    else return EINA_FALSE;
 
    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
@@ -698,6 +788,8 @@
 _del_hook(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
+   if(wd->match.buf)
+            free(wd->match.buf);
    free(wd);
 }
 
@@ -938,13 +1030,22 @@
    item->hilighted = EINA_TRUE;
 }
 
+
 static void
+_item_unhilight(Elm_Gengrid_Item *item)
+{
+   if ( (item->delete_me) || (item->selected)) return;
+   edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
+   item->hilighted = EINA_FALSE;
+}
+static void
 _item_realize(Elm_Gengrid_Item *item)
 {
    char buf[1024];
    char style[1024];
 
    if ((item->realized) || (item->delete_me)) return;
+   Widget_Data *wd = item->wd;
    item->base.view = edje_object_add(evas_object_evas_get(item->wd->self));
    edje_object_scale_set(item->base.view, elm_widget_scale_get(item->wd->self) *
                          _elm_config->scale);
@@ -1172,12 +1273,15 @@
    if (ELM_RECTS_INTERSECT(x, y, item->wd->item_width, item->wd->item_height,
                            cvx, cvy, cvw, cvh))
      {
-        _item_realize(item);
-        if (!was_realized)
-          evas_object_smart_callback_call(item->wd->self, "realized", item);
-        evas_object_move(item->base.view, x, y);
-        evas_object_resize(item->base.view, item->wd->item_width,
-                           item->wd->item_height);
+        if(!_is_filtered(item))
+        {
+                _item_realize(item);
+                if (!was_realized)
+                  evas_object_smart_callback_call(item->wd->self, "realized", item);
+                evas_object_move(item->base.view, x, y);
+                evas_object_resize(item->base.view, item->wd->item_width,
+                                   item->wd->item_height);
+        }
      }
    else
      {
@@ -1517,6 +1621,155 @@
    evas_object_smart_callback_call(data, "scroll", NULL);
 }
 
+static void 
+_search_next(Evas_Object *obj, Eina_Bool cont)
+{
+        Widget_Data *wd = elm_widget_data_get(obj);
+        Elm_Gengrid_Item  *item = wd->last_search_item;
+        if(cont)
+        {
+                 item = elm_gengrid_item_next_get(item);
+        }
+        else
+                item = elm_gengrid_first_item_get(obj);
+
+        if(!item)
+                 return;
+
+        for(;item;item=elm_gengrid_item_next_get(item))
+        {
+                if(!wd->match.func(item->base.data, wd->match.buf))
+                {
+                        elm_gengrid_item_bring_in(item);
+                        _item_hilight(item);
+                        if(wd->last_search_item)
+                            _item_unhilight(wd->last_search_item);
+                        wd->last_search_item = item;
+                        return;
+                }
+        }
+        item = elm_gengrid_first_item_get(obj);
+        for(;item != wd->last_search_item; item =elm_gengrid_item_next_get(item))
+        {
+                if(!wd->match.func(item->base.data, wd->match.buf))
+                {
+                        elm_gengrid_item_bring_in(item);
+                        _item_hilight(item);
+                        if(wd->last_search_item)
+                            _item_unhilight(wd->last_search_item);
+                        wd->last_search_item = item;
+                        return;
+                }
+        }
+}
+
+static void 
+_search_prev(Evas_Object *obj)
+{
+        Widget_Data *wd = elm_widget_data_get(obj);
+        Elm_Gengrid_Item  *item = wd->last_search_item;
+        item = elm_gengrid_item_prev_get(item);
+
+        if(!item)
+                 return;
+
+        for(;item;item=elm_gengrid_item_prev_get(item))
+        {
+                if(!wd->match.func(item->base.data, wd->match.buf))
+                {
+                        elm_gengrid_item_bring_in(item);
+                        _item_hilight(item);
+                        if(wd->last_search_item)
+                            _item_unhilight(wd->last_search_item);
+                        wd->last_search_item = item;
+                        return;
+                }
+        }
+
+        item = elm_gengrid_last_item_get(obj);
+        for(;item != wd->last_search_item; item = elm_gengrid_item_prev_get(item))
+        {
+                if(!wd->match.func(item->base.data, wd->match.buf))
+                {
+                        elm_gengrid_item_bring_in(item);
+                        _item_hilight(item);
+                        if(wd->last_search_item)
+                            _item_unhilight(wd->last_search_item);
+                        wd->last_search_item = item;
+                        return;
+                }
+        }
+}
+
+static void 
+_search_finish(Evas_Object *obj)
+{
+        Widget_Data *data = elm_widget_data_get(obj);
+        Elm_Gengrid_Item *item;
+        data->last_search_item = NULL;
+        if(data->match.buf)
+        {
+                free(data->match.buf);
+                data->match.buf = NULL;
+        }
+}
+
+static void 
+_filter_finish(Evas_Object *obj)
+{
+        Widget_Data *data = elm_widget_data_get(obj);
+        Elm_Gengrid_Item *item;
+        Evas_Object * o;
+        data->last_search_item = NULL;
+        item = elm_gengrid_first_item_get(obj);
+
+        if(data->match.buf)
+        {
+                free(data->match.buf);
+                data->match.buf = NULL;
+        }
+        printf("filter finished\n");
+
+        for(;item;item = elm_gengrid_item_next_get(item))
+        {
+                o = item->base.view;
+                 evas_object_show(o);
+        }
+}
+
+static void
+_filter(Evas_Object *obj)
+{
+        Widget_Data *wd = elm_widget_data_get(obj);
+        Elm_Gengrid_Item *item;
+        Evas_Object * o;
+        wd->last_search_item = NULL;
+        item = elm_gengrid_first_item_get(obj);
+        for(;item;item=elm_gengrid_item_next_get(item))
+        {
+                o = item->base.view;
+                Eina_Bool was_realized = item->realized;
+                if(!wd->match.func(item->base.data, wd->match.buf))
+                {
+                        evas_object_show(o);
+                }
+                else
+                {
+                        evas_object_hide(o);
+                }
+        }
+        evas_object_show(obj);
+}
+
+static Eina_Bool
+_is_filtered(Elm_Gengrid_Item *i)
+{
+        Widget_Data *wd = i->wd;
+        if(!wd->filter) return EINA_FALSE;
+        if(!wd->match.buf) return EINA_FALSE;
+        return (wd->match.func(i->base.data, wd->match.buf)) == 0 ? EINA_FALSE : EINA_TRUE;
+}
+
 /**
  * Add a new Gengrid object.
  *
@@ -1714,6 +1967,66 @@
 }
 
 /**
+ * TODO: write docs
+ */
+EAPI void elm_gengrid_item_match_func_set(Evas_Object *obj,
+                                            Eina_Compare_Cb cb)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   wd->match.func = cb;
+}
+
+/**
+ * TODO: write docs
+ */
+EAPI void
+elm_gengrid_search_set(Evas_Object *obj,
+                        Eina_Bool search)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if(!wd->filter && search)
+   {
+        wd->search = EINA_TRUE;
+   }
+   else
+        wd->search = EINA_FALSE;
+}
+
+EAPI void 
+elm_gengrid_search_stop(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   _search_finish(obj);
+
+}
+
+/**
+ * TODO: write docs
+ */
+EAPI void
+elm_gengrid_filter_set(Evas_Object *obj,
+                        Eina_Bool filter)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if(!wd->search && filter)
+   {
+        wd->filter = EINA_TRUE;
+   }
+   else
+        wd->filter = EINA_FALSE;
+}
+
+EAPI void
+elm_gengrid_filter_stop(Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   _filter_finish(obj);
+}
+
+/**
  * Add item to the end of the Gengrid.
  *
  * @param obj The Gengrid object.
Index: src/bin/test_gengrid.c
===================================================================
--- src/bin/test_gengrid.c	(Revision 57300)
+++ src/bin/test_gengrid.c	(Arbeitskopie)
@@ -141,6 +141,16 @@
    printf("sel item data [%p] on grid obj [%p], pointer [%p]\n", data, obj, event_info);
 }
 
+static int
+_compare_item(void* a1, void* a2)
+{
+        char* s = (char*)a2;
+        Testitem *ti = (Testitem*)a1;
+        printf("comparing %s == %s\n", s, ti->path);
+        char* p = strstr(ti->path, s);
+        return p == NULL;
+}
+
 void
 test_gengrid(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
@@ -162,6 +172,8 @@
    elm_gengrid_item_size_set(grid, 150, 150);
    elm_gengrid_horizontal_set(grid, EINA_FALSE);
    elm_gengrid_multi_select_set(grid, EINA_TRUE);
+   elm_gengrid_filter_set(grid, EINA_TRUE);
+   elm_gengrid_item_match_func_set(grid, _compare_item);
    evas_object_smart_callback_add(grid, "selected", grid_selected, NULL);
    evas_object_smart_callback_add(grid, "clicked", grid_clicked, NULL);
    evas_object_smart_callback_add(grid, "longpressed", grid_longpress, NULL);

Attachment: signature.asc
Description: Digital signature

------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in 
Real-Time with Splunk. Collect, index and harness all the fast moving IT data 
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business 
insights. http://p.sf.net/sfu/splunk-dev2dev 
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to