1 #include <Elementary.h>
3 #include "elm_widget_calendar.h"
5 EAPI const char ELM_CALENDAR_SMART_NAME[] = "elm_calendar";
7 static const char SIG_CHANGED[] = "changed";
8 static const char SIG_DISPLAY_CHANGED[] = "display,changed";
10 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
12 {SIG_DISPLAY_CHANGED, ""},
16 /* Should not be translated, it's used if we failed
17 * getting from locale. */
18 static const char *_days_abbrev[] =
20 "Sun", "Mon", "Tue", "Wed",
24 static int _days_in_month[2][12] =
26 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
27 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
30 EVAS_SMART_SUBCLASS_NEW
31 (ELM_CALENDAR_SMART_NAME, _elm_calendar, Elm_Calendar_Smart_Class,
32 Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
34 static Elm_Calendar_Mark *
35 _mark_new(Evas_Object *obj,
36 const char *mark_type,
38 Elm_Calendar_Mark_Repeat_Type repeat)
40 Elm_Calendar_Mark *mark;
42 mark = calloc(1, sizeof(Elm_Calendar_Mark));
43 if (!mark) return NULL;
45 mark->mark_type = eina_stringshare_add(mark_type);
46 mark->mark_time = *mark_time;
47 mark->repeat = repeat;
53 _mark_free(Elm_Calendar_Mark *mark)
55 eina_stringshare_del(mark->mark_type);
60 _elm_calendar_smart_sizing_eval(Evas_Object *obj)
62 Evas_Coord minw = -1, minh = -1;
64 ELM_CALENDAR_DATA_GET(obj, sd);
66 elm_coords_finger_size_adjust(8, &minw, ELM_DAY_LAST, &minh);
67 edje_object_size_min_restricted_calc
68 (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh);
69 evas_object_size_hint_min_set(obj, minw, minh);
70 evas_object_size_hint_max_set(obj, -1, -1);
74 _maxdays_get(struct tm *selected_time)
78 month = selected_time->tm_mon;
79 year = selected_time->tm_year + 1900;
82 [((!(year % 4)) && ((!(year % 400)) || (year % 100)))][month];
86 _unselect(Evas_Object *obj,
91 snprintf(emission, sizeof(emission), "cit_%i,unselected", selected);
92 elm_layout_signal_emit(obj, emission, "elm");
96 _select(Evas_Object *obj,
101 ELM_CALENDAR_DATA_GET(obj, sd);
103 sd->selected_it = selected;
104 snprintf(emission, sizeof(emission), "cit_%i,selected", selected);
105 elm_layout_signal_emit(obj, emission, "elm");
109 _not_today(Elm_Calendar_Smart_Data *sd)
113 snprintf(emission, sizeof(emission), "cit_%i,not_today", sd->today_it);
114 elm_layout_signal_emit(ELM_WIDGET_DATA(sd)->obj, emission, "elm");
119 _today(Elm_Calendar_Smart_Data *sd,
124 snprintf(emission, sizeof(emission), "cit_%i,today", it);
125 elm_layout_signal_emit(ELM_WIDGET_DATA(sd)->obj, emission, "elm");
130 _format_month_year(struct tm *selected_time)
134 if (!strftime(buf, sizeof(buf), E_("%B %Y"), selected_time)) return NULL;
139 _cit_mark(Evas_Object *cal,
145 snprintf(sign, sizeof(sign), "cit_%i,%s", cit, mtype);
146 elm_layout_signal_emit(cal, sign, "elm");
150 _weekday_get(int first_week_day,
153 return (day + first_week_day - 1) % ELM_DAY_LAST;
158 _text_day_color_update(Elm_Calendar_Smart_Data *sd,
163 switch (sd->day_color[pos])
166 snprintf(emission, sizeof(emission), "cit_%i,weekday", pos);
170 snprintf(emission, sizeof(emission), "cit_%i,saturday", pos);
174 snprintf(emission, sizeof(emission), "cit_%i,sunday", pos);
181 elm_layout_signal_emit(ELM_WIDGET_DATA(sd)->obj, emission, "elm");
185 _set_month_year(Elm_Calendar_Smart_Data *sd)
189 /* Set selected month */
190 buf = sd->format_func(&sd->shown_time);
193 elm_layout_text_set(ELM_WIDGET_DATA(sd)->obj, "month_text", buf);
196 else elm_layout_text_set(ELM_WIDGET_DATA(sd)->obj, "month_text", "");
200 _access_info_cb(void *data __UNUSED__, Evas_Object *obj)
204 buf = eina_strbuf_new();
206 eina_strbuf_append_printf(buf, "day %s", elm_widget_access_info_get(obj));
208 ret = eina_strbuf_string_steal(buf);
209 eina_strbuf_free(buf);
214 _access_calendar_item_register(Evas_Object *obj)
217 char day_s[3], pname[14];
220 ELM_CALENDAR_DATA_GET(obj, sd);
223 maxdays = _maxdays_get(&sd->shown_time);
224 for (i = 0; i < 42; i++)
226 if ((!day) && (i == sd->first_day_it)) day = 1;
227 if ((day) && (day <= maxdays))
229 snprintf(pname, sizeof(pname), "cit_%i.access", i);
231 ao = _elm_access_edje_object_part_object_register
232 (obj, elm_layout_edje_get(obj), pname);
233 _elm_access_text_set(_elm_access_object_get(ao),
234 ELM_ACCESS_TYPE, E_("calendar item"));
235 _elm_access_callback_set(_elm_access_object_get(ao),
236 ELM_ACCESS_INFO, _access_info_cb, NULL);
238 snprintf(day_s, sizeof(day_s), "%i", day++);
239 elm_widget_access_info_set(ao, (const char*)day_s);
243 snprintf(pname, sizeof(pname), "cit_%i.access", i);
244 _elm_access_edje_object_part_object_unregister
245 (obj, elm_layout_edje_get(obj), pname);
251 _access_calendar_spinner_register(Evas_Object *obj)
255 ELM_CALENDAR_DATA_GET(obj, sd);
258 sd->dec_btn_access = _elm_access_edje_object_part_object_register
259 (obj, elm_layout_edje_get(obj), "left_bt");
260 ai = _elm_access_object_get(sd->dec_btn_access);
261 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar decrement button"));
264 sd->inc_btn_access = _elm_access_edje_object_part_object_register
265 (obj, elm_layout_edje_get(obj), "right_bt");
266 ai = _elm_access_object_get(sd->inc_btn_access);
267 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar increment button"));
270 sd->month_access = _elm_access_edje_object_part_object_register
271 (obj, elm_layout_edje_get(obj), "month_text");
272 ai = _elm_access_object_get(sd->month_access);
273 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar month"));
275 po = (Evas_Object *)edje_object_part_object_get
276 (elm_layout_edje_get(obj), "month_text");
277 evas_object_pass_events_set(po, EINA_FALSE);
282 _access_calendar_register(Evas_Object *obj)
284 _access_calendar_spinner_register(obj);
285 _access_calendar_item_register(obj);
289 _populate(Evas_Object *obj)
291 int maxdays, day, mon, yr, i;
292 Elm_Calendar_Mark *mark;
293 char part[12], day_s[3];
296 Eina_Bool last_row = EINA_TRUE;
298 ELM_CALENDAR_DATA_GET(obj, sd);
300 elm_layout_freeze(obj);
302 if (sd->today_it > 0) _not_today(sd);
304 maxdays = _maxdays_get(&sd->shown_time);
305 mon = sd->shown_time.tm_mon;
306 yr = sd->shown_time.tm_year;
312 first_day = sd->shown_time;
313 first_day.tm_mday = 1;
316 // Layout of the calendar is changed for removing the unfilled last row.
317 if (first_day.tm_wday < (int)sd->first_week_day)
318 sd->first_day_it = first_day.tm_wday + ELM_DAY_LAST - sd->first_week_day;
320 sd->first_day_it = first_day.tm_wday - sd->first_week_day;
322 if ((35 - sd->first_day_it) > (maxdays - 1)) last_row = EINA_FALSE;
328 for (i = 0; i < 5; i++)
330 snprintf(emission, sizeof(emission), "cseph_%i,row_hide", i);
331 elm_layout_signal_emit(obj, emission, "elm");
333 snprintf(emission, sizeof(emission), "cseph_%i,row_invisible", 5);
334 elm_layout_signal_emit(obj, emission, "elm");
335 for (i = 0; i < 35; i++)
337 snprintf(emission, sizeof(emission), "cit_%i,cell_expanded", i);
338 elm_layout_signal_emit(obj, emission, "elm");
340 for (i = 35; i < 42; i++)
342 snprintf(emission, sizeof(emission), "cit_%i,cell_invisible", i);
343 elm_layout_signal_emit(obj, emission, "elm");
350 for (i = 0; i < 6; i++)
352 snprintf(emission, sizeof(emission), "cseph_%i,row_show", i);
353 elm_layout_signal_emit(obj, emission, "elm");
355 for (i = 0; i < 42; i++)
357 snprintf(emission, sizeof(emission), "cit_%i,cell_default", i);
358 elm_layout_signal_emit(obj, emission, "elm");
362 for (i = 0; i < 42; i++)
364 _text_day_color_update(sd, i); // EINA_DEPRECATED
365 if ((!day) && (i == sd->first_day_it)) day = 1;
367 if ((day == sd->current_time.tm_mday)
368 && (mon == sd->current_time.tm_mon)
369 && (yr == sd->current_time.tm_year))
372 if (day == sd->selected_time.tm_mday)
374 if ((sd->selected_it > -1) && (sd->selected_it != i))
375 _unselect(obj, sd->selected_it);
377 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
379 if ((mon == sd->selected_time.tm_mon)
380 && (yr == sd->selected_time.tm_year)
386 else if (sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE)
392 if ((day) && (day <= maxdays))
393 snprintf(day_s, sizeof(day_s), "%i", day++);
397 snprintf(part, sizeof(part), "cit_%i.text", i);
398 elm_layout_text_set(obj, part, day_s);
400 /* Clear previous marks */
401 _cit_mark(obj, i, "clear");
405 if ((_elm_config->access_mode != ELM_ACCESS_MODE_OFF))
406 _access_calendar_item_register(obj);
409 EINA_LIST_FOREACH(sd->marks, l, mark)
411 struct tm *mtime = &mark->mark_time;
412 int month = sd->shown_time.tm_mon;
413 int year = sd->shown_time.tm_year;
414 int mday_it = mtime->tm_mday + sd->first_day_it - 1;
416 switch (mark->repeat)
418 case ELM_CALENDAR_UNIQUE:
419 if ((mtime->tm_mon == month) && (mtime->tm_year == year))
420 _cit_mark(obj, mday_it, mark->mark_type);
423 case ELM_CALENDAR_DAILY:
424 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
425 (mtime->tm_year < year))
427 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
428 day = mtime->tm_mday;
431 for (; day <= maxdays; day++)
432 _cit_mark(obj, day + sd->first_day_it - 1,
436 case ELM_CALENDAR_WEEKLY:
437 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
438 (mtime->tm_year < year))
440 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
441 day = mtime->tm_mday;
444 for (; day <= maxdays; day++)
445 if (mtime->tm_wday == _weekday_get(sd->first_day_it, day))
446 _cit_mark(obj, day + sd->first_day_it - 1,
450 case ELM_CALENDAR_MONTHLY:
451 if (((mtime->tm_year < year) ||
452 ((mtime->tm_year == year) && (mtime->tm_mon <= month))) &&
453 (mtime->tm_mday <= maxdays))
454 _cit_mark(obj, mday_it, mark->mark_type);
457 case ELM_CALENDAR_ANNUALLY:
458 if ((mtime->tm_year <= year) && (mtime->tm_mon == month) &&
459 (mtime->tm_mday <= maxdays))
460 _cit_mark(obj, mday_it, mark->mark_type);
463 case ELM_CALENDAR_LAST_DAY_OF_MONTH:
464 if (((mtime->tm_year < year) ||
465 ((mtime->tm_year == year) && (mtime->tm_mon <= month))))
466 _cit_mark(obj, maxdays + sd->first_day_it - 1, mark->mark_type);
471 elm_layout_thaw(obj);
475 _set_headers(Evas_Object *obj)
477 static char part[] = "ch_0.text";
479 ELM_CALENDAR_DATA_GET(obj, sd);
481 elm_layout_freeze(obj);
483 for (i = 0; i < ELM_DAY_LAST; i++)
487 (obj, part, sd->weekdays[(i + sd->first_week_day) % ELM_DAY_LAST]);
490 elm_layout_thaw(obj);
494 _elm_calendar_smart_theme(Evas_Object *obj)
496 if (!ELM_WIDGET_CLASS(_elm_calendar_parent_sc)->theme(obj))
499 evas_object_smart_changed(obj);
504 /* Set correct tm_wday and tm_yday after other fields changes*/
506 _fix_selected_time(Elm_Calendar_Smart_Data *sd)
508 if (sd->selected_time.tm_mon != sd->shown_time.tm_mon)
509 sd->selected_time.tm_mon = sd->shown_time.tm_mon;
510 if (sd->selected_time.tm_year != sd->shown_time.tm_year)
511 sd->selected_time.tm_year = sd->shown_time.tm_year;
512 mktime(&sd->selected_time);
516 _update_month(Evas_Object *obj,
519 struct tm time_check;
522 ELM_CALENDAR_DATA_GET(obj, sd);
524 /* check if it's a valid time. for 32 bits, year greater than 2037 is not */
525 time_check = sd->shown_time;
526 time_check.tm_mon += delta;
527 if (mktime(&time_check) == -1)
530 sd->shown_time.tm_mon += delta;
531 if (sd->shown_time.tm_mon < 0)
533 if (sd->shown_time.tm_year == sd->year_min)
535 sd->shown_time.tm_mon++;
538 sd->shown_time.tm_mon = 11;
539 sd->shown_time.tm_year--;
541 else if (sd->shown_time.tm_mon > 11)
543 if (sd->shown_time.tm_year == sd->year_max)
545 sd->shown_time.tm_mon--;
548 sd->shown_time.tm_mon = 0;
549 sd->shown_time.tm_year++;
552 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
553 && (sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE))
555 maxdays = _maxdays_get(&sd->shown_time);
556 if (sd->selected_time.tm_mday > maxdays)
557 sd->selected_time.tm_mday = maxdays;
559 _fix_selected_time(sd);
560 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
562 evas_object_smart_callback_call(obj, SIG_DISPLAY_CHANGED, NULL);
568 _spin_value(void *data)
570 ELM_CALENDAR_DATA_GET(data, sd);
572 if (_update_month(data, sd->spin_speed))
573 evas_object_smart_changed(data);
575 sd->interval = sd->interval / 1.05;
576 ecore_timer_interval_set(sd->spin, sd->interval);
578 return ECORE_CALLBACK_RENEW;
582 _button_inc_start(void *data,
583 Evas_Object *obj __UNUSED__,
584 const char *emission __UNUSED__,
585 const char *source __UNUSED__)
587 ELM_CALENDAR_DATA_GET(data, sd);
589 sd->interval = sd->first_interval;
591 if (sd->spin) ecore_timer_del(sd->spin);
592 sd->spin = ecore_timer_add(sd->interval, _spin_value, data);
598 _button_dec_start(void *data,
599 Evas_Object *obj __UNUSED__,
600 const char *emission __UNUSED__,
601 const char *source __UNUSED__)
603 ELM_CALENDAR_DATA_GET(data, sd);
605 sd->interval = sd->first_interval;
607 if (sd->spin) ecore_timer_del(sd->spin);
608 sd->spin = ecore_timer_add(sd->interval, _spin_value, data);
614 _button_stop(void *data,
615 Evas_Object *obj __UNUSED__,
616 const char *emission __UNUSED__,
617 const char *source __UNUSED__)
619 ELM_CALENDAR_DATA_GET(data, sd);
621 sd->interval = sd->first_interval;
622 if (sd->spin) ecore_timer_del(sd->spin);
627 _get_item_day(Evas_Object *obj,
632 ELM_CALENDAR_DATA_GET(obj, sd);
634 day = selected_it - sd->first_day_it + 1;
635 if ((day < 0) || (day > _maxdays_get(&sd->shown_time)))
642 _update_sel_it(Evas_Object *obj,
647 ELM_CALENDAR_DATA_GET(obj, sd);
649 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE)
652 day = _get_item_day(obj, sel_it);
656 _unselect(obj, sd->selected_it);
658 sd->selected = EINA_TRUE;
660 sd->selected_time.tm_mday = day;
661 _fix_selected_time(sd);
662 _select(obj, sel_it);
663 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
667 _day_selected(void *data,
668 Evas_Object *obj __UNUSED__,
669 const char *emission __UNUSED__,
674 ELM_CALENDAR_DATA_GET(data, sd);
676 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE)
679 sel_it = atoi(source);
681 _update_sel_it(data, sel_it);
685 _time_to_next_day(struct tm *t)
687 return ((((24 - t->tm_hour) * 60) - t->tm_min) * 60) - t->tm_sec;
691 _update_cur_date(void *data)
695 ELM_CALENDAR_DATA_GET(data, sd);
697 if (sd->today_it > 0) _not_today(sd);
699 current_time = time(NULL);
700 localtime_r(¤t_time, &sd->current_time);
701 t = _time_to_next_day(&sd->current_time);
702 ecore_timer_interval_set(sd->update_timer, t);
704 if ((sd->current_time.tm_mon != sd->shown_time.tm_mon) ||
705 (sd->current_time.tm_year != sd->shown_time.tm_year))
706 return ECORE_CALLBACK_RENEW;
708 day = sd->current_time.tm_mday + sd->first_day_it - 1;
711 return ECORE_CALLBACK_RENEW;
715 _elm_calendar_smart_event(Evas_Object *obj,
716 Evas_Object *src __UNUSED__,
717 Evas_Callback_Type type,
720 Evas_Event_Key_Down *ev = event_info;
722 ELM_CALENDAR_DATA_GET(obj, sd);
724 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
725 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
727 if ((!strcmp(ev->keyname, "Prior")) ||
728 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
730 if (_update_month(obj, -1)) _populate(obj);
732 else if ((!strcmp(ev->keyname, "Next")) ||
733 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
735 if (_update_month(obj, 1)) _populate(obj);
737 else if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE)
738 && ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
741 if ((!strcmp(ev->keyname, "Left")) ||
742 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
744 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
745 || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
746 && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
747 _update_sel_it(obj, sd->selected_it - 1);
749 else if ((!strcmp(ev->keyname, "Right")) ||
750 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
752 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
753 || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
754 && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
755 _update_sel_it(obj, sd->selected_it + 1);
757 else if ((!strcmp(ev->keyname, "Up")) ||
758 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
760 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
761 || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
762 && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
763 _update_sel_it(obj, sd->selected_it - ELM_DAY_LAST);
765 else if ((!strcmp(ev->keyname, "Down")) ||
766 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
768 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
769 || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
770 && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
771 _update_sel_it(obj, sd->selected_it + ELM_DAY_LAST);
773 else return EINA_FALSE;
775 else return EINA_FALSE;
781 _elm_calendar_smart_calculate(Evas_Object *obj)
783 elm_layout_freeze(obj);
788 elm_layout_thaw(obj);
792 _elm_calendar_smart_add(Evas_Object *obj)
794 time_t weekday = 259200; /* Just the first sunday since epoch */
798 EVAS_SMART_DATA_ALLOC(obj, Elm_Calendar_Smart_Data);
800 ELM_WIDGET_CLASS(_elm_calendar_parent_sc)->base.add(obj);
802 priv->first_interval = 0.85;
806 priv->selected_it = -1;
807 priv->first_day_it = -1;
808 priv->format_func = _format_month_year;
810 priv->selectable = (~(ELM_CALENDAR_SELECTABLE_NONE));
812 edje_object_signal_callback_add
813 (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,increment,start", "*",
814 _button_inc_start, obj);
815 edje_object_signal_callback_add
816 (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,decrement,start", "*",
817 _button_dec_start, obj);
818 edje_object_signal_callback_add
819 (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,stop", "*",
821 edje_object_signal_callback_add
822 (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,selected", "*",
825 for (i = 0; i < ELM_DAY_LAST; i++)
827 /* FIXME: I'm not aware of a known max, so if it fails,
828 * just make it larger. :| */
830 /* I don't know of a better way of doing it */
831 if (strftime(buf, sizeof(buf), "%a", gmtime(&weekday)))
833 priv->weekdays[i] = eina_stringshare_add(buf);
837 /* If we failed getting day, get a default value */
838 priv->weekdays[i] = _days_abbrev[i];
839 WRN("Failed getting weekday name for '%s' from locale.",
842 weekday += 86400; /* Advance by a day */
845 current_time = time(NULL);
846 localtime_r(¤t_time, &priv->shown_time);
847 priv->current_time = priv->shown_time;
848 priv->selected_time = priv->shown_time;
849 t = _time_to_next_day(&priv->current_time);
850 priv->update_timer = ecore_timer_add(t, _update_cur_date, obj);
852 elm_widget_can_focus_set(obj, EINA_TRUE);
854 elm_layout_theme_set(obj, "calendar", "base", elm_object_style_get(obj));
855 evas_object_smart_changed(obj);
858 if ((_elm_config->access_mode != ELM_ACCESS_MODE_OFF))
859 _access_calendar_spinner_register(obj);
863 _elm_calendar_smart_del(Evas_Object *obj)
866 Elm_Calendar_Mark *mark;
867 ELM_CALENDAR_DATA_GET(obj, sd);
869 if (sd->spin) ecore_timer_del(sd->spin);
870 if (sd->update_timer) ecore_timer_del(sd->update_timer);
874 EINA_LIST_FREE (sd->marks, mark)
880 for (i = 0; i < ELM_DAY_LAST; i++)
881 eina_stringshare_del(sd->weekdays[i]);
883 ELM_WIDGET_CLASS(_elm_calendar_parent_sc)->base.del(obj);
887 _elm_calendar_smart_focus_next(const Evas_Object *obj,
888 Elm_Focus_Direction dir,
892 Eina_List *items = NULL;
896 ELM_CALENDAR_CHECK(obj) EINA_FALSE;
897 ELM_CALENDAR_DATA_GET(obj, sd);
899 items = eina_list_append(items, sd->month_access);
900 items = eina_list_append(items, sd->dec_btn_access);
901 items = eina_list_append(items, sd->inc_btn_access);
904 maxdays = _maxdays_get(&sd->shown_time);
905 for (i = 0; i < 42; i++)
907 if ((!day) && (i == sd->first_day_it)) day = 1;
908 if ((day) && (day <= maxdays))
911 snprintf(pname, sizeof(pname), "cit_%i.access", i);
913 po = (Evas_Object *)edje_object_part_object_get
914 (elm_layout_edje_get(obj), pname);
915 ao = evas_object_data_get(po, "_part_access_obj");
916 items = eina_list_append(items, ao);
920 return elm_widget_focus_list_next_get
921 (obj, items, eina_list_data_get, dir, next);
925 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
929 ELM_CALENDAR_DATA_GET(obj, sd);
932 _access_calendar_register(obj);
936 maxdays = _maxdays_get(&sd->shown_time);
937 for (i = 0; i < 42; i++)
939 if ((!day) && (i == sd->first_day_it)) day = 1;
940 if ((day) && (day <= maxdays))
943 snprintf(pname, sizeof(pname), "cit_%i.access", i);
945 _elm_access_edje_object_part_object_unregister
946 (obj, elm_layout_edje_get(obj), pname);
950 if (sd->dec_btn_access)
951 _elm_access_edje_object_part_object_unregister
952 (obj, elm_layout_edje_get(obj), "left_bt");
953 if (sd->inc_btn_access)
954 _elm_access_edje_object_part_object_unregister
955 (obj, elm_layout_edje_get(obj), "right_bt");
956 if (sd->month_access)
957 _elm_access_edje_object_part_object_unregister
958 (obj, elm_layout_edje_get(obj), "month_text");
963 _access_hook(Evas_Object *obj, Eina_Bool is_access)
965 ELM_CALENDAR_CHECK(obj);
966 ELM_CALENDAR_DATA_GET(obj, sd);
969 ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
970 _elm_calendar_smart_focus_next;
972 ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
973 _access_obj_process(obj, is_access);
977 _elm_calendar_smart_set_user(Elm_Calendar_Smart_Class *sc)
979 ELM_WIDGET_CLASS(sc)->base.add = _elm_calendar_smart_add;
980 ELM_WIDGET_CLASS(sc)->base.del = _elm_calendar_smart_del;
981 ELM_WIDGET_CLASS(sc)->base.calculate = _elm_calendar_smart_calculate;
983 ELM_WIDGET_CLASS(sc)->theme = _elm_calendar_smart_theme;
984 ELM_WIDGET_CLASS(sc)->event = _elm_calendar_smart_event;
986 /* not a 'focus chain manager' */
987 ELM_WIDGET_CLASS(sc)->focus_next = NULL;
988 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
990 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_calendar_smart_sizing_eval;
993 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
994 ELM_WIDGET_CLASS(sc)->focus_next = _elm_calendar_smart_focus_next;
996 ELM_WIDGET_CLASS(sc)->access = _access_hook;
999 EAPI const Elm_Calendar_Smart_Class *
1000 elm_calendar_smart_class_get(void)
1002 static Elm_Calendar_Smart_Class _sc =
1003 ELM_CALENDAR_SMART_CLASS_INIT_NAME_VERSION(ELM_CALENDAR_SMART_NAME);
1004 static const Elm_Calendar_Smart_Class *class = NULL;
1005 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1010 _elm_calendar_smart_set(&_sc);
1011 esc->callbacks = _smart_callbacks;
1018 elm_calendar_add(Evas_Object *parent)
1022 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1024 obj = elm_widget_add(_elm_calendar_smart_class_new(), parent);
1025 if (!obj) return NULL;
1027 if (!elm_widget_sub_object_add(parent, obj))
1028 ERR("could not add %p as sub object of %p", obj, parent);
1034 elm_calendar_weekdays_names_set(Evas_Object *obj,
1035 const char *weekdays[])
1039 ELM_CALENDAR_CHECK(obj);
1040 ELM_CALENDAR_DATA_GET(obj, sd);
1041 EINA_SAFETY_ON_NULL_RETURN(weekdays);
1043 for (i = 0; i < ELM_DAY_LAST; i++)
1045 eina_stringshare_replace(&sd->weekdays[i], weekdays[i]);
1048 evas_object_smart_changed(obj);
1052 elm_calendar_weekdays_names_get(const Evas_Object *obj)
1054 ELM_CALENDAR_CHECK(obj) NULL;
1055 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
1057 return sd->weekdays;
1061 elm_calendar_interval_set(Evas_Object *obj,
1064 ELM_CALENDAR_CHECK(obj);
1065 ELM_CALENDAR_DATA_GET(obj, sd);
1067 sd->first_interval = interval;
1071 elm_calendar_interval_get(const Evas_Object *obj)
1073 ELM_CALENDAR_CHECK(obj) 0.0;
1074 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, 0.0);
1076 return sd->first_interval;
1080 elm_calendar_min_max_year_set(Evas_Object *obj,
1084 ELM_CALENDAR_CHECK(obj);
1085 ELM_CALENDAR_DATA_GET(obj, sd);
1089 if ((sd->year_min == min) && (sd->year_max == max)) return;
1090 sd->year_min = min > 2 ? min : 2;
1091 if (max > sd->year_min)
1094 sd->year_max = sd->year_min;
1095 if (sd->shown_time.tm_year > sd->year_max)
1096 sd->shown_time.tm_year = sd->year_max;
1097 if (sd->shown_time.tm_year < sd->year_min)
1098 sd->shown_time.tm_year = sd->year_min;
1099 evas_object_smart_changed(obj);
1103 elm_calendar_min_max_year_get(const Evas_Object *obj,
1107 ELM_CALENDAR_CHECK(obj);
1108 ELM_CALENDAR_DATA_GET(obj, sd);
1110 if (min) *min = sd->year_min + 1900;
1111 if (max) *max = sd->year_max + 1900;
1114 EINA_DEPRECATED EAPI void
1115 elm_calendar_day_selection_disabled_set(Evas_Object *obj,
1118 ELM_CALENDAR_CHECK(obj);
1121 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_NONE);
1123 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_DEFAULT);
1126 EINA_DEPRECATED EAPI Eina_Bool
1127 elm_calendar_day_selection_disabled_get(const Evas_Object *obj)
1129 ELM_CALENDAR_CHECK(obj) EINA_FALSE;
1130 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
1132 return !!(sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE);
1136 elm_calendar_selected_time_set(Evas_Object *obj,
1137 struct tm *selected_time)
1139 ELM_CALENDAR_CHECK(obj);
1140 ELM_CALENDAR_DATA_GET(obj, sd);
1141 EINA_SAFETY_ON_NULL_RETURN(selected_time);
1143 if (sd->selectable & ELM_CALENDAR_SELECTABLE_YEAR)
1144 sd->selected_time.tm_year = selected_time->tm_year;
1145 if (sd->selectable & ELM_CALENDAR_SELECTABLE_MONTH)
1146 sd->selected_time.tm_mon = selected_time->tm_mon;
1147 if (sd->selectable & ELM_CALENDAR_SELECTABLE_DAY)
1149 sd->selected_time.tm_mday = selected_time->tm_mday;
1151 sd->selected = EINA_TRUE;
1153 else if (sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1156 sd->selected = EINA_TRUE;
1158 if (sd->selected_time.tm_year != sd->shown_time.tm_year)
1159 sd->shown_time.tm_year = sd->selected_time.tm_year;
1160 if (sd->selected_time.tm_mon != sd->shown_time.tm_mon)
1161 sd->shown_time.tm_mon = sd->selected_time.tm_mon;
1163 _fix_selected_time(sd);
1165 evas_object_smart_changed(obj);
1169 elm_calendar_selected_time_get(const Evas_Object *obj,
1170 struct tm *selected_time)
1172 ELM_CALENDAR_CHECK(obj) EINA_FALSE;
1173 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
1174 EINA_SAFETY_ON_NULL_RETURN_VAL(selected_time, EINA_FALSE);
1176 if ((sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1179 *selected_time = sd->selected_time;
1185 elm_calendar_format_function_set(Evas_Object *obj,
1186 Elm_Calendar_Format_Cb format_function)
1188 ELM_CALENDAR_CHECK(obj);
1189 ELM_CALENDAR_DATA_GET(obj, sd);
1191 sd->format_func = format_function;
1192 _set_month_year(sd);
1195 EAPI Elm_Calendar_Mark *
1196 elm_calendar_mark_add(Evas_Object *obj,
1197 const char *mark_type,
1198 struct tm *mark_time,
1199 Elm_Calendar_Mark_Repeat_Type repeat)
1201 ELM_CALENDAR_CHECK(obj) NULL;
1202 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
1204 Elm_Calendar_Mark *mark;
1206 mark = _mark_new(obj, mark_type, mark_time, repeat);
1207 sd->marks = eina_list_append(sd->marks, mark);
1208 mark->node = eina_list_last(sd->marks);
1214 elm_calendar_mark_del(Elm_Calendar_Mark *mark)
1216 EINA_SAFETY_ON_NULL_RETURN(mark);
1217 ELM_CALENDAR_CHECK(mark->obj);
1218 ELM_CALENDAR_DATA_GET(mark->obj, sd);
1220 sd->marks = eina_list_remove_list(sd->marks, mark->node);
1225 elm_calendar_marks_clear(Evas_Object *obj)
1227 ELM_CALENDAR_CHECK(obj);
1228 ELM_CALENDAR_DATA_GET(obj, sd);
1230 Elm_Calendar_Mark *mark;
1232 EINA_LIST_FREE (sd->marks, mark)
1236 EAPI const Eina_List *
1237 elm_calendar_marks_get(const Evas_Object *obj)
1239 ELM_CALENDAR_CHECK(obj) NULL;
1240 ELM_CALENDAR_DATA_GET(obj, sd);
1246 elm_calendar_marks_draw(Evas_Object *obj)
1248 ELM_CALENDAR_CHECK(obj);
1250 evas_object_smart_changed(obj);
1254 elm_calendar_first_day_of_week_set(Evas_Object *obj,
1255 Elm_Calendar_Weekday day)
1257 ELM_CALENDAR_CHECK(obj);
1258 ELM_CALENDAR_DATA_GET(obj, sd);
1260 if (day >= ELM_DAY_LAST) return;
1261 if (sd->first_week_day != day)
1263 sd->first_week_day = day;
1264 evas_object_smart_changed(obj);
1268 EAPI Elm_Calendar_Weekday
1269 elm_calendar_first_day_of_week_get(const Evas_Object *obj)
1271 ELM_CALENDAR_CHECK(obj) - 1;
1272 ELM_CALENDAR_DATA_GET(obj, sd);
1274 return sd->first_week_day;
1278 elm_calendar_select_mode_set(Evas_Object *obj,
1279 Elm_Calendar_Select_Mode mode)
1281 ELM_CALENDAR_CHECK(obj);
1282 ELM_CALENDAR_DATA_GET(obj, sd);
1284 if ((mode <= ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1285 && (sd->select_mode != mode))
1287 sd->select_mode = mode;
1288 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1289 sd->selected = EINA_FALSE;
1290 if ((sd->select_mode == ELM_CALENDAR_SELECT_MODE_ALWAYS)
1291 || (sd->select_mode == ELM_CALENDAR_SELECT_MODE_DEFAULT))
1292 _select(obj, sd->selected_it);
1294 _unselect(obj, sd->selected_it);
1298 EAPI Elm_Calendar_Select_Mode
1299 elm_calendar_select_mode_get(const Evas_Object *obj)
1301 ELM_CALENDAR_CHECK(obj) - 1;
1302 ELM_CALENDAR_DATA_GET(obj, sd);
1304 return sd->select_mode;
1308 elm_calendar_selectable_set(Evas_Object *obj, Elm_Calendar_Selectable selectable)
1310 ELM_CALENDAR_CHECK(obj);
1311 ELM_CALENDAR_DATA_GET(obj, sd);
1313 sd->selectable = selectable;
1316 EAPI Elm_Calendar_Selectable
1317 elm_calendar_selectable_get(const Evas_Object *obj)
1319 ELM_CALENDAR_CHECK(obj) -1;
1320 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, -1);
1322 return sd->selectable;
1326 elm_calendar_displayed_time_get(const Evas_Object *obj, struct tm *displayed_time)
1328 EINA_SAFETY_ON_NULL_RETURN_VAL(displayed_time, EINA_FALSE);
1329 ELM_CALENDAR_CHECK(obj) EINA_FALSE;
1330 ELM_CALENDAR_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
1332 *displayed_time = sd->shown_time;