From 38ea4489eaf0b4b8975e65527ff59b35c29875de Mon Sep 17 00:00:00 2001 From: Eric Maupin Date: Fri, 14 Dec 2018 13:45:30 -0500 Subject: [mac] Type selector control --- .../Controls/TypeSelectorControl.cs | 211 +++++++++++++++++++++ .../Xamarin.PropertyEditing.Mac.csproj | 1 + 2 files changed, 212 insertions(+) create mode 100644 Xamarin.PropertyEditing.Mac/Controls/TypeSelectorControl.cs (limited to 'Xamarin.PropertyEditing.Mac') diff --git a/Xamarin.PropertyEditing.Mac/Controls/TypeSelectorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/TypeSelectorControl.cs new file mode 100644 index 0000000..747ca64 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/TypeSelectorControl.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading; +using AppKit; +using Foundation; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + internal class TypeSelectorControl + : NotifyingView + { + public TypeSelectorControl() + { + this.checkbox = NSButton.CreateCheckbox (Properties.Resources.ShowAllAssemblies, OnCheckedChanged); + this.checkbox.TranslatesAutoresizingMaskIntoConstraints = false; + AddSubview (this.checkbox); + + var scroll = new NSScrollView { + TranslatesAutoresizingMaskIntoConstraints = false + }; + + var d = new TypeSelectorDelegate (); + this.outlineView = new NSOutlineView { + Delegate = d, + AutoresizingMask = NSViewResizingMask.WidthSizable, + HeaderView = null, + Action = new ObjCRuntime.Selector ("onActivatedItem"), + Target = this + }; + var col = new NSTableColumn (); + this.outlineView.AddColumn (col); + this.outlineView.OutlineTableColumn = col; + scroll.DocumentView = this.outlineView; + + AddSubview (scroll); + + this.filter = new NSTextField { + TranslatesAutoresizingMaskIntoConstraints = false, + PlaceholderString = "Filter" + }; + this.filter.Changed += OnFilterChanged; + + AddSubview (this.filter); + + AddConstraints (new[] { + NSLayoutConstraint.Create (this.filter, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, 10), + NSLayoutConstraint.Create (this.filter, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1, -20), + NSLayoutConstraint.Create (this.filter, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterX, 1, 0), + + NSLayoutConstraint.Create (scroll, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this.filter, NSLayoutAttribute.Bottom, 1, 8), + NSLayoutConstraint.Create (scroll, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this.filter, NSLayoutAttribute.Width, 1, 0), + NSLayoutConstraint.Create (scroll, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterX, 1, 0), + NSLayoutConstraint.Create (scroll, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this.checkbox, NSLayoutAttribute.Top, 1, -8), + + NSLayoutConstraint.Create (this.checkbox, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this, NSLayoutAttribute.Bottom, 1, -10), + NSLayoutConstraint.Create (this.checkbox, NSLayoutAttribute.Left, NSLayoutRelation.Equal, scroll, NSLayoutAttribute.Left, 1, 0) + }); + } + + public override void OnViewModelChanged (TypeSelectorViewModel oldModel) + { + base.OnViewModelChanged (oldModel); + + this.outlineView.DataSource = new TypeSelectorDataSource (ViewModel); + OnPropertyChanged (ViewModel, new PropertyChangedEventArgs (null)); + } + + public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) + { + base.OnPropertyChanged (sender, e); + + switch (e.PropertyName) { + case nameof (TypeSelectorViewModel.Types): + Reload (); + break; + case nameof (TypeSelectorViewModel.FilterText): + default: + UpdateFilter (); + break; + } + } + + public override void KeyDown (NSEvent theEvent) + { + if (theEvent.KeyCode == 76 || theEvent.KeyCode == 36) { + if (this.outlineView.SelectedRow >= 0) { + var facade = (NSObjectFacade)this.outlineView.ItemAtRow (this.outlineView.SelectedRow); + if (facade.Target is ITypeInfo) + OnActivatedItem (); + } else { + OnActivatedItem (); + } + } + + base.KeyDown (theEvent); + } + + private readonly NSOutlineView outlineView; + private readonly NSTextField filter; + private readonly NSButton checkbox; + + private void Reload() + { + this.outlineView.ReloadData (); + + if (!String.IsNullOrWhiteSpace (ViewModel?.FilterText)) { + for (int i = 0; i < this.outlineView.RowCount; i++) { + this.outlineView.ExpandItem (this.outlineView.ItemAtRow (i)); + } + } + } + + [Export ("onActivatedItem")] + private void OnActivatedItem() + { + if (this.outlineView.SelectedRow >= 0) { + var facade = (NSObjectFacade)this.outlineView.ItemAtRow (this.outlineView.SelectedRow); + ViewModel.SelectedType = facade.Target as ITypeInfo; + } else { + ViewModel.SelectedType = null; + } + } + + private void OnFilterChanged (object sender, EventArgs e) + { + if (ViewModel == null) + return; + + ViewModel.FilterText = this.filter.StringValue; + Reload (); + } + + private void UpdateFilter() + { + this.filter.StringValue = ViewModel?.FilterText ?? String.Empty; + } + + private void OnCheckedChanged () + { + ViewModel.ShowAllAssemblies = this.checkbox.State == NSCellStateValue.On; + Reload (); + } + + private class TypeSelectorDataSource + : NSOutlineViewDataSource + { + public TypeSelectorDataSource (TypeSelectorViewModel viewModel) + { + this.viewModel = viewModel; + } + + public override nint GetChildrenCount (NSOutlineView outlineView, NSObject item) + { + if (item == null) { + return this.viewModel.Types?.Count ?? 0; + } else if (((NSObjectFacade)item).Target is KeyValuePair kvp) { + return kvp.Value.Count; + } + + return base.GetChildrenCount (outlineView, item); + } + + public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, NSObject item) + { + if (item == null) { + return new NSObjectFacade (this.viewModel.Types[(int)childIndex]); + } else if (((NSObjectFacade)item).Target is KeyValuePair kvp) { + return new NSObjectFacade (kvp.Value[(int)childIndex]); + } + + return base.GetChild (outlineView, childIndex, item); + } + + public override bool ItemExpandable (NSOutlineView outlineView, NSObject item) + { + return !(((NSObjectFacade)item).Target is ITypeInfo); + } + + private TypeSelectorViewModel viewModel; + } + + private class TypeSelectorDelegate + : NSOutlineViewDelegate + { + + public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) + { + var label = (UnfocusableTextField)outlineView.MakeView (LabelId, outlineView); + if (label == null) { + label = new UnfocusableTextField { + Identifier = LabelId + }; + } + + string text = String.Empty; + var facade = (NSObjectFacade)item; + if (facade.Target is KeyValuePair kvp) + text = kvp.Key; + else if (facade.Target is ITypeInfo type) + text = type.Name; + + label.StringValue = text; + return label; + } + + private const string LabelId = "label"; + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj index 1e4aa71..ce10228 100644 --- a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj +++ b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj @@ -145,6 +145,7 @@ + -- cgit v1.2.3