Browse Source

Added IsVisible and Opacity Undo, along with new UndoManager root option

flabbet 4 years ago
parent
commit
64ec716c01

+ 36 - 9
PixiEditor/Models/Controllers/UndoManager.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Reflection;
 using PixiEditor.Models.Undo;
 using PixiEditor.Models.Undo;
 using PixiEditor.ViewModels;
 using PixiEditor.ViewModels;
 
 
@@ -9,6 +11,8 @@ namespace PixiEditor.Models.Controllers
     {
     {
         private bool lastChangeWasUndo;
         private bool lastChangeWasUndo;
 
 
+        private PropertyInfo newUndoChangeBlockedProperty;
+
         public Stack<Change> UndoStack { get; set; } = new Stack<Change>();
         public Stack<Change> UndoStack { get; set; } = new Stack<Change>();
 
 
         public Stack<Change> RedoStack { get; set; } = new Stack<Change>();
         public Stack<Change> RedoStack { get; set; } = new Stack<Change>();
@@ -37,13 +41,19 @@ namespace PixiEditor.Models.Controllers
         /// </summary>
         /// </summary>
         public void AddUndoChange(Change change)
         public void AddUndoChange(Change change)
         {
         {
+            if (change.Property != null && ChangeIsBlockedProperty(change))
+            {
+                newUndoChangeBlockedProperty = null;
+                return;
+            }
+
             lastChangeWasUndo = false;
             lastChangeWasUndo = false;
 
 
             // Clears RedoStack if last move wasn't redo or undo and if redo stack is greater than 0.
             // Clears RedoStack if last move wasn't redo or undo and if redo stack is greater than 0.
             if (lastChangeWasUndo == false && RedoStack.Count > 0)
             if (lastChangeWasUndo == false && RedoStack.Count > 0)
-            {
-                RedoStack.Clear();
-            }
+                {
+                    RedoStack.Clear();
+                }
 
 
             change.Root ??= MainRoot;
             change.Root ??= MainRoot;
             UndoStack.Push(change);
             UndoStack.Push(change);
@@ -58,7 +68,7 @@ namespace PixiEditor.Models.Controllers
             Change change = UndoStack.Pop();
             Change change = UndoStack.Pop();
             if (change.ReverseProcess == null)
             if (change.ReverseProcess == null)
             {
             {
-                SetPropertyValue(change.Root, change.Property, change.OldValue);
+                SetPropertyValue(GetChangeRoot(change), change.Property, change.OldValue);
             }
             }
             else
             else
             {
             {
@@ -77,7 +87,7 @@ namespace PixiEditor.Models.Controllers
             Change change = RedoStack.Pop();
             Change change = RedoStack.Pop();
             if (change.Process == null)
             if (change.Process == null)
             {
             {
-                SetPropertyValue(change.Root, change.Property, change.NewValue);
+                SetPropertyValue(GetChangeRoot(change), change.Property, change.NewValue);
             }
             }
             else
             else
             {
             {
@@ -87,17 +97,34 @@ namespace PixiEditor.Models.Controllers
             UndoStack.Push(change);
             UndoStack.Push(change);
         }
         }
 
 
+        private bool ChangeIsBlockedProperty(Change change)
+        {
+            return (change.Root != null || change.FindRootProcess != null)
+                && GetProperty(GetChangeRoot(change), change.Property) == newUndoChangeBlockedProperty;
+        }
+
+        private object GetChangeRoot(Change change)
+        {
+            return change.FindRootProcess != null ? change.FindRootProcess(change.FindRootProcessArgs) : change.Root;
+        }
+
         private void SetPropertyValue(object target, string propName, object value)
         private void SetPropertyValue(object target, string propName, object value)
+        {
+            PropertyInfo propertyToSet = GetProperty(target, propName);
+            newUndoChangeBlockedProperty = propertyToSet;
+            propertyToSet.SetValue(target, value, null);
+        }
+
+        private PropertyInfo GetProperty(object target, string propName)
         {
         {
             string[] bits = propName.Split('.');
             string[] bits = propName.Split('.');
             for (int i = 0; i < bits.Length - 1; i++)
             for (int i = 0; i < bits.Length - 1; i++)
             {
             {
-                System.Reflection.PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
+                PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
                 target = propertyToGet.GetValue(target, null);
                 target = propertyToGet.GetValue(target, null);
             }
             }
 
 
-            System.Reflection.PropertyInfo propertyToSet = target.GetType().GetProperty(bits.Last());
-            propertyToSet.SetValue(target, value, null);
+            return target.GetType().GetProperty(bits.Last());
         }
         }
     }
     }
 }
 }

+ 31 - 5
PixiEditor/Models/Layers/Layer.cs

@@ -4,8 +4,11 @@ using System.Linq;
 using System.Windows;
 using System.Windows;
 using System.Windows.Media;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Media.Imaging;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
+using PixiEditor.Models.Undo;
+using PixiEditor.ViewModels;
 
 
 namespace PixiEditor.Models.Layers
 namespace PixiEditor.Models.Layers
 {
 {
@@ -24,7 +27,7 @@ namespace PixiEditor.Models.Layers
 
 
         private Thickness offset;
         private Thickness offset;
 
 
-        private float opacity = 1;
+        private float opacity = 1f;
 
 
         public Layer(string name)
         public Layer(string name)
         {
         {
@@ -80,8 +83,20 @@ namespace PixiEditor.Models.Layers
             get => isVisible;
             get => isVisible;
             set
             set
             {
             {
-                isVisible = value;
-                RaisePropertyChanged("IsVisible");
+                if (isVisible != value)
+                {
+                    ViewModelMain.Current?.BitmapManager?.ActiveDocument?.UndoManager
+                        .AddUndoChange(
+                        new Change(
+                            nameof(IsVisible),
+                            isVisible,
+                            value,
+                            LayerHelper.FindLayerByGuidProcess,
+                            new object[] { LayerGuid },
+                            "Change layer visibility"));
+                    isVisible = value;
+                    RaisePropertyChanged("IsVisible");
+                }
             }
             }
         }
         }
 
 
@@ -110,8 +125,19 @@ namespace PixiEditor.Models.Layers
             get => opacity;
             get => opacity;
             set
             set
             {
             {
-                opacity = value;
-                RaisePropertyChanged("Opacity");
+                if (opacity != value)
+                {
+                    ViewModelMain.Current?.BitmapManager?.ActiveDocument?.UndoManager
+                        .AddUndoChange(new Change(
+                            nameof(Opacity),
+                            opacity,
+                            value,
+                            LayerHelper.FindLayerByGuidProcess,
+                            new object[] { LayerGuid },
+                            "Change layer opacity"));
+                    opacity = value;
+                    RaisePropertyChanged("Opacity");
+                }
             }
             }
         }
         }
 
 

+ 25 - 0
PixiEditor/Models/Layers/LayerHelper.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Linq;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.ViewModels;
+
+namespace PixiEditor.Models.Layers
+{
+    public static class LayerHelper
+    {
+         public static Layer FindLayerByGuid(Document document, Guid guid)
+         {
+            return document.Layers.FirstOrDefault(x => x.LayerGuid == guid);
+         }
+
+         public static object FindLayerByGuidProcess(object[] parameters)
+         {
+            if (parameters != null && parameters.Length > 0 && parameters[0] is Guid guid)
+            {
+                return FindLayerByGuid(ViewModelMain.Current.BitmapManager.ActiveDocument, guid);
+            }
+
+            return null;
+        }
+    }
+}

+ 29 - 0
PixiEditor/Models/Undo/Change.cs

@@ -28,6 +28,31 @@ namespace PixiEditor.Models.Undo
             Root = root;
             Root = root;
         }
         }
 
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Change"/> class.
+        ///     Creates new change for property based undo system.
+        /// </summary>
+        /// <param name="property">Name of property.</param>
+        /// <param name="oldValue">Old value of property.</param>
+        /// <param name="newValue">New value of property.</param>
+        /// <param name="description">Description of change.</param>
+        /// <param name="root">Custom root for finding property.</param>
+        public Change(
+            string property,
+            object oldValue,
+            object newValue,
+            Func<object[], object> findRootProcess,
+            object[] findRootProcessArgs = null,
+            string description = "")
+        {
+            Property = property;
+            OldValue = oldValue;
+            Description = description;
+            NewValue = newValue;
+            FindRootProcess = findRootProcess;
+            FindRootProcessArgs = findRootProcessArgs;
+        }
+
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="Change"/> class.
         /// Initializes a new instance of the <see cref="Change"/> class.
         ///     Creates new change for mixed reverse process based system with new value property based system.
         ///     Creates new change for mixed reverse process based system with new value property based system.
@@ -94,5 +119,9 @@ namespace PixiEditor.Models.Undo
         public Action<object[]> Process { get; set; }
         public Action<object[]> Process { get; set; }
 
 
         public object Root { get; set; }
         public object Root { get; set; }
+
+        public Func<object[], object> FindRootProcess { get; set; }
+
+        public object[] FindRootProcessArgs { get; set; }
     }
     }
 }
 }