13013ab0889067260938f53d3a3e2bc01e49600a
[framework/uifw/elementary.git] / src / lib / elm_datefield.c
1 #include <locale.h>
2 #include <Elementary.h>
3 #include "elm_priv.h"
4
5 /**
6  * @defgroup Datefield Datefield
7  * @ingroup Elementary
8  *
9  * This is a date edit field. it is used to input date and time using
10  * diskselector integrated ctxpopup.
11  *
12  * Datefield Format can be like "%b %d, %Y %I : %M %p".
13  * Maximum allowed format length is 32 chars.
14  * Format can include separators for each individual datefield item.
15  * Each separator can be a maximum of 6 UTF-8 bytes.
16  * Space is also taken as a separator.
17  * Following are the allowed set of format specifiers for each datefield item.
18  * These specifiers can be arranged at any order as per user requirement and
19  * their value will be replaced in the format as mentioned below.
20  * %Y : The year as a decimal number including the century.
21  * %y : The year as a decimal number without a century (range 00 to 99)
22  * %m : The month as a decimal number (range 01 to 12).
23  * %b : The abbreviated month name according to the current locale.
24  * %B : The full month name according to the current locale.
25  * %d : The day of the month as a decimal number (range 01 to 31).
26  * %I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
27  * %H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
28  * %k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
29  *      digits are preceded by a blank.
30  * %l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
31  *      digits are preceded by a blank.
32  * %M : The minute as a decimal number (range 00 to 59).
33  * %p : Either 'AM' or 'PM' according to the given time value, or the
34  *      corresponding strings for the current locale. Noon is treated as 'PM'
35  *      and midnight as 'AM'
36  * %P : Like %p but in lowercase: 'am' or 'pm' or a corresponding string for
37  *      the current locale.
38  * For more reference, see the below link:
39  * http://www.gnu.org/s/hello/manual/libc.html#Formatting-Calendar-Time
40  * Default format is taken as per the system display language and Region format.
41  *
42  */
43
44 typedef struct _Widget_Data Widget_Data;
45
46 #define DATEFIELD_TYPE_COUNT        6
47 #define BUFFER_SIZE                 64
48 #define MAX_FORMAT_LEN              32
49 #define MAX_SEPARATOR_LEN           6
50 #define MAX_ITEM_FORMAT_LEN         3
51 #define DISKSELECTOR_ITEMS_NUM_MIN  4
52
53 // Interface between EDC & C code. Item names & signal names.
54 // Values 0 to 6 are valid range, can be substituted for %d.
55 #define EDC_DATEFIELD_ENABLE_SIG_STR        "elm,state,enabled"
56 #define EDC_DATEFIELD_DISABLE_SIG_STR       "elm,state,disabled"
57 #define EDC_DATEFIELD_FOCUSIN_SIG_STR       "elm,action,focus"
58 #define EDC_DATEFIELD_FOCUSOUT_SIG_STR      "elm,action,unfocus"
59 #define EDC_PART_ITEM_STR                   "item%d"
60 #define EDC_PART_SEPARATOR_STR              "separator%d"
61 #define EDC_PART_ITEM_OVER_STR              "item%d.over"
62 #define EDC_PART_ITEM_ENABLE_SIG_STR        "item%d,enable"
63 #define EDC_PART_ITEM_DISABLE_SIG_STR       "item%d,disable"
64 #define EDC_PART_ITEM_FOCUSIN_SIG_STR       "item%d,focus,in"
65 #define EDC_PART_ITEM_FOCUSOUT_SIG_STR      "item%d,focus,out"
66 #define EDC_PART_ITEM_STYLE_DEFAULT_SIG_STR "item%d,style,default"
67 #define EDC_PART_ITEM_STYLE_AMPM_SIG_STR    "item%d,style,ampm"
68
69 #define DEFAULT_FORMAT "%b %d, %Y %I : %M %p"
70
71 typedef struct _Format_Map
72 {
73    Elm_Datefield_ItemType type;
74    char fmt_char[5];
75    int def_min;
76    int def_max;
77 }Format_Map;
78
79 static const Format_Map mapping[DATEFIELD_TYPE_COUNT] = {
80    { ELM_DATEFIELD_YEAR,   "Yy",    70, 137 },
81    { ELM_DATEFIELD_MONTH,  "mbB",   0,  11  },
82    { ELM_DATEFIELD_DATE,   "d",     1,  31  },
83    { ELM_DATEFIELD_HOUR,   "IHkl",  0,  23  },
84    { ELM_DATEFIELD_MINUTE, "M",     0,  59  },
85    { ELM_DATEFIELD_AMPM,   "pP",    0,  1   }
86 };
87
88 static int _days_in_month[12] = { 31, 28, 31, 30, 31, 30,
89                                   31, 31, 30, 31, 30, 31 };
90
91 typedef enum _Elm_Datefield_HourType
92   {
93      ELM_DATEFIELD_HOUR_12 = 1000,
94      ELM_DATEFIELD_HOUR_24,
95      ELM_DATEFIELD_HOUR_NA
96   } Elm_Datefield_HourType;
97
98
99 typedef struct _Datefield_Item
100 {
101    char fmt[MAX_ITEM_FORMAT_LEN];
102    Elm_Datefield_ItemType type;
103    Elm_Datefield_HourType hour_type;
104    const char *content; //string to be displayed
105    const char *separator;
106    int location; //location of the item as per the current format
107    int *value;
108    int min, max;
109    int default_min, default_max;
110    Eina_Bool fmt_exist:1; //if item format is present or not
111    Eina_Bool enabled:1; //if item is to be shown or not
112    Eina_Bool abs_min:1;
113    Eina_Bool abs_max:1;
114 } Datefield_Item;
115
116 struct _Widget_Data
117 {
118    Evas_Object *base;
119    struct tm *time;
120    int ampm;
121    Datefield_Item *item_list; //Fixed set of items, so no Eina list.
122    Evas_Object *ctxpopup;
123    Datefield_Item *selected_it;
124    char format[MAX_FORMAT_LEN];
125    Eina_Bool user_format:1; //whether user set format or the default format.
126
127    //////////////////////DEPRECATED//////////////////////
128    unsigned int datefield_layout; // user set layout
129    const char *old_style_format; // user set format
130    Eina_Bool time_mode; // current time mode 12hr/24hr
131    //////////////////////////////////////////////////////
132 };
133
134 typedef struct _DiskItem_Data
135 {
136    Evas_Object *datefield;
137    unsigned int sel_item_value;
138 } DiskItem_Data;
139
140 static const char *widtype = NULL;
141
142 static void _del_hook(Evas_Object *obj);
143 static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
144 static void _disable_hook(Evas_Object *obj);
145 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
146 static void _sizing_eval(Evas_Object *obj);
147 static void _theme_hook(Evas_Object *obj);
148 static void _ctxpopup_dismissed_cb(void *data, Evas_Object *obj __UNUSED__,
149                                    void *event_info __UNUSED__);
150 static void _datefield_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj
151                                  __UNUSED__, void *event_info __UNUSED__);
152 static void _datefield_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj
153                                  __UNUSED__, void *event_info __UNUSED__);
154
155 static void _update_items(Evas_Object *obj);
156 static void _field_value_set(Evas_Object * obj, Elm_Datefield_ItemType type,
157                              int value, Eina_Bool adjust_time);
158 static void _diskselector_cb(void *data, Evas_Object *obj __UNUSED__,
159                              void *event_info __UNUSED__);
160 static void _ampm_clicked (void *data);
161 static void _diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__,
162                                        void *event_info __UNUSED__);
163 static void _load_field_options(Evas_Object * data, Evas_Object *diskselector,
164                                 Datefield_Item *it);
165 static void _datefield_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
166                      const char *emission __UNUSED__, const char *source);
167 static void _format_reload(Evas_Object *obj);
168 static void _item_list_init(Evas_Object *obj);
169
170 static const char SIG_CHANGED[] = "changed";
171 static const Evas_Smart_Cb_Description _signals[] = {
172        {SIG_CHANGED, ""},
173        {NULL, NULL}
174 };
175
176 static void
177 _del_hook(Evas_Object *obj)
178 {
179    Widget_Data *wd;
180    Datefield_Item *tmp;
181    unsigned int idx;
182
183    wd = elm_widget_data_get(obj);
184    if (!wd) return;
185    if (wd->time) free(wd->time);
186    for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
187      {
188         tmp = wd->item_list + idx;
189         eina_stringshare_replace(&tmp->content, NULL);
190         eina_stringshare_replace(&tmp->separator, NULL);
191      }
192    if (wd->item_list) free(wd->item_list);
193    evas_object_del(wd->ctxpopup);
194
195    free(wd);
196 }
197
198 static void
199 _disable_hook(Evas_Object *obj)
200 {
201    Widget_Data *wd;
202
203    wd = elm_widget_data_get(obj);
204    if (!wd || !wd->base) return;
205    if (elm_widget_disabled_get(obj))
206      {
207         evas_object_hide(wd->ctxpopup);
208         edje_object_signal_emit(wd->base, EDC_DATEFIELD_DISABLE_SIG_STR,"elm");
209      }
210    else
211      edje_object_signal_emit(wd->base, EDC_DATEFIELD_ENABLE_SIG_STR, "elm");
212 }
213
214 static void
215 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
216 {
217    Widget_Data *wd;
218
219    wd = elm_widget_data_get(obj);
220    if (!wd ) return;
221    if (elm_widget_focus_get(obj))
222       edje_object_signal_emit(wd->base, EDC_DATEFIELD_FOCUSIN_SIG_STR, "elm");
223    else
224       edje_object_signal_emit(wd->base, EDC_DATEFIELD_FOCUSOUT_SIG_STR, "elm");
225 }
226
227 static void
228 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
229 {
230    Widget_Data *wd;
231
232    wd = elm_widget_data_get(obj);
233    if (!wd) return;
234    evas_object_hide(wd->ctxpopup);
235    edje_object_mirrored_set(wd->base, rtl);
236 }
237
238 static void
239 _sizing_eval(Evas_Object *obj)
240 {
241    Widget_Data *wd;
242    Evas_Coord minw = -1, minh = -1;
243
244    wd = elm_widget_data_get(obj);
245    if (!wd || !wd->base) return;
246    edje_object_size_min_calc(wd->base, &minw, &minh);
247    evas_object_size_hint_min_set(obj, minw, minh);
248    evas_object_size_hint_max_set(obj, -1, -1);
249 }
250
251 static void
252 _theme_hook(Evas_Object *obj)
253 {
254    Widget_Data *wd;
255    Datefield_Item *it;
256    char buf[BUFFER_SIZE];
257    unsigned int idx;
258    //Evas_Object *diskselector;
259
260    wd = elm_widget_data_get(obj);
261    if (!wd || !wd->base) return;
262    _elm_theme_object_set(obj, wd->base, "datefield", "base",
263                          elm_widget_style_get(obj));
264    _elm_widget_mirrored_reload(obj);
265    _mirrored_set(obj, elm_widget_mirrored_get(obj));
266
267    snprintf(buf, sizeof(buf), "datefield/%s", elm_object_style_get(obj));
268    elm_object_style_set(wd->ctxpopup, buf);
269    /*//Enabled once elm_object_content_get() API comes to git.
270    if (diskselector = elm_object_content_get(wd->ctxpopup))
271    elm_object_style_set(diskselector, buf);*/
272    edje_object_scale_set(wd->base,elm_widget_scale_get(obj)*_elm_config->scale);
273
274    if (elm_widget_disabled_get(obj))
275      edje_object_signal_emit(wd->base, EDC_DATEFIELD_DISABLE_SIG_STR,"elm");
276    else
277      edje_object_signal_emit(wd->base, EDC_DATEFIELD_ENABLE_SIG_STR, "elm");
278
279    for (idx= 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
280      {
281         it = wd->item_list + idx;
282         if (it->fmt_exist && it->enabled )
283           {
284              snprintf(buf, sizeof(buf), EDC_PART_ITEM_STR, it->location);
285              edje_object_part_text_set(wd->base, buf, it->content);
286              snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, it->location);
287              edje_object_part_text_set(wd->base, buf, it->separator);
288              snprintf(buf, sizeof(buf), EDC_PART_ITEM_ENABLE_SIG_STR,
289                       it->location);
290              edje_object_signal_emit(wd->base, buf, "elm");
291              if (it->type == ELM_DATEFIELD_AMPM)
292                snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_AMPM_SIG_STR,
293                         it->location);
294              else
295                snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_DEFAULT_SIG_STR,
296                         it->location);
297              edje_object_signal_emit(wd->base, buf, "elm");
298           }
299         else
300           {
301              snprintf(buf, sizeof(buf),EDC_PART_ITEM_DISABLE_SIG_STR,
302                       it->location);
303              edje_object_signal_emit(wd->base, buf, "elm");
304           }
305      }
306    edje_object_message_signal_process(wd->base);
307    _sizing_eval(obj);
308 }
309
310 static void
311 _ctxpopup_dismissed_cb(void *data, Evas_Object *obj __UNUSED__,
312                        void *event_info __UNUSED__)
313 {
314    Widget_Data *wd;
315    Evas_Object *diskselector;
316    char buf[BUFFER_SIZE];
317
318    wd = elm_widget_data_get(data);
319    if (!wd || !wd->base) return;
320    diskselector = elm_ctxpopup_content_unset(wd->ctxpopup);
321    if (diskselector) evas_object_del(diskselector);
322
323    if (wd->selected_it)
324      {
325         snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSOUT_SIG_STR,
326                  wd->selected_it->location);
327         edje_object_signal_emit(wd->base, buf, "elm");
328         wd->selected_it = NULL;
329      }
330 }
331
332 static void
333 _datefield_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
334                      void *event_info __UNUSED__)
335 {
336    Widget_Data *wd;
337
338    wd = elm_widget_data_get(data);
339    if (!wd) return;
340    evas_object_hide(wd->ctxpopup);
341 }
342
343 static void
344 _datefield_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
345                      void *event_info __UNUSED__)
346 {
347    Widget_Data *wd;
348
349    wd = elm_widget_data_get(data);
350    if (!wd) return;
351    evas_object_hide(wd->ctxpopup);
352 }
353
354 static void
355 _contextual_field_limit_get(Evas_Object * obj, Datefield_Item * it,
356                 Eina_Bool hr_fmt_check, int *range_min, int *range_max)
357 {
358    Widget_Data *wd;
359    Datefield_Item * tmp;
360    unsigned int idx;
361    int ctx_max;
362    Eina_Bool min_limit = EINA_TRUE;
363    Eina_Bool max_limit = EINA_TRUE;
364
365    wd = elm_widget_data_get(obj);
366    if (!wd || !it) return;
367
368    //Top to down check for current field relative min/max limit
369    if (!it->abs_min || !it->abs_max )
370      {
371         for (idx = ELM_DATEFIELD_YEAR; idx < it->type; idx++)
372           {
373              tmp = wd->item_list + idx;
374              if (max_limit && (*(tmp->value) < tmp->max)) max_limit= EINA_FALSE;
375              if (min_limit && (*(tmp->value) > tmp->min)) min_limit= EINA_FALSE;
376           }
377      }
378
379    if (it->abs_min || min_limit) (*range_min) = it->min;
380    else (*range_min) = it->default_min;
381
382    if (it->abs_max || max_limit) (*range_max) = it->max;
383    else (*range_max) = it->default_max;
384
385    ctx_max = it->default_max;
386    if (it->type == ELM_DATEFIELD_DATE )
387      {
388         ctx_max = _days_in_month[wd->time->tm_mon];
389         // Check for Leap year Feb.
390         if (__isleap((wd->time->tm_year)) && wd->time->tm_mon == 1) ctx_max= 29;
391      }
392    else if (it->type == ELM_DATEFIELD_HOUR  &&  hr_fmt_check &&
393             it->hour_type == ELM_DATEFIELD_HOUR_12 )  ctx_max = 11;
394
395    if (*range_max > ctx_max) *range_max = ctx_max;
396 }
397
398 static void
399 _update_items(Evas_Object *obj)
400 {
401    Widget_Data *wd;
402    Datefield_Item *it;
403    char buf[BUFFER_SIZE];
404    unsigned int idx= 0;
405
406    wd = elm_widget_data_get(obj);
407    if (!wd || !wd->base) return;
408    for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
409      {
410         it = wd->item_list + idx;
411         if ( it->fmt_exist && it->enabled )
412           {
413              strftime(buf, BUFFER_SIZE, it->fmt, wd->time);
414
415              // FIXME: no locale string availble from Libc...
416              if ((!strncmp(buf, "",1)) && (it->type == ELM_DATEFIELD_AMPM))
417                {
418                   if (wd->ampm) strncpy(buf, E_("PM"), BUFFER_SIZE);
419                   else strncpy(buf, E_("AM"), BUFFER_SIZE);
420                }
421              eina_stringshare_replace(&it->content, buf);
422              snprintf(buf, sizeof(buf), EDC_PART_ITEM_STR, it->location);
423              edje_object_part_text_set(wd->base, buf, it->content);
424           }
425      }
426 }
427
428 static void
429 _field_value_set(Evas_Object * obj, Elm_Datefield_ItemType item_type, int value,
430                  Eina_Bool adjust_time)
431 {
432    Widget_Data *wd;
433    Datefield_Item * it;
434    unsigned int idx;
435    int min, max;
436    Eina_Bool value_changed = EINA_FALSE;
437
438    wd = elm_widget_data_get(obj);
439    if (!wd) return;
440
441    if (item_type == ELM_DATEFIELD_AMPM)
442      {
443         if ( value == wd->ampm ) return;
444         item_type = ELM_DATEFIELD_HOUR;
445         value = (wd->time->tm_hour + 12) % 24;
446         adjust_time =  EINA_FALSE;
447      }
448
449    it = wd->item_list + item_type;
450    _contextual_field_limit_get(obj, it, EINA_FALSE, &min, &max);
451
452    //12 hr format & PM then add 12 to value.
453    if (adjust_time && it->type == ELM_DATEFIELD_HOUR &&
454        it->hour_type == ELM_DATEFIELD_HOUR_12 && wd->ampm && value < 12)
455       value += 12;
456
457    if (value < min) value = min;
458    else if (value > max) value = max;
459    if ( *(it->value) == value) return;
460    *(it->value) = value;
461    value_changed = EINA_TRUE;
462
463    //Validate & reset lower order fields
464    for ( idx = item_type+1; idx < DATEFIELD_TYPE_COUNT; idx++ )
465      {
466         it = wd->item_list + idx;
467         _contextual_field_limit_get(obj, it, EINA_FALSE, &min, &max);
468         //Validate current value against context based Min/Max restriction.
469         if (*it->value < min)
470           {
471              *it->value = min;
472              value_changed = EINA_TRUE;
473           }
474         else if (*it->value > max)
475           {
476              *it->value = max;
477              value_changed = EINA_TRUE;
478           }
479      }
480    //update AM/PM state
481    wd->ampm = (wd->time->tm_hour > 11 );
482    _update_items(obj);
483
484    if (value_changed)
485      evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
486 }
487
488 static void
489 _diskselector_cb(void *data, Evas_Object *obj __UNUSED__,
490                  void *event_info __UNUSED__)
491 {
492    DiskItem_Data *cb_data;
493    Widget_Data *wd;
494
495    cb_data = (DiskItem_Data *)data;
496    if (!cb_data) return;
497    wd = elm_widget_data_get(cb_data->datefield);
498    if (!wd ) return;
499
500    _field_value_set(cb_data->datefield, wd->selected_it->type,
501                     cb_data->sel_item_value, EINA_TRUE);
502
503    evas_object_hide(wd->ctxpopup);
504 }
505
506 static void
507 _ampm_clicked (void *data)
508 {
509    Widget_Data *wd;
510    char buf[BUFFER_SIZE];
511
512    wd = elm_widget_data_get(data);
513    if (!wd || !wd->base) return;
514
515    _field_value_set( data, ELM_DATEFIELD_AMPM, !wd->ampm, EINA_FALSE );
516
517    snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSOUT_SIG_STR,
518             wd->selected_it->location);
519    edje_object_signal_emit(wd->base, buf, "elm");
520    wd->selected_it = NULL;
521 }
522
523 static void
524 _diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__,
525                            void *event_info __UNUSED__)
526 {
527    if (data) free(data);
528 }
529 \r
530 static void
531 _load_field_options(Evas_Object * data, Evas_Object *diskselector,
532                     Datefield_Item *it)
533 {
534    Widget_Data *wd;
535    DiskItem_Data *disk_data;
536    Elm_Diskselector_Item *item;
537    int idx, min, max, selected_val;
538    int text_len, max_len = 0;
539    char item_label[BUFFER_SIZE];
540    int cur_val, date_val;
541
542    wd = elm_widget_data_get(data);
543    if (!wd) return;
544
545    cur_val = *(it->value);
546    date_val = wd->time->tm_mday;
547    _contextual_field_limit_get(data, it, EINA_TRUE, &min, &max );
548
549    selected_val = *(it->value);
550    wd->time->tm_mday = 1;
551    // If 12hr format & PM, reduce 12
552    if (it->hour_type == ELM_DATEFIELD_HOUR_12 && wd->ampm) selected_val -= 12;
553
554    for (idx = min; idx <= max; idx++)\r
555      {
556         *(it->value) = idx;
557         strftime(item_label, BUFFER_SIZE, it->fmt, wd->time );
558         text_len = strlen(item_label);
559         if (text_len > max_len ) max_len = text_len; //Store max. label length
560
561         if (idx == selected_val) //Selected Item, dont attach a callback handler
562           {
563              item = elm_diskselector_item_append(diskselector, item_label,
564                                                  NULL, NULL, NULL);
565              elm_diskselector_item_selected_set(item, EINA_TRUE);
566           }
567         else
568           {
569              disk_data = (DiskItem_Data *) malloc (sizeof(DiskItem_Data));
570              disk_data->datefield = data;
571              disk_data->sel_item_value = idx;
572              item = elm_diskselector_item_append(diskselector,
573                                  item_label, NULL, _diskselector_cb, disk_data);
574              elm_diskselector_item_del_cb_set(item, _diskselector_item_free_cb);
575           }
576      }
577    *(it->value) = cur_val;
578    wd->time->tm_mday = date_val;
579    elm_diskselector_side_label_length_set(diskselector, max_len);
580 }
581
582 static void
583 _datefield_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
584                       const char *emission __UNUSED__, const char *source)
585 {
586    Widget_Data *wd = elm_widget_data_get(data);
587    Evas_Object *diskselector;
588    const Evas_Object *edj_part;
589    char buf[BUFFER_SIZE];
590    unsigned int idx = 0, idx1 = 0, display_item_num;
591    Evas_Coord x = 0, y = 0, w = 0, h = 0;
592    Evas_Coord disksel_width;
593
594    if (!wd || !wd->base) return;
595    if (elm_widget_disabled_get(data)) return;
596
597    wd->selected_it = NULL;
598    //Locate the selected Index & Selected Datefield_Item
599    for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
600      {
601         snprintf(buf, sizeof(buf), EDC_PART_ITEM_OVER_STR, idx);
602         if (!strncmp(buf, source, sizeof(buf)))
603           {
604              for (idx1 = 0; idx1 < DATEFIELD_TYPE_COUNT; idx1++ )
605                {
606                  if ((wd->item_list + idx1)->location == (int)idx)
607                    {
608                       wd->selected_it = wd->item_list + idx1;
609                       break;
610                    }
611                }
612              break;
613           }
614      }
615
616    if ( !wd->selected_it || !wd->selected_it->fmt_exist
617                          || !wd->selected_it->enabled ) return;
618    snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSIN_SIG_STR,
619             wd->selected_it->location);
620    edje_object_signal_emit(wd->base, buf, "elm");
621
622    if ( wd->selected_it->type == ELM_DATEFIELD_AMPM )
623      {
624         _ampm_clicked (data);
625         return;
626      }
627
628    //Recreating diskselector everytime due to diskselector behavior
629    diskselector = elm_diskselector_add(elm_widget_top_get(data));
630    snprintf(buf, sizeof(buf), "datefield/%s", elm_object_style_get(data));
631    elm_object_style_set(diskselector, buf);
632
633    //Load the options list
634    _load_field_options(data, diskselector, wd->selected_it);
635
636    elm_ctxpopup_direction_priority_set(wd->ctxpopup, ELM_CTXPOPUP_DIRECTION_DOWN,
637                                        ELM_CTXPOPUP_DIRECTION_UP, -1, -1);
638    elm_object_content_set(wd->ctxpopup, diskselector);
639    snprintf(buf,sizeof(buf), EDC_PART_ITEM_STR, wd->selected_it->location);
640    edj_part = edje_object_part_object_get(wd->base, buf);
641    evas_object_geometry_get(edj_part, &x, &y, &w, &h);
642    evas_object_move(wd->ctxpopup, (x+w/2), (y+h));
643
644    //If the direction of Ctxpopup is upwards, move it to the top of datefield
645    if (elm_ctxpopup_direction_get (wd->ctxpopup) == ELM_CTXPOPUP_DIRECTION_UP)
646      {
647         elm_ctxpopup_direction_priority_set(wd->ctxpopup, ELM_CTXPOPUP_DIRECTION_UP,
648                                             ELM_CTXPOPUP_DIRECTION_DOWN, -1, -1);
649         evas_object_move(wd->ctxpopup, (x+w/2), y);
650      }
651    evas_object_show(wd->ctxpopup);
652
653    evas_object_geometry_get(diskselector, NULL, NULL, &disksel_width, NULL);
654    display_item_num = disksel_width / (w +  elm_finger_size_get());
655    //odd number of items leads to auto selection.
656    //making as event number of item to prevent auto selection.
657    if (display_item_num%2) display_item_num-=1;
658    if (display_item_num < DISKSELECTOR_ITEMS_NUM_MIN)
659      display_item_num = DISKSELECTOR_ITEMS_NUM_MIN;
660
661    elm_diskselector_display_item_num_set(diskselector, display_item_num);
662    elm_diskselector_round_set(diskselector, EINA_TRUE);
663 }
664
665 static unsigned int
666 _parse_format( Evas_Object *obj )
667 {
668    Widget_Data *wd;
669    Datefield_Item *it = NULL;
670    unsigned int len = 0, idx, location = 0;
671    char separator[MAX_SEPARATOR_LEN];
672    char *fmt_ptr;
673    char cur;
674    Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
675              sep_lookup = EINA_FALSE;
676
677    wd = elm_widget_data_get(obj);
678    fmt_ptr = wd->format;
679
680    while ( (cur = *fmt_ptr ) )
681      {
682         if (fmt_parsing)
683           {
684              for ( idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
685                {
686                   if ( strchr( mapping[idx].fmt_char, cur ) )
687                     {
688                        it = wd->item_list + idx;
689                        //Ignore the items already have or disabled
690                        //valid formats, means already parsed & repeated, ignore.
691                        if (!it->enabled || it->location != -1) break;
692                        it->fmt[1] = cur;
693
694                       //set the hour display format 12h/24h
695                        if (it->type == ELM_DATEFIELD_HOUR)
696                          {
697                             if (cur == 'H' || cur == 'k' )
698                               it->hour_type = ELM_DATEFIELD_HOUR_24;
699                             else if (cur == 'I' || cur == 'l' )
700                               it->hour_type = ELM_DATEFIELD_HOUR_12;
701                          }
702                        else it->hour_type = ELM_DATEFIELD_HOUR_NA;
703
704                        it->fmt_exist = EINA_TRUE;
705                        it->location = location++;
706                        fmt_parsing = EINA_FALSE;
707                        sep_lookup = EINA_TRUE;
708                        len = 0;
709                        break;
710                     }
711                }
712           }
713
714         if (cur == '%')
715           {
716              fmt_parsing = EINA_TRUE;
717              sep_parsing = EINA_FALSE;
718              // Set the separator to previous Item
719              separator[len] = 0;
720              if (it) eina_stringshare_replace(&it->separator, separator);
721           }
722         if (sep_parsing && (len < MAX_SEPARATOR_LEN-1)) separator[len++] = cur;
723         if (sep_lookup) sep_parsing = EINA_TRUE;
724         sep_lookup = EINA_FALSE;
725         fmt_ptr++;
726    }
727    // Return the number of valid items parsed.
728    return location;
729 }
730
731 static void
732 _format_reload(Evas_Object *obj)
733 {
734    Widget_Data *wd;
735    Datefield_Item *it;
736    char buf[BUFFER_SIZE];
737    unsigned int idx, location;
738    char *def_fmt;
739
740    wd = elm_widget_data_get(obj);
741    if (!wd) return;
742
743     // fetch the format from locale specific po file.
744    if (!wd->user_format )
745      {
746         def_fmt = E_("DateTimeFormat");
747         if (!strncmp(def_fmt, "DateTimeFormat", sizeof("DateTimeFormat")))
748           strncpy(wd->format, DEFAULT_FORMAT, MAX_FORMAT_LEN );
749         else
750           strncpy(wd->format, def_fmt, MAX_FORMAT_LEN );
751      }
752
753    //reset all the items to disable state
754    for ( idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
755      {
756         it = wd->item_list + idx;
757         eina_stringshare_replace(&it->content, NULL);
758         it->fmt_exist = EINA_FALSE;
759         it->location = -1;
760      }
761    location = _parse_format( obj );
762
763    //assign locations to disabled fields for uniform usage
764    for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++)
765      {
766         it = wd->item_list + idx;
767         if (it->location == -1) it->location = location++;
768
769         if (it->fmt_exist && it->enabled)
770           {
771              snprintf(buf, sizeof(buf), EDC_PART_ITEM_ENABLE_SIG_STR,
772                       it->location);
773              edje_object_signal_emit(wd->base, buf, "elm");
774              if (it->type == ELM_DATEFIELD_AMPM)
775                snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_AMPM_SIG_STR,
776                         it->location);
777              else
778                snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_DEFAULT_SIG_STR,
779                         it->location);
780              edje_object_signal_emit(wd->base, buf, "elm");
781           }
782         else
783           {
784              snprintf(buf, sizeof(buf),EDC_PART_ITEM_DISABLE_SIG_STR,
785                       it->location);
786              edje_object_signal_emit(wd->base, buf, "elm");
787           }
788         snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, it->location+1);
789         edje_object_part_text_set(wd->base, buf, it->separator);
790      }
791    edje_object_message_signal_process(wd->base);
792
793    wd->time_mode = ((wd->item_list + ELM_DATEFIELD_HOUR)->hour_type
794                         == ELM_DATEFIELD_HOUR_12);
795    _update_items(obj);
796 }
797
798 static void
799 _item_list_init(Evas_Object *obj)
800 {
801    Widget_Data *wd;
802    Datefield_Item *it;
803    char buf[BUFFER_SIZE];
804    unsigned int idx;
805    time_t t;
806
807    wd = elm_widget_data_get(obj);
808    if (!wd) return;
809
810    wd->item_list = calloc(1, DATEFIELD_TYPE_COUNT * sizeof(Datefield_Item));
811    wd->time = calloc(1, sizeof(struct tm));
812    t = time(NULL);
813    localtime_r(&t, wd->time);
814
815    (wd->item_list + ELM_DATEFIELD_YEAR)->value = &wd->time->tm_year;
816    (wd->item_list + ELM_DATEFIELD_MONTH)->value = &wd->time->tm_mon;
817    (wd->item_list + ELM_DATEFIELD_DATE)->value = &wd->time->tm_mday;
818    (wd->item_list + ELM_DATEFIELD_HOUR)->value = &wd->time->tm_hour;
819    (wd->item_list + ELM_DATEFIELD_MINUTE)->value = &wd->time->tm_min;
820    (wd->item_list + ELM_DATEFIELD_AMPM)->value = &wd->ampm;
821     wd->ampm = (wd->time->tm_hour > 11 );
822
823    for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++)
824      {
825         it = wd->item_list + idx;
826         it->type = ELM_DATEFIELD_YEAR + idx;
827         it->fmt[0] = '%';
828         it->fmt_exist = EINA_FALSE;
829         it->enabled  = EINA_TRUE;
830         it->min = mapping[idx].def_min;
831         it->default_min = mapping[idx].def_min;
832         it->max = mapping[idx].def_max;
833         it->default_max = mapping[idx].def_max;
834         snprintf(buf, sizeof(buf), EDC_PART_ITEM_OVER_STR, idx);
835         edje_object_signal_callback_add(wd->base, "mouse,clicked,1", buf,
836                                         _datefield_clicked_cb, obj);
837      }
838 }
839
840 /**
841  * @brief Add a new datefield Widget
842  * The date format and strings are based on current locale
843  *
844  * @param[in] parent The parent object
845  * @return The new object or NULL if it cannot be created
846  *
847  * @ingroup Datefield
848  */
849 EAPI Evas_Object *
850 elm_datefield_add(Evas_Object *parent)
851 {
852    Evas_Object *obj;
853    Evas *e;
854    Widget_Data *wd;
855
856    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
857
858    ELM_SET_WIDTYPE(widtype, "datefield");
859    elm_widget_type_set(obj, widtype);
860    elm_widget_sub_object_add(parent, obj);
861    elm_widget_data_set(obj, wd);
862    elm_widget_del_hook_set(obj, _del_hook);
863    elm_widget_theme_hook_set(obj, _theme_hook);
864    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
865    elm_widget_disable_hook_set(obj, _disable_hook);
866    elm_widget_can_focus_set(obj, EINA_TRUE);
867
868    wd->base = edje_object_add(e);
869    elm_widget_resize_object_set(obj, wd->base);
870    _elm_theme_object_set(obj, wd->base, "datefield", "base", "default");
871    evas_object_smart_callbacks_descriptions_set(obj, _signals);
872
873    _item_list_init(obj);
874    _format_reload(obj);
875
876    wd->datefield_layout = ELM_DATEFIELD_LAYOUT_DATEANDTIME;
877    wd->time_mode = EINA_TRUE;
878    wd->old_style_format = "mmddyy";
879
880    wd->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj));
881    elm_object_style_set(wd->ctxpopup, "datefield/default");
882    elm_ctxpopup_horizontal_set(wd->ctxpopup, EINA_TRUE);
883    evas_object_size_hint_weight_set(wd->ctxpopup, EVAS_HINT_EXPAND,
884                                     EVAS_HINT_EXPAND);
885    evas_object_size_hint_align_set(wd->ctxpopup, EVAS_HINT_FILL,EVAS_HINT_FILL);
886    evas_object_smart_callback_add(wd->ctxpopup, "dismissed",
887                                   _ctxpopup_dismissed_cb, obj);
888    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
889                                   _datefield_resize_cb, obj);
890    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOVE,
891                                   _datefield_move_cb, obj);
892    _mirrored_set(obj, elm_widget_mirrored_get(obj));
893
894    return obj;
895 }
896
897 /**
898  * Set the format of datefield. Formats can be like "%b %d, %Y %I : %M %p".
899  * Maximum allowed format length is 32 chars.
900  * Format can include separators for each individual datefield item.
901  * Each separator can be a maximum of 6 UTF-8 bytes.
902  * Space is also taken as a separator.
903  * Following are the allowed set of format specifiers for each datefield item.
904  * These specifiers can be arranged at any order as per user requirement and
905  * their value will be replaced in the format as mentioned below.
906  * %Y : The year as a decimal number including the century.
907  * %y : The year as a decimal number without a century (range 00 to 99)
908  * %m : The month as a decimal number (range 01 to 12).
909  * %b : The abbreviated month name according to the current locale.
910  * %B : The full month name according to the current locale.
911  * %d : The day of the month as a decimal number (range 01 to 31).
912  * %I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
913  * %H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
914  * %k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
915  *      digits are preceded by a blank.
916  * %l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
917  *      digits are preceded by a blank.
918  * %M : The minute as a decimal number (range 00 to 59).
919  * %p : Either 'AM' or 'PM' according to the given time value, or the
920  *      corresponding strings for the current locale. Noon is treated as 'PM'
921  *      and midnight as 'AM'
922  * %P : Like %p but in lowercase: 'am' or 'pm' or a corresponding string for
923  *      the current locale.
924  * Default format is taken as per the system display language and Region format.
925  *
926  * @param[in] obj The datefield object
927  * @param[in] fmt The date format
928  *
929  */
930 EAPI void
931 elm_datefield_format_set(Evas_Object *obj, const char *fmt)
932 {
933    ELM_CHECK_WIDTYPE(obj, widtype);
934    Widget_Data *wd;
935
936    wd = elm_widget_data_get(obj);
937    if (!wd) return;
938
939    if (fmt)
940      {
941         strncpy( wd->format, fmt, MAX_FORMAT_LEN );
942         wd->user_format = EINA_TRUE;
943      }
944    else  wd->user_format = EINA_FALSE;
945
946    _format_reload(obj);
947 }
948
949 /**
950  * Get the format of datefield. Formats can be like "%b %d, %Y %I : %M %p".
951  * Maximum allowed format length is 32 chars.
952  * Format can include separators for each individual datefield item.
953  * Each separator can be a maximum of 6 UTF-8 bytes.
954  * Space is also taken as a separator.
955  * Following are the allowed set of format specifiers for each datefield item.
956  * These specifiers can be arranged at any order as per user requirement and
957  * their value will be replaced in the format as mentioned below.
958  * %Y : The year as a decimal number including the century.
959  * %y : The year as a decimal number without a century (range 00 to 99)
960  * %m : The month as a decimal number (range 01 to 12).
961  * %b : The abbreviated month name according to the current locale.
962  * %B : The full month name according to the current locale.
963  * %d : The day of the month as a decimal number (range 01 to 31).
964  * %I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
965  * %H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
966  * %k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
967  *      digits are preceded by a blank.
968  * %l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
969  *      digits are preceded by a blank.
970  * %M : The minute as a decimal number (range 00 to 59).
971  * %p : Either 'AM' or 'PM' according to the given time value, or the
972  *      corresponding strings for the current locale. Noon is treated as 'PM'
973  *      and midnight as 'AM'
974  * %P : Like %p but in lowercase: 'am' or 'pm' or a corresponding string for
975  *      the current locale.
976  * Default format is taken as per the system display language and Region format.
977  *
978  * @param[in] obj The datefield object
979  * @return date format string. ex) %b %d, %Y %I : %M %p
980  *
981  */
982 EAPI char *
983 elm_datefield_format_get(const Evas_Object *obj)
984 {
985    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
986    Widget_Data *wd = elm_widget_data_get(obj);
987    if (!wd ) return NULL;
988    return strdup(wd->format);
989 }
990
991 /**
992  * @brief Set the selected value of the datefield
993  * Year : years since 1900. Negative value represents year below 1900. (
994  * year value -30 represents 1870). Year default range is from 70 to 137.
995  * Month value range is from 0 to 11
996  * Date value range is from 1 to 31 according to the month value.
997  * The hour value should be set according to 24hr format (0~23)
998  * Minute value range is from 0 to 59.
999  * AM/PM. Value 0 for AM and 1 for PM.
1000  * If the value is beyond the range,
1001  * a) Value is less than Min range value, then Min range value is set.
1002  * b) Greater than Max range value, then Max Range value is set.
1003  * Both Min and Max range of individual fields are bound to the current context.
1004  *
1005  * @param[in] obj The datefield object
1006  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1007  * @param[in] value The data to be set. ex. year/month/date/hour/minute/ampm
1008  *
1009  * @ingroup Datefield
1010  */
1011 EAPI void
1012 elm_datefield_item_value_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1013                              int value)
1014 {
1015    ELM_CHECK_WIDTYPE(obj, widtype);
1016    Widget_Data *wd;
1017    Datefield_Item *it;
1018
1019    wd = elm_widget_data_get(obj);
1020    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1021
1022    it = wd->item_list + itemtype;
1023    _field_value_set(obj, it->type, value, EINA_FALSE);
1024 }
1025
1026 /**
1027  * @brief Get Current value date of the datefield
1028  * Year : years since 1900. Negative value represents year below 1900. (
1029  * year value -30 represents 1870). Year default range is from 70 to 137.
1030  * Month value range is from 0 to 11
1031  * Date value range is from 1 to 31 according to the month value.
1032  * The hour value should be set according to 24hr format (0~23)
1033  * Minute value range is from 0 to 59.
1034  * AM/PM. Value 0 for AM and 1 for PM.
1035  * If the value is beyond the range,
1036  * a) Value is less than Min range value, then Min range value is set.
1037  * b) Greater than Max range value, then Max Range value is set.
1038  * Both Min and Max range of individual fields are bound to the current context.
1039  *
1040  * @param[in] obj The datefield object
1041  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1042  * @return int The value of the field.
1043  *
1044  * @ingroup Datefield
1045  */
1046 EAPI int
1047 elm_datefield_item_value_get(const Evas_Object *obj, Elm_Datefield_ItemType
1048                              itemtype)
1049 {
1050    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1051    Widget_Data *wd;
1052
1053    wd = elm_widget_data_get(obj);
1054    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1055
1056    return (*(wd->item_list + itemtype)->value);
1057 }
1058
1059
1060 /**
1061  * @brief Enable/Disable an item of the datefield
1062  *
1063  * @param[in] obj The datefield object
1064  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1065  * @param[in] enable Item is Enabled or disabled.
1066  *
1067  * @ingroup Datefield
1068  */
1069
1070 EAPI void
1071 elm_datefield_item_enabled_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1072                               Eina_Bool enable)
1073 {
1074    ELM_CHECK_WIDTYPE(obj, widtype);
1075    Widget_Data *wd;
1076    Datefield_Item *it;
1077
1078    wd = elm_widget_data_get(obj);
1079    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1080
1081    it = wd->item_list + itemtype;
1082    if ( it->enabled == enable ) return;
1083    it->enabled = enable;
1084    _format_reload(obj);
1085 }
1086
1087 /**
1088  * @brief Get whether the item is Enabled/Disabled
1089  *
1090  * @param[in] obj The datefield object
1091  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1092  * @return EINA_TRUE = Item is Enabled or EINA_FALSE = disabled.
1093  *
1094  * @ingroup Datefield
1095  */
1096
1097 EAPI Eina_Bool
1098 elm_datefield_item_enabled_get(const Evas_Object *obj, Elm_Datefield_ItemType itemtype)
1099 {
1100    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1101    Widget_Data *wd;
1102    Datefield_Item *it;
1103
1104    wd = elm_widget_data_get(obj);
1105    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1106
1107    it = wd->item_list + itemtype;
1108    return it->enabled;
1109 }
1110
1111 /**
1112  * @brief Get lower boundary of the datefield
1113  * Year : years since 1900. Negative value represents year below 1900. (
1114  * year value -30 represents 1870). Year default range is from 70 to 137.
1115  * Month default value range is from 0 to 11
1116  * Date default value range is from 1 to 31 according to the month value.
1117  * Hour default value will be in terms of 24 hr format (0~23)
1118  * Minute default value range will be from 0 to 59.
1119  * AM/PM. Value 0 for AM and 1 for PM.
1120  * If the value is beyond the range,
1121  * a) Value is less than Min range value, then Min range value is set.
1122  * b) Greater than Max range value, then Max Range value is set.
1123  * Both Min and Max range of individual fields are bound to the current context.
1124  *
1125  * @param[in] obj The datefield object
1126  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1127  * @param[in] value The minimum value of the field that is to be set.
1128  * @ingroup Datefield
1129  */
1130 EAPI void
1131 elm_datefield_item_min_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1132                            int value,  Eina_Bool abs_limit)
1133 {
1134    ELM_CHECK_WIDTYPE(obj, widtype);
1135    Widget_Data *wd;
1136    Datefield_Item *it;
1137
1138    wd = elm_widget_data_get(obj);
1139    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1140
1141    it = wd->item_list + itemtype;
1142    if ( it->type != ELM_DATEFIELD_YEAR && value < it->default_min )
1143       it->min = it->default_min;
1144    else
1145       it->min = value;
1146
1147    if(it->min > it->max ) it->max = it->min;
1148    it->abs_min = abs_limit;
1149    _field_value_set(obj, it->type, *(it->value), EINA_FALSE);  // Trigger the validation
1150 }
1151
1152 /**
1153  * @brief Get lower boundary of the datefield
1154  * Year : years since 1900. Negative value represents year below 1900. (
1155  * year value -30 represents 1870). Year default range is from 70 to 137.
1156  * Year default range is from 70 to 137.
1157  * Month default value range is from 0 to 11
1158  * Date default value range is from 1 to 31 according to the month value.
1159  * Hour default value will be in terms of 24 hr format (0~23)
1160  * Minute default value range will be from 0 to 59.
1161  * AM/PM. Value 0 for AM and 1 for PM.
1162  * If the value is beyond the range,
1163  * a) Value is less than Min range value, then Min range value is set.
1164  * b) Greater than Max range value, then Max Range value is set.
1165  * Both Min and Max range of individual fields are bound to the current context.
1166  *
1167  * @param[in] obj The datefield object
1168  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1169  * @return int The minimum value of the field.
1170  *
1171  * @ingroup Datepicker
1172  */
1173 EAPI int
1174 elm_datefield_item_min_get(const Evas_Object *obj, Elm_Datefield_ItemType
1175                            itemtype)
1176 {
1177    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1178    Widget_Data *wd;
1179
1180    wd = elm_widget_data_get(obj);
1181    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1182
1183    return ((wd->item_list + itemtype)->min);
1184 }
1185
1186 /**
1187  * @brief Get whether the minimum value of the item is absolute or not
1188  *
1189  * @param[in] obj The datefield object
1190  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1191  * @return EINA_TRUE = Minimim is absolute or EINA_FALSE = Minimum is relative.
1192  *
1193  * @ingroup Datefield
1194  */
1195
1196 EAPI Eina_Bool
1197 elm_datefield_item_min_is_absolute(const Evas_Object *obj,
1198                                    Elm_Datefield_ItemType itemtype)
1199 {
1200    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1201    Widget_Data *wd;
1202
1203    wd = elm_widget_data_get(obj);
1204    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1205
1206    return ((wd->item_list + itemtype)->abs_min);
1207 }
1208
1209 /**
1210  * @brief Set upper boundary of the datefield
1211  * Year : years since 1900. Negative value represents year below 1900. (
1212  * year value -30 represents 1870). Year default range is from 70 to 137.
1213  * Month:default value range is from 0 to 11
1214  * Date : default value range is from 1 to 31 according to the month value.
1215  * Hour : default value will be in terms of 24 hr format (0~23)
1216  * Minute  : default value range will be from 0 to 59.
1217  * AM/PM: Value 0 for AM and 1 for PM.
1218  * If the value is beyond the contextual range,
1219  * a) Value is less than Min range value, then Min range value is set.
1220  * b) Greater than Max range value, then Max Range value is set.
1221  * Both Min and Max range of individual fields are bound to the current context.
1222  *
1223  * @param[in] obj The datefield object
1224  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1225  * @param[in] value The maximum field value that is to be set.
1226  *
1227  * @ingroup Datefield
1228  */
1229 EAPI void
1230 elm_datefield_item_max_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1231                            int value, Eina_Bool abs_limit )
1232 {
1233    ELM_CHECK_WIDTYPE(obj, widtype);
1234    Widget_Data *wd;
1235    Datefield_Item *it;
1236
1237    wd = elm_widget_data_get(obj);
1238    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1239
1240    it = wd->item_list + itemtype;
1241    if (it->type != ELM_DATEFIELD_YEAR && value > it->default_max )
1242       it->max = it->default_max;
1243    else
1244       it->max = value;
1245
1246    if(it->max < it->min) it->min = it->max;
1247    it->abs_max = abs_limit;
1248
1249    _field_value_set(obj, it->type, *(it->value), EINA_FALSE);  // Trigger the validation
1250 }
1251
1252 /**
1253  * @brief Get upper boundary of the datefield
1254  * Year : years since 1900. Negative value represents year below 1900. (
1255  * year value -30 represents 1870). Year default range is from 70 to 137.
1256  * Month default value range is from 0 to 11
1257  * Date default value range is from 1 to 31 according to the month value.
1258  * Hour default value will be in terms of 24 hr format (0~23)
1259  * Minute default value range will be from 0 to 59.
1260  * AM/PM. Value 0 for AM and 1 for PM.
1261  * If the value is beyond the range,
1262  * a) Value is less than Min range value, then Min range value is set.
1263  * b) Greater than Max range value, then Max Range value is set.
1264  * Both Min and Max range of individual fields are bound to the current context.
1265  *
1266  * @param[in] obj The datefield object
1267  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1268  * @return int The maximum value of the field.
1269  *
1270  * @ingroup Datefield
1271  */
1272 EAPI int
1273 elm_datefield_item_max_get(const Evas_Object *obj, Elm_Datefield_ItemType
1274                            itemtype)
1275 {
1276    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1277    Widget_Data *wd;
1278
1279    wd = elm_widget_data_get(obj);
1280    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1281
1282    return ((wd->item_list + itemtype)->max);
1283 }
1284
1285 /**
1286  * @brief Get whether the max value of the item is absolute or not
1287  *
1288  * @param[in] obj The datefield object
1289  * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1290  * @return EINA_TRUE = Max is absolute or EINA_FALSE = Max is relative.
1291  *
1292  * @ingroup Datefield
1293  */
1294
1295 EAPI Eina_Bool
1296 elm_datefield_item_max_is_absolute(const Evas_Object *obj,
1297                                    Elm_Datefield_ItemType itemtype)
1298 {
1299    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1300    Widget_Data *wd;
1301
1302    wd = elm_widget_data_get(obj);
1303    if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1304
1305    return ((wd->item_list + itemtype)->abs_max);
1306 }
1307
1308
1309 /////////////////////////////////////////////////////////////////////////////////
1310 ////////////////////////// Date Field DEPRECATED APIs ///////////////////////////
1311 ////////////////////////////////////////////////////////////////////////////////
1312
1313 #define DATE_FORMAT_TYPE_COUNT 6
1314
1315 typedef struct _format_mapper
1316 {
1317    char old_fmt[BUFFER_SIZE];
1318    char new_fmt[BUFFER_SIZE];
1319 }format_mapper;
1320
1321 format_mapper map_format[DATE_FORMAT_TYPE_COUNT] = {
1322    { "ddmmyy",  "%d %b %Y" },
1323    { "ddyymm",  "%d %Y %b" },
1324    { "mmddyy",  "%b %d %Y" },
1325    { "mmyydd",  "%b %Y %d" },
1326    { "yymmdd",  "%Y %b %d" },
1327    { "yyddmm",  "%Y %d %b" }
1328 };
1329
1330 static char*
1331 _get_format(Evas_Object *obj, const char * format)
1332 {
1333    Widget_Data *wd = elm_widget_data_get(obj);
1334    Eina_Strbuf *strbuf;
1335    char * fmt;
1336    unsigned int i= 0;
1337
1338    if (!wd) return NULL;
1339
1340    strbuf =  eina_strbuf_new();
1341
1342    if (wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATE ||
1343               wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
1344      {
1345         for (i =0; i< DATE_FORMAT_TYPE_COUNT; i++)
1346           {
1347              if (!strncmp(format, map_format[i].old_fmt, BUFFER_SIZE))
1348                {
1349                   eina_strbuf_append(strbuf, map_format[i].new_fmt);
1350                   break;
1351                }
1352           }
1353      }
1354
1355    if (wd->datefield_layout == ELM_DATEFIELD_LAYOUT_TIME ||
1356               wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME)
1357      {
1358         if (wd->time_mode)
1359           eina_strbuf_append(strbuf, "%I : %M %p");
1360         else
1361           eina_strbuf_append(strbuf, "%H : %M");
1362      }
1363
1364    eina_strbuf_append_char(strbuf, 0); // NULL terminated string
1365    fmt = eina_strbuf_string_steal(strbuf);
1366    eina_strbuf_free( strbuf );
1367
1368    return fmt;
1369 }
1370
1371 /**
1372  * @brief Set layout for the datefield
1373  *
1374  * @param[in] obj The datefield object
1375  * @param[in] layout set layout for date/time/dateandtime
1376  * (default: ELM_DATEFIELD_LAYOUT_DATEANDTIME)
1377  *
1378  * @ingroup Datefield
1379  */
1380 EINA_DEPRECATED EAPI void
1381 elm_datefield_layout_set(Evas_Object *obj, Elm_Datefield_Layout layout)
1382 {
1383    ELM_CHECK_WIDTYPE(obj, widtype);
1384    Widget_Data *wd = elm_widget_data_get(obj);
1385    Eina_Bool date_enabled;
1386    Eina_Bool time_enabled;
1387
1388    if (!wd || layout > ELM_DATEFIELD_LAYOUT_DATEANDTIME) return;
1389    if (layout == wd->datefield_layout) return;
1390    wd->datefield_layout = layout;
1391    date_enabled = ((wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATE)
1392                   ||(wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME));
1393
1394    time_enabled = ((wd->datefield_layout == ELM_DATEFIELD_LAYOUT_TIME)
1395                   ||(wd->datefield_layout == ELM_DATEFIELD_LAYOUT_DATEANDTIME));
1396
1397    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_YEAR, date_enabled);
1398    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_MONTH, date_enabled);
1399    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_DATE, date_enabled);
1400    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_HOUR, time_enabled);
1401    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_MINUTE, time_enabled);
1402    elm_datefield_item_enabled_set(obj, ELM_DATEFIELD_AMPM,
1403                                  (time_enabled && wd->time_mode));
1404 }
1405
1406 /**
1407  * @brief Get layout of the datefield
1408  *
1409  * @param[in] obj The datefield object
1410  * @return layout of the datefield
1411  *
1412  * @ingroup Datefield
1413  */
1414 EINA_DEPRECATED EAPI Elm_Datefield_Layout
1415 elm_datefield_layout_get(const Evas_Object *obj)
1416 {
1417    ELM_CHECK_WIDTYPE(obj, widtype)-1;
1418    Widget_Data *wd = elm_widget_data_get(obj);
1419
1420    if (!wd) return -1;
1421
1422    return (wd->datefield_layout);
1423 }
1424
1425 /**
1426  * @brief Set date format of datefield
1427  *
1428  * @param[in] obj The datefield object
1429  * @param[in] fmt The date format, ex) mmddyy.
1430  * Default value is taken according to the system locale settings.
1431  *
1432  * @ingroup Datefield
1433  */
1434 EINA_DEPRECATED EAPI void
1435 elm_datefield_date_format_set(Evas_Object *obj, const char *fmt)
1436 {
1437    ELM_CHECK_WIDTYPE(obj, widtype);
1438    Widget_Data *wd = elm_widget_data_get(obj);
1439
1440    if (!wd) return;
1441
1442    wd->old_style_format = strdup(fmt);
1443    elm_datefield_format_set(obj, _get_format(obj, fmt));
1444 }
1445
1446 /**
1447  * @brief Get the user set format of the datefield
1448  *
1449  * @param[in] obj The datefield object
1450  * @return date format string. ex) mmddyy
1451  *
1452  * @ingroup Datefield
1453  */
1454 EINA_DEPRECATED EAPI const char *
1455 elm_datefield_date_format_get(const Evas_Object *obj)
1456 {
1457    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1458    Widget_Data *wd = elm_widget_data_get(obj);
1459
1460    if (!wd) return NULL;
1461
1462    return (wd->old_style_format);
1463 }
1464
1465 /**
1466  * @brief Set if the datefield show hours in military or am/pm mode
1467  *
1468  * @param[in] obj The datefield object
1469  * @param[in] mode option for the hours mode. If true, it is shown as 12h mode,
1470  * if false, it is shown as 24h mode. Default value is true
1471  *
1472  * @ingroup Datefield
1473  */
1474 EINA_DEPRECATED EAPI void
1475 elm_datefield_time_mode_set(Evas_Object *obj, Eina_Bool mode)
1476 {
1477    ELM_CHECK_WIDTYPE(obj, widtype);
1478    Widget_Data *wd = elm_widget_data_get(obj);
1479
1480    if (!wd) return;
1481
1482    wd->time_mode = mode;
1483    elm_datefield_format_set(obj, _get_format(obj, wd->old_style_format));
1484 }
1485
1486 /**
1487  * @brief get time mode of the datefield
1488  *
1489  * @param[in] obj The datefield object
1490  * @return time mode (EINA_TRUE: 12hour mode / EINA_FALSE: 24hour mode)
1491  *
1492  * @ingroup Datefield
1493  */
1494 EINA_DEPRECATED EAPI Eina_Bool
1495 elm_datefield_time_mode_get(const Evas_Object *obj)
1496 {
1497    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1498    Widget_Data *wd = elm_widget_data_get(obj);
1499
1500    if (!wd) return EINA_FALSE;
1501
1502    return (wd->time_mode);
1503 }
1504
1505 /**
1506  * @brief Set selected date of the datefield
1507  *
1508  * @param[in] obj The datefield object
1509  * @param[in] year The year to set
1510  * @param[in] month The month to set (1-12)
1511  * @param[in] day The day to set
1512  * @param[in] hour The hours to set (24hour mode - 0~23)
1513  * @param[in] min The minutes to set (0~59)
1514  *
1515  * @ingroup Datefield
1516  * @deprecated, use elm_datefield_item_value_set() instead.
1517  */
1518 EINA_DEPRECATED EAPI void
1519 elm_datefield_date_set(Evas_Object *obj, int year, int month, int day, int hour,
1520                        int min)
1521 {
1522    year -= 1900;  // backward compatibility
1523    elm_datefield_item_value_set(obj, ELM_DATEFIELD_YEAR, year);
1524    month -= 1;  // backward compatibility
1525    elm_datefield_item_value_set(obj, ELM_DATEFIELD_MONTH, month);
1526    elm_datefield_item_value_set(obj, ELM_DATEFIELD_DATE, day);
1527    elm_datefield_item_value_set(obj, ELM_DATEFIELD_HOUR, hour);
1528    elm_datefield_item_value_set(obj, ELM_DATEFIELD_MINUTE, min);
1529 }
1530
1531 /**
1532  * @brief Get selected date of the datefield
1533  *
1534  * @param[in] obj The datefield object
1535  * @param[in] year The pointer to the variable get the selected year
1536  * @param[in] month The pointer to the variable get the selected month (1-12)
1537  * @param[in] day The pointer to the variable get the selected day
1538  * @param[in] hour The pointer to the variable get the selected hour(24hour mode)
1539  * @param[in] hour The pointer to the variable get the selected min
1540  *
1541  * @ingroup Datefield
1542  * @deprecated, use elm_datefield_item_value_get() instead.
1543  */
1544 EINA_DEPRECATED EAPI void
1545 elm_datefield_date_get(const Evas_Object *obj, int *year, int *month, int *day,
1546                        int *hour, int *min)
1547 {
1548    if (year)
1549      {
1550         *year = elm_datefield_item_value_get(obj, ELM_DATEFIELD_YEAR);
1551         *year = (*year+1900);  // backward compatibility
1552      }
1553    if (month)
1554      {
1555         *month = elm_datefield_item_value_get(obj, ELM_DATEFIELD_MONTH);
1556         (*month)+=1;  // backward compatibility
1557      }
1558    if (day)
1559      *day = elm_datefield_item_value_get(obj, ELM_DATEFIELD_DATE);
1560    if (hour)
1561      *hour = elm_datefield_item_value_get(obj, ELM_DATEFIELD_HOUR);
1562    if (min)
1563      *min = elm_datefield_item_value_get(obj, ELM_DATEFIELD_MINUTE);
1564 }
1565
1566 /**
1567  * @brief Set lower boundary of the datefield
1568  *
1569  * @param[in] obj The datefield object
1570  * @param[in] year The year to set
1571  * @param[in] month The month to set (1-12)
1572  * @param[in] day The day to set
1573  * @return TRUE/FALSE
1574  *
1575  * @ingroup Datepicker
1576  * @deprecated, use elm_datefield_item_min_set() instead.
1577  */
1578 EINA_DEPRECATED EAPI Eina_Bool
1579 elm_datefield_date_min_set(Evas_Object *obj, int year, int month, int day)
1580 {
1581    year -= 1900;  // backward compatibility
1582    elm_datefield_item_min_set(obj, ELM_DATEFIELD_YEAR, year, EINA_FALSE);
1583    month -= 1;  // backward compatibility
1584    elm_datefield_item_min_set(obj, ELM_DATEFIELD_MONTH, month, EINA_FALSE);
1585    elm_datefield_item_min_set(obj, ELM_DATEFIELD_DATE, day, EINA_FALSE);
1586    return EINA_TRUE;
1587 }
1588
1589 /**
1590  * @brief Get lower boundary of the datefield
1591  *
1592  * @param[in] obj The datefield object
1593  * @param[in] year The pointer to the variable get the maximum year
1594  * @param[in] month The pointer to the variable get the maximum month (1-12)
1595  * @param[in] day The pointer to the variable get the maximum day
1596  *
1597  * @ingroup Datefield
1598  * @deprecated, use elm_datefield_item_min_get() instead.
1599  */
1600 EINA_DEPRECATED EAPI void
1601 elm_datefield_date_min_get(const Evas_Object *obj, int *year, int *month,
1602                            int *day)
1603 {
1604    if (year)
1605      {
1606         *year = elm_datefield_item_min_get(obj, ELM_DATEFIELD_YEAR);
1607         *year = (*year) + 1900;  // backward compatibility
1608      }
1609    if (month)
1610      {
1611         *month = elm_datefield_item_min_get(obj, ELM_DATEFIELD_MONTH);
1612         (*month)+=1;  // backward compatibility
1613      }
1614    if (day)
1615      *day = elm_datefield_item_min_get(obj, ELM_DATEFIELD_DATE);
1616 }
1617
1618 /**
1619  * @brief Set upper boundary of the datefield
1620  *
1621  * @param[in] obj The datefield object
1622  * @param[in] year The year to set
1623  * @param[in] month The month to set (1-12)
1624  * @param[in] day The day to set
1625  * @return TRUE/FALSE
1626  *
1627  * @ingroup Datefield
1628  * @deprecated, use elm_datefield_item_max_set() instead.
1629  */
1630 EINA_DEPRECATED EAPI Eina_Bool
1631 elm_datefield_date_max_set(Evas_Object *obj, int year, int month, int day)
1632 {
1633    year -= 1900;  // backward compatibility
1634    elm_datefield_item_max_set(obj, ELM_DATEFIELD_YEAR, year, EINA_FALSE);
1635    month -= 1;  // backward compatibility
1636    elm_datefield_item_max_set(obj, ELM_DATEFIELD_MONTH, month, EINA_FALSE);
1637    elm_datefield_item_max_set(obj, ELM_DATEFIELD_DATE, day, EINA_FALSE);
1638    return EINA_TRUE;
1639 }
1640
1641 /**
1642  * @brief Get upper boundary of the datefield
1643  *
1644  * @param[in] obj The datefield object
1645  * @param[in] year The pointer to the variable get the maximum year
1646  * @param[in] month The pointer to the variable get the maximum month (1-12)
1647  * @param[in] day The pointer to the variable get the maximum day
1648  *
1649  * @ingroup Datefield
1650  * @deprecated, use elm_datefield_item_max_get() instead.
1651  */
1652 EINA_DEPRECATED EAPI void
1653 elm_datefield_date_max_get(const Evas_Object *obj, int *year, int *month,
1654                            int *day)
1655 {
1656    if (year)
1657    {
1658      *year = elm_datefield_item_max_get(obj, ELM_DATEFIELD_YEAR);
1659      *year = (*year) + 1900;  // backward compatibility
1660    }
1661    if (month)
1662      {
1663        *month = elm_datefield_item_max_get(obj, ELM_DATEFIELD_MONTH);
1664        (*month)+=1;  // backward compatibility
1665      }
1666    if (day)
1667      *day = elm_datefield_item_max_get(obj, ELM_DATEFIELD_DATE);
1668 }
1669
1670 /**
1671  * @brief Add a callback function for input panel state
1672  *
1673  * @param[in] obj The datefield object
1674  * @param[in] func The function to be called when the event is triggered
1675  * (value will be the Ecore_IMF_Input_Panel_State)
1676  * @param[in] data The data pointer to be passed to @p func
1677  *
1678  * @ingroup Datefield
1679  * @deprecated and will no longer be in use.
1680  */
1681 EINA_DEPRECATED EAPI void
1682 elm_datefield_input_panel_state_callback_add(Evas_Object *obj __UNUSED__,
1683           void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value)
1684           __UNUSED__, void *data __UNUSED__)
1685 {
1686    //Empty implementation
1687 }
1688
1689 /**
1690  * @brief Delete a callback function for input panel state
1691  *
1692  * @param[in] obj The datefield object
1693  * @param[in] func The function to be called when the event is triggered
1694  *
1695  * @ingroup Datefield
1696  * @deprecated and will no longer be in use.
1697  */
1698 EINA_DEPRECATED EAPI void
1699 elm_datefield_input_panel_state_callback_del(Evas_Object *obj __UNUSED__,
1700           void (*pEventCallbackFunc) (void *data, Evas_Object *obj, int value)
1701           __UNUSED__)
1702 {
1703    //Empty implementation
1704 }
1705 /////////////////////////////////////////////////////////////////////////////////
1706 //////////////////////////Date Field DEPRECATED APIs  END////////////////////////
1707 ////////////////////////////////////////////////////////////////////////////////
1708