DocumentStructureHelper.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System.Collections.Generic;
  2. using PixiEditor.AvaloniaUI.Models.Handlers;
  3. using PixiEditor.AvaloniaUI.Models.Layers;
  4. using PixiEditor.AvaloniaUI.ViewModels.Document;
  5. using PixiEditor.ChangeableDocument.Actions.Generated;
  6. using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
  7. using PixiEditor.ChangeableDocument.Enums;
  8. using PixiEditor.Extensions.Common.Localization;
  9. namespace PixiEditor.AvaloniaUI.Models.DocumentModels;
  10. #nullable enable
  11. internal class DocumentStructureHelper
  12. {
  13. private IDocument doc;
  14. private DocumentInternalParts internals;
  15. public DocumentStructureHelper(IDocument doc, DocumentInternalParts internals)
  16. {
  17. this.doc = doc;
  18. this.internals = internals;
  19. }
  20. private string GetUniqueName(string name, INodeHandler node)
  21. {
  22. int count = 1;
  23. node.TraverseBackwards(newNode =>
  24. {
  25. if (newNode is IStructureMemberHandler structureMemberHandler)
  26. {
  27. string childName = structureMemberHandler.NameBindable;
  28. if (childName.StartsWith(name))
  29. count++;
  30. }
  31. return true;
  32. });
  33. return $"{name} {count}";
  34. }
  35. public Guid CreateNewStructureMember(StructureMemberType type, string? name = null, bool finish = true)
  36. {
  37. IStructureMemberHandler? member = doc.SelectedStructureMember;
  38. if (member is null)
  39. {
  40. Guid guid = Guid.NewGuid();
  41. //put member on top
  42. internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(
  43. doc.NodeGraphHandler.OutputNode.Id,
  44. guid, type));
  45. name ??= GetUniqueName(
  46. type == StructureMemberType.Layer
  47. ? new LocalizedString("NEW_LAYER")
  48. : new LocalizedString("NEW_FOLDER"), doc.NodeGraphHandler.OutputNode);
  49. internals.ActionAccumulator.AddActions(new StructureMemberName_Action(guid, name));
  50. if (finish)
  51. internals.ActionAccumulator.AddFinishedActions();
  52. return guid;
  53. }
  54. if (member is IFolderHandler folder)
  55. {
  56. Guid guid = Guid.NewGuid();
  57. //put member inside folder on top
  58. internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(folder.Id, guid, type));
  59. name ??= GetUniqueName(
  60. type == StructureMemberType.Layer
  61. ? new LocalizedString("NEW_LAYER")
  62. : new LocalizedString("NEW_FOLDER"), folder);
  63. internals.ActionAccumulator.AddActions(new StructureMemberName_Action(guid, name));
  64. if (finish)
  65. internals.ActionAccumulator.AddFinishedActions();
  66. return guid;
  67. }
  68. if (member is ILayerHandler layer)
  69. {
  70. Guid guid = Guid.NewGuid();
  71. //put member above the layer
  72. INodeHandler parent = doc.StructureHelper.GetFirstForwardNode(layer);
  73. internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(parent.Id, guid, type));
  74. name ??= GetUniqueName(
  75. type == StructureMemberType.Layer
  76. ? new LocalizedString("NEW_LAYER")
  77. : new LocalizedString("NEW_FOLDER"), parent);
  78. internals.ActionAccumulator.AddActions(new StructureMemberName_Action(guid, name));
  79. if (finish)
  80. internals.ActionAccumulator.AddFinishedActions();
  81. return guid;
  82. }
  83. throw new ArgumentException($"Unknown member type: {type}");
  84. }
  85. private void HandleMoveInside(Guid memberToMove, Guid memberToMoveInto)
  86. {
  87. if (memberToMoveInto == memberToMove)
  88. return;
  89. internals.ActionAccumulator.AddFinishedActions(new MoveStructureMember_Action(memberToMove, memberToMoveInto,
  90. true));
  91. }
  92. private void HandleMoveAboveBelow(Guid memberToMove, Guid referenceMemberId, bool above)
  93. {
  94. var referenceMember = doc.StructureHelper.FindNode<INodeHandler>(referenceMemberId);
  95. var memberToMoveInto = !above ? referenceMember : doc.StructureHelper.GetFirstForwardNode(referenceMember);
  96. internals.ActionAccumulator.AddFinishedActions(
  97. new MoveStructureMember_Action(memberToMove, memberToMoveInto.Id, above && memberToMoveInto is IFolderHandler));
  98. }
  99. public void TryMoveStructureMember(Guid memberToMove, Guid memberToMoveIntoOrNextTo,
  100. StructureMemberPlacement placement)
  101. {
  102. switch (placement)
  103. {
  104. case StructureMemberPlacement.Above:
  105. HandleMoveAboveBelow(memberToMove, memberToMoveIntoOrNextTo, true);
  106. break;
  107. case StructureMemberPlacement.Below:
  108. HandleMoveAboveBelow(memberToMove, memberToMoveIntoOrNextTo, false);
  109. break;
  110. case StructureMemberPlacement.Inside:
  111. HandleMoveInside(memberToMove, memberToMoveIntoOrNextTo);
  112. break;
  113. case StructureMemberPlacement.BelowOutsideFolder:
  114. {
  115. var path = doc.StructureHelper.FindPath(memberToMoveIntoOrNextTo);
  116. var folder = path.FirstOrDefault(x => x is IFolderHandler) as IFolderHandler;
  117. if (folder is null)
  118. HandleMoveAboveBelow(memberToMove, memberToMoveIntoOrNextTo, false);
  119. else
  120. HandleMoveAboveBelow(memberToMove, folder.Id, false);
  121. }
  122. break;
  123. }
  124. }
  125. }