Browse Source

More palette controls wip

Krzysztof Krysiński 1 year ago
parent
commit
b1e20e20e5

+ 18 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/IndexToAssociatedKeyConverter.cs

@@ -0,0 +1,18 @@
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class IndexToAssociatedKeyConverter : SingleInstanceConverter<IndexToAssociatedKeyConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is int index and < 10)
+        {
+            if (index == 9) return 0;
+            return (int?)index + 1;
+        }
+
+        return (int?)null;
+    }
+}

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

@@ -88,12 +88,4 @@
       <AdditionalFiles Include="Views\Windows\Settings\ShortcutsBinder.axaml" />
     </ItemGroup>
   
-    <ItemGroup>
-      <AvaloniaXaml Include="Views\Palettes\PaletteViewer.axaml">
-        <Generator>MSBuild:Compile</Generator>
-        <XamlRuntime>Wpf</XamlRuntime>
-        <SubType>Designer</SubType>
-      </AvaloniaXaml>
-    </ItemGroup>
-  
 </Project>

+ 14 - 0
src/PixiEditor.AvaloniaUI/Views/Decorators/AlwaysEnabled.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+
+namespace PixiEditor.AvaloniaUI.Views.Decorators;
+
+public class AlwaysEnabled : ContentControl
+{
+    static AlwaysEnabled()
+    {
+        IsEnabledProperty.OverrideMetadata(
+            typeof(AlwaysEnabled), /*TODO: Validate if coerce is needed*/
+            new StyledPropertyMetadata<bool>(true, coerce: (_, x) => x));
+    }
+}

+ 3 - 2
src/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml

@@ -11,6 +11,7 @@
              xmlns:viewModels1="clr-namespace:PixiEditor.AvaloniaUI.ViewModels"
              xmlns:subViewModels="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.SubViewModels"
              xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+             xmlns:palettes1="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              x:Class="PixiEditor.AvaloniaUI.Views.Dock.DocumentTemplate">
     <userControls:Viewport
@@ -76,7 +77,7 @@
                                                                             </ItemsControl.ItemsPanel>
                                                                             <ItemsControl.ItemTemplate>
                                                                                 <DataTemplate>
-                                                                                    <palettes:PaletteColorControl Cursor="Hand" CornerRadius="0"
+                                                                                    <palettes1:PaletteColorControl Cursor="Hand" CornerRadius="0"
                                                                                         ui:Translator.TooltipKey="CLICK_SELECT_PRIMARY"
                                                                                         Width="22" Height="22" Color="{Binding}">
                                                                                         <Interaction.Behaviors>
@@ -92,7 +93,7 @@
                                                                                                      AncestorType={x:Type ContextMenu}}}" />
                                                                                             </EventTriggerBehavior>
                                                                                         </Interaction.Behaviors>
-                                                                                    </palettes:PaletteColorControl>
+                                                                                    </palettes1:PaletteColorControl>
                                                                                 </DataTemplate>
                                                                             </ItemsControl.ItemTemplate>
                                                                         </ItemsControl>

+ 92 - 0
src/PixiEditor.AvaloniaUI/Views/Palettes/ColorReplacer.axaml

@@ -0,0 +1,92 @@
+<UserControl x:Class="PixiEditor.AvaloniaUI.Views.Palettes.ColorReplacer"
+             x:ClassModifier="internal"
+             xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             xmlns:behaviours="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Behaviours"
+             xmlns:markupExtensions="clr-namespace:PixiEditor.AvaloniaUI.Helpers.MarkupExtensions"
+             xmlns:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker.AvaloniaUI"
+             xmlns:palettes="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
+             Name="uc">
+    <Border BorderBrush="{DynamicResource ThemeBorderMidColor}"
+            Background="{DynamicResource ThemeBackgroundColor}"
+            BorderThickness="0 2 0 0" MinWidth="60" Focusable="True">
+        <Interaction.Behaviors>
+            <behaviours:ClearFocusOnClickBehavior/>
+        </Interaction.Behaviors>
+        <Grid>
+            <Grid Grid.Row="0"  VerticalAlignment="Center">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*"/>
+                </Grid.ColumnDefinitions>
+                <Grid Grid.ColumnSpan="2" Grid.RowSpan="2">
+                    <Grid IsVisible="{Binding ElementName=VisibilityCheckbox, Path=!IsChecked}"  Background="Transparent"/>
+                </Grid>
+                <StackPanel Name="MiddleStackPanel" Height="40" Orientation="Horizontal" HorizontalAlignment="Center">
+                    <!--TODO: Drop PaletteColorControl_OnDrop-->
+                    <palettes:PaletteColorControl Color="{Binding ElementName=uc, Path=ColorToReplace}"
+                                               Height="35"
+                                               Width="35"
+                                               ui:Translator.TooltipKey="REPLACER_TOOLTIP"
+                                               DragDrop.AllowDrop="True" />
+                    <Image Source="/Images/Arrow-right.png" Height="20" Width="20" Margin="10 0" FlowDirection="{markupExtensions:Localization FlowDirection}"/>
+                    <colorPicker:PortableColorPicker
+                        UseHintColor="True"
+                        SelectedColor="{Binding ElementName=uc, Path=NewColor, Mode=TwoWay}"
+                        HintColor="{Binding ElementName=uc, Path=HintColor}"
+                        Height="37"
+                        Width="37" Focusable="False" Margin="0 0 10 0"
+                        ui:Translator.TooltipKey="CLICK_TO_CHOOSE_COLOR"
+                        ShowAlpha="False"/>
+                    <Button Click="ReplaceButton_OnClick" ui:Translator.TooltipKey="REPLACE_COLOR"
+                            Classes="ToolButtonStyle" Cursor="Hand" Height="20" Width="20">
+                        <Button.Background>
+                            <ImageBrush Source="/Images/Replace.png"/>
+                        </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.Triggers>
+                        <EventTrigger RoutedEvent="CheckBox.Checked">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation Storyboard.TargetName="MiddleStackPanel" Storyboard.TargetProperty="Height" From="40" To="0" Duration="0:0:0.15"/>
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                        <EventTrigger RoutedEvent="CheckBox.Unchecked">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation Storyboard.TargetName="MiddleStackPanel" Storyboard.TargetProperty="Height" From="0" To="40" Duration="0:0:0.15"/>
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+
+                    </CheckBox.Triggers>-->
+                    <CheckBox.Template>
+                        <ControlTemplate TargetType="{x:Type CheckBox}">
+                            <StackPanel Orientation="Horizontal" Focusable="False">
+                                <Image Focusable="False" Width="14" Cursor="Hand" x:Name="checkboxImage" Source="/Images/ChevronDown.png">
+                                    <Image.RenderTransform>
+                                        <RotateTransform Angle="0"/>
+                                    </Image.RenderTransform>
+                                </Image>
+                                <ContentPresenter Focusable="False"/>
+                            </StackPanel>
+                            <!--TODO: Write to Avalonia-->
+                            <!--<ControlTemplate.Triggers>
+                                <Trigger Property="IsChecked" Value="True">
+                                    <Setter TargetName="checkboxImage" Property="RenderTransform">
+                                        <Setter.Value>
+                                            <RotateTransform Angle="180" CenterX="7" CenterY="4"/>
+                                        </Setter.Value>
+                                    </Setter>
+                                </Trigger>
+                            </ControlTemplate.Triggers>-->
+                        </ControlTemplate>
+                    </CheckBox.Template>
+                </CheckBox>
+            </Grid>
+        </Grid>
+    </Border>
+</UserControl>

+ 103 - 0
src/PixiEditor.AvaloniaUI/Views/Palettes/ColorReplacer.axaml.cs

@@ -0,0 +1,103 @@
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Media;
+using PixiEditor.Extensions.Palettes;
+
+namespace PixiEditor.AvaloniaUI.Views.Palettes;
+
+internal partial class ColorReplacer : UserControl
+{
+    public static readonly StyledProperty<PaletteColor> ColorToReplaceProperty =
+        AvaloniaProperty.Register<ColorReplacer, PaletteColor>(
+            nameof(ColorToReplace),
+            PaletteColor.White);
+
+    public PaletteColor ColorToReplace
+    {
+        get => GetValue(ColorToReplaceProperty);
+        set => SetValue(ColorToReplaceProperty, value);
+    }
+
+    public static readonly StyledProperty<Color> HintColorProperty =
+        AvaloniaProperty.Register<ColorReplacer, Color>(
+            nameof(HintColor),
+            Colors.Black);
+
+    public Color HintColor
+    {
+        get => GetValue(HintColorProperty);
+        set => SetValue(HintColorProperty, value);
+    }
+
+    public static readonly StyledProperty<Color> NewColorProperty =
+        AvaloniaProperty.Register<ColorReplacer, Color>(
+            nameof(NewColor),
+            Colors.Black);
+
+    public Color NewColor
+    {
+        get => GetValue(NewColorProperty);
+        set => SetValue(NewColorProperty, value);
+    }
+
+    public static readonly StyledProperty<ICommand> ReplaceColorsCommandProperty =
+        AvaloniaProperty.Register<ColorReplacer, ICommand>(
+            nameof(ReplaceColorsCommand),
+            default(ICommand));
+
+    public ICommand ReplaceColorsCommand
+    {
+        get => GetValue(ReplaceColorsCommandProperty);
+        set => SetValue(ReplaceColorsCommandProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IsCollapsedProperty =
+        AvaloniaProperty.Register<ColorReplacer, bool>(
+            nameof(IsCollapsed),
+            false);
+
+    public bool IsCollapsed
+    {
+        get => GetValue(IsCollapsedProperty);
+        set => SetValue(IsCollapsedProperty, value);
+    }
+
+    private void PaletteColorControl_OnDrop(object sender, DragEventArgs e)
+    {
+        if (e.Data.Contains(PaletteColorControl.PaletteColorDaoFormat))
+        {
+            string hex = (string)e.Data.Get(PaletteColorControl.PaletteColorDaoFormat);
+            if (hex is null)
+            {
+                return;
+            }
+
+            ColorToReplace = PaletteColor.Parse(hex);
+        }
+    }
+
+    public ColorReplacer()
+    {
+        InitializeComponent();
+    }
+
+    private void ReplaceButton_OnClick(object sender, RoutedEventArgs e)
+    {
+        PaletteColor first = ColorToReplace;
+        Color rawSecond = NewColor;
+
+        PaletteColor second = new PaletteColor(rawSecond.R, rawSecond.G, rawSecond.B);
+
+        var pack = (first, second);
+        if (ReplaceColorsCommand.CanExecute(pack))
+        {
+            ReplaceColorsCommand.Execute(pack);
+        }
+
+        ColorToReplace = second;
+        NewColor = new Color(255, first.R, first.G, first.B);
+    }
+}

+ 35 - 0
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorAdder.axaml

@@ -0,0 +1,35 @@
+<UserControl x:Class="PixiEditor.AvaloniaUI.Views.Palettes.PaletteColorAdder"
+             x:ClassModifier="internal"
+             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:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker.AvaloniaUI"
+             xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             mc:Ignorable="d" Name="paletteColorAdder"
+             d:DesignHeight="36" d:DesignWidth="120">
+    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
+        <colorPicker:PortableColorPicker
+            ColorChanged="PortableColorPicker_ColorChanged"
+            SelectedColor="{Binding SelectedColor, ElementName=paletteColorAdder, Mode=TwoWay}"
+            UseHintColor="True" HintColor="{Binding ElementName=paletteColorAdder, Path=HintColor}"
+            Width="50" Focusable="False" Margin="0 0 10 0"
+            ShowAlpha="False"/>
+        <Button Name="AddButton" Margin="0" Width="24" Height="24" 
+                Classes="ToolButtonStyle"
+                ui:Translator.TooltipKey="ADD_COLOR_TO_PALETTE"
+                Cursor="Hand" Click="Button_Click">
+            <Button.Background>
+                <ImageBrush Source="/Images/Plus-square.png"/>
+            </Button.Background>
+        </Button>
+        <Button Name="AddFromSwatches" Margin="10 2 0 0" Width="24" Height="24" 
+                Classes="ToolButtonStyle"
+                ui:Translator.TooltipKey="ADD_FROM_SWATCHES"
+                Cursor="Hand" Click="AddFromSwatches_OnClick">
+            <Button.Background>
+                <ImageBrush Source="/Images/CopyAdd.png"/>
+            </Button.Background>
+        </Button>
+    </StackPanel>
+</UserControl>

+ 150 - 0
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorAdder.axaml.cs

@@ -0,0 +1,150 @@
+using System.Collections.Specialized;
+using System.Linq;
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Media;
+using PixiEditor.AvaloniaUI.Models.Structures;
+using PixiEditor.Extensions.Palettes;
+
+namespace PixiEditor.AvaloniaUI.Views.Palettes;
+
+internal partial class PaletteColorAdder : UserControl
+{
+    public static readonly StyledProperty<Color> HintColorProperty =
+        AvaloniaProperty.Register<PaletteColorAdder, Color>(
+            nameof(HintColor),
+            Avalonia.Media.Colors.Transparent);
+
+    public Color HintColor
+    {
+        get => GetValue(HintColorProperty);
+        set => SetValue(HintColorProperty, value);
+    }
+
+    public static readonly StyledProperty<ObservableRangeCollection<PaletteColor>> SwatchesProperty =
+        AvaloniaProperty.Register<PaletteColorAdder, ObservableRangeCollection<PaletteColor>>(
+            nameof(Swatches),
+            default(ObservableRangeCollection<PaletteColor>));
+
+    public ObservableRangeCollection<PaletteColor> Swatches
+    {
+        get => GetValue(SwatchesProperty);
+        set => SetValue(SwatchesProperty, value);
+    }
+
+    public static readonly StyledProperty<Color> SelectedColorProperty =
+        AvaloniaProperty.Register<PaletteColorAdder, Color>(
+            nameof(SelectedColor),
+            Avalonia.Media.Colors.Black);
+
+    public Color SelectedColor
+    {
+        get => GetValue(SelectedColorProperty);
+        set => SetValue(SelectedColorProperty, value);
+    }
+
+    public static readonly StyledProperty<ObservableRangeCollection<PaletteColor>> ColorsProperty =
+        AvaloniaProperty.Register<PaletteColorAdder, ObservableRangeCollection<PaletteColor>>(
+            nameof(Colors));
+
+    public ObservableRangeCollection<PaletteColor> Colors
+    {
+        get => GetValue(ColorsProperty);
+        set => SetValue(ColorsProperty, value);
+    }
+
+    static PaletteColorAdder()
+    {
+        ColorsProperty.Changed.Subscribe(OnColorsChanged);
+        SwatchesProperty.Changed.Subscribe(OnSwatchesChanged);
+    }
+
+    private void Colors_CollectionChanged(object sender,
+        NotifyCollectionChangedEventArgs e)
+    {
+        UpdateAddSwatchesButton();
+        UpdateAddButton();
+    }
+
+    private void UpdateAddButton()
+    {
+        AddButton.IsEnabled = !Colors.Contains(ToPaletteColor(SelectedColor)) && SelectedColor.A == 255;
+    }
+
+    private static void OnColorsChanged(AvaloniaPropertyChangedEventArgs<ObservableRangeCollection<PaletteColor>> e)
+    {
+        PaletteColorAdder adder = (PaletteColorAdder)e.Sender;
+        if (adder == null || adder.Colors == null) return;
+        if (e.NewValue != null)
+        {
+            adder.UpdateAddButton();
+            adder.Colors.CollectionChanged += adder.Colors_CollectionChanged;
+        }
+        else if (e.OldValue != null)
+        {
+            adder.Colors.CollectionChanged -= adder.Colors_CollectionChanged;
+        }
+    }
+
+    private static void OnSwatchesChanged(AvaloniaPropertyChangedEventArgs<ObservableRangeCollection<PaletteColor>> e)
+    {
+        PaletteColorAdder adder = (PaletteColorAdder)e.Sender;
+        if (adder == null || adder.Swatches == null) return;
+        if (e.NewValue != null)
+        {
+            adder.UpdateAddSwatchesButton();
+            adder.Swatches.CollectionChanged += adder.Swatches_CollectionChanged;
+        }
+        else if (e.OldValue != null)
+        {
+            adder.Swatches.CollectionChanged -= adder.Swatches_CollectionChanged;
+        }
+    }
+
+    private void Swatches_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+    {
+        UpdateAddSwatchesButton();
+    }
+
+    private void UpdateAddSwatchesButton()
+    {
+        AddFromSwatches.IsEnabled = Swatches != null && Swatches.Any(x => !Colors.Contains(x));
+    }
+
+    public PaletteColorAdder()
+    {
+        InitializeComponent();
+    }
+
+    private void Button_Click(object sender, RoutedEventArgs e)
+    {
+        PaletteColor color = ToPaletteColor(SelectedColor);
+        if (!Colors.Contains(color))
+        {
+            Colors.Add(color);
+            AddButton.IsEnabled = false;
+        }
+    }
+
+    private void PortableColorPicker_ColorChanged(object sender, RoutedEventArgs e) =>
+        AddButton.IsEnabled = !Colors.Contains(ToPaletteColor(SelectedColor));
+
+    private static PaletteColor ToPaletteColor(Color color) => new PaletteColor(color.R, color.G, color.B);
+
+    private void AddFromSwatches_OnClick(object sender, RoutedEventArgs e)
+    {
+        if (Swatches == null) return;
+
+        foreach (var color in Swatches)
+        {
+            if (!Colors.Contains(color))
+            {
+                Colors.Add(color);
+            }
+        }
+
+        AddFromSwatches.IsEnabled = false;
+    }
+}

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

@@ -1,11 +1,11 @@
-<UserControl x:Class="PixiEditor.Views.UserControls.Palettes.PaletteColorControl"
+<UserControl x:Class="PixiEditor.AvaloniaUI.Views.Palettes.PaletteColorControl"
              x:ClassModifier="internal"
              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.Views.UserControls.Palettes"
              xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+             xmlns:palettes1="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
              mc:Ignorable="d" 
              d:DesignHeight="45" d:DesignWidth="45" 
              x:Name="uc" 
@@ -13,7 +13,7 @@
              PointerMoved="PaletteColor_OnMouseMove"
              PointerReleased="PaletteColor_OnMouseUp">
     <UserControl.Styles>
-        <Style Selector="palettes|PaletteColorControl">
+        <Style Selector="palettes1|PaletteColorControl">
             <Setter Property="Width" Value="36"/>
             <Setter Property="Height" Value="36"/>
         </Style>

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

@@ -3,7 +3,7 @@ using Avalonia.Controls;
 using Avalonia.Input;
 using PixiEditor.Extensions.Palettes;
 
-namespace PixiEditor.Views.UserControls.Palettes;
+namespace PixiEditor.AvaloniaUI.Views.Palettes;
 
 internal partial class PaletteColorControl : UserControl
 {

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

@@ -1,20 +1,20 @@
-<UserControl x:Class="PixiEditor.Views.UserControls.Palettes.PaletteViewer"
+<UserControl x:Class="PixiEditor.AvaloniaUI.Views.Palettes.PaletteViewer"
              x:ClassModifier="internal"
              xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
-             xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
-             xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
-             xmlns:helpers="clr-namespace:PixiEditor.Helpers"
              xmlns:views="clr-namespace:PixiEditor.Views"
              xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             xmlns:palettes="clr-namespace:PixiEditor.AvaloniaUI.Views.Palettes"
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             xmlns:decorators="clr-namespace:PixiEditor.AvaloniaUI.Views.Decorators"
              d:DesignHeight="450" d:DesignWidth="300" Name="paletteControl">
     <DockPanel>
         <palettes:ColorReplacer Grid.Row="3" VerticalAlignment="Bottom" x:Name="Replacer" DockPanel.Dock="Bottom"
                                 ReplaceColorsCommand="{Binding ElementName=paletteControl, Path=ReplaceColorsCommand}"
                                 HintColor="{Binding ElementName=paletteControl, Path=HintColor}"/>
-        <Grid AllowDrop="True" PreviewDragEnter="Grid_PreviewDragEnter" PreviewDragLeave="Grid_PreviewDragLeave"
+        <Grid DragDrop.AllowDrop="True" PreviewDragEnter="Grid_PreviewDragEnter" PreviewDragLeave="Grid_PreviewDragLeave"
           Drop="Grid_Drop">
             <Grid.RowDefinitions>
                 <RowDefinition Height="37.5"/>
@@ -28,26 +28,26 @@
                                             HintColor="{Binding ElementName=paletteControl, Path=HintColor}"
                                             Colors="{Binding ElementName=paletteControl, Path=Colors}"/>
                     <StackPanel Margin="0, 0, 5, 0" HorizontalAlignment="Right" Width="110" VerticalAlignment="Center" Orientation="Horizontal">
-                        <local:AlwaysEnabled>
+                        <decorators:AlwaysEnabled>
                             <Button Margin="0, 0, 5, 0"
-                                    Style="{StaticResource ToolButtonStyle}" Click="BrowsePalettes_Click"
+                                    Classes="ToolButtonStyle" Click="BrowsePalettes_Click"
                                     Cursor="Hand" Height="24" Width="24" ui:Translator.TooltipKey="BROWSE_PALETTES">
                                 <Button.Background>
-                                    <ImageBrush ImageSource="/Images/Database.png"/>
+                                    <ImageBrush Source="/Images/Database.png"/>
                                 </Button.Background>
                             </Button>
-                        </local:AlwaysEnabled>
+                        </decorators:AlwaysEnabled>
                         <Button Margin="0, 0, 5, 0" Style="{StaticResource ToolButtonStyle}" 
                 Cursor="Hand" Height="24" Width="24" ui:Translator.TooltipKey="LOAD_PALETTE" Click="ImportPalette_OnClick">
                             <Button.Background>
-                                <ImageBrush ImageSource="/Images/Folder.png"/>
+                                <ImageBrush Source="/Images/Folder.png"/>
                             </Button.Background>
                         </Button>
                         <Button Height="24" Width="24" Margin="0, 0, 2.5, 0" Style="{StaticResource ToolButtonStyle}"
                                 IsEnabled="{Binding ElementName=paletteControl, Path=Colors.Count}"
                                 Cursor="Hand" ui:Translator.TooltipKey="SAVE_PALETTE" Click="SavePalette_OnClick">
                             <Button.Background>
-                                <ImageBrush ImageSource="/Images/Save.png"/>
+                                <ImageBrush Source="/Images/Save.png"/>
                             </Button.Background>
                         </Button>
                         <Button Height="24" Width="24" Margin="0, 0, 5, 0" Style="{StaticResource ToolButtonStyle}"
@@ -61,22 +61,12 @@
                 </DockPanel>
             </StackPanel>
             <Separator Grid.Row="1" Margin="0, 0, 0, 0" BorderBrush="{StaticResource DarkerAccentColor}" BorderThickness="2" />
-            <Grid Visibility="Hidden" Background="{StaticResource AccentColor}" Opacity="0.7" Grid.Row="2" Name="dragDropGrid">
+            <Grid IsVisible="False" Background="{StaticResource AccentColor}" Opacity="0.7" Grid.Row="2" Name="dragDropGrid">
                 <TextBlock TextWrapping="Wrap" ui:Translator.Key="DROP_PALETTE" Foreground="White" FontSize="32" HorizontalAlignment="Center" VerticalAlignment="Center"/>
             </Grid>
             <ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
-                <ItemsControl ItemsSource="{Binding Colors, ElementName=paletteControl}" AlternationCount="9999">
-                    <d:ItemsControl.ItemsSource>
-                        <x:Array Type="{x:Type Color}">
-                            <Color R="0" G="0" B="0" A="255"/>
-                            <Color R="255" G="255" B="255" A="255"/>
-                            <Color R="255" G="255" B="255" A="150"/>
-                            <Color R="255" G="255" B="255" A="0"/>
-                            <Color R="255" G="0" B="0" A="255"/>
-                            <Color R="0" G="255" B="0" A="255"/>
-                            <Color R="0" G="0" B="255" A="255"/>
-                        </x:Array>
-                    </d:ItemsControl.ItemsSource>
+                <!--TODO: Alternation count was here-->
+                <ItemsControl ItemsSource="{Binding Colors, ElementName=paletteControl}">
                     <ItemsControl.ItemsPanel>
                         <ItemsPanelTemplate>
                             <WrapPanel Margin="10" Orientation="Horizontal"
@@ -87,18 +77,18 @@
                         <DataTemplate>
                             <palettes:PaletteColorControl Cursor="Hand"
                                                    ui:Translator.TooltipKey="PALETTE_COLOR_TOOLTIP"
-                                                   AllowDrop="True" Color="{Binding}"
+                                                   DragDrop.AllowDrop="True" Color="{Binding}"
                                                Margin="2.5"
                                             Drop="PaletteColor_Drop"
                                             AssociatedKey="{Binding Path=(ItemsControl.AlternationIndex), 
                 RelativeSource={RelativeSource TemplatedParent}, Converter={converters:IndexToAssociatedKeyConverter}}">
-                                <b:Interaction.Triggers>
-                                    <b:EventTrigger EventName="MouseLeftButtonUp">
-                                        <b:InvokeCommandAction
+                                <Interaction.Behaviors>
+                                    <EventTriggerBehavior EventName="MouseLeftButtonUp">
+                                        <InvokeCommandAction
                                     Command="{Binding SelectColorCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type palettes:PaletteViewer}}}"
                                     CommandParameter="{Binding}" />
-                                    </b:EventTrigger>
-                                </b:Interaction.Triggers>
+                                    </EventTriggerBehavior>
+                                </Interaction.Behaviors>
                                 <palettes:PaletteColorControl.ContextMenu>
                                     <ContextMenu>
                                         <MenuItem ui:Translator.Key="CHOOSE" Foreground="White" Click="MenuItem_OnClick"

+ 89 - 64
src/PixiEditor.AvaloniaUI/Views/Palettes/PaletteViewer.axaml.cs

@@ -1,87 +1,104 @@
-using System.IO;
-using System.Windows;
-using System.Windows.Controls;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
 using System.Windows.Input;
-using System.Windows.Media;
-using Microsoft.Win32;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Media;
+using PixiEditor.AvaloniaUI.Helpers;
+using PixiEditor.AvaloniaUI.Models.AppExtensions.Services;
+using PixiEditor.AvaloniaUI.Models.Dialogs;
+using PixiEditor.AvaloniaUI.Models.Structures;
+using PixiEditor.AvaloniaUI.ViewModels;
+using PixiEditor.AvaloniaUI.Views.Dialogs;
+using PixiEditor.AvaloniaUI.Views.Windows;
 using PixiEditor.Extensions.Palettes;
-using PixiEditor.Extensions.Palettes.Parsers;
-using PixiEditor.Helpers;
-using PixiEditor.Models.AppExtensions.Services;
-using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.DataProviders;
-using PixiEditor.Models.Dialogs;
-using PixiEditor.Models.Enums;
 using PixiEditor.Models.IO;
-using PixiEditor.Views.Dialogs;
 
-namespace PixiEditor.Views.UserControls.Palettes;
+namespace PixiEditor.AvaloniaUI.Views.Palettes;
 
 /// <summary>
 /// Interaction logic for Palette.xaml
 /// </summary>
 internal partial class PaletteViewer : UserControl
 {
-    public static readonly DependencyProperty SwatchesProperty = DependencyProperty.Register(nameof(Swatches), typeof(WpfObservableRangeCollection<PaletteColor>), typeof(PaletteViewer), new PropertyMetadata(default(WpfObservableRangeCollection<PaletteColorControl>)));
+    public static readonly StyledProperty<ObservableRangeCollection<PaletteColor>> SwatchesProperty =
+        AvaloniaProperty.Register<PaletteViewer, ObservableRangeCollection<PaletteColor>>(
+            nameof(Swatches),
+            default(ObservableRangeCollection<PaletteColor>));
 
-    public WpfObservableRangeCollection<PaletteColor> Swatches
+    public ObservableRangeCollection<PaletteColor> Swatches
     {
-        get => (WpfObservableRangeCollection<PaletteColor>)GetValue(SwatchesProperty);
+        get => GetValue(SwatchesProperty);
         set => SetValue(SwatchesProperty, value);
     }
-    public static readonly DependencyProperty ColorsProperty = DependencyProperty.Register(nameof(Colors), typeof(WpfObservableRangeCollection<PaletteColor>), typeof(PaletteViewer));
 
-    public WpfObservableRangeCollection<PaletteColor> Colors
+    public static readonly StyledProperty<ObservableRangeCollection<PaletteColor>> ColorsProperty =
+        AvaloniaProperty.Register<PaletteViewer, ObservableRangeCollection<PaletteColor>>(
+            nameof(Colors));
+
+    public ObservableRangeCollection<PaletteColor> Colors
     {
-        get { return (WpfObservableRangeCollection<PaletteColor>)GetValue(ColorsProperty); }
-        set { SetValue(ColorsProperty, value); }
+        get => GetValue(ColorsProperty);
+        set => SetValue(ColorsProperty, value);
     }
 
+    public static readonly StyledProperty<Color> HintColorProperty =
+        AvaloniaProperty.Register<PaletteViewer, Color>(
+            nameof(HintColor),
+            default(Color));
+
     public Color HintColor
     {
-        get { return (Color)GetValue(HintColorProperty); }
-        set { SetValue(HintColorProperty, value); }
+        get => GetValue(HintColorProperty);
+        set => SetValue(HintColorProperty, value);
     }
 
-    public static readonly DependencyProperty HintColorProperty =
-        DependencyProperty.Register(nameof(HintColor), typeof(Color), typeof(PaletteViewer), new PropertyMetadata(System.Windows.Media.Colors.Transparent));
-
-    public static readonly DependencyProperty ReplaceColorsCommandProperty = DependencyProperty.Register(nameof(ReplaceColorsCommand), typeof(ICommand), typeof(PaletteViewer), new PropertyMetadata(default(ICommand)));
+    public static readonly StyledProperty<ICommand> ReplaceColorsCommandProperty =
+        AvaloniaProperty.Register<PaletteViewer, ICommand>(
+            nameof(ReplaceColorsCommand),
+            default(ICommand));
 
     public ICommand ReplaceColorsCommand
     {
-        get { return (ICommand)GetValue(ReplaceColorsCommandProperty); }
-        set { SetValue(ReplaceColorsCommandProperty, value); }
+        get => GetValue(ReplaceColorsCommandProperty);
+        set => SetValue(ReplaceColorsCommandProperty, value);
     }
 
+    public static readonly StyledProperty<ICommand> SelectColorCommandProperty =
+        AvaloniaProperty.Register<PaletteViewer, ICommand>(
+            nameof(SelectColorCommand));
+
     public ICommand SelectColorCommand
     {
-        get { return (ICommand)GetValue(SelectColorCommandProperty); }
-        set { SetValue(SelectColorCommandProperty, value); }
+        get => GetValue(SelectColorCommandProperty);
+        set => SetValue(SelectColorCommandProperty, value);
     }
 
-
-    public static readonly DependencyProperty SelectColorCommandProperty =
-        DependencyProperty.Register(nameof(SelectColorCommand), typeof(ICommand), typeof(PaletteViewer));
+    public static readonly StyledProperty<ICommand> ImportPaletteCommandProperty =
+        AvaloniaProperty.Register<PaletteViewer, ICommand>(
+            nameof(ImportPaletteCommand));
 
     public ICommand ImportPaletteCommand
     {
-        get { return (ICommand)GetValue(ImportPaletteCommandProperty); }
-        set { SetValue(ImportPaletteCommandProperty, value); }
+        get => GetValue(ImportPaletteCommandProperty);
+        set => SetValue(ImportPaletteCommandProperty, value);
     }
 
-    public static readonly DependencyProperty ImportPaletteCommandProperty =
-        DependencyProperty.Register(nameof(ImportPaletteCommand), typeof(ICommand), typeof(PaletteViewer));
-
-    public static readonly DependencyProperty PaletteProviderProperty = DependencyProperty.Register(
-        nameof(PaletteProvider), typeof(PaletteProvider), typeof(PaletteViewer), new PropertyMetadata(default(PaletteProvider)));
+    public static readonly StyledProperty<PaletteProvider> PaletteProviderProperty =
+        AvaloniaProperty.Register<PaletteViewer, PaletteProvider>(
+            nameof(PaletteProvider),
+            default(PaletteProvider));
 
     public PaletteProvider PaletteProvider
     {
-        get { return (PaletteProvider)GetValue(PaletteProviderProperty); }
-        set { SetValue(PaletteProviderProperty, value); }
+        get => GetValue(PaletteProviderProperty);
+        set => SetValue(PaletteProviderProperty, value);
     }
-    
+
     public PaletteViewer()
     {
         InitializeComponent();
@@ -111,7 +128,9 @@ internal partial class PaletteViewer : UserControl
 
     private async Task ImportPalette(string fileName)
     {
-        var parser = PaletteProvider.AvailableParsers.FirstOrDefault(x => x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+        var parser =
+            PaletteProvider.AvailableParsers.FirstOrDefault(x =>
+                x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
         if (parser == null) return;
         var data = await parser.Parse(fileName);
         if (data.IsCorrupted || data.Colors.Length == 0) return;
@@ -123,18 +142,22 @@ internal partial class PaletteViewer : UserControl
     {
         SaveFileDialog saveFileDialog = new SaveFileDialog
         {
-            Filter = PaletteHelpers.GetFilter(PaletteProvider.AvailableParsers.Where(x => x.CanSave).ToList(), false)
+            Filter = PaletteHelpers.GetFilter(PaletteProvider.AvailableParsers.Where(x => x.CanSave).ToList(),
+                false)
         };
 
         if (saveFileDialog.ShowDialog() == true)
         {
-            string fileName = saveFileDialog.FileName;
-            var foundParser = PaletteProvider.AvailableParsers.First(x => x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+            string fileName = saveFileDialog.Pa;
+            var foundParser =
+                PaletteProvider.AvailableParsers.First(x =>
+                    x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
             if (Colors == null || Colors.Count == 0)
             {
                 NoticeDialog.Show("NO_COLORS_TO_SAVE", "ERROR");
                 return;
             }
+
             bool saved = await foundParser.Save(fileName, new PaletteFileData(Colors.ToArray()));
             if (!saved)
             {
@@ -147,27 +170,28 @@ internal partial class PaletteViewer : UserControl
     {
         if (IsSupportedFilePresent(e, out _))
         {
-            dragDropGrid.Visibility = Visibility.Visible;
+            dragDropGrid.IsVisible = true;
             ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] = "IMPORT_PALETTE_FILE";
         }
         else if (ColorHelper.ParseAnyFormatList(e.Data, out var list))
         {
-            e.Effects = DragDropEffects.Copy;
-            ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] = list.Count > 1 ? "IMPORT_MULTIPLE_PALETTE_COLORS" : "IMPORT_SINGLE_PALETTE_COLOR";
+            e.DragEffects = DragDropEffects.Copy;
+            ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] =
+                list.Count > 1 ? "IMPORT_MULTIPLE_PALETTE_COLORS" : "IMPORT_SINGLE_PALETTE_COLOR";
             e.Handled = true;
         }
     }
 
     private void Grid_PreviewDragLeave(object sender, DragEventArgs e)
     {
-        dragDropGrid.Visibility = Visibility.Hidden;
+        dragDropGrid.IsVisible = false;
         ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] = null;
     }
 
     private async void Grid_Drop(object sender, DragEventArgs e)
     {
         ViewModelMain.Current.ActionDisplays[nameof(PaletteViewer)] = null;
-        
+
         if (!IsSupportedFilePresent(e, out string filePath))
         {
             if (!ColorHelper.ParseAnyFormatList(e.Data, out var colors))
@@ -176,8 +200,8 @@ internal partial class PaletteViewer : UserControl
             }
 
             List<PaletteColor> paletteColors = colors.Select(x => new PaletteColor(x.R, x.G, x.B)).ToList();
-            
-            e.Effects = DragDropEffects.Copy;
+
+            e.DragEffects = DragDropEffects.Copy;
             Colors.AddRange(paletteColors.Where(x => !Colors.Contains(new PaletteColor(x.R, x.G, x.B))).ToList());
             e.Handled = true;
             return;
@@ -185,18 +209,19 @@ internal partial class PaletteViewer : UserControl
 
         e.Handled = true;
         await ImportPalette(filePath);
-        dragDropGrid.Visibility = Visibility.Hidden;
+        dragDropGrid.IsVisible = false;
     }
 
     private bool IsSupportedFilePresent(DragEventArgs e, out string filePath)
     {
-        if (e.Data.GetDataPresent(DataFormats.FileDrop))
+        if (e.Data.Contains(DataFormats.Files))
         {
-            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
+            string[] files = (string[])e.Data.Get(DataFormats.Files);
             if (files is { Length: > 0 })
             {
                 var fileName = files[0];
-                var foundParser = PaletteProvider.AvailableParsers.FirstOrDefault(x => x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+                var foundParser = PaletteProvider.AvailableParsers.FirstOrDefault(x =>
+                    x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
                 if (foundParser != null)
                 {
                     filePath = fileName;
@@ -211,9 +236,9 @@ internal partial class PaletteViewer : UserControl
 
     private void PaletteColor_Drop(object sender, DragEventArgs e)
     {
-        if (e.Data.GetDataPresent(PaletteColorControl.PaletteColorDaoFormat))
+        if (e.Data.Contains(PaletteColorControl.PaletteColorDaoFormat))
         {
-            string data = (string)e.Data.GetData(PaletteColorControl.PaletteColorDaoFormat);
+            string data = (string)e.Data.Get(PaletteColorControl.PaletteColorDaoFormat);
 
             PaletteColor paletteColor = PaletteColor.Parse(data);
             if (Colors.Contains(paletteColor))
@@ -241,7 +266,7 @@ internal partial class PaletteViewer : UserControl
         MenuItem menuItem = (MenuItem)sender;
         PaletteColor color = (PaletteColor)menuItem.CommandParameter;
         Replacer.ColorToReplace = color;
-        Replacer.VisibilityCheckbox.IsChecked = false;
+        Replacer.IsVisibleCheckbox.IsChecked = false;
     }
 
     private void MenuItem_OnClick(object sender, RoutedEventArgs e)
@@ -253,9 +278,9 @@ internal partial class PaletteViewer : UserControl
         }
     }
 
-    private void DiscardPalette_OnClick(object sender, RoutedEventArgs e)
+    private async Task DiscardPalette_OnClick(object sender, RoutedEventArgs e)
     {
-        if(ConfirmationDialog.Show("DISCARD_PALETTE_CONFIRMATION", "DISCARD_PALETTE") == ConfirmationType.Yes)
+        if (await ConfirmationDialog.Show("DISCARD_PALETTE_CONFIRMATION", "DISCARD_PALETTE") == ConfirmationType.Yes)
         {
             Colors.Clear();
         }