/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; namespace ElmSharp { /// /// Enumeration for event periodicity, used to define if a mark should be repeated beyond event's day. It's set when a mark is added. /// public enum CalendarMarkRepeatType { /// /// Default value. Marks will be displayed only on event day. /// Unique, /// /// Marks will be displayed every day after event day. /// Daily, /// /// Marks will be displayed every week after event day. /// Weekly, /// /// Marks will be displayed every month day that coincides to event day. /// Monthly, /// /// Marks will be displayed every year that coincides to event day. /// Annually, /// /// Marks will be displayed every last day of month after event day. /// LastDayOfMonth } /// /// Enumeration for the mode, which determine how user could select a day. /// public enum CalendarSelectMode { /// /// Default value. a day is always selected. /// Default, /// /// A day is always selected. /// Always, /// /// None of the days can be selected. /// None, /// /// User may have selected a day or not. /// OnDemand } /// /// Enumeration used to define which fields of a tm struct will be taken into account /// [Flags] public enum CalendarSelectable { /// /// None will be taken into account /// None = 0, /// /// Year will be taken into account /// Year = 1 << 0, /// /// Month will be taken into account /// Month = 1 << 1, /// /// Day will be taken into account /// Day = 1 << 2 } /// /// The CalendarMark is a Item for marking a Calendar's type,date and repeat type. /// public class CalendarMark { internal IntPtr Handle; /// /// A string used to define the type of mark. /// public string Type; /// /// A time struct to represent the date of inclusion of the mark. /// public DateTime Date; /// /// Repeat the event following this periodicity. /// public CalendarMarkRepeatType Repeat; /// /// Creates and initializes a new instance of the CalendarMark class. /// /// Type of mark /// Date of inclusion of the mark /// Repeat type public CalendarMark(string type, DateTime date, CalendarMarkRepeatType repeat) { Handle = IntPtr.Zero; Type = type; Date = date; Repeat = repeat; } } /// /// The Calendar is a widget that helps applications to flexibly display a calender with day of the week, date, year and month. /// public class Calendar : Layout { SmartEvent _changed; DateTime _cacheSelectedDate; SmartEvent _displayedMonthChanged; int _cacheDisplayedMonth; Interop.Elementary.Elm_Calendar_Format_Cb _calendarFormat; DateFormatDelegate _dateFormatDelegate = null; /// /// Creates and initializes a new instance of the Calendar class. /// /// /// The EvasObject to which the new Calendar will be attached as a child. /// public Calendar(EvasObject parent) : base(parent) { _changed = new SmartEvent(this, this.RealHandle, "changed"); _changed.On += (sender, e) => { DateTime selectedDate = SelectedDate; DateChanged?.Invoke(this, new DateChangedEventArgs(_cacheSelectedDate, selectedDate)); _cacheSelectedDate = selectedDate; }; _displayedMonthChanged = new SmartEvent(this, this.RealHandle, "display,changed"); _displayedMonthChanged.On += (sender, e) => { int currentDisplayedMonth = DisplayedTime.Month; DisplayedMonthChanged?.Invoke(this, new DisplayedMonthChangedEventArgs(_cacheDisplayedMonth, currentDisplayedMonth)); _cacheDisplayedMonth = currentDisplayedMonth; }; _calendarFormat = (t) => { return _dateFormatDelegate(t); }; } /// /// DateChanged will be triggered when the date in the calendar is changed. /// public event EventHandler DateChanged; /// /// DisplayedMonthChanged will be triggered when the current month displayed in the calendar is changed. /// public event EventHandler DisplayedMonthChanged; /// /// This delegate type is used to format the string that will be used to display month and year. /// /// DateTime /// public delegate string DateFormatDelegate(DateTime time); /// /// Sets or gets the minimum for year. /// public int MinimumYear { get { int minimumYear; int unused; Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out minimumYear, out unused); return minimumYear; } set { int maximumYear; int unused; Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out unused, out maximumYear); if (maximumYear < 1902) { maximumYear = DateTime.MaxValue.Year; } Interop.Elementary.elm_calendar_min_max_year_set(RealHandle, value, maximumYear); } } /// /// Sets or gets the maximum for the year. /// public int MaximumYear { get { int maximumYear; int unused; Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out unused, out maximumYear); return maximumYear; } set { int minimumYear; int unused; Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out minimumYear, out unused); Interop.Elementary.elm_calendar_min_max_year_set(RealHandle, minimumYear, value); } } /// /// Sets or gets the first day of week, who are used on Calendar. /// public DateTime DisplayedTime { get { var tm = new Interop.Libc.SystemTime(); Interop.Elementary.elm_calendar_displayed_time_get(RealHandle, out tm); ///TODO ///If the defect is fixed, it will be removed. var daysInMonth = DateTime.DaysInMonth(tm.tm_year + 1900, tm.tm_mon + 1); var day = tm.tm_mday; if (day > daysInMonth) { day = daysInMonth; } DateTime date = new DateTime(tm.tm_year + 1900, tm.tm_mon + 1, day, tm.tm_hour, tm.tm_min, tm.tm_sec); return date; } } /// /// Sets or gets the first day of week, who are used on Calendar. /// public DayOfWeek FirstDayOfWeek { get { return (DayOfWeek)Interop.Elementary.elm_calendar_first_day_of_week_get(RealHandle); } set { Interop.Elementary.elm_calendar_first_day_of_week_set(RealHandle, (int)value); } } /// /// Sets or gets the weekdays names to be displayed by the Calendar. /// /// /// The usage should be like this; /// List weekDayNames = new List() { "S", "M", "T", "W", "T", "F", "S" }; /// Calendar.WeekDayNames = weekDayNames; /// public IReadOnlyList WeekDayNames { get { IntPtr stringArrayPtr = Interop.Elementary.elm_calendar_weekdays_names_get(RealHandle); string[] stringArray; IntPtrToStringArray(stringArrayPtr, 7, out stringArray); return stringArray; } set { if (value != null && value.Count == 7) { Interop.Elementary.elm_calendar_weekdays_names_set(RealHandle, value.ToArray()); } } } /// /// Sets or gets the selected date. /// /// /// Selected date changes when the user goes to next/previous month or select a day pressing over it on calendar. /// public DateTime SelectedDate { get { var tm = new Interop.Libc.SystemTime(); Interop.Elementary.elm_calendar_selected_time_get(RealHandle, ref tm); if (tm.tm_year == 0 && tm.tm_mon == 0 && tm.tm_mday == 0) { return DateTime.Now; } return tm; } set { Interop.Libc.SystemTime tm = value; Interop.Elementary.elm_calendar_selected_time_set(RealHandle, ref tm); _cacheSelectedDate = value; } } /// /// Sets or gets the interval on time updates for an user mouse button /// hold on calendar widgets' month/year selection. /// public double Interval { get { return Interop.Elementary.elm_calendar_interval_get(RealHandle); } set { Interop.Elementary.elm_calendar_interval_set(RealHandle, value); } } /// /// Gets or sets the select day mode used. /// public CalendarSelectMode SelectMode { get { return (CalendarSelectMode)Interop.Elementary.elm_calendar_select_mode_get(RealHandle); } set { Interop.Elementary.elm_calendar_select_mode_set(RealHandle, (Interop.Elementary.Elm_Calendar_Select_Mode)value); } } /// /// Gets or sets fields of a datetime will be taken into account, when SelectedDate set is invoked. /// public CalendarSelectable Selectable { get { return (CalendarSelectable)Interop.Elementary.elm_calendar_selectable_get(RealHandle); } set { Interop.Elementary.elm_calendar_selectable_set(RealHandle, (int)value); } } /// /// Gets or sets date format the string that will be used to display month and year. /// By default it uses strftime with "%B %Y" format string. /// It should allocate the memory that will be used by the string, that will be freed by the widget after usage.A pointer to the string and a pointer to the time struct will be provided. /// public DateFormatDelegate DateFormat { get { return _dateFormatDelegate; } set { _dateFormatDelegate = value; if (value != null) { Interop.Elementary.elm_calendar_format_function_set(RealHandle, _calendarFormat); } else { Interop.Elementary.elm_calendar_format_function_set(RealHandle, null); } } } /// /// Add a new mark to the calendar. /// /// A string used to define the type of mark. It will be emitted to the theme, that should display a related modification on these days representation. /// A time struct to represent the date of inclusion of the mark. For marks that repeats it will just be displayed after the inclusion date in the calendar. /// Repeat the event following this periodicity. Can be a unique mark (that don't repeat), daily, weekly, monthly or annually. /// Item for a calendar mark. public CalendarMark AddMark(string type, DateTime date, CalendarMarkRepeatType repeat) { CalendarMark mark = new CalendarMark(type, date, repeat); Interop.Libc.SystemTime tm = date; IntPtr nativeHandle = Interop.Elementary.elm_calendar_mark_add(RealHandle, type, ref tm, (Interop.Elementary.Elm_Calendar_Mark_Repeat_Type)repeat); mark.Handle = nativeHandle; return mark; } /// /// Delete mark from the calendar. /// /// Item for a calendar mark public void DeleteMark(CalendarMark mark) { Interop.Elementary.elm_calendar_mark_del(mark.Handle); } /// /// Draw calendar marks. /// public void DrawMarks() { Interop.Elementary.elm_calendar_marks_draw(RealHandle); } /// /// Remove all calendar's marks. /// public void ClearMarks() { Interop.Elementary.elm_calendar_marks_clear(RealHandle); } protected override IntPtr CreateHandle(EvasObject parent) { IntPtr handle = Interop.Elementary.elm_layout_add(parent.Handle); Interop.Elementary.elm_layout_theme_set(handle, "layout", "elm_widget", "default"); RealHandle = Interop.Elementary.elm_calendar_add(handle); Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle); return handle; } static void IntPtrToStringArray(IntPtr unmanagedArray, int size, out string[] managedArray) { managedArray = new string[size]; IntPtr[] IntPtrArray = new IntPtr[size]; Marshal.Copy(unmanagedArray, IntPtrArray, 0, size); for (int iterator = 0; iterator < size; iterator++) { managedArray[iterator] = Marshal.PtrToStringAnsi(IntPtrArray[iterator]); } } } }