public override bool Layout(object container, LayoutEventArgs args) { if (container is ToolStripPanel) { return(false); } if (container is ToolStrip) { return(LayoutToolStrip((ToolStrip)container)); } Control parent = container as Control; FlowLayoutSettings settings; if (parent is FlowLayoutPanel) { settings = (parent as FlowLayoutPanel).LayoutSettings; } else { settings = default_settings; } // Nothing to layout, exit method if (parent.Controls.Count == 0) { return(false); } // Use DisplayRectangle so that parent.Padding is honored. Rectangle_ parentDisplayRectangle = parent.DisplayRectangle; Drawing.Point_ currentLocation; // Set our starting Point_ based on flow direction switch (settings.FlowDirection) { case FlowDirection.BottomUp: currentLocation = new Point_(parentDisplayRectangle.Left, parentDisplayRectangle.Bottom); break; case FlowDirection.LeftToRight: case FlowDirection.TopDown: default: currentLocation = parentDisplayRectangle.Location; break; case FlowDirection.RightToLeft: currentLocation = new Point_(parentDisplayRectangle.Right, parentDisplayRectangle.Top); break; } bool forceFlowBreak = false; List <Control> rowControls = new List <Control> (); foreach (Control c in parent.Controls) { // Only apply layout to visible controls. if (!c.Visible) { continue; } // Resize any AutoSize controls to their preferred size if (c.AutoSize == true) { Size_ new_size = c.GetPreferredSize(c.Size); c.SetBoundsInternal(c.Left, c.Top, new_size.Width, new_size.Height, BoundsSpecified.None); } switch (settings.FlowDirection) { case FlowDirection.BottomUp: // Decide if it's time to start a new column // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) { currentLocation.X = FinishColumn(rowControls); currentLocation.Y = parentDisplayRectangle.Bottom; forceFlowBreak = false; rowControls.Clear(); } } // Offset the right margin and set the control to our point currentLocation.Offset(0, c.Margin.Bottom * -1); c.SetBoundsInternal(currentLocation.X + c.Margin.Left, currentLocation.Y - c.Height, c.Width, c.Height, BoundsSpecified.None); // Update our location pointer currentLocation.Y -= (c.Height + c.Margin.Top); break; case FlowDirection.LeftToRight: default: // Decide if it's time to start a new row // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents && !(parent is ToolStripPanel)) { if ((parentDisplayRectangle.Width + parentDisplayRectangle.Left - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) { currentLocation.Y = FinishRow(rowControls); currentLocation.X = parentDisplayRectangle.Left; forceFlowBreak = false; rowControls.Clear(); } } // Offset the left margin and set the control to our point currentLocation.Offset(c.Margin.Left, 0); c.SetBoundsInternal(currentLocation.X, currentLocation.Y + c.Margin.Top, c.Width, c.Height, BoundsSpecified.None); // Update our location pointer currentLocation.X += c.Width + c.Margin.Right; break; case FlowDirection.RightToLeft: // Decide if it's time to start a new row // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) { currentLocation.Y = FinishRow(rowControls); currentLocation.X = parentDisplayRectangle.Right; forceFlowBreak = false; rowControls.Clear(); } } // Offset the right margin and set the control to our point currentLocation.Offset(c.Margin.Right * -1, 0); c.SetBoundsInternal(currentLocation.X - c.Width, currentLocation.Y + c.Margin.Top, c.Width, c.Height, BoundsSpecified.None); // Update our location pointer currentLocation.X -= (c.Width + c.Margin.Left); break; case FlowDirection.TopDown: // Decide if it's time to start a new column // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((parentDisplayRectangle.Height + parentDisplayRectangle.Top - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) { currentLocation.X = FinishColumn(rowControls); currentLocation.Y = parentDisplayRectangle.Top; forceFlowBreak = false; rowControls.Clear(); } } // Offset the top margin and set the control to our point currentLocation.Offset(0, c.Margin.Top); c.SetBoundsInternal(currentLocation.X + c.Margin.Left, currentLocation.Y, c.Width, c.Height, BoundsSpecified.None); // Update our location pointer currentLocation.Y += c.Height + c.Margin.Bottom; break; } // Add it to our list of things to adjust the second dimension of rowControls.Add(c); // If user set a flowbreak on this control, it will be the last one in this row/column if (settings.GetFlowBreak(c)) { forceFlowBreak = true; } } // Set the control heights/widths for the last row/column if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft) { FinishRow(rowControls); } else { FinishColumn(rowControls); } return(false); }
private void LayoutControls(TableLayoutPanel panel) { TableLayoutSettings settings = panel.LayoutSettings; int border_width = TableLayoutPanel.GetCellBorderWidth(panel.CellBorderStyle); int columns = panel.actual_positions.GetLength(0); int rows = panel.actual_positions.GetLength(1); Point_ current_pos = new Point_(panel.DisplayRectangle.Left + border_width, panel.DisplayRectangle.Top + border_width); for (int y = 0; y < rows; y++) { for (int x = 0; x < columns; x++) { Control c = panel.actual_positions[x, y]; if (c != null && c != dummy_control) { Size_ preferred; if (c.AutoSize) { preferred = c.PreferredSize; } else { preferred = c.ExplicitBounds.Size; } int new_x = 0; int new_y = 0; int new_width = 0; int new_height = 0; // Figure out the width of the control int column_width = panel.column_widths[x]; for (int i = 1; i < Math.Min(settings.GetColumnSpan(c), panel.column_widths.Length); i++) { column_width += panel.column_widths[x + i]; } if (c.Dock == DockStyle.Fill || c.Dock == DockStyle.Top || c.Dock == DockStyle.Bottom || ((c.Anchor & AnchorStyles.Left) == AnchorStyles.Left && (c.Anchor & AnchorStyles.Right) == AnchorStyles.Right)) { new_width = column_width - c.Margin.Left - c.Margin.Right; } else { new_width = Math.Min(preferred.Width, column_width - c.Margin.Left - c.Margin.Right); } // Figure out the height of the control int column_height = panel.row_heights[y]; for (int i = 1; i < Math.Min(settings.GetRowSpan(c), panel.row_heights.Length); i++) { column_height += panel.row_heights[y + i]; } if (c.Dock == DockStyle.Fill || c.Dock == DockStyle.Left || c.Dock == DockStyle.Right || ((c.Anchor & AnchorStyles.Top) == AnchorStyles.Top && (c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom)) { new_height = column_height - c.Margin.Top - c.Margin.Bottom; } else { new_height = Math.Min(preferred.Height, column_height - c.Margin.Top - c.Margin.Bottom); } // Figure out the left location of the control if (c.Dock == DockStyle.Left || c.Dock == DockStyle.Fill || (c.Anchor & AnchorStyles.Left) == AnchorStyles.Left) { new_x = current_pos.X + c.Margin.Left; } else if (c.Dock == DockStyle.Right || (c.Anchor & AnchorStyles.Right) == AnchorStyles.Right) { new_x = (current_pos.X + column_width) - new_width - c.Margin.Right; } else // (center control) { new_x = (current_pos.X + (column_width - c.Margin.Left - c.Margin.Right) / 2) + c.Margin.Left - (new_width / 2); } // Figure out the top location of the control if (c.Dock == DockStyle.Top || c.Dock == DockStyle.Fill || (c.Anchor & AnchorStyles.Top) == AnchorStyles.Top) { new_y = current_pos.Y + c.Margin.Top; } else if (c.Dock == DockStyle.Bottom || (c.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom) { new_y = (current_pos.Y + column_height) - new_height - c.Margin.Bottom; } else // (center control) { new_y = (current_pos.Y + (column_height - c.Margin.Top - c.Margin.Bottom) / 2) + c.Margin.Top - (new_height / 2); } c.SetBoundsInternal(new_x, new_y, new_width, new_height, BoundsSpecified.None); } current_pos.Offset(panel.column_widths[x] + border_width, 0); } current_pos.Offset((-1 * current_pos.X) + border_width + panel.DisplayRectangle.Left, panel.row_heights[y] + border_width); } }
// ToolStrips use the same FlowLayout, but is made up of ToolStripItems which // are Components instead of Controls, so we have to duplicate this login for // ToolStripItems. private bool LayoutToolStrip(ToolStrip parent) { FlowLayoutSettings settings; settings = (FlowLayoutSettings)parent.LayoutSettings; // Nothing to layout, exit method if (parent.Items.Count == 0) { return(false); } foreach (ToolStripItem tsi in parent.Items) { tsi.SetPlacement(ToolStripItemPlacement.Main); } // Use DisplayRectangle so that parent.Padding is honored. Rectangle_ parentDisplayRectangle = parent.DisplayRectangle; Drawing.Point_ currentLocation; // Set our starting Point_ based on flow direction switch (settings.FlowDirection) { case FlowDirection.BottomUp: currentLocation = new Point_(parentDisplayRectangle.Left, parentDisplayRectangle.Bottom); break; case FlowDirection.LeftToRight: case FlowDirection.TopDown: default: currentLocation = parentDisplayRectangle.Location; break; case FlowDirection.RightToLeft: currentLocation = new Point_(parentDisplayRectangle.Right, parentDisplayRectangle.Top); break; } bool forceFlowBreak = false; List <ToolStripItem> rowControls = new List <ToolStripItem> (); foreach (ToolStripItem c in parent.Items) { // Only apply layout to visible controls. if (!c.Available) { continue; } // Resize any AutoSize controls to their preferred size if (c.AutoSize == true) { c.SetBounds(new Rectangle_(c.Location, c.GetPreferredSize(c.Size))); } switch (settings.FlowDirection) { case FlowDirection.BottomUp: // Decide if it's time to start a new column // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) { currentLocation.X = FinishColumn(rowControls); currentLocation.Y = parentDisplayRectangle.Bottom; forceFlowBreak = false; rowControls.Clear(); } } // Offset the right margin and set the control to our point currentLocation.Offset(0, c.Margin.Bottom * -1); c.Location = new Point_(currentLocation.X + c.Margin.Left, currentLocation.Y - c.Height); // Update our location pointer currentLocation.Y -= (c.Height + c.Margin.Top); break; case FlowDirection.LeftToRight: default: // Decide if it's time to start a new row // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((parentDisplayRectangle.Width - currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) { currentLocation.Y = FinishRow(rowControls); currentLocation.X = parentDisplayRectangle.Left; forceFlowBreak = false; rowControls.Clear(); } } // Offset the left margin and set the control to our point currentLocation.Offset(c.Margin.Left, 0); c.Location = new Point_(currentLocation.X, currentLocation.Y + c.Margin.Top); // Update our location pointer currentLocation.X += c.Width + c.Margin.Right; break; case FlowDirection.RightToLeft: // Decide if it's time to start a new row // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((currentLocation.X) < (c.Width + c.Margin.Left + c.Margin.Right) || forceFlowBreak) { currentLocation.Y = FinishRow(rowControls); currentLocation.X = parentDisplayRectangle.Right; forceFlowBreak = false; rowControls.Clear(); } } // Offset the right margin and set the control to our point currentLocation.Offset(c.Margin.Right * -1, 0); c.Location = new Point_(currentLocation.X - c.Width, currentLocation.Y + c.Margin.Top); // Update our location pointer currentLocation.X -= (c.Width + c.Margin.Left); break; case FlowDirection.TopDown: // Decide if it's time to start a new column // - Our settings must be WrapContents, and we ran out of room or the previous control's FlowBreak == true if (settings.WrapContents) { if ((parentDisplayRectangle.Height - currentLocation.Y) < (c.Height + c.Margin.Top + c.Margin.Bottom) || forceFlowBreak) { currentLocation.X = FinishColumn(rowControls); currentLocation.Y = parentDisplayRectangle.Top; forceFlowBreak = false; rowControls.Clear(); } } // Offset the top margin and set the control to our point currentLocation.Offset(0, c.Margin.Top); c.Location = new Point_(currentLocation.X + c.Margin.Left, currentLocation.Y); // Update our location pointer currentLocation.Y += c.Height + c.Margin.Bottom; break; } // Add it to our list of things to adjust the second dimension of rowControls.Add(c); // If user set a flowbreak on this control, it will be the last one in this row/column if (settings.GetFlowBreak(c)) { forceFlowBreak = true; } } int final_height = 0; // Set the control heights/widths for the last row/column if (settings.FlowDirection == FlowDirection.LeftToRight || settings.FlowDirection == FlowDirection.RightToLeft) { final_height = FinishRow(rowControls); } else { FinishColumn(rowControls); } if (final_height > 0) { parent.SetBoundsInternal(parent.Left, parent.Top, parent.Width, final_height + parent.Padding.Bottom, BoundsSpecified.None); } return(false); }