[NUI] Fix picker not to use ViewStyle. (#3267)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / DatePicker.cs
1 /* Copyright (c) 2021 Samsung Electronics Co., Ltd.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */
16 using System;
17 using Tizen.NUI;
18 using Tizen.NUI.BaseComponents;
19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.ComponentModel;
22 using System.Globalization;
23 using System.Diagnostics.CodeAnalysis;
24
25 namespace Tizen.NUI.Components
26 {
27     /// <summary>
28     /// DateChangedEventArgs is a class to notify changed DatePicker value argument which will sent to user.
29     /// </summary>
30     [EditorBrowsable(EditorBrowsableState.Never)]
31     public class DateChangedEventArgs : EventArgs
32     {
33         /// <summary>
34         /// DateChangedEventArgs default constructor.
35         /// <param name="date">date value of DatePicker.</param>
36         /// </summary>
37         [EditorBrowsable(EditorBrowsableState.Never)]   
38         public DateChangedEventArgs(DateTime date)
39         {
40             Date = date;
41         }
42
43         /// <summary>
44         /// DateChangedEventArgs default constructor.
45         /// <returns>The current date value of DatePicker.</returns>
46         /// </summary>
47         [EditorBrowsable(EditorBrowsableState.Never)]   
48         public DateTime Date { get; }
49     }
50
51     /// <summary>
52     /// DatePicker is a class which provides a function that allows the user to select 
53     /// a date through a scrolling motion by expressing the specified value as a list.
54     /// DatePicker expresses the current date using the locale information of the system.
55     /// Year range is 1970~2038 (glibc time_t struct min, max value)
56     /// </summary>
57     [EditorBrowsable(EditorBrowsableState.Never)]
58     public class DatePicker : Control
59     {
60         private DateTime currentDate;
61         private Picker dayPicker;
62         private Picker monthPicker;
63         private Picker yearPicker;
64         
65         /// <summary>
66         /// Creates a new instance of DatePicker.
67         /// </summary>
68         [EditorBrowsable(EditorBrowsableState.Never)]
69         public DatePicker()
70         {
71         }
72         
73         /// <summary>
74         /// Creates a new instance of DatePicker.
75         /// </summary>
76         /// <param name="style">Creates DatePicker by special style defined in UX.</param>
77         [EditorBrowsable(EditorBrowsableState.Never)]
78         public DatePicker(string style) : base(style)
79         {
80         }
81
82         /// <summary>
83         /// Creates a new instance of DatePicker.
84         /// </summary>
85         /// <param name="datePickerStyle">Creates DatePicker by style customized by user.</param>
86         [EditorBrowsable(EditorBrowsableState.Never)]
87         public DatePicker(DatePickerStyle datePickerStyle) : base(datePickerStyle)
88         {
89         }
90
91
92         /// <summary>
93         /// Dispose DatePicker and all children on it.
94         /// </summary>
95         /// <param name="type">Dispose type.</param>
96         [EditorBrowsable(EditorBrowsableState.Never)]
97         protected override void Dispose(DisposeTypes type)
98         {
99             if (disposed)
100             {
101                 return;
102             }
103
104             if (type == DisposeTypes.Explicit)
105             {
106                 Remove(monthPicker);
107                 Utility.Dispose(monthPicker);
108                 monthPicker = null;
109                 Remove(dayPicker);
110                 Utility.Dispose(dayPicker);
111                 dayPicker = null;
112                 Remove(yearPicker);
113                 Utility.Dispose(yearPicker);
114                 yearPicker = null;
115             }
116
117             base.Dispose(type);
118         }
119
120         /// <summary>
121         /// An event emitted when DatePicker value changed, user can subscribe or unsubscribe to this event handler.
122         /// </summary>
123         [EditorBrowsable(EditorBrowsableState.Never)]
124         public event EventHandler<DateChangedEventArgs> DateChanged;
125         
126         /// <summary>
127         /// The Date value of DatePicker.
128         /// </summary>
129         [EditorBrowsable(EditorBrowsableState.Never)]
130         public DateTime Date
131         {
132             get
133             {
134                 return currentDate;
135             }
136             set
137             {
138                 currentDate = value;
139                 dayPicker.CurrentValue = currentDate.Day;
140                 monthPicker.CurrentValue = currentDate.Month;
141                 yearPicker.CurrentValue = currentDate.Year;
142             }
143         }
144
145         /// <summary>
146         /// Initialize TimePicker object.
147         /// </summary>
148         [EditorBrowsable(EditorBrowsableState.Never)]
149         public override void OnInitialize()
150         {
151             base.OnInitialize();
152             SetAccessibilityConstructor(Role.DateEditor);
153
154             dayPicker = new Picker()
155             {
156                 MinValue = 1,
157                 MaxValue = 31,
158             };
159             dayPicker.ValueChanged += OnDayValueChanged;
160
161             monthPicker = new Picker()
162             {
163                 MinValue = 1,
164                 MaxValue = 12,
165             };
166             monthPicker.ValueChanged += OnMonthValueChanged;
167
168             yearPicker = new Picker()
169             {
170                 MinValue = 1970,
171                 MaxValue = 2100,
172             };
173             yearPicker.ValueChanged += OnYearValueChanged;
174
175             currentDate = DateTime.Now;
176             dayPicker.CurrentValue = currentDate.Day;
177             monthPicker.CurrentValue = currentDate.Month;
178             yearPicker.CurrentValue = currentDate.Year;
179
180             Initialize();
181         }
182
183         /// <inheritdoc/>
184         [EditorBrowsable(EditorBrowsableState.Never)]
185         [SuppressMessage("Microsoft.Reliability",
186                          "CA2000:DisposeObjectsBeforeLosingScope",
187                          Justification = "The CellPadding will be dispose when the date picker disposed")]
188         public override void ApplyStyle(ViewStyle viewStyle)
189         {
190             base.ApplyStyle(viewStyle);
191
192             if (viewStyle is DatePickerStyle datePickerStyle && Layout is LinearLayout linearLayout)
193             {
194                 linearLayout.CellPadding = new Size(datePickerStyle.CellPadding.Width, datePickerStyle.CellPadding.Height);
195
196                 yearPicker.ApplyStyle(datePickerStyle.Pickers);
197                 monthPicker.ApplyStyle(datePickerStyle.Pickers);
198                 dayPicker.ApplyStyle(datePickerStyle.Pickers);
199             }
200         }
201
202         private void Initialize()
203         {
204             HeightSpecification = LayoutParamPolicies.MatchParent;
205
206             Layout = new LinearLayout() { 
207                 LinearOrientation = LinearLayout.Orientation.Horizontal,
208             };
209
210             PickersOrderSet();
211             SetMonthText();
212             MaxDaySet(currentDate.Month);
213         }
214
215         private void OnDayValueChanged(object sender, ValueChangedEventArgs e)
216         {
217             if (currentDate.Day == e.Value) return;
218
219             currentDate = new DateTime(currentDate.Year, currentDate.Month, e.Value);
220             
221             OnDateChanged();
222         }
223
224         private void OnMonthValueChanged(object sender, ValueChangedEventArgs e)
225         { 
226             if (currentDate.Month == e.Value) return;
227
228             MaxDaySet(e.Value);
229
230             OnDateChanged();
231         }
232
233         private void OnYearValueChanged(object sender, ValueChangedEventArgs e)
234         { 
235             if (currentDate.Year == e.Value) return;
236
237             currentDate = new DateTime(e.Value, currentDate.Month, currentDate.Day);
238
239             OnDateChanged();
240         }
241
242         private void OnDateChanged()
243         { 
244             DateChangedEventArgs eventArgs = new DateChangedEventArgs(currentDate);
245             DateChanged?.Invoke(this, eventArgs);
246         }
247
248         private void MaxDaySet(int month)
249         {
250             int maxDaysInMonth = DateTime.DaysInMonth(currentDate.Year, month);
251             dayPicker.MaxValue = maxDaysInMonth;
252             if (currentDate.Day > maxDaysInMonth)
253             {
254                 currentDate = new DateTime(currentDate.Year, month, maxDaysInMonth);
255                 dayPicker.CurrentValue = maxDaysInMonth;
256                 return;
257             }
258             currentDate = new DateTime(currentDate.Year, month, currentDate.Day);
259         }
260
261         //FIXME: There is no way to know when system locale changed in NUI.
262         //       Pickers order and Month text has to be follow system locale.
263         private void PickersOrderSet()
264         {           
265             String locale = Environment.GetEnvironmentVariable("LC_TIME");
266             DateTimeFormatInfo DateFormat = new CultureInfo(locale, false ).DateTimeFormat;
267             String temp = DateFormat.ShortDatePattern;
268             String[] strArray = temp.Split(' ', '/');
269             foreach (String format in strArray) {
270                 if (format.IndexOf("M") != -1|| format.IndexOf("m") != -1)  Add(monthPicker);
271                 else if (format.IndexOf("d") != -1 || format.IndexOf("D") != -1) Add(dayPicker);
272                 else if (format.IndexOf("y") != -1 || format.IndexOf("Y") != -1) Add(yearPicker);
273             }
274         }
275
276         private void SetMonthText()
277         {
278             String locale = Environment.GetEnvironmentVariable("LC_TIME");
279             CultureInfo info = new CultureInfo(locale);
280             monthPicker.DisplayedValues = new ReadOnlyCollection<string>(info.DateTimeFormat.AbbreviatedMonthNames);
281         }
282     }
283 }