1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define EFL_UI_FOCUS_COMPOSITION_PROTECTED
8 #define EFL_UI_FOCUS_OBJECT_PROTECTED
9
10 #include <Elementary.h>
11 #include "elm_priv.h"
12 #include "elm_widget_calendar.h"
13 #include "elm_calendar_eo.h"
14 #include "elm_calendar_item_eo.h"
15
16 #define MY_CLASS ELM_CALENDAR_CLASS
17
18 #define MY_CLASS_NAME "Elm_Calendar"
19 #define MY_CLASS_NAME_LEGACY "elm_calendar"
20
21 #define ELM_CALENDAR_BUTTON_LEFT "elm,calendar,button,left"
22 #define ELM_CALENDAR_BUTTON_RIGHT "elm,calendar,button,right"
23 #define ELM_CALENDAR_BUTTON_YEAR_LEFT "elm,calendar,button_year,left"
24 #define ELM_CALENDAR_BUTTON_YEAR_RIGHT "elm,calendar,button_year,right"
25 #define ELM_CALENDAR_CH_WEEKEND "elm,calendar,ch_%d,weekend"
26 #define ELM_CALENDAR_CH_WEEKDAY "elm,calendar,ch_%d,weekday"
27
28 #define ELM_CALENDAR_CH_TEXT_PART_STR "elm.ch_%d.text"
29 #define ELM_CALENDAR_CIT_TEXT_PART_STR "elm.cit_%d.text"
30 #define ELM_CALENDAR_CIT_ACCESS_PART_STR "elm.cit_%d.access"
31
_part_name_snprintf(char * buffer,int buffer_size,const Evas_Object * obj,const char * template,int n)32 static void _part_name_snprintf(char *buffer, int buffer_size,
33 const Evas_Object *obj, const char *template, int n)
34 {
35 snprintf(buffer, buffer_size, template, n);
36 if (!edje_object_part_exists (obj, buffer))
37 {
38 // Skip the namespace prefix "elm." which was not present
39 // in previous versions
40 snprintf(buffer, buffer_size, template + 4, n);
41 }
42 }
43
44 static const char SIG_CHANGED[] = "changed";
45 static const char SIG_DISPLAY_CHANGED[] = "display,changed";
46
47 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
48 {SIG_CHANGED, ""},
49 {SIG_DISPLAY_CHANGED, ""},
50 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
51 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
52 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
53 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
54 {NULL, NULL}
55 };
56
57 /* Originally, the button functionalities of month, year spinners were
58 * implemented by its own edc. There was a bunch of callback functions
59 * for handle the signals. The following functions are the old callback
60 * functions for handle the signals.
61 * _button_month_dec_start
62 * _button_year_inc_start
63 * _button_year_dec_start
64 * _button_month_stop
65 * _button_year_stop
66 *
67 * But, it is replaced by elm_button widget objects. The following
68 * callback functions are also newly added for button objects.
69 * We still keep the old signal callback functions for backward compatibility. */
70
71 static void
72 _inc_dec_button_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED);
73 static void
74 _inc_dec_button_pressed_cb(void *data, const Efl_Event *event);
75 static void
76 _inc_dec_button_unpressed_cb(void *data, const Efl_Event *event EINA_UNUSED);
77
78 EFL_CALLBACKS_ARRAY_DEFINE( _inc_dec_button_cb,
79 { EFL_INPUT_EVENT_CLICKED, _inc_dec_button_clicked_cb},
80 { EFL_INPUT_EVENT_PRESSED, _inc_dec_button_pressed_cb},
81 { EFL_INPUT_EVENT_UNPRESSED, _inc_dec_button_unpressed_cb}
82 );
83
84 static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
85
86 static const Elm_Action key_actions[] = {
87 {"activate", _key_action_activate},
88 {NULL, NULL}
89 };
90
91 /* Should not be translated, it's used if we failed
92 * getting from locale. */
93 static const char *_days_abbrev[] =
94 {
95 "Sun", "Mon", "Tue", "Wed",
96 "Thu", "Fri", "Sat"
97 };
98
99 static int _days_in_month[2][12] =
100 {
101 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
102 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
103 };
104
105 static Elm_Calendar_Mark *
_mark_new(Evas_Object * obj,const char * mark_type,struct tm * mark_time,Elm_Calendar_Mark_Repeat_Type repeat)106 _mark_new(Evas_Object *obj,
107 const char *mark_type,
108 struct tm *mark_time,
109 Elm_Calendar_Mark_Repeat_Type repeat)
110 {
111 Elm_Calendar_Mark *mark;
112
113 mark = calloc(1, sizeof(Elm_Calendar_Mark));
114 if (!mark) return NULL;
115 mark->obj = obj;
116 mark->mark_type = eina_stringshare_add(mark_type);
117 mark->mark_time = *mark_time;
118 mark->repeat = repeat;
119
120 return mark;
121 }
122
123 static inline void
_mark_free(Elm_Calendar_Mark * mark)124 _mark_free(Elm_Calendar_Mark *mark)
125 {
126 eina_stringshare_del(mark->mark_type);
127 free(mark);
128 }
129
130 static inline int
_maxdays_get(struct tm * selected_time,int month_offset)131 _maxdays_get(struct tm *selected_time, int month_offset)
132 {
133 int month, year;
134
135 month = (selected_time->tm_mon + month_offset) % 12;
136 year = selected_time->tm_year + 1900;
137
138 if (month < 0) month += 12;
139
140 return _days_in_month
141 [((!(year % 4)) && ((!(year % 400)) || (year % 100)))][month];
142 }
143
144 static inline void
_unselect(Evas_Object * obj,int selected)145 _unselect(Evas_Object *obj,
146 int selected)
147 {
148 char emission[32];
149
150 snprintf(emission, sizeof(emission), "cit_%i,unselected", selected);
151 elm_layout_signal_emit(obj, emission, "elm");
152 }
153
154 static inline void
_select(Evas_Object * obj,int selected)155 _select(Evas_Object *obj,
156 int selected)
157 {
158 char emission[32];
159
160 ELM_CALENDAR_DATA_GET(obj, sd);
161
162 sd->focused_it = sd->selected_it = selected;
163 snprintf(emission, sizeof(emission), "cit_%i,selected", selected);
164 elm_layout_signal_emit(obj, emission, "elm");
165 }
166
167 static inline void
_not_today(Elm_Calendar_Data * sd)168 _not_today(Elm_Calendar_Data *sd)
169 {
170 char emission[32];
171
172 snprintf(emission, sizeof(emission), "cit_%i,not_today", sd->today_it);
173 elm_layout_signal_emit(sd->obj, emission, "elm");
174 sd->today_it = -1;
175 }
176
177 static inline void
_today(Elm_Calendar_Data * sd,int it)178 _today(Elm_Calendar_Data *sd,
179 int it)
180 {
181 char emission[32];
182
183 snprintf(emission, sizeof(emission), "cit_%i,today", it);
184 elm_layout_signal_emit(sd->obj, emission, "elm");
185 sd->today_it = it;
186 }
187
188 static inline void
_enable(Elm_Calendar_Data * sd,int it)189 _enable(Elm_Calendar_Data *sd,
190 int it)
191 {
192 char emission[32];
193
194 snprintf(emission, sizeof(emission), "cit_%i,enable", it);
195 elm_layout_signal_emit(sd->obj, emission, "elm");
196 }
197
198 static inline void
_disable(Elm_Calendar_Data * sd,int it)199 _disable(Elm_Calendar_Data *sd,
200 int it)
201 {
202 char emission[32];
203
204 snprintf(emission, sizeof(emission), "cit_%i,disable", it);
205 elm_layout_signal_emit(sd->obj, emission, "elm");
206 }
207
208 static char *
_format_month_year(struct tm * selected_time)209 _format_month_year(struct tm *selected_time)
210 {
211 return eina_strftime(E_("%B %Y"), selected_time);
212 }
213
214 static char *
_format_month(struct tm * selected_time)215 _format_month(struct tm *selected_time)
216 {
217 return eina_strftime(E_("%B"), selected_time);
218 }
219
220 static char *
_format_year(struct tm * selected_time)221 _format_year(struct tm *selected_time)
222 {
223 return eina_strftime(E_("%Y"), selected_time);
224 }
225
226 static inline void
_cit_mark(Evas_Object * cal,int cit,const char * mtype)227 _cit_mark(Evas_Object *cal,
228 int cit,
229 const char *mtype)
230 {
231 ELM_CALENDAR_DATA_GET(cal, sd);
232
233 int day = cit - sd->first_day_it + 1;
234 int mon = sd->shown_time.tm_mon;
235 int yr = sd->shown_time.tm_year;
236
237 if (strcmp(mtype, "clear")
238 && (((yr == sd->date_min.tm_year) && (mon == sd->date_min.tm_mon) && (day < sd->date_min.tm_mday))
239 || ((yr == sd->date_max.tm_year) && (mon == sd->date_max.tm_mon) && (day > sd->date_max.tm_mday))))
240 return;
241
242 char sign[64];
243
244 snprintf(sign, sizeof(sign), "cit_%i,%s", cit, mtype);
245 elm_layout_signal_emit(cal, sign, "elm");
246 }
247
248 static inline int
_weekday_get(int first_week_day,int day)249 _weekday_get(int first_week_day,
250 int day)
251 {
252 return (day + first_week_day - 1) % ELM_DAY_LAST;
253 }
254
255 // EINA_DEPRECATED
256 static void
_text_day_color_update(Elm_Calendar_Data * sd,int pos)257 _text_day_color_update(Elm_Calendar_Data *sd,
258 int pos)
259 {
260 char emission[32];
261
262 switch (sd->day_color[pos])
263 {
264 case DAY_WEEKDAY:
265 snprintf(emission, sizeof(emission), "cit_%i,weekday", pos);
266 break;
267
268 case DAY_SATURDAY:
269 snprintf(emission, sizeof(emission), "cit_%i,saturday", pos);
270 break;
271
272 case DAY_SUNDAY:
273 snprintf(emission, sizeof(emission), "cit_%i,sunday", pos);
274 break;
275
276 default:
277 return;
278 }
279
280 elm_layout_signal_emit(sd->obj, emission, "elm");
281 }
282
283 static void
_set_month_year(Elm_Calendar_Data * sd)284 _set_month_year(Elm_Calendar_Data *sd)
285 {
286 char *buf;
287
288 sd->filling = EINA_TRUE;
289 if (sd->double_spinners) /* theme has spinner for year */
290 {
291 buf = _format_year(&sd->shown_time);
292 if (buf)
293 {
294 elm_layout_text_set(sd->obj, "year_text", buf);
295 free(buf);
296 }
297 else elm_layout_text_set(sd->obj, "year_text", "");
298
299 buf = _format_month(&sd->shown_time);
300 }
301 else
302 buf = sd->format_func(&sd->shown_time);
303
304 if (buf)
305 {
306 elm_layout_text_set(sd->obj, "month_text", buf);
307 free(buf);
308 }
309 else elm_layout_text_set(sd->obj, "month_text", "");
310 sd->filling = EINA_FALSE;
311 }
312
313 static char *
_access_info_cb(void * data EINA_UNUSED,Evas_Object * obj)314 _access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
315 {
316 char *ret;
317 Eina_Strbuf *buf;
318 buf = eina_strbuf_new();
319
320 eina_strbuf_append_printf(buf, "day %s", elm_widget_access_info_get(obj));
321
322 ret = eina_strbuf_string_steal(buf);
323 eina_strbuf_free(buf);
324 return ret;
325 }
326
327 static void
_access_calendar_item_register(Evas_Object * obj)328 _access_calendar_item_register(Evas_Object *obj)
329 {
330 unsigned int maxdays, i;
331 char day_s[13], pname[18];
332 unsigned day = 0;
333 Evas_Object *ao;
334
335 ELM_CALENDAR_DATA_GET(obj, sd);
336
337 maxdays = _maxdays_get(&sd->shown_time, 0);
338 for (i = 0; i < 42; i++)
339 {
340 if ((!day) && (i == sd->first_day_it)) day = 1;
341 if ((day) && (day <= maxdays))
342 {
343 _part_name_snprintf(pname, sizeof(pname),
344 elm_layout_edje_get(obj), ELM_CALENDAR_CIT_ACCESS_PART_STR, i);
345
346 ao = _elm_access_edje_object_part_object_register
347 (obj, elm_layout_edje_get(obj), pname);
348 _elm_access_text_set(_elm_access_info_get(ao),
349 ELM_ACCESS_TYPE, E_("calendar item"));
350 _elm_access_callback_set(_elm_access_info_get(ao),
351 ELM_ACCESS_INFO, _access_info_cb, NULL);
352
353 snprintf(day_s, sizeof(day_s), "%i", (int) (day++));
354 elm_widget_access_info_set(ao, (const char*)day_s);
355 }
356 else
357 {
358 _part_name_snprintf(pname, sizeof(pname),
359 elm_layout_edje_get(obj), ELM_CALENDAR_CIT_ACCESS_PART_STR, i);
360 _elm_access_edje_object_part_object_unregister
361 (obj, elm_layout_edje_get(obj), pname);
362 }
363 }
364 }
365
366 static void
_access_calendar_spinner_register(Evas_Object * obj)367 _access_calendar_spinner_register(Evas_Object *obj)
368 {
369 Evas_Object *po, *o;
370 Elm_Access_Info *ai;
371 ELM_CALENDAR_DATA_GET(obj, sd);
372
373 if (!sd->dec_btn_month)
374 sd->dec_btn_month = _elm_access_edje_object_part_object_register
375 (obj, elm_layout_edje_get(obj), "left_bt");
376 ai = _elm_access_info_get(sd->dec_btn_month);
377 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar decrement month button"));
378
379 if (!sd->dec_btn_year)
380 sd->dec_btn_year = _elm_access_edje_object_part_object_register
381 (obj, elm_layout_edje_get(obj), "left_bt_year");
382 ai = _elm_access_info_get(sd->dec_btn_year);
383 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar decrement year button"));
384
385 if (!sd->inc_btn_month)
386 sd->inc_btn_month = _elm_access_edje_object_part_object_register
387 (obj, elm_layout_edje_get(obj), "right_bt");
388 ai = _elm_access_info_get(sd->inc_btn_month);
389 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar increment month button"));
390
391 if (!sd->inc_btn_year)
392 sd->inc_btn_year = _elm_access_edje_object_part_object_register
393 (obj, elm_layout_edje_get(obj), "right_bt_year");
394 ai = _elm_access_info_get(sd->inc_btn_year);
395 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar increment year button"));
396
397 sd->month_access = _elm_access_edje_object_part_object_register
398 (obj, elm_layout_edje_get(obj), "text_month");
399 ai = _elm_access_info_get(sd->month_access);
400 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar month"));
401
402 sd->year_access = _elm_access_edje_object_part_object_register
403 (obj, elm_layout_edje_get(obj), "year_text");
404 ai = _elm_access_info_get(sd->year_access);
405 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("calendar year"));
406
407 o = elm_layout_edje_get(obj);
408 edje_object_freeze(o);
409 po = (Evas_Object *)edje_object_part_object_get(o, "month_text");
410 evas_object_pass_events_set(po, EINA_FALSE);
411
412 po = (Evas_Object *)edje_object_part_object_get(o, "year_text");
413 evas_object_pass_events_set(po, EINA_FALSE);
414 edje_object_thaw(o);
415 }
416
417 static void
_access_calendar_register(Evas_Object * obj)418 _access_calendar_register(Evas_Object *obj)
419 {
420 _access_calendar_spinner_register(obj);
421 _access_calendar_item_register(obj);
422 }
423
424 static void
_flush_calendar_composite_elements(Evas_Object * obj,Elm_Calendar_Data * sd)425 _flush_calendar_composite_elements(Evas_Object *obj, Elm_Calendar_Data *sd)
426 {
427 Eina_List *items = NULL;
428 int max_day = _maxdays_get(&sd->shown_time, 0);
429
430 #define EXTEND(v) \
431 if (v) items = eina_list_append(items, v); \
432
433 EXTEND(sd->month_access);
434 EXTEND(sd->dec_btn_month);
435 EXTEND(sd->inc_btn_month);
436 EXTEND(sd->year_access);
437 EXTEND(sd->dec_btn_year);
438 EXTEND(sd->inc_btn_year);
439
440 #undef EXTEND
441
442 for (int i = sd->first_day_it; i <= max_day; ++i)
443 items = eina_list_append(items, sd->items[i]);
444
445 efl_ui_focus_composition_elements_set(obj, items);
446 }
447
448 static void
_populate(Evas_Object * obj)449 _populate(Evas_Object *obj)
450 {
451 int maxdays, adjusted_wday, prev_month_maxdays, day, mon, yr, i;
452 Elm_Calendar_Mark *mark;
453 char part[16], day_s[16];
454 struct tm first_day;
455 Eina_List *l;
456 Eina_Bool last_row = EINA_TRUE;
457
458 ELM_CALENDAR_DATA_GET(obj, sd);
459
460 elm_layout_freeze(obj);
461
462 sd->filling = EINA_FALSE;
463 if (sd->today_it > 0) _not_today(sd);
464
465 maxdays = _maxdays_get(&sd->shown_time, 0);
466 prev_month_maxdays = _maxdays_get(&sd->shown_time, -1);
467 mon = sd->shown_time.tm_mon;
468 yr = sd->shown_time.tm_year;
469
470 _set_month_year(sd);
471 sd->filling = EINA_TRUE;
472
473 /* Set days */
474 day = 0;
475 first_day = sd->shown_time;
476 first_day.tm_mday = 1;
477 mktime(&first_day);
478
479 // Layout of the calendar is changed for removing the unfilled last row.
480 if (first_day.tm_wday < (int)sd->first_week_day)
481 sd->first_day_it = first_day.tm_wday + ELM_DAY_LAST - sd->first_week_day;
482 else
483 sd->first_day_it = first_day.tm_wday - sd->first_week_day;
484
485 if ((35 - sd->first_day_it) > (maxdays - 1)) last_row = EINA_FALSE;
486
487 if (!last_row)
488 {
489 char emission[32];
490
491 for (i = 0; i < 5; i++)
492 {
493 snprintf(emission, sizeof(emission), "cseph_%i,row_hide", i);
494 elm_layout_signal_emit(obj, emission, "elm");
495 }
496 snprintf(emission, sizeof(emission), "cseph_%i,row_invisible", 5);
497 elm_layout_signal_emit(obj, emission, "elm");
498 for (i = 0; i < 35; i++)
499 {
500 snprintf(emission, sizeof(emission), "cit_%i,cell_expanded", i);
501 elm_layout_signal_emit(obj, emission, "elm");
502 }
503 for (i = 35; i < 42; i++)
504 {
505 snprintf(emission, sizeof(emission), "cit_%i,cell_invisible", i);
506 elm_layout_signal_emit(obj, emission, "elm");
507 }
508 }
509 else
510 {
511 char emission[32];
512
513 for (i = 0; i < 6; i++)
514 {
515 snprintf(emission, sizeof(emission), "cseph_%i,row_show", i);
516 elm_layout_signal_emit(obj, emission, "elm");
517 }
518 for (i = 0; i < 42; i++)
519 {
520 snprintf(emission, sizeof(emission), "cit_%i,cell_default", i);
521 elm_layout_signal_emit(obj, emission, "elm");
522 }
523 }
524
525 for (i = 0; i < 42; i++)
526 {
527 _text_day_color_update(sd, i); // EINA_DEPRECATED
528 if ((!day) && (i == sd->first_day_it)) day = 1;
529
530 if ((day == sd->current_time.tm_mday)
531 && (mon == sd->current_time.tm_mon)
532 && (yr == sd->current_time.tm_year))
533 _today(sd, i);
534
535 if (day == sd->selected_time.tm_mday)
536 {
537 if ((sd->selected_it > -1) && (sd->selected_it != i))
538 _unselect(obj, sd->selected_it);
539
540 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
541 {
542 if ((mon == sd->selected_time.tm_mon)
543 && (yr == sd->selected_time.tm_year)
544 && (sd->selected))
545 {
546 _select(obj, i);
547 }
548 }
549 else if (sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE)
550 {
551 _select(obj, i);
552 }
553 }
554
555 if ((day) && (day <= maxdays))
556 {
557 if (((yr == sd->date_min.tm_year) && (mon == sd->date_min.tm_mon) && (day < sd->date_min.tm_mday))
558 || ((yr == sd->date_max.tm_year) && (mon == sd->date_max.tm_mon) && (day > sd->date_max.tm_mday)))
559 _disable(sd, i);
560 else
561 _enable(sd, i);
562
563 snprintf(day_s, sizeof(day_s), "%i", day++);
564 }
565 else
566 {
567 _disable(sd, i);
568
569 if (day <= maxdays)
570 snprintf(day_s, sizeof(day_s), "%i", prev_month_maxdays - sd->first_day_it + i + 1);
571 else
572 snprintf(day_s, sizeof(day_s), "%i", i - sd->first_day_it - maxdays + 1);
573 }
574
575 _part_name_snprintf(part, sizeof(part), obj, ELM_CALENDAR_CIT_TEXT_PART_STR, i);
576 elm_layout_text_set(obj, part, day_s);
577
578 /* Clear previous marks */
579 _cit_mark(obj, i, "clear");
580 }
581
582 // ACCESS
583 if ((_elm_config->access_mode != ELM_ACCESS_MODE_OFF))
584 _access_calendar_item_register(obj);
585
586 /* Set marks */
587 EINA_LIST_FOREACH(sd->marks, l, mark)
588 {
589 struct tm *mtime = &mark->mark_time;
590 int month = sd->shown_time.tm_mon;
591 int year = sd->shown_time.tm_year;
592 int mday_it = mtime->tm_mday + sd->first_day_it - 1;
593
594 switch (mark->repeat)
595 {
596 case ELM_CALENDAR_UNIQUE:
597 if ((mtime->tm_mon == month) && (mtime->tm_year == year))
598 _cit_mark(obj, mday_it, mark->mark_type);
599 break;
600
601 case ELM_CALENDAR_DAILY:
602 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
603 (mtime->tm_year < year))
604 day = 1;
605 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
606 day = mtime->tm_mday;
607 else
608 break;
609 for (; day <= maxdays; day++)
610 _cit_mark(obj, day + sd->first_day_it - 1,
611 mark->mark_type);
612 break;
613
614 case ELM_CALENDAR_WEEKLY:
615 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
616 (mtime->tm_year < year))
617 day = 1;
618 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
619 day = mtime->tm_mday;
620 else
621 break;
622
623 adjusted_wday = (mtime->tm_wday - sd->first_week_day);
624 if (adjusted_wday < 0)
625 adjusted_wday = ELM_DAY_LAST + adjusted_wday;
626
627 for (; day <= maxdays; day++)
628 if (adjusted_wday == _weekday_get(sd->first_day_it, day))
629 _cit_mark(obj, day + sd->first_day_it - 1,
630 mark->mark_type);
631 break;
632
633 case ELM_CALENDAR_MONTHLY:
634 if (((mtime->tm_year < year) ||
635 ((mtime->tm_year == year) && (mtime->tm_mon <= month))) &&
636 (mtime->tm_mday <= maxdays))
637 _cit_mark(obj, mday_it, mark->mark_type);
638 break;
639
640 case ELM_CALENDAR_ANNUALLY:
641 if ((mtime->tm_year <= year) && (mtime->tm_mon == month) &&
642 (mtime->tm_mday <= maxdays))
643 _cit_mark(obj, mday_it, mark->mark_type);
644 break;
645
646 case ELM_CALENDAR_LAST_DAY_OF_MONTH:
647 if (((mtime->tm_year < year) ||
648 ((mtime->tm_year == year) && (mtime->tm_mon <= month))))
649 _cit_mark(obj, maxdays + sd->first_day_it - 1, mark->mark_type);
650 break;
651
652 case ELM_CALENDAR_REVERSE_DAILY:
653 if (((mtime->tm_year == year) && (mtime->tm_mon > month)) ||
654 (mtime->tm_year > year))
655 day = maxdays;
656 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
657 day = mtime->tm_mday - 1;
658 else
659 break;
660 for (; day >= 1; day--)
661 _cit_mark(obj, day + sd->first_day_it - 1,
662 mark->mark_type);
663 break;
664
665 }
666 }
667 sd->filling = EINA_FALSE;
668
669 elm_layout_thaw(obj);
670 edje_object_message_signal_process(elm_layout_edje_get(obj));
671
672 _flush_calendar_composite_elements(obj, sd);
673 }
674
675 static void
_set_headers(Evas_Object * obj)676 _set_headers(Evas_Object *obj)
677 {
678 static char part[64];
679 static char emission[64];
680 int i;
681 struct tm *t;
682 time_t temp = 259200; // the first sunday since epoch
683 ELM_CALENDAR_DATA_GET(obj, sd);
684
685 elm_layout_freeze(obj);
686
687 sd->filling = EINA_TRUE;
688
689 t = gmtime(&temp);
690 if (t && !sd->weekdays_set)
691 {
692 t->tm_wday = 0;
693 for (i = 0; i < ELM_DAY_LAST; i++)
694 {
695 char *buf;
696 buf = eina_strftime("%a", t);
697 if (buf)
698 {
699 sd->weekdays[i] = eina_stringshare_add(buf);
700 free(buf);
701 }
702 else
703 {
704 /* If we failed getting day, get a default value */
705 sd->weekdays[i] = _days_abbrev[i];
706 WRN("Failed getting weekday name for '%s' from locale.",
707 _days_abbrev[i]);
708 }
709 t->tm_wday++;
710 }
711 }
712
713 for (i = 0; i < ELM_DAY_LAST; i++)
714 {
715 _part_name_snprintf(part, sizeof(part), obj, ELM_CALENDAR_CH_TEXT_PART_STR, i);
716 int weekday_index = (i + sd->first_week_day) % ELM_DAY_LAST;
717 elm_layout_text_set(obj, part, sd->weekdays[weekday_index]);
718 // Signaling the theme about which days are weekdays and which weekend
719 if (weekday_index == ELM_DAY_SATURDAY || weekday_index == ELM_DAY_SUNDAY)
720 _part_name_snprintf(emission, sizeof(emission), obj, ELM_CALENDAR_CH_WEEKEND, i);
721 else
722 _part_name_snprintf(emission, sizeof(emission), obj, ELM_CALENDAR_CH_WEEKDAY, i);
723
724 elm_layout_signal_emit(obj, emission, "elm");
725 }
726
727 sd->filling = EINA_FALSE;
728
729 elm_layout_thaw(obj);
730 }
731
732 static void
_spinner_buttons_add(Evas_Object * obj,Elm_Calendar_Data * sd)733 _spinner_buttons_add(Evas_Object *obj, Elm_Calendar_Data *sd)
734 {
735 char left_buf[255] = { 0 };
736 char right_buf[255] = { 0 };
737
738 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
739
740 snprintf(left_buf, sizeof(left_buf), "calendar/decrease/%s", elm_object_style_get(obj));
741 snprintf(right_buf, sizeof(right_buf), "calendar/increase/%s", elm_object_style_get(obj));
742
743 if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_LEFT))
744 {
745 if (sd->dec_btn_month && efl_isa(sd->dec_btn_month, ELM_ACCESS_CLASS))
746 {
747 _elm_access_edje_object_part_object_unregister
748 (obj, elm_layout_edje_get(obj), "left_bt");
749 sd->dec_btn_month = NULL;
750 }
751
752 if (!sd->dec_btn_month)
753 {
754 sd->dec_btn_month = elm_button_add(obj);
755 efl_event_callback_array_add(sd->dec_btn_month, _inc_dec_button_cb(), obj);
756 }
757
758 elm_object_style_set(sd->dec_btn_month, left_buf);
759 elm_layout_content_set(obj, ELM_CALENDAR_BUTTON_LEFT, sd->dec_btn_month);
760 }
761 else if (sd->dec_btn_month && !efl_isa(sd->dec_btn_month, ELM_ACCESS_CLASS))
762 {
763 evas_object_del(sd->dec_btn_month);
764 sd->dec_btn_month = NULL;
765 }
766
767 if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_RIGHT))
768 {
769 if (sd->inc_btn_month && efl_isa(sd->inc_btn_month, ELM_ACCESS_CLASS))
770 {
771 _elm_access_edje_object_part_object_unregister
772 (obj, elm_layout_edje_get(obj), "right_bt");
773 sd->inc_btn_month = NULL;
774 }
775
776 if (!sd->inc_btn_month)
777 {
778 sd->inc_btn_month = elm_button_add(obj);
779 efl_event_callback_array_add(sd->inc_btn_month, _inc_dec_button_cb(), obj);
780 }
781
782 elm_object_style_set(sd->inc_btn_month, right_buf);
783 elm_layout_content_set(obj, ELM_CALENDAR_BUTTON_RIGHT, sd->inc_btn_month);
784 }
785 else if (sd->inc_btn_month && !efl_isa(sd->inc_btn_month, ELM_ACCESS_CLASS))
786 {
787 evas_object_del(sd->inc_btn_month);
788 sd->inc_btn_month = NULL;
789 }
790
791 if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_LEFT))
792 {
793 if (sd->dec_btn_year && efl_isa(sd->dec_btn_year, ELM_ACCESS_CLASS))
794 {
795 _elm_access_edje_object_part_object_unregister
796 (obj, elm_layout_edje_get(obj), "left_bt_year");
797 sd->dec_btn_year = NULL;
798 }
799
800 if (!sd->dec_btn_year)
801 {
802 sd->dec_btn_year = elm_button_add(obj);
803 efl_event_callback_array_add(sd->dec_btn_year, _inc_dec_button_cb(), obj);
804 }
805
806 elm_object_style_set(sd->dec_btn_year, left_buf);
807 elm_layout_content_set(obj, ELM_CALENDAR_BUTTON_YEAR_LEFT, sd->dec_btn_year);
808 }
809 else if (sd->dec_btn_year && !efl_isa(sd->dec_btn_year, ELM_ACCESS_CLASS))
810 {
811 evas_object_del(sd->dec_btn_year);
812 sd->dec_btn_year = NULL;
813 }
814
815 if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT))
816 {
817 if (sd->inc_btn_year && efl_isa(sd->inc_btn_year, ELM_ACCESS_CLASS))
818 {
819 _elm_access_edje_object_part_object_unregister
820 (obj, elm_layout_edje_get(obj), "right_bt_year");
821 sd->inc_btn_year = NULL;
822 }
823
824 if (!sd->inc_btn_year)
825 {
826 sd->inc_btn_year = elm_button_add(obj);
827 efl_event_callback_array_add(sd->inc_btn_year, _inc_dec_button_cb(), obj);
828 }
829
830 elm_object_style_set(sd->inc_btn_year, right_buf);
831 elm_layout_content_set(obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT, sd->inc_btn_year);
832 }
833 else if (sd->inc_btn_year && !efl_isa(sd->inc_btn_year, ELM_ACCESS_CLASS))
834 {
835 evas_object_del(sd->inc_btn_year);
836 sd->inc_btn_year = NULL;
837 }
838 }
839
840 EOLIAN static Eina_Error
_elm_calendar_efl_ui_widget_theme_apply(Eo * obj,Elm_Calendar_Data * sd)841 _elm_calendar_efl_ui_widget_theme_apply(Eo *obj, Elm_Calendar_Data *sd)
842 {
843 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
844
845 int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
846 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
847
848 _spinner_buttons_add(obj, sd);
849
850 evas_object_smart_changed(obj);
851 return int_ret;
852 }
853
854 /* Set correct tm_wday and tm_yday after other fields changes*/
855 static inline void
_fix_selected_time(Elm_Calendar_Data * sd)856 _fix_selected_time(Elm_Calendar_Data *sd)
857 {
858 if (sd->selected_time.tm_mon != sd->shown_time.tm_mon)
859 sd->selected_time.tm_mon = sd->shown_time.tm_mon;
860 if (sd->selected_time.tm_year != sd->shown_time.tm_year)
861 sd->selected_time.tm_year = sd->shown_time.tm_year;
862
863 if ((sd->selected_time.tm_year == sd->date_min.tm_year)
864 && (sd->selected_time.tm_mon == sd->date_min.tm_mon)
865 && (sd->selected_time.tm_mday < sd->date_min.tm_mday))
866 {
867 sd->selected_time.tm_mday = sd->date_min.tm_mday;
868 }
869 else if ((sd->selected_time.tm_year == sd->date_max.tm_year)
870 && (sd->selected_time.tm_mon == sd->date_max.tm_mon)
871 && (sd->selected_time.tm_mday > sd->date_max.tm_mday))
872 {
873 sd->selected_time.tm_mday = sd->date_max.tm_mday;
874 }
875
876 mktime(&sd->selected_time);
877 }
878
879 static Eina_Bool
_update_data(Evas_Object * obj,Eina_Bool month,int delta)880 _update_data(Evas_Object *obj, Eina_Bool month,
881 int delta)
882 {
883 struct tm time_check;
884 int maxdays, years;
885
886 ELM_CALENDAR_DATA_GET(obj, sd);
887
888 /* check if it's a valid time. for 32 bits, year greater than 2037 is not */
889 time_check = sd->shown_time;
890 if (month)
891 time_check.tm_mon += delta;
892 else
893 time_check.tm_year += delta;
894 if (mktime(&time_check) == -1)
895 return EINA_FALSE;
896
897 if (month)
898 {
899 sd->shown_time.tm_mon += delta;
900 if (delta < 0)
901 {
902 if (sd->shown_time.tm_year == sd->date_min.tm_year)
903 {
904 if (sd->shown_time.tm_mon < sd->date_min.tm_mon)
905 {
906 sd->shown_time.tm_mon = sd->date_min.tm_mon;
907 return EINA_FALSE;
908 }
909 }
910 else if (sd->shown_time.tm_mon < 0)
911 {
912 sd->shown_time.tm_mon = 11;
913 sd->shown_time.tm_year--;
914 }
915 }
916 else
917 {
918 if (sd->shown_time.tm_year == sd->date_max.tm_year)
919 {
920 if (sd->shown_time.tm_mon > sd->date_max.tm_mon)
921 {
922 sd->shown_time.tm_mon = sd->date_max.tm_mon;
923 return EINA_FALSE;
924 }
925 }
926 else if (sd->shown_time.tm_mon > 11)
927 {
928 sd->shown_time.tm_mon = 0;
929 sd->shown_time.tm_year++;
930 }
931 }
932 }
933 else
934 {
935 years = sd->shown_time.tm_year + delta;
936 if (((years > sd->date_max.tm_year) && (sd->date_max.tm_year != -1)) ||
937 years < sd->date_min.tm_year)
938 return EINA_FALSE;
939
940 sd->shown_time.tm_year = years;
941 if ((years == sd->date_min.tm_year) && (sd->shown_time.tm_mon < sd->date_min.tm_mon))
942 {
943 sd->shown_time.tm_mon = sd->date_min.tm_mon;
944 }
945 else if ((years == sd->date_max.tm_year) && (sd->shown_time.tm_mon > sd->date_max.tm_mon))
946 {
947 sd->shown_time.tm_mon = sd->date_max.tm_mon;
948 }
949 }
950
951 if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
952 && (sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE))
953 {
954 maxdays = _maxdays_get(&sd->shown_time, 0);
955 if (sd->selected_time.tm_mday > maxdays)
956 sd->selected_time.tm_mday = maxdays;
957
958 _fix_selected_time(sd);
959 efl_event_callback_legacy_call(obj, ELM_CALENDAR_EVENT_CHANGED, NULL);
960 }
961 efl_event_callback_legacy_call(obj, ELM_CALENDAR_EVENT_DISPLAY_CHANGED, NULL);
962
963 return EINA_TRUE;
964 }
965
966 static Eina_Bool
_spin_value(void * data)967 _spin_value(void *data)
968 {
969 ELM_CALENDAR_DATA_GET(data, sd);
970
971 if (_update_data(data, sd->month_btn_clicked, sd->spin_speed))
972 evas_object_smart_changed(data);
973
974 if (sd->spin_timer)
975 {
976 sd->interval = sd->interval / 1.05;
977 ecore_timer_interval_set(sd->spin_timer, sd->interval);
978 }
979
980 return ECORE_CALLBACK_RENEW;
981 }
982
983 /* Legacy callbacks for signals from edje */
984 static void
_button_month_inc_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)985 _button_month_inc_start(void *data,
986 Evas_Object *obj EINA_UNUSED,
987 const char *emission EINA_UNUSED,
988 const char *source EINA_UNUSED)
989 {
990 ELM_CALENDAR_DATA_GET(data, sd);
991
992 sd->interval = sd->first_interval;
993 sd->spin_speed = 1;
994 sd->month_btn_clicked = EINA_TRUE;
995 ecore_timer_del(sd->spin_timer);
996 sd->spin_timer = ecore_timer_add(sd->interval, _spin_value, data);
997
998 elm_widget_scroll_freeze_push(data);
999
1000 _spin_value(data);
1001 }
1002
1003 /* Legacy callbacks for signals from edje */
1004 static void
_button_month_dec_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1005 _button_month_dec_start(void *data,
1006 Evas_Object *obj EINA_UNUSED,
1007 const char *emission EINA_UNUSED,
1008 const char *source EINA_UNUSED)
1009 {
1010 ELM_CALENDAR_DATA_GET(data, sd);
1011
1012 sd->interval = sd->first_interval;
1013 sd->spin_speed = -1;
1014 sd->month_btn_clicked = EINA_TRUE;
1015 ecore_timer_del(sd->spin_timer);
1016 sd->spin_timer = ecore_timer_add(sd->interval, _spin_value, data);
1017
1018 elm_widget_scroll_freeze_push(data);
1019
1020 _spin_value(data);
1021 }
1022
1023 /* Legacy callbacks for signals from edje */
1024 static void
_button_month_stop(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1025 _button_month_stop(void *data,
1026 Evas_Object *obj EINA_UNUSED,
1027 const char *emission EINA_UNUSED,
1028 const char *source EINA_UNUSED)
1029 {
1030 ELM_CALENDAR_DATA_GET(data, sd);
1031
1032 sd->interval = sd->first_interval;
1033 ELM_SAFE_FREE(sd->spin_timer, ecore_timer_del);
1034
1035 elm_widget_scroll_freeze_pop(obj);
1036 }
1037
1038 /* Legacy callbacks for signals from edje */
1039 static void
_button_year_inc_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1040 _button_year_inc_start(void *data,
1041 Evas_Object *obj EINA_UNUSED,
1042 const char *emission EINA_UNUSED,
1043 const char *source EINA_UNUSED)
1044 {
1045 ELM_CALENDAR_DATA_GET(data, sd);
1046
1047 sd->interval = sd->first_interval;
1048 sd->spin_speed = 1;
1049 sd->month_btn_clicked = EINA_FALSE;
1050 ecore_timer_del(sd->spin_timer);
1051 sd->spin_timer = ecore_timer_add(sd->interval, _spin_value, data);
1052
1053 elm_widget_scroll_freeze_push(data);
1054
1055 _spin_value(data);
1056 }
1057
1058 /* Legacy callbacks for signals from edje */
1059 static void
_button_year_dec_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1060 _button_year_dec_start(void *data,
1061 Evas_Object *obj EINA_UNUSED,
1062 const char *emission EINA_UNUSED,
1063 const char *source EINA_UNUSED)
1064 {
1065 ELM_CALENDAR_DATA_GET(data, sd);
1066
1067 sd->interval = sd->first_interval;
1068 sd->spin_speed = -1;
1069 sd->month_btn_clicked = EINA_FALSE;
1070 ecore_timer_del(sd->spin_timer);
1071 sd->spin_timer = ecore_timer_add(sd->interval, _spin_value, data);
1072
1073 elm_widget_scroll_freeze_push(data);
1074
1075 _spin_value(data);
1076 }
1077
1078 /* Legacy callbacks for signals from edje */
1079 static void
_button_year_stop(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1080 _button_year_stop(void *data,
1081 Evas_Object *obj EINA_UNUSED,
1082 const char *emission EINA_UNUSED,
1083 const char *source EINA_UNUSED)
1084 {
1085 ELM_CALENDAR_DATA_GET(data, sd);
1086
1087 sd->interval = sd->first_interval;
1088 ELM_SAFE_FREE(sd->spin_timer, ecore_timer_del);
1089
1090 elm_widget_scroll_freeze_pop(obj);
1091 }
1092
1093 static void
_inc_dec_button_clicked_cb(void * data,const Efl_Event * event EINA_UNUSED)1094 _inc_dec_button_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
1095 {
1096 ELM_CALENDAR_DATA_GET(data, sd);
1097
1098 sd->interval = sd->first_interval;
1099 ELM_SAFE_FREE(sd->spin_timer, ecore_timer_del);
1100
1101 _spin_value(data);
1102 }
1103 static void
_inc_dec_button_pressed_cb(void * data,const Efl_Event * event)1104 _inc_dec_button_pressed_cb(void *data, const Efl_Event *event)
1105 {
1106 ELM_CALENDAR_DATA_GET(data, sd);
1107
1108 sd->interval = sd->first_interval;
1109 sd->spin_speed = ((sd->inc_btn_month == event->object) ||
1110 (sd->inc_btn_year == event->object)) ? 1 : -1;
1111
1112 sd->month_btn_clicked = ((sd->inc_btn_month == event->object) ||
1113 (sd->dec_btn_month == event->object)) ? EINA_TRUE : EINA_FALSE;
1114
1115 ELM_SAFE_FREE(sd->spin_timer, ecore_timer_del);
1116 sd->spin_timer = ecore_timer_add(sd->interval, _spin_value, data);
1117
1118 elm_widget_scroll_freeze_push(data);
1119 }
1120
1121 static void
_inc_dec_button_unpressed_cb(void * data,const Efl_Event * event EINA_UNUSED)1122 _inc_dec_button_unpressed_cb(void *data, const Efl_Event *event EINA_UNUSED)
1123 {
1124 ELM_CALENDAR_DATA_GET(data, sd);
1125
1126 sd->interval = sd->first_interval;
1127 ELM_SAFE_FREE(sd->spin_timer, ecore_timer_del);
1128
1129 elm_widget_scroll_freeze_pop(data);
1130 }
1131
1132 static int
_get_item_day(Evas_Object * obj,int selected_it)1133 _get_item_day(Evas_Object *obj,
1134 int selected_it)
1135 {
1136 int day;
1137
1138 ELM_CALENDAR_DATA_GET(obj, sd);
1139
1140 day = selected_it - sd->first_day_it + 1;
1141 if ((day < 0) || (day > _maxdays_get(&sd->shown_time, 0)))
1142 return 0;
1143
1144 if ((sd->shown_time.tm_year == sd->date_min.tm_year)
1145 && (sd->shown_time.tm_mon == sd->date_min.tm_mon)
1146 && (day < sd->date_min.tm_mday))
1147 {
1148 return 0;
1149 }
1150 else if ((sd->shown_time.tm_year == sd->date_max.tm_year)
1151 && (sd->shown_time.tm_mon == sd->date_max.tm_mon)
1152 && (day > sd->date_max.tm_mday))
1153 {
1154 return 0;
1155 }
1156
1157 return day;
1158 }
1159
1160 static void
_update_unfocused_it(Evas_Object * obj,int unfocused_it)1161 _update_unfocused_it(Evas_Object *obj, int unfocused_it)
1162 {
1163 int day;
1164 char emission[32];
1165
1166 ELM_CALENDAR_DATA_GET(obj, sd);
1167
1168 day = _get_item_day(obj, unfocused_it);
1169 if (!day)
1170 return;
1171
1172 sd->focused_it = -1;
1173
1174 snprintf(emission, sizeof(emission), "cit_%i,unfocused", unfocused_it);
1175 elm_layout_signal_emit(obj, emission, "elm");
1176 }
1177
1178 static Eina_Bool
_update_focused_it(Evas_Object * obj,int focused_it)1179 _update_focused_it(Evas_Object *obj, int focused_it)
1180 {
1181 int day;
1182 char emission[32];
1183
1184 ELM_CALENDAR_DATA_GET(obj, sd);
1185
1186 day = _get_item_day(obj, focused_it);
1187 if (!day)
1188 return EINA_FALSE;
1189
1190 snprintf(emission, sizeof(emission), "cit_%i,unfocused", sd->focused_it);
1191 elm_layout_signal_emit(obj, emission, "elm");
1192
1193 sd->focused_it = focused_it;
1194
1195 snprintf(emission, sizeof(emission), "cit_%i,focused", sd->focused_it);
1196 elm_layout_signal_emit(obj, emission, "elm");
1197
1198 return EINA_TRUE;
1199 }
1200
1201 static void
_update_sel_it(Evas_Object * obj,int sel_it)1202 _update_sel_it(Evas_Object *obj,
1203 int sel_it)
1204 {
1205 int day;
1206
1207 ELM_CALENDAR_DATA_GET(obj, sd);
1208
1209 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE)
1210 return;
1211
1212 day = _get_item_day(obj, sel_it);
1213 if (!day)
1214 return;
1215
1216 _unselect(obj, sd->selected_it);
1217 if (!sd->selected)
1218 sd->selected = EINA_TRUE;
1219 if (sd->focused_it)
1220 _update_unfocused_it(obj, sd->focused_it);
1221
1222 sd->selected_time.tm_mday = day;
1223 _fix_selected_time(sd);
1224 _select(obj, sel_it);
1225 efl_event_callback_legacy_call(obj, ELM_CALENDAR_EVENT_CHANGED, NULL);
1226 }
1227
1228 static void
_day_selected(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source)1229 _day_selected(void *data,
1230 Evas_Object *obj EINA_UNUSED,
1231 const char *emission EINA_UNUSED,
1232 const char *source)
1233 {
1234 int sel_it;
1235
1236 ELM_CALENDAR_DATA_GET(data, sd);
1237
1238 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE)
1239 return;
1240
1241 sel_it = atoi(source);
1242
1243 _update_sel_it(data, sel_it);
1244 }
1245
1246 static inline int
_time_to_next_day(struct tm * t)1247 _time_to_next_day(struct tm *t)
1248 {
1249 return ((((24 - t->tm_hour) * 60) - t->tm_min) * 60) - t->tm_sec;
1250 }
1251
1252 static Eina_Bool
_update_cur_date(void * data)1253 _update_cur_date(void *data)
1254 {
1255 time_t current_time;
1256 int t, day;
1257 ELM_CALENDAR_DATA_GET(data, sd);
1258
1259 if (sd->today_it > 0) _not_today(sd);
1260
1261 current_time = time(NULL);
1262 localtime_r(¤t_time, &sd->current_time);
1263 t = _time_to_next_day(&sd->current_time);
1264 ecore_timer_interval_set(sd->update_timer, t);
1265
1266 if ((sd->current_time.tm_mon != sd->shown_time.tm_mon) ||
1267 (sd->current_time.tm_year != sd->shown_time.tm_year))
1268 return ECORE_CALLBACK_RENEW;
1269
1270 day = sd->current_time.tm_mday + sd->first_day_it - 1;
1271 _today(sd, day);
1272
1273 return ECORE_CALLBACK_RENEW;
1274 }
1275
1276 static Eina_Bool
_key_action_activate(Evas_Object * obj,const char * params EINA_UNUSED)1277 _key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
1278 {
1279 ELM_CALENDAR_DATA_GET(obj, sd);
1280
1281 _update_sel_it(obj, sd->focused_it);
1282
1283 return EINA_TRUE;
1284 }
1285
1286 EOLIAN static Eina_Bool
_elm_calendar_efl_ui_focus_object_on_focus_update(Eo * obj,Elm_Calendar_Data * sd)1287 _elm_calendar_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Calendar_Data *sd)
1288 {
1289 Eina_Bool int_ret = EINA_FALSE;
1290
1291 int_ret = efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS));
1292 if (!int_ret) return EINA_FALSE;
1293
1294 if (efl_ui_focus_object_focus_get(obj))
1295 _update_focused_it(obj, sd->selected_it);
1296 else
1297 _update_unfocused_it(obj, sd->focused_it);
1298
1299 return EINA_TRUE;
1300 }
1301
1302 EOLIAN static void
_elm_calendar_efl_canvas_group_group_calculate(Eo * obj,Elm_Calendar_Data * _pd EINA_UNUSED)1303 _elm_calendar_efl_canvas_group_group_calculate(Eo *obj, Elm_Calendar_Data *_pd EINA_UNUSED)
1304 {
1305 efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
1306 _set_headers(obj);
1307 _populate(obj);
1308 efl_canvas_group_calculate(efl_super(obj, MY_CLASS));
1309 }
1310
1311 static void
_style_changed(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1312 _style_changed(void *data,
1313 Evas_Object *obj EINA_UNUSED,
1314 const char *emission EINA_UNUSED,
1315 const char *source EINA_UNUSED)
1316 {
1317 ELM_CALENDAR_DATA_GET(data, sd);
1318
1319 if (!strcmp("double_spinners", elm_object_style_get(sd->obj)))
1320 sd->double_spinners = EINA_TRUE;
1321 else
1322 sd->double_spinners = EINA_FALSE;
1323
1324 _set_month_year(sd);
1325 }
1326
1327 EOLIAN static void
_elm_calendar_efl_canvas_group_group_add(Eo * obj,Elm_Calendar_Data * priv)1328 _elm_calendar_efl_canvas_group_group_add(Eo *obj, Elm_Calendar_Data *priv)
1329 {
1330 time_t current_time;
1331 int t;
1332
1333 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1334
1335 efl_canvas_group_add(efl_super(obj, MY_CLASS));
1336
1337 priv->first_interval = 0.85;
1338 priv->date_min.tm_year = 2;
1339 priv->date_min.tm_mon = 0;
1340 priv->date_min.tm_mday = 1;
1341 priv->date_max.tm_year = -1;
1342 priv->date_max.tm_mon = 11;
1343 priv->date_max.tm_mday = 31;
1344 priv->today_it = -1;
1345 priv->selected_it = -1;
1346 priv->first_day_it = -1;
1347 priv->format_func = _format_month_year;
1348 priv->selectable = (~(ELM_CALENDAR_SELECTABLE_NONE));
1349
1350 edje_object_signal_callback_add
1351 (wd->resize_obj, "elm,action,increment,start", "*",
1352 _button_month_inc_start, obj);
1353 edje_object_signal_callback_add
1354 (wd->resize_obj, "elm,action,decrement,start", "*",
1355 _button_month_dec_start, obj);
1356 edje_object_signal_callback_add
1357 (wd->resize_obj, "elm,action,increment,startyear", "*",
1358 _button_year_inc_start, obj);
1359 edje_object_signal_callback_add
1360 (wd->resize_obj, "elm,action,decrement,startyear", "*",
1361 _button_year_dec_start, obj);
1362 edje_object_signal_callback_add
1363 (wd->resize_obj, "elm,action,stop", "*",
1364 _button_month_stop, obj);
1365 edje_object_signal_callback_add
1366 (wd->resize_obj, "elm,action,stopyear", "*",
1367 _button_year_stop, obj);
1368 edje_object_signal_callback_add
1369 (wd->resize_obj, "elm,action,selected", "*",
1370 _day_selected, obj);
1371 edje_object_signal_callback_add
1372 (wd->resize_obj, "load", "*",
1373 _style_changed, obj);
1374
1375 current_time = time(NULL);
1376 localtime_r(¤t_time, &priv->shown_time);
1377 priv->current_time = priv->shown_time;
1378 priv->selected_time = priv->shown_time;
1379 t = _time_to_next_day(&priv->current_time);
1380 priv->update_timer = ecore_timer_add(t, _update_cur_date, obj);
1381
1382 elm_widget_can_focus_set(obj, EINA_TRUE);
1383
1384 if (!elm_layout_theme_set(obj, "calendar", "base",
1385 elm_object_style_get(obj)))
1386 CRI("Failed to set layout!");
1387
1388 _spinner_buttons_add(obj, priv);
1389
1390 // 7x8 (1 month+year, days, 6 dates.)
1391 efl_ui_layout_finger_size_multiplier_set(obj, 7, 8);
1392
1393 evas_object_smart_changed(obj);
1394
1395 // ACCESS
1396 if ((_elm_config->access_mode != ELM_ACCESS_MODE_OFF))
1397 _access_calendar_spinner_register(obj);
1398
1399 // Items for composition
1400 for (int i = 0; i < 42; ++i)
1401 {
1402 priv->items[i] = efl_add(ELM_CALENDAR_ITEM_CLASS, obj, elm_calendar_item_day_number_set(efl_added, i));
1403 }
1404 }
1405
1406 EOLIAN static void
_elm_calendar_efl_canvas_group_group_del(Eo * obj,Elm_Calendar_Data * sd)1407 _elm_calendar_efl_canvas_group_group_del(Eo *obj, Elm_Calendar_Data *sd)
1408 {
1409 int i;
1410 Elm_Calendar_Mark *mark;
1411
1412 ecore_timer_del(sd->spin_timer);
1413 ecore_timer_del(sd->update_timer);
1414
1415 if (sd->marks)
1416 {
1417 EINA_LIST_FREE(sd->marks, mark)
1418 {
1419 _mark_free(mark);
1420 }
1421 }
1422
1423 for (i = 0; i < ELM_DAY_LAST; i++)
1424 eina_stringshare_del(sd->weekdays[i]);
1425
1426 efl_canvas_group_del(efl_super(obj, MY_CLASS));
1427 }
1428
1429 static Eina_Bool _elm_calendar_smart_focus_next_enable = EINA_FALSE;
1430
1431 static void
_access_obj_process(Evas_Object * obj,Eina_Bool is_access)1432 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1433 {
1434 int maxdays, day, i;
1435
1436 ELM_CALENDAR_DATA_GET(obj, sd);
1437 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1438
1439 if (is_access)
1440 _access_calendar_register(obj);
1441 else
1442 {
1443 day = 0;
1444 maxdays = _maxdays_get(&sd->shown_time, 0);
1445 for (i = 0; i < 42; i++)
1446 {
1447 if ((!day) && (i == sd->first_day_it)) day = 1;
1448 if ((day) && (day <= maxdays))
1449 {
1450 char pname[18];
1451 _part_name_snprintf(pname, sizeof(pname),
1452 obj, ELM_CALENDAR_CIT_ACCESS_PART_STR, i);
1453
1454 _elm_access_edje_object_part_object_unregister
1455 (obj, elm_layout_edje_get(obj), pname);
1456 }
1457 }
1458
1459 if (sd->dec_btn_month && efl_isa(sd->dec_btn_month, ELM_ACCESS_CLASS))
1460 {
1461 _elm_access_edje_object_part_object_unregister
1462 (obj, elm_layout_edje_get(obj), "left_bt");
1463 sd->dec_btn_month = NULL;
1464 }
1465 if (sd->inc_btn_month && efl_isa(sd->inc_btn_month, ELM_ACCESS_CLASS))
1466 {
1467 _elm_access_edje_object_part_object_unregister
1468 (obj, elm_layout_edje_get(obj), "right_bt");
1469 sd->inc_btn_month = NULL;
1470 }
1471 if (sd->month_access)
1472 _elm_access_edje_object_part_object_unregister
1473 (obj, elm_layout_edje_get(obj), "month_text");
1474
1475 if (sd->dec_btn_year && efl_isa(sd->dec_btn_year, ELM_ACCESS_CLASS))
1476 {
1477 _elm_access_edje_object_part_object_unregister
1478 (obj, elm_layout_edje_get(obj), "left_bt_year");
1479 sd->dec_btn_year = NULL;
1480 }
1481 if (sd->inc_btn_year && efl_isa(sd->inc_btn_year, ELM_ACCESS_CLASS))
1482 {
1483 _elm_access_edje_object_part_object_unregister
1484 (obj, elm_layout_edje_get(obj), "right_bt_year");
1485 sd->inc_btn_year = NULL;
1486 }
1487 if (sd->year_access)
1488 _elm_access_edje_object_part_object_unregister
1489 (obj, elm_layout_edje_get(obj), "year_text");
1490 }
1491 }
1492
1493 EOLIAN static void
_elm_calendar_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Calendar_Data * _pd EINA_UNUSED,Eina_Bool acs)1494 _elm_calendar_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Calendar_Data *_pd EINA_UNUSED, Eina_Bool acs)
1495 {
1496 _elm_calendar_smart_focus_next_enable = acs;
1497 _access_obj_process(obj, _elm_calendar_smart_focus_next_enable);
1498 }
1499
1500 EAPI Evas_Object *
elm_calendar_add(Evas_Object * parent)1501 elm_calendar_add(Evas_Object *parent)
1502 {
1503 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1504 return elm_legacy_add(MY_CLASS, parent);
1505 }
1506
1507 EOLIAN static Eo *
_elm_calendar_efl_object_constructor(Eo * obj,Elm_Calendar_Data * sd)1508 _elm_calendar_efl_object_constructor(Eo *obj, Elm_Calendar_Data *sd)
1509 {
1510 obj = efl_constructor(efl_super(obj, MY_CLASS));
1511 sd->obj = obj;
1512
1513 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
1514 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
1515 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_CALENDAR);
1516
1517 return obj;
1518 }
1519
1520 EOLIAN static void
_elm_calendar_weekdays_names_set(Eo * obj,Elm_Calendar_Data * sd,const char ** weekdays)1521 _elm_calendar_weekdays_names_set(Eo *obj, Elm_Calendar_Data *sd, const char **weekdays)
1522 {
1523 int i;
1524
1525 EINA_SAFETY_ON_NULL_RETURN(weekdays);
1526
1527 for (i = 0; i < ELM_DAY_LAST; i++)
1528 {
1529 eina_stringshare_replace(&sd->weekdays[i], weekdays[i]);
1530 }
1531 sd->weekdays_set = EINA_TRUE;
1532
1533 evas_object_smart_changed(obj);
1534 }
1535
1536 EOLIAN static const char**
_elm_calendar_weekdays_names_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1537 _elm_calendar_weekdays_names_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1538 {
1539 return sd->weekdays;
1540 }
1541
1542 EOLIAN static void
_elm_calendar_interval_set(Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd,double interval)1543 _elm_calendar_interval_set(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, double interval)
1544 {
1545 sd->first_interval = interval;
1546 }
1547
1548 EOLIAN static double
_elm_calendar_interval_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1549 _elm_calendar_interval_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1550 {
1551 return sd->first_interval;
1552 }
1553
1554 EAPI void
elm_calendar_min_max_year_set(Elm_Calendar * obj,int min,int max)1555 elm_calendar_min_max_year_set(Elm_Calendar *obj, int min, int max)
1556 {
1557 Elm_Calendar_Data *sd;
1558
1559 if (!efl_isa(obj, ELM_CALENDAR_CLASS)) return ;
1560 sd = efl_data_scope_get(obj, ELM_CALENDAR_CLASS);
1561
1562 min -= 1900;
1563 max -= 1900;
1564 if ((sd->date_min.tm_year == min) && (sd->date_max.tm_year == max)) return;
1565 sd->date_min.tm_year = min > 2 ? min : 2;
1566 if (max > sd->date_min.tm_year)
1567 sd->date_max.tm_year = max;
1568 else
1569 sd->date_max.tm_year = sd->date_min.tm_year;
1570 sd->date_min.tm_mon = 0;
1571 sd->date_min.tm_mday = 1;
1572 sd->date_max.tm_mon = 11;
1573 sd->date_max.tm_mday = 31;
1574
1575 if (sd->shown_time.tm_year > sd->date_max.tm_year)
1576 sd->shown_time.tm_year = sd->date_max.tm_year;
1577 if (sd->shown_time.tm_year < sd->date_min.tm_year)
1578 sd->shown_time.tm_year = sd->date_min.tm_year;
1579
1580 evas_object_smart_changed(obj);
1581 }
1582
1583 EAPI void
elm_calendar_min_max_year_get(const Elm_Calendar * obj,int * min,int * max)1584 elm_calendar_min_max_year_get(const Elm_Calendar *obj, int *min, int *max)
1585 {
1586 Elm_Calendar_Data *sd;
1587
1588 if (!efl_isa(obj, ELM_CALENDAR_CLASS)) return ;
1589 sd = efl_data_scope_get(obj, ELM_CALENDAR_CLASS);
1590
1591 if (min) *min = sd->date_min.tm_year + 1900;
1592 if (max) *max = sd->date_max.tm_year + 1900;
1593 }
1594
1595 EOLIAN static void
_elm_calendar_date_min_set(Eo * obj,Elm_Calendar_Data * sd,const struct tm * min)1596 _elm_calendar_date_min_set(Eo *obj, Elm_Calendar_Data *sd, const struct tm *min)
1597 {
1598 Eina_Bool upper = EINA_FALSE;
1599
1600 if ((sd->date_min.tm_year == min->tm_year)
1601 && (sd->date_min.tm_mon == min->tm_mon)
1602 && (sd->date_min.tm_mday == min->tm_mday))
1603 return;
1604
1605 if (min->tm_year < 2)
1606 {
1607 sd->date_min.tm_year = 2;
1608 sd->date_min.tm_mon = 0;
1609 sd->date_min.tm_mday = 1;
1610 }
1611 else
1612 {
1613 if (sd->date_max.tm_year != -1)
1614 {
1615 if (min->tm_year > sd->date_max.tm_year)
1616 {
1617 upper = EINA_TRUE;
1618 }
1619 else if (min->tm_year == sd->date_max.tm_year)
1620 {
1621 if (min->tm_mon > sd->date_max.tm_mon)
1622 upper = EINA_TRUE;
1623 else if ((min->tm_mon == sd->date_max.tm_mon) && (min->tm_mday > sd->date_max.tm_mday))
1624 upper = EINA_TRUE;
1625 }
1626 }
1627
1628 if (upper)
1629 {
1630 sd->date_min.tm_year = sd->date_max.tm_year;
1631 sd->date_min.tm_mon = sd->date_max.tm_mon;
1632 sd->date_min.tm_mday = sd->date_max.tm_mday;
1633 }
1634 else
1635 {
1636 sd->date_min.tm_year = min->tm_year;
1637 sd->date_min.tm_mon = min->tm_mon;
1638 sd->date_min.tm_mday = min->tm_mday;
1639 }
1640 }
1641
1642 if (sd->shown_time.tm_year <= sd->date_min.tm_year)
1643 {
1644 sd->shown_time.tm_year = sd->date_min.tm_year;
1645 if (sd->shown_time.tm_mon < sd->date_min.tm_mon)
1646 sd->shown_time.tm_mon = sd->date_min.tm_mon;
1647 }
1648
1649 _fix_selected_time(sd);
1650
1651 evas_object_smart_changed(obj);
1652 }
1653
1654 EOLIAN static const struct tm *
_elm_calendar_date_min_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1655 _elm_calendar_date_min_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1656 {
1657 return &(sd->date_min);
1658 }
1659
1660 EOLIAN static void
_elm_calendar_date_max_set(Eo * obj,Elm_Calendar_Data * sd,const struct tm * max)1661 _elm_calendar_date_max_set(Eo *obj, Elm_Calendar_Data *sd, const struct tm *max)
1662 {
1663 Eina_Bool lower = EINA_FALSE;
1664
1665 if ((sd->date_max.tm_year == max->tm_year)
1666 && (sd->date_max.tm_mon == max->tm_mon)
1667 && (sd->date_max.tm_mday == max->tm_mday))
1668 return;
1669
1670 if (max->tm_year < sd->date_min.tm_year)
1671 {
1672 lower = EINA_TRUE;
1673 }
1674 else if (max->tm_year == sd->date_min.tm_year)
1675 {
1676 if (max->tm_mon < sd->date_min.tm_mon)
1677 lower = EINA_TRUE;
1678 else if ((max->tm_mon == sd->date_min.tm_mon) && (max->tm_mday < sd->date_min.tm_mday))
1679 lower = EINA_TRUE;
1680 }
1681
1682 if (lower)
1683 {
1684 sd->date_max.tm_year = sd->date_min.tm_year;
1685 sd->date_max.tm_mon = sd->date_min.tm_mon;
1686 sd->date_max.tm_mday = sd->date_min.tm_mday;
1687 }
1688 else
1689 {
1690 sd->date_max.tm_year = max->tm_year;
1691 sd->date_max.tm_mon = max->tm_mon;
1692 sd->date_max.tm_mday = max->tm_mday;
1693 }
1694
1695 if (sd->shown_time.tm_year >= sd->date_max.tm_year)
1696 {
1697 sd->shown_time.tm_year = sd->date_max.tm_year;
1698 if (sd->shown_time.tm_mon > sd->date_max.tm_mon)
1699 sd->shown_time.tm_mon = sd->date_max.tm_mon;
1700 }
1701
1702 _fix_selected_time(sd);
1703
1704 evas_object_smart_changed(obj);
1705 }
1706
1707 EOLIAN static const struct tm *
_elm_calendar_date_max_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1708 _elm_calendar_date_max_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1709 {
1710 return &(sd->date_max);
1711 }
1712
1713 EINA_DEPRECATED EAPI void
elm_calendar_day_selection_disabled_set(Evas_Object * obj,Eina_Bool disabled)1714 elm_calendar_day_selection_disabled_set(Evas_Object *obj,
1715 Eina_Bool disabled)
1716 {
1717 ELM_CALENDAR_CHECK(obj);
1718
1719 if (disabled)
1720 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_NONE);
1721 else
1722 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_DEFAULT);
1723 }
1724
1725 EINA_DEPRECATED EAPI Eina_Bool
elm_calendar_day_selection_disabled_get(const Evas_Object * obj)1726 elm_calendar_day_selection_disabled_get(const Evas_Object *obj)
1727 {
1728 ELM_CALENDAR_CHECK(obj) EINA_FALSE;
1729 ELM_CALENDAR_DATA_GET(obj, sd);
1730
1731 return !!(sd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE);
1732 }
1733
1734 EOLIAN static void
_elm_calendar_selected_time_set(Eo * obj,Elm_Calendar_Data * sd,struct tm * selected_time)1735 _elm_calendar_selected_time_set(Eo *obj, Elm_Calendar_Data *sd, struct tm *selected_time)
1736 {
1737 EINA_SAFETY_ON_NULL_RETURN(selected_time);
1738
1739 if (sd->selectable & ELM_CALENDAR_SELECTABLE_YEAR)
1740 sd->selected_time.tm_year = selected_time->tm_year;
1741 if (sd->selectable & ELM_CALENDAR_SELECTABLE_MONTH)
1742 sd->selected_time.tm_mon = selected_time->tm_mon;
1743 if (sd->selectable & ELM_CALENDAR_SELECTABLE_DAY)
1744 {
1745 sd->selected_time.tm_mday = selected_time->tm_mday;
1746 if (!sd->selected)
1747 sd->selected = EINA_TRUE;
1748 }
1749 else if (sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1750 {
1751 if (!sd->selected)
1752 sd->selected = EINA_TRUE;
1753 }
1754 if (sd->selected_time.tm_year != sd->shown_time.tm_year)
1755 sd->shown_time.tm_year = sd->selected_time.tm_year;
1756 if (sd->selected_time.tm_mon != sd->shown_time.tm_mon)
1757 sd->shown_time.tm_mon = sd->selected_time.tm_mon;
1758
1759 _fix_selected_time(sd);
1760
1761 evas_object_smart_changed(obj);
1762 }
1763
1764 EOLIAN static Eina_Bool
_elm_calendar_selected_time_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd,struct tm * selected_time)1765 _elm_calendar_selected_time_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, struct tm *selected_time)
1766 {
1767 EINA_SAFETY_ON_NULL_RETURN_VAL(selected_time, EINA_FALSE);
1768
1769 if ((sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1770 && (!sd->selected))
1771 return EINA_FALSE;
1772 *selected_time = sd->selected_time;
1773
1774 return EINA_TRUE;
1775 }
1776
1777 EOLIAN static void
_elm_calendar_format_function_set(Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd,Elm_Calendar_Format_Cb format_function)1778 _elm_calendar_format_function_set(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, Elm_Calendar_Format_Cb format_function)
1779 {
1780 sd->format_func = format_function;
1781 if (sd->double_spinners) /* theme has spinner for year */
1782 _set_month_year(sd);
1783 }
1784
1785 EOLIAN static Elm_Calendar_Mark*
_elm_calendar_mark_add(Eo * obj,Elm_Calendar_Data * sd,const char * mark_type,struct tm * mark_time,Elm_Calendar_Mark_Repeat_Type repeat)1786 _elm_calendar_mark_add(Eo *obj, Elm_Calendar_Data *sd, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat_Type repeat)
1787 {
1788 Elm_Calendar_Mark *mark;
1789
1790 mark = _mark_new(obj, mark_type, mark_time, repeat);
1791 if (!mark) return NULL;
1792 sd->marks = eina_list_append(sd->marks, mark);
1793 mark->node = eina_list_last(sd->marks);
1794
1795 return mark;
1796 }
1797
1798 EOLIAN static void
_elm_calendar_mark_del(Eo * obj,Elm_Calendar_Data * sd,Elm_Calendar_Mark * mark)1799 _elm_calendar_mark_del(Eo *obj, Elm_Calendar_Data *sd, Elm_Calendar_Mark *mark)
1800 {
1801 EINA_SAFETY_ON_NULL_RETURN(mark);
1802 EINA_SAFETY_ON_TRUE_RETURN(mark->obj != obj);
1803
1804 sd->marks = eina_list_remove_list(sd->marks, mark->node);
1805 _mark_free(mark);
1806 }
1807
1808 EAPI void
elm_calendar_mark_del(Elm_Calendar_Mark * mark)1809 elm_calendar_mark_del(Elm_Calendar_Mark *mark)
1810 {
1811 EINA_SAFETY_ON_NULL_RETURN(mark);
1812 ELM_CALENDAR_CHECK(mark->obj);
1813 ELM_CALENDAR_DATA_GET(mark->obj, sd);
1814
1815 sd->marks = eina_list_remove_list(sd->marks, mark->node);
1816 _mark_free(mark);
1817 }
1818
1819 EOLIAN static void
_elm_calendar_marks_clear(Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1820 _elm_calendar_marks_clear(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1821 {
1822 Elm_Calendar_Mark *mark;
1823
1824 EINA_LIST_FREE(sd->marks, mark)
1825 _mark_free(mark);
1826 }
1827
1828 EOLIAN static const Eina_List*
_elm_calendar_marks_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1829 _elm_calendar_marks_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1830 {
1831 return sd->marks;
1832 }
1833
1834 EOLIAN static void
_elm_calendar_marks_draw(Eo * obj,Elm_Calendar_Data * _pd EINA_UNUSED)1835 _elm_calendar_marks_draw(Eo *obj, Elm_Calendar_Data *_pd EINA_UNUSED)
1836 {
1837 evas_object_smart_changed(obj);
1838 }
1839
1840 EOLIAN static void
_elm_calendar_first_day_of_week_set(Eo * obj,Elm_Calendar_Data * sd,Elm_Calendar_Weekday day)1841 _elm_calendar_first_day_of_week_set(Eo *obj, Elm_Calendar_Data *sd, Elm_Calendar_Weekday day)
1842 {
1843 if (day >= ELM_DAY_LAST) return;
1844 if (sd->first_week_day != day)
1845 {
1846 sd->first_week_day = day;
1847 evas_object_smart_changed(obj);
1848 }
1849 }
1850
1851 EOLIAN static Elm_Calendar_Weekday
_elm_calendar_first_day_of_week_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1852 _elm_calendar_first_day_of_week_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1853 {
1854 return sd->first_week_day;
1855 }
1856
1857 EOLIAN static void
_elm_calendar_select_mode_set(Eo * obj,Elm_Calendar_Data * sd,Elm_Calendar_Select_Mode mode)1858 _elm_calendar_select_mode_set(Eo *obj, Elm_Calendar_Data *sd, Elm_Calendar_Select_Mode mode)
1859 {
1860
1861 if ((mode <= ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1862 && (sd->select_mode != mode))
1863 {
1864 sd->select_mode = mode;
1865 if (sd->select_mode == ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1866 sd->selected = EINA_FALSE;
1867 if ((sd->select_mode == ELM_CALENDAR_SELECT_MODE_ALWAYS)
1868 || (sd->select_mode == ELM_CALENDAR_SELECT_MODE_DEFAULT))
1869 _select(obj, sd->selected_it);
1870 else
1871 _unselect(obj, sd->selected_it);
1872 }
1873 }
1874
1875 EOLIAN static Elm_Calendar_Select_Mode
_elm_calendar_select_mode_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1876 _elm_calendar_select_mode_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1877 {
1878 return sd->select_mode;
1879 }
1880
1881 EOLIAN static void
_elm_calendar_selectable_set(Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd,Elm_Calendar_Selectable selectable)1882 _elm_calendar_selectable_set(Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, Elm_Calendar_Selectable selectable)
1883 {
1884 sd->selectable = selectable;
1885 }
1886
1887 EOLIAN static Elm_Calendar_Selectable
_elm_calendar_selectable_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd)1888 _elm_calendar_selectable_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd)
1889 {
1890 return sd->selectable;
1891 }
1892
1893 EOLIAN static Eina_Bool
_elm_calendar_displayed_time_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd,struct tm * displayed_time)1894 _elm_calendar_displayed_time_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd, struct tm *displayed_time)
1895 {
1896 EINA_SAFETY_ON_NULL_RETURN_VAL(displayed_time, EINA_FALSE);
1897 *displayed_time = sd->shown_time;
1898 return EINA_TRUE;
1899 }
1900
1901 static void
_elm_calendar_class_constructor(Efl_Class * klass)1902 _elm_calendar_class_constructor(Efl_Class *klass)
1903 {
1904 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1905
1906 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
1907 _elm_calendar_smart_focus_next_enable = EINA_TRUE;
1908 }
1909
1910 EOLIAN static const Efl_Access_Action_Data*
_elm_calendar_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Data * sd EINA_UNUSED)1911 _elm_calendar_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Data *sd EINA_UNUSED)
1912 {
1913 static Efl_Access_Action_Data atspi_actions[] = {
1914 { "activate", "activate", NULL, _key_action_activate},
1915 { NULL, NULL, NULL, NULL }
1916 };
1917 return &atspi_actions[0];
1918 }
1919
1920 /* Standard widget overrides */
1921
1922 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_calendar, Elm_Calendar_Data)
1923
1924 /* Internal EO APIs and hidden overrides */
1925
1926 #define ELM_CALENDAR_EXTRA_OPS \
1927 EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_calendar)
1928
1929 #include "elm_calendar_eo.c"
1930
1931 typedef struct {
1932 int v;
1933 Evas_Object *part;
1934 } Elm_Calendar_Item_Data;
1935
1936 EOLIAN static void
_elm_calendar_item_day_number_set(Eo * obj,Elm_Calendar_Item_Data * pd,int i)1937 _elm_calendar_item_day_number_set(Eo *obj, Elm_Calendar_Item_Data *pd, int i)
1938 {
1939 char pname[18];
1940 Evas_Object *po, *o;
1941
1942 pd->v = i;
1943
1944 o = elm_layout_edje_get(efl_parent_get(obj));
1945 _part_name_snprintf(pname, sizeof(pname), o, ELM_CALENDAR_CIT_ACCESS_PART_STR, i);
1946 edje_object_freeze(o);
1947 po = (Evas_Object *)edje_object_part_object_get(o, pname);
1948 edje_object_thaw(o);
1949
1950 if (_elm_config->access_mode != ELM_ACCESS_MODE_ON)
1951 pd->part = po;
1952 else
1953 pd->part = evas_object_data_get(po, "_part_access_obj");
1954
1955 _efl_ui_focus_event_redirector(pd->part, obj);
1956
1957 EINA_SAFETY_ON_NULL_RETURN(pd->part);
1958 }
1959
1960 EOLIAN static int
_elm_calendar_item_day_number_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Item_Data * pd)1961 _elm_calendar_item_day_number_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Item_Data *pd)
1962 {
1963 return pd->v;
1964 }
1965
1966 EOLIAN static void
_elm_calendar_item_efl_ui_focus_object_focus_set(Eo * obj,Elm_Calendar_Item_Data * pd,Eina_Bool focus)1967 _elm_calendar_item_efl_ui_focus_object_focus_set(Eo *obj, Elm_Calendar_Item_Data *pd, Eina_Bool focus)
1968 {
1969 efl_ui_focus_object_focus_set(efl_super(obj, ELM_CALENDAR_ITEM_CLASS), focus);
1970
1971 _update_focused_it(efl_parent_get(obj), pd->v);
1972 evas_object_focus_set(pd->part, efl_ui_focus_object_focus_get(obj));
1973 }
1974
1975 EOLIAN static Eina_Rect
_elm_calendar_item_efl_ui_focus_object_focus_geometry_get(const Eo * obj EINA_UNUSED,Elm_Calendar_Item_Data * pd)1976 _elm_calendar_item_efl_ui_focus_object_focus_geometry_get(const Eo *obj EINA_UNUSED, Elm_Calendar_Item_Data *pd)
1977 {
1978 return efl_gfx_entity_geometry_get(pd->part);
1979 }
1980
1981 EOLIAN static Efl_Ui_Focus_Object*
_elm_calendar_item_efl_ui_focus_object_focus_parent_get(const Eo * obj,Elm_Calendar_Item_Data * pd EINA_UNUSED)1982 _elm_calendar_item_efl_ui_focus_object_focus_parent_get(const Eo *obj, Elm_Calendar_Item_Data *pd EINA_UNUSED)
1983 {
1984 return efl_parent_get(obj);
1985 }
1986
1987
1988 #include "elm_calendar_item_eo.c"
1989