[elm_datetime] Popup module bug fix: If picker popup is not created, no need to creat...
[framework/uifw/elementary.git] / src / modules / datetime_input_popup / datetime_input_popup.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define DATETIME_FIELD_COUNT            6
5 #define BUFF_SIZE                       1024
6 #define MONTH_STRING_MAX_SIZE           32
7 #define TOTAL_NUMBER_OF_MONTHS          12
8 #define STRUCT_TM_YEAR_BASE_VALUE       1900
9 #define STRUCT_TM_TIME_12HRS_MAX_VALUE  12
10 #define STRUCT_TM_TIME_24HRS_MAX_VALUE  23
11 #define PICKER_POPUP_FIELD_COUNT        3
12
13 /* struct tm does not define the fields in the order year, month,
14  * date, hour, minute. values are reassigned to an array for easy
15  * handling.
16  */
17 #define DATETIME_MODULE_TM_ARRAY(intptr, tmptr) \
18   int *intptr[] = {                             \
19      &(tmptr)->tm_year,                         \
20      &(tmptr)->tm_mon,                          \
21      &(tmptr)->tm_mday,                         \
22      &(tmptr)->tm_hour,                         \
23      &(tmptr)->tm_min}
24
25 static const char *field_styles[] = {
26                          "year", "month", "date", "hour", "minute", "ampm" };
27
28 static char month_arr[TOTAL_NUMBER_OF_MONTHS][MONTH_STRING_MAX_SIZE];
29
30 static const char SIG_EDIT_START[] = "edit,start";
31 static const char SIG_EDIT_END[] = "edit,end";
32 static const char SIG_PICKER_VALUE_SET[] = "picker,value,set";
33
34 typedef struct _Popup_Module_Data Popup_Module_Data;
35
36 struct _Popup_Module_Data
37 {
38    Elm_Datetime_Module_Data mod_data;
39    Evas_Object *popup;
40    Evas_Object *datepicker_layout, *timepicker_layout;
41    Evas_Object *popup_field[DATETIME_FIELD_COUNT];
42    int field_location[PICKER_POPUP_FIELD_COUNT];
43    Evas_Object *datetime_field[DATETIME_FIELD_COUNT];
44    struct tm set_time;
45    Eina_Bool time_12hr_fmt;
46    Eina_Bool is_pm;
47    Eina_Bool weekday_show;
48    Eina_Bool weekday_loc_first;
49 };
50
51 EAPI void field_value_display(Elm_Datetime_Module_Data *module_data, Evas_Object *obj);
52
53 static int
54 _picker_nextfield_location_get(void *data, int curr)
55 {
56    int idx, next_idx;
57    Popup_Module_Data *popup_mod;
58    popup_mod = (Popup_Module_Data *)data;
59    if (!popup_mod) return ELM_DATETIME_LAST;
60
61    for (idx = 0; idx < PICKER_POPUP_FIELD_COUNT; idx++)
62      if (popup_mod->field_location[idx] == curr) break;
63    if (idx < ELM_DATETIME_DATE)
64      {
65         next_idx = popup_mod->field_location[++idx];
66         return next_idx;
67      }
68    else return ELM_DATETIME_LAST;
69 }
70
71 static int
72 _picker_field_location_get(void *data, int curr)
73 {
74    int idx;
75    Popup_Module_Data *popup_mod;
76    popup_mod = (Popup_Module_Data *)data;
77    if (!popup_mod) return ELM_DATETIME_LAST;
78
79    for (idx = 0; idx < PICKER_POPUP_FIELD_COUNT; idx++)
80      if (popup_mod->field_location[idx] == curr) break;
81
82    return idx;
83 }
84
85 static void
86 _picker_hide_cb(void *data,
87                 Evas_Object *obj __UNUSED__,
88                 const char *emission __UNUSED__,
89                 const char *source __UNUSED__)
90 {
91    Popup_Module_Data *popup_mod;
92    popup_mod = (Popup_Module_Data *)data;
93    if (!popup_mod) return;
94
95    evas_object_smart_callback_call(obj, SIG_EDIT_END, NULL);
96    evas_object_hide(popup_mod->popup);
97 }
98
99 static void
100 _datetime_press_cb(void *data,
101                    Evas_Object *obj __UNUSED__,
102                    const char *emission __UNUSED__,
103                    const char *source)
104 {
105    Popup_Module_Data *popup_mod;
106    int idx;
107
108    popup_mod = (Popup_Module_Data *)data;
109    if (!popup_mod) return;
110
111    if (!strcmp(source, "date.picker.bg"))
112      {
113         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
114            elm_object_signal_emit(popup_mod->datetime_field[idx], "elm,state,select", "elm");
115      }
116    else if (!strcmp(source, "time.picker.bg"))
117      {
118         for (idx = ELM_DATETIME_HOUR; idx < DATETIME_FIELD_COUNT; idx++)
119            elm_object_signal_emit(popup_mod->datetime_field[idx], "elm,state,select", "elm");
120      }
121 }
122
123 static void
124 _datetime_unpress_cb(void *data,
125                      Evas_Object *obj __UNUSED__,
126                      const char *emission __UNUSED__,
127                      const char *source)
128 {
129    Popup_Module_Data *popup_mod;
130    int idx;
131
132    popup_mod = (Popup_Module_Data *)data;
133    if (!popup_mod) return;
134
135    if (!strcmp(source, "date.picker.bg"))
136      {
137         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
138            elm_object_signal_emit(popup_mod->datetime_field[idx], "elm,state,unselect", "elm");
139      }
140    else if (!strcmp(source, "time.picker.bg"))
141      {
142         for (idx = ELM_DATETIME_HOUR; idx < DATETIME_FIELD_COUNT; idx++)
143            elm_object_signal_emit(popup_mod->datetime_field[idx], "elm,state,unselect", "elm");
144      }
145 }
146
147 static void
148 _set_datepicker_value(Popup_Module_Data *popup_mod)
149 {
150    struct tm set_time;
151
152    if (!popup_mod) return;
153
154    elm_datetime_value_get(popup_mod->mod_data.base, &set_time);
155    set_time.tm_year = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_YEAR]) - STRUCT_TM_YEAR_BASE_VALUE;
156    set_time.tm_mon = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_MONTH]) - 1;
157    set_time.tm_mday = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_DATE]);
158    elm_datetime_value_set(popup_mod->mod_data.base, &set_time);
159 }
160
161 static void
162 _set_timepicker_value(Popup_Module_Data *popup_mod)
163 {
164    struct tm set_time;
165    int hour;
166
167    if (!popup_mod) return;
168
169    elm_datetime_value_get(popup_mod->mod_data.base, &set_time);
170
171    hour = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_HOUR]);
172    if (popup_mod->time_12hr_fmt)
173      {
174         if (popup_mod->is_pm)
175           hour += STRUCT_TM_TIME_12HRS_MAX_VALUE;
176         hour = (hour == STRUCT_TM_TIME_12HRS_MAX_VALUE) ? 0 : hour;
177         hour = (hour == 24) ? STRUCT_TM_TIME_12HRS_MAX_VALUE : hour;
178      }
179    set_time.tm_hour = hour;
180    set_time.tm_min = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_MINUTE]);
181    elm_datetime_value_set(popup_mod->mod_data.base, &set_time);
182 }
183
184 static void
185 _popup_set_btn_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
186 {
187    Popup_Module_Data *popup_mod;
188    Evas_Object *content, *widget;
189    int idx = 0;
190    Evas_Object *spinner, *entry;
191
192    popup_mod = (Popup_Module_Data *)data;
193    if (!popup_mod) return;
194
195    widget = popup_mod->mod_data.base;
196    if (widget)
197      evas_object_smart_callback_call(widget, SIG_EDIT_END, NULL);
198
199    evas_object_hide(popup_mod->popup);
200    content = elm_object_content_get(popup_mod->popup);
201    if (content == popup_mod->datepicker_layout)
202      {
203         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
204           {
205              spinner = popup_mod->popup_field[idx];
206              entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
207              if (!entry) continue;
208              if (elm_object_focus_get(entry))
209                {
210                   elm_layout_signal_emit(spinner, "elm,action,entry,toggle", "elm");
211                   edje_object_message_signal_process(elm_layout_edje_get(spinner));
212                }
213           }
214         _set_datepicker_value(popup_mod);
215      }
216    else if (content == popup_mod->timepicker_layout)
217      {
218         for (idx = ELM_DATETIME_HOUR; idx < ELM_DATETIME_AMPM; idx++)
219           {
220              spinner = popup_mod->popup_field[idx];
221              entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
222              if (!entry) continue;
223              if (elm_object_focus_get(entry))
224                {
225                   elm_layout_signal_emit(spinner, "elm,action,entry,toggle", "elm");
226                   edje_object_message_signal_process(elm_layout_edje_get(spinner));
227                }
228           }
229         _set_timepicker_value(popup_mod);
230      }
231
232    evas_object_smart_callback_call(popup_mod->mod_data.base, SIG_PICKER_VALUE_SET, NULL);
233 }
234
235 static void
236 _popup_cancel_btn_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
237 {
238    Popup_Module_Data *popup_mod;
239    Evas_Object *content, *widget;
240    int idx = 0;
241    Evas_Object *spinner, *entry;
242
243    popup_mod = (Popup_Module_Data *)data;
244    if (!popup_mod) return;
245
246    widget = popup_mod->mod_data.base;
247    if (widget)
248      evas_object_smart_callback_call(widget, SIG_EDIT_END, NULL);
249
250    evas_object_hide(popup_mod->popup);
251    content = elm_object_content_get(popup_mod->popup);
252    if (content == popup_mod->datepicker_layout)
253      {
254         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
255           {
256              spinner = popup_mod->popup_field[idx];
257              entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
258              if (!entry) continue;
259              if (elm_object_focus_get(entry))
260                {
261                   elm_layout_signal_emit(spinner, "elm,action,entry,toggle", "elm");
262                }
263           }
264      }
265    else if (content == popup_mod->timepicker_layout)
266      {
267         for (idx = ELM_DATETIME_HOUR; idx < ELM_DATETIME_AMPM; idx++)
268           {
269              spinner = popup_mod->popup_field[idx];
270              entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
271              if (!entry) continue;
272              if (elm_object_focus_get(entry))
273                {
274                   elm_layout_signal_emit(spinner, "elm,action,entry,toggle", "elm");
275                }
276           }
277      }
278 }
279
280 static void
281 _picker_hide_cb(void *data,
282                    Evas_Object *obj __UNUSED__,
283                    const char *emission __UNUSED__,
284                    const char *source __UNUSED__)
285 {
286    Popup_Module_Data *popup_mod;
287    popup_mod = (Popup_Module_Data *)data;
288    if (!popup_mod) return;
289
290    evas_object_smart_callback_call(obj, SIG_EDIT_END, NULL);
291    evas_object_hide(popup_mod->popup);
292 }
293
294 static void
295 _entry_activated_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
296 {
297    Popup_Module_Data *popup_mod;
298    Evas_Object *entry, *en;
299    int idx, next_idx;
300
301    popup_mod = (Popup_Module_Data *)data;
302    if (!popup_mod) return;
303
304    for (idx = 0; idx < PICKER_POPUP_FIELD_COUNT; idx++)
305      {
306         entry = elm_object_part_content_get(popup_mod->popup_field[idx], "elm.swallow.entry");
307         if (obj == entry)
308           {
309              next_idx = _picker_nextfield_location_get(popup_mod, idx);
310              if (next_idx != ELM_DATETIME_LAST)
311                elm_layout_signal_emit(popup_mod->popup_field[next_idx], "elm,action,entry,toggle", "elm");
312              return;
313           }
314      }
315    entry = elm_object_part_content_get(popup_mod->popup_field[ELM_DATETIME_HOUR], "elm.swallow.entry");
316    if (obj == entry)
317      {
318         en = elm_object_part_content_get(popup_mod->popup_field[ELM_DATETIME_MINUTE], "elm.swallow.entry");
319         elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_MINUTE],
320                                "elm,action,entry,toggle", "elm");
321      }
322 }
323
324 static void
325 _entry_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
326 {
327    Popup_Module_Data *popup_mod;
328
329    popup_mod = (Popup_Module_Data *)data;
330    if (!popup_mod || !obj) return;
331 }
332
333 static void
334 _entry_focused_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
335 {
336    Popup_Module_Data *popup_mod;
337    Evas_Object *entry;
338    int idx, value;
339
340    popup_mod = (Popup_Module_Data *)data;
341    if (!popup_mod) return;
342
343    entry = elm_object_part_content_get(popup_mod->popup_field[ELM_DATETIME_MONTH],
344                                        "elm.swallow.entry");
345    if (obj == entry)
346      {
347         value = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_MONTH]) - 1;
348         elm_object_text_set(obj, month_arr[value]);
349      }
350    for (idx = 0; idx < DATETIME_FIELD_COUNT -1; idx++)
351      {
352         entry = elm_object_part_content_get(popup_mod->popup_field[idx], "elm.swallow.entry");
353         if ((obj != entry) && elm_object_focus_get(entry))
354           {
355              elm_layout_signal_emit(popup_mod->popup_field[idx],
356                                     "elm,action,entry,toggle", "elm");
357              return;
358           }
359      }
360 }
361
362 static void
363 _entry_unfocused_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
364 {
365    Popup_Module_Data *popup_mod;
366
367    popup_mod = (Popup_Module_Data *)data;
368    if (!popup_mod) return;
369
370    // TODO: entry_unfocused code
371 }
372
373 void
374 _set_datepicker_popup_title_text(Popup_Module_Data *popup_mod)
375 {
376    struct tm set_time;
377    time_t t;
378    char weekday[BUFF_SIZE];
379    if (!popup_mod) return;
380
381    t = time(NULL);
382    localtime_r(&t, &set_time);
383    set_time.tm_year = (popup_mod->set_time).tm_year;
384    set_time.tm_mon = (popup_mod->set_time).tm_mon;
385    set_time.tm_mday = (popup_mod->set_time).tm_mday;
386    /* FIXME: To restrict month wrapping because of summer time in some locales,
387     * ignore day light saving mode in mktime(). */
388    set_time.tm_isdst = -1;
389    mktime(&set_time);
390    strftime(weekday, BUFF_SIZE, "%a", &set_time);
391    elm_object_part_text_set(popup_mod->popup, "elm.text.title2", weekday);
392
393    elm_object_domain_translatable_part_text_set(popup_mod->popup, "title,text", PACKAGE, E_("Set date"));
394 }
395
396 void
397 _set_timepicker_popup_title_text(Popup_Module_Data *popup_mod)
398 {
399    if (!popup_mod) return;
400
401    elm_object_domain_translatable_part_text_set(popup_mod->popup, "title,text", PACKAGE, E_("Set time"));
402    elm_object_part_text_set(popup_mod->popup, "elm.text.title2", "");
403 }
404
405 static void
406 _set_ampm_value(Popup_Module_Data *popup_mod)
407 {
408    char ampm_str[BUFF_SIZE] = {0,};
409    const char *fmt = NULL;
410
411    if (!popup_mod || !popup_mod->time_12hr_fmt) return;
412
413    fmt = popup_mod->mod_data.field_format_get(popup_mod->mod_data.base,
414                                               ELM_DATETIME_AMPM);
415    strftime(ampm_str, BUFF_SIZE, fmt, &(popup_mod->set_time));
416    if (ampm_str[0])
417      elm_object_text_set(popup_mod->popup_field[ELM_DATETIME_AMPM], ampm_str);
418    else if (popup_mod->set_time.tm_hour < STRUCT_TM_TIME_12HRS_MAX_VALUE)
419      elm_object_domain_translatable_text_set(popup_mod->popup_field[ELM_DATETIME_AMPM],
420                                              PACKAGE, E_("AM"));
421    else
422      elm_object_domain_translatable_text_set(popup_mod->popup_field[ELM_DATETIME_AMPM],
423                                              PACKAGE, E_("PM"));
424 }
425
426 static void
427 _datepicker_value_changed_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
428 {
429    Popup_Module_Data *popup_mod;
430    struct tm min_values, max_values;
431    int idx, field_idx, min, max;
432
433    popup_mod = (Popup_Module_Data *)data;
434    if (!popup_mod) return;
435
436    for (idx = 0; idx < DATETIME_FIELD_COUNT; idx++)
437      if ((obj == popup_mod->popup_field[idx])) break;
438
439    if (idx > ELM_DATETIME_DATE) return;
440
441    field_idx = idx;
442    DATETIME_MODULE_TM_ARRAY(set_val_arr, &popup_mod->set_time);
443    if (field_idx == ELM_DATETIME_YEAR)
444      *set_val_arr[field_idx] = (int)elm_spinner_value_get(obj) - STRUCT_TM_YEAR_BASE_VALUE;
445    else if (field_idx == ELM_DATETIME_MONTH)
446      *set_val_arr[field_idx] = (int)elm_spinner_value_get(obj) - 1;
447    else
448      *set_val_arr[field_idx] = (int)elm_spinner_value_get(obj);
449
450    popup_mod->mod_data.fields_min_max_get(popup_mod->mod_data.base,
451                        &(popup_mod->set_time), &min_values, &max_values);
452
453    DATETIME_MODULE_TM_ARRAY(min_val_arr, &min_values);
454    DATETIME_MODULE_TM_ARRAY(max_val_arr, &max_values);
455
456    for (idx = field_idx; idx <= ELM_DATETIME_DATE; idx++)
457      {
458         min = *min_val_arr[idx];
459         max = *max_val_arr[idx];
460         if (idx == ELM_DATETIME_YEAR)
461           {
462              min += STRUCT_TM_YEAR_BASE_VALUE;
463              max += STRUCT_TM_YEAR_BASE_VALUE;
464           }
465         else if (idx == ELM_DATETIME_MONTH)
466           {
467              min += 1;
468              max += 1;
469           }
470         elm_spinner_min_max_set(popup_mod->popup_field[idx], min, max);
471      }
472    for (idx = field_idx; idx <= ELM_DATETIME_DATE; idx++)
473      {
474         if (idx == ELM_DATETIME_YEAR)
475           *set_val_arr[idx] = (int)elm_spinner_value_get(popup_mod->popup_field[idx]) - STRUCT_TM_YEAR_BASE_VALUE;
476         else if (idx == ELM_DATETIME_MONTH)
477           *set_val_arr[idx] = (int)elm_spinner_value_get(popup_mod->popup_field[idx]) - 1;
478         else
479           *set_val_arr[idx] = (int)elm_spinner_value_get(popup_mod->popup_field[idx]);
480      }
481
482    _set_datepicker_popup_title_text(popup_mod);
483 }
484
485 static void
486 _timepicker_value_changed_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
487 {
488    Popup_Module_Data *popup_mod;
489    struct tm min_values, max_values;
490    int hour;
491
492    popup_mod = (Popup_Module_Data *)data;
493    if (!popup_mod) return;
494
495    if (obj == popup_mod->popup_field[ELM_DATETIME_HOUR])
496      {
497         hour = (int)elm_spinner_value_get(obj);
498         if (popup_mod->time_12hr_fmt && popup_mod->is_pm)
499           {
500              if (hour != STRUCT_TM_TIME_12HRS_MAX_VALUE)
501                hour += STRUCT_TM_TIME_12HRS_MAX_VALUE;
502              else
503                hour = 0;
504           }
505         (popup_mod->set_time).tm_hour = hour;
506         popup_mod->mod_data.fields_min_max_get(popup_mod->mod_data.base,
507                             &(popup_mod->set_time), &min_values, &max_values);
508         elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_MINUTE],
509                                 min_values.tm_min, max_values.tm_min);
510         (popup_mod->set_time).tm_min = (int)elm_spinner_value_get(
511                                  popup_mod->popup_field[ELM_DATETIME_MINUTE]);
512         popup_mod->is_pm = (hour < STRUCT_TM_TIME_12HRS_MAX_VALUE) ? 0 : 1;
513         _set_ampm_value(popup_mod);
514      }
515    else if (obj == popup_mod->popup_field[ELM_DATETIME_MINUTE])
516      (popup_mod->set_time).tm_min = (int)elm_spinner_value_get(obj);
517
518 }
519
520 static void
521 _ampm_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
522 {
523    Popup_Module_Data *popup_mod;
524    int hour;
525
526    popup_mod = (Popup_Module_Data *)data;
527    if (!popup_mod || !popup_mod->time_12hr_fmt) return;
528
529    hour = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_HOUR]);
530    if (popup_mod->time_12hr_fmt && popup_mod->is_pm && (hour != STRUCT_TM_TIME_12HRS_MAX_VALUE))
531      hour += STRUCT_TM_TIME_12HRS_MAX_VALUE;
532
533    if (hour > STRUCT_TM_TIME_12HRS_MAX_VALUE)
534      hour -= STRUCT_TM_TIME_12HRS_MAX_VALUE;
535    else if (hour < STRUCT_TM_TIME_12HRS_MAX_VALUE)
536      hour += STRUCT_TM_TIME_12HRS_MAX_VALUE;
537    else
538      {
539         if (popup_mod->is_pm) hour = 0;
540         else hour = STRUCT_TM_TIME_12HRS_MAX_VALUE;
541      }
542
543    (popup_mod->set_time).tm_hour = hour;
544    popup_mod->is_pm = (hour < STRUCT_TM_TIME_12HRS_MAX_VALUE) ? 0 : 1;
545    _set_ampm_value(popup_mod);
546 }
547
548 const char *
549 _text_insert(const char *text, char *input, int pos)
550 {
551    char *result;
552    int text_len, input_len;
553
554    text_len = strlen(text);
555    input_len = strlen(input);
556    result = (char *)malloc(sizeof(char) * (text_len + input_len) + 1);
557    memset(result, 0, sizeof(char) * (text_len + input_len) + 1);
558
559    strncpy(result, text, pos);
560    strcpy(result + pos, input);
561    strcpy(result + pos + input_len, text + pos);
562
563    return (const char *)result;
564 }
565
566 static void
567 _year_validity_checking_filter(void *data, Evas_Object *obj, char **text)
568 {
569    Popup_Module_Data *popup_mod;
570    Evas_Object *entry;
571    const char *new_str = NULL;
572    int min, max, val = 0, len;
573    char *insert;
574    const char *curr_str;
575    int next_idx = 0;
576
577    EINA_SAFETY_ON_NULL_RETURN(text);
578    popup_mod = (Popup_Module_Data *)data;
579    if (!popup_mod) return;
580
581    insert = *text;
582    len = strlen(elm_object_text_get(obj));
583    if (len < 3) return;
584
585    curr_str = elm_object_text_get(obj);
586    if (curr_str) new_str = _text_insert(curr_str, insert, elm_entry_cursor_pos_get(obj));
587    if (new_str) val = atoi(new_str);
588
589    popup_mod->mod_data.field_limit_get(popup_mod->mod_data.base, ELM_DATETIME_YEAR, &min, &max);
590    min += STRUCT_TM_YEAR_BASE_VALUE;
591    max += STRUCT_TM_YEAR_BASE_VALUE;
592
593    if (val <= max)
594      {
595         elm_entry_entry_set(obj, new_str);
596         elm_entry_cursor_end_set(obj);
597         next_idx = _picker_nextfield_location_get(popup_mod, ELM_DATETIME_YEAR);
598         if (next_idx != ELM_DATETIME_LAST)
599           {
600              elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_YEAR],
601                                     "elm,action,entry,toggle", "elm");
602              entry = elm_object_part_content_get(popup_mod->popup_field[next_idx],
603                                                 "elm.swallow.entry");
604              if (!elm_object_focus_get(entry))
605                elm_layout_signal_emit(popup_mod->popup_field[next_idx],
606                                       "elm,action,entry,toggle", "elm");
607          }
608      }
609
610    *insert = 0;
611    free((void *)new_str);
612    new_str = NULL;
613 }
614
615 static void
616 _month_validity_checking_filter(void *data, Evas_Object *obj, char **text)
617 {
618    Popup_Module_Data *popup_mod;
619    Evas_Object *entry;
620    const char *new_str = NULL;
621    double min, max;
622    int val = 0, len, max_digits;
623    char *insert;
624    const char *curr_str;
625    int next_idx = 0;
626
627    EINA_SAFETY_ON_NULL_RETURN(text);
628    popup_mod = (Popup_Module_Data *)data;
629    if (!popup_mod) return;
630
631    insert = *text;
632    len = strlen(elm_object_text_get(obj));
633    curr_str = elm_object_text_get(obj);
634    if (curr_str) new_str = _text_insert(curr_str, insert, elm_entry_cursor_pos_get(obj));
635    if (new_str) val = atoi(new_str) - 1;
636
637    elm_spinner_min_max_get(popup_mod->popup_field[ELM_DATETIME_MONTH], &min, &max);
638    min -= 1;
639    max -= 1;
640
641    max_digits = (max >= 10 ? 2 : 1);
642    if (len < 1 && max_digits > 1 && val < 1) return;
643
644    if ((val >= min) && (val <= max))
645      {
646         elm_entry_entry_set(obj, new_str);
647         elm_entry_cursor_end_set(obj);
648         next_idx = _picker_nextfield_location_get(popup_mod, ELM_DATETIME_MONTH);
649         if (next_idx != DATETIME_FIELD_COUNT)
650           {
651              elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_MONTH],
652                                     "elm,action,entry,toggle", "elm");
653              entry = elm_object_part_content_get(popup_mod->popup_field[next_idx],
654                                                  "elm.swallow.entry");
655              if (!elm_object_focus_get(entry))
656                elm_layout_signal_emit(popup_mod->popup_field[next_idx],
657                                       "elm,action,entry,toggle", "elm");
658          }
659      }
660    *insert = 0;
661    free((void *)new_str);
662    new_str = NULL;
663 }
664
665 static void
666 _hour_validity_checking_filter(void *data, Evas_Object *obj, char **text)
667 {
668    Popup_Module_Data *popup_mod;
669    Evas_Object *entry;
670    const char *new_str = NULL;
671    int val = 0, len;
672    char *insert;
673    const char *curr_str;
674
675    EINA_SAFETY_ON_NULL_RETURN(text);
676
677    popup_mod = (Popup_Module_Data *)data;
678    if (!popup_mod) return;
679
680    insert = *text;
681    len = strlen(elm_object_text_get(obj));
682    if (len < 1) return;
683
684    curr_str = elm_object_text_get(obj);
685    if (curr_str) new_str = _text_insert(curr_str, insert, elm_entry_cursor_pos_get(obj));
686    if (new_str) val = atoi(new_str);
687
688    if (popup_mod->time_12hr_fmt && val > STRUCT_TM_TIME_12HRS_MAX_VALUE)
689      {
690         *insert = 0;
691         free((void *)new_str);
692         new_str = NULL;
693         return;
694      }
695    else if (!popup_mod->time_12hr_fmt && val > STRUCT_TM_TIME_24HRS_MAX_VALUE)
696      {
697         *insert = 0;
698         free((void *)new_str);
699         new_str = NULL;
700         return;
701      }
702    elm_entry_entry_set(obj, new_str);
703    elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_HOUR],
704                           "elm,action,entry,toggle", "elm");
705
706     entry = elm_object_part_content_get(popup_mod->popup_field[ELM_DATETIME_MINUTE],
707                                                  "elm.swallow.entry");
708     if (!elm_object_focus_get(entry))
709       {
710          elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_MINUTE],
711                                          "elm,action,entry,toggle", "elm");
712       }
713     *insert = 0;
714     free((void *)new_str);
715     new_str = NULL;
716 }
717
718 static void
719 _date_validity_checking_filter(void *data, Evas_Object *obj, char **text)
720 {
721    Popup_Module_Data *popup_mod;
722    Evas_Object *entry;
723    const char *new_str = NULL;
724    int val = 0, len;
725    const char *curr_str;
726    char *insert;
727    double min, max;
728
729    EINA_SAFETY_ON_NULL_RETURN(text);
730    popup_mod = (Popup_Module_Data *)data;
731    if (!popup_mod) return;
732
733    insert = *text;
734    len = strlen(elm_object_text_get(obj));
735    if (len < 1) return;
736
737    curr_str = elm_object_text_get(obj);
738    if (curr_str) new_str = _text_insert(curr_str, insert, elm_entry_cursor_pos_get(obj));
739    if (new_str) val = atoi(new_str);
740    elm_spinner_min_max_get(popup_mod->popup_field[ELM_DATETIME_DATE], &min, &max);
741
742    if ((val >= min) && (val <= max))
743      {
744        elm_entry_entry_set(obj, new_str);
745        elm_entry_cursor_end_set(obj);
746        next_idx = _picker_nextfield_location_get(popup_mod, ELM_DATETIME_DATE);
747        if (next_idx != ELM_DATETIME_LAST)
748          {
749             elm_layout_signal_emit(popup_mod->popup_field[ELM_DATETIME_DATE],
750                                    "elm,action,entry,toggle", "elm");
751             entry = elm_object_part_content_get(popup_mod->popup_field[next_idx],
752                                                 "elm.swallow.entry");
753             if (!elm_object_focus_get(entry))
754               elm_layout_signal_emit(popup_mod->popup_field[next_idx],
755                                         "elm,action,entry,toggle", "elm");
756          }
757      }
758    *insert = 0;
759    free((void *)new_str);
760    new_str = NULL;
761 }
762
763 static void
764 _minute_validity_checking_filter(void *data, Evas_Object *obj, char **text)
765 {
766    Popup_Module_Data *popup_mod;
767    const char *new_str = NULL;
768    int min, max, val = 0, len;
769    char *insert;
770    const char *curr_str;
771
772    EINA_SAFETY_ON_NULL_RETURN(text);
773    popup_mod = (Popup_Module_Data *)data;
774    if (!popup_mod) return;
775
776    insert = *text;
777    len = strlen(elm_object_text_get(obj));
778    if (len < 1) return;
779
780    curr_str = elm_object_text_get(obj);
781    if (curr_str) new_str = _text_insert(curr_str, insert, elm_entry_cursor_pos_get(obj));
782    if (new_str) val = atoi(new_str);
783
784    popup_mod->mod_data.field_limit_get(popup_mod->mod_data.base, ELM_DATETIME_MINUTE, &min, &max);
785
786    if ((val >= min) && (val <= max))
787      {
788        elm_entry_entry_set(obj, new_str);
789        elm_entry_cursor_end_set(obj);
790      }
791    *insert = 0;
792    free((void *)new_str);
793    new_str = NULL;
794 }
795
796 static void
797 _set_datepicker_entry_filter(Popup_Module_Data *popup_mod)
798 {
799    Evas_Object *spinner, *entry;
800    static Elm_Entry_Filter_Accept_Set digits_filter_data;
801    static Elm_Entry_Filter_Limit_Size limit_filter_data;
802    char buf[BUFF_SIZE];
803    int idx, value;
804
805    if (!popup_mod) return;
806
807    digits_filter_data.accepted = "0123456789";
808    digits_filter_data.rejected = NULL;
809
810    limit_filter_data.max_byte_count = 0;
811
812    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
813      {
814        spinner = popup_mod->popup_field[idx];
815        entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
816        if (!entry) continue;
817
818        snprintf(buf, sizeof(buf), "datetime_popup/%s", field_styles[idx]);
819        elm_object_style_set(entry, buf);
820        elm_entry_magnifier_disabled_set(entry, EINA_TRUE);
821        elm_entry_context_menu_disabled_set(entry, EINA_TRUE);
822
823        if (idx == ELM_DATETIME_MONTH)
824          {
825             value = (int)elm_spinner_value_get(popup_mod->popup_field[ELM_DATETIME_MONTH]) - 1;
826             elm_object_text_set(entry, month_arr[value]);
827          }
828
829        elm_entry_markup_filter_append(entry, elm_entry_filter_accept_set, &digits_filter_data);
830
831        elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_DATETIME);
832
833        if (idx == ELM_DATETIME_YEAR)
834          limit_filter_data.max_char_count = 4;
835        else
836          limit_filter_data.max_char_count = 2;
837
838        elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &limit_filter_data);
839
840        evas_object_smart_callback_add(entry, "focused", _entry_focused_cb, popup_mod);
841        evas_object_smart_callback_add(entry, "unfocused", _entry_unfocused_cb, popup_mod);
842        evas_object_smart_callback_add(entry, "activated", _entry_activated_cb, popup_mod);
843        evas_object_smart_callback_add(entry, "clicked", _entry_clicked_cb, popup_mod);
844
845        if (idx == ELM_DATETIME_YEAR)
846          elm_entry_markup_filter_append(entry, _year_validity_checking_filter, popup_mod);
847        else if (idx == ELM_DATETIME_MONTH)
848          elm_entry_markup_filter_append(entry, _month_validity_checking_filter, popup_mod);
849        else if (idx == ELM_DATETIME_DATE)
850          elm_entry_markup_filter_append(entry, _date_validity_checking_filter, popup_mod);
851      }
852 }
853
854 static void
855 _set_timepicker_entry_filter(Popup_Module_Data *popup_mod)
856 {
857    Evas_Object *spinner, *entry;
858    static Elm_Entry_Filter_Accept_Set digits_filter_data;
859    static Elm_Entry_Filter_Limit_Size limit_filter_data;
860    char buf[BUFF_SIZE];
861    int idx;
862
863    if (!popup_mod) return;
864
865    digits_filter_data.accepted = "0123456789";
866    digits_filter_data.rejected = NULL;
867
868    limit_filter_data.max_byte_count = 0;
869
870    for (idx = ELM_DATETIME_HOUR; idx < ELM_DATETIME_AMPM; idx++)
871      {
872        spinner = popup_mod->popup_field[idx];
873        entry = elm_object_part_content_get(spinner, "elm.swallow.entry");
874        if (!entry) continue;
875
876        snprintf(buf, sizeof(buf), "datetime_popup/%s", field_styles[idx]);
877        elm_object_style_set(entry, buf);
878        elm_entry_magnifier_disabled_set(entry, EINA_TRUE);
879        elm_entry_context_menu_disabled_set(entry, EINA_TRUE);
880        elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_DATETIME);
881        elm_entry_markup_filter_append(entry, elm_entry_filter_accept_set, &digits_filter_data);
882
883        limit_filter_data.max_char_count = 2;
884        elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &limit_filter_data);
885
886        evas_object_smart_callback_add(entry, "focused", _entry_focused_cb, popup_mod);
887        evas_object_smart_callback_add(entry, "unfocused", _entry_unfocused_cb, popup_mod);
888        evas_object_smart_callback_add(entry, "activated", _entry_activated_cb, popup_mod);
889        evas_object_smart_callback_add(entry, "clicked", _entry_clicked_cb, popup_mod);
890
891        if (idx == ELM_DATETIME_HOUR)
892          elm_entry_markup_filter_append(entry, _hour_validity_checking_filter, popup_mod);
893        else if (idx == ELM_DATETIME_MINUTE)
894          elm_entry_markup_filter_append(entry, _minute_validity_checking_filter, popup_mod);
895      }
896 }
897
898 static void
899 _show_datepicker_layout(Popup_Module_Data *popup_mod)
900 {
901    Evas_Object *content;
902    struct tm curr_time;
903    int idx, year, month, min, max;
904    Elm_Datetime_Field_Type  field_type = ELM_DATETIME_YEAR;
905
906    if (!popup_mod || !popup_mod->mod_data.base) return;
907
908    content = elm_object_content_get(popup_mod->popup);
909    if (content != popup_mod->datepicker_layout)
910      {
911          elm_object_content_unset(popup_mod->popup);
912          if (content) evas_object_hide(content);
913          elm_object_content_set(popup_mod->popup, popup_mod->datepicker_layout);
914          evas_object_show(popup_mod->datepicker_layout);
915      }
916    elm_datetime_value_get(popup_mod->mod_data.base, &(popup_mod->set_time));
917    _set_datepicker_popup_title_text(popup_mod);
918
919    elm_datetime_value_get(popup_mod->mod_data.base, &curr_time);
920    year = curr_time.tm_year + STRUCT_TM_YEAR_BASE_VALUE;
921    elm_spinner_value_set(popup_mod->popup_field[ELM_DATETIME_YEAR], year);
922    month = curr_time.tm_mon + 1;
923    elm_spinner_value_set(popup_mod->popup_field[ELM_DATETIME_MONTH], month);
924    elm_spinner_value_set(popup_mod->popup_field[ELM_DATETIME_DATE], curr_time.tm_mday);
925
926    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
927      {
928          field_type = (Elm_Datetime_Field_Type)idx;
929          popup_mod->mod_data.field_limit_get(popup_mod->mod_data.base, field_type, &min, &max);
930          if (idx == ELM_DATETIME_YEAR)
931            elm_spinner_min_max_set(popup_mod->popup_field[idx], (STRUCT_TM_YEAR_BASE_VALUE + min), (STRUCT_TM_YEAR_BASE_VALUE + max));
932          else if (idx == ELM_DATETIME_MONTH)
933            elm_spinner_min_max_set(popup_mod->popup_field[idx], (1+min), (1+max));
934          else
935            elm_spinner_min_max_set(popup_mod->popup_field[idx], min, max);
936      }
937 }
938
939 static void
940 _show_timepicker_layout(Popup_Module_Data *popup_mod)
941 {
942    Evas_Object *content;
943    struct tm curr_time, min_time, max_time;
944    int hour, hour_min, hour_max;
945
946    if (!popup_mod || !popup_mod->mod_data.base) return;
947
948    content = elm_object_content_get(popup_mod->popup);
949    if (content != popup_mod->timepicker_layout)
950      {
951          elm_object_content_unset(popup_mod->popup);
952          if (content) evas_object_hide(content);
953          elm_object_content_set(popup_mod->popup, popup_mod->timepicker_layout);
954          evas_object_show(popup_mod->timepicker_layout);
955      }
956    elm_datetime_value_get(popup_mod->mod_data.base, &(popup_mod->set_time));
957    _set_timepicker_popup_title_text(popup_mod);
958
959    elm_datetime_value_get(popup_mod->mod_data.base, &curr_time);
960    hour = curr_time.tm_hour;
961    if (popup_mod->time_12hr_fmt)
962      {
963         if (hour >= STRUCT_TM_TIME_12HRS_MAX_VALUE)
964           popup_mod->is_pm = EINA_TRUE;
965         else
966           popup_mod->is_pm = EINA_FALSE;
967         if (hour >= STRUCT_TM_TIME_12HRS_MAX_VALUE)
968           hour -= STRUCT_TM_TIME_12HRS_MAX_VALUE;
969         hour = (hour == 0) ? STRUCT_TM_TIME_12HRS_MAX_VALUE : hour;
970      }
971
972     popup_mod->mod_data.fields_min_max_get(popup_mod->mod_data.base, &curr_time, &min_time, &max_time);
973     hour_min = min_time.tm_hour;
974     hour_max = max_time.tm_hour;
975     if (popup_mod->time_12hr_fmt)
976       {
977          if (hour_min < 1) hour_min = 1;
978          else if (hour_min > STRUCT_TM_TIME_12HRS_MAX_VALUE)
979            hour_min -= STRUCT_TM_TIME_12HRS_MAX_VALUE;
980          if (hour_max > STRUCT_TM_TIME_12HRS_MAX_VALUE)
981            hour_max = STRUCT_TM_TIME_12HRS_MAX_VALUE;
982       }
983     elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_HOUR], hour_min, hour_max);
984     elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_MINUTE],
985                             min_time.tm_min, max_time.tm_min);
986
987     elm_spinner_value_set(popup_mod->popup_field[ELM_DATETIME_HOUR], hour);
988     elm_spinner_value_set(popup_mod->popup_field[ELM_DATETIME_MINUTE], curr_time.tm_min);
989     if (popup_mod->time_12hr_fmt)
990       _set_ampm_value(popup_mod);
991 }
992
993 static void
994 _set_month_special_values(Popup_Module_Data *popup_mod)
995 {
996    struct tm curr_time;
997    const char *fmt = NULL;
998    int month;
999
1000    if (!popup_mod) return;
1001
1002    elm_datetime_value_get(popup_mod->mod_data.base, &curr_time);
1003    fmt = popup_mod->mod_data.field_format_get(popup_mod->mod_data.base, ELM_DATETIME_MONTH);
1004    for (month = 0; month < TOTAL_NUMBER_OF_MONTHS; month++)
1005      {
1006          curr_time.tm_mon = month;
1007          strftime(month_arr[month], MONTH_STRING_MAX_SIZE, fmt, &curr_time);
1008      }
1009    for (month = 0; month < 12; month++)
1010      elm_spinner_special_value_add(popup_mod->popup_field[ELM_DATETIME_MONTH],
1011                                    month + 1, month_arr[month]);
1012 }
1013
1014 static void
1015 _create_datetime_popup(Popup_Module_Data *popup_mod)
1016 {
1017    Evas_Object *set_btn, *cancel_btn;
1018    Evas_Object *parent, *widget, *conformant = NULL;
1019    const char *widget_type;
1020
1021    if (!popup_mod) return;
1022
1023    // add popup to the content of elm_conformant
1024    widget = popup_mod->mod_data.base;
1025    while(widget != NULL)
1026      {
1027         parent = elm_widget_parent_get(widget);
1028         widget_type = elm_widget_type_get(widget);
1029         if (!strcmp(widget_type, "elm_conformant"))
1030           {
1031              conformant = widget;
1032              break;
1033           }
1034         widget = parent;
1035      }
1036    if (conformant)
1037      popup_mod->popup = elm_popup_add(elm_object_content_get(conformant));
1038    else
1039      popup_mod->popup = elm_popup_add(elm_widget_top_get(popup_mod->mod_data.base));
1040
1041    evas_object_size_hint_weight_set(popup_mod->popup, EVAS_HINT_EXPAND,
1042                            EVAS_HINT_EXPAND);
1043    evas_object_size_hint_align_set(popup_mod->popup, EVAS_HINT_FILL, 0.5);
1044
1045    cancel_btn = elm_button_add(popup_mod->popup);
1046    elm_object_style_set(cancel_btn, "popup_button/default");
1047    elm_object_domain_translatable_text_set(cancel_btn, PACKAGE, E_("Cancel"));
1048    elm_object_part_content_set(popup_mod->popup, "button1", cancel_btn);
1049    evas_object_smart_callback_add(cancel_btn, "clicked", _popup_cancel_btn_clicked_cb, popup_mod);
1050
1051    set_btn = elm_button_add(popup_mod->popup);
1052    elm_object_style_set(set_btn, "popup_button/default");
1053    elm_object_domain_translatable_text_set(set_btn, PACKAGE, E_("Set"));
1054    elm_object_part_content_set(popup_mod->popup, "button2", set_btn);
1055    evas_object_smart_callback_add(set_btn, "clicked", _popup_set_btn_clicked_cb, popup_mod);
1056 }
1057
1058 static void
1059 _create_datepicker_layout(Popup_Module_Data *popup_mod)
1060 {
1061    Evas_Object *spinner;
1062    char buf[BUFF_SIZE];
1063    int idx, loc;
1064
1065    if (!popup_mod || !popup_mod->popup) return;
1066
1067    popup_mod->datepicker_layout = elm_layout_add(popup_mod->popup);
1068    elm_layout_theme_set(popup_mod->datepicker_layout, "layout", "datetime_popup", "date_layout");
1069
1070    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1071      {
1072        spinner = elm_spinner_add(popup_mod->popup);
1073        elm_spinner_editable_set(spinner, EINA_TRUE);
1074        snprintf(buf, sizeof(buf), "datetime_popup/%s", field_styles[idx]);
1075        elm_object_style_set(spinner, buf);
1076        elm_spinner_step_set(spinner, 1);
1077        elm_spinner_wrap_set(spinner, EINA_TRUE);
1078        elm_spinner_label_format_set(spinner, "%02.0f");
1079        snprintf(buf, sizeof(buf), "field%d", idx);
1080        elm_object_part_content_set(popup_mod->datepicker_layout, buf, spinner);
1081
1082        if (idx == ELM_DATETIME_YEAR)
1083          elm_spinner_min_max_set(spinner, 1902, 2037);
1084        else if (idx == ELM_DATETIME_MONTH)
1085          elm_spinner_min_max_set(spinner, 1, 12);
1086        else if (idx == ELM_DATETIME_DATE)
1087          elm_spinner_min_max_set(spinner, 1, 31);
1088
1089        evas_object_smart_callback_add(spinner, "changed", _datepicker_value_changed_cb, popup_mod);
1090        popup_mod->popup_field[idx] = spinner;
1091      }
1092
1093    _set_month_special_values(popup_mod);
1094    _set_datepicker_entry_filter(popup_mod);
1095 }
1096
1097 static void
1098 _create_timepicker_layout(Popup_Module_Data *popup_mod)
1099 {
1100    Evas_Object *spinner, *ampm;
1101    char buf[BUFF_SIZE];
1102    int idx;
1103
1104    if (!popup_mod || !popup_mod->popup) return;
1105
1106    popup_mod->timepicker_layout = elm_layout_add(popup_mod->popup);
1107    popup_mod->time_12hr_fmt = popup_mod->mod_data.field_location_get(popup_mod->mod_data.base, ELM_DATETIME_AMPM, NULL);
1108
1109    if (popup_mod->time_12hr_fmt)
1110      elm_layout_theme_set(popup_mod->timepicker_layout, "layout", "datetime_popup", "time_layout");
1111    else
1112      elm_layout_theme_set(popup_mod->timepicker_layout, "layout", "datetime_popup", "time_layout_24hr");
1113
1114    for (idx = ELM_DATETIME_HOUR; idx < ELM_DATETIME_AMPM; idx++)
1115      {
1116        spinner = elm_spinner_add(popup_mod->popup);
1117        elm_spinner_editable_set(spinner, EINA_TRUE);
1118        snprintf(buf, sizeof(buf), "datetime_popup/%s", field_styles[idx]);
1119        elm_object_style_set(spinner, buf);
1120        elm_spinner_step_set(spinner, 1);
1121        elm_spinner_wrap_set(spinner, EINA_TRUE);
1122        elm_spinner_label_format_set(spinner, "%02.0f");
1123        snprintf(buf, sizeof(buf), "field%d", (idx - ELM_DATETIME_HOUR));
1124        elm_object_part_content_set(popup_mod->timepicker_layout, buf, spinner);
1125        evas_object_smart_callback_add(spinner, "changed", _timepicker_value_changed_cb, popup_mod);
1126        popup_mod->popup_field[idx] = spinner;
1127     }
1128
1129    ampm = elm_entry_add(popup_mod->popup);
1130    elm_entry_single_line_set(ampm, EINA_TRUE);
1131    elm_entry_editable_set(ampm, EINA_FALSE);
1132    elm_entry_magnifier_disabled_set(ampm, EINA_TRUE);
1133    elm_entry_context_menu_disabled_set(ampm, EINA_TRUE);
1134    elm_object_style_set(ampm, "datetime_popup/ampm");
1135    evas_object_smart_callback_add(ampm, "clicked", _ampm_clicked_cb, popup_mod);
1136    elm_object_part_content_set(popup_mod->timepicker_layout, "field2",ampm);
1137    popup_mod->popup_field[ELM_DATETIME_AMPM] = ampm;
1138
1139    if (!popup_mod->time_12hr_fmt)
1140      elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_HOUR], 0, 23);
1141    else
1142      elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_HOUR], 1, 12);
1143    elm_spinner_min_max_set(popup_mod->popup_field[ELM_DATETIME_MINUTE], 0, 59);
1144
1145    _set_timepicker_entry_filter(popup_mod);
1146 }
1147
1148 static void
1149 _weekday_loc_update(Popup_Module_Data *popup_mod)
1150 {
1151    char *fmt;
1152
1153    if (!popup_mod) return;
1154
1155    fmt = nl_langinfo(D_T_FMT);
1156    if (!strncmp(fmt, "%a", 2) || !strncmp(fmt, "%A", 2))
1157      popup_mod->weekday_loc_first = EINA_TRUE;
1158    else
1159      popup_mod->weekday_loc_first = EINA_FALSE;
1160 }
1161
1162 static void
1163 _module_format_change(Popup_Module_Data *popup_mod)
1164 {
1165    Evas_Object *spinner_field[PICKER_POPUP_FIELD_COUNT];
1166    Evas_Object *datetime, *spinner;
1167    int field_loc[PICKER_POPUP_FIELD_COUNT];
1168    char buf[BUFF_SIZE];
1169    int idx, loc, prev_loc;
1170    Eina_Bool datepicker_bg_show = EINA_FALSE;
1171    Eina_Bool timepicker_bg_show = EINA_FALSE;
1172    Eina_Bool time_12hr;
1173
1174    if (!popup_mod) return;
1175
1176    datetime = popup_mod->mod_data.base;
1177    if (popup_mod->datepicker_layout)
1178      {
1179         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1180           {
1181              popup_mod->mod_data.field_location_get(datetime, idx, &loc);
1182              prev_loc = _picker_field_location_get(popup_mod, idx);
1183              snprintf(buf, sizeof(buf), "field%d", prev_loc);
1184              spinner_field[idx] = elm_object_part_content_unset(popup_mod->datepicker_layout, buf);
1185              field_loc[idx] = loc;
1186           }
1187         for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1188           {
1189              snprintf(buf, sizeof(buf), "field%d", field_loc[idx]);
1190              elm_object_part_content_set(popup_mod->datepicker_layout, buf, spinner_field[idx]);
1191              popup_mod->field_location[idx] = field_loc[idx];
1192           }
1193      }
1194    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1195      datepicker_bg_show |= popup_mod->mod_data.field_location_get(datetime, idx, NULL);
1196    if (!datepicker_bg_show)
1197      elm_layout_signal_emit(datetime, "datetime,datepicker,bg,hide", "elm");
1198
1199    for (idx = ELM_DATETIME_HOUR; idx < ELM_DATETIME_AMPM; idx++)
1200      timepicker_bg_show |= popup_mod->mod_data.field_location_get(datetime, idx, NULL);
1201    if (!timepicker_bg_show)
1202      elm_layout_signal_emit(datetime, "datetime,timepicker,bg,hide", "elm");
1203
1204    time_12hr = popup_mod->mod_data.field_location_get(datetime, ELM_DATETIME_AMPM, NULL);
1205    if ((popup_mod->time_12hr_fmt != time_12hr) && (popup_mod->timepicker_layout))
1206      {
1207        for (idx = ELM_DATETIME_HOUR; idx <= ELM_DATETIME_AMPM; idx++)
1208          {
1209             snprintf(buf, sizeof(buf), "field%d", (idx - ELM_DATETIME_HOUR));
1210             spinner = elm_object_part_content_unset(popup_mod->timepicker_layout, buf);
1211             if (spinner) evas_object_hide(spinner);
1212          }
1213         if (time_12hr)
1214           {
1215              elm_layout_theme_set(popup_mod->timepicker_layout, "layout", "datetime_popup", "time_layout");
1216              for (idx = ELM_DATETIME_HOUR; idx <= ELM_DATETIME_AMPM; idx++)
1217                {
1218                   snprintf(buf, sizeof(buf), "field%d", (idx - ELM_DATETIME_HOUR));
1219                   elm_object_part_content_set(popup_mod->timepicker_layout, buf, popup_mod->popup_field[idx]);
1220                }
1221           }
1222         else
1223           {
1224              elm_layout_theme_set(popup_mod->timepicker_layout, "layout", "datetime_popup", "time_layout_24hr");
1225              for (idx = ELM_DATETIME_HOUR; idx <= ELM_DATETIME_MINUTE; idx++)
1226                {
1227                   snprintf(buf, sizeof(buf), "field%d", (idx - ELM_DATETIME_HOUR));
1228                   elm_object_part_content_set(popup_mod->timepicker_layout, buf, popup_mod->popup_field[idx]);
1229                }
1230           }
1231      }
1232    popup_mod->time_12hr_fmt = time_12hr;
1233    _weekday_loc_update(popup_mod);
1234 }
1235
1236 static void
1237 _datepicker_show_cb(void *data,
1238                    Evas_Object *obj,
1239                    const char *emission __UNUSED__,
1240                    const char *source __UNUSED__)
1241 {
1242    Popup_Module_Data *popup_mod;
1243
1244    popup_mod = (Popup_Module_Data *)data;
1245    if (!popup_mod) return;
1246
1247    if (!popup_mod->popup)
1248      _create_datetime_popup(popup_mod);
1249
1250    if (!popup_mod->datepicker_layout)
1251      _create_datepicker_layout(popup_mod);
1252
1253    _show_datepicker_layout(popup_mod);
1254    evas_object_show(popup_mod->popup);
1255    evas_object_smart_callback_call(obj, SIG_EDIT_START, NULL);
1256 }
1257
1258 static void
1259 _timepicker_show_cb(void *data,
1260                    Evas_Object *obj,
1261                    const char *emission __UNUSED__,
1262                    const char *source __UNUSED__)
1263 {
1264    Popup_Module_Data *popup_mod;
1265
1266    popup_mod = (Popup_Module_Data *)data;
1267    if (!popup_mod) return;
1268
1269    if (!popup_mod->popup)
1270      _create_datetime_popup(popup_mod);
1271
1272    if (!popup_mod->timepicker_layout)
1273      _create_timepicker_layout(popup_mod);
1274
1275    _show_timepicker_layout(popup_mod);
1276    evas_object_show(popup_mod->popup);
1277    evas_object_smart_callback_call(obj, SIG_EDIT_START, NULL);
1278 }
1279
1280 static void
1281 _module_language_changed_cb(void *data,
1282                             Evas_Object *obj __UNUSED__,
1283                             void *event_info __UNUSED__)
1284 {
1285    Popup_Module_Data *popup_mod;
1286    Evas_Object *content;
1287    popup_mod = (Popup_Module_Data *)data;
1288    if (!popup_mod || !popup_mod->popup) return;
1289
1290    content = elm_object_content_get(popup_mod->popup);
1291    if (content == popup_mod->datepicker_layout)
1292      _set_datepicker_popup_title_text(popup_mod);
1293    else if (content == popup_mod->timepicker_layout)
1294      _set_timepicker_popup_title_text(popup_mod);
1295
1296    _set_month_special_values(popup_mod);
1297    _set_ampm_value(popup_mod);
1298 }
1299
1300 static void
1301 _weekday_show_cb(void *data,
1302                  Evas_Object *obj __UNUSED__,
1303                  const char *emission __UNUSED__,
1304                  const char *source __UNUSED__)
1305 {
1306    Popup_Module_Data *popup_mod;
1307    int idx, loc, weekday_loc;
1308
1309    popup_mod = (Popup_Module_Data *)data;
1310    if (!popup_mod) return;
1311
1312    popup_mod->weekday_show = EINA_TRUE;
1313
1314    weekday_loc = (popup_mod->weekday_loc_first) ? 0 : 2;
1315    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1316      {
1317         popup_mod->mod_data.field_location_get(popup_mod->mod_data.base, idx, &loc);
1318         if (loc == weekday_loc)
1319          {
1320             field_value_display((Elm_Datetime_Module_Data *)popup_mod,
1321                                 popup_mod->datetime_field[idx]);
1322             break;
1323          }
1324      }
1325 }
1326
1327 static void
1328 _weekday_hide_cb(void *data,
1329                  Evas_Object *obj __UNUSED__,
1330                  const char *emission __UNUSED__,
1331                  const char *source __UNUSED__)
1332 {
1333    Popup_Module_Data *popup_mod;
1334    int idx, loc, weekday_loc;
1335
1336    popup_mod = (Popup_Module_Data *)data;
1337    if (!popup_mod) return;
1338
1339    popup_mod->weekday_show = EINA_FALSE;
1340    weekday_loc = (popup_mod->weekday_loc_first) ? 0 : 2;
1341    for (idx = 0; idx <= ELM_DATETIME_DATE; idx++)
1342      {
1343         popup_mod->mod_data.field_location_get(popup_mod->mod_data.base, idx, &loc);
1344         if (loc == weekday_loc)
1345          {
1346             field_value_display((Elm_Datetime_Module_Data *)popup_mod,
1347                                 popup_mod->datetime_field[idx]);
1348             break;
1349          }
1350      }
1351 }
1352
1353 static void
1354 _access_set(Evas_Object *obj, Elm_Datetime_Field_Type field_type)
1355 {
1356    const char* type = NULL;
1357
1358    switch (field_type)
1359      {
1360        case ELM_DATETIME_YEAR:
1361         type = "datetime field, year";
1362         break;
1363
1364       case ELM_DATETIME_MONTH:
1365         type = "datetime field, month";
1366         break;
1367
1368      case ELM_DATETIME_DATE:
1369         type = "datetime field, date";
1370         break;
1371
1372       case ELM_DATETIME_HOUR:
1373         type = "datetime field, hour";
1374         break;
1375
1376       case ELM_DATETIME_MINUTE:
1377         type = "datetime field, minute";
1378         break;
1379
1380       case ELM_DATETIME_AMPM:
1381         type = "datetime field, AM PM";
1382         break;
1383
1384       default:
1385         break;
1386      }
1387
1388    _elm_access_text_set
1389      (_elm_access_object_get(obj), ELM_ACCESS_TYPE, type);
1390    _elm_access_callback_set
1391      (_elm_access_object_get(obj), ELM_ACCESS_STATE, NULL, NULL);
1392 }
1393
1394 // module functions for the specific module type
1395 EAPI void
1396 field_value_display(Elm_Datetime_Module_Data *module_data, Evas_Object *obj)
1397 {
1398    Popup_Module_Data *popup_mod;
1399    Elm_Datetime_Field_Type  field_type;
1400    struct tm curr_time;
1401    char buf[BUFF_SIZE] = {0,};
1402    char weekday[BUFF_SIZE], label[BUFF_SIZE];
1403    int loc, weekday_loc;
1404    const char *fmt;
1405    Eina_Bool is_weekday_shown;
1406
1407    popup_mod = (Popup_Module_Data *)module_data;
1408    if (!popup_mod || !obj) return;
1409
1410    elm_datetime_value_get(popup_mod->mod_data.base, &curr_time);
1411    field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type");
1412    fmt = popup_mod->mod_data.field_format_get(popup_mod->mod_data.base, field_type);
1413    strftime(buf, sizeof(buf), fmt, &curr_time);
1414
1415    if ((!buf[0]) && ((!strcmp(fmt, "%p")) || (!strcmp(fmt, "%P"))))
1416      {
1417         if (curr_time.tm_hour < STRUCT_TM_TIME_12HRS_MAX_VALUE)
1418           elm_object_domain_translatable_text_set(obj, PACKAGE, E_("AM"));
1419         else
1420           elm_object_domain_translatable_text_set(obj, PACKAGE, E_("PM"));
1421      }
1422    else if (!popup_mod->weekday_show)
1423      elm_object_text_set(obj, buf);
1424    else
1425      {
1426         /* FIXME: To restrict month wrapping because of summer time in some locales,
1427          * ignore day light saving mode in mktime(). */
1428         curr_time.tm_isdst = -1;
1429         mktime(&curr_time);
1430         strftime(weekday, sizeof(weekday), "%a", &curr_time);
1431         weekday_loc = (popup_mod->weekday_loc_first) ? 0 : 2;
1432         is_weekday_shown = popup_mod->mod_data.field_location_get(
1433                            popup_mod->mod_data.base, field_type, &loc);
1434         if (!is_weekday_shown || (loc != weekday_loc))
1435           elm_object_text_set(obj, buf);
1436         else if (loc == 0)
1437           {
1438              snprintf(label, sizeof(label), "%s %s", weekday, buf);
1439              elm_object_text_set(obj, label);
1440           }
1441         else
1442           {
1443              snprintf(label, sizeof(label), "%s %s", buf, weekday);
1444              elm_object_text_set(obj, label);
1445           }
1446      }
1447 }
1448
1449 EAPI Evas_Object *
1450 field_create(Elm_Datetime_Module_Data *module_data, Elm_Datetime_Field_Type field_type)
1451 {
1452    Popup_Module_Data *popup_mod;
1453    Evas_Object *field_obj;
1454    char buf[BUFF_SIZE];
1455
1456    popup_mod = (Popup_Module_Data *)module_data;
1457    if (!popup_mod) return NULL;
1458
1459    field_obj = elm_label_add(popup_mod->mod_data.base);
1460    snprintf(buf, sizeof(buf), "datetime/%s/default", field_styles[field_type]);
1461    elm_object_style_set(field_obj, buf);
1462    evas_object_data_set(field_obj, "_field_type", (void *)field_type);
1463    popup_mod->datetime_field[field_type] = field_obj;
1464
1465    _access_set(field_obj, field_type);
1466
1467    return field_obj;
1468 }
1469
1470 EAPI Elm_Datetime_Module_Data *
1471 obj_hook(Evas_Object *obj)
1472 {
1473    Popup_Module_Data *popup_mod;
1474
1475    popup_mod = ELM_NEW(Popup_Module_Data);
1476    if (!popup_mod) return NULL;
1477
1478    elm_object_signal_callback_add(obj, "datepicker,show", "",
1479                                   _datepicker_show_cb, popup_mod);
1480    elm_object_signal_callback_add(obj, "timepicker,show", "",
1481                                   _timepicker_show_cb, popup_mod);
1482    elm_object_signal_callback_add(obj, "picker,hide", "",
1483                                   _picker_hide_cb, popup_mod);
1484    elm_object_signal_callback_add(obj, "language,changed", "",
1485                                   _module_language_changed_cb, popup_mod);
1486    elm_object_signal_callback_add(obj, "elm,action,press", "*",
1487                                   _datetime_press_cb, popup_mod);
1488    elm_object_signal_callback_add(obj, "elm,action,unpress", "*",
1489                                   _datetime_unpress_cb, popup_mod);
1490    elm_object_signal_callback_add(obj, "weekday,show", "",
1491                                   _weekday_show_cb, popup_mod);
1492    elm_object_signal_callback_add(obj, "weekday,hide", "",
1493                                   _weekday_hide_cb, popup_mod);
1494
1495    popup_mod->popup = NULL;
1496    popup_mod->datepicker_layout = NULL;
1497    popup_mod->timepicker_layout = NULL;
1498    popup_mod->weekday_show = EINA_FALSE;
1499    popup_mod->weekday_loc_first = EINA_TRUE;
1500
1501    return ((Elm_Datetime_Module_Data*)popup_mod);
1502 }
1503
1504 EAPI void
1505 obj_unhook(Elm_Datetime_Module_Data *module_data)
1506 {
1507    Popup_Module_Data *popup_mod;
1508
1509    popup_mod = (Popup_Module_Data *)module_data;
1510    if (!popup_mod) return;
1511
1512    if (popup_mod->popup)
1513      evas_object_del(popup_mod->popup);
1514
1515    if (popup_mod)
1516      {
1517         free(popup_mod);
1518         popup_mod = NULL;
1519      }
1520 }
1521
1522 EAPI void
1523 obj_format_hook(Elm_Datetime_Module_Data *module_data)
1524 {
1525    Popup_Module_Data *popup_mod;
1526
1527    popup_mod = (Popup_Module_Data *)module_data;
1528    if (!popup_mod) return;
1529
1530    _module_format_change(popup_mod);
1531 }
1532
1533 EAPI void
1534 obj_theme_hook(Elm_Datetime_Module_Data *module_data)
1535 {
1536    Popup_Module_Data *popup_mod;
1537
1538    popup_mod = (Popup_Module_Data *)module_data;
1539    if (!popup_mod) return;
1540
1541    // TODO: function can be improved to provide different popup styles.
1542 }
1543
1544 EAPI void
1545 obj_focus_hook(Elm_Datetime_Module_Data *module_data __UNUSED__)
1546 {
1547    // TODO: Default focus - enhance this func. for obj_show/obj_hide like below
1548 #if 0
1549    Popup_Module_Data *popup_mod;
1550    int idx;
1551    Eina_Bool is_focused = EINA_FALSE; //init with i/p argument
1552
1553    popup_mod = (Popup_Module_Data *)module_data;
1554    if (!popup_mod || popup_mod->popup) return;
1555
1556    for (idx = 0; idx < DATETIME_FIELD_COUNT; idx++)
1557       if (elm_object_focus_get(popup_mod->popup_field[idx]))
1558         is_focused = EINA_TRUE;
1559
1560    if (is_focused)
1561      evas_object_show(popup_mod->popup);
1562    else
1563      evas_object_hide(popup_mod->popup);
1564 #endif
1565 }
1566
1567 // module api funcs needed
1568 EAPI int
1569 elm_modapi_init(void *m __UNUSED__)
1570 {
1571    return 1; // succeed always
1572 }
1573
1574 EAPI int
1575 elm_modapi_shutdown(void *m __UNUSED__)
1576 {
1577    return 1; // succeed always
1578 }