Tizen 2.1 base
[apps/core/preloaded/calendar.git] / src / search.c
1 /*
2   *
3   *  Copyright 2012  Samsung Electronics Co., Ltd
4   *
5   *  Licensed under the Flora License, Version 1.0 (the "License");
6   *  you may not use this file except in compliance with the License.
7   *  You may obtain a copy of the License at
8   *
9   *       http://floralicense.org/license/
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17
18
19 #include <vconf.h>
20
21 #include "detail-view.h"
22 #include "noti-handler.h"
23 #include "external-ug.h"
24 #include "view.h"
25 #include "cld-images.h"
26 #include "list-base.h"
27 #include "searchbar.h"
28
29 static Elm_Entry_Filter_Limit_Size _limit_20char = {
30         .max_char_count = 20,
31 };
32
33
34 typedef enum {
35         CAL_SEARCH_ALL = 0,
36         CAL_SEARCH_EVENTS,
37         CAL_SEARCH_TASKS,
38 }search_scope_mode;
39
40
41 typedef struct {
42         struct appdata *ad;
43         Evas_Object *parent;
44         Evas_Object *layout; // self
45
46         Evas_Object *box;
47         Evas_Object *searchbar;
48         Evas_Object *no_contents;
49
50         cal_list_base_h list;
51
52         Eina_List *append_list;
53         int appended_event_count;
54
55         const char *searchtext;
56
57         int cur_position;
58         Ecore_Idler* idler; // To append list
59
60         struct tm last_itc_h; // To prevent duplicated cal_list_itc_h, in add events & add events idler
61
62         Eina_Bool is_today_added; //To check real today item is added.
63
64         Evas_Object *popup;
65
66         Ecore_Event_Handler *event_handler;
67         Evas_Coord x;
68         Evas_Coord y;
69         Elm_Object_Item *sweep_it;
70
71         Elm_Object_Item* navi_item;
72
73         struct tm tm_start;
74         struct tm tm_end;
75         Evas_Object *ctx_popup;
76         Evas_Object *scope_button;
77         Eina_Bool has_repeated_events;
78         Elm_Object_Item *repeated_group_it;
79
80         search_scope_mode search_type;
81         Eina_Bool is_today_has_instance;
82 }cal_search_list_data;
83
84 typedef struct {
85         Elm_Object_Item *it;  // Genlist Item pointer
86         Eina_Bool checked;     // Check status
87         calendar_record_h record;
88         struct tm *tm;
89         char *color_str;
90 }cal_search_list_genlist_item_data;
91
92 static void __cal_search_list_create_ctx_popup(cal_search_list_data* p);
93 static void __cal_search_list_update_list(cal_search_list_data *p);
94
95 extern Elm_Genlist_Item_Class cal_list_today_group_itc_h;
96
97 static void __cal_search_list_append_list_with_iter(Eina_List **event_list, calendar_list_h list)
98 {
99         c_ret_if(!event_list);
100         c_ret_if(!list);
101
102         calendar_record_h record = NULL;
103
104         int i = 0;
105
106         int count = 0;
107
108         calendar_error_e error = CALENDAR_ERROR_NONE;
109
110         error = calendar_list_get_count(list, &count);
111         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_get_count() is failed(%x)", error);
112
113         for (i = 0; i < count; i++) {
114                 error = calendar_list_get_current_record_p(list, &record);
115                 c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_get_current_record_p() is failed(%x)", error);
116
117                 *event_list = eina_list_append(*event_list, record);
118
119                 calendar_list_next(list);
120         }
121 }
122
123 static void __cal_search_list_get_data_with_search(cal_search_list_data *p, calendar_list_h (*_cal_svc_search)(const char *))
124 {
125         CAL_FN_START;
126
127         c_ret_if(!p);
128
129         calendar_list_h list = _cal_svc_search(p->searchtext);
130         c_ret_if(!list);
131
132         __cal_search_list_append_list_with_iter(&p->append_list, list);
133
134         calendar_error_e error = CALENDAR_ERROR_NONE;
135
136         error = calendar_list_destroy(list, false);
137         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_list_destroy() is failed(%x)", error);
138
139         CAL_FN_END;
140 }
141
142 static void __cal_search_list_get_events_with_search(cal_search_list_data *p)
143 {
144         CAL_FN_START;
145
146         c_ret_if(!p);
147
148         __cal_search_list_get_data_with_search(p, _calendar_search_event);
149
150         CAL_FN_END;
151 }
152
153 static void __cal_search_list_get_todo_with_search(cal_search_list_data *p)
154 {
155         CAL_FN_START;
156
157         c_ret_if(!p);
158
159         __cal_search_list_get_data_with_search(p, _calendar_search_task);
160
161         CAL_FN_END;
162 }
163
164 static Eina_Bool __cal_search_list_check_idler_condition(cal_search_list_data *p)
165 {
166         c_retv_if(!p, ECORE_CALLBACK_CANCEL);
167
168         if (p->appended_event_count < eina_list_count(p->append_list)) {
169
170                 return ECORE_CALLBACK_RENEW;
171         }
172
173         if (p->idler) {
174                 ecore_idler_del(p->idler);
175                 p->idler = NULL;
176         }
177
178         return ECORE_CALLBACK_CANCEL;
179 }
180
181 static void __cal_search_list_append_event_to_genlist(cal_search_list_data *p)
182 {
183         c_ret_if(!p);
184
185         struct appdata* ad = p->ad;
186         c_ret_if(!ad);
187
188         Elm_Object_Item *it = NULL;
189         int time_previous = 0;
190         int time_today = (ad->today_tm.tm_year << 9) | (ad->today_tm.tm_mon << 5) | ad->today_tm.tm_mday;
191
192         Eina_List *l, *list;
193         calendar_record_h record;
194         int appended_event_count = 0;
195         struct tm tm_current;
196
197         calendar_time_s time = {0};
198
199         if (0 < p->appended_event_count) {
200                 list = eina_list_nth_list(p->append_list, p->appended_event_count - 1);
201                 c_ret_if(!list);
202
203                 record = eina_list_data_get(list);
204                 c_ret_if(!record);
205
206                 if (_calendar_is_task_record(record)) {
207                         _calendar_get_end_time(record, &time);
208
209                         cal_util_convert_lli_to_tm(NULL, time.time.utime, &tm_current);
210                 } else {
211                         _calendar_get_start_time(record, &time);
212
213                         if (_calendar_is_allday_record(record)) {
214
215                                 tm_current.tm_year = time.time.date.year - 1900;
216                                 tm_current.tm_mon = time.time.date.month  - 1;
217                                 tm_current.tm_mday = time.time.date.mday;
218                         } else {
219                                 cal_util_convert_lli_to_tm(NULL, time.time.utime, &tm_current);
220                         }
221                 }
222
223                 time_previous = (tm_current.tm_year << 9) | (tm_current.tm_mon << 5) | tm_current.tm_mday;
224
225                 list = eina_list_next(list);
226                 c_ret_if(!list);
227         }
228         else
229                 list = p->append_list;
230
231         EINA_LIST_FOREACH(list, l, record) {
232                 if (!record)
233                         continue;
234
235                 tm_current = p->ad->base_tm;
236
237                 if (_calendar_is_recurrent_record(record)) {
238                         p->has_repeated_events = EINA_TRUE;
239                 }
240
241                 if (_calendar_is_task_record(record)) {
242                         _calendar_get_end_time(record, &time);
243
244                         cal_util_convert_lli_to_tm(NULL, time.time.utime, &tm_current);
245                         if (tm_current.tm_mday == 0) {
246                                 continue;
247                         }
248                 } else {
249                         _calendar_get_start_time(record, &time);
250
251                         if (_calendar_is_allday_record(record)) {
252
253                                 tm_current.tm_year = time.time.date.year - 1900;
254                                 tm_current.tm_mon = time.time.date.month  - 1;
255                                 tm_current.tm_mday = time.time.date.mday;
256
257                         } else
258                                 cal_util_convert_lli_to_tm(NULL, time.time.utime, &tm_current);
259                 }
260
261                 int time_current = (tm_current.tm_year << 9) | (tm_current.tm_mon << 5) | tm_current.tm_mday;
262
263                 if (_calendar_is_recurrent_record(record)) {
264
265                         if (!p->repeated_group_it)
266                                 p->repeated_group_it = cal_list_base_append_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_itc_h, NULL, CAL_TASK_NONE);
267                         cal_list_base_add_item_after(p->list, record, p->repeated_group_it);
268
269                 } else {
270
271                         if (time_previous != time_current) {
272                                 if ((time_current == time_today) && (!p->is_today_has_instance)) {
273                                         it = cal_list_base_append_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_today_group_itc_h, &tm_current, CAL_TASK_NONE);
274                                         p->is_today_has_instance = EINA_TRUE;
275                                 } else {
276                                         it = cal_list_base_append_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_itc_h, &tm_current, CAL_TASK_NONE);
277                                 }
278
279                                 time_previous = time_current;
280
281                                 if (time_today == time_current) {
282                                         ad->today_item = it;
283                                         p->is_today_added = EINA_TRUE;
284                                 }
285
286                                 if (!p->is_today_added) {
287                                         if (time_today < time_current) {
288                                                 ad->today_item = it;
289                                                 p->is_today_added = EINA_TRUE;
290                                         }
291                                         else
292                                                 ad->today_item = it;
293                                 }
294
295                                 p->last_itc_h = tm_current;
296
297                         }
298
299                         cal_list_base_add_item(p->list, record, false);
300                 }
301
302                 appended_event_count++;
303
304                 if (10 < appended_event_count)
305                         break;
306
307         }
308
309         p->appended_event_count += appended_event_count;
310 }
311
312 Eina_Bool __cal_search_list_idler_callback(void* data)
313 {
314         c_retv_if(!data, ECORE_CALLBACK_CANCEL);
315
316         cal_search_list_data *p = data;
317
318         c_retv_if(!p->idler, ECORE_CALLBACK_CANCEL);
319
320         __cal_search_list_append_event_to_genlist(p);
321
322         return __cal_search_list_check_idler_condition(p);
323 }
324
325 static void __cal_search_list_add_idler(cal_search_list_data *p)
326 {
327         c_ret_if(!p);
328
329         if (p->appended_event_count < eina_list_count(p->append_list)) {
330
331                 if (p->idler)
332                         ecore_idler_del(p->idler);
333
334                 p->idler = ecore_idler_add(__cal_search_list_idler_callback, p);
335                 c_ret_if(!p->idler);
336
337         }
338 }
339
340 static void __cal_search_list_delete_idler(cal_search_list_data *p)
341 {
342         CAL_FN_START;
343
344         c_ret_if(!p);
345
346         if (!p->idler)
347                 return;
348
349         ecore_idler_del(p->idler);
350
351         p->idler = NULL;
352 }
353
354 static void __cal_search_list_create_no_contents(cal_search_list_data *p)
355 {
356         CAL_FN_START;
357
358         c_ret_if(!p);
359         c_ret_if(!p->layout);
360
361         if (p->no_contents)
362                 return;
363
364         char* title = NULL;
365
366         title = S_("IDS_COM_BODY_NO_ITEMS");
367
368         Evas_Object *no_contents = cal_util_add_search_nocontents(p->layout, title);
369         c_ret_if(!no_contents);
370
371         elm_object_part_content_set(p->layout, "sw", no_contents);
372
373         p->no_contents = no_contents;
374 }
375
376 static inline void __cal_search_list_show_searchbar(cal_search_list_data *p)
377 {
378         edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->layout), "searchbar,show", "prog");
379 }
380
381 static inline void __cal_search_list_hide_searchbar(cal_search_list_data *p)
382 {
383         if (!CAL_STRLEN(p->searchtext))
384                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->layout), "searchbar,hide", "prog");
385 }
386
387 static void __cal_search_list_delete_no_contents(cal_search_list_data *p)
388 {
389         CAL_FN_START;
390
391         c_ret_if(!p);
392
393         if (!p->no_contents)
394                 return;
395
396         elm_object_part_content_unset(p->layout, "sw");
397
398         evas_object_del(p->no_contents);
399
400         p->no_contents = NULL;
401 }
402
403 static void __cal_search_list_delete_genlist(cal_search_list_data *p)
404 {
405         CAL_FN_START;
406
407         c_ret_if(!p);
408         c_ret_if(!cal_list_base_get_genlist_p(p->list));
409
410         cal_list_base_delete(p->list);
411
412         p->list = NULL;
413 }
414
415 static void __cal_search_genlist_item_selected_callback(void *data)
416 {
417         c_retm_if(!data, "data is null");
418
419         cal_search_list_data *p = data;
420         c_retm_if(!p, "p is null");
421
422         calendar_record_h record = _calendar_get_record_with_index(p->ad->cid);
423         c_retm_if(!record, "record is null");
424
425         cal_detail_create_view(p->ad, record, NULL, NULL);
426         calendar_record_destroy(record, true);
427
428         return;
429 }
430
431 static void __cal_search_list_update_genlist(cal_search_list_data *p)
432 {
433         CAL_FN_START;
434
435         c_ret_if(!p);
436
437         __cal_search_list_delete_idler(p);
438
439         cal_list_base_clear(p->list);
440
441         struct appdata* ad = p->ad;
442         c_ret_if(!ad);
443
444         ad->today_item = NULL;
445
446         p->appended_event_count = 0;
447         p->repeated_group_it = NULL;
448         p->has_repeated_events = EINA_FALSE;
449         p->is_today_has_instance  = EINA_FALSE;
450
451         if (eina_list_count(p->append_list)) {
452
453                 __cal_search_list_show_searchbar(p);
454
455                 __cal_search_list_delete_no_contents(p);
456
457                 if (!p->list) {
458                         p->list = cal_list_base_create(ad, p->layout, "sw", true,
459                                                         __cal_search_genlist_item_selected_callback, p);
460                         c_ret_if(!p->list);
461                 }
462
463                 cal_list_base_set_search_text(p->list, p->searchtext);
464
465                 __cal_search_list_append_event_to_genlist(p);
466
467                 __cal_search_list_add_idler(p);
468
469         } else {
470
471                 __cal_search_list_show_searchbar(p);
472
473                 __cal_search_list_delete_genlist(p);
474
475                 __cal_search_list_create_no_contents(p);
476         }
477
478         CAL_FN_END;
479 }
480
481 static void __cal_search_list_update_events(cal_search_list_data *p)
482 {
483         c_ret_if(!p);
484
485         _calendar_free_record_list(&p->append_list);
486
487         struct appdata *ad = p->ad;
488         c_ret_if(!ad);
489
490         if (CAL_STRLEN(p->searchtext)) {
491                 if (p->search_type == CAL_SEARCH_ALL) {
492                         __cal_search_list_get_events_with_search(p);
493                         __cal_search_list_get_todo_with_search(p);
494                 } else if (p->search_type == CAL_SEARCH_EVENTS) {
495                         __cal_search_list_get_events_with_search(p);
496                 } else if (p->search_type == CAL_SEARCH_TASKS) {
497                         __cal_search_list_get_todo_with_search(p);
498                 }
499         }
500 }
501
502 static void __cal_search_list_update_list(cal_search_list_data *p)
503 {
504         CAL_FN_START;
505
506         c_ret_if(!p);
507
508         __cal_search_list_update_events(p);
509
510         __cal_search_list_update_genlist(p);
511
512         CAL_FN_END;
513 }
514
515 static void __cal_search_list_searchbar_entry_changed_callback(void *data, Evas_Object *obj, void *event_info)
516 {
517         CAL_FN_START;
518         c_ret_if(!data);
519         c_ret_if(!obj);
520
521         cal_search_list_data *p = data;
522         c_ret_if(!p->searchbar);
523
524         p->searchtext = elm_entry_markup_to_utf8(elm_object_text_get(elm_object_part_content_get(p->searchbar, "elm.swallow.content")));
525
526         __cal_search_list_update_list(p);
527
528         CAL_FN_END;
529 }
530
531 static void __cal_search_list_cancel_button_callback(void *data, Evas_Object *obj, void *event_info)
532 {
533         CAL_FN_START;
534
535         cal_search_list_data *p = data;
536         c_ret_if(!p);
537
538         elm_object_disabled_set(p->ad->new_event_button, EINA_FALSE);
539
540         Evas_Object *en = elm_object_part_content_get(p->searchbar, "elm.swallow.content");
541
542         Ecore_IMF_Context *imf_context = elm_entry_imf_context_get(en);
543         c_ret_if(!imf_context);
544
545         ecore_imf_context_input_panel_hide(imf_context);
546
547         CAL_FN_END;
548 }
549
550 static void __cal_search_list_text_refresh_callback(void *data)
551 {
552         CAL_FN_START;
553
554         c_retm_if(!data, "data is null");
555         cal_search_list_data *p = data;
556
557         elm_object_item_part_text_set(p->navi_item, "default", S_("IDS_COM_BODY_SEARCH"));
558
559         if (p->search_type == CAL_SEARCH_ALL) {
560                 elm_object_text_set(p->scope_button,  S_("IDS_COM_BODY_ALL"));
561         } else if (p->search_type == CAL_SEARCH_EVENTS) {
562                 elm_object_text_set(p->scope_button,  C_("IDS_CLD_BODY_EVENTS"));
563         } else if (p->search_type == CAL_SEARCH_TASKS) {
564                 elm_object_text_set(p->scope_button,  C_("IDS_CLD_BODY_TASKS"));
565         }
566
567         elm_object_part_text_set(p->searchbar, "elm.guidetext", S_("IDS_COM_BODY_SEARCH"));
568         elm_object_text_set(elm_object_part_content_get(p->searchbar, "button_cancel"), S_("IDS_COM_SK_CANCEL"));
569
570         if(p->no_contents)
571                 elm_object_part_text_set(p->no_contents, "elm.text", S_("IDS_COM_BODY_NO_ITEMS"));
572
573         elm_genlist_realized_items_update(p->list);
574 }
575
576 static void __cal_search_list_delete_layout(void *data, Evas *e, Evas_Object *obj, void *ei)
577 {
578         CAL_FN_START;
579
580
581         cal_search_list_data *p = data;
582         c_retm_if(!p, "priv is null.");
583
584         elm_win_conformant_set(p->ad->win, EINA_TRUE);
585
586         p->ad->current_view = p->ad->tapbar_focus_view;
587
588         if (p->idler) {
589                 ecore_idler_del(p->idler);
590                 p->idler = NULL;
591         }
592
593         _calendar_free_record_list(&p->append_list);
594
595         if (p->event_handler)
596                 ecore_event_handler_del(p->event_handler);
597
598         if (p->popup) {
599                 evas_object_del(p->popup);
600                 p->popup = NULL;
601         }
602
603         cal_lang_manager_remove_callback(__cal_search_list_text_refresh_callback, p);
604
605         free(p);
606
607         CAL_FN_END;
608 }
609
610 static void __cal_search_list_searchbar_entry_unfocused_callback(void *data, Evas_Object *obj, void *event_info)
611 {
612         c_ret_if(!data);
613         c_ret_if(!obj);
614
615         cal_search_list_data *p = data;
616         c_ret_if(!p->searchbar);
617
618         elm_object_disabled_set(p->ad->new_event_button, EINA_FALSE);
619         elm_win_conformant_set(p->ad->win, EINA_TRUE);
620 }
621
622 static void __cal_search_list_searchbar_entry_focused_callback(void *data, Evas_Object *obj, void *event_info)
623 {
624         c_ret_if(!data);
625         c_ret_if(!obj);
626
627         cal_search_list_data *p = data;
628         c_ret_if(!p->searchbar);
629
630         elm_win_conformant_set(p->ad->win, EINA_FALSE);
631 }
632
633
634
635 static void __cal_search_list_searchbar_clicked_callback(void *data, Evas_Object *obj, void *event_info)
636 {
637         cal_search_list_data *p = data;
638
639         elm_object_disabled_set(p->ad->new_event_button, EINA_TRUE);
640 }
641
642 static void __cal_search_list_search_scope_click_callback(void *data, Evas_Object *obj, void *event_info)
643 {
644         CAL_FN_START;
645         c_retm_if(!data, "data is null");
646
647         cal_search_list_data *p = data;
648
649         __cal_search_list_create_ctx_popup(p);
650 }
651
652 static void __cal_search_list_create_searchbar(cal_search_list_data *p)
653 {
654         c_ret_if(!p);
655         c_ret_if(!p->layout);
656
657         Evas_Object *button = elm_button_add(p->layout);
658         c_retm_if(!button, "button is NULL");
659
660         p->scope_button = button;
661         elm_object_style_set(button, "searchbar/default");
662         if (p->ad->tapbar_focus_view == CV_TODO) {
663                 elm_object_text_set(button, C_("IDS_CLD_BODY_TASKS"));
664         } else {
665                 elm_object_text_set(button, S_("IDS_COM_BODY_ALL"));
666         }
667         evas_object_data_set(button, "priv", p);
668         elm_object_part_content_set(p->layout, "search_scope_button", button);
669         evas_object_smart_callback_add(button, "clicked", __cal_search_list_search_scope_click_callback, p);
670         elm_object_focus_allow_set(button, EINA_FALSE);
671
672         Evas_Object *searchbar = cal_util_add_searchbar(p->layout, NULL, NULL, EINA_TRUE, NULL, p);
673         c_ret_if(!searchbar);
674
675         Evas_Object *entry = elm_object_part_content_get(searchbar, "elm.swallow.content");
676         c_ret_if(!entry);
677         elm_entry_cnp_mode_set(entry, ELM_CNP_MODE_PLAINTEXT);
678
679         elm_object_focus_set(entry, EINA_TRUE);
680         elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NORMAL);
681         elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &_limit_20char);
682
683         evas_object_size_hint_weight_set(searchbar, EVAS_HINT_EXPAND, 0);
684         evas_object_size_hint_align_set(searchbar, EVAS_HINT_FILL, 0.0);
685
686         evas_object_smart_callback_add(entry, "changed", __cal_search_list_searchbar_entry_changed_callback, p);
687         evas_object_smart_callback_add(entry, "preedit,changed", __cal_search_list_searchbar_entry_changed_callback, p);
688         evas_object_smart_callback_add(entry, "unfocused", __cal_search_list_searchbar_entry_unfocused_callback, p);
689         evas_object_smart_callback_add(entry, "focused", __cal_search_list_searchbar_entry_focused_callback, p);
690         evas_object_smart_callback_add(searchbar, "clicked", __cal_search_list_searchbar_clicked_callback, p);
691         evas_object_smart_callback_add(searchbar, "cancel,clicked", __cal_search_list_cancel_button_callback, p);
692
693         evas_object_show(searchbar);
694         elm_object_part_content_set(p->layout, "searchbar", searchbar);
695
696         p->searchbar = searchbar;
697 }
698
699 static void __cal_search_list_context_popup_hide_callback(void *data, Evas_Object *obj, void *ei)
700 {
701         c_retm_if(!data, "data is null");
702         c_retm_if(!obj,  "obj is null");
703
704         cal_search_list_data* p = data;
705         p->ctx_popup = NULL;
706         evas_object_del(obj);
707
708         c_retm_if(!p->searchbar, "entry is NULL.");
709
710         Evas_Object *entry = elm_object_part_content_get(p->searchbar, "elm.swallow.content");
711         c_retm_if(!entry, "entry is NULL.");
712
713         elm_object_focus_set(entry, EINA_TRUE);
714 }
715
716
717 static void __cal_search_list_context_popup_selected_callback(void *data, Evas_Object *obj, void *ei)
718 {
719         cal_search_list_data* p = CAL_UTIL_GET_PRIV_DATA(obj);
720         c_retm_if(!p, "p is NULL.");
721
722         int index = (int)data;
723
724         if (p->search_type == index) {
725                 elm_ctxpopup_dismiss(obj);
726                 return;
727         }
728
729         p->search_type = index;
730
731         if (p->search_type == CAL_SEARCH_ALL) {
732                 elm_object_text_set(p->scope_button,  S_("IDS_COM_BODY_ALL"));
733         } else if (p->search_type == CAL_SEARCH_EVENTS) {
734                 elm_object_text_set(p->scope_button,  C_("IDS_CLD_BODY_EVENTS"));
735         } else if (p->search_type == CAL_SEARCH_TASKS) {
736                 elm_object_text_set(p->scope_button,  C_("IDS_CLD_BODY_TASKS"));
737         }
738         __cal_search_list_update_list(p);
739
740         elm_ctxpopup_dismiss(obj);
741 }
742
743
744 static void __cal_search_list_create_ctx_popup(cal_search_list_data* p)
745 {
746         c_retm_if(!p, "p is NULL.");
747         c_retm_if(!p->searchbar, "p->searchbar is NULL.");
748
749         int x, y, w, h;
750
751         Evas_Object *ctx = p->ctx_popup;
752
753         if (ctx)
754                 evas_object_del(ctx);
755
756         p->ctx_popup = elm_ctxpopup_add(p->ad->win);
757         c_retm_if(!p->ctx_popup, "elm_ctxpopup_add(p->ad->naviframe) returned null");
758
759         ctx = p->ctx_popup;
760         evas_object_data_set(ctx, "priv", p);
761
762         Evas_Object *entry = elm_object_part_content_get(p->searchbar, "elm.swallow.content");
763         c_retm_if(!entry, "entry is NULL.");
764
765         elm_object_focus_set(entry, EINA_FALSE);
766
767         evas_object_smart_callback_add(ctx, "dismissed", __cal_search_list_context_popup_hide_callback, p);
768         elm_ctxpopup_item_append(ctx, S_("IDS_COM_BODY_ALL"), NULL, __cal_search_list_context_popup_selected_callback, (const void *)0);
769         elm_ctxpopup_item_append(ctx, C_("IDS_CLD_BODY_EVENTS"), NULL, __cal_search_list_context_popup_selected_callback, (const void *)1);
770         elm_ctxpopup_item_append(ctx, C_("IDS_CLD_BODY_TASKS"), NULL, __cal_search_list_context_popup_selected_callback, (const void *)2);
771         elm_object_focus_allow_set(ctx, EINA_FALSE);
772
773         evas_object_geometry_get(p->scope_button, &x, &y, &w, &h);
774
775         evas_object_move(ctx, x + w/2 , y+h);
776
777         elm_ctxpopup_direction_priority_set(ctx, ELM_CTXPOPUP_DIRECTION_DOWN,
778                                                                                                                 ELM_CTXPOPUP_DIRECTION_LEFT,
779                                                                                                                 ELM_CTXPOPUP_DIRECTION_RIGHT,
780                                                                                                                 ELM_CTXPOPUP_DIRECTION_UP);
781         evas_object_show(ctx);
782 }
783
784 static Eina_Bool __cal_search_list_mouse_button_down_callback(void *data, int type, void *event)
785 {
786         c_retvm_if(!event, EINA_FALSE, "event is null");
787         c_retvm_if(!data, EINA_FALSE, "data is null");
788
789         Ecore_Event_Mouse_Button *ev = event;
790         cal_search_list_data *p = data;
791
792         p->x = ev->x;
793         p->y = ev->y;
794
795         return ECORE_CALLBACK_RENEW;
796 }
797
798 Evas_Object* cal_search_list_create_list(struct appdata *ad, Evas_Object *parent)
799 {
800         CAL_FN_START;
801
802         c_retv_if(!ad, NULL);
803         c_retv_if(!parent, NULL);
804
805         if (ad->current_view == CV_SEARCH) {
806                 return NULL;
807         }
808
809         ad->current_view = CV_SEARCH;
810
811         cal_search_list_data *p = calloc(1, sizeof(cal_search_list_data));
812         c_retv_if(!p, NULL);
813
814         p->ad = ad;
815         p->parent = parent;
816
817         p->tm_start.tm_year = 70;
818         p->tm_end.tm_year = 137;
819
820         Evas_Object *layout = cal_util_add_layout(parent, "search/list/base");
821         if (!layout) {
822                 free(p);
823
824                 ERR("layout is null.");
825
826                 return NULL;
827         }
828
829         evas_object_data_set(layout, "priv", p);
830
831         p->layout = layout;
832
833         Evas_Object *bg = cal_util_add_bg(layout, EINA_FALSE);
834         if (!bg) {
835
836                 free(p);
837                 free(layout);
838
839                 ERR("bg is null.");
840
841                 return NULL;
842         }
843
844         elm_object_part_content_set(layout, "base", bg);
845
846         p->navi_item = elm_naviframe_item_push(ad->naviframe, S_("IDS_COM_BODY_SEARCH"), NULL, NULL, layout, NULL);
847         if (!p->navi_item)
848         {
849                 ERR("elm_naviframe_item_push is failed");
850                 evas_object_del(layout);
851                 return NULL;
852         }
853
854         evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, __cal_search_list_delete_layout, p);
855
856         p->event_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, __cal_search_list_mouse_button_down_callback, p);
857
858         cal_lang_manager_add_callback(__cal_search_list_text_refresh_callback, p)
859
860         CAL_FN_END;
861
862         return layout;
863 }
864
865 void cal_search_list_scroll_today(struct appdata* ad)
866 {
867         CAL_FN_START;
868
869         c_retm_if(!ad, "ad is null.");
870
871         Elm_Object_Item* it = ad->today_item;
872         if (it) {
873                 elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
874                 DBG("scroll to : %p", it);
875         }
876
877         CAL_FN_END;
878 }
879
880 void cal_search_list_update_list(Evas_Object *ly)
881 {
882         CAL_FN_START;
883
884         c_ret_if(!ly);
885
886         cal_search_list_data *p = CAL_UTIL_GET_PRIV_DATA(ly);
887         c_ret_if(!p);
888
889         struct appdata *ad = p->ad;
890         c_ret_if(!ad);
891
892         if (!p->searchbar) {
893                 __cal_search_list_create_searchbar(p);
894         }
895
896         __cal_search_list_update_list(p);
897
898         CAL_FN_END;
899 }
900