01c3ccbb7ebdb5acf146bd7b394355149cedda6a
[framework/uifw/elementary.git] / src / lib / elm_autocompleteview.c
1 #include <Elementary.h>\r
2 #include "elm_priv.h"\r
3 #include <string.h>\r
4 \r
5 /**\r
6  * @defgroup Autocompleteview Autocompleteview\r
7  * @ingroup Elementary\r
8  *\r
9  * This widget show's the completed strings in a dropdown list \r
10  * based on the initial few characters entered by the user.\r
11  *\r
12  */\r
13 \r
14 typedef struct _Widget_Data Widget_Data;\r
15 \r
16 struct _Widget_Data\r
17 {\r
18    Evas_Object *editfield;\r
19    Evas_Object *hover;\r
20    Evas_Object *layout;\r
21    Evas_Object *list;\r
22    Evas_Object *entry;\r
23    Eina_List *data_list;\r
24    Eina_Bool text_set : 1;\r
25    elmautocompleteview_matchfunction func;\r
26    void *data;\r
27    int threshold;\r
28 };\r
29 \r
30 static void _editfield_clicked_cb(void *data, Evas_Object *obj, void *event_info)\r
31 {\r
32    evas_object_smart_callback_call(data, "clicked", NULL);\r
33 }\r
34 \r
35 static void _entry_changed_cb(void *data, Evas_Object *obj, void *event_info)\r
36 {\r
37    Widget_Data *wd = elm_widget_data_get(data);\r
38    const char *text = NULL;\r
39    int textlen = 0;\r
40    char *real = NULL,*res = NULL;\r
41    Eina_List *l;\r
42    Eina_Bool textfound = EINA_FALSE;\r
43    if(!wd) return;\r
44    if (elm_widget_disabled_get(data)) return;\r
45    if(wd->text_set)\r
46      {\r
47         evas_object_hide(wd->hover);\r
48         wd->text_set = EINA_FALSE;\r
49         return;\r
50      }\r
51    text = elm_entry_entry_get(obj);\r
52    if(text == NULL)\r
53       return;   \r
54    textlen  = strlen(text);\r
55    if(textlen <wd->threshold)\r
56      {\r
57         evas_object_hide(wd->hover);\r
58         return;\r
59      }          \r
60    evas_object_hide(wd->hover);\r
61    if(wd->func)\r
62      {\r
63         textfound = wd->func(data,text,wd->list,wd->data);\r
64      }\r
65    else if(wd->data_list) \r
66      {\r
67         elm_list_clear(wd->list);\r
68         EINA_LIST_FOREACH(wd->data_list, l, real) \r
69           {\r
70              res  = strcasestr(real,text);\r
71              if(res)\r
72                {\r
73                   elm_list_item_append(wd->list, real, NULL, NULL, \r
74                                        NULL, NULL);\r
75                   textfound=EINA_TRUE;\r
76                }\r
77           }\r
78      }\r
79    else\r
80       return;\r
81    if(textfound)\r
82      {\r
83         elm_list_go(wd->list);          \r
84         evas_object_show(wd->hover);\r
85      }\r
86 \r
87 }\r
88 \r
89 static void\r
90 _del_pre_hook(Evas_Object *obj)\r
91 {\r
92    Widget_Data *wd = elm_widget_data_get(obj);\r
93    if(wd->hover)\r
94       evas_object_del(wd->hover);\r
95 }\r
96 \r
97 \r
98 static void\r
99 _del_hook(Evas_Object *obj)\r
100 {\r
101    Widget_Data *wd = elm_widget_data_get(obj);\r
102    free(wd);\r
103 }\r
104 \r
105 static void\r
106 _sizing_eval(Evas_Object *obj)\r
107 {\r
108    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;\r
109 \r
110    evas_object_size_hint_min_set(obj, minw, minh);\r
111    evas_object_size_hint_max_set(obj, maxw, maxh);\r
112 }\r
113 \r
114 static void\r
115 _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
116 {\r
117    _sizing_eval(data);\r
118 }\r
119 \r
120 static void\r
121 _hover_clicked(void *data, Evas_Object *obj, void *event_info)\r
122 {\r
123    printf("\n\ncurrently nothin to be done\n");\r
124 }\r
125 \r
126 static void _list_click( void *data, Evas_Object *obj, void *event_info )\r
127 {\r
128    Elm_List_Item *it = (Elm_List_Item *) elm_list_selected_item_get(obj);\r
129    Widget_Data *wd = elm_widget_data_get(data);\r
130    if((it==NULL)||(wd==NULL))\r
131       return;\r
132    const char *text = elm_list_item_label_get(it);\r
133    evas_object_smart_callback_call((Evas_Object *)data, "selected", (void *)text);\r
134    if(wd->data_list)\r
135      {\r
136         if(text!=NULL)\r
137           {\r
138              elm_entry_entry_set(wd->entry, text);\r
139              elm_entry_cursor_end_set(wd->entry);\r
140              wd->text_set =  EINA_TRUE;\r
141           }\r
142      }\r
143 }\r
144 \r
145 static int\r
146 _eina_cmp_str(const char *a, const char *b)\r
147 {\r
148    return strcasecmp(a,b);\r
149 }\r
150 \r
151 \r
152 /**\r
153  * Add a new Autocompleteview object\r
154  *\r
155  * @param parent The parent object\r
156  * @return The new object or NULL if it cannot be created\r
157  *\r
158  * @ingroup Autocompleteview\r
159  */\r
160 EAPI Evas_Object *\r
161 elm_autocompleteview_add(Evas_Object *parent)\r
162 {\r
163    Evas_Object *obj;\r
164    Evas *e;\r
165    Widget_Data *wd;\r
166 \r
167    wd = ELM_NEW(Widget_Data);\r
168    e = evas_object_evas_get(parent);\r
169    obj = elm_widget_add(e);\r
170    elm_widget_type_set(obj, "autocompleteview");\r
171    elm_widget_sub_object_add(parent, obj);\r
172    elm_widget_data_set(obj, wd);\r
173    elm_widget_del_pre_hook_set(obj, _del_pre_hook);\r
174    elm_widget_del_hook_set(obj, _del_hook);\r
175 \r
176    wd->editfield = elm_editfield_add(parent);\r
177    elm_widget_resize_object_set(obj, wd->editfield);\r
178    elm_editfield_entry_single_line_set(wd->editfield, EINA_TRUE);\r
179    evas_object_size_hint_weight_set(wd->editfield, 0, EVAS_HINT_EXPAND);\r
180    evas_object_size_hint_align_set(wd->editfield, 0, EVAS_HINT_FILL);\r
181    evas_object_event_callback_add(wd->editfield,\r
182                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,\r
183                                   _changed_size_hints, obj);\r
184    wd->threshold = 1;\r
185    wd->entry = elm_editfield_entry_get(wd->editfield);\r
186 \r
187    evas_object_smart_callback_add(wd->editfield, "clicked", _editfield_clicked_cb, obj);\r
188    evas_object_smart_callback_add(wd->entry, "changed", _entry_changed_cb, obj);\r
189 \r
190    wd->hover = elm_hover_add(obj);\r
191    elm_hover_parent_set(wd->hover, parent);\r
192    elm_hover_target_set(wd->hover, wd->editfield);\r
193 \r
194    wd->layout = elm_layout_add(wd->hover);\r
195    elm_layout_theme_set(wd->layout,"autocompleteview","base","default");\r
196    wd->list = elm_list_add(wd->layout);\r
197    evas_object_size_hint_weight_set(wd->list, EVAS_HINT_EXPAND, 0.0);\r
198    evas_object_size_hint_align_set(wd->list, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
199    elm_list_horizontal_mode_set(wd->list, ELM_LIST_COMPRESS);\r
200    elm_object_style_set(wd->list,"autocompleteview");\r
201    elm_list_go(wd->list);\r
202    evas_object_smart_callback_add(wd->list, "selected", _list_click, obj);\r
203    elm_layout_content_set( wd->layout, "elm.swallow.content", wd->list );\r
204    elm_hover_content_set(wd->hover,\r
205                          elm_hover_best_content_location_get(wd->hover,\r
206                                                              ELM_HOVER_AXIS_VERTICAL),\r
207                          wd->layout);\r
208    evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, obj);\r
209 \r
210    _sizing_eval(obj);\r
211    return obj;\r
212 }\r
213 \r
214 \r
215 /**\r
216  * This Get's the entry object of Autocompleteview object.\r
217  *\r
218  * @param obj The Autocompleteview object.\r
219  * @return the entry object.\r
220  *\r
221  * @ingroup Autocompleteview\r
222  */\r
223 EAPI Evas_Object *\r
224 elm_autocompleteview_entry_get(Evas_Object *obj)\r
225 {\r
226    Widget_Data *wd = elm_widget_data_get(obj);\r
227    if(!wd) return NULL;\r
228 \r
229    return wd->entry;\r
230 }\r
231 \r
232 /**\r
233  * This Get's the editfield object of the Autocompleteview object.\r
234  *\r
235  * @param obj The Autocompleteview object.\r
236  * @return The Editfield object.\r
237  *\r
238  * @ingroup Autocompleteview\r
239  */\r
240 EAPI Evas_Object *\r
241 elm_autocompleteview_editfield_get(Evas_Object *obj)\r
242 {\r
243    Widget_Data *wd = elm_widget_data_get(obj);\r
244    if(!wd) return NULL;\r
245 \r
246    return wd->editfield;\r
247 }\r
248 \r
249 \r
250 /**\r
251  * This Specifies the minimum number of characters the user has to type in the editfield \r
252  * before the drop down list is shown.When threshold is less than or equals 0, a threshold of 1 is applied by default.\r
253  *\r
254  * @param obj The Autocompleteview object\r
255  * @param threshold the number of characters to type before the drop down is shown\r
256  *\r
257  * @ingroup Autocompleteview\r
258  */\r
259 EAPI void\r
260 elm_autocompleteview_threshold_set(Evas_Object *obj, int threshold)\r
261 {\r
262    Widget_Data *wd = elm_widget_data_get(obj);\r
263    if(!wd) return;\r
264 \r
265    if(threshold <=0)\r
266      {\r
267         wd->threshold = 1;\r
268      }\r
269    else\r
270      {\r
271         wd->threshold = threshold;\r
272      }\r
273 }\r
274 \r
275 \r
276 /**\r
277  * This Returns the number of characters the user must type before the drop down list is shown.\r
278  *\r
279  * @param obj The Autocompleteview object.\r
280  * @return The threshold value.\r
281  *\r
282  * @ingroup Autocompleteview\r
283  */\r
284 EAPI int\r
285 elm_autocompleteview_threshold_get(Evas_Object *obj)\r
286 {\r
287    Widget_Data *wd = elm_widget_data_get(obj);\r
288    if(!wd) return -1;\r
289 \r
290    return wd->threshold;\r
291 }\r
292 \r
293 \r
294 /**\r
295  * This Specifies the list of strings which has to be searched to get the list of completion strings.\r
296  *\r
297  * @param obj The Autocompleteview object\r
298  * @param data_list the list of static strings, which has to be searched to get the completion strings.\r
299  *\r
300  * @ingroup Autocompleteview\r
301  */\r
302 EAPI void\r
303 elm_autocompleteview_data_set(Evas_Object *obj, Eina_List *data_list)\r
304 {\r
305    Widget_Data *wd = elm_widget_data_get(obj);\r
306    if(!wd) return;\r
307 \r
308    wd->data_list = data_list;\r
309 \r
310    /*storing sorted list*/\r
311    wd->data_list = eina_list_sort(wd->data_list, eina_list_count(wd->data_list), EINA_COMPARE_CB(_eina_cmp_str));\r
312 }\r
313 \r
314 \r
315 /**\r
316  * This Registers the callback function that would be called whenever text is entered in to the entry.\r
317  *\r
318  * @param obj The Autocompleteview object\r
319  * @param elmautocompleteview_matchfunction completion function which list's the completion strings.\r
320  * @param data userdata that would be passed whenever the callback function is called.\r
321  *\r
322  * @ingroup Autocompleteview\r
323  */\r
324 EAPI void\r
325 elm_autocompleteview_match_func_set(Evas_Object *obj, elmautocompleteview_matchfunction func,void *data)\r
326 {\r
327    Widget_Data *wd = elm_widget_data_get(obj);\r
328    if(!wd) return;\r
329 \r
330    wd->func = func;\r
331    wd->data = data;\r
332 }\r
333 \r
334 /**\r
335  * This updates the text in to autocomplete view.\r
336  *\r
337  * @param obj The Autocompleteview object\r
338  * @param text the text to be updated in to the entry of autocompleteview.\r
339  *\r
340  * @ingroup Autocompleteview\r
341  */\r
342 EAPI void\r
343 elm_autocompleteview_text_update(Evas_Object *obj, char *text)\r
344 {\r
345    Widget_Data *wd = elm_widget_data_get(obj);\r
346    if(!wd) return;\r
347 \r
348    if(text!=NULL)\r
349      {\r
350         elm_entry_entry_set(wd->entry, text);\r
351         elm_entry_cursor_end_set(wd->entry);\r
352         wd->text_set =  EINA_TRUE;\r
353      }\r
354 }\r