Browse Source

PaletteViewer is somewhat working

Krzysztof Krysiński 1 year ago
parent
commit
65356a0839
21 changed files with 326 additions and 51 deletions
  1. 21 6
      src/PixiEditor.AvaloniaUI/Helpers/Converters/IndexToAssociatedKeyConverter.cs
  2. 5 3
      src/PixiEditor.AvaloniaUI/Helpers/Converters/NotNullToVisibilityConverter.cs
  3. 17 0
      src/PixiEditor.AvaloniaUI/Helpers/Converters/PaletteViewerWidthToVisibilityConverter.cs
  4. 3 1
      src/PixiEditor.AvaloniaUI/Helpers/PaletteHelpers.cs
  5. 149 0
      src/PixiEditor.AvaloniaUI/Helpers/UI/DragDropEvents.cs
  6. BIN
      src/PixiEditor.AvaloniaUI/Images/ChevronDown.png
  7. 4 0
      src/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj
  8. 1 0
      src/PixiEditor.AvaloniaUI/ViewModels/Dock/ColorPickerDockViewModel.cs
  9. 8 1
      src/PixiEditor.AvaloniaUI/ViewModels/Dock/DockFactory.cs
  10. 33 0
      src/PixiEditor.AvaloniaUI/ViewModels/Dock/PaletteViewerDockViewModel.cs
  11. 3 1
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/UpdateViewModel.cs
  12. 2 2
      src/PixiEditor.AvaloniaUI/Views/Dock/ColorPickerDockView.axaml
  13. 0 1
      src/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml
  14. 19 0
      src/PixiEditor.AvaloniaUI/Views/Dock/PaletteViewerDockView.axaml
  15. 14 0
      src/PixiEditor.AvaloniaUI/Views/Dock/PaletteViewerDockView.axaml.cs
  16. 0 1
      src/PixiEditor.AvaloniaUI/Views/MainView.axaml
  17. 1 1
      src/PixiEditor.AvaloniaUI/Views/Palettes/ColorReplacer.axaml
  18. 1 1
      src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml
  19. 17 12
      src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteViewer.axaml
  20. 27 20
      src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteViewer.axaml.cs
  21. 1 1
      src/PixiEditor/Helpers/Converters/PaletteViewerWidthToVisibilityConverter.cs

+ 21 - 6
src/PixiEditor.AvaloniaUI/Helpers/Converters/IndexToAssociatedKeyConverter.cs

@@ -1,18 +1,33 @@
-using System.Globalization;
+using System.Collections.Generic;
+using System.Globalization;
 using PixiEditor.AvaloniaUI.Helpers.Converters;
+using PixiEditor.Extensions.Palettes;
 
 namespace PixiEditor.Helpers.Converters;
 
-internal class IndexToAssociatedKeyConverter : SingleInstanceConverter<IndexToAssociatedKeyConverter>
+internal class IndexToAssociatedKeyConverter : SingleInstanceMultiValueConverter<IndexToAssociatedKeyConverter>
 {
     public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
-        if (value is int index and < 10)
+        return Convert(new List<object?> { value, parameter }, targetType, null, culture);
+    }
+
+    public override object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
+    {
+        if (values.Count != 2) return (int?)null;
+
+        if (values[0] is not PaletteColor paletteColor) return null;
+        if(values[1] is not IList<PaletteColor> paletteColors) return null;
+
+        int colIndex = paletteColors.IndexOf(paletteColor);
+
+        if (colIndex == -1) return null;
+        if (colIndex < 10)
         {
-            if (index == 9) return 0;
-            return (int?)index + 1;
+            if (colIndex == 9) return 0;
+            return (int?)colIndex + 1;
         }
 
-        return (int?)null;
+        return null;
     }
 }

+ 5 - 3
src/PixiEditor.AvaloniaUI/Helpers/Converters/NotNullToVisibilityConverter.cs

@@ -17,7 +17,7 @@ internal class NotNullToVisibilityConverter
             isNull = !isNull;
         }
 
-        return isNull ? false : true;
+        return !isNull;
     }
     
     bool IsDefaultValue(object obj)
@@ -29,11 +29,13 @@ internal class NotNullToVisibilityConverter
         
         var type = obj.GetType();
 
-        if (type.IsValueType)
+        //TODO: Try to find what breaks without below, because in my opinion this
+        // is not a correct thing to do with NotNull converter, lots with false positives, like 0 as a int
+        /*if (type.IsValueType)
         {
             object defaultValue = Activator.CreateInstance(type);
             return obj.Equals(defaultValue);
-        }
+        }*/
 
         return false;
     }

+ 17 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/PaletteViewerWidthToVisibilityConverter.cs

@@ -0,0 +1,17 @@
+using System.Globalization;
+
+namespace PixiEditor.AvaloniaUI.Helpers.Converters;
+
+internal class PaletteViewerWidthToVisibilityConverter : SingleInstanceConverter<PaletteViewerWidthToVisibilityConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        bool isCompact = value is double and < 100;
+        if (parameter is "False" or false)
+        {
+            return !isCompact;
+        }
+
+        return isCompact;
+    }
+}

+ 3 - 1
src/PixiEditor.AvaloniaUI/Helpers/PaletteHelpers.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.Linq;
 using Avalonia.Platform.Storage;
 using PixiEditor.Extensions.Palettes.Parsers;
 
@@ -15,7 +16,8 @@ internal static class PaletteHelpers
             List<string> allSupportedFormats = new();
             foreach (var parser in parsers)
             {
-                allSupportedFormats.AddRange(parser.SupportedFileExtensions);
+                allSupportedFormats.AddRange(parser.SupportedFileExtensions
+                    .Select(x => x.Replace(".", "*.")));
             }
 
             string allSupportedFormatsString = string.Join(';', allSupportedFormats).Replace(".", "*.");

+ 149 - 0
src/PixiEditor.AvaloniaUI/Helpers/UI/DragDropEvents.cs

@@ -0,0 +1,149 @@
+using Avalonia.Input;
+using Avalonia.Interactivity;
+
+namespace PixiEditor.AvaloniaUI.Helpers.UI;
+
+public delegate void DragEventHandler(object sender, DragEventArgs e);
+
+public static class DragDropEvents
+{
+    public static readonly RoutedEvent<DragEventArgs> DragEnterEvent =
+        RoutedEvent.Register<DragEventArgs>(
+            "DragEnter",
+            RoutingStrategies.Bubble,
+            typeof(DragDropEvents));
+
+
+    public static readonly RoutedEvent<DragEventArgs> DragLeaveEvent =
+        RoutedEvent.Register<DragEventArgs>(
+            "DragLeave",
+            RoutingStrategies.Bubble,
+            typeof(DragDropEvents));
+
+
+    public static readonly RoutedEvent<RoutedEventArgs> DragOverEvent =
+        RoutedEvent.Register<RoutedEventArgs>(
+            "DragOver",
+            RoutingStrategies.Bubble,
+            typeof(DragDropEvents));
+
+
+    public static readonly RoutedEvent<DragEventArgs> DropEvent =
+        RoutedEvent.Register<DragEventArgs>(
+            "Drop",
+            RoutingStrategies.Bubble,
+            typeof(DragDropEvents));
+
+    public static void AddDragEnterHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        var checkedHandler = WithCheck(control, handler);
+        control.AddHandler(
+            DragEnterEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+
+        control.AddHandler(
+            DragDrop.DragEnterEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+    }
+
+    public static void AddDragLeaveHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        var checkedHandler = WithCheck(control, handler);
+
+        control.AddHandler(
+            DragLeaveEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+
+        control.AddHandler(
+            DragDrop.DragLeaveEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+    }
+
+    public static void AddDragOverHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        var checkedHandler = WithCheck(control, handler);
+
+        control.AddHandler(
+            DragOverEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+
+        control.AddHandler(
+            DragDrop.DragOverEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+    }
+
+    public static void AddDropHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        var checkedHandler = WithCheck(control, handler);
+        control.AddHandler(
+            DropEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+
+        control.AddHandler(
+            DragDrop.DropEvent,
+            checkedHandler,
+            RoutingStrategies.Bubble);
+    }
+
+    public static void RemoveDragEnterHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        control.RemoveHandler(
+            DragEnterEvent,
+            handler);
+
+        control.RemoveHandler(
+            DragDrop.DragEnterEvent,
+            handler);
+    }
+
+    public static void RemoveDragLeaveHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        control.RemoveHandler(
+            DragLeaveEvent,
+            handler);
+
+        control.RemoveHandler(
+            DragDrop.DragLeaveEvent,
+            handler);
+    }
+
+    public static void RemoveDragOverHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        control.RemoveHandler(
+            DragOverEvent,
+            handler);
+
+        control.RemoveHandler(
+            DragDrop.DragOverEvent,
+            handler);
+    }
+
+    public static void RemoveDropHandler(Interactive control, EventHandler<DragEventArgs> handler)
+    {
+        control.RemoveHandler(
+            DropEvent,
+            handler);
+
+        control.RemoveHandler(
+            DragDrop.DropEvent,
+            handler);
+    }
+
+    private static EventHandler<T> WithCheck<T>(object source, EventHandler<T> handler) where T : RoutedEventArgs
+    {
+        return (sender, args) =>
+        {
+            if (args.Source != null && args.Source.Equals(source))
+            {
+                handler(sender, args);
+            }
+        };
+    }
+}

BIN
src/PixiEditor.AvaloniaUI/Images/ChevronDown.png


+ 4 - 0
src/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj

@@ -88,4 +88,8 @@
       <AdditionalFiles Include="Views\Windows\Settings\ShortcutsBinder.axaml" />
     </ItemGroup>
   
+    <ItemGroup>
+      <Resource Include="Images\ChevronDown.png" />
+    </ItemGroup>
+  
 </Project>

+ 1 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Dock/ColorPickerDockViewModel.cs

@@ -14,6 +14,7 @@ internal class ColorPickerDockViewModel : Tool
         get => GetValue(ColorsViewModelProperty);
         set => SetValue(ColorsViewModelProperty, value);
     }
+
     public ColorPickerDockViewModel(ColorsViewModel colorsVm)
     {
         ColorsViewModel = colorsVm;

+ 8 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/DockFactory.cs

@@ -5,6 +5,7 @@ using Dock.Model.Avalonia;
 using Dock.Model.Avalonia.Controls;
 using Dock.Model.Controls;
 using Dock.Model.Core;
+using PixiEditor.AvaloniaUI.Models.Palettes;
 using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
@@ -126,11 +127,17 @@ internal class DockFactory : Factory
             Title = "ColorPickerPane",
         };
 
+        PaletteViewerDockViewModel paletteViewerVm = new(colorsVm, fileVm.Owner.DocumentManagerSubViewModel)
+        {
+            Id = "PaletteViewerPane",
+            Title = "PaletteViewerPane",
+        };
+
         ToolDock colorPicker = new()
         {
             Id = "ColorPickerPane",
             Title = "ColorPickerPane",
-            VisibleDockables = new List<IDockable>() { colorPickerVm },
+            VisibleDockables = new List<IDockable>() { colorPickerVm, paletteViewerVm},
             ActiveDockable = colorPickerVm,
         };
 

+ 33 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Dock/PaletteViewerDockViewModel.cs

@@ -0,0 +1,33 @@
+using Avalonia;
+using Dock.Model.Avalonia.Controls;
+using PixiEditor.AvaloniaUI.ViewModels.Document;
+using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
+
+namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
+
+internal class PaletteViewerDockViewModel : Tool
+{
+    public static readonly StyledProperty<ColorsViewModel> ColorsViewModelProperty = AvaloniaProperty.Register<ColorPickerDockViewModel, ColorsViewModel>(
+        nameof(ColorsSubViewModel));
+
+    public ColorsViewModel ColorsSubViewModel
+    {
+        get => GetValue(ColorsViewModelProperty);
+        set => SetValue(ColorsViewModelProperty, value);
+    }
+
+    public static readonly StyledProperty<DocumentManagerViewModel> DocumentManagerSubViewModelProperty = AvaloniaProperty.Register<PaletteViewerDockViewModel, DocumentManagerViewModel>(
+        "DocumentManagerSubViewModel");
+
+    public DocumentManagerViewModel DocumentManagerSubViewModel
+    {
+        get => GetValue(DocumentManagerSubViewModelProperty);
+        set => SetValue(DocumentManagerSubViewModelProperty, value);
+    }
+
+    public PaletteViewerDockViewModel(ColorsViewModel colorsSubViewModel, DocumentManagerViewModel documentManagerViewModel)
+    {
+        ColorsSubViewModel = colorsSubViewModel;
+        DocumentManagerSubViewModel = documentManagerViewModel;
+    }
+}

+ 3 - 1
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/UpdateViewModel.cs

@@ -9,6 +9,7 @@ using Avalonia.Controls.ApplicationLifetimes;
 using PixiEditor.AvaloniaUI.Helpers;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Dialogs;
+using PixiEditor.AvaloniaUI.Views.Dialogs;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Common.UserPreferences;
 using PixiEditor.Platform;
@@ -135,7 +136,8 @@ internal class UpdateViewModel : SubViewModel<ViewModelMain>
                 {
                     ViewModelMain.Current.UpdateSubViewModel.UpdateReadyToInstall = true;
                     var result = ConfirmationDialog.Show("UPDATE_READY", "NEW_UPDATE");
-                    if (result == Models.Enums.ConfirmationType.Yes)
+                    result.Wait();
+                    if (result.Result == ConfirmationType.Yes)
                     {
                         if (updateFileExists && File.Exists(updaterPath))
                         {

+ 2 - 2
src/PixiEditor.AvaloniaUI/Views/Dock/ColorPickerDockView.axaml

@@ -7,7 +7,7 @@
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              x:Class="PixiEditor.AvaloniaUI.Views.Dock.ColorPickerDockView">
     <colorPicker:StandardColorPicker
-        SelectedColor="{Binding DataContext.ColorsViewModel.PrimaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
-        SecondaryColor="{Binding DataContext.ColorsViewModel.SecondaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
+        SelectedColor="{Binding DataContext.ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
+        SecondaryColor="{Binding DataContext.ColorsSubViewModel.SecondaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
         UseHintColor="False"/>
 </UserControl>

+ 0 - 1
src/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml

@@ -6,7 +6,6 @@
              xmlns:viewModels="clr-namespace:PixiEditor.ViewModels"
              xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
              xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
-             xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:document="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Document"
              xmlns:viewModels1="clr-namespace:PixiEditor.AvaloniaUI.ViewModels"
              xmlns:subViewModels="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.SubViewModels"

+ 19 - 0
src/PixiEditor.AvaloniaUI/Views/Dock/PaletteViewerDockView.axaml

@@ -0,0 +1,19 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:palettes="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
+             xmlns:cmds="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
+             xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.AvaloniaUI.Views.Dock.PaletteViewerDockView">
+    <palettes:PaletteViewer
+        IsEnabled="{Binding DocumentManagerSubViewModel.ActiveDocument, Converter={x:Static ObjectConverters.IsNotNull}}"
+        Colors="{Binding DocumentManagerSubViewModel.ActiveDocument.Palette}"
+        Swatches="{Binding DocumentManagerSubViewModel.ActiveDocument.Swatches}"
+        SelectColorCommand="{cmds:Command PixiEditor.Colors.SelectColor, UseProvided=True}"
+        HintColor="{Binding Path=ColorsSubViewModel.PrimaryColor,Converter={converters:GenericColorToMediaColorConverter}}"
+        PaletteProvider="{Binding ColorsSubViewModel.PaletteProvider}"
+        ImportPaletteCommand="{cmds:Command PixiEditor.Colors.ImportPalette, UseProvided=True}"
+        ReplaceColorsCommand="{cmds:Command PixiEditor.Colors.ReplaceColors, UseProvided=True}" />
+</UserControl>

+ 14 - 0
src/PixiEditor.AvaloniaUI/Views/Dock/PaletteViewerDockView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.AvaloniaUI.Views.Dock;
+
+public partial class PaletteViewerDockView : UserControl
+{
+    public PaletteViewerDockView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 0 - 1
src/PixiEditor.AvaloniaUI/Views/MainView.axaml

@@ -8,7 +8,6 @@
              xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
              xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"
              xmlns:viewModels="clr-namespace:PixiEditor.ViewModels"
-             xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:dock="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Dock"
              xmlns:zoombox="clr-namespace:PixiEditor.Zoombox;assembly=PixiEditor.Zoombox"
              xmlns:layers="clr-namespace:PixiEditor.AvaloniaUI.Views.Layers"

+ 1 - 1
src/PixiEditor.AvaloniaUI/Views/Palettes/ColorReplacer.axaml

@@ -45,7 +45,7 @@
                         </Button.Background>
                     </Button>
                 </StackPanel>
-                <CheckBox Focusable="False" IsChecked="{Binding ElementName=uc, Path=IsCollapsed}" Panel.ZIndex="10" Name="VisibilityCheckbox" Margin="0,0,5,0" Height="16" HorizontalAlignment="Right">
+                <CheckBox Focusable="False" IsChecked="{Binding ElementName=uc, Path=IsCollapsed}" ZIndex="10" Name="VisibilityCheckbox" Margin="0,0,5,0" Height="16" HorizontalAlignment="Right">
                     <!--<CheckBox.Triggers>
                         <EventTrigger RoutedEvent="CheckBox.Checked">
                             <BeginStoryboard>

+ 1 - 1
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml

@@ -36,7 +36,7 @@
         </Border>
         <Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="15" Margin="0 0 0 -1"
                 IsVisible="{Binding ElementName=uc, Path=AssociatedKey, Converter={converters:NotNullToVisibilityConverter}}"
-                Background="{StaticResource AccentColor}" CornerRadius="3.5 0 3.5 0">
+                Background="{DynamicResource ThemeBackground1Brush}" CornerRadius="3.5 0 3.5 0">
             <TextBlock Foreground="White" FontSize="16" HorizontalAlignment="Center" Margin="1 0 0 0"
                                         Text="{Binding AssociatedKey, ElementName=uc}"/>
         </Border>

+ 17 - 12
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteViewer.axaml

@@ -9,19 +9,20 @@
              xmlns:palettes="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              xmlns:decorators="clr-namespace:PixiEditor.AvaloniaUI.Views.Decorators"
+             xmlns:ui1="clr-namespace:PixiEditor.AvaloniaUI.Helpers.UI"
              d:DesignHeight="450" d:DesignWidth="300" Name="paletteControl">
     <DockPanel>
-        <palettes:ColorReplacer Grid.Row="3" VerticalAlignment="Bottom" x:Name="Replacer" DockPanel.Dock="Bottom"
+        <palettes:ColorReplacer Grid.Row="3" VerticalAlignment="Bottom" Name="Replacer" DockPanel.Dock="Bottom"
                                 ReplaceColorsCommand="{Binding ElementName=paletteControl, Path=ReplaceColorsCommand}"
                                 HintColor="{Binding ElementName=paletteControl, Path=HintColor}"/>
-        <Grid DragDrop.AllowDrop="True" PreviewDragEnter="Grid_PreviewDragEnter" PreviewDragLeave="Grid_PreviewDragLeave"
-          Drop="Grid_Drop">
+        <Grid DragDrop.AllowDrop="True" ui1:DragDropEvents.DragEnter="Grid_PreviewDragEnter" ui1:DragDropEvents.DragLeave="Grid_PreviewDragLeave"
+              ui1:DragDropEvents.Drop="Grid_Drop">
             <Grid.RowDefinitions>
                 <RowDefinition Height="37.5"/>
                 <RowDefinition Height="5"/>
                 <RowDefinition Height="*"/>
             </Grid.RowDefinitions>
-            <StackPanel Orientation="Vertical" Grid.Row="0" Background="{StaticResource MainColor}">
+            <StackPanel Orientation="Vertical" Grid.Row="0" Background="{DynamicResource ThemeBackgroundBrush}">
                 <DockPanel VerticalAlignment="Center" Margin="0 5 0 0">
                     <palettes:PaletteColorAdder DockPanel.Dock="Left" Margin="5 0 0 0"
                                             Swatches="{Binding ElementName=paletteControl, Path=Swatches}"
@@ -37,24 +38,24 @@
                                 </Button.Background>
                             </Button>
                         </decorators:AlwaysEnabled>
-                        <Button Margin="0, 0, 5, 0" Style="{StaticResource ToolButtonStyle}" 
+                        <Button Margin="0, 0, 5, 0" Classes="ToolButtonStyle"
                 Cursor="Hand" Height="24" Width="24" ui:Translator.TooltipKey="LOAD_PALETTE" Click="ImportPalette_OnClick">
                             <Button.Background>
                                 <ImageBrush Source="/Images/Folder.png"/>
                             </Button.Background>
                         </Button>
-                        <Button Height="24" Width="24" Margin="0, 0, 2.5, 0" Style="{StaticResource ToolButtonStyle}"
+                        <Button Height="24" Width="24" Margin="0, 0, 2.5, 0" Classes="ToolButtonStyle"
                                 IsEnabled="{Binding ElementName=paletteControl, Path=Colors.Count}"
                                 Cursor="Hand" ui:Translator.TooltipKey="SAVE_PALETTE" Click="SavePalette_OnClick">
                             <Button.Background>
                                 <ImageBrush Source="/Images/Save.png"/>
                             </Button.Background>
                         </Button>
-                        <Button Height="24" Width="24" Margin="0, 0, 5, 0" Style="{StaticResource ToolButtonStyle}"
+                        <Button Height="24" Width="24" Margin="0, 0, 5, 0" Classes="ToolButtonStyle"
                                 IsEnabled="{Binding ElementName=paletteControl, Path=Colors.Count}"
                                 Cursor="Hand" ui:Translator.TooltipKey="DISCARD_PALETTE" Click="DiscardPalette_OnClick">
                             <Button.Background>
-                                <ImageBrush ImageSource="/Images/Trash.png"/>
+                                <ImageBrush Source="/Images/Trash.png"/>
                             </Button.Background>
                         </Button>
                     </StackPanel>
@@ -79,11 +80,15 @@
                                                    ui:Translator.TooltipKey="PALETTE_COLOR_TOOLTIP"
                                                    DragDrop.AllowDrop="True" Color="{Binding}"
                                                Margin="2.5"
-                                            Drop="PaletteColor_Drop"
-                                            AssociatedKey="{Binding Path=(ItemsControl.AlternationIndex), 
-                RelativeSource={RelativeSource TemplatedParent}, Converter={converters:IndexToAssociatedKeyConverter}}">
+                                            ui1:DragDropEvents.Drop="PaletteColor_Drop">
+                                <palettes:PaletteColorControl.AssociatedKey>
+                                    <MultiBinding Converter="{converters:IndexToAssociatedKeyConverter}">
+                                        <Binding Path="." />
+                                        <Binding Path="Colors" ElementName="paletteControl" />
+                                    </MultiBinding>
+                                </palettes:PaletteColorControl.AssociatedKey>
                                 <Interaction.Behaviors>
-                                    <EventTriggerBehavior EventName="MouseLeftButtonUp">
+                                    <EventTriggerBehavior EventName="PointerReleased">
                                         <InvokeCommandAction
                                     Command="{Binding SelectColorCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type palettes:PaletteViewer}}}"
                                     CommandParameter="{Binding}" />

+ 27 - 20
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteViewer.axaml.cs

@@ -8,7 +8,9 @@ using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Interactivity;
 using Avalonia.Media;
+using Avalonia.Platform.Storage;
 using PixiEditor.AvaloniaUI.Helpers;
+using PixiEditor.AvaloniaUI.Helpers.Extensions;
 using PixiEditor.AvaloniaUI.Models.AppExtensions.Services;
 using PixiEditor.AvaloniaUI.Models.Dialogs;
 using PixiEditor.AvaloniaUI.Models.Structures;
@@ -116,23 +118,26 @@ internal partial class PaletteViewer : UserControl
 
     private async void ImportPalette_OnClick(object sender, RoutedEventArgs e)
     {
-        OpenFileDialog openFileDialog = new OpenFileDialog
+        await Application.Current.ForDesktopMainWindowAsync(async window =>
         {
-            Filter = PaletteHelpers.GetFilter(PaletteProvider.AvailableParsers, true),
-        };
-        if (openFileDialog.ShowDialog() == true)
-        {
-            await ImportPalette(openFileDialog.FileName);
-        }
+            var file = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
+            {
+                FileTypeFilter = PaletteHelpers.GetFilter(PaletteProvider.AvailableParsers, true),
+            });
+
+            if (file is null || file.Count == 0) return;
+
+            await ImportPalette(file[0].Path.AbsolutePath);
+        });
     }
 
-    private async Task ImportPalette(string fileName)
+    private async Task ImportPalette(string filePath)
     {
         var parser =
             PaletteProvider.AvailableParsers.FirstOrDefault(x =>
-                x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+                x.SupportedFileExtensions.Contains(Path.GetExtension(filePath)));
         if (parser == null) return;
-        var data = await parser.Parse(fileName);
+        var data = await parser.Parse(filePath);
         if (data.IsCorrupted || data.Colors.Length == 0) return;
         Colors.Clear();
         Colors.AddRange(data.Colors);
@@ -140,15 +145,17 @@ internal partial class PaletteViewer : UserControl
 
     private async void SavePalette_OnClick(object sender, RoutedEventArgs e)
     {
-        SaveFileDialog saveFileDialog = new SaveFileDialog
+        await Application.Current.ForDesktopMainWindowAsync(async window =>
         {
-            Filter = PaletteHelpers.GetFilter(PaletteProvider.AvailableParsers.Where(x => x.CanSave).ToList(),
-                false)
-        };
+            var file = await window.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions()
+            {
+                FileTypeChoices = PaletteHelpers.GetFilter(
+                    PaletteProvider.AvailableParsers.Where(x => x.CanSave).ToList(), false)
+            });
 
-        if (saveFileDialog.ShowDialog() == true)
-        {
-            string fileName = saveFileDialog.Pa;
+            if (file is null) return;
+
+            string fileName = file.Name;
             var foundParser =
                 PaletteProvider.AvailableParsers.First(x =>
                     x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
@@ -163,7 +170,7 @@ internal partial class PaletteViewer : UserControl
             {
                 NoticeDialog.Show("COULD_NOT_SAVE_PALETTE", "ERROR");
             }
-        }
+        });
     }
 
     private void Grid_PreviewDragEnter(object sender, DragEventArgs e)
@@ -266,7 +273,7 @@ internal partial class PaletteViewer : UserControl
         MenuItem menuItem = (MenuItem)sender;
         PaletteColor color = (PaletteColor)menuItem.CommandParameter;
         Replacer.ColorToReplace = color;
-        Replacer.IsVisibleCheckbox.IsChecked = false;
+        Replacer.VisibilityCheckbox.IsChecked = false;
     }
 
     private void MenuItem_OnClick(object sender, RoutedEventArgs e)
@@ -278,7 +285,7 @@ internal partial class PaletteViewer : UserControl
         }
     }
 
-    private async Task DiscardPalette_OnClick(object sender, RoutedEventArgs e)
+    private async void DiscardPalette_OnClick(object sender, RoutedEventArgs e)
     {
         if (await ConfirmationDialog.Show("DISCARD_PALETTE_CONFIRMATION", "DISCARD_PALETTE") == ConfirmationType.Yes)
         {

+ 1 - 1
src/PixiEditor/Helpers/Converters/PaletteViewerWidthToVisibilityConverter.cs

@@ -8,7 +8,7 @@ internal class PaletteViewerWidthToVisibilityConverter : SingleInstanceConverter
     public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     {
         bool isCompact = value is double and < 100;
-        if (parameter is string and "Hidden")
+        if (parameter is "Hidden")
         {
             return isCompact ? Visibility.Hidden : Visibility.Visible;
         }