Files
GSS2Rework/GSS2/App.axaml.cs
T

156 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using GSS2.ViewModels;
using GSS2.Views;
using GSS2.UI.Core;
using GSS2.UI.Core.Services;
using GSS2.UI.Core.ViewModels;
namespace GSS2;
public partial class Application : Avalonia.Application
{
private readonly IServiceProvider _services;
private readonly bool _fullscreen;
private readonly ILogger<Application> _logger;
private readonly DependencyInjectionViewLocator _viewLocator;
private bool _allShutdownSequencesRunning;
public NavigationService Navigation { get; }
public Application(IServiceProvider services, bool fullscreen = false)
{
_services = services;
_fullscreen = fullscreen;
// Создаём AvaloniaLogSink, который перенаправляет логи из Avalonia в хост
var loggerFactory = _services.GetRequiredService<ILoggerFactory>();
Avalonia.Logging.Logger.Sink = new AvaloniaLogSink(loggerFactory);
// Создаём DependencyInjectionViewLocator
_logger = _services.GetRequiredService<ILogger<Application>>();
_viewLocator = _services.GetRequiredService<DependencyInjectionViewLocator>();
Navigation = _services.GetRequiredService<NavigationService>();
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
// Добавляем наш DependencyInjectionViewLocator в DataTemplates приложения
DataTemplates.Add(_viewLocator);
}
public override void OnFrameworkInitializationCompleted()
{
// Получаем lifetime хоста
var hostLifetime = _services.GetRequiredService<IHostApplicationLifetime>();
// Регистрируем обработчик начатия Ctrl+C
Console.CancelKeyPress += (_, _) =>
{
_logger.LogInformation("Закрытие приложения вызвано из консоли");
hostLifetime.StopApplication();
};
// Создаём обработчик события закрытия хоста
hostLifetime.ApplicationStopped.Register(() =>
{
// Если всё что нужно для закрытия приложения уже вызвано, то ничего не делаем
if (_allShutdownSequencesRunning)
return;
// Иначе это событие вызвано не из интерфейса и графический интерфейс нужно закрыть
Dispatcher.UIThread.InvokeShutdown();
_allShutdownSequencesRunning = true;
});
// Создаём обработчик события закрытия графического интерфейса
Dispatcher.UIThread.ShutdownStarted += (_, _) =>
{
// Если всё что нужно для закрытия приложения уже вызвано, то ничего не делаем
if (_allShutdownSequencesRunning)
return;
// Иначе это событие вызвано из интерфейса и хост нужно закрыть
_logger.LogInformation("Закрытие приложения вызвано из интерфейса");
hostLifetime.StopApplication();
_allShutdownSequencesRunning = true;
};
// ApplicationLifetime == null, то невозможно определить в какой среде мы запускаемся,
// но такого быть не должно
if (ApplicationLifetime is null)
{
_logger.LogCritical("Приложение не может быть полностью инициализировано, ApplicationLifetime == null");
// Я не уверен, будет ли правильно в данном классе вместо выбрасывания исключений,
// использовать Environment.Exit,
// но если использовать исключения, то их может поймать какой-нибудь обработчик,
// а Environment.Exit гарантированно завершит текущий процесс
hostLifetime.StopApplication();
Environment.Exit(1);
}
// Создаём начальный элемент управления и переходим к нему
var mainView = new MainView()
{
DataContext = _services.GetRequiredService<MainViewModel>()
};
// var mainView = new GSS2.UI.Core.Views.CameraView(_services.GetService<ILogger<GSS2.UI.Core.Views.CameraView>>()!)
// {
// DataContext = _services.GetRequiredService<GSS2.UI.Core.ViewModels.CameraViewModel>()
// };
// Создаём главный элемент управления
// на основании типа ApplicationLifetime, который зависит от того как мы запустили приложение
// StartWithClassicDesktopLifetime IClassicDesktopStyleApplicationLifetime
// StartLinuxDrm ISingleViewApplicationLifetime
switch (ApplicationLifetime)
{
case IClassicDesktopStyleApplicationLifetime desktop:
_logger.LogInformation("Приложение запускается в классическом режиме");
_logger.LogInformation("Приложение запускается в {} режиме", _fullscreen ? "полноэкранном" : "оконном");
// Создаём главное окно
var mainWindow = new MainWindow()
{
DataContext = new MainWindowViewModel()
{
WindowDecorations = _fullscreen ? Avalonia.Controls.WindowDecorations.None : Avalonia.Controls.WindowDecorations.Full,
Topmost = _fullscreen,
WindowState = _fullscreen ? Avalonia.Controls.WindowState.FullScreen : Avalonia.Controls.WindowState.Normal
},
};
desktop.MainWindow = mainWindow;
// Переключаемся на начальный элемент управления
Navigation.NavigateTo(mainView);
break;
case ISingleViewApplicationLifetime singleView:
_logger.LogInformation("Приложение запускается в режиме отображение единой формы");
// Просто устанавливаем главным элементом управления начальный элемент
singleView.MainView = mainView;
break;
default:
_logger.LogCritical("Приложение не может быть полностью инициализировано, ApplicationLifetime имеет неизвестный тип, наследованный от: {}", string.Join(", ", ApplicationLifetime.GetType().GetInterfaces().Select(i => i.FullName)));
hostLifetime.StopApplication();
Environment.Exit(1);
break;
}
base.OnFrameworkInitializationCompleted();
}
}