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