Begind creating new layout system.
This commit is contained in:
@@ -7,7 +7,7 @@ using Dashboard.Pal;
|
|||||||
|
|
||||||
namespace Dashboard.Drawing
|
namespace Dashboard.Drawing
|
||||||
{
|
{
|
||||||
public record struct RectangleDrawInfo(Vector2 Position, ComputedBox Box, Brush Fill, Brush? Border = null);
|
public record struct RectangleDrawInfo(Vector2 Position, Box2d Box, Brush Fill, Brush? Border = null);
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = Size)]
|
[StructLayout(LayoutKind.Explicit, Size = Size)]
|
||||||
public struct ImmediateVertex()
|
public struct ImmediateVertex()
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Dashboard.Layout
|
||||||
|
{
|
||||||
|
public class ContainerLayoutInfo : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public FlowDirection FlowDirection
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
|
} = FlowDirection.Row;
|
||||||
|
|
||||||
|
public Extents Padding
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
public virtual void ValidateLayout(ILayoutContainer container)
|
||||||
|
{
|
||||||
|
if (container.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemSolution[] items = [.. container.Select(x => new ItemSolution(x))];
|
||||||
|
|
||||||
|
// TODO: is this the actual size budget available at draw time?
|
||||||
|
Vector2 budget = container.Layout.ComputedBox.Size - Padding.ExtentSize;
|
||||||
|
|
||||||
|
IEnumerable<ItemSolution> growItems = items.Where(x => x.DisplayMode == DisplayMode.Grow);
|
||||||
|
|
||||||
|
Vector2 denominator = growItems.Any()
|
||||||
|
? growItems.Select(x => x.Layout.Size + x.Layout.Margin.ExtentSize)
|
||||||
|
.Aggregate((a, b) => a + b)
|
||||||
|
: Vector2.One;
|
||||||
|
|
||||||
|
// TODO: The layout engine assumes row layout atm. Implement other layouts.
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Length; i++)
|
||||||
|
items[i].Measure(budget, budget/denominator);
|
||||||
|
|
||||||
|
float fixedWidth = items
|
||||||
|
.Where(x => x.DisplayMode != DisplayMode.Grow)
|
||||||
|
.Sum(x => x.DesiredSize.X);
|
||||||
|
|
||||||
|
float remaining = budget.X - fixedWidth;
|
||||||
|
float star = remaining / denominator.X;
|
||||||
|
|
||||||
|
Vector2 pen = container.Layout.ComputedBox.Min + new Vector2(Padding.Left, Padding.Top);
|
||||||
|
for (int i = 0; i < items.Length; i++)
|
||||||
|
{
|
||||||
|
items[i].Measure(budget, new Vector2(star, budget.Y));
|
||||||
|
items[i].Position = pen;
|
||||||
|
pen.X += items[i].DesiredSize.X;
|
||||||
|
|
||||||
|
items[i].Finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ItemSolution(ILayoutItem item)
|
||||||
|
{
|
||||||
|
public ILayoutItem Item { get; } = item;
|
||||||
|
public Vector2 InstrinsicSize { get; } = item.CalculateIntrinsicSize();
|
||||||
|
public Vector2 DesiredSize { get; private set; }
|
||||||
|
|
||||||
|
public readonly LayoutInfo Layout => Item.Layout;
|
||||||
|
public readonly DisplayMode DisplayMode => Item.Layout.DisplayMode;
|
||||||
|
|
||||||
|
public Vector2 Position { get; set; }
|
||||||
|
|
||||||
|
public void Measure(Vector2 budget, Vector2 coefficient)
|
||||||
|
{
|
||||||
|
switch (DisplayMode)
|
||||||
|
{
|
||||||
|
case DisplayMode.None:
|
||||||
|
DesiredSize = Vector2.Zero;
|
||||||
|
break;
|
||||||
|
case DisplayMode.Fit:
|
||||||
|
DesiredSize = InstrinsicSize;
|
||||||
|
break;
|
||||||
|
case DisplayMode.Fixed:
|
||||||
|
DesiredSize = Layout.Size;
|
||||||
|
break;
|
||||||
|
case DisplayMode.Grow:
|
||||||
|
DesiredSize = Layout.Size * coefficient;
|
||||||
|
break;
|
||||||
|
case DisplayMode.Relative:
|
||||||
|
DesiredSize = Layout.Size * budget;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesiredSize = Vector2.Clamp(DesiredSize, Layout.MinimumSize, Layout.MaximumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Finish()
|
||||||
|
{
|
||||||
|
Layout.ComputedBox = new Box2d(Position, Position + DesiredSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Dashboard.Layout
|
||||||
|
{
|
||||||
|
public enum ContainerMode
|
||||||
|
{
|
||||||
|
Basic,
|
||||||
|
Flex,
|
||||||
|
Grid,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Dashboard.Layout
|
||||||
|
{
|
||||||
|
public enum DisplayMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Fit,
|
||||||
|
Grow,
|
||||||
|
Relative,
|
||||||
|
Fixed,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Dashboard.Layout
|
||||||
|
{
|
||||||
|
public enum FlowDirection
|
||||||
|
{
|
||||||
|
Row,
|
||||||
|
Column,
|
||||||
|
RowReverse,
|
||||||
|
ColumnReverse,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ namespace Dashboard.Layout
|
|||||||
public Vector2 CalculateSize(Vector2 limits);
|
public Vector2 CalculateSize(Vector2 limits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ILayoutContainer : ILayoutItem, IEnumerable<ILayoutItem>
|
public interface ILayoutContainer : ILayoutItem, IReadOnlyList<ILayoutItem>
|
||||||
{
|
{
|
||||||
public ContainerLayoutInfo ContainerLayout { get; }
|
public ContainerLayoutInfo ContainerLayout { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,435 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using System.Numerics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Dashboard.Layout
|
|
||||||
{
|
|
||||||
public readonly record struct ComputedBox(Vector4 Margin, Vector4 Padding, Vector4 Border, Vector2 Size)
|
|
||||||
{
|
|
||||||
public float MarginLeft => Margin.X;
|
|
||||||
public float MarginTop => Margin.Y;
|
|
||||||
public float MarginRight => Margin.Z;
|
|
||||||
public float MarginBottom => Margin.W;
|
|
||||||
|
|
||||||
public float PaddingLeft => Padding.X;
|
|
||||||
public float PaddingTop => Padding.Y;
|
|
||||||
public float PaddingRight => Padding.Z;
|
|
||||||
public float PaddingBottom => Padding.W;
|
|
||||||
|
|
||||||
public float BorderLeft => Border.X;
|
|
||||||
public float BorderTop => Border.Y;
|
|
||||||
public float BorderRight => Border.Z;
|
|
||||||
public float BorderBottom => Border.W;
|
|
||||||
|
|
||||||
public float Width => Size.X;
|
|
||||||
public float Height => Size.Y;
|
|
||||||
|
|
||||||
public Vector2 BoundingSize => new Vector2(
|
|
||||||
MarginLeft + BorderLeft + Width + BorderRight + MarginRight,
|
|
||||||
MarginTop + BorderTop + Height + BorderBottom + MarginBottom);
|
|
||||||
|
|
||||||
public Vector2 ContentSize => new Vector2(
|
|
||||||
Width - PaddingLeft - PaddingRight,
|
|
||||||
Height - PaddingTop - PaddingBottom);
|
|
||||||
|
|
||||||
public Vector4 ContentExtents => new Vector4(
|
|
||||||
PaddingLeft,
|
|
||||||
PaddingTop,
|
|
||||||
PaddingLeft + PaddingRight + Width,
|
|
||||||
PaddingTop + PaddingBottom + Height);
|
|
||||||
|
|
||||||
public Vector4 CornerRadii { get; init; } = Vector4.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LayoutBox : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private Vector4 _margin = Vector4.Zero;
|
|
||||||
private Vector4 _padding = Vector4.Zero;
|
|
||||||
private Vector4 _border = Vector4.Zero;
|
|
||||||
private Vector2 _size = Vector2.Zero;
|
|
||||||
private Vector2 _minimumSize = -Vector2.One;
|
|
||||||
private Vector2 _maximumSize = -Vector2.One;
|
|
||||||
private Vector4 _cornerRadii = Vector4.Zero;
|
|
||||||
|
|
||||||
private LayoutUnit _marginLeftUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _marginTopUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _marginRightUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _marginBottomUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _paddingLeftUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _paddingTopUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _paddingRightUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _paddingBottomUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _borderLeftUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _borderTopUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _borderRightUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _borderBottomUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _widthUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _heightUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _minimumWidthUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _minimumHeightUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _maximumWidthUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _maximumHeightUnit = LayoutUnit.Pixel;
|
|
||||||
|
|
||||||
private LayoutUnit _cornerRadiusTopLeftUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _cornerRadiusBottomLeftUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _cornerRadiusBottomRightUnit = LayoutUnit.Pixel;
|
|
||||||
private LayoutUnit _cornerRadiusTopRightUnit = LayoutUnit.Pixel;
|
|
||||||
private ComputedBox _computedBox = new ComputedBox();
|
|
||||||
|
|
||||||
public bool UpdateRequired { get; private set; } = true;
|
|
||||||
|
|
||||||
public Vector4 Margin
|
|
||||||
{
|
|
||||||
get => _margin;
|
|
||||||
set => SetField(ref _margin, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector4 Padding
|
|
||||||
{
|
|
||||||
get => _padding;
|
|
||||||
set => SetField(ref _padding, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector4 Border
|
|
||||||
{
|
|
||||||
get => _border;
|
|
||||||
set => SetField(ref _border, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 Size
|
|
||||||
{
|
|
||||||
get => _size;
|
|
||||||
set => SetField(ref _size, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 MinimumSize
|
|
||||||
{
|
|
||||||
get => _minimumSize;
|
|
||||||
set => SetField(ref _minimumSize, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 MaximumSize
|
|
||||||
{
|
|
||||||
get => _maximumSize;
|
|
||||||
set => SetField(ref _maximumSize, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector4 CornerRadii
|
|
||||||
{
|
|
||||||
get => _cornerRadii;
|
|
||||||
set => SetField(ref _cornerRadii, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MarginLeft
|
|
||||||
{
|
|
||||||
get => Margin.X;
|
|
||||||
set => Margin = Margin with { X = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MarginTop
|
|
||||||
{
|
|
||||||
get => Margin.Y;
|
|
||||||
set => Margin = Margin with { Y = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MarginRight
|
|
||||||
{
|
|
||||||
get => Margin.Z;
|
|
||||||
set => Margin = Margin with { Z = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MarginBottom
|
|
||||||
{
|
|
||||||
get => Margin.W;
|
|
||||||
set => Margin = Margin with { W = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float PaddingLeft
|
|
||||||
{
|
|
||||||
get => Padding.X;
|
|
||||||
set => Padding = Padding with { X = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float PaddingTop
|
|
||||||
{
|
|
||||||
get => Padding.Y;
|
|
||||||
set => Padding = Padding with { Y = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float PaddingRight
|
|
||||||
{
|
|
||||||
get => Padding.Z;
|
|
||||||
set => Padding = Padding with { Z = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float PaddingBottom
|
|
||||||
{
|
|
||||||
get => Padding.W;
|
|
||||||
set => Padding = Padding with { W = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float BorderLeft
|
|
||||||
{
|
|
||||||
get => Border.X;
|
|
||||||
set => Border = Border with { X = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float BorderTop
|
|
||||||
{
|
|
||||||
get => Border.Y;
|
|
||||||
set => Border = Border with { Y = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float BorderRight
|
|
||||||
{
|
|
||||||
get => Border.Z;
|
|
||||||
set => Border = Border with { Z = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float BorderBottom
|
|
||||||
{
|
|
||||||
get => Border.W;
|
|
||||||
set => Border = Border with { W = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float CornerRadiusTopLeft
|
|
||||||
{
|
|
||||||
get => CornerRadii.X;
|
|
||||||
set => CornerRadii = CornerRadii with { X = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float CornerRadiusBottomLeft
|
|
||||||
{
|
|
||||||
get => CornerRadii.Y;
|
|
||||||
set => CornerRadii = CornerRadii with { Y = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float CornerRadiusBottomRight
|
|
||||||
{
|
|
||||||
get => CornerRadii.Z;
|
|
||||||
set => CornerRadii = CornerRadii with { Z = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public float CornerRadiusTopRight
|
|
||||||
{
|
|
||||||
get => CornerRadii.W;
|
|
||||||
set => CornerRadii = CornerRadii with { W = value };
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MarginLeftUnit
|
|
||||||
{
|
|
||||||
get => _marginLeftUnit;
|
|
||||||
set => SetField(ref _marginLeftUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MarginTopUnit
|
|
||||||
{
|
|
||||||
get => _marginTopUnit;
|
|
||||||
set => SetField(ref _marginTopUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MarginRightUnit
|
|
||||||
{
|
|
||||||
get => _marginRightUnit;
|
|
||||||
set => SetField(ref _marginRightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MarginBottomUnit
|
|
||||||
{
|
|
||||||
get => _marginBottomUnit;
|
|
||||||
set => SetField(ref _marginBottomUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit PaddingLeftUnit
|
|
||||||
{
|
|
||||||
get => _paddingLeftUnit;
|
|
||||||
set => SetField(ref _paddingLeftUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit PaddingTopUnit
|
|
||||||
{
|
|
||||||
get => _paddingTopUnit;
|
|
||||||
set => SetField(ref _paddingTopUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit PaddingRightUnit
|
|
||||||
{
|
|
||||||
get => _paddingRightUnit;
|
|
||||||
set => SetField(ref _paddingRightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit PaddingBottomUnit
|
|
||||||
{
|
|
||||||
get => _paddingBottomUnit;
|
|
||||||
set => SetField(ref _paddingBottomUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit BorderLeftUnit
|
|
||||||
{
|
|
||||||
get => _borderLeftUnit;
|
|
||||||
set => SetField(ref _borderLeftUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit BorderTopUnit
|
|
||||||
{
|
|
||||||
get => _borderTopUnit;
|
|
||||||
set => SetField(ref _borderTopUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit BorderRightUnit
|
|
||||||
{
|
|
||||||
get => _borderRightUnit;
|
|
||||||
set => SetField(ref _borderRightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit BorderBottomUnit
|
|
||||||
{
|
|
||||||
get => _borderBottomUnit;
|
|
||||||
set => SetField(ref _borderBottomUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit WidthUnit
|
|
||||||
{
|
|
||||||
get => _widthUnit;
|
|
||||||
set => SetField(ref _widthUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit HeightUnit
|
|
||||||
{
|
|
||||||
get => _heightUnit;
|
|
||||||
set => SetField(ref _heightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MinimumWidthUnit
|
|
||||||
{
|
|
||||||
get => _minimumWidthUnit;
|
|
||||||
set => SetField(ref _minimumWidthUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MinimumHeightUnit
|
|
||||||
{
|
|
||||||
get => _minimumHeightUnit;
|
|
||||||
set => SetField(ref _minimumHeightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MaximumWidthUnit
|
|
||||||
{
|
|
||||||
get => _maximumWidthUnit;
|
|
||||||
set => SetField(ref _maximumWidthUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit MaximumHeightUnit
|
|
||||||
{
|
|
||||||
get => _maximumHeightUnit;
|
|
||||||
set => SetField(ref _maximumHeightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit CornerRadiusTopLeftUnit
|
|
||||||
{
|
|
||||||
get => _cornerRadiusTopLeftUnit;
|
|
||||||
set => SetField(ref _cornerRadiusTopLeftUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit CornerRadiusBottomLeftUnit
|
|
||||||
{
|
|
||||||
get => _cornerRadiusBottomLeftUnit;
|
|
||||||
set => SetField(ref _cornerRadiusBottomLeftUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit CornerRadiusBottomRightUnit
|
|
||||||
{
|
|
||||||
get => _cornerRadiusBottomRightUnit;
|
|
||||||
set => SetField(ref _cornerRadiusBottomRightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutUnit CornerRadiusTopRightUnit
|
|
||||||
{
|
|
||||||
get => _cornerRadiusTopRightUnit;
|
|
||||||
set => SetField(ref _cornerRadiusTopRightUnit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputedBox ComputedBox
|
|
||||||
{
|
|
||||||
get => _computedBox;
|
|
||||||
private set => SetField(ref _computedBox, value, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
|
||||||
|
|
||||||
public ComputedBox ComputeLayout(Vector2 intrinsic, Vector2 dpi, Vector2 area, Vector2 star)
|
|
||||||
{
|
|
||||||
// TODO: take intrinsic into account.
|
|
||||||
Vector4 margin = Compute(_margin, dpi, area, star, _marginLeftUnit, _marginTopUnit, _marginRightUnit, _marginBottomUnit);
|
|
||||||
Vector4 padding = Compute(_padding, dpi, area, star, _paddingLeftUnit, _paddingTopUnit, _paddingRightUnit, _paddingBottomUnit);
|
|
||||||
Vector4 border = Compute(_border, dpi, area, star, _borderLeftUnit, _borderTopUnit, _borderRightUnit, _borderBottomUnit);
|
|
||||||
|
|
||||||
Vector2 size = Compute(_size, dpi, area, star, _widthUnit, _heightUnit);
|
|
||||||
Vector2 minimumSize = Compute(_minimumSize, dpi, area, star, _minimumWidthUnit, _minimumHeightUnit);
|
|
||||||
Vector2 maximumSize = Compute(_maximumSize, dpi, area, star, _maximumWidthUnit, _maximumHeightUnit);
|
|
||||||
Vector4 cornerRadii = Compute(_cornerRadii, dpi, area, star, _cornerRadiusTopLeftUnit,
|
|
||||||
_cornerRadiusBottomLeftUnit, _cornerRadiusBottomRightUnit, _cornerRadiusTopRightUnit);
|
|
||||||
|
|
||||||
size = Vector2.Clamp(size, minimumSize, maximumSize);
|
|
||||||
|
|
||||||
ComputedBox = new ComputedBox(margin, padding, border, size)
|
|
||||||
{
|
|
||||||
CornerRadii = cornerRadii,
|
|
||||||
};
|
|
||||||
|
|
||||||
UpdateRequired = false;
|
|
||||||
return ComputedBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Compute(float value, float dpi, float length, float star, LayoutUnit unit)
|
|
||||||
{
|
|
||||||
const float dpiToMm = 0f;
|
|
||||||
const float dpiToPt = 0f;
|
|
||||||
|
|
||||||
return unit switch
|
|
||||||
{
|
|
||||||
LayoutUnit.Pixel => value,
|
|
||||||
LayoutUnit.Millimeter => value * dpi * dpiToMm,
|
|
||||||
LayoutUnit.Percent => value * length,
|
|
||||||
LayoutUnit.Point => value * dpi * dpiToPt,
|
|
||||||
LayoutUnit.Star => value * star,
|
|
||||||
_ => throw new ArgumentException(nameof(unit)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Vector2 Compute(Vector2 value, Vector2 dpi, Vector2 size, Vector2 star, LayoutUnit xUnit, LayoutUnit yUnit)
|
|
||||||
{
|
|
||||||
return new Vector2(
|
|
||||||
Compute(value.X, dpi.X, size.X, star.X, xUnit),
|
|
||||||
Compute(value.Y, dpi.Y, size.Y, star.Y, yUnit));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Vector4 Compute(Vector4 value, Vector2 dpi, Vector2 size, Vector2 star, LayoutUnit xUnit, LayoutUnit yUnit, LayoutUnit zUnit, LayoutUnit wUnit)
|
|
||||||
{
|
|
||||||
return new Vector4(
|
|
||||||
Compute(value.X, dpi.X, size.X, star.X, xUnit),
|
|
||||||
Compute(value.Y, dpi.Y, size.Y, star.Y, yUnit),
|
|
||||||
Compute(value.Z, dpi.X, size.X, star.X, zUnit),
|
|
||||||
Compute(value.W, dpi.Y, size.Y, star.Y, wUnit));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool SetField<T>(ref T field, T value, bool updateRequired = true, [CallerMemberName] string? propertyName = null)
|
|
||||||
{
|
|
||||||
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
|
||||||
field = value;
|
|
||||||
UpdateRequired |= updateRequired;
|
|
||||||
OnPropertyChanged(propertyName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -6,68 +5,54 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Dashboard.Layout
|
namespace Dashboard.Layout
|
||||||
{
|
{
|
||||||
public enum DisplayMode
|
public class LayoutInfo : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
None,
|
/// <summary>
|
||||||
Inline,
|
/// Changes the control display.
|
||||||
Block,
|
/// </summary>
|
||||||
}
|
public DisplayMode DisplayMode
|
||||||
|
|
||||||
public enum ContainerMode
|
|
||||||
{
|
|
||||||
Basic,
|
|
||||||
Flex,
|
|
||||||
Grid,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum FlowDirection
|
|
||||||
{
|
|
||||||
Row,
|
|
||||||
Column,
|
|
||||||
RowReverse,
|
|
||||||
ColumnReverse,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PositionMode
|
|
||||||
{
|
|
||||||
Absolute,
|
|
||||||
Relative,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum OverflowMode
|
|
||||||
{
|
|
||||||
Hidden,
|
|
||||||
Overflow,
|
|
||||||
ScrollHorizontal,
|
|
||||||
ScrollVertical,
|
|
||||||
ScrollBoth,
|
|
||||||
}
|
|
||||||
|
|
||||||
public record struct TrackInfo(float Width, LayoutUnit Unit)
|
|
||||||
{
|
|
||||||
public static readonly TrackInfo Default = new TrackInfo(0, LayoutUnit.Auto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ContainerLayoutInfo : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private ContainerMode _containerMode;
|
|
||||||
private FlowDirection _flowDirection = FlowDirection.Row;
|
|
||||||
|
|
||||||
public ObservableCollection<TrackInfo> Rows { get; } = new ObservableCollection<TrackInfo>() { TrackInfo.Default };
|
|
||||||
|
|
||||||
public ObservableCollection<TrackInfo> Columns { get; } =
|
|
||||||
new ObservableCollection<TrackInfo>() { TrackInfo.Default };
|
|
||||||
|
|
||||||
public ContainerMode ContainerMode
|
|
||||||
{
|
{
|
||||||
get => _containerMode;
|
get;
|
||||||
set => SetField(ref _containerMode, value);
|
set => SetField(ref field, value);
|
||||||
|
} = DisplayMode.Fit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes how overflows are handled.
|
||||||
|
/// </summary>
|
||||||
|
public OverflowMode OverflowMode
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
|
} = OverflowMode.Hidden;
|
||||||
|
|
||||||
|
public Vector2 Size
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowDirection FlowDirection
|
public Vector2 MaximumSize
|
||||||
{
|
{
|
||||||
get => _flowDirection;
|
get;
|
||||||
set => SetField(ref _flowDirection, value);
|
set => SetField(ref field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 MinimumSize
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Extents Margin
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Box2d ComputedBox
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set => SetField(ref field, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
@@ -85,87 +70,4 @@ namespace Dashboard.Layout
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LayoutInfo : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private DisplayMode _displayMode = DisplayMode.Inline;
|
|
||||||
private PositionMode _positionMode = PositionMode.Relative;
|
|
||||||
private OverflowMode _overflowMode = OverflowMode.Overflow;
|
|
||||||
private int _row = 0;
|
|
||||||
private int _column = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes the control display.
|
|
||||||
/// </summary>
|
|
||||||
public DisplayMode DisplayMode
|
|
||||||
{
|
|
||||||
get => _displayMode;
|
|
||||||
set => SetField(ref _displayMode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes how the control is positioned.
|
|
||||||
/// </summary>
|
|
||||||
public PositionMode PositionMode
|
|
||||||
{
|
|
||||||
get => _positionMode;
|
|
||||||
set => SetField(ref _positionMode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes how overflows are handled.
|
|
||||||
/// </summary>
|
|
||||||
public OverflowMode OverflowMode
|
|
||||||
{
|
|
||||||
get => _overflowMode;
|
|
||||||
set => SetField(ref _overflowMode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutBox Box { get; } = new LayoutBox();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The row of the control in a grid container.
|
|
||||||
/// </summary>
|
|
||||||
public int Row
|
|
||||||
{
|
|
||||||
get => _row;
|
|
||||||
set => SetField(ref _row, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The column of the control in a grid container.
|
|
||||||
/// </summary>
|
|
||||||
public int Column
|
|
||||||
{
|
|
||||||
get => _column;
|
|
||||||
set => SetField(ref _column, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
|
||||||
|
|
||||||
public LayoutInfo()
|
|
||||||
{
|
|
||||||
Box.PropertyChanged += BoxOnPropertyChanged;
|
|
||||||
// Rows.CollectionChanged += RowsChanged;
|
|
||||||
// Columns.CollectionChanged += ColumnsChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BoxOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(Box));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
|
||||||
{
|
|
||||||
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
|
||||||
field = value;
|
|
||||||
OnPropertyChanged(propertyName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,364 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Dashboard.Layout
|
|
||||||
{
|
|
||||||
public record struct LayoutItemSolution(ILayoutItem Item, ComputedBox Solution);
|
|
||||||
|
|
||||||
public class LayoutSolution
|
|
||||||
{
|
|
||||||
public ILayoutContainer Container { get; }
|
|
||||||
public IReadOnlyList<LayoutItemSolution> Items { get; }
|
|
||||||
|
|
||||||
private LayoutSolution(ILayoutContainer container, IEnumerable<LayoutItemSolution> itemSolutions)
|
|
||||||
{
|
|
||||||
Container = container;
|
|
||||||
Items = itemSolutions.ToList().AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LayoutSolution CalculateLayout<T1>(T1 container, Vector2 limits, int iterations = 3, float absTol = 0.001f, float relTol = 0.01f)
|
|
||||||
where T1 : ILayoutContainer
|
|
||||||
{
|
|
||||||
switch (container.ContainerLayout.ContainerMode)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case ContainerMode.Basic:
|
|
||||||
return SolveForBasicLayout(container, limits, iterations, absTol, relTol);
|
|
||||||
case ContainerMode.Flex:
|
|
||||||
return SolveForFlex(container, limits, iterations, absTol, relTol);
|
|
||||||
case ContainerMode.Grid:
|
|
||||||
return SolveForGrid(container, limits, iterations, absTol, relTol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LayoutSolution SolveForGrid<T1>(T1 container, Vector2 limits, int iterations, float absTol, float relTol) where T1 : ILayoutContainer
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LayoutSolution SolveForFlex<T1>(T1 container, Vector2 limits,int iterations, float absTol, float relTol) where T1 : ILayoutContainer
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LayoutSolution SolveForBasicLayout<T1>(T1 container, Vector2 limits, int iterations, float absTol, float relTol) where T1 : ILayoutContainer
|
|
||||||
{
|
|
||||||
int count = container.Count();
|
|
||||||
LayoutItemSolution[] items = new LayoutItemSolution[count];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
foreach (ILayoutItem item in container)
|
|
||||||
{
|
|
||||||
items[i++] = new LayoutItemSolution(item, default);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool limitX = limits.X > 0;
|
|
||||||
bool limitY = limits.Y > 0;
|
|
||||||
|
|
||||||
while (iterations-- > 0)
|
|
||||||
{
|
|
||||||
Vector2 pen = Vector2.Zero;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
foreach (ILayoutItem item in container)
|
|
||||||
{
|
|
||||||
Vector2 size = item.CalculateIntrinsicSize();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LayoutSolution(container, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
private record TrackSolution(TrackInfo Track)
|
|
||||||
{
|
|
||||||
public bool Auto => Track.Unit == LayoutUnit.Auto;
|
|
||||||
|
|
||||||
public bool Absolute => Track.Unit.IsAbsolute();
|
|
||||||
|
|
||||||
public float Requested { get; private set; }
|
|
||||||
public float Value { get; private set; }
|
|
||||||
|
|
||||||
public float Result { get; set; } = 0.0f;
|
|
||||||
public bool IsFrozen { get; set; } = false;
|
|
||||||
|
|
||||||
public void CalculateRequested(float dpi, float rel, float star)
|
|
||||||
{
|
|
||||||
Requested = new Metric(Track.Unit, Track.Width).Compute(dpi, rel, star);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Freeze()
|
|
||||||
{
|
|
||||||
if (IsFrozen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IsFrozen = true;
|
|
||||||
Result = Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private delegate float GetItemLength<in T1>(float dpi, float rel, float star, T1 item)
|
|
||||||
where T1 : ILayoutItem;
|
|
||||||
|
|
||||||
private TrackSolution[] SolveForGridTracks<T1, T2, T3>(
|
|
||||||
float limit,
|
|
||||||
T1 tracks,
|
|
||||||
T2 container,
|
|
||||||
int iterations,
|
|
||||||
float absTol,
|
|
||||||
float relTol,
|
|
||||||
Func<int, T3> getItemTrack,
|
|
||||||
GetItemLength<T3> getItemLength)
|
|
||||||
where T1 : IList<TrackInfo>
|
|
||||||
where T2 : ILayoutContainer
|
|
||||||
where T3 : ILayoutItem
|
|
||||||
{
|
|
||||||
int itemCount = container.Count();
|
|
||||||
bool auto = limit < 0;
|
|
||||||
TrackSolution[] solution = new TrackSolution[tracks.Count];
|
|
||||||
|
|
||||||
foreach (TrackSolution track in solution)
|
|
||||||
{
|
|
||||||
if (track.Absolute) {
|
|
||||||
// FIXME: pass DPI here.
|
|
||||||
track.CalculateRequested(96f, limit, 0);
|
|
||||||
track.Freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (iterations-- > 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < tracks.Count; i++)
|
|
||||||
{
|
|
||||||
solution[i].Freeze();
|
|
||||||
}
|
|
||||||
|
|
||||||
return solution;
|
|
||||||
}
|
|
||||||
|
|
||||||
// private static void GetIntrinsicGridSizes<T1, T2>(Span<float> cols, Span<float> rows, T1 parent, T2 items)
|
|
||||||
// where T1 : ILayoutItem
|
|
||||||
// where T2 : IEnumerable<ILayoutItem>
|
|
||||||
// {
|
|
||||||
// CopyToSpan(rows, parent.Layout.Rows);
|
|
||||||
// CopyToSpan(cols, parent.Layout.Columns);
|
|
||||||
//
|
|
||||||
// foreach (ILayoutItem item in items)
|
|
||||||
// {
|
|
||||||
// int col = Math.Clamp(item.Layout.Column, 0, cols.Length - 1);
|
|
||||||
// int row = Math.Clamp(item.Layout.Row, 0, rows.Length - 1);
|
|
||||||
//
|
|
||||||
// bool autoCols = parent.Layout.Columns[col] < 0;
|
|
||||||
// bool autoRows = parent.Layout.Rows[row] < 0;
|
|
||||||
//
|
|
||||||
// if (!autoRows && !autoCols)
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// Vector2 size = item.CalculateIntrinsicSize();
|
|
||||||
// cols[col] = autoCols ? Math.Max(size.X, cols[col]) : cols[col];
|
|
||||||
// rows[row] = autoRows ? Math.Max(size.Y, rows[row]) : rows[row];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static Vector2 CalculateIntrinsicSize<T1, T2>(T1 parent, T2 items)
|
|
||||||
// where T1 : ILayoutItem
|
|
||||||
// where T2 : IEnumerable<ILayoutItem>
|
|
||||||
// {
|
|
||||||
// // Copy layout details.
|
|
||||||
// Span<float> cols = stackalloc float[parent.Layout.Columns.Count];
|
|
||||||
// Span<float> rows = stackalloc float[parent.Layout.Rows.Count];
|
|
||||||
//
|
|
||||||
// GetIntrinsicGridSizes(cols, rows, parent, items);
|
|
||||||
//
|
|
||||||
// float width = parent.Layout.Margin.X + parent.Layout.Margin.Z + parent.Layout.Padding.X + parent.Layout.Padding.Z + SumSpan<float>(cols);
|
|
||||||
// float height = parent.Layout.Margin.Y + parent.Layout.Margin.W + parent.Layout.Padding.Y + parent.Layout.Padding.W + SumSpan<float>(rows);
|
|
||||||
//
|
|
||||||
// return new Vector2(width, height);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static GridResult Layout<T1, T2>(T1 parent, T2 items, Vector2 limits, int iterations = 3, float abstol = 0.0001f, float reltol = 0.01f)
|
|
||||||
// where T1 : ILayoutItem
|
|
||||||
// where T2 : IEnumerable<ILayoutItem>
|
|
||||||
// {
|
|
||||||
// Vector4 contentSpace = parent.Layout.Margin + parent.Layout.Padding;
|
|
||||||
// Vector2 contentLimits = new Vector2(
|
|
||||||
// limits.X > 0 ? limits.X - contentSpace.X - contentSpace.Z : -1,
|
|
||||||
// limits.Y > 0 ? limits.Y - contentSpace.Y - contentSpace.W : -1);
|
|
||||||
//
|
|
||||||
// // Get rows and columns for now.
|
|
||||||
// Span<Track> cols = stackalloc Track[parent.Layout.Columns.Count];
|
|
||||||
// Span<Track> rows = stackalloc Track[parent.Layout.Rows.Count];
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < cols.Length; i++)
|
|
||||||
// {
|
|
||||||
// cols[i] = new Track(parent.Layout.Columns[i]);
|
|
||||||
//
|
|
||||||
// if (!cols[i].Auto)
|
|
||||||
// {
|
|
||||||
// cols[i].Freeze();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < rows.Length; i++)
|
|
||||||
// {
|
|
||||||
// rows[i] = new Track(parent.Layout.Rows[i]);
|
|
||||||
//
|
|
||||||
// if (!rows[i].Auto)
|
|
||||||
// {
|
|
||||||
// rows[i].Freeze();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// int freeRows = 0;
|
|
||||||
// int freeCols = 0;
|
|
||||||
// while (iterations-- > 0 && ((freeRows = CountFree(rows)) > 0 || (freeCols = CountFree(cols)) > 0))
|
|
||||||
// {
|
|
||||||
// // Calculate the remaining size.
|
|
||||||
// Vector2 remaining = contentLimits;
|
|
||||||
//
|
|
||||||
// for (int i = 0; contentLimits.X > 0 && i < cols.Length; i++)
|
|
||||||
// {
|
|
||||||
// if (cols[i].IsFrozen)
|
|
||||||
// remaining.X -= cols[i].Value;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (int i = 0; contentLimits.Y > 0 && i < rows.Length; i++)
|
|
||||||
// {
|
|
||||||
// if (rows[i].IsFrozen)
|
|
||||||
// remaining.Y -= rows[i].Value;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Vector2 childLimits = remaining / new Vector2(Math.Max(freeCols, 1), Math.Max(freeRows, 1));
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Calculate the size of each free track.
|
|
||||||
// foreach (ILayoutItem child in items)
|
|
||||||
// {
|
|
||||||
// int c = Math.Clamp(child.Layout.Column, 0, cols.Length - 1);
|
|
||||||
// int r = Math.Clamp(child.Layout.Row, 0, rows.Length - 1);
|
|
||||||
//
|
|
||||||
// bool autoRow = rows[r].Auto;
|
|
||||||
// bool autoCol = cols[c].Auto;
|
|
||||||
//
|
|
||||||
// if (!autoRow && !autoCol)
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// Vector2 childSize = child.CalculateSize(childLimits);
|
|
||||||
//
|
|
||||||
// if (autoCol)
|
|
||||||
// cols[c].Value = Math.Max(childLimits.X, childSize.X);
|
|
||||||
//
|
|
||||||
// if (autoRow)
|
|
||||||
// rows[r].Value = Math.Max(childLimits.Y, childSize.Y);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Calculate for errors and decide to freeze them.
|
|
||||||
//
|
|
||||||
// for (int i = 0; limits.X > 0 && i < cols.Length; i++)
|
|
||||||
// {
|
|
||||||
// if (WithinTolerance(cols[i].Value, childLimits.X, abstol, reltol))
|
|
||||||
// {
|
|
||||||
// cols[i].Freeze();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (int i = 0; limits.Y > 0 && i < rows.Length; i++)
|
|
||||||
// {
|
|
||||||
// if (WithinTolerance(rows[i].Value, childLimits.Y, abstol, reltol))
|
|
||||||
// {
|
|
||||||
// rows[i].Freeze();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Vector2 size = new Vector2(
|
|
||||||
// parent.Layout.Margin.X + parent.Layout.Margin.Z + parent.Layout.Padding.X + parent.Layout.Padding.Z,
|
|
||||||
// parent.Layout.Margin.Y + parent.Layout.Margin.W + parent.Layout.Padding.Y + parent.Layout.Padding.W);
|
|
||||||
//
|
|
||||||
// foreach (ref Track col in cols)
|
|
||||||
// {
|
|
||||||
// col.Freeze();
|
|
||||||
// size.X += col.Result;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// foreach (ref Track row in rows)
|
|
||||||
// {
|
|
||||||
// row.Freeze();
|
|
||||||
// size.Y += row.Result;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (limits.X > 0) size.X = Math.Max(size.X, limits.X);
|
|
||||||
// if (limits.Y > 0) size.Y = Math.Max(size.Y, limits.Y);
|
|
||||||
//
|
|
||||||
// // Temporary solution
|
|
||||||
// return new GridResult(size, cols.ToArray().Select(x => x.Result).ToArray(), rows.ToArray().Select(x => x.Result).ToArray());
|
|
||||||
//
|
|
||||||
// static int CountFree(Span<Track> tracks)
|
|
||||||
// {
|
|
||||||
// int i = 0;
|
|
||||||
// foreach (Track track in tracks)
|
|
||||||
// {
|
|
||||||
// if (!track.IsFrozen)
|
|
||||||
// i++;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static void CopyToSpan<T1, T2>(Span<T1> span, T2 items)
|
|
||||||
// where T2 : IEnumerable<T1>
|
|
||||||
// {
|
|
||||||
// using IEnumerator<T1> iterator = items.GetEnumerator();
|
|
||||||
// for (int i = 0; i < span.Length; i++)
|
|
||||||
// {
|
|
||||||
// if (!iterator.MoveNext())
|
|
||||||
// break;
|
|
||||||
//
|
|
||||||
// span[i] = iterator.Current;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static T1 SumSpan<T1>(ReadOnlySpan<T1> span)
|
|
||||||
// where T1 : struct, INumber<T1>
|
|
||||||
// {
|
|
||||||
// T1 value = default;
|
|
||||||
//
|
|
||||||
// foreach (T1 item in span)
|
|
||||||
// {
|
|
||||||
// value += item;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return value;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static bool WithinTolerance<T>(T value, T limit, T abstol, T reltol)
|
|
||||||
// where T : INumber<T>
|
|
||||||
// {
|
|
||||||
// T tol = T.Max(abstol, value * reltol);
|
|
||||||
// return T.Abs(value - limit) < tol;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public record GridResult(Vector2 Size, float[] Columns, float[] Rows)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private record struct Track(float Request)
|
|
||||||
// {
|
|
||||||
// public bool Auto => Request < 0;
|
|
||||||
//
|
|
||||||
// public bool IsFrozen { get; private set; } = false;
|
|
||||||
// public float Value { get; set; } = Request;
|
|
||||||
//
|
|
||||||
// public float Result { get; private set; }
|
|
||||||
//
|
|
||||||
// public void Freeze()
|
|
||||||
// {
|
|
||||||
// Result = Value;
|
|
||||||
// IsFrozen = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Dashboard.Layout
|
||||||
|
{
|
||||||
|
public enum OverflowMode
|
||||||
|
{
|
||||||
|
Hidden,
|
||||||
|
Overflow,
|
||||||
|
ScrollHorizontal,
|
||||||
|
ScrollVertical,
|
||||||
|
ScrollBoth,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Dashboard.Layout;
|
||||||
|
|
||||||
|
namespace Dashboard
|
||||||
|
{
|
||||||
|
public static class LayoutExtensions
|
||||||
|
{
|
||||||
|
extension<T>(T item)
|
||||||
|
where T : ILayoutItem
|
||||||
|
{
|
||||||
|
public DisplayMode DisplayMode
|
||||||
|
{
|
||||||
|
get => item.Layout.DisplayMode;
|
||||||
|
set => item.Layout.DisplayMode = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OverflowMode OverflowMode
|
||||||
|
{
|
||||||
|
get => item.Layout.OverflowMode;
|
||||||
|
set => item.Layout.OverflowMode = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Size
|
||||||
|
{
|
||||||
|
get => item.Layout.Size;
|
||||||
|
set => item.Layout.Size = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Width
|
||||||
|
{
|
||||||
|
get => item.Size.X;
|
||||||
|
set => item.Size = new Vector2(value, item.Size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Height
|
||||||
|
{
|
||||||
|
get => item.Size.Y;
|
||||||
|
set => item.Size = new Vector2(item.Size.X, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 MaximumSize
|
||||||
|
{
|
||||||
|
get => item.Layout.MaximumSize;
|
||||||
|
set => item.Layout.MaximumSize = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MaximumWidth
|
||||||
|
{
|
||||||
|
get => item.MaximumSize.X;
|
||||||
|
set => item.MaximumSize = new Vector2(value, item.MaximumSize.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MaximumHeight
|
||||||
|
{
|
||||||
|
get => item.MaximumSize.Y;
|
||||||
|
set => item.MaximumSize = new Vector2(item.MaximumSize.X, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 MinimumSize
|
||||||
|
{
|
||||||
|
get => item.Layout.MinimumSize;
|
||||||
|
set => item.Layout.MinimumSize = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MinimumWidth
|
||||||
|
{
|
||||||
|
get => item.MinimumSize.X;
|
||||||
|
set => item.MinimumSize = new Vector2(value, item.MinimumSize.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MinimumHeight
|
||||||
|
{
|
||||||
|
get => item.MinimumSize.Y;
|
||||||
|
set => item.MinimumSize = new Vector2(item.MinimumSize.X, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Extents Margin
|
||||||
|
{
|
||||||
|
get => item.Layout.Margin;
|
||||||
|
set => item.Layout.Margin = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MarginLeft
|
||||||
|
{
|
||||||
|
get => item.Layout.Margin.Left;
|
||||||
|
set => item.Layout.Margin = new Extents(value, item.MarginTop, item.MarginRight, item.MarginBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MarginTop
|
||||||
|
{
|
||||||
|
get => item.Layout.Margin.Top;
|
||||||
|
set => item.Layout.Margin = new Extents(item.MarginLeft, value, item.MarginRight, item.MarginBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MarginRight
|
||||||
|
{
|
||||||
|
get => item.Layout.Margin.Right;
|
||||||
|
set => item.Layout.Margin = new Extents(item.MarginLeft, item.MarginTop, value, item.MarginBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MarginBottom
|
||||||
|
{
|
||||||
|
get => item.Layout.Margin.Bottom;
|
||||||
|
set => item.Layout.Margin = new Extents(item.MarginLeft, item.MarginTop, item.MarginRight, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Box2d ComputedBox
|
||||||
|
{
|
||||||
|
get => item.Layout.ComputedBox;
|
||||||
|
set => item.Layout.ComputedBox = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension<T> (T item)
|
||||||
|
where T : ILayoutContainer
|
||||||
|
{
|
||||||
|
public FlowDirection FlowDirection
|
||||||
|
{
|
||||||
|
get => item.ContainerLayout.FlowDirection;
|
||||||
|
set => item.ContainerLayout.FlowDirection = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Extents Padding
|
||||||
|
{
|
||||||
|
get => item.ContainerLayout.Padding;
|
||||||
|
set => item.ContainerLayout.Padding = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -127,10 +127,8 @@ namespace Dashboard.OpenGL.Drawing
|
|||||||
int z = Context.ExtensionRequire<IDeviceContextBase>().IncrementZ();
|
int z = Context.ExtensionRequire<IDeviceContextBase>().IncrementZ();
|
||||||
Color color = (rectangle.Fill as SolidColorBrush)?.Color ?? Color.LightGray;
|
Color color = (rectangle.Fill as SolidColorBrush)?.Color ?? Color.LightGray;
|
||||||
Vector4 colorV = new Vector4(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
|
Vector4 colorV = new Vector4(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
|
||||||
Vector4 margin = rectangle.Box.Margin;
|
Vector2 size = rectangle.Box.Size;
|
||||||
Vector4 border = rectangle.Box.Border;
|
Box2d box = Box2d.FromPositionAndSize(rectangle.Position, size);
|
||||||
Vector2 size = rectangle.Box.Size + new Vector2(border.X + border.Z, border.Y = border.W);
|
|
||||||
Box2d box = Box2d.FromPositionAndSize(rectangle.Position + new Vector2(margin.X + border.X, margin.Y + border.Y), size);
|
|
||||||
|
|
||||||
Rectangle(box, z, colorV);
|
Rectangle(box, z, colorV);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
public ContainerLayoutInfo ContainerLayout { get; } = new ContainerLayoutInfo();
|
public ContainerLayoutInfo ContainerLayout { get; } = new ContainerLayoutInfo();
|
||||||
|
|
||||||
|
ILayoutItem IReadOnlyList<ILayoutItem>.this[int index] => _controls[index];
|
||||||
|
|
||||||
public event EventHandler<ContainerChildAddedEventArgs>? ChildAdded;
|
public event EventHandler<ContainerChildAddedEventArgs>? ChildAdded;
|
||||||
public event EventHandler<ContainerChildRemovedEventArgs>? ChildRemoved;
|
public event EventHandler<ContainerChildRemovedEventArgs>? ChildRemoved;
|
||||||
|
|
||||||
@@ -33,7 +35,10 @@ namespace Dashboard.Controls
|
|||||||
if (!IsLayoutEnabled || IsLayoutValid)
|
if (!IsLayoutEnabled || IsLayoutValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// LayoutSolution solution = LayoutSolution.CalculateLayout(this, ClientArea.Size);
|
ContainerLayout.ValidateLayout(this);
|
||||||
|
|
||||||
|
foreach (var child in this)
|
||||||
|
child.InvalidateLayout();
|
||||||
|
|
||||||
base.ValidateLayout();
|
base.ValidateLayout();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Events;
|
using Dashboard.Events;
|
||||||
using Dashboard.Layout;
|
using Dashboard.Layout;
|
||||||
@@ -29,7 +29,7 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
public Control? Parent { get; private set; } = null;
|
public Control? Parent { get; private set; } = null;
|
||||||
public bool Disposed { get; private set; }
|
public bool Disposed { get; private set; }
|
||||||
public virtual Box2d ClientArea { get; set; }
|
public virtual Box2d ClientArea => Layout.ComputedBox;
|
||||||
public bool IsFocused => _owner?.FocusedControl == this;
|
public bool IsFocused => _owner?.FocusedControl == this;
|
||||||
|
|
||||||
public Brush Background { get; set; } = new SolidColorBrush(Color.Transparent);
|
public Brush Background { get; set; } = new SolidColorBrush(Color.Transparent);
|
||||||
@@ -39,6 +39,7 @@ namespace Dashboard.Controls
|
|||||||
public bool IsLayoutEnabled { get; private set; } = true;
|
public bool IsLayoutEnabled { get; private set; } = true;
|
||||||
protected bool IsLayoutValid { get; set; } = false;
|
protected bool IsLayoutValid { get; set; } = false;
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
public event EventHandler<DeviceContext>? Painting;
|
public event EventHandler<DeviceContext>? Painting;
|
||||||
public event EventHandler<TickEventArgs>? AnimationTick;
|
public event EventHandler<TickEventArgs>? AnimationTick;
|
||||||
public event EventHandler? OwnerChanged;
|
public event EventHandler? OwnerChanged;
|
||||||
@@ -175,7 +176,18 @@ namespace Dashboard.Controls
|
|||||||
IsLayoutValid = false;
|
IsLayoutValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void SetField<T>(ref T field, T value, [CallerMemberName]string name = "")
|
||||||
|
{
|
||||||
|
field = value;
|
||||||
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
OnPropertyChanged(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged(string name)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
|
}
|
||||||
|
|
||||||
protected static Exception NoOwnerException => new Exception("No form owns this control");
|
protected static Exception NoOwnerException => new Exception("No form owns this control");
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Events;
|
using Dashboard.Events;
|
||||||
using Dashboard.Pal;
|
using Dashboard.Pal;
|
||||||
@@ -23,13 +24,11 @@ namespace Dashboard.Controls
|
|||||||
Window.Title = _title ?? "";
|
Window.Title = _title ?? "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Brush Background { get; set; } = new SolidColorBrush(Color.SlateGray);
|
|
||||||
public Control? FocusedControl { get; private set; } = null;
|
public Control? FocusedControl { get; private set; } = null;
|
||||||
|
|
||||||
public override Box2d ClientArea
|
public override Box2d ClientArea
|
||||||
{
|
{
|
||||||
get => new Box2d(0, 0, Window.ClientSize.Width, Window.ClientSize.Height);
|
get => new Box2d(0, 0, Window.ClientSize.Width, Window.ClientSize.Height);
|
||||||
set { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<WindowCloseEvent>? Closing;
|
public event EventHandler<WindowCloseEvent>? Closing;
|
||||||
@@ -37,9 +36,18 @@ namespace Dashboard.Controls
|
|||||||
public Form(IWindow window)
|
public Form(IWindow window)
|
||||||
{
|
{
|
||||||
Window = window;
|
Window = window;
|
||||||
window.Form = this;
|
Window.Form = this;
|
||||||
|
|
||||||
Window.Title = _title;
|
Window.Title = _title;
|
||||||
|
Window.EventRaised += WindowEventRaised;
|
||||||
|
Background = new SolidColorBrush(Color.SlateGray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WindowEventRaised(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (e is ResizeEventArgs)
|
||||||
|
{
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Focus(Control control)
|
public void Focus(Control control)
|
||||||
@@ -65,6 +73,11 @@ namespace Dashboard.Controls
|
|||||||
if (Background is SolidColorBrush solidColorBrush)
|
if (Background is SolidColorBrush solidColorBrush)
|
||||||
dcb.ClearColor(solidColorBrush.Color);
|
dcb.ClearColor(solidColorBrush.Color);
|
||||||
|
|
||||||
|
if (!IsLayoutValid)
|
||||||
|
{
|
||||||
|
ValidateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Control child in this)
|
foreach (Control child in this)
|
||||||
child.SendEvent(this, new PaintEventArgs(dc));
|
child.SendEvent(this, new PaintEventArgs(dc));
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,7 @@ namespace Dashboard.Controls
|
|||||||
protected void CalculateSize(DeviceContext dc)
|
protected void CalculateSize(DeviceContext dc)
|
||||||
{
|
{
|
||||||
Box2d box = dc.ExtensionRequire<ITextRenderer>().MeasureText(Font.Base, TextSize, Text);
|
Box2d box = dc.ExtensionRequire<ITextRenderer>().MeasureText(Font.Base, TextSize, Text);
|
||||||
// _intrinsicSize = box.Size;
|
_intrinsicSize = box.Size;
|
||||||
// Layout.Size = box.Size;
|
|
||||||
// ClientArea = new Box2d(ClientArea.Min, ClientArea.Min + Layout.Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnPaint(DeviceContext dc)
|
public override void OnPaint(DeviceContext dc)
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Collections.Specialized;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
@@ -36,12 +37,11 @@ namespace Dashboard.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MessageBox : Form
|
public class MessageBox : Form
|
||||||
{
|
{
|
||||||
private MessageBoxIcon _icon;
|
|
||||||
private MessageBoxButtons _buttons;
|
private MessageBoxButtons _buttons;
|
||||||
private ImageBox _iconBox = new ImageBox();
|
private readonly ImageBox _iconBox = new ImageBox();
|
||||||
private Label _label = new Label();
|
private readonly Label _label = new Label();
|
||||||
private Container _main = new Container();
|
private readonly Container _main = new Container();
|
||||||
private Container _buttonsContainer = new Container();
|
private readonly Container _buttonsContainer = new Container();
|
||||||
|
|
||||||
private Image? IconImage
|
private Image? IconImage
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
public MessageBoxIcon Icon
|
public MessageBoxIcon Icon
|
||||||
{
|
{
|
||||||
get => _icon;
|
get;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
IconImage = value switch
|
IconImage = value switch
|
||||||
@@ -63,7 +63,7 @@ namespace Dashboard.Controls
|
|||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
_icon = value;
|
field = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ namespace Dashboard.Controls
|
|||||||
public string? Message
|
public string? Message
|
||||||
{
|
{
|
||||||
get => _label.Text;
|
get => _label.Text;
|
||||||
set => _label.Text = value ?? String.Empty;
|
set => _label.Text = value ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageBoxButtons Buttons
|
public MessageBoxButtons Buttons
|
||||||
@@ -99,21 +99,24 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
public MessageBox(IWindow window) : base(window)
|
public MessageBox(IWindow window) : base(window)
|
||||||
{
|
{
|
||||||
// Layout.Rows.Clear();
|
Add(_main);
|
||||||
// Layout.Rows.Add(-1);
|
_main.DisplayMode = Dashboard.Layout.DisplayMode.Grow;
|
||||||
// Layout.Rows.Add(48);
|
_main.Size = Vector2.One;
|
||||||
//
|
_main.FlowDirection = Dashboard.Layout.FlowDirection.Row;
|
||||||
// Add(_main);
|
_main.Padding = new Extents(4f);
|
||||||
// _main.Layout.Columns.Clear();
|
|
||||||
// _main.Layout.Columns.Add(48);
|
|
||||||
// _main.Layout.Columns.Add(-1);
|
|
||||||
|
|
||||||
_main.Add(_iconBox);
|
_main.Add(_iconBox);
|
||||||
|
_iconBox.Size = new Vector2(72f);
|
||||||
|
_iconBox.Margin = new Extents(0f, 4f, 2f, 0f);
|
||||||
|
_iconBox.Background = new SolidColorBrush(Color.Purple);
|
||||||
|
|
||||||
_main.Add(_label);
|
_main.Add(_label);
|
||||||
_label.Layout.Column = 1;
|
_label.DisplayMode = Dashboard.Layout.DisplayMode.Fit;
|
||||||
|
_iconBox.Margin = new Extents(2f, 4f, 0f, 0f);
|
||||||
|
_iconBox.Background = new SolidColorBrush(Color.Black);
|
||||||
|
|
||||||
Add(_buttonsContainer);
|
Add(_buttonsContainer);
|
||||||
_buttonsContainer.Layout.Row = 1;
|
_buttonsContainer.Padding = new Extents(2f, 4f, 2f, 4f);
|
||||||
|
|
||||||
CustomButtons.CollectionChanged += (sender, ea) => UpdateButtons();
|
CustomButtons.CollectionChanged += (sender, ea) => UpdateButtons();
|
||||||
|
|
||||||
@@ -139,19 +142,19 @@ namespace Dashboard.Controls
|
|||||||
_ => s_ok,
|
_ => s_ok,
|
||||||
};
|
};
|
||||||
|
|
||||||
// _buttonsContainer.Clear();
|
_buttonsContainer.Clear();
|
||||||
// _buttonsContainer.Layout.Columns.Clear();
|
for (int i = 0; i < list.Count; i++)
|
||||||
// for (int i = 0; i < list.Count; i++)
|
{
|
||||||
// {
|
string str = list[i];
|
||||||
// _buttonsContainer.Layout.Columns.Add(-1);
|
|
||||||
// string str = list[i];
|
Button button = new Button() { Text = str };
|
||||||
//
|
button.Clicked += (sender, ea) => ButtonClicked(sender, ea, i);
|
||||||
// Button button = new Button() { Text = str };
|
button.Layout.Margin = new Extents(2f, 0f, 2f, 0f);
|
||||||
// button.Clicked += (sender, ea) => ButtonClicked(sender, ea, i);
|
// button.Layout.Column = i;
|
||||||
// button.Layout.Column = i;
|
_buttonsContainer.Add(button);
|
||||||
// _buttonsContainer.Add(button);
|
button.Background = new SolidColorBrush(Color.Red);
|
||||||
// Add(button);
|
// Add(button);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ButtonClicked(object? sender, EventArgs ea, int i)
|
private void ButtonClicked(object? sender, EventArgs ea, int i)
|
||||||
|
|||||||
@@ -3,15 +3,14 @@ using Dashboard.BlurgText;
|
|||||||
using Dashboard.BlurgText.OpenGL;
|
using Dashboard.BlurgText.OpenGL;
|
||||||
using Dashboard.Controls;
|
using Dashboard.Controls;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Events;
|
|
||||||
using Dashboard.OpenGL;
|
using Dashboard.OpenGL;
|
||||||
using Dashboard.OpenTK.PAL2;
|
using Dashboard.OpenTK.PAL2;
|
||||||
using Dashboard.Pal;
|
using Dashboard.Pal;
|
||||||
using Dashboard.StbImage;
|
using Dashboard.StbImage;
|
||||||
using OpenTK.Graphics.OpenGL;
|
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
using OpenTK.Platform;
|
using OpenTK.Platform;
|
||||||
using TK = OpenTK.Platform.Toolkit;
|
using TK = OpenTK.Platform.Toolkit;
|
||||||
|
|
||||||
Application app = new Pal2Application(new ToolkitOptions()
|
Application app = new Pal2Application(new ToolkitOptions()
|
||||||
{
|
{
|
||||||
ApplicationName = "DashTerm",
|
ApplicationName = "DashTerm",
|
||||||
@@ -57,59 +56,16 @@ window.Title = "DashTerm";
|
|||||||
TK.Window.SetMinClientSize(window.WindowHandle, 300, 200);
|
TK.Window.SetMinClientSize(window.WindowHandle, 300, 200);
|
||||||
TK.Window.SetClientSize(window.WindowHandle, new Vector2i(320, 240));
|
TK.Window.SetClientSize(window.WindowHandle, new Vector2i(320, 240));
|
||||||
TK.Window.SetBorderStyle(window.WindowHandle, WindowBorderStyle.ResizableBorder);
|
TK.Window.SetBorderStyle(window.WindowHandle, WindowBorderStyle.ResizableBorder);
|
||||||
// TK.Window.SetTransparencyMode(wnd, WindowTransparencyMode.TransparentFramebuffer, 0.1f);
|
|
||||||
|
|
||||||
GLDeviceContext context = (GLDeviceContext)window.DeviceContext;
|
GLDeviceContext context = (GLDeviceContext)window.DeviceContext;
|
||||||
|
|
||||||
context.GLContext.MakeCurrent();
|
context.GLContext.MakeCurrent();
|
||||||
context.GLContext.SwapGroup.SwapInterval = 1;
|
context.GLContext.SwapGroup.SwapInterval = 1;
|
||||||
|
|
||||||
GL.Disable(EnableCap.DepthTest);
|
|
||||||
GL.Enable(EnableCap.Blend);
|
|
||||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
|
||||||
GL.ColorMask(true, true, true, true);
|
|
||||||
|
|
||||||
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
|
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
|
||||||
|
|
||||||
window.DeviceContext.ExtensionRequire<IDeviceContextBase>().ScaleOverride = 1.5f;
|
window.DeviceContext.ExtensionRequire<IDeviceContextBase>().ScaleOverride = 1.5f;
|
||||||
|
|
||||||
IDirectRendering direct = window.DeviceContext.ExtensionRequire<IDirectRendering>();
|
|
||||||
IImmediateMode imm = window.DeviceContext.ExtensionRequire<IImmediateMode>();
|
|
||||||
ImmediateVertex[] vertices = new ImmediateVertex[]
|
|
||||||
{ // x, y, z, r, g, b, a
|
|
||||||
new ImmediateVertex(new System.Numerics.Vector3(-0.5f, -0.5f, 0.0f), System.Numerics.Vector2.Zero, new System.Numerics.Vector4(1, 0, 0, 1)),
|
|
||||||
new ImmediateVertex(new System.Numerics.Vector3(+0.5f, -0.5f, 0.0f), System.Numerics.Vector2.Zero, new System.Numerics.Vector4(0, 1, 0, 1)),
|
|
||||||
new ImmediateVertex(new System.Numerics.Vector3(+0.0f, +0.5f, 0.0f), System.Numerics.Vector2.Zero, new System.Numerics.Vector4(0, 0, 1, 1)),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
window.EventRaised += (sender, eventArgs) =>
|
|
||||||
{
|
|
||||||
if (eventArgs is not PaintEventArgs paint)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// window.DeviceContext.Begin();
|
|
||||||
var dcb = window.DeviceContext.ExtensionRequire<IDeviceContextBase>();
|
|
||||||
dcb.ResetTransforms();
|
|
||||||
dcb.ClearDepth();
|
|
||||||
|
|
||||||
imm.Rectangle(
|
|
||||||
new Dashboard.Box2d(
|
|
||||||
new System.Numerics.Vector2(30, 30),
|
|
||||||
new System.Numerics.Vector2(140, 110)),
|
|
||||||
0.2f,
|
|
||||||
new System.Numerics.Vector4(1, 1, 0, 1));
|
|
||||||
imm.Line(
|
|
||||||
new System.Numerics.Vector2(180, 40),
|
|
||||||
new System.Numerics.Vector2(290, 180),
|
|
||||||
6,
|
|
||||||
0.2f,
|
|
||||||
new System.Numerics.Vector4(0, 1, 1, 1));
|
|
||||||
imm.DrawImmediate(new ImmediateDrawCall(MeshPrimitive.Triangle, vertices.AsMemory()));
|
|
||||||
|
|
||||||
// window.DeviceContext.End();
|
|
||||||
};
|
|
||||||
|
|
||||||
app.Run(true, source.Token);
|
app.Run(true, source.Token);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user