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')
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/CombinablePropertyEditor.cs28
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs2
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs26
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs13
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyTextField.cs15
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/Custom/UnfocusableTextField.cs8
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/EditorContainer.cs53
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/NumericEditorControl.cs7
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/ObjectEditorControl.cs184
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/PanelHeaderEditorControl.cs2
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/PredefinedValuesEditor.cs22
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs53
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs9
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/TypeSelectorControl.cs211
-rw-r--r--Xamarin.PropertyEditing.Mac/Controls/TypeSelectorWindow.cs75
-rw-r--r--Xamarin.PropertyEditing.Mac/PropertyEditorPanel.cs17
-rw-r--r--Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs2
-rw-r--r--Xamarin.PropertyEditing.Mac/PropertyTableDataSource.cs30
-rw-r--r--Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs109
-rw-r--r--Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj4
20 files changed, 753 insertions, 117 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/CombinablePropertyEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/CombinablePropertyEditor.cs
index cf58bdc..29fd55f 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/CombinablePropertyEditor.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/CombinablePropertyEditor.cs
@@ -31,7 +31,7 @@ namespace Xamarin.PropertyEditing.Mac
public override nint GetHeight (EditorViewModel vm)
{
var realVm = (CombinablePropertyViewModel<T>)vm;
- return checkHeight * realVm.Choices.Count;
+ return DefaultControlHeight * realVm.Choices.Count;
}
protected override void HandleErrorsChanged (object sender, DataErrorsChangedEventArgs e)
@@ -58,9 +58,12 @@ namespace Xamarin.PropertyEditing.Mac
protected override void OnViewModelChanged (PropertyViewModel oldModel)
{
- nint rowHeight = GetHeight (ViewModel);
+ base.OnViewModelChanged (oldModel);
+
+ if (ViewModel == null)
+ return;
- float top = checkHeight;
+ float top = 0;
while (this.combinableList.Count > ViewModel.Choices.Count) {
var child = this.combinableList.KeyAt (ViewModel.Choices.Count);
@@ -75,7 +78,12 @@ namespace Xamarin.PropertyEditing.Mac
NSButton checkbox;
if (i >= this.combinableList.Count) {
checkbox = new NSButton {
+ AllowsExpansionToolTips = true,
AllowsMixedState = true,
+ Cell = {
+ LineBreakMode = NSLineBreakMode.TruncatingTail,
+ UsesSingleLineMode = true,
+ },
ControlSize = NSControlSize.Small,
Font = NSFont.FromFontName (DefaultFontName, DefaultFontSize),
TranslatesAutoresizingMaskIntoConstraints = false,
@@ -85,23 +93,26 @@ namespace Xamarin.PropertyEditing.Mac
checkbox.Activated += SelectionChanged;
AddSubview (checkbox);
+
+ this.AddConstraints (new[] {
+ NSLayoutConstraint.Create (checkbox, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1f, top),
+ NSLayoutConstraint.Create (checkbox, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 0f),
+ NSLayoutConstraint.Create (checkbox, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this, NSLayoutAttribute.Width, 1f, -33f),
+ NSLayoutConstraint.Create (checkbox, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, DefaultControlHeight),
+ });
} else {
checkbox = this.combinableList.KeyAt (i);
}
checkbox.Title = choice.Name;
- checkbox.Frame = new CGRect (0, rowHeight - top, Frame.Width, checkHeight);
this.combinableList[checkbox] = choice;
- top += checkHeight;
+ top += DefaultControlHeight;
}
// Set our tabable order
this.firstKeyView = this.combinableList.KeyAt (0);
this.lastKeyView = this.combinableList.KeyAt (this.combinableList.Count - 1);
-
- base.OnViewModelChanged (oldModel);
-
}
protected override void UpdateValue ()
@@ -125,7 +136,6 @@ namespace Xamarin.PropertyEditing.Mac
}
}
- private const int checkHeight = 22;
private readonly OrderedDictionary<NSButton, FlaggableChoiceViewModel<T>> combinableList = new OrderedDictionary<NSButton, FlaggableChoiceViewModel<T>> ();
private NSView firstKeyView;
private NSView lastKeyView;
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs
index 651d716..6fa2dd5 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs
@@ -58,7 +58,7 @@ namespace Xamarin.PropertyEditing.Mac
this.inhibitSelection = true;
base.OnViewModelChanged (oldModel);
- var existing = new HashSet<CommonBrushType> (ViewModel?.BrushTypes?.Values ?? Array.Empty<CommonBrushType> ());
+ var existing = new HashSet<CommonBrushType> (oldModel?.BrushTypes?.Values ?? Array.Empty<CommonBrushType> ());
existing.IntersectWith (this.brushTypeTable.Keys);
var removed = new HashSet<CommonBrushType> (this.brushTypeTable.Keys);
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs
index 5347283..22211fa 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using AppKit;
using CoreGraphics;
using Foundation;
@@ -6,13 +6,13 @@ using ObjCRuntime;
namespace Xamarin.PropertyEditing.Mac
{
- public class NumericTextField : NSTextField
+ internal class NumericTextField : PropertyTextField
{
- NSText CachedCurrentEditor {
+ private NSText CachedCurrentEditor {
get; set;
}
- string cachedValueString;
+ private string cachedValueString;
public bool AllowNegativeValues {
get; set;
@@ -54,7 +54,7 @@ namespace Xamarin.PropertyEditing.Mac
public override bool ShouldBeginEditing (NSText textObject)
{
CachedCurrentEditor = textObject;
- cachedValueString = textObject.Value;
+ this.cachedValueString = textObject.Value;
if (AllowRatios)
CachedCurrentEditor.Delegate = new RatioValidateDelegate (this);
@@ -81,7 +81,7 @@ namespace Xamarin.PropertyEditing.Mac
public virtual void ResetInvalidInput ()
{
- this.StringValue = cachedValueString;
+ this.StringValue = this.cachedValueString;
}
public static bool CheckIfNumber (string finalString, ValidationType mode, bool allowNegativeValues)
@@ -93,9 +93,8 @@ namespace Xamarin.PropertyEditing.Mac
public static bool ValidateDecimal (string finalString, bool allowNegativeValues)
{
- double value;
//Checks parsing to number
- if (!double.TryParse (finalString, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentUICulture, out value))
+ if (!double.TryParse (finalString, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentUICulture, out var value))
return false;
//Checks if needs to be possitive value
if (!allowNegativeValues && value < 0)
@@ -106,9 +105,8 @@ namespace Xamarin.PropertyEditing.Mac
public static bool ValidateInteger (string finalString, bool allowNegativeValues)
{
- int value;
//Checks parsing to number
- if (!int.TryParse (finalString, out value))
+ if (!int.TryParse (finalString, out var value))
return false;
//Checks if needs to be possitive value
if (!allowNegativeValues && value < 0)
@@ -156,7 +154,7 @@ namespace Xamarin.PropertyEditing.Mac
}
}
- class KeyUpDownDelegate : NSTextFieldDelegate
+ internal class KeyUpDownDelegate : NSTextFieldDelegate
{
public event EventHandler<bool> KeyArrowUp;
public event EventHandler<bool> KeyArrowDown;
@@ -194,7 +192,7 @@ namespace Xamarin.PropertyEditing.Mac
}
}
- public abstract class TextViewValidationDelegate : NSTextViewDelegate
+ internal abstract class TextViewValidationDelegate : NSTextViewDelegate
{
protected NumericTextField TextField {
get; set;
@@ -233,7 +231,7 @@ namespace Xamarin.PropertyEditing.Mac
protected abstract bool ValidateFinalString (string value);
}
- public class NumericValidationDelegate : TextViewValidationDelegate
+ internal class NumericValidationDelegate : TextViewValidationDelegate
{
public NumericValidationDelegate (NumericTextField textField)
: base (textField)
@@ -249,7 +247,7 @@ namespace Xamarin.PropertyEditing.Mac
}
}
- public class RatioValidateDelegate : TextViewValidationDelegate
+ internal class RatioValidateDelegate : TextViewValidationDelegate
{
public RatioValidateDelegate (NumericTextField textField)
: base (textField)
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs
index 17581f1..012fbc7 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs
@@ -18,14 +18,15 @@ namespace Xamarin.PropertyEditing.Mac
{
get { return viewModel; }
set {
- if (viewModel != null) {
- viewModel.PropertyChanged -= OnPropertyChanged;
+ if (this.viewModel != null) {
+ this.viewModel.PropertyChanged -= OnPropertyChanged;
}
- viewModel = value;
- viewModel.PropertyChanged += OnPropertyChanged;
-
- ValueSourceChanged (viewModel.ValueSource);
+ this.viewModel = value;
+ if (this.viewModel != null) {
+ this.viewModel.PropertyChanged += OnPropertyChanged;
+ ValueSourceChanged (this.viewModel.ValueSource);
+ }
}
}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyTextField.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyTextField.cs
new file mode 100644
index 0000000..2e7e158
--- /dev/null
+++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyTextField.cs
@@ -0,0 +1,15 @@
+using System;
+using AppKit;
+
+namespace Xamarin.PropertyEditing.Mac
+{
+ internal class PropertyTextField : NSTextField
+ {
+ public PropertyTextField ()
+ {
+ AllowsExpansionToolTips = true;
+ Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
+ Cell.UsesSingleLineMode = true;
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnfocusableTextField.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/UnfocusableTextField.cs
index a55341e..5f9dfab 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnfocusableTextField.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/UnfocusableTextField.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using AppKit;
using CoreGraphics;
using Foundation;
@@ -59,14 +59,10 @@ namespace Xamarin.PropertyEditing.Mac
private void SetDefaultTextProperties ()
{
- this.label = new NSTextField {
+ this.label = new PropertyTextField {
AccessibilityElement = false,
BackgroundColor = NSColor.Clear,
Bordered = false,
- Cell = {
- LineBreakMode = NSLineBreakMode.TruncatingTail,
- UsesSingleLineMode = true,
- },
ControlSize = NSControlSize.Small,
Editable = false,
Font = NSFont.FromFontName (PropertyEditorControl.DefaultFontName, PropertyEditorControl.DefaultPropertyLabelFontSize),
diff --git a/Xamarin.PropertyEditing.Mac/Controls/EditorContainer.cs b/Xamarin.PropertyEditing.Mac/Controls/EditorContainer.cs
index e5eec20..075cfd1 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/EditorContainer.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/EditorContainer.cs
@@ -1,5 +1,7 @@
using System;
using AppKit;
+using CoreGraphics;
+using Foundation;
namespace Xamarin.PropertyEditing.Mac
{
@@ -27,7 +29,7 @@ namespace Xamarin.PropertyEditing.Mac
this.AddConstraints (new[] {
NSLayoutConstraint.Create (EditorView.NativeView, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0f),
- NSLayoutConstraint.Create (EditorView.NativeView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.label, NSLayoutAttribute.Right, 1f, 5f),
+ NSLayoutConstraint.Create (EditorView.NativeView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.label, NSLayoutAttribute.Right, 1f, LabelToControlSpacing),
NSLayoutConstraint.Create (EditorView.NativeView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1f, 0f),
NSLayoutConstraint.Create (EditorView.NativeView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1f, 0f)
});
@@ -40,12 +42,54 @@ namespace Xamarin.PropertyEditing.Mac
public string Label {
get { return this.label.StringValue; }
- set { this.label.StringValue = value; }
+ set {
+ this.label.StringValue = value + ":";
+ this.label.ToolTip = value;
+ }
+ }
+
+ public NSView LeftEdgeView
+ {
+ get { return this.leftEdgeView; }
+ set
+ {
+ if (this.leftEdgeView != null) {
+ this.leftEdgeView.RemoveFromSuperview ();
+ RemoveConstraints (new[] { this.leftEdgeLeftConstraint, this.leftEdgeVCenterConstraint });
+ this.leftEdgeLeftConstraint.Dispose ();
+ this.leftEdgeLeftConstraint = null;
+ this.leftEdgeVCenterConstraint.Dispose ();
+ this.leftEdgeVCenterConstraint = null;
+ }
+
+ this.leftEdgeView = value;
+
+ if (value != null) {
+ AddSubview (value);
+
+ value.TranslatesAutoresizingMaskIntoConstraints = false;
+ this.leftEdgeLeftConstraint = NSLayoutConstraint.Create (this.leftEdgeView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 4);
+ this.leftEdgeVCenterConstraint = NSLayoutConstraint.Create (this.leftEdgeView, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1, 0);
+
+ AddConstraints (new[] { this.leftEdgeLeftConstraint, this.leftEdgeVCenterConstraint });
+ }
+ }
+ }
+
+ public override void ViewWillMoveToSuperview (NSView newSuperview)
+ {
+ if (newSuperview == null && EditorView != null)
+ EditorView.ViewModel = null;
+
+ base.ViewWillMoveToSuperview (newSuperview);
}
private UnfocusableTextField label = new UnfocusableTextField {
Alignment = NSTextAlignment.Right,
- TranslatesAutoresizingMaskIntoConstraints = false
+ Cell = {
+ LineBreakMode = NSLineBreakMode.TruncatingHead,
+ },
+ TranslatesAutoresizingMaskIntoConstraints = false,
};
#if DEBUG // Currently only used to highlight which controls haven't been implemented
@@ -54,6 +98,9 @@ namespace Xamarin.PropertyEditing.Mac
}
#endif
+ private NSView leftEdgeView;
+ private NSLayoutConstraint leftEdgeLeftConstraint, leftEdgeVCenterConstraint;
private readonly IHostResourceProvider hostResources;
+ private const float LabelToControlSpacing = 5f;
}
}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/NumericEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/NumericEditorControl.cs
index e6b1277..e15e206 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/NumericEditorControl.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/NumericEditorControl.cs
@@ -133,6 +133,11 @@ namespace Xamarin.PropertyEditing.Mac
protected override void OnViewModelChanged (PropertyViewModel oldModel)
{
+ base.OnViewModelChanged (oldModel);
+
+ if (ViewModel == null)
+ return;
+
if (ViewModel.HasInputModes) {
if (this.inputModePopup == null) {
this.inputModePopup = new NSPopUpButton {
@@ -169,8 +174,6 @@ namespace Xamarin.PropertyEditing.Mac
// If we are reusing the control we'll have to hid the inputMode if this doesn't have InputMode.
if (this.inputModePopup != null)
this.inputModePopup.Hidden = !ViewModel.HasInputModes;
-
- base.OnViewModelChanged (oldModel);
}
}
}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/ObjectEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/ObjectEditorControl.cs
new file mode 100644
index 0000000..ab9749b
--- /dev/null
+++ b/Xamarin.PropertyEditing.Mac/Controls/ObjectEditorControl.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using AppKit;
+using Foundation;
+using Xamarin.PropertyEditing.ViewModels;
+
+namespace Xamarin.PropertyEditing.Mac
+{
+ internal class ObjectEditorControl
+ : PropertyEditorControl<ObjectPropertyViewModel>
+ {
+ public ObjectEditorControl (IHostResourceProvider hostResources)
+ : base (hostResources)
+ {
+ this.typeLabel = new UnfocusableTextField {
+ TranslatesAutoresizingMaskIntoConstraints = false
+ };
+ AddSubview (this.typeLabel);
+
+ this.createObject = new NSButton {
+ Title = Properties.Resources.New,
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ BezelStyle = NSBezelStyle.Rounded
+ };
+ this.createObject.Activated += OnNewPressed;
+ AddSubview (this.createObject);
+
+ this.buttonConstraint = NSLayoutConstraint.Create (this.createObject, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, this.typeLabel, NSLayoutAttribute.Trailing, 1f, 12);
+
+ AddConstraints (new[] {
+ NSLayoutConstraint.Create (this.typeLabel, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, this, NSLayoutAttribute.Leading, 1f, 0f),
+ NSLayoutConstraint.Create (this.typeLabel, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0f),
+ NSLayoutConstraint.Create (this.typeLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1, 0),
+ this.buttonConstraint,
+ NSLayoutConstraint.Create (this.createObject, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, this, NSLayoutAttribute.Leading, 1, 0).WithPriority (NSLayoutPriority.DefaultLow),
+ NSLayoutConstraint.Create (this.createObject, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1f, 0f),
+ NSLayoutConstraint.Create (this.createObject, NSLayoutAttribute.Width, NSLayoutRelation.GreaterThanOrEqual, 1f, 70f),
+ });
+ }
+
+ public override NSView FirstKeyView => this.createObject;
+
+ public override NSView LastKeyView => this.createObject;
+
+ protected override void UpdateValue ()
+ {
+ }
+
+ protected override void UpdateErrorsDisplayed (IEnumerable errors)
+ {
+ }
+
+ protected override void HandleErrorsChanged (object sender, DataErrorsChangedEventArgs e)
+ {
+ }
+
+ protected override void SetEnabled ()
+ {
+ this.createObject.Enabled = ViewModel.Property.CanWrite;
+ }
+
+ protected override void UpdateAccessibilityValues ()
+ {
+ this.createObject.AccessibilityTitle = String.Format (Properties.Resources.NewInstanceForProperty, ViewModel.Property.Name);
+ }
+
+ protected override void OnViewModelChanged (PropertyViewModel oldModel)
+ {
+ base.OnViewModelChanged (oldModel);
+
+ if (oldModel is ObjectPropertyViewModel ovm) {
+ ovm.TypeRequested -= OnTypeRequested;
+ ovm.CreateInstanceCommand.CanExecuteChanged -= OnCreateInstanceExecutableChanged;
+ }
+
+ if (ViewModel != null) {
+ ViewModel.TypeRequested += OnTypeRequested;
+ ViewModel.CreateInstanceCommand.CanExecuteChanged += OnCreateInstanceExecutableChanged;
+
+ OnPropertyChanged (ViewModel, new PropertyChangedEventArgs (null));
+ }
+ }
+
+ protected override void OnPropertyChanged (object sender, PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName) {
+ case nameof (ObjectPropertyViewModel.ValueType):
+ UpdateTypeLabel ();
+ break;
+ case null:
+ case "":
+ UpdateTypeLabel ();
+ UpdateCreateInstanceCommand ();
+ break;
+ }
+
+ base.OnPropertyChanged (sender, e);
+ }
+
+ private readonly UnfocusableTextField typeLabel;
+ private readonly NSButton createObject;
+ private readonly NSLayoutConstraint buttonConstraint;
+
+ private void OnCreateInstanceExecutableChanged (object sender, EventArgs e)
+ {
+ UpdateCreateInstanceCommand ();
+ }
+
+ private void OnTypeRequested (object sender, TypeRequestedEventArgs e)
+ {
+ var tcs = new TaskCompletionSource<ITypeInfo> ();
+ e.SelectedType = tcs.Task;
+
+ var vm = new TypeSelectorViewModel (ViewModel.AssignableTypes);
+ var selector = new TypeSelectorControl {
+ ViewModel = vm,
+ Appearance = EffectiveAppearance
+ };
+
+ vm.PropertyChanged += (vms, ve) => {
+ if (ve.PropertyName == nameof (TypeSelectorViewModel.SelectedType)) {
+ tcs.TrySetResult (vm.SelectedType);
+ }
+ };
+
+ var popover = new NSPopover {
+ Behavior = NSPopoverBehavior.Transient,
+ Delegate = new PopoverDelegate<ITypeInfo> (tcs),
+ ContentViewController = new NSViewController {
+ View = selector,
+ PreferredContentSize = new CoreGraphics.CGSize (360, 335)
+ },
+ };
+
+ popover.SetAppearance (HostResources.GetVibrantAppearance (EffectiveAppearance));
+
+ tcs.Task.ContinueWith (t => {
+ popover.PerformClose (popover);
+ popover.Dispose ();
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+
+ popover.Show (this.createObject.Frame, this, NSRectEdge.MinYEdge);
+ }
+
+ private void UpdateTypeLabel ()
+ {
+ if (ViewModel.ValueType == null) {
+ this.typeLabel.StringValue = String.Empty;
+ this.buttonConstraint.Active = false;
+ } else {
+ this.typeLabel.StringValue = $"({ViewModel.ValueType.Name})";
+ this.buttonConstraint.Active = true;
+ }
+ }
+
+ private void UpdateCreateInstanceCommand()
+ {
+ this.createObject.Enabled = ViewModel.CreateInstanceCommand.CanExecute (null);
+ }
+
+ private void OnNewPressed (object sender, EventArgs e)
+ {
+ ViewModel.CreateInstanceCommand.Execute (null);
+ }
+
+ private class PopoverDelegate<T>
+ : NSPopoverDelegate
+ {
+ public PopoverDelegate (TaskCompletionSource<T> tcs)
+ {
+ this.tcs = tcs;
+ }
+
+ public override void WillClose (NSNotification notification)
+ {
+ this.tcs.TrySetCanceled ();
+ }
+
+ private readonly TaskCompletionSource<T> tcs;
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/PanelHeaderEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/PanelHeaderEditorControl.cs
index 0c76c5d..13ecdaf 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/PanelHeaderEditorControl.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/PanelHeaderEditorControl.cs
@@ -22,7 +22,7 @@ namespace Xamarin.PropertyEditing.Mac
NSControlSize controlSize = NSControlSize.Small;
TranslatesAutoresizingMaskIntoConstraints = false;
- this.propertyObjectName = new NSTextField {
+ this.propertyObjectName = new PropertyTextField {
ControlSize = controlSize,
PlaceholderString = LocalizationResources.ObjectNamePlaceholder,
TranslatesAutoresizingMaskIntoConstraints = false,
diff --git a/Xamarin.PropertyEditing.Mac/Controls/PredefinedValuesEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/PredefinedValuesEditor.cs
index cc7b4b0..b38237f 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/PredefinedValuesEditor.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/PredefinedValuesEditor.cs
@@ -21,22 +21,32 @@ namespace Xamarin.PropertyEditing.Mac
base.TranslatesAutoresizingMaskIntoConstraints = false;
this.comboBox = new FocusableComboBox {
- TranslatesAutoresizingMaskIntoConstraints = false,
+ AllowsExpansionToolTips = true,
BackgroundColor = NSColor.Clear,
- StringValue = String.Empty,
+ Cell = {
+ LineBreakMode = NSLineBreakMode.TruncatingTail,
+ UsesSingleLineMode = true,
+ },
ControlSize = NSControlSize.Small,
- Font = NSFont.FromFontName(DefaultFontName, DefaultFontSize),
+ Font = NSFont.FromFontName (DefaultFontName, DefaultFontSize),
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ StringValue = String.Empty,
};
this.comboBox.SelectionChanged += (sender, e) => {
- ViewModel.ValueName = comboBox.SelectedValue.ToString ();
+ ViewModel.ValueName = this.comboBox.SelectedValue.ToString ();
};
this.popUpButton = new NSPopUpButton {
- TranslatesAutoresizingMaskIntoConstraints = false,
- StringValue = String.Empty,
+ AllowsExpansionToolTips = true,
+ Cell = {
+ LineBreakMode = NSLineBreakMode.TruncatingTail,
+ UsesSingleLineMode = true,
+ },
ControlSize = NSControlSize.Small,
Font = NSFont.FromFontName (DefaultFontName, DefaultFontSize),
+ TranslatesAutoresizingMaskIntoConstraints = false,
+ StringValue = String.Empty,
};
popupButtonList = new NSMenu ();
diff --git a/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs
index efa2171..7106b79 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs
@@ -20,7 +20,6 @@ namespace Xamarin.PropertyEditing.Mac
public abstract NSView FirstKeyView { get; }
public abstract NSView LastKeyView { get; }
- public nint TableRow { get; set; } = -1;
public NSTableView TableView { get; set; }
public const int DefaultControlHeight = 22;
@@ -32,9 +31,9 @@ namespace Xamarin.PropertyEditing.Mac
PropertyViewModel viewModel;
public PropertyViewModel ViewModel {
- get { return viewModel; }
+ get { return this.viewModel; }
set {
- if (viewModel == value)
+ if (this.ViewModel == value)
return;
PropertyViewModel oldModel = this.viewModel;
@@ -45,10 +44,10 @@ namespace Xamarin.PropertyEditing.Mac
this.viewModel = value;
OnViewModelChanged (oldModel);
- viewModel.PropertyChanged += OnPropertyChanged;
-
- // FIXME: figure out what we want errors to display as (tooltip, etc.)
- viewModel.ErrorsChanged += HandleErrorsChanged;
+ if (this.viewModel != null) {
+ this.viewModel.PropertyChanged += OnPropertyChanged;
+ this.viewModel.ErrorsChanged += HandleErrorsChanged;
+ }
}
}
@@ -70,26 +69,23 @@ namespace Xamarin.PropertyEditing.Mac
public void UpdateKeyViews ()
{
- if (TableRow < 0)
+ nint row = TableView.RowForView (this);
+ if (row <= 0)
return;
+ NSView view;
PropertyEditorControl ctrl = null;
-
- var tr = TableRow;
- if (tr > 0) {
- NSView view;
- do {
- tr--;
- view = TableView.GetView (0, tr, false);
- ctrl = (view as EditorContainer)?.EditorView?.NativeView as PropertyEditorControl;
- } while (tr > 0 && ctrl == null);
-
- if (ctrl != null) {
- ctrl.LastKeyView.NextKeyView = FirstKeyView;
- ctrl.UpdateKeyViews ();
- } else if (tr == 0 && view is PanelHeaderEditorControl header) {
- header.SetNextKeyView (FirstKeyView);
- }
+ do {
+ row--;
+ view = TableView.GetView (0, row, makeIfNecessary: false);
+ ctrl = (view as EditorContainer)?.EditorView?.NativeView as PropertyEditorControl;
+ } while (row > 0 && ctrl == null);
+
+ if (ctrl != null) {
+ ctrl.LastKeyView.NextKeyView = FirstKeyView;
+ ctrl.UpdateKeyViews ();
+ } else if (row == 0 && view is PanelHeaderEditorControl header) {
+ header.SetNextKeyView (FirstKeyView);
}
}
@@ -103,11 +99,12 @@ namespace Xamarin.PropertyEditing.Mac
protected virtual void OnViewModelChanged (PropertyViewModel oldModel)
{
- SetEnabled ();
- UpdateValue ();
- UpdateAccessibilityValues ();
+ if (ViewModel != null) {
+ SetEnabled ();
+ UpdateValue ();
+ UpdateAccessibilityValues ();
+ }
- // Hook this up so we know when to reset values
PropertyButton.ViewModel = viewModel;
}
diff --git a/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs
index 75f46d4..b3b2efe 100644
--- a/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs
+++ b/Xamarin.PropertyEditing.Mac/Controls/StringEditorControl.cs
@@ -27,7 +27,7 @@ namespace Xamarin.PropertyEditing.Mac
public StringEditorControl (IHostResourceProvider hostResource)
: base (hostResource)
{
- this.stringEditor = new NSTextField {
+ this.stringEditor = new PropertyTextField {
BackgroundColor = NSColor.Clear,
ControlSize = NSControlSize.Small,
Font = NSFont.FromFontName (DefaultFontName, DefaultFontSize),
@@ -65,6 +65,11 @@ namespace Xamarin.PropertyEditing.Mac
protected override void OnViewModelChanged (PropertyViewModel oldModel)
{
+ base.OnViewModelChanged (oldModel);
+
+ if (ViewModel == null)
+ return;
+
if (ViewModel.HasInputModes) {
if (this.inputModePopup == null) {
this.inputModePopup = new NSPopUpButton {
@@ -101,8 +106,6 @@ namespace Xamarin.PropertyEditing.Mac
// If we are reusing the control we'll have to hid the inputMode if this doesn't have InputMode.
if (this.inputModePopup != null)
this.inputModePopup.Hidden = !ViewModel.HasInputModes;
-
- base.OnViewModelChanged (oldModel);
}
protected override void UpdateErrorsDisplayed (IEnumerable errors)
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<TypeSelectorViewModel>
+ {
+ 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<string, SimpleCollectionView> 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<string, SimpleCollectionView> 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<string, SimpleCollectionView> 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/Controls/TypeSelectorWindow.cs b/Xamarin.PropertyEditing.Mac/Controls/TypeSelectorWindow.cs
new file mode 100644
index 0000000..de4da3c
--- /dev/null
+++ b/Xamarin.PropertyEditing.Mac/Controls/TypeSelectorWindow.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using AppKit;
+using CoreGraphics;
+
+using Xamarin.PropertyEditing.ViewModels;
+
+namespace Xamarin.PropertyEditing.Mac
+{
+ internal class TypeSelectorWindow
+ : NSWindow
+ {
+ public TypeSelectorWindow (TypeSelectorViewModel viewModel)
+ : base (new CGRect (0, 0, 300, 300), NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Resizable, NSBackingStore.Buffered, true)
+ {
+ Title = Properties.Resources.SelectObjectTitle;
+
+ this.selector = new TypeSelectorControl {
+ ViewModel = viewModel,
+ TranslatesAutoresizingMaskIntoConstraints = false
+ };
+
+ ContentView.AddSubview (this.selector);
+
+ this.ok = NSButton.CreateButton (Properties.Resources.OK, OnOked);
+ this.ok.TranslatesAutoresizingMaskIntoConstraints = false;
+ ContentView.AddSubview (this.ok);
+
+ this.cancel = NSButton.CreateButton (Properties.Resources.Cancel, OnCanceled);
+ this.cancel.TranslatesAutoresizingMaskIntoConstraints = false;
+ ContentView.AddSubview (this.cancel);
+
+ ContentView.AddConstraints (new[] {
+ NSLayoutConstraint.Create (this.selector, NSLayoutAttribute.Width, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Width, 1, -20),
+ NSLayoutConstraint.Create (this.selector, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Top, 1, 0),
+ NSLayoutConstraint.Create (this.selector, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.CenterX, 1, 0),
+ NSLayoutConstraint.Create (this.selector, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this.ok, NSLayoutAttribute.Top, 1, -10),
+
+ NSLayoutConstraint.Create (this.ok, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Bottom, 1, -10),
+ NSLayoutConstraint.Create (this.ok, NSLayoutAttribute.Right, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Right, 1, -10),
+
+ NSLayoutConstraint.Create (this.cancel, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this.ok, NSLayoutAttribute.Left, 1, -10),
+ NSLayoutConstraint.Create (this.cancel, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Bottom, 1, -10),
+ });
+ }
+
+ private TypeSelectorControl selector;
+ private NSButton ok, cancel;
+
+ private void OnOked ()
+ {
+ NSApplication.SharedApplication.StopModalWithCode ((int)NSModalResponse.OK);
+ Close ();
+ }
+
+ private void OnCanceled ()
+ {
+ NSApplication.SharedApplication.StopModalWithCode ((int)NSModalResponse.Cancel);
+ Close ();
+ }
+
+ public static ITypeInfo RequestType (AsyncValue<IReadOnlyDictionary<IAssemblyInfo, ILookup<string, ITypeInfo>>> assignableTypes)
+ {
+ var w = new TypeSelectorWindow (new TypeSelectorViewModel (assignableTypes));
+
+ var result = (NSModalResponse)(int)NSApplication.SharedApplication.RunModalForWindow (w);
+ if (result != NSModalResponse.OK)
+ return null;
+
+ return w.selector.ViewModel.SelectedType;
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Mac/PropertyEditorPanel.cs b/Xamarin.PropertyEditing.Mac/PropertyEditorPanel.cs
index 1b6d71a..1494549 100644
--- a/Xamarin.PropertyEditing.Mac/PropertyEditorPanel.cs
+++ b/Xamarin.PropertyEditing.Mac/PropertyEditorPanel.cs
@@ -175,17 +175,16 @@ namespace Xamarin.PropertyEditing.Mac
((NSView)this.header.ContentView).AddSubview (this.tabStack);
this.propertyTable = new FirstResponderOutlineView {
+ IndentationPerLevel = 0,
RefusesFirstResponder = true,
SelectionHighlightStyle = NSTableViewSelectionHighlightStyle.None,
HeaderView = null,
+ IntercellSpacing = new CGSize (0, 0)
};
var propertyEditors = new NSTableColumn (PropertyEditorColId);
this.propertyTable.AddColumn (propertyEditors);
- // Set OutlineTableColumn or the arrows showing children/expansion will not be drawn
- this.propertyTable.OutlineTableColumn = propertyEditors;
-
var tableContainer = new NSScrollView {
TranslatesAutoresizingMaskIntoConstraints = false,
};
@@ -278,18 +277,6 @@ namespace Xamarin.PropertyEditing.Mac
{
return true;
}
-
- public override CGRect GetCellFrame (nint column, nint row)
- {
- var super = base.GetCellFrame (column, row);
- if (column == 0) {
- var obj = (NSObjectFacade)ItemAtRow (row);
- if (obj.Target is PropertyGroupViewModel)
- return new CGRect (0, super.Top, super.Right - (super.Left / 2), super.Height);
- }
-
- return super;
- }
}
}
} \ No newline at end of file
diff --git a/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs b/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs
index d3a7398..cb96191 100644
--- a/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs
+++ b/Xamarin.PropertyEditing.Mac/PropertyEditorSelector.cs
@@ -54,6 +54,8 @@ namespace Xamarin.PropertyEditing.Mac
{typeof (RatioViewModel), typeof (RatioEditorControl<CommonRatio>)},
{typeof (ThicknessPropertyViewModel), typeof (CommonThicknessEditorControl) },
{typeof (PropertyGroupViewModel), typeof (GroupEditorControl)},
+ {typeof (ObjectPropertyViewModel), typeof (ObjectEditorControl)},
+
};
}
}
diff --git a/Xamarin.PropertyEditing.Mac/PropertyTableDataSource.cs b/Xamarin.PropertyEditing.Mac/PropertyTableDataSource.cs
index da40034..2c0e403 100644
--- a/Xamarin.PropertyEditing.Mac/PropertyTableDataSource.cs
+++ b/Xamarin.PropertyEditing.Mac/PropertyTableDataSource.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using AppKit;
using Foundation;
@@ -27,8 +28,11 @@ namespace Xamarin.PropertyEditing.Mac
if (this.vm.ArrangedEditors.Count == 0)
return 0;
- var childCount = 0;
+ var facade = (NSObjectFacade)item;
+ if (facade?.Target is ObjectPropertyViewModel ovm)
+ return ovm.ValueModel.Properties.Count;
+ var childCount = 0;
if (this.vm.ArrangeMode == PropertyArrangeMode.Name)
childCount = Filtering ? this.vm.ArrangedEditors[0].Editors.Count : this.vm.ArrangedEditors[0].Editors.Count + 1;
else {
@@ -47,17 +51,20 @@ namespace Xamarin.PropertyEditing.Mac
{
object element;
+ var f = ((NSObjectFacade)item);
// We only want the Header to appear at the top of both Category and Name Modes, which means item is null in both.
if (childIndex == 0 && item == null && !Filtering)
element = null;
- else {
+ else if (f?.Target is ObjectPropertyViewModel ovm) {
+ element = ovm.ValueModel.Properties[(int)childIndex];
+ } else {
if (this.vm.ArrangeMode == PropertyArrangeMode.Name)
element = Filtering ? this.vm.ArrangedEditors[0].Editors[(int)childIndex] : this.vm.ArrangedEditors[0].Editors[(int)childIndex - 1];
else {
if (item == null)
element = Filtering ? this.vm.ArrangedEditors[(int)childIndex] : this.vm.ArrangedEditors[(int)childIndex - 1];
else {
- var group = (PanelGroupViewModel)((NSObjectFacade)item).Target;
+ var group = (PanelGroupViewModel)f.Target;
var list = group.Editors;
if (childIndex >= list.Count) {
childIndex -= list.Count;
@@ -74,10 +81,25 @@ namespace Xamarin.PropertyEditing.Mac
public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
{
+ var f = (NSObjectFacade)item;
+ if (f.Target is ObjectPropertyViewModel ovm) {
+ PropertyChangedEventHandler changed = null;
+ changed = (o, e) => {
+ if (e.PropertyName != nameof (ObjectPropertyViewModel.CanDelve))
+ return;
+
+ ovm.PropertyChanged -= changed;
+ outlineView.ReloadItem (item);
+ };
+ ovm.PropertyChanged += changed;
+
+ return ovm.CanDelve;
+ }
+
if (this.vm.ArrangeMode == PropertyArrangeMode.Name)
return false;
- return ((NSObjectFacade)item).Target is PanelGroupViewModel;
+ return f.Target is PanelGroupViewModel;
}
public NSObject GetFacade (object element)
diff --git a/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs b/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs
index 92e4382..bce86c0 100644
--- a/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs
+++ b/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs
@@ -53,14 +53,30 @@ namespace Xamarin.PropertyEditing.Mac
GetVMGroupCellItendifiterFromFacade (item, out evm, out group, out cellIdentifier);
if (group != null) {
- var labelContainer = (UnfocusableTextField)outlineView.MakeView (LabelIdentifier, this);
+ var labelContainer = (NSView)outlineView.MakeView (CategoryIdentifier, this);
if (labelContainer == null) {
- labelContainer = new UnfocusableTextField {
- Identifier = LabelIdentifier,
+ labelContainer = new NSView {
+ Identifier = CategoryIdentifier,
};
+
+ var disclosure = outlineView.MakeView ("NSOutlineViewDisclosureButtonKey", outlineView);
+ disclosure.TranslatesAutoresizingMaskIntoConstraints = false;
+ labelContainer.AddSubview (disclosure);
+
+ var label = new UnfocusableTextField {
+ TranslatesAutoresizingMaskIntoConstraints = false
+ };
+ labelContainer.AddSubview (label);
+
+ labelContainer.AddConstraints (new[] {
+ NSLayoutConstraint.Create (disclosure, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.CenterY, 1, 0),
+ NSLayoutConstraint.Create (disclosure, NSLayoutAttribute.Left, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.Left, 1, 4),
+ NSLayoutConstraint.Create (label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, disclosure, NSLayoutAttribute.Right, 1, 0),
+ NSLayoutConstraint.Create (label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, labelContainer, NSLayoutAttribute.Height, 1, 0),
+ });
}
- labelContainer.StringValue = group.Category;
+ ((UnfocusableTextField)labelContainer.Subviews[1]).StringValue = group.Category;
if (this.dataSource.DataContext.GetIsExpanded (group.Category)) {
SynchronizationContext.Current.Post (s => {
@@ -74,14 +90,14 @@ namespace Xamarin.PropertyEditing.Mac
NSView editorOrContainer = null;
if (this.firstCache.TryGetValue (cellIdentifier, out IEditorView editor)) {
this.firstCache.Remove (cellIdentifier);
- editorOrContainer = (editor.NativeView is PropertyEditorControl) ? new EditorContainer (this.hostResources, editor) : editor.NativeView;
+ editorOrContainer = (editor.NativeView is PropertyEditorControl) ? new EditorContainer (this.hostResources, editor) { Identifier = cellIdentifier } : editor.NativeView;
} else {
editorOrContainer = GetEditor (cellIdentifier, evm, outlineView);
editor = ((editorOrContainer as EditorContainer)?.EditorView) ?? editorOrContainer as IEditorView;
}
if (editorOrContainer is EditorContainer ec) {
- ec.Label = evm.Name + ":";
+ ec.Label = evm.Name;
#if DEBUG // Currently only used to highlight which controls haven't been implemented
if (editor == null)
@@ -90,15 +106,29 @@ namespace Xamarin.PropertyEditing.Mac
}
if (editor != null) {
- nint index = outlineView.RowForItem (item);
- if (editor.NativeView is PropertyEditorControl pec) {
- pec.TableRow = index;
+ editor.ViewModel = evm;
+
+ var ovm = evm as ObjectPropertyViewModel;
+ if (ovm != null && editorOrContainer is EditorContainer container) {
+ if (container.LeftEdgeView == null) {
+ if (ovm.CanDelve)
+ container.LeftEdgeView = outlineView.MakeView ("NSOutlineViewDisclosureButtonKey", outlineView);
+ } else if (!ovm.CanDelve) {
+ container.LeftEdgeView = null;
+ }
}
- editor.ViewModel = evm;
+ bool openObjectRow = ovm != null && outlineView.IsItemExpanded (item);
+ if (!openObjectRow) {
+ var parent = outlineView.GetParent (item);
+ openObjectRow = (parent != null && ((NSObjectFacade)parent).Target is ObjectPropertyViewModel);
+ }
+
+ SetRowValueBackground (editorOrContainer, openObjectRow);
// Force a row update due to new height, but only when we are non-default
if (editor.IsDynamicallySized) {
+ nint index = outlineView.RowForItem (item);
outlineView.NoteHeightOfRowsWithIndexesChanged (new NSIndexSet (index));
}
} else if (editorOrContainer is PanelHeaderEditorControl header) {
@@ -115,24 +145,46 @@ namespace Xamarin.PropertyEditing.Mac
public override void ItemDidExpand (NSNotification notification)
{
- if (this.isExpanding)
+ NSObjectFacade facade = notification.UserInfo.Values[0] as NSObjectFacade;
+ var outline = (NSOutlineView)notification.Object;
+ nint row = outline.RowForItem (facade);
+
+ if (this.isExpanding) {
+ NSView view = outline.GetView (0, row, makeIfNecessary: true);
+ if (view.Subviews[0] is NSButton expander)
+ expander.State = NSCellStateValue.On;
+
return;
+ }
- NSObjectFacade facade = notification.UserInfo.Values[0] as NSObjectFacade;
- var group = facade.Target as PanelGroupViewModel;
- if (group != null)
+ if (facade.Target is PanelGroupViewModel group)
this.dataSource.DataContext.SetIsExpanded (group.Category, isExpanded: true);
+ else if (facade.Target is ObjectPropertyViewModel ovm) {
+ NSView view = outline.GetView (0, row, makeIfNecessary: false);
+ SetRowValueBackground (view, valueBackground: true);
+ }
}
public override void ItemDidCollapse (NSNotification notification)
{
- if (this.isExpanding)
+ NSObjectFacade facade = notification.UserInfo.Values[0] as NSObjectFacade;
+ var outline = (NSOutlineView)notification.Object;
+ nint row = outline.RowForItem (facade);
+
+ if (this.isExpanding) {
+ NSView view = outline.GetView (0, row, makeIfNecessary: true);
+ if (view.Subviews[0] is NSButton expander)
+ expander.State = NSCellStateValue.Off;
+
return;
+ }
- NSObjectFacade facade = notification.UserInfo.Values[0] as NSObjectFacade;
- var group = facade.Target as PanelGroupViewModel;
- if (group != null)
+ if (facade.Target is PanelGroupViewModel group)
this.dataSource.DataContext.SetIsExpanded (group.Category, isExpanded: false);
+ else if (facade.Target is ObjectPropertyViewModel ovm) {
+ NSView view = outline.GetView (0, row, makeIfNecessary: false);
+ SetRowValueBackground (view, valueBackground: false);
+ }
}
public override nfloat GetRowHeight (NSOutlineView outlineView, NSObject item)
@@ -187,7 +239,7 @@ namespace Xamarin.PropertyEditing.Mac
}
}
- public const string LabelIdentifier = "label";
+ public const string CategoryIdentifier = "label";
private PropertyTableDataSource dataSource;
private bool isExpanding;
@@ -197,6 +249,25 @@ namespace Xamarin.PropertyEditing.Mac
private readonly Dictionary<string, EditorRegistration> registrations = new Dictionary<string, EditorRegistration> ();
private readonly Dictionary<string, IEditorView> firstCache = new Dictionary<string, IEditorView> ();
+ private NSView GetViewForItem (NSOutlineView outline, NSObjectFacade facade)
+ {
+ nint row = outline.RowForItem (facade);
+ return outline.GetView (0, row, false);
+ }
+
+ private void SetRowValueBackground (NSView view, bool valueBackground)
+ {
+ if (view == null)
+ return;
+
+ if (valueBackground) {
+ var c = this.hostResources.GetNamedColor (NamedResources.ValueBlockBackgroundColor);
+ view.SetValueForKey (c, new NSString ("backgroundColor"));
+ } else {
+ view.SetValueForKey (NSColor.Clear, new NSString ("backgroundColor"));
+ }
+ }
+
private NSView GetEditor (string identifier, EditorViewModel vm, NSOutlineView outlineView)
{
var view = outlineView.MakeView (identifier, this);
diff --git a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj
index 8277ff5..ef68417 100644
--- a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj
+++ b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj
@@ -145,6 +145,10 @@
<Compile Include="Controls\Custom\DynamicFillBox.cs" />
<Compile Include="Controls\Custom\TabButton.cs" />
<Compile Include="Controls\Custom\FocusableComboBox.cs" />
+ <Compile Include="Controls\ObjectEditorControl.cs" />
+ <Compile Include="Controls\TypeSelectorControl.cs" />
+ <Compile Include="Controls\TypeSelectorWindow.cs" />
+ <Compile Include="Controls\Custom\PropertyTextField.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controls\" />