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