TreeTraversal.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using QuestPDF.Infrastructure;
  4. namespace QuestPDF.Drawing.Proxy;
  5. internal class TreeNode<T>
  6. {
  7. public T Value { get; }
  8. public TreeNode<T>? Parent { get; set; }
  9. public ICollection<TreeNode<T>> Children { get; } = new List<TreeNode<T>>();
  10. public TreeNode(T Value)
  11. {
  12. this.Value = Value;
  13. }
  14. }
  15. internal static class TreeTraversal
  16. {
  17. public static IEnumerable<TreeNode<T>> ExtractElementsOfType<T>(this Element element) where T : Element
  18. {
  19. if (element is T proxy)
  20. {
  21. var result = new TreeNode<T>(proxy);
  22. foreach (var treeNode in proxy.GetChildren().SelectMany(ExtractElementsOfType<T>))
  23. {
  24. result.Children.Add(treeNode);
  25. treeNode.Parent = result;
  26. }
  27. yield return result;
  28. }
  29. else
  30. {
  31. foreach (var treeNode in element.GetChildren().SelectMany(ExtractElementsOfType<T>))
  32. yield return treeNode;
  33. }
  34. }
  35. public static IEnumerable<TreeNode<T>> Flatten<T>(this TreeNode<T> element) where T : Element
  36. {
  37. yield return element;
  38. foreach (var child in element.Children)
  39. foreach (var innerChild in Flatten(child))
  40. yield return innerChild;
  41. }
  42. public static ICollection<TreeNode<T>> ExtractAncestors<T>(this TreeNode<T> element)
  43. {
  44. var parent = element;
  45. var result = new List<TreeNode<T>>();
  46. while (parent is not null)
  47. {
  48. result.Add(parent);
  49. parent = parent.Parent;
  50. }
  51. return result;
  52. }
  53. public static TreeNode<OverflowDebuggingProxy>? FindElementOfType<TChild>(this TreeNode<OverflowDebuggingProxy> element)
  54. {
  55. TreeNode<OverflowDebuggingProxy> result = null;
  56. Traverse(element);
  57. return result;
  58. void Traverse(TreeNode<OverflowDebuggingProxy> currentElement)
  59. {
  60. if (currentElement.Value.Child is TChild)
  61. {
  62. result = currentElement;
  63. return;
  64. }
  65. foreach (var child in currentElement.Children)
  66. Traverse(child);
  67. }
  68. }
  69. }