protected virtual void OnLayout(LayoutEventArgs e) { if (Initialized && !_state[s_stateInLayout]) { _state[s_stateInLayout] = true; try { Margin = DefaultMargin; CachedBoundsMode = true; try { // dont layout in the constructor that's just tacky. bool parentNeedsLayout = LayoutEngine.Layout(this, e); } finally { CachedBoundsMode = false; } ToolStripPanelCell cell = RowManager.GetNextVisibleCell(Cells.Count - 1, /*forward*/ false); if (cell is null) { ApplyCachedBounds(); } else if (Orientation == Orientation.Horizontal) { OnLayoutHorizontalPostFix(); } else { OnLayoutVerticalPostFix(); } } finally { _state[s_stateInLayout] = false; } } }
private void OnLayoutVerticalPostFix() { ToolStripPanelCell cell = RowManager.GetNextVisibleCell(Cells.Count - 1, /*forward*/ false); // figure out how much space we actually need to free. int spaceToFree = cell.CachedBounds.Bottom - RowManager.DisplayRectangle.Bottom; if (spaceToFree <= 0) { // we're all good. Just apply the cached bounds. ApplyCachedBounds(); return; } // STEP 1 remove empty space in the row. // since layout sisuspended, we'll need to watch changes to the margin // as a result of calling FreeSpaceFromRow. int[] margins = new int[Cells.Count]; for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; margins[i] = c.Margin.Top; } spaceToFree -= RowManager.FreeSpaceFromRow(spaceToFree); // now apply those changes to the cached bounds. for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; Rectangle cachedBounds = c.CachedBounds; cachedBounds.X = Math.Max(0, cachedBounds.X - margins[i] - c.Margin.Top); c.CachedBounds = cachedBounds; } if (spaceToFree <= 0) { ApplyCachedBounds(); return; } // STEP 2 change the size of the remaing ToolStrips from Bottom to Top. int[] cellOffsets = null; for (int i = Cells.Count - 1; i >= 0; i--) { ToolStripPanelCell currentCell = Cells[i] as ToolStripPanelCell; if (currentCell.Visible) { Size minSize = GetMinimumSize(currentCell.Control as ToolStrip); Rectangle cachedBounds = currentCell.CachedBounds; // found some space to free. if (cachedBounds.Height > minSize.Height) { spaceToFree -= (cachedBounds.Height - minSize.Height); // make sure we dont take more space than we need - if spaceToFree is less than 0, add back in. cachedBounds.Height = (spaceToFree < 0) ? minSize.Height + -spaceToFree : minSize.Height; // we're not reperforming a layout, so we need to adjust the next cell for (int j = i + 1; j < Cells.Count; j++) { if (cellOffsets is null) { cellOffsets = new int[Cells.Count]; } cellOffsets[j] += Math.Max(0, currentCell.CachedBounds.Height - cachedBounds.Height); } currentCell.CachedBounds = cachedBounds; } } if (spaceToFree <= 0) { break; } } // fixup for items before it shrinking. if (cellOffsets != null) { for (int i = 0; i < Cells.Count; i++) { ToolStripPanelCell c = Cells[i] as ToolStripPanelCell; Rectangle cachedBounds = c.CachedBounds; cachedBounds.Y -= cellOffsets[i]; c.CachedBounds = cachedBounds; } } ApplyCachedBounds(); }