FastReport
395 строк · 11.6 Кб
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.ComponentModel;
5using System.Drawing;
6using FastReport.Data;
7using FastReport.Utils;
8
9namespace FastReport.Table
10{
11/// <summary>
12/// Represents a table row.
13/// </summary>
14/// <remarks>
15/// Use the <see cref="Height"/> property to set the height of a row. If <see cref="AutoSize"/>
16/// property is <b>true</b>, the row will calculate its height automatically.
17/// <para/>You can also set the <see cref="MinHeight"/> and <see cref="MaxHeight"/> properties
18/// to restrict the row's height.
19/// </remarks>
20public partial class TableRow : ComponentBase, IParent
21{
22#region Fields
23private List<TableCellData> cells;
24private float minHeight;
25private float maxHeight;
26private bool autoSize;
27private bool canBreak;
28private bool pageBreak;
29private int keepRows;
30private int index;
31private float saveHeight;
32private bool saveVisible;
33private bool serializingToPreview;
34#endregion
35
36#region Properties
37/// <summary>
38/// Gets or sets a height of the row, in pixels.
39/// </summary>
40/// <remarks>
41/// The row height cannot exceed the range defined by the <see cref="MinHeight"/>
42/// and <see cref="MaxHeight"/> properties.
43/// <note>To convert between pixels and report units, use the constants defined
44/// in the <see cref="Units"/> class.</note>
45/// </remarks>
46[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
47public override float Height
48{
49get { return base.Height; }
50set
51{
52value = Converter.DecreasePrecision(value, 2);
53if (value > MaxHeight && !canBreak)
54value = MaxHeight;
55if (value < MinHeight)
56value = MinHeight;
57base.Height = value;
58}
59}
60
61/// <summary>
62/// Gets or sets the minimal height for this row, in pixels.
63/// </summary>
64[DefaultValue(0f)]
65[Category("Layout")]
66[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
67public float MinHeight
68{
69get { return minHeight; }
70set { minHeight = value; }
71}
72
73/// <summary>
74/// Gets or sets the maximal height for this row, in pixels.
75/// </summary>
76[DefaultValue(1000f)]
77[Category("Layout")]
78[TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
79public float MaxHeight
80{
81get { return maxHeight; }
82set { maxHeight = value; }
83}
84
85/// <summary>
86/// Gets or sets a value determines if the row should calculate its height automatically.
87/// </summary>
88/// <remarks>
89/// The row height cannot exceed the range defined by the <see cref="MinHeight"/>
90/// and <see cref="MaxHeight"/> properties.
91/// </remarks>
92[DefaultValue(false)]
93[Category("Behavior")]
94public bool AutoSize
95{
96get { return autoSize; }
97set { autoSize = value; }
98}
99
100/// <summary>
101/// Gets or sets a value that determines if the component can break its contents across pages.
102/// </summary>
103[DefaultValue(false)]
104[Category("Behavior")]
105public bool CanBreak
106{
107get { return canBreak; }
108set { canBreak = value; }
109}
110
111/// <summary>
112/// Gets the index of this row.
113/// </summary>
114[Browsable(false)]
115public int Index
116{
117get { return index; }
118}
119
120/// <inheritdoc/>
121[Browsable(false)]
122public override float Top
123{
124get
125{
126TableBase table = Parent as TableBase;
127if (table == null)
128return 0;
129
130float result = 0;
131for (int i = 0; i < Index; i++)
132{
133result += table.Rows[i].Height;
134}
135return result;
136}
137set { base.Top = value; }
138}
139
140/// <summary>
141/// Gets or sets the cell with specified index.
142/// </summary>
143/// <param name="col">Column index.</param>
144/// <returns>The <b>TableCell</b> object.</returns>
145[Browsable(false)]
146public TableCell this[int col]
147{
148get
149{
150TableCellData cellData = CellData(col);
151TableCell cell = cellData.Cell;
152cell.SetParent(this);
153cell.SetValue(cellData.Value);
154return cell;
155}
156set
157{
158TableCellData cellData = CellData(col);
159cellData.AttachCell(value);
160}
161}
162
163/// <summary>
164/// Gets or sets the page break flag for this row.
165/// </summary>
166[Browsable(false)]
167public bool PageBreak
168{
169get { return pageBreak; }
170set { pageBreak = value; }
171}
172
173/// <summary>
174/// Gets or sets the number of rows to keep on the same page.
175/// </summary>
176[Browsable(false)]
177public int KeepRows
178{
179get { return keepRows; }
180set { keepRows = value; }
181}
182
183internal static float DefaultHeight
184{
185get { return (int)Math.Round(18 / (0.25f * Units.Centimeters)) * (0.25f * Units.Centimeters); }
186}
187#endregion
188
189#region IParent Members
190/// <inheritdoc/>
191public bool CanContain(Base child)
192{
193return child is TableCell;
194}
195
196/// <inheritdoc/>
197public void GetChildObjects(ObjectCollection list)
198{
199TableBase table = Parent as TableBase;
200if (table == null)
201return;
202
203for (int i = 0; i < table.Columns.Count; i++)
204{
205if (!serializingToPreview || table.Columns[i].Visible)
206list.Add(this[i]);
207}
208}
209
210/// <inheritdoc/>
211public void AddChild(Base child)
212{
213// support deserializing the cells
214if (child is TableCell)
215{
216this[cells.Count] = child as TableCell;
217child.SetParent(this);
218}
219}
220
221/// <inheritdoc/>
222public void RemoveChild(Base child)
223{
224}
225
226private TableCellData FindCellData(TableCell cell)
227{
228foreach (TableCellData cellData in cells)
229{
230if (cellData.Cell == cell)
231return cellData;
232}
233return null;
234}
235
236/// <inheritdoc/>
237public int GetChildOrder(Base child)
238{
239TableCellData cellData = FindCellData(child as TableCell);
240return cellData == null ? 0 : cells.IndexOf(cellData);
241}
242
243/// <inheritdoc/>
244public void SetChildOrder(Base child, int order)
245{
246TableCellData cellData = FindCellData(child as TableCell);
247if (cellData == null)
248return;
249
250int oldOrder = child.ZOrder;
251if (oldOrder != -1 && order != -1 && oldOrder != order)
252{
253if (order > cells.Count)
254order = cells.Count;
255if (oldOrder <= order)
256order--;
257cells.Remove(cellData);
258cells.Insert(order, cellData);
259}
260}
261
262/// <inheritdoc/>
263public void UpdateLayout(float dx, float dy)
264{
265TableBase table = Parent as TableBase;
266if (table == null)
267return;
268
269// update this row cells
270for (int i = 0; i < table.Columns.Count; i++)
271{
272this.CellData(i).UpdateLayout(dx, dy);
273}
274
275// update spanned cells that contains this row
276List<Rectangle> spanList = table.GetSpanList();
277foreach (Rectangle span in spanList)
278{
279if (Index > span.Top && Index < span.Bottom)
280table[span.Left, span.Top].CellData.UpdateLayout(dx, dy);
281}
282
283}
284#endregion
285
286#region Public Methods
287/// <inheritdoc/>
288public override void Assign(Base source)
289{
290TableRow src = source as TableRow;
291MinHeight = src.MinHeight;
292MaxHeight = src.MaxHeight;
293AutoSize = src.AutoSize;
294KeepRows = src.KeepRows;
295CanBreak = src.CanBreak;
296
297base.Assign(source);
298}
299
300internal TableCellData CellData(int col)
301{
302while (col >= cells.Count)
303{
304cells.Add(new TableCellData());
305}
306
307TableCellData cellData = cells[col];
308cellData.Table = Parent as TableBase;
309cellData.Address = new Point(col, Index);
310return cellData;
311}
312
313internal void CorrectCellsOnColumnChange(int index, int correct)
314{
315if (correct == 1)
316cells.Insert(index, new TableCellData());
317else if (index < cells.Count)
318cells.RemoveAt(index);
319}
320
321internal void SetIndex(int value)
322{
323index = value;
324}
325
326/// <inheritdoc/>
327public override void Serialize(FRWriter writer)
328{
329TableRow c = writer.DiffObject as TableRow;
330serializingToPreview = writer.SerializeTo == SerializeTo.Preview;
331base.Serialize(writer);
332
333if (FloatDiff(MinHeight, c.MinHeight))
334writer.WriteFloat("MinHeight", MinHeight);
335if (FloatDiff(MaxHeight, c.MaxHeight))
336writer.WriteFloat("MaxHeight", MaxHeight);
337if (FloatDiff(Height, c.Height))
338writer.WriteFloat("Height", Height);
339if (AutoSize != c.AutoSize)
340writer.WriteBool("AutoSize", AutoSize);
341if (CanBreak != c.CanBreak)
342writer.WriteBool("CanBreak", CanBreak);
343
344if (Parent is TableResult)
345{
346// write children by itself
347SetFlags(Flags.CanWriteChildren, true);
348writer.SaveChildren = true;
349
350TableResult table = Parent as TableResult;
351foreach (TableColumn column in table.ColumnsToSerialize)
352{
353TableCell cell = this[column.Index];
354writer.Write(cell);
355}
356}
357}
358
359/// <inheritdoc/>
360public override void Clear()
361{
362base.Clear();
363foreach (TableCellData cell in cells)
364{
365cell.Dispose();
366}
367cells.Clear();
368}
369
370internal void SaveState()
371{
372saveHeight = Height;
373saveVisible = Visible;
374}
375
376internal void RestoreState()
377{
378Height = saveHeight;
379Visible = saveVisible;
380}
381#endregion
382
383/// <summary>
384/// Initializes a new instance of the <see cref="TableRow"/> class.
385/// </summary>
386public TableRow()
387{
388cells = new List<TableCellData>();
389maxHeight = 1000;
390Height = DefaultHeight;
391SetFlags(Flags.CanCopy | Flags.CanDelete | Flags.CanWriteBounds, false);
392BaseName = "Row";
393}
394}
395}
396