80bfa59bc50077a1e8f05f32cb87ef77db9c36b3
[apps/home/smartsearch.git] / src / search_bar.cpp
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18
19
20
21
22 #include <string.h>
23 #include "smartsearch.h"
24 #include "Elementary.h"
25
26 Eina_Bool __search_entry_timer_cb(void *data)
27 {
28         SEARCH_FUNC_START;
29         struct appdata *ad = (struct appdata *)data;
30
31         search_set_result_list(ad);
32         ad->search_timer = NULL;
33
34         SEARCH_FUNC_END;
35         return ECORE_CALLBACK_CANCEL;
36 }
37
38 void __search_searchbar_entry_changed_cb(void *data, Evas_Object * obj,
39                                        void *event_info)
40 {
41         SEARCH_FUNC_START;
42
43         struct appdata *ad = (struct appdata *)data;
44         const char *text;
45         text = elm_entry_markup_to_utf8(elm_object_text_get(ad->search_entry));
46
47         SEARCH_DEBUG_LOG("text : %s", text);
48
49         if (elm_object_focus_get(ad->search_bar)) {
50                 if (elm_entry_is_empty(ad->search_entry))
51                         elm_object_signal_emit(ad->search_bar, "elm,state,eraser,hide", "elm");
52                 else
53                         elm_object_signal_emit(ad->search_bar, "elm,state,eraser,show", "elm");
54         } else {
55                 if (elm_entry_is_empty(ad->search_entry))
56                         elm_object_signal_emit(ad->search_bar, "elm,state,guidetext,show", "elm");
57                 else
58                         elm_object_signal_emit(ad->search_bar, "elm,state,guidetext,hide", "elm");
59         }
60
61         if ((text != NULL) && (strlen(text) > 0)
62                     && (SEARCH_STRCMP(text, ad->search_word) == 0)) {
63                         SEARCH_DEBUG_LOG("text is same as prev text");
64         } else {
65                 /* Make timer for check user's input */
66                 search_stop_search(ad);
67
68                 ad->search_timer = ecore_timer_add(0.4, __search_entry_timer_cb, ad);
69         }
70
71         SEARCH_FUNC_END;
72         return;
73 }
74
75
76 static void __search_searchbar_entry_focused_cb(void *data, Evas_Object *obj, void *event_info)
77 {
78         SEARCH_FUNC_START;
79
80         struct appdata *ad = (struct appdata *)data;
81
82         if (!elm_entry_is_empty(ad->search_entry))
83                 elm_object_signal_emit(ad->search_bar, "elm,state,eraser,show", "elm");
84
85         elm_object_signal_emit(ad->search_bar, "elm,state,guidetext,hide", "elm");
86         elm_object_signal_emit(ad->search_bar, "cancel,in", "");
87
88         SEARCH_FUNC_END;
89 }
90
91 static void __search_searchbar_entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
92 {
93         SEARCH_FUNC_START;
94
95         struct appdata *ad = (struct appdata *)data;
96
97         if (elm_entry_is_empty(ad->search_entry))
98                 elm_object_signal_emit(ad->search_bar, "elm,state,guidetext,show", "elm");
99
100         elm_object_signal_emit(ad->search_bar, "elm,state,eraser,hide", "elm");
101
102         SEARCH_FUNC_END;
103 }
104
105 static void __search_searchbar_bg_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
106 {
107         SEARCH_FUNC_START;
108
109         struct appdata *ad = (struct appdata *)data;
110
111         elm_object_focus_set(ad->search_entry, EINA_TRUE);
112
113         SEARCH_FUNC_END;
114 }
115
116 static void __search_searchbar_eraser_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source) // When X marked button is clicked, empty entry's contents.
117 {
118         SEARCH_FUNC_START;
119
120         struct appdata *ad = (struct appdata *)data;
121
122         elm_entry_entry_set(ad->search_entry, "");
123
124         SEARCH_FUNC_END;
125 }
126
127 static void __search_searchbar_key_down_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
128 {
129         SEARCH_FUNC_START;
130
131         struct appdata *ad = (struct appdata *)data;
132         Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *) event_info;
133
134         if (SEARCH_STRCMP(ev->key, "Return") == 0) {
135                              ecore_imf_context_input_panel_hide
136                             ((Ecore_IMF_Context *)elm_entry_imf_context_get
137                              (ad->search_entry));
138         }
139
140         SEARCH_FUNC_END;
141 }
142
143 static void __search_searchbar_cancel_clicked_cb(void *data, Evas_Object * obj,
144                                                  void *event_info)
145 {
146         SEARCH_FUNC_START;
147
148         struct appdata *ad = (struct appdata *)data;
149
150         const char* text;
151
152         elm_object_focus_set(ad->cate_btn, EINA_TRUE);
153         evas_object_hide(ad->search_cancel_btn);
154         elm_object_signal_emit(ad->search_bar, "cancel,out", "");
155         text = elm_entry_entry_get(ad->search_entry);
156
157         if (text != NULL && strlen(text) > 0)
158                 elm_entry_entry_set(ad->search_entry, NULL);
159
160         search_set_result_list(ad);
161
162         malloc_trim(0);
163
164         SEARCH_FUNC_END;
165 }
166
167 static void __search_searchbar_gl_drag_scroll_start_cb(void *data, Evas_Object * obj, void *event_info)
168 {
169         SEARCH_FUNC_START;
170
171         struct appdata *ad = (struct appdata *)data;
172
173         Ecore_IMF_Context *imf_context = (Ecore_IMF_Context *)elm_entry_imf_context_get(ad->search_entry);
174
175         if (imf_context) {
176                 ecore_imf_context_input_panel_hide(imf_context);
177         }
178
179         SEARCH_FUNC_END;
180 }
181
182
183 static void
184 __search_searchbar_state_event_cb(void *data, Ecore_IMF_Context *imf_context, int value)
185 {
186         SEARCH_FUNC_START;
187
188         struct appdata *ad = (struct appdata *)data;
189
190         switch (value)
191         {
192                 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
193                         evas_object_smart_callback_add(
194                                         ad->search_gl,
195                                         "scroll,drag,start",
196                                         __search_searchbar_gl_drag_scroll_start_cb,
197                                         data);
198                 break;
199                 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
200                         /* ISE state has changed to ISE_STATE_HIDE status */
201                         evas_object_smart_callback_del(
202                                         ad->search_gl,
203                                         "scroll,drag,start",
204                                         __search_searchbar_gl_drag_scroll_start_cb);
205                 break;
206         }
207
208         SEARCH_FUNC_END;
209 }
210
211 static Evas_Object* __search_searchbar_create(void *data)
212 {
213         SEARCH_FUNC_START;
214
215         struct appdata *ad = (struct appdata *)data;
216         int category = 0;
217         Evas_Object *search_layout = NULL;
218         Evas_Object *cate_btn;
219         Evas_Object *cate_icon;
220         char *imgpath = NULL;
221
222         if (!ad)
223                 return NULL;
224
225         if (ad->search_bar) {
226                 elm_object_signal_callback_del(ad->search_bar, "elm,bg,clicked", "elm",
227                                                                 __search_searchbar_bg_clicked_cb);
228                 elm_object_signal_callback_del(ad->search_bar, "elm,eraser,clicked", "elm",
229                                                                 __search_searchbar_eraser_clicked_cb);
230
231                 evas_object_del(ad->search_bar);
232                 ad->search_bar = NULL;
233         }
234
235         if (ad->search_entry) {
236                 evas_object_smart_callback_del(ad->search_entry, "changed",
237                                                                 __search_searchbar_entry_changed_cb);
238                 evas_object_smart_callback_del(ad->search_entry, "preedit,changed",
239                                                                 __search_searchbar_entry_changed_cb);
240                 evas_object_smart_callback_del(ad->search_entry, "focused",
241                                                                 __search_searchbar_entry_focused_cb);
242                 evas_object_smart_callback_del(ad->search_entry, "unfocused",
243                                                                 __search_searchbar_entry_unfocused_cb);
244
245                 evas_object_del(ad->search_entry);
246                 ad->search_entry = NULL;
247         }
248
249         if (ad->search_cancel_btn) {
250                 evas_object_smart_callback_del(ad->search_cancel_btn, "clicked",
251                                                __search_searchbar_cancel_clicked_cb);
252                 evas_object_del(ad->search_cancel_btn);
253                 ad->search_cancel_btn = NULL;
254         }
255
256         search_layout = elm_layout_add(ad->sb_layout);
257         elm_layout_file_set(search_layout,
258                                                 SEARCH_EDJ,
259                                                 "smartsearch/search_bar");
260
261         imgpath = ad->category_info[ad->search_category].btn_icon_path;
262         cate_icon = search_searchbar_category_icon_add(imgpath, search_layout);
263         cate_btn = elm_button_add(search_layout);
264
265         elm_object_style_set(cate_btn, "icon");
266         elm_object_content_set(ad->cate_btn, cate_icon);
267
268         evas_object_show(cate_btn);
269         ad->cate_btn = cate_btn;
270
271         elm_object_part_content_set(search_layout, "searchbar_area_category", cate_btn);
272
273         ad->search_cancel_btn = elm_button_add(ad->search_bar);
274         elm_object_part_content_set(ad->search_bar, "button_cancel", ad->search_cancel_btn);
275         elm_object_style_set(ad->search_cancel_btn, "searchbar/default");
276         elm_object_text_set(ad->search_cancel_btn, dgettext("sys_string", "IDS_COM_SK_CANCEL"));
277
278         ad->search_entry = elm_entry_add(ad->search_bar);
279         elm_entry_scrollable_set(ad->search_entry, EINA_TRUE);
280         elm_entry_single_line_set(ad->search_entry, EINA_TRUE);
281         elm_object_part_content_set(ad->search_bar, "elm.swallow.content", ad->search_entry);
282         elm_object_part_text_set(ad->search_bar, "elm.guidetext", dgettext("sys_string", "IDS_COM_BODY_SEARCH"));
283         elm_entry_cnp_mode_set(ad->search_entry, ELM_CNP_MODE_PLAINTEXT);
284
285         evas_object_size_hint_weight_set(ad->search_bar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
286         evas_object_size_hint_align_set(ad->search_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
287
288         elm_entry_input_panel_layout_set(ad->search_entry, ELM_INPUT_PANEL_LAYOUT_NORMAL);
289         Ecore_IMF_Context *imf_context = (Ecore_IMF_Context *)elm_entry_imf_context_get(ad->search_entry);
290         ecore_imf_context_input_panel_event_callback_add(imf_context,
291                                                          ECORE_IMF_INPUT_PANEL_STATE_EVENT,
292                                                          __search_searchbar_state_event_cb,
293                                                          data);
294
295         elm_object_part_content_set(search_layout, "searchbar_area_entry", ad->search_bar);
296
297         /* Set Searchbar Callback */
298         elm_object_signal_callback_add(ad->search_bar, "elm,bg,clicked", "elm",
299                                                                 __search_searchbar_bg_clicked_cb,
300                                                                 ad);
301         elm_object_signal_callback_add(ad->search_bar, "elm,eraser,clicked", "elm",
302                                                                 __search_searchbar_eraser_clicked_cb,
303                                                                 ad);
304
305         /* Set Search-Entry Callback */
306         evas_object_smart_callback_add(ad->search_entry, "changed",
307                                                                 __search_searchbar_entry_changed_cb,
308                                                                 ad);
309         evas_object_smart_callback_add(ad->search_entry, "preedit,changed",
310                                                                 __search_searchbar_entry_changed_cb,
311                                                                 ad);
312
313         evas_object_smart_callback_add(ad->search_entry, "focused",
314                                                                 __search_searchbar_entry_focused_cb,
315                                                                 ad);
316         evas_object_smart_callback_add(ad->search_entry, "unfocused",
317                                                                 __search_searchbar_entry_unfocused_cb,
318                                                                 ad);
319         evas_object_event_callback_add(ad->search_entry, EVAS_CALLBACK_KEY_DOWN,
320                                                                 __search_searchbar_key_down_cb,
321                                                         ad);
322
323         /* Set Searchbar Cancel Button Callback */
324         evas_object_smart_callback_add(ad->search_cancel_btn, "clicked",
325                                                                 __search_searchbar_cancel_clicked_cb,
326                                                                 ad);
327
328         evas_object_show(ad->search_bar);
329
330         return search_layout;
331
332         SEARCH_FUNC_END;
333 }
334
335 static Evas_Object *__search_init_noresult_view(void *data)
336 {
337         SEARCH_FUNC_START;
338
339         struct appdata *ad = (struct appdata *)data;
340         Evas_Object *noc;
341
342         noc = elm_layout_add(ad->navi_bar);
343         elm_layout_theme_set(noc, "layout", "nocontents", "search");
344         elm_object_part_text_set(noc, "elm.text", dgettext("sys_string", "IDS_COM_BODY_NO_SEARCH_RESULTS"));
345         elm_object_focus_allow_set(noc, EINA_TRUE);
346
347         SEARCH_FUNC_END;
348
349         return noc;
350 }
351
352 Evas_Object *search_searchbar_category_icon_add(char* img, Evas_Object *parent)
353 {
354         SEARCH_FUNC_START;
355
356         char buf[MAX_LENGTH_PER_PATH] = { 0, };
357         Evas_Object* cate_icon = NULL;
358
359         if( img != NULL ) {
360         cate_icon = elm_icon_add(parent);
361
362         snprintf(buf, sizeof(buf), SEARCH_ICON_PATH "%s", img);
363
364         SEARCH_DEBUG_LOG("buf : %s", buf);
365
366         elm_icon_file_set(cate_icon, buf, NULL);
367
368         evas_object_size_hint_aspect_set(cate_icon, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
369         elm_icon_resizable_set(cate_icon, EINA_FALSE, EINA_FALSE);
370         }
371
372         SEARCH_FUNC_END;
373
374         return cate_icon;
375 }
376
377 void search_searchbar_cb(void *data, Evas_Object * obj, void *event_info)
378 {
379         SEARCH_FUNC_START;
380
381         struct appdata *ad = (struct appdata *)data;
382
383         /* create layout */
384
385         ad->sb_layout = elm_layout_add(ad->navi_bar);
386         elm_layout_theme_set(ad->sb_layout, "layout", "application", "searchbar_base");
387         elm_object_signal_emit(ad->sb_layout, "elm,state,show,searchbar", "elm");
388
389         /* set search bar area */
390         ad->search_layout = __search_searchbar_create(ad);
391         elm_object_part_content_set(ad->sb_layout, "searchbar", ad->search_layout);
392
393         /* set search result area */
394         ad->result_layout = elm_layout_add(ad->sb_layout);
395         elm_layout_file_set(ad->result_layout,
396                                                 SEARCH_EDJ,
397                                                 "smartsearch/search_result");
398
399         /* set search result area */
400         ad->noresult_view = __search_init_noresult_view(ad);
401
402         elm_object_part_content_set(ad->result_layout,
403                                                 "list_noresult",
404                                                 ad->noresult_view);
405
406         elm_object_part_content_set(ad->sb_layout, "elm.swallow.content", ad->result_layout);
407         evas_object_size_hint_weight_set(
408                                                         ad->sb_layout,
409                                                         EVAS_HINT_EXPAND,
410                                                         EVAS_HINT_EXPAND);
411
412         SEARCH_FUNC_END;
413 }