CoreTreeNodes.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. namespace InABox.Core
  8. {
  9. public interface ICoreTreeNode
  10. {
  11. object? ID { get; set; }
  12. object? Parent { get; set; }
  13. object? Image { get; set; }
  14. CoreRow? Row { get; set; }
  15. object? this[string column] { get; set; }
  16. string Number { get; }
  17. }
  18. public class CoreTreeNode<TKey> : INotifyPropertyChanged, ICoreTreeNode
  19. {
  20. private CoreTreeNodes<TKey> _owner;
  21. public ObservableCollection<CoreTreeNode<TKey>> Children => new ObservableCollection<CoreTreeNode<TKey>>(_owner.GetChildrenOfParent(_id));
  22. object? ICoreTreeNode.ID
  23. {
  24. get => ID;
  25. set => ID = (TKey)value!;
  26. }
  27. private TKey _id;
  28. public TKey ID
  29. {
  30. get { return _id; }
  31. set
  32. {
  33. _id = value;
  34. RaisedOnPropertyChanged("ID");
  35. }
  36. }
  37. object? ICoreTreeNode.Parent
  38. {
  39. get => Parent;
  40. set => Parent = (TKey)value!;
  41. }
  42. private TKey _parent;
  43. public TKey Parent
  44. {
  45. get { return _parent; }
  46. set
  47. {
  48. _parent = value;
  49. RaisedOnPropertyChanged("Parent");
  50. }
  51. }
  52. private object? _image;
  53. public object? Image
  54. {
  55. get => _image;
  56. set
  57. {
  58. _image = value;
  59. RaisedOnPropertyChanged("Image");
  60. }
  61. }
  62. private CoreRow _row;
  63. public CoreRow Row
  64. {
  65. get => _row;
  66. set
  67. {
  68. _row = value;
  69. RaisedOnPropertyChanged("Row");
  70. RaisedOnPropertyChanged("Item[]");
  71. }
  72. }
  73. public object? this[string column]
  74. {
  75. get => Row[column];
  76. set
  77. {
  78. Row[column] = value;
  79. _owner.DoColumnChanged(this, column);
  80. }
  81. }
  82. public event PropertyChangedEventHandler? PropertyChanged;
  83. public void RaisedOnPropertyChanged(string propertyName)
  84. {
  85. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  86. }
  87. public CoreTreeNode(CoreTreeNodes<TKey> owner, CoreRow row)
  88. {
  89. _owner = owner;
  90. _row = row;
  91. }
  92. public CoreTreeNode(CoreTreeNodes<TKey> owner, TKey id, TKey parent, CoreRow row) : this(owner, row)
  93. {
  94. _id = id;
  95. _parent = parent;
  96. }
  97. public CoreTreeNode<TKey>? GetParent() => _owner[_parent];
  98. public int Index()
  99. {
  100. var parent = GetParent();
  101. return parent != null
  102. ? parent.Children.IndexOf(this) + 1
  103. : _owner.Nodes.IndexOf(this) + 1;
  104. }
  105. public void InvalidateData()
  106. {
  107. RaisedOnPropertyChanged("Row");
  108. RaisedOnPropertyChanged("Item[]");
  109. }
  110. public String Number
  111. {
  112. get
  113. {
  114. String result = Index().ToString();
  115. var parent = GetParent();
  116. while (parent != null)
  117. {
  118. int index = parent.Index();
  119. result = $"{index}.{result}";
  120. parent = parent.GetParent();
  121. }
  122. return result;
  123. }
  124. }
  125. public int Depth()
  126. {
  127. var result = 0;
  128. foreach (var child in Children)
  129. result = Math.Max(result, child.Depth());
  130. return 1 + result;
  131. }
  132. }
  133. public class CoreTreeNodes<TKey>
  134. {
  135. private List<CoreTreeNode<TKey>> _nodes;
  136. private Dictionary<TKey, CoreTreeNode<TKey>> _nodeMap;
  137. public TKey DefaultKey { get; set; }
  138. public ObservableCollection<CoreTreeNode<TKey>> Nodes { get; } = new ObservableCollection<CoreTreeNode<TKey>>();
  139. public CoreTreeNode<TKey>? this[TKey id] => _nodeMap.GetValueOrDefault(id);
  140. public CoreTreeNodes(TKey defaultKey)
  141. {
  142. _nodes = new List<CoreTreeNode<TKey>>();
  143. _nodeMap = new Dictionary<TKey, CoreTreeNode<TKey>>();
  144. DefaultKey = defaultKey;
  145. }
  146. public CoreTreeNode<TKey> Add(TKey id, TKey parent, CoreRow row)
  147. {
  148. var node = new CoreTreeNode<TKey>(this, id, parent, row);
  149. _nodes.Add(node);
  150. _nodeMap[id] = node;
  151. if(Equals(node.Parent, DefaultKey))
  152. {
  153. Nodes.Add(node);
  154. }
  155. return node;
  156. }
  157. public void Clear()
  158. {
  159. _nodes.Clear();
  160. _nodeMap.Clear();
  161. Nodes.Clear();
  162. }
  163. public CoreTreeNode<TKey> Find(TKey id) => _nodeMap.GetValueOrDefault(id);
  164. public CoreTreeNode<TKey>? Find(CoreRow row) => _nodes.FirstOrDefault(x => x.Row == row);
  165. /// <summary>
  166. /// Gets a given node and recursively all its children given by <paramref name="id"/>.
  167. /// </summary>
  168. /// <param name="id"></param>
  169. /// <returns></returns>
  170. public IEnumerable<CoreTreeNode<TKey>> GetChildren(TKey id)
  171. {
  172. if(!_nodeMap.TryGetValue(id, out var node))
  173. {
  174. yield break;
  175. }
  176. yield return node;
  177. var children = GetChildrenOfParent(id);
  178. foreach (var child in children)
  179. foreach (var item in GetChildren(child.ID))
  180. yield return item;
  181. }
  182. /// <summary>
  183. /// Get all the direct children of the parent given by <paramref name="id"/>.
  184. /// </summary>
  185. /// <param name="id"></param>
  186. /// <returns></returns>
  187. public IEnumerable<CoreTreeNode<TKey>> GetChildrenOfParent(TKey id)
  188. {
  189. return _nodes.Where(x => object.Equals(x.Parent, id) && !object.Equals(x.ID, id));
  190. }
  191. public void Load<T>(CoreTable table, Expression<Func<T, TKey>> id, Expression<Func<T, TKey>> parentid)
  192. {
  193. _nodes.Clear();
  194. foreach (var row in table.Rows)
  195. {
  196. var _id = row.Get(id);
  197. var _parent = row.Get(parentid);
  198. Add(_id, _parent, row);
  199. }
  200. }
  201. public delegate void ColumnChangedEventHandler(CoreTreeNode<TKey> node, string column);
  202. public event ColumnChangedEventHandler? ColumnChanged;
  203. internal void DoColumnChanged(CoreTreeNode<TKey> node, string column)
  204. {
  205. ColumnChanged?.Invoke(node, column);
  206. }
  207. public int Depth()
  208. {
  209. var result = 0;
  210. var roots = Nodes.Where(x => Equals(DefaultKey, x.Parent));
  211. foreach (var root in roots)
  212. result = Math.Max(result, root.Depth());
  213. return result;
  214. }
  215. }
  216. }