using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Drawing; using FastReport.Data; using FastReport.Utils; namespace FastReport.Table { /// /// Represents a table row. /// /// /// Use the property to set the height of a row. If /// property is true, the row will calculate its height automatically. /// You can also set the and properties /// to restrict the row's height. /// public partial class TableRow : ComponentBase, IParent { #region Fields private List cells; private float minHeight; private float maxHeight; private bool autoSize; private bool canBreak; private bool pageBreak; private int keepRows; private int index; private float saveHeight; private bool saveVisible; private bool serializingToPreview; #endregion #region Properties /// /// Gets or sets a height of the row, in pixels. /// /// /// The row height cannot exceed the range defined by the /// and properties. /// To convert between pixels and report units, use the constants defined /// in the class. /// [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public override float Height { get { return base.Height; } set { value = Converter.DecreasePrecision(value, 2); if (value > MaxHeight && !canBreak) value = MaxHeight; if (value < MinHeight) value = MinHeight; base.Height = value; } } /// /// Gets or sets the minimal height for this row, in pixels. /// [DefaultValue(0f)] [Category("Layout")] [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public float MinHeight { get { return minHeight; } set { minHeight = value; } } /// /// Gets or sets the maximal height for this row, in pixels. /// [DefaultValue(1000f)] [Category("Layout")] [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public float MaxHeight { get { return maxHeight; } set { maxHeight = value; } } /// /// Gets or sets a value determines if the row should calculate its height automatically. /// /// /// The row height cannot exceed the range defined by the /// and properties. /// [DefaultValue(false)] [Category("Behavior")] public bool AutoSize { get { return autoSize; } set { autoSize = value; } } /// /// Gets or sets a value that determines if the component can break its contents across pages. /// [DefaultValue(false)] [Category("Behavior")] public bool CanBreak { get { return canBreak; } set { canBreak = value; } } /// /// Gets the index of this row. /// [Browsable(false)] public int Index { get { return index; } } /// [Browsable(false)] public override float Top { get { TableBase table = Parent as TableBase; if (table == null) return 0; float result = 0; for (int i = 0; i < Index; i++) { result += table.Rows[i].Height; } return result; } set { base.Top = value; } } /// /// Gets or sets the cell with specified index. /// /// Column index. /// The TableCell object. [Browsable(false)] public TableCell this[int col] { get { TableCellData cellData = CellData(col); TableCell cell = cellData.Cell; cell.SetParent(this); cell.SetValue(cellData.Value); return cell; } set { TableCellData cellData = CellData(col); cellData.AttachCell(value); } } /// /// Gets or sets the page break flag for this row. /// [Browsable(false)] public bool PageBreak { get { return pageBreak; } set { pageBreak = value; } } /// /// Gets or sets the number of rows to keep on the same page. /// [Browsable(false)] public int KeepRows { get { return keepRows; } set { keepRows = value; } } internal static float DefaultHeight { get { return (int)Math.Round(18 / (0.25f * Units.Centimeters)) * (0.25f * Units.Centimeters); } } #endregion #region IParent Members /// public bool CanContain(Base child) { return child is TableCell; } /// public void GetChildObjects(ObjectCollection list) { TableBase table = Parent as TableBase; if (table == null) return; for (int i = 0; i < table.Columns.Count; i++) { if (!serializingToPreview || table.Columns[i].Visible) list.Add(this[i]); } } /// public void AddChild(Base child) { // support deserializing the cells if (child is TableCell) { this[cells.Count] = child as TableCell; child.SetParent(this); } } /// public void RemoveChild(Base child) { } private TableCellData FindCellData(TableCell cell) { foreach (TableCellData cellData in cells) { if (cellData.Cell == cell) return cellData; } return null; } /// public int GetChildOrder(Base child) { TableCellData cellData = FindCellData(child as TableCell); return cellData == null ? 0 : cells.IndexOf(cellData); } /// public void SetChildOrder(Base child, int order) { TableCellData cellData = FindCellData(child as TableCell); if (cellData == null) return; int oldOrder = child.ZOrder; if (oldOrder != -1 && order != -1 && oldOrder != order) { if (order > cells.Count) order = cells.Count; if (oldOrder <= order) order--; cells.Remove(cellData); cells.Insert(order, cellData); } } /// public void UpdateLayout(float dx, float dy) { TableBase table = Parent as TableBase; if (table == null) return; // update this row cells for (int i = 0; i < table.Columns.Count; i++) { this.CellData(i).UpdateLayout(dx, dy); } // update spanned cells that contains this row List spanList = table.GetSpanList(); foreach (Rectangle span in spanList) { if (Index > span.Top && Index < span.Bottom) table[span.Left, span.Top].CellData.UpdateLayout(dx, dy); } } #endregion #region Public Methods /// public override void Assign(Base source) { TableRow src = source as TableRow; MinHeight = src.MinHeight; MaxHeight = src.MaxHeight; AutoSize = src.AutoSize; KeepRows = src.KeepRows; CanBreak = src.CanBreak; base.Assign(source); } internal TableCellData CellData(int col) { while (col >= cells.Count) { cells.Add(new TableCellData()); } TableCellData cellData = cells[col]; cellData.Table = Parent as TableBase; cellData.Address = new Point(col, Index); return cellData; } internal void CorrectCellsOnColumnChange(int index, int correct) { if (correct == 1) cells.Insert(index, new TableCellData()); else if (index < cells.Count) cells.RemoveAt(index); } internal void SetIndex(int value) { index = value; } /// public override void Serialize(FRWriter writer) { TableRow c = writer.DiffObject as TableRow; serializingToPreview = writer.SerializeTo == SerializeTo.Preview; base.Serialize(writer); if (FloatDiff(MinHeight, c.MinHeight)) writer.WriteFloat("MinHeight", MinHeight); if (FloatDiff(MaxHeight, c.MaxHeight)) writer.WriteFloat("MaxHeight", MaxHeight); if (FloatDiff(Height, c.Height)) writer.WriteFloat("Height", Height); if (AutoSize != c.AutoSize) writer.WriteBool("AutoSize", AutoSize); if (CanBreak != c.CanBreak) writer.WriteBool("CanBreak", CanBreak); if (Parent is TableResult) { // write children by itself SetFlags(Flags.CanWriteChildren, true); writer.SaveChildren = true; TableResult table = Parent as TableResult; foreach (TableColumn column in table.ColumnsToSerialize) { TableCell cell = this[column.Index]; writer.Write(cell); } } } /// public override void Clear() { base.Clear(); foreach (TableCellData cell in cells) { cell.Dispose(); } cells.Clear(); } internal void SaveState() { saveHeight = Height; saveVisible = Visible; } internal void RestoreState() { Height = saveHeight; Visible = saveVisible; } #endregion /// /// Initializes a new instance of the class. /// public TableRow() { cells = new List(); maxHeight = 1000; Height = DefaultHeight; SetFlags(Flags.CanCopy | Flags.CanDelete | Flags.CanWriteBounds, false); BaseName = "Row"; } } }