Dashboard/Dashboard.OpenTK/PAL2/PhysicalWindow.cs

165 lines
5.4 KiB
C#

using System.Collections.Concurrent;
using System.Drawing;
using Dashboard.Drawing;
using Dashboard.Events;
using Dashboard.Windowing;
using OpenTK.Mathematics;
using OpenTK.Platform;
using MouseMoveEventArgs = Dashboard.Events.MouseMoveEventArgs;
using TK = OpenTK.Platform.Toolkit;
namespace Dashboard.OpenTK.PAL2
{
public class PhysicalWindow : IPhysicalWindow, IDrawQueuePaintable, IEventListener
{
public DrawQueue DrawQueue { get; } = new DrawQueue();
public WindowHandle WindowHandle { get; }
public IDeviceContext DeviceContext { get; }
public bool DoubleBuffered => true; // Always true for OpenTK windows.
public IWindowManager? WindowManager { get; set; }
public string Title
{
get => TK.Window.GetTitle(WindowHandle);
set => TK.Window.SetTitle(WindowHandle, value);
}
public SizeF OuterSize
{
get
{
TK.Window.GetSize(WindowHandle, out Vector2i size);
return new SizeF(size.X, size.Y);
}
set => TK.Window.SetSize(WindowHandle, new Vector2i((int)value.Width, (int)value.Height));
}
public SizeF ClientSize
{
get
{
TK.Window.GetClientSize(WindowHandle, out Vector2i size);
return new SizeF(size.X, size.Y);
}
set => TK.Window.SetClientSize(WindowHandle, new Vector2i((int)value.Width, (int)value.Height));
}
public event EventHandler? Painting;
public event EventHandler<AnimationTickEventArgs>? AnimationTimerEvent;
public event EventHandler<MouseMoveEventArgs>? MouseMoved;
public event EventHandler<MouseButtonEventArgs>? MouseButtonDown;
public event EventHandler<MouseButtonEventArgs>? MouseButtonUp;
public event EventHandler<MouseScrollEventArgs>? MouseScroll;
public PhysicalWindow(WindowHandle window, IDeviceContext dc)
{
WindowHandle = window;
DeviceContext = dc;
AddWindow(this);
}
public PhysicalWindow(WindowHandle window, OpenGLContextHandle context, ISwapGroup? swapGroup = null)
{
WindowHandle = window;
DeviceContext = new OpenGLDeviceContext(window, context, swapGroup);
AddWindow(this);
}
public PhysicalWindow(GraphicsApiHints hints)
{
WindowHandle = TK.Window.Create(hints);
DeviceContext = CreateDeviceContext(WindowHandle, hints);
AddWindow(this);
}
private static IDeviceContext CreateDeviceContext(WindowHandle window, GraphicsApiHints hints)
{
switch (hints.Api)
{
case GraphicsApi.OpenGL:
case GraphicsApi.OpenGLES:
OpenGLContextHandle context = TK.OpenGL.CreateFromWindow(window);
return new OpenGLDeviceContext(window, context);
default:
throw new Exception($"Unknown graphics API {hints.Api}.");
}
}
private bool _isDisposed = false;
public void Dispose()
{
if (_isDisposed) return;
_isDisposed = true;
RemoveWindow(this);
(DeviceContext as IDisposable)?.Dispose();
TK.Window.Destroy(WindowHandle);
}
protected virtual void OnPaint()
{
WindowManager?.Paint();
Painting?.Invoke(this, EventArgs.Empty);
}
public void Paint()
{
DrawQueue.Clear();
OnPaint();
}
protected virtual void OnAnimationTimerEvent(AnimationTickEventArgs ea) =>
AnimationTimerEvent?.Invoke(this, ea);
protected virtual void OnMouseMoved(MouseMoveEventArgs ea) => MouseMoved?.Invoke(this, ea);
protected virtual void OnMouseButtonDown(MouseButtonEventArgs ea) => MouseButtonDown?.Invoke(this, ea);
protected virtual void OnMouseButtonUp(MouseButtonEventArgs ea) => MouseButtonUp?.Invoke(this, ea);
protected virtual void OnMouseScroll(MouseScrollEventArgs ea) => MouseScroll?.Invoke(this, ea);
public void SendEvent(EventArgs args)
{
}
private static readonly ConcurrentDictionary<WindowHandle, PhysicalWindow> _windows =
new ConcurrentDictionary<WindowHandle, PhysicalWindow>();
static PhysicalWindow()
{
EventQueue.EventRaised += EventQueueOnEventRaised;
}
private static void AddWindow(PhysicalWindow window)
{
_windows.TryAdd(window.WindowHandle, window);
}
private static void RemoveWindow(PhysicalWindow window)
{
_windows.TryRemove(window.WindowHandle, out _);
}
private static void EventQueueOnEventRaised(PalHandle? handle, PlatformEventType type, EventArgs args)
{
if (handle is not WindowHandle windowHandle)
return;
if (!_windows.TryGetValue(windowHandle, out PhysicalWindow? window))
return;
switch (type)
{
case PlatformEventType.MouseMove:
case PlatformEventType.Scroll:
case PlatformEventType.MouseUp:
case PlatformEventType.MouseDown:
break;
}
}
}
}