2.0 alpha
[apps/core/preloaded/calendar.git] / src / timeblock.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://www.tizenopensource.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 <Ecore_X.h>
20 #include <vconf.h>
21 #include <vconf-keys.h>
22
23 #include "timeblock.h"
24
25 #define CAL_TIMEBLOCK_CONTENT_HEIGHT 16
26 #define CAL_TIMEBLOCK_MIN_HEIGHT 16
27 #define CAL_TIMEBLOCK_NORMAL_HEIGHT 158
28 #define CAL_TIMEBLOCK_EXPAND_HEIGHT 520
29 #define CAL_TIMEBLOCK_TEXT_HEIGHT 30
30 #define CAL_TIMEBLOCK_LONG_PRESS_TIME 0.5
31 #define CAL_TIMEBLOCK_EVENT_BLOCK_MAX 8
32
33 static void __cal_time_block_restack_time_block(struct timeblock *tb);
34 extern void cal_day_update_expand(Evas_Object *ly, int x);
35
36 void cal_time_block_show_current_time_line(struct timeblock *tb, int hour)
37 {
38         int i;
39         struct timeblock_slice *t;
40
41         if (!tb)
42                 return;
43
44         if(0 > hour || 23 < hour)
45                 return;
46
47         for(i = 0; i < sizeof(tb->tbs)/sizeof(tb->tbs[0]); i++)
48         {
49                 t = &tb->tbs[i];
50                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "hide,line", "prog");
51                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "hide,img", "prog");
52         }
53
54         if(NULL != tb->tbs[hour].ly)
55         {
56                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(tb->tbs[hour].ly), "show,line", "prog");
57                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(tb->tbs[hour].ly), "show,img", "prog");
58         }
59 }
60
61 void cal_time_block_hide_current_time_line(struct timeblock *tb)
62 {
63         int i;
64         struct timeblock_slice *t;
65
66         if (!tb)
67                 return;
68
69         for(i = 0; i < sizeof(tb->tbs)/sizeof(tb->tbs[0]); i++)
70         {
71                 t = &tb->tbs[i];
72                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "hide,line", "prog");
73                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "hide,img", "prog");
74         }
75 }
76
77 static int __cal_time_block_sort_ev(const void *d1, const void *d2)
78 {
79         const struct timeblock_event  *t1 = d1;
80         const struct timeblock_event  *t2 = d2;
81
82         if (!t1)
83                 return 1;
84         if (!t2)
85                 return -1;
86
87         return t1->sz < t2->sz ? 1 : -1;
88 }
89
90 static void __cal_time_block_delete_event_block_slice_overlap(struct timeblock *tb)
91 {
92         c_ret_if(!tb);
93
94         struct eventblock_overlap *ebv = NULL;
95         Eina_List *l = NULL;
96
97         EINA_LIST_FOREACH(tb->ebs_list, l, ebv) {
98                 if(ebv)
99                         free(ebv);
100         }
101
102         tb->ebs_list = eina_list_free(tb->ebs_list);
103 }
104
105 static void _cal_time_block_clear_start_index(struct timeblock *tb)
106 {
107         int i = 0;
108         struct eventblock_slice *eb = NULL;
109         if(NULL == tb)
110         {
111                 return;
112         }
113         for(i = 0; i<sizeof(tb->ebs)/sizeof(tb->ebs[0]); i++)
114         {
115                 eb = &tb->ebs[i];
116                 eb->start_index = 0;
117                 eb->real_sz = 0;
118         }
119 }
120 static void __cal_time_block_set_start_index(struct timeblock *tb)
121 {
122         int i = 0;
123         int j = 0;
124         int k = 0;
125         int e = 0;
126         int sz = 0;
127         struct eventblock_slice *eb = NULL;
128         struct eventblock_slice *eb_tmp = NULL;
129         Eina_List *l;
130         const struct timeblock_event *ev = NULL;
131         if(NULL == tb)
132         {
133                 return;
134         }
135         _cal_time_block_clear_start_index(tb);
136         for(i = 0; i<sizeof(tb->ebs)/sizeof(tb->ebs[0]); i++)
137         {
138                 eb = &tb->ebs[i];
139                 if(NULL != eb->list)
140                 {
141                         k = 0;
142                         EINA_LIST_FOREACH(eb->list, l, ev)
143                         {
144                                 if(NULL != ev)
145                                 {
146                                         e = ev->idx + ev->sz;
147                                         for(j = ev->idx; (j<e && j<sizeof(tb->ebs)/sizeof(tb->ebs[0])); j++)
148                                         {
149                                                 eb_tmp = &tb->ebs[j];
150                                                 if(j > ev->idx)
151                                                 {
152                                                         if(0 == k)
153                                                                 eb_tmp->start_index =  eb->start_index + 1;
154                                                         else
155                                                                 eb_tmp->start_index =  eb_tmp->start_index + 1;
156                                                 }
157                                                 sz = eina_list_count(eb_tmp->list);
158                                                 eb_tmp->real_sz = eb_tmp->start_index + sz;
159                                         }
160                                         k = 1;
161                                 }
162
163                         }
164                 }
165         }
166 }
167
168 static void __cal_time_block_set_event_block_slice_overlap_ranged(struct timeblock *tb)
169 {
170         int i = 0;
171         int j = 0;
172         struct eventblock_slice *eb = NULL;
173         struct eventblock_overlap *ebv = NULL;
174         int nebs = 0;
175         if(NULL == tb)
176         {
177                 return;
178         }
179         __cal_time_block_set_start_index(tb);
180         nebs = sizeof(tb->ebs)/sizeof(tb->ebs[0]);
181         __cal_time_block_delete_event_block_slice_overlap(tb);
182         while(i < nebs)
183         {
184
185                 eb = &tb->ebs[i];
186                 if(0 == eb->start_index)
187                 {
188                         if(0 == eb->real_sz)
189                         {
190                                 i++;
191                                 continue;
192                         }
193                         CAL_CALLOC(ebv, 1, struct eventblock_overlap);
194                         if(NULL == ebv)
195                         {
196                                 return;
197                         }
198                         ebv->start_idx = i;
199                         ebv->end_idx = i;
200                         ebv->size = eb->real_sz;
201
202                         if(nebs == i+1)
203                         {
204                                 tb->ebs_list = eina_list_append(tb->ebs_list, ebv);
205                         }
206                         for(j = i+1; j < nebs; j++)
207                         {
208
209                                 eb = &tb->ebs[j];
210                                 if((j == nebs-1) && (0 != eb->start_index))
211                                 {
212                                         if(eb->real_sz > ebv->size)
213                                         {
214                                                 ebv->size = eb->real_sz;
215                                         }
216                                         ebv->end_idx = j;
217                                         tb->ebs_list = eina_list_append(tb->ebs_list, ebv);
218                                 }
219                                 else if(0 == eb->start_index)
220                                 {
221                                         ebv->end_idx = j - 1;
222                                         tb->ebs_list = eina_list_append(tb->ebs_list, ebv);
223                                         i = j;
224                                         break;
225                                 }
226                                 else
227                                 {
228                                         if(eb->real_sz > ebv->size)
229                                         {
230                                                 ebv->size = eb->real_sz;
231                                         }
232                                 }
233                         }
234
235                         if(j >= nebs)
236                         {
237                                 break;
238                         }
239                 }
240         }
241
242 }
243
244 static void __cal_time_block_move_event(struct timeblock_event *ev, Evas_Coord_Rectangle *base,
245                 int idx, Evas_Coord w)
246 {
247         c_retm_if(!ev, "ev is null");
248         c_retm_if(!ev->tb, "ev->tb is null");
249         c_retm_if(!ev->ly, "ev->ly is null");
250
251         if (ev->tb->long_pressed_event == ev)
252                 return;
253
254         evas_object_move(ev->ly, base->x + (idx * w), base->y);
255         evas_object_resize(ev->ly, w, base->h * ev->sz);
256 }
257
258 static void __cal_time_block_move_event_block_slice(struct timeblock *tb)
259 {
260         c_retm_if(!tb, "tb is null");
261
262         struct eventblock_overlap *ebv = NULL;
263         Eina_List *l;
264         Eina_List *l2;
265         struct eventblock_slice *eb = NULL;
266         Evas_Coord_Rectangle base = {0};
267         struct timeblock_event *ev = NULL;
268         int count = 0;
269         int width = 0;
270         int i = 0;
271
272         __cal_time_block_set_event_block_slice_overlap_ranged(tb);
273
274         EINA_LIST_FOREACH(tb->ebs_list, l, ebv) {
275                 if (ebv) {
276                         if (0 < ebv->size) {
277                                 for ( i = ebv->start_idx; i <= ebv->end_idx; i++) {
278
279                                         eb = &tb->ebs[i];
280                                         cal_util_get_geometry(&base, eb->base);
281                                         if (ebv->size > CAL_TIMEBLOCK_EVENT_BLOCK_MAX) {
282                                                 width = base.w / CAL_TIMEBLOCK_EVENT_BLOCK_MAX;
283                                         } else {
284                                                 width = base.w / ebv->size;
285                                         }
286
287                                         count = eb->start_index;
288
289                                         EINA_LIST_FOREACH(eb->list, l2, ev) {
290                                                 if (ev) {
291                                                         if(count < CAL_TIMEBLOCK_EVENT_BLOCK_MAX-1) {
292                                                                 __cal_time_block_move_event(ev, &base, count, width);
293                                                         } else {
294                                                                 __cal_time_block_move_event(ev, &base, count, 0);
295                                                         }
296                                                         count ++;
297                                                 }
298                                         }
299                                 }
300                         }
301                 }
302         }
303 }
304
305 void cal_time_block_move(struct timeblock *time_block, Evas_Coord x, Evas_Coord y)
306 {
307         c_retm_if(!time_block, "time_block is null");
308
309         int i;
310         struct timeblock_slice *t;
311
312         time_block->x = x;
313         time_block->y = y;
314
315         for (i = 0; i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++) {
316                 t = &time_block->tbs[i];
317                 if (!t->ly)
318                         continue;
319
320                 evas_object_move(t->ly, x, y);
321                 t->x = x;
322                 t->y = y;
323
324                 y += t->h;
325         }
326
327         __cal_time_block_move_event_block_slice(time_block);
328 }
329
330 static void __cal_time_block_resize_time_block(struct timeblock *time_block)
331 {
332         int i;
333         Evas_Coord sum;
334
335         sum = 0;
336         for (i = 0; i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++) {
337                 struct timeblock_slice *t = &time_block->tbs[i];
338
339                 if (!t->ly)
340                         continue;
341
342                 if (t->h > CAL_TIMEBLOCK_TEXT_HEIGHT) {
343                         if (t->hide_text) {
344                                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "show,text", "prog");
345                                 t->hide_text = EINA_FALSE;
346                         }
347                 }
348                 else    {
349                         if (!t->hide_text) {
350                                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(t->ly), "hide,text", "prog");
351                                 t->hide_text = EINA_TRUE;
352                         }
353                 }
354
355                 evas_object_resize(t->ly, time_block->w, t->h);
356                 sum += t->h;
357         }
358
359         time_block->h = sum;
360 }
361
362 static inline void __cal_time_block_set_size(struct timeblock *tb, Evas_Coord h)
363 {
364         int i;
365         c_retm_if(!tb, "tb is null");
366         c_retm_if(!tb->ad, "tb->ad is null");
367         struct appdata *ad = tb->ad;
368
369         if (tb->expand_height <= h)
370                 h = tb->expand_height;
371
372         for (i = 0; i < sizeof(tb->tbs)/sizeof(tb->tbs[0]); i++)
373         {
374                 struct timeblock_slice *t = &tb->tbs[i];
375
376                 if (t->cnt == 0)
377                         t->h = h;
378                 else {
379                         if (tb->normal_height < h)
380                                 t->h = h;
381                         else
382                                 t->h = tb->normal_height;
383                 }
384         }
385         tb->ad->h_cur = h;
386 }
387
388 static int __cal_time_block_find_time_block(struct timeblock *tb, Evas_Coord y)
389 {
390         int i;
391         struct timeblock_slice *t;
392
393         for (i = 1; i < sizeof(tb->tbs)/sizeof(tb->tbs[0]); i++) {
394                 t = &tb->tbs[i];
395
396                 if (t->y > y)
397                         return i - 1;
398         }
399
400         return i - 1;
401 }
402
403 static void __cal_time_block_rearrange_time_block_after(struct timeblock *tb, int idx)
404 {
405         int i;
406         struct timeblock_slice *prev;
407         struct timeblock_slice *t;
408
409         for (i = idx + 1; i < sizeof(tb->tbs)/sizeof(tb->tbs[0]); i++) {
410                 t = &tb->tbs[i];
411                 prev = &tb->tbs[i - 1];
412
413                 t->y = prev->y + prev->h;
414                 evas_object_move(t->ly, t->x, t->y);
415         }
416 }
417
418 static inline void __cal_time_block_rearrange_time_block(struct timeblock *tb, int idx)
419 {
420         struct timeblock_slice *t;
421         struct timeblock_slice *next;
422         int i;
423
424         __cal_time_block_rearrange_time_block_after(tb, idx);
425
426         for (i = idx - 1; i >= 0; i--) {
427                 t = &tb->tbs[i];
428                 next = &tb->tbs[i + 1];
429
430                 t->y = next->y - t->h;
431                 evas_object_move(t->ly, t->x, t->y);
432         }
433
434         tb->y = tb->tbs[0].y;
435 }
436
437 void cal_time_block_resize(struct timeblock *tb, Evas_Coord y, Evas_Coord h)
438 {
439         int idx;
440         if(h < 30)
441         {
442                 return;
443         }
444         idx = __cal_time_block_find_time_block(tb, y);
445
446         __cal_time_block_set_size(tb, h);
447         __cal_time_block_resize_time_block(tb);
448         __cal_time_block_rearrange_time_block(tb, idx);
449         __cal_time_block_move_event_block_slice(tb);
450 }
451
452 static inline int __cal_time_block_get_color(struct timeblock *tb)
453 {
454         int r;
455
456         r = tb->color;
457         tb->color = (tb->color + 1) & 0x3;
458
459         return r;
460 }
461
462 static Evas_Object* __cal_time_block_add_event_layout(struct timeblock *tb, const char *text)
463 {
464         Evas_Object *ly;
465
466         ly = cal_util_add_layout(tb->parent, "main/day/tb/event");
467         CAL_ASSERT(ly);
468
469         evas_object_size_hint_align_set(ly, EVAS_HINT_FILL, EVAS_HINT_FILL);
470
471         if (text)
472                 edje_object_part_text_set(CAL_UTIL_GET_EDJ_DATA(ly), "text", text);
473
474         cal_util_emit_signal(CAL_UTIL_GET_EDJ_DATA(ly), "bg,color%d", __cal_time_block_get_color(tb));
475
476         evas_object_clip_set(ly, (Evas_Object*)tb->clip);
477
478         return ly;
479 }
480
481 static void __cal_time_event_mouse_down_callback(void *data, Evas *e, Evas_Object *ly, void *ei)
482 {
483         CAL_FN_START;
484
485         c_retm_if(!data, "data is null");
486         c_retm_if(!ei, "ei is null");
487
488         Evas_Event_Mouse_Down *ev = ei;
489         struct timeblock_event *event = data;
490
491         event->mouse_down_y = ev->canvas.y;
492 }
493
494 static struct timeblock_event* __cal_time_block_add_event(struct timeblock *time_block, int cid, int hh, int sz, const char *text, cal_struct *cs)
495 {
496         CAL_ASSERT(time_block);
497         CAL_ASSERT(cs);
498
499         struct timeblock_event *e;
500         Evas_Object *ly;
501
502         CAL_CALLOC(e, 1, struct timeblock_event);
503
504         ly = __cal_time_block_add_event_layout(time_block, text);
505         CAL_ASSERT(ly);
506
507         e->cid = cid;
508         e->idx = hh;
509         e->sz = sz;
510         e->tb = time_block;
511         e->ly = ly;
512         e->cs = cs;
513
514         evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_DOWN, __cal_time_event_mouse_down_callback, e);
515
516         return e;
517 }
518
519 static int __cal_time_block_get_event_block_index(struct timeblock_event *ev)
520 {
521         c_retvm_if(!ev, -1, "ev is null");
522         c_retvm_if(!ev->tb, -1, "ev->tb is null");
523
524         struct timeblock *tb = ev->tb;
525         int i = 0;
526         Evas_Coord_Rectangle r;
527         Evas_Coord event_y, ebs_y;
528
529         cal_util_get_geometry(&r, ev->ly);
530         event_y = r.y;
531
532         for (i = 0; i < sizeof(tb->ebs)/sizeof(tb->ebs[0]); i++) {
533
534                 cal_util_get_geometry(&r, tb->ebs[i].base);
535
536                 if (event_y <= r.y) {
537
538                         ebs_y = r.y;
539                         if (i != 0) {
540                                 cal_util_get_geometry(&r, tb->ebs[i - 1].base);
541
542                                 if (event_y - r.y < ebs_y - event_y)
543                                         return i-1;
544                         }
545
546                         return i;
547                 }
548         }
549
550         return -1;
551 }
552
553 static void __cal_time_block_event_callback(void *data, Evas_Object *obj, const char *e, const char *s)
554 {
555         CAL_FN_START;
556
557         c_retm_if(!data, "data is null");
558
559         struct timeblock_event *ev = data;
560         struct timeblock *tb = ev->tb;
561         c_retm_if(!tb, "tb is null");
562
563         if (tb->lock)
564                 return;
565
566         if (!CAL_STRCMP(e, "dn")) {
567                 if (!tb->dn) {
568                         tb->dn = obj;
569                         edje_object_signal_emit(obj, "select", "prog");
570                 }
571                 return;
572         }
573
574         if (!CAL_STRCMP(e, "up")) {
575
576                 if (tb->dn == obj) {
577                         if (tb->cb) {
578                                 tb->cb(tb->cb_d, tb, EVENT_CLICKED, ev);
579                         }
580
581                         tb->dn = NULL;
582                         edje_object_signal_emit(obj, "unselect", "prog");
583                 }
584
585                 return;
586         }
587 }
588
589 static int __cal_time_block_insert_event(struct timeblock *time_block, struct timeblock_event *ev)
590 {
591         CAL_ASSERT(time_block);
592         CAL_ASSERT(ev);
593
594         int idx;
595         int i;
596         int e;
597         struct eventblock_slice *eb;
598
599         idx = ev->idx >> 1;
600         e = (ev->idx + ev->sz + 1) >> 1;
601
602         for (i = idx; i < e && i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++)
603                 time_block->tbs[i].cnt++;
604
605         eb = &time_block->ebs[ev->idx];
606         eb->list = eina_list_sorted_insert(eb->list, __cal_time_block_sort_ev, ev);
607         edje_object_signal_callback_add(CAL_UTIL_GET_EDJ_DATA(ev->ly), "*", "edj", __cal_time_block_event_callback, ev);
608
609         return idx;
610 }
611
612 static struct timeblock_event* __cal_time_block_find_event(struct timeblock *time_block, int cid)
613 {
614         CAL_ASSERT(time_block);
615         int i;
616         struct eventblock_slice *eb;
617         struct timeblock_event *ev;
618         Eina_List *l;
619
620         for (i = 0; i < sizeof(time_block->ebs)/sizeof(time_block->ebs[0]); i++)
621         {
622                 eb = &time_block->ebs[i];
623
624                 EINA_LIST_FOREACH(eb->list, l, ev)
625                 {
626                         if (ev && ev->cid == cid)
627                                 return ev;
628                 }
629         }
630
631         return NULL;
632 }
633
634 static void __cal_time_block_restack_time_block(struct timeblock *tb)
635 {
636         int i;
637         Evas_Object *prev;
638         struct eventblock_slice *eb;
639         struct timeblock_event *ev;
640         Eina_List *l;
641
642         prev = NULL;
643         for (i = 0; i < sizeof(tb->ebs)/sizeof(tb->ebs[0]); i++)
644         {
645                 eb = &tb->ebs[i];
646
647                 EINA_LIST_FOREACH(eb->list, l, ev)
648                 {
649                         if (prev && NULL != ev) {
650                                 evas_object_stack_above(ev->ly, prev);
651                         }
652
653                         if(ev)
654                                 prev = ev->ly;
655                 }
656         }
657 }
658
659 void cal_time_block_add_event(struct timeblock *time_block, int cid, int hh, int sz, const char *text, cal_struct *cs)
660 {
661         CAL_ASSERT(time_block);
662         CAL_ASSERT(cs);
663
664         struct timeblock_event *e;
665         int idx;
666
667         e = __cal_time_block_find_event(time_block, cid);
668         if (e)
669         {
670                 // TODO: update
671                 e->cs = cs;
672                 return;
673         }
674
675         e = __cal_time_block_add_event(time_block, cid, hh, sz, text, cs);
676         CAL_ASSERT(e);
677
678         idx = __cal_time_block_insert_event(time_block, e);
679
680         __cal_time_block_restack_time_block(time_block);
681         __cal_time_block_rearrange_time_block_after(time_block, idx);
682         __cal_time_block_move_event_block_slice(time_block);
683 }
684
685 void cal_time_block_get_geometry(struct timeblock *time_block, Evas_Coord_Rectangle *r)
686 {
687         CAL_ASSERT(time_block);
688         CAL_ASSERT(r);
689
690         r->x = time_block->x;
691         r->y = time_block->y;
692         r->w = time_block->w;
693         r->h = time_block->h;
694 }
695
696 static void __cal_time_block_time_block_callback(void *data, Evas_Object *obj, const char *e, const char *s)
697 {
698         struct timeblock_slice *t = data;
699         struct timeblock *tb = t->tb;
700
701         if (tb->lock)
702                 return;
703
704         if (!CAL_STRCMP(e, "dn")) {
705                 if (!tb->dn && t->h == tb->normal_height ) {
706                         tb->dn = obj;
707                         edje_object_signal_emit(obj, "select", "prog");
708                 }
709                 return;
710         }
711
712         if (!CAL_STRCMP(e, "up")) {
713                 if (tb->dn == obj) {
714                         if (tb->cb)
715                                 tb->cb(tb->cb_d, tb, TIMEBLOCK_CLICKED, (void *)t->idx);
716                         tb->dn = NULL;
717                         edje_object_signal_emit(obj, "unselect", "prog");
718                 }
719                 return;
720         }
721 }
722
723 static void __cal_time_block_add_time_block(struct timeblock *time_block)
724 {
725         int i;
726         struct timeblock_slice *t;
727         struct eventblock_slice *e;
728         Evas_Object *ly;
729         Evas_Coord sum;
730         struct tm tm;
731         int is_hour24;
732         int r;
733
734         memset(&tm, 0, sizeof(struct tm));
735         cal_util_update_tm_hour(&tm, 0);
736         tm.tm_hour = 0;
737         tm.tm_min = 0;
738
739         r = vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &is_hour24);
740         if(0 > r)
741         {
742                 is_hour24 = 0;
743         }
744         else if(is_hour24 ==1 || is_hour24 == 2)
745         {
746                 is_hour24--;
747         }
748         else
749         {
750                 ERR("vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &is_hour24) is failed");
751         }
752
753         sum = 0;
754         char tmp[8] = {0};
755         for (i = 0; i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++)
756         {
757                 ly = cal_util_add_layout(time_block->parent, "main/day/tb/block");
758                 CAL_ASSERT(ly);
759
760                 if(is_hour24)
761                         cal_util_set_time_text(CAL_UTIL_GET_EDJ_DATA(ly), "text", NULL, CAL_UTIL_TIME_FORMAT_7, &tm);
762                 else {
763                         if (i == 0) {
764                                 edje_object_part_text_set(CAL_UTIL_GET_EDJ_DATA(ly), "AM", "AM");
765                                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(ly), "show,AM", "prog");
766                         }  else if (i == 12) {
767                                 edje_object_part_text_set(CAL_UTIL_GET_EDJ_DATA(ly), "PM", "PM");
768                                 edje_object_signal_emit(CAL_UTIL_GET_EDJ_DATA(ly), "show,PM", "prog");
769                         }
770
771                         sprintf(tmp, "%02d", (i > 12 ? i - 12 : i));
772                         edje_object_part_text_set(CAL_UTIL_GET_EDJ_DATA(ly), "text", tmp);
773                         memset(tmp, 0x00, 8);
774                 }
775
776                 cal_util_update_tm_hour(&tm, 1);
777
778                 evas_object_clip_set(ly, (Evas_Object*)time_block->clip);
779                 evas_object_show(ly);
780
781                 t = &time_block->tbs[i];
782                 t->ly = ly;
783                 t->h = time_block->normal_height;
784                 t->tb = time_block;
785                 t->idx = i;
786
787                 edje_object_signal_callback_add(CAL_UTIL_GET_EDJ_DATA(ly), "*", "edj", __cal_time_block_time_block_callback, t);
788
789                 e = &time_block->ebs[i << 1];
790                 e->tb = time_block;
791                 e->base = edje_object_part_object_get(CAL_UTIL_GET_EDJ_DATA(ly), "evtbase/top");
792                 e->real_sz = 0;
793                 e->start_index = 0;
794
795                 e = &time_block->ebs[(i << 1) + 1];
796                 e->tb = time_block;
797                 e->base = edje_object_part_object_get(CAL_UTIL_GET_EDJ_DATA(ly), "evtbase/bottom");
798                 e->real_sz = 0;
799                 e->start_index = 0;
800
801                 sum += t->h;
802         }
803
804         time_block->h = sum;
805 }
806
807 static void __cal_time_resize_time_block(void *data, Evas *e, Evas_Object *obj, void *ei)
808 {
809         struct timeblock *time_block = data;
810         c_retm_if(!time_block || !time_block->ad, "input param is NULL");
811
812         Evas_Coord w;
813         Evas_Coord h;
814
815         ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
816
817         if (!time_block->ad->is_landscape_mode) {
818                 time_block->w = w;
819                 time_block->h = h;
820         } else {
821                 time_block->w = h;
822                 time_block->h = w;
823         }
824
825         __cal_time_block_resize_time_block(time_block);
826         __cal_time_block_rearrange_time_block_after(time_block, 0);
827         __cal_time_block_move_event_block_slice(time_block);
828 }
829
830 struct timeblock* cal_time_block_create_time_block(Evas_Object *p, Evas_Object *clip, struct appdata *ad)
831 {
832         CAL_FN_START;
833         struct timeblock *time_block;
834
835         CAL_ASSERT(p);
836         CAL_ASSERT(clip);
837
838
839         CAL_CALLOC(time_block, 1, struct timeblock);
840
841         double scale = elm_config_scale_get();
842
843         time_block->parent = p;
844         time_block->clip = clip;
845         time_block->normal_height = CAL_TIMEBLOCK_NORMAL_HEIGHT * scale;
846         time_block->expand_height = CAL_TIMEBLOCK_EXPAND_HEIGHT * scale;
847         time_block->ad = ad;
848
849         __cal_time_block_add_time_block(time_block);
850         __cal_time_resize_time_block(time_block, NULL, p, NULL);
851
852         Evas_Object *ly = evas_object_data_get(p, "priv");
853
854         cal_day_update_expand(ly, 0);
855         return time_block;
856 }
857
858 static inline void __cal_time_block_clear_time_block(struct timeblock *time_block)
859 {
860         c_ret_if(!time_block);
861
862         struct timeblock_event *ev;
863         struct eventblock_slice *eb;
864         int i;
865         Eina_List *l;
866
867         __cal_time_block_delete_event_block_slice_overlap(time_block);
868
869         for (i = 0; i < sizeof(time_block->ebs)/sizeof(time_block->ebs[0]); i++) {
870                 eb = &time_block->ebs[i];
871
872                 if (!eb) {
873                         ERR("eb is null");
874                         continue;
875                 }
876
877                 EINA_LIST_FOREACH(eb->list, l, ev) {
878                         if (!ev) {
879                                 ERR("ev is null");
880                                 continue;
881                         }
882
883                         if (ev->ly)
884                                 evas_object_del(ev->ly);
885
886                         free(ev);
887                 }
888
889                 eb->list = eina_list_free(eb->list);
890         }
891 }
892
893 static void __cal_time_block_delete_time_block_slice(struct timeblock *time_block)
894 {
895         c_ret_if(!time_block);
896
897         struct timeblock_slice *tbs;
898         int i;
899
900         for (i = 0; i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++) {
901                 tbs = &time_block->tbs[i];
902                 if (!tbs) {
903                         ERR("tbs is null");
904                         continue;
905                 }
906
907                 if (tbs->ly) {
908                         evas_object_clip_unset(tbs->ly);
909
910                         edje_object_signal_callback_del(CAL_UTIL_GET_EDJ_DATA(tbs->ly), "*", "edj", __cal_time_block_time_block_callback);
911
912                         evas_object_del(tbs->ly);
913                 }
914         }
915 }
916
917 void cal_time_block_delete_time_block(struct timeblock **tb)
918 {
919         CAL_FN_START;
920
921         c_ret_if(!tb);
922         c_ret_if(!*tb);
923
924         __cal_time_block_clear_time_block(*tb);
925         __cal_time_block_delete_time_block_slice(*tb);
926
927         if ((*tb)->long_press_timer)
928                 ecore_timer_del((*tb)->long_press_timer);
929
930         free(*tb);
931         *tb = NULL;
932 }
933
934 Evas_Coord cal_time_block_get_min()
935 {
936         double scale = elm_config_scale_get();
937         return CAL_TIMEBLOCK_MIN_HEIGHT * scale;
938 }
939
940 Evas_Coord cal_time_block_get_max(struct timeblock *tb)
941 {
942         if (!tb)
943                 return 0;
944
945         return tb->normal_height;
946 }
947
948 Evas_Coord cal_time_block_get_expand_max(struct timeblock *tb)
949 {
950         if (!tb)
951                 return 0;
952
953         return tb->expand_height;
954 }
955
956 Evas_Coord cal_time_block_get_current(struct timeblock *tb)
957 {
958         if (!tb)
959                 return 0;
960
961         return tb->ad->h_cur;
962 }
963
964 void cal_time_block_set_event_lock(struct timeblock *tb, Eina_Bool lock)
965 {
966         if (!tb)
967                 return;
968
969         tb->lock = lock;
970         if (tb->lock && tb->dn) {
971                 edje_object_signal_emit(tb->dn, "unselect", "prog");
972                 tb->dn = NULL;
973         }
974 }
975
976 void cal_time_block_unset_callback(struct timeblock *tb)
977 {
978         if (!tb)
979                 return;
980
981         tb->cb = NULL;
982         tb->cb_d = NULL;
983 }
984
985
986 void cal_time_block_set_callback(struct timeblock *tb, void (*cb)(void *data,
987                         struct timeblock *tb ,enum timeblock_event_type e, void *event_info),
988                 void *data)
989 {
990         if (!tb)
991                 return;
992
993         tb->cb = cb;
994         tb->cb_d = data;
995 }
996
997 void cal_time_block_clear_event(struct timeblock *time_block)
998 {
999         CAL_FN_START;
1000
1001         c_retm_if(!time_block, "time_block is null");
1002
1003         int i;
1004
1005         if (!time_block)
1006                 return;
1007
1008         __cal_time_block_clear_time_block(time_block);
1009
1010         for (i = 0; i < sizeof(time_block->tbs)/sizeof(time_block->tbs[0]); i++)
1011                 time_block->tbs[i].cnt = 0;
1012
1013         time_block->color = 0;
1014 }
1015
1016 Evas_Coord cal_time_block_get_first_event_y(struct timeblock *tb)
1017 {
1018         int i;
1019         Evas_Coord h;
1020
1021         if (!tb)
1022                 return 0;
1023
1024         h = 0;
1025
1026         for (i = 0; i < sizeof(tb->ebs)/sizeof(tb->ebs[0]); i++) {
1027                 if (tb->ebs[i].real_sz> 0)
1028                         return h;
1029                 h += ((tb->tbs[i/2].h)/2);
1030         }
1031         return 0;
1032 }
1033
1034 int cal_time_block_get_default_current_height()
1035 {
1036         double scale = elm_config_scale_get();
1037         return CAL_TIMEBLOCK_NORMAL_HEIGHT * scale;
1038 }
1039