1+ using System . Collections . Generic ;
2+ using Avalonia ;
3+ using Avalonia . Controls ;
4+ using Avalonia . Data ;
5+ using Avalonia . Media ;
6+
7+ namespace Scribble . Controls . ScribbleColorPicker ;
8+
9+ public partial class ScribbleColorPicker : UserControl
10+ {
11+ private static readonly IReadOnlyList < Color > DefaultPalette = GenerateMaterialPalette ( ) ;
12+
13+ private static List < Color > GenerateMaterialPalette ( )
14+ {
15+ var palette = new MaterialHalfColorPalette ( ) ;
16+ var colors = new List < Color > ( ) ;
17+
18+ // Loop through every base color (columns) and every shade (rows)
19+ for ( int colorIndex = 0 ; colorIndex < palette . ColorCount ; colorIndex ++ )
20+ {
21+ for ( int shadeIndex = 0 ; shadeIndex < palette . ShadeCount ; shadeIndex ++ )
22+ {
23+ colors . Add ( palette . GetColor ( colorIndex , shadeIndex ) ) ;
24+ }
25+ }
26+
27+ return colors ;
28+ }
29+
30+ // Properties
31+ public static readonly StyledProperty < IEnumerable < Color > > PaletteColorsProperty =
32+ AvaloniaProperty . Register < ScribbleColorPicker , IEnumerable < Color > > (
33+ nameof ( PaletteColors ) ,
34+ defaultValue : DefaultPalette ) ;
35+
36+ public IEnumerable < Color > PaletteColors
37+ {
38+ get => GetValue ( PaletteColorsProperty ) ;
39+ set => SetValue ( PaletteColorsProperty , value ) ;
40+ }
41+
42+ public static readonly StyledProperty < Color > SelectedColorProperty =
43+ AvaloniaProperty . Register < ScribbleColorPicker , Color > (
44+ nameof ( SelectedColor ) ,
45+ Colors . White ,
46+ defaultBindingMode : BindingMode . TwoWay ) ;
47+
48+ public Color SelectedColor
49+ {
50+ get => GetValue ( SelectedColorProperty ) ;
51+ set => SetValue ( SelectedColorProperty , value ) ;
52+ }
53+
54+ // To prevent infinite loop from the textbox updating the color + the color pallet updating the textbox
55+ private bool _isUpdatingHex = false ;
56+
57+ public ScribbleColorPicker ( )
58+ {
59+ InitializeComponent ( ) ;
60+ }
61+
62+ protected override void OnPropertyChanged ( AvaloniaPropertyChangedEventArgs change )
63+ {
64+ base . OnPropertyChanged ( change ) ;
65+ if ( change . Property == SelectedColorProperty )
66+ {
67+ UpdateHexTextBox ( change . GetNewValue < Color > ( ) ) ;
68+ }
69+ }
70+
71+ private void UpdateHexTextBox ( Color color )
72+ {
73+ if ( _isUpdatingHex ) return ;
74+
75+ _isUpdatingHex = true ;
76+ HexTextBox . Text = color . ToString ( ) . TrimStart ( '#' ) . ToUpper ( ) ;
77+ _isUpdatingHex = false ;
78+ }
79+
80+ private void HexTextBox_OnTextChanged ( object ? sender , TextChangedEventArgs e )
81+ {
82+ if ( _isUpdatingHex ) return ;
83+
84+ var hex = HexTextBox . Text ? . Trim ( ) ;
85+ if ( string . IsNullOrEmpty ( hex ) ) return ;
86+
87+ if ( ! hex . StartsWith ( '#' ) ) hex = "#" + hex ;
88+
89+ if ( Color . TryParse ( hex , out Color parsedColor ) )
90+ {
91+ _isUpdatingHex = true ;
92+ SelectedColor = parsedColor ;
93+ _isUpdatingHex = false ;
94+ }
95+ }
96+
97+ private void ColorListBox_OnSelectionChanged ( object ? sender , SelectionChangedEventArgs e )
98+ {
99+ if ( e . AddedItems . Count > 0 )
100+ {
101+ ColorPickerButton . Flyout ? . Hide ( ) ;
102+ }
103+ }
104+ }
0 commit comments