2 #include <Elementary.h>
6 * @defgroup Datefield Datefield
9 * This is a date edit field. it is used to input date and time using
10 * diskselector integrated ctxpopup.
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
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.
44 typedef struct _Widget_Data Widget_Data;
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
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"
69 #define DEFAULT_FORMAT "%b %d, %Y %I : %M %p"
71 typedef struct _Format_Map
73 Elm_Datefield_ItemType type;
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 }
88 static int _days_in_month[12] = { 31, 28, 31, 30, 31, 30,
89 31, 31, 30, 31, 30, 31 };
91 typedef enum _Elm_Datefield_HourType
93 ELM_DATEFIELD_HOUR_12 = 1000,
94 ELM_DATEFIELD_HOUR_24,
96 } Elm_Datefield_HourType;
99 typedef struct _Datefield_Item
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
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
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.
128 typedef struct _DiskItem_Data
130 Evas_Object *datefield;
131 unsigned int sel_item_value;
134 static const char *widtype = NULL;
136 static void _del_hook(Evas_Object *obj);
137 static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
138 static void _disable_hook(Evas_Object *obj);
139 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
140 static void _sizing_eval(Evas_Object *obj);
141 static void _theme_hook(Evas_Object *obj);
142 static void _ctxpopup_dismissed_cb(void *data, Evas_Object *obj __UNUSED__,
143 void *event_info __UNUSED__);
144 static void _datefield_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj
145 __UNUSED__, void *event_info __UNUSED__);
146 static void _datefield_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj
147 __UNUSED__, void *event_info __UNUSED__);
149 static void _update_items(Evas_Object *obj);
150 static void _field_value_set(Evas_Object * obj, Elm_Datefield_ItemType type,
151 int value, Eina_Bool adjust_time);
152 static void _diskselector_cb(void *data, Evas_Object *obj __UNUSED__,
153 void *event_info __UNUSED__);
154 static void _ampm_clicked (void *data);
155 static void _diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__,
156 void *event_info __UNUSED__);
157 static void _load_field_options(Evas_Object * data, Evas_Object *diskselector,
159 static void _datefield_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
160 const char *emission __UNUSED__, const char *source);
161 static void _format_reload(Evas_Object *obj);
162 static void _item_list_init(Evas_Object *obj);
164 static const char SIG_CHANGED[] = "changed";
165 static const Evas_Smart_Cb_Description _signals[] = {
171 _del_hook(Evas_Object *obj)
177 wd = elm_widget_data_get(obj);
179 if (wd->time) free(wd->time);
180 for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
182 tmp = wd->item_list + idx;
183 eina_stringshare_replace(&tmp->content, NULL);
184 eina_stringshare_replace(&tmp->separator, NULL);
186 if (wd->item_list) free(wd->item_list);
187 evas_object_del(wd->ctxpopup);
193 _disable_hook(Evas_Object *obj)
197 wd = elm_widget_data_get(obj);
198 if (!wd || !wd->base) return;
199 if (elm_widget_disabled_get(obj))
201 evas_object_hide(wd->ctxpopup);
202 edje_object_signal_emit(wd->base, EDC_DATEFIELD_DISABLE_SIG_STR,"elm");
205 edje_object_signal_emit(wd->base, EDC_DATEFIELD_ENABLE_SIG_STR, "elm");
209 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
213 wd = elm_widget_data_get(obj);
215 if (elm_widget_focus_get(obj))
216 edje_object_signal_emit(wd->base, EDC_DATEFIELD_FOCUSIN_SIG_STR, "elm");
218 edje_object_signal_emit(wd->base, EDC_DATEFIELD_FOCUSOUT_SIG_STR, "elm");
222 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
226 wd = elm_widget_data_get(obj);
228 evas_object_hide(wd->ctxpopup);
229 edje_object_mirrored_set(wd->base, rtl);
233 _sizing_eval(Evas_Object *obj)
236 Evas_Coord minw = -1, minh = -1;
238 wd = elm_widget_data_get(obj);
239 if (!wd || !wd->base) return;
240 edje_object_size_min_calc(wd->base, &minw, &minh);
241 evas_object_size_hint_min_set(obj, minw, minh);
242 evas_object_size_hint_max_set(obj, -1, -1);
246 _theme_hook(Evas_Object *obj)
250 char buf[BUFFER_SIZE];
252 //Evas_Object *diskselector;
254 wd = elm_widget_data_get(obj);
255 if (!wd || !wd->base) return;
256 _elm_theme_object_set(obj, wd->base, "datefield", "base",
257 elm_widget_style_get(obj));
258 _elm_widget_mirrored_reload(obj);
259 _mirrored_set(obj, elm_widget_mirrored_get(obj));
261 snprintf(buf, sizeof(buf), "datefield/%s", elm_object_style_get(obj));
262 elm_object_style_set(wd->ctxpopup, buf);
263 /*//Enabled once elm_object_content_get() API comes to git.
264 if (diskselector = elm_object_content_get(wd->ctxpopup))
265 elm_object_style_set(diskselector, buf);*/
266 edje_object_scale_set(wd->base,elm_widget_scale_get(obj)*_elm_config->scale);
268 if (elm_widget_disabled_get(obj))
269 edje_object_signal_emit(wd->base, EDC_DATEFIELD_DISABLE_SIG_STR,"elm");
271 edje_object_signal_emit(wd->base, EDC_DATEFIELD_ENABLE_SIG_STR, "elm");
273 for (idx= 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
275 it = wd->item_list + idx;
276 if (it->fmt_exist && it->enabled )
278 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STR, it->location);
279 edje_object_part_text_set(wd->base, buf, it->content);
280 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, it->location);
281 edje_object_part_text_set(wd->base, buf, it->separator);
282 snprintf(buf, sizeof(buf), EDC_PART_ITEM_ENABLE_SIG_STR,
284 edje_object_signal_emit(wd->base, buf, "elm");
285 if (it->type == ELM_DATEFIELD_AMPM)
286 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_AMPM_SIG_STR,
289 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_DEFAULT_SIG_STR,
291 edje_object_signal_emit(wd->base, buf, "elm");
295 snprintf(buf, sizeof(buf),EDC_PART_ITEM_DISABLE_SIG_STR,
297 edje_object_signal_emit(wd->base, buf, "elm");
300 edje_object_message_signal_process(wd->base);
305 _ctxpopup_dismissed_cb(void *data, Evas_Object *obj __UNUSED__,
306 void *event_info __UNUSED__)
309 Evas_Object *diskselector;
310 char buf[BUFFER_SIZE];
312 wd = elm_widget_data_get(data);
313 if (!wd || !wd->base) return;
314 diskselector = elm_ctxpopup_content_unset(wd->ctxpopup);
315 if (diskselector) evas_object_del(diskselector);
319 snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSOUT_SIG_STR,
320 wd->selected_it->location);
321 edje_object_signal_emit(wd->base, buf, "elm");
322 wd->selected_it = NULL;
327 _datefield_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
328 void *event_info __UNUSED__)
332 wd = elm_widget_data_get(data);
334 evas_object_hide(wd->ctxpopup);
338 _datefield_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
339 void *event_info __UNUSED__)
343 wd = elm_widget_data_get(data);
345 evas_object_hide(wd->ctxpopup);
349 _contextual_field_limit_get(Evas_Object * obj, Datefield_Item * it,
350 Eina_Bool hr_fmt_check, int *range_min, int *range_max)
353 Datefield_Item * tmp;
356 Eina_Bool min_limit = EINA_TRUE;
357 Eina_Bool max_limit = EINA_TRUE;
359 wd = elm_widget_data_get(obj);
360 if (!wd || !it) return;
362 //Top to down check for current field relative min/max limit
363 if (!it->abs_min || !it->abs_max )
365 for (idx = ELM_DATEFIELD_YEAR; idx < it->type; idx++)
367 tmp = wd->item_list + idx;
368 if (max_limit && (*(tmp->value) < tmp->max)) max_limit= EINA_FALSE;
369 if (min_limit && (*(tmp->value) > tmp->min)) min_limit= EINA_FALSE;
373 if (it->abs_min || min_limit) (*range_min) = it->min;
374 else (*range_min) = it->default_min;
376 if (it->abs_max || max_limit) (*range_max) = it->max;
377 else (*range_max) = it->default_max;
379 ctx_max = it->default_max;
380 if (it->type == ELM_DATEFIELD_DATE )
382 ctx_max = _days_in_month[wd->time->tm_mon];
383 // Check for Leap year Feb.
384 if (__isleap((wd->time->tm_year)) && wd->time->tm_mon == 1) ctx_max= 29;
386 else if (it->type == ELM_DATEFIELD_HOUR && hr_fmt_check &&
387 it->hour_type == ELM_DATEFIELD_HOUR_12 ) ctx_max = 11;
389 if (*range_max > ctx_max) *range_max = ctx_max;
393 _update_items(Evas_Object *obj)
397 char buf[BUFFER_SIZE];
400 wd = elm_widget_data_get(obj);
401 if (!wd || !wd->base) return;
402 for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
404 it = wd->item_list + idx;
405 if ( it->fmt_exist && it->enabled )
407 strftime(buf, BUFFER_SIZE, it->fmt, wd->time);
409 // FIXME: no locale string availble from Libc...
410 if ((!strncmp(buf, "",1)) && (it->type == ELM_DATEFIELD_AMPM))
412 if (wd->ampm) strncpy(buf, E_("PM"), BUFFER_SIZE);
413 else strncpy(buf, E_("AM"), BUFFER_SIZE);
415 eina_stringshare_replace(&it->content, buf);
416 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STR, it->location);
417 edje_object_part_text_set(wd->base, buf, it->content);
423 _field_value_set(Evas_Object * obj, Elm_Datefield_ItemType item_type, int value,
424 Eina_Bool adjust_time)
430 Eina_Bool value_changed = EINA_FALSE;
432 wd = elm_widget_data_get(obj);
435 if (item_type == ELM_DATEFIELD_AMPM)
437 if ( value == wd->ampm ) return;
438 item_type = ELM_DATEFIELD_HOUR;
439 value = (wd->time->tm_hour + 12) % 24;
440 adjust_time = EINA_FALSE;
443 it = wd->item_list + item_type;
444 _contextual_field_limit_get(obj, it, EINA_FALSE, &min, &max);
446 //12 hr format & PM then add 12 to value.
447 if (adjust_time && it->type == ELM_DATEFIELD_HOUR &&
448 it->hour_type == ELM_DATEFIELD_HOUR_12 && wd->ampm && value < 12)
451 if (value < min) value = min;
452 else if (value > max) value = max;
453 if ( *(it->value) == value) return;
454 *(it->value) = value;
455 value_changed = EINA_TRUE;
457 //Validate & reset lower order fields
458 for ( idx = item_type+1; idx < DATEFIELD_TYPE_COUNT; idx++ )
460 it = wd->item_list + idx;
461 _contextual_field_limit_get(obj, it, EINA_FALSE, &min, &max);
462 //Validate current value against context based Min/Max restriction.
463 if (*it->value < min)
466 value_changed = EINA_TRUE;
468 else if (*it->value > max)
471 value_changed = EINA_TRUE;
475 wd->ampm = (wd->time->tm_hour > 11 );
479 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
483 _diskselector_cb(void *data, Evas_Object *obj __UNUSED__,
484 void *event_info __UNUSED__)
486 DiskItem_Data *cb_data;
489 cb_data = (DiskItem_Data *)data;
490 if (!cb_data) return;
491 wd = elm_widget_data_get(cb_data->datefield);
494 _field_value_set(cb_data->datefield, wd->selected_it->type,
495 cb_data->sel_item_value, EINA_TRUE);
497 evas_object_hide(wd->ctxpopup);
501 _ampm_clicked (void *data)
504 char buf[BUFFER_SIZE];
506 wd = elm_widget_data_get(data);
507 if (!wd || !wd->base) return;
509 _field_value_set( data, ELM_DATEFIELD_AMPM, !wd->ampm, EINA_FALSE );
511 snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSOUT_SIG_STR,
512 wd->selected_it->location);
513 edje_object_signal_emit(wd->base, buf, "elm");
514 wd->selected_it = NULL;
518 _diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__,
519 void *event_info __UNUSED__)
521 if (data) free(data);
525 _load_field_options(Evas_Object * data, Evas_Object *diskselector,
529 DiskItem_Data *disk_data;
530 Elm_Object_Item *item;
531 int idx, min, max, selected_val;
532 int text_len, max_len = 0;
533 char item_label[BUFFER_SIZE];
534 int cur_val, date_val;
536 wd = elm_widget_data_get(data);
539 cur_val = *(it->value);
540 date_val = wd->time->tm_mday;
541 _contextual_field_limit_get(data, it, EINA_TRUE, &min, &max );
543 selected_val = *(it->value);
544 wd->time->tm_mday = 1;
545 // If 12hr format & PM, reduce 12
546 if (it->hour_type == ELM_DATEFIELD_HOUR_12 && wd->ampm) selected_val -= 12;
548 for (idx = min; idx <= max; idx++)
\r
551 strftime(item_label, BUFFER_SIZE, it->fmt, wd->time );
552 text_len = strlen(item_label);
553 if (text_len > max_len ) max_len = text_len; //Store max. label length
555 if (idx == selected_val) //Selected Item, dont attach a callback handler
557 item = elm_diskselector_item_append(diskselector, item_label,
559 elm_diskselector_item_selected_set(item, EINA_TRUE);
563 disk_data = (DiskItem_Data *) malloc (sizeof(DiskItem_Data));
564 disk_data->datefield = data;
565 disk_data->sel_item_value = idx;
566 item = elm_diskselector_item_append(diskselector,
567 item_label, NULL, _diskselector_cb, disk_data);
568 elm_diskselector_item_del_cb_set(item, _diskselector_item_free_cb);
571 *(it->value) = cur_val;
572 wd->time->tm_mday = date_val;
573 elm_diskselector_side_label_length_set(diskselector, max_len);
577 _datefield_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
578 const char *emission __UNUSED__, const char *source)
580 Widget_Data *wd = elm_widget_data_get(data);
581 Evas_Object *diskselector;
582 const Evas_Object *edj_part;
583 char buf[BUFFER_SIZE];
584 unsigned int idx = 0, idx1 = 0, display_item_num;
585 Evas_Coord x = 0, y = 0, w = 0, h = 0;
586 Evas_Coord disksel_width;
588 if (!wd || !wd->base) return;
589 if (elm_widget_disabled_get(data)) return;
591 wd->selected_it = NULL;
592 //Locate the selected Index & Selected Datefield_Item
593 for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
595 snprintf(buf, sizeof(buf), EDC_PART_ITEM_OVER_STR, idx);
596 if (!strncmp(buf, source, sizeof(buf)))
598 for (idx1 = 0; idx1 < DATEFIELD_TYPE_COUNT; idx1++ )
600 if ((wd->item_list + idx1)->location == (int)idx)
602 wd->selected_it = wd->item_list + idx1;
610 if ( !wd->selected_it || !wd->selected_it->fmt_exist
611 || !wd->selected_it->enabled ) return;
612 snprintf(buf, sizeof(buf), EDC_PART_ITEM_FOCUSIN_SIG_STR,
613 wd->selected_it->location);
614 edje_object_signal_emit(wd->base, buf, "elm");
616 if ( wd->selected_it->type == ELM_DATEFIELD_AMPM )
618 _ampm_clicked (data);
622 //Recreating diskselector everytime due to diskselector behavior
623 diskselector = elm_diskselector_add(elm_widget_top_get(data));
624 snprintf(buf, sizeof(buf), "datefield/%s", elm_object_style_get(data));
625 elm_object_style_set(diskselector, buf);
627 //Load the options list
628 _load_field_options(data, diskselector, wd->selected_it);
630 elm_ctxpopup_direction_priority_set(wd->ctxpopup, ELM_CTXPOPUP_DIRECTION_DOWN,
631 ELM_CTXPOPUP_DIRECTION_UP, -1, -1);
632 elm_object_content_set(wd->ctxpopup, diskselector);
633 snprintf(buf,sizeof(buf), EDC_PART_ITEM_STR, wd->selected_it->location);
634 edj_part = edje_object_part_object_get(wd->base, buf);
635 evas_object_geometry_get(edj_part, &x, &y, &w, &h);
636 evas_object_move(wd->ctxpopup, (x+w/2), (y+h));
638 //If the direction of Ctxpopup is upwards, move it to the top of datefield
639 if (elm_ctxpopup_direction_get (wd->ctxpopup) == ELM_CTXPOPUP_DIRECTION_UP)
641 elm_ctxpopup_direction_priority_set(wd->ctxpopup, ELM_CTXPOPUP_DIRECTION_UP,
642 ELM_CTXPOPUP_DIRECTION_DOWN, -1, -1);
643 evas_object_move(wd->ctxpopup, (x+w/2), y);
645 evas_object_show(wd->ctxpopup);
647 evas_object_geometry_get(diskselector, NULL, NULL, &disksel_width, NULL);
648 display_item_num = disksel_width / (w + elm_finger_size_get());
649 //odd number of items leads to auto selection.
650 //making as event number of item to prevent auto selection.
651 if (display_item_num%2) display_item_num-=1;
652 if (display_item_num < DISKSELECTOR_ITEMS_NUM_MIN)
653 display_item_num = DISKSELECTOR_ITEMS_NUM_MIN;
655 elm_diskselector_display_item_num_set(diskselector, display_item_num);
656 elm_diskselector_round_set(diskselector, EINA_TRUE);
660 _parse_format( Evas_Object *obj )
663 Datefield_Item *it = NULL;
664 unsigned int len = 0, idx, location = 0;
665 char separator[MAX_SEPARATOR_LEN];
668 Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
669 sep_lookup = EINA_FALSE;
671 wd = elm_widget_data_get(obj);
672 fmt_ptr = wd->format;
674 while ( (cur = *fmt_ptr ) )
678 for ( idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
680 if ( strchr( mapping[idx].fmt_char, cur ) )
682 it = wd->item_list + idx;
683 //Ignore the items already have or disabled
684 //valid formats, means already parsed & repeated, ignore.
685 if (!it->enabled || it->location != -1) break;
688 //set the hour display format 12h/24h
689 if (it->type == ELM_DATEFIELD_HOUR)
691 if (cur == 'H' || cur == 'k' )
692 it->hour_type = ELM_DATEFIELD_HOUR_24;
693 else if (cur == 'I' || cur == 'l' )
694 it->hour_type = ELM_DATEFIELD_HOUR_12;
696 else it->hour_type = ELM_DATEFIELD_HOUR_NA;
698 it->fmt_exist = EINA_TRUE;
699 it->location = location++;
700 fmt_parsing = EINA_FALSE;
701 sep_lookup = EINA_TRUE;
710 fmt_parsing = EINA_TRUE;
711 sep_parsing = EINA_FALSE;
712 // Set the separator to previous Item
714 if (it) eina_stringshare_replace(&it->separator, separator);
716 if (sep_parsing && (len < MAX_SEPARATOR_LEN-1)) separator[len++] = cur;
717 if (sep_lookup) sep_parsing = EINA_TRUE;
718 sep_lookup = EINA_FALSE;
721 // Return the number of valid items parsed.
726 _format_reload(Evas_Object *obj)
730 char buf[BUFFER_SIZE];
731 unsigned int idx, location;
734 wd = elm_widget_data_get(obj);
737 // fetch the format from locale specific po file.
738 if (!wd->user_format )
740 def_fmt = E_("DateTimeFormat");
741 if (!strncmp(def_fmt, "DateTimeFormat", sizeof("DateTimeFormat")))
742 strncpy(wd->format, DEFAULT_FORMAT, MAX_FORMAT_LEN );
744 strncpy(wd->format, def_fmt, MAX_FORMAT_LEN );
747 //reset all the items to disable state
748 for ( idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++ )
750 it = wd->item_list + idx;
751 eina_stringshare_replace(&it->content, NULL);
752 it->fmt_exist = EINA_FALSE;
755 location = _parse_format( obj );
757 //assign locations to disabled fields for uniform usage
758 for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++)
760 it = wd->item_list + idx;
761 if (it->location == -1) it->location = location++;
763 if (it->fmt_exist && it->enabled)
765 snprintf(buf, sizeof(buf), EDC_PART_ITEM_ENABLE_SIG_STR,
767 edje_object_signal_emit(wd->base, buf, "elm");
768 if (it->type == ELM_DATEFIELD_AMPM)
769 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_AMPM_SIG_STR,
772 snprintf(buf, sizeof(buf), EDC_PART_ITEM_STYLE_DEFAULT_SIG_STR,
774 edje_object_signal_emit(wd->base, buf, "elm");
778 snprintf(buf, sizeof(buf),EDC_PART_ITEM_DISABLE_SIG_STR,
780 edje_object_signal_emit(wd->base, buf, "elm");
782 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, it->location+1);
783 edje_object_part_text_set(wd->base, buf, it->separator);
785 edje_object_message_signal_process(wd->base);
790 _item_list_init(Evas_Object *obj)
794 char buf[BUFFER_SIZE];
798 wd = elm_widget_data_get(obj);
801 wd->item_list = calloc(1, DATEFIELD_TYPE_COUNT * sizeof(Datefield_Item));
802 wd->time = calloc(1, sizeof(struct tm));
804 localtime_r(&t, wd->time);
806 (wd->item_list + ELM_DATEFIELD_YEAR)->value = &wd->time->tm_year;
807 (wd->item_list + ELM_DATEFIELD_MONTH)->value = &wd->time->tm_mon;
808 (wd->item_list + ELM_DATEFIELD_DATE)->value = &wd->time->tm_mday;
809 (wd->item_list + ELM_DATEFIELD_HOUR)->value = &wd->time->tm_hour;
810 (wd->item_list + ELM_DATEFIELD_MINUTE)->value = &wd->time->tm_min;
811 (wd->item_list + ELM_DATEFIELD_AMPM)->value = &wd->ampm;
812 wd->ampm = (wd->time->tm_hour > 11 );
814 for (idx = 0; idx < DATEFIELD_TYPE_COUNT; idx++)
816 it = wd->item_list + idx;
817 it->type = ELM_DATEFIELD_YEAR + idx;
819 it->fmt_exist = EINA_FALSE;
820 it->enabled = EINA_TRUE;
821 it->min = mapping[idx].def_min;
822 it->default_min = mapping[idx].def_min;
823 it->max = mapping[idx].def_max;
824 it->default_max = mapping[idx].def_max;
825 snprintf(buf, sizeof(buf), EDC_PART_ITEM_OVER_STR, idx);
826 edje_object_signal_callback_add(wd->base, "mouse,clicked,1", buf,
827 _datefield_clicked_cb, obj);
832 * @brief Add a new datefield Widget
833 * The date format and strings are based on current locale
835 * @param[in] parent The parent object
836 * @return The new object or NULL if it cannot be created
841 elm_datefield_add(Evas_Object *parent)
847 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
849 ELM_SET_WIDTYPE(widtype, "datefield");
850 elm_widget_type_set(obj, widtype);
851 elm_widget_sub_object_add(parent, obj);
852 elm_widget_data_set(obj, wd);
853 elm_widget_del_hook_set(obj, _del_hook);
854 elm_widget_theme_hook_set(obj, _theme_hook);
855 elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
856 elm_widget_disable_hook_set(obj, _disable_hook);
857 elm_widget_can_focus_set(obj, EINA_TRUE);
859 wd->base = edje_object_add(e);
860 elm_widget_resize_object_set(obj, wd->base);
861 _elm_theme_object_set(obj, wd->base, "datefield", "base", "default");
862 evas_object_smart_callbacks_descriptions_set(obj, _signals);
864 _item_list_init(obj);
867 wd->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj));
868 elm_object_style_set(wd->ctxpopup, "datefield/default");
869 elm_ctxpopup_horizontal_set(wd->ctxpopup, EINA_TRUE);
870 evas_object_size_hint_weight_set(wd->ctxpopup, EVAS_HINT_EXPAND,
872 evas_object_size_hint_align_set(wd->ctxpopup, EVAS_HINT_FILL,EVAS_HINT_FILL);
873 evas_object_smart_callback_add(wd->ctxpopup, "dismissed",
874 _ctxpopup_dismissed_cb, obj);
875 evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
876 _datefield_resize_cb, obj);
877 evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOVE,
878 _datefield_move_cb, obj);
879 _mirrored_set(obj, elm_widget_mirrored_get(obj));
885 * Set the format of datefield. Formats can be like "%b %d, %Y %I : %M %p".
886 * Maximum allowed format length is 32 chars.
887 * Format can include separators for each individual datefield item.
888 * Each separator can be a maximum of 6 UTF-8 bytes.
889 * Space is also taken as a separator.
890 * Following are the allowed set of format specifiers for each datefield item.
891 * These specifiers can be arranged at any order as per user requirement and
892 * their value will be replaced in the format as mentioned below.
893 * %Y : The year as a decimal number including the century.
894 * %y : The year as a decimal number without a century (range 00 to 99)
895 * %m : The month as a decimal number (range 01 to 12).
896 * %b : The abbreviated month name according to the current locale.
897 * %B : The full month name according to the current locale.
898 * %d : The day of the month as a decimal number (range 01 to 31).
899 * %I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
900 * %H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
901 * %k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
902 * digits are preceded by a blank.
903 * %l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
904 * digits are preceded by a blank.
905 * %M : The minute as a decimal number (range 00 to 59).
906 * %p : Either 'AM' or 'PM' according to the given time value, or the
907 * corresponding strings for the current locale. Noon is treated as 'PM'
908 * and midnight as 'AM'
909 * %P : Like %p but in lowercase: 'am' or 'pm' or a corresponding string for
910 * the current locale.
911 * Default format is taken as per the system display language and Region format.
913 * @param[in] obj The datefield object
914 * @param[in] fmt The date format
918 elm_datefield_format_set(Evas_Object *obj, const char *fmt)
920 ELM_CHECK_WIDTYPE(obj, widtype);
923 wd = elm_widget_data_get(obj);
928 strncpy( wd->format, fmt, MAX_FORMAT_LEN );
929 wd->user_format = EINA_TRUE;
931 else wd->user_format = EINA_FALSE;
937 * Get the format of datefield. Formats can be like "%b %d, %Y %I : %M %p".
938 * Maximum allowed format length is 32 chars.
939 * Format can include separators for each individual datefield item.
940 * Each separator can be a maximum of 6 UTF-8 bytes.
941 * Space is also taken as a separator.
942 * Following are the allowed set of format specifiers for each datefield item.
943 * These specifiers can be arranged at any order as per user requirement and
944 * their value will be replaced in the format as mentioned below.
945 * %Y : The year as a decimal number including the century.
946 * %y : The year as a decimal number without a century (range 00 to 99)
947 * %m : The month as a decimal number (range 01 to 12).
948 * %b : The abbreviated month name according to the current locale.
949 * %B : The full month name according to the current locale.
950 * %d : The day of the month as a decimal number (range 01 to 31).
951 * %I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
952 * %H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
953 * %k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
954 * digits are preceded by a blank.
955 * %l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
956 * digits are preceded by a blank.
957 * %M : The minute as a decimal number (range 00 to 59).
958 * %p : Either 'AM' or 'PM' according to the given time value, or the
959 * corresponding strings for the current locale. Noon is treated as 'PM'
960 * and midnight as 'AM'
961 * %P : Like %p but in lowercase: 'am' or 'pm' or a corresponding string for
962 * the current locale.
963 * Default format is taken as per the system display language and Region format.
965 * @param[in] obj The datefield object
966 * @return date format string. ex) %b %d, %Y %I : %M %p
970 elm_datefield_format_get(const Evas_Object *obj)
972 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
973 Widget_Data *wd = elm_widget_data_get(obj);
974 if (!wd ) return NULL;
975 return strdup(wd->format);
979 * @brief Set the selected value of the datefield
980 * Year : years since 1900. Negative value represents year below 1900. (
981 * year value -30 represents 1870). Year default range is from 70 to 137.
982 * Month value range is from 0 to 11
983 * Date value range is from 1 to 31 according to the month value.
984 * The hour value should be set according to 24hr format (0~23)
985 * Minute value range is from 0 to 59.
986 * AM/PM. Value 0 for AM and 1 for PM.
987 * If the value is beyond the range,
988 * a) Value is less than Min range value, then Min range value is set.
989 * b) Greater than Max range value, then Max Range value is set.
990 * Both Min and Max range of individual fields are bound to the current context.
992 * @param[in] obj The datefield object
993 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
994 * @param[in] value The data to be set. ex. year/month/date/hour/minute/ampm
999 elm_datefield_item_value_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1002 ELM_CHECK_WIDTYPE(obj, widtype);
1006 wd = elm_widget_data_get(obj);
1007 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1009 it = wd->item_list + itemtype;
1010 _field_value_set(obj, it->type, value, EINA_FALSE);
1014 * @brief Get Current value date of the datefield
1015 * Year : years since 1900. Negative value represents year below 1900. (
1016 * year value -30 represents 1870). Year default range is from 70 to 137.
1017 * Month value range is from 0 to 11
1018 * Date value range is from 1 to 31 according to the month value.
1019 * The hour value should be set according to 24hr format (0~23)
1020 * Minute value range is from 0 to 59.
1021 * AM/PM. Value 0 for AM and 1 for PM.
1022 * If the value is beyond the range,
1023 * a) Value is less than Min range value, then Min range value is set.
1024 * b) Greater than Max range value, then Max Range value is set.
1025 * Both Min and Max range of individual fields are bound to the current context.
1027 * @param[in] obj The datefield object
1028 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1029 * @return int The value of the field.
1031 * @ingroup Datefield
1034 elm_datefield_item_value_get(const Evas_Object *obj, Elm_Datefield_ItemType
1037 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1040 wd = elm_widget_data_get(obj);
1041 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1043 return (*(wd->item_list + itemtype)->value);
1048 * @brief Enable/Disable an item of the datefield
1050 * @param[in] obj The datefield object
1051 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1052 * @param[in] enable Item is Enabled or disabled.
1054 * @ingroup Datefield
1058 elm_datefield_item_enabled_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1061 ELM_CHECK_WIDTYPE(obj, widtype);
1065 wd = elm_widget_data_get(obj);
1066 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1068 it = wd->item_list + itemtype;
1069 if ( it->enabled == enable ) return;
1070 it->enabled = enable;
1071 _format_reload(obj);
1075 * @brief Get whether the item is Enabled/Disabled
1077 * @param[in] obj The datefield object
1078 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1079 * @return EINA_TRUE = Item is Enabled or EINA_FALSE = disabled.
1081 * @ingroup Datefield
1085 elm_datefield_item_enabled_get(const Evas_Object *obj, Elm_Datefield_ItemType itemtype)
1087 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1091 wd = elm_widget_data_get(obj);
1092 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1094 it = wd->item_list + itemtype;
1099 * @brief Get lower boundary of the datefield
1100 * Year : years since 1900. Negative value represents year below 1900. (
1101 * year value -30 represents 1870). Year default range is from 70 to 137.
1102 * Month default value range is from 0 to 11
1103 * Date default value range is from 1 to 31 according to the month value.
1104 * Hour default value will be in terms of 24 hr format (0~23)
1105 * Minute default value range will be from 0 to 59.
1106 * AM/PM. Value 0 for AM and 1 for PM.
1107 * If the value is beyond the range,
1108 * a) Value is less than Min range value, then Min range value is set.
1109 * b) Greater than Max range value, then Max Range value is set.
1110 * Both Min and Max range of individual fields are bound to the current context.
1112 * @param[in] obj The datefield object
1113 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1114 * @param[in] value The minimum value of the field that is to be set.
1115 * @ingroup Datefield
1118 elm_datefield_item_min_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1119 int value, Eina_Bool abs_limit)
1121 ELM_CHECK_WIDTYPE(obj, widtype);
1125 wd = elm_widget_data_get(obj);
1126 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1128 it = wd->item_list + itemtype;
1129 if ( it->type != ELM_DATEFIELD_YEAR && value < it->default_min )
1130 it->min = it->default_min;
1134 if(it->min > it->max ) it->max = it->min;
1135 it->abs_min = abs_limit;
1136 _field_value_set(obj, it->type, *(it->value), EINA_FALSE); // Trigger the validation
1140 * @brief Get lower boundary of the datefield
1141 * Year : years since 1900. Negative value represents year below 1900. (
1142 * year value -30 represents 1870). Year default range is from 70 to 137.
1143 * Year default range is from 70 to 137.
1144 * Month default value range is from 0 to 11
1145 * Date default value range is from 1 to 31 according to the month value.
1146 * Hour default value will be in terms of 24 hr format (0~23)
1147 * Minute default value range will be from 0 to 59.
1148 * AM/PM. Value 0 for AM and 1 for PM.
1149 * If the value is beyond the range,
1150 * a) Value is less than Min range value, then Min range value is set.
1151 * b) Greater than Max range value, then Max Range value is set.
1152 * Both Min and Max range of individual fields are bound to the current context.
1154 * @param[in] obj The datefield object
1155 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1156 * @return int The minimum value of the field.
1158 * @ingroup Datepicker
1161 elm_datefield_item_min_get(const Evas_Object *obj, Elm_Datefield_ItemType
1164 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1167 wd = elm_widget_data_get(obj);
1168 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1170 return ((wd->item_list + itemtype)->min);
1174 * @brief Get whether the minimum value of the item is absolute or not
1176 * @param[in] obj The datefield object
1177 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1178 * @return EINA_TRUE = Minimim is absolute or EINA_FALSE = Minimum is relative.
1180 * @ingroup Datefield
1184 elm_datefield_item_min_is_absolute(const Evas_Object *obj,
1185 Elm_Datefield_ItemType itemtype)
1187 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1190 wd = elm_widget_data_get(obj);
1191 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1193 return ((wd->item_list + itemtype)->abs_min);
1197 * @brief Set upper boundary of the datefield
1198 * Year : years since 1900. Negative value represents year below 1900. (
1199 * year value -30 represents 1870). Year default range is from 70 to 137.
1200 * Month:default value range is from 0 to 11
1201 * Date : default value range is from 1 to 31 according to the month value.
1202 * Hour : default value will be in terms of 24 hr format (0~23)
1203 * Minute : default value range will be from 0 to 59.
1204 * AM/PM: Value 0 for AM and 1 for PM.
1205 * If the value is beyond the contextual range,
1206 * a) Value is less than Min range value, then Min range value is set.
1207 * b) Greater than Max range value, then Max Range value is set.
1208 * Both Min and Max range of individual fields are bound to the current context.
1210 * @param[in] obj The datefield object
1211 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1212 * @param[in] value The maximum field value that is to be set.
1214 * @ingroup Datefield
1217 elm_datefield_item_max_set(Evas_Object *obj, Elm_Datefield_ItemType itemtype,
1218 int value, Eina_Bool abs_limit )
1220 ELM_CHECK_WIDTYPE(obj, widtype);
1224 wd = elm_widget_data_get(obj);
1225 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return;
1227 it = wd->item_list + itemtype;
1228 if (it->type != ELM_DATEFIELD_YEAR && value > it->default_max )
1229 it->max = it->default_max;
1233 if(it->max < it->min) it->min = it->max;
1234 it->abs_max = abs_limit;
1236 _field_value_set(obj, it->type, *(it->value), EINA_FALSE); // Trigger the validation
1240 * @brief Get upper boundary of the datefield
1241 * Year : years since 1900. Negative value represents year below 1900. (
1242 * year value -30 represents 1870). Year default range is from 70 to 137.
1243 * Month default value range is from 0 to 11
1244 * Date default value range is from 1 to 31 according to the month value.
1245 * Hour default value will be in terms of 24 hr format (0~23)
1246 * Minute default value range will be from 0 to 59.
1247 * AM/PM. Value 0 for AM and 1 for PM.
1248 * If the value is beyond the range,
1249 * a) Value is less than Min range value, then Min range value is set.
1250 * b) Greater than Max range value, then Max Range value is set.
1251 * Both Min and Max range of individual fields are bound to the current context.
1253 * @param[in] obj The datefield object
1254 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1255 * @return int The maximum value of the field.
1257 * @ingroup Datefield
1260 elm_datefield_item_max_get(const Evas_Object *obj, Elm_Datefield_ItemType
1263 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1266 wd = elm_widget_data_get(obj);
1267 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return -1;
1269 return ((wd->item_list + itemtype)->max);
1273 * @brief Get whether the max value of the item is absolute or not
1275 * @param[in] obj The datefield object
1276 * @param[in] itemtype The field type of datefield. ELM_DATEFIELD_YEAR etc.
1277 * @return EINA_TRUE = Max is absolute or EINA_FALSE = Max is relative.
1279 * @ingroup Datefield
1283 elm_datefield_item_max_is_absolute(const Evas_Object *obj,
1284 Elm_Datefield_ItemType itemtype)
1286 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1289 wd = elm_widget_data_get(obj);
1290 if (!wd || itemtype > ELM_DATEFIELD_AMPM ) return EINA_FALSE;
1292 return ((wd->item_list + itemtype)->abs_max);