Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xamarin/Xamarin.PropertyEditing.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.PropertyEditing.Mac/Controls/BindingEditor/BindingPathSelectorControl.cs')
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/BindingEditor/BindingPathSelectorControl.cs337
1 files changed, 337 insertions, 0 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/BindingEditor/BindingPathSelectorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/BindingEditor/BindingPathSelectorControl.cs
new file mode 100644
index 0000000..0123d7b
--- /dev/null
+++ b/Xamarin.PropertyEditing.Mac/Controls/BindingEditor/BindingPathSelectorControl.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AppKit;
+using Foundation;
+using Xamarin.PropertyEditing.ViewModels;
+
+namespace Xamarin.PropertyEditing.Mac
+{
+ internal class PathOutlineView : NSOutlineView
+ {
+ private IReadOnlyCollection<object> viewModel;
+ private PropertyTreeRoot propertyTreeRoot;
+
+ private IReadOnlyCollection<object> ViewModel
+ {
+ get => this.viewModel;
+ set {
+ if (this.viewModel != value) {
+ this.viewModel = value;
+
+ var dataSource = new PathOutlineViewDataSource (this.viewModel, this.targetName);
+ Delegate = new PathOutlineViewDelegate (dataSource);
+ DataSource = dataSource;
+
+ ReloadData ();
+
+ ExpandItem (ItemAtRow (0));
+ }
+ }
+ }
+
+ private string targetName { get; set; }
+ public PropertyTreeRoot PropertyTreeRoot
+ {
+ get { return this.propertyTreeRoot; }
+ internal set {
+ if (this.propertyTreeRoot != value) {
+ this.propertyTreeRoot = value;
+ if (this.propertyTreeRoot != null) {
+ targetName = this.propertyTreeRoot.TargetType.Name;
+ ViewModel = this.propertyTreeRoot.Children;
+ } else {
+ targetName = string.Empty;
+ ViewModel = null;
+ }
+ }
+ }
+ }
+
+ public PathOutlineView ()
+ {
+ Initialize ();
+ }
+
+ // Called when created from unmanaged code
+ public PathOutlineView (IntPtr handle) : base (handle)
+ {
+ Initialize ();
+ }
+
+ // Called when created directly from a XIB file
+ [Export ("initWithCoder:")]
+ public PathOutlineView (NSCoder coder) : base (coder)
+ {
+ Initialize ();
+ }
+
+ [Export ("validateProposedFirstResponder:forEvent:")]
+ public bool ValidateProposedFirstResponder (NSResponder responder, NSEvent forEvent)
+ {
+ return true;
+ }
+
+ public void Initialize ()
+ {
+ AutoresizingMask = NSViewResizingMask.WidthSizable;
+ HeaderView = null;
+ TranslatesAutoresizingMaskIntoConstraints = false;
+ }
+ }
+
+ internal class PathOutlineViewDelegate : NSOutlineViewDelegate
+ {
+ private readonly PathOutlineViewDataSource dataSource;
+
+ public PathOutlineViewDelegate (PathOutlineViewDataSource dataSource)
+ {
+ this.dataSource = dataSource;
+ }
+
+ public override nfloat GetRowHeight (NSOutlineView outlineView, NSObject item)
+ {
+ return PropertyEditorControl.DefaultControlHeight;
+ }
+
+ public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
+ {
+ var labelContainer = (UnfocusableTextField)outlineView.MakeView ("path", this);
+ if (labelContainer == null) {
+ labelContainer = new UnfocusableTextField {
+ Identifier = "path",
+ };
+ }
+ var target = (item as NSObjectFacade).Target;
+
+ switch (target) {
+ case PropertyTreeElement propertyTreeElement:
+ labelContainer.StringValue = string.Format("{0}: ({1})", propertyTreeElement.Property.Name, propertyTreeElement.Property.RealType.Name);
+ break;
+
+ case string targetName:
+ labelContainer.StringValue = targetName;
+ break;
+
+ default:
+ labelContainer.StringValue = "Type Not Supported";
+ break;
+ }
+
+ return labelContainer;
+ }
+
+ public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
+ {
+ if (item is NSObjectFacade facade) {
+ switch (facade.Target) {
+ case PropertyTreeElement propertyTreeElement:
+ var propertyTreeResult = propertyTreeElement.Children.Task.Result;
+ return propertyTreeResult.Count == 0;
+
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ internal class PathOutlineViewDataSource : NSOutlineViewDataSource
+ {
+ private readonly IReadOnlyCollection<object> viewModel;
+ private string targetName;
+
+ internal PathOutlineViewDataSource (IReadOnlyCollection<object> viewModel, string targetName)
+ {
+ this.viewModel = viewModel;
+ this.targetName = targetName;
+ }
+
+ public override nint GetChildrenCount (NSOutlineView outlineView, NSObject item)
+ {
+ nint childCount;
+ if (item == null) {
+ childCount = this.viewModel != null ? this.viewModel.Count () + 1 : 0;
+ } else {
+ var target = (item as NSObjectFacade).Target;
+ switch (target) {
+ case PropertyTreeElement propertyTreeElement:
+ IReadOnlyCollection<PropertyTreeElement> propertyTrees = propertyTreeElement.Children.Task.Result;
+ childCount = propertyTrees.Count;
+ break;
+
+ case string targetName:
+ childCount = this.viewModel.Count ();
+ break;
+
+ default:
+ childCount = 0;
+ break;
+ }
+ }
+
+ return childCount;
+ }
+
+ public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, NSObject item)
+ {
+ if (childIndex == 0 && item == null) {
+ return new NSObjectFacade (targetName);
+ }
+
+ if (item is NSObjectFacade objectFacade) {
+ var target = objectFacade.Target;
+ switch (target) {
+ case PropertyTreeElement propertyTreeElement:
+ IReadOnlyCollection<PropertyTreeElement> propertyTrees = propertyTreeElement.Children.Task.Result;
+ return new NSObjectFacade (propertyTrees.ElementAt ((int)childIndex));
+
+ case string targetName:
+ return new NSObjectFacade (this.viewModel.ElementAt ((int)childIndex));
+
+ default:
+ return null;
+ }
+
+ }
+ return null;
+ }
+
+ public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
+ {
+ if (item is NSObjectFacade objectFacade) {
+ var target = objectFacade.Target;
+ switch (target) {
+ case PropertyTreeElement propertyTreeElement:
+ IReadOnlyCollection<PropertyTreeElement> propertyTrees = propertyTreeElement.Children.Task.Result;
+ return propertyTrees.Count > 0;
+
+ case string targetName:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ internal class BindingPathSelectorControl : NSView
+ {
+ private PathOutlineView pathOutlineView;
+ internal const string PathSelectorColumnColId = "PathSelectorColumn";
+ private const float spacing = 10f;
+ private NSTextField customPath;
+ public NSTextField CustomPath { get; private set; }
+
+ public BindingPathSelectorControl (CreateBindingViewModel viewModel)
+ {
+ TranslatesAutoresizingMaskIntoConstraints = false;
+
+ var customCheckBox = new NSButton {
+ ControlSize = NSControlSize.Small,
+ Font = NSFont.FromFontName (PropertyEditorControl.DefaultFontName, PropertyEditorControl.DefaultFontSize),
+ Title = Properties.Resources.Custom,
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ };
+
+ customCheckBox.SetButtonType (NSButtonType.Switch);
+
+ AddSubview (customCheckBox);
+ AddConstraints (new[] {
+ NSLayoutConstraint.Create (customCheckBox, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 8f),
+ NSLayoutConstraint.Create (customCheckBox, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, -90f),
+ });
+
+ this.customPath = new NSTextField {
+ ControlSize = NSControlSize.Mini,
+ Enabled = false,
+ Font = NSFont.FromFontName (PropertyEditorControl.DefaultFontName, PropertyEditorControl.DefaultFontSize),
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ };
+
+ var customPathHeightConstraint = NSLayoutConstraint.Create (this.customPath, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 0);
+
+ AddSubview (this.customPath);
+ AddConstraints (new[] {
+ NSLayoutConstraint.Create (this.customPath, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, 45f),
+ NSLayoutConstraint.Create (this.customPath, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1f, -10f),
+ NSLayoutConstraint.Create (this.customPath, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterX, 1, 0),
+ customPathHeightConstraint,
+ });
+
+ // create a table view and a scroll view
+ var outlineViewContainer = new NSScrollView {
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ };
+
+ var outlineViewContainerTopConstraint = NSLayoutConstraint.Create (outlineViewContainer, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this.customPath, NSLayoutAttribute.Bottom, 1f, 0f);
+ customCheckBox.Activated += (sender, e) => {
+ this.customPath.Enabled = customCheckBox.State == NSCellStateValue.On;
+ customPathHeightConstraint.Constant = this.customPath.Enabled ? PropertyEditorControl.DefaultControlHeight : 0;
+ outlineViewContainerTopConstraint.Constant = this.customPath.Enabled ? 10 : 0;
+ SetCustomPath (viewModel);
+ };
+
+ this.customPath.Changed += (sender, e) => {
+ viewModel.Path = this.customPath.StringValue;
+ };
+
+ this.pathOutlineView = new PathOutlineView {
+
+ };
+
+ this.pathOutlineView.Activated += (sender, e) => {
+ if (sender is PathOutlineView pov) {
+ if (pov.SelectedRow != -1) {
+ if (pov.ItemAtRow (pov.SelectedRow) is NSObjectFacade facade) {
+ switch (facade.Target) {
+ case PropertyTreeElement propertyTreeElement:
+ viewModel.SelectedPropertyElement = propertyTreeElement;
+ break;
+
+ default:
+ break;
+ }
+ SetCustomPath (viewModel);
+ }
+ }
+ }
+ };
+
+ var pathColumn = new NSTableColumn (PathSelectorColumnColId);
+ this.pathOutlineView.AddColumn (pathColumn);
+
+ // Set OutlineTableColumn or the arrows showing children/expansion will not be drawn
+ this.pathOutlineView.OutlineTableColumn = pathColumn;
+
+ // add the panel to the window
+ outlineViewContainer.DocumentView = this.pathOutlineView;
+ AddSubview (outlineViewContainer);
+
+ AddConstraints (new[] {
+ outlineViewContainerTopConstraint,
+ NSLayoutConstraint.Create (outlineViewContainer, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1f, -10f),
+ NSLayoutConstraint.Create (outlineViewContainer, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterX, 1, 0),
+ NSLayoutConstraint.Create (outlineViewContainer, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal,this, NSLayoutAttribute.Bottom, 1f, -5f),
+ });
+
+ viewModel.PropertyChanged += async (sender, e) => {
+ if (viewModel.PropertyRoot != null) {
+ this.pathOutlineView.PropertyTreeRoot = await viewModel.PropertyRoot.Task;
+ } else {
+ this.pathOutlineView.PropertyTreeRoot = null;
+ }
+ };
+ }
+
+ private void SetCustomPath (CreateBindingViewModel viewModel)
+ {
+ this.customPath.StringValue = this.customPath.Enabled ? viewModel.Path ?? string.Empty : string.Empty;
+ }
+ }
+}