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