FastReport
294 строки · 9.9 Кб
1using System;2using System.Collections.Generic;3using System.Text;4using System.Collections;5using FastReport.Utils;6
7namespace FastReport.Matrix8{
9/// <summary>10/// Represents a collection of matrix header descriptors used in the <see cref="MatrixObject"/>.11/// </summary>12public class MatrixHeader : CollectionBase, IFRSerializable13{14private MatrixHeaderItem rootItem;15private int nextIndex;16private string name;17
18/// <summary>19/// Gets or sets the element at the specified index.20/// </summary>21/// <param name="index">Index of an element.</param>22/// <returns>The element at the specified index.</returns>23public MatrixHeaderDescriptor this[int index]24{25get { return List[index] as MatrixHeaderDescriptor; }26set { List[index] = value; }27}28
29internal MatrixHeaderItem RootItem30{31get { return rootItem; }32}33
34internal string Name35{36get { return name; }37set { name = value; }38}39
40/// <summary>41/// Adds the specified descriptors to the end of this collection.42/// </summary>43/// <param name="range">Array of descriptors to add.</param>44public void AddRange(MatrixHeaderDescriptor[] range)45{46foreach (MatrixHeaderDescriptor s in range)47{48Add(s);49}50}51
52/// <summary>53/// Adds a descriptor to the end of this collection.54/// </summary>55/// <param name="value">Descriptor to add.</param>56/// <returns>Index of the added descriptor.</returns>57public int Add(MatrixHeaderDescriptor value)58{59return List.Add(value);60}61
62/// <summary>63/// Inserts a descriptor into this collection at the specified index.64/// </summary>65/// <param name="index">The zero-based index at which value should be inserted.</param>66/// <param name="value">The descriptor to insert.</param>67public void Insert(int index, MatrixHeaderDescriptor value)68{69List.Insert(index, value);70}71
72/// <summary>73/// Removes the specified descriptor from the collection.74/// </summary>75/// <param name="value">Descriptor to remove.</param>76public void Remove(MatrixHeaderDescriptor value)77{78int i = IndexOf(value);79if (i != -1)80List.RemoveAt(i);81}82
83/// <summary>84/// Returns the zero-based index of the first occurrence of a descriptor.85/// </summary>86/// <param name="value">The descriptor to locate in the collection.</param>87/// <returns>The zero-based index of the first occurrence of descriptor within88/// the entire collection, if found; otherwise, -1.</returns>89public int IndexOf(MatrixHeaderDescriptor value)90{91return List.IndexOf(value);92}93
94/// <summary>95/// Determines whether a descriptor is in the collection.96/// </summary>97/// <param name="value">The descriptor to locate in the collection.</param>98/// <returns><b>true</b> if descriptor is found in the collection; otherwise, <b>false</b>.</returns>99public bool Contains(MatrixHeaderDescriptor value)100{101return List.Contains(value);102}103
104/// <summary>105/// Copies the elements of this collection to a new array.106/// </summary>107/// <returns>An array containing copies of this collection elements. </returns>108public MatrixHeaderDescriptor[] ToArray()109{110MatrixHeaderDescriptor[] result = new MatrixHeaderDescriptor[Count];111for (int i = 0; i < Count; i++)112{113result[i] = this[i];114}115return result;116}117
118/// <summary>119/// Gets the list of indices of terminal items of this header.120/// </summary>121/// <returns>The list of indices.</returns>122public int[] GetTerminalIndices()123{124return GetTerminalIndices(rootItem);125}126
127/// <summary>128/// Gets the list of indices of terminal items of the header with specified address.129/// </summary>130/// <param name="address">The address of a header.</param>131/// <returns>The list of indices.</returns>132public int[] GetTerminalIndices(object[] address)133{134MatrixHeaderItem rootItem = Find(address, false, 0);135return GetTerminalIndices(rootItem);136}137
138private int[] GetTerminalIndices(MatrixHeaderItem rootItem)139{140List<MatrixHeaderItem> terminalItems = rootItem.GetTerminalItems();141int[] result = new int[terminalItems.Count];142for (int i = 0; i < result.Length; i++)143result[i] = terminalItems[i].Index;144return result;145}146
147/// <summary>148/// Removes a header item with the address specified.149/// </summary>150/// <param name="address">The address of a header.</param>151public void RemoveItem(object[] address)152{153MatrixHeaderItem item = Find(address, false, 0);154if (item != null)155item.Parent.Items.Remove(item);156}157
158/// <summary>159/// Gets an index of header with the address specified.160/// </summary>161/// <param name="address">The address of a header.</param>162/// <returns>The index of header.</returns>163public int Find(object[] address)164{165MatrixHeaderItem item = Find(address, false, 0);166if (item != null)167return item.Index;168return -1;169}170
171/// <summary>172/// Gets an index of header with the address specified. If there is no such header item, it will be created.173/// </summary>174/// <param name="address">The address of a header.</param>175/// <returns>The index of header.</returns>176public int FindOrCreate(object[] address)177{178MatrixHeaderItem item = Find(address, true, 0);179if (item != null)180return item.Index;181return -1;182}183
184internal MatrixHeaderItem Find(object[] address, bool create, int dataRowNo)185{186// Note that the top header itself does not contain a value.187// It is used as a list of first-level headers only.188MatrixHeaderItem rootItem = RootItem;189
190for (int i = 0; i < address.Length; i++)191{192int index = rootItem.Find(address[i], this[i].Sort);193
194if (index >= 0)195rootItem = rootItem.Items[index];196else if (create)197{198// create new item if necessary.199MatrixHeaderItem newItem = new MatrixHeaderItem(rootItem);200newItem.Value = address[i];201newItem.TemplateColumn = this[i].TemplateColumn;202newItem.TemplateRow = this[i].TemplateRow;203newItem.TemplateCell = this[i].TemplateCell;204newItem.DataRowNo = dataRowNo;205newItem.PageBreak = this[i].PageBreak;206
207// index is used as a cell address in a matrix208if (i == address.Length - 1)209{210// create index for bottom-level header211newItem.Index = nextIndex;212nextIndex++;213}214
215rootItem.Items.Insert(~index, newItem);216rootItem = newItem;217}218else219return null;220}221
222return rootItem;223}224
225
226private void AddTotalItems(MatrixHeaderItem rootItem, int descriptorIndex, bool isTemplate)227{228if (descriptorIndex >= Count)229return;230
231foreach (MatrixHeaderItem item in rootItem.Items)232{233AddTotalItems(item, descriptorIndex + 1, isTemplate);234}235
236if (this[descriptorIndex].Totals &&237(isTemplate || !this[descriptorIndex].SuppressTotals || rootItem.Items.Count > 1))238{239MatrixHeaderItem totalItem = new MatrixHeaderItem(rootItem);240totalItem.IsTotal = true;241totalItem.Value = rootItem.Value;242totalItem.DataRowNo = rootItem.DataRowNo;243totalItem.TemplateColumn = this[descriptorIndex].TemplateTotalColumn;244totalItem.TemplateRow = this[descriptorIndex].TemplateTotalRow;245totalItem.TemplateCell = this[descriptorIndex].TemplateTotalCell;246totalItem.Index = nextIndex;247nextIndex++;248
249if (this[descriptorIndex].TotalsFirst && !isTemplate)250rootItem.Items.Insert(0, totalItem);251else252rootItem.Items.Add(totalItem);253}254}255
256internal void AddTotalItems(bool isTemplate)257{258AddTotalItems(RootItem, 0, isTemplate);259}260
261internal void Reset()262{263RootItem.Clear();264nextIndex = 0;265}266
267/// <inheritdoc/>268public void Serialize(FRWriter writer)269{270writer.ItemName = Name;271foreach (MatrixHeaderDescriptor d in this)272{273writer.Write(d);274}275}276
277/// <inheritdoc/>278public void Deserialize(FRReader reader)279{280Clear();281while (reader.NextItem())282{283MatrixHeaderDescriptor d = new MatrixHeaderDescriptor();284reader.Read(d);285Add(d);286}287}288
289internal MatrixHeader()290{291rootItem = new MatrixHeaderItem(null);292}293}294}
295