using Dashboard.Collections; using Dashboard.Windowing; using BindingFlags = System.Reflection.BindingFlags; namespace Dashboard.Pal { public abstract class DeviceContext : IContextBase { private readonly TypeDictionary _extensions = new TypeDictionary(true); private readonly TypeDictionary> _preloadedExtensions = new TypeDictionary>(true); private readonly Dictionary _attributes = new Dictionary(); public Application Application { get; } public IWindow? Window { get; } public abstract string DriverName { get; } public abstract string DriverVendor { get; } public abstract Version DriverVersion { get; } public bool IsDisposed { get; private set; } /// /// Optional debugging object for your pleasure. /// public IContextDebugger? Debugger { get; set; } protected DeviceContext(Application app, IWindow? window) { Application = app; Window = window; app.OnDeviceContextCreated(this); } ~DeviceContext() { Dispose(false); } public virtual void Begin() { } // public abstract void Paint(object renderbuffer); public virtual void End() { } public bool IsExtensionAvailable() where T : IDeviceContextExtension { return _extensions.Contains() || _preloadedExtensions.Contains(); } public bool ExtensionPreload(Func loader) where T : IDeviceContextExtension { return _preloadedExtensions.Add(loader); } public bool ExtensionPreload() where T : IDeviceContextExtension, new() { return _preloadedExtensions.Add(() => new T()); } public T ExtensionRequire() where T : IDeviceContextExtension { T? extension = default; if (_extensions.TryGet(out extension)) return extension; lock (_extensions) { if (_extensions.TryGet(out extension)) return extension; if (_preloadedExtensions.Remove(out Func? loader)) { extension = (T)loader!(); } else { extension = Activator.CreateInstance(); } _extensions.Add(extension); extension.Require(this); } return extension; } public bool ExtensionLoad(T instance) where T : IDeviceContextExtension { if (_extensions.Contains(instance)) return false; _extensions.Add(instance); return true; } public void SetAttribute(string name, object? v) { if (v != null) _attributes[name] = v; else _attributes.Remove(name); } public void SetAttribute(string name, T v) => SetAttribute(name, (object?)v); public object? GetAttribute(string name) { return _attributes.GetValueOrDefault(name); } public T? GetAttribute(string name) { object? o = GetAttribute(name); if (o != null) return (T?)o; return default; } /// /// Implement your dispose in this function. /// /// True if disposing, false otherwise. protected virtual void Dispose(bool isDisposing) { if (!isDisposing) return; foreach (IDeviceContextExtension 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); } }