summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKateryna Fesyna <k.fesyna@samsung.com>2014-05-27 15:53:11 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-05-27 15:55:05 +0900
commite4e57dc1949e7e2f5a08e54ceda039c6ab3c47f4 (patch)
treecdc0ee1a093517023e2f1ff3de127cf873dfec98
parent71fc5afd638dc0e59403bd774a4bcc72e9db84e0 (diff)
downloadelementary-e4e57dc1949e7e2f5a08e54ceda039c6ab3c47f4.tar.gz
Genlist: Add function to search item by string.
Summary: This function allows user to search for item in Genlist. It takes four search parameters: 1. pointer to function to get text of the item. It could be the same with item's get_text function. This parameter is added to let user use the specific search key and to avoid problems with setting item's text, that is not constant. 2. pointer to the item from which search should start. 3. search pattern. 4. fnmatch() flags. To check it's usage the new test is added to the elementary_test (Genlist Item Search By Text) Reviewers: cedric, seoz, raster CC: reutskiy.v.v Differential Revision: https://phab.enlightenment.org/D566
-rw-r--r--src/bin/test.c2
-rw-r--r--src/bin/test_genlist.c272
-rw-r--r--src/lib/elm_genlist.c29
-rw-r--r--src/lib/elm_genlist.eo45
-rw-r--r--src/lib/elm_genlist_legacy.h2
5 files changed, 349 insertions, 1 deletions
diff --git a/src/bin/test.c b/src/bin/test.c
index 9ff36fd8d..ada5c2516 100644
--- a/src/bin/test.c
+++ b/src/bin/test.c
@@ -112,6 +112,7 @@ void test_genlist16(void *data, Evas_Object *obj, void *event_info);
void test_genlist17(void *data, Evas_Object *obj, void *event_info);
void test_genlist18(void *data, Evas_Object *obj, void *event_info);
void test_genlist19(void *data, Evas_Object *obj, void *event_info);
+void test_genlist20(void *data, Evas_Object *obj, void *event_info);
void test_genlist_focus(void *data, Evas_Object *obj, void *event_info);
void test_genlist_item_styles(void *data, Evas_Object *obj, void *event_info);
void test_genlist_multi_select(void *data, Evas_Object *obj, void *event_info);
@@ -652,6 +653,7 @@ add_tests:
ADD_TEST(NULL, "Lists - Genlist", "Genlist Decorate Modes", test_genlist17);
ADD_TEST(NULL, "Lists - Genlist", "Genlist Tree and Decorate All Mode", test_genlist18);
ADD_TEST(NULL, "Lists - Genlist", "Genlist Full Widget", test_genlist19);
+ ADD_TEST(NULL, "Lists - Genlist", "Genlist Item Search By Text", test_genlist20);
ADD_TEST(NULL, "Lists - Genlist", "Genlist Focus", test_genlist_focus);
ADD_TEST(NULL, "Lists - Genlist", "Genlist Item Styles", test_genlist_item_styles);
ADD_TEST(NULL, "Lists - Genlist", "Genlist Multi Select", test_genlist_multi_select);
diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c
index ea9a4c6d1..d78f6455b 100644
--- a/src/bin/test_genlist.c
+++ b/src/bin/test_genlist.c
@@ -3468,6 +3468,278 @@ test_genlist_multi_select(void *data EINA_UNUSED,
evas_object_show(win);
}
+/* test genlist item search by text */
+
+typedef struct _gl20_Event_Data gl20_Event_Data;
+struct _gl20_Event_Data
+{
+ Evas_Object *gl_obj;
+ Evas_Object *tg_obj;
+ Evas_Object *en_obj;
+ Elm_Object_Item *last_item_found;
+};
+
+static const char *_gl20_items_text[] = {
+ "Albany", "Annapolis",
+ "Atlanta", "Augusta",
+ "Austin", "Baton Rouge",
+ "Bismarck", "Boise",
+ "Boston", "Carson City",
+ "Charleston", "Cheyenne",
+ "Columbia", "Columbus",
+ "Concord", "Denver",
+ "Des Moines", "Dover",
+ "Frankfort", "Harrisburg",
+ "Hartford", "Helena",
+ "Honolulu", "Indianapolis",
+ "Jackson", "Jefferson City",
+ "Juneau", "Lansing",
+ "Lincoln", "Little Rock",
+ "Madison", "Montgomery",
+ "Montpelier", "Nashville",
+ "Oklahoma City", "Olympia",
+ "Phoenix", "Pierre",
+ "Providence", "Raleigh",
+ "Richmond", "Sacramento",
+ "Saint Paul", "Salem",
+ "Salt Lake City", "Santa Fe",
+ "Springfield", "Tallahassee",
+ "Topeka", "Trenton" };
+
+static char *
+_gl20_search_text_get(void *data, Evas_Object *obj EINA_UNUSED,
+ const char *part EINA_UNUSED)
+{
+ char buf[32];
+ int item_index = (int)(uintptr_t)data;
+
+ if (item_index < 50)
+ {
+ snprintf(buf, sizeof(buf), "%s", _gl20_items_text[item_index]);
+ return strdup(buf);
+ }
+ else if (item_index < 100)
+ {
+ snprintf(buf, sizeof(buf), "%X", (item_index - 50));
+ return strdup(buf);
+ }
+ else if (item_index == 100)
+ return strdup("Tree Item");
+
+ return NULL;
+}
+
+static char *
+_gl20_text_get(void *data, Evas_Object *obj EINA_UNUSED,
+ const char *part EINA_UNUSED)
+{
+ char buf[64];
+ snprintf(buf, sizeof(buf), "(this text is not uset for search) %s",
+ _gl20_search_text_get(data, NULL, NULL));
+ return strdup(buf);
+}
+
+static void
+_gl20_searsh_item(gl20_Event_Data *event_data, Elm_Object_Item * it)
+{
+ const char *str = elm_entry_entry_get(event_data->en_obj);
+ if (!str || !strlen(str)) return;
+
+ int flag = 0;
+ if (!elm_check_state_get(event_data->tg_obj))
+ flag = FNM_CASEFOLD;
+
+ printf("Looking for \"%s\". ", str);
+ event_data->last_item_found = elm_genlist_search_by_text_item_get(event_data->gl_obj,
+ it, _gl20_search_text_get, NULL, str, flag);
+
+ if (event_data->last_item_found)
+ {
+ printf("Found.\n");
+ elm_genlist_item_selected_set(event_data->last_item_found, EINA_TRUE);
+ elm_genlist_item_bring_in(event_data->last_item_found,
+ ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
+ elm_object_focus_set(event_data->en_obj, EINA_TRUE);
+ }
+ else
+ printf("Not Found.\n");
+}
+
+static void
+_gl20_search_settings_changed_cb(void *data, Evas_Object *obj EINA_UNUSED,
+ void *einfo EINA_UNUSED)
+{
+ _gl20_searsh_item(data, NULL);
+}
+
+static Elm_Genlist_Item_Class *
+_gl20_item_class_create(const char *item_style)
+{
+ Elm_Genlist_Item_Class * itc = elm_genlist_item_class_new();
+ itc->item_style = item_style;
+ itc->func.text_get = _gl20_text_get;
+ itc->func.content_get = gl_content_get;
+ itc->func.state_get = gl_state_get;
+ itc->func.del = NULL;
+ return itc;
+}
+
+static void
+_gl20_expand_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED,
+ void *event_info)
+{
+ Elm_Object_Item *glit = event_info;
+ Evas_Object *gl = elm_object_item_widget_get(glit);
+ Elm_Genlist_Item_Class *itc = NULL;
+ int i = 0;
+
+ itc = _gl20_item_class_create("default");
+
+ for (i = 50; i < 100; i++)
+ {
+ elm_genlist_item_append(gl, itc,
+ (void *)(uintptr_t) i/* item data */,
+ glit/* parent */,
+ ELM_GENLIST_ITEM_NONE, NULL/* func */,
+ NULL/* func data */);
+ }
+ elm_genlist_item_class_free(itc);
+}
+
+static void _gl20_on_keydown(void *data, Evas *evas EINA_UNUSED,
+ Evas_Object *o EINA_UNUSED, void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+ gl20_Event_Data * event_data = (gl20_Event_Data *)data;
+
+ if (!strcmp(ev->key, "Return"))
+ {
+ printf("Looking for next item\n");
+ _gl20_searsh_item(data, event_data->last_item_found);
+ }
+}
+
+void
+test_genlist20(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ Evas_Object *win, *bx, *gl;
+ Evas_Object *fr, *lb_frame; // info frame
+ Evas_Object *bx_entry, *lb_entry, *en; // search line
+ Evas_Object *tg; // "case sensitive" toggle
+ Elm_Genlist_Item_Class *itc = NULL;
+ gl20_Event_Data* event_data = NULL;
+ int i = 0;
+
+ win = elm_win_util_standard_add("genlist-item-search-by-text",
+ "Genlist Item Search By Text");
+ elm_win_autodel_set(win, EINA_TRUE);
+
+ bx = elm_box_add(win);
+ evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bx);
+ evas_object_show(bx);
+
+ fr = elm_frame_add(bx);
+ evas_object_size_hint_weight_set(fr, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(fr, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_text_set(fr, "Information");
+ elm_box_pack_end(bx, fr);
+ evas_object_show(fr);
+
+ lb_frame = elm_label_add(fr);
+ elm_object_text_set(lb_frame,
+ "<align=left>This is an example of "
+ "elm_genlist_search_by_text_item_get() usage.<br>"
+ "Enter search string to the entry and press Enter to "
+ "show next search result.<br>");
+ elm_object_content_set(fr, lb_frame);
+ evas_object_show(lb_frame);
+
+ tg = elm_check_add(win);
+ elm_object_style_set(tg, "toggle");
+ elm_object_text_set(tg, " Case Sensitive Search");
+ elm_check_state_set(tg, EINA_TRUE);
+ elm_box_pack_end(bx, tg);
+ evas_object_show(tg);
+
+ bx_entry = elm_box_add(win);
+ elm_box_horizontal_set(bx_entry, EINA_TRUE);
+ evas_object_size_hint_weight_set(bx_entry, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(bx_entry, EVAS_HINT_FILL, 0.0);
+ elm_box_pack_end(bx, bx_entry);
+ evas_object_show(bx_entry);
+
+ lb_entry = elm_label_add(win);
+ elm_object_text_set(lb_entry, " Search:");
+ evas_object_size_hint_weight_set(lb_entry, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(lb_entry, 0.0, EVAS_HINT_FILL);
+ elm_box_pack_end(bx_entry, lb_entry);
+ evas_object_show(lb_entry);
+
+ en = elm_entry_add(win);
+ elm_entry_single_line_set(en, EINA_TRUE);
+ elm_entry_scrollable_set(en, EINA_TRUE);
+ elm_object_part_text_set(en, "guide", "Type item's name here to search.");
+ evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bx_entry, en);
+ evas_object_show(en);
+ elm_object_focus_set(en, EINA_TRUE);
+
+ gl = elm_genlist_add(bx);
+
+ evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bx, gl);
+ evas_object_show(gl);
+
+ event_data = calloc(1, sizeof(gl20_Event_Data));
+ event_data->tg_obj = tg;
+ event_data->en_obj = en;
+ event_data->gl_obj = gl;
+ event_data->last_item_found = NULL;
+
+ evas_object_event_callback_add(en, EVAS_CALLBACK_KEY_DOWN,
+ _gl20_on_keydown, (void*)event_data);
+ evas_object_event_callback_add(gl, EVAS_CALLBACK_FREE,
+ _cleanup_cb, (void*)event_data);
+ evas_object_smart_callback_add(en, "changed,user",
+ _gl20_search_settings_changed_cb, (void*)event_data);
+ evas_object_smart_callback_add(tg, "changed",
+ _gl20_search_settings_changed_cb, (void*)event_data);
+ evas_object_smart_callback_add(gl, "expand,request", gl4_exp_req, gl);
+ evas_object_smart_callback_add(gl, "contract,request", gl4_con_req, gl);
+ evas_object_smart_callback_add(gl, "contracted", gl4_con, gl);
+ evas_object_smart_callback_add(gl, "expanded", _gl20_expand_cb, gl);
+
+ itc = _gl20_item_class_create("tree_effect");
+
+ elm_genlist_item_append(gl, itc,
+ (void *)100/* item data */,
+ NULL/* parent */,
+ ELM_GENLIST_ITEM_TREE,
+ NULL/* func */,
+ NULL/* func data */);
+
+ itc->item_style = "default";
+
+ for (i = 0; i < 50; i++)
+ {
+ elm_genlist_item_append(gl, itc,
+ (void *)(uintptr_t)i/* item data */,
+ NULL/* parent */,
+ ELM_GENLIST_ITEM_NONE,
+ NULL/* func */,
+ NULL/* func data */);
+ }
+
+ elm_genlist_item_class_free(itc);
+
+ evas_object_resize(win, 320, 500);
+ evas_object_show(win);
+}
+
/* test genlist deletion */
static void _gl_del_sel(void *data, Evas_Object *obj, void *event_info);
diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c
index 5f73def7e..0e26793f8 100644
--- a/src/lib/elm_genlist.c
+++ b/src/lib/elm_genlist.c
@@ -7496,6 +7496,35 @@ _elm_genlist_elm_widget_focus_highlight_geometry_get(Eo *obj EINA_UNUSED, Elm_Ge
}
}
+EOLIAN static Elm_Object_Item *
+_elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED,
+ Elm_Genlist_Data *sd,
+ Elm_Object_Item * item_to_search_from,
+ Elm_Gen_Item_Text_Get_Cb _text_get,
+ const char * part_name,
+ const char * pattern,
+ int flags)
+{
+ Elm_Gen_Item *it = NULL;
+ const char * str = NULL;
+ Eina_Bool search_flag = (item_to_search_from) ? EINA_FALSE : EINA_TRUE;
+
+ if (!_text_get || !pattern) return NULL;
+ if (!sd->items) return NULL;
+
+ EINA_INLIST_FOREACH(sd->items, it)
+ {
+ if (search_flag)
+ {
+ str = _text_get((void *)it->base.data, VIEW(it), part_name);
+ if (!fnmatch(pattern, str, flags)) return (Elm_Object_Item *)it;
+ }
+ else if (item_to_search_from == (Elm_Object_Item *)it)
+ search_flag = EINA_TRUE;
+ }
+ return NULL;
+}
+
EOLIAN static Elm_Object_Item*
_elm_genlist_elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
{
diff --git a/src/lib/elm_genlist.eo b/src/lib/elm_genlist.eo
index 0a2d74af3..5f04a22f4 100644
--- a/src/lib/elm_genlist.eo
+++ b/src/lib/elm_genlist.eo
@@ -681,6 +681,51 @@ class Elm_Genlist (Elm_Layout, Elm_Interface_Scrollable, Evas_Clickable_Interfac
@in const void *func_data; /*@ Data passed to @p func above. */
}
}
+ search_by_text_item_get {
+ /*@
+ Get genlist item by given string.
+
+ @return Pointer to the genlist item which matches search_string in case of success, otherwise returns NULL.
+
+ This function takes pointer to the function that returns
+ comparison string for item (it could be the same function as used for setting text for labels).
+ Also it takes pointer to the genlist item that will be used to start search from it.
+
+ This function uses fnmatch() for searching and takes it's seatcing flags as last parameter.
+ The list of available flags:
+ <dl>
+ <dt>FNM_NOESCAPE</dt>
+ <dd>If this flag is set, treat backslash as an ordinary character, instead of an escape character.</dd>
+ <dt>FNM_PATHNAME</dt>
+ <dd>If this flag is set, match a slash in string only with a slash in pattern and not by an asterisk (*)
+ or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash.</dd>
+ <dt>FNM_PERIOD</dt>
+ <dd>If this flag is set, a leading period in string has to be matched exactly by a period in pattern.
+ A period is considered to be leading if it is the first character in string, or if both
+ FNM_PATHNAME is set and the period immediately follows a slash.</dd>
+ <dt>FNM_FILE_NAME</dt>
+ <dd>This is a GNU synonym for FNM_PATHNAME.</dd>
+ <dt>FNM_LEADING_DIR</dt>
+ <dd>If this flag (a GNU extension) is set, the pattern is considered to be matched if it matches an
+ initial segment of string which is followed by a slash. This flag is mainly for the internal
+ use of glibc and is only implemented in certain cases.</dd>
+ <dt>FNM_CASEFOLD</dt>
+ <dd>If this flag (a GNU extension) is set, the pattern is matched case-insensitively.</dd>
+ </dl>
+ For more details see <a href=http://man7.org/linux/man-pages/man3/fnmatch.3.html>Linux Programmer's Manual. FNMATCH()</a>
+
+ @ingroup Genlist
+ @since 1.10 */
+
+ return Elm_Object_Item *;
+ params {
+ @in Elm_Object_Item * item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the genlist. */
+ @in Elm_Gen_Item_Text_Get_Cb _text_get; /*@ Pointer to Elm_Gen_Item_Text_Get_Cb function to get text for comparison. */
+ @in const char * part_name; /*@ Name of the TEXT part of genlist item to search string in. */
+ @in const char * pattern; /*@ The search pattern. */
+ @in int flags; /*@ fnmatch search flags */
+ }
+ }
}
implements {
class::constructor;
diff --git a/src/lib/elm_genlist_legacy.h b/src/lib/elm_genlist_legacy.h
index 61be1f963..c83667e0e 100644
--- a/src/lib/elm_genlist_legacy.h
+++ b/src/lib/elm_genlist_legacy.h
@@ -31,4 +31,4 @@ EAPI Evas_Object *elm_genlist_add(Evas_Object *parent);
EAPI Elm_Object_Item *
elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth);
-#include "elm_genlist.eo.legacy.h" \ No newline at end of file
+#include "elm_genlist.eo.legacy.h"