review comments are corrected.elm_datefield.c , elm_actionslider.c]Prevent report...
[framework/uifw/elementary.git] / src / lib / elm_datefield.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #ifdef HAVE_ELEMENTARY_X
5 # include <langinfo.h>
6 #else
7 # include <evil_langinfo.h>
8 #endif
9
10 /**
11  * @defgroup Datefield Datefield
12  * @ingroup Elementary
13  *
14  * This is a date editfield. it is used to input date and time using keypad
15  */
16
17 typedef struct _Widget_Data Widget_Data;
18
19 enum
20 {
21   DATE_FORMAT_YYMMDD,
22   DATE_FORMAT_YYDDMM,
23   DATE_FORMAT_MMYYDD,
24   DATE_FORMAT_MMDDYY,
25   DATE_FORMAT_DDYYMM,
26   DATE_FORMAT_DDMMYY,
27   DATE_FORMAT_MAX
28 };
29
30 enum
31 {
32   ENTRY_YEAR,
33   ENTRY_MON,
34   ENTRY_DAY,
35   ENTRY_HOUR,
36   ENTRY_MIN
37 };
38
39 #define MONTH_MAXIMUM 12
40 #define HOUR_24H_MAXIMUM 23
41 #define HOUR_12H_MAXIMUM 12
42 #define MIN_MAXIMUM 59
43 #define YEAR_MAX_LENGTH 4
44
45 struct _Widget_Data
46 {
47    Evas_Object *base;
48    Evas_Object *time_ampm;
49    Evas_Object *ctxpopup;
50    Evas_Object *diskselector;
51    unsigned int layout;
52    int year, month, day, hour, min;
53    int y_max, m_max, d_max;
54    int y_min, m_min, d_min;
55    int date_format,date_focusedpart;
56    Eina_Bool pm:1;
57    Eina_Bool time_mode:1;
58    Eina_Bool format_exists:1;
59    Eina_Bool ctxpopup_show:1;
60 };
61
62 static const char *widtype = NULL;
63
64 static void _del_hook(Evas_Object *obj);
65 static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
66 static void _theme_hook(Evas_Object *obj);
67 static void _sizing_eval(Evas_Object *obj);
68 static void _datefield_resize_cb(void *data, Evas *e __UNUSED__,
69                                  Evas_Object *obj, void *event_info __UNUSED__);
70 static void _ampm_clicked_cb(void *data, Evas_Object *obj, void *event_info);
71 static void _signal_rect_mouse_down(void *data, Evas_Object *obj __UNUSED__,
72                                     const char *emission __UNUSED__,
73                                     const char *source);
74 static void _diskselector_cb(void *data, Evas_Object *obj __UNUSED__,
75                              void *event_info);
76 static void _datefield_focus_set(Evas_Object *data);
77 static int _maximum_day_get(int year, int month);
78 static int _check_date_boundary(Evas_Object *obj, int num, int flag);
79 static char* _get_i18n_string(Evas_Object *obj, nl_item item);
80 static void _date_update(Evas_Object *obj);
81
82 static void
83 _del_hook(Evas_Object *obj)
84 {
85    Widget_Data *wd = elm_widget_data_get(obj);
86
87    if (!wd) return ;
88    free(wd);
89 }
90
91 static void
92 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
93 {
94    Widget_Data *wd = elm_widget_data_get(obj);
95
96    if (!wd || !wd->base) return ;
97 }
98
99 static void
100 _theme_hook(Evas_Object *obj)
101 {
102    Widget_Data *wd = elm_widget_data_get(obj);
103    char sig[32] = {0,};
104    char buf[1024];
105
106    if (!wd || !wd->base) return;
107
108    if (wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
109       _elm_theme_object_set(obj, wd->base, "datefield", "dateandtime",
110                             elm_widget_style_get(obj));
111    else if (wd->layout == ELM_DATEFIELD_LAYOUT_DATE)
112       _elm_theme_object_set(obj, wd->base, "datefield", "date",
113                             elm_widget_style_get(obj));
114    else if (wd->layout == ELM_DATEFIELD_LAYOUT_TIME)
115       _elm_theme_object_set(obj, wd->base, "datefield", "time",
116                             elm_widget_style_get(obj));
117
118    if (wd->time_ampm)
119      {
120         edje_object_part_unswallow(wd->base,wd->time_ampm);
121         evas_object_del(wd->time_ampm);
122         wd->time_ampm = NULL;
123    }
124    if ((wd->layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME
125                   || wd->layout == ELM_DATEFIELD_LAYOUT_TIME) && wd->time_mode)
126      {
127         wd->time_ampm = elm_button_add(obj);
128         elm_widget_sub_object_add(obj, wd->time_ampm);
129         edje_object_part_swallow(wd->base, "elm.swallow.time.ampm",
130                                  wd->time_ampm);
131         snprintf(buf,sizeof(buf),"datefield.ampm/%s",elm_widget_style_get(obj));
132         elm_object_style_set(wd->time_ampm, buf);
133         evas_object_size_hint_weight_set(wd->time_ampm, EVAS_HINT_EXPAND,
134                                          EVAS_HINT_EXPAND);
135         evas_object_size_hint_align_set(wd->time_ampm, EVAS_HINT_FILL,
136                                         EVAS_HINT_FILL);
137         evas_object_smart_callback_add(wd->time_ampm, "clicked",
138                                        _ampm_clicked_cb, obj);
139      }
140
141    edje_object_scale_set(wd->base,elm_widget_scale_get(obj)*_elm_config->scale);
142
143    //set date format
144    if (wd->format_exists)
145      sprintf(sig, "elm,state,format,%s", elm_datefield_date_format_get(obj));
146    else
147      {
148         char *str = _get_i18n_string(obj, D_FMT);
149         if (str)
150           {
151              if (!strcmp(str, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
152              else if (!strcmp(str, "yyddmm"))
153                 wd->date_format = DATE_FORMAT_YYDDMM;
154              else if (!strcmp(str, "mmyydd"))
155                 wd->date_format = DATE_FORMAT_MMYYDD;
156              else if (!strcmp(str, "mmddyy"))
157                 wd->date_format = DATE_FORMAT_MMDDYY;
158              else if (!strcmp(str, "ddyymm"))
159                 wd->date_format = DATE_FORMAT_DDYYMM;
160              else if (!strcmp(str, "ddmmyy"))
161                 wd->date_format = DATE_FORMAT_DDMMYY;
162              sprintf(sig, "elm,state,format,%s",str);
163              free(str);
164           }
165      }
166    edje_object_signal_emit(wd->base, sig, "elm");
167    edje_object_message_signal_process(wd->base);
168
169    _date_update(obj);
170    _sizing_eval(obj);
171 }
172
173 static void
174 _sizing_eval(Evas_Object *obj)
175 {
176    Widget_Data *wd = elm_widget_data_get(obj);
177    Evas_Coord minw = -1, minh = -1;
178
179    edje_object_size_min_calc(wd->base, &minw, &minh);
180    evas_object_size_hint_min_set(obj, minw, minh);
181    evas_object_size_hint_max_set(obj, -1, -1);
182 }
183
184 static void
185 _datefield_resize_cb(void *data,Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
186                      void *event_info __UNUSED__)
187 {
188    Widget_Data *wd = elm_widget_data_get(data);
189
190    if (!wd || !wd->base) return ;
191
192    Evas_Object *disk = elm_ctxpopup_content_unset(wd->ctxpopup);
193    if (disk) evas_object_del(disk);
194    if (wd->ctxpopup_show)
195      wd->ctxpopup_show = EINA_FALSE;
196    evas_object_hide(wd->ctxpopup);
197 }
198
199 static void
200 _ctxpopup_dismissed_cb(void *data, Evas_Object *obj __UNUSED__,
201                        void *event_info __UNUSED__)
202 {
203    Widget_Data *wd = elm_widget_data_get(data);
204
205    if (!wd || !wd->base) return ;
206
207    Evas_Object *disk = elm_ctxpopup_content_unset(wd->ctxpopup);
208    if (disk) evas_object_del(disk);
209    if (wd->ctxpopup_show)
210      wd->ctxpopup_show = EINA_FALSE;
211
212    switch (wd->date_focusedpart)
213      {
214       case ENTRY_YEAR:
215         edje_object_signal_emit(wd->base, "elm,state,year,focus,out", "elm");
216         break;
217       case ENTRY_MON:
218         edje_object_signal_emit(wd->base, "elm,state,month,focus,out", "elm");
219         break;
220       case ENTRY_DAY:
221         edje_object_signal_emit(wd->base, "elm,state,day,focus,out", "elm");
222         break;
223       case ENTRY_HOUR:
224         edje_object_signal_emit(wd->base, "elm,state,hour,focus,out", "elm");
225         break;
226       case ENTRY_MIN:
227         edje_object_signal_emit(wd->base, "elm,state,min,focus,out", "elm");
228         break;
229      }
230 }
231
232 static void
233 _ampm_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
234                  void *event_info __UNUSED__)
235 {
236    Widget_Data *wd = elm_widget_data_get(data);
237    char *str;
238
239    if (!wd || !wd->base) return ;
240
241    wd->pm = !wd->pm;
242    if (wd->pm)
243      {
244    str = _get_i18n_string(data, PM_STR);
245    if (str)
246      {
247          elm_object_text_set(wd->time_ampm, str);
248         free(str);
249      }
250         wd->hour += HOUR_12H_MAXIMUM;
251      }
252    else
253      {
254    str = _get_i18n_string(data, AM_STR);
255    if (str)
256      {
257          elm_object_text_set(wd->time_ampm, str);
258         free(str);
259      }
260         wd->hour -= HOUR_12H_MAXIMUM;
261      }
262    evas_object_smart_callback_call(data, "changed", NULL);
263 }
264
265 static void
266 _signal_rect_mouse_down(void *data, Evas_Object *obj __UNUSED__,
267                         const char *emission __UNUSED__, const char *source)
268 {
269    Widget_Data *wd = elm_widget_data_get(data);
270
271    if (!wd) return;
272
273    if (!strcmp(source, "elm.rect.date.year.over"))
274       wd->date_focusedpart = ENTRY_YEAR;
275    else if (!strcmp(source, "elm.rect.date.month.over"))
276       wd->date_focusedpart = ENTRY_MON;
277    else if (!strcmp(source, "elm.rect.date.day.over"))
278       wd->date_focusedpart = ENTRY_DAY;
279    else if (!strcmp(source, "elm.rect.time.hour.over"))
280       wd->date_focusedpart = ENTRY_HOUR;
281    else if (!strcmp(source, "elm.rect.time.min.over"))
282      wd->date_focusedpart = ENTRY_MIN;
283
284    _datefield_focus_set(data);
285 }
286
287 static void
288 _diskselector_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
289 {
290     const char *label = elm_diskselector_item_label_get(
291                         (Elm_Diskselector_Item *) event_info);
292     Widget_Data *wd = elm_widget_data_get(data);
293     int i=0, mon = 0, hour =0;
294
295     if (!wd || !wd->base) return;
296
297     if (label)
298       {
299         if ((wd->date_focusedpart == ENTRY_YEAR) && (wd->year!=atoi(label)))
300           {
301              wd->year = _check_date_boundary(data, atoi(label), ENTRY_YEAR);
302              edje_object_signal_emit(wd->base,"elm,state,year,focus,out","elm");
303              _date_update(data);
304           }
305         else if (wd->date_focusedpart == ENTRY_MON)
306           {
307              char *month_list[] = {
308                              E_("Jan"), E_("Feb"), E_("Mar"), E_("Apr"),
309                              E_("May"), E_("Jun"), E_("Jul"), E_("Aug"),
310                              E_("Sep"), E_("Oct"), E_("Nov"), E_("Dec"),
311              };
312              for (i=0; i <12; i++)
313                {
314                    if (!(strcmp(month_list[i],label)))
315                      mon = _check_date_boundary(data, i+1, ENTRY_MON);
316                }
317              if (wd->month != mon)
318                {
319                   wd->month = mon;
320                   edje_object_signal_emit(wd->base, "elm,state,month,focus,out",
321                                           "elm");
322                   _date_update(data);
323                }
324           }
325         else if ((wd->date_focusedpart == ENTRY_DAY) && (wd->day!=atoi(label)))
326           {
327              wd->day = _check_date_boundary(data, atoi(label), ENTRY_DAY);
328              edje_object_signal_emit(wd->base,"elm,state,day,focus,out", "elm");
329              _date_update(data);
330           }
331         else if (wd->date_focusedpart == ENTRY_HOUR)
332           {
333              if ((wd->hour > 12)&& (wd->time_mode)&& (wd->pm))
334                hour = wd->hour - HOUR_12H_MAXIMUM;
335              else
336                hour = wd->hour;
337              if (hour!=atoi(label))
338                {
339                   wd->hour = atoi(label);
340                   edje_object_signal_emit(wd->base, "elm,state,hour,focus,out",
341                                           "elm");
342                   _date_update(data);
343                }
344           }
345         else if ((wd->date_focusedpart == ENTRY_MIN) && (wd->min!=atoi(label)))
346           {
347              wd->min = atoi(label);
348              edje_object_signal_emit(wd->base,"elm,state,min,focus,out", "elm");
349              _date_update(data);
350           }
351         evas_object_smart_callback_call(data, "changed", NULL);
352      }
353 }
354
355 static void
356 _datefield_focus_set(Evas_Object *data)
357 {
358    Elm_Diskselector_Item *item = NULL;
359    Evas_Object *diskselector, *disk, *edj_part = NULL;
360    const char *item_list[138], *value = NULL;
361    int idx, count_start = 0, count_end = 0;
362    Evas_Coord x, y, w, h;
363
364    Widget_Data *wd = elm_widget_data_get(data);
365    if (!wd || !wd->base) return;
366
367    diskselector = elm_diskselector_add(elm_widget_top_get(data));
368    elm_object_style_set(diskselector, "extended/timepicker");
369    evas_object_size_hint_weight_set(diskselector, EVAS_HINT_EXPAND,
370                                     EVAS_HINT_EXPAND);
371    evas_object_size_hint_align_set(diskselector, EVAS_HINT_FILL,EVAS_HINT_FILL);
372    elm_diskselector_display_item_num_set(diskselector, 8);
373    elm_object_focus_allow_set(diskselector, EINA_FALSE);
374    elm_diskselector_side_label_lenght_set(diskselector, 4);
375
376    char *month_list[] = {
377                E_("Jan"), E_("Feb"), E_("Mar"), E_("Apr"), E_("May"), E_("Jun"),
378                E_("Jul"), E_("Aug"), E_("Sep"), E_("Oct"), E_("Nov"), E_("Dec"),
379     };
380
381    if (wd->date_focusedpart == ENTRY_YEAR)
382      {
383         edje_object_signal_emit(wd->base, "elm,state,year,focus,in", "elm");
384         value = edje_object_part_text_get(wd->base,"elm.text.date.year");
385         edj_part = (Evas_Object *)edje_object_part_object_get(wd->base,
386                                                    "elm.rect.date.year.over");
387         count_start = wd->y_min;
388         if (wd->y_max > wd->y_min)
389            count_end = wd->y_max ;
390         else
391            count_end = 2037 ;
392         //Maximum limit is set for making it compatible with Calendar widget.
393      }
394    else if (wd->date_focusedpart == ENTRY_MON)
395      {
396         edje_object_signal_emit(wd->base, "elm,state,month,focus,in", "elm");
397         value= edje_object_part_text_get(wd->base,"elm.text.date.month");
398         edj_part = (Evas_Object *)edje_object_part_object_get(wd->base,
399                                                    "elm.rect.date.month.over");
400         count_start = 0;
401         count_end = MONTH_MAXIMUM - 1;
402      }
403    else if (wd->date_focusedpart == ENTRY_DAY)
404      {
405         edje_object_signal_emit(wd->base, "elm,state,day,focus,in", "elm");
406         value = edje_object_part_text_get(wd->base,"elm.text.date.day");
407         edj_part =(Evas_Object *) edje_object_part_object_get(wd->base,
408                                                    "elm.rect.date.day.over");
409         count_start = 1;
410         count_end = _maximum_day_get(wd->year, wd->month);
411      }
412    else if (wd->date_focusedpart == ENTRY_HOUR)
413      {
414         edje_object_signal_emit(wd->base, "elm,state,hour,focus,in", "elm");
415         value = edje_object_part_text_get(wd->base,"elm.text.time.hour");
416         edj_part = (Evas_Object *)edje_object_part_object_get(wd->base,
417                                                    "elm.rect.time.hour.over");
418         if (wd->time_mode)
419           {
420              count_start = 1;
421              count_end = HOUR_12H_MAXIMUM ;
422           }
423         else
424           {
425              count_start = 0;
426              count_end = HOUR_24H_MAXIMUM ;
427           }
428      }
429    else if (wd->date_focusedpart == ENTRY_MIN)
430      {
431         edje_object_signal_emit(wd->base, "elm,state,min,focus,in", "elm");
432         value = edje_object_part_text_get(wd->base,"elm.text.time.min");
433         edj_part = (Evas_Object *)edje_object_part_object_get(wd->base,
434                                                    "elm.rect.time.min.over");
435         count_start = 0;
436         count_end = MIN_MAXIMUM;
437      }
438    if (wd->ctxpopup_show) return;
439    for (idx=count_start; idx<= count_end; idx++)
440      {
441         char str[5];
442         if (wd->date_focusedpart == ENTRY_MON)
443           snprintf(str, sizeof(str), month_list[idx]);
444         else
445           snprintf(str, sizeof(str), "%02d", idx);
446         item_list[idx] = eina_stringshare_add(str);
447         if ((value) && (strcmp(value, item_list[idx]) == 0))
448           item = elm_diskselector_item_append(diskselector,item_list[idx],NULL,
449                                               _diskselector_cb, data);
450         else
451           elm_diskselector_item_append(diskselector, item_list[idx], NULL,
452                                        _diskselector_cb, data);
453         eina_stringshare_del(item_list[idx]);
454      }
455    elm_diskselector_round_set(diskselector, EINA_TRUE);
456    if(item != NULL) elm_diskselector_item_selected_set(item, EINA_TRUE);
457
458    disk = elm_ctxpopup_content_unset(wd->ctxpopup);
459    if (disk) evas_object_del(disk);
460    elm_ctxpopup_content_set(wd->ctxpopup, diskselector);
461    evas_object_show(wd->ctxpopup);
462    wd->ctxpopup_show = EINA_TRUE;
463    evas_object_geometry_get(edj_part, &x, &y, &w, &h);
464    evas_object_move(wd->ctxpopup, (x+w/2), (y+h) );
465 }
466
467 static int
468 _maximum_day_get(int year, int month)
469 {
470    int day_of_month = 0;
471    if (year == 0 || month == 0) return 0;
472
473    switch (month)
474      {
475       case 4:
476       case 6:
477       case 9:
478       case 11:
479         day_of_month = 30;
480         break;
481       case 2:
482         {
483            if ((!(year % 4) && (year % 100)) || !(year % 400))
484              day_of_month = 29;
485            else
486              day_of_month = 28;
487         }
488         break;
489       default:
490         day_of_month = 31;
491         break;
492      }
493
494    return day_of_month;
495 }
496
497 static int
498 _check_date_boundary(Evas_Object *obj, int num, int flag)
499 {
500    Widget_Data *wd = elm_widget_data_get(obj);
501    if (flag == ENTRY_YEAR)
502      {
503         if ((num > wd->y_max)&&(wd->y_max > wd->y_min)) num = wd->y_max;
504         else if (num < wd->y_min) num = wd->y_min;
505         return num;
506      }
507
508    else if (flag == ENTRY_MON)
509      {
510         if (wd->year == wd->y_max && num > wd->m_max) num = wd->m_max;
511         else if (wd->year == wd->y_min && num < wd->m_min) num = wd->m_min;
512         else if (num > MONTH_MAXIMUM) num = MONTH_MAXIMUM;
513         else if (num <= 0) num = 1;
514         return num;
515      }
516
517    else if (flag == ENTRY_DAY)
518      {
519         int day_of_month = _maximum_day_get(wd->year, wd->month);
520         if (wd->year == wd->y_max && wd->month == wd->m_max && num > wd->d_max)
521           num = wd->d_max;
522         else if (wd->year == wd->y_min && wd->month == wd->m_min
523                  && num < wd->d_min) num = wd->d_min;
524         else if (num > day_of_month) num = day_of_month;
525         else if (num <= 0) num = 1;
526         return num;
527      }
528    return num;
529 }
530
531 static char*
532 _get_i18n_string(Evas_Object *obj, nl_item item)
533 {
534    Widget_Data *wd = elm_widget_data_get(obj);
535    const char *fmt;
536    char *str = NULL;
537    int i = 0, j = 0;
538
539    if (!wd) return NULL;
540
541    fmt = nl_langinfo(item);
542    if (!fmt) return NULL;
543
544    switch (item)
545      {
546       case D_FMT:
547     str = calloc(7, sizeof(char));
548     while (fmt[i])
549       {
550          if (fmt[i] == '%' && fmt[i+1])
551       {
552          i++;
553          switch (fmt[i])
554            {
555             case 'Y': case 'M': case 'D': case 'y': case 'm': case 'd':
556           str[j++] = tolower(fmt[i]);
557           str[j++] = tolower(fmt[i]);
558           break;
559            }
560       }
561          i++;
562       }
563     return str;
564       case AM_STR:
565       case PM_STR:
566     if (strlen(fmt) > 0)
567       {
568          str = calloc(strlen(fmt)+1, sizeof(char));
569          strcpy(str, fmt);
570       }
571     else
572       {
573          str = calloc(3, sizeof(char));
574          if (item == AM_STR) strcpy(str, "AM");
575          else if (item == PM_STR) strcpy(str, "PM");
576       }
577     return str;
578       case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5:
579       case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10:
580       case ABMON_11: case ABMON_12:
581     str = calloc(strlen(fmt)+1, sizeof(char));
582     while (fmt[i])
583       {
584          str[j++] = fmt[i];
585          if (fmt[i] >= '1' && fmt[i] <= '9')
586       {
587          if (fmt[i+1] >= '1' && fmt[i+1] <= '9')
588            str[j] = fmt[i+1];
589          break;
590       }
591          i++;
592       }
593     return str;
594      }
595    return NULL;
596 }
597
598 static void
599 _date_update(Evas_Object *obj)
600 {
601    Widget_Data *wd = elm_widget_data_get(obj);
602    Evas_Object *diskselector;
603    char str[YEAR_MAX_LENGTH+1] = {0,};
604    char *i18n_str;
605
606    if (!wd || !wd->base) return;
607
608    sprintf(str, "%d", wd->year);
609    edje_object_part_text_set(wd->base, "elm.text.date.year", str);
610
611    i18n_str = _get_i18n_string(obj, ABMON_1+wd->month-1);
612    if (i18n_str)
613      {
614         edje_object_part_text_set(wd->base, "elm.text.date.month", i18n_str);
615         free(i18n_str);
616      }
617
618    sprintf(str, "%02d", wd->day);
619    edje_object_part_text_set(wd->base, "elm.text.date.day", str);
620
621    if (!wd->time_mode) //24 mode
622      sprintf(str, "%02d", wd->hour);
623    else
624      {
625         if (wd->hour >= HOUR_12H_MAXIMUM)
626           {
627              wd->pm = EINA_TRUE;
628              i18n_str = _get_i18n_string(obj, PM_STR);
629              if ((i18n_str)&&(wd->time_ampm))
630                {
631                   elm_object_text_set(wd->time_ampm, i18n_str);
632                   free(i18n_str);
633                }
634           }
635         else
636           {
637              wd->pm = EINA_FALSE;
638              i18n_str = _get_i18n_string(obj, AM_STR);
639              if ((i18n_str)&&(wd->time_ampm))
640                {
641                   elm_object_text_set(wd->time_ampm, i18n_str);
642                   free(i18n_str);
643                }
644           }
645
646         if (wd->hour > HOUR_12H_MAXIMUM)
647           sprintf(str, "%02d", wd->hour - HOUR_12H_MAXIMUM);
648         else if (wd->hour == 0)
649           sprintf(str, "%02d", HOUR_12H_MAXIMUM);
650         else
651           sprintf(str, "%02d", wd->hour);
652      }
653    edje_object_part_text_set(wd->base, "elm.text.time.hour", str);
654    sprintf(str, "%02d", wd->min);
655    edje_object_part_text_set(wd->base, "elm.text.time.min", str);
656
657    diskselector = elm_ctxpopup_content_unset(wd->ctxpopup);
658    if (diskselector) evas_object_del(diskselector);
659    evas_object_hide(wd->ctxpopup);
660    if (wd->ctxpopup_show)
661      wd->ctxpopup_show = EINA_FALSE;
662 }
663
664
665 /**
666  * Add a new datefield object
667  * The date format and strings are based on current locale
668  *
669  * @param parent The parent object
670  * @return The new object or NULL if it cannot be created
671  *
672  * @ingroup Datefield
673  */
674 EAPI Evas_Object *
675 elm_datefield_add(Evas_Object *parent)
676 {
677    Evas_Object *obj;
678    Evas *e;
679    char buf[4096];
680    Widget_Data *wd;
681
682    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
683
684    ELM_SET_WIDTYPE(widtype, "datefield");
685    elm_widget_type_set(obj, "datefield");
686    elm_widget_sub_object_add(parent, obj);
687    elm_widget_data_set(obj, wd);
688    elm_widget_del_hook_set(obj, _del_hook);
689    elm_widget_theme_hook_set(obj, _theme_hook);
690    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
691    elm_widget_can_focus_set(obj, EINA_TRUE);
692
693    wd->base = edje_object_add(e);
694    elm_widget_resize_object_set(obj, wd->base);
695    edje_object_signal_callback_add(wd->base, "mouse,down,1",
696                     "elm.rect.date.year.over", _signal_rect_mouse_down, obj);
697    edje_object_signal_callback_add(wd->base, "mouse,down,1",
698                     "elm.rect.date.month.over", _signal_rect_mouse_down, obj);
699    edje_object_signal_callback_add(wd->base, "mouse,down,1",
700                     "elm.rect.date.day.over", _signal_rect_mouse_down, obj);
701
702    edje_object_signal_callback_add(wd->base, "mouse,down,1",
703                     "elm.rect.time.hour.over", _signal_rect_mouse_down, obj);
704    edje_object_signal_callback_add(wd->base, "mouse,down,1",
705                      "elm.rect.time.min.over", _signal_rect_mouse_down, obj);
706
707    wd->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj));
708    snprintf(buf,sizeof(buf),"extended/timepicker/%s",elm_widget_style_get(obj));
709    elm_object_style_set(wd->ctxpopup, buf);
710    elm_ctxpopup_horizontal_set(wd->ctxpopup, EINA_TRUE);
711    elm_ctxpopup_direction_priority_set(wd->ctxpopup,ELM_CTXPOPUP_DIRECTION_DOWN,
712                ELM_CTXPOPUP_DIRECTION_UP,ELM_CTXPOPUP_DIRECTION_LEFT,
713                ELM_CTXPOPUP_DIRECTION_RIGHT);
714    evas_object_size_hint_weight_set(wd->ctxpopup, EVAS_HINT_EXPAND,
715                                     EVAS_HINT_EXPAND);
716    evas_object_size_hint_align_set(wd->ctxpopup, EVAS_HINT_FILL,EVAS_HINT_FILL);
717    elm_object_focus_allow_set(wd->ctxpopup, EINA_FALSE);
718    evas_object_smart_callback_add(wd->ctxpopup, "dismissed",
719                                   _ctxpopup_dismissed_cb, obj);
720    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
721                                   _datefield_resize_cb, obj);
722
723    wd->y_min = 1900;
724    wd->m_min = 1;
725    wd->d_min = 1;
726    wd->y_max = -1;
727    wd->m_max = 12;
728    wd->d_max = 31;
729    wd->year = wd->y_min;
730    wd->month = 1;
731    wd->day = 1;
732    wd->ctxpopup_show = EINA_FALSE;
733
734    wd->layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
735    wd->time_mode = EINA_TRUE;
736
737    _theme_hook(obj);
738
739    return obj;
740 }
741
742 /**
743  * set layout for the datefield
744  *
745  * @param obj The datefield object
746  * @param layout set layout for date/time/dateandtime
747  * (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
748  *
749  * @ingroup Datefield
750  */
751 EAPI void
752 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
753 {
754    ELM_CHECK_WIDTYPE(obj, widtype);
755    Widget_Data *wd = elm_widget_data_get(obj);
756
757    if (!wd) return;
758    if (layout > ELM_DATEFIELD_LAYOUT_DATEANDTIME) return;
759
760    if (wd->layout != layout)
761      {
762         if (wd->time_ampm)
763           {
764              edje_object_part_unswallow(wd->base,wd->time_ampm);
765              evas_object_del(wd->time_ampm);
766              wd->time_ampm = NULL;
767           }
768         wd->layout = layout;
769         _theme_hook(obj);
770      }
771    return;
772 }
773
774 /**
775  * get layout of the datefield
776  *
777  * @param obj The datefield object
778  * @return layout of the datefield
779  *
780  * @ingroup Datefield
781  */
782 EAPI Elm_Datefield_Layout
783 elm_datefield_layout_get(const Evas_Object *obj)
784 {
785    ELM_CHECK_WIDTYPE(obj, widtype) 0;
786    Widget_Data *wd = elm_widget_data_get(obj);
787
788    if (!wd) return 0;
789
790    return wd->layout;
791 }
792
793 /**
794  * Set selected date of the datefield
795  *
796  * @param obj The datefield object
797  * @param year The year to set
798  * @param month The month to set
799  * @param day The day to set
800  * @param hour The hours to set (24hour mode - 0~23)
801  * @param min The minutes to set (0~59)
802  *
803  * @ingroup Datefield
804  */
805 EAPI void
806 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour,
807                        int min)
808 {
809    ELM_CHECK_WIDTYPE(obj, widtype);
810    Widget_Data *wd = elm_widget_data_get(obj);
811
812    if (!wd) return;
813
814    wd->year = _check_date_boundary(obj, year, ENTRY_YEAR);
815    wd->month = _check_date_boundary(obj, month, ENTRY_MON);
816    wd->day = _check_date_boundary(obj, day, ENTRY_DAY);
817
818    if (hour > HOUR_24H_MAXIMUM) wd->hour = HOUR_24H_MAXIMUM;
819    else if (hour < 0) wd->hour = 0;
820    else wd->hour = hour;
821
822    if (min > MIN_MAXIMUM) wd->min = MIN_MAXIMUM;
823    else if (min < 0) wd->min = 0;
824    else wd->min = min;
825
826    _date_update(obj);
827 }
828
829 /**
830  * Get selected date of the datefield
831  *
832  * @param obj The datefield object
833  * @param year The pointer to the variable get the selected year
834  * @param month The pointer to the variable get the selected month
835  * @param day The pointer to the variable get the selected day
836  * @param hour The pointer to the variable get the selected hour (24hour mode)
837  * @param hour The pointer to the variable get the selected min
838  *
839  * @ingroup Datefield
840  */
841 EAPI void
842 elm_datefield_date_get(const Evas_Object *obj, int *year, int *month, int *day,
843                        int *hour, int *min)
844 {
845    ELM_CHECK_WIDTYPE(obj, widtype);
846    Widget_Data *wd = elm_widget_data_get(obj);
847
848    if (!wd) return;
849
850    if (year)
851      *year = wd->year;
852    if (month)
853      *month = wd->month;
854    if (day)
855      *day = wd->day;
856    if (hour)
857      *hour = wd->hour;
858    if (min)
859      *min = wd->min;
860 }
861
862 /**
863  * Set upper boundary of the datefield
864  *
865  * @param obj The datefield object
866  * @param year The year to set
867  * @param month The month to set
868  * @param day The day to set
869  * @return TRUE/FALSE
870  *
871  * @ingroup Datefield
872  */
873 EAPI Eina_Bool
874 elm_datefield_date_max_set(Evas_Object *obj, int year, int month, int day)
875 {
876    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
877    Widget_Data *wd = elm_widget_data_get(obj);
878    int day_of_month;
879    Eina_Bool update = EINA_FALSE;
880
881    if (!wd) return EINA_FALSE;
882    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
883    day_of_month = _maximum_day_get(year, month);
884    if (day < 1 || day > day_of_month) return EINA_FALSE;
885
886    wd->y_max = year;
887    wd->m_max = month;
888    wd->d_max = day;
889
890    if (wd->year > wd->y_max)
891      {
892         wd->year = wd->y_max;
893         update = EINA_TRUE;
894      }
895    if (wd->year == wd->y_max && wd->month > wd->m_max)
896      {
897         wd->month = wd->m_max;
898         update = EINA_TRUE;
899      }
900    if (wd->year == wd->y_max && wd->month == wd->m_max && wd->day > wd->d_max)
901      {
902         wd->day = wd->d_max;
903         update = EINA_TRUE;
904      }
905
906    if (update) _date_update(obj);
907    return EINA_TRUE;
908 }
909
910 /**
911  * Get upper boundary of the datefield
912  *
913  * @param obj The datefield object
914  * @param year The pointer to the variable get the maximum year
915  * @param month The pointer to the variable get the maximum month
916  * @param day The pointer to the variable get the maximum day
917  *
918  * @ingroup Datefield
919  */
920 EAPI void
921 elm_datefield_date_max_get(const Evas_Object *obj, int *year, int *month,
922                            int *day)
923 {
924    ELM_CHECK_WIDTYPE(obj, widtype);
925    Widget_Data *wd = elm_widget_data_get(obj);
926
927    if (!wd) return;
928
929    if (year)
930      *year = wd->y_max;
931    if (month)
932      *month = wd->m_max;
933    if (day)
934      *day = wd->d_max;
935 }
936
937 /**
938  * Set lower boundary of the datefield
939  *
940  * @param obj The datefield object
941  * @param year The year to set
942  * @param month The month to set
943  * @param day The day to set
944  * @return TRUE/FALSE
945  *
946  * @ingroup Datepicker
947  */
948 EAPI Eina_Bool
949 elm_datefield_date_min_set(Evas_Object *obj, int year, int month, int day)
950 {
951    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
952    Widget_Data *wd = elm_widget_data_get(obj);
953    int day_of_month;
954    Eina_Bool update = EINA_FALSE;
955
956    if (!wd) return EINA_FALSE;
957    if (month < 1 || month > MONTH_MAXIMUM) return EINA_FALSE;
958    day_of_month = _maximum_day_get(year, month);
959    if (day < 1 || day > day_of_month) return EINA_FALSE;
960
961    wd->y_min = year;
962    wd->m_min = month;
963    wd->d_min = day;
964
965    if (wd->year < wd->y_min)
966      {
967         wd->year = wd->y_min;
968         update = EINA_TRUE;
969      }
970    if (wd->year == wd->y_min && wd->month < wd->m_min)
971      {
972         wd->month = wd->m_min;
973         update = EINA_TRUE;
974      }
975    if (wd->year == wd->y_min && wd->month == wd->m_min && wd->day < wd->d_min)
976      {
977         wd->day = wd->d_min;
978         update = EINA_TRUE;
979      }
980
981    if (update) _date_update(obj);
982    return EINA_TRUE;
983 }
984
985 /**
986  * Get lower boundary of the datefield
987  *
988  * @param obj The datefield object
989  * @param year The pointer to the variable get the maximum year
990  * @param month The pointer to the variable get the maximum month
991  * @param day The pointer to the variable get the maximum day
992  *
993  * @ingroup Datefield
994  */
995 EAPI void
996 elm_datefield_date_min_get(const Evas_Object *obj, int *year, int *month,
997                            int *day)
998 {
999    ELM_CHECK_WIDTYPE(obj, widtype);
1000    Widget_Data *wd = elm_widget_data_get(obj);
1001
1002    if (!wd) return;
1003
1004    if (year)
1005      *year = wd->y_min;
1006    if (month)
1007      *month = wd->m_min;
1008    if (day)
1009      *day = wd->d_min;
1010 }
1011
1012 /**
1013  * Set if the datefield show hours in military or am/pm mode
1014  *
1015  * @param obj The datefield object
1016  * @param mode option for the hours mode. If true, it is shown as 12h mode,
1017  * if false, it is shown as 24h mode. Default value is true
1018  *
1019  * @ingroup Datefield
1020  */
1021 EAPI void
1022 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
1023 {
1024    ELM_CHECK_WIDTYPE(obj, widtype);
1025    Widget_Data *wd = elm_widget_data_get(obj);
1026
1027    if (!wd) return;
1028
1029    if (wd->time_mode != mode)
1030      {
1031         wd->time_mode = mode;
1032         if (!wd->time_mode)
1033           edje_object_signal_emit(wd->base, "elm,state,mode,24h","elm");
1034         else
1035           edje_object_signal_emit(wd->base, "elm,state,mode,12h", "elm");
1036         edje_object_message_signal_process(wd->base);
1037         _date_update(obj);
1038      }
1039 }
1040
1041 /**
1042  * get time mode of the datefield
1043  *
1044  * @param obj The datefield object
1045  * @return time mode (EINA_TRUE: 12hour mode / EINA_FALSE: 24hour mode)
1046  *
1047  * @ingroup Datefield
1048  */
1049 EAPI Eina_Bool
1050 elm_datefield_time_mode_get(const Evas_Object *obj)
1051 {
1052    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1053    Widget_Data *wd = elm_widget_data_get(obj);
1054
1055    if (!wd) return EINA_FALSE;
1056
1057    return wd->time_mode;
1058 }
1059
1060 /**
1061  * Set date format of datefield
1062  *
1063  * @param obj The datefield object
1064  * @param fmt The date format, ex) yymmdd. Default value is mmddyy.
1065  *
1066  * @ingroup Datefield
1067  */
1068 EAPI void
1069 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
1070 {
1071    ELM_CHECK_WIDTYPE(obj, widtype);
1072    Widget_Data *wd = elm_widget_data_get(obj);
1073    char sig[32] = "elm,state,format,";
1074    int i = 0, j;
1075
1076    if (!wd || !fmt) return;
1077
1078    j = strlen(sig);
1079    while (j < 31 )
1080      {
1081         sig[j++] = tolower(fmt[i++]);
1082      }
1083    if (j < 32) sig[j] = '\0';
1084    edje_object_signal_emit(wd->base, sig, "elm");
1085    edje_object_message_signal_process(wd->base);
1086
1087    if (strstr(sig, "yymmdd")) wd->date_format = DATE_FORMAT_YYMMDD;
1088    else if (strstr(sig, "yyddmm")) wd->date_format = DATE_FORMAT_YYDDMM;
1089    else if (strstr(sig, "mmyydd")) wd->date_format = DATE_FORMAT_MMYYDD;
1090    else if (strstr(sig, "mmddyy")) wd->date_format = DATE_FORMAT_MMDDYY;
1091    else if (strstr(sig, "ddyymm")) wd->date_format = DATE_FORMAT_DDYYMM;
1092    else if (strstr(sig, "ddmmyy")) wd->date_format = DATE_FORMAT_DDMMYY;
1093    wd->format_exists = EINA_TRUE;
1094 }
1095
1096 /**
1097  * get date format of the datefield
1098  *
1099  * @param obj The datefield object
1100  * @return date format string. ex) yymmdd
1101  *
1102  * @ingroup Datefield
1103  */
1104 EAPI const char *
1105 elm_datefield_date_format_get(const Evas_Object *obj)
1106 {
1107    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1108    Widget_Data *wd = elm_widget_data_get(obj);
1109
1110    switch (wd->date_format)
1111      {
1112       case DATE_FORMAT_YYMMDD: return "yymmdd";
1113       case DATE_FORMAT_YYDDMM: return "yyddmm";
1114       case DATE_FORMAT_MMYYDD: return "mmyydd";
1115       case DATE_FORMAT_MMDDYY: return "mmddyy";
1116       case DATE_FORMAT_DDYYMM: return "ddyymm";
1117       case DATE_FORMAT_DDMMYY: return "ddmmyy";
1118       default: return NULL;
1119      }
1120 }
1121
1122 /**
1123  * Add a callback function for input panel state
1124  *
1125  * @param obj The datefield object
1126  * @param func The function to be called when the event is triggered
1127  * (value will be the Ecore_IMF_Input_Panel_State)
1128  * @param data The data pointer to be passed to @p func
1129  *
1130  * @ingroup Datefield
1131  */
1132 EAPI void
1133 elm_datefield_input_panel_state_callback_add(Evas_Object *obj,
1134           void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value),
1135           void *data)
1136 {
1137    // This API will be no more in use after the redesigning of datefield widget
1138    //with ctxpopup & diskselector instead of using entry objects edited by Vkpd.
1139    // API will be deprecated soon.
1140    printf( "#####\nWARNING: API elm_datefield_input_panel_state_callback_add "
1141             "will be deprecated soon \n#####\n");
1142 }
1143
1144 /**
1145  * Delete a callback function for input panel state
1146  *
1147  * @param obj The datefield object
1148  * @param func The function to be called when the event is triggered
1149  *
1150  * @ingroup Datefield
1151  */
1152 EAPI void
1153 elm_datefield_input_panel_state_callback_del(Evas_Object *obj,
1154           void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value))
1155 {
1156    // This API will be no more in use after the redesigning of datefield widget
1157    //with ctxpopup & diskselector instead of using entry objects edited by Vkpd.
1158    // API will be deprecated soon.
1159    printf( "#####\nWARNING: API elm_datefield_input_panel_state_callback_del"
1160             "will be deprecated soon \n#####\n");
1161 }