Selaa lähdekoodia

Viewport progress

Krzysztof Krysiński 2 vuotta sitten
vanhempi
commit
b28fb7b3a5
24 muutettua tiedostoa jossa 535 lisäystä ja 86 poistoa
  1. 19 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ActiveToolToZoomModeConverter.cs
  2. 23 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/BoolOrToVisibilityConverter.cs
  3. 26 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/BoolToIntConverter.cs
  4. 38 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/GenericColorToMediaColorConverter.cs
  5. 17 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/IntToViewportRectConverter.cs
  6. 40 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/NotNullToVisibilityConverter.cs
  7. 19 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/PaletteItemsToWidthConverter.cs
  8. 20 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/RadiansToDegreesConverter.cs
  9. 17 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ReciprocalConverter.cs
  10. 25 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ScaleToBitmapScalingModeConverter.cs
  11. 19 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ThresholdVisibilityConverter.cs
  12. 22 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ZoomToViewportConverter.cs
  13. 1 2
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/Commands/XAML/ContextMenu.cs
  14. 1 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj
  15. 12 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Styles/PortingWipStyles.axaml
  16. 4 1
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/ToolVM.cs
  17. 62 50
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml
  18. 7 7
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs
  19. 12 13
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainView.axaml
  20. 26 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainView.axaml.cs
  21. 44 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml
  22. 81 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml.cs
  23. 0 3
      src/PixiEditor.Zoombox/Zoombox.axaml
  24. 0 10
      src/PixiEditor.Zoombox/Zoombox.axaml.cs

+ 19 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ActiveToolToZoomModeConverter.cs

@@ -0,0 +1,19 @@
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+using PixiEditor.AvaloniaUI.ViewModels.Tools.Tools;
+using PixiEditor.Zoombox;
+
+namespace PixiEditor.Helpers.Converters;
+internal class ActiveToolToZoomModeConverter : SingleInstanceConverter<ActiveToolToZoomModeConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return value switch
+        {
+            MoveViewportToolViewModel => ZoomboxMode.Move,
+            ZoomToolViewModel => ZoomboxMode.Zoom,
+            RotateViewportToolViewModel => ZoomboxMode.Rotate,
+            _ => ZoomboxMode.Normal,
+        };
+    }
+}

+ 23 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/BoolOrToVisibilityConverter.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+internal class BoolOrToVisibilityConverter : SingleInstanceMultiValueConverter<BoolOrToVisibilityConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return (bool)value;
+    }
+
+    public override object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
+    {
+        bool boolean = values.Aggregate(false, (acc, cur) => acc |= (cur as bool?) ?? false);
+        return boolean ? true : false;
+    }
+}

+ 26 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/BoolToIntConverter.cs

@@ -0,0 +1,26 @@
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class BoolToIntConverter
+    : SingleInstanceConverter<BoolToIntConverter>
+{
+    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return value.ToString() == "0";
+    }
+
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is bool boolean)
+        {
+            if (boolean == false)
+            {
+                return 0;
+            }
+        }
+
+        return 1;
+    }
+}

+ 38 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/GenericColorToMediaColorConverter.cs

@@ -0,0 +1,38 @@
+using System.Globalization;
+using System.Windows.Media;
+using Avalonia.Media;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+using PixiEditor.AvaloniaUI.Helpers.Extensions;
+using PixiEditor.Extensions.Palettes;
+using BackendColor = PixiEditor.DrawingApi.Core.ColorsImpl.Color;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class GenericColorToMediaColorConverter : SingleInstanceConverter<GenericColorToMediaColorConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        Color color = default;
+        if (value is BackendColor backendColor)
+        {
+            color = backendColor.ToColor();
+        }
+        else if (value is PaletteColor paletteColor)
+        {
+            color = paletteColor.ToMediaColor();
+        }
+
+        if (targetType == typeof(Brush))
+        {
+            return new SolidColorBrush(color);
+        }
+
+        return color;
+    }
+
+    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        var color = (Color)value;
+        return new BackendColor(color.R, color.G, color.B, color.A);
+    }
+}

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

@@ -0,0 +1,17 @@
+using System.Globalization;
+using System.Windows;
+using Avalonia;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class IntToViewportRectConverter
+    : SingleInstanceConverter<IntToViewportRectConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return parameter is string and "vertical"
+            ? new Rect(0, 0, 1d / (int)value, 1d)
+            : (object)new Rect(0, 0, 1d, 1d / (int)value);
+    }
+}

+ 40 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/NotNullToVisibilityConverter.cs

@@ -0,0 +1,40 @@
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class NotNullToVisibilityConverter
+    : MarkupConverter
+{
+    public bool Inverted { get; set; }
+
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        bool isNull = IsDefaultValue(value);
+
+        if (Inverted)
+        {
+            isNull = !isNull;
+        }
+
+        return isNull ? false : true;
+    }
+    
+    bool IsDefaultValue(object obj)
+    {
+        if (obj is null)
+        {
+            return true;
+        }
+        
+        var type = obj.GetType();
+
+        if (type.IsValueType)
+        {
+            object defaultValue = Activator.CreateInstance(type);
+            return obj.Equals(defaultValue);
+        }
+
+        return false;
+    }
+}

+ 19 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/PaletteItemsToWidthConverter.cs

@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class PaletteItemsToWidthConverter : SingleInstanceConverter<PaletteItemsToWidthConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is IList<Color> colors && colors.Count == 0)
+        {
+            return 0;
+        }
+
+        return 120;
+    }
+}

+ 20 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/RadiansToDegreesConverter.cs

@@ -0,0 +1,20 @@
+using System.Globalization;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class RadiansToDegreesConverter : SingleInstanceConverter<RadiansToDegreesConverter>
+{
+    private const double RadiansToDegrees = 180 / Math.PI;
+
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+
+        if (value is double angle)
+        {
+            return Math.Truncate((angle * RadiansToDegrees + 360) % 360);
+        }
+
+        return 0;
+    }
+}

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

@@ -0,0 +1,17 @@
+using System.Globalization;
+using System.Windows;
+using Avalonia;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+internal class ReciprocalConverter : SingleInstanceConverter<ReciprocalConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is not double num)
+            return AvaloniaProperty.UnsetValue;
+        if (parameter is not double mult)
+            return 1 / num;
+        return mult / num;
+    }
+}

+ 25 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ScaleToBitmapScalingModeConverter.cs

@@ -0,0 +1,25 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Media;
+using Avalonia;
+using Avalonia.Media.Imaging;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class ScaleToBitmapScalingModeConverter : SingleInstanceConverter<ScaleToBitmapScalingModeConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is not double scale)
+            return BitmapInterpolationMode.None;
+        if (scale < 1)
+            return BitmapInterpolationMode.HighQuality;
+        return BitmapInterpolationMode.None;
+    }
+
+    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 19 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ThresholdVisibilityConverter.cs

@@ -0,0 +1,19 @@
+using System.Globalization;
+using System.Windows;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class ThresholdVisibilityConverter
+    : MarkupConverter
+{
+    public double Threshold { get; set; } = 100;
+    public bool CheckIfLess { get; set; } = false;
+
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return CheckIfLess
+            ? (double)value < Threshold
+            : (double)value >= Threshold;
+    }
+}

+ 22 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/Converters/ZoomToViewportConverter.cs

@@ -0,0 +1,22 @@
+using System.Globalization;
+using Avalonia;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.Helpers.Converters;
+
+internal class ZoomToViewportConverter
+    : SingleInstanceConverter<ZoomToViewportConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is double scale && parameter is double factor)
+        {
+            double newSize = Math.Clamp((double)factor / scale, 1, 9999);
+            if (newSize > 1 && newSize < 4)
+                newSize = 4;
+            return new Rect(0, 0, newSize, newSize);
+        }
+
+        return AvaloniaProperty.UnsetValue;
+    }
+}

+ 1 - 2
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/Commands/XAML/ContextMenu.cs

@@ -34,8 +34,7 @@ internal class ContextMenu : global::Avalonia.Controls.ContextMenu
 
         var command = CommandController.Current.Commands[value];
 
-        //TODO: Same story as in Menu.cs
-        //item.Command = Command.GetICommand(command, false);
+        item.Command = Command.GetICommand(command, false);
         item.Bind(MenuItem.InputGestureProperty, ShortcutBinding.GetBinding(command, null));
     }
 

+ 1 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj

@@ -62,6 +62,7 @@
     </ItemGroup>
   
     <ItemGroup>
+      <Folder Include="PixiEditor\" />
       <Folder Include="Views\Buttons\" />
     </ItemGroup>
   

+ 12 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Styles/PortingWipStyles.axaml

@@ -9,4 +9,16 @@
     <Style Selector="Button.SocialMediaButton">
 
     </Style>
+
+    <Style Selector="Button.GrayRoundButton">
+
+    </Style>
+
+    <Style Selector="Button.OverlayToggleButton">
+
+    </Style>
+
+    <Style Selector="Button.OverlayButton">
+
+    </Style>
 </Styles>

+ 4 - 1
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/ToolVM.cs

@@ -1,4 +1,7 @@
-using System.Windows.Markup;
+using System.Linq;
+using System.Windows.Markup;
+using Avalonia.Markup.Xaml;
+using PixiEditor.AvaloniaUI.ViewModels;
 
 namespace PixiEditor.ViewModels;
 

+ 62 - 50
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml

@@ -13,6 +13,8 @@
     xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
     xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
     xmlns:zoombox="clr-namespace:PixiEditor.Zoombox;assembly=PixiEditor.Zoombox"
+    xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+    xmlns:subviews="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Document"
     mc:Ignorable="d"
     x:Name="vpUc"
     d:DesignHeight="450"
@@ -40,9 +42,9 @@
             </EventTriggerBehavior>
         </Interaction.Behaviors>
         <views:TogglableFlyout Margin="5" IconPath="/Images/Settings.png" ui:Translator.TooltipKey="VIEWPORT_SETTINGS"
-                               Panel.ZIndex="2" HorizontalAlignment="Right" VerticalAlignment="Top">
+                               ZIndex="2" HorizontalAlignment="Right" VerticalAlignment="Top">
             <views:TogglableFlyout.Child>
-                <Border BorderThickness="1" CornerRadius="5" Padding="5" Background="#C8202020" Panel.ZIndex="2">
+                <Border BorderThickness="1" CornerRadius="5" Padding="5" Background="#C8202020" ZIndex="2">
         <StackPanel Orientation="Vertical">
             <StackPanel Orientation="Horizontal">
             <TextBlock Margin="5 0" TextAlignment="Center"
@@ -50,7 +52,7 @@
              Converter={converters:RadiansToDegreesConverter}, StringFormat={}{0}°}"
                        Width="35" Foreground="White" VerticalAlignment="Center" FontSize="16"/>
             <Button Width="32" Height="32" ui:Translator.TooltipKey="RESET_VIEWPORT"
-                    Style="{StaticResource OverlayButton}"
+                    Classes="OverlayButton"
                     Click="ResetViewportClicked"
                     Cursor="Hand">
             <Button.Content>
@@ -61,7 +63,7 @@
             <Separator/>
             <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                 <ToggleButton Width="32" Height="32" ui:Translator.TooltipKey="TOGGLE_VERTICAL_SYMMETRY"
-                        Style="{StaticResource OverlayToggleButton}"
+                        Classes="OverlayToggleButton"
                         IsChecked="{Binding Document.VerticalSymmetryAxisEnabledBindable, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=TwoWay}"
                         Cursor="Hand">
                     <ToggleButton.Content>
@@ -69,14 +71,14 @@
                     </ToggleButton.Content>
                 </ToggleButton>
                 <ToggleButton Margin="10 0 0 0" Width="32" Height="32" ui:Translator.TooltipKey="TOGGLE_HORIZONTAL_SYMMETRY"
-                              Style="{StaticResource OverlayToggleButton}"
+                              Classes="OverlayToggleButton"
                               IsChecked="{Binding Document.HorizontalSymmetryAxisEnabledBindable, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=TwoWay}"
                               Cursor="Hand">
                     <ToggleButton.Content>
                         <Image Width="28" Height="28" Source="/Images/SymmetryVertical.png">
-                            <Image.LayoutTransform>
+                            <Image.RenderTransform>
                                 <RotateTransform Angle="90"/>
-                            </Image.LayoutTransform>
+                            </Image.RenderTransform>
                         </Image>
                     </ToggleButton.Content>
                 </ToggleButton>
@@ -84,7 +86,7 @@
             <Separator/>
             <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                 <ToggleButton Width="32" Height="32" ui:Translator.TooltipKey="FLIP_VIEWPORT_HORIZONTALLY"
-                              Style="{StaticResource OverlayToggleButton}"
+                              Classes="OverlayToggleButton"
                               IsChecked="{Binding FlipX, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=TwoWay}"
                               Cursor="Hand">
                     <ToggleButton.Content>
@@ -92,14 +94,14 @@
                     </ToggleButton.Content>
                 </ToggleButton>
                 <ToggleButton Margin="10 0 0 0" Width="32" Height="32" ui:Translator.TooltipKey="FLIP_VIEWPORT_VERTICALLY"
-                              Style="{StaticResource OverlayToggleButton}"
+                              Classes="OverlayToggleButton"
                               IsChecked="{Binding FlipY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=TwoWay}"
                               Cursor="Hand">
                     <ToggleButton.Content>
                         <Image Width="28" Height="28" Source="/Images/FlipHorizontal.png">
-                            <Image.LayoutTransform>
+                            <Image.RenderTransform>
                                 <RotateTransform Angle="90"/>
-                            </Image.LayoutTransform>
+                            </Image.RenderTransform>
                         </Image>
                     </ToggleButton.Content>
                 </ToggleButton>
@@ -127,30 +129,32 @@
                 HorizontalAlignment="Center"
                 VerticalAlignment="Center"
                 DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}}"
-                RenderOptions.BitmapScalingMode="NearestNeighbor">
+                RenderOptions.BitmapInterpolationMode="None">
                 <Border.Background>
-                    <ImageBrush ImageSource="/Images/CheckerTile.png" TileMode="Tile" ViewportUnits="Absolute">
-                        <ImageBrush.Viewport>
-                            <Binding Path="Scale" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type zoombox:Zoombox}}" Converter="{converters:ZoomToViewportConverter}">
+                    <ImageBrush Source="/Images/CheckerTile.png" TileMode="Tile">
+                        <ImageBrush.DestinationRect>
+                            <Binding Path="Scale" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type zoombox:Zoombox}}"
+                                     Converter="{converters:ZoomToViewportConverter}">
                                 <Binding.ConverterParameter>
                                     <sys:Double>16</sys:Double>
                                 </Binding.ConverterParameter>
                             </Binding>
-                        </ImageBrush.Viewport>
+                        </ImageBrush.DestinationRect>
                     </ImageBrush>
                 </Border.Background>
                 <Grid>
                     <Canvas
                         ZIndex="{Binding Document.ReferenceLayerViewModel.ShowHighest, Converter={converters:BoolToIntConverter}}"
                         IsHitTestVisible="{Binding Document.ReferenceLayerViewModel.IsTransforming}">
+                        <!--TODO: RenderOptions.BitmapInterpolationMode="{Binding ReferenceLayerScale, Converter={converters:ScaleToBitmapScalingModeConverter}}"-->
                         <Image
                             Focusable="False"
                             Width="{Binding Document.ReferenceLayerViewModel.ReferenceBitmap.Width}"
                             Height="{Binding Document.ReferenceLayerViewModel.ReferenceBitmap.Height}"
                             Source="{Binding Document.ReferenceLayerViewModel.ReferenceBitmap, Mode=OneWay}"
-                            Visibility="{Binding Document.ReferenceLayerViewModel.IsVisibleBindable, Converter={converters:BoolToHiddenVisibilityConverter}}"
+                            IsVisible="{Binding Document.ReferenceLayerViewModel.IsVisibleBindable}"
                             SizeChanged="OnReferenceImageSizeChanged"
-                            RenderOptions.BitmapScalingMode="{Binding ReferenceLayerScale, Converter={converters:ScaleToBitmapScalingModeConverter}}"
+
                             FlowDirection="LeftToRight">
                             <Image.RenderTransform>
                                 <TransformGroup>
@@ -158,8 +162,9 @@
                                         Matrix="{Binding Document.ReferenceLayerViewModel.ReferenceTransformMatrix}" />
                                 </TransformGroup>
                             </Image.RenderTransform>
-                            <Image.Style>
-                                <Style>
+                            <Image.Styles>
+                                <!--TODO: Implement this-->
+                                <!--<Style>
                                     <Style.Triggers>
                                         <DataTrigger Binding="{Binding Document.ReferenceLayerViewModel.ShowHighest, Mode=OneWay}" Value="True">
                                             <DataTrigger.EnterActions>
@@ -182,11 +187,12 @@
                                             </DataTrigger.ExitActions>
                                         </DataTrigger>
                                     </Style.Triggers>
-                                </Style>
-                            </Image.Style>
+                                </Style>-->
+                            </Image.Styles>
                         </Image>
-                        <Canvas.Style>
-                            <Style>
+                        <Canvas.Styles>
+                            <!--TODO: Implement this-->
+                            <!--<Style>
                                 <Style.Triggers>
                                     <DataTrigger Binding="{Binding Source={vm:ToolVM ColorPickerToolViewModel}, Path=PickFromReferenceLayer, Mode=OneWay}" Value="False">
                                         <DataTrigger.EnterActions>
@@ -209,18 +215,19 @@
                                         </DataTrigger.ExitActions>
                                     </DataTrigger>
                                 </Style.Triggers>
-                            </Style>
-                        </Canvas.Style>
+                            </Style>-->
+                        </Canvas.Styles>
                     </Canvas>
+                    <!--TODO: RenderOptions.BitmapInterpolationMode="{Binding Zoombox.Scale, Converter={converters:ScaleToBitmapScalingModeConverter}}"-->
                     <Image
                         Focusable="False"
                         Width="{Binding Document.Width}"
                         Height="{Binding Document.Height}"
                         Source="{Binding TargetBitmap}"
-                        RenderOptions.BitmapScalingMode="{Binding Zoombox.Scale, Converter={converters:ScaleToBitmapScalingModeConverter}}"
                         FlowDirection="LeftToRight">
-                        <Image.Style>
-                            <Style>
+                        <Image.Styles>
+                            <!--TODO: Implement-->
+                            <!--<Style>
                                 <Style.Triggers>
                                     <DataTrigger Binding="{Binding Source={vm:ToolVM ColorPickerToolViewModel}, Path=PickOnlyFromReferenceLayer, Mode=OneWay}" Value="True">
                                         <DataTrigger.EnterActions>
@@ -243,11 +250,12 @@
                                         </DataTrigger.ExitActions>
                                     </DataTrigger>
                                 </Style.Triggers>
-                            </Style>
-                        </Image.Style>
+                            </Style>-->
+                        </Image.Styles>
                     </Image>
                     <Grid ZIndex="5">
-                        <symOverlay:SymmetryOverlay
+                        <!--TODO: Implement overlays-->
+                        <!--<symOverlay:SymmetryOverlay
                             Focusable="False"
                             IsHitTestVisible="{Binding ZoomMode, Converter={converters:ZoomModeToHitTestVisibleConverter}}"
                             ZoomboxScale="{Binding Zoombox.Scale}"
@@ -300,38 +308,40 @@
                             LineStart="{Binding Document.LineToolOverlayViewModel.LineStart, Mode=TwoWay}"
                             LineEnd="{Binding Document.LineToolOverlayViewModel.LineEnd, Mode=TwoWay}"
                             ZoomboxScale="{Binding Zoombox.Scale}"
-                            FlowDirection="LeftToRight"/>
+                            FlowDirection="LeftToRight"/>-->
                     </Grid>
                     <Grid IsHitTestVisible="False" 
                         ShowGridLines="True" Width="{Binding Document.Width}" Height="{Binding Document.Height}" Panel.ZIndex="10" 
-                        Visibility="{Binding GridLinesVisible, Converter={converters:BoolToVisibilityConverter}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}}">
+                        IsVisible="{Binding GridLinesVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}}">
                         <Grid.Resources>
                             <converters:ThresholdVisibilityConverter Threshold="10" x:Key="ThresholdVisibilityConverter"/>
                         </Grid.Resources>
-                        <Rectangle Focusable="False" Visibility="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
+                        <Rectangle Focusable="False" IsVisible="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
                             <Rectangle.Fill>
-                                <VisualBrush Viewport="{Binding Document.Width, Converter={converters:IntToViewportRectConverter}, ConverterParameter=vertical}" ViewboxUnits="Absolute" TileMode="Tile" >
+                                <VisualBrush DestinationRect="{Binding Document.Width, Converter={converters:IntToViewportRectConverter}, ConverterParameter=vertical}"
+                                            TileMode="Tile" >
                                     <VisualBrush.Visual>
-                                        <Line X1="0" Y1="0" X2="0" Y2="1" Stroke="Black" 
+                                        <Line StartPoint="0, 0" EndPoint="0, 1" Stroke="Black"
                                               StrokeThickness="{Binding Zoombox.Scale, Converter={converters:ReciprocalConverter}}"/>
                                     </VisualBrush.Visual>
                                 </VisualBrush>
                             </Rectangle.Fill>
                         </Rectangle>
-                        <Rectangle Focusable="False" Visibility="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
+                        <Rectangle Focusable="False" IsVisible="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
                             <Rectangle.Fill>
-                                <VisualBrush Viewport="{Binding Document.Height, Converter={converters:IntToViewportRectConverter}}" ViewboxUnits="Absolute" TileMode="Tile" >
+                                <VisualBrush DestinationRect="{Binding Document.Height, Converter={converters:IntToViewportRectConverter}}"
+                                           TileMode="Tile" >
                                     <VisualBrush.Visual>
-                                        <Line X1="0" Y1="0" X2="1" Y2="0" Stroke="Black" StrokeThickness="{Binding Zoombox.Scale, Converter={converters:ReciprocalConverter}}"/>
+                                        <Line StartPoint="0, 0" EndPoint="1, 0" Stroke="Black" StrokeThickness="{Binding Zoombox.Scale, Converter={converters:ReciprocalConverter}}"/>
                                     </VisualBrush.Visual>
                                 </VisualBrush>
                             </Rectangle.Fill>
                         </Rectangle>
-                        <Rectangle Focusable="False" Visibility="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
+                        <Rectangle Focusable="False" IsVisible="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
                             <Rectangle.Fill>
-                                <VisualBrush Viewport="{Binding Document.Width, Converter={converters:IntToViewportRectConverter}, ConverterParameter=vertical}" ViewboxUnits="Absolute" TileMode="Tile" >
+                                <VisualBrush DestinationRect="{Binding Document.Width, Converter={converters:IntToViewportRectConverter}, ConverterParameter=vertical}" TileMode="Tile" >
                                     <VisualBrush.Visual>
-                                        <Line X1="0" Y1="0" X2="0" Y2="1" Stroke="White">
+                                        <Line StartPoint="0, 0" EndPoint="0, 1" Stroke="White">
                                             <Line.StrokeThickness>
                                                 <Binding Converter="{converters:ReciprocalConverter}">
                                                     <Binding.Path>Zoombox.Scale</Binding.Path>
@@ -347,11 +357,12 @@
                                 </VisualBrush>
                             </Rectangle.Fill>
                         </Rectangle>
-                        <Rectangle Focusable="False" Visibility="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
+                        <Rectangle Focusable="False" IsVisible="{Binding Zoombox.Scale, Converter={StaticResource ThresholdVisibilityConverter}}">
                             <Rectangle.Fill>
-                                <VisualBrush Viewport="{Binding Document.Height, Converter={converters:IntToViewportRectConverter}}" ViewboxUnits="Absolute" TileMode="Tile" >
+                                <!--TODO: Make sure Viewport is DestinationRect in Avalonia. Also Viewbox Units not found-->
+                                <VisualBrush DestinationRect="{Binding Document.Height, Converter={converters:IntToViewportRectConverter}}" TileMode="Tile">
                                     <VisualBrush.Visual>
-                                        <Line X1="0" Y1="0" X2="1" Y2="0" Stroke="White">
+                                        <Line StartPoint="0, 0" EndPoint="1, 0" Stroke="White">
                                             <Line.StrokeThickness>
                                                 <Binding Converter="{converters:ReciprocalConverter}">
                                                     <Binding.Path>Zoombox.Scale</Binding.Path>
@@ -368,7 +379,8 @@
                             </Rectangle.Fill>
                         </Rectangle>
                     </Grid>
-                    <Rectangle Stroke="{StaticResource AccentColor}" Opacity=".8" Panel.ZIndex="2" Visibility="{Binding Document.ReferenceLayerViewModel.IsVisibleBindable, Converter={converters:BoolToHiddenVisibilityConverter}}">
+                    <Rectangle Stroke="{DynamicResource ThemeAccentBrush}" Opacity=".8" ZIndex="2"
+                               IsVisible="{Binding Document.ReferenceLayerViewModel.IsVisibleBindable}">
                         <Rectangle.StrokeThickness>
                             <Binding Converter="{converters:ReciprocalConverter}">
                                 <Binding.Path>Zoombox.Scale</Binding.Path>
@@ -394,13 +406,13 @@
             </Border>
         </zoombox:Zoombox>
         <Button 
-            Panel.ZIndex="99999"
+            ZIndex="99999"
             DockPanel.Dock="Bottom"
             Margin="5"
             Padding="8,5,5,5"
             VerticalAlignment="Bottom" 
             HorizontalAlignment="Center"
-            Style="{StaticResource GrayRoundButton}"
+            Classes="GrayRoundButton"
             Command="{xaml:Command PixiEditor.Tools.ApplyTransform}">
             <Button.IsVisible>
                 <MultiBinding Converter="{converters:BoolOrToVisibilityConverter}">
@@ -412,7 +424,7 @@
             </Button.IsVisible>
             <StackPanel Orientation="Horizontal">
                 <TextBlock ui:Translator.Key="APPLY_TRANSFORM" VerticalAlignment="Center" Margin="0,0,5,0" />
-                <Border Padding="10,3" CornerRadius="5" Background="{StaticResource AccentColor}" Visibility="{cmds:ShortcutBinding PixiEditor.Tools.ApplyTransform, Converter={converters:NotNullToVisibilityConverter}}">
+                <Border Padding="10,3" CornerRadius="5" Background="{DynamicResource ThemeAccentBrush}" IsVisible="{xaml:ShortcutBinding PixiEditor.Tools.ApplyTransform, Converter={converters:NotNullToVisibilityConverter}}">
                     <TextBlock Text="{xaml:ShortcutBinding PixiEditor.Tools.ApplyTransform}" />
                 </Border>
             </StackPanel>

+ 7 - 7
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs

@@ -280,7 +280,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
     public double ReferenceLayerScale =>
         ZoomboxScale * ((Document?.ReferenceLayerViewModel.ReferenceBitmap != null && Document?.ReferenceLayerViewModel.ReferenceShapeBindable != null)
-            ? (Document.ReferenceLayerViewModel.ReferenceShapeBindable.RectSize.X / (double)Document.ReferenceLayerViewModel.ReferenceBitmap.PixelWidth)
+            ? (Document.ReferenceLayerViewModel.ReferenceShapeBindable.RectSize.X / (double)Document.ReferenceLayerViewModel.ReferenceBitmap.PixelSize.Width)
             : 1);
 
     public PixiEditor.Zoombox.Zoombox Zoombox => zoombox;
@@ -301,8 +301,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
     {
         InitializeComponent();
 
-        Binding binding = new Binding { Source = this, Path = new PropertyPath($"{nameof(Document)}.{nameof(Document.LazyBitmaps)}") };
-        Bind(BitmapsProperty, binding);
+        Binding binding = new Binding { Source = this, Path = $"{nameof(Document)}.{nameof(Document.LazyBitmaps)}" };
+        this.Bind(BitmapsProperty, binding);
 
         MainImage!.Loaded += OnImageLoaded;
         Loaded += OnLoad;
@@ -311,7 +311,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
     }
 
-    public Image? MainImage => (Image?)((Grid?)((Border?)zoombox.AdditionalContent)?.Child)?.Children[1];
+    public Image? MainImage => (Image?)((Grid?)((Border?)zoombox.Content)?.Child)?.Children[1];
     public Grid BackgroundGrid => mainGrid;
 
     private void ForceRefreshFinalImage()
@@ -362,12 +362,12 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         return new(Angle, Center, RealDimensions, Dimensions, CalculateResolution(), GuidValue, Delayed, ForceRefreshFinalImage);
     }
 
-    private void OnReferenceImageSizeChanged(object? sender, SizeChangedEventArgs e)
+    private void OnReferenceImageSizeChanged(object? sender, SizeChangedEventArgs sizeChangedEventArgs)
     {
         PropertyChanged?.Invoke(this, new(nameof(ReferenceLayerScale)));
     }
 
-    private void Image_MouseDown(object sender, PointerEventArgs e)
+    private void Image_MouseDown(object? sender, PointerPressedEventArgs e)
     {
         bool isMiddle = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
         HandleMiddleMouse(isMiddle);
@@ -390,7 +390,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
             MouseDownCommand.Execute(parameter);
     }
 
-    private void Image_MouseMove(PointerEventArgs pointerEventArgs)
+    private void Image_MouseMove(PointerEventArgs e)
     {
         if (MouseMoveCommand is null)
             return;

+ 12 - 13
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainView.axaml

@@ -8,6 +8,8 @@
              xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
              xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"
              xmlns:viewModels="clr-namespace:PixiEditor.ViewModels"
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              x:Class="PixiEditor.AvaloniaUI.Views.MainView"
              x:DataType="viewModels1:ViewModelMain" Background="{DynamicResource ThemeBackgroundBrush}">
@@ -75,16 +77,13 @@
                                             StylusOutOfRangeCommand="{xaml:Command PixiEditor.Stylus.StylusOutOfRange, UseProvided=True}"
                                             FlipX="{Binding FlipX, Mode=TwoWay}"
                                             FlipY="{Binding FlipY, Mode=TwoWay}"
-
-                                            ContextMenuOpening="Viewport_OnContextMenuOpening"
-                                            Stylus.IsTapFeedbackEnabled="False"
-                                            Stylus.IsTouchFeedbackEnabled="False"
+                                            ContextRequested="Viewport_OnContextMenuOpening"
                                             Document="{Binding Document}">
                                             <userControls:Viewport.ContextMenu>
                                                 <ContextMenu DataContext="{Binding PlacementTarget.Document, RelativeSource={RelativeSource Self}}">
                                                     <ContextMenu.Template>
                                                         <ControlTemplate>
-                                                            <Border Background="{StaticResource AccentColor}" BorderBrush="Black" BorderThickness="1" CornerRadius="5">
+                                                            <Border Background="{DynamicResource ThemeAccentBrush}" BorderBrush="Black" BorderThickness="1" CornerRadius="5">
                                                                 <Grid Height="235">
                                                                     <Grid.ColumnDefinitions>
                                                                         <ColumnDefinition Width="{Binding Palette, Converter={converters:PaletteItemsToWidthConverter}}"/>
@@ -130,19 +129,19 @@
                                                                                     <palettes:PaletteColorControl Cursor="Hand" CornerRadius="0"
                                                                                         ui:Translator.TooltipKey="CLICK_SELECT_PRIMARY"
                                                                                         Width="22" Height="22" Color="{Binding}">
-                                                                                        <b:Interaction.Triggers>
-                                                                                            <b:EventTrigger EventName="MouseLeftButtonUp">
-                                                                                                <b:InvokeCommandAction
+                                                                                        <Interaction.Behaviors>
+                                                                                            <EventTriggerBehavior EventName="MouseLeftButtonUp">
+                                                                                                <InvokeCommandAction
                                                                                                     Command="{xaml:Command PixiEditor.Colors.SelectColor, UseProvided=True}"
                                                                                                     CommandParameter="{Binding}" />
-                                                                                            </b:EventTrigger>
-                                                                                            <b:EventTrigger EventName="MouseLeftButtonUp">
-                                                                                                <b:InvokeCommandAction
+                                                                                            </EventTriggerBehavior>
+                                                                                            <EventTriggerBehavior EventName="MouseLeftButtonUp">
+                                                                                                <InvokeCommandAction
                                                                                                     Command="{xaml:Command PixiEditor.CloseContextMenu, UseProvided=True}"
                                                                                                     CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
                                                                                                      AncestorType={x:Type ContextMenu}}}" />
-                                                                                            </b:EventTrigger>
-                                                                                        </b:Interaction.Triggers>
+                                                                                            </EventTriggerBehavior>
+                                                                                        </Interaction.Behaviors>
                                                                                     </palettes:PaletteColorControl>
                                                                                 </DataTemplate>
                                                                             </ItemsControl.ItemTemplate>

+ 26 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainView.axaml.cs

@@ -1,4 +1,7 @@
 using Avalonia.Controls;
+using PixiEditor.AvaloniaUI.Models.Preferences;
+using PixiEditor.AvaloniaUI.ViewModels;
+using PixiEditor.AvaloniaUI.ViewModels.Tools.Tools;
 
 namespace PixiEditor.AvaloniaUI.Views;
 
@@ -9,4 +12,27 @@ public partial class MainView : UserControl
         InitializeComponent();
     }
 
+    private void Viewport_OnContextMenuOpening(object? sender, ContextRequestedEventArgs e)
+    {
+        ViewModelMain vm = (ViewModelMain)DataContext;
+        var tools = vm.ToolsSubViewModel;
+
+        var superSpecialBrightnessTool = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool is BrightnessToolViewModel;
+        var superSpecialColorPicker = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool is ColorPickerToolViewModel;
+
+        if (superSpecialBrightnessTool || superSpecialColorPicker)
+        {
+            e.Handled = true;
+            return;
+        }
+
+        var useContextMenu = vm.ToolsSubViewModel.RightClickMode == RightClickMode.ContextMenu;
+        var usesErase = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool.IsErasable;
+        var usesSecondaryColor = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool.UsesColor;
+
+        if (!useContextMenu && (usesErase || usesSecondaryColor))
+        {
+            e.Handled = true;
+        }
+    }
 }

+ 44 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml

@@ -0,0 +1,44 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.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:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
+             mc:Ignorable="d" 
+             d:DesignHeight="45" d:DesignWidth="45" 
+             x:Name="uc" 
+             PointerPressed="PaletteColor_OnMouseDown"
+             PointerMoved="PaletteColor_OnMouseMove"
+             PointerReleased="PaletteColor_OnMouseUp">
+    <UserControl.Styles>
+        <Style Selector="palettes|PaletteColorControl">
+            <Setter Property="Width" Value="36"/>
+            <Setter Property="Height" Value="36"/>
+        </Style>
+    </UserControl.Styles>
+    <Grid Width="{Binding ElementName=uc, Path=Width}" Height="{Binding ElementName=uc, Path=Height}">
+        <Border CornerRadius="{Binding ElementName=uc, Path=CornerRadius}" Width="{Binding ElementName=uc, Path=Width}" Height="{Binding ElementName=uc, Path=Height}"
+                RenderOptions.BitmapInterpolationMode="None">
+            <Border.Background>
+                <VisualBrush>
+                    <VisualBrush.Visual>
+                        <Image Source="/Images/CheckerTile.png" RenderOptions.BitmapInterpolationMode="None"/>
+                    </VisualBrush.Visual>
+                </VisualBrush>
+            </Border.Background>
+        </Border>
+        <Border CornerRadius="{Binding ElementName=uc, Path=CornerRadius}" BorderThickness="0 0 0 0.1" BorderBrush="White">
+            <Border.Background>
+                <SolidColorBrush Color="{Binding Color, Converter={converters:GenericColorToMediaColorConverter}, ElementName=uc}" />
+            </Border.Background>
+        </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">
+            <TextBlock Foreground="White" FontSize="16" HorizontalAlignment="Center" Margin="1 0 0 0"
+                                        Text="{Binding AssociatedKey, ElementName=uc}"/>
+        </Border>
+    </Grid>
+</UserControl>

+ 81 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Palettes/PaletteColorControl.axaml.cs

@@ -0,0 +1,81 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using PixiEditor.Extensions.Palettes;
+
+namespace PixiEditor.Views.UserControls.Palettes;
+
+internal partial class PaletteColorControl : UserControl
+{
+    public const string PaletteColorDaoFormat = "PixiEditor.PaletteColor";
+
+    public static readonly StyledProperty<PaletteColor> ColorProperty =
+        AvaloniaProperty.Register<PaletteColorControl, PaletteColor>(nameof(Color));
+
+    public PaletteColor Color
+    {
+        get { return (PaletteColor)GetValue(ColorProperty); }
+        set { SetValue(ColorProperty, value); }
+    }
+
+    public int? AssociatedKey
+    {
+        get { return (int?)GetValue(AssociatedKeyProperty); }
+        set { SetValue(AssociatedKeyProperty, value); }
+    }
+
+    public static readonly StyledProperty<int?> AssociatedKeyProperty =
+        AvaloniaProperty.Register<PaletteColorControl, int?>(nameof(AssociatedKey));
+
+    public CornerRadius CornerRadius
+    {
+        get { return (CornerRadius)GetValue(CornerRadiusProperty); }
+        set { SetValue(CornerRadiusProperty, value); }
+    }
+
+
+    public static readonly StyledProperty<CornerRadius> CornerRadiusProperty =
+        AvaloniaProperty.Register<PaletteColorControl, CornerRadius>(nameof(CornerRadius), new CornerRadius(5f));
+
+    private Point clickPoint;
+
+    public PaletteColorControl()
+    {
+        InitializeComponent();
+    }
+
+    private void PaletteColor_OnMouseMove(object? sender, PointerEventArgs e)
+    {
+        PaletteColorControl colorControl = sender as PaletteColorControl;
+
+        bool isLeftButtonPressed = e.GetCurrentPoint(this).Properties.IsLeftButtonPressed;
+
+        if (colorControl != null && isLeftButtonPressed && e.Pointer.Captured == this)
+        {
+            var movedDistance = (clickPoint - e.GetPosition(this));
+            float length = (float)Math.Sqrt(movedDistance.X * movedDistance.X + movedDistance.Y * movedDistance.Y);
+            if (length > 10)
+            {
+                DataObject data = new DataObject();
+                data.Set(PaletteColorControl.PaletteColorDaoFormat, colorControl.Color.ToString());
+                DragDrop.DoDragDrop(e, data, DragDropEffects.Move);
+                e.Handled = true;
+            }
+        }
+    }
+
+    private void PaletteColor_OnMouseDown(object? sender, PointerPressedEventArgs e)
+    {
+        var leftPressed = e.GetCurrentPoint(this).Properties.IsLeftButtonPressed;
+        if (leftPressed)
+        {
+            clickPoint = e.GetPosition(this);
+            e.Pointer.Capture(this);
+        }
+    }
+
+    private void PaletteColor_OnMouseUp(object? sender, PointerReleasedEventArgs e)
+    {
+        e.Pointer.Capture(null);
+    }
+}

+ 0 - 3
src/PixiEditor.Zoombox/Zoombox.axaml

@@ -26,14 +26,11 @@
             <Grid.RenderTransform>
                 <TransformGroup>
                     <ScaleTransform
-                        x:Name="scaleTransform"
                         ScaleX="{Binding ElementName=uc, Path=ScaleTransformXY}"
                         ScaleY="{Binding ElementName=uc, Path=ScaleTransformXY}" />
                     <RotateTransform
-                        x:Name="rotateTransform"
                         Angle="{Binding ElementName=uc, Path=RotateTransformAngle}" />
                     <ScaleTransform
-                        x:Name="flipTransform"
                         ScaleX="{Binding ElementName=uc, Path=FlipTransformX}"
                         ScaleY="{Binding ElementName=uc, Path=FlipTransformY}" />
                 </TransformGroup>

+ 0 - 10
src/PixiEditor.Zoombox/Zoombox.axaml.cs

@@ -13,9 +13,6 @@ namespace PixiEditor.Zoombox;
 
 public partial class Zoombox : ContentControl, INotifyPropertyChanged
 {
- public static readonly StyledProperty<object> AdditionalContentProperty =
-            AvaloniaProperty.Register<Zoombox, object>(nameof(AdditionalContent));
-
         public static readonly StyledProperty<ZoomboxMode> ZoomModeProperty =
             AvaloniaProperty.Register<Zoombox, ZoomboxMode>(nameof(ZoomMode), defaultValue: ZoomboxMode.Normal);
 
@@ -49,13 +46,6 @@ public partial class Zoombox : ContentControl, INotifyPropertyChanged
     public static readonly RoutedEvent<ViewportRoutedEventArgs> ViewportMovedEvent = RoutedEvent.Register<Zoombox, ViewportRoutedEventArgs>(
         nameof(ViewportMoved), RoutingStrategies.Bubble);
 
-    [Content]
-    public object AdditionalContent
-    {
-        get => GetValue(AdditionalContentProperty);
-        set => SetValue(AdditionalContentProperty, value);
-    }
-
     public ZoomboxMode ZoomMode
     {
         get => (ZoomboxMode)GetValue(ZoomModeProperty);