2
0
flabbet 4 жил өмнө
parent
commit
c597ce220f

+ 49 - 2
PixiEditor/Models/DataHolders/Document/Document.Layers.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Linq;
 using System.Windows;
 using System.Windows;
@@ -144,7 +145,7 @@ namespace PixiEditor.Models.DataHolders
         {
         {
             string name;
             string name;
 
 
-            // Wich name should be user
+            // Wich name should be used
             if (nameOfSecond)
             if (nameOfSecond)
             {
             {
                 name = secondLayer.Name;
                 name = secondLayer.Name;
@@ -177,7 +178,53 @@ namespace PixiEditor.Models.DataHolders
             Layer firstLayer = Layers[firstIndex];
             Layer firstLayer = Layers[firstIndex];
             Layer secondLayer = Layers[secondIndex];
             Layer secondLayer = Layers[secondIndex];
 
 
-            return MergeLayers(firstLayer, secondLayer, nameOfSecond, firstIndex);
+            IEnumerable<Layer> undoArgs = new[] { firstLayer, secondLayer };
+            if (firstIndex > secondIndex)
+            {
+                undoArgs = undoArgs.Reverse();
+            }
+
+            StorageBasedChange undoChange = new StorageBasedChange(this, undoArgs);
+
+            var layer = MergeLayers(firstLayer, secondLayer, nameOfSecond, firstIndex);
+
+            UndoManager.AddUndoChange(undoChange.ToChange(
+                InsertLayersAtIndexesProcess,
+                new object[] { firstIndex > secondIndex ? firstIndex - 1 : firstIndex },
+                MergeLayersProcess,
+                new object[] { firstIndex, secondIndex, nameOfSecond, layer.LayerGuid },
+                "Undo merge layers"));
+
+            return layer;
+        }
+
+        private void MergeLayersProcess(object[] args)
+        {
+            if (args.Length > 0 
+                && args[0] is int firstIndex
+                && args[1] is int secondIndex
+                && args[2] is bool nameOfSecond
+                && args[3] is Guid mergedLayerGuid)
+            {
+                Layer firstLayer = Layers[firstIndex];
+                Layer secondLayer = Layers[secondIndex];
+
+                Layer layer = MergeLayers(firstLayer, secondLayer, nameOfSecond, firstIndex);
+                layer.ChangeGuid(mergedLayerGuid);
+            }
+        }
+
+        private void InsertLayersAtIndexesProcess(Layer[] layers, UndoLayer[] data, object[] args)
+        {
+            if (args.Length > 0 && args[0] is int layerIndex)
+            {
+                Layers.RemoveAt(layerIndex);
+                for (int i = 0; i < layers.Length; i++)
+                {
+                    Layer layer = layers[i];
+                    Layers.Insert(data[i].LayerIndex, layer);
+                }
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>

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

@@ -30,6 +30,6 @@ namespace PixiEditor.Models.Layers
             }
             }
         }
         }
 
 
-        public Guid LayerGuid { get; init; }
+        public Guid LayerGuid { get; protected set; }
     }
     }
 }
 }

+ 10 - 0
PixiEditor/Models/Layers/Layer.cs

@@ -160,6 +160,16 @@ namespace PixiEditor.Models.Layers
 
 
         public int MaxHeight { get; set; } = int.MaxValue;
         public int MaxHeight { get; set; } = int.MaxValue;
 
 
+        /// <summary>
+        /// Changes Guid of layer.
+        /// </summary>
+        /// <param name="newGuid">Guid to set.</param>
+        /// <remarks>This is potentially destructive operation, use when absolutelly necessary.</remarks>
+        public void ChangeGuid(Guid newGuid)
+        {
+            LayerGuid = newGuid;
+        }
+
         /// <summary>
         /// <summary>
         ///     Returns clone of layer.
         ///     Returns clone of layer.
         /// </summary>
         /// </summary>

+ 53 - 1
PixiEditor/Models/Undo/StorageBasedChange.cs

@@ -88,10 +88,10 @@ namespace PixiEditor.Models.Undo
                     MaxHeight = storedLayer.MaxHeight,
                     MaxHeight = storedLayer.MaxHeight,
                     IsVisible = storedLayer.IsVisible,
                     IsVisible = storedLayer.IsVisible,
                     IsActive = storedLayer.IsActive,
                     IsActive = storedLayer.IsActive,
-                    LayerGuid = storedLayer.LayerGuid,
                     Width = storedLayer.Width,
                     Width = storedLayer.Width,
                     Height = storedLayer.Height,
                     Height = storedLayer.Height,
                 };
                 };
+                layers[i].ChangeGuid(storedLayer.LayerGuid);
 
 
                 File.Delete(StoredLayers[i].StoredPngLayerName);
                 File.Delete(StoredLayers[i].StoredPngLayerName);
             }
             }
@@ -100,6 +100,32 @@ namespace PixiEditor.Models.Undo
             return layers;
             return layers;
         }
         }
 
 
+        /// <summary>
+        ///     Creates UndoManager ready Change instance, where undo process loads layers from device, and redo saves them.
+        /// </summary>
+        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+        /// <param name="processArgs">Custom parameters for undo process.</param>
+        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+        /// <param name="redoProcessParameters">Parameters for redo process.</param>
+        /// <param name="description">Undo change description.</param>
+        /// <returns>UndoManager ready Change instance.</returns>
+        public Change ToChange(Action<Layer[], UndoLayer[], object[]> undoProcess, object[] processArgs, Action<object[]> redoProcess, object[] redoProcessParameters, string description = "")
+        {
+            Action<object[]> finalUndoProcess = processParameters =>
+            {
+                Layer[] layers = LoadLayersFromDevice();
+                undoProcess(layers, StoredLayers, processParameters);
+            };
+
+            Action<object[]> finalRedoProcess = parameters =>
+            {
+                SaveLayersOnDevice();
+                redoProcess(parameters);
+            };
+
+            return new Change(finalUndoProcess, processArgs, finalRedoProcess, redoProcessParameters, description);
+        }
+
         /// <summary>
         /// <summary>
         ///     Creates UndoManager ready Change instance, where undo process loads layers from device, and redo saves them.
         ///     Creates UndoManager ready Change instance, where undo process loads layers from device, and redo saves them.
         /// </summary>
         /// </summary>
@@ -150,6 +176,32 @@ namespace PixiEditor.Models.Undo
             return new Change(finalUndoProcess, undoProcessParameters, finalRedoProcess, null, description);
             return new Change(finalUndoProcess, undoProcessParameters, finalRedoProcess, null, description);
         }
         }
 
 
+        /// <summary>
+        ///     Creates UndoManager ready Change instance, where undo process saves layers on device, and redo loads them.
+        /// </summary>
+        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+        /// <param name="undoProcessParameters">Parameters for undo process.</param>
+        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+        /// <param name="redoProcessArgs">Parameters for redo process.</param>
+        /// <param name="description">Undo change description.</param>
+        /// <returns>UndoManager ready Change instance.</returns>
+        public Change ToChange(Action<object[]> undoProcess, object[] undoProcessParameters, Action<Layer[], UndoLayer[], object[]> redoProcess, object[] redoProcessArgs, string description = "")
+        {
+            Action<object[]> finalUndoProcess = parameters =>
+            {
+                SaveLayersOnDevice();
+                undoProcess(parameters);
+            };
+
+            Action<object[]> finalRedoProcess = parameters =>
+            {
+                Layer[] layers = LoadLayersFromDevice();
+                redoProcess(layers, StoredLayers, parameters);
+            };
+
+            return new Change(finalUndoProcess, undoProcessParameters, finalRedoProcess, redoProcessArgs, description);
+        }
+
         /// <summary>
         /// <summary>
         /// Generates UndoLayer[] StoredLayers data.
         /// Generates UndoLayer[] StoredLayers data.
         /// </summary>
         /// </summary>