Browse Source

Added more color pasting and dropping options and fixed action display persisting bug

CPKreuz 2 years ago
parent
commit
16a5c2468a

+ 39 - 0
src/PixiEditor/Helpers/ColorHelper.cs

@@ -0,0 +1,39 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Text.RegularExpressions;
+using System.Windows;
+
+namespace PixiEditor.Helpers;
+
+public class ColorHelper
+{
+    public static bool ParseAnyFormat(IDataObject data, [NotNullWhen(true)] out DrawingApi.Core.ColorsImpl.Color? result) => 
+        ParseAnyFormat(((DataObject)data).GetText().Trim(), out result);
+    
+    public static bool ParseAnyFormat(string value, [NotNullWhen(true)] out DrawingApi.Core.ColorsImpl.Color? result)
+    {
+        bool hex = Regex.IsMatch(value, "^#?([a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$");
+
+        if (hex)
+        {
+            result = DrawingApi.Core.ColorsImpl.Color.Parse(value);
+            return true;
+        }
+
+        var match = Regex.Match(value, @"(?:rgba?\(?)? *(?<r>\d{1,3})(?:, *| +)(?<g>\d{1,3})(?:, *| +)(?<b>\d{1,3})(?:(?:, *| +)(?<a>\d{0,3}))?\)?");
+
+        if (!match.Success)
+        {
+            result = null;
+            return false;
+        }
+
+        byte r = byte.Parse(match.Groups["r"].ValueSpan);
+        byte g = byte.Parse(match.Groups["g"].ValueSpan);
+        byte b = byte.Parse(match.Groups["b"].ValueSpan);
+        byte a = match.Groups["a"].Success ? byte.Parse(match.Groups["a"].ValueSpan) : (byte)255;
+
+        result = new DrawingApi.Core.ColorsImpl.Color(r, g, b, a);
+        return true;
+
+    }
+}

+ 56 - 33
src/PixiEditor/ViewModels/SubViewModels/Main/ClipboardViewModel.cs

@@ -3,6 +3,7 @@ using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Media;
+using PixiEditor.Helpers;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Controllers;
 
@@ -34,13 +35,23 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
         ClipboardController.TryPasteFromClipboard(Owner.DocumentManagerSubViewModel.ActiveDocument);
     }
 
-    [Command.Basic("PixiEditor.Clipboard.PasteColor", "Paste color", "Paste color from clipboard", CanExecute = "PixiEditor.Clipboard.CanPasteColor", IconEvaluator = "PixiEditor.Clipboard.PasteColorIcon")]
-    public void PasteColor()
+    [Command.Basic("PixiEditor.Clipboard.PasteColor", false, "Paste color", "Paste color from clipboard", CanExecute = "PixiEditor.Clipboard.CanPasteColor", IconEvaluator = "PixiEditor.Clipboard.PasteColorIcon")]
+    [Command.Basic("PixiEditor.Clipboard.PasteColorAsSecondary", true, "Paste color as secondary", "Paste color as secondary from clipboard", CanExecute = "PixiEditor.Clipboard.CanPasteColor", IconEvaluator = "PixiEditor.Clipboard.PasteColorIcon")]
+    public void PasteColor(bool secondary)
     {
-        if (ParseAnyFormat(Clipboard.GetText().Trim(), out var result))
+        if (!ColorHelper.ParseAnyFormat(Clipboard.GetText().Trim(), out var result))
+        {
+            return;
+        }
+
+        if (!secondary)
         {
             Owner.ColorsSubViewModel.PrimaryColor = result.Value;
         }
+        else
+        {
+            Owner.ColorsSubViewModel.SecondaryColor = result.Value;
+        }
     }
 
     [Command.Basic("PixiEditor.Clipboard.Copy", "Copy", "Copy to clipboard", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.C, Modifiers = ModifierKeys.Control)]
@@ -52,6 +63,31 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
         ClipboardController.CopyToClipboard(doc);
     }
 
+    [Command.Basic("PixiEditor.Clipboard.CopyPrimaryColorAsHex", CopyColor.PrimaryHEX, "Copy primary color (HEX)", "Copy primary color as hex code", IconEvaluator = "PixiEditor.Clipboard.CopyColorIcon")]
+    [Command.Basic("PixiEditor.Clipboard.CopyPrimaryColorAsRgb", CopyColor.PrimaryRGB, "Copy primary color (RGB)", "Copy primary color as RGB code", IconEvaluator = "PixiEditor.Clipboard.CopyColorIcon")]
+    [Command.Basic("PixiEditor.Clipboard.CopySecondaryColorAsHex", CopyColor.SecondaryHEX, "Copy secondary color (HEX)", "Copy secondary color as hex code", IconEvaluator = "PixiEditor.Clipboard.CopyColorIcon")]
+    [Command.Basic("PixiEditor.Clipboard.CopySecondaryColorAsRgb", CopyColor.SecondardRGB, "Copy secondary color (RGB)", "Copy secondary color as RGB code", IconEvaluator = "PixiEditor.Clipboard.CopyColorIcon")]
+    public void CopyColorAsHex(CopyColor color)
+    {
+        var targetColor = color switch
+        {
+            CopyColor.PrimaryHEX or CopyColor.PrimaryRGB => Owner.ColorsSubViewModel.PrimaryColor,
+            _ => Owner.ColorsSubViewModel.SecondaryColor
+        };
+
+        string text = color switch
+        {
+            CopyColor.PrimaryHEX or CopyColor.SecondaryHEX => targetColor.A == 255
+                ? $"#{targetColor.R:X2}{targetColor.G:X2}{targetColor.B:X2}"
+                : targetColor.ToString(),
+            _ => targetColor.A == 255
+                ? $"rgb({targetColor.R},{targetColor.G},{targetColor.B})"
+                : $"rgba({targetColor.R},{targetColor.G},{targetColor.B},{targetColor.A})",
+        };
+
+        Clipboard.SetText(text);
+    }
+
     [Evaluator.CanExecute("PixiEditor.Clipboard.CanPaste")]
     public bool CanPaste()
     {
@@ -59,50 +95,37 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
     }
 
     [Evaluator.CanExecute("PixiEditor.Clipboard.CanPasteColor")]
-    public static bool CanPasteColor() => ParseAnyFormat(Clipboard.GetText().Trim(), out _);
+    public static bool CanPasteColor() => ColorHelper.ParseAnyFormat(Clipboard.GetText().Trim(), out _);
 
     [Evaluator.Icon("PixiEditor.Clipboard.PasteColorIcon")]
     public static ImageSource GetPasteColorIcon()
     {
         Color color;
 
-        if (ParseAnyFormat(Clipboard.GetText().Trim(), out var result))
-        {
-            color = result.Value.ToOpaqueMediaColor();
-        }
-        else
-        {
-            color = Colors.Transparent;
-        }
+        color = ColorHelper.ParseAnyFormat(Clipboard.GetText().Trim(), out var result) ? result.Value.ToOpaqueMediaColor() : Colors.Transparent;
 
         return ColorSearchResult.GetIcon(color.ToOpaqueColor());
     }
 
-    private static bool ParseAnyFormat(string value, [NotNullWhen(true)] out DrawingApi.Core.ColorsImpl.Color? result)
+    [Evaluator.Icon("PixiEditor.Clipboard.CopyColorIcon")]
+    public ImageSource GetCopyColorIcon(CommandSearchResult result)
     {
-        bool hex = Regex.IsMatch(Clipboard.GetText().Trim(), "^#?([a-fA-F0-9]{8}|[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$");
+        var color = (CopyColor)((Models.Commands.Commands.Command.BasicCommand)result.Command).Parameter;
 
-        if (hex)
+        var targetColor = color switch
         {
-            result = DrawingApi.Core.ColorsImpl.Color.Parse(Clipboard.GetText().Trim());
-            return true;
-        }
-
-        var match = Regex.Match(Clipboard.GetText().Trim(), @"(?:rgba?\(?)? *(?<r>\d{1,3})(?:, *| +)(?<g>\d{1,3})(?:, *| +)(?<b>\d{1,3})(?:(?:, *| +)(?<a>\d{0,3}))?\)?");
+            CopyColor.PrimaryHEX or CopyColor.PrimaryRGB => Owner.ColorsSubViewModel.PrimaryColor,
+            _ => Owner.ColorsSubViewModel.SecondaryColor
+        };
 
-        if (!match.Success)
-        {
-            result = null;
-            return false;
-        }
-
-        byte r = byte.Parse(match.Groups["r"].ValueSpan);
-        byte g = byte.Parse(match.Groups["g"].ValueSpan);
-        byte b = byte.Parse(match.Groups["b"].ValueSpan);
-        byte a = match.Groups["a"].Success ? byte.Parse(match.Groups["a"].ValueSpan) : (byte)255;
-
-        result = new DrawingApi.Core.ColorsImpl.Color(r, g, b, a);
-        return true;
+        return ColorSearchResult.GetIcon(targetColor.ToOpaqueMediaColor().ToOpaqueColor());
+    }
 
+    public enum CopyColor
+    {
+        PrimaryHEX,
+        PrimaryRGB,
+        SecondaryHEX,
+        SecondardRGB
     }
 }

+ 16 - 5
src/PixiEditor/Views/MainWindow.xaml.cs

@@ -6,6 +6,7 @@ using System.Windows.Media.Imaging;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Skia;
+using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.UserPreferences;
@@ -185,8 +186,16 @@ internal partial class MainWindow : Window
 
     private void MainWindow_Drop(object sender, DragEventArgs e)
     {
+        DataContext.ActionDisplays[nameof(MainWindow_Drop)] = null;
+        
         if (!e.Data.GetDataPresent(DataFormats.FileDrop))
         {
+            if (!ColorHelper.ParseAnyFormat(e.Data, out var color))
+            {
+                return;
+            }
+
+            DataContext.ColorsSubViewModel.PrimaryColor = color.Value;
             return;
         }
 
@@ -202,7 +211,14 @@ internal partial class MainWindow : Window
     {
         if (!ClipboardController.IsImage((DataObject)e.Data))
         {
+            if (ColorHelper.ParseAnyFormat(e.Data, out _))
+            {
+                DataContext.ActionDisplays[nameof(MainWindow_Drop)] = "Paste as primary color";
+                return;
+            }
+            
             e.Effects = DragDropEffects.None;
+            e.Handled = true;
             return;
         }
 
@@ -211,11 +227,6 @@ internal partial class MainWindow : Window
 
     private void MainWindow_DragLeave(object sender, DragEventArgs e)
     {
-        if (!e.Data.GetDataPresent(DataFormats.FileDrop))
-        {
-            return;
-        }
-
         DataContext.ActionDisplays[nameof(MainWindow_Drop)] = null;
     }
 }

+ 2 - 0
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml.cs

@@ -115,6 +115,8 @@ internal partial class LayersManager : UserControl
 
     private void Grid_Drop(object sender, DragEventArgs e)
     {
+        ViewModelMain.Current.ActionDisplays[nameof(LayersManager)] = null;
+        
         if (ActiveDocument == null)
         {
             return;

+ 2 - 0
src/PixiEditor/Views/UserControls/Palettes/PaletteViewer.xaml.cs

@@ -159,6 +159,8 @@ internal partial class PaletteViewer : UserControl
 
     private async void Grid_Drop(object sender, DragEventArgs e)
     {
+        ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] = null;
+        
         if (!IsSupportedFilePresent(e, out string filePath))
         {
             return;