tizen 2.4 release
[framework/uifw/elementary.git] / src / lib / elm_clock.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6
7 #include <Elementary.h>
8 #include "elm_priv.h"
9 #include "elm_widget_clock.h"
10
11 #define MY_CLASS ELM_CLOCK_CLASS
12
13 #define MY_CLASS_NAME "Elm_Clock"
14 #define MY_CLASS_NAME_LEGACY "elm_clock"
15
16 #define DEFAULT_FIRST_INTERVAL 0.85
17 static void _time_update(Evas_Object *obj);
18
19 static const char SIG_CHANGED[] = "changed";
20
21 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
22    {SIG_CHANGED, ""},
23    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
24    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
25    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
26    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
27    {NULL, NULL}
28 };
29
30 static Eina_Bool
31 _on_clock_val_up(void *data)
32 {
33    ELM_CLOCK_DATA_GET(data, sd);
34
35    if (!sd->edit) goto clock_val_up_cancel;
36    if (!sd->sel_obj) goto clock_val_up_cancel;
37    if (sd->sel_obj == sd->digit[0])
38      {
39         sd->hrs = sd->hrs + 12;
40         if (sd->hrs >= 24) sd->hrs -= 24;
41      }
42    if (sd->sel_obj == sd->digit[1])
43      {
44         sd->hrs = sd->hrs + 1;
45         if (sd->hrs >= 24) sd->hrs -= 24;
46      }
47    if (sd->sel_obj == sd->digit[2])
48      {
49         sd->min = sd->min + 10;
50         if (sd->min >= 60) sd->min -= 60;
51      }
52    if (sd->sel_obj == sd->digit[3])
53      {
54         sd->min = sd->min + 1;
55         if (sd->min >= 60) sd->min -= 60;
56      }
57    if (sd->sel_obj == sd->digit[4])
58      {
59         sd->sec = sd->sec + 10;
60         if (sd->sec >= 60) sd->sec -= 60;
61      }
62    if (sd->sel_obj == sd->digit[5])
63      {
64         sd->sec = sd->sec + 1;
65         if (sd->sec >= 60) sd->sec -= 60;
66      }
67    if (sd->sel_obj == sd->am_pm_obj)
68      {
69         sd->hrs = sd->hrs + 12;
70         if (sd->hrs > 23) sd->hrs -= 24;
71      }
72
73    sd->interval = sd->interval / 1.05;
74    ecore_timer_interval_set(sd->spin, sd->interval);
75    _time_update(data);
76    evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
77    return ECORE_CALLBACK_RENEW;
78
79 clock_val_up_cancel:
80
81    sd->spin = NULL;
82
83    return ECORE_CALLBACK_CANCEL;
84 }
85
86 static Eina_Bool
87 _on_clock_val_down(void *data)
88 {
89    ELM_CLOCK_DATA_GET(data, sd);
90
91    if (!sd->edit) goto clock_val_down_cancel;
92    if (!sd->sel_obj) goto clock_val_down_cancel;
93    if (sd->sel_obj == sd->digit[0])
94      {
95         sd->hrs = sd->hrs - 12;
96         if (sd->hrs < 0) sd->hrs += 24;
97      }
98    if (sd->sel_obj == sd->digit[1])
99      {
100         sd->hrs = sd->hrs - 1;
101         if (sd->hrs < 0) sd->hrs += 24;
102      }
103    if (sd->sel_obj == sd->digit[2])
104      {
105         sd->min = sd->min - 10;
106         if (sd->min < 0) sd->min += 60;
107      }
108    if (sd->sel_obj == sd->digit[3])
109      {
110         sd->min = sd->min - 1;
111         if (sd->min < 0) sd->min += 60;
112      }
113    if (sd->sel_obj == sd->digit[4])
114      {
115         sd->sec = sd->sec - 10;
116         if (sd->sec < 0) sd->sec += 60;
117      }
118    if (sd->sel_obj == sd->digit[5])
119      {
120         sd->sec = sd->sec - 1;
121         if (sd->sec < 0) sd->sec += 60;
122      }
123    if (sd->sel_obj == sd->am_pm_obj)
124      {
125         sd->hrs = sd->hrs - 12;
126         if (sd->hrs < 0) sd->hrs += 24;
127      }
128    sd->interval = sd->interval / 1.05;
129    ecore_timer_interval_set(sd->spin, sd->interval);
130    _time_update(data);
131    evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
132    return ECORE_CALLBACK_RENEW;
133
134 clock_val_down_cancel:
135    sd->spin = NULL;
136
137    return ECORE_CALLBACK_CANCEL;
138 }
139
140 static void
141 _on_clock_val_up_start(void *data,
142                        Evas_Object *obj,
143                        const char *emission EINA_UNUSED,
144                        const char *source EINA_UNUSED)
145 {
146    ELM_CLOCK_DATA_GET(data, sd);
147
148    sd->interval = sd->first_interval;
149    sd->sel_obj = obj;
150    ecore_timer_del(sd->spin);
151    sd->spin = ecore_timer_add(sd->interval, _on_clock_val_up, data);
152
153    _on_clock_val_up(data);
154 }
155
156 static void
157 _on_clock_val_down_start(void *data,
158                          Evas_Object *obj,
159                          const char *emission EINA_UNUSED,
160                          const char *source EINA_UNUSED)
161 {
162    ELM_CLOCK_DATA_GET(data, sd);
163
164    sd->interval = sd->first_interval;
165    sd->sel_obj = obj;
166    ecore_timer_del(sd->spin);
167    sd->spin = ecore_timer_add(sd->interval, _on_clock_val_down, data);
168
169    _on_clock_val_down(data);
170 }
171
172 static void
173 _on_clock_val_change_stop(void *data,
174                           Evas_Object *obj EINA_UNUSED,
175                           const char *emission EINA_UNUSED,
176                           const char *source EINA_UNUSED)
177 {
178    ELM_CLOCK_DATA_GET(data, sd);
179
180    ELM_SAFE_FREE(sd->spin, ecore_timer_del);
181    sd->sel_obj = NULL;
182 }
183
184 static void
185 _access_activate_cb(void *data,
186                     Evas_Object *part_obj,
187                     Elm_Object_Item *item EINA_UNUSED)
188 {
189    Evas_Object *digit, *inc_btn;
190    ELM_CLOCK_DATA_GET(data, sd);
191
192    digit = evas_object_smart_parent_get(part_obj);
193    if (!digit) return;
194
195    inc_btn = (Evas_Object *)edje_object_part_object_get(digit, "access.t");
196
197    if (part_obj != inc_btn)
198      _on_clock_val_down_start(data, digit, NULL, NULL);
199    else
200      _on_clock_val_up_start(data, digit, NULL, NULL);
201
202    _on_clock_val_change_stop(sd, NULL, NULL, NULL);
203 }
204
205 static void
206 _access_time_register(Evas_Object *obj, Eina_Bool is_access)
207 {
208    Evas_Object *ao, *po;
209
210    ELM_CLOCK_DATA_GET(obj, sd);
211
212    if (!sd->edit) return;
213
214    /* hour, min, sec edit button */
215    int i;
216    for (i = 0; i < 6; i++)
217      {
218         if (is_access && (sd->digedit & (1 << i)))
219           {
220              char *digit = NULL;
221
222              switch (1 << i)
223                {
224                 case ELM_CLOCK_EDIT_HOUR_DECIMAL:
225                   digit = "hour decimal";
226                   break;
227                 case ELM_CLOCK_EDIT_HOUR_UNIT:
228                   digit = "hour unit";
229                   break;
230                 case ELM_CLOCK_EDIT_MIN_DECIMAL:
231                   digit = "minute decimal";
232                   break;
233                 case ELM_CLOCK_EDIT_MIN_UNIT:
234                   digit = "minute unit";
235                   break;
236                 case ELM_CLOCK_EDIT_SEC_DECIMAL:
237                   digit = "second decimal";
238                   break;
239                 case ELM_CLOCK_EDIT_SEC_UNIT:
240                   digit = "second unit";
241                   break;
242                }
243
244              Eina_Strbuf *strbuf;
245              strbuf = eina_strbuf_new();
246
247              /* increment button */
248              ao = _elm_access_edje_object_part_object_register
249                     (obj, sd->digit[i], "access.t");
250
251              eina_strbuf_append_printf(strbuf,
252                "clock increment button for %s", digit);
253              _elm_access_text_set(_elm_access_info_get(ao),
254                ELM_ACCESS_TYPE, eina_strbuf_string_get(strbuf));
255              _elm_access_activate_callback_set
256                (_elm_access_info_get(ao), _access_activate_cb, obj);
257
258              /* decrement button */
259              ao = _elm_access_edje_object_part_object_register
260                     (obj, sd->digit[i], "access.b");
261
262              eina_strbuf_replace(strbuf, "increment", "decrement", 1);
263              _elm_access_text_set(_elm_access_info_get(ao),
264                ELM_ACCESS_TYPE, eina_strbuf_string_get(strbuf));
265              _elm_access_activate_callback_set
266                (_elm_access_info_get(ao), _access_activate_cb, obj);
267
268              eina_strbuf_free(strbuf);
269
270              edje_object_signal_emit
271                (sd->digit[i], "elm,state,access,edit,on", "elm");
272           }
273         else if (!is_access && (sd->digedit & (1 << i)))
274           {
275              _elm_access_edje_object_part_object_unregister
276                (obj, sd->digit[i], "access.t");
277
278              _elm_access_edje_object_part_object_unregister
279                (obj, sd->digit[i], "access.b");
280
281              edje_object_signal_emit
282                (sd->digit[i], "elm,state,access,edit,off", "elm");
283           }
284
285         /* no need to propagate mouse event with acess */
286         po = (Evas_Object *)edje_object_part_object_get
287                (sd->digit[i], "access.t");
288         evas_object_propagate_events_set(po, !is_access);
289
290         po = (Evas_Object *)edje_object_part_object_get
291                (sd->digit[i], "access.b");
292         evas_object_propagate_events_set(po, !is_access);
293
294      }
295
296    /* am, pm edit button  */
297    if (is_access && sd->am_pm)
298      {
299         /* increment button */
300         ao = _elm_access_edje_object_part_object_register
301                (obj, sd->am_pm_obj, "access.t");
302         _elm_access_text_set(_elm_access_info_get(ao),
303           ELM_ACCESS_TYPE, E_("clock increment button for am,pm"));
304         _elm_access_activate_callback_set
305           (_elm_access_info_get(ao), _access_activate_cb, obj);
306
307         /* decrement button */
308         ao = _elm_access_edje_object_part_object_register
309                (obj, sd->am_pm_obj, "access.b");
310         _elm_access_text_set(_elm_access_info_get(ao),
311           ELM_ACCESS_TYPE, E_("clock decrement button for am,pm"));
312         _elm_access_activate_callback_set
313           (_elm_access_info_get(ao), _access_activate_cb, obj);
314
315          edje_object_signal_emit
316            (sd->am_pm_obj, "elm,state,access,edit,on", "elm");
317      }
318    else if (!is_access && sd->am_pm)
319      {
320         _elm_access_edje_object_part_object_register
321           (obj, sd->am_pm_obj, "access.t");
322
323         _elm_access_edje_object_part_object_register
324           (obj, sd->am_pm_obj, "access.b");
325
326          edje_object_signal_emit
327            (sd->am_pm_obj, "elm,state,access,edit,off", "elm");
328      }
329
330     /* no need to propagate mouse event with access */
331     po = (Evas_Object *)edje_object_part_object_get
332            (sd->am_pm_obj, "access.t");
333     evas_object_propagate_events_set(po, !is_access);
334
335     po = (Evas_Object *)edje_object_part_object_get
336            (sd->am_pm_obj, "access.b");
337     evas_object_propagate_events_set(po, !is_access);
338
339 }
340
341 static void
342 _time_update(Evas_Object *obj)
343 {
344    ELM_CLOCK_DATA_GET(obj, sd);
345    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
346
347    Edje_Message_Int msg;
348    const char *style = elm_widget_style_get(obj);
349
350    if ((sd->cur.seconds != sd->seconds) || (sd->cur.am_pm != sd->am_pm) ||
351        (sd->cur.edit != sd->edit) || (sd->cur.digedit != sd->digedit))
352      {
353         int i;
354         Evas_Coord mw, mh;
355
356         for (i = 0; i < 6; i++)
357           ELM_SAFE_FREE(sd->digit[i], evas_object_del);
358         ELM_SAFE_FREE(sd->am_pm_obj, evas_object_del);
359
360         if ((sd->seconds) && (sd->am_pm))
361           {
362              if (!elm_layout_theme_set(obj, "clock", "base-all", style))
363                ERR("Failed to set layout!");
364           }
365         else if (sd->seconds)
366           {
367              if (!elm_layout_theme_set(obj, "clock", "base-seconds", style))
368                ERR("Failed to set layout!");
369           }
370         else if (sd->am_pm)
371           {
372              if (!elm_layout_theme_set(obj, "clock", "base-am_pm", style))
373                ERR("Failed to set layout!");
374           }
375         else
376           {
377              if (!elm_layout_theme_set(obj, "clock", "base", style))
378                ERR("Failed to set layout!");
379           }
380
381         edje_object_scale_set
382           (wd->resize_obj, elm_widget_scale_get(obj) *
383           elm_config_scale_get());
384
385         for (i = 0; i < 6; i++)
386           {
387              char buf[16];
388
389              if ((!sd->seconds) && (i >= 4)) break;
390              sd->digit[i] = edje_object_add
391                  (evas_object_evas_get(wd->resize_obj));
392              elm_widget_theme_object_set
393                (obj, sd->digit[i], "clock", "flipdigit", style);
394              edje_object_scale_set
395                (sd->digit[i], elm_widget_scale_get(obj) *
396                elm_config_scale_get());
397
398              if ((sd->edit) && (sd->digedit & (1 << i)))
399                edje_object_signal_emit
400                  (sd->digit[i], "elm,state,edit,on", "elm");
401              edje_object_signal_callback_add
402                (sd->digit[i], "elm,action,up,start", "*",
403                _on_clock_val_up_start, obj);
404              edje_object_signal_callback_add
405                (sd->digit[i], "elm,action,up,stop", "*",
406                _on_clock_val_change_stop, obj);
407              edje_object_signal_callback_add
408                (sd->digit[i], "elm,action,down,start", "*",
409                _on_clock_val_down_start, obj);
410              edje_object_signal_callback_add
411                (sd->digit[i], "elm,action,down,stop", "*",
412                _on_clock_val_change_stop, obj);
413
414              mw = mh = -1;
415              elm_coords_finger_size_adjust(1, &mw, 2, &mh);
416              edje_object_size_min_restricted_calc
417                (sd->digit[i], &mw, &mh, mw, mh);
418              elm_coords_finger_size_adjust(1, &mw, 2, &mh);
419              evas_object_size_hint_min_set(sd->digit[i], mw, mh);
420              snprintf(buf, sizeof(buf), "d%i", i);
421              elm_layout_content_set(obj, buf, sd->digit[i]);
422              evas_object_show(sd->digit[i]);
423           }
424         if (sd->am_pm)
425           {
426              sd->am_pm_obj =
427                edje_object_add(evas_object_evas_get(wd->resize_obj));
428              elm_widget_theme_object_set
429                (obj, sd->am_pm_obj, "clock", "flipampm", style);
430              edje_object_scale_set(sd->am_pm_obj, elm_widget_scale_get(obj) *
431                                    _elm_config->scale);
432              if (sd->edit)
433                edje_object_signal_emit
434                  (sd->am_pm_obj, "elm,state,edit,on", "elm");
435              edje_object_signal_callback_add
436                (sd->am_pm_obj, "elm,action,up,start", "*",
437                _on_clock_val_up_start, obj);
438              edje_object_signal_callback_add
439                (sd->am_pm_obj, "elm,action,up,stop", "*",
440                _on_clock_val_change_stop, obj);
441              edje_object_signal_callback_add
442                (sd->am_pm_obj, "elm,action,down,start", "*",
443                _on_clock_val_down_start, obj);
444              edje_object_signal_callback_add
445                (sd->am_pm_obj, "elm,action,down,stop", "*",
446                _on_clock_val_change_stop, obj);
447
448              mw = mh = -1;
449              elm_coords_finger_size_adjust(1, &mw, 2, &mh);
450              edje_object_size_min_restricted_calc
451                (sd->am_pm_obj, &mw, &mh, mw, mh);
452              elm_coords_finger_size_adjust(1, &mw, 2, &mh);
453              evas_object_size_hint_min_set(sd->am_pm_obj, mw, mh);
454              elm_layout_content_set(obj, "ampm", sd->am_pm_obj);
455              evas_object_show(sd->am_pm_obj);
456           }
457
458         /* access */
459         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
460           _access_time_register(obj, EINA_TRUE);
461
462         edje_object_size_min_calc(wd->resize_obj, &mw, &mh);
463         evas_object_size_hint_min_set(obj, mw, mh);
464
465         sd->cur.hrs = 0;
466         sd->cur.min = 0;
467         sd->cur.sec = 0;
468         sd->cur.ampm = -1;
469         sd->cur.seconds = sd->seconds;
470         sd->cur.am_pm = sd->am_pm;
471         sd->cur.edit = sd->edit;
472         sd->cur.digedit = sd->digedit;
473      }
474    if (sd->hrs != sd->cur.hrs)
475      {
476         int hrs;
477         int d1, d2, dc1, dc2;
478
479         hrs = sd->hrs;
480         if (sd->am_pm)
481           {
482              if (hrs > 12) hrs -= 12;
483              else if (!hrs) hrs = 12;
484           }
485         d1 = hrs / 10;
486         d2 = hrs % 10;
487         dc1 = sd->cur.hrs / 10;
488         dc2 = sd->cur.hrs % 10;
489         if (d1 != dc1)
490           {
491              msg.val = d1;
492              edje_object_message_send(sd->digit[0], EDJE_MESSAGE_INT, 1, &msg);
493           }
494         if (d2 != dc2)
495           {
496              msg.val = d2;
497              edje_object_message_send(sd->digit[1], EDJE_MESSAGE_INT, 1, &msg);
498           }
499         sd->cur.hrs = hrs;
500      }
501    if (sd->min != sd->cur.min)
502      {
503         int d1, d2, dc1, dc2;
504
505         d1 = sd->min / 10;
506         d2 = sd->min % 10;
507         dc1 = sd->cur.min / 10;
508         dc2 = sd->cur.min % 10;
509         if (d1 != dc1)
510           {
511              msg.val = d1;
512              edje_object_message_send(sd->digit[2], EDJE_MESSAGE_INT, 1, &msg);
513           }
514         if (d2 != dc2)
515           {
516              msg.val = d2;
517              edje_object_message_send(sd->digit[3], EDJE_MESSAGE_INT, 1, &msg);
518           }
519         sd->cur.min = sd->min;
520      }
521    if (sd->seconds)
522      {
523         if (sd->sec != sd->cur.sec)
524           {
525              int d1, d2, dc1, dc2;
526
527              d1 = sd->sec / 10;
528              d2 = sd->sec % 10;
529              dc1 = sd->cur.sec / 10;
530              dc2 = sd->cur.sec % 10;
531              if (d1 != dc1)
532                {
533                   msg.val = d1;
534                   edje_object_message_send
535                     (sd->digit[4], EDJE_MESSAGE_INT, 1, &msg);
536                }
537              if (d2 != dc2)
538                {
539                   msg.val = d2;
540                   edje_object_message_send
541                     (sd->digit[5], EDJE_MESSAGE_INT, 1, &msg);
542                }
543              sd->cur.sec = sd->sec;
544           }
545      }
546    else
547      sd->cur.sec = -1;
548
549    if (sd->am_pm)
550      {
551         int ampm = 0;
552         if (sd->hrs >= 12) ampm = 1;
553         if (ampm != sd->cur.ampm)
554           {
555              msg.val = ampm;
556              edje_object_message_send
557                (sd->am_pm_obj, EDJE_MESSAGE_INT, 1, &msg);
558              sd->cur.ampm = ampm;
559           }
560      }
561    else
562      sd->cur.ampm = -1;
563 }
564
565 EOLIAN static Eina_Bool
566 _elm_clock_elm_widget_theme_apply(Eo *obj, Elm_Clock_Data *sd EINA_UNUSED)
567 {
568    Eina_Bool int_ret = EINA_FALSE;
569
570    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
571    if (!int_ret) return EINA_FALSE;
572
573    _time_update(obj);
574
575    return EINA_TRUE;
576 }
577
578 static Eina_Bool
579 _ticker(void *data)
580 {
581    ELM_CLOCK_DATA_GET(data, sd);
582
583    double t;
584    struct timeval timev;
585    struct tm *tm;
586    time_t tt;
587
588    gettimeofday(&timev, NULL);
589    t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
590
591    sd->ticker = ecore_timer_add(t, _ticker, data);
592    if (!sd->edit)
593      {
594         tt = (time_t)(timev.tv_sec) + sd->timediff;
595         tzset();
596         tm = localtime(&tt);
597         if (tm)
598           {
599              sd->hrs = tm->tm_hour;
600              sd->min = tm->tm_min;
601              sd->sec = tm->tm_sec;
602              _time_update(data);
603           }
604      }
605
606    return ECORE_CALLBACK_CANCEL;
607 }
608
609 static char *
610 _access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
611 {
612    int hrs;
613    char *ret;
614    Eina_Strbuf *buf;
615
616    ELM_CLOCK_DATA_GET(obj, sd);
617
618    buf = eina_strbuf_new();
619
620    hrs = sd->hrs;
621
622    if (sd->am_pm)
623      {
624         char *ampm = NULL;
625         if (hrs >= 12)
626           {
627              if (hrs > 12) hrs -= 12;
628              ampm = "PM";
629           }
630         else ampm = "AM";
631
632         eina_strbuf_append_printf(buf, "%d, %d, %s", hrs, sd->min, ampm);
633      }
634    else
635      {
636         eina_strbuf_append_printf(buf, "%d, %d", hrs, sd->min);
637      }
638
639    ret = eina_strbuf_string_steal(buf);
640    eina_strbuf_free(buf);
641    return ret;
642 }
643
644 static char *
645 _access_state_cb(void *data EINA_UNUSED, Evas_Object *obj)
646 {
647    ELM_CLOCK_DATA_GET(obj, sd);
648    if (sd->edit)
649      return strdup(E_("State: Editable"));
650
651    return NULL;
652 }
653
654 EOLIAN static void
655 _elm_clock_evas_object_smart_add(Eo *obj, Elm_Clock_Data *priv)
656 {
657    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
658
659    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
660    elm_widget_sub_object_parent_add(obj);
661
662    priv->cur.ampm = -1;
663    priv->cur.seconds = EINA_TRUE;
664    priv->cur.am_pm = EINA_TRUE;
665    priv->cur.edit = EINA_TRUE;
666    priv->cur.digedit = ELM_CLOCK_EDIT_DEFAULT;
667    priv->first_interval = DEFAULT_FIRST_INTERVAL;
668
669    elm_widget_can_focus_set(obj, EINA_TRUE);
670
671    _time_update(obj);
672    _ticker(obj);
673
674    /* access */
675    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
676      {
677         evas_object_propagate_events_set(obj, EINA_FALSE);
678         edje_object_signal_emit(wd->resize_obj,
679           "elm,state,access,on", "elm");
680      }
681
682    _elm_access_object_register(obj, wd->resize_obj);
683    _elm_access_text_set
684      (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("Clock"));
685    _elm_access_callback_set
686      (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
687    evas_object_propagate_events_set(obj, EINA_FALSE);
688    _elm_access_callback_set
689      (_elm_access_info_get(obj), ELM_ACCESS_STATE, _access_state_cb, NULL);
690 }
691
692 EOLIAN static void
693 _elm_clock_evas_object_smart_del(Eo *obj, Elm_Clock_Data *sd)
694 {
695
696    ecore_timer_del(sd->ticker);
697    ecore_timer_del(sd->spin);
698
699    /* NB: digits are killed for being sub objects, automatically */
700
701    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
702 }
703
704 static Eina_Bool _elm_clock_smart_focus_next_enable = EINA_FALSE;
705
706 EOLIAN static Eina_Bool
707 _elm_clock_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Clock_Data *_pd EINA_UNUSED)
708 {
709    return _elm_clock_smart_focus_next_enable;
710 }
711
712 EOLIAN static Eina_Bool
713 _elm_clock_elm_widget_focus_next(Eo *obj, Elm_Clock_Data *sd, Elm_Focus_Direction dir, Evas_Object **next)
714 {
715    Evas_Object *ao, *po;
716    Eina_List *items = NULL;
717
718
719    if (!sd->edit)
720      {
721         *next = (Evas_Object *)obj;
722         return !elm_widget_highlight_get(obj);
723      }
724    else if (!elm_widget_highlight_get(obj))
725      {
726         *next = (Evas_Object *)obj;
727         return EINA_TRUE;
728      }
729
730    int i;
731    for (i = 0; i < 6; i++)
732      {
733         if ((!sd->seconds) && (i >= 4)) break;
734         if (sd->digedit & (1 << i))
735           {
736              po = (Evas_Object *)edje_object_part_object_get
737                     (sd->digit[i], "access.t");
738              ao = evas_object_data_get(po, "_part_access_obj");
739              items = eina_list_append(items, ao);
740
741              po = (Evas_Object *)edje_object_part_object_get
742                     (sd->digit[i], "access.b");
743              ao = evas_object_data_get(po, "_part_access_obj");
744              items = eina_list_append(items, ao);
745           }
746      }
747
748    if (sd->am_pm)
749      {
750         po = (Evas_Object *)edje_object_part_object_get
751                (sd->am_pm_obj, "access.t");
752         ao = evas_object_data_get(po, "_part_access_obj");
753         items = eina_list_append(items, ao);
754
755         po = (Evas_Object *)edje_object_part_object_get
756                (sd->am_pm_obj, "access.b");
757         ao = evas_object_data_get(po, "_part_access_obj");
758         items = eina_list_append(items, ao);
759      }
760
761    return elm_widget_focus_list_next_get
762            (obj, items, eina_list_data_get, dir, next);
763 }
764
765 static void
766 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
767 {
768    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
769
770    /* clock object */
771    evas_object_propagate_events_set(obj, !is_access);
772
773    if (is_access)
774      edje_object_signal_emit(wd->resize_obj,
775        "elm,state,access,on", "elm");
776    else
777      edje_object_signal_emit(wd->resize_obj,
778        "elm,state,access,off", "elm");
779
780     /* clock time objects */
781     _access_time_register(obj, is_access);
782 }
783
784 EOLIAN static void
785 _elm_clock_elm_widget_access(Eo *obj EINA_UNUSED, Elm_Clock_Data *_pd EINA_UNUSED, Eina_Bool acs)
786 {
787    _elm_clock_smart_focus_next_enable = acs;
788    _access_obj_process(obj, _elm_clock_smart_focus_next_enable);
789 }
790
791 EAPI Evas_Object *
792 elm_clock_add(Evas_Object *parent)
793 {
794    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
795    Evas_Object *obj = eo_add(MY_CLASS, parent);
796    return obj;
797 }
798
799 EOLIAN static void
800 _elm_clock_eo_base_constructor(Eo *obj, Elm_Clock_Data *_pd EINA_UNUSED)
801 {
802    eo_do_super(obj, MY_CLASS, eo_constructor());
803    eo_do(obj,
804          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
805          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
806          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_TEXT));
807 }
808
809 static void
810 _timediff_set(Elm_Clock_Data *sd)
811 {
812    struct timeval timev;
813    struct tm *tm;
814    time_t tt;
815
816    gettimeofday(&timev, NULL);
817    tt = (time_t)(timev.tv_sec);
818    tzset();
819    tm = localtime(&tt);
820
821    if (tm)
822      {
823         sd->timediff = (((sd->hrs - tm->tm_hour) * 60 +
824                          sd->min - tm->tm_min) * 60) + sd->sec - tm->tm_sec;
825      }
826    else
827      {
828         ERR("Failed to get local time!");
829         sd->timediff = 0;
830      }
831 }
832
833 EOLIAN static void
834 _elm_clock_time_set(Eo *obj, Elm_Clock_Data *sd, int hrs, int min, int sec)
835 {
836    sd->hrs = hrs;
837    sd->min = min;
838    sd->sec = sec;
839
840    _timediff_set(sd);
841    _time_update(obj);
842 }
843
844 EOLIAN static void
845 _elm_clock_time_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd, int *hrs, int *min, int *sec)
846 {
847    if (hrs) *hrs = sd->hrs;
848    if (min) *min = sd->min;
849    if (sec) *sec = sd->sec;
850 }
851
852 EOLIAN static void
853 _elm_clock_edit_set(Eo *obj, Elm_Clock_Data *sd, Eina_Bool edit)
854 {
855    sd->edit = edit;
856    if (!edit)
857      _timediff_set(sd);
858    if ((edit) && (sd->digedit == ELM_CLOCK_EDIT_DEFAULT))
859      elm_clock_edit_mode_set(obj, ELM_CLOCK_EDIT_ALL);
860    else
861      _time_update(obj);
862 }
863
864 EOLIAN static Eina_Bool
865 _elm_clock_edit_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
866 {
867    return sd->edit;
868 }
869
870 EOLIAN static void
871 _elm_clock_edit_mode_set(Eo *obj, Elm_Clock_Data *sd, Elm_Clock_Edit_Mode digedit)
872 {
873    sd->digedit = digedit;
874    if (digedit == ELM_CLOCK_EDIT_DEFAULT)
875      elm_clock_edit_set(obj, EINA_FALSE);
876    else
877      _time_update(obj);
878 }
879
880 EOLIAN static Elm_Clock_Edit_Mode
881 _elm_clock_edit_mode_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
882 {
883    return sd->digedit;
884 }
885
886 EOLIAN static void
887 _elm_clock_show_am_pm_set(Eo *obj, Elm_Clock_Data *sd, Eina_Bool am_pm)
888 {
889    sd->am_pm = !!am_pm;
890    _time_update(obj);
891 }
892
893 EOLIAN static Eina_Bool
894 _elm_clock_show_am_pm_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
895 {
896    return sd->am_pm;
897 }
898
899 EOLIAN static void
900 _elm_clock_show_seconds_set(Eo *obj, Elm_Clock_Data *sd, Eina_Bool seconds)
901 {
902    sd->seconds = !!seconds;
903    _time_update(obj);
904 }
905
906 EOLIAN static Eina_Bool
907 _elm_clock_show_seconds_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
908 {
909    return sd->seconds;
910 }
911
912 EOLIAN static void
913 _elm_clock_first_interval_set(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd, double interval)
914 {
915    sd->first_interval = interval;
916 }
917
918 EOLIAN static double
919 _elm_clock_first_interval_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
920 {
921    return sd->first_interval;
922 }
923
924 EOLIAN static void
925 _elm_clock_pause_set(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd, Eina_Bool paused)
926 {
927    paused = !!paused;
928    if (sd->paused == paused)
929      return;
930    sd->paused = paused;
931    if (paused)
932      ecore_timer_freeze(sd->ticker);
933    else
934      {
935         _timediff_set(sd);
936         ecore_timer_thaw(sd->ticker);
937      }
938 }
939
940 EOLIAN static Eina_Bool
941 _elm_clock_pause_get(Eo *obj EINA_UNUSED, Elm_Clock_Data *sd)
942 {
943    return sd->paused;
944 }
945
946 EOLIAN static Eina_Bool
947 _elm_clock_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Clock_Data *_pd EINA_UNUSED)
948 {
949    return EINA_FALSE;
950 }
951
952 static void
953 _elm_clock_class_constructor(Eo_Class *klass)
954 {
955    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
956
957    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
958       _elm_clock_smart_focus_next_enable = EINA_TRUE;
959 }
960
961 #include "elm_clock.eo.c"