using System; using System.Collections.Generic; using Dashboard.CommandMachine; namespace Dashboard.Controls { public abstract class Control : UIBase { private readonly CommandList drawCommands = new CommandList(); public Style Style { get; set; } = new Style(); public float Padding { get => (float)(Style["padding"] ?? 0.0f); set => Style["padding"] = value; } public bool IsVisualsValid { get; private set; } = false; public bool IsLayoutValid { get; private set; } = false; protected bool IsLayoutSuspended { get; private set; } = false; public void InvalidateVisual() { IsVisualsValid = false; OnVisualsInvalidated(this, EventArgs.Empty); } public void InvalidateLayout() { IsLayoutValid = false; OnLayoutInvalidated(this, EventArgs.Empty); } public void SuspendLayout() { IsLayoutSuspended = true; } public void ResumeLayout() { IsLayoutSuspended = false; InvalidateLayout(); } protected abstract void ValidateVisual(CommandList cmd); protected abstract void ValidateLayout(); protected override void PaintBegin(CommandList cmd) { base.PaintBegin(cmd); if (!IsLayoutValid && !IsLayoutSuspended) { ValidateLayout(); OnLayoutValidated(this, EventArgs.Empty); IsLayoutValid = true; InvalidateVisual(); } if (!IsVisualsValid) { ValidateVisual(drawCommands); OnVisualsValidated(this, EventArgs.Empty); IsVisualsValid = true; } cmd.PushStyle(Style); cmd.PushViewport(); cmd.StoreViewport(AbsoluteBounds); cmd.Splice(drawCommands); cmd.PopViewport(); cmd.PopStyle(); } public event EventHandler? StyleChanged; public event EventHandler? VisualsInvalidated; public event EventHandler? VisualsValidated; public event EventHandler? LayoutInvalidated; public event EventHandler? LayoutValidated; protected virtual void OnStyleChanged(object sender, EventArgs ea) { StyleChanged?.Invoke(sender, ea); InvalidateLayout(); } protected virtual void OnVisualsInvalidated(object sender, EventArgs ea) { VisualsInvalidated?.Invoke(sender, ea); } protected virtual void OnVisualsValidated(object sender, EventArgs ea) { VisualsValidated?.Invoke(sender, ea); } protected virtual void OnLayoutInvalidated(object sender, EventArgs ea) { LayoutInvalidated?.Invoke(sender, ea); } protected virtual void OnLayoutValidated(object sender, EventArgs ea) { LayoutValidated?.Invoke(sender, ea); } protected void ValidateChildrenLayout() { if (this is IEnumerable enumerable) { foreach (Control child in enumerable) { if (child.IsLayoutValid) continue; child.ValidateLayout(); } } } } }