diff options
author | Dominique Louis <savagesoftware@gmail.com> | 2019-03-27 14:59:29 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-27 14:59:29 +0300 |
commit | 187cc8fa6d484cb653df5a9782fdf2d89a265299 (patch) | |
tree | 2c4ba480bdd083153152581bf1ac0ccb80bd9a00 /Xamarin.PropertyEditing.Mac/Controls | |
parent | 01d336ed9e99034d8b27b9f80d8e7f8059cf44b6 (diff) | |
parent | 90383f96ded1ad04484f203b912524b88e33df6b (diff) |
Merge pull request #573 from xamarin/ermau-timespan-editor
[mac] Refactor & Add TimeSpan / Char editors
Diffstat (limited to 'Xamarin.PropertyEditing.Mac/Controls')
4 files changed, 242 insertions, 41 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/CharEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/CharEditorControl.cs new file mode 100644 index 0000000..075a9e3 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/CharEditorControl.cs @@ -0,0 +1,50 @@ +using System; +using Xamarin.PropertyEditing.Mac.Resources; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + internal class CharEditorControl + : EntryPropertyEditor<char> + { + public CharEditorControl (IHostResourceProvider hostResources) + : base (hostResources) + { + } + + protected override EntryPropertyEditorDelegate<char> CreateDelegate (PropertyViewModel<char> viewModel) + { + return new CharDelegate (viewModel); + } + + protected override void UpdateAccessibilityValues () + { + base.UpdateAccessibilityValues (); + Entry.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityChar, ViewModel.Property.Name); + } + + protected override string GetValue (char value) + { + return (value == default (char)) ? null : value.ToString(); + } + + private class CharDelegate + : EntryPropertyEditorDelegate<char> + { + public CharDelegate (PropertyViewModel<char> viewModel) + : base (viewModel) + { + } + + protected override char GetValue (string value) + { + return (String.IsNullOrEmpty (value) ? default (char) : value[0]); + } + + protected override bool CanGetValue (string value) + { + return Char.TryParse (value, out _); + } + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/EntryPropertyEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/EntryPropertyEditor.cs new file mode 100644 index 0000000..f1d92ac --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/EntryPropertyEditor.cs @@ -0,0 +1,128 @@ +using System; +using AppKit; +using Foundation; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + internal abstract class EntryPropertyEditor<T> + : PropertyEditorControl<PropertyViewModel<T>> + { + public EntryPropertyEditor (IHostResourceProvider hostResources) + : base (hostResources) + { + Entry = new PropertyTextField { + BackgroundColor = NSColor.Clear, + ControlSize = NSControlSize.Small, + Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Small)), + TranslatesAutoresizingMaskIntoConstraints = false, + }; + AddSubview (Entry); + + RightEdgeConstraint = NSLayoutConstraint.Create (Entry, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0); + AddConstraints (new[] { + NSLayoutConstraint.Create (Entry, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0), + NSLayoutConstraint.Create (Entry, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 0), + RightEdgeConstraint, + NSLayoutConstraint.Create (Entry, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1, -6), + }); + } + + public override NSView FirstKeyView => Entry; + public override NSView LastKeyView => Entry; + + protected PropertyTextField Entry + { + get; + } + + protected NSLayoutConstraint RightEdgeConstraint { get; } + + protected override void OnViewModelChanged (PropertyViewModel oldModel) + { + base.OnViewModelChanged (oldModel); + Entry.Delegate = (ViewModel != null) ? CreateDelegate (ViewModel) : null; + } + + protected override void UpdateValue () + { + Entry.StringValue = GetValue (ViewModel.Value) ?? String.Empty; + } + + protected override void SetEnabled () + { + Entry.Enabled = ViewModel.Property.CanWrite; + } + + protected override void UpdateAccessibilityValues () + { + Entry.AccessibilityEnabled = Entry.Enabled; + } + + protected virtual EntryPropertyEditorDelegate<T> CreateDelegate (PropertyViewModel<T> viewModel) + { + return new EntryPropertyEditorDelegate<T> (viewModel); + } + + protected virtual string GetValue (T value) + { + return value?.ToString (); + } + } + + internal class EntryPropertyEditorDelegate<T> + : NSTextFieldDelegate + { + public EntryPropertyEditorDelegate (PropertyViewModel<T> viewModel) + { + if (viewModel == null) + throw new ArgumentNullException (nameof (viewModel)); + + ViewModel = viewModel; + } + + protected PropertyViewModel<T> ViewModel + { + get; + } + + public override void EditingBegan (NSNotification notification) + { + NSTextField text = (NSTextField)notification.Object; + this.lastValid = text.StringValue; + } + + public override void EditingEnded (NSNotification notification) + { + var text = (NSTextField)notification.Object; + ViewModel.Value = GetValue (text.StringValue); + } + + public override bool TextShouldEndEditing (NSControl control, NSText fieldEditor) + { + if (!CanGetValue (fieldEditor.Value)) { + NSTextField text = (NSTextField)control; + text.StringValue = this.lastValid; + AppKitFramework.NSBeep (); + return false; + } + + return true; + } + + protected virtual T GetValue (string value) + { + if (String.IsNullOrEmpty (value)) + return default (T); + + return (T)Convert.ChangeType (value, typeof(T)); + } + + protected virtual bool CanGetValue (string value) + { + return true; + } + + private string lastValid; + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs index 0b2933a..7696f79 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs @@ -10,46 +10,24 @@ using Xamarin.PropertyEditing.ViewModels; namespace Xamarin.PropertyEditing.Mac { internal class StringEditorControl - : PropertyEditorControl<PropertyViewModel<string>> + : EntryPropertyEditor<string> { - public override NSView FirstKeyView => this.stringEditor; - private NSView lastKeyView; - public override NSView LastKeyView => this.lastKeyView; - public StringEditorControl (IHostResourceProvider hostResources) : base (hostResources) { - this.stringEditor = new PropertyTextField { - BackgroundColor = NSColor.Clear, - ControlSize = NSControlSize.Small, - Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Small)), - StringValue = string.Empty, - TranslatesAutoresizingMaskIntoConstraints = false, - }; - - // update the value on keypress - this.stringEditor.Changed += (sender, e) => { - ViewModel.Value = this.stringEditor.StringValue; - }; - AddSubview (this.stringEditor); - - this.lastKeyView = this.stringEditor; - this.editorRightConstraint = NSLayoutConstraint.Create (this.stringEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0); - - this.AddConstraints (new[] { - NSLayoutConstraint.Create (this.stringEditor, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0), - NSLayoutConstraint.Create (this.stringEditor, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 0), - this.editorRightConstraint, - NSLayoutConstraint.Create (this.stringEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1, -6), - }); + this.lastKeyView = Entry; } + public override NSView LastKeyView => this.lastKeyView; + protected override void UpdateValue () { - this.stringEditor.StringValue = ViewModel.Value ?? string.Empty; - this.stringEditor.Enabled = CanEnable; + base.UpdateValue (); + if (this.inputModePopup != null) this.inputModePopup.SelectItem ((ViewModel.InputMode == null) ? string.Empty : ViewModel.InputMode.Identifier); + + SetEnabled (); } protected override void OnViewModelChanged (PropertyViewModel oldModel) @@ -59,7 +37,7 @@ namespace Xamarin.PropertyEditing.Mac if (ViewModel == null) return; - this.editorRightConstraint.Active = !ViewModel.HasInputModes; + RightEdgeConstraint.Active = !ViewModel.HasInputModes; if (ViewModel.HasInputModes) { if (this.inputModePopup == null) { this.inputModePopup = new FocusablePopUpButton { @@ -76,14 +54,14 @@ namespace Xamarin.PropertyEditing.Mac AddSubview (this.inputModePopup); - this.editorInputModeConstraint = NSLayoutConstraint.Create (this.stringEditor, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this.inputModePopup, NSLayoutAttribute.Left, 1, -4); + this.editorInputModeConstraint = NSLayoutConstraint.Create (Entry, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this.inputModePopup, NSLayoutAttribute.Left, 1, -4); AddConstraints (new[] { this.editorInputModeConstraint, NSLayoutConstraint.Create (this.inputModePopup, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0f), NSLayoutConstraint.Create (this.inputModePopup, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0), NSLayoutConstraint.Create (this.inputModePopup, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1f, 80f), - NSLayoutConstraint.Create (this.inputModePopup, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this.stringEditor, NSLayoutAttribute.Height, 1, 0), + NSLayoutConstraint.Create (this.inputModePopup, NSLayoutAttribute.Height, NSLayoutRelation.Equal, Entry, NSLayoutAttribute.Height, 1, 0), }); this.lastKeyView = this.inputModePopup; @@ -107,27 +85,27 @@ namespace Xamarin.PropertyEditing.Mac protected override void SetEnabled () { - this.stringEditor.Enabled = CanEnable; + Entry.Enabled = ViewModel.Property.CanWrite && (((ViewModel.InputMode != null) && !ViewModel.InputMode.IsSingleValue) || (this.inputModePopup == null)); + if (this.inputModePopup != null) this.inputModePopup.Enabled = ViewModel.Property.CanWrite; } protected override void UpdateAccessibilityValues () { - this.stringEditor.AccessibilityEnabled = this.stringEditor.Enabled; - this.stringEditor.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityString, ViewModel.Property.Name); + base.UpdateAccessibilityValues (); + Entry.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityString, ViewModel.Property.Name); + if (this.inputModePopup != null) { this.inputModePopup.AccessibilityEnabled = this.inputModePopup.Enabled; this.inputModePopup.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityInpueModeEditor, ViewModel.Property.Name); } } - private readonly NSTextField stringEditor; - private NSLayoutConstraint editorRightConstraint, editorInputModeConstraint; - internal NSPopUpButton inputModePopup; + private NSView lastKeyView; + private NSLayoutConstraint editorInputModeConstraint; + private NSPopUpButton inputModePopup; private IReadOnlyList<InputMode> viewModelInputModes; - - private bool CanEnable => ViewModel.Property.CanWrite && (((ViewModel.InputMode != null) && !ViewModel.InputMode.IsSingleValue) || (this.inputModePopup == null)); } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/TimeSpanEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/TimeSpanEditorControl.cs new file mode 100644 index 0000000..7277acb --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/TimeSpanEditorControl.cs @@ -0,0 +1,45 @@ +using System; +using Xamarin.PropertyEditing.Mac.Resources; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + internal class TimeSpanEditorControl + : EntryPropertyEditor<TimeSpan> + { + public TimeSpanEditorControl (IHostResourceProvider hostResources) + : base (hostResources) + { + } + + protected override EntryPropertyEditorDelegate<TimeSpan> CreateDelegate (PropertyViewModel<TimeSpan> viewModel) + { + return new TimeSpanDelegate (viewModel); + } + + protected override void UpdateAccessibilityValues () + { + base.UpdateAccessibilityValues (); + Entry.AccessibilityTitle = string.Format (LocalizationResources.AccessibilityTimeSpan, ViewModel.Property.Name); + } + + private class TimeSpanDelegate + : EntryPropertyEditorDelegate<TimeSpan> + { + public TimeSpanDelegate (PropertyViewModel<TimeSpan> viewModel) + : base (viewModel) + { + } + + protected override TimeSpan GetValue (string value) + { + return TimeSpan.Parse (value); + } + + protected override bool CanGetValue (string value) + { + return TimeSpan.TryParse (value, out _); + } + } + } +} |