[elm_datefield]add time_mope_set
[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->time_mode) //24 mode
585                 sprintf(str, "%d", wd->hour);
586         else
587         {
588                 if (wd->hour >= HOUR_12H_MAXIMUM)
589                 {
590                         wd->pm = EINA_TRUE;
591                         edje_object_part_text_set(wd->base, "elm.text.ampm", "PM");
592                 }
593                 else
594                 {
595                         wd->pm = EINA_FALSE;
596                         edje_object_part_text_set(wd->base, "elm.text.ampm", "AM");             
597                 }
598
599                 if (wd->hour > HOUR_12H_MAXIMUM)
600                         sprintf(str, "%d", wd->hour - HOUR_12H_MAXIMUM);
601                 else if (wd->hour == 0)
602                         sprintf(str, "%d", HOUR_12H_MAXIMUM);
603                 else
604                         sprintf(str, "%d", wd->hour);
605         }
606         elm_entry_entry_set(wd->time[TIME_HOUR], str);
607
608         sprintf(str, "%d", wd->min);
609         if (wd->min == 0) str[1] = '0';
610         elm_entry_entry_set(wd->time[TIME_MIN], str);
611 }
612
613 static void 
614 _date_entry_add(Evas_Object *obj)
615 {
616         Widget_Data *wd = elm_widget_data_get(obj);
617         int i;
618
619         if (!wd) return;        
620         
621         for (i = 0; i < DATE_MAX; i++)
622         {
623                 wd->date[i] = elm_entry_add(obj);
624                 elm_entry_context_menu_disabled_set(wd->date[i], EINA_TRUE);
625                 if (i == DATE_MON) elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_MONTH);
626                 else elm_entry_input_panel_layout_set(wd->date[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
627                 evas_object_size_hint_weight_set(wd->date[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
628                 evas_object_size_hint_align_set(wd->date[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
629                 evas_object_smart_callback_add(wd->date[i], "focused", _entry_focused_cb, obj);
630                 evas_object_smart_callback_add(wd->date[i], "unfocused", _entry_unfocused_cb, obj);
631                 evas_object_event_callback_add(wd->date[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
632                 elm_widget_sub_object_add(obj, wd->date[i]);
633         }
634         elm_entry_maximum_bytes_set(wd->date[DATE_YEAR], YEAR_MAX_LENGTH);
635         elm_entry_maximum_bytes_set(wd->date[DATE_MON], MONTH_MAX_LENGTH);
636         elm_entry_maximum_bytes_set(wd->date[DATE_DAY], DAY_MAX_LENGTH);
637 }
638
639 static void 
640 _time_entry_add(Evas_Object *obj)
641 {
642         Widget_Data *wd = elm_widget_data_get(obj);
643         int i;
644
645         if (!wd) return;        
646         
647         for (i = 0; i < TIME_MAX; i++)
648         {
649                 wd->time[i] = elm_entry_add(obj);
650                 elm_entry_context_menu_disabled_set(wd->time[i], EINA_TRUE);
651                 elm_entry_input_panel_layout_set(wd->time[i], ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);               
652                 elm_entry_maximum_bytes_set(wd->time[i], TIME_MAX_LENGTH);
653                 evas_object_size_hint_weight_set(wd->time[i], EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
654                 evas_object_size_hint_align_set(wd->time[i], EVAS_HINT_FILL, EVAS_HINT_FILL);
655                 evas_object_smart_callback_add(wd->time[i], "focused", _entry_focused_cb, obj);
656                 evas_object_smart_callback_add(wd->time[i], "unfocused", _entry_unfocused_cb, obj);
657                 evas_object_event_callback_add(wd->time[i], EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
658                 elm_widget_sub_object_add(obj, wd->time[i]);
659         }
660 }
661
662 /**
663  * Add a new datefield object
664  *
665  * @param parent The parent object
666  * @return The new object or NULL if it cannot be created
667  *
668  * @ingroup Datefield
669  */
670 EAPI Evas_Object *
671 elm_datefield_add(Evas_Object *parent)
672 {
673         Evas_Object *obj;
674         Evas *e;
675         Widget_Data *wd;
676
677         e = evas_object_evas_get(parent);
678         if (!e) return NULL; 
679         wd = ELM_NEW(Widget_Data);
680         obj = elm_widget_add(e); 
681         ELM_SET_WIDTYPE(widtype, "datefield");
682         elm_widget_type_set(obj, "datefield");
683         elm_widget_sub_object_add(parent, obj);
684         elm_widget_data_set(obj, wd);
685         elm_widget_del_hook_set(obj, _del_hook);
686         elm_widget_theme_hook_set(obj, _theme_hook);
687         elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
688         elm_widget_can_focus_set(obj, EINA_TRUE);
689
690         wd->base = edje_object_add(e);
691         elm_widget_resize_object_set(obj, wd->base);
692         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.left.pad", _signal_rect_mouse_down, obj);
693         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.year.over", _signal_rect_mouse_down, obj);
694         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.month.over", _signal_rect_mouse_down, obj);
695         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.day.over", _signal_rect_mouse_down, obj);      
696         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.date.right.pad", _signal_rect_mouse_down, obj);
697
698         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.hour.over", _signal_rect_mouse_down, obj);
699         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.min.over", _signal_rect_mouse_down, obj);
700         edje_object_signal_callback_add(wd->base, "mouse,down,1", "elm.rect.time.ampm.over", _signal_ampm_mouse_down, obj);
701         edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "elm.rect.time.ampm.over", _signal_ampm_clicked, obj);
702
703         wd->handler =  ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _imf_event_commit_cb, obj);
704         _date_entry_add(obj);
705         _time_entry_add(obj);   
706
707         wd->year = YEAR_MINIMUM;
708         wd->month = 1;
709         wd->day = 1;
710         wd->hour = 0;
711         wd->min = 0;
712         wd->layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
713         wd->editing = EINA_FALSE;
714         wd->time_mode = EINA_TRUE;
715         wd->date_format = DATE_FORMAT_MMDDYY;
716         
717         _theme_hook(obj);
718         
719         return obj;
720 }
721
722 /**
723  * set layout for the datefield
724  *
725  * @param obj The datefield object
726  * @param layout set layout for date/time/dateandtime (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
727  *
728  * @ingroup Datefield
729  */
730 EAPI void
731 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
732 {
733         ELM_CHECK_WIDTYPE(obj, widtype);
734         Widget_Data *wd = elm_widget_data_get(obj);
735         
736         if (!wd) return;
737
738         if (wd->layout != layout)
739         {
740                 wd->layout = layout;
741                 _theme_hook(obj);
742         }
743 }
744
745 /**
746  * Set selected date of the datefield
747  *
748  * @param obj The datefield object
749  * @param year The year to set
750  * @param month The month to set
751  * @param day The day to set
752  * @param hour The hours to set (24hour mode - 0~23)
753  * @param min The minutes to set (0~59)
754  *
755  * @ingroup Datefield
756  */
757 EAPI void
758 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour, int min)
759 {
760         ELM_CHECK_WIDTYPE(obj, widtype);
761         Widget_Data *wd = elm_widget_data_get(obj);
762         int day_of_month;
763         
764         if (!wd) return;
765
766         if (year > YEAR_MAXIMUM) wd->year = YEAR_MAXIMUM;
767         else if (year < YEAR_MINIMUM) wd->year = YEAR_MINIMUM;
768         else wd->year = year;
769
770         if (month > MONTH_MAXIMUM) wd->month = MONTH_MAXIMUM;
771         else if (month <= 0) wd->month = 1;
772         else wd->month = month;
773
774         day_of_month = _maximum_day_get(wd->year, wd->month);   
775         if (day > day_of_month) wd->day = day_of_month;
776         else if (day <= 0) wd->day = 1;
777         else wd->day = day;
778         
779         if (hour > HOUR_24H_MAXIMUM) wd->hour = HOUR_24H_MAXIMUM;
780         else if (hour < 0) wd->hour = 0;
781         else wd->hour = hour;
782
783         if (min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
784         else if (min < 0) wd->min = 0;
785         else wd->min = min;
786
787         _date_update(obj);
788 }
789
790 /**
791  * Get selected date of the datefield
792  *
793  * @param obj The datefield object
794  * @param year The pointer to the variable get the selected year
795  * @param month The pointer to the variable get the selected month
796  * @param day The pointer to the variable get the selected day
797  * @param hour The pointer to the variable get the selected hour (24hour mode)
798  * @param hour The pointer to the variable get the selected min
799  *
800  * @ingroup Datefield
801  */
802 EAPI void
803 elm_datefield_date_get(Evas_Object *obj, int *year, int *month, int *day, int *hour, int *min)
804 {
805         ELM_CHECK_WIDTYPE(obj, widtype);
806         Widget_Data *wd = elm_widget_data_get(obj);
807         
808         if (!wd) return;
809         
810         if (year)
811                 *year = wd->year;
812         if (month)
813                 *month = wd->month;
814         if (day)
815                 *day = wd->day;
816         if (hour)
817                 *hour = wd->hour;
818         if (min)
819                 *min = wd->min;
820 }
821
822 /**
823  * Set if the datefield show hours in military or am/pm mode
824  *
825  * @param obj The datefield object
826  * @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 
827  *
828  * @ingroup Datefield
829  */
830 EAPI void
831 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
832 {
833         ELM_CHECK_WIDTYPE(obj, widtype);
834         Widget_Data *wd = elm_widget_data_get(obj);
835         
836         if (!wd) return;
837
838         if (wd->time_mode != mode) 
839         {
840                 char str[YEAR_MAX_LENGTH+1];
841                 
842                 wd->time_mode = mode;
843                 if (!wd->time_mode) edje_object_signal_emit(wd->base, "elm,state,mode,24h", "elm");
844                 else edje_object_signal_emit(wd->base, "elm,state,mode,12h", "elm");
845
846                 if (!wd->time_mode) //24 mode
847                         sprintf(str, "%d", wd->hour);
848                 else
849                 {
850                         if (wd->hour >= HOUR_12H_MAXIMUM)
851                         {
852                                 wd->pm = EINA_TRUE;
853                                 edje_object_part_text_set(wd->base, "elm.text.ampm", "PM");
854                         }
855                         else
856                         {
857                                 wd->pm = EINA_FALSE;
858                                 edje_object_part_text_set(wd->base, "elm.text.ampm", "AM");             
859                         }
860
861                         if (wd->hour > HOUR_12H_MAXIMUM)
862                                 sprintf(str, "%d", wd->hour - HOUR_12H_MAXIMUM);
863                         else if (wd->hour == 0)
864                                 sprintf(str, "%d", HOUR_12H_MAXIMUM);
865                         else
866                                 sprintf(str, "%d", wd->hour);
867                 }
868                 elm_entry_entry_set(wd->time[TIME_HOUR], str);
869         }
870 }
871
872 /**
873  * Set date format of datefield
874  *
875  * @param obj The datefield object
876  * @param fmt The date format, ex) yymmdd. Default value is mmddyy.
877  *
878  * @ingroup Datefield
879  */
880 EAPI void
881 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
882 {
883         char sig[32] = "elm,state,format,";
884         int i = 0, j;
885         Widget_Data *wd = elm_widget_data_get(obj);
886
887         if (!wd || !fmt) return;
888
889         j = strlen(sig);
890         while (j < 32) {
891                 sig[j++] = tolower(fmt[i++]);
892         }
893
894         edje_object_signal_emit(wd->base, sig, "elm");
895
896         if (strstr(sig, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
897         else if (strstr(sig, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
898         else if (strstr(sig, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
899         else if (strstr(sig, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
900         else if (strstr(sig, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
901         else if (strstr(sig, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
902 }
903
904 /**
905  * Add a callback function for input panel state
906  *
907  * @param obj The datefield object
908  * @param func The function to be called when the event is triggered (value will be the Ecore_IMF_Input_Panel_State)
909  * @param data The data pointer to be passed to @p func 
910  *
911  * @ingroup Datefield
912  */
913 EAPI void 
914 elm_datefield_input_panel_state_callback_add(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value), void *data)
915 {
916         Widget_Data *wd = elm_widget_data_get(obj);
917         int i;
918
919         if (!wd) return;
920
921         if (wd->func && (wd->func != pEventCallbackFunc))
922                 elm_datefield_input_panel_state_callback_del(obj, wd->func);    
923
924         if (pEventCallbackFunc)
925         {
926                 wd->func = pEventCallbackFunc;
927                 wd->func_data = data;
928
929                 for (i = 0; i < DATE_MAX; i++)
930                         ecore_imf_context_input_panel_event_callback_add(
931                                 elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
932
933                 for (i = 0; i < TIME_MAX; i++)
934                         ecore_imf_context_input_panel_event_callback_add(
935                                 elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback, obj);
936         }               
937 }
938
939 /**
940  * Delete a callback function for input panel state
941  *
942  * @param obj The datefield object
943  * @param func The function to be called when the event is triggered
944  *
945  * @ingroup Datefield
946  */
947 EAPI void 
948 elm_datefield_input_panel_state_callback_del(Evas_Object *obj, void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value))
949 {
950         Widget_Data *wd = elm_widget_data_get(obj);
951         int i;
952
953         if (!wd) return;
954
955         if (wd->func && wd->func == pEventCallbackFunc) 
956         {
957                 for (i = 0; i < DATE_MAX; i++)
958                         ecore_imf_context_input_panel_event_callback_del(
959                                 elm_entry_imf_context_get(wd->date[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
960
961                 for (i = 0; i < TIME_MAX; i++)
962                         ecore_imf_context_input_panel_event_callback_del(
963                                 elm_entry_imf_context_get(wd->time[i]), ECORE_IMF_INPUT_PANEL_STATE_EVENT, _input_panel_event_callback);
964
965                 wd->func = NULL;
966                 wd->func_data = NULL;
967         }
968 }
969