148 lines
4.3 KiB
C#
148 lines
4.3 KiB
C#
using Dashboard.Collections;
|
|
using Dashboard.Windowing;
|
|
|
|
namespace Dashboard.Pal
|
|
{
|
|
public abstract class AppContext : IContextBase<AppContext, IAppContextExtension>
|
|
{
|
|
public abstract string DriverName { get; }
|
|
public abstract string DriverVendor { get; }
|
|
public abstract Version DriverVersion { get; }
|
|
|
|
public virtual string AppTitle { get; set; } = "Dashboard Application";
|
|
|
|
public bool IsInitialized { get; private set; } = false;
|
|
public bool IsDisposed { get; private set; } = false;
|
|
public IContextDebugger? Debugger { get; set; }
|
|
|
|
private readonly TypeDictionary<IAppContextExtension> _extensions =
|
|
new TypeDictionary<IAppContextExtension>(true);
|
|
private readonly TypeDictionary<IAppContextExtension, Func<IAppContextExtension>> _preloadedExtensions =
|
|
new TypeDictionary<IAppContextExtension, Func<IAppContextExtension>>(true);
|
|
|
|
~AppContext()
|
|
{
|
|
InvokeDispose(false);
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
if (IsInitialized)
|
|
return;
|
|
|
|
IsInitialized = true;
|
|
|
|
InitializeInternal();
|
|
}
|
|
|
|
protected virtual void InitializeInternal()
|
|
{
|
|
}
|
|
|
|
public virtual void RunEvents(bool wait)
|
|
{
|
|
if (!IsInitialized)
|
|
Initialize();
|
|
}
|
|
|
|
public void Run() => Run(true, CancellationToken.None);
|
|
|
|
public void Run(bool wait) => Run(wait, CancellationToken.None);
|
|
|
|
public void Run(bool waitForEvents, CancellationToken token)
|
|
{
|
|
InitializeInternal();
|
|
|
|
while (!token.IsCancellationRequested)
|
|
{
|
|
RunEvents(waitForEvents);
|
|
}
|
|
}
|
|
|
|
#region Window API
|
|
/// <summary>
|
|
/// Creates a window. It could be a virtual window, or a physical window.
|
|
/// </summary>
|
|
/// <returns>A window.</returns>
|
|
public abstract IWindow CreateWindow();
|
|
|
|
/// <summary>
|
|
/// Always creates a physical window.
|
|
/// </summary>
|
|
/// <returns>A physical window.</returns>
|
|
public abstract IPhysicalWindow CreatePhysicalWindow();
|
|
|
|
/// <summary>
|
|
/// Create a physical window with a window manager.
|
|
/// </summary>
|
|
/// <returns>A physical window with the given window manager.</returns>
|
|
public IPhysicalWindow CreatePhysicalWindow(IWindowManager wm)
|
|
{
|
|
IPhysicalWindow window = CreatePhysicalWindow();
|
|
window.WindowManager = wm;
|
|
return window;
|
|
}
|
|
#endregion
|
|
|
|
public bool IsExtensionAvailable<T>() where T : IAppContextExtension
|
|
{
|
|
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
|
}
|
|
|
|
public bool ExtensionPreload<T>() where T : IAppContextExtension, new()
|
|
{
|
|
return _preloadedExtensions.Add<T>(() => new T());
|
|
}
|
|
|
|
public T ExtensionRequire<T>() where T : IAppContextExtension, new()
|
|
{
|
|
T? extension = default;
|
|
|
|
if (_extensions.TryGet(out extension))
|
|
return extension;
|
|
|
|
lock (_extensions)
|
|
{
|
|
if (_extensions.TryGet(out extension))
|
|
return extension;
|
|
|
|
if (_preloadedExtensions.Remove<T>(out Func<IAppContextExtension>? loader))
|
|
{
|
|
extension = (T)loader!();
|
|
}
|
|
else
|
|
{
|
|
extension = new T();
|
|
}
|
|
|
|
_extensions.Add(extension);
|
|
extension.Require(this);
|
|
}
|
|
|
|
return extension;
|
|
}
|
|
|
|
protected virtual void Dispose(bool isDisposing)
|
|
{
|
|
if (!isDisposing) return;
|
|
|
|
foreach (IAppContextExtension extension in _extensions)
|
|
{
|
|
extension.Dispose();
|
|
}
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private void InvokeDispose(bool isDisposing)
|
|
{
|
|
if (IsDisposed) return;
|
|
IsDisposed = true;
|
|
|
|
Dispose(isDisposing);
|
|
}
|
|
|
|
public void Dispose() => InvokeDispose(true);
|
|
}
|
|
}
|