namespace TheaterGui.Components; using System; using System.Collections; class Container : Component { public this(StringView pName, StringView pComponentName = "Container") : base(pName, pComponentName) { } private List _LayoutData = new .() ~ delete _; public List Children = new .() ~ DeleteContainerAndItems!(_); ///Recalculate the layout of all entries public virtual void Reorder(int32 w) { /* List {Entry, Entry, Entry, RB, Entry, Entry, RB, Entry, RB} null is a rowbreak while non null isnt a rowbreak Algorithm if the current entry is a rowbreak, reset the cursor to x = 0, y = y + height try to fit the current entry after the cursor if it fits add it, if it doesnt fit break */ int32 maxWidth = 0; //The highest width line int32 rowHeight = 0; //How high the current row is int32 x = 0; int32 y = 0; for(var e in _LayoutData) { if(e == null) { //Manual row break x = 0; y = y + rowHeight; rowHeight = 0; continue; } if(e is Container) { ((Container)e).Reorder(w); MoveChildrenRecursive((Container)e, x, y); } if(e is Toolbar) e.Width = App.Width; if(x+e.Width+e.MarginLeft > w-MarginLeft) //Change both instances of padding to 2*Padding to ensure proper padding on the leftmost side of the screen { //Automatic row break x = 0; y = y + rowHeight; rowHeight = 0; } e.[Friend]X = x + e.MarginLeft; x = x + e.Width + e.MarginLeft + e.MarginRight; e.[Friend]Y = y + e.MarginTop; if(x > maxWidth) maxWidth = x; if(rowHeight < e.Height+e.MarginTop+e.MarginBottom) rowHeight = e.Height+e.MarginTop+e.MarginBottom; } Width = maxWidth + MarginLeft + MarginRight; Height = y + rowHeight + MarginTop + MarginBottom; } private void MoveChildrenRecursive(Container c, int32 x, int32 y) { for(var i in c.Children) { i.[Friend]X += x + MarginLeft + c.MarginLeft; i.[Friend]Y += y + MarginTop + c.MarginTop; if(i is Container) MoveChildrenRecursive((Container)i, x, y); } } ///Add a new item to the list of items public void AddChild(Component pToAdd) { _LayoutData.Add(pToAdd); Children.Add(pToAdd); pToAdd.Parent = this; } public virtual void InsertBefore(Component pToAdd, Component Position, bool pReorder = true) { var idx = _LayoutData.IndexOf(Position); if(idx < 0) { delete pToAdd; //Avoid memory leaks return; } _LayoutData.Insert(idx, pToAdd); Children.Add(pToAdd); pToAdd.Parent = this; if(pReorder) App.ForceReorder(); } public virtual void InsertAfter(Component pToAdd, Component Position, bool pReorder = true) { var idx = _LayoutData.IndexOf(Position); idx++; if(idx < 0) { delete pToAdd; //Avoid memory leaks return; } _LayoutData.Insert(idx, pToAdd); Children.Add(pToAdd); pToAdd.Parent = this; if(pReorder) App.ForceReorder(); } ///Forcefully terminates the current row public void EndRow() => _LayoutData.Add(null); public override void Render() { for(var i in Children) { i.Render(); } } public override bool OnClick(int32 x, int32 y) { for(var e in Children) { if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, y)) return e.OnClick(x, y); } return false; } public override Component OnHover(int32 x, int32 y) { for(var e in Children) { if(RaylibBeef.Rectangle(e.X, e.Y, e.Width, e.Height).Overlaps(x, y)) return e.OnHover(x, y); } return null; } }