using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Barotrauma; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Graphics; namespace QICrabUI { /// /// A Grid containing children in its cells /// Dividing host into rows and columns basing on GridTemplate /// And then placing children basin on their GridCell /// public class CUILayoutGrid : CUILayout { public enum TrackSizeType { Unknown, Absolute, Relative, Fractional, } public class GridTrack { public TrackSizeType Type; public float? Absolute; public float? Relative; public float? Fractional; public float Start; public float End; public float Size; public float RealSize(float hostSize) { float size = 0; if (Absolute.HasValue) size = Absolute.Value; if (Relative.HasValue) size = Relative.Value * hostSize; return size; } public GridTrack(string value) { value = value.Trim(); float f = 0; if (value.EndsWith("fr")) { if (float.TryParse(value.Substring(0, value.Length - 2), out f)) { Fractional = f; Type = TrackSizeType.Fractional; } } if (value.EndsWith("%")) { if (float.TryParse(value.Substring(0, value.Length - 1), out f)) { Relative = f / 100f; Type = TrackSizeType.Relative; } } if (float.TryParse(value, out f)) { Absolute = f; Type = TrackSizeType.Absolute; } } public override string ToString() => $"[{Absolute},{Relative},{Fractional}]"; } List Rows = new(); List Columns = new(); public void CalculateTracks() { Rows.Clear(); Columns.Clear(); if (Host.GridTemplateRows != null) { foreach (string s in Host.GridTemplateRows.Split(' ')) { Rows.Add(new GridTrack(s)); } } if (Host.GridTemplateColumns != null) { foreach (string s in Host.GridTemplateColumns.Split(' ')) { Columns.Add(new GridTrack(s)); } } if (Rows.Count == 0) Rows.Add(new GridTrack("100%")); if (Columns.Count == 0) Columns.Add(new GridTrack("100%")); float x = 0; foreach (GridTrack track in Columns) { track.Start = x; track.Size = track.RealSize(Host.Real.Width); x += track.Size; track.End = x; } float y = 0; foreach (GridTrack track in Rows) { track.Start = y; track.Size = track.RealSize(Host.Real.Height); y += track.Size; track.End = y; } } internal override void Update() { if (Changed && Host.Children.Count > 0) { Host.InvokeOnLayoutUpdated(); CalculateTracks(); foreach (CUIComponent c in Host.Children) { float x = 0; float y = 0; float w = 0; float h = 0; int startCellX = 0; int startCellY = 0; if (c.GridStartCell != null) { startCellX = Math.Clamp(c.GridStartCell.Value.X, 0, Rows.Count); startCellY = Math.Clamp(c.GridStartCell.Value.Y, 0, Columns.Count); } int endCellX = 0; int endCellY = 0; if (c.GridEndCell != null) { endCellX = Math.Clamp(c.GridEndCell.Value.X, 0, Rows.Count); endCellY = Math.Clamp(c.GridEndCell.Value.Y, 0, Columns.Count); } CUIRect real = new CUIRect( Columns[startCellX].Start, Rows[startCellY].Start, Columns[endCellX].End - Columns[startCellX].Start, Rows[endCellY].End - Rows[startCellY].Start ); real = real.Shift(Host.Real.Position); c.AmIOkWithThisSize(real.Size); c.SetReal(real, "Grid Layout update"); } } base.Update(); } public CUILayoutGrid() : base() { } public CUILayoutGrid(CUIComponent host) : base(host) { } } }