瀏覽代碼

Avalonia port project upload

Krzysztof Krysiński 5 年之前
父節點
當前提交
f4b3b7ef35
共有 67 個文件被更改,包括 694 次插入548 次删除
  1. 25 0
      PixiEditor.sln
  2. 13 0
      PixiEditor/App.axaml
  3. 29 0
      PixiEditor/App.axaml.cs
  4. 二進制
      PixiEditor/Assets/avalonia-logo.ico
  5. 22 23
      PixiEditor/Helpers/Behaviours/AllowableCharactersTextBoxBehavior.cs
  6. 10 10
      PixiEditor/Helpers/Behaviours/HintTextBehavior.cs
  7. 18 17
      PixiEditor/Helpers/Behaviours/MouseBehaviour.cs
  8. 28 29
      PixiEditor/Helpers/Behaviours/TextBoxFocusBehavior.cs
  9. 2 2
      PixiEditor/Helpers/Converters/BoolToColorConverter.cs
  10. 2 2
      PixiEditor/Helpers/Converters/BoolToIntConverter.cs
  11. 2 4
      PixiEditor/Helpers/Converters/DoubleToIntConverter.cs
  12. 2 4
      PixiEditor/Helpers/Converters/FloatNormalizeConverter.cs
  13. 2 3
      PixiEditor/Helpers/Converters/ToolSizeToIntConverter.cs
  14. 11 11
      PixiEditor/Helpers/UI/ReversedOrderStackPanel.cs
  15. 9 0
      PixiEditor/Models/Colors/ConstColors.cs
  16. 2 2
      PixiEditor/Models/Colors/ExColor.cs
  17. 11 19
      PixiEditor/Models/Controllers/BitmapManager.cs
  18. 4 8
      PixiEditor/Models/Controllers/BitmapOperationsUtility.cs
  19. 35 19
      PixiEditor/Models/Controllers/ClipboardController.cs
  20. 48 0
      PixiEditor/Models/Controllers/Keyboard.cs
  21. 0 1
      PixiEditor/Models/Controllers/MouseMovementController.cs
  22. 1 1
      PixiEditor/Models/Controllers/PixelChangesController.cs
  23. 6 4
      PixiEditor/Models/Controllers/Shortcuts/Shortcut.cs
  24. 4 3
      PixiEditor/Models/Controllers/Shortcuts/ShortcutController.cs
  25. 1 1
      PixiEditor/Models/DataHolders/BitmapPixelChanges.cs
  26. 8 7
      PixiEditor/Models/DataHolders/Document.cs
  27. 5 7
      PixiEditor/Models/DataHolders/Selection.cs
  28. 1 1
      PixiEditor/Models/DataHolders/SerializableDocument.cs
  29. 2 2
      PixiEditor/Models/Dialogs/CustomDialog.cs
  30. 4 3
      PixiEditor/Models/Dialogs/ExportFileDialog.cs
  31. 3 3
      PixiEditor/Models/Dialogs/ImportFileDialog.cs
  32. 4 4
      PixiEditor/Models/Dialogs/NewFileDialog.cs
  33. 3 3
      PixiEditor/Models/Dialogs/ResizeDocumentDialog.cs
  34. 8 15
      PixiEditor/Models/IO/Exporter.cs
  35. 8 7
      PixiEditor/Models/IO/Importer.cs
  36. 6 9
      PixiEditor/Models/ImageManipulation/BitmapUtils.cs
  37. 4 4
      PixiEditor/Models/Layers/BasicLayer.cs
  38. 22 20
      PixiEditor/Models/Layers/Layer.cs
  39. 23 28
      PixiEditor/Models/Position/CoordinatesCalculator.cs
  40. 2 1
      PixiEditor/Models/Tools/BitmapOperationTool.cs
  41. 3 4
      PixiEditor/Models/Tools/ShapeTool.cs
  42. 6 5
      PixiEditor/Models/Tools/Tool.cs
  43. 10 13
      PixiEditor/Models/Tools/ToolSettings/Settings/BoolSetting.cs
  44. 2 2
      PixiEditor/Models/Tools/ToolSettings/Settings/ColorSetting.cs
  45. 8 13
      PixiEditor/Models/Tools/ToolSettings/Settings/DropdownSetting.cs
  46. 1 1
      PixiEditor/Models/Tools/ToolSettings/Settings/FloatSetting.cs
  47. 5 3
      PixiEditor/Models/Tools/ToolSettings/Settings/Setting.cs
  48. 8 6
      PixiEditor/Models/Tools/ToolSettings/Settings/SizeSetting.cs
  49. 1 1
      PixiEditor/Models/Tools/ToolType.cs
  50. 2 4
      PixiEditor/Models/Tools/Tools/BrightnessTool.cs
  51. 49 66
      PixiEditor/Models/Tools/Tools/CircleTool.cs
  52. 0 2
      PixiEditor/Models/Tools/Tools/ColorPickerTool.cs
  53. 35 0
      PixiEditor/Models/Tools/Tools/EarserTool.cs
  54. 1 2
      PixiEditor/Models/Tools/Tools/FloodFill.cs
  55. 1 2
      PixiEditor/Models/Tools/Tools/LineTool.cs
  56. 9 7
      PixiEditor/Models/Tools/Tools/MoveTool.cs
  57. 3 2
      PixiEditor/Models/Tools/Tools/PenTool.cs
  58. 1 1
      PixiEditor/Models/Tools/Tools/RectangleTool.cs
  59. 1 3
      PixiEditor/Models/Tools/Tools/SelectTool.cs
  60. 11 67
      PixiEditor/PixiEditor.csproj
  61. 24 0
      PixiEditor/Program.cs
  62. 32 0
      PixiEditor/ViewLocator.cs
  63. 3 23
      PixiEditor/ViewModels/ViewModelBase.cs
  64. 37 44
      PixiEditor/ViewModels/ViewModelMain.cs
  65. 17 0
      PixiEditor/Views/MainWindow.axaml
  66. 23 0
      PixiEditor/Views/MainWindow.axaml.cs
  67. 11 0
      PixiEditor/nuget.config

+ 25 - 0
PixiEditor.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30320.27
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor", "PixiEditor\PixiEditor.csproj", "{BF1A561F-842C-44CB-AC6B-2AEA16647FD3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BF1A561F-842C-44CB-AC6B-2AEA16647FD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF1A561F-842C-44CB-AC6B-2AEA16647FD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BF1A561F-842C-44CB-AC6B-2AEA16647FD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BF1A561F-842C-44CB-AC6B-2AEA16647FD3}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {A95E9B9E-EF1E-44DE-A004-A7343C0EC00D}
+	EndGlobalSection
+EndGlobal

+ 13 - 0
PixiEditor/App.axaml

@@ -0,0 +1,13 @@
+<Application xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:PixiEditor"
+             x:Class="PixiEditor.App">
+    <Application.DataTemplates>
+        <local:ViewLocator/>
+    </Application.DataTemplates>
+
+    <Application.Styles>
+        <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
+        <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
+    </Application.Styles>
+</Application>

+ 29 - 0
PixiEditor/App.axaml.cs

@@ -0,0 +1,29 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using PixiEditor.ViewModels;
+using PixiEditor.Views;
+
+namespace PixiEditor
+{
+    public class App : Application
+    {
+        public override void Initialize()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+
+        public override void OnFrameworkInitializationCompleted()
+        {
+            if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                desktop.MainWindow = new MainWindow
+                {
+                    DataContext = new MainWindowViewModel(),
+                };
+            }
+
+            base.OnFrameworkInitializationCompleted();
+        }
+    }
+}

二進制
PixiEditor/Assets/avalonia-logo.ico


+ 22 - 23
PixiEditor/Helpers/Behaviours/AllowableCharactersTextBoxBehavior.cs

@@ -1,21 +1,20 @@
-using System;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Xaml.Interactivity;
+using AvaloniaPlayground.Models;
+using System;
 using System.Text.RegularExpressions;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Interactivity;
 
 namespace PixiEditor.Helpers.Behaviours
 {
     public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
     {
-        public static readonly DependencyProperty RegularExpressionProperty =
-            DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),
-                new FrameworkPropertyMetadata(".*"));
+        public static readonly StyledProperty<string> RegularExpressionProperty =
+            AvaloniaProperty.Register<AllowableCharactersTextBoxBehavior, string>(nameof(RegularExpression), ".*");
 
-        public static readonly DependencyProperty MaxLengthProperty =
-            DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),
-                new FrameworkPropertyMetadata(int.MinValue));
+        public static readonly StyledProperty<int> MaxLengthProperty =
+            AvaloniaProperty.Register<AllowableCharactersTextBoxBehavior, int>(nameof(MaxLength), int.MinValue);
 
         public string RegularExpression
         {
@@ -32,25 +31,25 @@ namespace PixiEditor.Helpers.Behaviours
         protected override void OnAttached()
         {
             base.OnAttached();
-            AssociatedObject.PreviewTextInput += OnPreviewTextInput;
-            DataObject.AddPastingHandler(AssociatedObject, OnPaste);
+            AssociatedObject.TextInput += OnTextInput;
+            AssociatedObject.KeyDown += OnKeyDown;
         }
 
-        private void OnPaste(object sender, DataObjectPastingEventArgs e)
+        private void OnKeyDown(object sender, KeyEventArgs e)
         {
-            if (e.DataObject.GetDataPresent(DataFormats.Text))
+            if (e.Key == Key.V && e.KeyModifiers == KeyModifiers.Control)
             {
-                string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
+                string text = Convert.ToString(Application.Current.Clipboard.GetTextAsync());
 
-                if (!IsValid(text, true)) e.CancelCommand();
+                if (!IsValid(text, true)) e.Handled = true;
             }
             else
             {
-                e.CancelCommand();
+                e.Handled = true;
             }
         }
 
-        private void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
+        private void OnTextInput(object sender, TextInputEventArgs e)
         {
             e.Handled = !IsValid(e.Text, false);
         }
@@ -58,8 +57,8 @@ namespace PixiEditor.Helpers.Behaviours
         protected override void OnDetaching()
         {
             base.OnDetaching();
-            AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
-            DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
+            AssociatedObject.TextInput -= OnTextInput;
+            AssociatedObject.KeyDown -= OnKeyDown;
         }
 
         private bool IsValid(string newText, bool paste)
@@ -76,7 +75,7 @@ namespace PixiEditor.Helpers.Behaviours
 
         private int LengthOfModifiedText(string newText, bool paste)
         {
-            var countOfSelectedChars = AssociatedObject.SelectedText.Length;
+            var countOfSelectedChars = AssociatedObject.SelectionEnd - AssociatedObject.SelectionStart;
             var caretIndex = AssociatedObject.CaretIndex;
             string text = AssociatedObject.Text;
 
@@ -86,7 +85,7 @@ namespace PixiEditor.Helpers.Behaviours
                 return text.Length + newText.Length;
             }
 
-            var insert = Keyboard.IsKeyToggled(Key.Insert);
+            var insert = Keyboard.IsKeyPressed(Key.Insert);
 
             return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
         }

+ 10 - 10
PixiEditor/Helpers/Behaviours/HintTextBehavior.cs

@@ -1,22 +1,22 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Interactivity;
-using System.Windows.Media;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Media;
+using Avalonia.Xaml.Interactivity;
 
 namespace PixiEditor.Helpers.Behaviours
 {
     internal class HintTextBehavior : Behavior<TextBox>
     {
-        // Using a DependencyProperty as the backing store for Hint.  This enables animation, styling, binding, etc...
-        public static readonly DependencyProperty HintProperty =
-            DependencyProperty.Register("Hint", typeof(string), typeof(HintTextBehavior),
-                new PropertyMetadata(string.Empty));
+        // Using a StyledProperty as the backing store for Hint.  This enables animation, styling, binding, etc...
+        public static readonly StyledProperty<string> HintProperty =
+            AvaloniaProperty.Register<TextBox, string>(nameof(Hint));
 
         private Brush _textColor;
 
         public string Hint
         {
-            get => (string) GetValue(HintProperty);
+            get => GetValue(HintProperty);
             set => SetValue(HintProperty, value);
         }
 
@@ -26,7 +26,7 @@ namespace PixiEditor.Helpers.Behaviours
             base.OnAttached();
             AssociatedObject.GotFocus += AssociatedObject_GotFocus;
             AssociatedObject.LostFocus += AssociatedObject_LostFocus;
-            _textColor = AssociatedObject.Foreground;
+            _textColor = (Brush)AssociatedObject.Foreground;
             SetHint(true);
         }
 

+ 18 - 17
PixiEditor/Helpers/Behaviours/MouseBehaviour.cs

@@ -1,21 +1,22 @@
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Interactivity;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Xaml.Interactivity;
+using System;
 
 namespace PixiEditor.Helpers.Behaviours
 {
-    public class MouseBehaviour : Behavior<FrameworkElement>
+    public class MouseBehaviour : Behavior<Control>
     {
-        public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
-            "MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
+        public static readonly StyledProperty<double> MouseYProperty = AvaloniaProperty.Register<MouseBehaviour, double>(
+            nameof(MouseY), default);
 
-        public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
-            "MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
+        public static readonly StyledProperty<double> MouseXProperty = AvaloniaProperty.Register<MouseBehaviour, double>(
+            nameof(MouseX), default);
 
         // Using a DependencyProperty as the backing store for RelativeTo.  This enables animation, styling, binding, etc...
-        public static readonly DependencyProperty RelativeToProperty =
-            DependencyProperty.Register("RelativeTo", typeof(FrameworkElement), typeof(MouseBehaviour),
-                new PropertyMetadata(default(FrameworkElement)));
+        public static readonly StyledProperty<Control> RelativeToProperty =
+            AvaloniaProperty.Register<MouseBehaviour, Control>(nameof(MouseY), default);
 
         public double MouseY
         {
@@ -30,29 +31,29 @@ namespace PixiEditor.Helpers.Behaviours
         }
 
 
-        public FrameworkElement RelativeTo
+        public Control RelativeTo
         {
-            get => (FrameworkElement) GetValue(RelativeToProperty);
+            get => (Control) GetValue(RelativeToProperty);
             set => SetValue(RelativeToProperty, value);
         }
 
 
         protected override void OnAttached()
         {
-            AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
+            AssociatedObject.PointerMoved += AssociatedObjectOnMouseMove;
         }
 
-        private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
+        private void AssociatedObjectOnMouseMove(object sender, PointerEventArgs e)
         {
             if (RelativeTo == null) RelativeTo = AssociatedObject;
-            var pos = mouseEventArgs.GetPosition(RelativeTo);
+            var pos = e.GetPosition(RelativeTo);
             MouseX = pos.X;
             MouseY = pos.Y;
         }
 
         protected override void OnDetaching()
         {
-            AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
+            AssociatedObject.PointerMoved -= AssociatedObjectOnMouseMove;
         }
     }
 }

+ 28 - 29
PixiEditor/Helpers/Behaviours/TextBoxFocusBehavior.cs

@@ -1,17 +1,17 @@
-using System.Text.RegularExpressions;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Interactivity;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Xaml.Interactivity;
+using System.Text.RegularExpressions;
 
 namespace PixiEditor.Helpers.Behaviours
 {
     internal class TextBoxFocusBehavior : Behavior<TextBox>
     {
-        // Using a DependencyProperty as the backing store for FillSize.  This enables animation, styling, binding, etc...
-        public static readonly DependencyProperty FillSizeProperty =
-            DependencyProperty.Register("FillSize", typeof(bool), typeof(TextBoxFocusBehavior),
-                new PropertyMetadata(false));
+        // Using a StyledProperty as the backing store for FillSize.  This enables animation, styling, binding, etc...
+        public static readonly StyledProperty<bool> FillSizeProperty =
+            AvaloniaProperty.Register<TextBoxFocusBehavior, bool>(nameof(FillSize), false);
 
 
         private string _oldText; //Value of textbox before editing
@@ -29,33 +29,31 @@ namespace PixiEditor.Helpers.Behaviours
             if (e.Key != Key.Enter) return;
 
             ConvertValue();
-            AssociatedObject.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
+            FocusManager.Instance.Focus(null);
         }
 
         protected override void OnAttached()
         {
             base.OnAttached();
-            AssociatedObject.GotKeyboardFocus += AssociatedObjectGotKeyboardFocus;
-            AssociatedObject.GotMouseCapture += AssociatedObjectGotMouseCapture;
-            AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
-            AssociatedObject.LostKeyboardFocus += AssociatedObject_LostKeyboardFocus;
+            AssociatedObject.GotFocus += AssociatedObjectGotKeyboardFocus;
+            AssociatedObject.PointerPressed += AssociatedObjectGotMouseCapture;
+            AssociatedObject.LostFocus += AssociatedObject_LostKeyboardFocus;
             AssociatedObject.KeyUp += AssociatedObject_KeyUp;
         }
 
         protected override void OnDetaching()
         {
             base.OnDetaching();
-            AssociatedObject.GotKeyboardFocus -= AssociatedObjectGotKeyboardFocus;
-            AssociatedObject.GotMouseCapture -= AssociatedObjectGotMouseCapture;
-            AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
-            AssociatedObject.LostKeyboardFocus -= AssociatedObject_LostKeyboardFocus;
+            AssociatedObject.GotFocus -= AssociatedObjectGotKeyboardFocus;
+            AssociatedObject.PointerPressed -= AssociatedObjectGotMouseCapture;
+            AssociatedObject.LostFocus -= AssociatedObject_LostKeyboardFocus;
             AssociatedObject.KeyUp -= AssociatedObject_KeyUp;
         }
 
         private void AssociatedObjectGotKeyboardFocus(object sender,
-            KeyboardFocusChangedEventArgs e)
+            GotFocusEventArgs e)
         {
-            AssociatedObject.SelectAll();
+            SelectAll();
             if (FillSize)
             {
                 _valueConverted = false;
@@ -63,22 +61,23 @@ namespace PixiEditor.Helpers.Behaviours
             }
         }
 
-        private void AssociatedObjectGotMouseCapture(object sender,
-            MouseEventArgs e)
+        private void AssociatedObjectGotMouseCapture(object sender, PointerPressedEventArgs e)
         {
-            AssociatedObject.SelectAll();
-        }
-
-        private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
-        {
-            if (!AssociatedObject.IsKeyboardFocusWithin)
+            if (!AssociatedObject.IsFocused)
             {
                 AssociatedObject.Focus();
                 e.Handled = true;
             }
+            SelectAll();
+        }
+
+        private void SelectAll()
+        {
+            AssociatedObject.SelectionStart = 0;
+            AssociatedObject.SelectionEnd = AssociatedObject.Text.Length;
         }
 
-        private void AssociatedObject_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
+        private void AssociatedObject_LostKeyboardFocus(object sender, RoutedEventArgs e)
         {
             ConvertValue();
         }

+ 2 - 2
PixiEditor/Helpers/Converters/BoolToColorConverter.cs

@@ -1,6 +1,6 @@
-using System;
+using Avalonia.Data.Converters;
+using System;
 using System.Globalization;
-using System.Windows.Data;
 
 namespace PixiEditor.Helpers.Converters
 {

+ 2 - 2
PixiEditor/Helpers/Converters/BoolToIntConverter.cs

@@ -1,6 +1,6 @@
-using System;
+using Avalonia.Data.Converters;
+using System;
 using System.Globalization;
-using System.Windows.Data;
 
 namespace PixiEditor.Helpers.Converters
 {

+ 2 - 4
PixiEditor/Helpers/Converters/DoubleToIntConverter.cs

@@ -1,8 +1,6 @@
-using System;
-using System.Collections.Generic;
+using Avalonia.Data.Converters;
+using System;
 using System.Globalization;
-using System.Text;
-using System.Windows.Data;
 
 namespace PixiEditor.Helpers.Converters
 {

+ 2 - 4
PixiEditor/Helpers/Converters/FloatNormalizeConverter.cs

@@ -1,8 +1,6 @@
-using System;
-using System.Collections.Generic;
+using Avalonia.Data.Converters;
+using System;
 using System.Globalization;
-using System.Text;
-using System.Windows.Data;
 
 namespace PixiEditor.Helpers.Converters
 {

+ 2 - 3
PixiEditor/Helpers/Converters/ToolSizeToIntConverter.cs

@@ -1,12 +1,11 @@
-using System;
+using Avalonia.Data.Converters;
+using System;
 using System.Globalization;
 using System.Linq;
 using System.Text.RegularExpressions;
-using System.Windows.Data;
 
 namespace PixiEditor.Helpers
 {
-    [ValueConversion(typeof(string), typeof(int))]
     internal class ToolSizeToIntConverter : IValueConverter
     {
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

+ 11 - 11
PixiEditor/Helpers/UI/ReversedOrderStackPanel.cs

@@ -1,7 +1,9 @@
-using System;
+using Avalonia;
+using Avalonia.Controls;
+using System;
 using System.Linq;
 using System.Windows;
-using System.Windows.Controls;
+
 
 namespace PixiEditor.Helpers.UI
 {
@@ -9,29 +11,27 @@ namespace PixiEditor.Helpers.UI
     {
         protected override Size ArrangeOverride(Size arrangeSize)
         {
-            bool fHorizontal = Orientation == Orientation.Horizontal;
+            bool fHorizontal = Orientation == Avalonia.Layout.Orientation.Horizontal;
             var rcChild = new Rect(arrangeSize);
             double previousChildSize = 0.0;
 
-            var children = InternalChildren.Cast<UIElement>().Reverse();
-            foreach (UIElement child in children)
+            var children = Children.Cast<Control>().Reverse();
+            foreach (Control child in children)
             {
                 if (child == null)
                     continue;
 
                 if (fHorizontal)
                 {
-                    rcChild.X += previousChildSize;
+                    rcChild = new Rect(rcChild.X + previousChildSize, rcChild.Y, rcChild.Width, rcChild.Height);
                     previousChildSize = child.DesiredSize.Width;
-                    rcChild.Width = previousChildSize;
-                    rcChild.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
+                    rcChild = new Rect(rcChild.X, rcChild.Y, previousChildSize, Math.Max(arrangeSize.Height, child.DesiredSize.Height));
                 }
                 else
                 {
-                    rcChild.Y += previousChildSize;
+                    rcChild = new Rect(rcChild.X, rcChild.Y + previousChildSize, rcChild.Width, rcChild.Height);
                     previousChildSize = child.DesiredSize.Height;
-                    rcChild.Height = previousChildSize;
-                    rcChild.Width = Math.Max(arrangeSize.Width, child.DesiredSize.Width);
+                    rcChild = new Rect(rcChild.X, rcChild.Y, Math.Max(arrangeSize.Width, child.DesiredSize.Width), previousChildSize);
                 }
 
                 child.Arrange(rcChild);

+ 9 - 0
PixiEditor/Models/Colors/ConstColors.cs

@@ -0,0 +1,9 @@
+using Avalonia.Media;
+
+namespace PixiEditor.Models.Colors
+{
+    public static class ConstColors
+    {
+        public static Color Transparent { get; } = Color.FromArgb(0, 0, 0, 0);
+    }
+}

+ 2 - 2
PixiEditor/Models/Colors/ExColor.cs

@@ -1,5 +1,5 @@
-using System;
-using System.Windows.Media;
+using Avalonia.Media;
+using System;
 
 namespace PixiEditor.Models.Colors
 {

+ 11 - 19
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -1,10 +1,9 @@
 using System;
 using System.Linq;
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Helpers;
+using Avalonia;
+using Avalonia.Input;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Events;
@@ -12,31 +11,24 @@ using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Controllers
 {
-    public class BitmapManager : NotifyableObject
+    public class BitmapManager : ReactiveObject
     {
         public MouseMovementController MouseController { get; set; }
 
         public Tool SelectedTool
         {
             get => _selectedTool;
-            private set
-            {
-                _selectedTool = value;
-                RaisePropertyChanged("SelectedTool");
-            }
+            private set => this.RaiseAndSetIfChanged(ref _selectedTool, value);
         }
 
         public Layer PreviewLayer
         {
             get => _previewLayer;
-            set
-            {
-                _previewLayer = value;
-                RaisePropertyChanged("PreviewLayer");
-            }
+            set => this.RaiseAndSetIfChanged(ref _previewLayer, value);
         }
 
         public Layer ActiveLayer => ActiveDocument.ActiveLayer;
@@ -56,7 +48,7 @@ namespace PixiEditor.Models.Controllers
             set
             {
                 _activeDocument = value;
-                RaisePropertyChanged("ActiveDocument");
+                this.RaisePropertyChanged("ActiveDocument");
                 DocumentChanged?.Invoke(this, new DocumentChangedEventArgs(value));
             }
         }
@@ -98,7 +90,7 @@ namespace PixiEditor.Models.Controllers
 
         public void AddNewLayer(string name, WriteableBitmap bitmap, bool setAsActive = true)
         {
-            AddNewLayer(name, bitmap.PixelWidth, bitmap.PixelHeight, setAsActive);
+            AddNewLayer(name, bitmap.PixelSize.Width, bitmap.PixelSize.Height, setAsActive);
             ActiveDocument.Layers.Last().LayerBitmap = bitmap;
         }
 
@@ -217,7 +209,7 @@ namespace PixiEditor.Models.Controllers
 
         public WriteableBitmap GetCombinedLayersBitmap()
         {
-            return BitmapUtils.CombineLayers(ActiveDocument.Layers.Where(x => x.IsVisible).ToArray(), ActiveDocument.Width, ActiveDocument.Height);
+            return BitmapUtils.CombineLayers(ActiveDocument.Layers.ToArray(), ActiveDocument.Width, ActiveDocument.Height);
         }
 
         /// <summary>

+ 4 - 8
PixiEditor/Models/Controllers/BitmapOperationsUtility.cs

@@ -1,9 +1,9 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
+using Avalonia.Input;
+using Avalonia.Media;
+using AvaloniaPlayground.Models;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
@@ -82,7 +82,7 @@ namespace PixiEditor.Models.Controllers
 
         private void UseTool(List<Coordinates> mouseMoveCords, BitmapOperationTool tool, Color color)
         {
-            if (Keyboard.IsKeyDown(Key.LeftShift) && !MouseCordsNotInLine(mouseMoveCords))
+            if (Keyboard.IsKeyPressed(Key.LeftShift) && !MouseCordsNotInLine(mouseMoveCords))
                 mouseMoveCords = GetSquareCoordiantes(mouseMoveCords);
             if (!tool.RequiresPreviewLayer)
             {
@@ -138,16 +138,12 @@ namespace PixiEditor.Models.Controllers
         private BitmapPixelChanges GetOldPixelsValues(Coordinates[] coordinates)
         {
             Dictionary<Coordinates, Color> values = new Dictionary<Coordinates, Color>();
-            using (Manager.ActiveLayer.LayerBitmap.GetBitmapContext(ReadWriteMode.ReadOnly))
-            {
                 var relativeCoords = Manager.ActiveLayer.ConvertToRelativeCoordinates(coordinates);
                 for (int i = 0; i < coordinates.Length; i++)
                 {
                     values.Add(coordinates[i],
                         Manager.ActiveLayer.GetPixel(relativeCoords[i].X, relativeCoords[i].Y));
                 }
-
-            }
             return new BitmapPixelChanges(values);
         }
 

+ 35 - 19
PixiEditor/Models/Controllers/ClipboardController.cs

@@ -1,12 +1,15 @@
 using System.IO;
 using System.Linq;
-using System.Windows;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.DataHolders;
+using System.Linq.Expressions;
+using Avalonia;
+using Avalonia.Input;
+using Avalonia.Input.Platform;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditor.ViewModels;
+using SharpDX.WIC;
 
 namespace PixiEditor.Models.Controllers
 {
@@ -21,21 +24,30 @@ namespace PixiEditor.Models.Controllers
         /// <param name="originalImageHeight"></param>
         public static void CopyToClipboard(Layer[] layers, Coordinates[] selection, int originalImageWidth, int originalImageHeight)
         {
-            Clipboard.Clear();
+            var clipboard = (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard));
             WriteableBitmap combinedBitmaps = BitmapUtils.CombineLayers(layers, originalImageWidth, originalImageHeight);
             using (var pngStream = new MemoryStream())
             {
-                DataObject data = new DataObject();
+                DataObject data = new ClipboardDataObject();
                 var croppedBmp = BitmapSelectionToBmpSource(combinedBitmaps, selection);
                 data.SetData(DataFormats.Bitmap, croppedBmp, true); //Bitmap, no transparency support
 
-                PngBitmapEncoder encoder = new PngBitmapEncoder();
-                encoder.Frames.Add(BitmapFrame.Create(croppedBmp));
-                encoder.Save(pngStream);
-                data.SetData("PNG", pngStream, false); //PNG, supports transparency
+                using (var bmpData = croppedBmp.Lock())
+                {
+                    var format = PixelFormat.FormatDontCare;
+                    PngBitmapEncoder encoder = new PngBitmapEncoder(new ImagingFactory(bmpData.Address), pngStream);
+                    BitmapFrameEncode frameEncode = new BitmapFrameEncode(encoder);
+                    frameEncode.Initialize();
+                    frameEncode.SetSize(bmpData.Size.Width, bmpData.Size.Height);
+                    frameEncode.SetPixelFormat(ref format);
+                    frameEncode.WritePixels(bmpData.Size.Height, new SharpDX.DataRectangle(bmpData.Address, 4 * sizeof(ushort)));
+                    frameEncode.Commit();
+                    encoder.Commit();
+                    data.SetData("PNG", pngStream, false); //PNG, supports transparency
 
-                Clipboard.SetImage(croppedBmp); //DIB format
-                Clipboard.SetDataObject(data, true);
+                    Clipboard.SetImage(croppedBmp); //DIB format
+                    Clipboard.SetDataObject(data, true);
+                }
             }
         }
 
@@ -61,9 +73,13 @@ namespace PixiEditor.Models.Controllers
                 {
                     if (pngStream != null)
                     {
-                        PngBitmapDecoder decoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.IgnoreImageCache,
-                            BitmapCacheOption.OnLoad);
-                        finalImage = new WriteableBitmap(decoder.Frames[0].Clone());
+                        var imagingFactory = new ImagingFactory2();
+                        PngBitmapDecoder decoder = new PngBitmapDecoder(imagingFactory);
+                        decoder.Initialize(new WICStream(new ImagingFactory2(), pngStream), DecodeOptions.CacheOnLoad);
+                        var frame = decoder.GetFrame(0);
+                        byte[] output = new byte[4 * frame.Size.Width * frame.Size.Height];
+                        frame.CopyPixels(output, 4);
+                        return BitmapFactory.New(frame.Size.Width, frame.Size.Height).FromByteArray(output);
                     }
                 }
             else if (dao.GetDataPresent(DataFormats.Dib))
@@ -76,10 +92,10 @@ namespace PixiEditor.Models.Controllers
 
         public static bool IsImageInClipboard()
         {
-            DataObject dao = (DataObject) Clipboard.GetDataObject();
+            DataObject dao = (DataObject)Application.Current.Clipboard.GetDataObject();
             if (dao == null) return false;
-            return dao.GetDataPresent("PNG") || dao.GetDataPresent(DataFormats.Dib) ||
-                   dao.GetDataPresent(DataFormats.Bitmap);
+            return dao.Contains("PNG") || dao.Contains("Dib") ||
+                   dao.Contains("Bitmap");
         }
 
         private static void AddImageToLayers(WriteableBitmap image)
@@ -87,7 +103,7 @@ namespace PixiEditor.Models.Controllers
             ViewModelMain.Current.BitmapManager.AddNewLayer("Image", image);
         }
 
-        public static BitmapSource BitmapSelectionToBmpSource(WriteableBitmap bitmap, Coordinates[] selection)
+        public static WriteableBitmap BitmapSelectionToBmpSource(WriteableBitmap bitmap, Coordinates[] selection)
         {
             int offsetX = selection.Min(x => x.X);
             int offsetY = selection.Min(x => x.Y);

+ 48 - 0
PixiEditor/Models/Controllers/Keyboard.cs

@@ -0,0 +1,48 @@
+using Avalonia.Input;
+using System.Collections.Generic;
+
+namespace AvaloniaPlayground.Models
+{
+    public static class Keyboard
+    {
+        public static HashSet<Key> Keys { get; set; } = new HashSet<Key>();
+        public static KeyModifiers Modifiers { get; private set; } = KeyModifiers.None;
+
+        public static void AddKeyPressed(Key key)
+        {
+            if (!Keys.Contains(key))
+            {
+                Keys.Add(key);
+            }
+        }
+
+        public static void RemoveKeyPressed(Key key)
+        {
+            if (Keys.Contains(key))
+            {
+                Keys.Remove(key);
+            }
+        }
+
+        public static bool IsKeyPressed(Key key)
+        {
+            return Keys.Contains(key);
+        }
+
+        public static void AddKeyModifiersPressed(KeyModifiers modifiers)
+        {
+            if (!Modifiers.HasFlag(modifiers))
+            {
+                Modifiers |= modifiers;
+            }
+        }
+
+        public static void RemoveModifierPressed(KeyModifiers modifiers)
+        {
+            if (Modifiers.HasFlag(modifiers))
+            {
+                Modifiers &= ~modifiers;
+            }
+        }
+    }
+}

+ 0 - 1
PixiEditor/Models/Controllers/MouseMovementController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using Accessibility;
 using PixiEditor.Models.Position;
 
 namespace PixiEditor.Models.Controllers

+ 1 - 1
PixiEditor/Models/Controllers/PixelChangesController.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Media;
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;

+ 6 - 4
PixiEditor/Models/Controllers/Shortcuts/Shortcut.cs

@@ -1,16 +1,18 @@
-using System.Windows.Input;
+using Avalonia.Input;
+using ReactiveUI;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Controllers.Shortcuts
 {
     public class Shortcut
     {
         public Key ShortcutKey { get; set; }
-        public ModifierKeys Modifier { get; set; }
+        public KeyModifiers Modifier { get; set; }
         public ICommand Command { get; set; }
         public object CommandParameter { get; set; }
 
         public Shortcut(Key shortcutKey, ICommand command, object commandParameter = null,
-            ModifierKeys modifier = ModifierKeys.None)
+            KeyModifiers modifier = KeyModifiers.None)
         {
             ShortcutKey = shortcutKey;
             Modifier = modifier;
@@ -19,7 +21,7 @@ namespace PixiEditor.Models.Controllers.Shortcuts
         }
 
         public void Execute()
-        {
+        {            
             if (Command.CanExecute(CommandParameter)) Command.Execute(CommandParameter);
         }
     }

+ 4 - 3
PixiEditor/Models/Controllers/Shortcuts/ShortcutController.cs

@@ -1,6 +1,7 @@
-using System.Collections.Generic;
+using Avalonia.Input;
+using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Input;
+
 
 namespace PixiEditor.Models.Controllers.Shortcuts
 {
@@ -16,7 +17,7 @@ namespace PixiEditor.Models.Controllers.Shortcuts
             Shortcuts = new List<Shortcut>();
         }
 
-        public void KeyPressed(Key key, ModifierKeys modifiers)
+        public void KeyPressed(Key key, KeyModifiers modifiers)
         {
             if (!BlockShortcutExecution)
             {

+ 1 - 1
PixiEditor/Models/DataHolders/BitmapPixelChanges.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Media;
+using Avalonia.Media;
 using PixiEditor.Exceptions;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.Position;

+ 8 - 7
PixiEditor/Models/DataHolders/Document.cs

@@ -3,8 +3,8 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Windows;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
+using Avalonia;
+using Avalonia.Media;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
@@ -12,10 +12,11 @@ using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.Tools;
 using PixiEditor.ViewModels;
+using ReactiveUI;
 
 namespace PixiEditor.Models.DataHolders
 {
-    public class Document : NotifyableObject
+    public class Document : ReactiveObject
     {
         public int Width
         {
@@ -23,7 +24,7 @@ namespace PixiEditor.Models.DataHolders
             set
             {
                 _width = value;
-                RaisePropertyChanged("Width");
+                this.RaisePropertyChanged("Width");
             }
         }
 
@@ -33,7 +34,7 @@ namespace PixiEditor.Models.DataHolders
             set
             {
                 _height = value;
-                RaisePropertyChanged("Height");
+                this.RaisePropertyChanged("Height");
             }
         }
 
@@ -47,8 +48,8 @@ namespace PixiEditor.Models.DataHolders
             set
             {
                 _activeLayerIndex = value;
-                RaisePropertyChanged("ActiveLayerIndex");
-                RaisePropertyChanged("ActiveLayer");
+                this.RaisePropertyChanged("ActiveLayerIndex");
+                this.RaisePropertyChanged("ActiveLayer");
             }
         }
 

+ 5 - 7
PixiEditor/Models/DataHolders/Selection.cs

@@ -1,16 +1,14 @@
 using System.Collections.ObjectModel;
 using System.Linq;
-using System.Windows.Media;
-using PixiEditor.Helpers;
+using Avalonia.Media;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditor.Models.Tools;
-using PixiEditor.ViewModels;
+using ReactiveUI;
 
 namespace PixiEditor.Models.DataHolders
 {
-    public class Selection : NotifyableObject
+    public class Selection : ReactiveObject
     {
         public ObservableCollection<Coordinates> SelectedPoints { get; private set; }
 
@@ -20,7 +18,7 @@ namespace PixiEditor.Models.DataHolders
             set
             {
                 _selectionLayer = value;
-                RaisePropertyChanged("SelectionLayer");
+                this.RaisePropertyChanged("SelectionLayer");
             }
         }
 
@@ -48,7 +46,7 @@ namespace PixiEditor.Models.DataHolders
                     break;
                 case SelectionType.Subtract:
                     SelectedPoints = new ObservableCollection<Coordinates>(SelectedPoints.Except(selection));
-                    selectionColor = System.Windows.Media.Colors.Transparent;
+                    selectionColor = Color.FromArgb(0,0,0,0);
                     break;
             }
 

+ 1 - 1
PixiEditor/Models/DataHolders/SerializableDocument.cs

@@ -2,7 +2,7 @@
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Windows;
-using System.Windows.Media;
+
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 

+ 2 - 2
PixiEditor/Models/Dialogs/CustomDialog.cs

@@ -1,8 +1,8 @@
-using PixiEditor.Helpers;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Dialogs
 {
-    public abstract class CustomDialog : NotifyableObject
+    public abstract class CustomDialog : ReactiveObject
     {
         public abstract bool ShowDialog();
     }

+ 4 - 3
PixiEditor/Models/Dialogs/ExportFileDialog.cs

@@ -1,4 +1,5 @@
 using System.Windows;
+using Avalonia;
 using PixiEditor.Views;
 
 namespace PixiEditor.Models.Dialogs
@@ -13,7 +14,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_fileWidth != value)
                 {
                     _fileWidth = value;
-                    RaisePropertyChanged("Width");
+                    this.RaisePropertyChanged("Width");
                 }
             }
         }
@@ -26,7 +27,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_fileHeight != value)
                 {
                     _fileHeight = value;
-                    RaisePropertyChanged("FileHeight");
+                    this.RaisePropertyChanged("FileHeight");
                 }
             }
         }
@@ -39,7 +40,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_filePath != value)
                 {
                     _filePath = value;
-                    RaisePropertyChanged("FilePath");
+                    this.RaisePropertyChanged("FilePath");
                 }
             }
         }

+ 3 - 3
PixiEditor/Models/Dialogs/ImportFileDialog.cs

@@ -12,7 +12,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_fileWidth != value)
                 {
                     _fileWidth = value;
-                    RaisePropertyChanged("Width");
+                    this.RaisePropertyChanged("Width");
                 }
             }
         }
@@ -25,7 +25,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_fileHeight != value)
                 {
                     _fileHeight = value;
-                    RaisePropertyChanged("FileHeight");
+                    this.RaisePropertyChanged("FileHeight");
                 }
             }
         }
@@ -38,7 +38,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_filePath != value)
                 {
                     _filePath = value;
-                    RaisePropertyChanged("FilePath");
+                    this.RaisePropertyChanged("FilePath");
                 }
             }
         }

+ 4 - 4
PixiEditor/Models/Dialogs/NewFileDialog.cs

@@ -1,5 +1,5 @@
-using System.Windows;
-using PixiEditor.Views;
+using Avalonia.Controls;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Dialogs
 {
@@ -13,7 +13,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_width != value)
                 {
                     _width = value;
-                    RaisePropertyChanged("Width");
+                    this.RaisePropertyChanged("Width");
                 }
             }
         }
@@ -26,7 +26,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_height != value)
                 {
                     _height = value;
-                    RaisePropertyChanged("Height");
+                    this.RaisePropertyChanged("Height");
                 }
             }
         }

+ 3 - 3
PixiEditor/Models/Dialogs/ResizeDocumentDialog.cs

@@ -1,5 +1,5 @@
 using PixiEditor.Models.Enums;
-using PixiEditor.Views;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Dialogs
 {
@@ -16,7 +16,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_width != value)
                 {
                     _width = value;
-                    RaisePropertyChanged("Width");
+                    this.RaisePropertyChanged("Width");
                 }
             }
         }
@@ -29,7 +29,7 @@ namespace PixiEditor.Models.Dialogs
                 if (_height != value)
                 {
                     _height = value;
-                    RaisePropertyChanged("Height");
+                    this.RaisePropertyChanged("Height");
                 }
             }
         }

+ 8 - 15
PixiEditor/Models/IO/Exporter.cs

@@ -1,8 +1,8 @@
 using System;
 using System.IO;
-using System.Windows;
-using System.Windows.Media.Imaging;
-using Microsoft.Win32;
+using Avalonia;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Dialogs;
 
@@ -48,10 +48,8 @@ namespace PixiEditor.Models.IO
             if (info.ShowDialog())
             {
                 //If sizes are incorrect
-                if (info.FileWidth < bitmap.Width || info.FileHeight < bitmap.Height)
+                if (info.FileWidth < bitmap.PixelSize.Width || info.FileHeight < bitmap.PixelSize.Height)
                 {
-                    MessageBox.Show("Incorrect height or width value", "Error", MessageBoxButton.OK,
-                        MessageBoxImage.Error);
                     return;
                 }
 
@@ -71,18 +69,13 @@ namespace PixiEditor.Models.IO
         {
             try
             {
-                bitmap = bitmap.Resize(exportWidth, exportHeight,
-                    WriteableBitmapExtensions.Interpolation.NearestNeighbor);
-                using (FileStream stream = new FileStream(savePath, FileMode.Create))
-                {
-                    PngBitmapEncoder encoder = new PngBitmapEncoder();
-                    encoder.Frames.Add(BitmapFrame.Create(bitmap));
-                    encoder.Save(stream);
-                }
+                bitmap = bitmap.Resize(exportWidth, exportHeight, WriteableBitmapEx.Interpolation.NearestNeighbor);
+                bitmap.Save(savePath);
             }
             catch (Exception err)
             {
-                MessageBox.Show(err.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+                //TODO implement this
+                //MessageBox.Show(err.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
             }
         }
     }

+ 8 - 7
PixiEditor/Models/IO/Importer.cs

@@ -1,11 +1,12 @@
 using System;
-using System.Windows.Media.Imaging;
-using PixiEditor.Helpers;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 using PixiEditor.Models.DataHolders;
+using ReactiveUI;
 
 namespace PixiEditor.Models.IO
 {
-    public class Importer : NotifyableObject
+    public class Importer : ReactiveObject
     {
         /// <summary>
         ///     Imports image from path and resizes it to given dimensions
@@ -17,9 +18,9 @@ namespace PixiEditor.Models.IO
         public static WriteableBitmap ImportImage(string path, int width, int height)
         {
             var wbmp = ImportImage(path);
-            if (wbmp.PixelWidth != width || wbmp.PixelHeight != height)
+            if (wbmp.PixelSize.Width != width || wbmp.PixelSize.Height != height)
             {
-                return wbmp.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
+                return wbmp.Resize(width, height, WriteableBitmapEx.Interpolation.NearestNeighbor);
             }
 
             return wbmp;
@@ -31,13 +32,13 @@ namespace PixiEditor.Models.IO
         /// <param name="path">Path of image.</param>
         public static WriteableBitmap ImportImage(string path)
         {
-            Uri uri = new Uri(path);
+            Uri uri = new Uri(path);        
             BitmapImage bitmap = new BitmapImage();
             bitmap.BeginInit();
             bitmap.UriSource = uri;
             bitmap.EndInit();
 
-            return BitmapFactory.ConvertToPbgra32Format(bitmap);
+            return /*BitmapFactory.ConvertToPbgra32Format(*/bitmap;//); TODO: Implement this
         }
 
         public static Document ImportDocument(string path)

+ 6 - 9
PixiEditor/Models/ImageManipulation/BitmapUtils.cs

@@ -1,12 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Windows;
-using System.Windows.Interop;
-using System.Windows.Media.Imaging;
+using System.Collections.Generic;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using Color = System.Windows.Media.Color;
 
 namespace PixiEditor.Models.ImageManipulation
 {
@@ -41,8 +38,8 @@ namespace PixiEditor.Models.ImageManipulation
             using (finalBitmap.GetBitmapContext())
             {
                 for (int i = 0; i < layers.Length; i++)
-                for (int y = 0; y < finalBitmap.Height; y++)
-                for (int x = 0; x < finalBitmap.Width; x++)
+                for (int y = 0; y < finalBitmap.PixelSize.Width; y++)
+                for (int x = 0; x < finalBitmap.PixelSize.Height; x++)
                 {
                     Color color = layers[i].GetPixelWithOffset(x, y);
                     color = Color.FromArgb((byte)(color.A * layers[i].Opacity), color.R,color.G, color.B);

+ 4 - 4
PixiEditor/Models/Layers/BasicLayer.cs

@@ -1,10 +1,10 @@
 using System;
-using PixiEditor.Helpers;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Layers
 {
     [Serializable]
-    public class BasicLayer : NotifyableObject
+    public class BasicLayer : ReactiveObject
     {
         public int Width
         {
@@ -12,7 +12,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _width = value;
-                RaisePropertyChanged("Width");
+                this.RaisePropertyChanged("Width");
             }
         }
 
@@ -22,7 +22,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _height = value;
-                RaisePropertyChanged("Height");
+                this.RaisePropertyChanged("Height");
             }
         }
 

+ 22 - 20
PixiEditor/Models/Layers/Layer.cs

@@ -1,12 +1,13 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
+using Avalonia;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
-using PixiEditor.Models.Tools;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Layers
 {
@@ -21,7 +22,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _name = value;
-                RaisePropertyChanged("Name");
+                this.RaisePropertyChanged("Name");
             }
         }
 
@@ -31,7 +32,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _isActive = value;
-                RaisePropertyChanged("IsActive");
+                this.RaisePropertyChanged("IsActive");
             }
         }
 
@@ -41,7 +42,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _isVisible = value;
-                RaisePropertyChanged("IsVisible");
+                this.RaisePropertyChanged("IsVisible");
             }
         }
 
@@ -51,7 +52,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _isRenaming = value;
-                RaisePropertyChanged("IsRenaming");
+                this.RaisePropertyChanged("IsRenaming");
             }
         }
 
@@ -62,7 +63,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _layerBitmap = value;
-                RaisePropertyChanged("LayerBitmap");
+                this.RaisePropertyChanged("LayerBitmap");
             }
         }
 
@@ -74,7 +75,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _opacity = value;
-                RaisePropertyChanged("Opacity");
+                this.RaisePropertyChanged("Opacity");
             }
         }
 
@@ -90,7 +91,7 @@ namespace PixiEditor.Models.Layers
             set
             {
                 _offset = value;
-                RaisePropertyChanged("Offset");
+                this.RaisePropertyChanged("Offset");
             }
         }
 
@@ -111,7 +112,7 @@ namespace PixiEditor.Models.Layers
         public Layer(string name)
         {
             Name = name;
-            LayerBitmap = BitmapFactory.New(0, 0);
+            LayerBitmap = new WriteableBitmap(new PixelSize(0, 0), new Vector(72, 72));
             Width = 0;
             Height = 0;
         }
@@ -119,7 +120,7 @@ namespace PixiEditor.Models.Layers
         public Layer(string name, int width, int height)
         {
             Name = name;
-            LayerBitmap = BitmapFactory.New(width, height);
+            LayerBitmap = new WriteableBitmap(new PixelSize(width, height), new Vector(72,72));
             Width = width;
             Height = height;
         }
@@ -129,8 +130,8 @@ namespace PixiEditor.Models.Layers
         {
             Name = name;
             LayerBitmap = layerBitmap;
-            Width = layerBitmap.PixelWidth;
-            Height = layerBitmap.PixelHeight;
+            Width = _layerBitmap.PixelSize.Width;
+            Height = _layerBitmap.PixelSize.Height;
         }
 
         /// <summary>
@@ -160,7 +161,7 @@ namespace PixiEditor.Models.Layers
         /// <param name="newMaxHeight">New layer maximum height, this should be document height</param>
         public void Resize(int width, int height, int newMaxWidth, int newMaxHeight)
         {
-            LayerBitmap = LayerBitmap.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
+            LayerBitmap = LayerBitmap.Resize(width, height, WriteableBitmapEx.Interpolation.NearestNeighbor);
             Width = width;
             Height = height;
             MaxWidth = newMaxWidth;
@@ -421,10 +422,11 @@ namespace PixiEditor.Models.Layers
         /// <returns></returns>
         public byte[] ConvertBitmapToBytes()
         {
-            LayerBitmap.Lock();
-            byte[] byteArray = LayerBitmap.ToByteArray();
-            LayerBitmap.Unlock();
-            return byteArray;
+            using (LayerBitmap.GetBitmapContext())
+            {
+                byte[] byteArray = LayerBitmap.ToByteArray(0, LayerBitmap.PixelSize.Height * LayerBitmap.PixelSize.Width * 4);
+                return byteArray;
+            }
         }
 
         /// <summary>

+ 23 - 28
PixiEditor/Models/Position/CoordinatesCalculator.cs

@@ -1,9 +1,8 @@
 using System;
 using System.Collections.Generic;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.Layers;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using AvaloniaWriteableBitmapEx;
 
 namespace PixiEditor.Models.Position
 {
@@ -91,11 +90,10 @@ namespace PixiEditor.Models.Position
 
         public static int FindMinYNonTransparent(WriteableBitmap bitmap)
         {
-            Color transparent = Color.FromArgb(0, 0, 0, 0);
             using var ctx = bitmap.GetBitmapContext(ReadWriteMode.ReadOnly);
             for (int y = 0; y < ctx.Height; y++)
             for (int x = 0; x < ctx.Width; x++)
-                if (ctx.WriteableBitmap.GetPixel(x, y) != transparent)
+                if (ctx.WriteableBitmap.GetPixel(x, y).A > 0)
                     return y;
 
             return -1;
@@ -103,11 +101,10 @@ namespace PixiEditor.Models.Position
 
         public static int FindMinXNonTransparent(WriteableBitmap bitmap)
         {
-            Color transparent = Color.FromArgb(0, 0, 0, 0);
             using var ctx = bitmap.GetBitmapContext(ReadWriteMode.ReadOnly);
             for (int x = 0; x < ctx.Width; x++)
             for (int y = 0; y < ctx.Height; y++)
-                if (bitmap.GetPixel(x, y) != transparent)
+                if (bitmap.GetPixel(x, y).A > 0)
                     return x;
 
             return -1;
@@ -115,33 +112,31 @@ namespace PixiEditor.Models.Position
 
         public static int FindMaxYNonTransparent(WriteableBitmap bitmap)
         {
-            Color transparent = Color.FromArgb(0, 0, 0, 0);
-            bitmap.Lock();
-            for (int y = (int) bitmap.Height - 1; y >= 0; y--)
-            for (int x = (int) bitmap.Width - 1; x >= 0; x--)
-                if (bitmap.GetPixel(x, y) != transparent)
-                {
-                    bitmap.Unlock();
-                    return y;
-                }
+            using (bitmap.Lock())
+            {
+                for (int y = bitmap.PixelSize.Height - 1; y >= 0; y--)
+                    for (int x = bitmap.PixelSize.Width - 1; x >= 0; x--)
+                        if (bitmap.GetPixel(x, y).A > 0)
+                        {
+                            return y;
+                        }
+            }
 
-            bitmap.Unlock();
             return -1;
         }
 
         public static int FindMaxXNonTransparent(WriteableBitmap bitmap)
         {
-            Color transparent = Color.FromArgb(0, 0, 0, 0);
-            bitmap.Lock();
-            for (int x = (int) bitmap.Width - 1; x >= 0; x--)
-            for (int y = (int) bitmap.Height - 1; y >= 0; y--)
-                if (bitmap.GetPixel(x, y) != transparent)
-                {
-                    bitmap.Unlock();
-                    return x;
-                }
+            using (bitmap.Lock())
+            {
+                for (int x = (int)bitmap.PixelSize.Height - 1; x >= 0; x--)
+                    for (int y = (int)bitmap.PixelSize.Width - 1; y >= 0; y--)
+                        if (bitmap.GetPixel(x, y).A > 0)
+                        {
+                            return x;
+                        }
 
-            bitmap.Unlock();
+            }
             return -1;
         }
     }

+ 2 - 1
PixiEditor/Models/Tools/BitmapOperationTool.cs

@@ -1,4 +1,5 @@
-using System.Windows.Media;
+
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;

+ 3 - 4
PixiEditor/Models/Tools/ShapeTool.cs

@@ -1,11 +1,10 @@
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Input;
-using System.Windows.Media;
+using Avalonia.Input;
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditor.Models.Tools.ToolSettings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 
 namespace PixiEditor.Models.Tools
@@ -17,7 +16,7 @@ namespace PixiEditor.Models.Tools
         public ShapeTool()
         {
             RequiresPreviewLayer = true;
-            Cursor = Cursors.Cross;
+            Cursor = new Cursor(StandardCursorType.Cross);
             Toolbar = new BasicShapeToolbar();
         }
 

+ 6 - 5
PixiEditor/Models/Tools/Tool.cs

@@ -1,11 +1,12 @@
-using System.Windows.Input;
-using PixiEditor.Helpers;
+
+using Avalonia.Input;
 using PixiEditor.Models.Tools.ToolSettings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Tools
 {
-    public abstract class Tool : NotifyableObject
+    public abstract class Tool : ReactiveObject
     {
         public abstract ToolType ToolType { get; }
         public string ImagePath => $"/Images/{ToolType}Image.png";
@@ -18,11 +19,11 @@ namespace PixiEditor.Models.Tools
             set
             {
                 _isActive = value;
-                RaisePropertyChanged("IsActive");
+                this.RaisePropertyChanged("IsActive");
             }
         }
 
-        public Cursor Cursor { get; set; } = Cursors.Arrow;
+        public Cursor Cursor { get; set; } = new Cursor(StandardCursorType.Arrow);
 
         public Toolbar Toolbar { get; set; } = new EmptyToolbar();
 

+ 10 - 13
PixiEditor/Models/Tools/ToolSettings/Settings/BoolSetting.cs

@@ -1,7 +1,9 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Layout;
+using System;
+using System.Reactive.Subjects;
 
 namespace PixiEditor.Models.Tools.ToolSettings.Settings
 {
@@ -23,19 +25,14 @@ namespace PixiEditor.Models.Tools.ToolSettings.Settings
 
         private Control GenerateCheckBox()
         {
+            var source = new Subject<bool>();
             CheckBox checkBox = new CheckBox
             {
-                IsChecked = (bool) Value,
-                VerticalAlignment = VerticalAlignment.Center
+                IsChecked = (bool)Value,
+                VerticalAlignment = VerticalAlignment.Center,
+                [!ToggleButton.IsCheckedProperty] = source.ToBinding()
             };
 
-            Binding binding = new Binding("Value")
-            {
-                Mode = BindingMode.TwoWay
-            };
-
-            checkBox.SetBinding(ToggleButton.IsCheckedProperty, binding);
-
             return checkBox;
         }
     }

+ 2 - 2
PixiEditor/Models/Tools/ToolSettings/Settings/ColorSetting.cs

@@ -1,5 +1,5 @@
-using System.Windows.Data;
-using System.Windows.Media;
+using Avalonia.Data;
+using Avalonia.Media;
 using ColorPicker;
 
 namespace PixiEditor.Models.Tools.ToolSettings.Settings

+ 8 - 13
PixiEditor/Models/Tools/ToolSettings/Settings/DropdownSetting.cs

@@ -1,7 +1,7 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using System.Linq;
+using Avalonia.Layout;
 
 namespace PixiEditor.Models.Tools.ToolSettings.Settings
 {
@@ -13,24 +13,19 @@ namespace PixiEditor.Models.Tools.ToolSettings.Settings
         {
             Values = values;
             SettingControl = GenerateDropdown();
-            Value = ((ComboBox) SettingControl).Items[0];
+            Value = ((ComboBox)SettingControl).Items; //TODO: Fix later
             Label = label;
         }
 
 
         private ComboBox GenerateDropdown()
         {
+
             ComboBox combobox = new ComboBox
             {
-                VerticalAlignment = VerticalAlignment.Center
+                VerticalAlignment = VerticalAlignment.Center,
             };
             GenerateItems(combobox);
-
-            Binding binding = new Binding("Value")
-            {
-                Mode = BindingMode.TwoWay
-            };
-            combobox.SetBinding(Selector.SelectedValueProperty, binding);
             return combobox;
         }
 
@@ -42,7 +37,7 @@ namespace PixiEditor.Models.Tools.ToolSettings.Settings
                 {
                     Content = Values[i]
                 };
-                comboBox.Items.Add(item);
+                comboBox.Items = comboBox.Items.Cast<ComboBoxItem>().Append(item);
             }
         }
     }

+ 1 - 1
PixiEditor/Models/Tools/ToolSettings/Settings/FloatSetting.cs

@@ -1,4 +1,4 @@
-using System.Windows.Data;
+using Avalonia.Data;
 using PixiEditor.Views;
 
 namespace PixiEditor.Models.Tools.ToolSettings.Settings

+ 5 - 3
PixiEditor/Models/Tools/ToolSettings/Settings/Setting.cs

@@ -1,9 +1,11 @@
-using System.Windows.Controls;
+
+using Avalonia.Controls;
 using PixiEditor.Helpers;
+using ReactiveUI;
 
 namespace PixiEditor.Models.Tools.ToolSettings
 {
-    public abstract class Setting : NotifyableObject
+    public abstract class Setting : ReactiveObject
     {
         public string Name { get; protected set; }
         public string Label { get; set; }
@@ -15,7 +17,7 @@ namespace PixiEditor.Models.Tools.ToolSettings
             set
             {
                 this.value = value;
-                RaisePropertyChanged("Value");
+                this.RaisePropertyChanged("Value");
             }
         }
 

+ 8 - 6
PixiEditor/Models/Tools/ToolSettings/Settings/SizeSetting.cs

@@ -1,7 +1,9 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Interactivity;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Media;
+using Avalonia.Styling;
+using Avalonia.Xaml.Interactivity;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Behaviours;
 
@@ -28,7 +30,7 @@ namespace PixiEditor.Models.Tools.ToolSettings.Settings
 
             if (Application.Current != null)
             {
-                tb.Style = (Style)Application.Current.TryFindResource("DarkTextBoxStyle"); ;
+                tb.Styles.Add((Style)Application.Current.FindResource("DarkTextBoxStyle"));
             }
 
             Binding binding = new Binding("Value")
@@ -36,7 +38,7 @@ namespace PixiEditor.Models.Tools.ToolSettings.Settings
                 Converter = new ToolSizeToIntConverter(),
                 Mode = BindingMode.TwoWay
             };
-            tb.SetBinding(TextBox.TextProperty, binding);
+            tb.Bind(TextBox.TextProperty, binding);
             TextBoxFocusBehavior behavor = new TextBoxFocusBehavior
             {
                 FillSize = true

+ 1 - 1
PixiEditor/Models/Tools/ToolType.cs

@@ -10,7 +10,7 @@
         Line,
         Circle,
         Rectangle,
-        Eraser,
+        Earser,
         Brightness,
         ColorPicker
     }

+ 2 - 4
PixiEditor/Models/Tools/Tools/BrightnessTool.cs

@@ -1,9 +1,7 @@
 using System;
 using System.Collections.Generic;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
+using Avalonia.Controls;
+using Avalonia.Media;
 using PixiEditor.Models.Colors;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;

+ 49 - 66
PixiEditor/Models/Tools/Tools/CircleTool.cs

@@ -1,9 +1,7 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Linq;
-using System.Numerics;
-using System.Windows.Media;
+using Avalonia.Media;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
@@ -69,13 +67,11 @@ namespace PixiEditor.Models.Tools.Tools
         
         public Coordinates[] CreateEllipse(Coordinates startCoordinates, Coordinates endCoordinates, int thickness)
         {
-            double radiusX = (endCoordinates.X - startCoordinates.X) / 2.0;
-            double radiusY = (endCoordinates.Y - startCoordinates.Y) / 2.0;
-            double centerX = (startCoordinates.X + endCoordinates.X + 1) / 2.0;
-            double centerY = (startCoordinates.Y + endCoordinates.Y + 1) / 2.0;
-
+            Coordinates centerCoordinates = CoordinatesCalculator.GetCenterPoint(startCoordinates, endCoordinates);
+            int radiusX = endCoordinates.X - centerCoordinates.X;
+            int radiusY = endCoordinates.Y - centerCoordinates.Y;
             List<Coordinates> output = new List<Coordinates>();
-            Coordinates[] ellipse = MidpointEllipse(radiusX, radiusY, centerX, centerY);
+            Coordinates[] ellipse = MidpointEllipse(radiusX, radiusY, centerCoordinates.X, centerCoordinates.Y);
             if (thickness == 1)
                 output.AddRange(ellipse);
             else
@@ -83,74 +79,60 @@ namespace PixiEditor.Models.Tools.Tools
             return output.Distinct().ToArray();
         }
 
-        public Coordinates[] MidpointEllipse(double halfWidth, double halfHeight, double centerX, double centerY)
+        public Coordinates[] MidpointEllipse(double rx, double ry, double xc, double yc)
         {
-            if (halfWidth < 1 || halfHeight < 1)
-                return FallbackRectangle(halfWidth, halfHeight, centerX, centerY);
-
-            //ellipse formula: halfHeight^2 * x^2 + halfWidth^2 * y^2 - halfHeight^2 * halfWidth^2 = 0
-
-            //Make sure we are always at the center of a pixel
-            double currentX = Math.Ceiling(centerX - 0.5) + 0.5;
-            double currentY = centerY + halfHeight;
-
             List<Coordinates> outputCoordinates = new List<Coordinates>();
+            double dx, dy, d1, d2, x, y;
+            x = 0;
+            y = ry;
 
-            double currentSlope;
+            d1 = ry * ry - rx * rx * ry + 0.25f * rx * rx;
+            dx = 2 * ry * ry * x;
+            dy = 2 * rx * rx * y;
 
-            //from PI/2 to middle
-            do
+            while (dx < dy)
             {
-                outputCoordinates.AddRange(GetRegionPoints(currentX, centerX, currentY, centerY));
-
-                //calculate next pixel coords
-                currentX++;
-
-                if (Math.Pow(halfHeight, 2) * Math.Pow(currentX - centerX, 2) +
-                    Math.Pow(halfWidth, 2) * Math.Pow(currentY - centerY - 0.5, 2) -
-                    Math.Pow(halfWidth, 2) * Math.Pow(halfHeight, 2) >= 0)
+                outputCoordinates.AddRange(GetRegionPoints(x, xc, y, yc));
+                if (d1 < 0)
                 {
-                    currentY--;
+                    x++;
+                    dx += 2 * ry * ry;
+                    d1 = d1 + dx + ry * ry;
                 }
+                else
+                {
+                    x++;
+                    y--;
+                    dx += 2 * ry * ry;
+                    dy -= 2 * rx * rx;
+                    d1 = d1 + dx - dy + ry * ry;
+                }
+            }
 
-                //calculate how far we've advanced
-                double derivativeX = 2 * Math.Pow(halfHeight, 2) * (currentX - centerX);
-                double derivativeY = 2 * Math.Pow(halfWidth, 2) * (currentY - centerY);
-                currentSlope = -(derivativeX / derivativeY);
-
-            } while (currentSlope > -1 && currentY - centerY > 0.5);
+            //Decision parameter of region 2
+            d2 = ry * ry * ((x + 0.5f) * (x + 0.5f)) + rx * rx * ((y - 1) * (y - 1)) - rx * rx * ry * ry;
 
-            //from middle to 0
-            while (currentY - centerY >= 0)
+            while (y >= 0)
             {
-                outputCoordinates.AddRange(GetRegionPoints(currentX, centerX, currentY, centerY));
+                outputCoordinates.AddRange(GetRegionPoints(x, xc, y, yc));
 
-                currentY--;
-                if (Math.Pow(halfHeight, 2) * Math.Pow(currentX - centerX + 0.5, 2) +
-                    Math.Pow(halfWidth, 2) * Math.Pow(currentY - centerY, 2) -
-                    Math.Pow(halfWidth, 2) * Math.Pow(halfHeight, 2) < 0)
+                if (d2 > 0)
                 {
-                    currentX++;
+                    y--;
+                    dy -= 2 * rx * rx;
+                    d2 = d2 + rx * rx - dy;
+                }
+                else
+                {
+                    y--;
+                    x++;
+                    dx += 2 * ry * ry;
+                    dy -= 2 * rx * rx;
+                    d2 = d2 + dx - dy + rx * rx;
                 }
             }
 
-            return outputCoordinates.ToArray();
-        }
-
-        private Coordinates[] FallbackRectangle(double halfWidth, double halfHeight, double centerX, double centerY)
-        {
-            List<Coordinates> coordinates = new List<Coordinates>();
-            for (double x = centerX - halfWidth; x <= centerX + halfWidth; x++)
-            {
-                coordinates.Add(new Coordinates((int)x, (int)(centerY - halfHeight)));
-                coordinates.Add(new Coordinates((int)x, (int)(centerY + halfHeight)));
-            }
-            for (double y = centerY - halfHeight + 1; y <= centerY + halfHeight - 1; y++)
-            {
-                coordinates.Add(new Coordinates((int)(centerX - halfWidth), (int)y));
-                coordinates.Add(new Coordinates((int)(centerX + halfWidth), (int)y));
-            }
-            return coordinates.ToArray();
+            return outputCoordinates.Distinct().ToArray();
         }
 
         private Coordinates[] CalculateFillForEllipse(Coordinates[] outlineCoordinates)
@@ -168,13 +150,14 @@ namespace PixiEditor.Models.Tools.Tools
 
             return finalCoordinates.ToArray();
         }
+
         private Coordinates[] GetRegionPoints(double x, double xc, double y, double yc)
         {
             Coordinates[] outputCoordinates = new Coordinates[4];
-            outputCoordinates[0] = new Coordinates((int)Math.Floor(x),                  (int)Math.Floor(y));
-            outputCoordinates[1] = new Coordinates((int)Math.Floor((-(x - xc) + xc)),   (int)Math.Floor(y));
-            outputCoordinates[2] = new Coordinates((int)Math.Floor(x),                  (int)Math.Floor((-(y - yc) + yc)));
-            outputCoordinates[3] = new Coordinates((int)Math.Floor((-(x - xc) + xc)),   (int)Math.Floor((-(y - yc) + yc)));
+            outputCoordinates[0] = new Coordinates((int) x + (int) xc, (int) y + (int) yc);
+            outputCoordinates[1] = new Coordinates((int) -x + (int) xc, (int) y + (int) yc);
+            outputCoordinates[2] = new Coordinates((int) x + (int) xc, (int) -y + (int) yc);
+            outputCoordinates[3] = new Coordinates((int) -x + (int) xc, (int) -y + (int) yc);
             return outputCoordinates;
         }
     }

+ 0 - 2
PixiEditor/Models/Tools/Tools/ColorPickerTool.cs

@@ -1,7 +1,5 @@
 using System.Drawing;
 using PixiEditor.Models.Position;
-using PixiEditor.ViewModels;
-using Color = System.Windows.Media.Color;
 
 namespace PixiEditor.Models.Tools.Tools
 {

+ 35 - 0
PixiEditor/Models/Tools/Tools/EarserTool.cs

@@ -0,0 +1,35 @@
+
+using Avalonia.Media;
+using PixiEditor.Models.Colors;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Layers;
+using PixiEditor.Models.Position;
+using PixiEditor.Models.Tools.ToolSettings;
+using PixiEditor.Models.Tools.ToolSettings.Toolbars;
+
+namespace PixiEditor.Models.Tools.Tools
+{
+    public class EarserTool : BitmapOperationTool
+    {
+        public override ToolType ToolType => ToolType.Earser;
+
+        public EarserTool()
+        {
+            Tooltip = "Earsers color from pixel (E)";
+            Toolbar = new BasicToolbar();
+        }
+
+        public override LayerChange[] Use(Layer layer, Coordinates[] coordinates, Color color)
+        {
+            return Earse(layer, coordinates, (int) Toolbar.GetSetting("ToolSize").Value);
+        }
+
+        public LayerChange[] Earse(Layer layer, Coordinates[] coordinates, int toolSize)
+        {
+            Coordinates startingCords = coordinates.Length > 1 ? coordinates[1] : coordinates[0];
+            PenTool pen = new PenTool();
+            var pixels = pen.Draw(startingCords, coordinates[0], ConstColors.Transparent, toolSize);
+            return new[] {new LayerChange(pixels, layer)};
+        }
+    }
+}

+ 1 - 2
PixiEditor/Models/Tools/Tools/FloodFill.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;

+ 1 - 2
PixiEditor/Models/Tools/Tools/LineTool.cs

@@ -1,12 +1,11 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Media;
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditor.Models.Tools.ToolSettings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 
 namespace PixiEditor.Models.Tools.Tools

+ 9 - 7
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -2,8 +2,9 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Windows;
-using System.Windows.Input;
-using System.Windows.Media;
+using Avalonia;
+using Avalonia.Input;
+using Avalonia.Media;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
@@ -11,7 +12,6 @@ using PixiEditor.Models.Enums;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditor.ViewModels;
 using Transform = PixiEditor.Models.ImageManipulation.Transform;
 
 namespace PixiEditor.Models.Tools.Tools
@@ -31,10 +31,12 @@ namespace PixiEditor.Models.Tools.Tools
         private Coordinates[] _startSelection;
         private bool _updateViewModelSelection = true;
 
+        private Color _transparent = Color.FromArgb(0, 0, 0, 0);
+
         public MoveTool()
         {
             Tooltip = "Moves selected pixels (V). Hold Ctrl to move all layers";
-            Cursor = Cursors.Arrow;
+            Cursor = new Cursor(StandardCursorType.Arrow);
             HideHighlight = true;
             RequiresPreviewLayer = true;
             UseDefaultUndoMethod = true;
@@ -54,9 +56,9 @@ namespace PixiEditor.Models.Tools.Tools
                     ((LayerChange[]) changes.OldValue).First(x=> x.LayerIndex == layerIndex).PixelChanges.ChangedPixels
                         .AddRangeOverride(beforeMovePixels.ChangedPixels);
 
-                    ((LayerChange[]) changes.NewValue).First(x => x.LayerIndex == layerIndex).PixelChanges.ChangedPixels
+                    ((LayerChange[])changes.NewValue).First(x => x.LayerIndex == layerIndex).PixelChanges.ChangedPixels
                         .AddRangeNewOnly(BitmapPixelChanges
-                            .FromSingleColoredArray(_startSelection, System.Windows.Media.Colors.Transparent)
+                            .FromSingleColoredArray(_startSelection, _transparent)
                             .ChangedPixels);
                 }
             }
@@ -183,7 +185,7 @@ namespace PixiEditor.Models.Tools.Tools
             if (!_clearedPixels.ContainsKey(layer) || _clearedPixels[layer] == false)
             {
                 ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.First(x => x == layer)
-                    .SetPixels(BitmapPixelChanges.FromSingleColoredArray(selection, System.Windows.Media.Colors.Transparent));
+                    .SetPixels(BitmapPixelChanges.FromSingleColoredArray(selection, _transparent));
 
                 _clearedPixels[layer] = true;
             }

+ 3 - 2
PixiEditor/Models/Tools/Tools/PenTool.cs

@@ -1,5 +1,6 @@
-using System.Windows.Input;
-using System.Windows.Media;
+
+
+using Avalonia.Media;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;

+ 1 - 1
PixiEditor/Models/Tools/Tools/RectangleTool.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Media;
+using Avalonia.Media;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;

+ 1 - 3
PixiEditor/Models/Tools/Tools/SelectTool.cs

@@ -1,14 +1,12 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Controls;
+using Avalonia.Controls;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
-using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
-using PixiEditor.ViewModels;
 
 namespace PixiEditor.Models.Tools.Tools
 {

+ 11 - 67
PixiEditor/PixiEditor.csproj

@@ -1,80 +1,24 @@
-<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
-
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <OutputType>WinExe</OutputType>
     <TargetFramework>netcoreapp3.1</TargetFramework>
-    <UseWPF>true</UseWPF>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
-    <AssemblyName>PixiEditor</AssemblyName>
-    <RootNamespace>PixiEditor</RootNamespace>
-    <RepositoryUrl>https://github.com/flabbet/PixiEditor</RepositoryUrl>
-    <PackageLicenseFile>LICENSE</PackageLicenseFile>
-    <PackageIcon>icon.ico</PackageIcon>
-    <ApplicationIcon>..\icon.ico</ApplicationIcon>
-    <Authors>Krzysztof Krysiński</Authors>
   </PropertyGroup>
-
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <DebugType>full</DebugType>
-    <DebugSymbols>true</DebugSymbols>
   </PropertyGroup>
-
-  <ItemGroup>
-    <None Remove="Images\AnchorDot.png" />
-    <None Remove="Images\MoveImage.png" />
-    <None Remove="Images\PixiEditorLogo.png" />
-    <None Remove="Images\SelectImage.png" />
-    <None Include="..\icon.ico">
-      <Pack>True</Pack>
-      <PackagePath></PackagePath>
-    </None>
-    <None Include="..\LICENSE">
-      <Pack>True</Pack>
-      <PackagePath></PackagePath>
-    </None>
-  </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Dirkster.AvalonDock.Themes.VS2013" Version="4.30.0" />
-    <PackageReference Include="Expression.Blend.Sdk">
-      <Version>1.0.2</Version>
-    </PackageReference>
-    <PackageReference Include="Extended.Wpf.Toolkit" Version="3.8.2" />
-    <PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
-    <PackageReference Include="PixiEditor.ColorPicker" Version="1.0.0" />
-    <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
-    <PackageReference Include="WriteableBitmapEx">
-      <Version>1.6.7</Version>
-    </PackageReference>
+    <AvaloniaResource Include="Assets\**" />
   </ItemGroup>
   <ItemGroup>
-    <Resource Include="Images\AnchorDot.png" />
-    <Resource Include="Images\BucketImage.png" />
-    <Resource Include="Images\CircleImage.png" />
-    <Resource Include="Images\EraserImage.png" />
-    <Resource Include="Images\BrightnessImage.png" />
-    <Resource Include="Images\LineImage.png" />
-    <Resource Include="Images\MoveImage.png" />
-    <Resource Include="Images\PenImage.png" />
-    <Resource Include="Images\ColorPickerImage.png" />
-    <Resource Include="Images\PixiEditorLogo.png">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Resource>
-    <Resource Include="Images\RectangleImage.png" />
-    <Resource Include="Images\SelectImage.png" />
-    <Resource Include="Images\transparentbg.png" />
+    <PackageReference Include="Avalonia" Version="0.9.12" />
+    <PackageReference Include="Avalonia.Desktop" Version="0.9.12" />
+    <PackageReference Include="Avalonia.Native" Version="0.9.12" />
+    <PackageReference Include="Avalonia.ReactiveUI" Version="0.9.12" />
+    <PackageReference Include="Avalonia.Xaml.Interactivity" Version="0.9.9" />
   </ItemGroup>
   <ItemGroup>
-    <None Include="..\LICENSE">
-      <Pack>True</Pack>
-      <PackagePath></PackagePath>
-    </None>
+    <Reference Include="AvaloniaWriteableBitmapEx">
+      <HintPath>E:\Git\AvaloniaWriteableBitmapEx\AvaloniaWriteableBitmapEx\bin\Release\netcoreapp3.1\AvaloniaWriteableBitmapEx.dll</HintPath>
+    </Reference>
   </ItemGroup>
-  
-</Project>
+</Project>

+ 24 - 0
PixiEditor/Program.cs

@@ -0,0 +1,24 @@
+using System;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Logging.Serilog;
+using Avalonia.ReactiveUI;
+
+namespace PixiEditor
+{
+    class Program
+    {
+        // Initialization code. Don't use any Avalonia, third-party APIs or any
+        // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+        // yet and stuff might break.
+        public static void Main(string[] args) => BuildAvaloniaApp()
+            .StartWithClassicDesktopLifetime(args);
+
+        // Avalonia configuration, don't remove; also used by visual designer.
+        public static AppBuilder BuildAvaloniaApp()
+            => AppBuilder.Configure<App>()
+                .UsePlatformDetect()
+                .LogToDebug()
+                .UseReactiveUI();
+    }
+}

+ 32 - 0
PixiEditor/ViewLocator.cs

@@ -0,0 +1,32 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using PixiEditor.ViewModels;
+
+namespace PixiEditor
+{
+    public class ViewLocator : IDataTemplate
+    {
+        public bool SupportsRecycling => false;
+
+        public IControl Build(object data)
+        {
+            var name = data.GetType().FullName.Replace("ViewModel", "View");
+            var type = Type.GetType(name);
+
+            if (type != null)
+            {
+                return (Control)Activator.CreateInstance(type);
+            }
+            else
+            {
+                return new TextBlock { Text = "Not Found: " + name };
+            }
+        }
+
+        public bool Match(object data)
+        {
+            return data is ViewModelBase;
+        }
+    }
+}

+ 3 - 23
PixiEditor/ViewModels/ViewModelBase.cs

@@ -1,28 +1,8 @@
-using System.ComponentModel;
-using System.Linq;
-using System.Windows;
-using System.Windows.Input;
+using ReactiveUI;
 
 namespace PixiEditor.ViewModels
 {
-    public class ViewModelBase : INotifyPropertyChanged
+    public class ViewModelBase : ReactiveObject
     {
-        public event PropertyChangedEventHandler PropertyChanged = delegate { };
-
-        protected void RaisePropertyChanged(string property)
-        {
-            if (property != null) PropertyChanged(this, new PropertyChangedEventArgs(property));
-        }
-
-        protected void CloseButton(object parameter)
-        {
-            ((Window) parameter).Close();
-        }
-
-        protected void DragMove(object parameter)
-        {
-            Window popup = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
-            if (Mouse.LeftButton == MouseButtonState.Pressed) popup.DragMove();
-        }
     }
-}
+}

+ 37 - 44
PixiEditor/ViewModels/ViewModelMain.cs

@@ -5,11 +5,12 @@ using System.ComponentModel;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using Microsoft.Win32;
+using System.Reactive;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers.Shortcuts;
@@ -21,6 +22,7 @@ using PixiEditor.Models.IO;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools.Tools;
+using ReactiveUI;
 
 namespace PixiEditor.ViewModels
 {
@@ -90,7 +92,7 @@ namespace PixiEditor.ViewModels
             set
             {
                 _mouseXonCanvas = value;
-                RaisePropertyChanged("MouseXOnCanvas");
+                this.RaisePropertyChanged("MouseXOnCanvas");
             }
         }
 
@@ -100,7 +102,7 @@ namespace PixiEditor.ViewModels
             set
             {
                 _mouseYonCanvas = value;
-                RaisePropertyChanged("MouseYOnCanvas");
+                this.RaisePropertyChanged("MouseYOnCanvas");
             }
         }
 
@@ -110,7 +112,7 @@ namespace PixiEditor.ViewModels
             set
             {
                 _recenterZoombox = value;
-                RaisePropertyChanged("RecenterZoombox");
+                this.RaisePropertyChanged("RecenterZoombox");
             }
         }
 
@@ -119,12 +121,8 @@ namespace PixiEditor.ViewModels
             get => _primaryColor;
             set
             {
-                if (_primaryColor != value)
-                {
-                    _primaryColor = value;
-                    BitmapManager.PrimaryColor = value;
-                    RaisePropertyChanged("PrimaryColor");
-                }
+                this.RaiseAndSetIfChanged(ref _secondaryColor, value);
+                BitmapManager.PrimaryColor = value;
             }
         }
 
@@ -133,11 +131,7 @@ namespace PixiEditor.ViewModels
             get => _secondaryColor;
             set
             {
-                if (_secondaryColor != value)
-                {
-                    _secondaryColor = value;
-                    RaisePropertyChanged("SecondaryColor");
-                }
+                this.RaiseAndSetIfChanged(ref _secondaryColor, value);
             }
         }
 
@@ -160,7 +154,7 @@ namespace PixiEditor.ViewModels
             set
             {
                 _toolCursor = value;
-                RaisePropertyChanged("ToolCursor");
+                this.RaisePropertyChanged("ToolCursor");
             }
         }
 
@@ -175,7 +169,7 @@ namespace PixiEditor.ViewModels
             set
             {
                 _selection = value;
-                RaisePropertyChanged("ActiveSelection");
+                this.RaisePropertyChanged("ActiveSelection");
             }
         }
 
@@ -226,7 +220,7 @@ namespace PixiEditor.ViewModels
             ToolSet = new ObservableCollection<Tool>
             {
                 new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
-                new CircleTool(), new RectangleTool(), new EraserTool(), new ColorPickerTool(), new BrightnessTool()
+                new CircleTool(), new RectangleTool(), new EarserTool(), new ColorPickerTool(), new BrightnessTool()
             };
             ShortcutController = new ShortcutController
             {
@@ -234,7 +228,7 @@ namespace PixiEditor.ViewModels
                 {
                     //Tools
                     new Shortcut(Key.B, SelectToolCommand, ToolType.Pen),
-                    new Shortcut(Key.E, SelectToolCommand, ToolType.Eraser),
+                    new Shortcut(Key.E, SelectToolCommand, ToolType.Earser),
                     new Shortcut(Key.O, SelectToolCommand, ToolType.ColorPicker),
                     new Shortcut(Key.R, SelectToolCommand, ToolType.Rectangle),
                     new Shortcut(Key.C, SelectToolCommand, ToolType.Circle),
@@ -245,24 +239,24 @@ namespace PixiEditor.ViewModels
                     new Shortcut(Key.M, SelectToolCommand, ToolType.Select),
                     //Editor
                     new Shortcut(Key.X, SwapColorsCommand),
-                    new Shortcut(Key.Y, RedoCommand, modifier: ModifierKeys.Control),
+                    new Shortcut(Key.Y, RedoCommand, modifier: KeyModifiers.Control),
                     new Shortcut(Key.Z, UndoCommand),
-                    new Shortcut(Key.D, DeselectCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.A, SelectAllCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.C, CopyCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.V, PasteCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.J, DuplicateCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.X, CutCommand, modifier: ModifierKeys.Control),
+                    new Shortcut(Key.D, DeselectCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.A, SelectAllCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.C, CopyCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.V, PasteCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.J, DuplicateCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.X, CutCommand, modifier: KeyModifiers.Control),
                     new Shortcut(Key.Delete, DeletePixelsCommand),
-                    new Shortcut(Key.I, OpenResizePopupCommand, modifier: ModifierKeys.Control | ModifierKeys.Shift),
-                    new Shortcut(Key.C, OpenResizePopupCommand, "canvas", ModifierKeys.Control | ModifierKeys.Shift),
+                    new Shortcut(Key.I, OpenResizePopupCommand, modifier: KeyModifiers.Control | KeyModifiers.Shift),
+                    new Shortcut(Key.C, OpenResizePopupCommand, "canvas", KeyModifiers.Control | KeyModifiers.Shift),
                     //File
-                    new Shortcut(Key.O, OpenFileCommand, modifier: ModifierKeys.Control),
+                    new Shortcut(Key.O, OpenFileCommand, modifier: KeyModifiers.Control),
                     new Shortcut(Key.S, ExportFileCommand,
-                        modifier: ModifierKeys.Control | ModifierKeys.Shift | ModifierKeys.Alt),
-                    new Shortcut(Key.S, SaveDocumentCommand, modifier: ModifierKeys.Control),
-                    new Shortcut(Key.S, SaveDocumentCommand, "AsNew", ModifierKeys.Control | ModifierKeys.Shift),
-                    new Shortcut(Key.N, OpenNewFilePopupCommand, modifier: ModifierKeys.Control),
+                        modifier: KeyModifiers.Control | KeyModifiers.Shift | KeyModifiers.Alt),
+                    new Shortcut(Key.S, SaveDocumentCommand, modifier: KeyModifiers.Control),
+                    new Shortcut(Key.S, SaveDocumentCommand, "AsNew", KeyModifiers.Control | KeyModifiers.Shift),
+                    new Shortcut(Key.N, OpenNewFilePopupCommand, modifier: KeyModifiers.Control),
                 }
             };
             UndoManager.SetMainRoot(this);
@@ -320,16 +314,15 @@ namespace PixiEditor.ViewModels
         }
 
         private void Open(object property)
-        {
+        { //"All Files|*.*|PixiEditor Files | *.pixi|PNG Files|*.png"
             OpenFileDialog dialog = new OpenFileDialog
             {
-                Filter = "All Files|*.*|PixiEditor Files | *.pixi|PNG Files|*.png",
-                DefaultExt = "pixi"
+                //Filters = new List<FileDialogFilter>() {new FileDialogFilter() },
             };
             if ((bool) dialog.ShowDialog())
             {
-                if (Importer.IsSupportedFile(dialog.FileName))
-                    Open(dialog.FileName);
+                if (Importer.IsSupportedFile(dialog.Title)) //Title? should be sth like filename
+                    Open(dialog.Title);
                 RecenterZoombox = !RecenterZoombox;
             }
         }
@@ -610,7 +603,7 @@ namespace PixiEditor.ViewModels
             if (tool != ToolType.None)
                 ToolCursor = BitmapManager.SelectedTool.Cursor;
             else
-                ToolCursor = Cursors.Arrow;
+                ToolCursor = new Cursor(StandardCursorType.Arrow);
         }
 
         /// <summary>
@@ -763,7 +756,7 @@ namespace PixiEditor.ViewModels
         private void ExportFile(object parameter)
         {
             WriteableBitmap bitmap = BitmapManager.GetCombinedLayersBitmap();
-            Exporter.Export(bitmap, new Size(bitmap.PixelWidth, bitmap.PixelHeight));
+            Exporter.Export(bitmap, new Size(bitmap.PixelSize.Width, bitmap.PixelSize.Height));
         }
 
         /// <summary>

+ 17 - 0
PixiEditor/Views/MainWindow.axaml

@@ -0,0 +1,17 @@
+<Window xmlns="https://github.com/avaloniaui"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:vm="clr-namespace:PixiEditor.ViewModels;assembly=PixiEditor"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+        x:Class="PixiEditor.Views.MainWindow"
+        Icon="/Assets/avalonia-logo.ico"
+        Title="PixiEditor">
+
+    <Design.DataContext>
+        <vm:MainWindowViewModel/>
+    </Design.DataContext>
+
+    <TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
+
+</Window>

+ 23 - 0
PixiEditor/Views/MainWindow.axaml.cs

@@ -0,0 +1,23 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views
+{
+    public class MainWindow : Window
+    {
+        public MainWindow()
+        {
+            InitializeComponent();
+#if DEBUG
+            this.AttachDevTools();
+            this.PointerPressed += MainWindow_PointerPressed;
+#endif
+        }
+
+        private void InitializeComponent()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+    }
+}

+ 11 - 0
PixiEditor/nuget.config

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 
+  To use the Avalonia CI feed to get unstable packages, move this file to the root of your solution.
+-->
+
+<configuration>
+  <packageSources>
+    <add key="AvaloniaCI" value="https://www.myget.org/F/avalonia-ci/api/v2" />
+  </packageSources>
+</configuration>