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);
}
}
}