diff --git a/samples/AvalonDraw/MainWindow.axaml b/samples/AvalonDraw/MainWindow.axaml index 5eef287744..854ef0d77a 100644 --- a/samples/AvalonDraw/MainWindow.axaml +++ b/samples/AvalonDraw/MainWindow.axaml @@ -204,7 +204,9 @@ + ItemsSource="{Binding Swatches}" + SelectionChanged="SwatchList_OnSelectionChanged" + PointerPressed="SwatchList_OnPointerPressed"/> Layers => _layerService.Layers; public ObservableCollection Patterns => _patternService.Patterns; public ObservableCollection BrushStyles => _brushService.Brushes; + public ObservableCollection Swatches => _brushService.Swatches; public ObservableCollection Symbols => _symbolService.Symbols; public ObservableCollection Styles => _appearanceService.Styles; private ArtboardInfo? _selectedArtboard; private LayerService.LayerEntry? _selectedLayer; private PatternService.PatternEntry? _selectedPattern; private BrushService.BrushEntry? _selectedBrush; + private BrushService.SwatchEntry? _selectedSwatch; private SymbolService.SymbolEntry? _selectedSymbol; private AppearanceService.StyleEntry? _selectedStyle; private ListBox? _artboardList; @@ -1567,6 +1569,7 @@ private void BuildTree() UpdateArtboards(); UpdateLayers(); UpdatePatterns(); + UpdateSwatches(); UpdateBrushes(); UpdateSymbols(); UpdateStyles(); @@ -1630,6 +1633,17 @@ private void UpdatePatterns() } } + private void UpdateSwatches() + { + _brushService.LoadSwatches(_document); + if (Swatches.Count > 0) + { + _selectedSwatch = Swatches[0]; + if (_swatchList is { }) + _swatchList.SelectedIndex = 0; + } + } + private void UpdateBrushes() { if (BrushStyles.Count > 0) @@ -2331,9 +2345,27 @@ private void LayerTree_OnSelectionChanged(object? sender, SelectionChangedEventA private void SwatchList_OnSelectionChanged(object? sender, SelectionChangedEventArgs e) { - if (e.AddedItems.Count > 0 && e.AddedItems[0] is PatternService.PatternEntry info) + if (e.AddedItems.Count > 0 && e.AddedItems[0] is BrushService.SwatchEntry info) + { + _selectedSwatch = info; + } + } + + private async void SwatchList_OnPointerPressed(object? sender, PointerPressedEventArgs e) + { + if (e.ClickCount == 2 && _swatchList?.SelectedItem is BrushService.SwatchEntry info) { - _selectedPattern = info; + var dlg = new SwatchEditorWindow(info.Color); + var result = await dlg.ShowDialog(this); + if (result) + { + info.Color = dlg.Result; + if (_document is { }) + { + SvgView.SkSvg!.FromSvgDocument(_document); + SvgView.InvalidateVisual(); + } + } } } diff --git a/samples/AvalonDraw/Services/BrushService.cs b/samples/AvalonDraw/Services/BrushService.cs index a97e5d1644..cca458a454 100644 --- a/samples/AvalonDraw/Services/BrushService.cs +++ b/samples/AvalonDraw/Services/BrushService.cs @@ -1,4 +1,7 @@ using System.Collections.ObjectModel; +using Avalonia.Media; +using Svg; +using System.Linq; namespace AvalonDraw.Services; @@ -27,5 +30,75 @@ public BrushService() Brushes.Add(new BrushEntry("Default", def)); SelectedBrush = Brushes[0]; } + + public class SwatchEntry + { + public SvgLinearGradientServer Swatch { get; } + public string Name { get; } + + public SwatchEntry(SvgLinearGradientServer swatch, string name) + { + Swatch = swatch; + Name = name; + } + + public string Color + { + get => ColorToString(GetColor()); + set => SetColor(ParseColor(value)); + } + + private System.Drawing.Color GetColor() + { + var stop = Swatch.Stops.FirstOrDefault(); + return stop?.GetColor(Swatch) ?? System.Drawing.Color.Black; + } + + private void SetColor(System.Drawing.Color c) + { + Swatch.Children.Clear(); + Swatch.Children.Add(new SvgGradientStop + { + Offset = new SvgUnit(0f), + StopColor = new SvgColourServer(c), + StopOpacity = 1f + }); + Swatch.Children.Add(new SvgGradientStop + { + Offset = new SvgUnit(1f), + StopColor = new SvgColourServer(c), + StopOpacity = 1f + }); + } + + private static string ColorToString(System.Drawing.Color c) + => $"#{c.A:X2}{c.R:X2}{c.G:X2}{c.B:X2}"; + + private static System.Drawing.Color ParseColor(string color) + { + var ac = Avalonia.Media.Color.Parse(color); + return System.Drawing.Color.FromArgb(ac.A, ac.R, ac.G, ac.B); + } + + public override string ToString() => Name; + } + + public ObservableCollection Swatches { get; } = new(); + + public void LoadSwatches(SvgDocument? document) + { + Swatches.Clear(); + if (document is null) + return; + int index = 1; + foreach (var grad in document.Descendants().OfType()) + { + if (grad.Stops.Count == 1 || (grad.Stops.Count == 2 && grad.Stops[0].GetColor(grad) == grad.Stops[1].GetColor(grad))) + { + var name = string.IsNullOrEmpty(grad.ID) ? $"Swatch {index++}" : grad.ID!; + Swatches.Add(new SwatchEntry(grad, name)); + } + } + } } diff --git a/samples/AvalonDraw/SwatchEditorWindow.axaml b/samples/AvalonDraw/SwatchEditorWindow.axaml new file mode 100644 index 0000000000..2cb6e62fee --- /dev/null +++ b/samples/AvalonDraw/SwatchEditorWindow.axaml @@ -0,0 +1,13 @@ + + + + +