[ElmSharp] Modify source file mode (#621)
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / Calendar.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 using System.Runtime.InteropServices;
21
22
23 namespace ElmSharp
24 {
25     /// <summary>
26     /// 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.
27     /// </summary>
28     /// <since_tizen> preview </since_tizen>
29     public enum CalendarMarkRepeatType
30     {
31         /// <summary>
32         /// Default value. Marks will be displayed only on the event day.
33         /// </summary>
34         Unique,
35
36         /// <summary>
37         /// Marks will be displayed every day after the event day.
38         /// </summary>
39         Daily,
40
41         /// <summary>
42         /// Marks will be displayed every week after the event day.
43         /// </summary>
44         Weekly,
45
46         /// <summary>
47         /// Marks will be displayed every month that coincides to the event day.
48         /// </summary>
49         Monthly,
50
51         /// <summary>
52         /// Marks will be displayed every year that coincides to the event day.
53         /// </summary>
54         Annually,
55
56         /// <summary>
57         /// Marks will be displayed every last day of month after the event day.
58         /// </summary>
59         LastDayOfMonth
60     }
61
62     /// <summary>
63     /// Enumeration for the mode, which determines how a user could select a day.
64     /// </summary>
65     /// <since_tizen> preview </since_tizen>
66     public enum CalendarSelectMode
67     {
68         /// <summary>
69         /// Default value. A day is always selected.
70         /// </summary>
71         Default,
72
73         /// <summary>
74         /// A day is always selected.
75         /// </summary>
76         Always,
77
78         /// <summary>
79         /// None of the days can be selected.
80         /// </summary>
81         None,
82
83         /// <summary>
84         /// User may have selected a day.
85         /// </summary>
86         OnDemand
87     }
88
89     /// <summary>
90     /// Enumeration for defining which fields of a tm struct will be taken into account.
91     /// </summary>
92     /// <since_tizen> preview </since_tizen>
93     [Flags]
94     public enum CalendarSelectable
95     {
96         /// <summary>
97         /// None will be taken into account.
98         /// </summary>
99         None = 0,
100         /// <summary>
101         /// Year will be taken into account.
102         /// </summary>
103         Year = 1 << 0,
104         /// <summary>
105         /// Month will be taken into account.
106         /// </summary>
107         Month = 1 << 1,
108         /// <summary>
109         /// Day will be taken into account.
110         /// </summary>
111         Day = 1 << 2
112     }
113
114     /// <summary>
115     /// The CalendarMark is an item for marking a Calendar's type, date, and repeat type.
116     /// </summary>
117     /// <since_tizen> preview </since_tizen>
118     public class CalendarMark
119     {
120         internal IntPtr Handle;
121
122         /// <summary>
123         /// A string used to define the type of mark.
124         /// </summary>
125         /// <since_tizen> preview </since_tizen>
126         public string Type;
127
128         /// <summary>
129         /// A time struct to represent the date of inclusion of the mark.
130         /// </summary>
131         /// <since_tizen> preview </since_tizen>
132         public DateTime Date;
133
134         /// <summary>
135         /// Repeats the event following this periodicity.
136         /// </summary>
137         /// <since_tizen> preview </since_tizen>
138         public CalendarMarkRepeatType Repeat;
139
140         /// <summary>
141         /// Creates and initializes a new instance of the CalendarMark class.
142         /// </summary>
143         /// <param name="type">Type of mark.</param>
144         /// <param name="date">Date of inclusion of the mark.</param>
145         /// <param name="repeat">Repeat type.</param>
146         /// <since_tizen> preview </since_tizen>
147         public CalendarMark(string type, DateTime date, CalendarMarkRepeatType repeat)
148         {
149             Handle = IntPtr.Zero;
150             Type = type;
151             Date = date;
152             Repeat = repeat;
153         }
154     }
155
156     /// <summary>
157     /// The Calendar is a widget that helps applications to flexibly display a calender with day of the week, date, year, and month.
158     /// </summary>
159     /// <since_tizen> preview </since_tizen>
160     public class Calendar : Layout
161     {
162         SmartEvent _changed;
163         DateTime _cacheSelectedDate;
164         SmartEvent _displayedMonthChanged;
165         int _cacheDisplayedMonth;
166
167         Interop.Elementary.Elm_Calendar_Format_Cb _calendarFormat;
168         DateFormatDelegate _dateFormatDelegate = null;
169
170         /// <summary>
171         /// Creates and initializes a new instance of the Calendar class.
172         /// </summary>
173         /// <param name="parent">
174         /// The EvasObject to which the new calendar will be attached as a child.
175         /// </param>
176         /// <since_tizen> preview </since_tizen>
177         public Calendar(EvasObject parent) : base(parent)
178         {
179             _changed = new SmartEvent(this, this.RealHandle, "changed");
180             _changed.On += (sender, e) =>
181             {
182                 DateTime selectedDate = SelectedDate;
183                 DateChanged?.Invoke(this, new DateChangedEventArgs(_cacheSelectedDate, selectedDate));
184                 _cacheSelectedDate = selectedDate;
185             };
186
187             _displayedMonthChanged = new SmartEvent(this, this.RealHandle, "display,changed");
188             _displayedMonthChanged.On += (sender, e) =>
189             {
190                 int currentDisplayedMonth = DisplayedTime.Month;
191                 DisplayedMonthChanged?.Invoke(this, new DisplayedMonthChangedEventArgs(_cacheDisplayedMonth, currentDisplayedMonth));
192                 _cacheDisplayedMonth = currentDisplayedMonth;
193             };
194
195             _calendarFormat = (ref Interop.Libc.SystemTime t) => { return _dateFormatDelegate(t); };
196         }
197
198         /// <summary>
199         /// DateChanged will be triggered when the date in the calendar is changed.
200         /// </summary>
201         /// <since_tizen> preview </since_tizen>
202         public event EventHandler<DateChangedEventArgs> DateChanged;
203
204         /// <summary>
205         /// DisplayedMonthChanged will be triggered when the current month displayed in the calendar is changed.
206         /// </summary>
207         /// <since_tizen> preview </since_tizen>
208         public event EventHandler<DisplayedMonthChangedEventArgs> DisplayedMonthChanged;
209
210         /// <summary>
211         /// This delegate type is used to format the string that will be used to display month and year.
212         /// </summary>
213         /// <param name="time">DateTime</param>
214         /// <returns></returns>
215         /// <since_tizen> preview </since_tizen>
216         public delegate string DateFormatDelegate(DateTime time);
217
218         /// <summary>
219         /// Sets or gets the minimum for year.
220         /// </summary>
221         /// <since_tizen> preview </since_tizen>
222         public int MinimumYear
223         {
224             get
225             {
226                 int minimumYear;
227                 int unused;
228                 Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out minimumYear, out unused);
229                 return minimumYear;
230             }
231             set
232             {
233                 int maximumYear;
234                 int unused;
235                 Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out unused, out maximumYear);
236                 if (maximumYear < 1902)
237                 {
238                     maximumYear = DateTime.MaxValue.Year;
239                 }
240                 Interop.Elementary.elm_calendar_min_max_year_set(RealHandle, value, maximumYear);
241             }
242         }
243
244         /// <summary>
245         /// Sets or gets the maximum for the year.
246         /// </summary>
247         /// <since_tizen> preview </since_tizen>
248         public int MaximumYear
249         {
250             get
251             {
252                 int maximumYear;
253                 int unused;
254                 Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out unused, out maximumYear);
255                 return maximumYear;
256             }
257             set
258             {
259                 int minimumYear;
260                 int unused;
261                 Interop.Elementary.elm_calendar_min_max_year_get(RealHandle, out minimumYear, out unused);
262                 Interop.Elementary.elm_calendar_min_max_year_set(RealHandle, minimumYear, value);
263             }
264         }
265
266         /// <summary>
267         /// Sets or gets the first day of the week, which is used on the calendar.
268         /// </summary>
269         /// <since_tizen> preview </since_tizen>
270         public DateTime DisplayedTime
271         {
272             get
273             {
274                 Interop.Elementary.elm_calendar_displayed_time_get(RealHandle, out Interop.Libc.SystemTime tm);
275                 // TODO
276                 // If the defect is fixed, it will be removed.
277                 var daysInMonth = DateTime.DaysInMonth(tm.tm_year + 1900, tm.tm_mon + 1);
278                 var day = tm.tm_mday;
279
280                 if (day > daysInMonth)
281                 {
282                     day = daysInMonth;
283                 }
284
285                 DateTime date = new DateTime(tm.tm_year + 1900, tm.tm_mon + 1, day, tm.tm_hour, tm.tm_min, tm.tm_sec);
286
287                 return date;
288             }
289         }
290
291         /// <summary>
292         /// Sets or gets the first day of the week, which is used on the calendar.
293         /// </summary>
294         /// <since_tizen> preview </since_tizen>
295         public DayOfWeek FirstDayOfWeek
296         {
297             get
298             {
299                 return (DayOfWeek)Interop.Elementary.elm_calendar_first_day_of_week_get(RealHandle);
300             }
301             set
302             {
303                 Interop.Elementary.elm_calendar_first_day_of_week_set(RealHandle, (int)value);
304             }
305         }
306
307         /// <summary>
308         /// Sets or gets the weekdays name to be displayed by the calendar.
309         /// </summary>
310         /// <remarks>
311         /// The usage should be like this:
312         /// <![CDATA[List<string> weekDayNames = new List<string>() { "S", "M", "T", "W", "T", "F", "S" };]]>
313         /// Calendar.WeekDayNames = weekDayNames;
314         /// </remarks>
315         /// <since_tizen> preview </since_tizen>
316         public IReadOnlyList<string> WeekDayNames
317         {
318             get
319             {
320                 IntPtr stringArrayPtr = Interop.Elementary.elm_calendar_weekdays_names_get(RealHandle);
321                 string[] stringArray;
322                 IntPtrToStringArray(stringArrayPtr, 7, out stringArray);
323                 return stringArray;
324             }
325             set
326             {
327                 if (value != null && value.Count == 7)
328                 {
329                     Interop.Elementary.elm_calendar_weekdays_names_set(RealHandle, value.ToArray());
330                 }
331             }
332         }
333
334         /// <summary>
335         /// Sets or gets the selected date.
336         /// </summary>
337         /// <remarks>
338         /// The selected date changes when the user goes to the next/previous month or selects a day pressing over it on the calendar.
339         /// </remarks>
340         /// <since_tizen> preview </since_tizen>
341         public DateTime SelectedDate
342         {
343             get
344             {
345                 var tm = new Interop.Libc.SystemTime();
346                 Interop.Elementary.elm_calendar_selected_time_get(RealHandle, ref tm);
347                 if (tm.tm_year == 0 && tm.tm_mon == 0 && tm.tm_mday == 0)
348                 {
349                     return DateTime.Now;
350                 }
351                 return tm;
352             }
353             set
354             {
355                 Interop.Libc.SystemTime tm = value;
356                 Interop.Elementary.elm_calendar_selected_time_set(RealHandle, ref tm);
357                 _cacheSelectedDate = value;
358             }
359         }
360
361         /// <summary>
362         /// Sets or gets the interval on time updates for a user mouse button
363         /// hold, on the calendar widgets' month/year selection.
364         /// </summary>
365         /// <since_tizen> preview </since_tizen>
366         public double Interval
367         {
368             get
369             {
370                 return Interop.Elementary.elm_calendar_interval_get(RealHandle);
371             }
372             set
373             {
374                 Interop.Elementary.elm_calendar_interval_set(RealHandle, value);
375             }
376         }
377
378         /// <summary>
379         /// Gets or sets the select day mode used.
380         /// </summary>
381         /// <since_tizen> preview </since_tizen>
382         public CalendarSelectMode SelectMode
383         {
384             get
385             {
386                 return (CalendarSelectMode)Interop.Elementary.elm_calendar_select_mode_get(RealHandle);
387             }
388             set
389             {
390                 Interop.Elementary.elm_calendar_select_mode_set(RealHandle, (Interop.Elementary.Elm_Calendar_Select_Mode)value);
391             }
392         }
393
394         /// <summary>
395         /// Gets or sets the fields of a datetime that will be taken into account, when SelectedDate set is invoked.
396         /// </summary>
397         /// <since_tizen> preview </since_tizen>
398         public CalendarSelectable Selectable
399         {
400             get
401             {
402                 return (CalendarSelectable)Interop.Elementary.elm_calendar_selectable_get(RealHandle);
403             }
404             set
405             {
406                 Interop.Elementary.elm_calendar_selectable_set(RealHandle, (int)value);
407             }
408         }
409
410         /// <summary>
411         /// Gets or sets the date format of the string that will be used to display month and year.
412         /// </summary>
413         /// <since_tizen> preview </since_tizen>
414         public DateFormatDelegate DateFormat
415         {
416             get
417             {
418                 return _dateFormatDelegate;
419             }
420             set
421             {
422                 _dateFormatDelegate = value;
423                 if (value != null)
424                 {
425                     Interop.Elementary.elm_calendar_format_function_set(RealHandle, _calendarFormat);
426                 }
427                 else
428                 {
429                     Interop.Elementary.elm_calendar_format_function_set(RealHandle, null);
430                 }
431             }
432         }
433
434         /// <summary>
435         /// Adds a new mark to the calendar.
436         /// </summary>
437         /// <param name="type">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.</param>
438         /// <param name="date">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.</param>
439         /// <param name="repeat">Repeat the event following this periodicity. Can be a unique mark (that doesn't repeat), daily, weekly, monthly, or annually.</param>
440         /// <returns>Item for a calendar mark.</returns>
441         /// <since_tizen> preview </since_tizen>
442         public CalendarMark AddMark(string type, DateTime date, CalendarMarkRepeatType repeat)
443         {
444             CalendarMark mark = new CalendarMark(type, date, repeat);
445             Interop.Libc.SystemTime tm = date;
446             IntPtr nativeHandle = Interop.Elementary.elm_calendar_mark_add(RealHandle, type, ref tm, (Interop.Elementary.Elm_Calendar_Mark_Repeat_Type)repeat);
447             mark.Handle = nativeHandle;
448
449             return mark;
450         }
451
452         /// <summary>
453         /// Deletes a mark from the calendar.
454         /// </summary>
455         /// <param name="mark">Item for a calendar mark.</param>
456         /// <since_tizen> preview </since_tizen>
457         public void DeleteMark(CalendarMark mark)
458         {
459             Interop.Elementary.elm_calendar_mark_del(mark.Handle);
460         }
461
462         /// <summary>
463         /// Draws the calendar marks.
464         /// </summary>
465         /// <since_tizen> preview </since_tizen>
466         public void DrawMarks()
467         {
468             Interop.Elementary.elm_calendar_marks_draw(RealHandle);
469         }
470
471         /// <summary>
472         /// Removes all the calendar's marks.
473         /// </summary>
474         /// <since_tizen> preview </since_tizen>
475         public void ClearMarks()
476         {
477             Interop.Elementary.elm_calendar_marks_clear(RealHandle);
478         }
479
480         /// <summary>
481         /// Creates a widget handle.
482         /// </summary>
483         /// <param name="parent">Parent EvasObject.</param>
484         /// <returns>Handle IntPtr.</returns>
485         /// <since_tizen> preview </since_tizen>
486         protected override IntPtr CreateHandle(EvasObject parent)
487         {
488             IntPtr handle = Interop.Elementary.elm_layout_add(parent.Handle);
489             Interop.Elementary.elm_layout_theme_set(handle, "layout", "elm_widget", "default");
490
491             RealHandle = Interop.Elementary.elm_calendar_add(handle);
492             Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
493
494             return handle;
495         }
496
497         static void IntPtrToStringArray(IntPtr unmanagedArray, int size, out string[] managedArray)
498         {
499             managedArray = new string[size];
500             IntPtr[] IntPtrArray = new IntPtr[size];
501
502             Marshal.Copy(unmanagedArray, IntPtrArray, 0, size);
503
504             for (int iterator = 0; iterator < size; iterator++)
505             {
506                 managedArray[iterator] = Marshal.PtrToStringAnsi(IntPtrArray[iterator]);
507             }
508         }
509     }
510 }