/* * 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 the event's day. It's set when a mark is added. /// /// preview public enum CalendarMarkRepeatType { /// /// Default value. Marks will be displayed only on the event day. /// Unique, /// /// Marks will be displayed every day after the event day. /// Daily, /// /// Marks will be displayed every week after the event day. /// Weekly, /// /// Marks will be displayed every month that coincides to the event day. /// Monthly, /// /// Marks will be displayed every year that coincides to the event day. /// Annually, /// /// Marks will be displayed every last day of month after the event day. /// LastDayOfMonth } /// /// Enumeration for the mode, which determines how a user could select a day. /// /// preview 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. /// OnDemand } /// /// Enumeration for defining which fields of a tm struct will be taken into account. /// /// preview [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 an item for marking a Calendar's type, date, and repeat type. /// /// preview public class CalendarMark { internal IntPtr Handle; /// /// A string used to define the type of mark. /// /// preview public string Type; /// /// A time struct to represent the date of inclusion of the mark. /// /// preview public DateTime Date; /// /// Repeats the event following this periodicity. /// /// preview public CalendarMarkRepeatType Repeat; /// /// Creates and initializes a new instance of the CalendarMark class. /// /// Type of mark. /// Date of inclusion of the mark. /// Repeat type. /// preview 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. /// /// preview 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. /// /// preview 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 = (ref Interop.Libc.SystemTime t) => { return _dateFormatDelegate(t); }; } /// /// DateChanged will be triggered when the date in the calendar is changed. /// /// preview public event EventHandler DateChanged; /// /// DisplayedMonthChanged will be triggered when the current month displayed in the calendar is changed. /// /// preview public event EventHandler DisplayedMonthChanged; /// /// This delegate type is used to format the string that will be used to display month and year. /// /// DateTime /// /// preview public delegate string DateFormatDelegate(DateTime time); /// /// Sets or gets the minimum for year. /// /// preview 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. /// /// preview 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 the week, which is used on the calendar. /// /// preview public DateTime DisplayedTime { get { Interop.Elementary.elm_calendar_displayed_time_get(RealHandle, out Interop.Libc.SystemTime 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 the week, which is used on the calendar. /// /// preview 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 name to be displayed by the calendar. /// /// /// The usage should be like this: /// weekDayNames = new List() { "S", "M", "T", "W", "T", "F", "S" };]]> /// Calendar.WeekDayNames = weekDayNames; /// /// preview 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. /// /// /// The selected date changes when the user goes to the next/previous month or selects a day pressing over it on the calendar. /// /// preview 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 a user mouse button /// hold, on the calendar widgets' month/year selection. /// /// preview 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. /// /// preview 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 the fields of a datetime that will be taken into account, when SelectedDate set is invoked. /// /// preview 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 the date format of the string that will be used to display month and year. /// /// preview 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); } } } /// /// Adds 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 day's representation. /// A time struct to represent the date of inclusion of the mark. For marks that repeat, it will just be displayed after the inclusion date in the calendar. /// Repeat the event following this periodicity. Can be a unique mark (that doesn't repeat), daily, weekly, monthly, or annually. /// Item for a calendar mark. /// preview 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; } /// /// Deletes a mark from the calendar. /// /// Item for a calendar mark. /// preview public void DeleteMark(CalendarMark mark) { Interop.Elementary.elm_calendar_mark_del(mark.Handle); } /// /// Draws the calendar marks. /// /// preview public void DrawMarks() { Interop.Elementary.elm_calendar_marks_draw(RealHandle); } /// /// Removes all the calendar's marks. /// /// preview public void ClearMarks() { Interop.Elementary.elm_calendar_marks_clear(RealHandle); } /// /// Creates a widget handle. /// /// Parent EvasObject. /// Handle IntPtr. /// preview 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]); } } } }