mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
The way SDL handles window coordinates passes through the native platform API's behavior instead of trying to make a consistent API, so the way sizes are handled on macOS is different.
225 lines
6.6 KiB
C#
225 lines
6.6 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Maths;
|
|
|
|
namespace Robust.Client.UserInterface.Controls
|
|
{
|
|
/// <summary>
|
|
/// Represents an operating system-based UI window.
|
|
/// </summary>
|
|
/// <seealso cref="BaseWindow"/>
|
|
[Virtual]
|
|
public class OSWindow : Control
|
|
{
|
|
[Dependency] private readonly IClyde _clyde = default!;
|
|
|
|
private string _title = "Window";
|
|
private WindowRoot? _root;
|
|
|
|
/// <summary>
|
|
/// The window instance backing this window instance.
|
|
/// Not guaranteed to be available unless the window is currently open.
|
|
/// </summary>
|
|
public IClydeWindow? ClydeWindow { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The window that will "own" this window.
|
|
/// Owned windows always appear on top of their owners and have some other misc behavior depending on the OS.
|
|
/// </summary>
|
|
public IClydeWindow? Owner { get; set; }
|
|
|
|
/// <summary>
|
|
/// Whether the window is created and currently open.
|
|
/// </summary>
|
|
public bool IsOpen => ClydeWindow?.IsVisible ?? false;
|
|
|
|
/// <summary>
|
|
/// The title of the window.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Can be changed while the window is open.
|
|
/// </remarks>
|
|
public string Title
|
|
{
|
|
get => _title;
|
|
set
|
|
{
|
|
_title = value;
|
|
|
|
if (ClydeWindow != null)
|
|
ClydeWindow.Title = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The location to place the window at when it is opened.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Changing this while the window is open has no effect.
|
|
/// </remarks>
|
|
public WindowStartupLocation StartupLocation { get; set; }
|
|
|
|
/// <summary>
|
|
/// Controls whether to automatically size one or both axis of the window to fit the content.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Changing this while the window is open has no effect.
|
|
/// </remarks>
|
|
public WindowSizeToContent SizeToContent { get; set; }
|
|
|
|
/// <summary>
|
|
/// Specifies window styling options for the window.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Changing this while the window is open has no effect.
|
|
/// </remarks>
|
|
public OSWindowStyles WindowStyles { get; set; }
|
|
|
|
/// <summary>
|
|
/// Raised when the window is being closed
|
|
/// (via calling <see cref="Close"/> or the user clicking the close button).
|
|
/// Can be cancelled.
|
|
/// </summary>
|
|
public event Action<CancelEventArgs>? Closing;
|
|
|
|
/// <summary>
|
|
/// Raised when the window has been closed.
|
|
/// </summary>
|
|
public event Action? Closed;
|
|
|
|
public OSWindow()
|
|
{
|
|
IoCManager.InjectDependencies(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create the window if not already created.
|
|
/// This window is not visible by default, call <see cref="Show"/> to display it.
|
|
/// </summary>
|
|
public IClydeWindow Create()
|
|
{
|
|
if (ClydeWindow != null)
|
|
return ClydeWindow;
|
|
|
|
var parameters = new WindowCreateParameters();
|
|
|
|
if (!float.IsNaN(SetWidth))
|
|
parameters.Width = (int) SetWidth;
|
|
|
|
if (!float.IsNaN(SetHeight))
|
|
parameters.Height = (int) SetHeight;
|
|
|
|
if (SizeToContent != WindowSizeToContent.Manual)
|
|
{
|
|
Measure(Vector2Helpers.Infinity);
|
|
|
|
if ((SizeToContent & WindowSizeToContent.Width) != 0)
|
|
parameters.Width = (int)DesiredSize.X;
|
|
|
|
if ((SizeToContent & WindowSizeToContent.Height) != 0)
|
|
parameters.Height = (int)DesiredSize.Y;
|
|
}
|
|
|
|
parameters.Title = _title;
|
|
parameters.Styles = WindowStyles;
|
|
parameters.Owner = Owner;
|
|
parameters.StartupLocation = StartupLocation;
|
|
parameters.Visible = false;
|
|
|
|
ClydeWindow = _clyde.CreateWindow(parameters);
|
|
ClydeWindow.RequestClosed += OnWindowRequestClosed;
|
|
ClydeWindow.Destroyed += OnWindowDestroyed;
|
|
ClydeWindow.Resized += OnWindowResized;
|
|
|
|
_root = UserInterfaceManager.CreateWindowRoot(ClydeWindow);
|
|
_root.CreateRootControls();
|
|
|
|
// Add ourselves *after* creating the root.
|
|
// This way root controls are valid in EnteredTree().
|
|
// We have to re-organize the controls after, of course.
|
|
_root.AddChild(this);
|
|
SetPositionFirst();
|
|
|
|
// Resize the window by our UIScale
|
|
ClydeWindow.Size = new((int)(parameters.Width * UIScale), (int)(parameters.Height * UIScale));
|
|
return ClydeWindow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Show the window to the user, creating it if necessary
|
|
/// </summary>
|
|
public void Show()
|
|
{
|
|
ClydeWindow = Create();
|
|
ClydeWindow.IsVisible = true;
|
|
|
|
Shown();
|
|
}
|
|
|
|
protected virtual void Shown()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to close the window.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This can be cancelled by anything handling <see cref="Closing"/>.
|
|
/// </remarks>
|
|
public void Close()
|
|
{
|
|
if (ClydeWindow == null)
|
|
return;
|
|
|
|
var eventArgs = new CancelEventArgs();
|
|
Closing?.Invoke(eventArgs);
|
|
if (eventArgs.Cancel)
|
|
return;
|
|
|
|
ClydeWindow.Dispose();
|
|
}
|
|
|
|
private void OnWindowRequestClosed(WindowRequestClosedEventArgs eventArgs)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
private void OnWindowDestroyed(WindowDestroyedEventArgs obj)
|
|
{
|
|
// I give it a 75% chance that some Linux user can force close the window,
|
|
// breaking GLFW,
|
|
// and forcing us to have a code path that ignores the RequestClosed code.
|
|
|
|
RealClosed();
|
|
}
|
|
|
|
private void OnWindowResized(WindowResizedEventArgs obj)
|
|
{
|
|
SetSize = obj.NewSize / UIScale;
|
|
}
|
|
|
|
private void RealClosed()
|
|
{
|
|
Orphan();
|
|
|
|
ClydeWindow = null;
|
|
_root = null;
|
|
|
|
Closed?.Invoke();
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
public enum WindowSizeToContent : byte
|
|
{
|
|
Manual = 0,
|
|
Width = 1 << 0,
|
|
Height = 1 << 1,
|
|
WidthAndHeight = Width | Height
|
|
}
|
|
}
|