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