StructuredLayerTree.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using PixiEditor.Helpers;
  2. using PixiEditor.Models.DataHolders;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using System.Linq;
  7. namespace PixiEditor.Models.Layers
  8. {
  9. public class StructuredLayerTree : NotifyableObject
  10. {
  11. private List<Guid> layersInStructure = new();
  12. public WpfObservableRangeCollection<IHasGuid> RootDirectoryItems { get; } = new WpfObservableRangeCollection<IHasGuid>();
  13. private static void Swap(ref int startIndex, ref int endIndex)
  14. {
  15. (startIndex, endIndex) = (endIndex, startIndex);
  16. }
  17. public StructuredLayerTree(WpfObservableRangeCollection<Layer> layers, LayerStructure structure)
  18. {
  19. if (layers == null || structure == null)
  20. {
  21. return;
  22. }
  23. if (structure.Groups == null || structure.Groups.Count == 0)
  24. {
  25. RootDirectoryItems.AddRange(layers);
  26. return;
  27. }
  28. var parsedFolders = ParseFolders(structure.Groups, layers);
  29. parsedFolders = parsedFolders.OrderBy(x => x.DisplayIndex).ToList();
  30. PlaceItems(parsedFolders, layers);
  31. layersInStructure.Clear();
  32. }
  33. private void PlaceItems(List<LayerGroup> parsedFolders, ObservableCollection<Layer> layers)
  34. {
  35. LayerGroup currentFolder = null;
  36. List<LayerGroup> groupsAtIndex = new();
  37. Stack<LayerGroup> unfinishedFolders = new();
  38. for (int i = 0; i < layers.Count; i++)
  39. {
  40. if (currentFolder != null && layers[i].GuidValue == currentFolder.StructureData.EndLayerGuid)
  41. {
  42. if (unfinishedFolders.Count > 0)
  43. {
  44. currentFolder = unfinishedFolders.Pop();
  45. }
  46. else
  47. {
  48. currentFolder = null;
  49. }
  50. continue;
  51. }
  52. AssignGroup(parsedFolders, layers, ref currentFolder, ref groupsAtIndex, unfinishedFolders, i);
  53. if (currentFolder == null && !layersInStructure.Contains(layers[i].GuidValue))
  54. {
  55. RootDirectoryItems.Add(layers[i]);
  56. }
  57. else if (!RootDirectoryItems.Contains(currentFolder))
  58. {
  59. RootDirectoryItems.AddRange(groupsAtIndex.Where(x => !RootDirectoryItems.Contains(x)));
  60. }
  61. }
  62. }
  63. private void AssignGroup(List<LayerGroup> parsedFolders, ObservableCollection<Layer> layers, ref LayerGroup currentFolder, ref List<LayerGroup> groupsAtIndex, Stack<LayerGroup> unfinishedFolders, int i)
  64. {
  65. if (parsedFolders.Any(x => x.StructureData.StartLayerGuid == layers[i].GuidValue))
  66. {
  67. groupsAtIndex = parsedFolders.Where(x => x.StructureData.StartLayerGuid == layers[i].GuidValue).ToList();
  68. for (int j = 0; j < groupsAtIndex.Count; j++)
  69. {
  70. LayerGroup group = groupsAtIndex[j];
  71. if (currentFolder != null)
  72. {
  73. unfinishedFolders.Push(currentFolder);
  74. }
  75. groupsAtIndex[j] = parsedFolders.First(x => x.StructureData.StartLayerGuid == layers[i].GuidValue);
  76. groupsAtIndex[j].DisplayIndex = RootDirectoryItems.Count;
  77. groupsAtIndex[j].TopIndex = CalculateTopIndex(group.DisplayIndex, group.StructureData, layers);
  78. if (groupsAtIndex[j].StructureData.EndLayerGuid != layers[i].GuidValue)
  79. {
  80. currentFolder = groupsAtIndex[j];
  81. }
  82. }
  83. }
  84. }
  85. private int CalculateTopIndex(int displayIndex, GuidStructureItem structureData, ObservableCollection<Layer> layers)
  86. {
  87. var endLayer = layers.FirstOrDefault(x => x.GuidValue == structureData.EndLayerGuid);
  88. var bottomLayer = layers.FirstOrDefault(x => x.GuidValue == structureData.StartLayerGuid);
  89. int originalTopIndex = 0;
  90. int originalBottomIndex = 0;
  91. if (endLayer != null)
  92. {
  93. originalTopIndex = layers.IndexOf(endLayer);
  94. }
  95. if (bottomLayer != null)
  96. {
  97. originalBottomIndex = layers.IndexOf(bottomLayer);
  98. }
  99. return displayIndex + (originalTopIndex - originalBottomIndex);
  100. }
  101. private List<LayerGroup> ParseFolders(IEnumerable<GuidStructureItem> folders, ObservableCollection<Layer> layers)
  102. {
  103. List<LayerGroup> parsedFolders = new();
  104. foreach (var structureItem in folders)
  105. {
  106. parsedFolders.Add(ParseFolder(structureItem, layers));
  107. }
  108. return parsedFolders;
  109. }
  110. private LayerGroup ParseFolder(GuidStructureItem structureItem, ObservableCollection<Layer> layers)
  111. {
  112. List<Layer> structureItemLayers = new();
  113. Guid[] layersInFolder = GetLayersInGroup(layers, structureItem);
  114. var subFolders = new List<LayerGroup>();
  115. if (structureItem.Subgroups.Count > 0)
  116. {
  117. subFolders = ParseFolders(structureItem.Subgroups, layers);
  118. }
  119. foreach (var guid in layersInFolder)
  120. {
  121. var layer = layers.FirstOrDefault(x => x.GuidValue == guid);
  122. if (layer != null)
  123. {
  124. if (!layersInStructure.Contains(layer.GuidValue))
  125. {
  126. layersInStructure.Add(layer.GuidValue);
  127. structureItemLayers.Add(layer);
  128. }
  129. }
  130. }
  131. int displayIndex = layersInFolder.Length > 0 ? layers.IndexOf(layers.First(x => x.GuidValue == structureItem.StartLayerGuid)) : 0;
  132. structureItemLayers.Reverse();
  133. LayerGroup folder = new(structureItemLayers, subFolders, structureItem.Name,
  134. structureItem.GroupGuid, displayIndex, displayIndex + structureItemLayers.Count - 1, structureItem)
  135. {
  136. IsExpanded = structureItem.IsExpanded,
  137. IsRenaming = structureItem.IsRenaming
  138. };
  139. return folder;
  140. }
  141. private Guid[] GetLayersInGroup(ObservableCollection<Layer> layers, GuidStructureItem structureItem)
  142. {
  143. var startLayer = layers.FirstOrDefault(x => x.GuidValue == structureItem.StartLayerGuid);
  144. var endLayer = layers.FirstOrDefault(x => x.GuidValue == structureItem.EndLayerGuid);
  145. if (startLayer == null || endLayer == null)
  146. {
  147. return Array.Empty<Guid>();
  148. }
  149. int startIndex = layers.IndexOf(startLayer);
  150. int endIndex = layers.IndexOf(endLayer);
  151. if (startIndex > endIndex)
  152. {
  153. Swap(ref startIndex, ref endIndex);
  154. }
  155. int len = endIndex - startIndex + 1;
  156. Guid[] guids = new Guid[len];
  157. for (int i = 0; i < len; i++)
  158. {
  159. guids[i] = layers[i + startIndex].GuidValue;
  160. }
  161. return guids;
  162. }
  163. }
  164. }