Compare commits
No commits in common. "c6a9dd800857a53d7133bbc5d34b2560cb94e442" and "9b6a15c6ecaa0182985410e00f117ee4c20df5d9" have entirely different histories.
c6a9dd8008
...
9b6a15c6ec
@ -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);
|
||||
|
||||
LastResizeEvent = ea;
|
||||
InvalidateLayout();
|
||||
if (this is IEnumerable<Control> enumerable)
|
||||
{
|
||||
foreach (Control child in enumerable)
|
||||
{
|
||||
if (child.IsLayoutValid)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user