Sfoglia il codice sorgente

Layer structure is not parsed and displayed correctly

flabbet 4 anni fa
parent
commit
0f6ed5a673

+ 0 - 37
PixiEditor/Helpers/Converters/ILayerContainerToLayersConverter.cs

@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Windows.Data;
-using PixiEditor.Models.Layers;
-
-namespace PixiEditor.Helpers.Converters
-{
-    public class ILayerContainerToLayersConverter : IValueConverter
-    {
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            List<Layer> layers = new ();
-            if (value is IEnumerable<ILayerContainer> items)
-            {
-                foreach (var item in items)
-                {
-                    layers.AddRange(item.GetLayers());
-                }
-
-                return layers;
-            }
-            else if (value is Layer layer)
-            {
-                layers.Add(layer);
-                return layers;
-            }
-
-            return Binding.DoNothing;
-        }
-
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}

+ 10 - 11
PixiEditor/Helpers/Converters/IndexOfConverter.cs

@@ -1,28 +1,27 @@
 using System;
-using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Controls;
 using System.Windows.Data;
+using PixiEditor.Models.Layers;
+using PixiEditor.ViewModels;
 
 namespace PixiEditor.Helpers.Converters
 {
-    public class IndexOfConverter : IMultiValueConverter
+    public class IndexOfConverter : IValueConverter
     {
-        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            if (values[0] is int containerIndex && values[1] is int relativeIndex)
+            if (value is Layer layer && ViewModelMain.Current.BitmapManager.ActiveDocument != null)
             {
-                return containerIndex + relativeIndex;
+                return ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(layer);
             }
 
-            return -1;
+            return Binding.DoNothing;
         }
 
-        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            return targetTypes.Select(t => Binding.DoNothing).ToArray();
+            throw new NotImplementedException();
         }
     }
 }

+ 0 - 35
PixiEditor/Helpers/Converters/LayersCountToVisiblityConverter.cs

@@ -1,35 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using System.Windows;
-using System.Windows.Data;
-using PixiEditor.Models.Layers;
-
-namespace PixiEditor.Helpers.Converters
-{
-    public class LayersCountToVisiblityConverter : IValueConverter
-    {
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            if (value is ILayerContainer container)
-            {
-                bool moreThan = true;
-                if (parameter is string)
-                {
-                    moreThan = false;
-                }
-
-                int layersCount = container.GetLayers().Count();
-
-                return layersCount > 0 && (layersCount > 1 || (!moreThan && layersCount == 1)) ? Visibility.Visible : Visibility.Collapsed;
-            }
-
-            return Binding.DoNothing;
-        }
-
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}

+ 14 - 14
PixiEditor/Helpers/Converters/LayersToStructuredLayersConverter.cs

@@ -12,28 +12,28 @@ namespace PixiEditor.Helpers.Converters
     {
         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
         {
-            if (values[0] is IEnumerable<ILayerContainer> layers && values[1] is LayerStructure structure)
+            if (values[0] is IEnumerable<Layer> layers && values[1] is LayerStructure structure)
             {
-                return new StructuredLayerTree(layers, structure).Items;
+                return new StructuredLayerTree(layers, structure).RootDirectoryItems;
             }
 
-            return new StructuredLayerTree().Items;
+            return Binding.DoNothing;
         }
 
         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
         {
-            if (value is ObservableCollection<LayerStructureItem> tree)
-            {
-                List<Layer> layers = new ();
-                LayerStructure structure = new ();
-                foreach (var branchLayers in tree.Select(x => x.Children))
-                {
-                    //layers.AddRange(branchLayers);
-                    //structure.Items.Add(new GuidStructureItem(new ObservableCollection<Guid>(branchLayers.Select(x => x.LayerGuid))));
-                }
+            //if (value is ObservableCollection<object> tree)
+            //{
+            //    List<Layer> layers = new ();
+            //    LayerStructure structure = new ();
+            //    foreach (var branchLayers in tree.Select(x => x.Children))
+            //    {
+            //        //layers.AddRange(branchLayers);
+            //        //structure.Items.Add(new GuidStructureItem(new ObservableCollection<Guid>(branchLayers.Select(x => x.LayerGuid))));
+            //    }
 
-                return new object[] { layers, structure };
-            }
+            //    return new object[] { layers, structure };
+            //}
 
             throw new ArgumentException("Value is not a StructuredLayerTree");
         }

+ 11 - 3
PixiEditor/Models/Layers/GuidStructureItem.cs

@@ -1,15 +1,23 @@
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using System.Collections.ObjectModel;
 
 namespace PixiEditor.Models.Layers
 {
     public class GuidStructureItem
     {
-        public ObservableCollection<Guid> Children { get; set; }
+        public string Name { get; set; }
 
-        public GuidStructureItem(ObservableCollection<Guid> children)
+        public ObservableCollection<Guid> LayerGuids { get; set; }
+
+        public ObservableCollection<GuidStructureItem> Subfolders { get; set; }
+
+        public GuidStructureItem(string name, IEnumerable<Guid> children, IEnumerable<GuidStructureItem> subfolders)
         {
-            Children = children;
+            Name = name;
+            LayerGuids = new ObservableCollection<Guid>(children);
+            Subfolders = new ObservableCollection<GuidStructureItem>(subfolders);
         }
     }
 }

+ 0 - 9
PixiEditor/Models/Layers/ILayerContainer.cs

@@ -1,9 +0,0 @@
-using System.Collections.Generic;
-
-namespace PixiEditor.Models.Layers
-{
-    public interface ILayerContainer
-    {
-        public IEnumerable<Layer> GetLayers();
-    }
-}

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

@@ -13,7 +13,7 @@ using PixiEditor.ViewModels;
 namespace PixiEditor.Models.Layers
 {
     [DebuggerDisplay("'{name,nq}' {width}x{height}")]
-    public class Layer : BasicLayer, ILayerContainer
+    public class Layer : BasicLayer
     {
         private const int SizeOfArgb = 4;
         private bool clipRequested;

+ 36 - 0
PixiEditor/Models/Layers/LayerFolder.cs

@@ -0,0 +1,36 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using PixiEditor.Helpers;
+
+namespace PixiEditor.Models.Layers
+{
+    public class LayerFolder : NotifyableObject
+    {
+        public ObservableCollection<Layer> Layers { get; set; } = new ObservableCollection<Layer>();
+
+        public ObservableCollection<LayerFolder> Subfolders { get; set; } = new ObservableCollection<LayerFolder>();
+
+        public IEnumerable Items => Subfolders?.Cast<object>().Concat(Layers);
+
+        private string name;
+
+        public string Name
+        {
+            get => name;
+            set
+            {
+                name = value;
+                RaisePropertyChanged(nameof(Name));
+            }
+        }
+
+        public LayerFolder(IEnumerable<Layer> layers, IEnumerable<LayerFolder> subfolders, string name)
+        {
+            Layers = new ObservableCollection<Layer>(layers);
+            Subfolders = new ObservableCollection<LayerFolder>(subfolders);
+            Name = name;
+        }
+    }
+}

+ 3 - 3
PixiEditor/Models/Layers/LayerStructure.cs

@@ -4,16 +4,16 @@ namespace PixiEditor.Models.Layers
 {
     public class LayerStructure
     {
-        public ObservableCollection<GuidStructureItem> Items { get; set; }
+        public ObservableCollection<GuidStructureItem> Folders { get; set; }
 
         public LayerStructure(ObservableCollection<GuidStructureItem> items)
         {
-            Items = items;
+            Folders = items;
         }
 
         public LayerStructure()
         {
-            Items = new ObservableCollection<GuidStructureItem>();
+            Folders = new ObservableCollection<GuidStructureItem>();
         }
     }
 }

+ 0 - 14
PixiEditor/Models/Layers/LayerStructureItem.cs

@@ -1,14 +0,0 @@
-using System.Collections.ObjectModel;
-
-namespace PixiEditor.Models.Layers
-{
-    public class LayerStructureItem
-    {
-        public ObservableCollection<ILayerContainer> Children { get; set; } = new ObservableCollection<ILayerContainer>();
-
-        public LayerStructureItem(ObservableCollection<ILayerContainer> children)
-        {
-            Children = children;
-        }
-    }
-}

+ 40 - 21
PixiEditor/Models/Layers/StructuredLayerTree.cs

@@ -1,42 +1,61 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
+using PixiEditor.Helpers;
 using PixiEditor.Helpers.Extensions;
 
 namespace PixiEditor.Models.Layers
 {
-    public class StructuredLayerTree
+    public class StructuredLayerTree : NotifyableObject
     {
-        public ObservableCollection<LayerStructureItem> Items { get; set; } = new ObservableCollection<LayerStructureItem>();
+        private readonly List<Layer> layersInStructure = new ();
 
-        public StructuredLayerTree(IEnumerable<ILayerContainer> layers, LayerStructure structure)
+        public ObservableCollection<object> RootDirectoryItems { get; } = new ObservableCollection<object>();
+
+        public StructuredLayerTree(IEnumerable<Layer> layers, LayerStructure structure)
         {
-            if (structure == null || structure.Items.Count == 0)
+            if (structure.Folders == null || structure.Folders.Count == 0)
             {
-                foreach (var layer in layers)
-                {
-                    var collection = new ObservableCollection<ILayerContainer>();
-                    collection.AddRange(layer.GetLayers());
-                    Items.Add(new LayerStructureItem(collection));
-                }
-
+                RootDirectoryItems.AddRange(layers);
                 return;
             }
 
-            for (int i = 0; i < structure.Items.Count; i++)
-            {
-                var itemChildren = new ObservableCollection<ILayerContainer>();
-                foreach (var guid in structure.Items[i].Children)
-                {
-                    itemChildren.Add(layers.First(x => x.GetLayers().First(y => y.LayerGuid == guid).LayerGuid == guid));
-                }
+            RootDirectoryItems.AddRange(ParseFolders(structure.Folders, layers));
+            RootDirectoryItems.AddRange(layers.Where(x => !layersInStructure.Contains(x)));
+            layersInStructure.Clear();
+        }
 
-                Items.Add(new LayerStructureItem(itemChildren));
+        private List<LayerFolder> ParseFolders(IEnumerable<GuidStructureItem> folders, IEnumerable<Layer> layers)
+        {
+            List<LayerFolder> parsedFolders = new ();
+            foreach (var structureItem in folders)
+            {
+                parsedFolders.Add(ParseFolder(structureItem, layers));
             }
+
+            return parsedFolders;
         }
 
-        public StructuredLayerTree()
+        private LayerFolder ParseFolder(GuidStructureItem structureItem, IEnumerable<Layer> layers)
         {
+            List<Layer> structureItemLayers = new ();
+            foreach (var guid in structureItem.LayerGuids)
+            {
+                var layer = layers.First(x => x.LayerGuid == guid);
+                layersInStructure.Add(layer);
+                structureItemLayers.Add(layer);
+            }
+
+            var subFolders = new List<LayerFolder>();
+
+            if (structureItem.Subfolders.Count > 0)
+            {
+                subFolders = ParseFolders(structureItem.Subfolders, layers);
+            }
+
+            LayerFolder folder = new (structureItemLayers, subFolders, structureItem.Name);
+            return folder;
         }
     }
 }

+ 20 - 0
PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs

@@ -14,6 +14,7 @@ using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.IO;
+using PixiEditor.Models.Layers;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.Parser;
 
@@ -108,6 +109,25 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             }
 
             Owner.ResetProgramStateValues();
+
+
+            Owner.BitmapManager.ActiveDocument.AddNewLayer("Test");
+            Owner.BitmapManager.ActiveDocument.AddNewLayer("Test1");
+            Owner.BitmapManager.ActiveDocument.AddNewLayer("Test1 sub1");
+            Owner.BitmapManager.ActiveDocument.AddNewLayer("Test1 sub2");
+            Owner.BitmapManager.ActiveDocument.LayerStructure.Folders.Add(
+                new GuidStructureItem("Folder 1", new ObservableCollection<Guid>()
+                {
+                    Owner.BitmapManager.ActiveDocument.Layers[1].LayerGuid,
+                    Owner.BitmapManager.ActiveDocument.Layers[2].LayerGuid
+                },
+                new GuidStructureItem[] {
+                        new GuidStructureItem("Subfolder 1", new ObservableCollection<Guid>()
+                    {
+                        Owner.BitmapManager.ActiveDocument.Layers[3].LayerGuid,
+                        Owner.BitmapManager.ActiveDocument.Layers[4].LayerGuid
+                    },  Array.Empty<GuidStructureItem>()
+                    )}));
         }
 
         /// <summary>

+ 2 - 2
PixiEditor/Views/MainWindow.xaml

@@ -301,12 +301,12 @@
                                             LayerCommandsViewModel="{Binding LayersSubViewModel}"
                                             OpacityInputEnabled="{Binding BitmapManager.ActiveDocument, 
                     Converter={StaticResource NotNullToBoolConverter}}">
-                                            <usercontrols:LayersManager.StructuredLayers>
+                                            <usercontrols:LayersManager.LayerTreeRoot>
                                                 <MultiBinding Converter="{StaticResource LayersToStructuredLayersConverter}">
                                                     <Binding Path="BitmapManager.ActiveDocument.Layers" />
                                                     <Binding Path="BitmapManager.ActiveDocument.LayerStructure"/>
                                                 </MultiBinding>
-                                            </usercontrols:LayersManager.StructuredLayers>
+                                            </usercontrols:LayersManager.LayerTreeRoot>
                                         </usercontrols:LayersManager>
                                     </LayoutAnchorable>
                                 </LayoutAnchorablePane>

+ 6 - 9
PixiEditor/Views/UserControls/LayerItem.xaml.cs

@@ -152,17 +152,14 @@ namespace PixiEditor.Views
             if (e.Data.GetDataPresent("PixiEditor.Views.UserControls.LayerStructureItemContainer"))
             {
                 var data = (LayerStructureItemContainer)e.Data.GetData("PixiEditor.Views.UserControls.LayerStructureItemContainer");
-                for (int i = 0; i < data.Item.Children.Count; i++)
+                int oldIndex = data.ContainerIndex;
+                int moveBy = LayerIndex + indexModifier - oldIndex;
+                if (moveBy > 0)
                 {
-                    int oldIndex = data.ContainerIndex + i;
-                    int moveBy = LayerIndex + indexModifier - oldIndex;
-                    if (moveBy > 0)
-                    {
-                        moveBy--;
-                    }
-
-                    data.LayerCommandsViewModel.Owner.BitmapManager.ActiveDocument.MoveLayerIndexBy(oldIndex, moveBy);
+                    moveBy--;
                 }
+
+                data.LayerCommandsViewModel.Owner.BitmapManager.ActiveDocument.MoveLayerIndexBy(oldIndex, moveBy);
             }
         }
 

+ 30 - 93
PixiEditor/Views/UserControls/LayerStructureItemContainer.xaml

@@ -7,113 +7,50 @@
              xmlns:vws="clr-namespace:PixiEditor.Views" xmlns:ui="clr-namespace:PixiEditor.Helpers.UI" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d"
              d:DesignHeight="60" d:DesignWidth="250" Name="layerStructureContainer">
-    <UserControl.Resources>
-        <converters:IndexOfConverter x:Key="IndexOfConverter"/>
-        <converters:LayersCountToVisiblityConverter x:Key="LayersCountToVisiblityConverter"/>
-        <converters:ILayerContainerToLayersConverter x:Key="ILayerContainerToLayersConverter"/>
-    </UserControl.Resources>
-    <ItemsControl Name="itemsControl" ItemsSource="{Binding Item.Children, ElementName=layerStructureContainer}" AlternationCount="9999">
-            <ItemsControl.ItemsPanel>
-                <ItemsPanelTemplate>
-                    <ui:ReversedOrderStackPanel Orientation="Vertical"/>
-                </ItemsPanelTemplate>
-            </ItemsControl.ItemsPanel>
-            <ItemsControl.ItemTemplate>
-            <DataTemplate>
-                <Grid>
-                    <ItemsControl Visibility="{Binding Converter={StaticResource LayersCountToVisiblityConverter}, ConverterParameter='equalsOne'}" ItemsSource="{Binding Converter={StaticResource ILayerContainerToLayersConverter}}">
-                        <ItemsControl.ItemTemplate>
-                            <DataTemplate>
-                                <vws:LayerItem Tag="{Binding ElementName=layerStructureContainer}"
+    <vws:LayerItem Tag="{Binding ElementName=layerStructureContainer}"
                                SetActiveLayerCommand="{Binding LayerCommandsViewModel.SetActiveLayerCommand, ElementName=layerStructureContainer}"
                                        LayerName="{Binding Name, Mode=TwoWay}" 
                                        IsActive="{Binding IsActive, Mode=TwoWay}"
                                        IsRenaming="{Binding IsRenaming, Mode=TwoWay}"
                                        PreviewImage="{Binding LayerBitmap}"
                                        LayerColor="{Binding LayerHighlightColor}"
+                                       LayerIndex="{Binding ContainerIndex, ElementName=layerStructureContainer}"
                                       MoveToBackCommand="{Binding LayerCommandsViewModel.MoveToBackCommand, ElementName=layerStructureContainer}"
                                       MoveToFrontCommand="{Binding LayerCommandsViewModel.MoveToFrontCommand, ElementName=layerStructureContainer}">
-                                    <vws:LayerItem.LayerIndex>
-                                        <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                            <Binding Path="ContainerIndex" ElementName="layerStructureContainer" />
-                                            <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                        </MultiBinding>
-                                    </vws:LayerItem.LayerIndex>
-                                    <vws:LayerItem.ContextMenu>
-                                        <ContextMenu>
-                                            <MenuItem Header="Delete"
+        <vws:LayerItem.ContextMenu>
+            <ContextMenu>
+                <MenuItem Header="Delete"
                                          Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.DeleteLayersCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                            <MenuItem Header="Rename"
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" 
+                          CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex,  RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+                <MenuItem Header="Rename"
                                      Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.RenameLayerCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                            <MenuItem Header="Move to front"
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+                <MenuItem Header="Move to front"
                                      Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MoveToFrontCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                            <MenuItem Header="Move to back"
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
+                          CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+                <MenuItem Header="Move to back"
                                     Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MoveToBackCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                            <Separator/>
-                                            <MenuItem Header="Merge selected"
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" 
+                          CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+                <Separator/>
+                <MenuItem Header="Merge selected"
                                      Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MergeSelectedCommand, 
                                             RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
-                                            <MenuItem Header="Merge with above"
+                <MenuItem Header="Merge with above"
                                      Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MergeWithAboveCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                            <MenuItem Header="Merge with below"
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+                <MenuItem Header="Merge with below"
                                     Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MergeWithBelowCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                                                <MenuItem.CommandParameter>
-                                                    <MultiBinding Converter="{StaticResource IndexOfConverter}">
-                                                        <Binding Path="PlacementTarget.Tag.ContainerIndex" RelativeSource="{RelativeSource AncestorType=ContextMenu}" />
-                                                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource TemplatedParent}"/>
-                                                    </MultiBinding>
-                                                </MenuItem.CommandParameter>
-                                            </MenuItem>
-                                        </ContextMenu>
-                                    </vws:LayerItem.ContextMenu>
-                                </vws:LayerItem>
-                            </DataTemplate>
-                        </ItemsControl.ItemTemplate>
-                    </ItemsControl>
-                    <local:LayerStructureItemContainer Margin="20 0 0 0" Item="{Binding}" Visibility="{Binding Converter={StaticResource LayersCountToVisiblityConverter}}"/>
-                </Grid>
-            </DataTemplate>
-            </ItemsControl.ItemTemplate>
-        </ItemsControl>
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
+                </MenuItem>
+            </ContextMenu>
+        </vws:LayerItem.ContextMenu>
+    </vws:LayerItem>
 </UserControl>

+ 6 - 10
PixiEditor/Views/UserControls/LayerStructureItemContainer.xaml.cs

@@ -10,19 +10,15 @@ namespace PixiEditor.Views.UserControls
     /// </summary>
     public partial class LayerStructureItemContainer : UserControl
     {
-        public LayerStructureItem Item
+        public Layer Layer
         {
-            get { return (LayerStructureItem)GetValue(ItemProperty); }
-            set { SetValue(ItemProperty, value); }
+            get { return (Layer)GetValue(LayerProperty); }
+            set { SetValue(LayerProperty, value); }
         }
 
-        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
-        public static readonly DependencyProperty ItemProperty =
-            DependencyProperty.Register(
-                "Item",
-                typeof(LayerStructureItem),
-                typeof(LayerStructureItemContainer),
-                new PropertyMetadata(default(LayerStructureItem)));
+        // Using a DependencyProperty as the backing store for Layer.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty LayerProperty =
+            DependencyProperty.Register("Layer", typeof(Layer), typeof(LayerStructureItemContainer), new PropertyMetadata(default(Layer)));
 
         public LayersViewModel LayerCommandsViewModel
         {

+ 15 - 2
PixiEditor/Views/UserControls/LayersManager.xaml

@@ -12,6 +12,7 @@
              d:DesignHeight="450" d:DesignWidth="250" Name="layersManager">
     <UserControl.Resources>
         <converters:FloatNormalizeConverter x:Key="FloatNormalizeConverter" />
+        <converters:IndexOfConverter x:Key="IndexOfConverter"/>
     </UserControl.Resources>
     <Grid>
         <Grid.RowDefinitions>
@@ -36,7 +37,19 @@
         </StackPanel>
         <Separator Grid.Row="2" Background="{StaticResource BrighterAccentColor}"/>
         <ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
-            <ItemsControl DataContext="{Binding ElementName=layersManager}"
+            <TreeView ItemsSource="{Binding LayerTreeRoot, ElementName=layersManager}">
+                <TreeView.Resources>
+                    <HierarchicalDataTemplate DataType="{x:Type layers:LayerFolder}" ItemsSource="{Binding Items}">
+                        <Label Content="{Binding Name}" />
+                    </HierarchicalDataTemplate>
+                    <DataTemplate DataType="{x:Type layers:Layer}">
+                        <local:LayerStructureItemContainer 
+                            MouseMove="LayerStructureItemContainer_MouseMove" ContainerIndex="{Binding Converter={StaticResource IndexOfConverter}}"
+                            Layer="{Binding}" LayerCommandsViewModel="{Binding LayerCommandsViewModel, ElementName=layersManager}"/>
+                    </DataTemplate>
+                </TreeView.Resources>
+            </TreeView>
+            <!--<ItemsControl DataContext="{Binding ElementName=layersManager}"
                           x:Name="layersItemsControl" AlternationCount="9999" ItemsSource="{Binding StructuredLayers}">
                 <ItemsControl.ItemsPanel>
                     <ItemsPanelTemplate>
@@ -50,7 +63,7 @@
                                                            LayerCommandsViewModel="{Binding LayerCommandsViewModel, ElementName=layersManager}"/>
                     </DataTemplate>
                 </ItemsControl.ItemTemplate>
-            </ItemsControl>
+            </ItemsControl>-->
         </ScrollViewer>
     </Grid>
 </UserControl>

+ 10 - 13
PixiEditor/Views/UserControls/LayersManager.xaml.cs

@@ -1,9 +1,6 @@
 using System.Collections.ObjectModel;
 using System.Windows;
 using System.Windows.Controls;
-using GalaSoft.MvvmLight.Command;
-using PixiEditor.Models.Controllers;
-using PixiEditor.Models.Layers;
 using PixiEditor.ViewModels.SubViewModels.Main;
 
 namespace PixiEditor.Views.UserControls
@@ -13,19 +10,20 @@ namespace PixiEditor.Views.UserControls
     /// </summary>
     public partial class LayersManager : UserControl
     {
-        public ObservableCollection<LayerStructureItem> StructuredLayers
+
+        public ObservableCollection<object> LayerTreeRoot
         {
-            get { return (ObservableCollection<LayerStructureItem>)GetValue(StructuredLayersProperty); }
-            set { SetValue(StructuredLayersProperty, value); }
+            get { return (ObservableCollection<object>)GetValue(LayerTreeRootProperty); }
+            set { SetValue(LayerTreeRootProperty, value); }
         }
 
-        // Using a DependencyProperty as the backing store for StructuredLayers.  This enables animation, styling, binding, etc...
-        public static readonly DependencyProperty StructuredLayersProperty =
+        // Using a DependencyProperty as the backing store for LayerTreeRoot.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty LayerTreeRootProperty =
             DependencyProperty.Register(
-                "StructuredLayers",
-                typeof(ObservableCollection<LayerStructureItem>),
+                "LayerTreeRoot",
+                typeof(ObservableCollection<object>),
                 typeof(LayersManager),
-                new PropertyMetadata(default(ObservableCollection<LayerStructureItem>)));
+                new PropertyMetadata(default(ObservableCollection<object>)));
 
         public float LayerOpacity
         {
@@ -64,8 +62,7 @@ namespace PixiEditor.Views.UserControls
 
         private void LayerStructureItemContainer_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
         {
-            LayerStructureItemContainer container = sender as LayerStructureItemContainer;
-            if (container != null && e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
+            if (sender is LayerStructureItemContainer container && e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
             {
                 DragDrop.DoDragDrop(container, container, DragDropEffects.Move);
             }