MatrixCells.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Collections;
  5. using FastReport.Utils;
  6. namespace FastReport.Matrix
  7. {
  8. /// <summary>
  9. /// Represents a collection of matrix data descriptors used in the <see cref="MatrixObject"/>.
  10. /// </summary>
  11. public class MatrixCells : CollectionBase, IFRSerializable
  12. {
  13. private List<ArrayList>[] rows;
  14. private string name;
  15. /// <summary>
  16. /// Gets or sets the element at the specified index.
  17. /// </summary>
  18. /// <param name="index">Index of an element.</param>
  19. /// <returns>The element at the specified index.</returns>
  20. public MatrixCellDescriptor this[int index]
  21. {
  22. get { return List[index] as MatrixCellDescriptor; }
  23. set { List[index] = value; }
  24. }
  25. internal string Name
  26. {
  27. get { return name; }
  28. set { name = value; }
  29. }
  30. internal bool IsEmpty
  31. {
  32. get { return rows == null; }
  33. }
  34. /// <summary>
  35. /// Adds the specified descriptors to the end of this collection.
  36. /// </summary>
  37. /// <param name="range">Array of descriptors to add.</param>
  38. public void AddRange(MatrixCellDescriptor[] range)
  39. {
  40. foreach (MatrixCellDescriptor s in range)
  41. {
  42. Add(s);
  43. }
  44. }
  45. /// <summary>
  46. /// Adds a descriptor to the end of this collection.
  47. /// </summary>
  48. /// <param name="value">Descriptor to add.</param>
  49. /// <returns>Index of the added descriptor.</returns>
  50. public int Add(MatrixCellDescriptor value)
  51. {
  52. return List.Add(value);
  53. }
  54. /// <summary>
  55. /// Inserts a descriptor into this collection at the specified index.
  56. /// </summary>
  57. /// <param name="index">The zero-based index at which value should be inserted.</param>
  58. /// <param name="value">The descriptor to insert.</param>
  59. public void Insert(int index, MatrixCellDescriptor value)
  60. {
  61. List.Insert(index, value);
  62. }
  63. /// <summary>
  64. /// Removes the specified descriptor from the collection.
  65. /// </summary>
  66. /// <param name="value">Descriptor to remove.</param>
  67. public void Remove(MatrixCellDescriptor value)
  68. {
  69. int i = IndexOf(value);
  70. if (i != -1)
  71. List.RemoveAt(i);
  72. }
  73. /// <summary>
  74. /// Returns the zero-based index of the first occurrence of a descriptor.
  75. /// </summary>
  76. /// <param name="value">The descriptor to locate in the collection.</param>
  77. /// <returns>The zero-based index of the first occurrence of descriptor within
  78. /// the entire collection, if found; otherwise, -1.</returns>
  79. public int IndexOf(MatrixCellDescriptor value)
  80. {
  81. return List.IndexOf(value);
  82. }
  83. /// <summary>
  84. /// Determines whether a descriptor is in the collection.
  85. /// </summary>
  86. /// <param name="value">The descriptor to locate in the collection.</param>
  87. /// <returns><b>true</b> if descriptor is found in the collection; otherwise, <b>false</b>.</returns>
  88. public bool Contains(MatrixCellDescriptor value)
  89. {
  90. return List.Contains(value);
  91. }
  92. /// <summary>
  93. /// Copies the elements of this collection to a new array.
  94. /// </summary>
  95. /// <returns>An array containing copies of this collection elements. </returns>
  96. public MatrixCellDescriptor[] ToArray()
  97. {
  98. MatrixCellDescriptor[] result = new MatrixCellDescriptor[Count];
  99. for (int i = 0; i < Count; i++)
  100. {
  101. result[i] = this[i];
  102. }
  103. return result;
  104. }
  105. private void CheckIndices(int columnIndex, int rowIndex, List<ArrayList> rows)
  106. {
  107. // append rows if row index is out of bounds
  108. if (rowIndex >= rows.Count)
  109. {
  110. int delta = rowIndex - rows.Count + 1;
  111. for (int i = 0; i < delta; i++)
  112. {
  113. rows.Add(new ArrayList());
  114. }
  115. }
  116. ArrayList row = rows[rowIndex];
  117. if (columnIndex >= row.Count)
  118. {
  119. int delta = columnIndex - row.Count + 1;
  120. for (int i = 0; i < delta; i++)
  121. {
  122. row.Add(null);
  123. }
  124. }
  125. }
  126. private void AddValue(int columnIndex, int rowIndex, object value, List<ArrayList> rows)
  127. {
  128. // do not put null values to the matrix!
  129. if (value == null || value == DBNull.Value)
  130. return;
  131. CheckIndices(columnIndex, rowIndex, rows);
  132. ArrayList row = rows[rowIndex];
  133. object oldValue = row[columnIndex];
  134. if (oldValue == null)
  135. {
  136. // initial state - the cell is empty. Put the value into the cell
  137. row[columnIndex] = value;
  138. }
  139. else if (oldValue is ArrayList)
  140. {
  141. // cell contains a list of values. Add a new value to the list
  142. (oldValue as ArrayList).Add(value);
  143. }
  144. else
  145. {
  146. // cell contains single value, we need to create a list of values
  147. ArrayList valuesList = new ArrayList();
  148. valuesList.Add(oldValue);
  149. valuesList.Add(value);
  150. row[columnIndex] = valuesList;
  151. }
  152. }
  153. private void SetValue(int columnIndex, int rowIndex, object value, List<ArrayList> rows)
  154. {
  155. CheckIndices(columnIndex, rowIndex, rows);
  156. rows[rowIndex][columnIndex] = value;
  157. }
  158. internal void AddValue(int columnIndex, int rowIndex, object[] value)
  159. {
  160. if (value == null)
  161. throw new ArgumentNullException("value");
  162. if (value.Length != Count)
  163. throw new MatrixValueException(Count);
  164. if (rows == null)
  165. rows = new List<ArrayList>[Count];
  166. for (int i = 0; i < Count; i++)
  167. {
  168. if (rows[i] == null)
  169. rows[i] = new List<ArrayList>();
  170. AddValue(columnIndex, rowIndex, value[i], rows[i]);
  171. }
  172. }
  173. // return value(s) contained in a cell.
  174. // in case of empty cell, return null.
  175. internal object GetValue(int columnIndex, int rowIndex, int cellIndex)
  176. {
  177. if (rows == null ||
  178. cellIndex >= rows.Length ||
  179. rowIndex >= rows[cellIndex].Count ||
  180. columnIndex >= rows[cellIndex][rowIndex].Count)
  181. return null;
  182. // cell may contain either null, single value, or ArrayList containing several values.
  183. object value = rows[cellIndex][rowIndex][columnIndex];
  184. return value;
  185. }
  186. // return value(s) contained in a cell as ArrayList, even if there is only one value.
  187. // in case of empty cell, return null.
  188. internal ArrayList GetValues(int columnIndex, int rowIndex, int cellIndex)
  189. {
  190. object value = GetValue(columnIndex, rowIndex, cellIndex);
  191. if (value == null)
  192. return null;
  193. if (value is ArrayList)
  194. return (ArrayList)value;
  195. ArrayList list = new ArrayList();
  196. list.Add(value);
  197. return list;
  198. }
  199. // replaces the list of values in a cell by the single value
  200. internal void SetValues(int columnIndex, int rowIndex, object[] cellValues)
  201. {
  202. // do not put all nulls into the matrix
  203. bool allNulls = true;
  204. for (int i = 0; i < Count; i++)
  205. {
  206. if (cellValues[i] != null)
  207. allNulls = false;
  208. }
  209. if (!allNulls)
  210. {
  211. if (rows == null)
  212. rows = new List<ArrayList>[Count];
  213. for (int i = 0; i < Count; i++)
  214. {
  215. if (rows[i] == null)
  216. rows[i] = new List<ArrayList>();
  217. SetValue(columnIndex, rowIndex, cellValues[i], rows[i]);
  218. }
  219. }
  220. }
  221. internal void Reset()
  222. {
  223. rows = null;
  224. }
  225. /// <inheritdoc/>
  226. public void Serialize(FRWriter writer)
  227. {
  228. writer.ItemName = Name;
  229. foreach (MatrixCellDescriptor d in this)
  230. {
  231. writer.Write(d);
  232. }
  233. }
  234. /// <inheritdoc/>
  235. public void Deserialize(FRReader reader)
  236. {
  237. Clear();
  238. while (reader.NextItem())
  239. {
  240. MatrixCellDescriptor d = new MatrixCellDescriptor();
  241. reader.Read(d);
  242. Add(d);
  243. }
  244. }
  245. internal MatrixCells()
  246. {
  247. }
  248. }
  249. }