d7771435e28414a8b30dba79ea6ede4c34fec8ac
[framework/uifw/elementary.git] / src / lib / elm_datefield.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Datefield Datefield
6  * @ingroup Elementary
7  *
8  * This is a date editfield. it is used to input date and time using keypad
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12
13 enum {
14         DATE_YEAR,
15         DATE_MON,
16         DATE_DAY,
17         DATE_MAX
18 };
19
20 enum {
21         TIME_HOUR,
22         TIME_MIN,
23         TIME_MAX
24 };
25
26 enum {
27         DATE_FORMAT_YYMMDD,
28         DATE_FORMAT_YYDDMM,
29         DATE_FORMAT_MMYYDD,
30         DATE_FORMAT_MMDDYY,
31         DATE_FORMAT_DDYYMM,
32         DATE_FORMAT_DDMMYY,
33         DATE_FORMAT_MAX
34 };
35
36 #define YEAR_MAX_LENGTH 4
37 #define MONTH_MAX_LENGTH        3
38 #define DAY_MAX_LENGTH          2
39 #define TIME_MAX_LENGTH 2
40
41 #define YEAR_MAXIMUM            2099
42 #define YEAR_MINIMUM            1900
43 #define MONTH_MAXIMUM           12
44 #define HOUR_24H_MAXIMUM        23
45 #define HOUR_12H_MAXIMUM        12
46 #define MIN_MAXIMUM             59
47
48 static char month_label[13][4] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
49
50 struct _Widget_Data
51 {
52         Evas_Object *base;      
53         Evas_Object *date[DATE_MAX];
54         Evas_Object *time[TIME_MAX];
55         Ecore_Event_Handler *handler;
56         int layout;
57
58         int year, month, day, hour, min;
59         int date_format;
60         Eina_Bool pm:1;
61         Eina_Bool time_mode:1;
62         Eina_Bool editing:1;
63
64         void (*func)(void *data, Evas_Object *obj, int value);
65         void *func_data;
66 };
67
68 static const char *widtype = NULL;
69
70 static void _del_hook(Evas_Object *obj);
71 static void _theme_hook(Evas_Object *obj);
72 static void _sizing_eval(Evas_Object *obj);
73 static void _on_focus_hook(void *data, Evas_Object *obj);
74
75 static void _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
76 static void _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source);
77 static void _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
78 static void _entry_focused_cb(void *data, Evas_Object *obj, void *event_info);
79 static void _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info);
80 static void _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info);
81 static int _imf_event_commit_cb(void *data, int type, void *event);
82 static void _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value);
83
84 static void _date_entry_add(Evas_Object *obj);
85 static void _time_entry_add(Evas_Object *obj);
86 static void _date_update(Evas_Object *obj);
87 static void _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj);
88 static Eina_Bool _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen);
89 static int _maximum_day_get(int year, int month);
90
91 static void
92 _del_hook(Evas_Object *obj)
93 {
94         Widget_Data *wd = elm_widget_data_get(obj);
95         if (!wd) return ;       
96
97         ecore_event_handler_del(wd->handler);
98                 
99         free(wd);
100 }
101
102 static void
103 _on_focus_hook(void *data, Evas_Object *obj)
104 {
105         Widget_Data *wd = elm_widget_data_get(obj);
106         if (!wd || !wd->base) return ;  
107
108         if (!elm_widget_focus_get(obj))
109                 edje_object_signal_emit(wd->base, "elm,state,focus,out", "elm");
110 }
111
112 static void
113 _theme_hook(Evas_Object *obj)
114 {
115         Widget_Data *wd = elm_widget_data_get(obj);
116         int i;
117         if (!wd || !wd->base) return;
118
119         if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
120         {
121                 _elm_theme_object_set(obj, wd->base, "datefield", "dateandtime", elm_widget_style_get(obj));
122
123                 for (i = 0; i < DATE_MAX; i++)
124                         elm_object_style_set(wd->date[i], "datefield/hybrid");
125                 for (i = 0; i < TIME_MAX; i++)
126                         elm_object_style_set(wd->time[i], "datefield/hybrid");
127         }
128         else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
129         {
130                 _elm_theme_object_set(obj, wd->base, "datefield", "date", elm_widget_style_get(obj));
131
132                 for (i = 0; i < DATE_MAX; i++)
133                         elm_object_style_set(wd->date[i], "datefield");
134
135                 for (i = 0; i < TIME_MAX; i++)
136                         evas_object_hide(wd->time[i]);
137         }
138         else if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
139         {
140                 _elm_theme_object_set(obj, wd->base, "datefield", "time", elm_widget_style_get(obj));
141
142                 for (i = 0; i < TIME_MAX; i++)
143                         elm_object_style_set(wd->time[i], "datefield");
144
145                 for (i = 0; i < DATE_MAX; i++)
146                         evas_object_hide(wd->date[i]);
147         }
148
149         if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
150         {
151                 edje_object_part_swallow(wd->base, "elm.swallow.date.year", wd->date[DATE_YEAR]);
152                 edje_object_part_swallow(wd->base, "elm.swallow.date.month", wd->date[DATE_MON]);
153                 edje_object_part_swallow(wd->base, "elm.swallow.date.day", wd->date[DATE_DAY]);
154                 edje_object_part_text_set(wd->base, "elm.text.date.comma", ",");        
155         }
156         
157         if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME || wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
158         {
159                 edje_object_part_swallow(wd->base, "elm.swallow.time.hour", wd->time[TIME_HOUR]);
160                 edje_object_part_swallow(wd->base, "elm.swallow.time.min", wd->time[TIME_MIN]);
161                 edje_object_part_text_set(wd->base, "elm.text.colon", ":");
162         }
163
164         edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
165
166         _date_update(obj);
167         _sizing_eval(obj);
168 }
169
170 static void
171 _sizing_eval(Evas_Object *obj)
172 {
173         Widget_Data *wd = elm_widget_data_get(obj);
174         Evas_Coord minw = -1, minh = -1;
175
176         edje_object_size_min_calc(wd->base, &minw, &minh);
177         evas_object_size_hint_min_set(obj, minw, minh);
178         evas_object_size_hint_max_set(obj, -1, -1);
179 }
180
181 static void
182 _signal_ampm_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
183 {
184         Widget_Data *wd = elm_widget_data_get(data);
185         Evas_Object *focus_obj;
186         
187         if (!wd || !wd->base) return ;  
188
189         focus_obj = elm_widget_focused_object_get(data);
190         if (focus_obj) elm_object_unfocus(focus_obj);
191         edje_object_signal_emit(wd->base, "elm,state,focus,out", "elm");
192 }
193
194 static void
195 _signal_ampm_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
196 {
197         Widget_Data *wd = elm_widget_data_get(data);
198         if (!wd || !wd->base) return ;  
199
200         wd->pm = !wd->pm;
201
202         if (wd->pm)
203         {
204                 edje_object_part_text_set(wd->base, "elm.text.ampm", "PM");
205                 wd->hour += HOUR_12H_MAXIMUM;
206         }
207         else
208         {
209                 edje_object_part_text_set(wd->base, "elm.text.ampm", "AM");
210                 wd->hour -= HOUR_12H_MAXIMUM;
211         }
212 }
213
214 static void
215 _signal_rect_mouse_down(void *data, Evas_Object *obj, const char *emission, const char *source)
216 {
217         Widget_Data *wd = elm_widget_data_get(data);
218         if (!wd) return ;
219
220         if (!strcmp(source, "elm.rect.date.year.over"))
221                 elm_object_focus(wd->date[DATE_YEAR]);
222         else if (!strcmp(source, "elm.rect.date.month.over"))
223                 elm_object_focus(wd->date[DATE_MON]);
224         else if (!strcmp(source, "elm.rect.date.day.over"))
225                 elm_object_focus(wd->date[DATE_DAY]);
226         else if (!strcmp(source, "elm.rect.time.hour.over"))
227                 elm_object_focus(wd->time[TIME_HOUR]);
228         else if (!strcmp(source, "elm.rect.time.min.over"))
229                 elm_object_focus(wd->time[TIME_MIN]);
230         else if (!strcmp(source, "elm.rect.date.left.pad"))
231         {
232                 switch (wd->date_format)
233                 {
234                         case DATE_FORMAT_YYDDMM:
235                         case DATE_FORMAT_YYMMDD:
236                                 elm_object_focus(wd->date[DATE_YEAR]);
237                                 break;
238                         case DATE_FORMAT_MMDDYY:
239                         case DATE_FORMAT_MMYYDD:
240                                 elm_object_focus(wd->date[DATE_MON]);
241                                 break;
242                         case DATE_FORMAT_DDMMYY:
243                         case DATE_FORMAT_DDYYMM:
244                                 elm_object_focus(wd->date[DATE_DAY]);
245                 }
246         }
247         else if (!strcmp(source, "elm.rect.date.right.pad"))
248         {
249                 switch (wd->date_format)
250                 {
251                         case DATE_FORMAT_MMDDYY:
252                         case DATE_FORMAT_DDMMYY:
253                                 elm_object_focus(wd->date[DATE_YEAR]);
254                                 break;
255                         case DATE_FORMAT_DDYYMM:
256                         case DATE_FORMAT_YYDDMM:
257                                 elm_object_focus(wd->date[DATE_MON]);
258                                 break;
259                         case DATE_FORMAT_YYMMDD:
260                         case DATE_FORMAT_MMYYDD:
261                                 elm_object_focus(wd->date[DATE_DAY]);
262                 }
263         }
264 }
265
266 static void
267 _entry_focused_cb(void *data, Evas_Object *obj, void *event_info)
268 {
269         Widget_Data *wd = elm_widget_data_get(data);
270         if (!wd || !wd->base) return;
271  
272         if (elm_widget_focus_get(data))
273                 edje_object_signal_emit(wd->base, "elm,state,focus,in", "elm");
274
275         if (obj == wd->date[DATE_YEAR])
276                 edje_object_signal_emit(wd->base, "elm,state,year,focus,in", "elm");
277         else if (obj == wd->date[DATE_MON])
278                 edje_object_signal_emit(wd->base, "elm,state,month,focus,in", "elm");
279         else if (obj == wd->date[DATE_DAY])
280                 edje_object_signal_emit(wd->base, "elm,state,day,focus,in", "elm");
281         else if (obj == wd->time[TIME_HOUR])
282                 edje_object_signal_emit(wd->base, "elm,state,hour,focus,in", "elm");
283         else if (obj == wd->time[TIME_MIN])
284                 edje_object_signal_emit(wd->base, "elm,state,min,focus,in", "elm");
285 }
286
287 static void
288 _entry_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
289 {
290         Widget_Data *wd = elm_widget_data_get(data);
291         char str[YEAR_MAX_LENGTH+1] = {0,};
292         int num = 0;
293
294         if (!wd || !wd->base) return;
295         
296         wd->editing = FALSE;
297
298         if (obj == wd->date[DATE_YEAR])
299         {
300                 if (!strlen(elm_entry_entry_get(wd->date[DATE_YEAR]))) num = wd->year;
301                 else num = atoi(elm_entry_entry_get(wd->date[DATE_YEAR]));
302                 
303                 if (num > YEAR_MAXIMUM) num = YEAR_MAXIMUM;
304                 else if (num < YEAR_MINIMUM) num = YEAR_MINIMUM;
305                 wd->year = num;
306
307                 sprintf(str, "%d", num);
308                 elm_entry_entry_set(wd->date[DATE_YEAR], str);
309                 edje_object_signal_emit(wd->base, "elm,state,year,focus,out", "elm");
310         }
311         else if (obj == wd->date[DATE_MON])
312         {
313                 int day_of_month = _maximum_day_get(wd->year, wd->month);
314
315                 if (wd->day > day_of_month) 
316                 {
317                         wd->day = day_of_month;
318                         sprintf(str, "%d", wd->day);
319                         elm_entry_entry_set(wd->date[DATE_DAY], str);
320                 }
321                 edje_object_signal_emit(wd->base, "elm,state,month,focus,out", "elm");
322         }       
323         else if (obj == wd->date[DATE_DAY])
324         {
325                 int day_of_month = _maximum_day_get(wd->year, wd->month);
326
327                 if (!strlen(elm_entry_entry_get(wd->date[DATE_DAY]))) num = wd->day;
328                 else num = atoi(elm_entry_entry_get(wd->date[DATE_DAY]));
329                 
330                 if (num > day_of_month) num = day_of_month;
331                 else if (num == 0) num = 1;
332                 wd->day = num;
333                 
334                 sprintf(str, "%d", num);                
335                 elm_entry_entry_set(wd->date[DATE_DAY], str);
336                 edje_object_signal_emit(wd->base, "elm,state,day,focus,out", "elm");
337         }
338         else if (obj == wd->time[TIME_HOUR])
339         {
340                 if (!strlen(elm_entry_entry_get(wd->time[TIME_HOUR]))) num = (wd->hour == 0)? 24 : wd->hour;
341                 else num = atoi(elm_entry_entry_get(wd->time[TIME_HOUR]));
342
343                 if (!wd->time_mode) // 24 mode
344                 {
345                         if (num > HOUR_24H_MAXIMUM) num = HOUR_24H_MAXIMUM;
346                         wd->hour = num;
347                 }
348                 else // 12 mode
349                 {
350                         if (num > HOUR_24H_MAXIMUM)
351                         {
352                                 num = HOUR_12H_MAXIMUM;
353                                 wd->pm = EINA_FALSE;
354                         }
355                         else if (num > HOUR_12H_MAXIMUM)
356                         {
357                                 num -= HOUR_12H_MAXIMUM;
358                                 wd->pm = EINA_TRUE;
359                         }
360                         else if (num == 0) num = 1;
361                         
362                         wd->hour = (wd->pm == EINA_TRUE)? num + HOUR_12H_MAXIMUM : num;
363                         if((wd->hour % 12) == 0) wd->hour -= HOUR_12H_MAXIMUM;
364
365                         if (wd->pm) edje_object_part_text_set(wd->base, "elm.text.ampm", "PM");
366                         else edje_object_part_text_set(wd->base, "elm.text.ampm", "AM");
367                 }
368                 sprintf(str, "%d", num);                
369                 elm_entry_entry_set(wd->time[TIME_HOUR], str);
370                 edje_object_signal_emit(wd->base, "elm,state,hour,focus,out", "elm");                   
371         }
372         else if (obj == wd->time[TIME_MIN])
373         {
374                 if (!strlen(elm_entry_entry_get(wd->time[TIME_MIN]))) num = wd->min;
375                 else num = atoi(elm_entry_entry_get(wd->time[TIME_MIN]));
376                 
377                 if (num > MIN_MAXIMUM) num = MIN_MAXIMUM;
378                 wd->min = num;
379
380                 sprintf(str, "%d", num);
381                 elm_entry_entry_set(wd->time[TIME_MIN], str);
382                 edje_object_signal_emit(wd->base, "elm,state,min,focus,out", "elm");
383         }
384         edje_object_signal_emit(wd->base, "elm,state,focus,out", "elm");
385 }
386
387 static void 
388 _entry_focus_move(Evas_Object *obj, Evas_Object *focus_obj)
389 {
390         Widget_Data *wd = elm_widget_data_get(obj);
391
392         if (!wd) return;
393  
394         if (focus_obj == wd->date[DATE_YEAR])
395         {
396                 switch (wd->date_format)
397                 {
398                         case DATE_FORMAT_DDMMYY:
399                         case DATE_FORMAT_MMDDYY:
400                                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
401                                         elm_object_focus(wd->time[TIME_HOUR]);
402                                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
403                                         elm_object_unfocus(wd->date[DATE_YEAR]);
404                                 break;
405                         case DATE_FORMAT_DDYYMM:
406                         case DATE_FORMAT_YYMMDD:
407                                 elm_object_focus(wd->date[DATE_MON]);
408                                 break;
409                         case DATE_FORMAT_MMYYDD:
410                         case DATE_FORMAT_YYDDMM:
411                                 elm_object_focus(wd->date[DATE_DAY]);
412                 }
413         }
414         else if (focus_obj == wd->date[DATE_MON])
415         {
416                 switch (wd->date_format)
417                 {
418                         case DATE_FORMAT_DDYYMM:
419                         case DATE_FORMAT_YYDDMM:
420                                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
421                                         elm_object_focus(wd->time[TIME_HOUR]);
422                                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
423                                         elm_object_unfocus(wd->date[DATE_MON]);
424                                 break;
425                         case DATE_FORMAT_DDMMYY:
426                         case DATE_FORMAT_MMYYDD:
427                                 elm_object_focus(wd->date[DATE_YEAR]);
428                                 break;
429                         case DATE_FORMAT_MMDDYY:
430                         case DATE_FORMAT_YYMMDD:
431                                 elm_object_focus(wd->date[DATE_DAY]);
432                 }
433         }
434         else if (focus_obj == wd->date[DATE_DAY])
435         {
436                 switch (wd->date_format)
437                 {
438                         case DATE_FORMAT_YYMMDD:
439                         case DATE_FORMAT_MMYYDD:
440                                 if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
441                                         elm_object_focus(wd->time[TIME_HOUR]);
442                                 else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
443                                         elm_object_unfocus(wd->date[DATE_DAY]);
444                                 break;
445                         case DATE_FORMAT_DDYYMM:
446                         case DATE_FORMAT_MMDDYY:
447                                 elm_object_focus(wd->date[DATE_YEAR]);
448                                 break;
449                         case DATE_FORMAT_DDMMYY:
450                         case DATE_FORMAT_YYDDMM:
451                                 elm_object_focus(wd->date[DATE_MON]);
452                 }
453         }
454         else if (focus_obj == wd->time[TIME_HOUR])
455                 elm_object_focus(wd->time[TIME_MIN]);
456         else if (focus_obj == wd->time[TIME_MIN])
457                 elm_object_unfocus(wd->time[TIME_MIN]);
458 }
459
460 static int
461 _maximum_day_get(int year, int month)
462 {
463         int day_of_month = 0;
464         if (year == 0 || month == 0) return 0;
465
466         switch (month) {
467                 case 4: 
468                 case 6: 
469                 case 9: 
470                 case 11:
471                         day_of_month = 30;
472                         break;
473                 case 2:
474                         if ((!(year % 4) && (year % 100)) || !(year % 400))
475                                 day_of_month = 29;
476                         else
477                                 day_of_month = 28;
478                         break;
479                 default:
480                         day_of_month = 31;
481                         break;
482         }
483
484         return day_of_month;
485 }
486
487 static Eina_Bool 
488 _check_input_done(Evas_Object *obj, Evas_Object *focus_obj, int strlen)
489 {
490         Widget_Data *wd = elm_widget_data_get(obj);
491
492         if (!wd) return EINA_FALSE;
493
494         if (focus_obj == wd->date[DATE_YEAR] && strlen == YEAR_MAX_LENGTH)
495                 wd->editing = EINA_FALSE;
496         else if (focus_obj == wd->date[DATE_MON] && strlen == MONTH_MAX_LENGTH)
497                 wd->editing = EINA_FALSE;
498         else if (focus_obj == wd->date[DATE_DAY] && strlen == DAY_MAX_LENGTH)
499                 wd->editing = EINA_FALSE;
500         else if (focus_obj == wd->time[TIME_HOUR])
501         {       
502                 if (strlen == TIME_MAX_LENGTH || atoi(elm_entry_entry_get(focus_obj)) > 2)
503                         wd->editing = EINA_FALSE;
504         }
505         else if (focus_obj == wd->time[TIME_MIN] && strlen == TIME_MAX_LENGTH) 
506                 wd->editing = EINA_FALSE;
507
508         return !wd->editing;
509 }
510
511 static void
512 _entry_key_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
513 {
514         Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
515
516         if (!strcmp(ev->keyname, "BackSpace"))
517                 elm_entry_entry_set(obj, "");
518 }
519
520 static int 
521 _imf_event_commit_cb(void *data, int type, void *event)
522 {
523         Widget_Data *wd = elm_widget_data_get(data);
524         Ecore_IMF_Event_Commit *ev = (Ecore_IMF_Event_Commit *) event;
525         Evas_Object *focus_obj;
526         char str[YEAR_MAX_LENGTH+1] = {0,};
527         
528         if (!wd) return ECORE_CALLBACK_RENEW;
529         if(!elm_widget_focus_get(data)) return ECORE_CALLBACK_RENEW;
530         
531         focus_obj = elm_widget_focused_object_get(data);
532         if (!wd->editing) 
533         {
534                 elm_entry_entry_set(focus_obj, "");
535                 wd->editing = EINA_TRUE;
536         }
537         
538         if (focus_obj == wd->date[DATE_MON])
539         {
540                 wd->month = atoi(ev->str);
541                 strcpy(str, month_label[wd->month]);
542         }
543         else
544         {
545                 strcpy(str, elm_entry_entry_get(focus_obj));
546                 str[strlen(str)] = ev->str[0];
547         }
548         elm_entry_entry_set(focus_obj, str);
549
550         if (_check_input_done(data, focus_obj, strlen(str)))
551                 _entry_focus_move(data, focus_obj);
552
553         return ECORE_CALLBACK_CANCEL;
554 }
555
556 static void 
557 _input_panel_event_callback(void *data, Ecore_IMF_Context *ctx, int value)
558 {
559         Widget_Data *wd = elm_widget_data_get(data);
560
561         if (!wd) return;
562
563         if (wd->func)
564                 wd->func(wd->func_data, data, value);
565 }
566
567 static void
568 _date_update(Evas_Object *obj)
569 {
570         Widget_Data *wd = elm_widget_data_get(obj);
571         char str[YEAR_MAX_LENGTH+1];
572
573         if (!wd || !wd->base) return;
574         
575         sprintf(str, "%d", wd->year);
576         elm_entry_entry_set(wd->date[DATE_YEAR], str);
577
578         sprintf(str, "%s", month_label[wd->month]);
579         elm_entry_entry_set(wd->date[DATE_MON], str);
580
581         sprintf(str, "%d", wd->day);
582         elm_entry_entry_set(wd->date[DATE_DAY], str);
583
584         if (wd->hour >= HOUR_12H_MAXIMUM)
585         {
586                 wd->pm = EINA_TRUE;
587                 edje_object_part_text_set(wd->base, "elm.text.ampm", "PM");
588         }
589         else
590         {
591                 wd->pm = EINA_FALSE;
592                 edje_object_part_text_set(wd->base, "elm.text.ampm", "AM");             
593         }
594
595         if (wd->time_mode && (wd->hour > HOUR_12H_MAXIMUM))
596                 sprintf(str, "%d", wd->hour - HOUR_12H_MAXIMUM);
597         else if (wd->time_mode && (wd->hour == 0))
598                 sprintf(str, "%d", HOUR_12H_MAXIMUM);
599         else
600                 sprintf(str, "%d", wd->hour);
601         elm_entry_entry_set(wd->time[TIME_HOUR], str);
602
603         sprintf(str, "%d", wd->min);
604         if (wd->min == 0) str[1] = '0';
605         elm_entry_entry_set(wd->time[TIME_MIN], str);
606 }
607
608 static void 
609 _date_entry_add(Evas_Object *obj)
610 {
611         Widget_Data *wd = elm_widget_data_get(obj);
612         int i;
613
614         if (!wd) return;        
615         
616         for (i = 0; i < DATE_MAX; i++)
617         {
618                 wd->date[i] = elm_entry_add(obj);
619                 elm_entry_context_menu_disabled_set(wd->date[i], EINA_TRUE);
620                 if (i == DATE_MON) elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_MONTH);
621                 else elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
622                 evas_object_size_hint_weight_set(wd->date[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
623                 evas_object_size_hint_align_set(wd->date[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
624                 evas_object_smart_callback_add(wd->date[i], "focused", _entry_focused_cb, obj);
625                 evas_object_smart_callback_add(wd->date[i], "unfocused", _entry_unfocused_cb, obj);
626                 evas_object_event_callback_add(wd->date[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
627                 elm_widget_sub_object_add(obj, wd->date[i]);
628         }
629         elm_entry_maximum_bytes_set(wd->date[DATE_YEAR], YEAR_MAX_LENGTH);
630         elm_entry_maximum_bytes_set(wd->date[DATE_MON], MONTH_MAX_LENGTH);
631         elm_entry_maximum_bytes_set(wd->date[DATE_DAY], DAY_MAX_LENGTH);
632 }
633
634 static void 
635 _time_entry_add(Evas_Object *obj)
636 {
637         Widget_Data *wd = elm_widget_data_get(obj);
638         int i;
639
640         if (!wd) return;        
641         
642         for (i = 0; i < TIME_MAX; i++)
643         {
644                 wd->time[i] = elm_entry_add(obj);
645                 elm_entry_context_menu_disabled_set(wd->time[i], EINA_TRUE);
646                 elm_entry_input_panel_layout_set(wd->time[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);               
647                 elm_entry_maximum_bytes_set(wd->time[i], TIME_MAX_LENGTH);
648                 evas_object_size_hint_weight_set(wd->time[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
649                 evas_object_size_hint_align_set(wd->time[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
650                 evas_object_smart_callback_add(wd->time[i], "focused", _entry_focused_cb, obj);
651                 evas_object_smart_callback_add(wd->time[i], "unfocused", _entry_unfocused_cb, obj);
652                 evas_object_event_callback_add(wd->time[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
653                 elm_widget_sub_object_add(obj, wd->time[i]);
654         }
655 }
656
657 /**
658  * Add a new datefield object
659  *
660  * @param parent The parent object
661  * @return The new object or NULL if it cannot be created
662  *
663  * @ingroup Datefield
664  */
665 EAPI Evas_Object *
666 elm_datefield_add(Evas_Object *parent)
667 {
668         Evas_Object *obj;
669         Evas *e;
670         Widget_Data *wd;
671
672         e = evas_object_evas_get(parent);
673         if (!e) return NULL; 
674         wd = ELM_NEW(Widget_Data);
675         obj = elm_widget_add(e); 
676         ELM_SET_WIDTYPE(widtype, "datefield");
677         elm_widget_type_set(obj, "datefield");
678         elm_widget_sub_object_add(parent, obj);
679         elm_widget_data_set(obj, wd);
680         elm_widget_del_hook_set(obj, _del_hook);
681         elm_widget_theme_hook_set(obj, _theme_hook);
682         elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
683         elm_widget_can_focus_set(obj, EINA_TRUE);
684
685         wd->base = edje_object_add(e);
686         elm_widget_resize_object_set(obj, wd->base);
687         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.left.pad", _signal_rect_mouse_down, obj);
688         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.year.over", _signal_rect_mouse_down, obj);
689         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.month.over", _signal_rect_mouse_down, obj);
690         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.day.over", _signal_rect_mouse_down, obj);      
691         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.right.pad", _signal_rect_mouse_down, obj);
692
693         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.hour.over", _signal_rect_mouse_down, obj);
694         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.min.over", _signal_rect_mouse_down, obj);
695         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.ampm.over", _signal_ampm_mouse_down, obj);
696         edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "elm.rect.time.ampm.over", _signal_ampm_clicked, obj);
697
698         wd->handler =  ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _imf_event_commit_cb, obj);
699         _date_entry_add(obj);
700         _time_entry_add(obj);   
701
702         wd->year = YEAR_MINIMUM;
703         wd->month = 1;
704         wd->day = 1;
705         wd->hour = 0;
706         wd->min = 0;
707         wd->layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
708         wd->editing = EINA_FALSE;
709         wd->time_mode = EINA_TRUE;
710         wd->date_format = DATE_FORMAT_MMDDYY;
711         
712         _theme_hook(obj);
713         
714         return obj;
715 }
716
717 /**
718  * set layout for the datefield
719  *
720  * @param obj The datefield object
721  * @param layout set layout for date/time/dateandtime (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
722  *
723  * @ingroup Datefield
724  */
725 EAPI void
726 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
727 {
728         ELM_CHECK_WIDTYPE(obj, widtype);
729         Widget_Data *wd = elm_widget_data_get(obj);
730         
731         if (!wd) return;
732
733         if (wd->layout != layout)
734         {
735                 wd->layout = layout;
736                 _theme_hook(obj);
737         }
738 }
739
740 /**
741  * Set selected date of the datefield
742  *
743  * @param obj The datefield object
744  * @param year The year to set
745  * @param month The month to set
746  * @param day The day to set
747  * @param hour The hours to set (24hour mode - 0~23)
748  * @param min The minutes to set (0~59)
749  *
750  * @ingroup Datefield
751  */
752 EAPI void
753 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour, int min)
754 {
755         ELM_CHECK_WIDTYPE(obj, widtype);
756         Widget_Data *wd = elm_widget_data_get(obj);
757         int day_of_month;
758         
759         if (!wd) return;
760
761         if (year > YEAR_MAXIMUM) wd->year = YEAR_MAXIMUM;
762         else if (year < YEAR_MINIMUM) wd->year = YEAR_MINIMUM;
763         else wd->year = year;
764
765         if (month > MONTH_MAXIMUM) wd->month = MONTH_MAXIMUM;
766         else if (month <= 0) wd->month = 1;
767         else wd->month = month;
768
769         day_of_month = _maximum_day_get(wd->year, wd->month);   
770         if (day > day_of_month) wd->day = day_of_month;
771         else if (day <= 0) wd->day = 1;
772         else wd->day = day;
773         
774         if (hour > HOUR_24H_MAXIMUM) wd->hour = HOUR_24H_MAXIMUM;
775         else if (hour < 0) wd->hour = 0;
776         else wd->hour = hour;
777
778         if (min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
779         else if (min < 0) wd->min = 0;
780         else wd->min = min;
781
782         _date_update(obj);
783 }
784
785 /**
786  * Get selected date of the datefield
787  *
788  * @param obj The datefield object
789  * @param year The pointer to the variable get the selected year
790  * @param month The pointer to the variable get the selected month
791  * @param day The pointer to the variable get the selected day
792  * @param hour The pointer to the variable get the selected hour (24hour mode)
793  * @param hour The pointer to the variable get the selected min
794  *
795  * @ingroup Datefield
796  */
797 EAPI void
798 elm_datefield_date_get(Evas_Object *obj, int *year, int *month, int *day, int *hour, int *min)
799 {
800         ELM_CHECK_WIDTYPE(obj, widtype);
801         Widget_Data *wd = elm_widget_data_get(obj);
802         
803         if (!wd) return;
804         
805         if (year)
806                 *year = wd->year;
807         if (month)
808                 *month = wd->month;
809         if (day)
810                 *day = wd->day;
811         if (hour)
812                 *hour = wd->hour;
813         if (min)
814                 *min = wd->min;
815 }
816
817 /**
818  * Set if the datefield show hours in military or am/pm mode
819  *
820  * @param obj The datefield object
821  * @param mode option for the hours mode. If true, it is shown as 12h mode, if false, it is shown as 24h mode. Default value is true 
822  *
823  * @ingroup Datefield
824  */
825 EAPI void
826 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
827 {
828         ELM_CHECK_WIDTYPE(obj, widtype);
829         Widget_Data *wd = elm_widget_data_get(obj);
830         
831         if (!wd) return;
832
833         if (wd->time_mode != mode) {
834                 wd->time_mode = mode;
835                 //_update_ampm(obj);
836         }
837 }
838
839 /**
840  * Set date format of datefield
841  *
842  * @param obj The datefield object
843  * @param fmt The date format, ex) yymmdd. Default value is mmddyy.
844  *
845  * @ingroup Datefield
846  */
847 EAPI void
848 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
849 {
850         char sig[32] = "elm,state,format,";
851         int i = 0, j;
852         Widget_Data *wd = elm_widget_data_get(obj);
853
854         if (!wd || !fmt) return;
855
856         j = strlen(sig);
857         while (j < 32) {
858                 sig[j++] = tolower(fmt[i++]);
859         }
860
861         edje_object_signal_emit(wd->base, sig, "elm");
862
863         if (strstr(sig, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
864         else if (strstr(sig, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
865         else if (strstr(sig, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
866         else if (strstr(sig, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
867         else if (strstr(sig, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
868         else if (strstr(sig, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
869 }
870
871 /**
872  * Add a callback function for input panel state
873  *
874  * @param obj The datefield object
875  * @param func The function to be called when the event is triggered (value will be the Ecore_IMF_Input_Panel_State)
876  * @param data The data pointer to be passed to @p func 
877  *
878  * @ingroup Datefield
879  */
880 EAPI void 
881 elm_datefield_input_panel_state_callback_add(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value), void *data)
882 {
883         Widget_Data *wd = elm_widget_data_get(obj);
884         int i;
885
886         if (!wd) return;
887
888         if (wd->func && (wd->func != pEventCallbackFunc))
889                 elm_datefield_input_panel_state_callback_del(obj, wd->func);    
890
891         if (pEventCallbackFunc)
892         {
893                 wd->func = pEventCallbackFunc;
894                 wd->func_data = data;
895
896                 for (i = 0; i < DATE_MAX; i++)
897                         ecore_imf_context_input_panel_event_callback_add(
898                                 elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
899
900                 for (i = 0; i < TIME_MAX; i++)
901                         ecore_imf_context_input_panel_event_callback_add(
902                                 elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
903         }               
904 }
905
906 /**
907  * Delete a callback function for input panel state
908  *
909  * @param obj The datefield object
910  * @param func The function to be called when the event is triggered
911  *
912  * @ingroup Datefield
913  */
914 EAPI void 
915 elm_datefield_input_panel_state_callback_del(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value))
916 {
917         Widget_Data *wd = elm_widget_data_get(obj);
918         int i;
919
920         if (!wd) return;
921
922         if (wd->func && wd->func == pEventCallbackFunc) 
923         {
924                 for (i = 0; i < DATE_MAX; i++)
925                         ecore_imf_context_input_panel_event_callback_del(
926                                 elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
927
928                 for (i = 0; i < TIME_MAX; i++)
929                         ecore_imf_context_input_panel_event_callback_del(
930                                 elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
931
932                 wd->func = NULL;
933                 wd->func_data = NULL;
934         }
935 }
936