123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- using System.Collections.Generic;
- using System.Drawing;
- namespace System.Windows.Forms
- {
- internal class LayoutEngine
- {
- private Control control;
- private List<LayoutTransaction> transactions = new();
- private bool suspended;
- private bool updatingLayout;
- public void SuspendLayout()
- {
- suspended = true;
- }
- public void AddTransaction(int deltaX, int deltaY)
- {
- if (updatingLayout)
- return;
- int width = control.DisplayRectangle.Width;
- int height = control.DisplayRectangle.Height;
- if (suspended)
- transactions.Add(new LayoutTransaction(deltaX, deltaY, width, height));
- else
- UpdateLayout(deltaX, deltaY, width, height);
- }
- public void AddTransaction() => AddTransaction(0, 0);
- public void ResumeLayout(bool resume)
- {
- if (resume)
- {
- foreach (LayoutTransaction tr in transactions)
- {
- UpdateLayout(tr.DeltaX, tr.DeltaY, tr.Width, tr.Height);
- }
- }
- transactions.Clear();
- suspended = false;
- }
- private Rectangle Bounds(int left, int top, int width, int height)
- {
- if (left < 0)
- left = 0;
- if (top < 0)
- top = 0;
- if (width < 0)
- width = 0;
- if (height < 0)
- height = 0;
- return new Rectangle(left, top, width, height);
- }
- private void UpdateLayout(int dx, int dy, int width, int height)
- {
- if (updatingLayout)
- return;
- updatingLayout = true;
- try
- {
- Rectangle remainingBounds = new Rectangle(control.Padding.Left + control.DefaultPadding.Left,
- control.Padding.Top + control.DefaultPadding.Top,
- width - control.Padding.Horizontal - control.DefaultPadding.Horizontal,
- height - control.Padding.Vertical - control.DefaultPadding.Vertical);
- remainingBounds.Width += dx;
- remainingBounds.Height += dy;
- // phase 1: everything except Dock = Fill
- for (int i = control.Controls.Count - 1; i >= 0; i--)
- {
- var c = control.Controls[i];
- if ((c.Anchor & AnchorStyles.Right) != 0)
- {
- if ((c.Anchor & AnchorStyles.Left) != 0)
- c.Width += dx;
- else
- c.Left += dx;
- }
- else if ((c.Anchor & AnchorStyles.Left) == 0)
- {
- c.Left += dx / 2;
- }
- if ((c.Anchor & AnchorStyles.Bottom) != 0)
- {
- if ((c.Anchor & AnchorStyles.Top) != 0)
- c.Height += dy;
- else
- c.Top += dy;
- }
- else if ((c.Anchor & AnchorStyles.Top) == 0)
- {
- c.Top += dy / 2;
- }
- if (!c.Visible)
- continue;
- switch (c.Dock)
- {
- case DockStyle.Left:
- c.Bounds = Bounds(remainingBounds.Left, remainingBounds.Top, c.Width, remainingBounds.Height);
- remainingBounds.X += c.Width;
- remainingBounds.Width -= c.Width;
- break;
- case DockStyle.Top:
- c.Bounds = Bounds(remainingBounds.Left, remainingBounds.Top, remainingBounds.Width, c.Height);
- remainingBounds.Y += c.Height;
- remainingBounds.Height -= c.Height;
- break;
- case DockStyle.Right:
- c.Bounds = Bounds(remainingBounds.Right - c.Width, remainingBounds.Top, c.Width, remainingBounds.Height);
- remainingBounds.Width -= c.Width;
- break;
- case DockStyle.Bottom:
- c.Bounds = Bounds(remainingBounds.Left, remainingBounds.Bottom - c.Height, remainingBounds.Width, c.Height);
- remainingBounds.Height -= c.Height;
- break;
- }
- }
- // phase 2: Dock = Fill
- for (int i = control.Controls.Count - 1; i >= 0; i--)
- {
- var c = control.Controls[i];
- if (!c.Visible)
- continue;
- switch (c.Dock)
- {
- case DockStyle.Fill:
- c.Bounds = Bounds(remainingBounds.Left, remainingBounds.Top, remainingBounds.Width, remainingBounds.Height);
- break;
- }
- }
- }
- finally
- {
- updatingLayout = false;
- control.OnLayout();
- }
- }
- public LayoutEngine(Control control) => this.control = control;
- private struct LayoutTransaction
- {
- public int DeltaX { get; }
- public int DeltaY { get; }
- public int Width { get; }
- public int Height { get; }
- public LayoutTransaction(int deltaX, int deltaY, int width, int height)
- {
- DeltaX = deltaX;
- DeltaY = deltaY;
- Width = width;
- Height = height;
- }
- }
- }
- }
|