LayerStructure.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. using PixiEditor.Models.DataHolders;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.Linq;
  6. namespace PixiEditor.Models.Layers
  7. {
  8. // Notice for further developemnt. Remember to expose only GroupData classes if you want to modify this LayerStructure groups
  9. // LayerStructure should figure out the GuidStructureItem from its internal data. This will ensure that data will
  10. // modify correctly.
  11. // You should pass GuidStructureItem for operating on protected and private methods for faster data manipulation.
  12. /// <summary>
  13. /// Class containing layer groups structure and methods to operate on it.
  14. /// </summary>
  15. public class LayerStructure
  16. {
  17. public event EventHandler<LayerStructureChangedEventArgs> LayerStructureChanged;
  18. public WpfObservableRangeCollection<GuidStructureItem> Groups { get; set; }
  19. private Document Owner { get; }
  20. /// <summary>
  21. /// Checks whenever group contains only single layer and none subgroups.
  22. /// </summary>
  23. /// <param name="layerGuid">Guid of layer to check.</param>
  24. /// <param name="layerGroup">Group to check.</param>
  25. /// <returns>True if group contains single layer (EndLayerGuid and StartLayerGuid == layerGuid) and none subgroups.</returns>
  26. public static bool GroupContainsOnlyLayer(Guid layerGuid, GuidStructureItem layerGroup)
  27. {
  28. return layerGroup != null && layerGroup.Subgroups.Count == 0 && layerGroup.StartLayerGuid == layerGuid && layerGroup.EndLayerGuid == layerGuid;
  29. }
  30. /// <summary>
  31. /// Deep clones groups.
  32. /// </summary>
  33. /// <param name="groups">Groups to clone.</param>
  34. /// <returns>ObservableCollection with cloned groups.</returns>
  35. public static WpfObservableRangeCollection<GuidStructureItem> CloneGroups(WpfObservableRangeCollection<GuidStructureItem> groups)
  36. {
  37. WpfObservableRangeCollection<GuidStructureItem> outputGroups = new();
  38. foreach (var group in groups.ToArray())
  39. {
  40. outputGroups.Add(group.CloneGroup());
  41. }
  42. return outputGroups;
  43. }
  44. /// <summary>
  45. /// Finds parent group by layer guid.
  46. /// </summary>
  47. /// <param name="layerGuid">Guid of group to check.</param>
  48. /// <returns><see cref="GuidStructureItem"/>if parent group was found or null if not.</returns>
  49. public GuidStructureItem GetGroupByLayer(Guid layerGuid)
  50. {
  51. return GetGroupByLayer(layerGuid, Groups);
  52. }
  53. /// <summary>
  54. /// Finds <see cref="GuidStructureItem"/> (Group) by it's guid.
  55. /// </summary>
  56. /// <param name="groupGuid">Guid of group.</param>
  57. /// <returns><see cref="GuidStructureItem"/> if group was found or null if not.</returns>
  58. public GuidStructureItem GetGroupByGuid(Guid? groupGuid)
  59. {
  60. return GetGroupByGuid(groupGuid, Groups);
  61. }
  62. public WpfObservableRangeCollection<GuidStructureItem> CloneGroups()
  63. {
  64. return CloneGroups(Groups);
  65. }
  66. // This will allow to add new group with multiple layers and groups at once. Not working well, todo fix
  67. /*public GuidStructureItem AddNewGroup(string groupName, IEnumerable<Layer> layers, Guid activeLayer)
  68. {
  69. var activeLayerParent = GetGroupByLayer(activeLayer);
  70. List<GuidStructureItem> sameLevelGroups = new List<GuidStructureItem>();
  71. var group = AddNewGroup(groupName, activeLayer);
  72. if (activeLayerParent == null)
  73. {
  74. sameLevelGroups.AddRange(Groups);
  75. }
  76. else
  77. {
  78. sameLevelGroups.AddRange(activeLayerParent.Subgroups);
  79. }
  80. sameLevelGroups.Remove(group);
  81. group.Subgroups = new ObservableCollection<GuidStructureItem>(sameLevelGroups);
  82. sameLevelGroups = new(sameLevelGroups.Where(x => IsChildOf(activeLayer, x)));
  83. Guid lastLayer = activeLayer;
  84. foreach (var layer in layers)
  85. {
  86. if (layer.LayerGuid == activeLayer)
  87. {
  88. continue;
  89. }
  90. Owner.MoveLayerInStructure(layer.LayerGuid, lastLayer, false);
  91. lastLayer = layer.LayerGuid;
  92. }
  93. return group;
  94. }*/
  95. /// <summary>
  96. /// Adds a new group to layer structure taking into consideration nesting. Invokes LayerStructureChanged event.
  97. /// </summary>
  98. /// <param name="groupName">Name of a group.</param>
  99. /// <param name="childLayer">Child layer of a new group.</param>
  100. /// <returns>Newly created group (<see cref="GuidStructureItem"/>).</returns>
  101. public GuidStructureItem AddNewGroup(string groupName, Guid childLayer)
  102. {
  103. var parent = GetGroupByLayer(childLayer);
  104. GuidStructureItem group = new(groupName, childLayer) { IsExpanded = true };
  105. if (parent == null)
  106. {
  107. Groups.Add(group);
  108. }
  109. else
  110. {
  111. group.Parent = parent;
  112. parent.Subgroups.Add(group);
  113. }
  114. group.GroupsChanged += Group_GroupsChanged;
  115. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(childLayer));
  116. return group;
  117. }
  118. public GuidStructureItem AddNewGroup(string groupName, GuidStructureItem childGroup)
  119. {
  120. if (childGroup == null)
  121. {
  122. throw new ArgumentException("Child group can't be null.");
  123. }
  124. GuidStructureItem group = new(groupName, childGroup.StartLayerGuid, childGroup.EndLayerGuid, new[] { childGroup }, childGroup.Parent) { IsExpanded = true };
  125. if (childGroup.Parent == null)
  126. {
  127. Groups.Add(group);
  128. Groups.Remove(childGroup);
  129. }
  130. else
  131. {
  132. childGroup.Parent.Subgroups.Add(group);
  133. childGroup.Parent.Subgroups.Remove(childGroup);
  134. }
  135. childGroup.Parent = group;
  136. group.GroupsChanged += Group_GroupsChanged;
  137. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(GetGroupLayerGuids(group)));
  138. return group;
  139. }
  140. /// <summary>
  141. /// Moves group and it's children from one index to another. This method makes changes in <see cref="Document"/> Layers.
  142. /// </summary>
  143. /// <param name="groupGuid">Group guid to move.</param>
  144. /// <param name="newIndex">New group index, relative to <see cref="Document"/> Layers.</param>
  145. public void MoveGroup(Guid groupGuid, int newIndex)
  146. {
  147. var group = GetGroupByGuid(groupGuid);
  148. var parentGroup = group.Parent;
  149. bool reverseOrder = true;
  150. int groupTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == group.EndLayerGuid));
  151. int groupBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == group.StartLayerGuid));
  152. int difference = newIndex - groupTopIndex;
  153. if (newIndex < groupTopIndex)
  154. {
  155. reverseOrder = false;
  156. difference = newIndex - groupBottomIndex;
  157. }
  158. if (difference == 0)
  159. {
  160. return;
  161. }
  162. Unassign(parentGroup, group);
  163. List<Guid> layersInOrder = GetLayersInOrder(new GroupData(groupTopIndex, groupBottomIndex));
  164. MoveLayersInGroup(layersInOrder, difference, reverseOrder);
  165. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(layersInOrder));
  166. }
  167. /// <summary>
  168. /// Checks if group is nested inside parent group.
  169. /// </summary>
  170. /// <param name="group">Group to check.</param>
  171. /// <param name="parent">Parent of that group.</param>
  172. /// <returns>True if group is nested inside parent, false if not.</returns>
  173. public bool IsChildOf(GuidStructureItem group, GuidStructureItem parent)
  174. {
  175. if (group == null)
  176. {
  177. return false;
  178. }
  179. foreach (var subgroup in parent.Subgroups)
  180. {
  181. if (subgroup == group)
  182. {
  183. return true;
  184. }
  185. if (subgroup.Subgroups.Count > 0)
  186. {
  187. if (IsChildOf(group, subgroup))
  188. {
  189. return true;
  190. }
  191. }
  192. }
  193. return false;
  194. }
  195. /// <summary>
  196. /// Checks if layer is nested inside parent group.
  197. /// </summary>
  198. /// <param name="layerGuid">Layer GUID to check.</param>
  199. /// <param name="parent">Parent of that group.</param>
  200. /// <returns>True if layer is nested inside parent, false if not.</returns>
  201. public bool IsChildOf(Guid layerGuid, GuidStructureItem parent)
  202. {
  203. var layerParent = GetGroupByLayer(layerGuid);
  204. return layerParent == parent ? true : IsChildOf(layerParent, parent);
  205. }
  206. /// <summary>
  207. /// Reassigns (removes) group data from parent group.
  208. /// </summary>
  209. /// <param name="parentGroup">Parent group to reassign data in.</param>
  210. /// <param name="group">Group which data should be reassigned.</param>
  211. public void Unassign(GroupData parentGroup, GroupData group)
  212. {
  213. Unassign(GetGroupByGuid(parentGroup.GroupGuid), GetGroupByGuid(group.GroupGuid));
  214. }
  215. /// <summary>
  216. /// Reassigns (removes) layer data from parent group.
  217. /// </summary>
  218. /// <param name="parentGroup">Parent group to reassign data in.</param>
  219. /// <param name="layer">Layer which data should be reassigned.</param>
  220. public void Unassign(GroupData parentGroup, Guid layer)
  221. {
  222. PreMoveReassignBounds(GetGroupByGuid(parentGroup.GroupGuid), layer);
  223. }
  224. /// <summary>
  225. /// Reassigns (adds) layer data to parent group.
  226. /// </summary>
  227. /// <param name="parentGroup">Parent group to reassign data in.</param>
  228. /// <param name="layerGuid">Group which data should be reassigned.</param>
  229. public void Assign(GroupData parentGroup, Guid layerGuid)
  230. {
  231. Assign(GetGroupByGuid(parentGroup.GroupGuid), layerGuid);
  232. }
  233. /// <summary>
  234. /// Reassigns (adds) group data to parent group.
  235. /// </summary>
  236. /// <param name="parentGroup">Parent group to reassign data in.</param>
  237. /// <param name="group">Group which data should be reassigned.</param>
  238. public void Assign(GroupData parentGroup, GroupData group)
  239. {
  240. Assign(GetGroupByGuid(parentGroup?.GroupGuid), GetGroupByGuid(group.GroupGuid));
  241. }
  242. /// <summary>
  243. /// Assigns parent to a layer.
  244. /// </summary>
  245. /// <param name="layer">Layer to assign parent to.</param>
  246. /// <param name="parent">Parent which should be assigned. Null indicates no parent.</param>
  247. public void AssignParent(Guid layer, Guid? parent)
  248. {
  249. AssignParent(layer, parent.HasValue ? GetGroupByGuid(parent) : null);
  250. }
  251. /// <summary>
  252. /// Assigns group new parent.
  253. /// </summary>
  254. /// <param name="group">Group to assign parent</param>
  255. /// <param name="referenceLayerGroup">Parent of group.</param>
  256. public void ReassignParent(GuidStructureItem group, GuidStructureItem referenceLayerGroup)
  257. {
  258. group.Parent?.Subgroups.Remove(group);
  259. if (Groups.Contains(group))
  260. {
  261. Groups.Remove(group);
  262. }
  263. if (referenceLayerGroup == null)
  264. {
  265. if (!Groups.Contains(group))
  266. {
  267. Groups.Add(group);
  268. group.Parent = null;
  269. }
  270. }
  271. else
  272. {
  273. referenceLayerGroup.Subgroups.Add(group);
  274. group.Parent = referenceLayerGroup;
  275. }
  276. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(GetGroupLayerGuids(group)));
  277. }
  278. /// <summary>
  279. /// Gets all layers inside group, including nested groups.
  280. /// </summary>
  281. /// <param name="group">Group to get layers from.</param>
  282. /// <returns>List of layers.</returns>
  283. public List<Layer> GetGroupLayers(GuidStructureItem group)
  284. {
  285. List<Layer> layers = new();
  286. var layerGuids = GetGroupLayerGuids(group);
  287. foreach (var layerGuid in layerGuids)
  288. {
  289. layers.Add(Owner.Layers.First(x => x.GuidValue == layerGuid));
  290. }
  291. return layers;
  292. }
  293. /// <summary>
  294. /// Sets parent groups IsExpanded to true.
  295. /// </summary>
  296. /// <param name="layerGuid">Guid of layer which parents will be affected.</param>
  297. public void ExpandParentGroups(Guid layerGuid)
  298. {
  299. var group = GetGroupByLayer(layerGuid);
  300. while (group != null)
  301. {
  302. group.IsExpanded = true;
  303. group = group.Parent;
  304. }
  305. }
  306. /// <summary>
  307. /// Sets parent groups IsExpanded to true.
  308. /// </summary>
  309. /// <param name="group">Group which parents will be affected.</param>
  310. public void ExpandParentGroups(GuidStructureItem group)
  311. {
  312. GuidStructureItem currentGroup = group;
  313. while (currentGroup != null)
  314. {
  315. currentGroup.IsExpanded = true;
  316. currentGroup = currentGroup.Parent;
  317. }
  318. }
  319. private static Guid GetNextLayerGuid(Guid layer, List<Guid> allLayers, bool above)
  320. {
  321. int indexOfLayer = allLayers.IndexOf(layer);
  322. int modifier = above ? 1 : -1;
  323. int newIndex = Math.Clamp(indexOfLayer + modifier, 0, allLayers.Count - 1);
  324. return allLayers[newIndex];
  325. }
  326. /// <summary>
  327. /// Gets all layers inside group, including nested groups.
  328. /// </summary>
  329. /// <param name="group">Group to get layers from.</param>
  330. /// <returns>List of layer guids.</returns>
  331. private List<Guid> GetGroupLayerGuids(GuidStructureItem group)
  332. {
  333. Layer layerTop = Owner.Layers.FirstOrDefault(x => x.GuidValue == group.EndLayerGuid);
  334. Layer layerBottom = Owner.Layers.FirstOrDefault(x => x.GuidValue == group.StartLayerGuid);
  335. if (layerTop == null || layerBottom == null)
  336. {
  337. return new List<Guid>();
  338. }
  339. int indexTop = Owner.Layers.IndexOf(layerTop);
  340. int indexBottom = Owner.Layers.IndexOf(layerBottom);
  341. return GetLayersInOrder(new GroupData(indexTop, indexBottom));
  342. }
  343. private List<Guid> GetLayersInOrder(GroupData group)
  344. {
  345. List<Guid> layerGuids = new();
  346. int minIndex = group.BottomIndex;
  347. int maxIndex = group.TopIndex;
  348. for (int i = minIndex; i <= maxIndex; i++)
  349. {
  350. layerGuids.Add(Owner.Layers[i].GuidValue);
  351. }
  352. return layerGuids;
  353. }
  354. private void PreMoveReassignBounds(GuidStructureItem parentGroup, Guid layer)
  355. {
  356. if (parentGroup != null)
  357. {
  358. Guid oldStart = parentGroup.StartLayerGuid;
  359. Guid oldEnd = parentGroup.EndLayerGuid;
  360. GuidStructureItem parentOfParent = parentGroup.Parent;
  361. if (parentGroup.Subgroups.Count == 0 && parentGroup.StartLayerGuid == layer && parentGroup.EndLayerGuid == layer)
  362. {
  363. RemoveGroup(parentGroup);
  364. }
  365. else
  366. {
  367. if (parentGroup.EndLayerGuid == layer)
  368. {
  369. parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, layer, false);
  370. }
  371. if (parentGroup.StartLayerGuid == layer)
  372. {
  373. parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, layer, true);
  374. }
  375. }
  376. if (parentOfParent != null)
  377. {
  378. ApplyBoundsToParents(parentOfParent, parentGroup, oldStart, oldEnd);
  379. }
  380. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(layer));
  381. }
  382. }
  383. private void Unassign(GuidStructureItem parentGroup, GuidStructureItem group)
  384. {
  385. if (parentGroup != null)
  386. {
  387. Guid oldStart = parentGroup.StartLayerGuid;
  388. Guid oldEnd = parentGroup.EndLayerGuid;
  389. if (parentGroup.Subgroups.Count == 1 && parentGroup.StartLayerGuid == group.StartLayerGuid && parentGroup.EndLayerGuid == group.EndLayerGuid)
  390. {
  391. RemoveGroup(parentGroup);
  392. }
  393. else
  394. {
  395. if (group.EndLayerGuid == parentGroup.EndLayerGuid)
  396. {
  397. parentGroup.EndLayerGuid = FindBoundLayer(parentGroup, group.StartLayerGuid, false);
  398. }
  399. if (group.StartLayerGuid == parentGroup.StartLayerGuid)
  400. {
  401. parentGroup.StartLayerGuid = FindBoundLayer(parentGroup, group.EndLayerGuid, true);
  402. }
  403. }
  404. if (parentGroup.Parent != null)
  405. {
  406. ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
  407. }
  408. }
  409. }
  410. private void Assign(GuidStructureItem parentGroup, Guid layerGuid)
  411. {
  412. if (parentGroup != null)
  413. {
  414. Guid? oldStart = parentGroup.StartLayerGuid;
  415. Guid? oldEnd = parentGroup.EndLayerGuid;
  416. int layerIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == layerGuid));
  417. int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentGroup.EndLayerGuid));
  418. int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentGroup.StartLayerGuid));
  419. int finalTopIndex = Math.Max(folderTopIndex, layerIndex);
  420. int finalBottomIndex = Math.Min(folderBottomIndex, layerIndex);
  421. Guid? topBoundLayer = FindBoundLayer(layerGuid, finalTopIndex, finalBottomIndex, false);
  422. Guid? bottomBoundLayer = FindBoundLayer(layerGuid, finalTopIndex, finalBottomIndex, true);
  423. if (topBoundLayer == parentGroup.EndLayerGuid)
  424. {
  425. parentGroup.EndLayerGuid = layerGuid;
  426. }
  427. if (bottomBoundLayer == parentGroup.StartLayerGuid)
  428. {
  429. parentGroup.StartLayerGuid = layerGuid;
  430. }
  431. if (parentGroup.Parent != null)
  432. {
  433. ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
  434. }
  435. var args = new LayerStructureChangedEventArgs(layerGuid);
  436. if (topBoundLayer.HasValue)
  437. {
  438. args.AffectedLayerGuids.Add(topBoundLayer.Value);
  439. }
  440. if (bottomBoundLayer.HasValue)
  441. {
  442. args.AffectedLayerGuids.Add(bottomBoundLayer.Value);
  443. }
  444. LayerStructureChanged?.Invoke(this, args);
  445. }
  446. }
  447. private void Assign(GuidStructureItem parentGroup, GuidStructureItem group)
  448. {
  449. if (parentGroup != null)
  450. {
  451. Guid oldStart = parentGroup.StartLayerGuid;
  452. Guid oldEnd = parentGroup.EndLayerGuid;
  453. int folderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == group.EndLayerGuid));
  454. int folderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == group.StartLayerGuid));
  455. int parentFolderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentGroup.EndLayerGuid));
  456. int parentFolderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentGroup.StartLayerGuid));
  457. int finalTopIndex = Math.Max(folderTopIndex, parentFolderTopIndex);
  458. int finalBottomIndex = Math.Min(folderBottomIndex, parentFolderBottomIndex);
  459. Guid topBoundLayer = FindBoundLayer(group.StartLayerGuid, finalTopIndex, finalBottomIndex, false);
  460. Guid bottomBoundLayer = FindBoundLayer(group.EndLayerGuid, finalTopIndex, finalBottomIndex, true);
  461. if (topBoundLayer == parentGroup.EndLayerGuid)
  462. {
  463. parentGroup.EndLayerGuid = group.EndLayerGuid;
  464. }
  465. if (bottomBoundLayer == parentGroup.StartLayerGuid)
  466. {
  467. parentGroup.StartLayerGuid = group.StartLayerGuid;
  468. }
  469. if (parentGroup.Parent != null)
  470. {
  471. ApplyBoundsToParents(parentGroup.Parent, parentGroup, oldStart, oldEnd);
  472. }
  473. }
  474. }
  475. private void AssignParent(Guid layer, GuidStructureItem parent)
  476. {
  477. var currentParent = GetGroupByLayer(layer);
  478. if (currentParent != null)
  479. {
  480. PreMoveReassignBounds(currentParent, layer);
  481. }
  482. Assign(parent, layer);
  483. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(layer));
  484. }
  485. private void Group_GroupsChanged(object sender, GroupChangedEventArgs e)
  486. {
  487. List<Guid> layersAffected = new List<Guid>();
  488. e.GroupsAffected.ForEach(x => layersAffected.AddRange(GetGroupLayerGuids(x)));
  489. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(layersAffected));
  490. }
  491. private void RemoveGroup(GuidStructureItem parentFolder)
  492. {
  493. parentFolder.GroupsChanged -= Group_GroupsChanged;
  494. var layerGuids = GetGroupLayerGuids(parentFolder);
  495. if (parentFolder.Parent == null)
  496. {
  497. Groups.Remove(parentFolder);
  498. }
  499. else
  500. {
  501. parentFolder.Parent.Subgroups.Remove(parentFolder);
  502. }
  503. LayerStructureChanged?.Invoke(this, new LayerStructureChangedEventArgs(layerGuids));
  504. }
  505. private void ApplyBoundsToParents(GuidStructureItem parent, GuidStructureItem group, Guid? oldStart, Guid? oldEnd)
  506. {
  507. Guid parentOldStart = parent.StartLayerGuid;
  508. Guid parentOldEnd = parent.EndLayerGuid;
  509. if (parent.Subgroups.Count == 0)
  510. {
  511. RemoveGroup(parent);
  512. }
  513. if (parent.StartLayerGuid == oldStart)
  514. {
  515. parent.StartLayerGuid = group.StartLayerGuid;
  516. }
  517. if (parent.EndLayerGuid == oldEnd)
  518. {
  519. parent.EndLayerGuid = group.EndLayerGuid;
  520. }
  521. if (parent.Parent != null)
  522. {
  523. ApplyBoundsToParents(parent.Parent, parent, parentOldStart, parentOldEnd);
  524. }
  525. }
  526. private Guid FindBoundLayer(Guid layerGuid, int parentFolderTopIndex, int parentFolderBottomIndex, bool above)
  527. {
  528. return GetNextLayerGuid(
  529. layerGuid,
  530. GetLayersInOrder(new GroupData(parentFolderTopIndex, parentFolderBottomIndex)),
  531. above);
  532. }
  533. private Guid FindBoundLayer(GuidStructureItem parentFolder, Guid layerGuid, bool above)
  534. {
  535. int parentFolderTopIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentFolder.EndLayerGuid));
  536. int parentFolderBottomIndex = Owner.Layers.IndexOf(Owner.Layers.First(x => x.GuidValue == parentFolder.StartLayerGuid));
  537. return FindBoundLayer(layerGuid, parentFolderTopIndex, parentFolderBottomIndex, above);
  538. }
  539. private void MoveLayersInGroup(List<Guid> layers, int moveBy, bool reverseOrder)
  540. {
  541. List<Guid> layerGuids = reverseOrder ? layers.Reverse<Guid>().ToList() : layers;
  542. for (int i = 0; i < layers.Count; i++)
  543. {
  544. Guid layerGuid = layerGuids[i];
  545. var layer = Owner.Layers.First(x => x.GuidValue == layerGuid);
  546. int layerIndex = Owner.Layers.IndexOf(layer);
  547. Owner.Layers.Move(layerIndex, layerIndex + moveBy);
  548. }
  549. }
  550. private GuidStructureItem GetGroupByLayer(Guid layerGuid, IEnumerable<GuidStructureItem> groups)
  551. {
  552. foreach (var currentGroup in groups)
  553. {
  554. var endLayer = Owner.Layers.First(x => x.GuidValue == currentGroup.EndLayerGuid);
  555. var startLayer = Owner.Layers.First(x => x.GuidValue == currentGroup.StartLayerGuid);
  556. int topIndex = Owner.Layers.IndexOf(endLayer);
  557. int bottomIndex = Owner.Layers.IndexOf(startLayer);
  558. var layers = GetLayersInOrder(new GroupData(topIndex, bottomIndex));
  559. if (currentGroup.Subgroups.Count > 0)
  560. {
  561. var group = GetGroupByLayer(layerGuid, currentGroup.Subgroups);
  562. if (group != null)
  563. {
  564. return group;
  565. }
  566. }
  567. if (layers.Contains(layerGuid))
  568. {
  569. return currentGroup;
  570. }
  571. }
  572. return null;
  573. }
  574. private GuidStructureItem GetGroupByGuid(Guid? groupGuid, IEnumerable<GuidStructureItem> groups)
  575. {
  576. foreach (var group in groups)
  577. {
  578. if (group.GroupGuid == groupGuid)
  579. {
  580. return group;
  581. }
  582. if (group.Subgroups.Count > 0)
  583. {
  584. var guid = GetGroupByGuid(groupGuid, group.Subgroups);
  585. if (guid != null)
  586. {
  587. return guid;
  588. }
  589. }
  590. }
  591. return null;
  592. }
  593. public LayerStructure(WpfObservableRangeCollection<GuidStructureItem> items, Document owner)
  594. {
  595. Groups = items;
  596. Owner = owner;
  597. }
  598. public LayerStructure(Document owner)
  599. {
  600. Groups = new WpfObservableRangeCollection<GuidStructureItem>();
  601. Owner = owner;
  602. }
  603. }
  604. }