Просмотр исходного кода

Bug fixes wip, raw layers viewer added

flabbet 4 лет назад
Родитель
Сommit
8c41bd5c84

+ 24 - 0
PixiEditor/Helpers/Converters/InverseBooleanConverter.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Windows.Data;
+
+namespace PixiEditor.Helpers.Converters
+{
+    [ValueConversion(typeof(bool), typeof(bool))]
+    public class InverseBooleanConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            if (targetType != typeof(bool))
+            {
+                throw new InvalidOperationException("The target must be a boolean");
+            }
+
+            return !(bool)value;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            throw new NotSupportedException();
+        }
+    }
+}

+ 56 - 0
PixiEditor/Helpers/Converters/LayerStructureToGroupsConverter.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.Linq;
+using System.Windows.Data;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Layers;
+
+namespace PixiEditor.Helpers.Converters
+{
+    public class LayerStructureToGroupsConverter : IMultiValueConverter
+    {
+        private ObservableCollection<GuidStructureItem> GetSubGroups(IEnumerable<GuidStructureItem> groups)
+        {
+            ObservableCollection<GuidStructureItem> finalGroups = new ObservableCollection<GuidStructureItem>();
+            foreach (var group in groups)
+            {
+                finalGroups.AddRange(GetSubGroups(group));
+            }
+
+            return finalGroups;
+        }
+
+        private IEnumerable<GuidStructureItem> GetSubGroups(GuidStructureItem group)
+        {
+            List<GuidStructureItem> groups = new List<GuidStructureItem>() { group };
+
+            foreach (var subGroup in group.Subgroups)
+            {
+                groups.Add(subGroup);
+                if(subGroup.Subgroups.Count > 0)
+                {
+                    groups.AddRange(GetSubGroups(subGroup));
+                }
+            }
+
+            return groups.Distinct();
+        }
+
+        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (values[0] is LayerStructure structure)
+            {
+                return GetSubGroups(structure.Groups);
+            }
+
+            return Binding.DoNothing;
+        }
+
+        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 7 - 7
PixiEditor/Models/DataHolders/Document/Document.Layers.cs

@@ -42,11 +42,6 @@ namespace PixiEditor.Models.DataHolders
             }
         }
 
-        private void Folders_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
-        {
-            RaisePropertyChanged(nameof(LayerStructure));
-        }
-
         public Layer ActiveLayer => Layers.Count > 0 ? Layers.FirstOrDefault(x => x.LayerGuid == ActiveLayerGuid) : null;
 
         public Guid ActiveLayerGuid
@@ -250,6 +245,8 @@ namespace PixiEditor.Models.DataHolders
                 return;
             }
 
+            LayerStructure.AssignParent(Layers[layerIndex].LayerGuid, null);
+
             bool wasActive = Layers[layerIndex].IsActive;
 
             StorageBasedChange change = new StorageBasedChange(this, new[] { Layers[layerIndex] });
@@ -493,7 +490,7 @@ namespace PixiEditor.Models.DataHolders
 
         private void ReassignParent(GuidStructureItem folder, GuidStructureItem referenceLayerFolder)
         {
-            folder.Parent?.Subfolders.Remove(folder);
+            folder.Parent?.Subgroups.Remove(folder);
             if (LayerStructure.Groups.Contains(folder))
             {
                 LayerStructure.Groups.Remove(folder);
@@ -509,7 +506,7 @@ namespace PixiEditor.Models.DataHolders
             }
             else
             {
-                referenceLayerFolder.Subfolders.Add(folder);
+                referenceLayerFolder.Subgroups.Add(folder);
                 folder.Parent = referenceLayerFolder;
             }
         }
@@ -575,6 +572,9 @@ namespace PixiEditor.Models.DataHolders
                 Layer layer = Layers.First(x => x.LayerGuid == layerGuid);
                 int index = Layers.IndexOf(layer);
                 bool wasActive = layer.IsActive;
+
+                LayerStructure.AssignParent(Layers[index].LayerGuid, null);
+
                 Layers.Remove(layer);
 
                 if (wasActive || Layers.IndexOf(ActiveLayer) >= index)

+ 16 - 7
PixiEditor/Models/Layers/GuidStructureItem.cs

@@ -6,10 +6,12 @@ using PixiEditor.Helpers;
 
 namespace PixiEditor.Models.Layers
 {
-    [DebuggerDisplay("{Name} - {FolderGuid}")]
+    [DebuggerDisplay("{Name} - {GroupGuid}")]
     public class GuidStructureItem : NotifyableObject
     {
-        public Guid FolderGuid { get; init; }
+        public event EventHandler GroupsChanged;
+
+        public Guid GroupGuid { get; init; }
 
         private string name;
 
@@ -47,7 +49,7 @@ namespace PixiEditor.Models.Layers
             }
         }
 
-        public ObservableCollection<GuidStructureItem> Subfolders { get; set; }
+        public ObservableCollection<GuidStructureItem> Subgroups { get; set; } = new ObservableCollection<GuidStructureItem>();
 
         public GuidStructureItem Parent { get; set; }
 
@@ -71,21 +73,28 @@ namespace PixiEditor.Models.Layers
             GuidStructureItem parent)
         {
             Name = name;
-            Subfolders = new ObservableCollection<GuidStructureItem>(subfolders);
-            FolderGuid = Guid.NewGuid();
+            Subgroups = new ObservableCollection<GuidStructureItem>(subfolders);
+            GroupGuid = Guid.NewGuid();
             Parent = parent;
             StartLayerGuid = startLayerGuid;
             EndLayerGuid = endLayerGuid;
+            Subgroups.CollectionChanged += Subgroups_CollectionChanged;
         }
 
         public GuidStructureItem(string name, Guid layer)
         {
             Name = name;
-            Subfolders = new ObservableCollection<GuidStructureItem>();
-            FolderGuid = Guid.NewGuid();
+            GroupGuid = Guid.NewGuid();
             Parent = null;
             StartLayerGuid = layer;
             EndLayerGuid = layer;
+            Subgroups.CollectionChanged += Subgroups_CollectionChanged;
+        }
+
+        private void Subgroups_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+        {
+            GroupsChanged?.Invoke(this, EventArgs.Empty);
+            Parent?.GroupsChanged?.Invoke(this, EventArgs.Empty);
         }
     }
 }

+ 97 - 77
PixiEditor/Models/Layers/LayerStructure.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Windows;
+using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
 
 namespace PixiEditor.Models.Layers
@@ -36,9 +37,11 @@ namespace PixiEditor.Models.Layers
             else
             {
                 group.Parent = parent;
-                parent.Subfolders.Add(group);
+                parent.Subgroups.Add(group);
             }
 
+            group.GroupsChanged += Group_GroupsChanged;
+
             LayerStructureChanged?.Invoke(this, EventArgs.Empty);
         }
 
@@ -72,14 +75,71 @@ namespace PixiEditor.Models.Layers
             LayerStructureChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        public void PostMoveReassignBounds(GuidStructureItem? parentFolder, Guid layerGuid)
+        public void PreMoveReassignBounds(GuidStructureItem? parentGroup, Guid layer)
+        {
+            if (parentGroup != null)
+            {
+                Guid? oldStart = parentGroup.StartLayerGuid;
+                Guid? oldEnd = parentGroup.EndLayerGuid;
+                GuidStructureItem parentOfParent = parentGroup.Parent;
+                if (parentGroup.Subgroups.Count == 0 && parentGroup.StartLayerGuid == layer && parentGroup.EndLayerGuid == layer)
+                {
+                    RemoveGroup(parentGroup);
+                }
+                else
+                {
+                    if (parentGroup.EndLayerGuid == layer)
+                    {
+                        parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, layer, false);
+                    }
+
+                    if (parentGroup.StartLayerGuid == layer)
+                    {
+                        parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, layer, true);
+                    }
+                }
+
+                if (parentOfParent != null)
+                {
+                    ApplyBoundsToParents(parentOfParent, parentGroup, oldStart, oldEnd);
+                }
+            }
+        }
+
+        public void PreMoveReassignBounds(GuidStructureItem? parentGroup, GuidStructureItem group)
         {
-            if (parentFolder != null)
+            if (parentGroup != null)
             {
+                Guid? oldStart = parentGroup.StartLayerGuid;
+                Guid? oldEnd = parentGroup.EndLayerGuid;
+                if (group.EndLayerGuid == parentGroup.EndLayerGuid && group.StartLayerGuid != null)
+                {
+                    parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, (Guid)group.StartLayerGuid, false);
+                }
+
+                if (group.StartLayerGuid == parentGroup.StartLayerGuid && group.EndLayerGuid != null)
+                {
+                    parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, (Guid)group.EndLayerGuid, true);
+                }
+
+                if (parentGroup.Parent != null)
+                {
+                    ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
+                }
+            }
+        }
+
+        public void PostMoveReassignBounds(GuidStructureItem? parentGroup, Guid layerGuid)
+        {
+            if (parentGroup != null)
+            {
+                Guid? oldStart = parentGroup.StartLayerGuid;
+                Guid? oldEnd = parentGroup.EndLayerGuid;
+
                 int layerIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == layerGuid));
 
-                int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentFolder.EndLayerGuid));
-                int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentFolder.StartLayerGuid));
+                int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentGroup.EndLayerGuid));
+                int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentGroup.StartLayerGuid));
 
                 int finalTopIndex = Math.Max(folderTopIndex, layerIndex);
                 int finalBottomIndex = Math.Min(folderBottomIndex, layerIndex);
@@ -87,31 +147,35 @@ namespace PixiEditor.Models.Layers
                 Guid? topBoundLayer = FindBoundLayer(layerGuid, finalTopIndex, finalBottomIndex, false);
                 Guid? bottomBoundLayer = FindBoundLayer(layerGuid, finalTopIndex, finalBottomIndex, true);
 
-                if (topBoundLayer == parentFolder.EndLayerGuid)
+                if (topBoundLayer == parentGroup.EndLayerGuid)
                 {
-                    parentFolder.EndLayerGuid = layerGuid;
+                    parentGroup.EndLayerGuid = layerGuid;
                 }
 
-                if (bottomBoundLayer == parentFolder.StartLayerGuid)
+                if (bottomBoundLayer == parentGroup.StartLayerGuid)
                 {
-                    parentFolder.StartLayerGuid = layerGuid;
+                    parentGroup.StartLayerGuid = layerGuid;
                 }
 
-                if (parentFolder.Parent != null)
+                if (parentGroup.Parent != null)
                 {
-                    PostMoveReassignBounds(parentFolder.Parent, layerGuid);
+                    ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
                 }
             }
         }
 
-        public void PostMoveReassignBounds(GuidStructureItem? parentGroup, GuidStructureItem folder)
+        public void PostMoveReassignBounds(GuidStructureItem? parentGroup, GuidStructureItem group)
         {
             if (parentGroup != null)
             {
-                if (folder.StartLayerGuid != null && folder.EndLayerGuid != null)
+                Guid? oldStart = parentGroup.StartLayerGuid;
+                Guid? oldEnd = parentGroup.EndLayerGuid;
+
+                if (group.StartLayerGuid != null && group.EndLayerGuid != null)
                 {
-                    int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == folder.EndLayerGuid));
-                    int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == folder.StartLayerGuid));
+
+                    int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == group.EndLayerGuid));
+                    int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == group.StartLayerGuid));
 
                     int parentFolderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentGroup.EndLayerGuid));
                     int parentFolderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == parentGroup.StartLayerGuid));
@@ -119,23 +183,23 @@ namespace PixiEditor.Models.Layers
                     int finalTopIndex = Math.Max(folderTopIndex, parentFolderTopIndex);
                     int finalBottomIndex = Math.Min(folderBottomIndex, parentFolderBottomIndex);
 
-                    Guid? topBoundLayer = FindBoundLayer((Guid)folder.StartLayerGuid, finalTopIndex, finalBottomIndex, false);
-                    Guid? bottomBoundLayer = FindBoundLayer((Guid)folder.EndLayerGuid, finalTopIndex, finalBottomIndex, true);
+                    Guid? topBoundLayer = FindBoundLayer((Guid)group.StartLayerGuid, finalTopIndex, finalBottomIndex, false);
+                    Guid? bottomBoundLayer = FindBoundLayer((Guid)group.EndLayerGuid, finalTopIndex, finalBottomIndex, true);
 
                     if (topBoundLayer == parentGroup.EndLayerGuid)
                     {
-                        parentGroup.EndLayerGuid = folder.EndLayerGuid;
+                        parentGroup.EndLayerGuid = group.EndLayerGuid;
                     }
 
                     if (bottomBoundLayer == parentGroup.StartLayerGuid)
                     {
-                        parentGroup.StartLayerGuid = folder.StartLayerGuid;
+                        parentGroup.StartLayerGuid = group.StartLayerGuid;
                     }
                 }
 
                 if (parentGroup.Parent != null)
                 {
-                    PostMoveReassignBounds(parentGroup.Parent, parentGroup);
+                    ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
                 }
             }
         }
@@ -153,75 +217,31 @@ namespace PixiEditor.Models.Layers
             LayerStructureChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        public void PreMoveReassignBounds(GuidStructureItem? parentGroup, Guid layer)
+        private void Group_GroupsChanged(object sender, EventArgs e)
         {
-            if (parentGroup != null)
-            {
-                GuidStructureItem parentOfParent = parentGroup.Parent;
-                if (parentGroup.Subfolders.Count == 0 && parentGroup.StartLayerGuid == layer && parentGroup.EndLayerGuid == layer)
-                {
-                    RemoveGroup(parentGroup);
-                }
-                else
-                {
-                    if (parentGroup.EndLayerGuid == layer)
-                    {
-                        parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, layer, false);
-                    }
-
-                    if (parentGroup.StartLayerGuid == layer)
-                    {
-                        parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, layer, true);
-                    }
-                }
-
-                if (parentOfParent != null)
-                {
-                    PreMoveReassignBounds(parentOfParent, layer);
-                }
-            }
+            LayerStructureChanged?.Invoke(this, EventArgs.Empty);
         }
 
         private void RemoveGroup(GuidStructureItem parentFolder)
         {
+            parentFolder.GroupsChanged -= Group_GroupsChanged;
             if (parentFolder.Parent == null)
             {
                 Groups.Remove(parentFolder);
             }
             else
             {
-                parentFolder.Parent.Subfolders.Remove(parentFolder);
+                parentFolder.Parent.Subgroups.Remove(parentFolder);
             }
 
             LayerStructureChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        private void PreMoveReassignBounds(GuidStructureItem? parentGroup, GuidStructureItem group)
-        {
-            if (parentGroup != null)
-            {
-                Guid? oldStart = group.StartLayerGuid;
-                Guid? oldEnd = group.EndLayerGuid;
-                if (group.EndLayerGuid == parentGroup.EndLayerGuid && group.StartLayerGuid != null)
-                {
-                    parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, (Guid)group.StartLayerGuid, false);
-                }
-
-                if (group.StartLayerGuid == parentGroup.StartLayerGuid && group.EndLayerGuid != null)
-                {
-                    parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, (Guid)group.EndLayerGuid, true);
-                }
-
-                if (parentGroup.Parent != null)
-                {
-                    ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
-                }
-            }
-        }
-
         private void ApplyBoundsToParents(GuidStructureItem parent, GuidStructureItem group, Guid? oldStart, Guid? oldEnd)
         {
-            if(parent.StartLayerGuid == oldStart)
+            Guid? parentOldStart = parent.StartLayerGuid;
+            Guid? parentOldEnd = parent.EndLayerGuid;
+            if (parent.StartLayerGuid == oldStart)
             {
                 parent.StartLayerGuid = group.StartLayerGuid;
             }
@@ -233,7 +253,7 @@ namespace PixiEditor.Models.Layers
 
             if (parent.Parent != null)
             {
-                ApplyBoundsToParents(parent.Parent, parent, oldStart, oldEnd);
+                ApplyBoundsToParents(parent.Parent, parent, parentOldStart, parentOldEnd);
             }
         }
 
@@ -310,9 +330,9 @@ namespace PixiEditor.Models.Layers
                 int bottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.LayerGuid == folder.StartLayerGuid));
                 var layers = GetLayersInOrder(new FolderData(topIndex, bottomIndex));
 
-                if (folder.Subfolders.Count > 0)
+                if (folder.Subgroups.Count > 0)
                 {
-                    var group = GetGroupByLayer(layerGuid, folder.Subfolders);
+                    var group = GetGroupByLayer(layerGuid, folder.Subgroups);
                     if(group != null)
                     {
                         return group;
@@ -332,14 +352,14 @@ namespace PixiEditor.Models.Layers
         {
             foreach (var folder in folders)
             {
-                if (folder.FolderGuid == folderGuid)
+                if (folder.GroupGuid == folderGuid)
                 {
                     return folder;
                 }
 
-                if (folder.Subfolders.Count > 0)
+                if (folder.Subgroups.Count > 0)
                 {
-                    var guid = GetGroupByGuid(folderGuid, folder.Subfolders);
+                    var guid = GetGroupByGuid(folderGuid, folder.Subgroups);
                     if(guid != null)
                     {
                         return guid;

+ 13 - 13
PixiEditor/Models/Layers/StructuredLayerTree.cs

@@ -34,7 +34,7 @@ namespace PixiEditor.Models.Layers
         private void PlaceItems(List<LayerGroup> parsedFolders, ObservableCollection<Layer> layers)
         {
             LayerGroup currentFolder = null;
-            List<LayerGroup> foldersAtIndex = new ();
+            List<LayerGroup> groupsAtIndex = new ();
             Stack<LayerGroup> unfinishedFolders = new ();
 
             for (int i = 0; i < layers.Count; i++)
@@ -55,22 +55,22 @@ namespace PixiEditor.Models.Layers
 
                 if (parsedFolders.Any(x => x.StructureData.StartLayerGuid == layers[i].LayerGuid))
                 {
-                    foldersAtIndex = parsedFolders.Where(x => x.StructureData.StartLayerGuid == layers[i].LayerGuid).ToList();
-                    for (int j = 0; j < foldersAtIndex.Count; j++)
+                    groupsAtIndex = parsedFolders.Where(x => x.StructureData.StartLayerGuid == layers[i].LayerGuid).ToList();
+                    for (int j = 0; j < groupsAtIndex.Count; j++)
                     {
-                        LayerGroup folder = foldersAtIndex[j];
+                        LayerGroup group = groupsAtIndex[j];
 
                         if (currentFolder != null)
                         {
                             unfinishedFolders.Push(currentFolder);
                         }
 
-                        foldersAtIndex[j] = parsedFolders.First(x => x.StructureData.StartLayerGuid == layers[i].LayerGuid);
-                        foldersAtIndex[j].DisplayIndex = RootDirectoryItems.Count;
-                        foldersAtIndex[j].TopIndex = CalculateTopIndex(folder.DisplayIndex, folder.StructureData, layers);
-                        if (foldersAtIndex[j].StructureData.EndLayerGuid != layers[i].LayerGuid)
+                        groupsAtIndex[j] = parsedFolders.First(x => x.StructureData.StartLayerGuid == layers[i].LayerGuid);
+                        groupsAtIndex[j].DisplayIndex = RootDirectoryItems.Count;
+                        groupsAtIndex[j].TopIndex = CalculateTopIndex(group.DisplayIndex, group.StructureData, layers);
+                        if (groupsAtIndex[j].StructureData.EndLayerGuid != layers[i].LayerGuid)
                         {
-                            currentFolder = foldersAtIndex[j];
+                            currentFolder = groupsAtIndex[j];
                         }
                     }
                 }
@@ -81,7 +81,7 @@ namespace PixiEditor.Models.Layers
                 }
                 else if (!RootDirectoryItems.Contains(currentFolder))
                 {
-                    RootDirectoryItems.AddRange(foldersAtIndex.Where(x => !RootDirectoryItems.Contains(x)));
+                    RootDirectoryItems.AddRange(groupsAtIndex.Where(x => !RootDirectoryItems.Contains(x)));
                 }
             }
         }
@@ -113,9 +113,9 @@ namespace PixiEditor.Models.Layers
 
             var subFolders = new List<LayerGroup>();
 
-            if (structureItem.Subfolders.Count > 0)
+            if (structureItem.Subgroups.Count > 0)
             {
-                subFolders = ParseFolders(structureItem.Subfolders, layers);
+                subFolders = ParseFolders(structureItem.Subgroups, layers);
             }
 
             foreach (var guid in layersInFolder)
@@ -133,7 +133,7 @@ namespace PixiEditor.Models.Layers
             structureItemLayers.Reverse();
 
             LayerGroup folder = new (structureItemLayers, subFolders, structureItem.Name,
-                structureItem.FolderGuid, displayIndex, displayIndex + structureItemLayers.Count - 1, structureItem)
+                structureItem.GroupGuid, displayIndex, displayIndex + structureItemLayers.Count - 1, structureItem)
             {
                 IsExpanded = structureItem.IsExpanded
             };

+ 5 - 4
PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -48,7 +48,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
         public void NewGroup(object parameter)
         {
-            Owner.BitmapManager.ActiveDocument?.LayerStructure.AddNewGroup("New Group", Owner.BitmapManager.ActiveLayer.LayerGuid);
+            Owner.BitmapManager.ActiveDocument?.LayerStructure.AddNewGroup($"{Owner.BitmapManager.ActiveLayer.Name} Group", Owner.BitmapManager.ActiveLayer.LayerGuid);
         }
 
         public bool CanAddNewGroup(object property)
@@ -97,13 +97,14 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
         public void DeleteLayer(object parameter)
         {
             int index = (int)parameter;
-            if (!Owner.BitmapManager.ActiveDocument.Layers[index].IsActive)
+            var doc = Owner.BitmapManager.ActiveDocument;
+            if (!doc.Layers[index].IsActive)
             {
-                Owner.BitmapManager.ActiveDocument.RemoveLayer(index);
+                doc.RemoveLayer(index);
             }
             else
             {
-                Owner.BitmapManager.ActiveDocument.RemoveActiveLayers();
+                doc.RemoveActiveLayers();
             }
         }
 

+ 2 - 12
PixiEditor/Views/MainWindow.xaml

@@ -310,18 +310,8 @@
                                         </usercontrols:LayersManager>
                                     </LayoutAnchorable>
                                     <LayoutAnchorable ContentId="rawLayer" Title="Raw layers">
-                                        <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Layers}">
-                                            <ItemsControl.ItemsPanel>
-                                                <ItemsPanelTemplate>
-                                                    <ui:ReversedOrderStackPanel />
-                                                </ItemsPanelTemplate>
-                                            </ItemsControl.ItemsPanel>
-                                            <ItemsControl.ItemTemplate>
-                                                <DataTemplate>
-                                                    <Label Foreground="White" Content="{Binding Name}"/>
-                                                </DataTemplate>
-                                            </ItemsControl.ItemTemplate>
-                                        </ItemsControl>
+                                        <usercontrols:RawLayersViewer Layers="{Binding BitmapManager.ActiveDocument.Layers}"
+                                                                      Structure="{Binding BitmapManager.ActiveDocument.LayerStructure}"/>
                                     </LayoutAnchorable>
                                 </LayoutAnchorablePane>
                             </LayoutAnchorablePaneGroup>

+ 5 - 2
PixiEditor/Views/UserControls/LayerGroupControl.xaml

@@ -3,9 +3,12 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-             xmlns:local="clr-namespace:PixiEditor.Views.UserControls" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:userControls="clr-namespace:PixiEditor.Views"
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:userControls="clr-namespace:PixiEditor.Views" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d" Focusable="True"
              d:DesignHeight="60" d:DesignWidth="250" Name="groupControl">
+    <UserControl.Resources>
+        <converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
+    </UserControl.Resources>
     <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True" >
         <i:Interaction.Behaviors>
             <behaviors:ClearFocusOnClickBehavior/>
@@ -32,7 +35,7 @@
                     Text="{Binding GroupName, ElementName=groupControl, Mode=TwoWay}" />
                 </StackPanel>
             </Grid>
-            <Grid DragEnter="Grid_DragEnter" Drop="Grid_Drop_Bottom"  DragLeave="Grid_DragLeave" Grid.Row="2" AllowDrop="True" Grid.ColumnSpan="3" Background="Transparent"/>
+            <Grid DragEnter="Grid_DragEnter" Drop="Grid_Drop_Bottom"  DragLeave="Grid_DragLeave" Grid.Row="2" AllowDrop="{Binding  GroupData.IsExpanded, ElementName=groupControl, Converter={StaticResource InverseBooleanConverter}}" Grid.ColumnSpan="3" Background="Transparent"/>
         </Grid>
     </Border>
 </UserControl>

+ 7 - 2
PixiEditor/Views/UserControls/LayerGroupControl.xaml.cs

@@ -91,13 +91,18 @@ namespace PixiEditor.Views.UserControls
                 Guid group = data.GroupGuid;
                 var document = data.LayersViewModel.Owner.BitmapManager.ActiveDocument;
 
+                int modifier = above ? 1 : -1;
+
                 Layer layer = document.Layers.First(x => x.LayerGuid == referenceLayer);
-                int indexOfReferenceLayer = document.Layers.IndexOf(layer) + 1;
+                int indexOfReferenceLayer = Math.Clamp(document.Layers.IndexOf(layer) + modifier, 0, document.Layers.Count);
 
                 Layer tempLayer = new("_temp");
                 document.Layers.Insert(indexOfReferenceLayer, tempLayer);
+
+                document.LayerStructure.AssignParent(tempLayer.LayerGuid, GroupData.Parent);
                 document.MoveFolderInStructure(group, tempLayer.LayerGuid, above);
-                document.Layers.Remove(tempLayer);
+                document.LayerStructure.AssignParent(tempLayer.LayerGuid, null);
+                document.RemoveLayer(tempLayer);
             }
         }
 

+ 60 - 0
PixiEditor/Views/UserControls/RawLayersViewer.xaml

@@ -0,0 +1,60 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.RawLayersViewer"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls" xmlns:ui="clr-namespace:PixiEditor.Helpers.UI" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="250" Name="rawLayersControl">
+    <UserControl.Resources>
+        <converters:LayerStructureToGroupsConverter x:Key="LayerStructureToGroupsConverter"/>
+    </UserControl.Resources>
+    <StackPanel DataContext="{Binding ElementName=rawLayersControl}">
+        <ItemsControl ItemsSource="{Binding Layers}">
+            <ItemsControl.ItemsPanel>
+                <ItemsPanelTemplate>
+                    <ui:ReversedOrderStackPanel />
+                </ItemsPanelTemplate>
+            </ItemsControl.ItemsPanel>
+            <ItemsControl.ItemTemplate>
+                <DataTemplate>
+                    <StackPanel VerticalAlignment="Center" Orientation="Horizontal">
+                        <Label Foreground="White" Content="{Binding Name}"/>
+                        <TextBlock Foreground="Wheat" Text="{Binding LayerGuid}"/>
+                    </StackPanel>
+                </DataTemplate>
+            </ItemsControl.ItemTemplate>
+        </ItemsControl>
+        <Separator/>
+        <ItemsControl>
+            <ItemsControl.ItemsSource>
+                <MultiBinding Converter="{StaticResource LayerStructureToGroupsConverter}">
+                    <Binding Path="Structure"/>
+                    <Binding Path="Structure.Groups.Count"/>
+                    <Binding Path="Layers.Count"/>
+                </MultiBinding>
+            </ItemsControl.ItemsSource>
+            <ItemsControl.ItemTemplate>
+                <DataTemplate>
+                    <Border BorderThickness="1" BorderBrush="Black">
+                    <StackPanel>
+                        <Label Foreground="White" Content="{Binding Name}"/>
+                        <StackPanel Orientation="Horizontal">
+                            <TextBlock Foreground="White" Text="Parent: "/>
+                                <TextBlock Foreground="Wheat" Text="{Binding Parent.Name}"/>
+                        </StackPanel>
+                        <StackPanel Orientation="Horizontal">
+                            <TextBlock Foreground="White" Text="End Layer: "/>
+                                <TextBlock Foreground="Wheat" Text="{Binding EndLayerGuid}"/>
+                        </StackPanel>
+                        <StackPanel Orientation="Horizontal">
+                            <TextBlock Foreground="White" Text="Start Layer: "/>
+                                <TextBlock Foreground="Wheat" Text="{Binding StartLayerGuid}"/>
+                        </StackPanel>
+                    </StackPanel>
+                    </Border>
+                </DataTemplate>
+            </ItemsControl.ItemTemplate>
+        </ItemsControl>
+    </StackPanel>
+</UserControl>

+ 49 - 0
PixiEditor/Views/UserControls/RawLayersViewer.xaml.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Controls;
+using PixiEditor.Models.Layers;
+
+namespace PixiEditor.Views.UserControls
+{
+    /// <summary>
+    /// Interaction logic for RawLayersViewer.xaml.
+    /// </summary>
+    public partial class RawLayersViewer : UserControl
+    {
+        public ObservableCollection<Layer> Layers
+        {
+            get { return (ObservableCollection<Layer>)GetValue(LayersProperty); }
+            set { SetValue(LayersProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for Layers.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty LayersProperty =
+            DependencyProperty.Register(
+                "Layers",
+                typeof(ObservableCollection<Layer>),
+                typeof(RawLayersViewer),
+                new PropertyMetadata(default(ObservableCollection<Layer>)));
+
+        public LayerStructure Structure
+        {
+            get { return (LayerStructure)GetValue(StructureProperty); }
+            set { SetValue(StructureProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for Structure.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty StructureProperty =
+            DependencyProperty.Register("Structure", typeof(LayerStructure), typeof(RawLayersViewer), new PropertyMetadata(default(LayerStructure), StructureChangedCallback));
+
+        private static void StructureChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            Debug.Write("asd");
+        }
+
+        public RawLayersViewer()
+        {
+            InitializeComponent();
+        }
+    }
+}