2022-08-21 03:50:38 +03:00
|
|
|
using Eto.Drawing;
|
|
|
|
using Eto.Forms;
|
2022-10-16 21:51:29 +03:00
|
|
|
using NAPS2.EtoForms.Layout;
|
2022-08-21 03:50:38 +03:00
|
|
|
|
|
|
|
namespace NAPS2.EtoForms;
|
|
|
|
|
2022-12-10 08:39:46 +03:00
|
|
|
// TODO: Verify all the size handling works correctly with maximized forms.
|
2022-11-02 23:06:42 +03:00
|
|
|
public class FormStateController
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
|
|
|
private readonly Window _window;
|
|
|
|
private readonly Naps2Config _config;
|
|
|
|
private FormState? _formState;
|
|
|
|
private bool _loaded;
|
2022-10-15 01:49:33 +03:00
|
|
|
private bool _hasSetSize;
|
2022-10-16 21:51:29 +03:00
|
|
|
private Size _minimumClientSize;
|
2022-10-23 07:21:44 +03:00
|
|
|
private Size _maximumClientSize;
|
2022-08-21 03:50:38 +03:00
|
|
|
|
|
|
|
public FormStateController(Window window, Naps2Config config)
|
|
|
|
{
|
|
|
|
_window = window;
|
|
|
|
_config = config;
|
|
|
|
window.SizeChanged += OnResize;
|
|
|
|
window.LocationChanged += OnMove;
|
|
|
|
window.PreLoad += OnLoadInternal;
|
2022-10-15 01:49:33 +03:00
|
|
|
window.Shown += OnShownInternal;
|
2022-08-21 03:50:38 +03:00
|
|
|
window.Closed += OnClosed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool SaveFormState { get; set; } = true;
|
|
|
|
|
|
|
|
public bool RestoreFormState { get; set; } = true;
|
|
|
|
|
2022-10-16 21:51:29 +03:00
|
|
|
public bool AutoLayoutSize { get; set; } = true;
|
2022-10-15 01:49:33 +03:00
|
|
|
|
2022-10-16 21:51:29 +03:00
|
|
|
public Size DefaultExtraLayoutSize { get; set; }
|
2022-10-15 01:49:33 +03:00
|
|
|
|
2022-10-24 04:38:35 +03:00
|
|
|
public Size DefaultClientSize { get; set; }
|
|
|
|
|
2022-10-23 07:21:44 +03:00
|
|
|
public bool FixedHeightLayout { get; set; }
|
|
|
|
|
2022-11-02 08:44:06 +03:00
|
|
|
public bool Resizable { get; set; } = true;
|
|
|
|
|
2022-08-21 03:50:38 +03:00
|
|
|
public string FormName => _window.GetType().Name;
|
|
|
|
|
2022-10-16 21:51:29 +03:00
|
|
|
public void UpdateLayoutSize(LayoutController layoutController)
|
|
|
|
{
|
|
|
|
if (AutoLayoutSize)
|
|
|
|
{
|
2022-10-23 04:23:09 +03:00
|
|
|
_minimumClientSize = layoutController.GetLayoutSize(false);
|
2022-12-10 08:39:46 +03:00
|
|
|
var oldDefaultClientSize = DefaultClientSize;
|
|
|
|
var oldMaximumClientSize = _maximumClientSize;
|
2022-10-24 04:38:35 +03:00
|
|
|
DefaultClientSize = layoutController.GetLayoutSize(true) + DefaultExtraLayoutSize;
|
2022-12-10 08:39:46 +03:00
|
|
|
_maximumClientSize = FixedHeightLayout ? new Size(0, _minimumClientSize.Height) : Size.Empty;
|
|
|
|
|
|
|
|
if (_loaded)
|
2022-10-23 07:21:44 +03:00
|
|
|
{
|
2022-12-10 08:39:46 +03:00
|
|
|
// Dynamic re-sizing because the layout contents have changed (not just a normal resize/maximize etc).
|
|
|
|
var size = EtoPlatform.Current.GetClientSize(_window);
|
|
|
|
if (oldMaximumClientSize.Height > 0)
|
|
|
|
{
|
|
|
|
size.Height = Math.Min(size.Height, oldMaximumClientSize.Height);
|
|
|
|
}
|
2024-08-05 20:40:59 +03:00
|
|
|
// TODO: Maybe we can add a flag to do this behavior? It makes it so that changes to the layout size
|
|
|
|
// after the form is loaded cause the form size to change proportionally (even if we're still within
|
|
|
|
// our min/max bounds). This is causing problems for dynamically sized images/labels etc. but maybe
|
|
|
|
// there's a world where we want to re-enable this for some forms.
|
|
|
|
// size += DefaultClientSize - oldDefaultClientSize;
|
2022-12-10 08:39:46 +03:00
|
|
|
size = Size.Max(size, _minimumClientSize);
|
|
|
|
if (_maximumClientSize.Height > 0)
|
|
|
|
{
|
|
|
|
size.Height = Math.Min(size.Height, _maximumClientSize.Height);
|
|
|
|
}
|
|
|
|
EtoPlatform.Current.SetMinimumClientSize(_window, _minimumClientSize);
|
|
|
|
EtoPlatform.Current.SetClientSize(_window, size);
|
2022-10-23 07:21:44 +03:00
|
|
|
}
|
2022-10-16 21:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-21 03:50:38 +03:00
|
|
|
private void OnLoadInternal(object? sender, EventArgs eventArgs)
|
|
|
|
{
|
|
|
|
if (RestoreFormState || SaveFormState)
|
|
|
|
{
|
|
|
|
var formStates = _config.Get(c => c.FormStates);
|
|
|
|
_formState = formStates.SingleOrDefault(x => x.Name == FormName) ?? new FormState {Name = FormName};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RestoreFormState)
|
|
|
|
{
|
|
|
|
DoRestoreFormState();
|
|
|
|
}
|
2022-10-24 04:38:35 +03:00
|
|
|
if (!_hasSetSize && !DefaultClientSize.IsEmpty)
|
2022-10-15 01:49:33 +03:00
|
|
|
{
|
2022-10-24 04:56:52 +03:00
|
|
|
// TODO: Use size delta to re-center
|
2022-10-24 04:38:35 +03:00
|
|
|
EtoPlatform.Current.SetClientSize(_window, DefaultClientSize);
|
2022-10-15 01:49:33 +03:00
|
|
|
}
|
2022-08-21 03:50:38 +03:00
|
|
|
_loaded = true;
|
|
|
|
}
|
|
|
|
|
2022-12-21 21:15:03 +03:00
|
|
|
private void OnShownInternal(object? sender, EventArgs e)
|
2022-10-15 01:49:33 +03:00
|
|
|
{
|
2022-10-16 21:51:29 +03:00
|
|
|
if (!_minimumClientSize.IsEmpty)
|
2022-10-15 01:49:33 +03:00
|
|
|
{
|
2022-10-16 21:51:29 +03:00
|
|
|
EtoPlatform.Current.SetMinimumClientSize(_window, _minimumClientSize);
|
2022-10-15 01:49:33 +03:00
|
|
|
}
|
2022-11-02 08:44:06 +03:00
|
|
|
_window.Resizable = Resizable;
|
2022-10-15 01:49:33 +03:00
|
|
|
}
|
|
|
|
|
2022-08-21 03:50:38 +03:00
|
|
|
protected void DoRestoreFormState()
|
|
|
|
{
|
|
|
|
if (_formState == null)
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
}
|
|
|
|
var location = new Point(_formState.Location.X, _formState.Location.Y);
|
|
|
|
var size = new Size(_formState.Size.Width, _formState.Size.Height);
|
|
|
|
if (!location.IsZero)
|
|
|
|
{
|
|
|
|
if (Screen.Screens.Any(x => x.WorkingArea.Contains(location)))
|
|
|
|
{
|
|
|
|
// Only move to the specified location if it's onscreen
|
|
|
|
// It might be offscreen if the user has disconnected a monitor
|
2022-11-02 09:16:54 +03:00
|
|
|
EtoPlatform.Current.SetFormLocation(_window, location);
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
}
|
2024-02-18 09:07:36 +03:00
|
|
|
if (!size.IsEmpty && Resizable)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-10-23 07:21:44 +03:00
|
|
|
if (!_minimumClientSize.IsEmpty)
|
|
|
|
{
|
|
|
|
size = Size.Max(size, _minimumClientSize);
|
|
|
|
}
|
|
|
|
if (_maximumClientSize.Height > 0)
|
|
|
|
{
|
|
|
|
size.Height = Math.Min(size.Height, _maximumClientSize.Height);
|
|
|
|
}
|
|
|
|
EtoPlatform.Current.SetClientSize(_window, size);
|
2022-10-15 01:49:33 +03:00
|
|
|
_hasSetSize = true;
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
2022-10-23 07:21:44 +03:00
|
|
|
if (_formState.Maximized && _window.Resizable)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
|
|
|
_window.WindowState = WindowState.Maximized;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnResize(object? sender, EventArgs eventArgs)
|
|
|
|
{
|
|
|
|
if (_loaded && _formState != null && SaveFormState)
|
|
|
|
{
|
|
|
|
_formState.Maximized = (_window.WindowState == WindowState.Maximized);
|
|
|
|
if (_window.WindowState == WindowState.Normal)
|
|
|
|
{
|
2022-10-23 07:21:44 +03:00
|
|
|
var size = EtoPlatform.Current.GetClientSize(_window);
|
2022-10-14 02:17:05 +03:00
|
|
|
_formState.Size = new FormState.FormSize(size.Width, size.Height);
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnMove(object? sender, EventArgs eventArgs)
|
|
|
|
{
|
|
|
|
if (_loaded && _formState != null && SaveFormState)
|
|
|
|
{
|
|
|
|
if (_window.WindowState == WindowState.Normal)
|
|
|
|
{
|
|
|
|
_formState.Location = new FormState.FormLocation(_window.Location.X, _window.Location.Y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnClosed(object? sender, EventArgs eventArgs)
|
2022-11-02 23:06:42 +03:00
|
|
|
{
|
|
|
|
DoSaveFormState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void DoSaveFormState()
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
|
|
|
if (SaveFormState && _formState != null)
|
|
|
|
{
|
|
|
|
var formStates = _config.Get(c => c.FormStates);
|
|
|
|
formStates = formStates.RemoveAll(fs => fs.Name == FormName).Add(_formState);
|
|
|
|
_config.User.Set(c => c.FormStates, formStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|