using Sarand.Net.Mobile.Maui.Layouts; using Sarand.Net.Mobile.Maui.Views; using Sarand.Net.Standard.Base.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sarand.Net.Mobile.Maui.Controls { //======================================================================= public class SamDatePicker : SamContentView { //------------------------------------------------------------------- // Definitions. //------------------------------------------------------------------- // Data members. private bool allowInvalidDate = false; private bool invalidDate = true; private DateTime previousDate = DateTime.MinValue; private SamStackLayout controlLayout = new SamStackLayout() { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.Fill }; private DatePicker pickerDate = new DatePicker() { IsVisible = false }; private SamEntry entryDate = new SamEntry() { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.Fill }; private SamLabel labelResetDate = new SamLabel() { Text = "X", FontAttributes = FontAttributes.Bold, TextColor = Colors.Red, HorizontalOptions = LayoutOptions.Center, VerticalTextAlignment = TextAlignment.Center }; //------------------------------------------------------------------- // Construction. public SamDatePicker() { // Initialise controls. // Date picker. Hidden but used to display calendar. DefaultFontSize = pickerDate.FontSize; pickerDate.Format = "dd-MMM-yyyy"; pickerDate.DateSelected += PickerDate_DateSelected; // Date display entry. entryDate.FontSize = pickerDate.FontSize; entryDate.FontFamily = pickerDate.FontFamily; entryDate.FontAttributes = pickerDate.FontAttributes; entryDate.TextColor = pickerDate.TextColor; entryDate.Focused += EntryDate_Focused; // 'Reset' date label - to invalidate the date value. labelResetDate.FontSize = pickerDate.FontSize; labelResetDate.FontFamily = pickerDate.FontFamily; // 'Reset' label tap gesture. var tapGestureRecognizer = new TapGestureRecognizer(); tapGestureRecognizer.Tapped += LabelValidDate_Tapped; labelResetDate.GestureRecognizers.Add(tapGestureRecognizer); // Initialise layout. Content = controlLayout; controlLayout.Children.Add(pickerDate); controlLayout.Children.Add(entryDate); controlLayout.Children.Add(labelResetDate); RefreshDateDisplay(); } //------------------------------------------------------------------- // Properties. // Configuration. public Boolean AllowInvalid { get { return allowInvalidDate; } set { if (allowInvalidDate = value) return; allowInvalidDate = value; if (!allowInvalidDate) invalidDate = false; RefreshDateDisplay(); } } public string Format { get { return pickerDate.Format; } set { if (pickerDate.Format.Equals(value)) return; pickerDate.Format = value; } } public DateTime MinimumDate { get { return pickerDate.MinimumDate; } set { pickerDate.MinimumDate = value; } } public DateTime MaximumDate { get { return pickerDate.MaximumDate; } set { pickerDate.MaximumDate = value; } } //------------------------------------------------------------------- // Date value. public DateTime Date { get { if (invalidDate) return DateTime.MinValue; return pickerDate.Date; } set { if (Date.Equals(value)) return; if (!DateUtil.IsValid(value)) { invalidDate = true; pickerDate.Date = DateTime.Today; } else { invalidDate = false; pickerDate.Date = value; } previousDate = value; } } public String FormattedDate { get { return !invalidDate ? DateUtil.Format(Date, pickerDate.Format) : ""; } } //------------------------------------------------------------------- // Font. public double DefaultFontSize { get; } public double FontSize { get { return pickerDate.FontSize; } set { if (pickerDate.FontSize == value) return; pickerDate.FontSize = value; entryDate.FontSize = value; } } public String FontFamily { get { return pickerDate.FontFamily; } set { if (pickerDate.FontFamily == value) return; pickerDate.FontFamily = value; entryDate.FontFamily = value; } } public FontAttributes FontAttributes { get { return pickerDate.FontAttributes; } set { if (pickerDate.FontAttributes == value) return; pickerDate.FontAttributes = value; entryDate.FontAttributes = value; } } public Color TextColor { get { return pickerDate.TextColor; } set { if (pickerDate.TextColor == value) return; pickerDate.TextColor = value; entryDate.TextColor = value; } } //------------------------------------------------------------------- // Utilities. private void RefreshDateDisplay() { if (allowInvalidDate) { pickerDate.IsVisible = false; entryDate.IsVisible = true; labelResetDate.IsVisible = true; } else { pickerDate.IsVisible = true; entryDate.IsVisible = false; labelResetDate.IsVisible = false; } String dateValue = ""; if (!invalidDate) dateValue = DateUtil.Format(Date, pickerDate.Format); entryDate.Text = dateValue; } //------------------------------------------------------------------- // C o n t r o l E v e n t s //------------------------------------------------------------------- private void PickerDate_DateSelected(object? sender, DateChangedEventArgs e) { // Date has changed in control. invalidDate = !DateUtil.IsValid(e.NewDate); RefreshDateDisplay(); if (DateSelected != null) DateSelected.Invoke(sender, e); } public event EventHandler? DateSelected; //------------------------------------------------------------------- private void EntryDate_Focused(object? sender, FocusEventArgs e) { // Control has gained focus. entryDate.Unfocus(); pickerDate.Focus(); invalidDate = false; RefreshDateDisplay(); } //------------------------------------------------------------------- private void LabelValidDate_Tapped(object? sender, EventArgs e) { // 'Valid' label tapped. if (invalidDate) return; invalidDate = true; DateTime oldDate = previousDate; RefreshDateDisplay(); if (DateSelected != null) DateSelected.Invoke(sender, new DateChangedEventArgs(oldDate, Date)); previousDate = Date; } //------------------------------------------------------------------- } //======================================================================= }