using System; using System.Collections.Generic; using System.Text; using System.Collections; using FastReport.Utils; namespace FastReport.Matrix { /// /// Represents a collection of matrix header descriptors used in the . /// public class MatrixHeader : CollectionBase, IFRSerializable { private MatrixHeaderItem rootItem; private int nextIndex; private string name; /// /// Gets or sets the element at the specified index. /// /// Index of an element. /// The element at the specified index. public MatrixHeaderDescriptor this[int index] { get { return List[index] as MatrixHeaderDescriptor; } set { List[index] = value; } } internal MatrixHeaderItem RootItem { get { return rootItem; } } internal string Name { get { return name; } set { name = value; } } /// /// Adds the specified descriptors to the end of this collection. /// /// Array of descriptors to add. public void AddRange(MatrixHeaderDescriptor[] range) { foreach (MatrixHeaderDescriptor s in range) { Add(s); } } /// /// Adds a descriptor to the end of this collection. /// /// Descriptor to add. /// Index of the added descriptor. public int Add(MatrixHeaderDescriptor value) { return List.Add(value); } /// /// Inserts a descriptor into this collection at the specified index. /// /// The zero-based index at which value should be inserted. /// The descriptor to insert. public void Insert(int index, MatrixHeaderDescriptor value) { List.Insert(index, value); } /// /// Removes the specified descriptor from the collection. /// /// Descriptor to remove. public void Remove(MatrixHeaderDescriptor value) { int i = IndexOf(value); if (i != -1) List.RemoveAt(i); } /// /// Returns the zero-based index of the first occurrence of a descriptor. /// /// The descriptor to locate in the collection. /// The zero-based index of the first occurrence of descriptor within /// the entire collection, if found; otherwise, -1. public int IndexOf(MatrixHeaderDescriptor value) { return List.IndexOf(value); } /// /// Determines whether a descriptor is in the collection. /// /// The descriptor to locate in the collection. /// true if descriptor is found in the collection; otherwise, false. public bool Contains(MatrixHeaderDescriptor value) { return List.Contains(value); } /// /// Copies the elements of this collection to a new array. /// /// An array containing copies of this collection elements. public MatrixHeaderDescriptor[] ToArray() { MatrixHeaderDescriptor[] result = new MatrixHeaderDescriptor[Count]; for (int i = 0; i < Count; i++) { result[i] = this[i]; } return result; } /// /// Gets the list of indices of terminal items of this header. /// /// The list of indices. public int[] GetTerminalIndices() { return GetTerminalIndices(rootItem); } /// /// Gets the list of indices of terminal items of the header with specified address. /// /// The address of a header. /// The list of indices. public int[] GetTerminalIndices(object[] address) { MatrixHeaderItem rootItem = Find(address, false, 0); return GetTerminalIndices(rootItem); } private int[] GetTerminalIndices(MatrixHeaderItem rootItem) { List terminalItems = rootItem.GetTerminalItems(); int[] result = new int[terminalItems.Count]; for (int i = 0; i < result.Length; i++) result[i] = terminalItems[i].Index; return result; } /// /// Removes a header item with the address specified. /// /// The address of a header. public void RemoveItem(object[] address) { MatrixHeaderItem item = Find(address, false, 0); if (item != null) item.Parent.Items.Remove(item); } /// /// Gets an index of header with the address specified. /// /// The address of a header. /// The index of header. public int Find(object[] address) { MatrixHeaderItem item = Find(address, false, 0); if (item != null) return item.Index; return -1; } /// /// Gets an index of header with the address specified. If there is no such header item, it will be created. /// /// The address of a header. /// The index of header. public int FindOrCreate(object[] address) { MatrixHeaderItem item = Find(address, true, 0); if (item != null) return item.Index; return -1; } internal MatrixHeaderItem Find(object[] address, bool create, int dataRowNo) { // Note that the top header itself does not contain a value. // It is used as a list of first-level headers only. MatrixHeaderItem rootItem = RootItem; for (int i = 0; i < address.Length; i++) { int index = rootItem.Find(address[i], this[i].Sort); if (index >= 0) rootItem = rootItem.Items[index]; else if (create) { // create new item if necessary. MatrixHeaderItem newItem = new MatrixHeaderItem(rootItem); newItem.Value = address[i]; newItem.TemplateColumn = this[i].TemplateColumn; newItem.TemplateRow = this[i].TemplateRow; newItem.TemplateCell = this[i].TemplateCell; newItem.DataRowNo = dataRowNo; newItem.PageBreak = this[i].PageBreak; // index is used as a cell address in a matrix if (i == address.Length - 1) { // create index for bottom-level header newItem.Index = nextIndex; nextIndex++; } rootItem.Items.Insert(~index, newItem); rootItem = newItem; } else return null; } return rootItem; } private void AddTotalItems(MatrixHeaderItem rootItem, int descriptorIndex, bool isTemplate) { if (descriptorIndex >= Count) return; foreach (MatrixHeaderItem item in rootItem.Items) { AddTotalItems(item, descriptorIndex + 1, isTemplate); } if (this[descriptorIndex].Totals && (isTemplate || !this[descriptorIndex].SuppressTotals || rootItem.Items.Count > 1)) { MatrixHeaderItem totalItem = new MatrixHeaderItem(rootItem); totalItem.IsTotal = true; totalItem.Value = rootItem.Value; totalItem.DataRowNo = rootItem.DataRowNo; totalItem.TemplateColumn = this[descriptorIndex].TemplateTotalColumn; totalItem.TemplateRow = this[descriptorIndex].TemplateTotalRow; totalItem.TemplateCell = this[descriptorIndex].TemplateTotalCell; totalItem.Index = nextIndex; nextIndex++; if (this[descriptorIndex].TotalsFirst && !isTemplate) rootItem.Items.Insert(0, totalItem); else rootItem.Items.Add(totalItem); } } internal void AddTotalItems(bool isTemplate) { AddTotalItems(RootItem, 0, isTemplate); } internal void Reset() { RootItem.Clear(); nextIndex = 0; } /// public void Serialize(FRWriter writer) { writer.ItemName = Name; foreach (MatrixHeaderDescriptor d in this) { writer.Write(d); } } /// public void Deserialize(FRReader reader) { Clear(); while (reader.NextItem()) { MatrixHeaderDescriptor d = new MatrixHeaderDescriptor(); reader.Read(d); Add(d); } } internal MatrixHeader() { rootItem = new MatrixHeaderItem(null); } } }