1 /* Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 using Tizen.NUI.BaseComponents;
18 using System.Collections.Generic;
19 using System.Collections.ObjectModel;
20 using System.ComponentModel;
21 using System.Diagnostics.CodeAnalysis;
22 using System.Globalization;
23 using Tizen.NUI.Binding;
25 namespace Tizen.NUI.Components
28 /// TimeChangedEventArgs is a class to notify changed TimePicker value argument which will sent to user.
30 /// <since_tizen> 9 </since_tizen>
31 public class TimeChangedEventArgs : EventArgs
34 /// TimeChangedEventArgs default constructor.
35 /// <param name="time">time value of TimePicker.</param>
37 [EditorBrowsable(EditorBrowsableState.Never)]
38 public TimeChangedEventArgs(DateTime time)
44 /// TimeChangedEventArgs default constructor.
45 /// <returns>The current time value of TimePicker.</returns>
47 /// <since_tizen> 9 </since_tizen>
48 public DateTime Time { get; }
52 /// TimePicker is a class which provides a function that allows the user to select
53 /// a time through a scrolling motion by expressing the specified value as a list.
54 /// TimePicker expresses the current time using the locale information of the system.
56 /// <since_tizen> 9 </since_tizen>
57 public class TimePicker : Control
62 [EditorBrowsable(EditorBrowsableState.Never)]
63 public static readonly BindableProperty TimeProperty = BindableProperty.Create(nameof(Time), typeof(DateTime), typeof(TimePicker), default(DateTime), propertyChanged: (bindable, oldValue, newValue) =>
65 var instance = (TimePicker)bindable;
68 instance.InternalTime = (DateTime)newValue;
71 defaultValueCreator: (bindable) =>
73 var instance = (TimePicker)bindable;
74 return instance.InternalTime;
78 /// Is24HourViewProperty
80 [EditorBrowsable(EditorBrowsableState.Never)]
81 public static readonly BindableProperty Is24HourViewProperty = BindableProperty.Create(nameof(Is24HourView), typeof(bool), typeof(TimePicker), default(bool), propertyChanged: (bindable, oldValue, newValue) =>
83 var instance = (TimePicker)bindable;
86 instance.InternalIs24HourView = (bool)newValue;
89 defaultValueCreator: (bindable) =>
91 var instance = (TimePicker)bindable;
92 return instance.InternalIs24HourView;
96 private bool is24HourView;
97 private DateTime currentTime;
98 private String[] ampmText;
99 private Picker hourPicker;
100 private Picker minutePicker;
101 private Picker ampmPicker;
104 /// Creates a new instance of TimePicker.
106 /// <since_tizen> 9 </since_tizen>
112 /// Creates a new instance of TimePicker.
114 /// <param name="style">Creates TimePicker by special style defined in UX.</param>
115 /// <since_tizen> 9 </since_tizen>
116 public TimePicker(string style) : base(style)
121 /// Creates a new instance of TimePicker.
123 /// <param name="timePickerStyle">Creates TimePicker by style customized by user.</param>
124 /// <since_tizen> 9 </since_tizen>
125 public TimePicker(TimePickerStyle timePickerStyle) : base(timePickerStyle)
130 /// Dispose TimePicker and all children on it.
132 /// <param name="type">Dispose type.</param>
133 [EditorBrowsable(EditorBrowsableState.Never)]
134 protected override void Dispose(DisposeTypes type)
141 if (type == DisposeTypes.Explicit)
144 Utility.Dispose(hourPicker);
146 Remove(minutePicker);
147 Utility.Dispose(minutePicker);
150 Utility.Dispose(ampmPicker);
158 /// An event emitted when TimePicker value changed, user can subscribe or unsubscribe to this event handler.
160 /// <since_tizen> 9 </since_tizen>
161 public event EventHandler<TimeChangedEventArgs> TimeChanged;
164 /// The hour value of TimePicker.
166 /// <since_tizen> 9 </since_tizen>
171 return (DateTime)GetValue(TimeProperty);
175 SetValue(TimeProperty, value);
176 NotifyPropertyChanged();
179 private DateTime InternalTime
190 if (currentTime.Hour >= 12 && currentTime.Hour <= 23)
193 if (currentTime.Hour == 12) hourPicker.CurrentValue = currentTime.Hour;
194 else hourPicker.CurrentValue = currentTime.Hour - 12;
195 ampmPicker.CurrentValue = 2;
200 if (currentTime.Hour == 0) hourPicker.CurrentValue = 12;
201 else hourPicker.CurrentValue = currentTime.Hour;
202 ampmPicker.CurrentValue = 1;
205 else hourPicker.CurrentValue = currentTime.Hour;
207 minutePicker.CurrentValue = currentTime.Minute;
212 /// The is24hourview value of TimePicker.
214 /// <since_tizen> 9 </since_tizen>
215 public bool Is24HourView
219 return (bool)GetValue(Is24HourViewProperty);
223 SetValue(Is24HourViewProperty, value);
224 NotifyPropertyChanged();
227 private bool InternalIs24HourView
235 if (is24HourView == value) return;
237 Console.WriteLine(" Is 24 Hour View");
238 is24HourView = value;
242 hourPicker.MinValue = 0;
243 hourPicker.MaxValue = 23;
244 hourPicker.CurrentValue = currentTime.Hour;
248 hourPicker.MinValue = 1;
249 hourPicker.MaxValue = 12;
250 PickersOrderSet(true);
252 if (currentTime.Hour > 12)
254 ampmPicker.CurrentValue = 2;
255 hourPicker.CurrentValue = currentTime.Hour - 12;
262 /// Initialize TimePicker object.
264 [EditorBrowsable(EditorBrowsableState.Never)]
265 public override void OnInitialize()
268 SetAccessibilityConstructor(Role.DateEditor);
270 hourPicker = new Picker()
275 hourPicker.ValueChanged += OnHourValueChanged;
277 minutePicker = new Picker()
282 minutePicker.ValueChanged += OnMinuteValueChanged;
284 ampmPicker = new Picker()
289 ampmPicker.ValueChanged += OnAmpmValueChanged;
291 currentTime = DateTime.Now;
292 if (currentTime.Hour > 12)
294 ampmPicker.CurrentValue = 2;
295 hourPicker.CurrentValue = currentTime.Hour - 12;
299 ampmPicker.CurrentValue = 1;
300 hourPicker.CurrentValue = currentTime.Hour;
303 minutePicker.CurrentValue = currentTime.Minute;
309 /// Applies style to TimePicker.
311 /// <param name="viewStyle">The style to apply.</param>
312 [EditorBrowsable(EditorBrowsableState.Never)]
313 public override void ApplyStyle(ViewStyle viewStyle)
315 base.ApplyStyle(viewStyle);
317 var timePickerStyle = viewStyle as TimePickerStyle;
319 if (timePickerStyle == null) return;
322 if (timePickerStyle?.CellPadding != null && Layout != null)
323 ((LinearLayout)Layout).CellPadding = new Size2D(timePickerStyle.CellPadding.Width, timePickerStyle.CellPadding.Height);
325 //Apply Internal Pickers style.
326 if (timePickerStyle?.Pickers != null && hourPicker != null && minutePicker != null && ampmPicker != null)
328 hourPicker.ApplyStyle(timePickerStyle.Pickers);
329 minutePicker.ApplyStyle(timePickerStyle.Pickers);
330 ampmPicker.ApplyStyle(timePickerStyle.Pickers);
334 [SuppressMessage("Microsoft.Reliability",
335 "CA2000:DisposeObjectsBeforeLosingScope",
336 Justification = "The CellPadding will be dispose when the time picker disposed")]
337 private void Initialize()
339 HeightSpecification = LayoutParamPolicies.MatchParent;
341 Layout = new LinearLayout() {
342 LinearOrientation = LinearLayout.Orientation.Horizontal,
344 Console.WriteLine("initialize");
346 is24HourView = false;
348 PickersOrderSet(false);
352 private void ChangeTime(int hour, int minute, bool hourUpdate)
355 currentTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, hour, currentTime.Minute, 0);
357 currentTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, currentTime.Hour, minute, 0);
360 private void OnHourValueChanged(object sender, ValueChangedEventArgs e)
362 if (currentTime.Hour == e.Value) return;
368 if (e.Value == 12) ChangeTime(0, 0, true);
369 else ChangeTime(e.Value, 0, true);
373 if (e.Value == 12) ChangeTime(12, 0, true);
374 else ChangeTime(e.Value + 12, 0, true);
378 ChangeTime(e.Value, 0, true);
383 private void OnMinuteValueChanged(object sender, ValueChangedEventArgs e)
385 if (currentTime.Minute == e.Value) return;
387 ChangeTime(0, e.Value, false);
392 private void OnAmpmValueChanged(object sender, ValueChangedEventArgs e)
394 if ((isAm && e.Value == 1) || (!isAm && e.Value == 2)) return;
398 if (currentTime.Hour == 12) ChangeTime(0, 0, true);
399 else ChangeTime(currentTime.Hour - 12, 0, true);
405 if (currentTime.Hour == 0) ChangeTime(12, 0, true);
406 else ChangeTime(currentTime.Hour + 12, 0, true);
414 private void OnTimeChanged()
416 TimeChangedEventArgs eventArgs = new TimeChangedEventArgs(currentTime);
417 TimeChanged?.Invoke(this, eventArgs);
420 private void PickersOrderSet(bool ampmForceSet)
422 //FIXME: Check the pickers located in already proper position or not.
424 Remove(minutePicker);
427 //Get current system locale's time pattern
428 DateTimeFormatInfo timeFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat;
429 String timePattern = timeFormatInfo.ShortTimePattern;
430 String[] timePatternArray = timePattern.Split(' ', ':');
432 foreach (String format in timePatternArray) {
433 if (format.IndexOf("H") != -1|| format.IndexOf("h") != -1) Add(hourPicker);
434 else if (format.IndexOf("M") != -1 || format.IndexOf("m") != -1) Add(minutePicker);
435 else if (format.IndexOf("t") != -1)
437 is24HourView = false;
438 ampmForceSet = false;
443 if (ampmForceSet) Add(ampmPicker);
446 private void SetAmpmText()
448 //FIXME: There is no localeChanged Event for Component now
449 // AMPM text has to update when system locale changed.
450 CultureInfo info = CultureInfo.CurrentCulture;
451 ampmText = new string[] {info.DateTimeFormat.AMDesignator, info.DateTimeFormat.PMDesignator};
452 ampmPicker.DisplayedValues = new ReadOnlyCollection<string>(ampmText);