TreeBuilder.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Terminal.Gui {
  5. /// <summary>
  6. /// Interface for supplying data to a <see cref="TreeView{T}"/> on demand as root level nodes
  7. /// are expanded by the user
  8. /// </summary>
  9. public interface ITreeBuilder<T> {
  10. /// <summary>
  11. /// Returns true if <see cref="CanExpand"/> is implemented by this class
  12. /// </summary>
  13. /// <value></value>
  14. bool SupportsCanExpand { get; }
  15. /// <summary>
  16. /// Returns true/false for whether a model has children. This method should be implemented
  17. /// when <see cref="GetChildren"/> is an expensive operation otherwise
  18. /// <see cref="SupportsCanExpand"/> should return false (in which case this method will not
  19. /// be called)
  20. /// </summary>
  21. /// <remarks>Only implement this method if you have a very fast way of determining whether
  22. /// an object can have children e.g. checking a Type (directories can always be expanded)
  23. /// </remarks>
  24. /// <param name="toExpand"></param>
  25. /// <returns></returns>
  26. bool CanExpand (T toExpand);
  27. /// <summary>
  28. /// Returns all children of a given <paramref name="forObject"/> which should be added to the
  29. /// tree as new branches underneath it
  30. /// </summary>
  31. /// <param name="forObject"></param>
  32. /// <returns></returns>
  33. IEnumerable<T> GetChildren (T forObject);
  34. }
  35. /// <summary>
  36. /// Abstract implementation of <see cref="ITreeBuilder{T}"/>.
  37. /// </summary>
  38. public abstract class TreeBuilder<T> : ITreeBuilder<T> {
  39. /// <inheritdoc/>
  40. public bool SupportsCanExpand { get; protected set; } = false;
  41. /// <summary>
  42. /// Override this method to return a rapid answer as to whether <see cref="GetChildren(T)"/>
  43. /// returns results. If you are implementing this method ensure you passed true in base
  44. /// constructor or set <see cref="SupportsCanExpand"/>
  45. /// </summary>
  46. /// <param name="toExpand"></param>
  47. /// <returns></returns>
  48. public virtual bool CanExpand (T toExpand)
  49. {
  50. return GetChildren (toExpand).Any ();
  51. }
  52. /// <inheritdoc/>
  53. public abstract IEnumerable<T> GetChildren (T forObject);
  54. /// <summary>
  55. /// Constructs base and initializes <see cref="SupportsCanExpand"/>
  56. /// </summary>
  57. /// <param name="supportsCanExpand">Pass true if you intend to
  58. /// implement <see cref="CanExpand(T)"/> otherwise false</param>
  59. public TreeBuilder (bool supportsCanExpand)
  60. {
  61. SupportsCanExpand = supportsCanExpand;
  62. }
  63. }
  64. /// <summary>
  65. /// <see cref="ITreeBuilder{T}"/> implementation for <see cref="ITreeNode"/> objects
  66. /// </summary>
  67. public class TreeNodeBuilder : TreeBuilder<ITreeNode> {
  68. /// <summary>
  69. /// Initialises a new instance of builder for any model objects of
  70. /// Type <see cref="ITreeNode"/>
  71. /// </summary>
  72. public TreeNodeBuilder () : base (false)
  73. {
  74. }
  75. /// <summary>
  76. /// Returns <see cref="ITreeNode.Children"/> from <paramref name="model"/>
  77. /// </summary>
  78. /// <param name="model"></param>
  79. /// <returns></returns>
  80. public override IEnumerable<ITreeNode> GetChildren (ITreeNode model)
  81. {
  82. return model.Children;
  83. }
  84. }
  85. /// <summary>
  86. /// Implementation of <see cref="ITreeBuilder{T}"/> that uses user defined functions
  87. /// </summary>
  88. public class DelegateTreeBuilder<T> : TreeBuilder<T> {
  89. private Func<T, IEnumerable<T>> childGetter;
  90. private Func<T, bool> canExpand;
  91. /// <summary>
  92. /// Constructs an implementation of <see cref="ITreeBuilder{T}"/> that calls the user
  93. /// defined method <paramref name="childGetter"/> to determine children
  94. /// </summary>
  95. /// <param name="childGetter"></param>
  96. /// <returns></returns>
  97. public DelegateTreeBuilder (Func<T, IEnumerable<T>> childGetter) : base (false)
  98. {
  99. this.childGetter = childGetter;
  100. }
  101. /// <summary>
  102. /// Constructs an implementation of <see cref="ITreeBuilder{T}"/> that calls the user
  103. /// defined method <paramref name="childGetter"/> to determine children
  104. /// and <paramref name="canExpand"/> to determine expandability
  105. /// </summary>
  106. /// <param name="childGetter"></param>
  107. /// <param name="canExpand"></param>
  108. /// <returns></returns>
  109. public DelegateTreeBuilder (Func<T, IEnumerable<T>> childGetter, Func<T, bool> canExpand) : base (true)
  110. {
  111. this.childGetter = childGetter;
  112. this.canExpand = canExpand;
  113. }
  114. /// <summary>
  115. /// Returns whether a node can be expanded based on the delegate passed during construction
  116. /// </summary>
  117. /// <param name="toExpand"></param>
  118. /// <returns></returns>
  119. public override bool CanExpand (T toExpand)
  120. {
  121. return canExpand?.Invoke (toExpand) ?? base.CanExpand (toExpand);
  122. }
  123. /// <summary>
  124. /// Returns children using the delegate method passed during construction
  125. /// </summary>
  126. /// <param name="forObject"></param>
  127. /// <returns></returns>
  128. public override IEnumerable<T> GetChildren (T forObject)
  129. {
  130. return childGetter.Invoke (forObject);
  131. }
  132. }
  133. }