// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Windows.Forms; using System.Windows.Forms.Layout; namespace AntdUI { /// /// GridPanel 格栅布局 /// [Description("GridPanel 格栅布局")] [ToolboxItem(true)] [DefaultProperty("Span")] [Designer(typeof(IControlDesigner))] public class GridPanel : IControl { public override Rectangle DisplayRectangle { get => ClientRectangle.DeflateRect(Padding); } /// /// 跨度 /// [Description("跨度"), Category("外观"), DefaultValue("50% 50%;50% 50%")] [Editor(typeof(System.ComponentModel.Design.MultilineStringEditor), typeof(UITypeEditor))] public string Span { get => layoutengine.Span; set { if (layoutengine.Span == value) return; layoutengine.Span = value; OSizeChanged(); } } /// /// 间距 /// [Description("间距"), Category("外观"), DefaultValue(0)] public int Gap { get => layoutengine.Gap; set { if (layoutengine.Gap == value) return; layoutengine.Gap = value; OSizeChanged(); } } #region 布局 internal void OSizeChanged() { OnSizeChanged(EventArgs.Empty); } GridLayout layoutengine = new GridLayout(); public override LayoutEngine LayoutEngine => layoutengine; internal class GridLayout : LayoutEngine { /// /// 内容大小 /// public string Span { get; set; } = "50% 50%;50% 50%"; /// /// 间距 /// public int Gap { get; set; } public override bool Layout(object container, LayoutEventArgs layoutEventArgs) { if (container is GridPanel parent) { var rect = parent.DisplayRectangle; if (!string.IsNullOrEmpty(Span) && parent.Controls.Count > 0) { var controls = new List(parent.Controls.Count); foreach (Control it in parent.Controls) { if (it.Visible) controls.Insert(0, it); } if (controls.Count > 0) { int data_count = 0; var rows = Span.Split(';', '\n'); var data = new List(rows.Length); foreach (var row in rows) { if (!string.IsNullOrEmpty(row)) { var cels = row.Split(' ', ','); var cels_tmp = new List(cels.Length); int use_width = 0; foreach (string it in cels) { var cel = it.Trim(); if (cel.EndsWith("%") && float.TryParse(cel.TrimEnd('%'), out var f)) cels_tmp.Add(f / 100F); else if (int.TryParse(cel, out var i)) { int uw = (int)Math.Round(i * Config.Dpi); cels_tmp.Add(uw); use_width += uw; } else if (float.TryParse(cel, out float f2)) cels_tmp.Add(f2); } int read_width = rect.Width - use_width; var cel_tmp = new List(cels_tmp.Count); foreach (var it in cels_tmp) { if (it is float f) cel_tmp.Add((int)Math.Round(read_width * f)); else if (it is int i) cel_tmp.Add(i); } if (cel_tmp.Count > 0) { data_count += cel_tmp.Count; data.Add(cel_tmp.ToArray()); } } } if (data_count > 0) { Rectangle[] rects; if (data_count == 1) rects = new Rectangle[1] { rect }; else { if (data.Count > 1) { int height_one = rect.Height / data.Count; var tmp_rects = new List(); int hasx = 0, hasy = 0; foreach (var item in data) { foreach (var it in item) { tmp_rects.Add(new Rectangle(rect.X + hasx, rect.Y + hasy, it, height_one)); hasx += it; } hasx = 0; hasy += height_one; } rects = tmp_rects.ToArray(); } else { var tmp_rects = new List(data[0].Length); int hasx = 0, hasy = 0; foreach (var it in data[0]) { tmp_rects.Add(new Rectangle(rect.X + hasx, rect.Y + hasy, it, rect.Height)); hasx += it; } rects = tmp_rects.ToArray(); } } HandLayout(controls, rects); } } } } return false; } void HandLayout(List controls, Rectangle[] rects) { int gap = (int)Math.Round(Gap * Config.Dpi), gap2 = gap * 2; int max_len = controls.Count; if (rects.Length < controls.Count) max_len = rects.Length; for (int i = 0; i < max_len; i++) { Control control = controls[i]; Point point = rects[i].Location; point.Offset(control.Margin.Left + gap, control.Margin.Top + gap); control.Location = point; control.Size = new Size(rects[i].Width - control.Margin.Horizontal - gap2, rects[i].Height - control.Margin.Vertical - gap2); } } } #endregion } }