From f93b21a2a21c8b043389a13ea9f2c524e674b2e8 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 21 Dec 2021 10:27:09 -0600 Subject: [PATCH] [controls] Brush.Foo should return immutable instances When profiling a `dotnet new maui` app, with this package: https://github.com/jonathanpeppers/Mono.Profiler.Android The `alloc` report shows: Allocation summary Bytes Count Average Type name 39984 147 2 72 Microsoft.Maui.Controls.SolidColorBrush Stack trace: 38352 bytes from: (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) Microsoft.Maui.Controls.VisualElement:.cctor () (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr) Microsoft.Maui.Controls.Brush:.cctor () Reviewing the `Brush` class, there are indeed 147 `SolidColorBrush` created on startup that are stored in fields. But what is weird about this, is that `SolidColorBrush` is mutable! public Color Color { get => (Color)GetValue(ColorProperty); set => SetValue(ColorProperty, value); } So I could literally write code like: Brush.Blue.Color = Colors.Red; Blue is red! (insert evil laughter?) I think the appropriate fix here is that all of these `static readonly` fields should just be properties that return a new `ImmutableBrush`. We can cache the values in fields on demand. Then someone can't do something evil like change `Blue` to `Red`? I reviewed WPF source code to check what they do, and they took a similar approach: https://github.com/dotnet/wpf/blob/5e8187344b2b561ef08b9ca2735cd89cbdd3c11e/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/brushes.cs#L33-L1586 We should make this API change now before MAUI is stable, and we have the side benefit to save 39984 bytes of memory on startup? I added tests for these scenarios, and discovered 3 typos for `Brush` colors that listed the wrong color. --- src/Controls/src/Core/Brush.cs | 423 +++++++++++++++-------- src/Controls/src/Core/ImmutableBrush.cs | 23 ++ src/Controls/src/Core/SolidColorBrush.cs | 2 +- src/Core/tests/UnitTests/BrushTests.cs | 39 +++ 4 files changed, 345 insertions(+), 142 deletions(-) create mode 100644 src/Controls/src/Core/ImmutableBrush.cs create mode 100644 src/Core/tests/UnitTests/BrushTests.cs diff --git a/src/Controls/src/Core/Brush.cs b/src/Controls/src/Core/Brush.cs index 61196a3bd435..d3d8e7c1d99a 100644 --- a/src/Controls/src/Core/Brush.cs +++ b/src/Controls/src/Core/Brush.cs @@ -19,146 +19,287 @@ public static bool IsNullOrEmpty(Brush brush) return brush == null || brush.IsEmpty; } - public static readonly SolidColorBrush AliceBlue = new SolidColorBrush(Colors.AliceBlue); - public static readonly SolidColorBrush AntiqueWhite = new SolidColorBrush(Colors.AntiqueWhite); - public static readonly SolidColorBrush Aqua = new SolidColorBrush(Colors.Aqua); - public static readonly SolidColorBrush Aquamarine = new SolidColorBrush(Colors.Aquamarine); - public static readonly SolidColorBrush Azure = new SolidColorBrush(Colors.Azure); - public static readonly SolidColorBrush Beige = new SolidColorBrush(Colors.Beige); - public static readonly SolidColorBrush Bisque = new SolidColorBrush(Colors.Bisque); - public static readonly SolidColorBrush Black = new SolidColorBrush(Colors.Black); - public static readonly SolidColorBrush BlanchedAlmond = new SolidColorBrush(Colors.BlanchedAlmond); - public static readonly SolidColorBrush Blue = new SolidColorBrush(Colors.Blue); - public static readonly SolidColorBrush BlueViolet = new SolidColorBrush(Colors.BlueViolet); - public static readonly SolidColorBrush Brown = new SolidColorBrush(Colors.Brown); - public static readonly SolidColorBrush BurlyWood = new SolidColorBrush(Colors.BurlyWood); - public static readonly SolidColorBrush CadetBlue = new SolidColorBrush(Colors.CadetBlue); - public static readonly SolidColorBrush Chartreuse = new SolidColorBrush(Colors.Chartreuse); - public static readonly SolidColorBrush Chocolate = new SolidColorBrush(Colors.Chocolate); - public static readonly SolidColorBrush Coral = new SolidColorBrush(Colors.Coral); - public static readonly SolidColorBrush CornflowerBlue = new SolidColorBrush(Colors.CornflowerBlue); - public static readonly SolidColorBrush Cornsilk = new SolidColorBrush(Colors.Cornsilk); - public static readonly SolidColorBrush Crimson = new SolidColorBrush(Colors.Crimson); - public static readonly SolidColorBrush Cyan = new SolidColorBrush(Colors.Cyan); - public static readonly SolidColorBrush DarkBlue = new SolidColorBrush(Colors.DarkBlue); - public static readonly SolidColorBrush DarkCyan = new SolidColorBrush(Colors.DarkCyan); - public static readonly SolidColorBrush DarkGoldenrod = new SolidColorBrush(Colors.DarkGoldenrod); - public static readonly SolidColorBrush DarkGray = new SolidColorBrush(Colors.DarkGray); - public static readonly SolidColorBrush DarkGreen = new SolidColorBrush(Colors.DarkGreen); - public static readonly SolidColorBrush DarkKhaki = new SolidColorBrush(Colors.DarkKhaki); - public static readonly SolidColorBrush DarkMagenta = new SolidColorBrush(Colors.DarkMagenta); - public static readonly SolidColorBrush DarkOliveGreen = new SolidColorBrush(Colors.DarkOliveGreen); - public static readonly SolidColorBrush DarkOrange = new SolidColorBrush(Colors.DarkOrange); - public static readonly SolidColorBrush DarkOrchid = new SolidColorBrush(Colors.DarkOrchid); - public static readonly SolidColorBrush DarkRed = new SolidColorBrush(Colors.DarkRed); - public static readonly SolidColorBrush DarkSalmon = new SolidColorBrush(Colors.DarkSalmon); - public static readonly SolidColorBrush DarkSeaGreen = new SolidColorBrush(Colors.DarkSeaGreen); - public static readonly SolidColorBrush DarkSlateBlue = new SolidColorBrush(Colors.DarkSlateBlue); - public static readonly SolidColorBrush DarkSlateGray = new SolidColorBrush(Colors.DarkSlateGray); - public static readonly SolidColorBrush DarkTurquoise = new SolidColorBrush(Colors.DarkTurquoise); - public static readonly SolidColorBrush DarkViolet = new SolidColorBrush(Colors.DarkViolet); - public static readonly SolidColorBrush DeepPink = new SolidColorBrush(Colors.DeepPink); - public static readonly SolidColorBrush DeepSkyBlue = new SolidColorBrush(Colors.DeepSkyBlue); - public static readonly SolidColorBrush DimGray = new SolidColorBrush(Colors.DimGray); - public static readonly SolidColorBrush DodgerBlue = new SolidColorBrush(Colors.DodgerBlue); - public static readonly SolidColorBrush Firebrick = new SolidColorBrush(Colors.Firebrick); - public static readonly SolidColorBrush FloralWhite = new SolidColorBrush(Colors.FloralWhite); - public static readonly SolidColorBrush ForestGreen = new SolidColorBrush(Colors.ForestGreen); - public static readonly SolidColorBrush Fuchsia = new SolidColorBrush(Colors.Fuchsia); - public static readonly SolidColorBrush Gainsboro = new SolidColorBrush(Colors.Gainsboro); - public static readonly SolidColorBrush GhostWhite = new SolidColorBrush(Colors.GhostWhite); - public static readonly SolidColorBrush Gold = new SolidColorBrush(Colors.Gold); - public static readonly SolidColorBrush Goldenrod = new SolidColorBrush(Colors.Goldenrod); - public static readonly SolidColorBrush Gray = new SolidColorBrush(Colors.Gray); - public static readonly SolidColorBrush Green = new SolidColorBrush(Colors.Green); - public static readonly SolidColorBrush GreenYellow = new SolidColorBrush(Colors.GreenYellow); - public static readonly SolidColorBrush Honeydew = new SolidColorBrush(Colors.Honeydew); - public static readonly SolidColorBrush HotPink = new SolidColorBrush(Colors.HotPink); - public static readonly SolidColorBrush IndianRed = new SolidColorBrush(Colors.IndianRed); - public static readonly SolidColorBrush Indigo = new SolidColorBrush(Colors.Indigo); - public static readonly SolidColorBrush Ivory = new SolidColorBrush(Colors.Ivory); - public static readonly SolidColorBrush Khaki = new SolidColorBrush(Colors.Ivory); - public static readonly SolidColorBrush Lavender = new SolidColorBrush(Colors.Lavender); - public static readonly SolidColorBrush LavenderBlush = new SolidColorBrush(Colors.LavenderBlush); - public static readonly SolidColorBrush LawnGreen = new SolidColorBrush(Colors.LawnGreen); - public static readonly SolidColorBrush LemonChiffon = new SolidColorBrush(Colors.LemonChiffon); - public static readonly SolidColorBrush LightBlue = new SolidColorBrush(Colors.LightBlue); - public static readonly SolidColorBrush LightCoral = new SolidColorBrush(Colors.LightCoral); - public static readonly SolidColorBrush LightCyan = new SolidColorBrush(Colors.LightCyan); - public static readonly SolidColorBrush LightGoldenrodYellow = new SolidColorBrush(Colors.LightGoldenrodYellow); - public static readonly SolidColorBrush LightGray = new SolidColorBrush(Colors.LightGray); - public static readonly SolidColorBrush LightGreen = new SolidColorBrush(Colors.LightGreen); - public static readonly SolidColorBrush LightPink = new SolidColorBrush(Colors.LightPink); - public static readonly SolidColorBrush LightSalmon = new SolidColorBrush(Colors.LightSalmon); - public static readonly SolidColorBrush LightSeaGreen = new SolidColorBrush(Colors.LightSeaGreen); - public static readonly SolidColorBrush LightSkyBlue = new SolidColorBrush(Colors.LightSkyBlue); - public static readonly SolidColorBrush LightSlateGray = new SolidColorBrush(Colors.LightSlateGray); - public static readonly SolidColorBrush LightSteelBlue = new SolidColorBrush(Colors.LightSteelBlue); - public static readonly SolidColorBrush LightYellow = new SolidColorBrush(Colors.LightYellow); - public static readonly SolidColorBrush Lime = new SolidColorBrush(Colors.Lime); - public static readonly SolidColorBrush LimeGreen = new SolidColorBrush(Colors.LimeGreen); - public static readonly SolidColorBrush Linen = new SolidColorBrush(Colors.Linen); - public static readonly SolidColorBrush Magenta = new SolidColorBrush(Colors.Magenta); - public static readonly SolidColorBrush Maroon = new SolidColorBrush(Colors.Maroon); - public static readonly SolidColorBrush MediumAquamarine = new SolidColorBrush(Colors.MediumAquamarine); - public static readonly SolidColorBrush MediumBlue = new SolidColorBrush(Colors.MediumBlue); - public static readonly SolidColorBrush MediumOrchid = new SolidColorBrush(Colors.MediumOrchid); - public static readonly SolidColorBrush MediumPurple = new SolidColorBrush(Colors.MediumPurple); - public static readonly SolidColorBrush MediumSeaGreen = new SolidColorBrush(Colors.MediumSeaGreen); - public static readonly SolidColorBrush MediumSlateBlue = new SolidColorBrush(Colors.MediumSlateBlue); - public static readonly SolidColorBrush MediumSpringGreen = new SolidColorBrush(Colors.MediumSpringGreen); - public static readonly SolidColorBrush MediumTurquoise = new SolidColorBrush(Colors.MediumTurquoise); - public static readonly SolidColorBrush MediumVioletRed = new SolidColorBrush(Colors.MediumVioletRed); - public static readonly SolidColorBrush MidnightBlue = new SolidColorBrush(Colors.MidnightBlue); - public static readonly SolidColorBrush MintCream = new SolidColorBrush(Colors.MintCream); - public static readonly SolidColorBrush MistyRose = new SolidColorBrush(Colors.MistyRose); - public static readonly SolidColorBrush Moccasin = new SolidColorBrush(Colors.Moccasin); - public static readonly SolidColorBrush NavajoWhite = new SolidColorBrush(Colors.NavajoWhite); - public static readonly SolidColorBrush Navy = new SolidColorBrush(Colors.Navy); - public static readonly SolidColorBrush OldLace = new SolidColorBrush(Colors.DarkBlue); - public static readonly SolidColorBrush Olive = new SolidColorBrush(Colors.Olive); - public static readonly SolidColorBrush OliveDrab = new SolidColorBrush(Colors.OliveDrab); - public static readonly SolidColorBrush Orange = new SolidColorBrush(Colors.Orange); - public static readonly SolidColorBrush OrangeRed = new SolidColorBrush(Colors.OrangeRed); - public static readonly SolidColorBrush Orchid = new SolidColorBrush(Colors.Orchid); - public static readonly SolidColorBrush PaleGoldenrod = new SolidColorBrush(Colors.PaleGoldenrod); - public static readonly SolidColorBrush PaleGreen = new SolidColorBrush(Colors.MistyRose); - public static readonly SolidColorBrush PaleTurquoise = new SolidColorBrush(Colors.PaleTurquoise); - public static readonly SolidColorBrush PaleVioletRed = new SolidColorBrush(Colors.PaleVioletRed); - public static readonly SolidColorBrush PapayaWhip = new SolidColorBrush(Colors.PapayaWhip); - public static readonly SolidColorBrush PeachPuff = new SolidColorBrush(Colors.PeachPuff); - public static readonly SolidColorBrush Peru = new SolidColorBrush(Colors.Peru); - public static readonly SolidColorBrush Pink = new SolidColorBrush(Colors.Pink); - public static readonly SolidColorBrush Plum = new SolidColorBrush(Colors.Plum); - public static readonly SolidColorBrush PowderBlue = new SolidColorBrush(Colors.PowderBlue); - public static readonly SolidColorBrush Purple = new SolidColorBrush(Colors.Purple); - public static readonly SolidColorBrush Red = new SolidColorBrush(Colors.Red); - public static readonly SolidColorBrush RosyBrown = new SolidColorBrush(Colors.RosyBrown); - public static readonly SolidColorBrush RoyalBlue = new SolidColorBrush(Colors.RoyalBlue); - public static readonly SolidColorBrush SaddleBrown = new SolidColorBrush(Colors.SaddleBrown); - public static readonly SolidColorBrush Salmon = new SolidColorBrush(Colors.Salmon); - public static readonly SolidColorBrush SandyBrown = new SolidColorBrush(Colors.SandyBrown); - public static readonly SolidColorBrush SeaGreen = new SolidColorBrush(Colors.SeaGreen); - public static readonly SolidColorBrush SeaShell = new SolidColorBrush(Colors.SeaShell); - public static readonly SolidColorBrush Sienna = new SolidColorBrush(Colors.Sienna); - public static readonly SolidColorBrush Silver = new SolidColorBrush(Colors.Silver); - public static readonly SolidColorBrush SkyBlue = new SolidColorBrush(Colors.SkyBlue); - public static readonly SolidColorBrush SlateBlue = new SolidColorBrush(Colors.SlateBlue); - public static readonly SolidColorBrush SlateGray = new SolidColorBrush(Colors.SlateGray); - public static readonly SolidColorBrush Snow = new SolidColorBrush(Colors.Snow); - public static readonly SolidColorBrush SpringGreen = new SolidColorBrush(Colors.SpringGreen); - public static readonly SolidColorBrush SteelBlue = new SolidColorBrush(Colors.SteelBlue); - public static readonly SolidColorBrush Tan = new SolidColorBrush(Colors.Tan); - public static readonly SolidColorBrush Teal = new SolidColorBrush(Colors.Teal); - public static readonly SolidColorBrush Thistle = new SolidColorBrush(Colors.Thistle); - public static readonly SolidColorBrush Tomato = new SolidColorBrush(Colors.Tomato); - public static readonly SolidColorBrush Transparent = new SolidColorBrush(Colors.Transparent); - public static readonly SolidColorBrush Turquoise = new SolidColorBrush(Colors.Turquoise); - public static readonly SolidColorBrush Violet = new SolidColorBrush(Colors.Violet); - public static readonly SolidColorBrush Wheat = new SolidColorBrush(Colors.Wheat); - public static readonly SolidColorBrush White = new SolidColorBrush(Colors.White); - public static readonly SolidColorBrush WhiteSmoke = new SolidColorBrush(Colors.WhiteSmoke); - public static readonly SolidColorBrush Yellow = new SolidColorBrush(Colors.Yellow); - public static readonly SolidColorBrush YellowGreen = new SolidColorBrush(Colors.YellowGreen); + static ImmutableBrush aliceBlue; + public static SolidColorBrush AliceBlue => aliceBlue ??= new(Colors.AliceBlue); + static ImmutableBrush antiqueWhite; + public static SolidColorBrush AntiqueWhite => antiqueWhite ??= new(Colors.AntiqueWhite); + static ImmutableBrush aqua; + public static SolidColorBrush Aqua => aqua ??= new(Colors.Aqua); + static ImmutableBrush aquamarine; + public static SolidColorBrush Aquamarine => aquamarine ??= new(Colors.Aquamarine); + static ImmutableBrush azure; + public static SolidColorBrush Azure => azure ??= new(Colors.Azure); + static ImmutableBrush beige; + public static SolidColorBrush Beige => beige ??= new(Colors.Beige); + static ImmutableBrush bisque; + public static SolidColorBrush Bisque => bisque ??= new(Colors.Bisque); + static ImmutableBrush black; + public static SolidColorBrush Black => black ??= new(Colors.Black); + static ImmutableBrush blanchedAlmond; + public static SolidColorBrush BlanchedAlmond => blanchedAlmond ??= new(Colors.BlanchedAlmond); + static ImmutableBrush blue; + public static SolidColorBrush Blue => blue ??= new(Colors.Blue); + static ImmutableBrush blueViolet; + public static SolidColorBrush BlueViolet => blueViolet ??= new(Colors.BlueViolet); + static ImmutableBrush brown; + public static SolidColorBrush Brown => brown ??= new(Colors.Brown); + static ImmutableBrush burlyWood; + public static SolidColorBrush BurlyWood => burlyWood ??= new(Colors.BurlyWood); + static ImmutableBrush cadetBlue; + public static SolidColorBrush CadetBlue => cadetBlue ??= new(Colors.CadetBlue); + static ImmutableBrush chartreuse; + public static SolidColorBrush Chartreuse => chartreuse ??= new(Colors.Chartreuse); + static ImmutableBrush chocolate; + public static SolidColorBrush Chocolate => chocolate ??= new(Colors.Chocolate); + static ImmutableBrush coral; + public static SolidColorBrush Coral => coral ??= new(Colors.Coral); + static ImmutableBrush cornflowerBlue; + public static SolidColorBrush CornflowerBlue => cornflowerBlue ??= new(Colors.CornflowerBlue); + static ImmutableBrush cornsilk; + public static SolidColorBrush Cornsilk => cornsilk ??= new(Colors.Cornsilk); + static ImmutableBrush crimson; + public static SolidColorBrush Crimson => crimson ??= new(Colors.Crimson); + static ImmutableBrush cyan; + public static SolidColorBrush Cyan => cyan ??= new(Colors.Cyan); + static ImmutableBrush darkBlue; + public static SolidColorBrush DarkBlue => darkBlue ??= new(Colors.DarkBlue); + static ImmutableBrush darkCyan; + public static SolidColorBrush DarkCyan => darkCyan ??= new(Colors.DarkCyan); + static ImmutableBrush darkGoldenrod; + public static SolidColorBrush DarkGoldenrod => darkGoldenrod ??= new(Colors.DarkGoldenrod); + static ImmutableBrush darkGray; + public static SolidColorBrush DarkGray => darkGray ??= new(Colors.DarkGray); + static ImmutableBrush darkGreen; + public static SolidColorBrush DarkGreen => darkGreen ??= new(Colors.DarkGreen); + static ImmutableBrush darkKhaki; + public static SolidColorBrush DarkKhaki => darkKhaki ??= new(Colors.DarkKhaki); + static ImmutableBrush darkMagenta; + public static SolidColorBrush DarkMagenta => darkMagenta ??= new(Colors.DarkMagenta); + static ImmutableBrush darkOliveGreen; + public static SolidColorBrush DarkOliveGreen => darkOliveGreen ??= new(Colors.DarkOliveGreen); + static ImmutableBrush darkOrange; + public static SolidColorBrush DarkOrange => darkOrange ??= new(Colors.DarkOrange); + static ImmutableBrush darkOrchid; + public static SolidColorBrush DarkOrchid => darkOrchid ??= new(Colors.DarkOrchid); + static ImmutableBrush darkRed; + public static SolidColorBrush DarkRed => darkRed ??= new(Colors.DarkRed); + static ImmutableBrush darkSalmon; + public static SolidColorBrush DarkSalmon => darkSalmon ??= new(Colors.DarkSalmon); + static ImmutableBrush darkSeaGreen; + public static SolidColorBrush DarkSeaGreen => darkSeaGreen ??= new(Colors.DarkSeaGreen); + static ImmutableBrush darkSlateBlue; + public static SolidColorBrush DarkSlateBlue => darkSlateBlue ??= new(Colors.DarkSlateBlue); + static ImmutableBrush darkSlateGray; + public static SolidColorBrush DarkSlateGray => darkSlateGray ??= new(Colors.DarkSlateGray); + static ImmutableBrush darkTurquoise; + public static SolidColorBrush DarkTurquoise => darkTurquoise ??= new(Colors.DarkTurquoise); + static ImmutableBrush darkViolet; + public static SolidColorBrush DarkViolet => darkViolet ??= new(Colors.DarkViolet); + static ImmutableBrush deepPink; + public static SolidColorBrush DeepPink => deepPink ??= new(Colors.DeepPink); + static ImmutableBrush deepSkyBlue; + public static SolidColorBrush DeepSkyBlue => deepSkyBlue ??= new(Colors.DeepSkyBlue); + static ImmutableBrush dimGray; + public static SolidColorBrush DimGray => dimGray ??= new(Colors.DimGray); + static ImmutableBrush dodgerBlue; + public static SolidColorBrush DodgerBlue => dodgerBlue ??= new(Colors.DodgerBlue); + static ImmutableBrush firebrick; + public static SolidColorBrush Firebrick => firebrick ??= new(Colors.Firebrick); + static ImmutableBrush floralWhite; + public static SolidColorBrush FloralWhite => floralWhite ??= new(Colors.FloralWhite); + static ImmutableBrush forestGreen; + public static SolidColorBrush ForestGreen => forestGreen ??= new(Colors.ForestGreen); + static ImmutableBrush fuschia; + public static SolidColorBrush Fuchsia => fuschia ??= new(Colors.Fuchsia); + static ImmutableBrush gainsboro; + public static SolidColorBrush Gainsboro => gainsboro ??= new(Colors.Gainsboro); + static ImmutableBrush ghostWhite; + public static SolidColorBrush GhostWhite => ghostWhite ??= new(Colors.GhostWhite); + static ImmutableBrush gold; + public static SolidColorBrush Gold => gold ??= new(Colors.Gold); + static ImmutableBrush goldenrod; + public static SolidColorBrush Goldenrod => goldenrod ??= new(Colors.Goldenrod); + static ImmutableBrush gray; + public static SolidColorBrush Gray => gray ??= new(Colors.Gray); + static ImmutableBrush green; + public static SolidColorBrush Green => green ??= new(Colors.Green); + static ImmutableBrush greenYellow; + public static SolidColorBrush GreenYellow => greenYellow ??= new(Colors.GreenYellow); + static ImmutableBrush honeydew; + public static SolidColorBrush Honeydew => honeydew ??= new(Colors.Honeydew); + static ImmutableBrush hotPink; + public static SolidColorBrush HotPink => hotPink ??= new(Colors.HotPink); + static ImmutableBrush indianRed; + public static SolidColorBrush IndianRed => indianRed ??= new(Colors.IndianRed); + static ImmutableBrush indigo; + public static SolidColorBrush Indigo => indigo ??= new(Colors.Indigo); + static ImmutableBrush ivory; + public static SolidColorBrush Ivory => ivory ??= new(Colors.Ivory); + static ImmutableBrush khaki; + public static SolidColorBrush Khaki => khaki ??= new(Colors.Khaki); + static ImmutableBrush lavender; + public static SolidColorBrush Lavender => lavender ??= new(Colors.Lavender); + static ImmutableBrush lavenderBlush; + public static SolidColorBrush LavenderBlush => lavenderBlush ??= new(Colors.LavenderBlush); + static ImmutableBrush lawnGreen; + public static SolidColorBrush LawnGreen => lawnGreen ??= new(Colors.LawnGreen); + static ImmutableBrush lemonChiffon; + public static SolidColorBrush LemonChiffon => lemonChiffon ??= new(Colors.LemonChiffon); + static ImmutableBrush lightBlue; + public static SolidColorBrush LightBlue => lightBlue ??= new(Colors.LightBlue); + static ImmutableBrush lightCoral; + public static SolidColorBrush LightCoral => lightCoral ??= new(Colors.LightCoral); + static ImmutableBrush lightCyan; + public static SolidColorBrush LightCyan => lightCyan ??= new(Colors.LightCyan); + static ImmutableBrush lightGoldenrodYellow; + public static SolidColorBrush LightGoldenrodYellow => lightGoldenrodYellow ??= new(Colors.LightGoldenrodYellow); + static ImmutableBrush lightGray; + public static SolidColorBrush LightGray => lightGray ??= new(Colors.LightGray); + static ImmutableBrush lightGreen; + public static SolidColorBrush LightGreen => lightGreen ??= new(Colors.LightGreen); + static ImmutableBrush lightPink; + public static SolidColorBrush LightPink => lightPink ??= new(Colors.LightPink); + static ImmutableBrush lightSalmon; + public static SolidColorBrush LightSalmon => lightSalmon ??= new(Colors.LightSalmon); + static ImmutableBrush lightSeaGreen; + public static SolidColorBrush LightSeaGreen => lightSeaGreen ??= new(Colors.LightSeaGreen); + static ImmutableBrush lightSkyBlue; + public static SolidColorBrush LightSkyBlue => lightSkyBlue ??= new(Colors.LightSkyBlue); + static ImmutableBrush lightSlateGray; + public static SolidColorBrush LightSlateGray => lightSlateGray ??= new(Colors.LightSlateGray); + static ImmutableBrush lightSteelBlue; + public static SolidColorBrush LightSteelBlue => lightSteelBlue ??= new(Colors.LightSteelBlue); + static ImmutableBrush lightYellow; + public static SolidColorBrush LightYellow => lightYellow ??= new(Colors.LightYellow); + static ImmutableBrush lime; + public static SolidColorBrush Lime => lime ??= new(Colors.Lime); + static ImmutableBrush limeGreen; + public static SolidColorBrush LimeGreen => limeGreen ??= new(Colors.LimeGreen); + static ImmutableBrush linen; + public static SolidColorBrush Linen => linen ??= new(Colors.Linen); + static ImmutableBrush magenta; + public static SolidColorBrush Magenta => magenta ??= new(Colors.Magenta); + static ImmutableBrush maroon; + public static SolidColorBrush Maroon => maroon ??= new(Colors.Maroon); + static ImmutableBrush mediumAquararine; + public static SolidColorBrush MediumAquamarine => mediumAquararine ??= new(Colors.MediumAquamarine); + static ImmutableBrush mediumBlue; + public static SolidColorBrush MediumBlue => mediumBlue ??= new(Colors.MediumBlue); + static ImmutableBrush mediumOrchid; + public static SolidColorBrush MediumOrchid => mediumOrchid ??= new(Colors.MediumOrchid); + static ImmutableBrush mediumPurple; + public static SolidColorBrush MediumPurple => mediumPurple ??= new(Colors.MediumPurple); + static ImmutableBrush mediumSeaGreen; + public static SolidColorBrush MediumSeaGreen => mediumSeaGreen ??= new(Colors.MediumSeaGreen); + static ImmutableBrush mediumSlateBlue; + public static SolidColorBrush MediumSlateBlue => mediumSlateBlue ??= new(Colors.MediumSlateBlue); + static ImmutableBrush mediumSpringGreen; + public static SolidColorBrush MediumSpringGreen => mediumSpringGreen ??= new(Colors.MediumSpringGreen); + static ImmutableBrush mediumTurquoise; + public static SolidColorBrush MediumTurquoise => mediumTurquoise ??= new(Colors.MediumTurquoise); + static ImmutableBrush mediumVioletRed; + public static SolidColorBrush MediumVioletRed => mediumVioletRed ??= new(Colors.MediumVioletRed); + static ImmutableBrush midnightBlue; + public static SolidColorBrush MidnightBlue => midnightBlue ??= new(Colors.MidnightBlue); + static ImmutableBrush mintCream; + public static SolidColorBrush MintCream => mintCream ??= new(Colors.MintCream); + static ImmutableBrush mistyRose; + public static SolidColorBrush MistyRose => mistyRose ??= new(Colors.MistyRose); + static ImmutableBrush moccasin; + public static SolidColorBrush Moccasin => moccasin ??= new(Colors.Moccasin); + static ImmutableBrush navajoWhite; + public static SolidColorBrush NavajoWhite => navajoWhite ??= new(Colors.NavajoWhite); + static ImmutableBrush navy; + public static SolidColorBrush Navy => navy ??= new(Colors.Navy); + static ImmutableBrush oldLace; + public static SolidColorBrush OldLace => oldLace ??= new(Colors.OldLace); + static ImmutableBrush olive; + public static SolidColorBrush Olive => olive ??= new(Colors.Olive); + static ImmutableBrush oliveDrab; + public static SolidColorBrush OliveDrab => oliveDrab ??= new(Colors.OliveDrab); + static ImmutableBrush orange; + public static SolidColorBrush Orange => orange ??= new(Colors.Orange); + static ImmutableBrush orangeRed; + public static SolidColorBrush OrangeRed => orangeRed ??= new(Colors.OrangeRed); + static ImmutableBrush orchid; + public static SolidColorBrush Orchid => orchid ??= new(Colors.Orchid); + static ImmutableBrush paleGoldenrod; + public static SolidColorBrush PaleGoldenrod => paleGoldenrod ??= new(Colors.PaleGoldenrod); + static ImmutableBrush paleGreen; + public static SolidColorBrush PaleGreen => paleGreen ??= new(Colors.PaleGreen); + static ImmutableBrush paleTurquoise; + public static SolidColorBrush PaleTurquoise => paleTurquoise ??= new(Colors.PaleTurquoise); + static ImmutableBrush paleVioletRed; + public static SolidColorBrush PaleVioletRed => paleVioletRed ??= new(Colors.PaleVioletRed); + static ImmutableBrush papayaWhip; + public static SolidColorBrush PapayaWhip => papayaWhip ??= new(Colors.PapayaWhip); + static ImmutableBrush peachPuff; + public static SolidColorBrush PeachPuff => peachPuff ??= new(Colors.PeachPuff); + static ImmutableBrush peru; + public static SolidColorBrush Peru => peru ??= new(Colors.Peru); + static ImmutableBrush pink; + public static SolidColorBrush Pink => pink ??= new(Colors.Pink); + static ImmutableBrush plum; + public static SolidColorBrush Plum => plum ??= new(Colors.Plum); + static ImmutableBrush powderBlue; + public static SolidColorBrush PowderBlue => powderBlue ??= new(Colors.PowderBlue); + static ImmutableBrush purple; + public static SolidColorBrush Purple => purple ??= new(Colors.Purple); + static ImmutableBrush red; + public static SolidColorBrush Red => red ??= new(Colors.Red); + static ImmutableBrush rosyBrown; + public static SolidColorBrush RosyBrown => rosyBrown ??= new(Colors.RosyBrown); + static ImmutableBrush royalBlue; + public static SolidColorBrush RoyalBlue => royalBlue ??= new(Colors.RoyalBlue); + static ImmutableBrush saddleBrown; + public static SolidColorBrush SaddleBrown => saddleBrown ??= new(Colors.SaddleBrown); + static ImmutableBrush salmon; + public static SolidColorBrush Salmon => salmon ??= new(Colors.Salmon); + static ImmutableBrush sandyBrown; + public static SolidColorBrush SandyBrown => sandyBrown ??= new(Colors.SandyBrown); + static ImmutableBrush seaGreen; + public static SolidColorBrush SeaGreen => seaGreen ??= new(Colors.SeaGreen); + static ImmutableBrush seaShell; + public static SolidColorBrush SeaShell => seaShell ??= new(Colors.SeaShell); + static ImmutableBrush sienna; + public static SolidColorBrush Sienna => sienna ??= new(Colors.Sienna); + static ImmutableBrush silver; + public static SolidColorBrush Silver => silver ??= new(Colors.Silver); + static ImmutableBrush skyBlue; + public static SolidColorBrush SkyBlue => skyBlue ??= new(Colors.SkyBlue); + static ImmutableBrush slateBlue; + public static SolidColorBrush SlateBlue => slateBlue ??= new(Colors.SlateBlue); + static ImmutableBrush slateGray; + public static SolidColorBrush SlateGray => slateGray ??= new(Colors.SlateGray); + static ImmutableBrush snow; + public static SolidColorBrush Snow => snow ??= new(Colors.Snow); + static ImmutableBrush springGreen; + public static SolidColorBrush SpringGreen => springGreen ??= new(Colors.SpringGreen); + static ImmutableBrush steelBlue; + public static SolidColorBrush SteelBlue => steelBlue ??= new(Colors.SteelBlue); + static ImmutableBrush tan; + public static SolidColorBrush Tan => tan ??= new(Colors.Tan); + static ImmutableBrush teal; + public static SolidColorBrush Teal => teal ??= new(Colors.Teal); + static ImmutableBrush thistle; + public static SolidColorBrush Thistle => thistle ??= new(Colors.Thistle); + static ImmutableBrush tomato; + public static SolidColorBrush Tomato => tomato ??= new(Colors.Tomato); + static ImmutableBrush transparent; + public static SolidColorBrush Transparent => transparent ??= new(Colors.Transparent); + static ImmutableBrush turquoise; + public static SolidColorBrush Turquoise => turquoise ??= new(Colors.Turquoise); + static ImmutableBrush violet; + public static SolidColorBrush Violet => violet ??= new(Colors.Violet); + static ImmutableBrush wheat; + public static SolidColorBrush Wheat => wheat ??= new(Colors.Wheat); + static ImmutableBrush white; + public static SolidColorBrush White => white ??= new(Colors.White); + static ImmutableBrush whiteSmoke; + public static SolidColorBrush WhiteSmoke => whiteSmoke ??= new(Colors.WhiteSmoke); + static ImmutableBrush yellow; + public static SolidColorBrush Yellow => yellow ??= new(Colors.Yellow); + static ImmutableBrush yellowGreen; + public static SolidColorBrush YellowGreen => yellowGreen ??= new(Colors.YellowGreen); } } \ No newline at end of file diff --git a/src/Controls/src/Core/ImmutableBrush.cs b/src/Controls/src/Core/ImmutableBrush.cs new file mode 100644 index 000000000000..e2836cb8bf61 --- /dev/null +++ b/src/Controls/src/Core/ImmutableBrush.cs @@ -0,0 +1,23 @@ +using Microsoft.Maui.Graphics; + +namespace Microsoft.Maui.Controls +{ + internal class ImmutableBrush : SolidColorBrush + { + static readonly BindablePropertyKey ColorPropertyKey = + BindableProperty.CreateReadOnly(nameof(Color), typeof(Color), typeof(ImmutableBrush), null); + + public new static readonly BindableProperty ColorProperty = ColorPropertyKey.BindableProperty; + + public ImmutableBrush(Color color) + { + SetValue(ColorPropertyKey, color); + } + + public override Color Color + { + get => (Color)GetValue(ColorProperty); + set { } + } + } +} diff --git a/src/Controls/src/Core/SolidColorBrush.cs b/src/Controls/src/Core/SolidColorBrush.cs index 3c76fab4f8eb..f6af096a3bdd 100644 --- a/src/Controls/src/Core/SolidColorBrush.cs +++ b/src/Controls/src/Core/SolidColorBrush.cs @@ -27,7 +27,7 @@ public override bool IsEmpty public static readonly BindableProperty ColorProperty = BindableProperty.Create( nameof(Color), typeof(Color), typeof(SolidColorBrush), null); - public Color Color + public virtual Color Color { get => (Color)GetValue(ColorProperty); set => SetValue(ColorProperty, value); diff --git a/src/Core/tests/UnitTests/BrushTests.cs b/src/Core/tests/UnitTests/BrushTests.cs new file mode 100644 index 000000000000..2d18968a3400 --- /dev/null +++ b/src/Core/tests/UnitTests/BrushTests.cs @@ -0,0 +1,39 @@ +using System.Reflection; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Graphics; +using Xunit; + +namespace Microsoft.Maui.UnitTests +{ + [Category(TestCategory.Core)] + public class BrushTests + { + [Fact] + public void BrushColorsAreImmutable() + { + Brush.Red.Color = Colors.Blue; + Assert.Equal(Brush.Red.Color, Colors.Red); + + Brush.Red.SetValue(SolidColorBrush.ColorProperty, Colors.Blue); + Assert.Equal(Brush.Red.Color, Colors.Red); + } + + [Fact] + public void BrushValuesMatchColorValues() + { + //Brush.Red property is a SolidColorBrush that maps to Colors.Red field + + var flags = BindingFlags.Static | BindingFlags.Public; + foreach (var property in typeof(Brush).GetProperties(flags)) + { + if (property.PropertyType != typeof(SolidColorBrush)) + continue; + var brush = (SolidColorBrush)property.GetValue(null); + Assert.NotNull(brush); + var expected = typeof(Colors).GetField(property.Name, flags); + Assert.NotNull(expected); + Assert.Equal((Color)expected.GetValue(null), brush.Color); + } + } + } +}