1 #include <Elementary.h>
5 * @defgroup Clock Clock
8 * It's a widget to show clock with animation. The update of time is
9 * shown in an animation like the flip of a sheet.
13 typedef struct _Widget_Data Widget_Data;
18 double interval, first_interval;
19 Eina_Bool seconds : 1;
22 Elm_Clock_Digedit digedit;
24 Evas_Object *digit[6];
27 Ecore_Timer *ticker, *spin;
32 Eina_Bool seconds : 1;
35 Elm_Clock_Digedit digedit;
39 static const char *widtype = NULL;
40 static void _del_hook(Evas_Object *obj);
41 static void _theme_hook(Evas_Object *obj);
42 static Eina_Bool _ticker(void *data);
43 static Eina_Bool _signal_clock_val_up(void *data);
44 static Eina_Bool _signal_clock_val_down(void *data);
45 static void _time_update(Evas_Object *obj);
48 _del_hook(Evas_Object *obj)
50 Widget_Data *wd = elm_widget_data_get(obj);
53 for (i = 0; i < 6; i++)
55 if (wd->digit[i]) evas_object_del(wd->digit[i]);
57 if (wd->ampm) evas_object_del(wd->ampm);
58 if (wd->ticker) ecore_timer_del(wd->ticker);
59 if (wd->spin) ecore_timer_del(wd->spin);
64 _theme_hook(Evas_Object *obj)
66 Widget_Data *wd = elm_widget_data_get(obj);
68 if (elm_widget_focus_get(obj))
69 edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
71 edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
72 wd->cur.am_pm = !wd->cur.am_pm; /* hack - force update */
77 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
79 Widget_Data *wd = elm_widget_data_get(obj);
81 if (elm_widget_focus_get(obj))
82 edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
84 edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
88 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
90 Widget_Data *wd = elm_widget_data_get(obj);
93 edje_object_signal_emit(wd->clk, emission, source);
94 for (i = 0; i < 6; i++)
97 edje_object_signal_emit(wd->digit[i], emission, source);
102 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
104 Widget_Data *wd = elm_widget_data_get(obj);
107 edje_object_signal_callback_add(wd->clk, emission, source, func_cb, data);
108 for (i = 0; i < 6; i++)
111 edje_object_signal_callback_add(wd->digit[i], emission, source,
117 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source))
119 Widget_Data *wd = elm_widget_data_get(obj);
121 if (!wd) return NULL;
122 for (i = 0; i < 6; i++)
124 edje_object_signal_callback_del(wd->digit[i], emission, source,
127 return edje_object_signal_callback_del(wd->clk, emission, source, func_cb);
133 Widget_Data *wd = elm_widget_data_get(data);
135 struct timeval timev;
138 if (!wd) return ECORE_CALLBACK_CANCEL;
139 gettimeofday(&timev, NULL);
140 t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
141 wd->ticker = ecore_timer_add(t, _ticker, data);
144 tt = (time_t)(timev.tv_sec);
149 wd->hrs = tm->tm_hour;
150 wd->min = tm->tm_min;
151 wd->sec = tm->tm_sec;
155 return ECORE_CALLBACK_CANCEL;
159 _signal_clock_val_up(void *data)
161 Widget_Data *wd = elm_widget_data_get(data);
162 if (!wd) goto clock_val_up_exit_on_error;
163 if (!wd->edit) goto clock_val_up_cancel;
164 if (!wd->sel_obj) goto clock_val_up_cancel;
165 if (wd->sel_obj == wd->digit[0])
167 wd->hrs = wd->hrs + 10;
168 if (wd->hrs >= 24) wd->hrs -= 24;
170 if (wd->sel_obj == wd->digit[1])
172 wd->hrs = wd->hrs + 1;
173 if (wd->hrs >= 24) wd->hrs -= 24;
175 if (wd->sel_obj == wd->digit[2])
177 wd->min = wd->min + 10;
178 if (wd->min >= 60) wd->min -= 60;
180 if (wd->sel_obj == wd->digit[3])
182 wd->min = wd->min + 1;
183 if (wd->min >= 60) wd->min -= 60;
185 if (wd->sel_obj == wd->digit[4])
187 wd->sec = wd->sec + 10;
188 if (wd->sec >= 60) wd->sec -= 60;
190 if (wd->sel_obj == wd->digit[5])
192 wd->sec = wd->sec + 1;
193 if (wd->sec >= 60) wd->sec -= 60;
195 if (wd->sel_obj == wd->ampm)
197 wd->hrs = wd->hrs + 12;
198 if (wd->hrs > 23) wd->hrs -= 24;
200 wd->interval = wd->interval / 1.05;
201 ecore_timer_interval_set(wd->spin, wd->interval);
203 evas_object_smart_callback_call(data, "changed", NULL);
204 return ECORE_CALLBACK_RENEW;
207 clock_val_up_exit_on_error:
208 return ECORE_CALLBACK_CANCEL;
212 _signal_clock_val_down(void *data)
214 Widget_Data *wd = elm_widget_data_get(data);
215 if (!wd) goto clock_val_down_exit_on_error;
216 if (!wd->edit) goto clock_val_down_cancel;
217 if (!wd->sel_obj) goto clock_val_down_cancel;
218 if (wd->sel_obj == wd->digit[0])
220 wd->hrs = wd->hrs - 10;
221 if (wd->hrs < 0) wd->hrs += 24;
223 if (wd->sel_obj == wd->digit[1])
225 wd->hrs = wd->hrs - 1;
226 if (wd->hrs < 0) wd->hrs += 24;
228 if (wd->sel_obj == wd->digit[2])
230 wd->min = wd->min - 10;
231 if (wd->min < 0) wd->min += 60;
233 if (wd->sel_obj == wd->digit[3])
235 wd->min = wd->min - 1;
236 if (wd->min < 0) wd->min += 60;
238 if (wd->sel_obj == wd->digit[4])
240 wd->sec = wd->sec - 10;
241 if (wd->sec < 0) wd->sec += 60;
243 if (wd->sel_obj == wd->digit[5])
245 wd->sec = wd->sec - 1;
246 if (wd->sec < 0) wd->sec += 60;
248 if (wd->sel_obj == wd->ampm)
250 wd->hrs = wd->hrs - 12;
251 if (wd->hrs < 0) wd->hrs += 24;
253 wd->interval = wd->interval / 1.05;
254 ecore_timer_interval_set(wd->spin, wd->interval);
256 evas_object_smart_callback_call(data, "changed", NULL);
257 return ECORE_CALLBACK_RENEW;
258 clock_val_down_cancel:
260 clock_val_down_exit_on_error:
261 return ECORE_CALLBACK_CANCEL;
265 _signal_clock_val_up_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
267 Widget_Data *wd = elm_widget_data_get(data);
269 wd->interval = wd->first_interval;
271 if (wd->spin) ecore_timer_del(wd->spin);
272 wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_up, data);
273 _signal_clock_val_up(data);
277 _signal_clock_val_down_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
279 Widget_Data *wd = elm_widget_data_get(data);
281 wd->interval = wd->first_interval;
283 if (wd->spin) ecore_timer_del(wd->spin);
284 wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_down, data);
285 _signal_clock_val_down(data);
289 _signal_clock_val_change_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
291 Widget_Data *wd = elm_widget_data_get(data);
293 if (wd->spin) ecore_timer_del(wd->spin);
299 _time_update(Evas_Object *obj)
301 Widget_Data *wd = elm_widget_data_get(obj);
302 Edje_Message_Int msg;
304 const char *style = elm_widget_style_get(obj);
306 if ((wd->cur.seconds != wd->seconds) || (wd->cur.am_pm != wd->am_pm) ||
307 (wd->cur.edit != wd->edit) || (wd->cur.digedit != wd->digedit))
312 for (i = 0; i < 6; i++)
316 evas_object_del(wd->digit[i]);
322 evas_object_del(wd->ampm);
326 if ((wd->seconds) && (wd->am_pm))
327 _elm_theme_object_set(obj, wd->clk, "clock", "base-all", style);
328 else if (wd->seconds)
329 _elm_theme_object_set(obj, wd->clk, "clock", "base-seconds", style);
331 _elm_theme_object_set(obj, wd->clk, "clock", "base-am_pm", style);
333 _elm_theme_object_set(obj, wd->clk, "clock", "base", style);
334 edje_object_scale_set(wd->clk, elm_widget_scale_get(obj) *
337 for (i = 0; i < 6; i++)
341 if ((!wd->seconds) && (i >= 4)) break;
342 wd->digit[i] = edje_object_add(evas_object_evas_get(wd->clk));
343 _elm_theme_object_set(obj, wd->digit[i], "clock", "flipdigit", style);
344 edje_object_scale_set(wd->digit[i], elm_widget_scale_get(obj) *
346 if (wd->edit && (wd->digedit & (1 << i)))
347 edje_object_signal_emit(wd->digit[i], "elm,state,edit,on", "elm");
348 edje_object_signal_callback_add(wd->digit[i], "elm,action,up,start",
349 "", _signal_clock_val_up_start, obj);
350 edje_object_signal_callback_add(wd->digit[i], "elm,action,up,stop",
351 "", _signal_clock_val_change_stop, obj);
352 edje_object_signal_callback_add(wd->digit[i], "elm,action,down,start",
353 "", _signal_clock_val_down_start, obj);
354 edje_object_signal_callback_add(wd->digit[i], "elm,action,down,stop",
355 "", _signal_clock_val_change_stop, obj);
357 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
358 edje_object_size_min_restricted_calc(wd->digit[i], &mw, &mh, mw, mh);
359 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
360 edje_extern_object_min_size_set(wd->digit[i], mw, mh);
361 snprintf(buf, sizeof(buf), "d%i", i);
362 edje_object_part_swallow(wd->clk , buf, wd->digit[i]);
363 evas_object_show(wd->digit[i]);
367 wd->ampm = edje_object_add(evas_object_evas_get(wd->clk));
368 _elm_theme_object_set(obj, wd->ampm, "clock", "flipampm", style);
369 edje_object_scale_set(wd->ampm, elm_widget_scale_get(obj) *
372 edje_object_signal_emit(wd->ampm, "elm,state,edit,on", "elm");
373 edje_object_signal_callback_add(wd->ampm, "elm,action,up,start",
374 "", _signal_clock_val_up_start, obj);
375 edje_object_signal_callback_add(wd->ampm, "elm,action,up,stop",
376 "", _signal_clock_val_change_stop, obj);
377 edje_object_signal_callback_add(wd->ampm, "elm,action,down,start",
378 "", _signal_clock_val_down_start, obj);
379 edje_object_signal_callback_add(wd->ampm, "elm,action,down,stop",
380 "", _signal_clock_val_change_stop, obj);
382 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
383 edje_object_size_min_restricted_calc(wd->ampm, &mw, &mh, mw, mh);
384 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
385 edje_extern_object_min_size_set(wd->ampm, mw, mh);
386 edje_object_part_swallow(wd->clk , "ampm", wd->ampm);
387 evas_object_show(wd->ampm);
390 edje_object_size_min_calc(wd->clk, &mw, &mh);
391 evas_object_size_hint_min_set(obj, mw, mh);
397 wd->cur.seconds = wd->seconds;
398 wd->cur.am_pm = wd->am_pm;
399 wd->cur.edit = wd->edit;
400 wd->cur.digedit = wd->digedit;
402 if (wd->hrs != wd->cur.hrs)
405 int d1, d2, dc1, dc2;
412 if (hrs > 12) hrs -= 12;
415 else if (hrs == 0) hrs = 12;
419 dc1 = wd->cur.hrs / 10;
420 dc2 = wd->cur.hrs % 10;
424 edje_object_message_send(wd->digit[0], EDJE_MESSAGE_INT, 1, &msg);
429 edje_object_message_send(wd->digit[1], EDJE_MESSAGE_INT, 1, &msg);
433 if (wd->min != wd->cur.min)
435 int d1, d2, dc1, dc2;
439 dc1 = wd->cur.min / 10;
440 dc2 = wd->cur.min % 10;
444 edje_object_message_send(wd->digit[2], EDJE_MESSAGE_INT, 1, &msg);
449 edje_object_message_send(wd->digit[3], EDJE_MESSAGE_INT, 1, &msg);
451 wd->cur.min = wd->min;
455 if (wd->sec != wd->cur.sec)
457 int d1, d2, dc1, dc2;
461 dc1 = wd->cur.sec / 10;
462 dc2 = wd->cur.sec % 10;
466 edje_object_message_send(wd->digit[4], EDJE_MESSAGE_INT, 1, &msg);
471 edje_object_message_send(wd->digit[5], EDJE_MESSAGE_INT, 1, &msg);
473 wd->cur.sec = wd->sec;
481 if (wd->hrs >= 12) ampm = 1;
482 if (ampm != wd->cur.ampm)
484 if (wd->cur.ampm != ampm)
487 edje_object_message_send(wd->ampm, EDJE_MESSAGE_INT, 1, &msg);
497 * Add a new clock to the parent
499 * @param parent The parent object
501 * This function inserts a clock widget on a given canvas to show a
507 elm_clock_add(Evas_Object *parent)
513 wd = ELM_NEW(Widget_Data);
514 e = evas_object_evas_get(parent);
515 obj = elm_widget_add(e);
516 ELM_SET_WIDTYPE(widtype, "clock");
517 elm_widget_type_set(obj, "clock");
518 elm_widget_sub_object_add(parent, obj);
519 elm_widget_data_set(obj, wd);
520 elm_widget_del_hook_set(obj, _del_hook);
521 elm_widget_theme_hook_set(obj, _theme_hook);
522 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
523 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
524 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
525 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
527 wd->clk = edje_object_add(e);
528 elm_widget_resize_object_set(obj, wd->clk);
531 wd->cur.seconds = EINA_TRUE;
532 wd->cur.am_pm = EINA_TRUE;
533 wd->cur.edit = EINA_TRUE;
534 wd->cur.digedit = ELM_CLOCK_NONE;
535 wd->first_interval = 0.85;
546 * @param obj The clock object
547 * @param hrs The hours to set
548 * @param min The minutes to set
549 * @param sec The secondes to set
551 * This function updates the time that is showed by the clock widget
556 elm_clock_time_set(Evas_Object *obj, int hrs, int min, int sec)
558 ELM_CHECK_WIDTYPE(obj, widtype);
559 Widget_Data *wd = elm_widget_data_get(obj);
570 * @param obj The clock object
571 * @param hrs Pointer to the variable to get the hour of this clock
573 * @param min Pointer to the variable to get the minute of this clock
575 * @param sec Pointer to the variable to get the second of this clock
578 * This function gets the time set of the clock widget and returns it
579 * on the variables passed as the arguments to function
584 elm_clock_time_get(const Evas_Object *obj, int *hrs, int *min, int *sec)
586 ELM_CHECK_WIDTYPE(obj, widtype);
587 Widget_Data *wd = elm_widget_data_get(obj);
589 if (hrs) *hrs = wd->hrs;
590 if (min) *min = wd->min;
591 if (sec) *sec = wd->sec;
595 * Set if the clock settings can be edited
597 * @param obj The clock object
598 * @param edit Bool option for edited (1 = yes, 0 = no)
600 * This function sets if the clock settings can be edited or not.
601 * By default or if digit_edit option was previously set to ELM_CLOCK_NONE,
602 * all digits are editable. To choose what digits to make editable
603 * use elm_clock_digit_edit_set().
608 elm_clock_edit_set(Evas_Object *obj, Eina_Bool edit)
610 ELM_CHECK_WIDTYPE(obj, widtype);
611 Widget_Data *wd = elm_widget_data_get(obj);
614 if (edit && (wd->digedit == ELM_CLOCK_NONE))
615 elm_clock_digit_edit_set(obj, ELM_CLOCK_ALL);
621 * Get if the clock settings can be edited
623 * @param obj The clock object
624 * @return Bool option for edited (1 = yes, 0 = no)
626 * This function gets if the clock settings can be edited or not.
631 elm_clock_edit_get(const Evas_Object *obj)
633 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
634 Widget_Data *wd = elm_widget_data_get(obj);
635 if (!wd) return EINA_FALSE;
640 * Set what digits of the clock are editable
642 * @param obj The clock object
643 * @param digedit Bit mask indicating the digits to edit
645 * If the digedit param is ELM_CLOCK_NONE, editing will be disabled.
650 elm_clock_digit_edit_set(Evas_Object *obj, Elm_Clock_Digedit digedit)
652 ELM_CHECK_WIDTYPE(obj, widtype);
653 Widget_Data *wd = elm_widget_data_get(obj);
655 wd->digedit = digedit;
656 if (digedit == ELM_CLOCK_NONE)
657 elm_clock_edit_set(obj, EINA_FALSE);
663 * Get what digits of the clock are editable
665 * @param obj The clock object
666 * @return Bit mask indicating the digits.
670 EAPI Elm_Clock_Digedit
671 elm_clock_digit_edit_get(const Evas_Object *obj)
673 ELM_CHECK_WIDTYPE(obj, widtype) 0;
674 Widget_Data *wd = elm_widget_data_get(obj);
680 * Set if the clock shows hours in military or am/pm mode
682 * @param obj The clock object
683 * @param am_pm Bool option for the hours mode
684 * (1 = am/pm, 0 = military)
686 * This function sets the clock to show hours in military or am/pm
687 * mode. Some countries like Brazil the military mode (00-24h-format)
688 * is used in opposition to the USA where the am/pm mode is more
694 elm_clock_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm)
696 ELM_CHECK_WIDTYPE(obj, widtype);
697 Widget_Data *wd = elm_widget_data_get(obj);
704 * Get if the clock shows hours in military or am/pm mode
706 * @param obj The clock object
707 * @return Bool option for the hours mode
708 * (1 = am/pm, 0 = military)
710 * This function gets if the clock show hours in military or am/pm
711 * mode. Some countries like Brazil the military mode (00-24h-format)
712 * is used in opposition to the USA where the am/pm mode is more
718 elm_clock_show_am_pm_get(const Evas_Object *obj)
720 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
721 Widget_Data *wd = elm_widget_data_get(obj);
722 if (!wd) return EINA_FALSE;
727 * Set if the clock shows hour with the seconds
729 * @param obj The clock object
730 * @param seconds Bool option for the show seconds
731 * (1 = show seconds, 0 = not show seconds)
733 * This function sets the clock to show or not to show the elapsed
739 elm_clock_show_seconds_set(Evas_Object *obj, Eina_Bool seconds)
741 ELM_CHECK_WIDTYPE(obj, widtype);
742 Widget_Data *wd = elm_widget_data_get(obj);
744 wd->seconds = seconds;
749 * Get if the clock shows hour with the seconds
751 * @param obj The clock object
752 * @return Bool option for the show seconds
753 * (1 = show seconds, 0 = not show seconds)
755 * This function gets if the clock show or not show the elapsed
761 elm_clock_show_seconds_get(const Evas_Object *obj)
763 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
764 Widget_Data *wd = elm_widget_data_get(obj);
765 if (!wd) return EINA_FALSE;
770 * Set the interval for the clock
772 * @param obj The clock object
773 * @param interval The interval value in seconds
775 * The interval value is decreased while the user increments or decrements
776 * the clock value. The next interval value is the previous interval / 1.05,
777 * so it speed up a bit. Default value is 0.85 seconds.
782 elm_clock_interval_set(Evas_Object *obj, double interval)
784 ELM_CHECK_WIDTYPE(obj, widtype);
785 Widget_Data *wd = elm_widget_data_get(obj);
787 wd->first_interval = interval;
791 * Get the interval of the clock
793 * @param obj The clock object
794 * @return The value of the first interval in seconds
796 * The interval value is decreased while the user increments or decrements
797 * the clock value. The next interval value is the previous interval / 1.05,
798 * so it speed up a bit. Default value is 0.85 seconds.
803 elm_clock_interval_get(const Evas_Object *obj)
805 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
806 Widget_Data *wd = elm_widget_data_get(obj);
808 return wd->first_interval;