New controls, main view
This commit is contained in:
@@ -5,14 +5,15 @@ using TerminalUI.ViewExtensions;
|
||||
|
||||
namespace TerminalUI.Controls;
|
||||
|
||||
public class Grid<T> : View<T>
|
||||
public class Grid<T> : ChildContainerView<T>
|
||||
{
|
||||
private delegate void WithSizes(Span<int> widths, Span<int> heights);
|
||||
|
||||
private delegate TResult WithSizes<TResult>(Span<int> widths, Span<int> heights);
|
||||
|
||||
private const int ToBeCalculated = -1;
|
||||
private readonly ObservableCollection<IView> _children = new();
|
||||
public ReadOnlyObservableCollection<IView> Children { get; }
|
||||
public GridChildInitializer<T> ChildInitializer { get; }
|
||||
public ObservableCollection<RowDefinition> RowDefinitions { get; } = new();
|
||||
public ObservableCollection<ColumnDefinition> ColumnDefinitions { get; } = new();
|
||||
public ObservableCollection<RowDefinition> RowDefinitions { get; } = new() {RowDefinition.Star(1)};
|
||||
public ObservableCollection<ColumnDefinition> ColumnDefinitions { get; } = new() {ColumnDefinition.Star(1)};
|
||||
|
||||
public object? ColumnDefinitionsObject
|
||||
{
|
||||
@@ -62,35 +63,76 @@ public class Grid<T> : View<T>
|
||||
}
|
||||
}
|
||||
|
||||
public Grid()
|
||||
{
|
||||
ChildInitializer = new GridChildInitializer<T>(this);
|
||||
Children = new ReadOnlyObservableCollection<IView>(_children);
|
||||
_children.CollectionChanged += (o, e) =>
|
||||
public override Size GetRequestedSize()
|
||||
=> WithCalculatedSize((columnWidths, rowHeights) =>
|
||||
{
|
||||
if (Attached)
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
|
||||
for (var i = 0; i < columnWidths.Length; i++)
|
||||
{
|
||||
if (e.NewItems?.OfType<IView>() is { } newItems)
|
||||
{
|
||||
foreach (var newItem in newItems)
|
||||
{
|
||||
newItem.Attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationContext?.EventLoop.RequestRerender();
|
||||
width += columnWidths[i];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Size GetRequestedSize() => throw new NotImplementedException();
|
||||
for (var i = 0; i < rowHeights.Length; i++)
|
||||
{
|
||||
height += rowHeights[i];
|
||||
}
|
||||
|
||||
return new Size(width, height);
|
||||
}, new Option<Size>(new Size(0, 0), false));
|
||||
|
||||
protected override void DefaultRenderer(Position position, Size size)
|
||||
=> WithCalculatedSize((columnWidths, rowHeights) =>
|
||||
{
|
||||
foreach (var child in Children)
|
||||
{
|
||||
var positionExtension = child.GetExtension<GridPositionExtension>();
|
||||
var x = positionExtension?.Column ?? 0;
|
||||
var y = positionExtension?.Row ?? 0;
|
||||
|
||||
var width = columnWidths[x];
|
||||
var height = rowHeights[y];
|
||||
|
||||
var left = 0;
|
||||
var top = 0;
|
||||
|
||||
for (var i = 0; i < x; i++)
|
||||
{
|
||||
left += columnWidths[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < y; i++)
|
||||
{
|
||||
top += rowHeights[i];
|
||||
}
|
||||
|
||||
child.Render(new Position(position.X + left, position.Y + top), new Size(width, height));
|
||||
}
|
||||
}, new Option<Size>(size, true));
|
||||
|
||||
private void WithCalculatedSize(WithSizes actionWithSizes, Option<Size> size)
|
||||
{
|
||||
//TODO: Optimize it, dont calculate all of these only if there is Auto value(s)
|
||||
WithCalculatedSize(Helper, size);
|
||||
|
||||
object? Helper(Span<int> widths, Span<int> heights)
|
||||
{
|
||||
actionWithSizes(widths, heights);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private TResult WithCalculatedSize<TResult>(WithSizes<TResult> actionWithSizes, Option<Size> size)
|
||||
{
|
||||
//TODO: Optimize it, dont calculate all of these, only if there is Auto value(s)
|
||||
var columns = ColumnDefinitions.Count;
|
||||
Span<int> allWidth = stackalloc int[columns * RowDefinitions.Count];
|
||||
Span<int> allHeight = stackalloc int[columns * RowDefinitions.Count];
|
||||
var rows = RowDefinitions.Count;
|
||||
|
||||
if (columns < 1) columns = 1;
|
||||
if (rows < 1) rows = 1;
|
||||
|
||||
Span<int> allWidth = stackalloc int[columns * rows];
|
||||
Span<int> allHeight = stackalloc int[columns * rows];
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
@@ -104,38 +146,47 @@ public class Grid<T> : View<T>
|
||||
}
|
||||
|
||||
Span<int> columnWidths = stackalloc int[columns];
|
||||
Span<int> rowHeights = stackalloc int[RowDefinitions.Count];
|
||||
Span<int> rowHeights = stackalloc int[rows];
|
||||
|
||||
var usedWidth = 0;
|
||||
var widthStars = 0;
|
||||
for (var i = 0; i < columnWidths.Length; i++)
|
||||
{
|
||||
if (ColumnDefinitions[i].Type == GridUnitType.Pixel)
|
||||
{
|
||||
columnWidths[i] = ColumnDefinitions[i].Value;
|
||||
}
|
||||
else if (ColumnDefinitions[i].Type == GridUnitType.Star)
|
||||
else if (size.IsSome && ColumnDefinitions[i].Type == GridUnitType.Star)
|
||||
{
|
||||
widthStars += ColumnDefinitions[i].Value;
|
||||
columnWidths[i] = ToBeCalculated;
|
||||
}
|
||||
else
|
||||
{
|
||||
var max = 0;
|
||||
for (var j = 0; j < RowDefinitions.Count; j++)
|
||||
for (var j = 0; j < rows; j++)
|
||||
{
|
||||
max = Math.Max(max, allWidth.GetFromMatrix(i, j, columns));
|
||||
}
|
||||
|
||||
columnWidths[i] = max;
|
||||
}
|
||||
|
||||
if (columnWidths[i] != ToBeCalculated)
|
||||
usedWidth += columnWidths[i];
|
||||
}
|
||||
|
||||
var usedHeight = 0;
|
||||
var heightStars = 0;
|
||||
for (var i = 0; i < rowHeights.Length; i++)
|
||||
{
|
||||
if (RowDefinitions[i].Type == GridUnitType.Pixel)
|
||||
{
|
||||
rowHeights[i] = RowDefinitions[i].Value;
|
||||
}
|
||||
else if (RowDefinitions[i].Type == GridUnitType.Star)
|
||||
else if (size.IsSome && RowDefinitions[i].Type == GridUnitType.Star)
|
||||
{
|
||||
heightStars += RowDefinitions[i].Value;
|
||||
rowHeights[i] = ToBeCalculated;
|
||||
}
|
||||
else
|
||||
@@ -148,33 +199,39 @@ public class Grid<T> : View<T>
|
||||
|
||||
rowHeights[i] = max;
|
||||
}
|
||||
|
||||
if (rowHeights[i] != ToBeCalculated)
|
||||
usedHeight += rowHeights[i];
|
||||
}
|
||||
|
||||
foreach (var child in Children)
|
||||
if (size.IsSome)
|
||||
{
|
||||
var childSize = child.GetRequestedSize();
|
||||
var positionExtension = child.GetExtension<GridPositionExtension>();
|
||||
var x = positionExtension?.Column ?? 0;
|
||||
var y = positionExtension?.Row ?? 0;
|
||||
var widthLeft = size.Value.Width - usedWidth;
|
||||
var heightLeft = size.Value.Height - usedHeight;
|
||||
|
||||
var width = columnWidths[x];
|
||||
var height = rowHeights[y];
|
||||
var widthPerStart = (int) Math.Floor((double) widthLeft / widthStars);
|
||||
var heightPerStart = (int) Math.Floor((double) heightLeft / heightStars);
|
||||
|
||||
var left = 0;
|
||||
var top = 0;
|
||||
|
||||
for (var i = 0; i < x; i++)
|
||||
for (var i = 0; i < columnWidths.Length; i++)
|
||||
{
|
||||
left += columnWidths[i];
|
||||
var column = ColumnDefinitions[i];
|
||||
if (column.Type == GridUnitType.Star)
|
||||
{
|
||||
columnWidths[i] = widthPerStart * column.Value;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < y; i++)
|
||||
for (var i = 0; i < rowHeights.Length; i++)
|
||||
{
|
||||
top += rowHeights[i];
|
||||
var row = RowDefinitions[i];
|
||||
if (row.Type == GridUnitType.Star)
|
||||
{
|
||||
rowHeights[i] = heightPerStart * row.Value;
|
||||
}
|
||||
}
|
||||
|
||||
child.Render(new Position(left, top), new Size(width, height));
|
||||
}
|
||||
|
||||
return actionWithSizes(columnWidths, rowHeights);
|
||||
}
|
||||
|
||||
public void SetRowDefinitions(string value)
|
||||
@@ -190,7 +247,7 @@ public class Grid<T> : View<T>
|
||||
}
|
||||
else if (v.EndsWith("*"))
|
||||
{
|
||||
var starValue = int.Parse(v[0..^1]);
|
||||
var starValue = v.Length == 1 ? 1 : int.Parse(v[..^1]);
|
||||
RowDefinitions.Add(RowDefinition.Star(starValue));
|
||||
}
|
||||
else if (int.TryParse(v, out var pixelValue))
|
||||
@@ -217,7 +274,7 @@ public class Grid<T> : View<T>
|
||||
}
|
||||
else if (v.EndsWith("*"))
|
||||
{
|
||||
var starValue = int.Parse(v[0..^1]);
|
||||
var starValue = v.Length == 1 ? 1 : int.Parse(v[..^1]);
|
||||
ColumnDefinitions.Add(ColumnDefinition.Star(starValue));
|
||||
}
|
||||
else if (int.TryParse(v, out var pixelValue))
|
||||
@@ -230,19 +287,4 @@ public class Grid<T> : View<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override TChild AddChild<TChild>(TChild child)
|
||||
{
|
||||
child = base.AddChild(child);
|
||||
_children.Add(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
public override TChild AddChild<TChild, TDataContext>(TChild child, Func<T?, TDataContext?> dataContextMapper)
|
||||
where TDataContext : default
|
||||
{
|
||||
child = base.AddChild(child, dataContextMapper);
|
||||
_children.Add(child);
|
||||
return child;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user