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