Tizen 2.1 base
[apps/core/preloaded/calendar.git] / src / month-calendar.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 #include <vconf.h>
19
20 #include "view.h"
21 #include "edit-view.h"
22 #include "detail-view.h"
23 #include "cld-images.h"
24 #include "list-base.h"
25 #include "month-data.h"
26
27 #define WEEKS_OF_MONTH_5 5
28 #define WEEKS_OF_MONTH_4 4
29
30 enum {
31         ST_PREV = -1,
32         ST_CURR = 0,
33         ST_NEXT = 1,
34 };
35
36 typedef enum {
37         CAL_MONTH_CALENDAR_DAY_TYPE_SUNDAY = 0,
38         CAL_MONTH_CALENDAR_DAY_TYPE_SATDAY,
39         CAL_MONTH_CALENDAR_DAY_TYPE_WEEKDAY,
40 } cal_month_calendar_day_type_t;
41
42 struct _day {
43         int enabled:1;
44         int checked:1;
45         cal_month_calendar_day_type_t d_type;
46 };
47
48 typedef struct {
49         const char *name;
50         struct appdata *ad;
51         Evas_Object *parent;
52         Evas_Object *weekly_events_ly[WEEKS_OF_MONTH];
53         Evas_Object *month;
54         Evas_Object *month_monthly;
55         Evas_Object *month_daily;
56         Evas_Object *month_landscape;
57         Eina_List *event_list;
58         cal_list_base_h list;
59         Evas_Object *popup;
60
61         Ecore_Idler *idler;
62
63         int base_pos_for_weekly;
64         int index_for_press;
65         struct _day day[DAYS_OF_WEEKLY_MONTHS_VIEW];
66         int pos_today;
67         int pos_selected;
68         int pos_start;
69         int pos_end;
70         int pos_down;
71         cal_month_data_h month_data;
72         int weekline;
73         int down_x;
74         int down_y;
75 } cal_month_calendar_data;
76
77 static const char *_name = NULL;
78
79 static void __cal_month_calendar_signal_week(cal_month_calendar_data *p, Evas_Object *obj, int index);
80
81 static void __cal_month_calendar_events_of_one_weekday(void *data);
82 static void __cal_month_calendar_get_events(cal_month_calendar_data *p);
83 static void __cal_month_calendar_create_event_lists(Evas_Object *ly, cal_month_calendar_data *p);
84 static void __cal_month_calendar_signal_all_week(cal_month_calendar_data *p);
85 static void __cal_month_calendar_signal_all_clean(cal_month_calendar_data *p);
86 static void __cal_month_calendar_set_more_text(Evas_Object *ly, int count, int index);
87 static void __cal_month_calendar_set_check_text(Evas_Object *ly, cal_month_calendar_data *p, int count, int index);
88 static void __cal_month_calendar_set_event_rect_color(Evas_Object *obj, cal_month_calendar_data *p, int line, int pos, int calendar_id);
89 static void __cal_month_calendar_set_day_default_color(cal_month_calendar_data* p, Evas_Object *eo, int pos);
90 static void __cal_month_calendar_fill_week_number(Evas_Object *ly);
91 static void __cal_month_quick_add_input_panel_event_callback(void *data, Ecore_IMF_Context *imf_context, int value);
92
93
94 static Elm_Genlist_Item_Class itc_1icon_title, itc_1icon_start, itc_1icon_end;
95
96 static int __cal_month_calendar_get_first_wday(int mday, int wday)
97 {
98         return CAL_UTIL_GET_WDAY(wday - mday + 1);
99 }
100
101 static void __cal_month_calendar_delete_layout(void *data, Evas *e, Evas_Object *obj, void *ei)
102 {
103         CAL_FN_START;
104
105         c_retm_if(!data, "data is null");
106         cal_month_calendar_data *p = data;
107
108         struct appdata *ad = p->ad;
109         c_retm_if(!ad, "ad is null");
110
111         if (ad->today_edj && ad->today_edj == CAL_UTIL_GET_EDJ_DATA(obj))
112                 ad->today_edj = NULL;
113
114         if (p->idler)
115                 ecore_idler_del(p->idler);
116
117         if (p->popup) {
118                 ad->need_to_show_popup = EINA_TRUE;
119                 evas_object_del(p->popup);
120         }
121
122         cal_month_data_clear(p->month_data);
123
124         cal_month_data_destroy(p->month_data);
125
126         free(p);
127
128         CAL_FN_END;
129 }
130
131 static inline void __cal_month_calendar_set_color(Evas_Object *ly, cal_month_calendar_data *p, int pos, int wday)
132 {
133         c_retm_if(!p, "p is null");
134
135         struct _day *d = &p->day[pos];
136
137         const char *day_color;
138
139         switch (wday) {
140         case 0:
141                 day_color = "sunday";
142                 d->d_type = CAL_MONTH_CALENDAR_DAY_TYPE_SUNDAY;
143                 break;
144         case 6:
145                 day_color = "satday";
146                 d->d_type = CAL_MONTH_CALENDAR_DAY_TYPE_SATDAY;
147                 break;
148         default:
149                 d->d_type = CAL_MONTH_CALENDAR_DAY_TYPE_WEEKDAY;
150                 day_color = "weekday";
151                 break;
152         }
153
154         cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "%s,%d", day_color, pos);
155 }
156
157 static inline void __cal_month_calendar_set_disabled(Evas_Object *ly, cal_month_calendar_data *p, int pos)
158 {
159         struct _day *d = &p->day[pos];
160
161         cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "disable,%d", pos);
162
163         d->enabled = 0;
164 }
165
166 static inline void __cal_month_calendar_set_enabled(Evas_Object *ly, cal_month_calendar_data *p, int pos, int wday)
167 {
168         struct _day *d = &p->day[pos];
169
170         if (!d->enabled) {
171                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "enable,%d", pos);
172
173                 __cal_month_calendar_set_color(ly, p, pos, wday);
174                 d->enabled = 1;
175         }
176 }
177
178 static inline void __cal_month_calendar_set_today(Evas_Object *eo, int pos)
179 {
180         if (pos == -1)
181                 return;
182
183         cal_util_emit_signal(eo, "today,%d", pos);
184 }
185
186 static inline void __cal_month_calendar_unset_today(Evas_Object *eo, int *pos)
187 {
188         if (*pos == -1)
189                 return;
190
191         cal_util_emit_signal(eo, "notoday,%d", *pos);
192         *pos = -1;
193 }
194
195 static inline void __cal_month_calendar_set_selected(Evas_Object *eo, int pos)
196 {
197         if (pos < 0 || DAYS_OF_WEEKLY_MONTHS_VIEW <= pos)
198                 return;
199
200         cal_util_emit_signal(eo, "select,%d", pos);
201 }
202
203 static inline void __cal_month_calendar_set_unselected(cal_month_calendar_data* p, Evas_Object *eo, int *pos)
204 {
205         c_retm_if(!p, "p is NULL");
206         c_retm_if(-1 == *pos, "pos is invalid");
207         c_retm_if(!eo, "eo is invalid");
208
209         cal_util_emit_signal(eo, "unselect,%d", *pos);
210
211         __cal_month_calendar_set_day_default_color(p, eo, *pos);
212
213         *pos = -1;
214 }
215
216 static inline int __cal_month_calendar_get_start_day(int *st, struct tm *tm, int start, int max)
217 {
218         int day;
219         int prev_day;
220
221         prev_day = CAL_UTIL_GET_WDAY(__cal_month_calendar_get_first_wday(tm->tm_mday, tm->tm_wday) - start);
222         if (prev_day > 0) {
223                 day = max - prev_day + 1;
224                 *st = ST_PREV;
225         } else {
226                 day = 1;
227                 *st = ST_CURR;
228         }
229
230         return day;
231 }
232
233 static int __cal_month_calendar_update_today(Evas_Object *eo, cal_month_calendar_data *p)
234 {
235         c_retv_if(!eo, -1);
236         c_retv_if(!p, -1);
237
238         struct appdata *ad = p->ad;
239         c_retv_if(!ad, -1);
240
241         struct tm *base_tm = &ad->base_tm;
242         c_retv_if(!base_tm, -1);
243
244         __cal_month_calendar_unset_today(eo, &p->pos_today);
245
246         ad->today_edj = NULL;
247
248         if (base_tm->tm_year == ad->today_tm.tm_year && base_tm->tm_mon == ad->today_tm.tm_mon) {
249                 p->pos_today = p->pos_start + ad->today_tm.tm_mday - 1;
250                 __cal_month_calendar_set_today(eo, p->pos_today);
251                 ad->today_edj = eo;
252         }
253
254         return 0;
255 }
256
257 static inline void __cal_month_calendar_set_selected_today(Evas_Object *eo, int pos)
258 {
259         if (pos < 0 || DAYS_OF_WEEKLY_MONTHS_VIEW <= pos)
260                 return;
261
262         cal_util_emit_signal(eo, "select,today,%d", pos);
263 }
264
265 void cal_month_calendar_update_select(Evas_Object *ly)
266 {
267         CAL_ASSERT(ly);
268         Evas_Object* eo = CAL_UTIL_GET_EDJ_DATA(ly);
269
270         cal_month_calendar_data* p = CAL_UTIL_GET_PRIV_DATA(ly);
271         CAL_ASSERT(p);
272         CAL_ASSERT(p->ad);
273
274         struct appdata *ad = p->ad;
275         c_ret_if(!ad);
276
277         struct tm *base_tm = &ad->base_tm;
278         c_ret_if(!base_tm);
279
280         cal_main_update_title_text(p->ad);
281
282         __cal_month_calendar_set_unselected(p, eo, &p->pos_selected);
283         p->pos_selected = p->pos_start + p->ad->base_tm.tm_mday - 1;
284
285         if (base_tm->tm_year == ad->today_tm.tm_year && base_tm->tm_mon == ad->today_tm.tm_mon && base_tm->tm_mday == ad->today_tm.tm_mday) {
286                 __cal_month_calendar_set_selected_today(eo, p->pos_selected);
287         } else {
288                 __cal_month_calendar_set_selected(eo, p->pos_selected);
289         }
290
291
292 }
293
294 static void __cal_month_calendar_update_check(Evas_Object *ly, cal_month_calendar_data *p)
295 {
296         c_ret_if(!ly);
297         c_ret_if(!p);
298         c_ret_if(p->pos_start < 0);
299
300         struct appdata *ad = p->ad;
301         c_ret_if(!ad);
302
303         int week = 0;
304         for (week = 0; week < WEEKS_OF_MONTH; week++) {
305                 int wday = 0;
306                 for (wday = 0; wday < DAYS_OF_WEEK; wday++) {
307                         int count = cal_month_data_get_event_count(p->month_data, week, wday);
308                         __cal_month_calendar_set_check_text(ly, p, count, week * DAYS_OF_WEEK + wday);
309                 }
310         }
311 }
312
313 static int __cal_month_calendar_get_week_last_line(cal_month_calendar_data *p, int wday)
314 {
315         c_retv_if(!p, -1);
316
317         struct appdata *ad = p->ad;
318         c_retv_if(!ad, -1);
319
320         struct tm base_tm = ad->base_tm;
321
322         int prev_max = cal_util_get_max_days(base_tm.tm_year, base_tm.tm_mon - 1);
323         int cur_max = cal_util_get_max_days(base_tm.tm_year, base_tm.tm_mon);
324
325         int st;
326         int day = __cal_month_calendar_get_start_day(&st, &base_tm, wday, prev_max);
327
328         p->pos_start = 0;
329         p->pos_end = 41;
330
331         int i;
332         int line = WEEKS_OF_MONTH;
333
334         for (i = 0; i < DAYS_OF_WEEKLY_MONTHS_VIEW; i++) {
335                 switch (st) {
336
337                 case ST_PREV:
338                         if (day == prev_max) {
339                                 st = ST_CURR;
340                                 day = 0;
341                                 p->pos_start = i + 1;
342                         }
343                         break;
344
345                 case ST_CURR:
346                         if (day == cur_max) {
347                                 st = ST_NEXT;
348                                 day = 0;
349                                 line = (int)(i / DAYS_OF_WEEK) + 1;
350                                 p->pos_end = i;
351                         }
352                         break;
353
354                 case ST_NEXT:
355                         break;
356                 }
357
358                 day++;
359                 wday = CAL_UTIL_GET_WDAY(wday + 1);
360         }
361
362         return line;
363 }
364
365 static int __cal_month_calendar_fill_calendar(Evas_Object *ly, int wday)
366 {
367         c_retv_if(!ly, -1);
368
369         cal_month_calendar_data *p = CAL_UTIL_GET_PRIV_DATA(ly);
370         c_retv_if(!p, -1);
371
372         struct appdata *ad = p->ad;
373         c_retv_if(!ad, -1);
374
375         struct tm base_tm = ad->base_tm;
376
377         int prev_max = cal_util_get_max_days(base_tm.tm_year, base_tm.tm_mon - 1);
378         int cur_max = cal_util_get_max_days(base_tm.tm_year, base_tm.tm_mon);
379
380         int st;
381         int day = __cal_month_calendar_get_start_day(&st, &base_tm, wday, prev_max);
382
383         p->pos_start = 0;
384         p->pos_end = 41;
385
386         int i;
387         int line = WEEKS_OF_MONTH;
388
389         for (i = 0; i < DAYS_OF_WEEKLY_MONTHS_VIEW; i++) {
390                 cal_util_set_text(CAL_UTIL_GET_EDJ_DATA(ly), cal_util_get_part_text("db/%d/text", i), "%d", day);
391
392                 switch (st) {
393
394                 case ST_PREV:
395                         __cal_month_calendar_set_disabled(ly, p, i);
396                         if (day == prev_max) {
397                                 st = ST_CURR;
398                                 day = 0;
399                                 p->pos_start = i + 1;
400                         }
401                         break;
402
403                 case ST_CURR:
404                         __cal_month_calendar_set_enabled(ly, p, i, wday);
405                         if (day == cur_max) {
406                                 st = ST_NEXT;
407                                 day = 0;
408                                 line = (int)(i / DAYS_OF_WEEK) + 1;
409                                 p->pos_end = i;
410                         }
411                         break;
412
413                 case ST_NEXT:
414                         __cal_month_calendar_set_disabled(ly, p, i);
415                         break;
416                 }
417
418                 day++;
419                 wday = CAL_UTIL_GET_WDAY(wday + 1);
420         }
421
422         __cal_month_calendar_update_today(CAL_UTIL_GET_EDJ_DATA(ly), p);
423
424         __cal_month_calendar_fill_week_number(ly);
425
426         return line;
427 }
428
429 static void __cal_month_calendar_click_event_callback(cal_month_calendar_data *p, Evas_Object *obj, int pos)
430 {
431         c_ret_if(!p);
432
433         struct appdata *ad = p->ad;
434         c_ret_if(!ad);
435
436         if (p->pos_selected == pos) {
437                 DBG("cal_cb: double clicked %d", pos);
438
439                 if (p->day[pos].checked) {
440                         __cal_month_calendar_events_of_one_weekday(p);
441                 } else {
442                         ad->base_hour = -1;
443                         ad->cid = 0;
444
445                         calendar_record_h record = NULL;
446                         calendar_error_e error = CALENDAR_ERROR_NONE;
447
448                         error = calendar_record_create(_calendar_event._uri, &record);
449                         c_retm_if(error != CALENDAR_ERROR_NONE, "calendar_record_create() is failed(%x)", error);
450                         cal_edit_create_view(ad, record, NULL, NULL);
451                 }
452
453                 return;
454         }
455
456         ad->base_tm.tm_mday = pos - p->pos_start + 1;
457
458         cal_month_calendar_update_select(p->month);
459
460         edje_object_signal_emit(obj, "changed", "prog");
461 }
462
463 static void __cal_month_calendar_cal_event_callback(void *data, Evas_Object *obj, const char *e, const char *src)
464 {
465         cal_month_calendar_data *p = data;
466         c_retm_if(!p, "p is null");
467
468         struct appdata *ad = p->ad;
469         c_retm_if(!ad, "ad is null");
470
471         int pos = atoi(&e[3]);
472         c_retm_if((p->pos_end < pos) || (pos < p->pos_start), "pos is diabled");
473
474         if (!strncmp(e, "up,", 3)) {
475
476                 if (p->pos_down == pos) {
477                         __cal_month_calendar_click_event_callback(p, obj, pos);
478                 }
479
480                 edje_object_signal_emit(obj, e, "prog");
481
482         }else if (!strncmp(e, "dn,", 3)) {
483
484                 p->pos_down = pos;
485
486                 edje_object_signal_emit(obj, e, "prog");
487         }
488 }
489
490 static void __cal_month_calendar_prog_event_callback(void *data, Evas_Object *obj, const char *e, const char *src)
491 {
492         cal_month_calendar_data *p = data;
493
494         if (!CAL_STRCMP(e, "update_today")) {
495                 __cal_month_calendar_update_today(obj, p);
496                 return;
497         }
498
499         if (CAL_STRCMP(e, "moved")) {
500                 return;
501         }
502
503         if (p->pos_down == -1) {
504                 return;
505         }
506
507         cal_util_emit_signal(obj, "up,%d", p->pos_down);
508         if (p->pos_selected!= p->pos_down) {
509                 __cal_month_calendar_set_day_default_color(p, obj, p->pos_down);
510                 cal_util_emit_signal(obj, "unselect,%d", p->pos_down);
511         }
512         p->pos_down = -1;
513 }
514
515 void cal_month_calendar_set_wday_text(Evas_Object *ly, int start)
516 {
517         c_ret_if(!ly);
518
519         cal_month_calendar_data* p = CAL_UTIL_GET_PRIV_DATA(ly);
520         c_ret_if(!p);
521
522         struct appdata *ad = p->ad;
523         c_ret_if(!ad);
524
525         struct tm base_tm = ad->base_tm;
526
527         cal_util_update_tm_day(&base_tm, base_tm.tm_wday*(-1)+start);
528
529         int i;
530         for (i = 0; i < DAYS_OF_WEEK; i++) {
531                 cal_util_set_time_text_toupper(CAL_UTIL_GET_EDJ_DATA(ly), cal_util_get_part_text("wday/%d/text", i), CAL_UTIL_DATE_FORMAT_2, NULL, &base_tm);
532
533                 if (base_tm.tm_wday == 6)
534                         cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "satday,%d", i);
535
536                 if (base_tm.tm_wday == 0)
537                         cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "sunday,%d", i);
538
539                 cal_util_update_tm_day(&base_tm, 1);
540         }
541
542         edje_object_part_text_set(CAL_UTIL_GET_EDJ_DATA(ly),  "wday/weeknumber/text", C_("IDS_CLD_POP_WEEK_INITIAL"));
543 }
544
545 static void __cal_month_calendar_signal_clean(cal_month_calendar_data *p,Evas_Object *eo)
546 {
547         c_retm_if(!p, "p is null");
548         c_retm_if(!eo, "eo is null");
549
550         int i = 0;
551         int line = 0;
552
553         for (i = 0; i < DAYS_OF_WEEK; i++) {
554                 for (line = 1; line <= WEEKS_OF_MONTH; line++) {
555                         cal_util_emit_signal(eo, "%d,%d,%d", line, 0, i);
556                         cal_util_emit_signal(eo, "%d,%s,%d", line, "nocolor", i);
557                 }
558         }
559
560 }
561
562 static int __cal_month_calendar_get_week_time(cal_month_calendar_data *p, int *first_day, int *last_day)
563 {
564         int day = 0;
565         int today = 0;
566         int start_day = 0;
567
568         if(-1 == p->pos_selected)
569                 day = p->pos_today;
570         else
571                 day = p->pos_selected;
572
573         today = day - p->pos_start + 1;
574         start_day = day - ((day + 1) % DAYS_OF_WEEK) + 1;
575
576         if (day < DAYS_OF_WEEK) {
577                 *first_day = 1;
578                 *last_day = DAYS_OF_WEEK - p->pos_start;
579         } else if (0 == ((day + 1) % DAYS_OF_WEEK)) {
580                 *first_day = today - DAYS_OF_WEEK + 1;
581                 *last_day = today;
582         } else {
583                 *first_day = today - (day % DAYS_OF_WEEK);
584                 if ((start_day + DAYS_OF_WEEK - 1) > p->pos_end) {
585                         *last_day = p->pos_end - p->pos_start + 1;
586                 } else {
587                         *last_day = *first_day + DAYS_OF_WEEK - 1;
588                 }
589         }
590
591         return 0;
592 }
593
594 static void __cal_month_calendar_signal_week(cal_month_calendar_data *p, Evas_Object *obj, int week)
595 {
596         c_ret_if(!p);
597         c_ret_if(!obj);
598
599         int wday = 0;
600         char text[20] = {0};
601
602         Evas_Object *eo = CAL_UTIL_GET_EDJ_DATA(obj);
603         c_ret_if(!eo);
604
605         for (wday = 0; wday < DAYS_OF_WEEK; wday++) {
606
607                 if (cal_month_data_get_event_count(p->month_data, week, wday) == 0)
608                         continue;
609
610                 int row;
611                 for (row = 1; row <= CAL_MONTH_MAX_ROWS_PER_CELL; row++) {
612                         cal_month_calendar_event* event =
613                                         cal_month_data_get_event(p->month_data, week, wday, row - 1);
614
615                         if (event == NULL)
616                                 continue;
617
618                         cal_util_emit_signal(eo, "%d,%d,%d", row, event->width, wday);
619                         cal_util_emit_signal(eo, "%d,show,%d", row, wday);
620
621                         __cal_month_calendar_set_event_rect_color(obj, p, row, wday, event->calendar_id);
622
623                         memset(text,0x00,sizeof(text));
624                         g_snprintf(text, sizeof(text), "%d/text/%d", row, wday);
625                         edje_object_part_text_set(eo, text, event->title);
626                 }
627         }
628 }
629
630 static void __cal_month_calendar_mouse_down(void *data, Evas *e, Evas_Object *ly, void *ei)
631 {
632         c_retm_if(!data, "p is null");
633         c_retm_if(!ly, "ly is null");
634         c_retm_if(!ei, "ei is null");
635
636         cal_month_calendar_data *p = data;
637         Evas_Event_Mouse_Down *ev = ei;
638         char eve[8] = {0};
639         int offset = 0;
640
641         int list_index = (int)evas_object_data_get(ly, "list_index");
642         p->base_pos_for_weekly = list_index * DAYS_OF_WEEK;
643
644         Evas_Coord_Rectangle r;
645         cal_util_get_geometry(&r, ly);
646         offset = ev->canvas.x / (r.w / DAYS_OF_WEEK);
647         if (DAYS_OF_WEEK <= offset)
648                 offset = DAYS_OF_WEEK - 1;
649
650         p->down_x = ev->canvas.x;
651         p->down_y = ev->canvas.y;
652
653         if (p->day[p->base_pos_for_weekly + offset].enabled) {
654                 p->index_for_press = p->base_pos_for_weekly + offset;
655                 snprintf(eve, sizeof(eve) , "dn,%d", p->index_for_press);
656                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->month), eve, "cal");
657         }
658 }
659
660 static void __cal_month_calendar_mouse_move(void *data, Evas *e, Evas_Object *ly, void *ei)
661 {
662         c_retm_if(!data, "data is null");
663         c_retm_if(!ly, "ly is null");
664         c_retm_if(!ei, "ei is null");
665
666         cal_month_calendar_data *p = data;
667         Evas_Event_Mouse_Move *ev = ei;
668         char eve[8] = {0};
669         Evas_Coord th = elm_config_finger_size_get();
670         Evas_Coord dx;
671         Evas_Coord dy;
672
673         dx = ev->cur.canvas.x - p->down_x ;
674         dy = p->down_y - ev->cur.canvas.y;
675         if (dy > th ||  dy < (th * -1) || dx > th ||  dx < (th * -1)) {
676
677                 if( -1 != p->index_for_press) {
678                         snprintf(eve, sizeof(eve) , "up,%d", p->index_for_press);
679                         edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->month), eve, "prog");
680                         if (p->pos_selected != p->index_for_press) {
681                                 __cal_month_calendar_set_day_default_color(p, CAL_UTIL_GET_EDJ_DATA(p->month), p->index_for_press);
682                                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(p->month), "unselect,%d", p->index_for_press);
683                         }
684                         p->index_for_press = -1;
685                 }
686         }
687 }
688
689 static void __cal_month_calendar_get_events(cal_month_calendar_data *p)
690 {
691         struct tm tm_start = p->ad->base_tm;
692         tm_start.tm_hour = 0;
693         tm_start.tm_min = 0;
694         tm_start.tm_sec = 0;
695
696         struct tm tm_end = tm_start;
697         tm_end.tm_hour = 23;
698         tm_end.tm_min = 59;
699         tm_end.tm_sec = 59;
700         p->event_list = _calendar_get_all_instance_list(&tm_start, &tm_end);
701
702         Eina_List *todo_list = _calendar_get_due_date_task_list(&tm_start, &tm_end, p->ad->is_display_complete_todo, _CALENDAR_TASK_SORT_TYPE_DUEDATE_ASC);
703         p->event_list = eina_list_merge(p->event_list, todo_list);
704 }
705
706 static void __cal_month_calendar_update_genlist(cal_month_calendar_data *p)
707 {
708         CAL_FN_START;
709
710         c_retm_if(!p, "p is null");
711         c_retm_if(!p->list, "p->list is null");
712
713         Eina_List *l;
714         calendar_record_h record = NULL;
715
716         cal_list_base_clear(p->list);
717
718         if (p->event_list)
719                 _calendar_free_record_list(&p->event_list);
720
721         __cal_month_calendar_get_events(p);
722         c_retm_if(!p->event_list, "p->event_list is null");
723
724         EINA_LIST_FOREACH(p->event_list, l, record) {
725                 if (record) {
726                         cal_list_base_add_item(p->list, record, false);
727                 }
728         }
729         CAL_FN_END;
730 }
731
732 static void __cal_month_calendar_popup_response_callback(void *data, Evas_Object *obj, void *ei)
733 {
734         c_retm_if(!data, "data is null");
735
736         Evas_Object *popup = data;
737
738         cal_month_calendar_data *p = evas_object_data_get(popup, "data");
739         c_ret_if(!p);
740
741         evas_object_del(popup);
742         p->popup = NULL;
743
744         c_ret_if(!cal_list_base_get_genlist_p(p->list));
745         cal_list_base_delete(p->list);
746
747         p->list = NULL;
748
749         struct appdata *ad = p->ad;
750         c_ret_if(!ad);
751
752         ad->need_to_show_popup = EINA_FALSE;
753 }
754
755 static void __cal_month_calendar_popup_genlist_item_selected_callback(void *data)
756 {
757         c_retm_if(!data, "data is null");
758
759         cal_month_calendar_data *p = data;
760         c_retm_if(!p->popup, "p->popup is null");
761
762         evas_object_del(p->popup);
763         p->popup = NULL;
764
765         c_ret_if(!cal_list_base_get_genlist_p(p->list));
766         cal_list_base_delete(p->list);
767
768         p->list = NULL;
769
770         struct appdata *ad = p->ad;
771         c_ret_if(!ad);
772
773         ad->need_to_show_popup = EINA_FALSE;
774
775         calendar_record_h record = _calendar_get_record_with_index(p->ad->cid);
776         c_retm_if(!record, "record is null");
777
778         cal_detail_create_view(p->ad, record, NULL, NULL);
779         calendar_record_destroy(record, true);
780
781         return;
782 }
783
784 static void __cal_month_calendar_events_of_one_weekday(void *data)
785 {
786         c_retm_if(!data, "data is null");
787
788         cal_month_calendar_data *p = data;
789         c_retm_if(!p->parent, "p->parent is null");
790
791         struct appdata *ad = p->ad;
792         c_ret_if(!ad);
793
794         char title[128] = {0};
795
796         if (p->event_list)
797                 _calendar_free_record_list(&p->event_list);
798
799         __cal_month_calendar_get_events(p);
800         c_retm_if(!p->event_list, "p->event_list is null");
801
802         int count = eina_list_count(p->event_list);
803         if (2 <= count) {
804                 cal_util_get_time_text(title, sizeof(title), CAL_UTIL_DATE_FORMAT_13, NULL, &p->ad->base_tm);
805
806                 if (!p->popup) {
807                         p->popup = cal_util_add_popup(ad->win, "menustyle", title, NULL,
808                                 __cal_month_calendar_popup_response_callback, p,
809                                 S_("IDS_COM_BODY_CLOSE"), NULL);
810
811                         c_retm_if(!p->popup, "cal_util_add_popup returned null");
812                 } else {
813                         elm_object_part_text_set(p->popup, "title,text", title);
814                         evas_object_show(p->popup);
815                 }
816
817                 if (!p->list) {
818                         p->list = cal_list_base_create(ad, p->popup, NULL, false, __cal_month_calendar_popup_genlist_item_selected_callback, p);
819                 }
820
821         } else if (1 == count) {
822                 calendar_record_h record = eina_list_data_get(p->event_list);
823                 c_ret_if(!record);
824
825                 p->ad->cid = _calendar_get_record_index(record);
826
827                 cal_detail_create_view(p->ad, record, NULL, NULL);
828         }
829         __cal_month_calendar_update_genlist(p);
830 }
831
832 static void __cal_month_calendar_mouse_up(void *data, Evas *e, Evas_Object *ly, void *ei)
833 {
834         c_retm_if(!data, "data is null");
835         c_retm_if(!ly, "ly is null");
836
837         cal_month_calendar_data *p = data;
838         Evas_Event_Mouse_Down *ev = ei;
839         int start_day = 0;
840         int end_day = 0;
841         int num_of_enable = 0;
842         char eve[8] = {0};
843         int list_index = 0;
844         int i = 0;
845
846         list_index = (int)evas_object_data_get(ly, "list_index");
847
848         c_retm_if(-1 == p->index_for_press, "p->index_for_press is -1");
849
850         Evas_Coord_Rectangle r;
851         cal_util_get_geometry (&r, ly);
852         int day_width = r.w / DAYS_OF_WEEK;
853
854         snprintf(eve, sizeof(eve) , "up,%d", p->index_for_press);
855         edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(p->month), eve, "cal");
856
857         if (p->pos_selected != p->index_for_press) {
858                 p->index_for_press = -1;
859                 return;
860         }
861
862         p->index_for_press = -1;
863
864         __cal_month_calendar_get_week_time(p,&start_day,&end_day);
865
866         if (DAYS_OF_WEEK != (num_of_enable = end_day - start_day + 1)) {
867
868                 if (end_day < DAYS_OF_WEEK) {
869
870                         if (ev->canvas.x < (DAYS_OF_WEEK- num_of_enable) * day_width)
871                                 return;
872
873                         start_day -= (DAYS_OF_WEEK - num_of_enable);
874                 } else if (DAYS_OF_WEEK < start_day) {
875
876                         if (ev->canvas.x > num_of_enable * day_width)
877                                 return;
878                 }
879         }
880
881 }
882
883 Evas_Object* cal_month_calendar_create_view(struct appdata *ad,
884                 Evas_Object *parent, Eina_Bool tmp)
885 {
886         c_retv_if(!ad, NULL);
887         c_retv_if(!parent, NULL);
888
889         cal_month_calendar_data *p = calloc(1, sizeof(cal_month_calendar_data));
890         c_retv_if(!p, NULL);
891
892         if (ad->is_landscape_mode)
893                 p->month_data = cal_month_data_create(ad, 1);
894         else
895                 p->month_data = cal_month_data_create(ad, 3);
896
897         p->ad = ad;
898         p->parent = parent;
899         p->pos_down = p->pos_today = p->pos_selected = -1;
900         p->index_for_press = -1;
901
902         p->weekline = __cal_month_calendar_get_week_last_line(p, ad->wday_start);
903
904         if (ad->daily_events_mode || ad->is_landscape_mode) {
905                 if (!ad->is_landscape_mode) {
906                         if (WEEKS_OF_MONTH == p->weekline) {
907                                 p->name = _name = "main/month/cal/weekly/6";
908                         } else if (WEEKS_OF_MONTH_5 == p->weekline) {
909                                 p->name = _name = "main/month/cal/weekly/5";
910                         } else if (WEEKS_OF_MONTH_4 == p->weekline) {
911                                 p->name = _name = "main/month/cal/weekly/4";
912                         }
913                 } else {
914                         if (WEEKS_OF_MONTH == p->weekline) {
915                                 p->name = _name = "main/month/cal/weekly/6/l";
916                         } else if (WEEKS_OF_MONTH_5 == p->weekline) {
917                                 p->name = _name = "main/month/cal/weekly/5/l";
918                         } else if (WEEKS_OF_MONTH_4 == p->weekline) {
919                                 p->name = _name = "main/month/cal/weekly/4/l";
920                         }
921                 }
922         } else {
923                 p->name = _name = "main/month/cal";
924         }
925
926
927         Evas_Object *ly = cal_util_add_layout(ad->naviframe, p->name);
928         if (!ly) {
929                 ERR("ly is null");
930                 free(p);
931                 return NULL;
932         }
933
934         p->month = ly;
935         evas_object_data_set(ly, "priv", p);
936         edje_object_signal_callback_add(CAL_UTIL_GET_EDJ_DATA(ly), "*", "cal", __cal_month_calendar_cal_event_callback, p);
937         edje_object_signal_callback_add(CAL_UTIL_GET_EDJ_DATA(ly), "*", "prog", __cal_month_calendar_prog_event_callback, p);
938
939         cal_month_calendar_set_wday_text(ly, ad->wday_start);
940
941         cal_month_data_clear(p->month_data);
942         cal_month_data_load(p->month_data);
943
944         if (tmp == EINA_TRUE) {
945                 p->weekline = __cal_month_calendar_fill_calendar(ly, ad->wday_start);
946                 __cal_month_calendar_update_check(ly, p);
947         }
948
949         if (p->ad->daily_events_mode || p->ad->is_landscape_mode) {
950                 __cal_month_calendar_create_event_lists(ly, p);
951                 __cal_month_calendar_signal_all_clean(p);
952                 __cal_month_calendar_signal_all_week(p);
953         }
954
955         if (ad->is_display_weeknumber)
956                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "display_week_number");
957
958         evas_object_event_callback_add(ly, EVAS_CALLBACK_DEL, __cal_month_calendar_delete_layout, p);
959
960         return ly;
961 }
962
963 void cal_month_calendar_update_view(Evas_Object *ly)
964 {
965         CAL_FN_START;
966
967         c_ret_if(!ly);
968
969         cal_month_calendar_data *p = CAL_UTIL_GET_PRIV_DATA(ly);
970 //      if (!p || CAL_STRCMP(p->name, _name)) {
971 //              ERR("update month calendar: Invalid object");
972 //              return;
973 //      }
974
975         struct appdata *ad = p->ad;
976         c_ret_if(!ad);
977
978         p->weekline = __cal_month_calendar_fill_calendar(ly, ad->wday_start);
979
980         __cal_month_calendar_update_check(ly, p);
981
982         if (p->ad->daily_events_mode || p->ad->is_landscape_mode) {
983                 __cal_month_calendar_signal_all_clean(p);
984                 __cal_month_calendar_signal_all_week(p);
985         }
986
987         if (ad->need_to_show_popup) {
988                 __cal_month_calendar_events_of_one_weekday(p);
989                 ad->need_to_show_popup = EINA_FALSE;
990         }
991
992         cal_month_calendar_update_select(ly);
993
994         CAL_FN_END;
995 }
996
997 int cal_month_calendar_get_weekline(Evas_Object *ly)
998 {
999         c_retv_if(!ly, 6);
1000
1001         cal_month_calendar_data *p = NULL;
1002
1003         p = CAL_UTIL_GET_PRIV_DATA(ly);
1004         c_retv_if(!p, 6);
1005
1006         return p->weekline;
1007 }
1008
1009 static void __cal_month_calendar_set_more_text(Evas_Object *ly, int count, int index)
1010 {
1011         c_retm_if(!ly, "ly is null");
1012         c_retm_if(index < 0 , "index is wrong");
1013
1014         cal_month_calendar_data* p = CAL_UTIL_GET_PRIV_DATA(ly);
1015         c_retm_if(!p, "p is null");
1016         c_retm_if(!p->ad, "p->ad is null");
1017
1018         char part[32] = {0};
1019         char text[32] = {0};
1020
1021         if (count <= (p->ad->is_landscape_mode ? LINES_OF_WEEKLY_MONTHS_EVENT_LANDSCAPE : LINES_OF_WEEKLY_MONTHS_EVENT)) {
1022                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "hide_count,%d", index);
1023         } else {
1024                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "show_count,%d", index);
1025         }
1026 }
1027
1028 static void __cal_month_calendar_create_event_lists(Evas_Object *ly, cal_month_calendar_data *p)
1029 {
1030         c_ret_if(!p);
1031         c_ret_if(!ly);
1032
1033         char part[32] = {0};
1034         int week = 0;
1035
1036         for (week = 0; week < WEEKS_OF_MONTH; week++) {
1037                 snprintf(part, sizeof part, "list/sw/%d", week * DAYS_OF_WEEK);
1038                 Evas_Object *events = NULL;
1039
1040                 if (p->ad->is_landscape_mode) {
1041                         events = cal_util_add_layout(p->ad->naviframe, "main/month/week/events/l");
1042                 } else {
1043                         events = cal_util_add_layout(p->ad->naviframe, "main/month/week/events");
1044                 }
1045
1046                 c_retm_if(!events, "events is null");
1047
1048                 evas_object_data_set(events, "list_index", (void*)week);
1049
1050                 elm_object_part_content_set(ly, part, events);
1051                 evas_object_event_callback_add(events, EVAS_CALLBACK_MOUSE_DOWN, __cal_month_calendar_mouse_down, p);
1052                 evas_object_event_callback_add(events, EVAS_CALLBACK_MOUSE_UP, __cal_month_calendar_mouse_up, p);
1053                 evas_object_event_callback_add(events, EVAS_CALLBACK_MOUSE_MOVE, __cal_month_calendar_mouse_move, p);
1054
1055                 p->weekly_events_ly[week] = events;
1056         }
1057 }
1058
1059 static void __cal_month_calendar_signal_all_week(cal_month_calendar_data *p)
1060 {
1061         c_retm_if(!p, "p is null");
1062
1063         int week = 0;
1064         for (week = 0; week < WEEKS_OF_MONTH; week++)
1065                 __cal_month_calendar_signal_week(p, p->weekly_events_ly[week], week);
1066 }
1067
1068 static void __cal_month_calendar_signal_all_clean(cal_month_calendar_data *p)
1069 {
1070         c_retm_if(!p, "p is null");
1071
1072         int i = 0;
1073         for (i = 0; i < WEEKS_OF_MONTH; i++)
1074                 __cal_month_calendar_signal_clean(p,CAL_UTIL_GET_EDJ_DATA(p->weekly_events_ly[i]));
1075 }
1076
1077 static void __cal_month_calendar_set_check_text(Evas_Object *ly, cal_month_calendar_data *p, int count, int index)
1078 {
1079         c_retm_if(!ly, "ly is null");
1080         c_retm_if(index < 0 , "index is wrong");
1081
1082         char part[32] = {0};
1083         char text[32] = {0};
1084
1085         if (count <= 0) {
1086                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "hide_count,%d", index);
1087                 p->day[index].checked = 0;
1088         } else {
1089                 cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "show_count,%d", index);
1090                 p->day[index].checked = 1;
1091         }
1092 }
1093
1094 static void __cal_month_calendar_set_event_rect_color(Evas_Object *obj, cal_month_calendar_data *p, int line, int pos, int calendar_id)
1095 {
1096         c_retm_if(!obj, "obj is null");
1097         c_retm_if(!p, "p is null");
1098
1099         calendar_record_h calendar = NULL;
1100         _calendar_book_color calendar_color = {0};
1101         Evas_Object *event_content = NULL;
1102         char part[20] = {0};
1103
1104         snprintf(part, sizeof part, "%d/bgcolor/%d", line, pos);
1105
1106         calendar_error_e error = CALENDAR_ERROR_NONE;
1107         error = calendar_db_get_record(_calendar_book._uri, calendar_id, &calendar);
1108         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_db_get_record() is failed(%x)", error);
1109
1110         _calendar_get_calendar_color(calendar, &calendar_color);
1111
1112         error = calendar_record_destroy(calendar, true);
1113         c_warn_if(error != CALENDAR_ERROR_NONE, "calendar_record_destroy() is failed(%x)", error);
1114
1115         event_content = cal_util_add_rectangle(obj);
1116         c_retm_if(!event_content, "event_content is null");
1117
1118         evas_object_size_hint_align_set(event_content, EVAS_HINT_FILL, 0);
1119         evas_object_size_hint_weight_set(event_content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1120         evas_object_color_set(event_content, calendar_color.red, calendar_color.green, calendar_color.blue, calendar_color.alpha);
1121
1122         elm_object_part_content_set(obj, part, event_content);
1123
1124 }
1125
1126 static void __cal_month_calendar_set_day_default_color(cal_month_calendar_data* p, Evas_Object *eo, int pos)
1127 {
1128         c_retm_if(!p, "p is null");
1129         c_retm_if(!eo, "eo is null");
1130
1131         struct _day *d = &p->day[pos];
1132         c_retm_if(!d, "d is null");
1133
1134         switch (d->d_type) {
1135         case CAL_MONTH_CALENDAR_DAY_TYPE_SUNDAY:
1136                 cal_util_emit_signal(eo, "sunday,%d", pos);
1137                 break;
1138         case CAL_MONTH_CALENDAR_DAY_TYPE_SATDAY:
1139                 cal_util_emit_signal(eo, "satday,%d", pos);
1140                 break;
1141         case CAL_MONTH_CALENDAR_DAY_TYPE_WEEKDAY:
1142                 cal_util_emit_signal(eo, "weekday,%d", pos);
1143                 break;
1144         default:
1145                 cal_util_emit_signal(eo, "weekday,%d", pos);
1146                 break;
1147         }
1148 }
1149
1150 static void __cal_month_calendar_fill_week_number(Evas_Object *ly)
1151 {
1152         c_retm_if(!ly, "ly is null");
1153
1154         int k = 0;
1155         cal_month_calendar_data *p = CAL_UTIL_GET_PRIV_DATA(ly);
1156         c_retm_if(!p, "p is null");
1157
1158         for (k = 0; k < WEEKS_OF_MONTH; k++) {
1159                 int start_day = 0;
1160                 int end_day = 0;
1161                 char week[8] = {0};
1162                 struct tm end_time = {0};
1163                 struct tm start_time = {0};
1164                 cal_month_data_get_day_time_by_pos(p->ad,
1165                                 p->pos_today, p->pos_selected, p->pos_start, p->pos_end,
1166                                 &start_day, &end_day, &start_time, &end_time, (k + 1) * DAYS_OF_WEEK - 1);
1167                 cal_util_get_week_number_text(&start_time, week, sizeof(week) - 1);
1168                 cal_util_set_text(CAL_UTIL_GET_EDJ_DATA(ly), cal_util_get_part_text("wn/%d/text", k), "%s", week);
1169         }
1170 }