namespace TheaterGui.Controls; using System; using System.Collections; class Container : GuiObject { private List _LayoutData = new .() ~ delete _; public List Children = new .() ~ DeleteContainerAndItems!(_); //Entries => LayoutData without nulls public this(StringView pName, StringView pComponentName = "Container") : base(pName, pComponentName) { } ///Reorder all entries /// @params w The Maximum width that the container should take 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); for(var i in ((Container)e).Children) { i.X += x + Padding + e.Padding; i.Y += y + Padding + e.Padding; } } if(x+e.Width+e.Padding > w-Padding) //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.X = x + e.Padding; x = x + e.Width + 2*e.Padding; e.Y = y + e.Padding; if(x > maxWidth) maxWidth = x; if(rowHeight < e.Height+2*e.Padding) rowHeight = e.Height+2*e.Padding; } Width = maxWidth + 2*Padding; Height = y + rowHeight + 2*Padding; } ///Add a new item to the list of items public void AddChild(GuiObject pToAdd) { _LayoutData.Add(pToAdd); Children.Add(pToAdd); pToAdd.Parent = this; } public virtual void InsertBefore(GuiObject pToAdd, GuiObject 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(GuiObject pToAdd, GuiObject 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 GuiObject 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; } }