TemplateBuilder.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using System;
  2. using FastReport.Data;
  3. using FastReport.Table;
  4. namespace FastReport.AdvMatrix
  5. {
  6. internal static class TemplateBuilder
  7. {
  8. public static int EnumColumnDescriptors(HeaderDescriptor root, int columnIndex, int rowIndex, Action<HeaderDescriptor, int, int, bool> func)
  9. {
  10. foreach (HeaderDescriptor d in root.Items)
  11. {
  12. func(d, columnIndex, rowIndex, true);
  13. if (d.Items.Count > 0)
  14. {
  15. if (d.Stepped)
  16. columnIndex = EnumColumnDescriptors(d, columnIndex + 1, rowIndex, func);
  17. else
  18. columnIndex = EnumColumnDescriptors(d, columnIndex, rowIndex + 1, func);
  19. }
  20. columnIndex++;
  21. }
  22. return columnIndex - 1;
  23. }
  24. public static int EnumRowDescriptors(HeaderDescriptor root, int columnIndex, int rowIndex, Action<HeaderDescriptor, int, int, bool> func)
  25. {
  26. foreach (HeaderDescriptor d in root.Items)
  27. {
  28. func(d, columnIndex, rowIndex, false);
  29. if (d.Items.Count > 0)
  30. {
  31. if (d.Stepped)
  32. rowIndex = EnumRowDescriptors(d, columnIndex, rowIndex + 1, func);
  33. else
  34. rowIndex = EnumRowDescriptors(d, columnIndex + 1, rowIndex, func);
  35. }
  36. rowIndex++;
  37. }
  38. return rowIndex - 1;
  39. }
  40. private static void CopyFromResultTable(AdvMatrixObject matrix, TableResult resultTable)
  41. {
  42. matrix.ColumnCount = resultTable.ColumnCount;
  43. matrix.RowCount = resultTable.RowCount;
  44. matrix.CreateUniqueNames();
  45. for (int x = 0; x < matrix.Columns.Count; x++)
  46. {
  47. matrix.Columns[x].Assign(resultTable.Columns[x]);
  48. }
  49. for (int y = 0; y < matrix.Rows.Count; y++)
  50. {
  51. matrix.Rows[y].Assign(resultTable.Rows[y]);
  52. }
  53. for (int x = 0; x < matrix.Columns.Count; x++)
  54. {
  55. for (int y = 0; y < matrix.Rows.Count; y++)
  56. {
  57. TableCell cell = matrix[x, y];
  58. // call AssignAll with assignName parameter to preserve names of objects contained in a cell
  59. resultTable[x, y].Name = cell.Name;
  60. cell.AssignAll(resultTable[x, y], true);
  61. cell.SetFlags(Flags.CanEdit, true);
  62. }
  63. }
  64. }
  65. private static TableCell CreateHeaderCell(AdvMatrixObject matrix, HeaderDescriptor descr)
  66. {
  67. TableCell cell = new TableCell();
  68. cell.HorzAlign = HorzAlign.Center;
  69. cell.VertAlign = VertAlign.Center;
  70. ApplyStyle(matrix, cell, "Header");
  71. if (descr != null)
  72. {
  73. if (descr.IsGroup)
  74. cell.Text = descr.Expression;
  75. else
  76. cell.Text = descr.DisplayText;
  77. }
  78. return cell;
  79. }
  80. private static TableCell CreateCell(AdvMatrixObject matrix)
  81. {
  82. TableCell cell = new TableCell();
  83. cell.HorzAlign = HorzAlign.Right;
  84. cell.VertAlign = VertAlign.Center;
  85. ApplyStyle(matrix, cell, "Body");
  86. return cell;
  87. }
  88. private static void ApplyStyle(AdvMatrixObject matrix, TableCell cell, string styleName)
  89. {
  90. Style style = null;
  91. int styleIndex = matrix.StyleSheet.IndexOf(matrix.Style);
  92. if (styleIndex != -1)
  93. {
  94. StyleCollection styles = matrix.StyleSheet[styleIndex];
  95. style = styles[styles.IndexOf(styleName)];
  96. }
  97. if (style != null)
  98. cell.ApplyStyle(style);
  99. }
  100. public static void UpdateStyle(AdvMatrixObject matrix)
  101. {
  102. int cornerWidth = matrix.Data.Rows.Size;
  103. int cornerHeight = matrix.Data.Columns.Size;
  104. for (int y = 0; y < matrix.RowCount; y++)
  105. {
  106. for (int x = 0; x < matrix.ColumnCount; x++)
  107. {
  108. string style = x < cornerWidth || y < cornerHeight ? "Header" : "Body";
  109. ApplyStyle(matrix, matrix[x, y], style);
  110. }
  111. }
  112. }
  113. public static void UpdateDescriptors(AdvMatrixObject matrix)
  114. {
  115. int cornerWidth = matrix.Data.Rows.Size;
  116. int cornerHeight = matrix.Data.Columns.Size;
  117. // update header descriptors
  118. Action<HeaderDescriptor, int, int, bool> func = (d, columnIndex, rowIndex, isColumn) =>
  119. {
  120. d.Matrix = matrix;
  121. d.IsColumn = isColumn;
  122. d.TemplateColumn = matrix.Columns[columnIndex];
  123. d.TemplateRow = matrix.Rows[rowIndex];
  124. d.TemplateCell = matrix[columnIndex, rowIndex];
  125. if (d.IsGroup)
  126. d.TemplateCell.AllowExpressions = false;
  127. if (!d.IsGroup && String.IsNullOrEmpty(d.DisplayText))
  128. d.DisplayText = d.TemplateCell.Text;
  129. };
  130. EnumColumnDescriptors(matrix.Data.Columns.Descriptor, cornerWidth, 0, func);
  131. EnumRowDescriptors(matrix.Data.Rows.Descriptor, 0, cornerHeight, func);
  132. // create cell descriptors
  133. matrix.Data.CellData.InitDescriptors();
  134. }
  135. public static void BuildTemplate(AdvMatrixObject matrix)
  136. {
  137. TableResult resultTable = new TableResult();
  138. int cornerWidth = matrix.Data.Rows.Size;
  139. int cornerHeight = matrix.Data.Columns.Size;
  140. TableColumn[] cornerColumns = new TableColumn[cornerWidth];
  141. TableRow[] cornerRows = new TableRow[cornerHeight];
  142. Action<HeaderDescriptor, int, int, bool> func = (d, columnIndex, rowIndex, isColumn) =>
  143. {
  144. // create resultTable columns and rows. Assign properties from existing template columns/rows
  145. while (columnIndex >= resultTable.Columns.Count)
  146. resultTable.Columns.Add(new TableColumn());
  147. while (rowIndex >= resultTable.Rows.Count)
  148. resultTable.Rows.Add(new TableRow());
  149. // the same assignment may occur several times, but it's a cheap operation so it's ok
  150. if (d.TemplateColumn != null)
  151. {
  152. resultTable.Columns[columnIndex].Assign(d.TemplateColumn);
  153. if (columnIndex < cornerWidth)
  154. cornerColumns[columnIndex] = d.TemplateColumn;
  155. }
  156. if (d.TemplateRow != null)
  157. {
  158. resultTable.Rows[rowIndex].Assign(d.TemplateRow);
  159. if (rowIndex < cornerHeight)
  160. cornerRows[rowIndex] = d.TemplateRow;
  161. }
  162. };
  163. EnumColumnDescriptors(matrix.Data.Columns.Descriptor, cornerWidth, 0, func);
  164. EnumRowDescriptors(matrix.Data.Rows.Descriptor, 0, cornerHeight, func);
  165. // header cells
  166. Action<HeaderDescriptor, int, int, bool> func1 = (d, columnIndex, rowIndex, isColumn) =>
  167. {
  168. TableCellData resultCell = resultTable.GetCellData(columnIndex, rowIndex);
  169. if (d.TemplateCell != null)
  170. resultCell.RunTimeAssign(d.TemplateCell, true);
  171. else
  172. resultCell.RunTimeAssign(CreateHeaderCell(matrix, d), true);
  173. if (d.IsGroup)
  174. resultCell.Text = d.Expression;
  175. if (!d.IsGroup && !String.IsNullOrEmpty(d.DisplayText))
  176. resultCell.Text = d.DisplayText;
  177. if (isColumn)
  178. {
  179. resultCell.ColSpan = d.Span;
  180. if (d.Items.Count == 0 || d.Stepped)
  181. resultCell.RowSpan = cornerHeight - rowIndex;
  182. }
  183. else
  184. {
  185. resultCell.RowSpan = d.Span;
  186. if (d.Items.Count == 0 || d.Stepped)
  187. resultCell.ColSpan = cornerWidth - columnIndex;
  188. }
  189. };
  190. EnumColumnDescriptors(matrix.Data.Columns.Descriptor, cornerWidth, 0, func1);
  191. EnumRowDescriptors(matrix.Data.Rows.Descriptor, 0, cornerHeight, func1);
  192. // corner
  193. int left, top;
  194. for (left = 0; left < cornerWidth; left++)
  195. {
  196. for (top = 0; top < cornerHeight; top++)
  197. {
  198. TableCellData resultCell = resultTable.GetCellData(left, top);
  199. if (cornerColumns[left] != null && cornerRows[top] != null)
  200. {
  201. TableCell templateCell = matrix[cornerColumns[left].Index, cornerRows[top].Index];
  202. resultCell.RunTimeAssign(templateCell, true);
  203. // do not allow spans to go outside corner area
  204. resultCell.ColSpan = Math.Min(templateCell.ColSpan, cornerWidth - left);
  205. resultCell.RowSpan = Math.Min(templateCell.RowSpan, cornerHeight - top);
  206. }
  207. else
  208. {
  209. resultCell.RunTimeAssign(CreateHeaderCell(matrix, null), true);
  210. }
  211. }
  212. }
  213. // cells
  214. left = cornerWidth;
  215. foreach (HeaderDescriptor columnItem in matrix.Data.Columns.Descriptor.TerminalItems)
  216. {
  217. top = cornerHeight;
  218. foreach (HeaderDescriptor rowItem in matrix.Data.Rows.Descriptor.TerminalItems)
  219. {
  220. TableCellData resultCell = resultTable.GetCellData(left, top);
  221. if (columnItem.TemplateColumn != null && rowItem.TemplateRow != null)
  222. {
  223. TableCell templateCell = matrix[columnItem.TemplateColumn.Index, rowItem.TemplateRow.Index];
  224. resultCell.RunTimeAssign(templateCell, true);
  225. resultCell.ColSpan = templateCell.ColSpan;
  226. resultCell.RowSpan = templateCell.RowSpan;
  227. }
  228. else
  229. {
  230. resultCell.RunTimeAssign(CreateCell(matrix), true);
  231. }
  232. top++;
  233. }
  234. left++;
  235. }
  236. // copy resultTable to matrix
  237. CopyFromResultTable(matrix, resultTable);
  238. UpdateDescriptors(matrix);
  239. resultTable.Dispose();
  240. }
  241. }
  242. }