4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
31 using System.Collections.Generic;
32 using System.ComponentModel;
33 using System.Runtime.InteropServices;
34 using System.Windows.Forms.Layout;
35 using System.ComponentModel.Design.Serialization;
37 namespace System.Windows.Forms
40 [ClassInterface (ClassInterfaceType.AutoDispatch)]
41 [ProvideProperty ("CellPosition", typeof (Control))]
42 [ProvideProperty ("Column", typeof (Control))]
43 [ProvideProperty ("ColumnSpan", typeof (Control))]
44 [ProvideProperty ("Row", typeof (Control))]
45 [ProvideProperty ("RowSpan", typeof (Control))]
46 [DefaultProperty ("ColumnCount")]
47 [Docking (DockingBehavior.Never)]
48 [Designer ("System.Windows.Forms.Design.TableLayoutPanelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 [DesignerSerializer ("System.Windows.Forms.Design.TableLayoutPanelCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
50 public class TableLayoutPanel : Panel, IExtenderProvider
52 private TableLayoutSettings settings;
53 private static TableLayout layout_engine = new TableLayout ();
54 private TableLayoutPanelCellBorderStyle cell_border_style;
56 // This is the row/column the Control actually got placed
57 internal Control[,] actual_positions;
59 // Widths and heights of each column/row
60 internal int[] column_widths;
61 internal int[] row_heights;
63 #region Public Constructor
64 public TableLayoutPanel ()
66 settings = new TableLayoutSettings(this);
67 cell_border_style = TableLayoutPanelCellBorderStyle.None;
68 column_widths = new int[0];
69 row_heights = new int[0];
74 #region Public Properties
77 [EditorBrowsable (EditorBrowsableState.Never)]
78 new public BorderStyle BorderStyle {
79 get { return base.BorderStyle; }
80 set { base.BorderStyle = value; }
84 [DefaultValue (TableLayoutPanelCellBorderStyle.None)]
85 public TableLayoutPanelCellBorderStyle CellBorderStyle {
86 get { return this.cell_border_style; }
88 if (this.cell_border_style != value) {
89 this.cell_border_style = value;
90 this.PerformLayout (this, "CellBorderStyle");
98 public int ColumnCount {
99 get { return settings.ColumnCount; }
100 set { settings.ColumnCount = value; }
104 [DisplayName ("Columns")]
105 [MergableProperty (false)]
106 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
107 public TableLayoutColumnStyleCollection ColumnStyles {
108 get { return settings.ColumnStyles; }
112 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
113 new public TableLayoutControlCollection Controls {
114 get { return (TableLayoutControlCollection) base.Controls; }
117 [DefaultValue (TableLayoutPanelGrowStyle.AddRows)]
118 public TableLayoutPanelGrowStyle GrowStyle {
119 get { return settings.GrowStyle; }
120 set { settings.GrowStyle = value; }
123 public override System.Windows.Forms.Layout.LayoutEngine LayoutEngine {
124 get { return TableLayoutPanel.layout_engine; }
128 [EditorBrowsable (EditorBrowsableState.Never)]
129 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
130 public TableLayoutSettings LayoutSettings {
131 get { return this.settings; }
133 if (value.isSerialized) {
134 // Serialized version doesn't calculate these.
135 value.ColumnCount = value.ColumnStyles.Count;
136 value.RowCount = value.RowStyles.Count;
139 this.settings = value;
141 throw new NotSupportedException ("LayoutSettings value cannot be set directly.");
147 public int RowCount {
148 get { return settings.RowCount; }
149 set { settings.RowCount = value; }
153 [DisplayName ("Rows")]
154 [MergableProperty (false)]
155 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
156 public TableLayoutRowStyleCollection RowStyles {
157 get { return settings.RowStyles; }
161 #region Public Methods
163 [DisplayName ("Cell")]
164 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
165 public TableLayoutPanelCellPosition GetCellPosition (Control control)
167 return settings.GetCellPosition (control);
170 [DisplayName ("Column")]
172 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
173 public int GetColumn (Control control)
175 return settings.GetColumn (control);
178 [DisplayName ("ColumnSpan")]
180 public int GetColumnSpan (Control control)
182 return settings.GetColumnSpan (control);
186 [EditorBrowsable (EditorBrowsableState.Never)]
187 public int[] GetColumnWidths ()
189 return this.column_widths;
192 public Control GetControlFromPosition (int column, int row)
194 if (column < 0 || row < 0)
195 throw new ArgumentException ();
197 TableLayoutPanelCellPosition pos = new TableLayoutPanelCellPosition (column, row);
199 foreach (Control c in this.Controls)
200 if (settings.GetCellPosition (c) == pos)
206 public TableLayoutPanelCellPosition GetPositionFromControl (Control control)
208 for (int x = 0; x < this.actual_positions.GetLength (0); x++)
209 for (int y = 0; y < this.actual_positions.GetLength (1); y++)
210 if (this.actual_positions[x, y] == control)
211 return new TableLayoutPanelCellPosition (x, y);
213 return new TableLayoutPanelCellPosition (-1, -1);
216 [DisplayName ("Row")]
217 [DefaultValue ("-1")]
218 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
219 public int GetRow (Control control)
221 return settings.GetRow (control);
225 [EditorBrowsable (EditorBrowsableState.Never)]
226 public int[] GetRowHeights ()
228 return this.row_heights;
231 [DisplayName ("RowSpan")]
233 public int GetRowSpan (Control control)
235 return settings.GetRowSpan (control);
238 public void SetCellPosition (Control control, TableLayoutPanelCellPosition position)
240 settings.SetCellPosition (control, position);
243 public void SetColumn (Control control, int column)
245 settings.SetColumn (control, column);
248 public void SetColumnSpan (Control control, int value)
250 settings.SetColumnSpan (control, value);
253 public void SetRow (Control control, int row)
255 settings.SetRow (control, row);
258 public void SetRowSpan (Control control, int value)
260 settings.SetRowSpan (control, value);
264 #region Protected Methods
265 [EditorBrowsable (EditorBrowsableState.Advanced)]
266 protected override ControlCollection CreateControlsInstance ()
268 return new TableLayoutControlCollection (this);
271 protected virtual void OnCellPaint (TableLayoutCellPaintEventArgs e)
273 TableLayoutCellPaintEventHandler eh = (TableLayoutCellPaintEventHandler)(Events [CellPaintEvent]);
278 [EditorBrowsable (EditorBrowsableState.Advanced)]
279 protected override void OnLayout (LayoutEventArgs levent)
281 base.OnLayout (levent);
285 protected override void OnPaintBackground (PaintEventArgs e)
287 base.OnPaintBackground (e);
291 int border_width = GetCellBorderWidth (CellBorderStyle);
293 int x = border_width;
294 int y = border_width;
296 for (int i = 0; i < column_widths.Length; i++) {
297 for (int j = 0; j < row_heights.Length; j++) {
298 this.OnCellPaint (new TableLayoutCellPaintEventArgs (e.Graphics, e.ClipRectangle, new Rectangle (x, y, column_widths[i] + border_width, row_heights[j] + border_width), i, j));
299 y += row_heights[j] + border_width;
302 x += column_widths[i] + border_width;
307 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
309 base.ScaleControl (factor, specified);
312 [EditorBrowsable (EditorBrowsableState.Never)]
313 protected override void ScaleCore (float dx, float dy)
315 base.ScaleCore (dx, dy);
319 #region Internal Methods
320 internal static int GetCellBorderWidth (TableLayoutPanelCellBorderStyle style)
323 case TableLayoutPanelCellBorderStyle.Single:
325 case TableLayoutPanelCellBorderStyle.Inset:
326 case TableLayoutPanelCellBorderStyle.Outset:
328 case TableLayoutPanelCellBorderStyle.InsetDouble:
329 case TableLayoutPanelCellBorderStyle.OutsetPartial:
330 case TableLayoutPanelCellBorderStyle.OutsetDouble:
337 private void DrawCellBorders (PaintEventArgs e)
339 Rectangle paint_here = new Rectangle (Point.Empty, this.Size);
341 switch (CellBorderStyle) {
342 case TableLayoutPanelCellBorderStyle.Single:
343 DrawSingleBorder (e.Graphics, paint_here);
345 case TableLayoutPanelCellBorderStyle.Inset:
346 DrawInsetBorder (e.Graphics, paint_here);
348 case TableLayoutPanelCellBorderStyle.InsetDouble:
349 DrawInsetDoubleBorder (e.Graphics, paint_here);
351 case TableLayoutPanelCellBorderStyle.Outset:
352 DrawOutsetBorder (e.Graphics, paint_here);
354 case TableLayoutPanelCellBorderStyle.OutsetDouble:
355 case TableLayoutPanelCellBorderStyle.OutsetPartial:
356 DrawOutsetDoubleBorder (e.Graphics, paint_here);
361 private void DrawSingleBorder (Graphics g, Rectangle rect)
363 ControlPaint.DrawBorder (g, rect, SystemColors.ControlDark, ButtonBorderStyle.Solid);
365 int x = DisplayRectangle.X;
366 int y = DisplayRectangle.Y;
368 for (int i = 0; i < column_widths.Length - 1; i++) {
369 x += column_widths[i] + 1;
371 g.DrawLine (SystemPens.ControlDark, new Point (x, 1), new Point (x, Bottom - 2));
374 for (int j = 0; j < row_heights.Length - 1; j++) {
375 y += row_heights[j] + 1;
377 g.DrawLine (SystemPens.ControlDark, new Point (1, y), new Point (Right - 2, y));
381 private void DrawInsetBorder (Graphics g, Rectangle rect)
383 ControlPaint.DrawBorder3D (g, rect, Border3DStyle.Etched);
385 int x = DisplayRectangle.X;
386 int y = DisplayRectangle.Y;
388 for (int i = 0; i < column_widths.Length - 1; i++) {
389 x += column_widths[i] + 2;
391 g.DrawLine (SystemPens.ControlDark, new Point (x, 1), new Point (x, Bottom - 3));
392 g.DrawLine (Pens.White, new Point (x + 1, 1), new Point (x + 1, Bottom - 3));
395 for (int j = 0; j < row_heights.Length - 1; j++) {
396 y += row_heights[j] + 2;
398 g.DrawLine (SystemPens.ControlDark, new Point (1, y), new Point (Right - 3, y));
399 g.DrawLine (Pens.White, new Point (1, y + 1), new Point (Right - 3, y + 1));
403 private void DrawOutsetBorder (Graphics g, Rectangle rect)
405 g.DrawRectangle (SystemPens.ControlDark, new Rectangle (rect.Left + 1, rect.Top + 1, rect.Width - 2, rect.Height - 2));
406 g.DrawRectangle (Pens.White, new Rectangle (rect.Left, rect.Top, rect.Width - 2, rect.Height - 2));
408 int x = DisplayRectangle.X;
409 int y = DisplayRectangle.Y;
411 for (int i = 0; i < column_widths.Length - 1; i++) {
412 x += column_widths[i] + 2;
414 g.DrawLine (Pens.White, new Point (x, 1), new Point (x, Bottom - 3));
415 g.DrawLine (SystemPens.ControlDark, new Point (x + 1, 1), new Point (x + 1, Bottom - 3));
418 for (int j = 0; j < row_heights.Length - 1; j++) {
419 y += row_heights[j] + 2;
421 g.DrawLine (Pens.White, new Point (1, y), new Point (Right - 3, y));
422 g.DrawLine (SystemPens.ControlDark, new Point (1, y + 1), new Point (Right - 3, y + 1));
426 private void DrawOutsetDoubleBorder (Graphics g, Rectangle rect)
431 g.DrawRectangle (SystemPens.ControlDark, new Rectangle (rect.Left + 2, rect.Top + 2, rect.Width - 2, rect.Height - 2));
432 g.DrawRectangle (Pens.White, new Rectangle (rect.Left, rect.Top, rect.Width - 2, rect.Height - 2));
434 int x = DisplayRectangle.X;
435 int y = DisplayRectangle.Y;
437 for (int i = 0; i < column_widths.Length - 1; i++) {
438 x += column_widths[i] + 3;
440 g.DrawLine (Pens.White, new Point (x, 3), new Point (x, Bottom - 5));
441 g.DrawLine (SystemPens.ControlDark, new Point (x + 2, 3), new Point (x + 2, Bottom - 5));
444 for (int j = 0; j < row_heights.Length - 1; j++) {
445 y += row_heights[j] + 3;
447 g.DrawLine (Pens.White, new Point (3, y), new Point (Right - 4, y));
448 g.DrawLine (SystemPens.ControlDark, new Point (3, y + 2), new Point (Right - 4, y + 2));
451 x = DisplayRectangle.X;
452 y = DisplayRectangle.Y;
454 for (int i = 0; i < column_widths.Length - 1; i++) {
455 x += column_widths[i] + 3;
457 g.DrawLine (ThemeEngine.Current.ResPool.GetPen (BackColor), new Point (x + 1, 3), new Point (x + 1, Bottom - 5));
460 for (int j = 0; j < row_heights.Length - 1; j++) {
461 y += row_heights[j] + 3;
463 g.DrawLine (ThemeEngine.Current.ResPool.GetPen (BackColor), new Point (3, y + 1), new Point (Right - 4, y + 1));
467 private void DrawInsetDoubleBorder (Graphics g, Rectangle rect)
472 g.DrawRectangle (Pens.White, new Rectangle (rect.Left + 2, rect.Top + 2, rect.Width - 2, rect.Height - 2));
473 g.DrawRectangle (SystemPens.ControlDark, new Rectangle (rect.Left, rect.Top, rect.Width - 2, rect.Height - 2));
475 int x = DisplayRectangle.X;
476 int y = DisplayRectangle.Y;
478 for (int i = 0; i < column_widths.Length - 1; i++) {
479 x += column_widths[i] + 3;
481 g.DrawLine (SystemPens.ControlDark, new Point (x, 3), new Point (x, Bottom - 5));
482 g.DrawLine (Pens.White, new Point (x + 2, 3), new Point (x + 2, Bottom - 5));
485 for (int j = 0; j < row_heights.Length - 1; j++) {
486 y += row_heights[j] + 3;
488 g.DrawLine (SystemPens.ControlDark, new Point (3, y), new Point (Right - 4, y));
489 g.DrawLine (Pens.White, new Point (3, y + 2), new Point (Right - 4, y + 2));
492 x = DisplayRectangle.X;
493 y = DisplayRectangle.Y;
495 for (int i = 0; i < column_widths.Length - 1; i++) {
496 x += column_widths[i] + 3;
498 g.DrawLine (ThemeEngine.Current.ResPool.GetPen (BackColor), new Point (x + 1, 3), new Point (x + 1, Bottom - 5));
501 for (int j = 0; j < row_heights.Length - 1; j++) {
502 y += row_heights[j] + 3;
504 g.DrawLine (ThemeEngine.Current.ResPool.GetPen (BackColor), new Point (3, y + 1), new Point (Right - 4, y + 1));
508 internal override Size GetPreferredSizeCore (Size proposedSize)
510 // If the tablelayoutowner is autosize, we have to make sure it is big enough
511 // to hold every non-autosize control
512 actual_positions = (LayoutEngine as TableLayout).CalculateControlPositions (this, Math.Max (ColumnCount, 1), Math.Max (RowCount, 1));
514 // Use actual row/column counts, not user set ones
515 int actual_cols = actual_positions.GetLength (0);
516 int actual_rows = actual_positions.GetLength (1);
518 // Find the largest column-span/row-span values. A table entry that spans more than one
519 // column (row) should not be treated as though it's width (height) all belongs to the
520 // first column (row), but should be spread out across all the columns (rows) that are
521 // spanned. So we need to keep track of the widths (heights) of spans as well as
522 // individual columns (rows).
523 int max_colspan = 1, max_rowspan = 1;
524 foreach (Control c in Controls)
526 max_colspan = Math.Max(max_colspan, GetColumnSpan(c));
527 max_rowspan = Math.Max(max_rowspan, GetRowSpan(c));
530 // Figure out how wide the owner needs to be
531 int[] column_widths = new int[actual_cols];
532 // Keep track of widths for spans as well as columns. column_span_widths[i,j] stores
533 // the maximum width for items column i than have a span of j+1 (ie, covers columns
535 int[,] column_span_widths = new int[actual_cols, max_colspan];
536 int[] biggest = new int[max_colspan];
537 float total_column_percentage = 0f;
539 // Figure out how wide each column wants to be
540 for (int i = 0; i < actual_cols; i++) {
541 if (i < ColumnStyles.Count && ColumnStyles[i].SizeType == SizeType.Percent)
542 total_column_percentage += ColumnStyles[i].Width;
543 int absolute_width = -1;
544 if (i < ColumnStyles.Count && ColumnStyles[i].SizeType == SizeType.Absolute)
545 absolute_width = (int)ColumnStyles[i].Width; // use the absolute width if it's absolute!
547 for (int s = 0; s < max_colspan; ++s)
550 for (int j = 0; j < actual_rows; j++) {
551 Control c = actual_positions[i, j];
554 int colspan = GetColumnSpan (c);
557 if (colspan == 1 && absolute_width > -1)
558 biggest[0] = absolute_width; // use the absolute width if the column has absolute width assigned!
559 else if (!c.AutoSize)
560 biggest[colspan-1] = Math.Max (biggest[colspan-1], c.ExplicitBounds.Width + c.Margin.Horizontal + Padding.Horizontal);
562 biggest[colspan-1] = Math.Max (biggest[colspan-1], c.PreferredSize.Width + c.Margin.Horizontal + Padding.Horizontal);
564 else if (absolute_width > -1) {
565 biggest[0] = absolute_width;
569 for (int s = 0; s < max_colspan; ++s)
570 column_span_widths[i,s] = biggest[s];
573 for (int i = 0; i < actual_cols; ++i) {
574 for (int s = 1; s < max_colspan; ++s) {
575 if (column_span_widths[i,s] > 0)
576 AdjustWidthsForSpans (column_span_widths, i, s);
578 column_widths[i] = column_span_widths[i,0];
581 // Because percentage based rows divy up the remaining space,
582 // we have to make the owner big enough so that all the rows
583 // get bigger, even if we only need one to be bigger.
584 int non_percent_total_width = 0;
585 int percent_total_width = 0;
587 for (int i = 0; i < actual_cols; i++) {
588 if (i < ColumnStyles.Count && ColumnStyles[i].SizeType == SizeType.Percent)
589 percent_total_width = Math.Max (percent_total_width, (int)(column_widths[i] / ((ColumnStyles[i].Width) / total_column_percentage)));
591 non_percent_total_width += column_widths[i];
594 int border_width = GetCellBorderWidth (CellBorderStyle);
595 int needed_width = non_percent_total_width + percent_total_width + (border_width * (actual_cols + 1));
597 // Figure out how tall the owner needs to be
598 int[] row_heights = new int[actual_rows];
599 int[,] row_span_heights = new int[actual_rows, max_rowspan];
600 biggest = new int[max_rowspan];
601 float total_row_percentage = 0f;
603 // Figure out how tall each row wants to be
604 for (int j = 0; j < actual_rows; j++) {
605 if (j < RowStyles.Count && RowStyles[j].SizeType == SizeType.Percent)
606 total_row_percentage += RowStyles[j].Height;
607 int absolute_height = -1;
608 if (j < RowStyles.Count && RowStyles[j].SizeType == SizeType.Absolute)
609 absolute_height = (int)RowStyles[j].Height; // use the absolute height if it's absolute!
611 for (int s = 0; s < max_rowspan; ++s)
614 for (int i = 0; i < actual_cols; i++) {
615 Control c = actual_positions[i, j];
618 int rowspan = GetRowSpan (c);
621 if (rowspan == 1 && absolute_height > -1)
622 biggest[0] = absolute_height; // use the absolute height if the row has absolute height assigned!
623 else if (!c.AutoSize)
624 biggest[rowspan-1] = Math.Max (biggest[rowspan-1], c.ExplicitBounds.Height + c.Margin.Vertical + Padding.Vertical);
626 biggest[rowspan-1] = Math.Max (biggest[rowspan-1], c.PreferredSize.Height + c.Margin.Vertical + Padding.Vertical);
628 else if (absolute_height > -1) {
629 biggest[0] = absolute_height;
633 for (int s = 0; s < max_rowspan; ++s)
634 row_span_heights[j,s] = biggest[s];
637 for (int j = 0; j < actual_rows; ++j) {
638 for (int s = 1; s < max_rowspan; ++s) {
639 if (row_span_heights[j,s] > 0)
640 AdjustHeightsForSpans (row_span_heights, j, s);
642 row_heights[j] = row_span_heights[j,0];
645 // Because percentage based rows divy up the remaining space,
646 // we have to make the owner big enough so that all the rows
647 // get bigger, even if we only need one to be bigger.
648 int non_percent_total_height = 0;
649 int percent_total_height = 0;
651 for (int j = 0; j < actual_rows; j++) {
652 if (j < RowStyles.Count && RowStyles[j].SizeType == SizeType.Percent)
653 percent_total_height = Math.Max (percent_total_height, (int)(row_heights[j] / ((RowStyles[j].Height) / total_row_percentage)));
655 non_percent_total_height += row_heights[j];
658 int needed_height = non_percent_total_height + percent_total_height + (border_width * (actual_rows + 1));
660 return new Size (needed_width, needed_height);
664 /// Adjust the widths of the columns underlying a span if necessary.
666 private void AdjustWidthsForSpans (int[,] widths, int col, int span)
668 // Get the combined width of the columns underlying the span.
669 int existing_width = 0;
670 for (int i = col; i <= col+span; ++i)
671 existing_width += widths[i,0];
672 if (widths[col,span] > existing_width)
674 // We need to expand one or more of the underlying columns to fit the span,
675 // preferably ones that are not Absolute style.
676 int excess = widths[col,span] - existing_width;
677 int remaining = excess;
678 List<int> adjusting = new List<int>();
679 List<float> adjusting_widths = new List<float>();
680 for (int i = col; i <= col+span; ++i) {
681 if (i < ColumnStyles.Count && ColumnStyles[i].SizeType != SizeType.Absolute) {
683 adjusting_widths.Add((float)widths[i,0]);
686 if (adjusting.Count == 0) {
687 // if every column is Absolute, spread the gain across every column
688 for (int i = col; i <= col+span; ++i) {
690 adjusting_widths.Add((float)widths[i,0]);
693 float original_total = 0f;
694 foreach (var w in adjusting_widths)
696 // Divide up the needed additional width proportionally.
697 for (int i = 0; i < adjusting.Count; ++i) {
698 var idx = adjusting[i];
699 var percent = adjusting_widths[i] / original_total;
700 var adjust = (int)(percent * excess);
701 widths[idx,0] += adjust;
704 // Any remaining fragment (1 or 2 pixels?) is divided evenly.
705 while (remaining > 0) {
706 for (int i = 0; i < adjusting.Count && remaining > 0; ++i) {
707 ++widths[adjusting[i],0];
715 /// Adjust the heights of the rows underlying a span if necessary.
717 private void AdjustHeightsForSpans (int[,] heights, int row, int span)
719 // Get the combined height of the rows underlying the span.
720 int existing_height = 0;
721 for (int i = row; i <= row+span; ++i)
722 existing_height += heights[i,0];
723 if (heights[row,span] > existing_height)
725 // We need to expand one or more of the underlying rows to fit the span,
726 // preferably ones that are not Absolute style.
727 int excess = heights[row,span] - existing_height;
728 int remaining = excess;
729 List<int> adjusting = new List<int>();
730 List<float> adjusting_heights = new List<float>();
731 for (int i = row; i <= row+span; ++i) {
732 if (i < RowStyles.Count && RowStyles[i].SizeType != SizeType.Absolute) {
734 adjusting_heights.Add((float)heights[i,0]);
737 if (adjusting.Count == 0) {
738 // if every row is Absolute, spread the gain across every row
739 for (int i = row; i <= row+span; ++i) {
741 adjusting_heights.Add((float)heights[i,0]);
744 float original_total = 0f;
745 foreach (var w in adjusting_heights)
747 // Divide up the needed additional height proportionally.
748 for (int i = 0; i < adjusting.Count; ++i) {
749 var idx = adjusting[i];
750 var percent = adjusting_heights[i] / original_total;
751 var adjust = (int)(percent * excess);
752 heights[idx,0] += adjust;
755 // Any remaining fragment (1 or 2 pixels?) is divided evenly.
756 while (remaining > 0) {
757 for (int i = 0; i < adjusting.Count && remaining > 0; ++i) {
758 ++heights[adjusting[i],0];
766 #region Public Events
767 static object CellPaintEvent = new object ();
769 public event TableLayoutCellPaintEventHandler CellPaint {
770 add { Events.AddHandler (CellPaintEvent, value); }
771 remove { Events.RemoveHandler (CellPaintEvent, value); }
775 #region IExtenderProvider
776 bool IExtenderProvider.CanExtend (object obj)
779 if ((obj as Control).Parent == this)