Browse Source

Added layer selected colors

flabbet 4 years ago
parent
commit
6d1623bbb5

+ 0 - 27
PixiEditor/Helpers/Converters/BoolToColorConverter.cs

@@ -1,27 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows.Data;
-
-namespace PixiEditor.Helpers.Converters
-{
-    public class BoolToColorConverter : IValueConverter
-    {
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            return value?.ToString() == "Transparent";
-        }
-
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            if (value is bool boolean)
-            {
-                if (boolean == false)
-                {
-                    return "Transparent";
-                }
-            }
-
-            return "#505056";
-        }
-    }
-}

+ 6 - 3
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -70,20 +70,23 @@ namespace PixiEditor.Models.Controllers
 
         public BitmapOperationsUtility BitmapOperations { get; set; }
 
-        public ReadonlyToolUtility ReadonlyToolUtility { get; set; }
-
+        public ReadonlyToolUtility ReadonlyToolUtility { get; set; }
+
+#nullable enable
         public Document ActiveDocument
         {
             get => activeDocument;
             set
             {
                 activeDocument?.UpdatePreviewImage();
+                Document? oldDoc = activeDocument;
                 activeDocument = value;
                 RaisePropertyChanged(nameof(ActiveDocument));
-                DocumentChanged?.Invoke(this, new DocumentChangedEventArgs(value));
+                DocumentChanged?.Invoke(this, new DocumentChangedEventArgs(value, oldDoc));
             }
         }
 
+#nullable disable
         public ObservableCollection<Document> Documents { get; set; } = new ObservableCollection<Document>();
 
         /// <summary>

+ 52 - 10
PixiEditor/Models/DataHolders/Document/Document.Layers.cs

@@ -15,6 +15,8 @@ namespace PixiEditor.Models.DataHolders
 {
     public partial class Document
     {
+        public const string MainSelectedLayerColor = "#505056";
+        public const string SecondarySelectedLayerColor = "#7D505056";
         private int activeLayerIndex;
 
         public ObservableCollection<Layer> Layers { get; set; } = new ObservableCollection<Layer>();
@@ -34,17 +36,19 @@ namespace PixiEditor.Models.DataHolders
 
         public event EventHandler<LayersChangedEventArgs> LayersChanged;
 
-        public void SetActiveLayer(int index)
+        public void SetMainActiveLayer(int index)
         {
             if (ActiveLayerIndex <= Layers.Count - 1)
             {
                 ActiveLayer.IsActive = false;
             }
 
-            if (Layers.Any(x => x.IsActive))
+            foreach (var layer in Layers)
             {
-                var guids = Layers.Where(x => x.IsActive).Select(y => y.LayerGuid);
-                guids.ToList().ForEach(x => Layers.First(layer => layer.LayerGuid == x).IsActive = false);
+                if (layer.IsActive)
+                {
+                    layer.IsActive = false;
+                }
             }
 
             ActiveLayerIndex = index;
@@ -52,6 +56,24 @@ namespace PixiEditor.Models.DataHolders
             LayersChanged?.Invoke(this, new LayersChangedEventArgs(index, LayerAction.SetActive));
         }
 
+        public void UpdateLayersColor()
+        {
+            int index = 0;
+            foreach (var layer in Layers)
+            {
+                if (index == ActiveLayerIndex)
+                {
+                    layer.LayerHighlightColor = MainSelectedLayerColor;
+                }
+                else
+                {
+                    layer.LayerHighlightColor = SecondarySelectedLayerColor;
+                }
+
+                index++;
+            }
+        }
+
         public void MoveLayerIndexBy(int layerIndex, int amount)
         {
             MoveLayerProcess(new object[] { layerIndex, amount });
@@ -84,7 +106,7 @@ namespace PixiEditor.Models.DataHolders
             });
             if (setAsActive)
             {
-                SetActiveLayer(Layers.Count - 1);
+                SetMainActiveLayer(Layers.Count - 1);
             }
 
             if (Layers.Count > 1)
@@ -107,11 +129,25 @@ namespace PixiEditor.Models.DataHolders
             {
                 if (lastLayerIndex == 0)
                 {
-                    SetActiveLayer(0);
+                    SetMainActiveLayer(0);
                 }
                 else
                 {
-                    SetActiveLayer(lastLayerIndex - 1);
+                    SetMainActiveLayer(lastLayerIndex - 1);
+                }
+            }
+        }
+
+        public void SetNextSelectedLayerAsActive(Guid lastLayerGuid)
+        {
+            var selectedLayers = Layers.Where(x => x.IsActive);
+            foreach (var layer in selectedLayers)
+            {
+                if (layer.LayerGuid != lastLayerGuid)
+                {
+                    ActiveLayerIndex = Layers.IndexOf(layer);
+                    LayersChanged?.Invoke(this, new LayersChangedEventArgs(ActiveLayerIndex, LayerAction.SetActive));
+                    return;
                 }
             }
         }
@@ -125,6 +161,12 @@ namespace PixiEditor.Models.DataHolders
                 {
                     return;
                 }
+
+                if (ActiveLayerIndex == Layers.IndexOf(layer))
+                {
+                    SetNextSelectedLayerAsActive(layer.LayerGuid);
+                }
+
                 layer.IsActive = !layer.IsActive;
             }
         }
@@ -237,7 +279,7 @@ namespace PixiEditor.Models.DataHolders
 
             Layers.Insert(index, mergedLayer);
 
-            SetActiveLayer(Layers.IndexOf(mergedLayer));
+            SetMainActiveLayer(Layers.IndexOf(mergedLayer));
 
             return mergedLayer;
         }
@@ -354,7 +396,7 @@ namespace PixiEditor.Models.DataHolders
             Layers.Move(layerIndex, layerIndex + amount);
             if (ActiveLayerIndex == layerIndex)
             {
-                SetActiveLayer(layerIndex + amount);
+                SetMainActiveLayer(layerIndex + amount);
             }
         }
 
@@ -367,7 +409,7 @@ namespace PixiEditor.Models.DataHolders
                 Layers.Insert(layersData[i].LayerIndex, layer);
                 if (layersData[i].IsActive)
                 {
-                    SetActiveLayer(Layers.IndexOf(layer));
+                    SetMainActiveLayer(Layers.IndexOf(layer));
                 }
             }
         }

+ 4 - 1
PixiEditor/Models/Events/DocumentChangedEventArgs.cs

@@ -4,11 +4,14 @@ namespace PixiEditor.Models.Events
 {
     public class DocumentChangedEventArgs
     {
-        public DocumentChangedEventArgs(Document newDocument)
+        public DocumentChangedEventArgs(Document newDocument, Document oldDocument)
         {
             NewDocument = newDocument;
+            OldDocument = oldDocument;
         }
 
+        public Document OldDocument { get; set; }
+
         public Document NewDocument { get; set; }
     }
 }

+ 13 - 1
PixiEditor/Models/Layers/Layer.cs

@@ -4,7 +4,6 @@ using System.Linq;
 using System.Windows;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
-using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Undo;
@@ -29,6 +28,8 @@ namespace PixiEditor.Models.Layers
 
         private float opacity = 1f;
 
+        private string layerHighlightColor = "#666666";
+
         public Layer(string name)
         {
             Name = name;
@@ -58,6 +59,16 @@ namespace PixiEditor.Models.Layers
 
         public Dictionary<Coordinates, Color> LastRelativeCoordinates { get; set; }
 
+        public string LayerHighlightColor
+        {
+            get => IsActive ? layerHighlightColor : "#00000000";
+            set
+            {
+                layerHighlightColor = value;
+                RaisePropertyChanged(nameof(LayerHighlightColor));
+            }
+        }
+
         public string Name
         {
             get => name;
@@ -75,6 +86,7 @@ namespace PixiEditor.Models.Layers
             {
                 isActive = value;
                 RaisePropertyChanged(nameof(IsActive));
+                RaisePropertyChanged(nameof(LayerHighlightColor));
             }
         }
 

+ 24 - 1
PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -2,6 +2,7 @@
 using System.Linq;
 using System.Windows.Input;
 using PixiEditor.Helpers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Layers;
 
 namespace PixiEditor.ViewModels.SubViewModels.Main
@@ -38,6 +39,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             MergeSelectedCommand = new RelayCommand(MergeSelected, CanMergeSelected);
             MergeWithAboveCommand = new RelayCommand(MergeWithAbove, CanMergeWithAbove);
             MergeWithBelowCommand = new RelayCommand(MergeWithBelow, CanMergeWithBelow);
+            Owner.BitmapManager.DocumentChanged += BitmapManager_DocumentChanged;
         }
 
         public bool CanMergeSelected(object obj)
@@ -68,7 +70,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
             else
             {
-                Owner.BitmapManager.ActiveDocument.SetActiveLayer(index);
+                Owner.BitmapManager.ActiveDocument.SetMainActiveLayer(index);
             }
         }
 
@@ -162,5 +164,26 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             int index = (int)property;
             return Owner.DocumentIsNotNull(null) && index != 0 && Owner.BitmapManager.ActiveDocument.Layers.Count(x => x.IsActive) == 1;
         }
+
+        private void BitmapManager_DocumentChanged(object sender, Models.Events.DocumentChangedEventArgs e)
+        {
+            if (e.OldDocument != null)
+            {
+                e.OldDocument.LayersChanged -= Document_LayersChanged;
+            }
+
+            if (e.NewDocument != null)
+            {
+                e.NewDocument.LayersChanged += Document_LayersChanged;
+            }
+        }
+
+        private void Document_LayersChanged(object sender, LayersChangedEventArgs e)
+        {
+            if (e.LayerChangeType == Models.Enums.LayerAction.SetActive)
+            {
+                Owner.BitmapManager.ActiveDocument.UpdateLayersColor();
+            }
+        }
     }
 }

+ 2 - 1
PixiEditor/Views/MainWindow.xaml

@@ -333,7 +333,8 @@
                                 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}"
+                                                                   PreviewImage="{Binding LayerBitmap}" 
+                                                                   LayerColor="{Binding LayerHighlightColor}"
                                                                    MoveToBackCommand="{Binding DataContext.LayersSubViewModel.MoveToBackCommand, ElementName=mainWindow}"
                                                                    MoveToFrontCommand="{Binding DataContext.LayersSubViewModel.MoveToFrontCommand, ElementName=mainWindow}">
                                                                 <vws:LayerItem.ContextMenu>

+ 1 - 4
PixiEditor/Views/UserControls/LayerItem.xaml

@@ -9,11 +9,8 @@
              mc:Ignorable="d" Focusable="True"
              d:DesignHeight="60" d:DesignWidth="250" Name="uc"
              MouseLeave="LayerItem_OnMouseLeave" MouseEnter="LayerItem_OnMouseEnter">
-    <UserControl.Resources>
-        <converters:BoolToColorConverter x:Key="BoolToColorConverter" />
-    </UserControl.Resources>
     <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True"
-            Background="{Binding IsActive, Mode=TwoWay, Converter={StaticResource BoolToColorConverter}}">
+            Background="{Binding LayerColor, ElementName=uc}">
         <i:Interaction.Behaviors>
             <behaviors:ClearFocusOnClickBehavior/>
         </i:Interaction.Behaviors>

+ 10 - 0
PixiEditor/Views/UserControls/LayerItem.xaml.cs

@@ -82,6 +82,16 @@ namespace PixiEditor.Views
         public static readonly DependencyProperty PreviewImageProperty =
             DependencyProperty.Register("PreviewImage", typeof(WriteableBitmap), typeof(LayerItem), new PropertyMetadata(null));
 
+        public string LayerColor
+        {
+            get { return (string)GetValue(LayerColorProperty); }
+            set { SetValue(LayerColorProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for LayerColor.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty LayerColorProperty =
+            DependencyProperty.Register("LayerColor", typeof(string), typeof(LayerItem), new PropertyMetadata("#00000000"));
+
         public Visibility ControlButtonsVisible
         {
             get { return (Visibility)GetValue(ControlButtonsVisibleProperty); }

+ 82 - 11
PixiEditorTests/ModelsTests/DataHoldersTests/DocumentLayersTests.cs

@@ -1,9 +1,6 @@
-using PixiEditor.Models.DataHolders;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.ViewModels.SubViewModels.Main;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
@@ -12,13 +9,27 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
     public class DocumentLayersTests
     {
         [Fact]
-        public void TestThatToggleLayerTogglesLayer()
+        public void TestThatToggleLayerDoesNotToggleLastLayer()
         {
-            Document doc = new Document(5, 5);
+            Document doc = new (5, 5);
             doc.AddNewLayer("layer");
             bool isActive = doc.Layers[^1].IsActive;
             doc.ToggleLayer(0);
-            Assert.True(doc.Layers[^1].IsActive != isActive);
+            Assert.False(doc.Layers[^1].IsActive != isActive);
+        }
+
+        [Fact]
+        public void TestThatToggleLayerTogglesLayer()
+        {
+            Document doc = new (5, 5);
+            doc.AddNewLayer("layer");
+            doc.AddNewLayer("layer 1");
+            doc.Layers[0].IsActive = true;
+            doc.Layers[^1].IsActive = true;
+
+            doc.ToggleLayer(0);
+            Assert.False(doc.Layers[0].IsActive);
+            Assert.True(doc.Layers[1].IsActive);
         }
 
         [Fact]
@@ -43,7 +54,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             document.AddNewLayer("2");
             document.AddNewLayer("3");
 
-            document.SetActiveLayer(startIndex);
+            document.SetMainActiveLayer(startIndex);
 
             document.SelectLayersRange(endIndex);
 
@@ -68,7 +79,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             document.AddNewLayer("2");
             document.AddNewLayer("3");
 
-            document.SetActiveLayer(0);
+            document.SetMainActiveLayer(0);
             document.Layers[1].IsActive = true;
             document.Layers[2].IsActive = true;
 
@@ -79,5 +90,65 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
                 Assert.Equal(layer == document.Layers[index], layer.IsActive);
             }
         }
+
+        [Fact]
+        public void TestThatUpdateLayersColorMakesOnlyOneLayerMainColorAndOtherSecondary()
+        {
+            Document document = new Document(1, 1);
+
+            document.AddNewLayer("1");
+            document.AddNewLayer("2");
+            document.AddNewLayer("3");
+
+            document.SetMainActiveLayer(0);
+            document.Layers[1].IsActive = true; // This makes layer selected, but not main
+            document.Layers[2].IsActive = true;
+
+            document.UpdateLayersColor();
+
+            Assert.Equal(Document.MainSelectedLayerColor, document.Layers[0].LayerHighlightColor);
+            Assert.Equal(Document.SecondarySelectedLayerColor, document.Layers[1].LayerHighlightColor);
+            Assert.Equal(Document.SecondarySelectedLayerColor, document.Layers[2].LayerHighlightColor);
+        }
+
+        [Fact]
+        public void TestThatUpdateLayersColorMakesLayerMainColorAndRestNonActiveReturnsTransparent()
+        {
+            Document document = new Document(1, 1);
+
+            document.AddNewLayer("1");
+            document.AddNewLayer("2");
+            document.AddNewLayer("3");
+
+            document.SetMainActiveLayer(1);
+
+            document.UpdateLayersColor();
+
+            string transparentHex = "#00000000";
+
+            Assert.Equal(transparentHex, document.Layers[0].LayerHighlightColor);
+            Assert.Equal(Document.MainSelectedLayerColor, document.Layers[1].LayerHighlightColor);
+            Assert.Equal(transparentHex, document.Layers[2].LayerHighlightColor);
+        }
+
+        [Fact]
+        public void TestThatSetNextSelectedLayerAsActiveSelectsFirstAvailableLayer()
+        {
+            Document document = new Document(1, 1);
+
+            document.AddNewLayer("1");
+            document.AddNewLayer("2");
+            document.AddNewLayer("3");
+            document.AddNewLayer("4");
+
+            foreach (var layer in document.Layers)
+            {
+                layer.IsActive = true;
+            }
+
+            document.SetNextSelectedLayerAsActive(document.Layers[1].LayerGuid);
+
+            Assert.Equal(0, document.ActiveLayerIndex);
+        }
     }
 }

+ 1 - 1
PixiEditorTests/ModelsTests/DataHoldersTests/DocumentTests.cs

@@ -155,7 +155,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             doc.Layers.Add(new PixiEditor.Models.Layers.Layer("Test"));
             doc.Layers.Add(new PixiEditor.Models.Layers.Layer("Test 2"));
 
-            doc.SetActiveLayer(1);
+            doc.SetMainActiveLayer(1);
 
             doc.SetNextLayerAsActive(1);