Browse Source

Merge branch 'master' into multiple-layers-selection

Krzysztof Krysiński 4 years ago
parent
commit
737ba71939
28 changed files with 1130 additions and 639 deletions
  1. 31 1
      PixiEditor/Models/DataHolders/Document/Document.IO.cs
  2. 2 2
      PixiEditor/Models/Dialogs/NewFileDialog.cs
  3. 17 0
      PixiEditor/Models/Dialogs/NoticeDialog.cs
  4. 32 0
      PixiEditor/Models/UserPreferences/IPreferences.cs
  5. 97 34
      PixiEditor/Models/UserPreferences/PreferencesSettings.cs
  6. 1 0
      PixiEditor/PixiEditor.csproj
  7. 8 8
      PixiEditor/ViewModels/SubViewModels/Main/DiscordViewModel.cs
  8. 50 1
      PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs
  9. 1 1
      PixiEditor/ViewModels/SubViewModels/Main/UpdateViewModel.cs
  10. 89 0
      PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/DiscordSettings.cs
  11. 62 0
      PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/FileSettings.cs
  12. 18 0
      PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/UpdateSettings.cs
  13. 3 3
      PixiEditor/ViewModels/SubViewModels/UserPreferences/SettingsGroup.cs
  14. 3 143
      PixiEditor/ViewModels/SubViewModels/UserPreferences/SettingsViewModel.cs
  15. 9 3
      PixiEditor/ViewModels/ViewModelMain.cs
  16. 40 0
      PixiEditor/Views/Dialogs/NoticePopup.xaml
  17. 41 0
      PixiEditor/Views/Dialogs/NoticePopup.xaml.cs
  18. 8 4
      PixiEditor/Views/Dialogs/SettingsWindow.xaml
  19. 436 421
      PixiEditor/Views/MainWindow.xaml
  20. 8 0
      PixiEditor/Views/MainWindow.xaml.cs
  21. 24 0
      PixiEditorTests/Helpers.cs
  22. 56 0
      PixiEditorTests/Mocks/PreferenceSettingsMock.cs
  23. 18 0
      PixiEditorTests/ModelsTests/DataHoldersTests/DocumentTests.cs
  24. 4 2
      PixiEditorTests/ModelsTests/ToolsTests/ZoomToolTests.cs
  25. 43 1
      PixiEditorTests/ModelsTests/UserPreferencesTests/PreferencesSettingsTests.cs
  26. 2 0
      PixiEditorTests/PixiEditorTests.csproj
  27. 24 12
      PixiEditorTests/ViewModelsTests/ViewModelMainTests.cs
  28. 3 3
      README.md

+ 31 - 1
PixiEditor/Models/DataHolders/Document/Document.IO.cs

@@ -1,4 +1,6 @@
-using PixiEditor.Models.IO;
+using System.Collections.ObjectModel;
+using PixiEditor.Models.IO;
+using PixiEditor.Models.UserPreferences;
 
 
 namespace PixiEditor.Models.DataHolders
 namespace PixiEditor.Models.DataHolders
 {
 {
@@ -14,6 +16,7 @@ namespace PixiEditor.Models.DataHolders
                 documentFilePath = value;
                 documentFilePath = value;
                 RaisePropertyChanged(nameof(DocumentFilePath));
                 RaisePropertyChanged(nameof(DocumentFilePath));
                 RaisePropertyChanged(nameof(Name));
                 RaisePropertyChanged(nameof(Name));
+                UpdateRecentlyOpened(value);
             }
             }
         }
         }
 
 
@@ -47,5 +50,32 @@ namespace PixiEditor.Models.DataHolders
             DocumentFilePath = Exporter.SaveAsEditableFile(this, path);
             DocumentFilePath = Exporter.SaveAsEditableFile(this, path);
             ChangesSaved = true;
             ChangesSaved = true;
         }
         }
+
+        private void UpdateRecentlyOpened(string newPath)
+        {
+            ObservableCollection<string> recentlyOpened = XamlAccesibleViewModel.FileSubViewModel.RecentlyOpened;
+
+            if (!recentlyOpened.Contains(newPath))
+            {
+                recentlyOpened.Insert(0, newPath);
+            }
+            else
+            {
+                int index = recentlyOpened.IndexOf(newPath);
+                recentlyOpened.Move(index, 0);
+            }
+
+            if (recentlyOpened.Count > IPreferences.Current.GetPreference("maxOpenedRecently", 10))
+            {
+                for (int i = 4; i < recentlyOpened.Count; i++)
+                {
+                    recentlyOpened.RemoveAt(i);
+                }
+            }
+
+            IPreferences.Current.UpdateLocalPreference("RecentlyOpened", recentlyOpened);
+
+            XamlAccesibleViewModel.FileSubViewModel.HasRecent = true;
+        }
     }
     }
 }
 }

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

@@ -7,9 +7,9 @@ namespace PixiEditor.Models.Dialogs
 {
 {
     public class NewFileDialog : CustomDialog
     public class NewFileDialog : CustomDialog
     {
     {
-        private int height = (int)PreferencesSettings.GetPreference("DefaultNewFileHeight", 16L);
+        private int height = (int)IPreferences.Current.GetPreference("DefaultNewFileHeight", 16L);
 
 
-        private int width = (int)PreferencesSettings.GetPreference("DefaultNewFileWidth", 16L);
+        private int width = (int)IPreferences.Current.GetPreference("DefaultNewFileWidth", 16L);
 
 
         public int Width
         public int Width
         {
         {

+ 17 - 0
PixiEditor/Models/Dialogs/NoticeDialog.cs

@@ -0,0 +1,17 @@
+using PixiEditor.Views.Dialogs;
+
+namespace PixiEditor.Models.Dialogs
+{
+    public static class NoticeDialog
+    {
+        public static void Show(string message)
+        {
+            NoticePopup popup = new NoticePopup
+            {
+                Body = message
+            };
+
+            popup.ShowDialog();
+        }
+    }
+}

+ 32 - 0
PixiEditor/Models/UserPreferences/IPreferences.cs

@@ -0,0 +1,32 @@
+using System;
+using PixiEditor.ViewModels;
+
+namespace PixiEditor.Models.UserPreferences
+{
+    public interface IPreferences
+    {
+        public static IPreferences Current => ViewModelMain.Current.Preferences;
+
+        public void Save();
+
+        public void AddCallback(string setting, Action<object> action);
+
+        public void Init();
+
+        public void Init(string path, string localPath);
+
+        public void UpdatePreference<T>(string name, T value);
+
+        public void UpdateLocalPreference<T>(string name, T value);
+
+#nullable enable
+
+        public T? GetPreference<T>(string name);
+
+        public T? GetPreference<T>(string name, T? fallbackValue);
+
+        public T? GetLocalPreference<T>(string name);
+
+        public T? GetLocalPreference<T>(string name, T? fallbackValue);
+    }
+}

+ 97 - 34
PixiEditor/Models/UserPreferences/PreferencesSettings.cs

@@ -2,51 +2,44 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using Newtonsoft.Json;
 using Newtonsoft.Json;
+using PixiEditor.ViewModels;
 
 
 namespace PixiEditor.Models.UserPreferences
 namespace PixiEditor.Models.UserPreferences
 {
 {
-    public static class PreferencesSettings
+    public class PreferencesSettings : IPreferences
     {
     {
-        public static bool IsLoaded { get; private set; } = false;
+        public static IPreferences Current => ViewModelMain.Current.Preferences;
 
 
-        public static string PathToUserPreferences { get; private set; } = Path.Join(
-            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
-            "PixiEditor",
-            "user_preferences.json");
+        public bool IsLoaded { get; private set; } = false;
+
+        public string PathToRoamingUserPreferences { get; private set; } = GetPathToSettings(Environment.SpecialFolder.ApplicationData, "user_preferences.json");
+
+        public string PathToLocalPreferences { get; private set; } = GetPathToSettings(Environment.SpecialFolder.LocalApplicationData, "editor_data.json");
+
+        public Dictionary<string, object> Preferences { get; set; } = new Dictionary<string, object>();
 
 
-        public static Dictionary<string, object> Preferences { get; set; } = new Dictionary<string, object>();
+        public Dictionary<string, object> LocalPreferences { get; set; } = new Dictionary<string, object>();
 
 
-        public static void Init()
+        public void Init()
         {
         {
-            Init(PathToUserPreferences);
+            Init(PathToRoamingUserPreferences, PathToLocalPreferences);
         }
         }
 
 
-        public static void Init(string path)
+        public void Init(string path, string localPath)
         {
         {
-            PathToUserPreferences = path;
+            PathToRoamingUserPreferences = path;
+            PathToLocalPreferences = localPath;
+
             if (IsLoaded == false)
             if (IsLoaded == false)
             {
             {
-                string dir = Path.GetDirectoryName(path);
-                if (!Directory.Exists(dir))
-                {
-                    Directory.CreateDirectory(dir);
-                }
-
-                if (!File.Exists(path))
-                {
-                    File.WriteAllText(path, "{\n}");
-                }
-                else
-                {
-                    string json = File.ReadAllText(path);
-                    Preferences = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
-                }
+                Preferences = InitPath(path);
+                LocalPreferences = InitPath(localPath);
 
 
                 IsLoaded = true;
                 IsLoaded = true;
             }
             }
         }
         }
 
 
-        public static void UpdatePreference<T>(string name, T value)
+        public void UpdatePreference<T>(string name, T value)
         {
         {
             if (IsLoaded == false)
             if (IsLoaded == false)
             {
             {
@@ -66,21 +59,40 @@ namespace PixiEditor.Models.UserPreferences
             Save();
             Save();
         }
         }
 
 
-        public static void Save()
+        public void UpdateLocalPreference<T>(string name, T value)
         {
         {
             if (IsLoaded == false)
             if (IsLoaded == false)
             {
             {
                 Init();
                 Init();
             }
             }
 
 
-            File.WriteAllText(PathToUserPreferences, JsonConvert.SerializeObject(Preferences));
+            LocalPreferences[name] = value;
+
+            if (Callbacks.ContainsKey(name))
+            {
+                foreach (var action in Callbacks[name])
+                {
+                    action.Invoke(value);
+                }
+            }
+
+            Save();
         }
         }
 
 
-#nullable enable
+        public void Save()
+        {
+            if (IsLoaded == false)
+            {
+                Init();
+            }
 
 
-        public static Dictionary<string, List<Action<object>>> Callbacks { get; set; } = new Dictionary<string, List<Action<object>>>();
+            File.WriteAllText(PathToRoamingUserPreferences, JsonConvert.SerializeObject(Preferences));
+            File.WriteAllText(PathToLocalPreferences, JsonConvert.SerializeObject(LocalPreferences));
+        }
+
+        public Dictionary<string, List<Action<object>>> Callbacks { get; set; } = new Dictionary<string, List<Action<object>>>();
 
 
-        public static void AddCallback(string setting, Action<object> action)
+        public void AddCallback(string setting, Action<object> action)
         {
         {
             if (Callbacks.ContainsKey(setting))
             if (Callbacks.ContainsKey(setting))
             {
             {
@@ -91,12 +103,14 @@ namespace PixiEditor.Models.UserPreferences
             Callbacks.Add(setting, new List<Action<object>>() { action });
             Callbacks.Add(setting, new List<Action<object>>() { action });
         }
         }
 
 
-        public static T? GetPreference<T>(string name)
+#nullable enable
+
+        public T? GetPreference<T>(string name)
         {
         {
             return GetPreference(name, default(T));
             return GetPreference(name, default(T));
         }
         }
 
 
-        public static T? GetPreference<T>(string name, T? fallbackValue)
+        public T? GetPreference<T>(string name, T? fallbackValue)
         {
         {
             if (IsLoaded == false)
             if (IsLoaded == false)
             {
             {
@@ -107,5 +121,54 @@ namespace PixiEditor.Models.UserPreferences
                 ? (T)Preferences[name]
                 ? (T)Preferences[name]
                 : fallbackValue;
                 : fallbackValue;
         }
         }
+
+        public T? GetLocalPreference<T>(string name)
+        {
+            return GetPreference(name, default(T));
+        }
+
+        public T? GetLocalPreference<T>(string name, T? fallbackValue)
+        {
+            if (IsLoaded == false)
+            {
+                Init();
+            }
+
+            return LocalPreferences.ContainsKey(name)
+                ? (T)LocalPreferences[name]
+                : fallbackValue;
+        }
+
+#nullable disable
+
+        private static string GetPathToSettings(Environment.SpecialFolder folder, string fileName)
+        {
+            return Path.Join(
+            Environment.GetFolderPath(folder),
+            "PixiEditor",
+            fileName);
+        }
+
+        private static Dictionary<string, object> InitPath(string path)
+        {
+            string dir = Path.GetDirectoryName(path);
+
+            if (!Directory.Exists(dir))
+            {
+                Directory.CreateDirectory(dir);
+            }
+
+            if (!File.Exists(path))
+            {
+                File.WriteAllText(path, "{\n}");
+            }
+            else
+            {
+                string json = File.ReadAllText(path);
+                return JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
+            }
+
+            return new Dictionary<string, object>();
+        }
     }
     }
 }
 }

+ 1 - 0
PixiEditor/PixiEditor.csproj

@@ -59,6 +59,7 @@
       <Version>1.0.2</Version>
       <Version>1.0.2</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="Extended.Wpf.Toolkit" Version="3.8.2" />
     <PackageReference Include="Extended.Wpf.Toolkit" Version="3.8.2" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
     <PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
     <PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
     <PackageReference Include="PixiEditor.ColorPicker" Version="2.0.0" />
     <PackageReference Include="PixiEditor.ColorPicker" Version="2.0.0" />

+ 8 - 8
PixiEditor/ViewModels/SubViewModels/Main/DiscordViewModel.cs

@@ -30,7 +30,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
             }
         }
         }
 
 
-        private bool showDocumentName = PreferencesSettings.GetPreference(nameof(ShowDocumentName), true);
+        private bool showDocumentName = IPreferences.Current.GetPreference(nameof(ShowDocumentName), true);
 
 
         public bool ShowDocumentName
         public bool ShowDocumentName
         {
         {
@@ -45,7 +45,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
             }
         }
         }
 
 
-        private bool showDocumentSize = PreferencesSettings.GetPreference(nameof(ShowDocumentSize), true);
+        private bool showDocumentSize = IPreferences.Current.GetPreference(nameof(ShowDocumentSize), true);
 
 
         public bool ShowDocumentSize
         public bool ShowDocumentSize
         {
         {
@@ -60,7 +60,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
             }
         }
         }
 
 
-        private bool showLayerCount = PreferencesSettings.GetPreference(nameof(ShowLayerCount), true);
+        private bool showLayerCount = IPreferences.Current.GetPreference(nameof(ShowLayerCount), true);
 
 
         public bool ShowLayerCount
         public bool ShowLayerCount
         {
         {
@@ -81,11 +81,11 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             Owner.BitmapManager.DocumentChanged += DocumentChanged;
             Owner.BitmapManager.DocumentChanged += DocumentChanged;
             this.clientId = clientId;
             this.clientId = clientId;
 
 
-            Enabled = PreferencesSettings.GetPreference<bool>("EnableRichPresence");
-            PreferencesSettings.AddCallback("EnableRichPresence", x => Enabled = (bool)x);
-            PreferencesSettings.AddCallback(nameof(ShowDocumentName), x => ShowDocumentName = (bool)x);
-            PreferencesSettings.AddCallback(nameof(ShowDocumentSize), x => ShowDocumentSize = (bool)x);
-            PreferencesSettings.AddCallback(nameof(ShowLayerCount), x => ShowLayerCount = (bool)x);
+            Enabled = IPreferences.Current.GetPreference<bool>("EnableRichPresence");
+            IPreferences.Current.AddCallback("EnableRichPresence", x => Enabled = (bool)x);
+            IPreferences.Current.AddCallback(nameof(ShowDocumentName), x => ShowDocumentName = (bool)x);
+            IPreferences.Current.AddCallback(nameof(ShowDocumentSize), x => ShowDocumentSize = (bool)x);
+            IPreferences.Current.AddCallback(nameof(ShowLayerCount), x => ShowLayerCount = (bool)x);
 
 
             AppDomain.CurrentDomain.ProcessExit += (_, _) => Enabled = false;
             AppDomain.CurrentDomain.ProcessExit += (_, _) => Enabled = false;
         }
         }

+ 50 - 1
PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs

@@ -1,9 +1,12 @@
 using System;
 using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Windows;
 using System.Windows;
 using System.Windows.Media.Imaging;
 using System.Windows.Media.Imaging;
 using Microsoft.Win32;
 using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
 using PixiEditor.Exceptions;
 using PixiEditor.Exceptions;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
@@ -18,6 +21,8 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 {
 {
     public class FileViewModel : SubViewModel<ViewModelMain>
     public class FileViewModel : SubViewModel<ViewModelMain>
     {
     {
+        private bool hasRecent;
+
         public RelayCommand OpenNewFilePopupCommand { get; set; }
         public RelayCommand OpenNewFilePopupCommand { get; set; }
 
 
         public RelayCommand SaveDocumentCommand { get; set; }
         public RelayCommand SaveDocumentCommand { get; set; }
@@ -26,6 +31,20 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public RelayCommand ExportFileCommand { get; set; } // Command that is used to save file
         public RelayCommand ExportFileCommand { get; set; } // Command that is used to save file
 
 
+        public RelayCommand OpenRecentCommand { get; set; }
+
+        public bool HasRecent
+        {
+            get => hasRecent;
+            set
+            {
+                hasRecent = value;
+                RaisePropertyChanged(nameof(HasRecent));
+            }
+        }
+
+        public ObservableCollection<string> RecentlyOpened { get; set; } = new ObservableCollection<string>();
+
         public FileViewModel(ViewModelMain owner)
         public FileViewModel(ViewModelMain owner)
             : base(owner)
             : base(owner)
         {
         {
@@ -33,7 +52,37 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             SaveDocumentCommand = new RelayCommand(SaveDocument, Owner.DocumentIsNotNull);
             SaveDocumentCommand = new RelayCommand(SaveDocument, Owner.DocumentIsNotNull);
             OpenFileCommand = new RelayCommand(Open);
             OpenFileCommand = new RelayCommand(Open);
             ExportFileCommand = new RelayCommand(ExportFile, CanSave);
             ExportFileCommand = new RelayCommand(ExportFile, CanSave);
+            OpenRecentCommand = new RelayCommand(OpenRecent);
             Owner.OnStartupEvent += Owner_OnStartupEvent;
             Owner.OnStartupEvent += Owner_OnStartupEvent;
+            RecentlyOpened = new ObservableCollection<string>(IPreferences.Current.GetLocalPreference<JArray>(nameof(RecentlyOpened), new JArray()).ToObject<string[]>());
+
+            if (RecentlyOpened.Count > 0)
+            {
+                HasRecent = true;
+            }
+        }
+
+        public void OpenRecent(object parameter)
+        {
+            string path = (string)parameter;
+
+            foreach (Document document in Owner.BitmapManager.Documents)
+            {
+                if (document.DocumentFilePath == path)
+                {
+                    Owner.BitmapManager.ActiveDocument = document;
+                    return;
+                }
+            }
+
+            if (!File.Exists(path))
+            {
+                NoticeDialog.Show("The file does no longer exist at that path");
+                RecentlyOpened.Remove(path);
+                return;
+            }
+
+            Open((string)parameter);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -98,7 +147,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
             }
             else
             else
             {
             {
-                if (PreferencesSettings.GetPreference("ShowNewFilePopupOnStartup", true))
+                if (IPreferences.Current.GetPreference("ShowNewFilePopupOnStartup", true))
                 {
                 {
                     OpenNewFilePopup(null);
                     OpenNewFilePopup(null);
                 }
                 }

+ 1 - 1
PixiEditor/ViewModels/SubViewModels/Main/UpdateViewModel.cs

@@ -86,7 +86,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         private async void Owner_OnStartupEvent(object sender, EventArgs e)
         private async void Owner_OnStartupEvent(object sender, EventArgs e)
         {
         {
-            if (PreferencesSettings.GetPreference("CheckUpdatesOnStartup", true))
+            if (IPreferences.Current.GetPreference("CheckUpdatesOnStartup", true))
             {
             {
                 await CheckForUpdate();
                 await CheckForUpdate();
             }
             }

+ 89 - 0
PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/DiscordSettings.cs

@@ -0,0 +1,89 @@
+namespace PixiEditor.ViewModels.SubViewModels.UserPreferences.Settings
+{
+    public class DiscordSettings : SettingsGroup
+    {
+        private bool enableRichPresence = GetPreference(nameof(EnableRichPresence), true);
+
+        public bool EnableRichPresence
+        {
+            get => enableRichPresence;
+            set
+            {
+                enableRichPresence = value;
+                RaiseAndUpdatePreference(nameof(EnableRichPresence), value);
+            }
+        }
+
+        private bool showDocumentName = GetPreference(nameof(ShowDocumentName), true);
+
+        public bool ShowDocumentName
+        {
+            get => showDocumentName;
+            set
+            {
+                showDocumentName = value;
+                RaiseAndUpdatePreference(nameof(ShowDocumentName), value);
+                RaisePropertyChanged(nameof(DetailPreview));
+            }
+        }
+
+        private bool showDocumentSize = GetPreference(nameof(ShowDocumentSize), true);
+
+        public bool ShowDocumentSize
+        {
+            get => showDocumentSize;
+            set
+            {
+                showDocumentSize = value;
+                RaiseAndUpdatePreference(nameof(ShowDocumentSize), value);
+                RaisePropertyChanged(nameof(StatePreview));
+            }
+        }
+
+        private bool showLayerCount = GetPreference(nameof(ShowLayerCount), true);
+
+        public bool ShowLayerCount
+        {
+            get => showLayerCount;
+            set
+            {
+                showLayerCount = value;
+                RaiseAndUpdatePreference(nameof(ShowLayerCount), value);
+                RaisePropertyChanged(nameof(StatePreview));
+            }
+        }
+
+        public string DetailPreview
+        {
+            get
+            {
+                return ShowDocumentName ? $"Editing coolPixelArt.pixi" : "Editing something (incognito)";
+            }
+        }
+
+        public string StatePreview
+        {
+            get
+            {
+                string state = string.Empty;
+
+                if (ShowDocumentSize)
+                {
+                    state = "16x16";
+                }
+
+                if (ShowDocumentSize && ShowLayerCount)
+                {
+                    state += ", ";
+                }
+
+                if (ShowLayerCount)
+                {
+                    state += "2 Layers";
+                }
+
+                return state;
+            }
+        }
+    }
+}

+ 62 - 0
PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/FileSettings.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PixiEditor.ViewModels.SubViewModels.UserPreferences.Settings
+{
+    public class FileSettings : SettingsGroup
+    {
+        private bool showNewFilePopupOnStartup = GetPreference("ShowNewFilePopupOnStartup", true);
+
+        public bool ShowNewFilePopupOnStartup
+        {
+            get => showNewFilePopupOnStartup;
+            set
+            {
+                showNewFilePopupOnStartup = value;
+                string name = nameof(ShowNewFilePopupOnStartup);
+                RaiseAndUpdatePreference(name, value);
+            }
+        }
+
+        private long defaultNewFileWidth = GetPreference("DefaultNewFileWidth", 16L);
+
+        public long DefaultNewFileWidth
+        {
+            get => defaultNewFileWidth;
+            set
+            {
+                defaultNewFileWidth = value;
+                string name = nameof(DefaultNewFileWidth);
+                RaiseAndUpdatePreference(name, value);
+            }
+        }
+
+        private long defaultNewFileHeight = GetPreference("DefaultNewFileHeight", 16L);
+
+        public long DefaultNewFileHeight
+        {
+            get => defaultNewFileHeight;
+            set
+            {
+                defaultNewFileHeight = value;
+                string name = nameof(DefaultNewFileHeight);
+                RaiseAndUpdatePreference(name, value);
+            }
+        }
+
+        private int maxOpenedRecently = GetPreference(nameof(MaxOpenedRecently), 10);
+
+        public int MaxOpenedRecently
+        {
+            get => maxOpenedRecently;
+            set
+            {
+                maxOpenedRecently = value;
+                RaiseAndUpdatePreference(nameof(MaxOpenedRecently), value);
+            }
+        }
+    }
+}

+ 18 - 0
PixiEditor/ViewModels/SubViewModels/UserPreferences/Settings/UpdateSettings.cs

@@ -0,0 +1,18 @@
+namespace PixiEditor.ViewModels.SubViewModels.UserPreferences.Settings
+{
+    public class UpdateSettings : SettingsGroup
+    {
+        private bool checkUpdatesOnStartup = GetPreference("CheckUpdatesOnStartup", true);
+
+        public bool CheckUpdatesOnStartup
+        {
+            get => checkUpdatesOnStartup;
+            set
+            {
+                checkUpdatesOnStartup = value;
+                string name = nameof(CheckUpdatesOnStartup);
+                RaiseAndUpdatePreference(name, value);
+            }
+        }
+    }
+}

+ 3 - 3
PixiEditor/ViewModels/SubViewModels/UserPreferences/SettingsGroup.cs

@@ -8,14 +8,14 @@ namespace PixiEditor.ViewModels.SubViewModels.UserPreferences
     {
     {
         protected static T GetPreference<T>(string name)
         protected static T GetPreference<T>(string name)
         {
         {
-            return PreferencesSettings.GetPreference<T>(name);
+            return IPreferences.Current.GetPreference<T>(name);
         }
         }
 
 
 #nullable enable
 #nullable enable
 
 
         protected static T? GetPreference<T>(string name, T? fallbackValue)
         protected static T? GetPreference<T>(string name, T? fallbackValue)
         {
         {
-            return PreferencesSettings.GetPreference(name, fallbackValue);
+            return IPreferences.Current.GetPreference(name, fallbackValue);
         }
         }
 
 
 #nullable disable
 #nullable disable
@@ -23,7 +23,7 @@ namespace PixiEditor.ViewModels.SubViewModels.UserPreferences
         protected void RaiseAndUpdatePreference<T>(string name, T value)
         protected void RaiseAndUpdatePreference<T>(string name, T value)
         {
         {
             RaisePropertyChanged(name);
             RaisePropertyChanged(name);
-            PreferencesSettings.UpdatePreference(name, value);
+            IPreferences.Current.UpdatePreference(name, value);
         }
         }
     }
     }
 }
 }

+ 3 - 143
PixiEditor/ViewModels/SubViewModels/UserPreferences/SettingsViewModel.cs

@@ -1,158 +1,18 @@
 using System;
 using System;
 using System.Configuration;
 using System.Configuration;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.Models.UserPreferences;
+using PixiEditor.ViewModels.SubViewModels.UserPreferences.Settings;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.UserPreferences
 namespace PixiEditor.ViewModels.SubViewModels.UserPreferences
 {
 {
     public class SettingsViewModel : SubViewModel<SettingsWindowViewModel>
     public class SettingsViewModel : SubViewModel<SettingsWindowViewModel>
     {
     {
-        private bool showNewFilePopupOnStartup = PreferencesSettings.GetPreference("ShowNewFilePopupOnStartup", true);
+        public FileSettings File { get; set; } = new FileSettings();
 
 
-        public bool ShowNewFilePopupOnStartup
-        {
-            get => showNewFilePopupOnStartup;
-            set
-            {
-                showNewFilePopupOnStartup = value;
-                string name = nameof(ShowNewFilePopupOnStartup);
-                RaiseAndUpdatePreference(name, value);
-            }
-        }
-
-        private bool checkUpdatesOnStartup = PreferencesSettings.GetPreference("CheckUpdatesOnStartup", true);
-
-        public bool CheckUpdatesOnStartup
-        {
-            get => checkUpdatesOnStartup;
-            set
-            {
-                checkUpdatesOnStartup = value;
-                string name = nameof(CheckUpdatesOnStartup);
-                RaiseAndUpdatePreference(name, value);
-            }
-        }
-
-        private long defaultNewFileWidth = (int)PreferencesSettings.GetPreference("DefaultNewFileWidth", 16L);
-
-        public long DefaultNewFileWidth
-        {
-            get => defaultNewFileWidth;
-            set
-            {
-                defaultNewFileWidth = value;
-                string name = nameof(DefaultNewFileWidth);
-                RaiseAndUpdatePreference(name, value);
-            }
-        }
-
-        private long defaultNewFileHeight = (int)PreferencesSettings.GetPreference("DefaultNewFileHeight", 16L);
-
-        public long DefaultNewFileHeight
-        {
-            get => defaultNewFileHeight;
-            set
-            {
-                defaultNewFileHeight = value;
-                string name = nameof(DefaultNewFileHeight);
-                RaiseAndUpdatePreference(name, value);
-            }
-        }
-
-        public class DiscordSettings : SettingsGroup
-        {
-            private bool enableRichPresence = GetPreference(nameof(EnableRichPresence), true);
-
-            public bool EnableRichPresence
-            {
-                get => enableRichPresence;
-                set
-                {
-                    enableRichPresence = value;
-                    RaiseAndUpdatePreference(nameof(EnableRichPresence), value);
-                }
-            }
-
-            private bool showDocumentName = GetPreference(nameof(ShowDocumentName), true);
-
-            public bool ShowDocumentName
-            {
-                get => showDocumentName;
-                set
-                {
-                    showDocumentName = value;
-                    RaiseAndUpdatePreference(nameof(ShowDocumentName), value);
-                    RaisePropertyChanged(nameof(DetailPreview));
-                }
-            }
-
-            private bool showDocumentSize = GetPreference(nameof(ShowDocumentSize), true);
-
-            public bool ShowDocumentSize
-            {
-                get => showDocumentSize;
-                set
-                {
-                    showDocumentSize = value;
-                    RaiseAndUpdatePreference(nameof(ShowDocumentSize), value);
-                    RaisePropertyChanged(nameof(StatePreview));
-                }
-            }
-
-            private bool showLayerCount = GetPreference(nameof(ShowLayerCount), true);
-
-            public bool ShowLayerCount
-            {
-                get => showLayerCount;
-                set
-                {
-                    showLayerCount = value;
-                    RaiseAndUpdatePreference(nameof(ShowLayerCount), value);
-                    RaisePropertyChanged(nameof(StatePreview));
-                }
-            }
-
-            public string DetailPreview
-            {
-                get
-                {
-                    return ShowDocumentName ? $"Editing coolPixelArt.pixi" : "Editing something (incognito)";
-                }
-            }
-
-            public string StatePreview
-            {
-                get
-                {
-                    string state = string.Empty;
-
-                    if (ShowDocumentSize)
-                    {
-                        state = "16x16";
-                    }
-
-                    if (ShowDocumentSize && ShowLayerCount)
-                    {
-                        state += ", ";
-                    }
-
-                    if (ShowLayerCount)
-                    {
-                        state += "2 Layers";
-                    }
-
-                    return state;
-                }
-            }
-        }
+        public UpdateSettings Update { get; set; } = new UpdateSettings();
 
 
         public DiscordSettings Discord { get; set; } = new DiscordSettings();
         public DiscordSettings Discord { get; set; } = new DiscordSettings();
 
 
-        public void RaiseAndUpdatePreference<T>(string name, T value)
-        {
-            RaisePropertyChanged(name);
-            PreferencesSettings.UpdatePreference(name, value);
-        }
-
         public SettingsViewModel(SettingsWindowViewModel owner)
         public SettingsViewModel(SettingsWindowViewModel owner)
             : base(owner)
             : base(owner)
         {
         {

+ 9 - 3
PixiEditor/ViewModels/ViewModelMain.cs

@@ -4,6 +4,7 @@ using System.ComponentModel;
 using System.Linq;
 using System.Linq;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
+using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers.Shortcuts;
 using PixiEditor.Models.Controllers.Shortcuts;
@@ -64,9 +65,15 @@ namespace PixiEditor.ViewModels
 
 
         public ShortcutController ShortcutController { get; set; }
         public ShortcutController ShortcutController { get; set; }
 
 
-        public ViewModelMain()
+        public IPreferences Preferences { get; set; }
+
+        public ViewModelMain(IServiceProvider services)
         {
         {
-            PreferencesSettings.Init();
+            Current = this;
+
+            Preferences = services.GetRequiredService<IPreferences>();
+
+            Preferences.Init();
 
 
             BitmapManager = new BitmapManager();
             BitmapManager = new BitmapManager();
             BitmapManager.BitmapOperations.BitmapChanged += BitmapUtility_BitmapChanged;
             BitmapManager.BitmapOperations.BitmapChanged += BitmapUtility_BitmapChanged;
@@ -144,7 +151,6 @@ namespace PixiEditor.ViewModels
                 }
                 }
             };
             };
             BitmapManager.PrimaryColor = ColorsSubViewModel.PrimaryColor;
             BitmapManager.PrimaryColor = ColorsSubViewModel.PrimaryColor;
-            Current = this;
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 40 - 0
PixiEditor/Views/Dialogs/NoticePopup.xaml

@@ -0,0 +1,40 @@
+<Window x:Class="PixiEditor.Views.Dialogs.NoticePopup"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:system="clr-namespace:System;assembly=System.Runtime" xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        mc:Ignorable="d"
+        Title="NoticePopup" Height="200" Width="500"
+        x:Name="popup">
+
+    <WindowChrome.WindowChrome>
+        <WindowChrome CaptionHeight="32"
+                      ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
+    </WindowChrome.WindowChrome>
+
+    <Grid Background="{StaticResource AccentColor}" Focusable="True">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="35" />
+            <RowDefinition Height="34*" />
+            <RowDefinition Height="21*" />
+        </Grid.RowDefinitions>
+        <i:Interaction.Behaviors>
+            <behaviours:ClearFocusOnClickBehavior/>
+        </i:Interaction.Behaviors>
+        <TextBlock Grid.Row="1" Text="{Binding Body, ElementName=popup}" HorizontalAlignment="Center"
+                   VerticalAlignment="Center" FontSize="18" Foreground="White" />
+        <DockPanel Grid.Row="0" Background="{StaticResource MainColor}">
+            <Button DockPanel.Dock="Right" HorizontalAlignment="Right" Style="{StaticResource CloseButtonStyle}"
+                    WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Close"
+                    Command="{Binding DataContext.CancelCommand, ElementName=popup}" />
+        </DockPanel>
+        <StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center"
+                    Margin="0,0,10,10">
+            <Button Height="30" Width="60"
+                    Click="OkButton_Close"
+                    Style="{StaticResource DarkRoundButton}" Content="Ok">
+            </Button>
+        </StackPanel>
+    </Grid>
+</Window>

+ 41 - 0
PixiEditor/Views/Dialogs/NoticePopup.xaml.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace PixiEditor.Views.Dialogs
+{
+    /// <summary>
+    /// Interaction logic for NoticePopup.xaml.
+    /// </summary>
+    public partial class NoticePopup : Window
+    {
+        public static readonly DependencyProperty BodyProperty =
+            DependencyProperty.Register(nameof(Body), typeof(string), typeof(NoticePopup));
+
+        public string Body
+        {
+            get => (string)GetValue(BodyProperty);
+            set => SetValue(BodyProperty, value);
+        }
+
+        public NoticePopup()
+        {
+            InitializeComponent();
+        }
+
+        private void OkButton_Close(object sender, RoutedEventArgs e)
+        {
+            Close();
+        }
+    }
+}

+ 8 - 4
PixiEditor/Views/Dialogs/SettingsWindow.xaml

@@ -58,13 +58,17 @@
                     <Label Content="File" Style="{StaticResource Header1}"/>
                     <Label Content="File" Style="{StaticResource Header1}"/>
                     <StackPanel Orientation="Vertical" Margin="50 0 50 0">
                     <StackPanel Orientation="Vertical" Margin="50 0 50 0">
                         <CheckBox Content="Show New File dialog on startup" 
                         <CheckBox Content="Show New File dialog on startup" 
-                                  IsChecked="{Binding SettingsSubViewModel.ShowNewFilePopupOnStartup}"/>
+                                  IsChecked="{Binding SettingsSubViewModel.File.ShowNewFilePopupOnStartup}"/>
+                        <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
+                            <Label Content="Max Saved Opened Recently:" ToolTip="How many documents are shown under File > Recent. Default: 10" Style="{StaticResource BaseLabel}"/>
+                            <views:NumberInput FontSize="16" Value="{Binding SettingsSubViewModel.File.MaxOpenedRecently}" Width="40"/>
+                        </StackPanel>
                         <Label Content="Default new file size:" Style="{StaticResource Header2}" Margin="0 20 0 20"/>
                         <Label Content="Default new file size:" Style="{StaticResource Header2}" Margin="0 20 0 20"/>
                         <StackPanel Orientation="Horizontal" Margin="40,0,0,0">
                         <StackPanel Orientation="Horizontal" Margin="40,0,0,0">
                             <Label Content="Width:" Style="{StaticResource BaseLabel}"/>
                             <Label Content="Width:" Style="{StaticResource BaseLabel}"/>
-                            <views:SizeInput FontSize="16" Size="{Binding SettingsSubViewModel.DefaultNewFileWidth, Mode=TwoWay}" Width="60" Height="25"/>
+                            <views:SizeInput FontSize="16" Size="{Binding SettingsSubViewModel.File.DefaultNewFileWidth, Mode=TwoWay}" Width="60" Height="25"/>
                             <Label Content="Height:" Style="{StaticResource BaseLabel}"/>
                             <Label Content="Height:" Style="{StaticResource BaseLabel}"/>
-                            <views:SizeInput FontSize="16" Size="{Binding SettingsSubViewModel.DefaultNewFileHeight, Mode=TwoWay}" Width="60" Height="25"/>
+                            <views:SizeInput FontSize="16" Size="{Binding SettingsSubViewModel.File.DefaultNewFileHeight, Mode=TwoWay}" Width="60" Height="25"/>
                         </StackPanel>
                         </StackPanel>
                     </StackPanel>
                     </StackPanel>
                 </StackPanel>
                 </StackPanel>
@@ -74,7 +78,7 @@
                 <StackPanel Orientation="Vertical">
                 <StackPanel Orientation="Vertical">
                     <Label Style="{StaticResource Header1}" Content="Auto-updates"/>
                     <Label Style="{StaticResource Header1}" Content="Auto-updates"/>
                     <StackPanel Orientation="Vertical" Margin="50 0 50 0">
                     <StackPanel Orientation="Vertical" Margin="50 0 50 0">
-                        <CheckBox IsChecked="{Binding SettingsSubViewModel.CheckUpdatesOnStartup}" Content="Check updates on startup"/>
+                        <CheckBox IsChecked="{Binding SettingsSubViewModel.Update.CheckUpdatesOnStartup}" Content="Check updates on startup"/>
                     </StackPanel>
                     </StackPanel>
                 </StackPanel>
                 </StackPanel>
             </Grid>
             </Grid>

+ 436 - 421
PixiEditor/Views/MainWindow.xaml

@@ -1,422 +1,437 @@
-<Window x:Class="PixiEditor.MainWindow" MinHeight="500" MinWidth="1100"
-        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:vm="clr-namespace:PixiEditor.ViewModels"
-        xmlns:vws="clr-namespace:PixiEditor.Views"
-        xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
-        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
-        xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
-        xmlns:cmd="http://www.galasoft.ch/mvvmlight" 
-        xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
-        xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker" xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls" xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
-        xmlns:avalonDockTheme="clr-namespace:PixiEditor.Styles.AvalonDock"
-        mc:Ignorable="d" WindowStyle="None" Initialized="MainWindow_Initialized"
-        Title="PixiEditor" Name="mainWindow" Height="1000" Width="1600" Background="{StaticResource MainColor}"
-        WindowStartupLocation="CenterScreen" WindowState="Maximized" DataContext="{DynamicResource ViewModelMain}">
-    <WindowChrome.WindowChrome>
-        <WindowChrome CaptionHeight="32"
-                      ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
-    </WindowChrome.WindowChrome>
-
-    <Window.Resources>
-        <ResourceDictionary>
-            <vm:ViewModelMain x:Key="ViewModelMain" />
-            <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
-            <converters:BoolToIntConverter x:Key="BoolToIntConverter" />
-            <converters:NotNullToBoolConverter x:Key="NotNullToBoolConverter" />
-            <converters:FloatNormalizeConverter x:Key="FloatNormalizeConverter" />
-            <converters:DoubleToIntConverter x:Key="DoubleToIntConverter"/>
-            <ResourceDictionary.MergedDictionaries>
-                <ResourceDictionary Source="pack://application:,,,/ColorPicker;component/Styles/DefaultColorPickerStyle.xaml" />
-            </ResourceDictionary.MergedDictionaries>
-        </ResourceDictionary>
-    </Window.Resources>
-
-    <Window.CommandBindings>
-        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute"
-                        Executed="CommandBinding_Executed_Close" />
-        <CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}"
-                        CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
-        <CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}"
-                        CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
-        <CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute"
-                        Executed="CommandBinding_Executed_Restore" />
-    </Window.CommandBindings>
-
-    <i:Interaction.Triggers>
-        <i:EventTrigger EventName="KeyDown">
-            <cmd:EventToCommand Command="{Binding IoSubViewModel.KeyDownCommand}" PassEventArgsToCommand="True" />
-        </i:EventTrigger>
-        <i:EventTrigger EventName="KeyUp">
-            <cmd:EventToCommand Command="{Binding IoSubViewModel.KeyUpCommand}" PassEventArgsToCommand="True"/>
-        </i:EventTrigger>
-        <i:EventTrigger EventName="ContentRendered">
-            <i:InvokeCommandAction Command="{Binding OnStartupCommand}" />
-        </i:EventTrigger>
-        <i:EventTrigger EventName="Closing">
-            <cmd:EventToCommand Command="{Binding CloseWindowCommand}" PassEventArgsToCommand="True" />
-        </i:EventTrigger>
-    </i:Interaction.Triggers>
-    <Grid Name="mainGrid" Margin="5" Focusable="True">
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="45" />
-            <ColumnDefinition Width="1*" />
-        </Grid.ColumnDefinitions>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="30" />
-            <RowDefinition Height="40" />
-            <RowDefinition Height="1*" />
-            <RowDefinition Height="30" />
-        </Grid.RowDefinitions>
-        <i:Interaction.Behaviors>
-            <behaviours:ClearFocusOnClickBehavior/>
-        </i:Interaction.Behaviors>
-        <DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Background="{StaticResource MainColor}">
-            <Image DockPanel.Dock="Left" HorizontalAlignment="Left" VerticalAlignment="Top"
-                   Source="/Images/PixiEditorLogo.png" Width="20" Height="20" Margin="5,5,0,0" />
-            <Menu WindowChrome.IsHitTestVisibleInChrome="True" Margin="10, 4, 0, 0" DockPanel.Dock="Left"
-                  HorizontalAlignment="Left" VerticalAlignment="Top" Background="Transparent" IsMainMenu="True">
-                <Menu.Resources>
-                    <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource menuItemStyle}" />
-                </Menu.Resources>
-                <MenuItem Header="_File">
-                    <MenuItem InputGestureText="CTRL+N" Header="_New" Command="{Binding FileSubViewModel.OpenNewFilePopupCommand}" />
-                    <MenuItem Header="_Open" InputGestureText="Ctrl+O" Command="{Binding FileSubViewModel.OpenFileCommand}" />
-                    <MenuItem Header="_Save" InputGestureText="Ctrl+S" Command="{Binding FileSubViewModel.SaveDocumentCommand}" />
-                    <MenuItem Header="_Save As..." InputGestureText="Ctrl+Shift+S"
-                              Command="{Binding FileSubViewModel.SaveDocumentCommand}" CommandParameter="AsNew" />
-                    <MenuItem Header="_Export" InputGestureText="Ctrl+Shift+Alt+S" Command="{Binding FileSubViewModel.ExportFileCommand}" />
-                    <Separator />
-                    <MenuItem Header="_Exit" Command="{x:Static SystemCommands.CloseWindowCommand}" />
-                </MenuItem>
-                <MenuItem Header="_Edit">
-                    <MenuItem Header="_Undo" InputGestureText="Ctrl+Z" Command="{Binding UndoSubViewModel.UndoCommand}" />
-                    <MenuItem Header="_Redo" InputGestureText="Ctrl+Y" Command="{Binding UndoSubViewModel.RedoCommand}" />
-                    <Separator />
-                    <MenuItem Header="_Cut" Command="{Binding ClipboardSubViewModel.CutCommand}" InputGestureText="Ctrl+X" />
-                    <MenuItem Header="_Copy" Command="{Binding ClipboardSubViewModel.CopyCommand}" InputGestureText="Ctrl+C" />
-                    <MenuItem Header="_Paste" Command="{Binding ClipboardSubViewModel.PasteCommand}" InputGestureText="Ctrl+V" />
-                    <MenuItem Header="_Duplicate" Command="{Binding ClipboardSubViewModel.DuplicateCommand}" InputGestureText="Ctrl+J" />
-                    <Separator />
-                    <MenuItem Header="_Delete Selected" Command="{Binding DocumentSubViewModel.DeletePixelsCommand}"
-                              InputGestureText="Delete" />
-                    <Separator />
-                    <MenuItem Header="_Settings" Command="{Binding MiscSubViewModel.OpenSettingsWindowCommand}" />
-                </MenuItem>
-                <MenuItem Header="_Select">
-                    <MenuItem Header="_Select All" Command="{Binding SelectionSubViewModel.SelectAllCommand}" InputGestureText="Ctrl+A" />
-                    <MenuItem Header="_Deselect" Command="{Binding SelectionSubViewModel.DeselectCommand}" InputGestureText="Ctrl+D" />
-                </MenuItem>
-                <MenuItem Header="_Document">
-                    <MenuItem Header="_Resize Document..." Command="{Binding DocumentSubViewModel.OpenResizePopupCommand}"
-                              InputGestureText="Ctrl+Shift+I" />
-                    <MenuItem Header="_Resize Canvas..." Command="{Binding DocumentSubViewModel.OpenResizePopupCommand}"
-                              CommandParameter="canvas" InputGestureText="Ctrl+Shift+C" />
-                    <MenuItem Header="_Clip Canvas" Command="{Binding DocumentSubViewModel.ClipCanvasCommand}" />
-                    <Separator/>
-                    <MenuItem Header="_Center Content" Command="{Binding DocumentSubViewModel.CenterContentCommand}" />
-                </MenuItem>
-                <MenuItem Header="_View">
-                    <MenuItem Header="_Show Grid Lines" IsChecked="{Binding ViewportSubViewModel.GridLinesEnabled, Mode=TwoWay}"
-                              IsCheckable="True" InputGestureText="Ctrl+`"/>
-                </MenuItem>
-                <MenuItem Header="_Help">
-                    <MenuItem Header="_Documentation" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
-                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki"/>
-                    <MenuItem Header="_Repository" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
-                              CommandParameter="https://github.com/PixiEditor/PixiEditor"/>
-                    <MenuItem Header="_Shortcuts" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
-                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki/Shortcuts"/>
-                    <Separator/>
-                    <MenuItem Header="_License" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
-                              CommandParameter="https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE"/>
-                    <MenuItem Header="_Third Party Licenses" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
-                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki/Third-party-licenses"/>
-                </MenuItem>
-            </Menu>
-            <StackPanel DockPanel.Dock="Right" VerticalAlignment="Top" Orientation="Horizontal"
-                        HorizontalAlignment="Right" WindowChrome.IsHitTestVisibleInChrome="True">
-                <Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
-                        ToolTip="Minimize"
-                        Command="{x:Static SystemCommands.MinimizeWindowCommand}" />
-                <Button x:Name="RestoreButton" Visibility="Visible" Style="{StaticResource RestoreButtonStyle}"
-                        Command="{x:Static SystemCommands.RestoreWindowCommand}"
-                        WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Restore" />
-                <Button x:Name="MaximizeButton" Visibility="Collapsed" Style="{StaticResource MaximizeButtonStyle}"
-                        Command="{x:Static SystemCommands.MaximizeWindowCommand}"
-                        WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Maximize" />
-                <Button Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
-                        ToolTip="Close"
-                        Command="{x:Static SystemCommands.CloseWindowCommand}" />
-            </StackPanel>
-        </DockPanel>
-        <StackPanel Background="{StaticResource MainColor}" Orientation="Horizontal" Grid.ColumnSpan="3" Grid.Column="0"
-                     Grid.Row="1">
-            <Label Style="{StaticResource BaseLabel}" Margin="10,0,0,0" FontSize="12" VerticalAlignment="Center" Content="{Binding BitmapManager.SelectedTool.ToolName}"/>
-            <Label Style="{StaticResource BaseLabel}" Padding="0" FontSize="12" VerticalAlignment="Center" Content="tool"/>
-            <ItemsControl ItemsSource="{Binding BitmapManager.SelectedTool.Toolbar.Settings}">
-                <ItemsControl.ItemsPanel>
-                    <ItemsPanelTemplate>
-                        <StackPanel Orientation="Horizontal" Margin="10, 0, 0, 0" />
-                    </ItemsPanelTemplate>
-                </ItemsControl.ItemsPanel>
-                <ItemsControl.ItemTemplate>
-                    <DataTemplate>
-                        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,10,0">
-                            <Label
-                                Visibility="{Binding HasLabel, Converter={StaticResource BoolToVisibilityConverter}}"
-                                Foreground="White" Content="{Binding Label}" />
-                            <ContentControl Content="{Binding SettingControl}" />
-                        </StackPanel>
-                    </DataTemplate>
-                </ItemsControl.ItemTemplate>
-            </ItemsControl>
-        </StackPanel>
-        <Grid Grid.Column="1" Grid.Row="2" Background="#303030">
-            <Grid>
-                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay}" 
-                                           DocumentsSource="{Binding BitmapManager.Documents}">
-                    <DockingManager.Theme>
-                        <avalonDockTheme:PixiEditorDockTheme />
-                    </DockingManager.Theme>
-                    <avalondock:DockingManager.LayoutItemContainerStyleSelector>
-                        <ui:PanelsStyleSelector>
-                            <ui:PanelsStyleSelector.DocumentTabStyle>
-                                <Style TargetType="{x:Type avalondock:LayoutItem}">
-                                    <Setter Property="Title" Value="{Binding Model.Name}" />
-                                    <Setter Property="CloseCommand" Value="{Binding Model.RequestCloseDocumentCommand}" />
-                                </Style>
-                            </ui:PanelsStyleSelector.DocumentTabStyle>
-                        </ui:PanelsStyleSelector>
-                    </avalondock:DockingManager.LayoutItemContainerStyleSelector>
-                    <DockingManager.LayoutItemTemplateSelector>
-                        <ui:DocumentsTemplateSelector>
-                            <ui:DocumentsTemplateSelector.DocumentsViewTemplate>
-                                <DataTemplate DataType="{x:Type vm:ViewModelMain}">
-                                    <usercontrols:DrawingViewPort
-                                        ZoomPercentage="{Binding ZoomPercentage}"
-                                        RecenterZoombox="{Binding RecenterZoombox}"
-                                        GridLinesVisible="{Binding XamlAccesibleViewModel.ViewportSubViewModel.GridLinesEnabled}"
-                                        Cursor="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ToolCursor}"
-                                        MiddleMouseClickedCommand="{Binding XamlAccesibleViewModel.ToolsSubViewModel.SelectToolCommand}"
-                                        ViewportPosition="{Binding ViewportPosition}"
-                                        MouseMoveCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseMoveCommand}"
-                                        MouseDownCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseDownCommand}"
-                                        MouseXOnCanvas="{Binding MouseXOnCanvas, Mode=TwoWay}"
-                                        MouseYOnCanvas="{Binding MouseYOnCanvas, Mode=TwoWay}">
-                                        <i:Interaction.Triggers>
-                                            <i:EventTrigger EventName="PreviewMouseDown">
-                                                <i:InvokeCommandAction Command="{Binding SetAsActiveOnClickCommand}"/>
-                                            </i:EventTrigger>
-                                        </i:Interaction.Triggers>
-                                    </usercontrols:DrawingViewPort>
-                                </DataTemplate>
-                            </ui:DocumentsTemplateSelector.DocumentsViewTemplate>
-                        </ui:DocumentsTemplateSelector>
-                    </DockingManager.LayoutItemTemplateSelector>
-                    <avalondock:LayoutRoot x:Name="LayoutRoot">
-                        <LayoutPanel Orientation="Horizontal">
-                            <LayoutDocumentPane/>
-                            <LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="290">
-                                <LayoutAnchorablePane>
-                                <LayoutAnchorable ContentId="colorPicker" Title="Color Picker" CanHide="False"
-                                                             CanClose="False" CanAutoHide="False"
-                                                             CanDockAsTabbedDocument="False" CanFloat="True">
-                                    <colorpicker:StandardColorPicker Grid.Row="0" SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay}"
-                                     SecondaryColor="{Binding ColorsSubViewModel.SecondaryColor, Mode=TwoWay}" Style="{StaticResource DefaultColorPickerStyle}" >
-                                        <i:Interaction.Behaviors>
-                                            <behaviours:GlobalShortcutFocusBehavior/>
-                                        </i:Interaction.Behaviors>
-                                    </colorpicker:StandardColorPicker>
-                                </LayoutAnchorable>
-                                <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"
-                                                         CanClose="False" CanAutoHide="False"
-                                                         CanDockAsTabbedDocument="False" CanFloat="True">
-                                    <ScrollViewer HorizontalScrollBarVisibility="Disabled"
-                                              VerticalScrollBarVisibility="Auto">
-                                        <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Swatches}">
-                                            <ItemsControl.ItemsPanel>
-                                                <ItemsPanelTemplate>
-                                                    <WrapPanel Margin="10,10,0,10" Orientation="Horizontal"
-                                                           VerticalAlignment="Top" HorizontalAlignment="Left" />
-                                                </ItemsPanelTemplate>
-                                            </ItemsControl.ItemsPanel>
-                                            <ItemsControl.ItemTemplate>
-                                                <DataTemplate>
-                                                    <Grid Width="45" Height="45" Margin="0 5 5 5">
-                                                        <Border CornerRadius="5.5" Width="44" Height="44">
-                                                            <Border.Background>
-                                                                <ImageBrush ImageSource="../Images/transparentbg.png"
-                                                                        Stretch="UniformToFill">
-                                                                    <ImageBrush.RelativeTransform>
-                                                                        <ScaleTransform ScaleX="6" ScaleY="6" CenterX="0.5"
-                                                                                    CenterY="0.5" />
-                                                                    </ImageBrush.RelativeTransform>
-                                                                </ImageBrush>
-                                                            </Border.Background>
-                                                        </Border>
-                                                        <Border CornerRadius="5.5" BorderThickness="0 0 0 0.1" BorderBrush="White" Cursor="Hand">
-                                                            <Border.Background>
-                                                                <SolidColorBrush Color="{Binding}" />
-                                                            </Border.Background>
-                                                        </Border>
-                                                        <i:Interaction.Triggers>
-                                                            <i:EventTrigger EventName="MouseDown">
-                                                                <i:InvokeCommandAction
-                                                                Command="{Binding
-                                                                    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ColorsSubViewModel.SelectColorCommand}"
-                                                                CommandParameter="{Binding}" />
-                                                            </i:EventTrigger>
-                                                        </i:Interaction.Triggers>
-                                                        <Grid.ContextMenu>
-                                                            <ContextMenu>
-                                                                <MenuItem Header="Remove" Foreground="White"
-                                                                      Command="{Binding ColorsSubViewModel.RemoveSwatchCommand, Source={StaticResource ViewModelMain}}"
-                                                                      CommandParameter="{Binding}" />
-                                                            </ContextMenu>
-                                                        </Grid.ContextMenu>
-                                                    </Grid>
-                                                </DataTemplate>
-                                            </ItemsControl.ItemTemplate>
-                                        </ItemsControl>
-                                    </ScrollViewer>
-                                </avalondock:LayoutAnchorable>
-                            </LayoutAnchorablePane>
-                                <LayoutAnchorablePane>
-                                    <LayoutAnchorable ContentId="layers" Title="Layers" CanHide="False"
-                                                         CanClose="False" CanAutoHide="False"
-                                                         CanDockAsTabbedDocument="True" CanFloat="True">
-                                        <Grid>
-                                            <Grid.RowDefinitions>
-                                                <RowDefinition Height="40"/>
-                                                <RowDefinition Height="30"/>
-                                                <RowDefinition Height="15"/>
-                                                <RowDefinition Height="1*"/>
-                                            </Grid.RowDefinitions>
-                                            <Button Grid.Row="0" Command="{Binding LayersSubViewModel.NewLayerCommand}" Height="30" Content="New Layer"
-                                            HorizontalAlignment="Stretch" Margin="5"
-                                            Style="{StaticResource DarkRoundButton}" />
-                                            <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10,0">
-                                                <Label Content="Opacity" Foreground="White" VerticalAlignment="Center"/>
-                                                <vws:NumberInput 
-                                                    Min="0" Max="100"
-                                                    IsEnabled="{Binding Path=BitmapManager.ActiveDocument, 
-                                                    Converter={StaticResource NotNullToBoolConverter}}" 
-                                                    Width="40" Height="20"
-                                                    VerticalAlignment="Center"
-                                                   Value="{Binding BitmapManager.ActiveDocument.ActiveLayer.OpacityUndoTriggerable, Mode=TwoWay, 
-                                            Converter={StaticResource FloatNormalizeConverter}}" />
-                                                <Label Content="%" Foreground="White" VerticalAlignment="Center"/>
-                                            </StackPanel>
-                                            <Separator Grid.Row="2" Background="{StaticResource BrighterAccentColor}"/>
-                                            <ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
-                                                <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Layers}"
-                                                      x:Name="layersItemsControl" AlternationCount="9999">
-                                                    <ItemsControl.ItemsPanel>
-                                                        <ItemsPanelTemplate>
-                                                            <ui:ReversedOrderStackPanel Orientation="Vertical" />
-                                                        </ItemsPanelTemplate>
-                                                    </ItemsControl.ItemsPanel>
-                                                    <ItemsControl.ItemTemplate>
-                                                        <DataTemplate>
-                                                            <vws:LayerItem LayerIndex="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" SetActiveLayerCommand="{Binding Path=DataContext.LayersSubViewModel.SetActiveLayerCommand, ElementName=mainWindow}"
-                                                                   LayerName="{Binding Name, Mode=TwoWay}" IsActive="{Binding IsActive, Mode=TwoWay}"
-                                                                   IsRenaming="{Binding IsRenaming, Mode=TwoWay}"
-                                                                   PreviewImage="{Binding LayerBitmap}"
-                                                                   MoveToBackCommand="{Binding DataContext.LayersSubViewModel.MoveToBackCommand, ElementName=mainWindow}"
-                                                                   MoveToFrontCommand="{Binding DataContext.LayersSubViewModel.MoveToFrontCommand, ElementName=mainWindow}">
-                                                                <vws:LayerItem.ContextMenu>
-                                                                    <ContextMenu>
-                                                                        <MenuItem Header="Delete"
-                                                                                  Command="{Binding LayersSubViewModel.DeleteLayersCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                        <MenuItem Header="Rename"
-                                                                                  Command="{Binding LayersSubViewModel.RenameLayerCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                        <MenuItem Header="Move to front"
-                                                                                  Command="{Binding LayersSubViewModel.MoveToFrontCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                        <MenuItem Header="Move to back"
-                                                                                  Command="{Binding LayersSubViewModel.MoveToBackCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                        <Separator/>
-                                                                        <MenuItem Header="Merge selected"
-                                                                                  Command="{Binding LayersSubViewModel.MergeSelectedCommand, Source={StaticResource ViewModelMain}}"/>
-                                                                        <MenuItem Header="Merge with above"
-                                                                                  Command="{Binding LayersSubViewModel.MergeWithAboveCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                        <MenuItem Header="Merge with below"
-                                                                                  Command="{Binding LayersSubViewModel.MergeWithBelowCommand, Source={StaticResource ViewModelMain}}"
-                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
-                                Path=(ItemsControl.AlternationIndex)}" />
-                                                                    </ContextMenu>
-                                                                </vws:LayerItem.ContextMenu>
-                                                            </vws:LayerItem>
-                                                        </DataTemplate>
-                                                    </ItemsControl.ItemTemplate>
-                                                </ItemsControl>
-                                            </ScrollViewer>
-                                        </Grid>
-                                    </LayoutAnchorable>
-                                </LayoutAnchorablePane>
-                            </LayoutAnchorablePaneGroup>
-                        </LayoutPanel>
-                    </avalondock:LayoutRoot>
-                </DockingManager>
-            </Grid>
-        </Grid>
-
-        <StackPanel Orientation="Vertical" Cursor="Arrow" Grid.Row="2" Grid.Column="0"
-                    Background="{StaticResource AccentColor}" Grid.RowSpan="2">
-
-            <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ToolSet}">
-                <ItemsControl.ItemTemplate>
-                    <DataTemplate>
-                        <Button BorderBrush="White"
-                                BorderThickness="{Binding IsActive, Converter={StaticResource BoolToIntConverter}}"
-                                Style="{StaticResource ToolButtonStyle}"
-                                Command="{Binding Path=DataContext.ToolsSubViewModel.SelectToolCommand,
-                            RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
-                                CommandParameter="{Binding}" ToolTip="{Binding Tooltip}">
-                            <Button.Background>
-                                <ImageBrush ImageSource="{Binding ImagePath}" Stretch="Uniform" />
-                            </Button.Background>
-                        </Button>
-                    </DataTemplate>
-                </ItemsControl.ItemTemplate>
-            </ItemsControl>
-        </StackPanel>
-
-        <Grid Grid.Row="3" Grid.Column="1">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*"/>
-                <ColumnDefinition Width="290"/>
-            </Grid.ColumnDefinitions>
-            <DockPanel>
-            <TextBlock Text="{Binding BitmapManager.SelectedTool.ActionDisplay}" Foreground="White" FontSize="15" Margin="10,0,0,0" VerticalAlignment="Center"/>
-            <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
-                <TextBlock Text="X:" Foreground="White" FontSize="16"/>
-                <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseXOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
-                <TextBlock Text="Y:" Foreground="White" FontSize="16"/>
-                <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseYOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
-            </StackPanel>
-        </DockPanel>
-        <StackPanel Margin="10,0,0,0" VerticalAlignment="Center" Grid.Row="3"
-                       Grid.Column="3" Orientation="Horizontal">
-            <Button Style="{StaticResource BaseDarkButton}" 
-                    Visibility="{Binding UpdateSubViewModel.UpdateReadyToInstall, Converter={StaticResource BoolToVisibilityConverter}}" FontSize="14" Height="20" 
-                    Command="{Binding UpdateSubViewModel.RestartApplicationCommand}">Restart</Button>
-            <TextBlock VerticalAlignment="Center" Padding="10" HorizontalAlignment="Right"
-                       Foreground="White" FontSize="14"  Text="{Binding UpdateSubViewModel.VersionText}" />
-        </StackPanel>
-        </Grid>
-    </Grid>
+<Window x:Class="PixiEditor.MainWindow" MinHeight="500" MinWidth="1100"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:vm="clr-namespace:PixiEditor.ViewModels"
+        xmlns:vws="clr-namespace:PixiEditor.Views"
+        xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
+        xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
+        xmlns:cmd="http://www.galasoft.ch/mvvmlight" 
+        xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
+        xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker" xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls" xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
+        xmlns:avalonDockTheme="clr-namespace:PixiEditor.Styles.AvalonDock"
+        mc:Ignorable="d" WindowStyle="None" Initialized="MainWindow_Initialized"
+        Title="PixiEditor" Name="mainWindow" Height="1000" Width="1600" Background="{StaticResource MainColor}"
+        WindowStartupLocation="CenterScreen" WindowState="Maximized">
+    <WindowChrome.WindowChrome>
+        <WindowChrome CaptionHeight="32"
+                      ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
+    </WindowChrome.WindowChrome>
+
+    <Window.Resources>
+        <ResourceDictionary>
+            <!--<vm:ViewModelMain x:Key="ViewModelMain" />-->
+            <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
+            <converters:BoolToIntConverter x:Key="BoolToIntConverter" />
+            <converters:NotNullToBoolConverter x:Key="NotNullToBoolConverter" />
+            <converters:FloatNormalizeConverter x:Key="FloatNormalizeConverter" />
+            <converters:DoubleToIntConverter x:Key="DoubleToIntConverter"/>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="pack://application:,,,/ColorPicker;component/Styles/DefaultColorPickerStyle.xaml" />
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </Window.Resources>
+
+    <Window.CommandBindings>
+        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute"
+                        Executed="CommandBinding_Executed_Close" />
+        <CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}"
+                        CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
+        <CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}"
+                        CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
+        <CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute"
+                        Executed="CommandBinding_Executed_Restore" />
+    </Window.CommandBindings>
+
+    <i:Interaction.Triggers>
+        <i:EventTrigger EventName="KeyDown">
+            <cmd:EventToCommand Command="{Binding IoSubViewModel.KeyDownCommand}" PassEventArgsToCommand="True" />
+        </i:EventTrigger>
+        <i:EventTrigger EventName="KeyUp">
+            <cmd:EventToCommand Command="{Binding IoSubViewModel.KeyUpCommand}" PassEventArgsToCommand="True"/>
+        </i:EventTrigger>
+        <i:EventTrigger EventName="ContentRendered">
+            <i:InvokeCommandAction Command="{Binding OnStartupCommand}" />
+        </i:EventTrigger>
+        <i:EventTrigger EventName="Closing">
+            <cmd:EventToCommand Command="{Binding CloseWindowCommand}" PassEventArgsToCommand="True" />
+        </i:EventTrigger>
+    </i:Interaction.Triggers>
+    <Grid Name="mainGrid" Margin="5" Focusable="True">
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="45" />
+            <ColumnDefinition Width="1*" />
+        </Grid.ColumnDefinitions>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="30" />
+            <RowDefinition Height="40" />
+            <RowDefinition Height="1*" />
+            <RowDefinition Height="30" />
+        </Grid.RowDefinitions>
+        <i:Interaction.Behaviors>
+            <behaviours:ClearFocusOnClickBehavior/>
+        </i:Interaction.Behaviors>
+        <DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Background="{StaticResource MainColor}">
+            <Image DockPanel.Dock="Left" HorizontalAlignment="Left" VerticalAlignment="Top"
+                   Source="/Images/PixiEditorLogo.png" Width="20" Height="20" Margin="5,5,0,0" />
+            <Menu WindowChrome.IsHitTestVisibleInChrome="True" Margin="10, 4, 0, 0" DockPanel.Dock="Left"
+                  HorizontalAlignment="Left" VerticalAlignment="Top" Background="Transparent" IsMainMenu="True">
+                <Menu.Resources>
+                    <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource menuItemStyle}" />
+                </Menu.Resources>
+                <MenuItem Header="_File">
+                    <MenuItem InputGestureText="CTRL+N" Header="_New" Command="{Binding FileSubViewModel.OpenNewFilePopupCommand}" />
+                    <MenuItem Header="_Open" InputGestureText="Ctrl+O" Command="{Binding FileSubViewModel.OpenFileCommand}" />
+                    <MenuItem Header="_Recent" ItemsSource="{Binding FileSubViewModel.RecentlyOpened}" x:Name="recentItemMenu" IsEnabled="{Binding FileSubViewModel.HasRecent}">
+                        <MenuItem.ItemContainerStyle>
+                            <Style TargetType="MenuItem" BasedOn="{StaticResource menuItemStyle}">
+                                <Setter Property="Command" Value="{Binding ElementName=recentItemMenu, Path=DataContext.FileSubViewModel.OpenRecentCommand}"/>
+                                <Setter Property="CommandParameter" Value="{Binding}"/>
+                            </Style>
+                        </MenuItem.ItemContainerStyle>
+                    </MenuItem>
+                    <MenuItem Header="_Save" InputGestureText="Ctrl+S" Command="{Binding FileSubViewModel.SaveDocumentCommand}" />
+                    <MenuItem Header="_Save As..." InputGestureText="Ctrl+Shift+S"
+                              Command="{Binding FileSubViewModel.SaveDocumentCommand}" CommandParameter="AsNew" />
+                    <MenuItem Header="_Export" InputGestureText="Ctrl+Shift+Alt+S" Command="{Binding FileSubViewModel.ExportFileCommand}" />
+                    <Separator />
+                    <MenuItem Header="_Exit" Command="{x:Static SystemCommands.CloseWindowCommand}" />
+                </MenuItem>
+                <MenuItem Header="_Edit">
+                    <MenuItem Header="_Undo" InputGestureText="Ctrl+Z" Command="{Binding UndoSubViewModel.UndoCommand}" />
+                    <MenuItem Header="_Redo" InputGestureText="Ctrl+Y" Command="{Binding UndoSubViewModel.RedoCommand}" />
+                    <Separator />
+                    <MenuItem Header="_Cut" Command="{Binding ClipboardSubViewModel.CutCommand}" InputGestureText="Ctrl+X" />
+                    <MenuItem Header="_Copy" Command="{Binding ClipboardSubViewModel.CopyCommand}" InputGestureText="Ctrl+C" />
+                    <MenuItem Header="_Paste" Command="{Binding ClipboardSubViewModel.PasteCommand}" InputGestureText="Ctrl+V" />
+                    <MenuItem Header="_Duplicate" Command="{Binding ClipboardSubViewModel.DuplicateCommand}" InputGestureText="Ctrl+J" />
+                    <Separator />
+                    <MenuItem Header="_Delete Selected" Command="{Binding DocumentSubViewModel.DeletePixelsCommand}"
+                              InputGestureText="Delete" />
+                    <Separator />
+                    <MenuItem Header="_Settings" Command="{Binding MiscSubViewModel.OpenSettingsWindowCommand}" />
+                </MenuItem>
+                <MenuItem Header="_Select">
+                    <MenuItem Header="_Select All" Command="{Binding SelectionSubViewModel.SelectAllCommand}" InputGestureText="Ctrl+A" />
+                    <MenuItem Header="_Deselect" Command="{Binding SelectionSubViewModel.DeselectCommand}" InputGestureText="Ctrl+D" />
+                </MenuItem>
+                <MenuItem Header="_Document">
+                    <MenuItem Header="_Resize Document..." Command="{Binding DocumentSubViewModel.OpenResizePopupCommand}"
+                              InputGestureText="Ctrl+Shift+I" />
+                    <MenuItem Header="_Resize Canvas..." Command="{Binding DocumentSubViewModel.OpenResizePopupCommand}"
+                              CommandParameter="canvas" InputGestureText="Ctrl+Shift+C" />
+                    <MenuItem Header="_Clip Canvas" Command="{Binding DocumentSubViewModel.ClipCanvasCommand}" />
+                    <Separator/>
+                    <MenuItem Header="_Center Content" Command="{Binding DocumentSubViewModel.CenterContentCommand}" />
+                </MenuItem>
+                <MenuItem Header="_View">
+                    <MenuItem Header="_Show Grid Lines" IsChecked="{Binding ViewportSubViewModel.GridLinesEnabled, Mode=TwoWay}"
+                              IsCheckable="True" InputGestureText="Ctrl+`"/>
+                </MenuItem>
+                <MenuItem Header="_Help">
+                    <MenuItem Header="_Documentation" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
+                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki"/>
+                    <MenuItem Header="_Repository" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
+                              CommandParameter="https://github.com/PixiEditor/PixiEditor"/>
+                    <MenuItem Header="_Shortcuts" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
+                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki/Shortcuts"/>
+                    <Separator/>
+                    <MenuItem Header="_License" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
+                              CommandParameter="https://github.com/PixiEditor/PixiEditor/blob/master/LICENSE"/>
+                    <MenuItem Header="_Third Party Licenses" Command="{Binding MiscSubViewModel.OpenHyperlinkCommand}"
+                              CommandParameter="https://github.com/PixiEditor/PixiEditor/wiki/Third-party-licenses"/>
+                </MenuItem>
+            </Menu>
+            <StackPanel DockPanel.Dock="Right" VerticalAlignment="Top" Orientation="Horizontal"
+                        HorizontalAlignment="Right" WindowChrome.IsHitTestVisibleInChrome="True">
+                <Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
+                        ToolTip="Minimize"
+                        Command="{x:Static SystemCommands.MinimizeWindowCommand}" />
+                <Button x:Name="RestoreButton" Visibility="Visible" Style="{StaticResource RestoreButtonStyle}"
+                        Command="{x:Static SystemCommands.RestoreWindowCommand}"
+                        WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Restore" />
+                <Button x:Name="MaximizeButton" Visibility="Collapsed" Style="{StaticResource MaximizeButtonStyle}"
+                        Command="{x:Static SystemCommands.MaximizeWindowCommand}"
+                        WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Maximize" />
+                <Button Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
+                        ToolTip="Close"
+                        Command="{x:Static SystemCommands.CloseWindowCommand}" />
+            </StackPanel>
+        </DockPanel>
+        <StackPanel Background="{StaticResource MainColor}" Orientation="Horizontal" Grid.ColumnSpan="3" Grid.Column="0"
+                     Grid.Row="1">
+            <Label Style="{StaticResource BaseLabel}" Margin="10,0,0,0" FontSize="12" VerticalAlignment="Center" Content="{Binding BitmapManager.SelectedTool.ToolName}"/>
+            <Label Style="{StaticResource BaseLabel}" Padding="0" FontSize="12" VerticalAlignment="Center" Content="tool"/>
+            <ItemsControl ItemsSource="{Binding BitmapManager.SelectedTool.Toolbar.Settings}">
+                <ItemsControl.ItemsPanel>
+                    <ItemsPanelTemplate>
+                        <StackPanel Orientation="Horizontal" Margin="10, 0, 0, 0" />
+                    </ItemsPanelTemplate>
+                </ItemsControl.ItemsPanel>
+                <ItemsControl.ItemTemplate>
+                    <DataTemplate>
+                        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,10,0">
+                            <Label
+                                Visibility="{Binding HasLabel, Converter={StaticResource BoolToVisibilityConverter}}"
+                                Foreground="White" Content="{Binding Label}" />
+                            <ContentControl Content="{Binding SettingControl}" />
+                        </StackPanel>
+                    </DataTemplate>
+                </ItemsControl.ItemTemplate>
+            </ItemsControl>
+        </StackPanel>
+        <Grid Grid.Column="1" Grid.Row="2" Background="#303030">
+            <Grid>
+                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay}" 
+                                           DocumentsSource="{Binding BitmapManager.Documents}">
+                    <DockingManager.Theme>
+                        <avalonDockTheme:PixiEditorDockTheme />
+                    </DockingManager.Theme>
+                    <avalondock:DockingManager.LayoutItemContainerStyleSelector>
+                        <ui:PanelsStyleSelector>
+                            <ui:PanelsStyleSelector.DocumentTabStyle>
+                                <Style TargetType="{x:Type avalondock:LayoutItem}">
+                                    <Setter Property="Title" Value="{Binding Model.Name}" />
+                                    <Setter Property="CloseCommand" Value="{Binding Model.RequestCloseDocumentCommand}" />
+                                </Style>
+                            </ui:PanelsStyleSelector.DocumentTabStyle>
+                        </ui:PanelsStyleSelector>
+                    </avalondock:DockingManager.LayoutItemContainerStyleSelector>
+                    <DockingManager.LayoutItemTemplateSelector>
+                        <ui:DocumentsTemplateSelector>
+                            <ui:DocumentsTemplateSelector.DocumentsViewTemplate>
+                                <DataTemplate DataType="{x:Type vm:ViewModelMain}">
+                                    <usercontrols:DrawingViewPort
+                                        ZoomPercentage="{Binding ZoomPercentage}"
+                                        RecenterZoombox="{Binding RecenterZoombox}"
+                                        GridLinesVisible="{Binding XamlAccesibleViewModel.ViewportSubViewModel.GridLinesEnabled}"
+                                        Cursor="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ToolCursor}"
+                                        MiddleMouseClickedCommand="{Binding XamlAccesibleViewModel.ToolsSubViewModel.SelectToolCommand}"
+                                        ViewportPosition="{Binding ViewportPosition}"
+                                        MouseMoveCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseMoveCommand}"
+                                        MouseDownCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseDownCommand}"
+                                        MouseXOnCanvas="{Binding MouseXOnCanvas, Mode=TwoWay}"
+                                        MouseYOnCanvas="{Binding MouseYOnCanvas, Mode=TwoWay}">
+                                        <i:Interaction.Triggers>
+                                            <i:EventTrigger EventName="PreviewMouseDown">
+                                                <i:InvokeCommandAction Command="{Binding SetAsActiveOnClickCommand}"/>
+                                            </i:EventTrigger>
+                                        </i:Interaction.Triggers>
+                                    </usercontrols:DrawingViewPort>
+                                </DataTemplate>
+                            </ui:DocumentsTemplateSelector.DocumentsViewTemplate>
+                        </ui:DocumentsTemplateSelector>
+                    </DockingManager.LayoutItemTemplateSelector>
+                    <avalondock:LayoutRoot x:Name="LayoutRoot">
+                        <LayoutPanel Orientation="Horizontal">
+                            <LayoutDocumentPane/>
+                            <LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="290">
+                                <LayoutAnchorablePane>
+                                <LayoutAnchorable ContentId="colorPicker" Title="Color Picker" CanHide="False"
+                                                             CanClose="False" CanAutoHide="False"
+                                                             CanDockAsTabbedDocument="False" CanFloat="True">
+                                    <colorpicker:StandardColorPicker Grid.Row="0" SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay}"
+                                     SecondaryColor="{Binding ColorsSubViewModel.SecondaryColor, Mode=TwoWay}" Style="{StaticResource DefaultColorPickerStyle}" >
+                                        <i:Interaction.Behaviors>
+                                            <behaviours:GlobalShortcutFocusBehavior/>
+                                        </i:Interaction.Behaviors>
+                                    </colorpicker:StandardColorPicker>
+                                </LayoutAnchorable>
+                                <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"
+                                                         CanClose="False" CanAutoHide="False"
+                                                         CanDockAsTabbedDocument="False" CanFloat="True">
+                                    <ScrollViewer HorizontalScrollBarVisibility="Disabled"
+                                              VerticalScrollBarVisibility="Auto">
+                                        <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Swatches}">
+                                            <ItemsControl.ItemsPanel>
+                                                <ItemsPanelTemplate>
+                                                    <WrapPanel Margin="10,10,0,10" Orientation="Horizontal"
+                                                           VerticalAlignment="Top" HorizontalAlignment="Left" />
+                                                </ItemsPanelTemplate>
+                                            </ItemsControl.ItemsPanel>
+                                            <ItemsControl.ItemTemplate>
+                                                <DataTemplate>
+                                                    <Grid Width="45" Height="45" Margin="0 5 5 5">
+                                                        <Border CornerRadius="5.5" Width="44" Height="44">
+                                                            <Border.Background>
+                                                                <ImageBrush ImageSource="../Images/transparentbg.png"
+                                                                        Stretch="UniformToFill">
+                                                                    <ImageBrush.RelativeTransform>
+                                                                        <ScaleTransform ScaleX="6" ScaleY="6" CenterX="0.5"
+                                                                                    CenterY="0.5" />
+                                                                    </ImageBrush.RelativeTransform>
+                                                                </ImageBrush>
+                                                            </Border.Background>
+                                                        </Border>
+                                                        <Border CornerRadius="5.5" BorderThickness="0 0 0 0.1" BorderBrush="White" Cursor="Hand">
+                                                            <Border.Background>
+                                                                <SolidColorBrush Color="{Binding}" />
+                                                            </Border.Background>
+                                                        </Border>
+                                                        <i:Interaction.Triggers>
+                                                            <i:EventTrigger EventName="MouseDown">
+                                                                <i:InvokeCommandAction
+                                                                Command="{Binding
+                                                                    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ColorsSubViewModel.SelectColorCommand}"
+                                                                CommandParameter="{Binding}" />
+                                                            </i:EventTrigger>
+                                                        </i:Interaction.Triggers>
+                                                        <Grid.ContextMenu>
+                                                            <ContextMenu>
+                                                                <MenuItem Header="Remove" Foreground="White"
+                                                                      Command="{Binding ColorsSubViewModel.RemoveSwatchCommand}"
+                                                                      CommandParameter="{Binding}" />
+                                                            </ContextMenu>
+                                                        </Grid.ContextMenu>
+                                                    </Grid>
+                                                </DataTemplate>
+                                            </ItemsControl.ItemTemplate>
+                                        </ItemsControl>
+                                    </ScrollViewer>
+                                </avalondock:LayoutAnchorable>
+                            </LayoutAnchorablePane>
+                                <LayoutAnchorablePane>
+                                    <LayoutAnchorable ContentId="layers" Title="Layers" CanHide="False"
+                                                         CanClose="False" CanAutoHide="False"
+                                                         CanDockAsTabbedDocument="True" CanFloat="True">
+                                        <Grid>
+                                            <Grid.RowDefinitions>
+                                                <RowDefinition Height="40"/>
+                                                <RowDefinition Height="30"/>
+                                                <RowDefinition Height="15"/>
+                                                <RowDefinition Height="1*"/>
+                                            </Grid.RowDefinitions>
+                                            <Button Grid.Row="0" Command="{Binding LayersSubViewModel.NewLayerCommand}" Height="30" Content="New Layer"
+                                            HorizontalAlignment="Stretch" Margin="5"
+                                            Style="{StaticResource DarkRoundButton}" />
+                                            <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10,0">
+                                                <Label Content="Opacity" Foreground="White" VerticalAlignment="Center"/>
+                                                <vws:NumberInput 
+                                                    Min="0" Max="100"
+                                                    IsEnabled="{Binding Path=BitmapManager.ActiveDocument, 
+                                                    Converter={StaticResource NotNullToBoolConverter}}" 
+                                                    Width="40" Height="20"
+                                                    VerticalAlignment="Center"
+                                                   Value="{Binding BitmapManager.ActiveDocument.ActiveLayer.OpacityUndoTriggerable, Mode=TwoWay, 
+                                            Converter={StaticResource FloatNormalizeConverter}}" />
+                                                <Label Content="%" Foreground="White" VerticalAlignment="Center"/>
+                                            </StackPanel>
+                                            <Separator Grid.Row="2" Background="{StaticResource BrighterAccentColor}"/>
+                                            <ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
+                                                <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Layers}"
+                                                      x:Name="layersItemsControl" AlternationCount="9999">
+                                                    <ItemsControl.ItemsPanel>
+                                                        <ItemsPanelTemplate>
+                                                            <ui:ReversedOrderStackPanel Orientation="Vertical" />
+                                                        </ItemsPanelTemplate>
+                                                    </ItemsControl.ItemsPanel>
+                                                    <ItemsControl.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <vws:LayerItem Tag="{Binding DataContext, ElementName=mainWindow}" LayerIndex="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" SetActiveLayerCommand="{Binding Path=DataContext.LayersSubViewModel.SetActiveLayerCommand, ElementName=mainWindow}"
+                                                                   LayerName="{Binding Name, Mode=TwoWay}" IsActive="{Binding IsActive, Mode=TwoWay}"
+                                                                   IsRenaming="{Binding IsRenaming, Mode=TwoWay}"
+                                                                   PreviewImage="{Binding LayerBitmap}"
+                                                                   MoveToBackCommand="{Binding DataContext.LayersSubViewModel.MoveToBackCommand, ElementName=mainWindow}"
+                                                                   MoveToFrontCommand="{Binding DataContext.LayersSubViewModel.MoveToFrontCommand, ElementName=mainWindow}">
+                                                                <vws:LayerItem.ContextMenu>
+                                                                    <ContextMenu>
+                                                                        <MenuItem Header="Delete"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.DeleteLayerCommand,
+                                                                                    RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                        <MenuItem Header="Rename"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.RenameLayerCommand,
+                                                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                        <MenuItem Header="Move to front"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.MoveToFrontCommand, 
+                                                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                        <MenuItem Header="Move to back"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.MoveToBackCommand, 
+                                                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                        <Separator/>
+                                                                        <MenuItem Header="Merge selected"
+                                                                                  Command="{Binding LayersSubViewModel.MergeSelectedCommand, Source={StaticResource ViewModelMain}}"/>
+                                                                        <MenuItem Header="Merge with above"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.MergeWithAboveCommand, 
+                                                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                        <MenuItem Header="Merge with below"
+                                                                                  Command="{Binding PlacementTarget.Tag.LayersSubViewModel.MergeWithBelowCommand, 
+                                                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                                                                                  CommandParameter="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
+                                Path=(ItemsControl.AlternationIndex)}" />
+                                                                    </ContextMenu>
+                                                                </vws:LayerItem.ContextMenu>
+                                                            </vws:LayerItem>
+                                                        </DataTemplate>
+                                                    </ItemsControl.ItemTemplate>
+                                                </ItemsControl>
+                                            </ScrollViewer>
+                                        </Grid>
+                                    </LayoutAnchorable>
+                                </LayoutAnchorablePane>
+                            </LayoutAnchorablePaneGroup>
+                        </LayoutPanel>
+                    </avalondock:LayoutRoot>
+                </DockingManager>
+            </Grid>
+        </Grid>
+
+        <StackPanel Orientation="Vertical" Cursor="Arrow" Grid.Row="2" Grid.Column="0"
+                    Background="{StaticResource AccentColor}" Grid.RowSpan="2">
+
+            <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ToolSet}">
+                <ItemsControl.ItemTemplate>
+                    <DataTemplate>
+                        <Button BorderBrush="White"
+                                BorderThickness="{Binding IsActive, Converter={StaticResource BoolToIntConverter}}"
+                                Style="{StaticResource ToolButtonStyle}"
+                                Command="{Binding Path=DataContext.ToolsSubViewModel.SelectToolCommand,
+                            RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
+                                CommandParameter="{Binding}" ToolTip="{Binding Tooltip}">
+                            <Button.Background>
+                                <ImageBrush ImageSource="{Binding ImagePath}" Stretch="Uniform" />
+                            </Button.Background>
+                        </Button>
+                    </DataTemplate>
+                </ItemsControl.ItemTemplate>
+            </ItemsControl>
+        </StackPanel>
+
+        <Grid Grid.Row="3" Grid.Column="1">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="*"/>
+                <ColumnDefinition Width="290"/>
+            </Grid.ColumnDefinitions>
+            <DockPanel>
+            <TextBlock Text="{Binding BitmapManager.SelectedTool.ActionDisplay}" Foreground="White" FontSize="15" Margin="10,0,0,0" VerticalAlignment="Center"/>
+            <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
+                <TextBlock Text="X:" Foreground="White" FontSize="16"/>
+                <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseXOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
+                <TextBlock Text="Y:" Foreground="White" FontSize="16"/>
+                <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseYOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
+            </StackPanel>
+        </DockPanel>
+        <StackPanel Margin="10,0,0,0" VerticalAlignment="Center" Grid.Row="3"
+                       Grid.Column="3" Orientation="Horizontal">
+            <Button Style="{StaticResource BaseDarkButton}" 
+                    Visibility="{Binding UpdateSubViewModel.UpdateReadyToInstall, Converter={StaticResource BoolToVisibilityConverter}}" FontSize="14" Height="20" 
+                    Command="{Binding UpdateSubViewModel.RestartApplicationCommand}">Restart</Button>
+            <TextBlock VerticalAlignment="Center" Padding="10" HorizontalAlignment="Right"
+                       Foreground="White" FontSize="14"  Text="{Binding UpdateSubViewModel.VersionText}" />
+        </StackPanel>
+        </Grid>
+    </Grid>
 </Window>
 </Window>

+ 8 - 0
PixiEditor/Views/MainWindow.xaml.cs

@@ -5,9 +5,11 @@ using System.IO;
 using System.Reflection;
 using System.Reflection;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
+using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Processes;
 using PixiEditor.Models.Processes;
+using PixiEditor.Models.UserPreferences;
 using PixiEditor.UpdateModule;
 using PixiEditor.UpdateModule;
 using PixiEditor.ViewModels;
 using PixiEditor.ViewModels;
 
 
@@ -23,6 +25,12 @@ namespace PixiEditor
         public MainWindow()
         public MainWindow()
         {
         {
             InitializeComponent();
             InitializeComponent();
+
+            IServiceCollection services = new ServiceCollection()
+                .AddSingleton<IPreferences>(new PreferencesSettings());
+
+            DataContext = new ViewModelMain(services.BuildServiceProvider());
+
             StateChanged += MainWindowStateChangeRaised;
             StateChanged += MainWindowStateChangeRaised;
             MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
             MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
             viewModel = (ViewModelMain)DataContext;
             viewModel = (ViewModelMain)DataContext;

+ 24 - 0
PixiEditorTests/Helpers.cs

@@ -0,0 +1,24 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using PixiEditor.Models.UserPreferences;
+using PixiEditor.ViewModels;
+
+namespace PixiEditorTests
+{
+    public static class Helpers
+    {
+        public static ViewModelMain MockedViewModelMain()
+        {
+            IServiceProvider provider = MockedServiceProvider();
+
+            return new ViewModelMain(provider);
+        }
+
+        public static IServiceProvider MockedServiceProvider()
+        {
+            return new ServiceCollection()
+                .AddSingleton<IPreferences>(new Mocks.PreferenceSettingsMock())
+                .BuildServiceProvider();
+        }
+    }
+}

+ 56 - 0
PixiEditorTests/Mocks/PreferenceSettingsMock.cs

@@ -0,0 +1,56 @@
+using System;
+using PixiEditor.Models.UserPreferences;
+
+namespace PixiEditorTests.Mocks
+{
+    public class PreferenceSettingsMock : IPreferences
+    {
+        public void AddCallback(string setting, Action<object> action)
+        {
+        }
+
+#nullable enable
+
+        public T? GetLocalPreference<T>(string name)
+        {
+            return default;
+        }
+
+        public T? GetLocalPreference<T>(string name, T? fallbackValue)
+        {
+            return fallbackValue;
+        }
+
+        public T? GetPreference<T>(string name)
+        {
+            return default;
+        }
+
+        public T? GetPreference<T>(string name, T? fallbackValue)
+        {
+            return fallbackValue;
+        }
+
+#nullable disable
+
+        public void Init()
+        {
+        }
+
+        public void Init(string path, string localPath)
+        {
+        }
+
+        public void Save()
+        {
+        }
+
+        public void UpdateLocalPreference<T>(string name, T value)
+        {
+        }
+
+        public void UpdatePreference<T>(string name, T value)
+        {
+        }
+    }
+}

+ 18 - 0
PixiEditorTests/ModelsTests/DataHoldersTests/DocumentTests.cs

@@ -4,6 +4,7 @@ using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
+using PixiEditor.ViewModels;
 using Xunit;
 using Xunit;
 
 
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
@@ -283,5 +284,22 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             Assert.Equal("Test", document.Layers[1].Name);
             Assert.Equal("Test", document.Layers[1].Name);
             Assert.Equal("Test2", document.Layers[0].Name);
             Assert.Equal("Test2", document.Layers[0].Name);
         }
         }
+
+        [StaFact]
+        public void TestThatDocumentGetsAddedToRecentlyOpenedList()
+        {
+            ViewModelMain viewModel = Helpers.MockedViewModelMain();
+
+            Document document = new Document(1, 1)
+            {
+                XamlAccesibleViewModel = viewModel
+            };
+
+            string testFilePath = @"C:\idk\somewhere\homework";
+
+            document.DocumentFilePath = testFilePath;
+
+            Assert.Contains(viewModel.FileSubViewModel.RecentlyOpened, x => x == testFilePath);
+        }
     }
     }
 }
 }

+ 4 - 2
PixiEditorTests/ModelsTests/ToolsTests/ZoomToolTests.cs

@@ -1,4 +1,6 @@
-using PixiEditor.Models.Tools.Tools;
+using Microsoft.Extensions.DependencyInjection;
+using PixiEditor.Models.Tools.Tools;
+using PixiEditor.Models.UserPreferences;
 using PixiEditor.ViewModels;
 using PixiEditor.ViewModels;
 using Xunit;
 using Xunit;
 
 
@@ -10,7 +12,7 @@ namespace PixiEditorTests.ModelsTests.ToolsTests
         [StaFact]
         [StaFact]
         public void TestThatZoomSetsActiveDocumentZoomPercentage()
         public void TestThatZoomSetsActiveDocumentZoomPercentage()
         {
         {
-            ViewModelMain vm = new ViewModelMain();
+            ViewModelMain vm = new ViewModelMain(new ServiceCollection().AddSingleton<IPreferences>(new Mocks.PreferenceSettingsMock()).BuildServiceProvider());
             vm.BitmapManager.ActiveDocument = new PixiEditor.Models.DataHolders.Document(10, 10);
             vm.BitmapManager.ActiveDocument = new PixiEditor.Models.DataHolders.Document(10, 10);
             ZoomTool zoomTool = new ZoomTool();
             ZoomTool zoomTool = new ZoomTool();
             double zoom = 110;
             double zoom = 110;

+ 43 - 1
PixiEditorTests/ModelsTests/UserPreferencesTests/PreferencesSettingsTests.cs

@@ -10,9 +10,13 @@ namespace PixiEditorTests.ModelsTests.UserPreferencesTests
     {
     {
         public static string PathToPreferencesFile { get; } = Path.Join("PixiEditor", "test_preferences.json");
         public static string PathToPreferencesFile { get; } = Path.Join("PixiEditor", "test_preferences.json");
 
 
+        public static string PathToLocalPreferencesFile { get; } = Path.Join("PixiEditor", "local_test_preferences.json");
+
+        public static readonly PreferencesSettings PreferencesSettings = new PreferencesSettings();
+
         public PreferencesSettingsTests()
         public PreferencesSettingsTests()
         {
         {
-            PreferencesSettings.Init(PathToPreferencesFile);
+            PreferencesSettings.Init(PathToPreferencesFile, PathToLocalPreferencesFile);
         }
         }
 
 
         [Fact]
         [Fact]
@@ -25,6 +29,7 @@ namespace PixiEditorTests.ModelsTests.UserPreferencesTests
         public void TestThatInitCreatesUserPreferencesJson()
         public void TestThatInitCreatesUserPreferencesJson()
         {
         {
             Assert.True(File.Exists(PathToPreferencesFile));
             Assert.True(File.Exists(PathToPreferencesFile));
+            Assert.True(File.Exists(PathToLocalPreferencesFile));
         }
         }
 
 
         [Theory]
         [Theory]
@@ -63,5 +68,42 @@ namespace PixiEditorTests.ModelsTests.UserPreferencesTests
                 Assert.Equal(value, dict[name]);
                 Assert.Equal(value, dict[name]);
             }
             }
         }
         }
+
+        [Theory]
+        [InlineData(-2)]
+        [InlineData(false)]
+        [InlineData("string")]
+        [InlineData(null)]
+        public void TestThatGetPreferenceOnNonExistingKeyReturnsFallbackValueLocal<T>(T value)
+        {
+            T fallbackValue = value;
+            T preferenceValue = PreferencesSettings.GetLocalPreference<T>("NonExistingPreference", fallbackValue);
+            Assert.Equal(fallbackValue, preferenceValue);
+        }
+
+        [Theory]
+        [InlineData("IntPreference", 1)]
+        [InlineData("BoolPreference", true)]
+        public void TestThatUpdatePreferenceUpdatesDictionaryLocal<T>(string name, T value)
+        {
+            PreferencesSettings.UpdateLocalPreference(name, value);
+            Assert.Equal(value, PreferencesSettings.GetLocalPreference<T>(name));
+        }
+
+        [Theory]
+        [InlineData("LongPreference", 1L)]
+        public void TestThatSaveUpdatesFileLocal<T>(string name, T value)
+        {
+            PreferencesSettings.LocalPreferences[name] = value;
+            PreferencesSettings.Save();
+            using (var fs = new FileStream(PathToPreferencesFile, FileMode.Open, FileAccess.Read, FileShare.Read))
+            {
+                using StreamReader sr = new StreamReader(fs);
+                string json = sr.ReadToEnd();
+                var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
+                Assert.True(dict.ContainsKey(name));
+                Assert.Equal(value, dict[name]);
+            }
+        }
     }
     }
 }
 }

+ 2 - 0
PixiEditorTests/PixiEditorTests.csproj

@@ -23,6 +23,8 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     </PackageReference>
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
     <PackageReference Include="Moq" Version="4.16.0" />
     <PackageReference Include="Moq" Version="4.16.0" />
     <PackageReference Include="OpenCover" Version="4.7.922" />
     <PackageReference Include="OpenCover" Version="4.7.922" />

+ 24 - 12
PixiEditorTests/ViewModelsTests/ViewModelMainTests.cs

@@ -1,12 +1,15 @@
-using System.IO;
+using System;
+using System.IO;
 using System.Windows.Input;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media;
+using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools.Tools;
 using PixiEditor.Models.Tools.Tools;
+using PixiEditor.Models.UserPreferences;
 using PixiEditor.ViewModels;
 using PixiEditor.ViewModels;
 using Xunit;
 using Xunit;
 
 
@@ -15,10 +18,19 @@ namespace PixiEditorTests.ViewModelsTests
     [Collection("Application collection")]
     [Collection("Application collection")]
     public class ViewModelMainTests
     public class ViewModelMainTests
     {
     {
+        public static IServiceProvider Services;
+
+        public ViewModelMainTests()
+        {
+            Services = new ServiceCollection()
+                .AddSingleton<IPreferences>(new Mocks.PreferenceSettingsMock())
+                .BuildServiceProvider();
+        }
+
         [StaFact]
         [StaFact]
         public void TestThatConstructorSetsUpControllersCorrectly()
         public void TestThatConstructorSetsUpControllersCorrectly()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             Assert.NotNull(viewModel.ChangesController);
             Assert.NotNull(viewModel.ChangesController);
             Assert.NotNull(viewModel.ShortcutController);
             Assert.NotNull(viewModel.ShortcutController);
@@ -30,7 +42,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatSwapColorsCommandSwapsColors()
         public void TestThatSwapColorsCommandSwapsColors()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             viewModel.ColorsSubViewModel.PrimaryColor = Colors.Black;
             viewModel.ColorsSubViewModel.PrimaryColor = Colors.Black;
             viewModel.ColorsSubViewModel.SecondaryColor = Colors.White;
             viewModel.ColorsSubViewModel.SecondaryColor = Colors.White;
@@ -44,7 +56,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatNewDocumentCreatesNewDocumentWithBaseLayer()
         public void TestThatNewDocumentCreatesNewDocumentWithBaseLayer()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             viewModel.FileSubViewModel.NewDocument(5, 5);
             viewModel.FileSubViewModel.NewDocument(5, 5);
 
 
@@ -55,7 +67,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatMouseMoveCommandUpdatesCurrentCoordinates()
         public void TestThatMouseMoveCommandUpdatesCurrentCoordinates()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
             viewModel.BitmapManager.ActiveDocument = new Document(10, 10);
             viewModel.BitmapManager.ActiveDocument = new Document(10, 10);
 
 
             Assert.Equal(new Coordinates(0, 0), MousePositionConverter.CurrentCoordinates);
             Assert.Equal(new Coordinates(0, 0), MousePositionConverter.CurrentCoordinates);
@@ -71,7 +83,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatSelectToolCommandSelectsNewTool()
         public void TestThatSelectToolCommandSelectsNewTool()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             Assert.Equal(typeof(MoveViewportTool), viewModel.BitmapManager.SelectedTool.GetType());
             Assert.Equal(typeof(MoveViewportTool), viewModel.BitmapManager.SelectedTool.GetType());
 
 
@@ -83,7 +95,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatMouseUpCommandStopsRecordingMouseMovements()
         public void TestThatMouseUpCommandStopsRecordingMouseMovements()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             viewModel.BitmapManager.MouseController.StartRecordingMouseMovementChanges(true);
             viewModel.BitmapManager.MouseController.StartRecordingMouseMovementChanges(true);
 
 
@@ -97,7 +109,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatNewLayerCommandCreatesNewLayer()
         public void TestThatNewLayerCommandCreatesNewLayer()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
 
 
@@ -111,7 +123,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatSaveDocumentCommandSavesFile()
         public void TestThatSaveDocumentCommandSavesFile()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
             string fileName = "testFile.pixi";
             string fileName = "testFile.pixi";
 
 
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1)
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1)
@@ -129,7 +141,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatAddSwatchAddsNonDuplicateSwatch()
         public void TestThatAddSwatchAddsNonDuplicateSwatch()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
 
 
             viewModel.ColorsSubViewModel.AddSwatch(Colors.Green);
             viewModel.ColorsSubViewModel.AddSwatch(Colors.Green);
@@ -149,7 +161,7 @@ namespace PixiEditorTests.ViewModelsTests
         [InlineData(120, 150)]
         [InlineData(120, 150)]
         public void TestThatSelectAllCommandSelectsWholeDocument(int docWidth, int docHeight)
         public void TestThatSelectAllCommandSelectsWholeDocument(int docWidth, int docHeight)
         {
         {
-            ViewModelMain viewModel = new ViewModelMain
+            ViewModelMain viewModel = new ViewModelMain(Services)
             {
             {
                 BitmapManager = { ActiveDocument = new Document(docWidth, docHeight) }
                 BitmapManager = { ActiveDocument = new Document(docWidth, docHeight) }
             };
             };
@@ -165,7 +177,7 @@ namespace PixiEditorTests.ViewModelsTests
         [StaFact]
         [StaFact]
         public void TestThatDocumentIsNotNullReturnsTrue()
         public void TestThatDocumentIsNotNullReturnsTrue()
         {
         {
-            ViewModelMain viewModel = new ViewModelMain();
+            ViewModelMain viewModel = new ViewModelMain(Services);
 
 
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
 
 

+ 3 - 3
README.md

@@ -24,9 +24,9 @@ Have you ever used Photoshop or Gimp? Reinventing the wheel is unnecessary, we w
 
 
 
 
 
 
-### Light weighted
+### Lightweight
 
 
-Program weights only 3.3 MB! Already have .NET 5 installed? Download installer and enjoy saved space.
+Program weighs only 3.3 MB! Already have .NET 5 installed? Download installer and enjoy saved space.
 
 
 ### Active development
 ### Active development
 
 
@@ -38,7 +38,7 @@ PixiEditor started in 2018 and it's been actively developed since. We continuous
 
 
 Follow these instructions to get PixiEditor working on your machine.
 Follow these instructions to get PixiEditor working on your machine.
 
 
-1. Download .exe file from [here](https://github.com/flabbet/PixiEditor/releases)
+1. Download the .exe file from [here](https://github.com/flabbet/PixiEditor/releases)
 2. Open installer
 2. Open installer
 3. Follow installer instructions
 3. Follow installer instructions