diff options
author | Alex Corrado <alexc@xamarin.com> | 2020-03-05 17:29:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-05 17:29:13 +0300 |
commit | a2750e5370917f910c332e73ad6091a5b92f5c8a (patch) | |
tree | 16c2580d01b22d18fbe03258d5a54b9afe2b03f8 | |
parent | fa6feaed8a01161215daf68b85369f414909e2e7 (diff) | |
parent | f96ad43f7cdd5753ec016faabe6ed10111c67af7 (diff) |
Merge pull request #713 from xamarin/d16-5-backportsd16-5
[d16-5] Backports of #704, #672, #706
28 files changed, 474 insertions, 366 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/BrushEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/BrushEditorControl.cs index c0e6344..cb8bc44 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/BrushEditorControl.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/BrushEditorControl.cs @@ -1,8 +1,11 @@ using System; using System.Collections; using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; using AppKit; using CoreGraphics; +using Foundation; using Xamarin.PropertyEditing.Drawing; using Xamarin.PropertyEditing.ViewModels; @@ -19,17 +22,14 @@ namespace Xamarin.PropertyEditing.Mac if (!Popover.Shown) { Popover.Show (new CGRect (26, this.Frame.Height / 2 - 2, 2, 2), this, NSRectEdge.MinYEdge); - Window.MakeFirstResponder (this); - Window.MakeFirstResponder (Popover); } } public override void KeyDown (NSEvent theEvent) { - if (theEvent.KeyCode == 36 || theEvent.KeyCode == 49) { + if (theEvent.KeyCode == (ushort)NSKey.Space) { MouseDown (theEvent); - } - else { + } else { base.KeyDown (theEvent); } } @@ -46,8 +46,7 @@ namespace Xamarin.PropertyEditing.Mac Frame = new CGRect (0, 0, 30, 10) }; - this.popover = new NSPopover { - Behavior = NSPopoverBehavior.Transient, + this.popover = new AutoClosePopOver (hostResources, hostResources.GetVibrantAppearance (EffectiveAppearance)) { ContentViewController = this.brushTabViewController = new BrushTabViewController (hostResources) { PreferredContentSize = new CGSize (550, 363) } diff --git a/Xamarin.PropertyEditing.Mac/Controls/CategoryContainerControl.cs b/Xamarin.PropertyEditing.Mac/Controls/CategoryContainerControl.cs new file mode 100644 index 0000000..dfec28e --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/CategoryContainerControl.cs @@ -0,0 +1,44 @@ +using System; +using AppKit; + +namespace Xamarin.PropertyEditing.Mac +{ + internal class CategoryContainerControl + : PropertyEditorControl + { + private NSOutlineView outlineView; + private NSButton disclosure; + + public CategoryContainerControl (IHostResourceProvider hostResources, NSOutlineView outlineView) : base (hostResources) + { + if (outlineView == null) + throw new ArgumentNullException (nameof (outlineView)); + + this.outlineView = outlineView; + + this.disclosure = this.outlineView.MakeView ("NSOutlineViewDisclosureButtonKey", outlineView) as NSButton; + this.disclosure.TranslatesAutoresizingMaskIntoConstraints = false; + AddSubview (this.disclosure); + + var label = new UnfocusableTextField { + TranslatesAutoresizingMaskIntoConstraints = false + }; + AddSubview (label); + + AddConstraints (new[] { + NSLayoutConstraint.Create (this.disclosure, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this, NSLayoutAttribute.CenterY, 1, 0), + NSLayoutConstraint.Create (this.disclosure, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 4), + NSLayoutConstraint.Create (label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.disclosure, NSLayoutAttribute.Right, 1, 0), + NSLayoutConstraint.Create (label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this, NSLayoutAttribute.Height, 1, 0), + }); + } + + public override bool IsDynamicallySized => false; + + public override bool NeedsPropertyButton => false; + + public override NSView FirstKeyView => this.disclosure; + + public override NSView LastKeyView => this.disclosure; + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/ControlExtensions.cs b/Xamarin.PropertyEditing.Mac/Controls/ControlExtensions.cs index cad49a8..cd51e74 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/ControlExtensions.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/ControlExtensions.cs @@ -26,15 +26,13 @@ namespace Xamarin.PropertyEditing.Mac } }; - var popover = new NSPopover { - Behavior = NSPopoverBehavior.Transient, + var popover = new AutoClosePopOver (hostResources, hostResources.GetVibrantAppearance (source.EffectiveAppearance)) { Delegate = new PopoverDelegate<ITypeInfo> (tcs), ContentViewController = new NSViewController { View = selector, PreferredContentSize = new CoreGraphics.CGSize (360, 335) }, }; - popover.SetAppearance (hostResources.GetVibrantAppearance (source.EffectiveAppearance)); tcs.Task.ContinueWith (t => { // Focus back to the button that popped us up diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/AutoClosePopOver.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/AutoClosePopOver.cs index f3a25ac..bb1fafd 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/AutoClosePopOver.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/AutoClosePopOver.cs @@ -1,5 +1,6 @@ using System; using AppKit; +using Foundation; namespace Xamarin.PropertyEditing.Mac { @@ -17,6 +18,7 @@ namespace Xamarin.PropertyEditing.Mac this.hostResources = hostResources; Behavior = NSPopoverBehavior.Semitransient; + Delegate = new PopoverFocusRestoreDelegate (); CloseOnEnter = true; this.SetAppearance (this.hostResources.GetVibrantAppearance (effectiveAppearance)); diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs index 9430e25..c55e2c6 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs @@ -24,8 +24,8 @@ namespace Xamarin.PropertyEditing.Mac ContentPadding = new NSEdgeInsets (8, 8, 8, 8);
this.filterResource = new NSSearchField {
- ControlSize = NSControlSize.Mini,
- Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Mini)),
+ ControlSize = NSControlSize.Small,
+ Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Small)),
PlaceholderString = Properties.Resources.SearchResourcesTitle,
};
@@ -107,7 +107,7 @@ namespace Xamarin.PropertyEditing.Mac this.resource.ViewModel = ViewModel; item.ViewController = this.resource; item.ToolTip = Properties.Resources.ResourceBrush; - image = "pe-property-brush-resources-16";
+ image = "pe-property-brush-resources-16";
break;
case CommonBrushType.Gradient: @@ -158,8 +158,9 @@ namespace Xamarin.PropertyEditing.Mac public override void WillSelect (NSTabView tabView, NSTabViewItem item) { - if (item.ViewController is NotifyingViewController<BrushPropertyViewModel> brushController) + if (item.ViewController is NotifyingViewController<BrushPropertyViewModel> brushController) { brushController.ViewModel = ViewModel; + } if (this.inhibitSelection) return; @@ -174,13 +175,25 @@ namespace Xamarin.PropertyEditing.Mac ViewModel.SelectedBrushType = ViewModel.BrushTypes[item.Label]; this.filterResource.Hidden = ViewModel.SelectedBrushType != CommonBrushType.Resource; + if (!this.filterResource.Hidden) { + if (Selected is TabButton tb) { + tb.NextKeyView = this.filterResource; + item.View.Window?.MakeFirstResponder (this.filterResource); + if (item.View.Subviews.Length > 1 + && item.View.Subviews[1].Subviews.Length > 0 + && item.View.Subviews[1].Subviews[0] is NSOutlineView rov) { + rov.NextKeyView = this.filterResource.NextKeyView; + this.filterResource.NextKeyView = rov; + } + } + } base.DidSelect (tabView, item); } public override void ViewDidLoad () { - View.Frame = new CGRect (0, 0, 430, 230); + View.Frame = new CGRect (0, 0, NotifyingViewController<BrushPropertyViewModel>.PreferredContentSizeWidth, NotifyingViewController<BrushPropertyViewModel>.PreferredContentSizeHeight); this.inhibitSelection = true; base.ViewDidLoad (); diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs index 30c43b6..47caf85 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs @@ -31,11 +31,11 @@ namespace Xamarin.PropertyEditing.Mac Initialize (hostResources); } - private ChannelGroup [] Editors { get; set; } + internal ChannelGroup [] Editors { get; set; } private UnfocusableTextField hexLabel; private NSTextField hexEditor; - class ChannelGroup + internal class ChannelGroup { public UnfocusableTextField Label { get; set; } public ComponentSpinEditor Editor { get; set; } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentTabViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentTabViewController.cs index 532b9ec..abe4f96 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentTabViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentTabViewController.cs @@ -68,5 +68,14 @@ namespace Xamarin.PropertyEditing.Mac var controller = item.ViewController as ColorComponentViewController; EditorType = controller.EditorType; } + + public override void ViewDidLayout () + { + base.ViewDidLayout (); + + if (Selected is TabButton tb) { + View.Window?.MakeFirstResponder (tb); + } + } } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs index c8dbbef..988c9cd 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs @@ -19,7 +19,7 @@ namespace Xamarin.PropertyEditing.Mac Color0 = c0, Color1 = c1, Width = (float)Math.Min (frame.Height / 2f, 10), - Center = new CIVector (new nfloat [] { 0, 0 }), + Center = new CIVector (new nfloat[] { 0, 0 }), }) { using (var context = new CIContext (null)) { return context.CreateCGImage (board.OutputImage, new CGRect (0, 0, frame.Width, frame.Height)); diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs index f355eb9..71a56bc 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs @@ -4,18 +4,18 @@ using Xamarin.PropertyEditing.ViewModels; namespace Xamarin.PropertyEditing.Mac { - class EmptyBrushEditorViewController : NotifyingViewController<BrushPropertyViewModel> + internal class EmptyBrushEditorViewController : NotifyingViewController<BrushPropertyViewModel> { public EmptyBrushEditorViewController () { - PreferredContentSize = new CGSize (430, 230); + PreferredContentSize = new CGSize (PreferredContentSizeWidth, PreferredContentSizeHeight); } private NSButton brushEditor; public override void LoadView () { - View = brushEditor = new NSButton { + View = this.brushEditor = new NSButton { Bordered = false, Title = Properties.Resources.NoBrush, Enabled = false diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs index 5920c75..e34af27 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs @@ -16,7 +16,7 @@ namespace Xamarin.PropertyEditing.Mac throw new ArgumentNullException (nameof (hostResources)); this.hostResources = hostResources; - PreferredContentSize = new CGSize (430, 230); + PreferredContentSize = new CGSize (PreferredContentSizeWidth, PreferredContentSizeHeight); } public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) @@ -65,7 +65,7 @@ namespace Xamarin.PropertyEditing.Mac alphaLabel.Cell.LineBreakMode = NSLineBreakMode.Clipping; alphaStack.AddView (alphaLabel, NSStackViewGravity.Trailing); - alphaStack.AddView (alphaSpinEditor, NSStackViewGravity.Trailing); + alphaStack.AddView (this.alphaSpinEditor, NSStackViewGravity.Trailing); stack.AddView (this.materialEditor, NSStackViewGravity.Leading); stack.AddView (alphaStack, NSStackViewGravity.Trailing); @@ -73,6 +73,20 @@ namespace Xamarin.PropertyEditing.Mac View = stack; } + public override void ViewDidLayout () + { + base.ViewDidLayout (); + + var window = View.Window; + window?.RecalculateKeyViewLoop (); + + if (this.materialEditor.Subviews.Length > 0 + && (this.materialEditor.SelectedButton ?? this.materialEditor.Subviews[0]) is FocusableButton fb + && fb.CanBecomeKeyView) { + window?.MakeFirstResponder (fb); + } + } + private readonly IHostResourceProvider hostResources; private MaterialView materialEditor; diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs index d65aec1..45a93b3 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs @@ -13,40 +13,31 @@ namespace Xamarin.PropertyEditing.Mac { internal class MaterialView : NotifyingView<MaterialDesignColorViewModel> { - public override bool IsFlipped => true; - - public MaterialView () + public override bool AcceptsFirstResponder () { - Initialize (); + return false; } - private void Initialize () - { - WantsLayer = true; - } + public override bool IsFlipped => true; + + public FocusableButton SelectedButton { get; private set; } public override void OnViewModelChanged (MaterialDesignColorViewModel oldModel) { - NeedsLayout = true; - } + base.OnViewModelChanged (oldModel); - public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) - { - switch (e.PropertyName) { - case nameof (ViewModel.ColorName): - case nameof (ViewModel.AccentColor): - case nameof (ViewModel.NormalColor): - NeedsLayout = true; - break; - } + CreateColourPallette (); } - public override void Layout () + private void CreateColourPallette () { - if (Layer?.Sublayers != null) { - foreach (var l in Layer.Sublayers) { - l.RemoveFromSuperLayer (); - l.Dispose (); + var subViews = Subviews; + if (subViews.Length > 0) { + foreach (var sv in subViews) { + if (sv is FocusableButton fb) + fb.Activated -= MaterialColourButton_Activated; + sv.RemoveFromSuperview (); + sv.Dispose (); } } @@ -57,8 +48,11 @@ namespace Xamarin.PropertyEditing.Mac int col = 0; nfloat x = 0; nfloat y = 6; - var width = (Frame.Width - 54) / 10; - var height = (Frame.Height - 49) / 4; + const int FrameWidth = 430; // TODO Get proper Frame.Width, but hacking to get this working + const int FrameHeight = 202; // TODO Get proper Frame.Height, but hacking to get this working + var width = (FrameWidth - 54) / 10; + var height = (FrameHeight - 49) / 4; + MaterialColorLayer CreateLayer (CommonColor color) { @@ -76,20 +70,32 @@ namespace Xamarin.PropertyEditing.Mac foreach (var p in colors) { var frame = new CGRect (x, y, width, height); var selectedColor = p.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White; + var isSelected = ViewModel.Color == p.Color || ViewModel.ColorName == p.Name; var l = new MaterialColorLayer { - Frame = frame, + Frame = new CGRect (0, 0, width, height), ForegroundColor = selectedColor.CGColor, BackgroundColor = p.Color, CornerRadius = 3, BorderColor = new CGColor (.5f, .5f, .5f, .5f), MasksToBounds = false, - IsSelected = ViewModel.Color == p.Color || ViewModel.ColorName == p.Name + IsSelected = isSelected + }; + + var materialColourButton = new FocusableButton { + Frame = frame, + WantsLayer = true, + Layer = l, + ToolTip = p.Name, + Transparent = false, + TranslatesAutoresizingMaskIntoConstraints = true, }; + if (isSelected) + SelectedButton = materialColourButton; + + materialColourButton.Activated += MaterialColourButton_Activated; + + AddSubview (materialColourButton); - l.BorderColor = new CGColor (.5f, .5f, .5f, .5f); - l.Frame = new CGRect (x, y, width, height); - Layer.AddSublayer (l); - AddToolTip (new CGRect (x, y, width, height), new NSString(p.Name), IntPtr.Zero); x += width + 6; col++; if (col >= 10) { @@ -99,90 +105,118 @@ namespace Xamarin.PropertyEditing.Mac } } - Layer.AddSublayer (new CATextLayer { - ForegroundColor = NSColor.ControlText.CGColor, - Frame = new CGRect (x, y + 6, Frame.Width, 25), - String = ViewModel.ColorName, - FontSize = NSFont.SmallSystemFontSize, - ContentsScale = Window?.Screen?.BackingScaleFactor ?? NSScreen.MainScreen.BackingScaleFactor - }); + var colourName = new UnfocusableTextField { + Frame = new CGRect (x, y + 6, FrameWidth, PropertyEditorControl.DefaultControlHeight), + StringValue = ViewModel.ColorName, + TranslatesAutoresizingMaskIntoConstraints = true, + }; + + AddSubview (colourName); y += 25; x = 0; - width = Frame.Width / ViewModel.NormalColorScale.Count (); - var normal = new CALayer { - CornerRadius = 3, - MasksToBounds = true, - Frame = new CGRect (x, y, Frame.Width, height), - BorderColor = new CGColor (.5f, .5f, .5f, .5f), - BorderWidth = 1 - }; - Layer.AddSublayer (normal); + width = FrameWidth / ViewModel.NormalColorScale.Count (); + foreach (var color in ViewModel.NormalColorScale) { var l = CreateLayer (color.Value); + var isSelected = color.Value == ViewModel.NormalColor || color.Value == ViewModel.Color; l.ColorType = MaterialColorType.Normal; - l.IsSelected = color.Value == ViewModel.NormalColor || color.Value == ViewModel.Color; - l.Frame = new CGRect (x, 0, width, height); - AddToolTip (new CGRect (x, y, width, height), new NSString (color.ToString ()), IntPtr.Zero); - normal.AddSublayer (l); + l.IsSelected = isSelected; + l.Frame = new CGRect (0, 0, width, height); + + var normalColourButton = new FocusableButton { + Frame = new CGRect (x, y, width, height), + WantsLayer = true, + Layer = l, + ToolTip = color.ToString (), + Transparent = false, + TranslatesAutoresizingMaskIntoConstraints = true, + }; + if (isSelected) + SelectedButton = normalColourButton; + + normalColourButton.Activated += MaterialColourButton_Activated; + + AddSubview (normalColourButton); + x += width; } - if (ViewModel.AccentColorScale.Count () <= 0) + var window = Window; + if (!ViewModel.AccentColorScale.Any ()) { + if (window != null) { + window.RecalculateKeyViewLoop (); // Still needs to be called for the Buttons above. + if (SelectedButton != null) + window.MakeFirstResponder (SelectedButton); + } return; + } y += height + 6; x = 0; - var accent = new CALayer { - CornerRadius = 3, - MasksToBounds = true, - Frame = new CGRect (x, y, Frame.Width, height), - BorderColor = new CGColor (.5f, .5f, .5f, .5f), - BorderWidth = 1 - }; - Layer.AddSublayer (accent); - width = Frame.Width / ViewModel.AccentColorScale.Count (); + width = FrameWidth / ViewModel.AccentColorScale.Count (); foreach (var color in ViewModel.AccentColorScale) { var l = CreateLayer (color.Value); + var isSelected = color.Value == ViewModel.AccentColor || color.Value == ViewModel.Color; l.ColorType = MaterialColorType.Accent; - l.IsSelected = color.Value == ViewModel.AccentColor || color.Value == ViewModel.Color; - l.Frame = new CGRect (x, 0, width, height); - AddToolTip (new CGRect (x, y, width, height), new NSString (color.ToString ()), IntPtr.Zero); - accent.AddSublayer (l); + l.IsSelected = isSelected; + l.Frame = new CGRect (0, 0, width, height); + + var accentColourButton = new FocusableButton { + Frame = new CGRect (x, y, width, height), + WantsLayer = true, + Layer = l, + ToolTip = color.ToString (), + Transparent = false, + TranslatesAutoresizingMaskIntoConstraints = true, + }; + if (isSelected) + SelectedButton = accentColourButton; + + accentColourButton.Activated += MaterialColourButton_Activated; + + AddSubview (accentColourButton); + x += width; } + + if (window != null) { + window.RecalculateKeyViewLoop (); + if (SelectedButton != null) + window.MakeFirstResponder (SelectedButton); + } } - public override void MouseDown (NSEvent theEvent) + private void MaterialColourButton_Activated (object sender, EventArgs e) { - UpdateFromEvent (theEvent); + var button = sender as FocusableButton; + var editor = button?.Layer as MaterialColorLayer; + + if (editor != null) { + switch (editor.ColorType) { + case MaterialColorType.Accent: + ViewModel.AccentColor = editor.BackgroundColor; + break; + case MaterialColorType.Normal: + ViewModel.NormalColor = editor.BackgroundColor; + break; + case MaterialColorType.Palette: + var match = ViewModel.Palettes.First (palette => palette.MainColor == editor.BackgroundColor); + ViewModel.ColorName = match.Name; + break; + } + } } - public void UpdateFromEvent (NSEvent theEvent) + public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) { - var location = ConvertPointToLayer (ConvertPointFromView (theEvent.LocationInWindow, null)); - - foreach (var layer in Layer.Sublayers) { - var hit = layer.HitTest (location); - for (var c = hit; c != null; c = c.SuperLayer) { - var editor = c as MaterialColorLayer; - if (editor != null) { - switch (editor.ColorType) { - case MaterialColorType.Accent: - ViewModel.AccentColor = editor.BackgroundColor; - break; - case MaterialColorType.Normal: - ViewModel.NormalColor = editor.BackgroundColor; - break; - case MaterialColorType.Palette: - var match = ViewModel.Palettes.First (palette => palette.MainColor == editor.BackgroundColor); - ViewModel.ColorName = match.Name; - break; - } - NeedsLayout = true; - } - } + switch (e.PropertyName) { + case nameof (ViewModel.ColorName): + case nameof (ViewModel.AccentColor): + case nameof (ViewModel.NormalColor): + CreateColourPallette (); + break; } } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/NotifyingViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/NotifyingViewController.cs index c572a27..e79e46f 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/NotifyingViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/NotifyingViewController.cs @@ -12,6 +12,9 @@ namespace Xamarin.PropertyEditing.Mac { internal class NotifyingViewController<T> : NSViewController, INotifyingListner<T> where T : NotifyingObject { + internal const int PreferredContentSizeWidth = 430; + internal const int PreferredContentSizeHeight = 230; + internal T ViewModel { get => Adaptor.ViewModel; set => Adaptor.ViewModel = value; diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericSpinEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericSpinEditor.cs index e7ddd5d..831dfff 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericSpinEditor.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericSpinEditor.cs @@ -224,7 +224,7 @@ namespace Xamarin.PropertyEditing.Mac AddSubview (this.incrementButton); AddSubview (this.decrementButton); - this.AddConstraints (new[] { + AddConstraints (new[] { NSLayoutConstraint.Create (this.numericEditor, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1f, 0), NSLayoutConstraint.Create (this.numericEditor, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1f, 18), diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs index 22211fa..4c215b7 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/NumericTextField.cs @@ -8,6 +8,8 @@ namespace Xamarin.PropertyEditing.Mac { internal class NumericTextField : PropertyTextField { + public override bool CanBecomeKeyView { get { return Enabled; } } + private NSText CachedCurrentEditor { get; set; } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/PopoverFocusRestoreDelegate.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/PopoverFocusRestoreDelegate.cs new file mode 100644 index 0000000..f8283f0 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/PopoverFocusRestoreDelegate.cs @@ -0,0 +1,59 @@ +using System; +using AppKit; +using Foundation; + +namespace Xamarin.PropertyEditing.Mac +{ + internal class PopoverFocusRestoreDelegate : NSPopoverDelegate + { + static readonly NSString key = new NSString ("firstResponder"); + + private bool ignore; + private NSResponder prevFirstResponder; + + public PopoverFocusRestoreDelegate () + { + } + + public override void DidShow (NSNotification notification) + { + this.ignore = false; + var window = ((NSPopover)notification.Object).ContentViewController.View.Window; + + if (this.prevFirstResponder != null) { + window.MakeFirstResponder (this.prevFirstResponder); + } else { + window.AddObserver (this, key, NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.New, IntPtr.Zero); + } + } + + public override void WillClose (NSNotification notification) + { + this.ignore = true; + } + + public override void ObserveValue (NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) + { + var window = ofObject as NSWindow; + if (window != null && keyPath == key) { + if (!ignore) { + var firstResponder = change [ChangeNewKey] as NSResponder; + if (firstResponder != null && !(firstResponder is NSWindow) && (!(firstResponder is NSView view) || view.Window == window)) + this.prevFirstResponder = ResolveResponder (firstResponder); + } + } else { + base.ObserveValue (keyPath, ofObject, change, context); + } + } + + // See first paragraph under "How the Field Editor Works" + // https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TextEditing/TextEditing.html#//apple_ref/doc/uid/TP40009459-CH3-SW29 + static NSResponder ResolveResponder (NSResponder responder) + { + if (responder is NSText text && text.FieldEditor) + return (text.WeakDelegate as NSResponder) ?? responder; + + return responder; + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs index 0070f6c..28d656f 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/PropertyButton.cs @@ -84,7 +84,7 @@ namespace Xamarin.PropertyEditing.Mac private readonly IHostResourceProvider hostResources; - private void PopUpContextMenu () + internal void PopUpContextMenu () { if (this.popUpContextMenu == null) { this.popUpContextMenu = new NSMenu (); diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceBrushViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceBrushViewController.cs index cf73e47..3859c10 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceBrushViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceBrushViewController.cs @@ -6,14 +6,15 @@ using Xamarin.PropertyEditing.ViewModels; namespace Xamarin.PropertyEditing.Mac { - internal class ResourceBrushViewController : NotifyingViewController<BrushPropertyViewModel> + internal class ResourceBrushViewController + : NotifyingViewController<BrushPropertyViewModel> { private ResourceOutlineView resourceSelector; private readonly ResourceBrushPropertyViewDelegate viewDelegate; public ResourceBrushViewController (IHostResourceProvider hostResources) { - PreferredContentSize = new CGSize (430, 230); + PreferredContentSize = new CGSize (PreferredContentSizeWidth, PreferredContentSizeHeight); this.viewDelegate = new ResourceBrushPropertyViewDelegate (hostResources); } @@ -22,15 +23,15 @@ namespace Xamarin.PropertyEditing.Mac { switch (e.PropertyName) { case nameof (BrushPropertyViewModel.Resource): - if (resource == ViewModel.Resource) + if (this.resource == ViewModel.Resource) return; - resource = ViewModel?.Resource; + this.resource = ViewModel?.Resource; UpdateSelection (); break; case nameof (BrushPropertyViewModel.Solid): - if (resourceSelector != null) - resourceSelector.ViewModel = ViewModel?.ResourceSelector; + if (this.resourceSelector != null) + this.resourceSelector.ViewModel = ViewModel?.ResourceSelector; break; case nameof (BrushPropertyViewModel.Value): break; @@ -39,30 +40,30 @@ namespace Xamarin.PropertyEditing.Mac private void UpdateSelection () { - if (resourceSelector == null) + if (this.resourceSelector == null) return; - var source = resourceSelector.DataSource as ResourceDataSource; + var source = this.resourceSelector.DataSource as ResourceDataSource; if (source == null || ViewModel == null) return; nint index = -1; if (ViewModel.Resource != null && source.TryGetFacade (ViewModel?.Resource, out var facade)) { - index = resourceSelector.RowForItem (facade); + index = this.resourceSelector.RowForItem (facade); } if (index < 0) - resourceSelector.DeselectAll (null); + this.resourceSelector.DeselectAll (null); else - resourceSelector.SelectRow (index, false); + this.resourceSelector.SelectRow (index, false); } public override void OnViewModelChanged (BrushPropertyViewModel oldModel) { base.OnViewModelChanged (oldModel); - if (resourceSelector != null) { - viewDelegate.ViewModel = ViewModel; - resourceSelector.ViewModel = ViewModel?.ResourceSelector; + if (this.resourceSelector != null) { + this.viewDelegate.ViewModel = ViewModel; + this.resourceSelector.ViewModel = ViewModel?.ResourceSelector; } } @@ -73,7 +74,7 @@ namespace Xamarin.PropertyEditing.Mac public override void LoadView () { - viewDelegate.ViewModel = ViewModel; + this.viewDelegate.ViewModel = ViewModel; this.resourceSelector = new ResourceOutlineView { Delegate = viewDelegate, }; @@ -88,7 +89,7 @@ namespace Xamarin.PropertyEditing.Mac View = tableContainer; if (ViewModel != null) { - resourceSelector.ViewModel = ViewModel?.ResourceSelector; + this.resourceSelector.ViewModel = ViewModel?.ResourceSelector; } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceOutlineView.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceOutlineView.cs index 8428b69..7437ae2 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceOutlineView.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ResourceOutlineView.cs @@ -45,8 +45,7 @@ namespace Xamarin.PropertyEditing.Mac HeaderView = null; } - [Export ("validateProposedFirstResponder:forEvent:")] - public bool validateProposedFirstResponder (NSResponder responder, NSEvent ev) + public override bool ValidateProposedFirstResponder (NSResponder responder, NSEvent forEvent) { return true; } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs index 4c1398b..40304bc 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs @@ -60,13 +60,13 @@ namespace Xamarin.PropertyEditing.Mac }; Layer = new CALayer (); - Layer.AddSublayer (background); - Layer.AddSublayer (shadeLayer); - Layer.AddSublayer (hueLayer); - Layer.AddSublayer (historyLayer); - Layer.AddSublayer (componentBackground); + Layer.AddSublayer (this.background); + Layer.AddSublayer (this.shadeLayer); + Layer.AddSublayer (this.hueLayer); + Layer.AddSublayer (this.historyLayer); + Layer.AddSublayer (this.componentBackground); WantsLayer = true; - AddSubview (componentTabs.View); + AddSubview (this.componentTabs.View); } public override bool AcceptsFirstResponder () => true; @@ -104,9 +104,9 @@ namespace Xamarin.PropertyEditing.Mac for (var c = hit?.ModelLayer; c != null; c = c.SuperLayer) { var active = c as ColorEditorLayer; if (active != null) { - interaction = new EditorInteraction (ViewModel, active); + this.interaction = new EditorInteraction (ViewModel, active); active.UpdateFromLocation ( - interaction, + this.interaction, Layer.ConvertPointToLayer (location, active)); OnPropertyChanged (ViewModel, new PropertyChangedEventArgs (nameof (SolidBrushViewModel.Color))); return; @@ -124,9 +124,9 @@ namespace Xamarin.PropertyEditing.Mac if (diff.X * diff.X < .5 && diff.Y * diff.Y < .5) return; - interaction?.Layer?.UpdateFromLocation ( - interaction, - Layer.ConvertPointToLayer (location, interaction.Layer)); + this.interaction?.Layer?.UpdateFromLocation ( + this.interaction, + Layer.ConvertPointToLayer (location, this.interaction.Layer)); OnPropertyChanged (ViewModel, new PropertyChangedEventArgs (nameof (SolidBrushViewModel.Color))); } @@ -134,14 +134,15 @@ namespace Xamarin.PropertyEditing.Mac public override void MouseUp (NSEvent theEvent) { base.MouseUp (theEvent); - interaction?.Commit (); - interaction = null; + this.interaction?.Commit (); + this.interaction = null; } private bool modelChanged = true; + public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) { - var inter = interaction ?? new EditorInteraction (ViewModel, null); + var inter = this.interaction ?? new EditorInteraction (ViewModel, null); switch (e.PropertyName) { case nameof (SolidBrushViewModel.Color): @@ -154,9 +155,9 @@ namespace Xamarin.PropertyEditing.Mac public override void OnViewModelChanged (SolidBrushViewModel oldModel) { base.OnViewModelChanged (oldModel); - var inter = interaction ?? new EditorInteraction (ViewModel, null); + var inter = this.interaction ?? new EditorInteraction (ViewModel, null); - componentTabs.ViewModel = ViewModel; + this.componentTabs.ViewModel = ViewModel; foreach (var editor in Layer.Sublayers.OfType<ColorEditorLayer> ()) { editor.UpdateFromModel (inter); } @@ -165,7 +166,7 @@ namespace Xamarin.PropertyEditing.Mac public override void Layout () { if (this.modelChanged) { - var interx = interaction ?? new EditorInteraction (ViewModel, null); + var interx = this.interaction ?? new EditorInteraction (ViewModel, null); foreach (var editor in Layer.Sublayers.OfType<ColorEditorLayer> ()) { editor.UpdateFromModel (interx); } @@ -207,7 +208,7 @@ namespace Xamarin.PropertyEditing.Mac var inset = backgroundFrame.Inset (componentPadding, componentPadding); this.componentTabs.View.Frame = inset; - var inter = interaction ?? new EditorInteraction (ViewModel, null); + var inter = this.interaction ?? new EditorInteraction (ViewModel, null); foreach (var editor in Layer.Sublayers.OfType<ColorEditorLayer> ()) { editor.UpdateFromModel (inter); } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditorViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditorViewController.cs index dee1962..49d6b0a 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditorViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditorViewController.cs @@ -14,7 +14,7 @@ namespace Xamarin.PropertyEditing.Mac throw new ArgumentNullException (nameof (hostResources)); this.hostResources = hostResources; - PreferredContentSize = new CGSize (430, 230); + PreferredContentSize = new CGSize (PreferredContentSizeWidth, PreferredContentSizeHeight); } public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/TabButton.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/TabButton.cs index 703e944..6a480b4 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/TabButton.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/TabButton.cs @@ -5,15 +5,21 @@ using Foundation; namespace Xamarin.PropertyEditing.Mac { + internal interface IUnderliningTabView + { + event EventHandler Clicked; + + bool Selected { get; set; } + int LineWidth { get; set; } + } + internal class TabButton - : FocusableButton + : FocusableButton, IUnderliningTabView { - public TabButton (IHostResourceProvider hostResource, string imageName) + public TabButton (IHostResourceProvider hostResource, string imageName = null) { if (hostResource == null) throw new ArgumentNullException (nameof (hostResource)); - if (imageName == null) - throw new ArgumentNullException (nameof (imageName)); Bordered = false; Action = new ObjCRuntime.Selector (ClickedName); @@ -29,20 +35,55 @@ namespace Xamarin.PropertyEditing.Mac public event EventHandler Clicked; - public bool Selected - { - get { return this.selected; } - set - { + public bool Selected { + get => this.selected; + set { + if (this.selected == value) + return; + this.selected = value; + + TitleColor = this.selected ? NSColor.Text : NSColor.DisabledControlText; NeedsDisplay = true; } } - public override CGSize IntrinsicContentSize - { - get - { + private int lineWidth = 2; + public int LineWidth { + get => this.lineWidth; + set { + if (this.lineWidth == value) + return; + + this.lineWidth = value; + NeedsLayout = true; + } + } + + private NSColor titleColor; + protected NSColor TitleColor { + get => this.titleColor; + private set { + if (this.titleColor == value) + return; + + this.titleColor = value; + + // No point changing the text color if there's nothing to change. + if (!string.IsNullOrEmpty (Title)) { + var coloredTitle = new NSMutableAttributedString (Title); + var titleRange = new NSRange (0, coloredTitle.Length); + coloredTitle.AddAttribute (NSStringAttributeKey.ForegroundColor, this.titleColor, titleRange); + var centeredAttribute = new NSMutableParagraphStyle (); + centeredAttribute.Alignment = NSTextAlignment.Center; + coloredTitle.AddAttribute (NSStringAttributeKey.ParagraphStyle, centeredAttribute, titleRange); + AttributedTitle = coloredTitle; + } + } + } + + public override CGSize IntrinsicContentSize { + get { var size = base.IntrinsicContentSize; return new CGSize (size.Width + 2 + 10, size.Height + 2 + 10); } @@ -62,14 +103,15 @@ namespace Xamarin.PropertyEditing.Mac return; NSBezierPath path = new NSBezierPath (); - path.AppendPathWithRect (new CGRect (Bounds.X, Bounds.Height - 2, Bounds.Width, 2)); - (Selected ? NSColor.Text : NSColor.DisabledControlText).Set (); + path.AppendPathWithRect (new CGRect (Bounds.X, Bounds.Height - this.lineWidth, Bounds.Width, this.lineWidth)); + this.titleColor.Set (); path.Fill (); } private void AppearanceChanged () { - Image = this.hostResource.GetNamedImage (this.imageName); + if (!string.IsNullOrEmpty (this.imageName)) + Image = this.hostResource.GetNamedImage (this.imageName); } private readonly string imageName; @@ -84,4 +126,4 @@ namespace Xamarin.PropertyEditing.Mac Clicked?.Invoke (this, EventArgs.Empty); } } -} +}
\ No newline at end of file diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTabViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTabViewController.cs index 4911171..4b85c39 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTabViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTabViewController.cs @@ -1,5 +1,6 @@ using System; - +using System.Threading; +using System.Threading.Tasks; using AppKit; using CoreGraphics; using Foundation; @@ -44,7 +45,7 @@ namespace Xamarin.PropertyEditing.Mac public override void InsertTabViewItem (NSTabViewItem tabViewItem, nint index) {
- this.tabStack.InsertView (GetView (tabViewItem), (nuint)index, NSStackViewGravity.Leading);
+ this.tabStack.InsertView (GetView (tabViewItem, index), (nuint)index, NSStackViewGravity.Leading); base.InsertTabViewItem (tabViewItem, index); } @@ -52,6 +53,9 @@ namespace Xamarin.PropertyEditing.Mac {
int index = (int)TabView.IndexOf (tabViewItem);
NSView tabView = this.tabStack.Views[index];
+ if (tabView is TabButton tb) { + tb.Clicked -= OnTabButtonClicked; + }
this.tabStack.RemoveView (tabView);
tabView.Dispose ();
@@ -150,8 +154,10 @@ namespace Xamarin.PropertyEditing.Mac Spacing = 1f,
};
- protected NSStackView TabStack => this.tabStack;
-
+ protected NSStackView TabStack => this.tabStack; + + internal IUnderliningTabView Selected { get => this.selected; set => this.selected = value; } + private NSEdgeInsets edgeInsets = new NSEdgeInsets (0, 0, 0, 0);
private void UpdatePadding() @@ -178,31 +184,38 @@ namespace Xamarin.PropertyEditing.Mac }
this.selected = this.tabStack.Views[index] as IUnderliningTabView;
- if (this.selected != null)
- this.selected.Selected = true;
+ if (this.selected != null) + this.selected.Selected = true; }
- private NSView GetView (NSTabViewItem item)
+ private NSView GetView (NSTabViewItem item, nint index)
{ var id = item.Identifier as NSObjectFacade;
- NSView tabView;
+ TabButton tabButton;
if (id != null) {
- tabView = new UnderlinedImageView (HostResources, ((string)id.Target)) {
- Selected = this.tabStack.Views.Length == SelectedTabViewItemIndex,
- ToolTip = item.ToolTip
- };
- } else {
- tabView = new UnderlinedTextField {
- BackgroundColor = NSColor.Clear,
- Editable = false,
- Bezeled = false,
- StringValue = item.Label,
- Selected = this.tabStack.Views.Length == SelectedTabViewItemIndex,
- ToolTip = item.ToolTip
- };
+ tabButton = new TabButton (HostResources, (string)id.Target);
+ } else { + tabButton = new TabButton (HostResources) {
+ ControlSize = NSControlSize.Mini,
+ Font = NSFont.SystemFontOfSize (NSFont.SystemFontSizeForControlSize (NSControlSize.Mini)),
+ Title = item.Label,
+ }; }
- return tabView;
+ tabButton.Tag = index;
+ tabButton.Selected = this.tabStack.Views.Length == SelectedTabViewItemIndex;
+ tabButton.ToolTip = item.ToolTip;
+ tabButton.Clicked += OnTabButtonClicked;
+
+ return tabButton;
+ } + + private void OnTabButtonClicked (object sender, EventArgs e) + { + if (sender is TabButton tabButton) { + if (SelectedTabViewItemIndex != tabButton.Tag) + SelectedTabViewItemIndex = tabButton.Tag; + } } } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTextField.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTextField.cs deleted file mode 100644 index 43d2e83..0000000 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/UnderlinedTextField.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using AppKit; -using CoreGraphics; - -namespace Xamarin.PropertyEditing.Mac -{ - internal interface IUnderliningTabView { - event EventHandler Clicked; - - bool Selected { get; set; } - int LineWidth { get; set; } - } - - internal class UnderlinedImageView : NSImageView, IUnderliningTabView - { - public UnderlinedImageView (IHostResourceProvider hostResources, string name) - { - if (hostResources == null) - throw new ArgumentNullException (nameof (hostResources)); - - this.hostResources = hostResources; - this.name = name; - } - - public event EventHandler Clicked; - - private bool selected; - public bool Selected - { - get => selected; - set { - if (selected == value && Image != null) - return; - - selected = value; - NeedsDisplay = true; - } - } - - private int lineWidth = 2; - public int LineWidth - { - get => lineWidth; - set { - if (this.lineWidth == value) - return; - - this.lineWidth = value; - NeedsLayout = true; - } - } - - public override void DrawRect (CGRect dirtyRect) - { - Image = this.hostResources.GetNamedImage (this.name + ((Selected) ? "~sel" : String.Empty)); - - base.DrawRect (dirtyRect); - if (!Selected) - return; - - NSBezierPath path = new NSBezierPath (); - path.AppendPathWithRect (new CGRect (Bounds.X, Bounds.Top + this.lineWidth, Bounds.Width, this.lineWidth)); - (Selected ? NSColor.Text: NSColor.DisabledControlText).Set (); - path.Fill (); - } - - public override CGSize IntrinsicContentSize - { - get { - var size = base.IntrinsicContentSize; - return new CGSize (size.Width + this.lineWidth + 10, size.Height + this.lineWidth + 10); - } - } - - public override void MouseDown (NSEvent theEvent) - { - Clicked?.Invoke (this, EventArgs.Empty); - base.MouseDown (theEvent); - } - - private readonly IHostResourceProvider hostResources; - private readonly string name; - } - - internal class UnderlinedTextField : NSTextField, IUnderliningTabView - { - public UnderlinedTextField () - { - TranslatesAutoresizingMaskIntoConstraints = false; - AutoresizingMask = NSViewResizingMask.MaxXMargin; - UsesSingleLineMode = true; - Alignment = NSTextAlignment.Center; - } - - public event EventHandler Clicked; - - private bool selected; - public bool Selected - { - get => this.selected; - set - { - this.selected = value; - TextColor = this.selected ? NSColor.Text : NSColor.DisabledControlText; - - ///NeedsDisplay = true; - } - } - - private int lineWidth = 2; - public int LineWidth { - get =>this.lineWidth; - set { - if (this.lineWidth == value) - return; - - this.lineWidth = value; - NeedsLayout = true; - } - } - - public override void MouseDown (NSEvent theEvent) - { - Clicked?.Invoke (this, EventArgs.Empty); - base.MouseDown (theEvent); - } - - public override void DrawRect (CGRect dirtyRect) - { - base.DrawRect (dirtyRect); - if (!Selected) - return; - - NSBezierPath path = new NSBezierPath (); - path.AppendPathWithRect (new CGRect (Bounds.X, Bounds.Bottom - lineWidth, Bounds.Width, lineWidth)); - TextColor.Set (); - path.Fill (); - } - - public override CGSize IntrinsicContentSize - { - get - { - var size = base.IntrinsicContentSize; - return new CGSize (size.Width, size.Height + lineWidth + 3); - } - } - } -} diff --git a/Xamarin.PropertyEditing.Mac/Controls/PropertyContainer.cs b/Xamarin.PropertyEditing.Mac/Controls/PropertyContainer.cs index 712b1bc..73a7f5b 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/PropertyContainer.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/PropertyContainer.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using AppKit; namespace Xamarin.PropertyEditing.Mac @@ -57,6 +58,38 @@ namespace Xamarin.PropertyEditing.Mac } } + public override bool PerformKeyEquivalent (NSEvent theEvent) + { + if (theEvent.KeyCode == (ushort)NSKey.I + && (theEvent.ModifierFlags & (NSEventModifierMask.ShiftKeyMask | NSEventModifierMask.ControlKeyMask)) + == (NSEventModifierMask.ShiftKeyMask | NSEventModifierMask.ControlKeyMask)) { + if (theEvent.Window.FirstResponder is NSView fr) { + var propertyContainer = FindPropertyContainer (fr); // Recursive on SuperView, up the chain + if (propertyContainer != null) { + SynchronizationContext.Current.Post (s => { + propertyContainer.PropertyButton.PopUpContextMenu (); + }, null); + return true; + } + } + } + + return base.PerformKeyEquivalent (theEvent); + } + + private PropertyContainer FindPropertyContainer (NSView fr) + { + if (fr.Superview != null) { + if (fr.Superview is PropertyContainer propertyContainer) { + return propertyContainer; + } else { + return FindPropertyContainer (fr.Superview); + } + } else { + return null; + } + } + public string Label { get { return this.label.StringValue; } diff --git a/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs b/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs index bdbef92..e2d5eb9 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/PropertyEditorControl.cs @@ -86,7 +86,11 @@ namespace Xamarin.PropertyEditing.Mac do { row--; view = TableView.GetView (0, row, makeIfNecessary: false); - ctrl = (view as EditorContainer)?.EditorView?.NativeView as PropertyEditorControl; + if (view is PropertyEditorControl pec) { // This is to include the CategoryContainer + ctrl = pec; + } else { + ctrl = (view as EditorContainer)?.EditorView?.NativeView as PropertyEditorControl; + } } while (row > 0 && ctrl == null); if (ctrl != null) { diff --git a/Xamarin.PropertyEditing.Mac/Controls/RequestResource/RequestResourceView.cs b/Xamarin.PropertyEditing.Mac/Controls/RequestResource/RequestResourceView.cs index 798342e..fdc0060 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/RequestResource/RequestResourceView.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/RequestResource/RequestResourceView.cs @@ -12,8 +12,7 @@ namespace Xamarin.PropertyEditing.Mac { internal class FirstResponderTableView : NSTableView { - [Export ("validateProposedFirstResponder:forEvent:")] - public bool validateProposedFirstResponder (NSResponder responder, NSEvent ev) + public override bool ValidateProposedFirstResponder (NSResponder responder, NSEvent forEvent) { return true; } diff --git a/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs b/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs index a322768..9410bc5 100644 --- a/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs +++ b/Xamarin.PropertyEditing.Mac/PropertyTableDelegate.cs @@ -49,30 +49,15 @@ namespace Xamarin.PropertyEditing.Mac GetVMGroupCellItendifiterFromFacade (item, out EditorViewModel evm, out PanelGroupViewModel group, out var cellIdentifier); if (group != null) { - var labelContainer = (NSView)outlineView.MakeView (CategoryIdentifier, this); - if (labelContainer == null) { - labelContainer = new NSView { + var categoryContainer = (CategoryContainerControl)outlineView.MakeView (CategoryIdentifier, this); + if (categoryContainer == null) { + categoryContainer = new CategoryContainerControl (this.hostResources, outlineView) { Identifier = CategoryIdentifier, + TableView = outlineView, }; - - 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), - }); } - ((UnfocusableTextField)labelContainer.Subviews[1]).StringValue = group.Category; + ((UnfocusableTextField)categoryContainer.Subviews[1]).StringValue = group.Category; if (this.dataSource.DataContext.GetIsExpanded (group.Category)) { SynchronizationContext.Current.Post (s => { @@ -80,7 +65,7 @@ namespace Xamarin.PropertyEditing.Mac }, null); } - return labelContainer; + return categoryContainer; } NSView editorOrContainer = null; @@ -204,7 +189,7 @@ namespace Xamarin.PropertyEditing.Mac if (!this.registrations.TryGetValue (cellIdentifier, out EditorRegistration registration)) { registration = new EditorRegistration (); - if (cellIdentifier == nameof(PanelHeaderEditorControl)) { + if (cellIdentifier == nameof (PanelHeaderEditorControl)) { registration.RowSize = 54; } else { NSView editorOrContainer = GetEditor (cellIdentifier, vm, outlineView); diff --git a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj index eb49853..0caef7a 100644 --- a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj +++ b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj @@ -18,6 +18,9 @@ <ProjectReference Include="..\Xamarin.PropertyEditing\Xamarin.PropertyEditing.csproj" />
</ItemGroup>
+ <ItemGroup>
+ <Compile Remove="Controls\Custom\UnderlinedTextField.cs" />
+ </ItemGroup>
<Target Name="IncludeIconsInBundle" BeforeTargets="AssignTargetPaths">
<ItemGroup>
<PropertyEditingResourceBundlePath Include="PropertyEditingResource\**\*" />
|