committed by
GitHub
34 changed files with 2944 additions and 420 deletions
@ -0,0 +1,284 @@ |
|||
using Avalonia.Media; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Implements a reduced flat design or flat UI color palette.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// See:
|
|||
/// - https://htmlcolorcodes.com/color-chart/
|
|||
/// - https://htmlcolorcodes.com/color-chart/flat-design-color-chart/
|
|||
/// - http://designmodo.github.io/Flat-UI/
|
|||
///
|
|||
/// The GitHub project is licensed as MIT: https://github.com/designmodo/Flat-UI.
|
|||
///
|
|||
/// </remarks>
|
|||
public class FlatColorPalette : IColorPalette |
|||
{ |
|||
// The full Flat UI color chart has 10 rows and 20 columns
|
|||
// See: https://htmlcolorcodes.com/assets/downloads/flat-design-colors/flat-design-color-chart.png
|
|||
// This is a reduced palette for usability
|
|||
private static Color[,] colorChart = new Color[,] |
|||
{ |
|||
// Pomegranate
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xF9, 0xEB, 0xEA), |
|||
Color.FromArgb(0xFF, 0xE6, 0xB0, 0xAA), |
|||
Color.FromArgb(0xFF, 0xCD, 0x61, 0x55), |
|||
Color.FromArgb(0xFF, 0xA9, 0x32, 0x26), |
|||
Color.FromArgb(0xFF, 0x7B, 0x24, 0x1C), |
|||
}, |
|||
|
|||
// Amethyst
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xF5, 0xEE, 0xF8), |
|||
Color.FromArgb(0xFF, 0xD7, 0xBD, 0xE2), |
|||
Color.FromArgb(0xFF, 0xAF, 0x7A, 0xC5), |
|||
Color.FromArgb(0xFF, 0x88, 0x4E, 0xA0), |
|||
Color.FromArgb(0xFF, 0x63, 0x39, 0x74), |
|||
}, |
|||
|
|||
// Belize Hole
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xEA, 0xF2, 0xF8), |
|||
Color.FromArgb(0xFF, 0xA9, 0xCC, 0xE3), |
|||
Color.FromArgb(0xFF, 0x54, 0x99, 0xC7), |
|||
Color.FromArgb(0xFF, 0x24, 0x71, 0xA3), |
|||
Color.FromArgb(0xFF, 0x1A, 0x52, 0x76), |
|||
}, |
|||
|
|||
// Turquoise
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xE8, 0xF8, 0xF5), |
|||
Color.FromArgb(0xFF, 0xA3, 0xE4, 0xD7), |
|||
Color.FromArgb(0xFF, 0x48, 0xC9, 0xB0), |
|||
Color.FromArgb(0xFF, 0x17, 0xA5, 0x89), |
|||
Color.FromArgb(0xFF, 0x11, 0x78, 0x64), |
|||
}, |
|||
|
|||
// Nephritis
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xE9, 0xF7, 0xEF), |
|||
Color.FromArgb(0xFF, 0xA9, 0xDF, 0xBF), |
|||
Color.FromArgb(0xFF, 0x52, 0xBE, 0x80), |
|||
Color.FromArgb(0xFF, 0x22, 0x99, 0x54), |
|||
Color.FromArgb(0xFF, 0x19, 0x6F, 0x3D), |
|||
}, |
|||
|
|||
// Sunflower
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xFE, 0xF9, 0xE7), |
|||
Color.FromArgb(0xFF, 0xF9, 0xE7, 0x9F), |
|||
Color.FromArgb(0xFF, 0xF4, 0xD0, 0x3F), |
|||
Color.FromArgb(0xFF, 0xD4, 0xAC, 0x0D), |
|||
Color.FromArgb(0xFF, 0x9A, 0x7D, 0x0A), |
|||
}, |
|||
|
|||
// Carrot
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xFD, 0xF2, 0xE9), |
|||
Color.FromArgb(0xFF, 0xF5, 0xCB, 0xA7), |
|||
Color.FromArgb(0xFF, 0xEB, 0x98, 0x4E), |
|||
Color.FromArgb(0xFF, 0xCA, 0x6F, 0x1E), |
|||
Color.FromArgb(0xFF, 0x93, 0x51, 0x16), |
|||
}, |
|||
|
|||
// Clouds
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xFD, 0xFE, 0xFE), |
|||
Color.FromArgb(0xFF, 0xF7, 0xF9, 0xF9), |
|||
Color.FromArgb(0xFF, 0xF0, 0xF3, 0xF4), |
|||
Color.FromArgb(0xFF, 0xD0, 0xD3, 0xD4), |
|||
Color.FromArgb(0xFF, 0x97, 0x9A, 0x9A), |
|||
}, |
|||
|
|||
// Concrete
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xF4, 0xF6, 0xF6), |
|||
Color.FromArgb(0xFF, 0xD5, 0xDB, 0xDB), |
|||
Color.FromArgb(0xFF, 0xAA, 0xB7, 0xB8), |
|||
Color.FromArgb(0xFF, 0x83, 0x91, 0x92), |
|||
Color.FromArgb(0xFF, 0x5F, 0x6A, 0x6A), |
|||
}, |
|||
|
|||
// Wet Asphalt
|
|||
{ |
|||
Color.FromArgb(0xFF, 0xEB, 0xED, 0xEF), |
|||
Color.FromArgb(0xFF, 0xAE, 0xB6, 0xBF), |
|||
Color.FromArgb(0xFF, 0x5D, 0x6D, 0x7E), |
|||
Color.FromArgb(0xFF, 0x2E, 0x40, 0x53), |
|||
Color.FromArgb(0xFF, 0x21, 0x2F, 0x3C), |
|||
}, |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Gets the index of the default shade of colors in this palette.
|
|||
/// </summary>
|
|||
public const int DefaultShadeIndex = 2; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Pomegranate' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int PomegranateIndex = 0; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Amethyst' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int AmethystIndex = 1; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'BelizeHole' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int BelizeHoleIndex = 2; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Turquoise' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int TurquoiseIndex = 3; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Nephritis' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int NephritisIndex = 4; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Sunflower' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int SunflowerIndex = 5; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Carrot' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int CarrotIndex = 6; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Clouds' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int CloudsIndex = 7; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Concrete' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int ConcreteIndex = 8; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'WetAsphalt' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int WetAsphaltIndex = 9; |
|||
|
|||
/// <inheritdoc/>
|
|||
public int ColorCount |
|||
{ |
|||
// Table is transposed compared to the reference chart
|
|||
get => colorChart.GetLength(0); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public int ShadeCount |
|||
{ |
|||
// Table is transposed compared to the reference chart
|
|||
get => colorChart.GetLength(1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFC0392B.
|
|||
/// </summary>
|
|||
public static Color Pomegranate |
|||
{ |
|||
get => colorChart[PomegranateIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF9B59B6.
|
|||
/// </summary>
|
|||
public static Color Amethyst |
|||
{ |
|||
get => colorChart[AmethystIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF2980B9.
|
|||
/// </summary>
|
|||
public static Color BelizeHole |
|||
{ |
|||
get => colorChart[BelizeHoleIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF1ABC9C.
|
|||
/// </summary>
|
|||
public static Color Turquoise |
|||
{ |
|||
get => colorChart[TurquoiseIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF27AE60.
|
|||
/// </summary>
|
|||
public static Color Nephritis |
|||
{ |
|||
get => colorChart[NephritisIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFF1C40F.
|
|||
/// </summary>
|
|||
public static Color Sunflower |
|||
{ |
|||
get => colorChart[SunflowerIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFE67E22.
|
|||
/// </summary>
|
|||
public static Color Carrot |
|||
{ |
|||
get => colorChart[CarrotIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFECF0F1.
|
|||
/// </summary>
|
|||
public static Color Clouds |
|||
{ |
|||
get => colorChart[CloudsIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF95A5A6.
|
|||
/// </summary>
|
|||
public static Color Concrete |
|||
{ |
|||
get => colorChart[ConcreteIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF34495E.
|
|||
/// </summary>
|
|||
public static Color WetAsphalt |
|||
{ |
|||
get => colorChart[WetAsphaltIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Color GetColor(int colorIndex, int shadeIndex) |
|||
{ |
|||
// Table is transposed compared to the reference chart
|
|||
return colorChart[ |
|||
MathUtilities.Clamp(colorIndex, 0, colorChart.GetLength(0) - 1), |
|||
MathUtilities.Clamp(shadeIndex, 0, colorChart.GetLength(1) - 1)]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,136 @@ |
|||
using Avalonia.Media; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the standard Windows 10 color palette.
|
|||
/// </summary>
|
|||
public class FluentColorPalette : IColorPalette |
|||
{ |
|||
// Values were taken from the Settings App, Personalization > Colors which match with
|
|||
// https://docs.microsoft.com/en-us/windows/uwp/whats-new/windows-docs-december-2017
|
|||
//
|
|||
// The default ordering and grouping of colors was undesirable so was modified.
|
|||
// Colors were transposed: the colors in rows within the Settings app became columns here.
|
|||
// This is because columns in an IColorPalette generally should contain different shades of
|
|||
// the same color. In the settings app this concept is somewhat loosely reversed.
|
|||
// The first 'column' ordering, after being transposed, was then reversed so 'red' colors
|
|||
// were near to each other.
|
|||
//
|
|||
// This new ordering most closely follows the Windows standard while:
|
|||
//
|
|||
// 1. Keeping colors in a 'spectrum' order
|
|||
// 2. Keeping like colors next to each both in rows and columns
|
|||
// (which is unique for the windows palette).
|
|||
// For example, similar red colors are next to each other in both
|
|||
// rows within the same column and rows within the column next to it.
|
|||
// This follows a 'snake-like' pattern as illustrated below.
|
|||
// 3. A downside of this ordering is colors don't follow strict 'shades'
|
|||
// as in other palettes.
|
|||
//
|
|||
// The colors will be displayed in the below pattern.
|
|||
// This pattern follows a spectrum while keeping like-colors near to one
|
|||
// another across both rows and columns.
|
|||
//
|
|||
// ┌Red───┐ ┌Blue──┐ ┌Gray──┐
|
|||
// │ │ │ │ │ |
|
|||
// │ │ │ │ │ |
|
|||
// Yellow └Violet┘ └Green─┘ Brown
|
|||
|
|||
private static Color[,] colorChart = new Color[,] |
|||
{ |
|||
{ |
|||
// Ordering reversed for this section only
|
|||
Color.FromArgb(255, 255, 67, 67), /* #FF4343 */ |
|||
Color.FromArgb(255, 209, 52, 56), /* #D13438 */ |
|||
Color.FromArgb(255, 239, 105, 80), /* #EF6950 */ |
|||
Color.FromArgb(255, 218, 59, 1), /* #DA3B01 */ |
|||
Color.FromArgb(255, 202, 80, 16), /* #CA5010 */ |
|||
Color.FromArgb(255, 247, 99, 12), /* #F7630C */ |
|||
Color.FromArgb(255, 255, 140, 0), /* #FF8C00 */ |
|||
Color.FromArgb(255, 255, 185, 0), /* #FFB900 */ |
|||
}, |
|||
{ |
|||
Color.FromArgb(255, 231, 72, 86), /* #E74856 */ |
|||
Color.FromArgb(255, 232, 17, 35), /* #E81123 */ |
|||
Color.FromArgb(255, 234, 0, 94), /* #EA005E */ |
|||
Color.FromArgb(255, 195, 0, 82), /* #C30052 */ |
|||
Color.FromArgb(255, 227, 0, 140), /* #E3008C */ |
|||
Color.FromArgb(255, 191, 0, 119), /* #BF0077 */ |
|||
Color.FromArgb(255, 194, 57, 179), /* #C239B3 */ |
|||
Color.FromArgb(255, 154, 0, 137), /* #9A0089 */ |
|||
}, |
|||
{ |
|||
Color.FromArgb(255, 0, 120, 215), /* #0078D7 */ |
|||
Color.FromArgb(255, 0, 99, 177), /* #0063B1 */ |
|||
Color.FromArgb(255, 142, 140, 216), /* #8E8CD8 */ |
|||
Color.FromArgb(255, 107, 105, 214), /* #6B69D6 */ |
|||
Color.FromArgb(255, 135, 100, 184), /* #8764B8 */ |
|||
Color.FromArgb(255, 116, 77, 169), /* #744DA9 */ |
|||
Color.FromArgb(255, 177, 70, 194), /* #B146C2 */ |
|||
Color.FromArgb(255, 136, 23, 152), /* #881798 */ |
|||
}, |
|||
{ |
|||
Color.FromArgb(255, 0, 153, 188), /* #0099BC */ |
|||
Color.FromArgb(255, 45, 125, 154), /* #2D7D9A */ |
|||
Color.FromArgb(255, 0, 183, 195), /* #00B7C3 */ |
|||
Color.FromArgb(255, 3, 131, 135), /* #038387 */ |
|||
Color.FromArgb(255, 0, 178, 148), /* #00B294 */ |
|||
Color.FromArgb(255, 1, 133, 116), /* #018574 */ |
|||
Color.FromArgb(255, 0, 204, 106), /* #00CC6A */ |
|||
Color.FromArgb(255, 16, 137, 62), /* #10893E */ |
|||
}, |
|||
{ |
|||
Color.FromArgb(255, 122, 117, 116), /* #7A7574 */ |
|||
Color.FromArgb(255, 93, 90, 80), /* #5D5A58 */ |
|||
Color.FromArgb(255, 104, 118, 138), /* #68768A */ |
|||
Color.FromArgb(255, 81, 92, 107), /* #515C6B */ |
|||
Color.FromArgb(255, 86, 124, 115), /* #567C73 */ |
|||
Color.FromArgb(255, 72, 104, 96), /* #486860 */ |
|||
Color.FromArgb(255, 73, 130, 5), /* #498205 */ |
|||
Color.FromArgb(255, 16, 124, 16), /* #107C10 */ |
|||
}, |
|||
{ |
|||
Color.FromArgb(255, 118, 118, 118), /* #767676 */ |
|||
Color.FromArgb(255, 76, 74, 72), /* #4C4A48 */ |
|||
Color.FromArgb(255, 105, 121, 126), /* #69797E */ |
|||
Color.FromArgb(255, 74, 84, 89), /* #4A5459 */ |
|||
Color.FromArgb(255, 100, 124, 100), /* #647C64 */ |
|||
Color.FromArgb(255, 82, 94, 84), /* #525E54 */ |
|||
Color.FromArgb(255, 132, 117, 69), /* #847545 */ |
|||
Color.FromArgb(255, 126, 115, 95), /* #7E735F */ |
|||
} |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Gets the total number of colors in this palette.
|
|||
/// A color is not necessarily a single value and may be composed of several shades.
|
|||
/// This has little meaning in this palette as colors are not strictly separated.
|
|||
/// </summary>
|
|||
/// <inheritdoc path="/remarks"/>
|
|||
public int ColorCount |
|||
{ |
|||
get => colorChart.GetLength(0); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the total number of shades for each color in this palette.
|
|||
/// Shades are usually a variation of the color lightening or darkening it.
|
|||
/// This has little meaning in this palette as colors are not strictly separated by shade.
|
|||
/// </summary>
|
|||
/// <inheritdoc path="/remarks"/>
|
|||
public int ShadeCount |
|||
{ |
|||
get => colorChart.GetLength(1); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Color GetColor(int colorIndex, int shadeIndex) |
|||
{ |
|||
return colorChart[ |
|||
MathUtilities.Clamp(colorIndex, 0, colorChart.GetLength(0) - 1), |
|||
MathUtilities.Clamp(shadeIndex, 0, colorChart.GetLength(1) - 1)]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Interface to define a color palette.
|
|||
/// </summary>
|
|||
public interface IColorPalette |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the total number of colors in this palette.
|
|||
/// A color is not necessarily a single value and may be composed of several shades.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Represents total columns in a table.
|
|||
/// </remarks>
|
|||
int ColorCount { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the total number of shades for each color in this palette.
|
|||
/// Shades are usually a variation of the color lightening or darkening it.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Represents total rows in a table.
|
|||
/// </remarks>
|
|||
int ShadeCount { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a color in the palette by index.
|
|||
/// </summary>
|
|||
/// <param name="colorIndex">The index of the color in the palette.
|
|||
/// The index must be between zero and <see cref="ColorCount"/>.</param>
|
|||
/// <param name="shadeIndex">The index of the color shade in the palette.
|
|||
/// The index must be between zero and <see cref="ShadeCount"/>.</param>
|
|||
/// <returns>The color at the specified index or an exception.</returns>
|
|||
Color GetColor(int colorIndex, int shadeIndex); |
|||
} |
|||
} |
|||
@ -0,0 +1,302 @@ |
|||
using Avalonia.Media; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the standard sixteen color palette from the HTML 4.01 specification.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// See https://en.wikipedia.org/wiki/Web_colors#HTML_color_names.
|
|||
/// </remarks>
|
|||
public class SixteenColorPalette : IColorPalette |
|||
{ |
|||
// The 16 standard colors from HTML and early Windows computers
|
|||
// https://en.wikipedia.org/wiki/List_of_software_palettes
|
|||
// https://en.wikipedia.org/wiki/Web_colors#HTML_color_names
|
|||
private static Color[,] colorChart = new Color[,] |
|||
{ |
|||
{ |
|||
Colors.White, |
|||
Colors.Silver |
|||
}, |
|||
{ |
|||
Colors.Gray, |
|||
Colors.Black |
|||
}, |
|||
{ |
|||
Colors.Red, |
|||
Colors.Maroon |
|||
}, |
|||
{ |
|||
Colors.Yellow, |
|||
Colors.Olive |
|||
}, |
|||
{ |
|||
Colors.Lime, |
|||
Colors.Green |
|||
}, |
|||
{ |
|||
Colors.Aqua, |
|||
Colors.Teal |
|||
}, |
|||
{ |
|||
Colors.Blue, |
|||
Colors.Navy |
|||
}, |
|||
{ |
|||
Colors.Fuchsia, |
|||
Colors.Purple |
|||
} |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Gets the index of the default shade of colors in this palette.
|
|||
/// </summary>
|
|||
public const int DefaultShadeIndex = 0; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'White' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int WhiteIndex = 0; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Silver' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int SilverIndex = 1; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Gray' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int GrayIndex = 2; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Black' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int BlackIndex = 3; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Red' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int RedIndex = 4; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Maroon' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int MaroonIndex = 5; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Yellow' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int YellowIndex = 6; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Olive' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int OliveIndex = 7; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Lime' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int LimeIndex = 8; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Green' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int GreenIndex = 9; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Aqua' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int AquaIndex = 10; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Teal' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int TealIndex = 11; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Blue' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int BlueIndex = 12; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Navy' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int NavyIndex = 13; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Fuchsia' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int FuchsiaIndex = 14; |
|||
|
|||
/// <summary>
|
|||
/// The index in the color palette of the 'Purple' color.
|
|||
/// This index can correspond to multiple color shades.
|
|||
/// </summary>
|
|||
public const int PurpleIndex = 15; |
|||
|
|||
/// <inheritdoc/>
|
|||
public int ColorCount |
|||
{ |
|||
get => colorChart.GetLength(0); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public int ShadeCount |
|||
{ |
|||
get => colorChart.GetLength(1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFFFFFFF.
|
|||
/// </summary>
|
|||
public static Color White |
|||
{ |
|||
get => colorChart[WhiteIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFC0C0C0.
|
|||
/// </summary>
|
|||
public static Color Silver |
|||
{ |
|||
get => colorChart[SilverIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF808080.
|
|||
/// </summary>
|
|||
public static Color Gray |
|||
{ |
|||
get => colorChart[GrayIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF000000.
|
|||
/// </summary>
|
|||
public static Color Black |
|||
{ |
|||
get => colorChart[BlackIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFFF0000.
|
|||
/// </summary>
|
|||
public static Color Red |
|||
{ |
|||
get => colorChart[RedIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF800000.
|
|||
/// </summary>
|
|||
public static Color Maroon |
|||
{ |
|||
get => colorChart[MaroonIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFFFFF00.
|
|||
/// </summary>
|
|||
public static Color Yellow |
|||
{ |
|||
get => colorChart[YellowIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF808000.
|
|||
/// </summary>
|
|||
public static Color Olive |
|||
{ |
|||
get => colorChart[OliveIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF00FF00.
|
|||
/// </summary>
|
|||
public static Color Lime |
|||
{ |
|||
get => colorChart[LimeIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF008000.
|
|||
/// </summary>
|
|||
public static Color Green |
|||
{ |
|||
get => colorChart[GreenIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF00FFFF.
|
|||
/// </summary>
|
|||
public static Color Aqua |
|||
{ |
|||
get => colorChart[AquaIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF008080.
|
|||
/// </summary>
|
|||
public static Color Teal |
|||
{ |
|||
get => colorChart[TealIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF0000FF.
|
|||
/// </summary>
|
|||
public static Color Blue |
|||
{ |
|||
get => colorChart[BlueIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF000080.
|
|||
/// </summary>
|
|||
public static Color Navy |
|||
{ |
|||
get => colorChart[NavyIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FFFF00FF.
|
|||
/// </summary>
|
|||
public static Color Fuchsia |
|||
{ |
|||
get => colorChart[FuchsiaIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the palette defined color that has an ARGB value of #FF800080.
|
|||
/// </summary>
|
|||
public static Color Purple |
|||
{ |
|||
get => colorChart[PurpleIndex, DefaultShadeIndex]; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Color GetColor(int colorIndex, int shadeIndex) |
|||
{ |
|||
return colorChart[ |
|||
MathUtilities.Clamp(colorIndex, 0, colorChart.GetLength(0) - 1), |
|||
MathUtilities.Clamp(shadeIndex, 0, colorChart.GetLength(1) - 1)]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Presents a color for user editing using a spectrum, palette and component sliders within a drop down.
|
|||
/// Editing is available when the drop down flyout is opened; otherwise, only the preview color is shown.
|
|||
/// </summary>
|
|||
public class ColorPicker : ColorView |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorPicker"/> class.
|
|||
/// </summary>
|
|||
public ColorPicker() : base() |
|||
{ |
|||
// Completely ignore property changes here
|
|||
// The ColorView in the control template is responsible to manage this
|
|||
base.ignorePropertyChanged = true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,495 @@ |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Data; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public partial class ColorView |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the <see cref="Color"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<Color> ColorProperty = |
|||
AvaloniaProperty.Register<ColorView, Color>( |
|||
nameof(Color), |
|||
Colors.White, |
|||
defaultBindingMode: BindingMode.TwoWay, |
|||
coerce: CoerceColor) ; |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="ColorModel"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<ColorModel> ColorModelProperty = |
|||
AvaloniaProperty.Register<ColorView, ColorModel>( |
|||
nameof(ColorModel), |
|||
ColorModel.Rgba); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="ColorSpectrumComponents"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<ColorSpectrumComponents> ColorSpectrumComponentsProperty = |
|||
AvaloniaProperty.Register<ColorView, ColorSpectrumComponents>( |
|||
nameof(ColorSpectrumComponents), |
|||
ColorSpectrumComponents.HueSaturation); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="ColorSpectrumShape"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<ColorSpectrumShape> ColorSpectrumShapeProperty = |
|||
AvaloniaProperty.Register<ColorView, ColorSpectrumShape>( |
|||
nameof(ColorSpectrumShape), |
|||
ColorSpectrumShape.Box); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="HsvColor"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<HsvColor> HsvColorProperty = |
|||
AvaloniaProperty.Register<ColorView, HsvColor>( |
|||
nameof(HsvColor), |
|||
Colors.White.ToHsv(), |
|||
defaultBindingMode: BindingMode.TwoWay, |
|||
coerce: CoerceHsvColor); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsAccentColorsVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsAccentColorsVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsAccentColorsVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsAlphaEnabled"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsAlphaEnabledProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsAlphaEnabled), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsAlphaVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsAlphaVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsAlphaVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorComponentsVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorComponentsVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorComponentsVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorModelVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorModelVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorModelVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorPaletteVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorPaletteVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorPaletteVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorPreviewVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorPreviewVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorPreviewVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorSpectrumVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorSpectrumVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorSpectrumVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsColorSpectrumSliderVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsColorSpectrumSliderVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsColorSpectrumSliderVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsComponentSliderVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsComponentSliderVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsComponentSliderVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsComponentTextInputVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsComponentTextInputVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsComponentTextInputVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="IsHexInputVisible"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<bool> IsHexInputVisibleProperty = |
|||
AvaloniaProperty.Register<ColorView, bool>( |
|||
nameof(IsHexInputVisible), |
|||
true); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MaxHue"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MaxHueProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MaxHue), |
|||
359); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MaxSaturation"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MaxSaturationProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MaxSaturation), |
|||
100); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MaxValue"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MaxValueProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MaxValue), |
|||
100); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MinHue"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MinHueProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MinHue), |
|||
0); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MinSaturation"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MinSaturationProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MinSaturation), |
|||
0); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MinValue"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> MinValueProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(MinValue), |
|||
0); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="PaletteColors"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<IEnumerable<Color>?> PaletteColorsProperty = |
|||
AvaloniaProperty.Register<ColorView, IEnumerable<Color>?>( |
|||
nameof(PaletteColors), |
|||
null); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="PaletteColumnCount"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> PaletteColumnCountProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(PaletteColumnCount), |
|||
4); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="Palette"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<IColorPalette?> PaletteProperty = |
|||
AvaloniaProperty.Register<ColorView, IColorPalette?>( |
|||
nameof(Palette), |
|||
null); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="SelectedIndex"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<int> SelectedIndexProperty = |
|||
AvaloniaProperty.Register<ColorView, int>( |
|||
nameof(SelectedIndex), |
|||
(int)ColorViewTab.Spectrum); |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.Color"/>
|
|||
public Color Color |
|||
{ |
|||
get => GetValue(ColorProperty); |
|||
set => SetValue(ColorProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSlider.ColorModel"/>
|
|||
/// <remarks>
|
|||
/// This property is only applicable to the components tab.
|
|||
/// The spectrum tab must always be in HSV and the palette tab contains only pre-defined colors.
|
|||
/// </remarks>
|
|||
public ColorModel ColorModel |
|||
{ |
|||
get => GetValue(ColorModelProperty); |
|||
set => SetValue(ColorModelProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.Components"/>
|
|||
public ColorSpectrumComponents ColorSpectrumComponents |
|||
{ |
|||
get => GetValue(ColorSpectrumComponentsProperty); |
|||
set => SetValue(ColorSpectrumComponentsProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.Shape"/>
|
|||
public ColorSpectrumShape ColorSpectrumShape |
|||
{ |
|||
get => GetValue(ColorSpectrumShapeProperty); |
|||
set => SetValue(ColorSpectrumShapeProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.HsvColor"/>
|
|||
public HsvColor HsvColor |
|||
{ |
|||
get => GetValue(HsvColorProperty); |
|||
set => SetValue(HsvColorProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorPreviewer.IsAccentColorsVisible"/>
|
|||
public bool IsAccentColorsVisible |
|||
{ |
|||
get => GetValue(IsAccentColorsVisibleProperty); |
|||
set => SetValue(IsAccentColorsVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the alpha component is enabled.
|
|||
/// When disabled (set to false) the alpha component will be fixed to maximum and
|
|||
/// editing controls disabled.
|
|||
/// </summary>
|
|||
public bool IsAlphaEnabled |
|||
{ |
|||
get => GetValue(IsAlphaEnabledProperty); |
|||
set => SetValue(IsAlphaEnabledProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the alpha component editing controls
|
|||
/// (Slider(s) and TextBox) are visible. When hidden, the existing alpha component
|
|||
/// value is maintained.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Note that <see cref="IsComponentTextInputVisible"/> also controls the alpha
|
|||
/// component TextBox visibility.
|
|||
/// </remarks>
|
|||
public bool IsAlphaVisible |
|||
{ |
|||
get => GetValue(IsAlphaVisibleProperty); |
|||
set => SetValue(IsAlphaVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the color components tab/panel/page (subview) is visible.
|
|||
/// </summary>
|
|||
public bool IsColorComponentsVisible |
|||
{ |
|||
get => GetValue(IsColorComponentsVisibleProperty); |
|||
set => SetValue(IsColorComponentsVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the active color model indicator/selector is visible.
|
|||
/// </summary>
|
|||
public bool IsColorModelVisible |
|||
{ |
|||
get => GetValue(IsColorModelVisibleProperty); |
|||
set => SetValue(IsColorModelVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the color palette tab/panel/page (subview) is visible.
|
|||
/// </summary>
|
|||
public bool IsColorPaletteVisible |
|||
{ |
|||
get => GetValue(IsColorPaletteVisibleProperty); |
|||
set => SetValue(IsColorPaletteVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the color preview is visible.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Note that accent color visibility is controlled separately by
|
|||
/// <see cref="IsAccentColorsVisible"/>.
|
|||
/// </remarks>
|
|||
public bool IsColorPreviewVisible |
|||
{ |
|||
get => GetValue(IsColorPreviewVisibleProperty); |
|||
set => SetValue(IsColorPreviewVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the color spectrum tab/panel/page (subview) is visible.
|
|||
/// </summary>
|
|||
public bool IsColorSpectrumVisible |
|||
{ |
|||
get => GetValue(IsColorSpectrumVisibleProperty); |
|||
set => SetValue(IsColorSpectrumVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the color spectrum's third component slider
|
|||
/// is visible.
|
|||
/// </summary>
|
|||
public bool IsColorSpectrumSliderVisible |
|||
{ |
|||
get => GetValue(IsColorSpectrumSliderVisibleProperty); |
|||
set => SetValue(IsColorSpectrumSliderVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether color component sliders are visible.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// All color components are controlled by this property but alpha can also be
|
|||
/// controlled with <see cref="IsAlphaVisible"/>.
|
|||
/// </remarks>
|
|||
public bool IsComponentSliderVisible |
|||
{ |
|||
get => GetValue(IsComponentSliderVisibleProperty); |
|||
set => SetValue(IsComponentSliderVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether color component text inputs are visible.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// All color components are controlled by this property but alpha can also be
|
|||
/// controlled with <see cref="IsAlphaVisible"/>.
|
|||
/// </remarks>
|
|||
public bool IsComponentTextInputVisible |
|||
{ |
|||
get => GetValue(IsComponentTextInputVisibleProperty); |
|||
set => SetValue(IsComponentTextInputVisibleProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the hexadecimal color value text input
|
|||
/// is visible.
|
|||
/// </summary>
|
|||
public bool IsHexInputVisible |
|||
{ |
|||
get => GetValue(IsHexInputVisibleProperty); |
|||
set => SetValue(IsHexInputVisibleProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MaxHue"/>
|
|||
public int MaxHue |
|||
{ |
|||
get => GetValue(MaxHueProperty); |
|||
set => SetValue(MaxHueProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MaxSaturation"/>
|
|||
public int MaxSaturation |
|||
{ |
|||
get => GetValue(MaxSaturationProperty); |
|||
set => SetValue(MaxSaturationProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MaxValue"/>
|
|||
public int MaxValue |
|||
{ |
|||
get => GetValue(MaxValueProperty); |
|||
set => SetValue(MaxValueProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MinHue"/>
|
|||
public int MinHue |
|||
{ |
|||
get => GetValue(MinHueProperty); |
|||
set => SetValue(MinHueProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MinSaturation"/>
|
|||
public int MinSaturation |
|||
{ |
|||
get => GetValue(MinSaturationProperty); |
|||
set => SetValue(MinSaturationProperty, value); |
|||
} |
|||
|
|||
/// <inheritdoc cref="ColorSpectrum.MinValue"/>
|
|||
public int MinValue |
|||
{ |
|||
get => GetValue(MinValueProperty); |
|||
set => SetValue(MinValueProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the collection of individual colors in the palette.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is not commonly set manually. Instead, it should be set automatically by
|
|||
/// providing an <see cref="IColorPalette"/> to the <see cref="Palette"/> property.
|
|||
/// <br/><br/>
|
|||
/// Also note that this property is what should be bound in the control template.
|
|||
/// <see cref="Palette"/> is too high-level to use on its own.
|
|||
/// </remarks>
|
|||
public IEnumerable<Color>? PaletteColors |
|||
{ |
|||
get => GetValue(PaletteColorsProperty); |
|||
set => SetValue(PaletteColorsProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the number of colors in each row (section) of the color palette.
|
|||
/// Within a standard palette, rows are shades and columns are colors.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is not commonly set manually. Instead, it should be set automatically by
|
|||
/// providing an <see cref="IColorPalette"/> to the <see cref="Palette"/> property.
|
|||
/// <br/><br/>
|
|||
/// Also note that this property is what should be bound in the control template.
|
|||
/// <see cref="Palette"/> is too high-level to use on its own.
|
|||
/// </remarks>
|
|||
public int PaletteColumnCount |
|||
{ |
|||
get => GetValue(PaletteColumnCountProperty); |
|||
set => SetValue(PaletteColumnCountProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the color palette.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This will automatically set both <see cref="PaletteColors"/> and
|
|||
/// <see cref="PaletteColumnCount"/> overwriting any existing values.
|
|||
/// </remarks>
|
|||
public IColorPalette? Palette |
|||
{ |
|||
get => GetValue(PaletteProperty); |
|||
set => SetValue(PaletteProperty, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the index of the selected tab/panel/page (subview).
|
|||
/// </summary>
|
|||
public int SelectedIndex |
|||
{ |
|||
get => GetValue(SelectedIndexProperty); |
|||
set => SetValue(SelectedIndexProperty, value); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,379 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Globalization; |
|||
using Avalonia.Controls.Converters; |
|||
using Avalonia.Controls.Metadata; |
|||
using Avalonia.Controls.Presenters; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Media; |
|||
using Avalonia.Threading; |
|||
using Avalonia.VisualTree; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Presents a color for user editing using a spectrum, palette and component sliders.
|
|||
/// </summary>
|
|||
[TemplatePart("PART_HexTextBox", typeof(TextBox))] |
|||
[TemplatePart("PART_TabControl", typeof(TabControl))] |
|||
public partial class ColorView : TemplatedControl |
|||
{ |
|||
/// <summary>
|
|||
/// Event for when the selected color changes within the slider.
|
|||
/// </summary>
|
|||
public event EventHandler<ColorChangedEventArgs>? ColorChanged; |
|||
|
|||
// XAML template parts
|
|||
private TextBox? _hexTextBox; |
|||
private TabControl? _tabControl; |
|||
|
|||
private ColorToHexConverter colorToHexConverter = new ColorToHexConverter(); |
|||
protected bool ignorePropertyChanged = false; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ColorView"/> class.
|
|||
/// </summary>
|
|||
public ColorView() : base() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the value of the hex TextBox and sets it as the current <see cref="Color"/>.
|
|||
/// If invalid, the TextBox hex text will revert back to the last valid color.
|
|||
/// </summary>
|
|||
private void GetColorFromHexTextBox() |
|||
{ |
|||
if (_hexTextBox != null) |
|||
{ |
|||
var convertedColor = colorToHexConverter.ConvertBack(_hexTextBox.Text, typeof(Color), null, CultureInfo.CurrentCulture); |
|||
|
|||
if (convertedColor is Color color) |
|||
{ |
|||
Color = color; |
|||
} |
|||
|
|||
// Re-apply the hex value
|
|||
// This ensure the hex color value is always valid and formatted correctly
|
|||
SetColorToHexTextBox(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the current <see cref="Color"/> to the hex TextBox.
|
|||
/// </summary>
|
|||
private void SetColorToHexTextBox() |
|||
{ |
|||
if (_hexTextBox != null) |
|||
{ |
|||
_hexTextBox.Text = colorToHexConverter.Convert(Color, typeof(string), null, CultureInfo.CurrentCulture) as string; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validates the tab/panel/page selection taking into account the visibility of each item
|
|||
/// as well as the current selection.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Derived controls may re-implement this based on their default style / control template
|
|||
/// and any specialized selection needs.
|
|||
/// </remarks>
|
|||
protected virtual void ValidateSelection() |
|||
{ |
|||
if (_tabControl != null && |
|||
_tabControl.Items != null) |
|||
{ |
|||
// Determine the number of visible tab items
|
|||
int numVisibleItems = 0; |
|||
foreach (var item in _tabControl.Items) |
|||
{ |
|||
if (item is Control control && |
|||
control.IsVisible) |
|||
{ |
|||
numVisibleItems++; |
|||
} |
|||
} |
|||
|
|||
// Verify the selection
|
|||
if (numVisibleItems > 0) |
|||
{ |
|||
object? selectedItem = null; |
|||
|
|||
if (_tabControl.SelectedItem == null && |
|||
_tabControl.ItemCount > 0) |
|||
{ |
|||
// As a failsafe, forcefully select the first item
|
|||
foreach (var item in _tabControl.Items) |
|||
{ |
|||
selectedItem = item; |
|||
break; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
selectedItem = _tabControl.SelectedItem; |
|||
} |
|||
|
|||
if (selectedItem is Control selectedControl && |
|||
selectedControl.IsVisible == false) |
|||
{ |
|||
// Select the first visible item instead
|
|||
foreach (var item in _tabControl.Items) |
|||
{ |
|||
if (item is Control control && |
|||
control.IsVisible) |
|||
{ |
|||
selectedItem = item; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
_tabControl.SelectedItem = selectedItem; |
|||
_tabControl.IsVisible = true; |
|||
} |
|||
else |
|||
{ |
|||
// Special case when all items are hidden
|
|||
// If TabControl ever properly supports no selected item /
|
|||
// all items hidden this can be removed
|
|||
_tabControl.SelectedItem = null; |
|||
_tabControl.IsVisible = false; |
|||
} |
|||
|
|||
// Hide the "tab strip" if there is only one tab
|
|||
// This allows, for example, to view only the palette
|
|||
/* |
|||
var itemsPresenter = _tabControl.FindDescendantOfType<ItemsPresenter>(); |
|||
if (itemsPresenter != null) |
|||
{ |
|||
if (numVisibleItems == 1) |
|||
{ |
|||
itemsPresenter.IsVisible = false; |
|||
} |
|||
else |
|||
{ |
|||
itemsPresenter.IsVisible = true; |
|||
} |
|||
} |
|||
*/ |
|||
|
|||
// Note that if externally the SelectedIndex is set to 4 or something
|
|||
// outside the valid range, the TabControl will ignore it and replace it
|
|||
// with a valid SelectedIndex. This however is not propagated back through
|
|||
// the TwoWay binding in the control template so the SelectedIndex and
|
|||
// SelectedIndex become out of sync.
|
|||
//
|
|||
// The work-around for this is done here where SelectedIndex is forcefully
|
|||
// synchronized with whatever the TabControl property value is. This is
|
|||
// possible since selection validation is already done by this method.
|
|||
SelectedIndex = _tabControl.SelectedIndex; |
|||
} |
|||
|
|||
return; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
|||
{ |
|||
if (_hexTextBox != null) |
|||
{ |
|||
_hexTextBox.KeyDown -= HexTextBox_KeyDown; |
|||
_hexTextBox.LostFocus -= HexTextBox_LostFocus; |
|||
} |
|||
|
|||
_hexTextBox = e.NameScope.Find<TextBox>("PART_HexTextBox"); |
|||
_tabControl = e.NameScope.Find<TabControl>("PART_TabControl"); |
|||
|
|||
SetColorToHexTextBox(); |
|||
|
|||
if (_hexTextBox != null) |
|||
{ |
|||
_hexTextBox.KeyDown += HexTextBox_KeyDown; |
|||
_hexTextBox.LostFocus += HexTextBox_LostFocus; |
|||
} |
|||
|
|||
base.OnApplyTemplate(e); |
|||
ValidateSelection(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) |
|||
{ |
|||
if (ignorePropertyChanged) |
|||
{ |
|||
base.OnPropertyChanged(change); |
|||
return; |
|||
} |
|||
|
|||
// Always keep the two color properties in sync
|
|||
if (change.Property == ColorProperty) |
|||
{ |
|||
ignorePropertyChanged = true; |
|||
|
|||
HsvColor = Color.ToHsv(); |
|||
SetColorToHexTextBox(); |
|||
|
|||
OnColorChanged(new ColorChangedEventArgs( |
|||
change.GetOldValue<Color>(), |
|||
change.GetNewValue<Color>())); |
|||
|
|||
ignorePropertyChanged = false; |
|||
} |
|||
else if (change.Property == HsvColorProperty) |
|||
{ |
|||
ignorePropertyChanged = true; |
|||
|
|||
Color = HsvColor.ToRgb(); |
|||
SetColorToHexTextBox(); |
|||
|
|||
OnColorChanged(new ColorChangedEventArgs( |
|||
change.GetOldValue<HsvColor>().ToRgb(), |
|||
change.GetNewValue<HsvColor>().ToRgb())); |
|||
|
|||
ignorePropertyChanged = false; |
|||
} |
|||
else if (change.Property == PaletteProperty) |
|||
{ |
|||
IColorPalette? palette = Palette; |
|||
|
|||
// Any custom palette change must be automatically synced with the
|
|||
// bound properties controlling the palette grid
|
|||
if (palette != null) |
|||
{ |
|||
PaletteColumnCount = palette.ColorCount; |
|||
|
|||
List<Color> newPaletteColors = new List<Color>(); |
|||
for (int shadeIndex = 0; shadeIndex < palette.ShadeCount; shadeIndex++) |
|||
{ |
|||
for (int colorIndex = 0; colorIndex < palette.ColorCount; colorIndex++) |
|||
{ |
|||
newPaletteColors.Add(palette.GetColor(colorIndex, shadeIndex)); |
|||
} |
|||
} |
|||
|
|||
PaletteColors = newPaletteColors; |
|||
} |
|||
} |
|||
else if (change.Property == IsAlphaEnabledProperty) |
|||
{ |
|||
// Manually coerce the HsvColor value
|
|||
// (Color will be coerced automatically if HsvColor changes)
|
|||
HsvColor = OnCoerceHsvColor(HsvColor); |
|||
} |
|||
else if (change.Property == IsColorComponentsVisibleProperty || |
|||
change.Property == IsColorPaletteVisibleProperty || |
|||
change.Property == IsColorSpectrumVisibleProperty) |
|||
{ |
|||
// When the property changed notification is received here the visibility
|
|||
// of individual tab items has not yet been updated through the bindings.
|
|||
// Therefore, the validation is delayed until after bindings update.
|
|||
Dispatcher.UIThread.Post(() => |
|||
{ |
|||
ValidateSelection(); |
|||
}, DispatcherPriority.Background); |
|||
} |
|||
else if (change.Property == SelectedIndexProperty) |
|||
{ |
|||
// Again, it is necessary to wait for the SelectedIndex value to
|
|||
// be applied to the TabControl through binding before validation occurs.
|
|||
Dispatcher.UIThread.Post(() => |
|||
{ |
|||
ValidateSelection(); |
|||
}, DispatcherPriority.Background); |
|||
} |
|||
|
|||
base.OnPropertyChanged(change); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called before the <see cref="ColorChanged"/> event occurs.
|
|||
/// </summary>
|
|||
/// <param name="e">The <see cref="ColorChangedEventArgs"/> defining old/new colors.</param>
|
|||
protected virtual void OnColorChanged(ColorChangedEventArgs e) |
|||
{ |
|||
ColorChanged?.Invoke(this, e); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when the <see cref="Color"/> property has to be coerced.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to coerce.</param>
|
|||
protected virtual Color OnCoerceColor(Color value) |
|||
{ |
|||
if (IsAlphaEnabled == false) |
|||
{ |
|||
return new Color(255, value.R, value.G, value.B); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when the <see cref="HsvColor"/> property has to be coerced.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to coerce.</param>
|
|||
protected virtual HsvColor OnCoerceHsvColor(HsvColor value) |
|||
{ |
|||
if (IsAlphaEnabled == false) |
|||
{ |
|||
return new HsvColor(1.0, value.H, value.S, value.V); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Coerces/validates the <see cref="Color"/> property value.
|
|||
/// </summary>
|
|||
/// <param name="instance">The <see cref="ColorView"/> instance.</param>
|
|||
/// <param name="value">The value to coerce.</param>
|
|||
/// <returns>The coerced/validated value.</returns>
|
|||
private static Color CoerceColor(IAvaloniaObject instance, Color value) |
|||
{ |
|||
if (instance is ColorView colorView) |
|||
{ |
|||
return colorView.OnCoerceColor(value); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Coerces/validates the <see cref="HsvColor"/> property value.
|
|||
/// </summary>
|
|||
/// <param name="instance">The <see cref="ColorView"/> instance.</param>
|
|||
/// <param name="value">The value to coerce.</param>
|
|||
/// <returns>The coerced/validated value.</returns>
|
|||
private static HsvColor CoerceHsvColor(IAvaloniaObject instance, HsvColor value) |
|||
{ |
|||
if (instance is ColorView colorView) |
|||
{ |
|||
return colorView.OnCoerceHsvColor(value); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Event handler for when a key is pressed within the Hex RGB value TextBox.
|
|||
/// This is used to trigger re-evaluation of the color based on the TextBox value.
|
|||
/// </summary>
|
|||
private void HexTextBox_KeyDown(object? sender, Input.KeyEventArgs e) |
|||
{ |
|||
if (e.Key == Input.Key.Enter) |
|||
{ |
|||
GetColorFromHexTextBox(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Event handler for when the Hex RGB value TextBox looses focus.
|
|||
/// This is used to trigger re-evaluation of the color based on the TextBox value.
|
|||
/// </summary>
|
|||
private void HexTextBox_LostFocus(object? sender, Interactivity.RoutedEventArgs e) |
|||
{ |
|||
GetColorFromHexTextBox(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
namespace Avalonia.Controls |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a specific tab/page (subview) within the <see cref="ColorView"/>.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is indexed to match the default control template ordering.
|
|||
/// </remarks>
|
|||
public enum ColorViewTab |
|||
{ |
|||
/// <summary>
|
|||
/// The color spectrum subview with a box/ring spectrum and sliders.
|
|||
/// </summary>
|
|||
Spectrum = 0, |
|||
|
|||
/// <summary>
|
|||
/// The color palette subview with a grid of selectable colors.
|
|||
/// </summary>
|
|||
Palette = 1, |
|||
|
|||
/// <summary>
|
|||
/// The components subview with sliders and numeric input boxes.
|
|||
/// </summary>
|
|||
Components = 2, |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using Avalonia.Controls.Converters; |
|||
using Avalonia.Data.Converters; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Controls.Primitives.Converters |
|||
{ |
|||
/// <summary>
|
|||
/// Gets a <see cref="SolidColorBrush"/>, either black or white, depending on the luminance of the supplied color.
|
|||
/// A default color supplied in the converter parameter may be returned if alpha is below the set threshold.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is a highly-specialized converter for the color picker.
|
|||
/// </remarks>
|
|||
public class ContrastBrushConverter : IValueConverter |
|||
{ |
|||
private ToColorConverter toColorConverter = new ToColorConverter(); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the alpha channel threshold below which a default color is used instead of black/white.
|
|||
/// </summary>
|
|||
public byte AlphaThreshold { get; set; } = 128; |
|||
|
|||
/// <inheritdoc/>
|
|||
public object? Convert( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
Color comparisonColor; |
|||
Color? defaultColor = null; |
|||
|
|||
// Get the changing color to compare against
|
|||
var convertedValue = toColorConverter.Convert(value, targetType, parameter, culture); |
|||
if (convertedValue is Color valueColor) |
|||
{ |
|||
comparisonColor = valueColor; |
|||
} |
|||
else |
|||
{ |
|||
// Invalid color value provided
|
|||
return AvaloniaProperty.UnsetValue; |
|||
} |
|||
|
|||
// Get the default color when transparency is high
|
|||
var convertedParameter = toColorConverter.Convert(parameter, targetType, parameter, culture); |
|||
if (convertedParameter is Color parameterColor) |
|||
{ |
|||
defaultColor = parameterColor; |
|||
} |
|||
|
|||
if (comparisonColor.A < AlphaThreshold && |
|||
defaultColor.HasValue) |
|||
{ |
|||
// If the transparency is less than the threshold, just use the default brush
|
|||
// This can commonly be something like the TextControlForeground brush
|
|||
return new SolidColorBrush(defaultColor.Value); |
|||
} |
|||
else |
|||
{ |
|||
// Chose a white/black brush based on contrast to the base color
|
|||
if (ColorHelper.GetRelativeLuminance(comparisonColor) <= 0.5) |
|||
{ |
|||
// Dark color, return light for contrast
|
|||
return new SolidColorBrush(Colors.White); |
|||
} |
|||
else |
|||
{ |
|||
// Bright color, return dark for contrast
|
|||
return new SolidColorBrush(Colors.Black); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public object? ConvertBack( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
return AvaloniaProperty.UnsetValue; |
|||
} |
|||
} |
|||
} |
|||
@ -1,50 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using Avalonia.Data.Converters; |
|||
|
|||
namespace Avalonia.Controls.Primitives.Converters |
|||
{ |
|||
/// <summary>
|
|||
/// Converter to chain together multiple converters.
|
|||
/// </summary>
|
|||
public class ValueConverterGroup : List<IValueConverter>, IValueConverter |
|||
{ |
|||
/// <inheritdoc/>
|
|||
/// <inheritdoc/>
|
|||
public object? Convert( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
object? curValue; |
|||
|
|||
curValue = value; |
|||
for (int i = 0; i < Count; i++) |
|||
{ |
|||
curValue = this[i].Convert(curValue, targetType, parameter, culture); |
|||
} |
|||
|
|||
return curValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public object? ConvertBack( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
object? curValue; |
|||
|
|||
curValue = value; |
|||
for (int i = (Count - 1); i >= 0; i--) |
|||
{ |
|||
curValue = this[i].ConvertBack(curValue, targetType, parameter, culture); |
|||
} |
|||
|
|||
return curValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
<Styles xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:controls="using:Avalonia.Controls" |
|||
x:CompileBindings="True"> |
|||
|
|||
<Styles.Resources> |
|||
<!-- This must follow OverlayCornerRadius --> |
|||
<CornerRadius x:Key="TopOverlayCornerRadius">5,5,0,0</CornerRadius> |
|||
</Styles.Resources> |
|||
|
|||
<Style Selector="ColorPicker"> |
|||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> |
|||
<Setter Property="Height" Value="32" /> |
|||
<Setter Property="Width" Value="64" /> |
|||
<Setter Property="MinWidth" Value="64" /> |
|||
<Setter Property="Palette"> |
|||
<controls:FluentColorPalette /> |
|||
</Setter> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate TargetType="{x:Type ColorPicker}"> |
|||
<DropDownButton CornerRadius="{TemplateBinding CornerRadius}" |
|||
Height="{TemplateBinding Height}" |
|||
Width="{TemplateBinding Width}" |
|||
HorizontalContentAlignment="Stretch" |
|||
VerticalContentAlignment="Stretch" |
|||
Padding="0,0,10,0" |
|||
UseLayoutRounding="False"> |
|||
<DropDownButton.Styles> |
|||
<Style Selector="FlyoutPresenter.NoPadding"> |
|||
<Setter Property="Padding" Value="0" /> |
|||
</Style> |
|||
</DropDownButton.Styles> |
|||
<DropDownButton.Content> |
|||
<!-- Preview color --> |
|||
<Panel> |
|||
<Border Background="{StaticResource ColorControlCheckeredBackgroundBrush}" |
|||
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" |
|||
Margin="1,1,0,1" /> |
|||
<Border Background="{TemplateBinding HsvColor, Converter={StaticResource ToBrushConverter}}" |
|||
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" |
|||
Margin="1,1,0,1" /> |
|||
</Panel> |
|||
</DropDownButton.Content> |
|||
<DropDownButton.Flyout> |
|||
<Flyout FlyoutPresenterClasses="NoPadding"> |
|||
<ColorView x:Name="FlyoutColorView" |
|||
Color="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
ColorModel="{Binding ColorModel, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
ColorSpectrumComponents="{TemplateBinding ColorSpectrumComponents}" |
|||
ColorSpectrumShape="{TemplateBinding ColorSpectrumShape}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}" |
|||
IsAlphaEnabled="{TemplateBinding IsAlphaEnabled}" |
|||
IsAlphaVisible="{TemplateBinding IsAlphaVisible}" |
|||
IsColorComponentsVisible="{TemplateBinding IsColorComponentsVisible}" |
|||
IsColorModelVisible="{TemplateBinding IsColorModelVisible}" |
|||
IsColorPaletteVisible="{TemplateBinding IsColorPaletteVisible}" |
|||
IsColorPreviewVisible="{TemplateBinding IsColorPreviewVisible}" |
|||
IsColorSpectrumVisible="{TemplateBinding IsColorSpectrumVisible}" |
|||
IsColorSpectrumSliderVisible="{TemplateBinding IsColorSpectrumSliderVisible}" |
|||
IsComponentSliderVisible="{TemplateBinding IsComponentSliderVisible}" |
|||
IsComponentTextInputVisible="{TemplateBinding IsComponentTextInputVisible}" |
|||
IsHexInputVisible="{TemplateBinding IsHexInputVisible}" |
|||
MaxHue="{TemplateBinding MaxHue}" |
|||
MaxSaturation="{TemplateBinding MaxSaturation}" |
|||
MaxValue="{TemplateBinding MaxValue}" |
|||
MinHue="{TemplateBinding MinHue}" |
|||
MinSaturation="{TemplateBinding MinSaturation}" |
|||
MinValue="{TemplateBinding MinValue}" |
|||
PaletteColors="{TemplateBinding PaletteColors}" |
|||
PaletteColumnCount="{TemplateBinding PaletteColumnCount}" |
|||
Palette="{TemplateBinding Palette}" |
|||
SelectedIndex="{Binding SelectedIndex, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" /> |
|||
</Flyout> |
|||
</DropDownButton.Flyout> |
|||
</DropDownButton> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<!-- Adjust Background within Flyout --> |
|||
<!-- Note: This is implemented but there seems to be an issue and the selector can't match across the Flyout --> |
|||
<Style Selector="ColorPicker /template/ ColorView#FlyoutColorView /template/ Border#TabBackgroundBorder"> |
|||
<Setter Property="CornerRadius" Value="{DynamicResource TopOverlayCornerRadius}" /> |
|||
</Style> |
|||
|
|||
</Styles> |
|||
@ -0,0 +1,650 @@ |
|||
<Styles xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:controls="using:Avalonia.Controls" |
|||
xmlns:converters="using:Avalonia.Controls.Converters" |
|||
xmlns:primitives="using:Avalonia.Controls.Primitives" |
|||
xmlns:pc="clr-namespace:Avalonia.Controls.Primitives.Converters;assembly=Avalonia.Controls.ColorPicker" |
|||
xmlns:globalization="clr-namespace:System.Globalization;assembly=mscorlib" |
|||
x:CompileBindings="True"> |
|||
|
|||
<Styles.Resources> |
|||
<pc:ContrastBrushConverter x:Key="ContrastBrushConverter" /> |
|||
<pc:ThirdComponentConverter x:Key="ThirdComponentConverter" /> |
|||
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" /> |
|||
<converters:ColorToHexConverter x:Key="ColorToHexConverter" /> |
|||
<globalization:NumberFormatInfo x:Key="ColorViewComponentNumberFormat" NumberDecimalDigits="0" /> |
|||
<x:Double x:Key="ColorViewTabStripHeight">48</x:Double> |
|||
<x:Double x:Key="ColorViewComponentLabelWidth">30</x:Double> |
|||
<x:Double x:Key="ColorViewComponentTextInputWidth">80</x:Double> |
|||
<!-- Fluent UI System Icons : ic_fluent_inking_tool_20_regular.svg --> |
|||
<PathGeometry x:Key="ColorViewSpectrumIconGeometry"> |
|||
M3 2C3.27614 2 3.5 2.22386 3.5 2.5V5.5C3.5 5.77614 3.72386 6 4 6H16C16.2761 6 16.5 5.77614 |
|||
16.5 5.5V2.5C16.5 2.22386 16.7239 2 17 2C17.2761 2 17.5 2.22386 17.5 2.5V5.5C17.5 6.32843 |
|||
16.8284 7 16 7H15.809L12.2236 14.1708C12.0615 14.4951 11.7914 14.7431 11.4695 |
|||
14.8802C11.4905 15.0808 11.5 15.2891 11.5 15.5C11.5 16.0818 11.4278 16.6623 11.2268 |
|||
17.1165C11.019 17.5862 10.6266 18 10 18C9.37343 18 8.98105 17.5862 8.77323 17.1165C8.57222 |
|||
16.6623 8.5 16.0818 8.5 15.5C8.5 15.2891 8.50952 15.0808 8.53051 14.8802C8.20863 14.7431 |
|||
7.93851 14.4951 7.77639 14.1708L4.19098 7H4C3.17157 7 2.5 6.32843 2.5 5.5V2.5C2.5 2.22386 |
|||
2.72386 2 3 2ZM9.11803 14H10.882C11.0714 14 11.2445 13.893 11.3292 13.7236L14.691 |
|||
7H5.30902L8.67082 13.7236C8.75552 13.893 8.92865 14 9.11803 14ZM9.52346 15C9.50787 15.1549 |
|||
9.5 15.3225 9.5 15.5C9.5 16.0228 9.56841 16.4423 9.6877 16.7119C9.8002 16.9661 9.90782 17 |
|||
10 17C10.0922 17 10.1998 16.9661 10.3123 16.7119C10.4316 16.4423 10.5 16.0228 10.5 |
|||
15.5C10.5 15.3225 10.4921 15.1549 10.4765 15H9.52346Z |
|||
</PathGeometry> |
|||
<!-- Fluent UI System Icons : ic_fluent_color_20_regular.svg --> |
|||
<PathGeometry x:Key="ColorViewPaletteIconGeometry"> |
|||
M9.75003 6.5C10.1642 6.5 10.5 6.16421 10.5 5.75C10.5 5.33579 10.1642 5 9.75003 5C9.33582 |
|||
5 9.00003 5.33579 9.00003 5.75C9.00003 6.16421 9.33582 6.5 9.75003 6.5ZM12.75 7.5C13.1642 |
|||
7.5 13.5 7.16421 13.5 6.75C13.5 6.33579 13.1642 6 12.75 6C12.3358 6 12 6.33579 12 6.75C12 |
|||
7.16421 12.3358 7.5 12.75 7.5ZM15.25 9C15.25 9.41421 14.9142 9.75 14.5 9.75C14.0858 9.75 |
|||
13.75 9.41421 13.75 9C13.75 8.58579 14.0858 8.25 14.5 8.25C14.9142 8.25 15.25 8.58579 |
|||
15.25 9ZM14.5 12.75C14.9142 12.75 15.25 12.4142 15.25 12C15.25 11.5858 14.9142 11.25 14.5 |
|||
11.25C14.0858 11.25 13.75 11.5858 13.75 12C13.75 12.4142 14.0858 12.75 14.5 12.75ZM13.25 |
|||
14C13.25 14.4142 12.9142 14.75 12.5 14.75C12.0858 14.75 11.75 14.4142 11.75 14C11.75 |
|||
13.5858 12.0858 13.25 12.5 13.25C12.9142 13.25 13.25 13.5858 13.25 14ZM13.6972 |
|||
2.99169C10.9426 1.57663 8.1432 1.7124 5.77007 3.16636C4.55909 3.9083 3.25331 5.46925 |
|||
2.51605 7.05899C2.14542 7.85816 1.89915 8.70492 1.90238 9.49318C1.90566 10.2941 2.16983 |
|||
11.0587 2.84039 11.6053C3.45058 12.1026 3.98165 12.353 4.49574 12.3784C5.01375 12.404 |
|||
5.41804 12.1942 5.73429 12.0076C5.80382 11.9666 5.86891 11.927 5.93113 11.8892C6.17332 |
|||
11.7421 6.37205 11.6214 6.62049 11.5426C6.90191 11.4534 7.2582 11.4205 7.77579 |
|||
11.5787C7.96661 11.637 8.08161 11.7235 8.16212 11.8229C8.24792 11.9289 8.31662 12.0774 |
|||
8.36788 12.2886C8.41955 12.5016 8.44767 12.7527 8.46868 13.0491C8.47651 13.1594 8.48379 |
|||
13.2855 8.49142 13.4176C8.50252 13.6098 8.51437 13.8149 8.52974 14.0037C8.58435 14.6744 |
|||
8.69971 15.4401 9.10362 16.1357C9.51764 16.8488 10.2047 17.439 11.307 17.8158C12.9093 |
|||
18.3636 14.3731 17.9191 15.5126 17.0169C16.6391 16.125 17.4691 14.7761 17.8842 |
|||
13.4272C19.1991 9.15377 17.6728 5.03394 13.6972 2.99169ZM6.29249 4.01905C8.35686 2.75426 |
|||
10.7844 2.61959 13.2403 3.88119C16.7473 5.68275 18.1135 9.28161 16.9284 13.1332C16.5624 |
|||
14.3227 15.8338 15.4871 14.8919 16.2329C13.963 16.9684 12.8486 17.286 11.6305 |
|||
16.8696C10.7269 16.5607 10.2467 16.1129 9.96842 15.6336C9.68001 15.1369 9.57799 14.5556 |
|||
9.52644 13.9225C9.51101 13.733 9.50132 13.5621 9.49147 13.3884C9.48399 13.2564 9.47642 |
|||
13.1229 9.46618 12.9783C9.44424 12.669 9.41175 12.3499 9.33968 12.0529C9.26719 11.7541 |
|||
9.14902 11.4527 8.93935 11.1937C8.72439 10.9282 8.43532 10.7346 8.06801 10.6223C7.36648 |
|||
10.408 6.80266 10.4359 6.31839 10.5893C5.94331 10.7082 5.62016 10.9061 5.37179 |
|||
11.0582C5.31992 11.0899 5.2713 11.1197 5.22616 11.1463C4.94094 11.3146 4.75357 11.39 |
|||
4.54514 11.3796C4.33279 11.3691 4.00262 11.2625 3.47218 10.8301C3.0866 10.5158 2.90473 |
|||
10.0668 2.90237 9.48908C2.89995 8.89865 3.08843 8.20165 3.42324 7.47971C4.09686 6.0272 |
|||
5.28471 4.63649 6.29249 4.01905Z |
|||
</PathGeometry> |
|||
<!-- Fluent UI System Icons : ic_fluent_options_20_regular.svg --> |
|||
<PathGeometry x:Key="ColorViewComponentsIconGeometry"> |
|||
M14.95 5C14.7184 3.85888 13.7095 3 12.5 3C11.2905 3 10.2816 3.85888 10.05 5H2.5C2.22386 |
|||
5 2 5.22386 2 5.5C2 5.77614 2.22386 6 2.5 6H10.05C10.2816 7.14112 11.2905 8 12.5 8C13.7297 |
|||
8 14.752 7.11217 14.961 5.94254C14.9575 5.96177 14.9539 5.98093 14.95 6H17.5C17.7761 6 18 |
|||
5.77614 18 5.5C18 5.22386 17.7761 5 17.5 5H14.95ZM12.5 7C11.6716 7 11 6.32843 11 5.5C11 |
|||
4.67157 11.6716 4 12.5 4C13.3284 4 14 4.67157 14 5.5C14 6.32843 13.3284 7 12.5 7ZM9.94999 |
|||
14C9.71836 12.8589 8.70948 12 7.5 12C6.29052 12 5.28164 12.8589 5.05001 14H2.5C2.22386 |
|||
14 2 14.2239 2 14.5C2 14.7761 2.22386 15 2.5 15H5.05001C5.28164 16.1411 6.29052 17 7.5 |
|||
17C8.70948 17 9.71836 16.1411 9.94999 15H17.5C17.7761 15 18 14.7761 18 14.5C18 14.2239 |
|||
17.7761 14 17.5 14H9.94999ZM7.5 16C6.67157 16 6 15.3284 6 14.5C6 13.6716 6.67157 13 7.5 |
|||
13C8.32843 13 9 13.6716 9 14.5C9 15.3284 8.32843 16 7.5 16Z |
|||
</PathGeometry> |
|||
</Styles.Resources> |
|||
|
|||
<Style Selector="ColorView"> |
|||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> |
|||
<Setter Property="Palette"> |
|||
<controls:FluentColorPalette /> |
|||
</Setter> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate TargetType="{x:Type ColorView}"> |
|||
<Grid RowDefinitions="Auto,Auto"> |
|||
|
|||
<!-- Backgrounds --> |
|||
<!-- These are separated for Fluent v2 re-styling without having to re-template. --> |
|||
<Border x:Name="TabBackgroundBorder" |
|||
Grid.Row="0" |
|||
Grid.RowSpan="2" |
|||
Height="48" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Top" |
|||
Background="{DynamicResource SystemControlBackgroundBaseLowBrush}" |
|||
CornerRadius="{TemplateBinding CornerRadius}" /> |
|||
<Border x:Name="ContentBackgroundBorder" |
|||
Grid.Row="0" |
|||
Grid.RowSpan="2" |
|||
Margin="0,48,0,0" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" |
|||
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource BottomCornerRadiusFilterConverter}}" |
|||
Background="Transparent" |
|||
BorderBrush="Transparent" |
|||
BorderThickness="0,1,0,0" /> |
|||
|
|||
<TabControl x:Name="PART_TabControl" |
|||
Grid.Row="0" |
|||
Height="338" |
|||
Width="350" |
|||
SelectedIndex="{Binding SelectedIndex, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"> |
|||
<TabControl.Resources> |
|||
<Thickness x:Key="TabItemMargin">0,0,0,0</Thickness> |
|||
</TabControl.Resources> |
|||
<TabControl.Styles> |
|||
<Style Selector="TabControl"> |
|||
<Setter Property="ItemsPanel"> |
|||
<Setter.Value> |
|||
<ItemsPanelTemplate> |
|||
<UniformGrid Columns="0" |
|||
Rows="1" /> |
|||
</ItemsPanelTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
</TabControl.Styles> |
|||
<!-- Spectrum Tab --> |
|||
<TabItem IsVisible="{TemplateBinding IsColorSpectrumVisible}"> |
|||
<TabItem.Header> |
|||
<Border Height="{DynamicResource ColorViewTabStripHeight}"> |
|||
<PathIcon Width="20" |
|||
Height="20" |
|||
Data="{DynamicResource ColorViewSpectrumIconGeometry}" /> |
|||
</Border> |
|||
</TabItem.Header> |
|||
<Grid RowDefinitions="*" |
|||
Margin="12"> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto" |
|||
MinWidth="32" /> |
|||
<ColumnDefinition Width="*" /> |
|||
<ColumnDefinition Width="Auto" |
|||
MinWidth="32" /> |
|||
</Grid.ColumnDefinitions> |
|||
<primitives:ColorSlider x:Name="ColorSpectrumThirdComponentSlider" |
|||
AutomationProperties.Name="Third Component" |
|||
Grid.Column="0" |
|||
IsAlphaMaxForced="True" |
|||
IsSaturationValueMaxForced="False" |
|||
Orientation="Vertical" |
|||
ColorModel="Hsva" |
|||
ColorComponent="{Binding Components, ElementName=ColorSpectrum, Converter={StaticResource ThirdComponentConverter}}" |
|||
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Stretch" |
|||
Margin="0,0,12,0" |
|||
IsVisible="{TemplateBinding IsColorSpectrumSliderVisible}"/> |
|||
<primitives:ColorSpectrum x:Name="ColorSpectrum" |
|||
Grid.Column="1" |
|||
Components="{TemplateBinding ColorSpectrumComponents}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
MinHue="{TemplateBinding MinHue}" |
|||
MaxHue="{TemplateBinding MaxHue}" |
|||
MinSaturation="{TemplateBinding MinSaturation}" |
|||
MaxSaturation="{TemplateBinding MaxSaturation}" |
|||
MinValue="{TemplateBinding MinValue}" |
|||
MaxValue="{TemplateBinding MaxValue}" |
|||
Shape="{TemplateBinding ColorSpectrumShape}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" /> |
|||
<primitives:ColorSlider x:Name="ColorSpectrumAlphaSlider" |
|||
AutomationProperties.Name="Alpha Component" |
|||
Grid.Column="2" |
|||
Orientation="Vertical" |
|||
ColorModel="Hsva" |
|||
ColorComponent="Alpha" |
|||
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum}" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Stretch" |
|||
Margin="12,0,0,0" |
|||
IsEnabled="{TemplateBinding IsAlphaEnabled}"> |
|||
<primitives:ColorSlider.IsVisible> |
|||
<MultiBinding Converter="{x:Static BoolConverters.And}"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsAlphaVisible" /> |
|||
</MultiBinding> |
|||
</primitives:ColorSlider.IsVisible> |
|||
</primitives:ColorSlider> |
|||
</Grid> |
|||
</TabItem> |
|||
<!-- Palette Tab --> |
|||
<TabItem IsVisible="{TemplateBinding IsColorPaletteVisible}"> |
|||
<TabItem.Header> |
|||
<Border Height="{DynamicResource ColorViewTabStripHeight}"> |
|||
<PathIcon Width="20" |
|||
Height="20" |
|||
Data="{DynamicResource ColorViewPaletteIconGeometry}" /> |
|||
</Border> |
|||
</TabItem.Header> |
|||
<ListBox Items="{TemplateBinding PaletteColors}" |
|||
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
UseLayoutRounding="False" |
|||
Margin="12"> |
|||
<ListBox.Styles> |
|||
|
|||
<Style Selector="ListBoxItem"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="Padding" Value="0" /> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate TargetType="{x:Type ListBoxItem}"> |
|||
<Grid UseLayoutRounding="False"> |
|||
<ContentPresenter Name="PART_ContentPresenter" |
|||
Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}" |
|||
CornerRadius="{TemplateBinding CornerRadius}" |
|||
ContentTemplate="{TemplateBinding ContentTemplate}" |
|||
Content="{TemplateBinding Content}" |
|||
Padding="{TemplateBinding Padding}" |
|||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
|||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" /> |
|||
<Rectangle x:Name="BorderRectangle" |
|||
IsHitTestVisible="False" |
|||
StrokeThickness="3" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" /> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
|
|||
<Style Selector="^ /template/ Rectangle#BorderRectangle"> |
|||
<Setter Property="Stroke" Value="{DynamicResource SystemControlHighlightListAccentLowBrush}" /> |
|||
<Setter Property="Opacity" Value="0" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:pointerover /template/ Rectangle#BorderRectangle"> |
|||
<Setter Property="Stroke" Value="{DynamicResource SystemControlHighlightListAccentLowBrush}" /> |
|||
<Setter Property="Opacity" Value="1" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:selected /template/ Rectangle#BorderRectangle" |
|||
x:DataType="Color"> |
|||
<!-- The below line really should be: |
|||
'Value="{Binding Converter={StaticResource ContrastBrushConverter}, ConverterParameter={DynamicResource TextControlForeground}}"' |
|||
However, DynamicResource and Binding is not currently supported in Avalonia for converter parameters. |
|||
This means certain colors with transparency less than 50% may have a selection border that is difficult |
|||
to see over top of the default control/window background. Since palettes do not usually have transparency |
|||
it is considered better to disable this functionality rather than work around it with a multi-value |
|||
converter. This should be revisited if Avalonia supports the above code in the future. --> |
|||
<Setter Property="Stroke" Value="{Binding Converter={StaticResource ContrastBrushConverter}}" /> |
|||
<Setter Property="Opacity" Value="1" /> |
|||
</Style> |
|||
</Style> |
|||
|
|||
</ListBox.Styles> |
|||
<ListBox.ItemTemplate> |
|||
<DataTemplate DataType="{x:Type Color}"> |
|||
<Border AutomationProperties.Name="{Binding Converter={StaticResource ColorToDisplayNameConverter}}" |
|||
ToolTip.Tip="{Binding Converter={StaticResource ColorToDisplayNameConverter}}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch"> |
|||
<Border.Background> |
|||
<SolidColorBrush Color="{Binding}" /> |
|||
</Border.Background> |
|||
</Border> |
|||
</DataTemplate> |
|||
</ListBox.ItemTemplate> |
|||
<ListBox.ItemsPanel> |
|||
<ItemsPanelTemplate> |
|||
<UniformGrid Columns="{Binding $parent[ColorView].PaletteColumnCount}" /> |
|||
</ItemsPanelTemplate> |
|||
</ListBox.ItemsPanel> |
|||
</ListBox> |
|||
</TabItem> |
|||
<!-- Components Tab --> |
|||
<TabItem IsVisible="{TemplateBinding IsColorComponentsVisible}"> |
|||
<TabItem.Header> |
|||
<Border Height="{DynamicResource ColorViewTabStripHeight}"> |
|||
<PathIcon Width="20" |
|||
Height="20" |
|||
Data="{DynamicResource ColorViewComponentsIconGeometry}" /> |
|||
</Border> |
|||
</TabItem.Header> |
|||
<Grid ColumnDefinitions="Auto,Auto,*" |
|||
RowDefinitions="Auto,24,1*,1*,1*,1*,12" |
|||
Margin="12"> |
|||
<!-- Top color model & Hex input --> |
|||
<Grid Grid.Column="0" |
|||
Grid.ColumnSpan="3" |
|||
Grid.Row="0" |
|||
ColumnDefinitions="1*,12,1*"> |
|||
<!-- Content RGB/HSV names are hard-coded and considered universal --> |
|||
<!-- RadioButtons are styled to look like a 'SegmentedControl' or 'ButtonGroup' --> |
|||
<Grid ColumnDefinitions="1*,1*" |
|||
IsVisible="{TemplateBinding IsColorModelVisible}"> |
|||
<Grid.Styles> |
|||
|
|||
<Style Selector="RadioButton"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackground}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForeground}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="BorderThickness" Value="1" /> |
|||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> |
|||
<Setter Property="Padding" Value="{DynamicResource ButtonPadding}" /> |
|||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
|||
<Setter Property="VerticalAlignment" Value="Center" /> |
|||
<Setter Property="HorizontalContentAlignment" Value="Center" /> |
|||
<Setter Property="VerticalContentAlignment" Value="Center" /> |
|||
<Setter Property="FontWeight" Value="Normal" /> |
|||
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" /> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate TargetType="{x:Type RadioButton}"> |
|||
<ContentPresenter x:Name="PART_ContentPresenter" |
|||
Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}" |
|||
CornerRadius="{TemplateBinding CornerRadius}" |
|||
Content="{TemplateBinding Content}" |
|||
ContentTemplate="{TemplateBinding ContentTemplate}" |
|||
Padding="{TemplateBinding Padding}" |
|||
RecognizesAccessKey="True" |
|||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" |
|||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" /> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
|
|||
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPointerOver}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForegroundPointerOver}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:pressed /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPressed}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForegroundPressed}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:checked /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundChecked}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForegroundChecked}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:checked:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPointerOver}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPointerOver}" /> |
|||
</Style> |
|||
|
|||
<Style Selector="^:checked:pressed /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPressed}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<Setter Property="Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPressed}" /> |
|||
</Style> |
|||
</Style> |
|||
|
|||
</Grid.Styles> |
|||
<RadioButton x:Name="RgbRadioButton" |
|||
Grid.Column="0" |
|||
Content="RGB" |
|||
CornerRadius="4,0,0,4" |
|||
IsChecked="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Rgba}, Mode=TwoWay}" /> |
|||
<RadioButton x:Name="HsvRadioButton" |
|||
Grid.Column="1" |
|||
Content="HSV" |
|||
CornerRadius="0,4,4,0" |
|||
IsChecked="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Hsva}, Mode=TwoWay}" /> |
|||
</Grid> |
|||
<Grid x:Name="HexInputGrid" |
|||
Grid.Column="2" |
|||
IsVisible="{TemplateBinding IsHexInputVisible}"> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="30" /> |
|||
<ColumnDefinition Width="*" /> |
|||
</Grid.ColumnDefinitions> |
|||
<Border Grid.Column="0" |
|||
Height="32" |
|||
Background="{DynamicResource TextControlBackgroundDisabled}" |
|||
BorderBrush="{DynamicResource TextControlBorderBrush}" |
|||
BorderThickness="1,1,0,1" |
|||
CornerRadius="4,0,0,4"> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="#" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" /> |
|||
</Border> |
|||
<!-- Color updated in code-behind --> |
|||
<TextBox x:Name="PART_HexTextBox" |
|||
Grid.Column="1" |
|||
AutomationProperties.Name="Hexadecimal Color" |
|||
Height="32" |
|||
MaxLength="8" |
|||
HorizontalAlignment="Stretch" |
|||
CornerRadius="0,4,4,0" /> |
|||
</Grid> |
|||
</Grid> |
|||
<!-- Color component editing controls --> |
|||
<!-- Component 1 RGB:Red HSV:Hue --> |
|||
<Border Grid.Column="0" |
|||
Grid.Row="2" |
|||
Height="{Binding ElementName=Component1NumericUpDown, Path=Bounds.Height}" |
|||
Width="{DynamicResource ColorViewComponentLabelWidth}" |
|||
Background="{DynamicResource TextControlBackgroundDisabled}" |
|||
BorderBrush="{DynamicResource TextControlBorderBrush}" |
|||
BorderThickness="1,1,0,1" |
|||
CornerRadius="4,0,0,4" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}"> |
|||
<Panel HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="R" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Rgba}, Mode=OneWay}"/> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="H" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Hsva}, Mode=OneWay}" /> |
|||
</Panel> |
|||
</Border> |
|||
<NumericUpDown x:Name="Component1NumericUpDown" |
|||
Grid.Column="1" |
|||
Grid.Row="2" |
|||
AllowSpin="True" |
|||
ShowButtonSpinner="False" |
|||
Height="32" |
|||
Width="{DynamicResource ColorViewComponentTextInputWidth}" |
|||
CornerRadius="0,4,4,0" |
|||
Margin="0,0,12,0" |
|||
VerticalAlignment="Center" |
|||
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" |
|||
Minimum="{Binding Minimum, ElementName=Component1Slider}" |
|||
Maximum="{Binding Maximum, ElementName=Component1Slider}" |
|||
Value="{Binding Value, ElementName=Component1Slider}" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}" /> |
|||
<primitives:ColorSlider x:Name="Component1Slider" |
|||
Grid.Column="2" |
|||
Grid.Row="2" |
|||
Orientation="Horizontal" |
|||
IsRoundingEnabled="True" |
|||
IsSnapToTickEnabled="True" |
|||
TickFrequency="1" |
|||
ColorComponent="Component1" |
|||
ColorModel="{TemplateBinding ColorModel, Mode=OneWay}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentSliderVisible}" /> |
|||
<!-- Component 2 RGB:Green HSV:Saturation --> |
|||
<Border Grid.Column="0" |
|||
Grid.Row="3" |
|||
Width="{DynamicResource ColorViewComponentLabelWidth}" |
|||
Height="{Binding ElementName=Component2NumericUpDown, Path=Bounds.Height}" |
|||
Background="{DynamicResource TextControlBackgroundDisabled}" |
|||
BorderBrush="{DynamicResource TextControlBorderBrush}" |
|||
BorderThickness="1,1,0,1" |
|||
CornerRadius="4,0,0,4" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}"> |
|||
<Panel HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="G" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Rgba}, Mode=OneWay}" /> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="S" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Hsva}, Mode=OneWay}" /> |
|||
</Panel> |
|||
</Border> |
|||
<NumericUpDown x:Name="Component2NumericUpDown" |
|||
Grid.Column="1" |
|||
Grid.Row="3" |
|||
AllowSpin="True" |
|||
ShowButtonSpinner="False" |
|||
Height="32" |
|||
Width="{DynamicResource ColorViewComponentTextInputWidth}" |
|||
CornerRadius="0,4,4,0" |
|||
Margin="0,0,12,0" |
|||
VerticalAlignment="Center" |
|||
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" |
|||
Minimum="{Binding Minimum, ElementName=Component2Slider}" |
|||
Maximum="{Binding Maximum, ElementName=Component2Slider}" |
|||
Value="{Binding Value, ElementName=Component2Slider}" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}" /> |
|||
<primitives:ColorSlider x:Name="Component2Slider" |
|||
Grid.Column="2" |
|||
Grid.Row="3" |
|||
Orientation="Horizontal" |
|||
IsRoundingEnabled="True" |
|||
IsSnapToTickEnabled="True" |
|||
TickFrequency="1" |
|||
ColorComponent="Component2" |
|||
ColorModel="{TemplateBinding ColorModel, Mode=OneWay}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentSliderVisible}" /> |
|||
<!-- Component 3 RGB:Blue HSV:Value --> |
|||
<Border Grid.Column="0" |
|||
Grid.Row="4" |
|||
Width="{DynamicResource ColorViewComponentLabelWidth}" |
|||
Height="{Binding ElementName=Component3NumericUpDown, Path=Bounds.Height}" |
|||
Background="{DynamicResource TextControlBackgroundDisabled}" |
|||
BorderBrush="{DynamicResource TextControlBorderBrush}" |
|||
BorderThickness="1,1,0,1" |
|||
CornerRadius="4,0,0,4" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}"> |
|||
<Panel HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="B" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Rgba}, Mode=OneWay}" /> |
|||
<TextBlock Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="V" |
|||
IsVisible="{TemplateBinding ColorModel, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static controls:ColorModel.Hsva}, Mode=OneWay}" /> |
|||
</Panel> |
|||
</Border> |
|||
<NumericUpDown x:Name="Component3NumericUpDown" |
|||
Grid.Column="1" |
|||
Grid.Row="4" |
|||
AllowSpin="True" |
|||
ShowButtonSpinner="False" |
|||
Height="32" |
|||
Width="{DynamicResource ColorViewComponentTextInputWidth}" |
|||
CornerRadius="0,4,4,0" |
|||
Margin="0,0,12,0" |
|||
VerticalAlignment="Center" |
|||
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" |
|||
Minimum="{Binding Minimum, ElementName=Component3Slider}" |
|||
Maximum="{Binding Maximum, ElementName=Component3Slider}" |
|||
Value="{Binding Value, ElementName=Component3Slider}" |
|||
IsVisible="{TemplateBinding IsComponentTextInputVisible}" /> |
|||
<primitives:ColorSlider x:Name="Component3Slider" |
|||
Grid.Column="2" |
|||
Grid.Row="4" |
|||
Orientation="Horizontal" |
|||
IsRoundingEnabled="True" |
|||
IsSnapToTickEnabled="True" |
|||
TickFrequency="1" |
|||
ColorComponent="Component3" |
|||
ColorModel="{TemplateBinding ColorModel, Mode=OneWay}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Center" |
|||
IsVisible="{TemplateBinding IsComponentSliderVisible}" /> |
|||
<!-- Alpha Component --> |
|||
<Border Grid.Column="0" |
|||
Grid.Row="5" |
|||
Width="{DynamicResource ColorViewComponentLabelWidth}" |
|||
Height="{Binding ElementName=AlphaComponentNumericUpDown, Path=Bounds.Height}" |
|||
Background="{DynamicResource TextControlBackgroundDisabled}" |
|||
BorderBrush="{DynamicResource TextControlBorderBrush}" |
|||
BorderThickness="1,1,0,1" |
|||
CornerRadius="4,0,0,4" |
|||
VerticalAlignment="Center" |
|||
IsEnabled="{TemplateBinding IsAlphaEnabled}"> |
|||
<TextBlock x:Name="AlphaComponentTextBlock" |
|||
Foreground="{DynamicResource TextControlForegroundDisabled}" |
|||
FontWeight="SemiBold" |
|||
Text="A" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" /> |
|||
<Border.IsVisible> |
|||
<MultiBinding Converter="{x:Static BoolConverters.And}"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsAlphaVisible" /> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsComponentTextInputVisible" /> |
|||
</MultiBinding> |
|||
</Border.IsVisible> |
|||
</Border> |
|||
<NumericUpDown x:Name="AlphaComponentNumericUpDown" |
|||
Grid.Column="1" |
|||
Grid.Row="5" |
|||
AllowSpin="True" |
|||
ShowButtonSpinner="False" |
|||
Height="32" |
|||
Width="{DynamicResource ColorViewComponentTextInputWidth}" |
|||
CornerRadius="0,4,4,0" |
|||
Margin="0,0,12,0" |
|||
VerticalAlignment="Center" |
|||
NumberFormat="{StaticResource ColorViewComponentNumberFormat}" |
|||
Minimum="{Binding Minimum, ElementName=AlphaComponentSlider}" |
|||
Maximum="{Binding Maximum, ElementName=AlphaComponentSlider}" |
|||
Value="{Binding Value, ElementName=AlphaComponentSlider}" |
|||
IsEnabled="{TemplateBinding IsAlphaEnabled}"> |
|||
<NumericUpDown.IsVisible> |
|||
<MultiBinding Converter="{x:Static BoolConverters.And}"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsAlphaVisible" /> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsComponentTextInputVisible" /> |
|||
</MultiBinding> |
|||
</NumericUpDown.IsVisible> |
|||
</NumericUpDown> |
|||
<primitives:ColorSlider x:Name="AlphaComponentSlider" |
|||
Grid.Column="2" |
|||
Grid.Row="5" |
|||
Orientation="Horizontal" |
|||
IsRoundingEnabled="True" |
|||
IsSnapToTickEnabled="True" |
|||
TickFrequency="1" |
|||
ColorComponent="Alpha" |
|||
ColorModel="{TemplateBinding ColorModel, Mode=OneWay}" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Center" |
|||
IsEnabled="{TemplateBinding IsAlphaEnabled}"> |
|||
<primitives:ColorSlider.IsVisible> |
|||
<MultiBinding Converter="{x:Static BoolConverters.And}"> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsAlphaVisible" /> |
|||
<Binding RelativeSource="{RelativeSource TemplatedParent}" |
|||
Path="IsComponentSliderVisible" /> |
|||
</MultiBinding> |
|||
</primitives:ColorSlider.IsVisible> |
|||
</primitives:ColorSlider> |
|||
</Grid> |
|||
</TabItem> |
|||
</TabControl> |
|||
<!-- Previewer --> |
|||
<!-- Note that top/bottom margins have -5 to remove for drop shadow padding --> |
|||
<primitives:ColorPreviewer Grid.Row="1" |
|||
HsvColor="{Binding HsvColor, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" |
|||
IsAccentColorsVisible="{TemplateBinding IsAccentColorsVisible}" |
|||
Margin="12,-5,12,7" |
|||
IsVisible="{TemplateBinding IsColorPreviewVisible}" /> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
</Styles> |
|||
@ -0,0 +1,56 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using Avalonia.Data; |
|||
using Avalonia.Data.Converters; |
|||
|
|||
namespace Avalonia.Controls.Converters |
|||
{ |
|||
/// <summary>
|
|||
/// Converter to convert an enum value to bool by comparing to the given parameter.
|
|||
/// Both value and parameter must be of the same enum type.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This converter is useful to enable binding of radio buttons with a selected enum value.
|
|||
/// </remarks>
|
|||
public class EnumToBoolConverter : IValueConverter |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public object? Convert( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
if (value == null && |
|||
parameter == null) |
|||
{ |
|||
return true; |
|||
} |
|||
else if (value == null || |
|||
parameter == null) |
|||
{ |
|||
return false; |
|||
} |
|||
else |
|||
{ |
|||
return value!.Equals(parameter); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public object? ConvertBack( |
|||
object? value, |
|||
Type targetType, |
|||
object? parameter, |
|||
CultureInfo culture) |
|||
{ |
|||
if (value is bool boolValue && |
|||
boolValue == true) |
|||
{ |
|||
return parameter; |
|||
} |
|||
|
|||
return BindingOperations.DoNothing; |
|||
} |
|||
} |
|||
} |
|||
@ -1,54 +0,0 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using Avalonia.Data.Converters; |
|||
|
|||
namespace Avalonia.Controls.Converters |
|||
{ |
|||
/// <summary>
|
|||
/// Converter that checks if an enum value is equal to the given parameter enum value.
|
|||
/// </summary>
|
|||
public class EnumValueEqualsConverter : IValueConverter |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) |
|||
{ |
|||
// Note: Unlike string comparisons, null/empty is not supported
|
|||
// Both 'value' and 'parameter' must exist and if both are missing they are not considered equal
|
|||
if (value != null && |
|||
parameter != null) |
|||
{ |
|||
Type type = value.GetType(); |
|||
|
|||
if (type.IsEnum) |
|||
{ |
|||
var valueStr = value?.ToString(); |
|||
var paramStr = parameter?.ToString(); |
|||
|
|||
if (string.Equals(valueStr, paramStr, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
/* |
|||
// TODO: When .net Standard 2.0 is no longer supported the code can be changed to below
|
|||
// This is a little more type safe
|
|||
if (type.IsEnum && |
|||
Enum.TryParse(type, value?.ToString(), true, out object? valueEnum) && |
|||
Enum.TryParse(type, parameter?.ToString(), true, out object? paramEnum)) |
|||
{ |
|||
return valueEnum == paramEnum; |
|||
} |
|||
*/ |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) |
|||
{ |
|||
throw new System.NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue