diff options
author | Larry Ewing <lewing@xamarin.com> | 2018-04-28 01:07:53 +0300 |
---|---|---|
committer | Larry Ewing <lewing@microsoft.com> | 2018-07-16 22:05:49 +0300 |
commit | e0301b2bcf120f07f2452549ba0a6c1eb51bcf0b (patch) | |
tree | 2c02fb95c0e882c4d17c3e1f2887c5b9f3e2ce14 /Xamarin.PropertyEditing.Mac | |
parent | aeac432cda69abd44d738750a5b144bfbfb72799 (diff) |
Extract and rename a bunch of classes
Diffstat (limited to 'Xamarin.PropertyEditing.Mac')
15 files changed, 813 insertions, 738 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs index 7f775f8..f56f787 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/BrushTabViewController.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using AppKit; -using CoreAnimation; using CoreGraphics; using Foundation; using Xamarin.PropertyEditing.Drawing; @@ -11,303 +8,6 @@ using Xamarin.PropertyEditing.ViewModels; namespace Xamarin.PropertyEditing.Mac { - class MaterialBrushEditorViewController : PropertyViewController <BrushPropertyViewModel> - { - MaterialView materialEditor; - - public MaterialBrushEditorViewController () - { - PreferredContentSize = new CGSize (200, 230); - } - - public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) - { - switch (e.PropertyName) { - case nameof (BrushPropertyViewModel.Value): - case nameof (BrushPropertyViewModel.MaterialDesign): - if (materialEditor != null) - materialEditor.ViewModel = ViewModel; - break; - } - } - - public override void OnViewModelChanged (BrushPropertyViewModel oldModel) - { - if (materialEditor != null) - materialEditor.ViewModel = ViewModel; - } - - public class MaterialColorLayer : CATextLayer - { - public MaterialColorLayer () - { - AddSublayer (Selection); - } - - CATextLayer Selection { get; } = new CATextLayer () { - CornerRadius = 3 - }; - - string text; - public string Text { - get => text; - set { - text = value; - SetNeedsLayout (); - } - } - - CommonColor materialColor; - public new CommonColor BackgroundColor - { - get => materialColor; - set - { - materialColor = value; - base.BackgroundColor = materialColor.ToCGColor (); - } - } - - bool isSelected; - public bool IsSelected { - get => isSelected; - set { - if (isSelected == value) - return; - isSelected = value; - SetNeedsLayout (); - } - } - - public override void LayoutSublayers () - { - base.LayoutSublayers (); - //String = isSelected ? "" : text; - Selection.String = text; - Selection.Frame = Frame.Bounds ().Border (new CommonThickness (3)); - Selection.BorderWidth = isSelected ? 2 : 0; - Selection.BorderColor = ForegroundColor; - Selection.ForegroundColor = ForegroundColor; - Selection.FontSize = FontSize; - Selection.ContentsScale = ContentsScale; - Selection.TextAlignmentMode = TextAlignmentMode; - } - } - - public class MaterialView : NSView - { - public override bool IsFlipped => true; - - readonly string[] ColorNames = { - "50", - "100", - "200", - "300", - "400", - "500", - "600", - "700", - "800", - "900" - }; - - readonly string [] AccentNames = { - "A100", - "A200", - "A400", - "A700" - }; - - readonly string [] BlackWhite = { - "White", - "Black" - }; - - public MaterialView () : base () - { - Initialize (); - } - - void Initialize () { - WantsLayer = true; - } - - BrushPropertyViewModel viewModel; - public BrushPropertyViewModel ViewModel - { - get => viewModel; - set { - viewModel = value; - NeedsLayout = true; - } - } - - public MaterialDesignColorViewModel MaterialDesign - { - get => ViewModel?.MaterialDesign; - } - - public override void Layout () - { - if (Layer?.Sublayers != null) - foreach (var l in Layer.Sublayers) - l.RemoveFromSuperLayer (); - - if (MaterialDesign == null) - return; - - var colors = MaterialDesign.Palettes.Select (p => new { p.Name, Color = p.MainColor }).ToArray (); - int col = 0; - nfloat x = 0; - nfloat y = 6; - var width = (Frame.Width - 54) / 10; - var height = (Frame.Height - 49) / 4; - - 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 l = new MaterialColorLayer { - Frame = frame, - ForegroundColor = selectedColor.CGColor, - BackgroundColor = p.Color, - CornerRadius = 3, - BorderColor = new CGColor (.5f, .5f, .5f, .5f), - MasksToBounds = false, - IsSelected = MaterialDesign.Color == p.Color - }; - - Layer.AddSublayer (l); - x += width + 6; - col++; - if (col >= 10) { - x = 0; - y += height + 6; - col = 0; - } - } - - Layer.AddSublayer (new CATextLayer { - ForegroundColor = NSColor.ControlText.CGColor, - Frame = new CGRect (x, y + 6, Frame.Width, 25), - String = MaterialDesign.ColorName, - FontSize = NSFont.SmallSystemFontSize, - ContentsScale = Window?.Screen?.BackingScaleFactor ?? NSScreen.MainScreen.BackingScaleFactor - }); - - y += 25; - x = 0; - width = Frame.Width / MaterialDesign.NormalColorScale.Count (); - var names = MaterialDesign.NormalColorScale.Count () > 2 ? ColorNames : BlackWhite; - 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); - foreach (var n in MaterialDesign.NormalColorScale.Zip (names, (c, name) => new { Name = name, Color = c.Value })) { - var frame = new CGRect (x, y, width, height); - var selectedColor = n.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White; - var l = new MaterialColorLayer { - BackgroundColor = n.Color, - ForegroundColor = selectedColor.CGColor, - Frame = new CGRect (x, 0, width, height), - Text = n.Name, - FontSize = 12, - ContentsScale = NSScreen.MainScreen.BackingScaleFactor, - TextAlignmentMode = CATextLayerAlignmentMode.Center, - IsSelected = MaterialDesign.Color == n.Color - }; - normal.AddSublayer (l); - x += width; - } - - if (MaterialDesign.AccentColorScale.Count () <= 0) - 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 / MaterialDesign.AccentColorScale.Count (); - foreach (var n in MaterialDesign.AccentColorScale.Zip (AccentNames, (c, n) => new { Name = n, Color = c.Value })) { - var frame = new CGRect (x, y, width, height); - var selectedColor = n.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White; - var l = new MaterialColorLayer { - BackgroundColor = n.Color, - ForegroundColor = selectedColor.CGColor, - Frame = new CGRect (x, 0, width, height), - Text = n.Name, - FontSize = 12, - ContentsScale = NSScreen.MainScreen.BackingScaleFactor, - TextAlignmentMode = CATextLayerAlignmentMode.Center, - IsSelected = ViewModel.Solid.Color == n.Color, - }; - - accent.AddSublayer (l); - x += width; - } - } - - public override void MouseDown (NSEvent theEvent) - { - UpdateFromEvent (theEvent); - } - - public void UpdateFromEvent (NSEvent theEvent) - { - 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) { - ViewModel.Solid.Color = editor.BackgroundColor; - NeedsLayout = true; - } - } - } - } - } - - public override void LoadView () - { - View = materialEditor = new MaterialView { - ViewModel = ViewModel - }; - } - } - - class EmptyBrushEditorViewController : PropertyViewController<BrushPropertyViewModel> - { - NSButton brushEditor; - - public EmptyBrushEditorViewController () - { - PreferredContentSize = new CGSize (100, 100); - } - - public override void LoadView () - { - View = brushEditor = new NSButton { - Title = "Edit" - }; - brushEditor.Activated += (o, e) => { - ViewModel.SelectedBrushType = CommonBrushType.Solid; - }; - } - } - class BrushTabViewController : PropertyTabViewController<BrushPropertyViewModel> { Dictionary<CommonBrushType, int> BrushTypeTable = new Dictionary<CommonBrushType, int> (); @@ -331,7 +31,7 @@ namespace Xamarin.PropertyEditing.Mac BrushTypeTable.Clear (); if (ViewModel == null) return; - + foreach (var key in ViewModel.BrushTypes.Keys) { var item = new NSTabViewItem (); item.Label = key; @@ -394,7 +94,7 @@ namespace Xamarin.PropertyEditing.Mac var brushController = item.ViewController as PropertyViewController<BrushPropertyViewModel>; if (brushController != null) brushController.ViewModel = ViewModel; - + if (inhibitSelection) return; @@ -405,11 +105,11 @@ namespace Xamarin.PropertyEditing.Mac { if (inhibitSelection) return; - + base.DidSelect (tabView, item); ViewModel.SelectedBrushType = ViewModel.BrushTypes[item.Label]; } - + public override void ViewDidLoad() { var old = View.Frame; diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditor.cs new file mode 100644 index 0000000..a3aad7e --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditor.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CoreAnimation; +using CoreGraphics; +using Xamarin.PropertyEditing.Drawing; + +namespace Xamarin.PropertyEditing.Mac +{ + public abstract class ChannelEditor + { + public string Name { get; } + public double MinimumValue { get; } + public double MaximumValue { get; } + public double IncrementValue { get; } + + static IEnumerable<double> LerpSteps (double min, double max, int steps) + => Enumerable.Range (0, steps).Select (v => { + var pos = v / (double)steps; + return max * pos - min * (1 - pos); + }); + + public ChannelEditor (string name, double min, double max, double increment) + { + MinimumValue = min; + MaximumValue = max; + IncrementValue = increment; + Name = name; + } + + public void UpdateGradientLayer (CAGradientLayer layer, CommonColor color) + { + var c = color.UpdateRGB (a: 255); + + layer.Colors = LerpSteps (MinimumValue, MaximumValue, 7) + .Select (value => UpdateColorFromValue (c, value).ToCGColor ()).ToArray (); + } + + public double InvLerp (CGPoint start, CGPoint end, CGPoint loc) + { + var a = new CGVector (end.X - start.X, end.Y - start.Y); + var b = new CGVector (loc.X - start.X, loc.Y - start.Y); + var dot = a.dx * b.dx + a.dy * b.dy; + var len = Math.Sqrt (a.dx * a.dx + a.dy * a.dy); + return dot / len; + } + + public static double InvLerp (double start, double end, double value) + => (value - start) / (end - start); + + public static double Lerp (double start, double end, double amount) + => end * amount - start * (1 - amount); + + public static CGPoint Lerp (CGPoint start, CGPoint end, double amount) + => new CGPoint ( + start.X + (end.X - start.X) * amount, + start.Y + (end.Y - start.Y) * amount); + + public double ValueFromLocation (CAGradientLayer layer, CGPoint loc) + { + var rect = layer.Frame; + var unitLoc = new CGPoint ( + (loc.X - rect.X) / rect.Width, + (loc.Y - rect.Y) / rect.Height); + + return Clamp (Lerp (MinimumValue, MaximumValue, InvLerp (layer.StartPoint, layer.EndPoint, unitLoc))); + } + + public CommonColor UpdateColorFromLocation (CAGradientLayer layer, CommonColor color, CGPoint loc) + => UpdateColorFromValue (color, ValueFromLocation (layer, loc)); + + public CGPoint LocationFromColor (CAGradientLayer layer, CommonColor color) + { + var pos = ValueFromColor (color); + + var amount = InvLerp (MinimumValue, MaximumValue, pos); + var unitLoc = Lerp (layer.StartPoint, layer.EndPoint, amount); + + return new CGPoint ( + layer.Frame.X + unitLoc.X * layer.Frame.Width, + layer.Frame.Y + unitLoc.Y * layer.Frame.Height); + } + + public double Clamp (double value) + => Math.Max (MinimumValue, Math.Min (MaximumValue, value)); + + public abstract CommonColor UpdateColorFromValue (CommonColor color, double value); + public abstract double ValueFromColor (CommonColor color); + } + + class RedChannelEditor : ChannelEditor + { + public RedChannelEditor () : base ("R", 0d, 255d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.R; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateRGB (r: (byte)Clamp (value)); + } + + class GreenChannelEditor : ChannelEditor + { + public GreenChannelEditor () : base ("G", 0d, 255d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.G; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateRGB (g: (byte)Clamp (value)); + } + + class BlueChannelEditor : ChannelEditor + { + public BlueChannelEditor () : base ("B", 0d, 255d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.B; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateRGB (b: (byte)Clamp (value)); + } + + class AlphaChannelEditor : ChannelEditor + { + public AlphaChannelEditor () : base ("A", 0d, 255d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.A; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateRGB (a: (byte)Clamp (value)); + } + + class CyanChannelEditor : ChannelEditor + { + public CyanChannelEditor () : base ("C", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.C; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateCMYK (c: Clamp (value)); + } + + class MagentaChannelEditor : ChannelEditor + { + public MagentaChannelEditor () : base ("M", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.M; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateCMYK (m: Clamp (value)); + } + + class YellowChannelEditor : ChannelEditor + { + public YellowChannelEditor () : base ("Y", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.Y; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateCMYK (y: Clamp (value)); + } + + class BlackChannelEditor : ChannelEditor + { + public BlackChannelEditor () : base ("K", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.K; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateCMYK (k: Clamp (value)); + } + + class HsbHueChannelEditor : ChannelEditor + { + public HsbHueChannelEditor () : base ("H", 0d, 360d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.Hue; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHSB (hue: Clamp (value)); + } + + class HsbSaturationChannelEditor : ChannelEditor + { + public HsbSaturationChannelEditor () : base ("S", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.Saturation; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHSB (saturation: Clamp (value)); + } + + class HsbBrightnessChannelEditor : ChannelEditor + { + public HsbBrightnessChannelEditor () : base ("B", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.Brightness; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHSB (brightness: Clamp (value)); + } + + class HlsHueChannelEditor : ChannelEditor + { + public HlsHueChannelEditor () : base ("H", 0d, 360d, 1d) + { + } + + public override double ValueFromColor (CommonColor color) + => color.Hue; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHLS (hue: Clamp (value)); + } + + class HlsLightnessChannelEditor : ChannelEditor + { + public HlsLightnessChannelEditor () : base ("L", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.Lightness; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHLS (lightness: Clamp (value)); + } + + class HlsSaturationChannelEditor : ChannelEditor + { + public HlsSaturationChannelEditor () : base ("S", 0d, 1d, .01d) + { + } + + public override double ValueFromColor (CommonColor color) + => (double)color.Saturation; + + public override CommonColor UpdateColorFromValue (CommonColor color, double value) + => color.UpdateHLS (saturation: Clamp (value)); + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditorType.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditorType.cs new file mode 100644 index 0000000..c9747fe --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ChannelEditorType.cs @@ -0,0 +1,10 @@ +namespace Xamarin.PropertyEditing.Mac +{ + public enum ChannelEditorType + { + RGB, + HLS, + HSB, + CMYK + }; +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs index 8d47998..8dbb03c 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/ColorComponentEditor.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Linq; using AppKit; @@ -41,7 +40,7 @@ namespace Xamarin.PropertyEditing.Mac public CAGradientLayer Gradient { get; set; } } - ComponentSet CreateEditor (ComponentEditor editor) + ComponentSet CreateEditor (ChannelEditor editor) { var ce = new ComponentSet { Label = new UnfocusableTextField { @@ -72,33 +71,33 @@ namespace Xamarin.PropertyEditing.Mac switch (type) { case ChannelEditorType.HSB: return new[] { - CreateEditor (new HsbHueComponentEditor ()), - CreateEditor (new HsbSaturationComponentEditor ()), - CreateEditor (new HsbBrightnessComponentEditor ()), - CreateEditor (new AlphaComponentEditor ()) + CreateEditor (new HsbHueChannelEditor ()), + CreateEditor (new HsbSaturationChannelEditor ()), + CreateEditor (new HsbBrightnessChannelEditor ()), + CreateEditor (new AlphaChannelEditor ()) }; case ChannelEditorType.HLS: return new[] { - CreateEditor (new HlsHueComponentEditor ()), - CreateEditor (new HlsLightnessComponentEditor ()), - CreateEditor (new HlsSaturationComponentEditor ()), - CreateEditor (new AlphaComponentEditor ()) + CreateEditor (new HlsHueChannelEditor ()), + CreateEditor (new HlsLightnessChannelEditor ()), + CreateEditor (new HlsSaturationChannelEditor ()), + CreateEditor (new AlphaChannelEditor ()) }; case ChannelEditorType.RGB: return new[] { - CreateEditor (new RedComponentEditor ()), - CreateEditor (new GreenComponentEditor ()), - CreateEditor (new BlueComponentEditor ()), - CreateEditor (new AlphaComponentEditor ()) + CreateEditor (new RedChannelEditor ()), + CreateEditor (new GreenChannelEditor ()), + CreateEditor (new BlueChannelEditor ()), + CreateEditor (new AlphaChannelEditor ()) }; default: case ChannelEditorType.CMYK: return new[] { - CreateEditor (new CyanComponentEditor ()), - CreateEditor (new MagentaComponentEditor ()), - CreateEditor (new YellowComponentEditor ()), - CreateEditor (new BlackComponentEditor ()), - CreateEditor (new AlphaComponentEditor ()) + CreateEditor (new CyanChannelEditor ()), + CreateEditor (new MagentaChannelEditor ()), + CreateEditor (new YellowChannelEditor ()), + CreateEditor (new BlackChannelEditor ()), + CreateEditor (new AlphaChannelEditor ()) }; } } @@ -233,9 +232,7 @@ namespace Xamarin.PropertyEditing.Mac var editorFrame = new CGRect (labelFrame.Right, labelFrame.Y, frame.Width - labelFrame.Right, DefaultControlHeight); var yOffset = DefaultControlHeight + DefaultGradientHeight + 3; - foreach (var e in Editors) { - //e.Label.TopAnchor.ConstraintEqualToAnchor (this.TopAnchor); e.Label.Frame = labelFrame; e.Editor.Frame = editorFrame; e.Gradient.Frame = new CGRect (editorFrame.X, editorFrame.Y - DefaultGradientHeight, editorFrame.Width - 16, DefaultGradientHeight); @@ -247,90 +244,9 @@ namespace Xamarin.PropertyEditing.Mac } } - public abstract class ComponentEditor - { - public string Name { get; } - public double MinimumValue { get; } - public double MaximumValue { get; } - public double IncrementValue { get; } - - static IEnumerable<double> LerpSteps (double min, double max, int steps) - => Enumerable.Range (0, steps).Select (v => { - var pos = v / (double)steps; - return max * pos - min * (1 - pos); - }); - - public ComponentEditor (string name, double min, double max, double increment) - { - MinimumValue = min; - MaximumValue = max; - IncrementValue = increment; - Name = name; - } - - public void UpdateGradientLayer (CAGradientLayer layer, CommonColor color) - { - var c = color.UpdateRGB (a: 255); - - layer.Colors = LerpSteps (MinimumValue, MaximumValue, 7) - .Select (value => UpdateColorFromValue (c, value).ToCGColor ()).ToArray (); - } - - public double InvLerp (CGPoint start, CGPoint end, CGPoint loc) - { - var a = new CGVector (end.X - start.X, end.Y - start.Y); - var b = new CGVector (loc.X - start.X, loc.Y - start.Y); - var dot = a.dx * b.dx + a.dy * b.dy; - var len = Math.Sqrt (a.dx * a.dx + a.dy * a.dy); - return dot / len; - } - - public static double InvLerp (double start, double end, double value) - => (value - start) / (end - start); - - public static double Lerp (double start, double end, double amount) - => end * amount - start * (1 - amount); - - public static CGPoint Lerp (CGPoint start, CGPoint end, double amount) - => new CGPoint ( - start.X + (end.X - start.X) * amount, - start.Y + (end.Y - start.Y) * amount); - - public double ValueFromLocation (CAGradientLayer layer, CGPoint loc) - { - var rect = layer.Frame; - var unitLoc = new CGPoint ( - (loc.X - rect.X) / rect.Width, - (loc.Y - rect.Y) / rect.Height); - - return Clamp (Lerp (MinimumValue, MaximumValue, InvLerp (layer.StartPoint, layer.EndPoint, unitLoc))); - } - - public CommonColor UpdateColorFromLocation (CAGradientLayer layer, CommonColor color, CGPoint loc) - => UpdateColorFromValue (color, ValueFromLocation (layer, loc)); - - public CGPoint LocationFromColor (CAGradientLayer layer, CommonColor color) - { - var pos = ValueFromColor (color); - - var amount = InvLerp (MinimumValue, MaximumValue, pos); - var unitLoc = Lerp (layer.StartPoint, layer.EndPoint, amount); - - return new CGPoint ( - layer.Frame.X + unitLoc.X * layer.Frame.Width, - layer.Frame.Y + unitLoc.Y * layer.Frame.Height); - } - - public double Clamp (double value) - => Math.Max (MinimumValue, Math.Min (MaximumValue, value)); - - public abstract CommonColor UpdateColorFromValue (CommonColor color, double value); - public abstract double ValueFromColor (CommonColor color); - } - class ComponentSpinEditor : NumericSpinEditor { - public ComponentSpinEditor (ComponentEditor component) + public ComponentSpinEditor (ChannelEditor component) { ComponentEditor = component; MinimumValue = component.MinimumValue; @@ -339,187 +255,6 @@ namespace Xamarin.PropertyEditing.Mac Digits = 2; } - public ComponentEditor ComponentEditor { get; } - } - - class RedComponentEditor : ComponentEditor - { - public RedComponentEditor () : base ("R", 0d, 255d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.R; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateRGB (r: (byte)Clamp (value)); - } - - class GreenComponentEditor : ComponentEditor - { - public GreenComponentEditor () : base ("G", 0d, 255d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.G; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateRGB (g: (byte)Clamp (value)); - } - - class BlueComponentEditor : ComponentEditor - { - public BlueComponentEditor () : base ("B", 0d, 255d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.B; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateRGB (b: (byte)Clamp (value)); - } - - class AlphaComponentEditor : ComponentEditor - { - public AlphaComponentEditor () : base ("A", 0d, 255d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.A; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateRGB (a: (byte)Clamp (value)); - } - - class CyanComponentEditor : ComponentEditor - { - public CyanComponentEditor () : base ("C", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.C; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateCMYK (c: Clamp (value)); - } - - class MagentaComponentEditor : ComponentEditor - { - public MagentaComponentEditor () : base ("M", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.M; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateCMYK (m: Clamp (value)); - } - - class YellowComponentEditor : ComponentEditor - { - public YellowComponentEditor () : base ("Y", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.Y; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateCMYK (y: Clamp (value)); - } - - class BlackComponentEditor : ComponentEditor - { - public BlackComponentEditor () : base ("K", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.K; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateCMYK (k: Clamp (value)); - } - - class HsbHueComponentEditor : ComponentEditor { - public HsbHueComponentEditor () : base ("H", 0d, 360d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.Hue; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHSB (hue: Clamp (value)); - } - - class HsbSaturationComponentEditor : ComponentEditor - { - public HsbSaturationComponentEditor () : base ("S", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.Saturation; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHSB (saturation: Clamp (value)); - } - - class HsbBrightnessComponentEditor : ComponentEditor - { - public HsbBrightnessComponentEditor () : base ("B", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.Brightness; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHSB (brightness: Clamp (value)); - } - - class HlsHueComponentEditor : ComponentEditor - { - public HlsHueComponentEditor () : base ("H", 0d, 360d, 1d) - { - } - - public override double ValueFromColor (CommonColor color) - => color.Hue; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHLS (hue: Clamp (value)); - } - - class HlsLightnessComponentEditor : ComponentEditor - { - public HlsLightnessComponentEditor () : base ("L", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.Lightness; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHLS (lightness: Clamp (value)); - } - - class HlsSaturationComponentEditor : ComponentEditor - { - public HlsSaturationComponentEditor () : base ("S", 0d, 1d, .01d) - { - } - - public override double ValueFromColor (CommonColor color) - => (double)color.Saturation; - - public override CommonColor UpdateColorFromValue (CommonColor color, double value) - => color.UpdateHLS (saturation: Clamp (value)); + public ChannelEditor ComponentEditor { get; } } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommandMenuItem.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommandMenuItem.cs index fd1039a..c945a80 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommandMenuItem.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommandMenuItem.cs @@ -50,7 +50,7 @@ namespace Xamarin.PropertyEditing.Mac private void CanExecuteChanged (object sender, EventArgs e) { - if(sender is ICommand cmd) + if (sender is ICommand cmd) this.Enabled = cmd.CanExecute (null); } } diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushLayer.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushLayer.cs new file mode 100644 index 0000000..1325567 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushLayer.cs @@ -0,0 +1,92 @@ +using System; +using AppKit; +using CoreAnimation; +using CoreGraphics; +using Xamarin.PropertyEditing.Drawing; + +namespace Xamarin.PropertyEditing.Mac +{ + class CommonBrushLayer : CALayer + { + public CommonBrushLayer () + { + this.CornerRadius = 3; + this.BorderColor = new CGColor (.5f, .5f, .5f, .5f); + this.BorderWidth = 1; + MasksToBounds = true; + } + + CALayer brushLayer; + CALayer BrushLayer + { + get => brushLayer; + set + { + if (brushLayer != null) + brushLayer.RemoveFromSuperLayer (); + + brushLayer = value; + + if (brushLayer != null) + AddSublayer (brushLayer); + } + } + + CommonBrush brush; + public CommonBrush Brush + { + get => brush; + set + { + brush = value; + BrushLayer = CreateBrushLayer (brush); + Opacity = brush == null ? 0 : 1; + } + } + + public static CALayer CreateBrushLayer (CommonBrush brush) + { + switch (brush) { + case CommonSolidBrush solid: + return new CALayer { + BackgroundColor = solid.Color.ToCGColor (), + Opacity = (float)solid.Opacity + }; + case CommonGradientBrush gradient: + return new CommonGradientBrushLayer { + Opacity = (float)gradient.Opacity + }; + default: + return new CALayer { + BackgroundColor = NSColor.Clear.CGColor + }; + } + } + + public override void LayoutSublayers () + { + base.LayoutSublayers (); + BrushLayer.Frame = new CGRect (0, 0, Frame.Width, Frame.Height); + Contents = DrawingExtensions.GenerateCheckerboard (Frame); + } + + public NSImage RenderPreview () + { + var scale = this.ContentsScale; + nint h = (nint)(this.Bounds.Height * scale); + nint w = (nint)(this.Bounds.Width * scale); + nint bytesPerRow = w * 4; + + if (h <= 0 || w <= 0) + return null; + + using (var colorSpace = CGColorSpace.CreateGenericRgb ()) + using (var context = new CGBitmapContext (IntPtr.Zero, w, h, 8, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast)) { + this.RenderInContext (context); + using (var image = context.ToImage ()) { + return new NSImage (image, new CGSize (w, h)); + } + } + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushView.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushView.cs index f303228..f9c355c 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushView.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonBrushView.cs @@ -12,7 +12,7 @@ namespace Xamarin.PropertyEditing.Mac set => (Layer as CommonBrushLayer).Brush = value; } - public CommonBrushView () : base () + public CommonBrushView () { Initialize (); } @@ -22,6 +22,11 @@ namespace Xamarin.PropertyEditing.Mac Initialize (); } + public CommonBrushView (IntPtr handle) : base (handle) + { + Initialize (); + } + void Initialize () { WantsLayer = true; Layer = new CommonBrushLayer diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonGradientBrushLayer.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonGradientBrushLayer.cs new file mode 100644 index 0000000..5b18fb9 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/CommonGradientBrushLayer.cs @@ -0,0 +1,62 @@ +using System; +using System.Linq; +using CoreAnimation; +using CoreGraphics; +using Xamarin.PropertyEditing.Drawing; + +namespace Xamarin.PropertyEditing.Mac +{ + class CommonGradientBrushLayer : CALayer + { + public CommonGradientBrushLayer () + { + } + + public CommonGradientBrushLayer (IntPtr handle) : base () + { + } + + CommonGradientBrush brush; + public CommonGradientBrush Brush + { + get => brush; + set + { + brush = value; + SetNeedsDisplay (); + } + } + + public override void DrawInContext (CGContext ctx) + { + ctx.SaveState (); + + var colorspace = CGColorSpace.CreateDeviceRGB (); + var colors = Brush.GradientStops.Select (stop => stop.Color.ToCGColor ()).ToArray (); + var locations = Brush.GradientStops.Select (stop => (nfloat)stop.Offset).ToArray (); + + var gradient = new CGGradient (colorspace, colors, locations); + var center = new CGPoint (Bounds.Width / 2f, Bounds.Height / 2f); + var radius = (float)Math.Min (Bounds.Width / 2.0, Bounds.Height / 2.0); + + switch (Brush) { + case CommonLinearGradientBrush linear: + ctx.DrawLinearGradient ( + gradient, + new CGPoint (0, 0), + new CGPoint (0, Bounds.Width), + CGGradientDrawingOptions.None); + break; + case CommonRadialGradientBrush radial: + ctx.DrawRadialGradient ( + gradient, + startCenter: center, + startRadius: 0f, + endCenter: center, + endRadius: radius, + options: CGGradientDrawingOptions.None); + break; + } + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs index e8cd5c9..bf812c2 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/DrawingExtensions.cs @@ -40,8 +40,6 @@ namespace Xamarin.PropertyEditing.Mac public static CGColor ToCGColor (this CommonColor color) => new CGColor (color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); - - public static NSColor ToNSColor (this CommonColor color) => NSColor.FromRgba (color.R, color.G, color.B, color.A); diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs new file mode 100644 index 0000000..ca91629 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/EmptyBrushEditorViewController.cs @@ -0,0 +1,28 @@ +using AppKit; +using CoreGraphics; +using Xamarin.PropertyEditing.Drawing; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + class EmptyBrushEditorViewController : PropertyViewController<BrushPropertyViewModel> + { + NSButton brushEditor; + + public EmptyBrushEditorViewController () + { + PreferredContentSize = new CGSize (100, 100); + } + + public override void LoadView () + { + View = brushEditor = new NSButton { + Title = "Edit" + }; + + brushEditor.Activated += (o, e) => { + ViewModel.SelectedBrushType = CommonBrushType.Solid; + }; + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs new file mode 100644 index 0000000..cde9f35 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialBrushEditorViewController.cs @@ -0,0 +1,43 @@ +using System; +using System.ComponentModel; +using System.Linq; +using AppKit; +using CoreGraphics; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + class MaterialBrushEditorViewController : PropertyViewController <BrushPropertyViewModel> + { + MaterialView materialEditor; + + public MaterialBrushEditorViewController () + { + PreferredContentSize = new CGSize (200, 230); + } + + public override void OnPropertyChanged (object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) { + case nameof (BrushPropertyViewModel.Value): + case nameof (BrushPropertyViewModel.MaterialDesign): + if (materialEditor != null) + materialEditor.ViewModel = ViewModel; + break; + } + } + + public override void OnViewModelChanged (BrushPropertyViewModel oldModel) + { + if (materialEditor != null) + materialEditor.ViewModel = ViewModel; + } + + public override void LoadView () + { + View = materialEditor = new MaterialView { + ViewModel = ViewModel + }; + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialColorLayer.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialColorLayer.cs new file mode 100644 index 0000000..042e7f9 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialColorLayer.cs @@ -0,0 +1,66 @@ +using CoreAnimation; +using Xamarin.PropertyEditing.Drawing; + +namespace Xamarin.PropertyEditing.Mac +{ + class MaterialColorLayer : CATextLayer + { + public MaterialColorLayer () + { + AddSublayer (Selection); + } + + CATextLayer Selection { get; } = new CATextLayer () { + CornerRadius = 3 + }; + + string text; + public string Text + { + get => text; + set + { + text = value; + SetNeedsLayout (); + } + } + + CommonColor materialColor; + public new CommonColor BackgroundColor + { + get => materialColor; + set + { + materialColor = value; + base.BackgroundColor = materialColor.ToCGColor (); + } + } + + bool isSelected; + public bool IsSelected + { + get => isSelected; + set + { + if (isSelected == value) + return; + isSelected = value; + SetNeedsLayout (); + } + } + + public override void LayoutSublayers () + { + base.LayoutSublayers (); + //String = isSelected ? "" : text; + Selection.String = text; + Selection.Frame = Frame.Bounds ().Border (new CommonThickness (3)); + Selection.BorderWidth = isSelected ? 2 : 0; + Selection.BorderColor = ForegroundColor; + Selection.ForegroundColor = ForegroundColor; + Selection.FontSize = FontSize; + Selection.ContentsScale = ContentsScale; + Selection.TextAlignmentMode = TextAlignmentMode; + } + } +} diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs new file mode 100644 index 0000000..b48bb41 --- /dev/null +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/MaterialView.cs @@ -0,0 +1,197 @@ +using System; +using System.Linq; +using AppKit; +using CoreAnimation; +using CoreGraphics; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Mac +{ + class MaterialView : NSView + { + public override bool IsFlipped => true; + + readonly string[] ColorNames = { + "50", + "100", + "200", + "300", + "400", + "500", + "600", + "700", + "800", + "900" + }; + + readonly string[] AccentNames = { + "A100", + "A200", + "A400", + "A700" + }; + + readonly string[] BlackWhite = { + "White", + "Black" + }; + + public MaterialView () : base () + { + Initialize (); + } + + void Initialize () + { + WantsLayer = true; + } + + BrushPropertyViewModel viewModel; + public BrushPropertyViewModel ViewModel + { + get => viewModel; + set + { + viewModel = value; + NeedsLayout = true; + } + } + + public MaterialDesignColorViewModel MaterialDesign + { + get => ViewModel?.MaterialDesign; + } + + public override void Layout () + { + if (Layer?.Sublayers != null) + foreach (var l in Layer.Sublayers) + l.RemoveFromSuperLayer (); + + if (MaterialDesign == null) + return; + + var colors = MaterialDesign.Palettes.Select (p => new { p.Name, Color = p.MainColor }).ToArray (); + int col = 0; + nfloat x = 0; + nfloat y = 6; + var width = (Frame.Width - 54) / 10; + var height = (Frame.Height - 49) / 4; + + 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 l = new MaterialColorLayer { + Frame = frame, + ForegroundColor = selectedColor.CGColor, + BackgroundColor = p.Color, + CornerRadius = 3, + BorderColor = new CGColor (.5f, .5f, .5f, .5f), + MasksToBounds = false, + IsSelected = MaterialDesign.Color == p.Color + }; + + Layer.AddSublayer (l); + x += width + 6; + col++; + if (col >= 10) { + x = 0; + y += height + 6; + col = 0; + } + } + + Layer.AddSublayer (new CATextLayer { + ForegroundColor = NSColor.ControlText.CGColor, + Frame = new CGRect (x, y + 6, Frame.Width, 25), + String = MaterialDesign.ColorName, + FontSize = NSFont.SmallSystemFontSize, + ContentsScale = Window?.Screen?.BackingScaleFactor ?? NSScreen.MainScreen.BackingScaleFactor + }); + + y += 25; + x = 0; + width = Frame.Width / MaterialDesign.NormalColorScale.Count (); + var names = MaterialDesign.NormalColorScale.Count () > 2 ? ColorNames : BlackWhite; + 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); + foreach (var n in MaterialDesign.NormalColorScale.Zip (names, (c, name) => new { Name = name, Color = c.Value })) { + var frame = new CGRect (x, y, width, height); + var selectedColor = n.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White; + var l = new MaterialColorLayer { + BackgroundColor = n.Color, + ForegroundColor = selectedColor.CGColor, + Frame = new CGRect (x, 0, width, height), + Text = n.Name, + FontSize = 12, + ContentsScale = NSScreen.MainScreen.BackingScaleFactor, + TextAlignmentMode = CATextLayerAlignmentMode.Center, + IsSelected = MaterialDesign.Color == n.Color + }; + normal.AddSublayer (l); + x += width; + } + + if (MaterialDesign.AccentColorScale.Count () <= 0) + 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 / MaterialDesign.AccentColorScale.Count (); + foreach (var n in MaterialDesign.AccentColorScale.Zip (AccentNames, (c, n) => new { Name = n, Color = c.Value })) { + var frame = new CGRect (x, y, width, height); + var selectedColor = n.Color.Lightness > 0.58 ? NSColor.Black : NSColor.White; + var l = new MaterialColorLayer { + BackgroundColor = n.Color, + ForegroundColor = selectedColor.CGColor, + Frame = new CGRect (x, 0, width, height), + Text = n.Name, + FontSize = 12, + ContentsScale = NSScreen.MainScreen.BackingScaleFactor, + TextAlignmentMode = CATextLayerAlignmentMode.Center, + IsSelected = ViewModel.Solid.Color == n.Color, + }; + + accent.AddSublayer (l); + x += width; + } + } + + public override void MouseDown (NSEvent theEvent) + { + UpdateFromEvent (theEvent); + } + + public void UpdateFromEvent (NSEvent theEvent) + { + 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) { + ViewModel.Solid.Color = editor.BackgroundColor; + NeedsLayout = true; + } + } + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs index 6f7d350..56d942c 100644 --- a/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs +++ b/Xamarin.PropertyEditing.Mac/Controls/Custom/SolidColorBrushEditor.cs @@ -103,147 +103,6 @@ namespace Xamarin.PropertyEditing.Mac abstract public void UpdateFromLocation (EditorInteraction viewModel, CGPoint location); } - class CommonGradientBrushLayer : CALayer - { - public CommonGradientBrushLayer () - { - } - - public CommonGradientBrushLayer (IntPtr handle) : base () - { - } - - CommonGradientBrush brush; - public CommonGradientBrush Brush - { - get => brush; - set { - brush = value; - SetNeedsDisplay (); - } - } - - public override void DrawInContext (CGContext ctx) - { - ctx.SaveState (); - - var colorspace = CGColorSpace.CreateDeviceRGB (); - var colors = Brush.GradientStops.Select (stop => stop.Color.ToCGColor ()).ToArray (); - var locations = Brush.GradientStops.Select (stop => (nfloat)stop.Offset).ToArray (); - - var gradient = new CGGradient (colorspace, colors, locations); - var center = new CGPoint (Bounds.Width / 2f, Bounds.Height / 2f); - var radius = (float)Math.Min (Bounds.Width / 2.0, Bounds.Height / 2.0); - - switch (Brush) { - case CommonLinearGradientBrush linear: - ctx.DrawLinearGradient ( - gradient, - new CGPoint (0, 0), - new CGPoint (0, Bounds.Width), - CGGradientDrawingOptions.None); - break; - case CommonRadialGradientBrush radial: - ctx.DrawRadialGradient ( - gradient, - startCenter: center, - startRadius: 0f, - endCenter: center, - endRadius: radius, - options: CGGradientDrawingOptions.None); - break; - } - } - } - - class CommonBrushLayer : CALayer - { - public CommonBrushLayer () - { - this.CornerRadius = 3; - this.BorderColor = new CGColor (.5f, .5f, .5f, .5f); - this.BorderWidth = 1; - MasksToBounds = true; - } - - CALayer brushLayer; - CALayer BrushLayer { - get => brushLayer; - set { - if (brushLayer != null) - brushLayer.RemoveFromSuperLayer (); - - brushLayer = value; - - if (brushLayer != null) - AddSublayer (brushLayer); - } - } - - CommonBrush brush; - public CommonBrush Brush { - get => brush; - set { - brush = value; - BrushLayer = CreateBrushLayer (brush); - Opacity = brush == null ? 0 : 1; - } - } - - public static CALayer CreateBrushLayer (CommonBrush brush) - { - switch (brush) { - case CommonSolidBrush solid: - return new CALayer { - BackgroundColor = solid.Color.ToCGColor (), - Opacity = (float)solid.Opacity - }; - case CommonGradientBrush gradient: - return new CommonGradientBrushLayer { - Opacity = (float)gradient.Opacity - }; - default: - return new CALayer { - BackgroundColor = NSColor.Clear.CGColor - }; - } - } - - public override void LayoutSublayers () - { - base.LayoutSublayers (); - BrushLayer.Frame = new CGRect (0, 0, Frame.Width, Frame.Height); - Contents = DrawingExtensions.GenerateCheckerboard (Frame); - } - - public NSImage RenderPreview () - { - var scale = this.ContentsScale; - nint h = (nint)(this.Bounds.Height * scale); - nint w = (nint)(this.Bounds.Width * scale); - nint bytesPerRow = w * 4; - - if (h <= 0 || w <= 0) - return null; - - using (var colorSpace = CGColorSpace.CreateGenericRgb ()) - using (var context = new CGBitmapContext (IntPtr.Zero, w, h, 8, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast)) { - this.RenderInContext (context); - using (var image = context.ToImage ()) { - return new NSImage (image, new CGSize (w, h)); - } - } - } - } - - public enum ChannelEditorType - { - RGB, - HLS, - HSB, - CMYK - }; - class HistoryLayer : ColorEditorLayer { const float Margin = 3; @@ -305,8 +164,8 @@ namespace Xamarin.PropertyEditing.Mac const float GripRadius = 4; const float BorderRadius = 3; const float Margin = 3; - ComponentEditor saturationEditor = new HsbSaturationComponentEditor (); - ComponentEditor brightnessEditor = new HsbBrightnessComponentEditor (); + ChannelEditor saturationEditor = new HsbSaturationChannelEditor (); + ChannelEditor brightnessEditor = new HsbBrightnessChannelEditor (); public ShadeLayer () { @@ -407,7 +266,7 @@ namespace Xamarin.PropertyEditing.Mac const float Margin = 3; const float BorderRadius = 3; const float GripRadius = 3; - ComponentEditor hueEditor = new HsbHueComponentEditor (); + ChannelEditor hueEditor = new HsbHueChannelEditor (); public CGColor GripColor { diff --git a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj index 45427ab..534033b 100644 --- a/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj +++ b/Xamarin.PropertyEditing.Mac/Xamarin.PropertyEditing.Mac.csproj @@ -105,6 +105,14 @@ <Compile Include="Controls\Custom\ColorComponentTabVewController.cs" />
<Compile Include="Controls\Custom\ColorComponentViewController.cs" />
<Compile Include="Controls\Custom\NotifyingViewAdaptor.cs" />
+ <Compile Include="Controls\Custom\MaterialBrushEditorViewController.cs" />
+ <Compile Include="Controls\Custom\MaterialView.cs" />
+ <Compile Include="Controls\Custom\MaterialColorLayer.cs" />
+ <Compile Include="Controls\Custom\EmptyBrushEditorViewController.cs" />
+ <Compile Include="Controls\Custom\ChannelEditorType.cs" />
+ <Compile Include="Controls\Custom\ChannelEditor.cs" />
+ <Compile Include="Controls\Custom\CommonBrushLayer.cs" />
+ <Compile Include="Controls\Custom\CommonGradientBrushLayer.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controls\" />
|