HeaderData.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace FastReport.AdvMatrix
  6. {
  7. internal class HeaderData : IEnumerable<HeaderData>
  8. {
  9. public HeaderDescriptor Descriptor { get; private set; }
  10. public HeaderData Parent { get; private set; }
  11. public List<HeaderDataList> Items { get; }
  12. public object Value { get; set; }
  13. public int Index { get; set; }
  14. public int DataRowNo { get; set; }
  15. public int RowNo { get; private set; }
  16. internal HeaderDataList ParentDataList
  17. {
  18. get
  19. {
  20. if (Parent == null)
  21. return null;
  22. foreach (HeaderDataList dl in Parent.Items)
  23. {
  24. if (dl.Descriptor == Descriptor && dl.IndexOf(this) != -1)
  25. return dl;
  26. }
  27. return null;
  28. }
  29. }
  30. internal int Span
  31. {
  32. get
  33. {
  34. if (Descriptor != null && Descriptor.Stepped)
  35. return 1;
  36. int count = TerminalItems.Count;
  37. return count > 0 ? count : 1;
  38. }
  39. }
  40. internal List<HeaderDataList> AllItems
  41. {
  42. get
  43. {
  44. List<HeaderDataList> list = new List<HeaderDataList>();
  45. GetAllItems(this, list);
  46. return list;
  47. }
  48. }
  49. internal List<HeaderData> TerminalItems
  50. {
  51. get
  52. {
  53. List<HeaderData> list = new List<HeaderData>();
  54. GetTerminalItems(this, list);
  55. return list;
  56. }
  57. }
  58. // returns all terminal items including invisible ones. Needed for TopN processing
  59. internal List<HeaderData> AllTerminalItems
  60. {
  61. get
  62. {
  63. List<HeaderData> list = new List<HeaderData>();
  64. GetAllTerminalItems(this, list);
  65. return list;
  66. }
  67. }
  68. internal object[] Values
  69. {
  70. get
  71. {
  72. int count = 0;
  73. HeaderData item = this;
  74. while (item.Parent != null)
  75. {
  76. count++;
  77. item = item.Parent;
  78. }
  79. object[] values = new object[count];
  80. item = this;
  81. int index = count - 1;
  82. while (item.Parent != null)
  83. {
  84. values[index] = item.Value;
  85. index--;
  86. item = item.Parent;
  87. }
  88. return values;
  89. }
  90. }
  91. internal int ItemCount
  92. {
  93. get
  94. {
  95. return this.Count();
  96. }
  97. }
  98. private void GetAllItems(HeaderData root, List<HeaderDataList> list)
  99. {
  100. foreach (HeaderDataList dl in root.Items)
  101. {
  102. list.Add(dl);
  103. foreach (HeaderData d in dl)
  104. {
  105. GetAllItems(d, list);
  106. }
  107. }
  108. }
  109. private void GetTerminalItems(HeaderData root, List<HeaderData> list)
  110. {
  111. if (root.Items.Count == 0 || (root.Descriptor != null && root.Descriptor.Stepped))
  112. list.Add(root);
  113. foreach (HeaderData d in root)
  114. {
  115. GetTerminalItems(d, list);
  116. }
  117. }
  118. private void GetAllTerminalItems(HeaderData root, List<HeaderData> list)
  119. {
  120. if (root.Items.Count == 0 || (root.Descriptor != null && root.Descriptor.Stepped))
  121. list.Add(root);
  122. foreach (HeaderDataList dl in root.Items)
  123. {
  124. foreach (HeaderData d in dl)
  125. {
  126. GetAllTerminalItems(d, list);
  127. }
  128. }
  129. }
  130. private HeaderDataList Find(HeaderDescriptor descr)
  131. {
  132. if (Items.Count == 0)
  133. {
  134. // Create data lists as they appear in the descriptor item list.
  135. // It fixes the problem when the descriptor's Filter property is set and some total items may appear before data
  136. foreach (HeaderDescriptor d in descr.Parent.Items)
  137. {
  138. Items.Add(new HeaderDataList(this, d));
  139. }
  140. }
  141. foreach (HeaderDataList dataList in Items)
  142. {
  143. if (dataList.Descriptor == descr)
  144. return dataList;
  145. }
  146. // this should never happen
  147. return null;
  148. }
  149. public HeaderData Add(HeaderDescriptor descr)
  150. {
  151. HeaderDataList dataList = Find(descr);
  152. object value = descr.CalcValue();
  153. int index = dataList.Find(value);
  154. if (index >= 0)
  155. {
  156. return dataList[index];
  157. }
  158. else
  159. {
  160. HeaderData data = new HeaderData(this, descr) { Value = value };
  161. dataList.Insert(~index, data);
  162. return data;
  163. }
  164. }
  165. public void Clear()
  166. {
  167. Items.Clear();
  168. }
  169. // this iterator is needed to return data from all datalists as a single list
  170. // it skips invisible items and sorts data if "sort by value" is on
  171. public IEnumerator<HeaderData> GetEnumerator()
  172. {
  173. foreach (HeaderDataList dl in Items)
  174. {
  175. if (!dl.Visible)
  176. continue;
  177. List<HeaderData> list = dl.GetSortedList();
  178. for (int i = 0; i < list.Count; i++)
  179. {
  180. HeaderData d = list[i];
  181. d.RowNo = i + 1;
  182. yield return d;
  183. }
  184. }
  185. }
  186. IEnumerator IEnumerable.GetEnumerator()
  187. {
  188. return GetEnumerator();
  189. }
  190. public HeaderData(HeaderData parent, HeaderDescriptor descr)
  191. {
  192. Parent = parent;
  193. Descriptor = descr;
  194. Items = new List<HeaderDataList>();
  195. }
  196. }
  197. }