using System; using System.Collections.Generic; using FastReport.Table; using FastReport.Utils; namespace FastReport.AdvMatrix { /// /// The descriptor that is used to describe one element of the matrix header. /// /// /// The class is used to define one header element of the matrix /// (either the column element or row element). The key properties are /// and . /// The collection of descriptors used to represent the matrix header is stored /// in the AdvMatrixObject.Data.Columns and AdvMatrixObject.Data.Rows properties. /// public class HeaderDescriptor : IFRSerializable { /// /// Gets or sets the name of this descriptor. /// /// /// This property is used by the TopN engine to find linked items such as TopNTotal, Others, OtherTotal. /// All others descriptors have empty name. /// public string Name { get; set; } /// /// Gets the parent descriptor of this descriptor. /// public HeaderDescriptor Parent { get; private set; } /// /// Gets child items of this descriptor. /// public List Items { get; } /// /// Gets or sets an expression which value will be used to fill the matrix. /// /// /// Expression may be any valid expression. Usually it's a data column: /// [DataSource.Column]. /// public string Expression { get; set; } /// /// Gets or sets a text which will be displayed in this item. /// /// /// DisplayText may contain text mixed with expressions just like in the TextObject, e.g. "Some text: [expr]". /// The default property value is empty for group descriptors. /// In this case the group value returned by the property will be displayed in this item. /// public string DisplayText { get; set; } /// /// Gets or sets the filter expression. /// public string Filter { get; set; } /// /// Gets or sets the sort order of header values. /// /// /// This property determines how the values displayed in this element are sorted. The default sort is ascending. /// public SortOrder Sort { get; set; } /// /// Gets or sets the sort button name which toggles the sort order of this item. /// public string SortToggledBy { get; set; } /// /// Gets or sets an expression which value will be used to sort the header values. /// /// This expression is used to sort header by its total value. The expression must contain single aggregate, e.g. "Sum([Table1.Field1])". /// The empty expression (by default) indicates that the header should be sorted by its value. /// public string SortByTotal { get; set; } /// /// Gets or sets a value indicating that this item can be sorted interactively. /// public bool InteractiveSort { get; set; } /// /// Gets or sets an expression which value will be used to sort the header values interactively. /// /// This expression is used to sort header values when interactive sorting is on. /// The expression must contain single aggregate, e.g. "Sum([Table1.Field1])". /// The empty expression (by default) indicates automatic mode. /// public string InteractiveSortBy { get; set; } /// /// Gets or sets the visibility of this item. /// public bool Visible { get; set; } /// /// Gets or sets the expression that returns the visibility of this item. /// public string VisibleExpression { get; set; } /// /// Gets or sets the collapse button name which toggles the visibility of this item. /// public string VisibleToggledBy { get; set; } /// /// Gets or sets a value indicating that the page break must be printed before this element. /// /// /// Page break is not printed before the very first element. /// public bool PageBreak { get; set; } /// /// Determines whether the item should merge itself with single subitem. /// public bool MergeSingleItem { get; set; } /// /// Determines whether this item and its subitems will be displayed stepped. /// public bool Stepped { get; set; } /// /// Gets TopN settings for this item. /// public TopNInfo TopN { get; private set; } /// /// Gets or sets column span of this item. 0 means span is set automatically. /// public int ColSpan { get; set; } /// /// Gets or sets row span of this item. 0 means span is set automatically. /// public int RowSpan { get; set; } // these items set by TemplateBuilder.UpdateDescriptors internal AdvMatrixObject Matrix { get; set; } internal bool IsColumn { get; set; } internal TableColumn TemplateColumn { get; set; } internal TableRow TemplateRow { get; set; } internal TableCell TemplateCell { get; set; } // Aggregate is used if "sort by total" is on internal AggregateExpressionPair SortAggregate { get; set; } // Aggregate is used if interactive sort is on internal AggregateExpressionPair InteractiveSortAggregate { get; set; } internal bool IsGroup { get { return !String.IsNullOrEmpty(Expression); } } internal bool IsTopNItem { get { return !String.IsNullOrEmpty(Name); } } internal HeaderDescriptor Root { get { HeaderDescriptor item = this; while (item.Parent != null) { item = item.Parent; } return item; } } internal int Span { get { if (Stepped) return 1; int count = TerminalItems.Count; return count > 0 ? count : 1; } } internal List AllItems { get { List list = new List(); GetAllItems(this, list); return list; } } internal List TerminalItems { get { List list = new List(); GetTerminalItems(this, list); return list; } } private void GetAllItems(HeaderDescriptor root, List list) { foreach (HeaderDescriptor d in root.Items) { list.Add(d); GetAllItems(d, list); } } private void GetTerminalItems(HeaderDescriptor root, List list) { if (root.Items.Count == 0 || root.Stepped) list.Add(root); foreach (HeaderDescriptor d in root.Items) { GetTerminalItems(d, list); } } internal void SetParent(HeaderDescriptor parent) { Parent = parent; } internal void InitAggregates() { ExpressionParser parser = new ExpressionParser(Matrix); if (!String.IsNullOrEmpty(SortByTotal)) { SortAggregate = parser.Parse(SortByTotal); } if (InteractiveSort && !String.IsNullOrEmpty(InteractiveSortBy)) { // use existing cell aggregate here InteractiveSortAggregate = Matrix.Data.CellData.FindAggregate(parser.Parse(InteractiveSortBy)); } } internal object CalcValue() { if (String.IsNullOrEmpty(Expression)) return null; return Matrix.Report.Calc(Expression); } /// /// Adds new child descriptor. /// /// The new descriptor. public HeaderDescriptor Add() { return Add(new HeaderDescriptor()); } /// /// Adds a child descriptor. /// /// The new descriptor. /// The new descriptor. public HeaderDescriptor Add(HeaderDescriptor descr) { Items.Add(descr); descr.Parent = this; return descr; } /// public void Serialize(FRWriter writer) { writer.ItemName = "Descriptor"; HeaderDescriptor c = writer.DiffObject as HeaderDescriptor; if (Name != c.Name) writer.WriteStr("Name", Name); if (Expression != c.Expression) writer.WriteStr("Expression", Expression); if (DisplayText != c.DisplayText) writer.WriteStr("DisplayText", DisplayText); if (Filter != c.Filter) writer.WriteStr("Filter", Filter); if (Sort != c.Sort) writer.WriteValue("Sort", Sort); if (SortToggledBy != c.SortToggledBy) writer.WriteStr("SortToggledBy", SortToggledBy); if (SortByTotal != c.SortByTotal) writer.WriteStr("SortByTotal", SortByTotal); if (InteractiveSort != c.InteractiveSort) writer.WriteBool("InteractiveSort", InteractiveSort); if (InteractiveSortBy != c.InteractiveSortBy) writer.WriteStr("InteractiveSortBy", InteractiveSortBy); if (Visible != c.Visible) writer.WriteBool("Visible", Visible); if (VisibleExpression != c.VisibleExpression) writer.WriteStr("VisibleExpression", VisibleExpression); if (VisibleToggledBy != c.VisibleToggledBy) writer.WriteStr("VisibleToggledBy", VisibleToggledBy); TopN.Serialize(writer, "TopN", c.TopN); if (Stepped != c.Stepped) writer.WriteBool("Stepped", Stepped); if (PageBreak != c.PageBreak) writer.WriteBool("PageBreak", PageBreak); if (MergeSingleItem != c.MergeSingleItem) writer.WriteBool("MergeSingleItem", MergeSingleItem); if (ColSpan != c.ColSpan) writer.WriteInt("ColSpan", ColSpan); if (RowSpan != c.RowSpan) writer.WriteInt("RowSpan", RowSpan); foreach (HeaderDescriptor d in Items) { writer.Write(d); } } /// public void Deserialize(FRReader reader) { reader.ReadProperties(this); Items.Clear(); while (reader.NextItem()) { reader.Read(Add()); } } /// /// Initializes a new instance of the class. /// public HeaderDescriptor() { Name = ""; Items = new List(); Expression = ""; DisplayText = ""; Filter = ""; Sort = SortOrder.Ascending; SortToggledBy = ""; SortByTotal = ""; InteractiveSort = true; InteractiveSortBy = ""; Visible = true; VisibleExpression = ""; VisibleToggledBy = ""; TopN = new TopNInfo(this); } /// /// Initializes a new instance of the class with the group expression specified. /// public HeaderDescriptor(string expression) : this() { Expression = expression; } } }