diff options
author | Jose Medrano <josmed@microsoft.com> | 2019-03-20 22:08:29 +0300 |
---|---|---|
committer | Eric Maupin <me@ermau.com> | 2019-03-20 22:08:29 +0300 |
commit | 7ab2544bc2f913f0e422c97b0915075990de17f7 (patch) | |
tree | 33170f973fbd3bbf38360f59c59b46c5955cae1f | |
parent | 0fa606c1688a86119d1b147cc1c9493b56f26940 (diff) |
[Mac] Adds implementation to handle DateTime fields (#480)
9 files changed, 137 insertions, 0 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/SpinnerButton.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/SpinnerButton.cs index fcefa67..8f766e9 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/SpinnerButton.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/SpinnerButton.cs @@ -1,5 +1,6 @@ using System; using AppKit; +using CoreGraphics; using ObjCRuntime; namespace Xamarin.PropertyEditing.Mac @@ -7,6 +8,16 @@ namespace Xamarin.PropertyEditing.Mac internal class SpinnerButton : UnfocusableButton { + public bool AcceptsUserInteraction { get; set; } = true; + + public override NSView HitTest (CGPoint aPoint) + { + if (!AcceptsUserInteraction) { + return null; + } + return this; + } + public SpinnerButton (IHostResourceProvider hostResource, bool isUp) { if (hostResource == null) diff --git a/Xamarin.PropertyEditing.Mac/Controls/DateExtensions.cs b/Xamarin.PropertyEditing.Mac/Controls/DateExtensions.cs new file mode 100644 index 0000000..150cc57 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/DateExtensions.cs @@ -0,0 +1,43 @@ +using System; +using Foundation; + +namespace Xamarin.PropertyEditing.Mac +{ + internal static class DateExtensions + { + /// <summary>The NSDate from Xamarin takes a reference point form January 1, 2001, at 12:00</summary> + /// <remarks> + /// It also has calls for NIX reference point 1970 but appears to be problematic + /// </remarks> + private static DateTime _nsRef = new DateTime (2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Local); // last zero is millisecond + + /// <summary>Returns the seconds interval for a DateTime from NSDate reference data of January 1, 2001</summary> + /// <param name="dt">The DateTime to evaluate</param> + /// <returns>The seconds since NSDate reference date</returns> + public static double SecondsSinceNsRefenceDate (this DateTime dt) + { + return (dt - _nsRef).TotalSeconds; + } + + /// <summary>Convert a DateTime to NSDate</summary> + /// <param name="dt">The DateTime to convert</param> + /// <returns>An NSDate</returns> + public static NSDate ToNSDate (this DateTime dt) + { + return NSDate.FromTimeIntervalSinceReferenceDate (dt.SecondsSinceNsRefenceDate ()); + } + + /// <summary>Convert an NSDate to DateTime</summary> + /// <param name="nsDate">The NSDate to convert</param> + /// <returns>A DateTime</returns> + public static DateTime ToDateTime (this NSDate nsDate) + { + try { + // We loose granularity below millisecond range but that is probably ok + return _nsRef.AddSeconds (nsDate.SecondsSinceReferenceDate); + } catch (ArgumentOutOfRangeException) { + return _nsRef; + } + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/DateTimeEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/DateTimeEditorControl.cs new file mode 100644 index 0000000..d25bc88 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/DateTimeEditorControl.cs @@ -0,0 +1,66 @@ +using System; +using AppKit; +using Xamarin.PropertyEditing.Mac.Resources; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{
+ internal class DateTimeEditorControl : PropertyEditorControl<PropertyViewModel<DateTime>> + {
+ private readonly NSDatePicker datePicker;
+ + public DateTimeEditorControl (IHostResourceProvider hostResources)
+ : base (hostResources) + {
+ this.datePicker = new NSDatePicker {
+ ControlSize = NSControlSize.Small,
+ DatePickerElements = NSDatePickerElementFlags.HourMinuteSecond | NSDatePickerElementFlags.YearMonthDateDay,
+ DatePickerStyle = NSDatePickerStyle.TextFieldAndStepper,
+ Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Small)),
+ TranslatesAutoresizingMaskIntoConstraints = false
+ }; + + // update the value on keypress + this.datePicker.Activated += Editor_Activated;
+
+ AddSubview (this.datePicker);
+ + AddConstraints (new[] { + NSLayoutConstraint.Create (this.datePicker, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0f), + NSLayoutConstraint.Create (this.datePicker, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, this, NSLayoutAttribute.Leading, 1f, 0f), + NSLayoutConstraint.Create (this.datePicker, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1f, 0),
+ NSLayoutConstraint.Create (this.datePicker, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1f, -6f),
+ }); + } +
+ private void Editor_Activated (object sender, EventArgs e) + { + ViewModel.Value = this.datePicker.DateValue.ToDateTime (); + } + + public override NSView FirstKeyView => this.datePicker; + public override NSView LastKeyView => this.datePicker;
+
+ protected override void UpdateValue () + {
+ this.datePicker.DateValue = ViewModel.Value.ToNSDate (); + } + + protected override void SetEnabled () + { + this.datePicker.Enabled = ViewModel.Property.CanWrite; + } + + protected override void UpdateAccessibilityValues () + { + this.datePicker.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityDateTime, ViewModel.Property.Name);
+ this.datePicker.Enabled = this.datePicker.Enabled; + }
+
+ protected override void Dispose (bool disposing) + {
+ this.datePicker.Activated -= Editor_Activated;
+ base.Dispose (disposing); + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs b/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs index 80f1f57..34cc51c 100644 --- a/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs +++ b/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs @@ -39,6 +39,7 @@ namespace Xamarin.PropertyEditing.Mac } private static readonly Dictionary<Type, Type> ViewModelTypes = new Dictionary<Type, Type> { + {typeof (PropertyViewModel<DateTime>), typeof (DateTimeEditorControl)}, {typeof (StringPropertyViewModel), typeof (StringEditorControl)}, {typeof (NumericPropertyViewModel<>), typeof (NumericEditorControl<>)}, {typeof (PropertyViewModel<bool?>), typeof (BooleanEditorControl)}, diff --git a/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.Designer.cs b/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.Designer.cs index 5589461..de42d93 100644 --- a/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.Designer.cs +++ b/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.Designer.cs @@ -119,6 +119,12 @@ namespace Xamarin.PropertyEditing.Mac.Resources { } } + internal static string AccessibilityDateTime { + get { + return ResourceManager.GetString("AccessibilityDateTime", resourceCulture); + } + } + internal static string AccessibilityXEditor { get { return ResourceManager.GetString("AccessibilityXEditor", resourceCulture); diff --git a/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.resx b/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.resx index 7fc761a..8d90192 100644 --- a/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.resx +++ b/Xamarin.PropertyEditing.Mac/Resources/LocalizationResources.resx @@ -56,6 +56,10 @@ <value>{0} String Editor</value> <comment>Editor for String Value</comment> </data> + <data name="AccessibilityDateTime" xml:space="preserve"> + <value>{0} DateTime Editor</value> + <comment>Editor for DateTime Value</comment> + </data> <data name="AccessibilityXEditor" xml:space="preserve"> <value>{0} X Editor</value> <comment>Editor for X Value</comment> diff --git a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj index a9da32b..d39da81 100644 --- a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj +++ b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj @@ -162,6 +162,8 @@ <Compile Include="Controls\FilePathEditorControl.cs" />
<Compile Include="Controls\Custom\TextFieldSmallButtonContainer.cs" />
<Compile Include="Controls\BasePathEditorControl.cs" />
+ <Compile Include="Controls\DateTimeEditorControl.cs" />
+ <Compile Include="Controls\DateExtensions.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controls\" />
diff --git a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs index 0939d88..cb7886e 100644 --- a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs +++ b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs @@ -84,8 +84,11 @@ namespace Xamarin.PropertyEditing.Tests.MockControls valueSources: ValueSources.Default | ValueSources.Local | ValueSources.Resource); AddProperty<CommonColor> (this.colorPropertyInfo); + AddProperty<FilePath> ("FilePath", ReadWrite, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding); AddReadOnlyProperty<FilePath> ("ReadOnlyFilePath", ReadOnly); + AddProperty<DateTime> ("DateTime", ReadWrite, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding); + AddReadOnlyProperty<DateTime> ("ReadDateTime", ReadOnly); AddEvents ("Click", "Hover", "Focus"); diff --git a/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs b/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs index 794e2a2..c2e9fe9 100644 --- a/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs +++ b/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs @@ -598,6 +598,7 @@ namespace Xamarin.PropertyEditing.ViewModels } = new AsyncWorkQueue(); private static readonly Dictionary<Type, Func<TargetPlatform, IPropertyInfo, IEnumerable<IObjectEditor>, PropertyVariation, PropertyViewModel>> ViewModelMap = new Dictionary<Type, Func<TargetPlatform, IPropertyInfo, IEnumerable<IObjectEditor>, PropertyVariation, PropertyViewModel>> { + { typeof(DateTime), (tp,p,e,v) => new PropertyViewModel<DateTime> (tp, p, e, v) }, { typeof(string), (tp,p,e,v) => new StringPropertyViewModel (tp, p, e, v) }, { typeof(bool), (tp,p,e,v) => new PropertyViewModel<bool?> (tp, p, e, v) }, { typeof(float), (tp,p,e,v) => new NumericPropertyViewModel<float?> (tp, p, e, v) }, |