Browse Source

Wrote load and save change on disk and wrote tests for it

flabbet 4 years ago
parent
commit
ca9c23b8f1

+ 3 - 2
PixiEditor/Models/IO/Importer.cs

@@ -18,7 +18,7 @@ namespace PixiEditor.Models.IO
         /// <param name="path">Path of image.</param>
         /// <param name="width">New width of image.</param>
         /// <param name="height">New height of image.</param>
-        /// <returns>WriteableBitmap of improted image.</returns>
+        /// <returns>WriteableBitmap of imported image.</returns>
         public static WriteableBitmap ImportImage(string path, int width, int height)
         {
             WriteableBitmap wbmp = ImportImage(path);
@@ -38,10 +38,11 @@ namespace PixiEditor.Models.IO
         {
             try
             {
-                Uri uri = new Uri(path);
+                Uri uri = new Uri(path, UriKind.RelativeOrAbsolute);
                 BitmapImage bitmap = new BitmapImage();
                 bitmap.BeginInit();
                 bitmap.UriSource = uri;
+                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                 bitmap.EndInit();
 
                 return BitmapFactory.ConvertToPbgra32Format(bitmap);

+ 79 - 3
PixiEditor/Models/Undo/StorageBasedChange.cs

@@ -1,4 +1,11 @@
-using PixiEditor.Models.DataHolders;
+using System;
+using System.Buffers.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Layers;
 
@@ -8,9 +15,78 @@ namespace PixiEditor.Models.Undo
     {
         public string UndoChangeLocation { get; set; }
 
-        public void SaveLayersOnDevice(Document document, Layer[] layers)
+        public UndoLayer[] StoredLayers { get; set; }
+
+        private IEnumerable<Layer> layersToStore;
+
+        private Document document;
+
+        public StorageBasedChange(Document doc, IEnumerable<Layer> layers, string undoChangeLocation)
+        {
+            document = doc;
+            layersToStore = layers;
+            UndoChangeLocation = undoChangeLocation;
+            GenerateUndoLayers();
+        }
+
+        public void SaveLayersOnDevice()
+        {
+            int i = 0;
+            foreach (var layer in layersToStore)
+            {
+                UndoLayer storedLayer = StoredLayers[i];
+                Exporter.SaveAsPng(storedLayer.StoredPngLayerName, storedLayer.Width, storedLayer.Height, layer.LayerBitmap);
+                i++;
+            }
+
+            layersToStore = null;
+        }
+
+        public Layer[] LoadLayersFromDevice()
+        {
+            Layer[] layers = new Layer[StoredLayers.Length];
+            for (int i = 0; i < StoredLayers.Length; i++)
+            {
+                UndoLayer storedLayer = StoredLayers[i];
+                var bitmap = Importer.ImportImage(storedLayer.StoredPngLayerName, storedLayer.Width, storedLayer.Height);
+                layers[i] = new Layer(storedLayer.Name, bitmap)
+                {
+                    Offset = new System.Windows.Thickness(storedLayer.OffsetX, storedLayer.OffsetY, 0, 0),
+                    Opacity = storedLayer.Opacity,
+                    MaxWidth = storedLayer.MaxWidth,
+                    MaxHeight = storedLayer.MaxHeight,
+                    IsVisible = storedLayer.IsVisible,
+                    IsActive = storedLayer.IsActive,
+                };
+
+                File.Delete(StoredLayers[i].StoredPngLayerName);
+            }
+
+            layersToStore = layers;
+            return layers;
+        }
+
+        private void GenerateUndoLayers()
         {
-            Exporter.SaveAsPng(UndoChangeLocation, layers[0].Width, layers[0].Height, layers[0].LayerBitmap)
+            StoredLayers = new UndoLayer[layersToStore.Count()];
+            int i = 0;
+            foreach (var layer in layersToStore)
+            {
+                if (!document.Layers.Contains(layer))
+                {
+                    throw new ArgumentException("Provided document doesn't contain selected layer");
+                }
+
+                int index = document.Layers.IndexOf(layer);
+                string pngName = layer.Name + index + Guid.NewGuid().ToString();
+                StoredLayers[i] = new UndoLayer(
+                    Path.Join(
+                        UndoChangeLocation,
+                        Convert.ToBase64String(Encoding.UTF8.GetBytes(pngName)) + ".png"),
+                    layer,
+                    index);
+                i++;
+            }
         }
     }
 }

+ 0 - 13
PixiEditor/Models/Undo/UndoChangeData.cs

@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace PixiEditor.Models.Undo
-{
-    public class UndoChangeData
-    {
-        public string 
-    }
-}

+ 48 - 0
PixiEditor/Models/Undo/UndoLayer.cs

@@ -0,0 +1,48 @@
+using PixiEditor.Models.Layers;
+using System;
+
+namespace PixiEditor.Models.Undo
+{
+    [Serializable]
+    public record UndoLayer
+    {
+        public string StoredPngLayerName { get; set; }
+
+        public string Name { get; set; }
+
+        public int LayerIndex { get; set; }
+
+        public int Width { get; set; }
+
+        public int Height { get; set; }
+
+        public int MaxWidth { get; set; }
+
+        public int MaxHeight { get; set; }
+
+        public bool IsVisible { get; set; }
+        public bool IsActive { get; set; }
+
+        public int OffsetX { get; set; }
+
+        public int OffsetY { get; set; }
+
+        public float Opacity { get; set; }
+
+        public UndoLayer(string storedPngLayerName, Layer layer, int layerIndex)
+        {
+            StoredPngLayerName = storedPngLayerName;
+            LayerIndex = layerIndex;
+            Name = layer.Name;
+            Width = layer.Width;
+            Height = layer.Height;
+            MaxWidth = layer.MaxWidth;
+            MaxHeight = layer.MaxHeight;
+            IsVisible = layer.IsVisible;
+            OffsetX = layer.OffsetX;
+            OffsetY = layer.OffsetY;
+            Opacity = layer.Opacity;
+            IsActive = layer.IsActive;
+        }
+    }
+}

+ 1 - 0
PixiEditorTests/ModelsTests/ControllersTests/UndoManagerTests.cs

@@ -1,5 +1,6 @@
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Undo;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ControllersTests

+ 1 - 10
PixiEditorTests/ModelsTests/LayersTests/LayerTests.cs

@@ -54,16 +54,7 @@ namespace PixiEditorTests.ModelsTests.LayersTests
 
             Layer clone = layer.Clone();
 
-            Assert.Equal(layer.Name, clone.Name);
-            Assert.Equal(layer.Offset, clone.Offset);
-            Assert.Equal(layer.Width, clone.Width);
-            Assert.Equal(layer.Height, clone.Height);
-            Assert.Equal(layer.MaxHeight, clone.MaxHeight);
-            Assert.Equal(layer.MaxWidth, clone.MaxWidth);
-            Assert.Equal(layer.Opacity, clone.Opacity);
-            Assert.Equal(layer.IsVisible, clone.IsVisible);
-            Assert.Equal(layer.IsRenaming, clone.IsRenaming);
-            Assert.Equal(layer.ConvertBitmapToBytes(), clone.ConvertBitmapToBytes());
+            LayersTestHelper.LayersAreEqual(layer, clone);
         }
 
         [Fact]

+ 28 - 0
PixiEditorTests/ModelsTests/LayersTests/LayersTestHelper.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using PixiEditor.Models.Layers;
+using Xunit;
+
+namespace PixiEditorTests.ModelsTests.LayersTests
+{
+    public static class LayersTestHelper
+    {
+        public static void LayersAreEqual(Layer expected, Layer actual)
+        {
+            Assert.Equal(expected == null, actual == null);
+            Assert.Equal(expected.Name, actual.Name);
+            Assert.Equal(expected.Offset, actual.Offset);
+            Assert.Equal(expected.Width, actual.Width);
+            Assert.Equal(expected.Height, actual.Height);
+            Assert.Equal(expected.MaxHeight, actual.MaxHeight);
+            Assert.Equal(expected.MaxWidth, actual.MaxWidth);
+            Assert.Equal(expected.Opacity, actual.Opacity);
+            Assert.Equal(expected.IsVisible, actual.IsVisible);
+            Assert.Equal(expected.IsRenaming, actual.IsRenaming);
+            Assert.Equal(expected.ConvertBitmapToBytes(), actual.ConvertBitmapToBytes());
+        }
+    }
+}

+ 108 - 0
PixiEditorTests/ModelsTests/UndoTests/StorageBasedChangeTests.cs

@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Layers;
+using PixiEditor.Models.Undo;
+using PixiEditorTests.ModelsTests.LayersTests;
+using Xunit;
+
+namespace PixiEditorTests.ModelsTests.UndoTests
+{
+    public class StorageBasedChangeTests
+    {
+        private const string UndoStoreLocation = "undoStack";
+
+        public StorageBasedChangeTests()
+        {
+            if (!Directory.Exists(UndoStoreLocation))
+            {
+                Directory.CreateDirectory(UndoStoreLocation);
+            }
+        }
+
+        public Document GenerateTestDocument()
+        {
+            Document testDocument = new Document(10, 10);
+            WriteableBitmap testBitmap = BitmapFactory.New(10, 10);
+            WriteableBitmap testBitmap2 = BitmapFactory.New(5, 8);
+            testBitmap.SetPixel(0, 0, Colors.Black);
+            testBitmap2.SetPixel(4, 4, Colors.Beige);
+            Random random = new Random();
+            testDocument.Layers = new ObservableCollection<Layer>()
+            {
+                new Layer("Test layer" + random.Next(int.MinValue, int.MaxValue), testBitmap),
+                new Layer("Test layer 2" + random.Next(int.MinValue, int.MaxValue), testBitmap2) { Offset = new System.Windows.Thickness(2, 3, 0, 0) }
+            };
+            return testDocument;
+        }
+
+        [Fact]
+        public void TestThatConstructorGeneratesUndoLayersProperly()
+        {
+            Document testDocument = GenerateTestDocument();
+
+            StorageBasedChange change = new StorageBasedChange(testDocument, testDocument.Layers, UndoStoreLocation);
+
+            Assert.Equal(testDocument.Layers.Count, change.StoredLayers.Length);
+
+            for (int i = 0; i < change.StoredLayers.Length; i++)
+            {
+                Layer testLayer = testDocument.Layers[i];
+                UndoLayer layer = change.StoredLayers[i];
+
+                Assert.Equal(testLayer.Name, layer.Name);
+                Assert.Equal(testLayer.Width, layer.Width);
+                Assert.Equal(testLayer.Height, layer.Height);
+                Assert.Equal(testLayer.IsActive, layer.IsActive);
+                Assert.Equal(testLayer.IsVisible, layer.IsVisible);
+                Assert.Equal(testLayer.OffsetX, layer.OffsetX);
+                Assert.Equal(testLayer.OffsetY, layer.OffsetY);
+                Assert.Equal(testLayer.MaxWidth, layer.MaxWidth);
+                Assert.Equal(testLayer.MaxHeight, layer.MaxHeight);
+                Assert.Equal(testLayer.Opacity, layer.Opacity);
+            }
+        }
+
+        [Fact]
+        public void TestThatSaveLayersOnDeviceSavesLayers()
+        {
+            Document document = GenerateTestDocument();
+
+            StorageBasedChange change = new StorageBasedChange(document, document.Layers, UndoStoreLocation);
+            change.SaveLayersOnDevice();
+
+            foreach (var layer in change.StoredLayers)
+            {
+                Assert.True(File.Exists(layer.StoredPngLayerName));
+                File.Delete(layer.StoredPngLayerName);
+            }
+        }
+
+        [Fact]
+        public void TestThatLoadLayersFromDeviceLoadsLayers()
+        {
+            Document document = GenerateTestDocument();
+
+            StorageBasedChange change = new StorageBasedChange(document, document.Layers, UndoStoreLocation);
+
+            change.SaveLayersOnDevice();
+
+            Layer[] layers = change.LoadLayersFromDevice();
+
+            Assert.Equal(document.Layers.Count, layers.Length);
+            for (int i = 0; i < document.Layers.Count; i++)
+            {
+                Layer expected = document.Layers[i];
+                Layer actual = layers[i];
+                LayersTestHelper.LayersAreEqual(expected, actual);
+            }
+        }
+    }
+}