3 * Copyright 2012 Samsung Electronics Co., Ltd
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
9 * http://floralicense.org/license/
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.
20 #include <Elementary.h>
23 #include "detail-view.h"
24 #include "noti-handler.h"
25 #include <calendar2.h>
26 #include <calendar_view.h>
28 #include "list-base.h"
29 #include "list-broker.h"
31 extern Elm_Genlist_Item_Class cal_list_itc_h;
32 extern Elm_Genlist_Item_Class cal_list_today_group_itc_h;
33 extern Elm_Genlist_Item_Class itc_1icon;
39 Evas_Object* no_contents;
43 Ecore_Idler* fetch_more_top_idler;
44 Ecore_Idler* fetch_more_bottom_idler;
46 Ecore_Event_Handler *event_handler;
50 Elm_Object_Item* navi_item;
51 Elm_Object_Item *bt_new;
52 Elm_Object_Item *bt_delete;
54 struct tm fetch_more_top_current_day;
55 Elm_Object_Item *fetching_more_top;
56 Elm_Object_Item *fetching_more_bottom;
58 cal_list_broker_h append_cursor;
59 cal_list_broker_h prepend_cursor;
61 Eina_Bool is_append_end;
65 static void __cal_list_add_date_group_title(cal_list_data *p, const struct tm* date, bool prepend)
67 struct appdata *ad = p->ad;
70 if (date->tm_year == ad->today_tm.tm_year &&
71 date->tm_mon == ad->today_tm.tm_mon &&
72 date->tm_mday == ad->today_tm.tm_mday) {
74 ad->today_item = cal_list_base_prepend_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_today_group_itc_h, date);
76 ad->today_item = cal_list_base_append_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_today_group_itc_h, date, CAL_TASK_NONE);
79 cal_list_base_prepend_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_itc_h, date);
81 cal_list_base_append_genlist_group_item(cal_list_base_get_genlist_p(p->list), &cal_list_itc_h, date, CAL_TASK_NONE);
85 static void __cal_list_prepend_more(void* data)
87 cal_list_data *p = data;
89 c_ret_if(p->fetch_more_top_idler);
91 cal_list_broker_h cursor = p->prepend_cursor;
94 calendar_record_h record = cal_list_broker_get_next(cursor, &day_has_changed);
98 if (p->prepend_count != 0 && n++ == p->prepend_count)
101 if (day_has_changed) {
102 if (p->fetch_more_top_current_day.tm_mday != 0)
103 __cal_list_add_date_group_title(p, &p->fetch_more_top_current_day, true);
104 p->fetch_more_top_current_day = *cal_list_broker_get_current_day_p(cursor);
107 cal_list_base_add_item(p->list, record, true);
109 record = cal_list_broker_get_next(cursor, &day_has_changed);
112 if (cal_list_broker_no_more(p->prepend_cursor)) {
113 __cal_list_add_date_group_title(p, &p->fetch_more_top_current_day, true);
117 static void __cal_list_append_more(void* data)
119 cal_list_data *p = data;
121 c_ret_if(p->fetch_more_bottom_idler);
126 cal_list_broker_h cursor = p->append_cursor;
128 bool day_has_changed;
129 calendar_record_h record = cal_list_broker_get_next(cursor, &day_has_changed);
132 if (day_has_changed) {
133 const struct tm* tm_current_day = cal_list_broker_get_current_day_p(cursor);
134 if(tm_current_day->tm_year == 137) {
135 p->is_append_end = EINA_TRUE;
138 __cal_list_add_date_group_title(p, tm_current_day, false);
141 cal_list_base_add_item(p->list, record, false);
143 record = cal_list_broker_get_next(cursor, &day_has_changed);
147 static Eina_Bool __cal_list_fetch_more_top(void* data)
149 cal_list_data *p = data;
151 cal_list_broker_fetch(p->prepend_cursor);
153 ecore_idler_del(p->fetch_more_top_idler);
154 p->fetch_more_top_idler = NULL;
156 if (p->fetching_more_top) { // UI is waiting for fetch to finish so that items can be prepended.
157 elm_object_item_del(p->fetching_more_top);
158 p->fetching_more_top = NULL;
159 __cal_list_prepend_more(p);
160 cal_list_broker_fetch(p->prepend_cursor); // Do next prefetch right away.
163 return ECORE_CALLBACK_CANCEL;
166 static Eina_Bool __cal_list_fetch_more_bottom(void* data)
168 cal_list_data *p = data;
170 cal_list_broker_fetch(p->append_cursor);
172 ecore_idler_del(p->fetch_more_bottom_idler);
173 p->fetch_more_bottom_idler = NULL;
175 if (p->fetching_more_bottom) { // UI is waiting for fetch to finish so that items can be appended.
176 elm_object_item_del(p->fetching_more_bottom);
177 p->fetching_more_bottom = NULL;
178 __cal_list_append_more(p);
179 cal_list_broker_fetch(p->append_cursor); // Do next prefetch right away.
182 return ECORE_CALLBACK_CANCEL;
185 void __cal_list_show_fetching_more_top(cal_list_data* p)
187 if (p->fetching_more_top)
189 Elm_Object_Item* it = elm_genlist_first_item_get(cal_list_base_get_genlist_p(p->list));
190 p->fetching_more_top = elm_genlist_item_prepend(cal_list_base_get_genlist_p(p->list), &itc_1icon, p, it, ELM_GENLIST_ITEM_NONE, NULL, NULL);
193 void __cal_list_show_fetching_more_bottom(cal_list_data* p)
195 if (p->fetching_more_bottom)
197 p->fetching_more_bottom = elm_genlist_item_prepend(cal_list_base_get_genlist_p(p->list), &itc_1icon, p, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
200 static void __cal_list_gl_mode_scroll_to_top(void *data, Evas_Object *obj, void *event_info)
202 c_ret_if(!obj || !data);
203 cal_list_data *p = data;
205 if(cal_list_broker_no_more(p->prepend_cursor))
208 if (p->fetch_more_top_idler) { // fetching in progress
209 __cal_list_show_fetching_more_top(p);
213 __cal_list_prepend_more(p);
214 p->fetch_more_top_idler = ecore_idler_add(__cal_list_fetch_more_top, p); // Schedule next prefetch right away.
217 static void __cal_list_gl_mode_scroll_to_bottom(void *data, Evas_Object *obj, void *event_info)
219 c_ret_if(!obj || !data);
220 cal_list_data *p = data;
222 if(cal_list_broker_no_more(p->append_cursor))
225 if (p->fetch_more_bottom_idler) { // fetching in progress
226 __cal_list_show_fetching_more_bottom(p);
230 __cal_list_append_more(p);
231 p->fetch_more_bottom_idler = ecore_idler_add(__cal_list_fetch_more_bottom, p); // Schedule next prefetch right away.
234 static void __cal_list_create_no_contents(cal_list_data *p)
239 c_ret_if(!p->layout);
246 title = C_("IDS_CLD_BODY_NO_EVENTS");
248 Evas_Object *no_contents = cal_util_add_search_nocontents(p->layout, title);
249 c_ret_if(!no_contents);
251 elm_object_part_content_set(p->layout, "sw", no_contents);
253 p->no_contents = no_contents;
256 static void __cal_list_delete_no_contents(cal_list_data *p)
265 elm_object_part_content_unset(p->layout, "sw");
267 evas_object_del(p->no_contents);
269 p->no_contents = NULL;
272 #define MIN_ITEM_COUNT_TO_FILL_PAGE 8
274 static void __cal_list_update_list(cal_list_data *p)
280 struct appdata *ad = p->ad;
282 ad->today_item = NULL;
284 p->fetch_more_top_current_day.tm_mday = 0;
286 if (p->list != NULL) {
287 cal_list_base_delete(p->list);
291 if (p->prepend_cursor != NULL)
292 cal_list_broker_destroy(p->prepend_cursor);
293 if (p->append_cursor != NULL)
294 cal_list_broker_destroy(p->append_cursor);
296 p->prepend_cursor = cal_list_broker_create(&ad->base_tm, -1, ad->is_display_complete_todo);
297 p->append_cursor = cal_list_broker_create(&ad->base_tm, 1, ad->is_display_complete_todo);
299 cal_list_broker_h cursor = p->append_cursor;
301 cal_list_broker_fetch(cursor);
303 bool day_has_changed;
304 calendar_record_h record = cal_list_broker_get_next(cursor, &day_has_changed);
308 if (p->list == NULL) {
309 __cal_list_delete_no_contents(p);
310 p->list = cal_list_base_create(ad, p->layout, "sw", true, NULL, NULL);
313 // Eina_Bool today_has_instance = EINA_FALSE;
316 if (day_has_changed) {
317 const struct tm* tm_current_day = cal_list_broker_get_current_day_p(cursor);
318 __cal_list_add_date_group_title(p, tm_current_day, false);
321 cal_list_base_add_item(p->list, record, false);
323 record = cal_list_broker_get_next(cursor, &day_has_changed);
327 if (p->list == NULL || cal_list_base_get_item_count(p->list) < MIN_ITEM_COUNT_TO_FILL_PAGE) {
329 cal_list_broker_fetch(p->prepend_cursor);
331 if (!cal_list_broker_no_more(p->prepend_cursor)) {
333 if (p->list == NULL) {
334 __cal_list_delete_no_contents(p);
335 p->list = cal_list_base_create(ad, p->layout, "sw", true, NULL, NULL);
338 p->prepend_count = MIN_ITEM_COUNT_TO_FILL_PAGE - cal_list_base_get_item_count(p->list);
339 __cal_list_prepend_more(p);
341 elm_genlist_item_bring_in(
342 elm_genlist_last_item_get(cal_list_base_get_genlist_p(p->list)),
343 ELM_GENLIST_ITEM_SCROLLTO_IN);
347 p->prepend_count = 10;
349 if (p->list == NULL) {
350 cal_list_base_delete(p->list);
351 __cal_list_create_no_contents(p);
353 evas_object_smart_callback_add(cal_list_base_get_genlist_p(p->list), "edge,bottom", __cal_list_gl_mode_scroll_to_bottom, p);
354 evas_object_smart_callback_add(cal_list_base_get_genlist_p(p->list), "edge,top", __cal_list_gl_mode_scroll_to_top, p);
357 // if (!today_has_instance) {
358 // cal_list_genlist_item_data *item_data = calloc(1, sizeof(cal_list_genlist_item_data));
359 // c_retm_if(!item_data, "calloc is failed");
361 // item_data->tm = calloc(1, sizeof(struct tm));
362 // c_retm_if(!item_data->tm, "malloc is failed");
364 // *(item_data->tm) = ad->today_tm;
365 // item_data->todo_group_type = CAL_TASK_NONE;
367 // Elm_Object_Item *first_item = elm_genlist_first_item_get(cal_list_base_get_genlist_p(p->list));
368 // item_data->it = elm_genlist_item_insert_before(cal_list_base_get_genlist_p(p->list), &cal_list_today_group_itc_h, item_data, NULL, first_item, ELM_GENLIST_ITEM_NONE, NULL, NULL);
369 // if (item_data->it == NULL) {
370 // ERR("insert failed");
371 // free(item_data->tm);
375 // elm_genlist_item_select_mode_set(item_data->it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
378 p->fetch_more_top_idler = ecore_idler_add(__cal_list_fetch_more_top, p);
379 p->fetch_more_bottom_idler = ecore_idler_add(__cal_list_fetch_more_bottom, p);
384 static void __cal_list_day_event_changed_callback(const char* view_uri, void *user_data)
386 c_retm_if(!user_data, "user_data is null");
388 cal_list_data *p = user_data;
390 cal_list_base_delete_popup(p->list);
392 cal_list_update_view(p->layout);
395 static void __cal_list_delete_layout(void *data, Evas *e, Evas_Object *obj, void *ei)
399 cal_list_data *p = data;
400 c_retm_if(!p, "priv is null.");
402 if (p->fetch_more_bottom_idler) {
403 ecore_idler_del(p->fetch_more_bottom_idler);
404 p->fetch_more_bottom_idler = NULL;
407 if (p->fetch_more_top_idler) {
408 ecore_idler_del(p->fetch_more_top_idler);
409 p->fetch_more_top_idler = NULL;
412 cal_list_base_delete_popup_idler(p->list);
414 calendar_db_remove_changed_cb(_calendar_event._uri, __cal_list_day_event_changed_callback, p);
416 if (p->event_handler)
417 ecore_event_handler_del(p->event_handler);
419 cal_list_base_delete_popup(p->list);
426 static Eina_Bool __cal_list_mouse_button_down_callback(void *data, int type, void *event)
428 c_retvm_if(!event, EINA_FALSE, "event is null");
429 c_retvm_if(!data, EINA_FALSE, "data is null");
431 Ecore_Event_Mouse_Button *ev = event;
432 cal_list_data *p = data;
437 return ECORE_CALLBACK_RENEW;
440 void cal_list_scroll_today(struct appdata* ad)
444 c_retm_if(!ad, "ad is null.");
446 Elm_Object_Item* it = ad->today_item;
448 elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
449 DBG("scroll to : %p", it);
455 static void __cal_list_update_delete_button(cal_list_data *p)
459 Elm_Object_Item *delete_button = NULL;
461 delete_button = p->ad->bt_delete;
463 if (cal_list_base_get_genlist_p(p->list) && elm_genlist_first_item_get(cal_list_base_get_genlist_p(p->list)))
464 elm_object_item_disabled_set(delete_button, EINA_FALSE);
466 elm_object_item_disabled_set(delete_button, EINA_TRUE);
469 Evas_Object* cal_list_create_view(struct appdata *ad, Evas_Object *main)
474 c_retv_if(!ad, NULL);
475 c_retv_if(!main, NULL);
477 cal_list_data *p = calloc(1, sizeof(cal_list_data));
482 Evas_Object *layout = cal_util_add_layout(main, "list/base/without_searchbar");
483 ad->tapbar_focus_view = CV_LIST;
488 ERR("layout is null.");
493 evas_object_data_set(layout, "priv", p);
497 elm_object_disabled_set(p->ad->new_event_button, EINA_FALSE);
499 Evas_Object *bg = cal_util_add_bg(layout, EINA_FALSE);
510 elm_object_part_content_set(layout, "base", bg);
512 evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, __cal_list_delete_layout, p);
514 p->event_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, __cal_list_mouse_button_down_callback, p);
521 void cal_list_update_view(Evas_Object *ly)
529 cal_list_data *p = CAL_UTIL_GET_PRIV_DATA(ly);
532 struct appdata *ad = p->ad;
535 __cal_list_update_list(p);
537 __cal_list_update_delete_button(p);