forked from amkovkov/GranuSightSoftware2
156 lines
7.6 KiB
C#
156 lines
7.6 KiB
C#
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();
|
||
}
|
||
}
|