Compare commits

..

No commits in common. "c6a9dd800857a53d7133bbc5d34b2560cb94e442" and "9b6a15c6ecaa0182985410e00f117ee4c20df5d9" have entirely different histories.

7 changed files with 22 additions and 243 deletions

@ -12,22 +12,13 @@ namespace Dashboard.Controls
public bool IsReadOnly => false;
public event EventHandler<ChildEventArgs>? ChildAdded;
public event EventHandler<ChildEventArgs>? ChildRemoved;
public void Add(Control item)
{
children.Add(item);
OnChildAdded(new ChildEventArgs(item));
}
public void Clear()
{
foreach (Control child in this)
{
OnChildRemoved(new ChildEventArgs(child));
}
children.Clear();
}
@ -48,25 +39,7 @@ namespace Dashboard.Controls
public bool Remove(Control item)
{
if (children.Remove(item))
{
OnChildRemoved(new ChildEventArgs(item));
return true;
}
return false;
}
public virtual void OnChildAdded(ChildEventArgs ea)
{
Adopt(ea.Child, this);
ChildAdded?.Invoke(this, ea);
}
public virtual void OnChildRemoved(ChildEventArgs ea)
{
Adopt(ea.Child, null);
ChildRemoved?.Invoke(this, ea);
return children.Remove(item);
}
IEnumerator IEnumerable.GetEnumerator()
@ -74,13 +47,4 @@ namespace Dashboard.Controls
return children.GetEnumerator();
}
}
public class ChildEventArgs : EventArgs
{
public Control Child { get; }
public ChildEventArgs(Control child)
{
Child = child;
}
}
}

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using Dashboard.ImmediateDraw;
using OpenTK.Mathematics;
namespace Dashboard.Controls
{
@ -9,18 +8,6 @@ namespace Dashboard.Controls
{
private readonly DrawList drawCommands = new DrawList();
public string? Id { get; set; }
public override Vector2 Position
{
get => base.Position;
set
{
base.Position = value;
InvalidateLayout();
}
}
public Style Style { get; set; } = new Style();
public float Padding
{
@ -33,8 +20,6 @@ namespace Dashboard.Controls
protected bool IsLayoutSuspended { get; private set; } = false;
protected ResizedEventArgs? LastResizeEvent { get; private set; }
public void InvalidateVisual()
{
IsVisualsValid = false;
@ -87,14 +72,6 @@ namespace Dashboard.Controls
cmd.Splice(drawCommands);
if (this is IEnumerable<Control> children)
{
foreach (Control child in children)
{
child.Paint(cmd);
}
}
cmd.PopViewport();
cmd.PopStyle();
}
@ -131,12 +108,18 @@ namespace Dashboard.Controls
LayoutValidated?.Invoke(sender, ea);
}
public override void OnResized(object sender, ResizedEventArgs ea)
protected void ValidateChildrenLayout()
{
base.OnResized(sender, ea);
if (this is IEnumerable<Control> enumerable)
{
foreach (Control child in enumerable)
{
if (child.IsLayoutValid)
continue;
LastResizeEvent = ea;
InvalidateLayout();
child.ValidateLayout();
}
}
}
}
}

@ -17,6 +17,7 @@ namespace Dashboard.Controls
protected override void ValidateLayout()
{
ValidateChildrenLayout();
}
protected override void ValidateVisual(DrawList cmd)

@ -1,31 +0,0 @@
using Dashboard.ImmediateDraw;
using Dashboard.Layout;
using OpenTK.Mathematics;
namespace Dashboard.Controls
{
public class GridBox : ContainerControl
{
protected override void ValidateLayout()
{
if (LastResizeEvent != null)
{
foreach (Control child in this)
{
GridLayoutAttribute attribute = GridLayoutAttribute.GetGridLayout(child);
attribute.Evaluate(LastResizeEvent, child.Bounds, out Rectangle newBounds);
child.Bounds = newBounds;
child.InvalidateLayout();
}
}
}
protected override void ValidateVisual(DrawList cmd)
{
cmd.Rectangle(new Rectangle(Size, Vector2.Zero));
}
}
}

@ -6,15 +6,15 @@ using OpenTK.Mathematics;
namespace Dashboard.Controls
{
/// <summary>
/// Bases for all UI elements.
/// </summary>
public abstract class UIBase : IDbAttribute
public abstract class UIBase : IDbUserdata
{
private Vector2 size;
public UIBase? Parent { get; protected set; }
public string? Id { get; set; }
public Rectangle Bounds
{
get => new Rectangle(Position + Size, Position);
@ -25,7 +25,7 @@ namespace Dashboard.Controls
}
}
public virtual Vector2 Position { get; set; }
public Vector2 Position { get; set; }
public Vector2 Size
{
@ -60,7 +60,7 @@ namespace Dashboard.Controls
public bool IsMaximumSizeSet => MaximumSize != new Vector2(-1, -1);
public bool IsMinimumSizeSet => MinimumSize != new Vector2(-1, -1);
public Dictionary<string, object> Attributes { get; } = new Dictionary<string, object>();
public Dictionary<string, object> Userdata { get; } = new Dictionary<string, object>();
public virtual void NotifyEvent(object? sender, EventArgs args)
{
@ -85,23 +85,17 @@ namespace Dashboard.Controls
}
public event EventHandler<ResizedEventArgs>? Resized;
public event EventHandler<AdoptedEventArgs>? Adopted;
public virtual void OnResized(object sender, ResizedEventArgs ea)
{
Resized?.Invoke(sender, ea);
}
protected virtual void OnAdopted(UIBase? parent)
{
Adopted?.Invoke(this, new AdoptedEventArgs(parent));
}
public bool IsDisposed { get; private set; } = false;
protected virtual void Dispose(bool disposing)
{
foreach (object userdata in Attributes.Values)
foreach (object userdata in Userdata.Values)
{
if (userdata is IDisposable disposable)
disposable.Dispose();
@ -119,12 +113,6 @@ namespace Dashboard.Controls
}
public void Dispose() => DisposeInvoker(true);
protected static void Adopt(UIBase child, UIBase? parent)
{
child.Parent = parent;
child.OnAdopted(parent);
}
}
public class ResizedEventArgs : EventArgs
@ -138,14 +126,4 @@ namespace Dashboard.Controls
OldSize = oldSize;
}
}
public class AdoptedEventArgs : EventArgs
{
public UIBase? Parent { get; }
public AdoptedEventArgs(UIBase? parent = null)
{
Parent = parent;
}
}
}

@ -5,17 +5,17 @@ using System.Collections.Generic;
namespace Dashboard
{
/// <summary>
/// Common interface for Dashboard objects that accept attributes.
/// Common interface for Dashboard objects that accept userdata.
/// </summary>
/// <remarks>
/// Dashboard will call dispose on any and all objects which implement IDisposable.
/// If this is an issue, please guard your object against this using a wrapper.
/// </remarks
public interface IDbAttribute : IDisposable
public interface IDbUserdata : IDisposable
{
/// <summary>
/// Attribute dictionary.
/// Userdata dictionary.
/// </summary>
public Dictionary<string, object> Attributes { get; }
public Dictionary<string, object> Userdata { get; }
}
}

@ -1,116 +0,0 @@
using OpenTK.Mathematics;
using Dashboard.Controls;
using System.Reflection.Metadata;
namespace Dashboard.Layout
{
/// <summary>
/// Control attributes for grid layout.
/// </summary>
public class GridLayoutAttribute
{
/// <summary>
/// An anchor will keep the relative distance of a control's edges the same during resizes.
/// </summary>
/// <remarks><see cref="Dock"/> has higher precedence.</remarks>
public Anchor Anchor { get; set; } = Anchor.Left | Anchor.Top;
/// <summary>
/// Dock will strongly attach a control to its container or its edges.
/// </summary>
/// <remarks>Has more precedence than <see cref="Anchor"/></remarks>
public Dock Dock { get; set; } = Dock.None;
public void Evaluate(
ResizedEventArgs parentResizeEvent,
in Rectangle oldBounds,
out Rectangle newBounds
)
{
switch (Dock)
{
default:
case Dock.None:
break;
case Dock.Top:
newBounds = new Rectangle(
parentResizeEvent.NewSize.X,
oldBounds.Size.Y,
0,
0
);
return;
case Dock.Bottom:
newBounds = new Rectangle(
parentResizeEvent.NewSize.X,
parentResizeEvent.NewSize.Y,
0,
oldBounds.Size.Y
);
return;
case Dock.Left:
newBounds = new Rectangle(
oldBounds.Size.X,
parentResizeEvent.NewSize.Y,
0,
0
);
return;
case Dock.Right:
newBounds = new Rectangle(
parentResizeEvent.NewSize.X,
parentResizeEvent.NewSize.Y,
parentResizeEvent.NewSize.Y - oldBounds.Size.Y,
0
);
return;
}
Vector2 scale = parentResizeEvent.NewSize / parentResizeEvent.OldSize;
newBounds = oldBounds;
if (Anchor.HasFlag(Anchor.Top))
{
newBounds.Top = scale.Y * oldBounds.Top;
}
if (Anchor.HasFlag(Anchor.Left))
{
newBounds.Left = scale.X * oldBounds.Left;
}
if (Anchor.HasFlag(Anchor.Bottom))
{
float margin = scale.Y * (parentResizeEvent.OldSize.Y - newBounds.Bottom);
newBounds.Bottom = parentResizeEvent.NewSize.Y - margin;
}
if (Anchor.HasFlag(Anchor.Right))
{
float margin = scale.X * (parentResizeEvent.OldSize.X - newBounds.Right);
newBounds.Right = parentResizeEvent.NewSize.X - margin;
}
}
/// <summary>
/// Get the grid layout attribute associated with the given UI-base.
/// </summary>
/// <param name="uiBase">The UI-base to query.</param>
/// <returns>It's grid layout attribute, if any.</returns>
public static GridLayoutAttribute GetGridLayout(UIBase uiBase)
{
const string GRID_LAYOUT_ATTRIBUTE_KEY = "486ddf8c-b75f-4ad4-a51d-5ba20db9bd0e";
if (
!uiBase.Attributes.TryGetValue(GRID_LAYOUT_ATTRIBUTE_KEY, out object? attribute)
|| attribute is not GridLayoutAttribute)
{
attribute = new GridLayoutAttribute();
uiBase.Attributes[GRID_LAYOUT_ATTRIBUTE_KEY] = attribute;
}
return (GridLayoutAttribute)attribute;
}
}
}