file-scoped namespaces and other cleanup stuff

This commit is contained in:
Holger Börchers 2023-04-02 22:49:00 +02:00
parent c2e7cc1a3c
commit fc7cdceb05
15 changed files with 415 additions and 443 deletions

View File

@ -1,5 +1,3 @@
using System;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
@ -11,100 +9,99 @@ using Avalonia.Themes.Simple;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using AvaloniaCoreRTDemo.Windows; using AvaloniaCoreRTDemo.Windows;
namespace AvaloniaCoreRTDemo namespace AvaloniaCoreRTDemo;
public sealed class App : Application, IThemeSwitch
{ {
public sealed class App : Application, IThemeSwitch private FluentTheme _fluentTheme = default!;
private SimpleTheme _simpleTheme = default!;
private IStyle _fluentDataGrid = default!;
private IStyle _simpleDataGrid = default!;
private ApplicationTheme _currentTheme;
public override void Initialize()
{ {
private FluentTheme _fluentTheme = default!; AvaloniaXamlLoader.Load(this);
private SimpleTheme _simpleTheme = default!; Name = "AvaloniaCoreRTDemo";
private IStyle _fluentDataGrid = default!; }
private IStyle _simpleDataGrid = default!;
private ApplicationTheme _currentTheme; public override void OnFrameworkInitializationCompleted()
{
public override void Initialize() InitializeThemes();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
AvaloniaXamlLoader.Load(this); desktop.MainWindow = new MainWindow();
Name = "AvaloniaCoreRTDemo"; DataContext = desktop.MainWindow.DataContext;
}
base.OnFrameworkInitializationCompleted();
}
private void InitializeThemes()
{
_simpleTheme = new SimpleTheme();
_fluentTheme = new FluentTheme();
_fluentDataGrid = (IStyle)Resources["fluentDataGrid"]!;
_simpleDataGrid = (IStyle)Resources["simpleDataGrid"]!;
Styles.Add(_fluentTheme);
Styles.Add(_fluentDataGrid);
_currentTheme = ApplicationTheme.FluentLight;
}
ApplicationTheme IThemeSwitch.Current => _currentTheme;
void IThemeSwitch.ChangeTheme(ApplicationTheme theme)
{
if (theme == _currentTheme)
return;
bool themeChanged = theme switch
{
ApplicationTheme.SimpleLight => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.SimpleDark => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.FluentLight => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
ApplicationTheme.FluentDark => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
_ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null)
};
_currentTheme = theme;
switch (theme)
{
case ApplicationTheme.SimpleLight:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
Styles[0] = _simpleTheme;
Styles[1] = _simpleDataGrid;
break;
case ApplicationTheme.SimpleDark:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
Styles[0] = _simpleTheme;
Styles[1] = _simpleDataGrid;
break;
case ApplicationTheme.FluentLight:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
Styles[0] = _fluentTheme;
Styles[1] = _fluentDataGrid;
break;
case ApplicationTheme.FluentDark:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
Styles[0] = _fluentTheme;
Styles[1] = _fluentDataGrid;
break;
} }
public override void OnFrameworkInitializationCompleted() if (themeChanged && ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
InitializeThemes(); MainWindow oldWindow = (desktop.MainWindow as MainWindow)!;
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) MainWindow newWindow = new MainWindow(oldWindow);
{
desktop.MainWindow = new MainWindow();
DataContext = desktop.MainWindow.DataContext;
}
base.OnFrameworkInitializationCompleted();
}
private void InitializeThemes() desktop.MainWindow = newWindow;
{ DataContext = newWindow.DataContext;
_simpleTheme = new SimpleTheme();
_fluentTheme = new FluentTheme();
_fluentDataGrid = (IStyle)Resources["fluentDataGrid"]!; oldWindow.Hide();
_simpleDataGrid = (IStyle)Resources["simpleDataGrid"]!; newWindow.Show();
oldWindow.Close();
Styles.Add(_fluentTheme);
Styles.Add(_fluentDataGrid);
_currentTheme = ApplicationTheme.FluentLight;
}
ApplicationTheme IThemeSwitch.Current => _currentTheme;
void IThemeSwitch.ChangeTheme(ApplicationTheme theme)
{
if (theme == _currentTheme)
return;
bool themeChanged = theme switch
{
ApplicationTheme.SimpleLight => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.SimpleDark => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.FluentLight => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
ApplicationTheme.FluentDark => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
_ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null)
};
_currentTheme = theme;
switch (theme)
{
case ApplicationTheme.SimpleLight:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
Styles[0] = _simpleTheme;
Styles[1] = _simpleDataGrid;
break;
case ApplicationTheme.SimpleDark:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
Styles[0] = _simpleTheme;
Styles[1] = _simpleDataGrid;
break;
case ApplicationTheme.FluentLight:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
Styles[0] = _fluentTheme;
Styles[1] = _fluentDataGrid;
break;
case ApplicationTheme.FluentDark:
SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
Styles[0] = _fluentTheme;
Styles[1] = _fluentDataGrid;
break;
}
if (themeChanged && ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
MainWindow oldWindow = (desktop.MainWindow as MainWindow)!;
MainWindow newWindow = new MainWindow(oldWindow);
desktop.MainWindow = newWindow;
DataContext = newWindow.DataContext;
oldWindow.Hide();
newWindow.Show();
oldWindow.Close();
}
} }
} }
} }

View File

@ -1,12 +1,9 @@
using System; namespace AvaloniaCoreRTDemo;
namespace AvaloniaCoreRTDemo public enum ApplicationTheme : byte
{ {
public enum ApplicationTheme : byte SimpleLight = 0,
{ SimpleDark = 1,
SimpleLight = 0, FluentLight = 2,
SimpleDark = 1, FluentDark = 3,
FluentLight = 2,
FluentDark = 3,
}
} }

View File

@ -11,7 +11,7 @@
<PublishAot>true</PublishAot> <PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed> <PublishTrimmed>true</PublishTrimmed>
<SelfContained>true</SelfContained> <SelfContained>true</SelfContained>
<ImplicitUsing>enable</ImplicitUsing> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -61,6 +61,7 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="PublishAotCompressed" Version="1.0.0" />
</ItemGroup> </ItemGroup>
<!-- Information for Dotnet.Bundle to Generate macOS app--> <!-- Information for Dotnet.Bundle to Generate macOS app-->

View File

@ -3,24 +3,23 @@ using Avalonia.Markup.Xaml;
using AvaloniaCoreRTDemo.Controls.ViewModels; using AvaloniaCoreRTDemo.Controls.ViewModels;
namespace AvaloniaCoreRTDemo.Controls namespace AvaloniaCoreRTDemo.Controls;
public sealed partial class MainControl : UserControl
{ {
public sealed partial class MainControl : UserControl public MainControl()
{ {
public MainControl() InitializeComponent();
{ }
InitializeComponent();
}
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
DataContext = new MainControlViewModel(); DataContext = new MainControlViewModel();
} }
public void Reload(IMainWindowState model) public void Reload(IMainWindowState model)
{ {
DataContext = new MainControlViewModel(model); DataContext = new MainControlViewModel(model);
}
} }
} }

View File

@ -1,46 +1,45 @@
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using MvvmGen; using MvvmGen;
namespace AvaloniaCoreRTDemo.Controls.ViewModels namespace AvaloniaCoreRTDemo.Controls.ViewModels;
[ViewModel]
internal sealed partial class MainControlViewModel : IMainWindowState
{ {
[ViewModel] private IBitmap _dotNetImage;
internal sealed partial class MainControlViewModel : IMainWindowState private IBitmap _avaloniaImage;
private bool _unloadable = false;
public IBitmap DotNetImage => _dotNetImage;
public IBitmap AvaloniaImage => _avaloniaImage;
public string? Text { get; set; }
partial void OnInitialize()
{ {
private IBitmap _dotNetImage; _dotNetImage = Utilities.GetImageFromFile("dotnet.png");
private IBitmap _avaloniaImage; _avaloniaImage = Utilities.GetImageFromFile("avalonia.png");
}
private bool _unloadable = false; public MainControlViewModel(IMainWindowState state) : this()
{
_avaloniaImage = state.AvaloniaImage;
_dotNetImage = state.DotNetImage;
Text = state.Text;
state.SetUnloadable();
}
public IBitmap DotNetImage => _dotNetImage; ~MainControlViewModel()
public IBitmap AvaloniaImage => _avaloniaImage; {
public string? Text { get; set; } if (!_unloadable)
partial void OnInitialize()
{ {
_dotNetImage = Utilities.GetImageFromFile("dotnet.png"); _dotNetImage.Dispose();
_avaloniaImage = Utilities.GetImageFromFile("avalonia.png"); _avaloniaImage.Dispose();
}
public MainControlViewModel(IMainWindowState state) : this()
{
_avaloniaImage = state.AvaloniaImage;
_dotNetImage = state.DotNetImage;
Text = state.Text;
state.SetUnloadable();
}
~MainControlViewModel()
{
if (!_unloadable)
{
_dotNetImage.Dispose();
_avaloniaImage.Dispose();
}
}
void IMainWindowState.SetUnloadable()
{
_unloadable = true;
} }
} }
void IMainWindowState.SetUnloadable()
{
_unloadable = true;
}
} }

View File

@ -1,15 +1,14 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
namespace AvaloniaCoreRTDemo.Interfaces namespace AvaloniaCoreRTDemo.Interfaces;
public interface IMainWindow
{ {
public interface IMainWindow IThemeSwitch ThemeSwitch { get; }
{ IMainWindowState Model { get; }
IThemeSwitch ThemeSwitch { get; } PixelPoint Position { get; }
IMainWindowState Model { get; } Size ClientSize { get; }
PixelPoint Position { get; } Size? FrameSize { get; }
Size ClientSize { get; } WindowState State { get; }
Size? FrameSize { get; }
WindowState State { get; }
}
} }

View File

@ -1,15 +1,12 @@
using System; using Avalonia.Media.Imaging;
using Avalonia.Media.Imaging; namespace AvaloniaCoreRTDemo;
namespace AvaloniaCoreRTDemo public interface IMainWindowState
{ {
public interface IMainWindowState IBitmap DotNetImage { get; }
{ IBitmap AvaloniaImage { get; }
IBitmap DotNetImage { get; } string? Text { get; }
IBitmap AvaloniaImage { get; }
string? Text { get; }
void SetUnloadable(); void SetUnloadable();
}
} }

View File

@ -1,8 +1,7 @@
namespace AvaloniaCoreRTDemo.Interfaces namespace AvaloniaCoreRTDemo.Interfaces;
public interface IThemeSwitch
{ {
public interface IThemeSwitch ApplicationTheme Current { get; }
{ void ChangeTheme(ApplicationTheme theme);
ApplicationTheme Current { get; }
void ChangeTheme(ApplicationTheme theme);
}
} }

View File

@ -1,17 +1,16 @@
using Avalonia; using Avalonia;
namespace AvaloniaCoreRTDemo namespace AvaloniaCoreRTDemo;
{
public static class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer. public static class Program
public static AppBuilder BuildAvaloniaApp() {
=> AppBuilder.Configure<App>().UsePlatformDetect() // Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>().UsePlatformDetect()
.LogToTrace(); .LogToTrace();
}
} }

View File

@ -1,49 +1,46 @@
using System; using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.InteropServices;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform; using Avalonia.Platform;
namespace AvaloniaCoreRTDemo namespace AvaloniaCoreRTDemo;
internal static class Utilities
{ {
internal static class Utilities public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static readonly bool IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static Bitmap GetImageFromResources(string fileName)
{ {
public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
public static readonly bool IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}"));
return new Bitmap(assetStream);
public static Bitmap GetImageFromResources(string fileName)
{
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}"));
return new Bitmap(assetStream);
}
public static PixelPoint GetWindowPosition(Window window)
{
if (!IsOSX || !window.FrameSize.HasValue)
return window.Position;
else
{
int yOffset = (int)(window.FrameSize.Value.Height - window.ClientSize.Height);
return new(window.Position.X, window.Position.Y + yOffset);
}
}
public static Bitmap GetImageFromFile(string path)
{
try
{
return new Bitmap(GetImageFullPath(path));
}
catch (Exception)
{
return GetImageFromResources("broken-link.png");
}
}
private static string GetImageFullPath(string fileName) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
} }
public static PixelPoint GetWindowPosition(Window window)
{
if (!IsOSX || !window.FrameSize.HasValue)
return window.Position;
else
{
int yOffset = (int)(window.FrameSize.Value.Height - window.ClientSize.Height);
return new(window.Position.X, window.Position.Y + yOffset);
}
}
public static Bitmap GetImageFromFile(string path)
{
try
{
return new Bitmap(GetImageFullPath(path));
}
catch (Exception)
{
return GetImageFromResources("broken-link.png");
}
}
private static string GetImageFullPath(string fileName) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
} }

View File

@ -1,32 +1,29 @@
using System;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using AvaloniaCoreRTDemo.Windows.ViewModels; using AvaloniaCoreRTDemo.Windows.ViewModels;
namespace AvaloniaCoreRTDemo.Windows namespace AvaloniaCoreRTDemo.Windows;
public sealed partial class AboutWindow : Window
{ {
public sealed partial class AboutWindow : Window private readonly bool _darkTheme;
public AboutWindow() : this(false) { }
public AboutWindow(bool darkTheme)
{ {
private readonly bool _darkTheme; _darkTheme = darkTheme;
InitializeComponent();
public AboutWindow() : this(false) { }
public AboutWindow(bool darkTheme)
{
_darkTheme = darkTheme;
InitializeComponent();
#if DEBUG #if DEBUG
this.AttachDevTools(); this.AttachDevTools();
#endif #endif
} }
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
DataContext = new AboutViewModel(_darkTheme); DataContext = new AboutViewModel(_darkTheme);
}
} }
} }

View File

@ -6,44 +6,43 @@ using AvaloniaCoreRTDemo.Controls;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using AvaloniaCoreRTDemo.Windows.ViewModels; using AvaloniaCoreRTDemo.Windows.ViewModels;
namespace AvaloniaCoreRTDemo.Windows namespace AvaloniaCoreRTDemo.Windows;
public sealed partial class MainWindow : Window, IMainWindow
{ {
public sealed partial class MainWindow : Window, IMainWindow private readonly Application? _app = Application.Current;
private MainControl MainController => this.GetControl<MainControl>("MainControl");
public MainWindow() : this(default) { }
public MainWindow(IMainWindow? window)
{ {
private readonly Application? _app = Application.Current; InitializeComponent(window);
private MainControl MainController => this.GetControl<MainControl>("MainControl");
public MainWindow() : this(default) { }
public MainWindow(IMainWindow? window)
{
InitializeComponent(window);
#if DEBUG #if DEBUG
this.AttachDevTools(); this.AttachDevTools();
#endif #endif
} }
IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)_app!; IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)_app!;
IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainController.DataContext!; IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainController.DataContext!;
PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this); PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this);
Size IMainWindow.ClientSize => ClientSize; Size IMainWindow.ClientSize => ClientSize;
Size? IMainWindow.FrameSize => FrameSize; Size? IMainWindow.FrameSize => FrameSize;
WindowState IMainWindow.State => WindowState; WindowState IMainWindow.State => WindowState;
private void InitializeComponent(IMainWindow? window) private void InitializeComponent(IMainWindow? window)
{
AvaloniaXamlLoader.Load(this);
DataContext = new MainViewModel<MainWindow>(this);
if (window is not null)
{ {
AvaloniaXamlLoader.Load(this); this.MainController.Reload(window.Model);
DataContext = new MainViewModel<MainWindow>(this); WindowStartupLocation = WindowStartupLocation.Manual;
if (window is not null) WindowState = window.State;
{ Position = window.Position;
this.MainController.Reload(window.Model); FrameSize = window.FrameSize;
WindowStartupLocation = WindowStartupLocation.Manual; ClientSize = window.ClientSize;
WindowState = window.State;
Position = window.Position;
FrameSize = window.FrameSize;
ClientSize = window.ClientSize;
}
} }
} }
} }

View File

@ -1,62 +1,59 @@
using System; using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using MvvmGen; using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels;
internal record SystemDetail(string Key, string Value);
[ViewModel]
internal sealed partial class AboutViewModel
{ {
internal record SystemDetail(string Key, string Value); private readonly IBitmap _computerImage;
private readonly bool _darkTheme;
[ViewModel] public IBitmap ComputerImage => _computerImage;
internal sealed partial class AboutViewModel
public IReadOnlyList<SystemDetail> SystemDetails { get; } =
new[]
{
new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()),
new SystemDetail("OS", RuntimeInformation.OSDescription),
new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()),
new SystemDetail("OS Version", Environment.OSVersion.ToString()),
new SystemDetail("Computer", Environment.MachineName),
new SystemDetail("User", Environment.UserName),
new SystemDetail("System Path", Environment.SystemDirectory),
new SystemDetail("Current Path", Environment.CurrentDirectory),
new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()),
new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription),
new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()),
new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()),
new SystemDetail("Framework Version", Environment.Version.ToString()),
};
private string ComputerImageName
{ {
private readonly IBitmap _computerImage; get
private readonly bool _darkTheme;
public IBitmap ComputerImage => _computerImage;
public IReadOnlyList<SystemDetail> SystemDetails { get; } =
new[]
{
new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()),
new SystemDetail("OS", RuntimeInformation.OSDescription),
new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()),
new SystemDetail("OS Version", Environment.OSVersion.ToString()),
new SystemDetail("Computer", Environment.MachineName),
new SystemDetail("User", Environment.UserName),
new SystemDetail("System Path", Environment.SystemDirectory),
new SystemDetail("Current Path", Environment.CurrentDirectory),
new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()),
new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription),
new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()),
new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()),
new SystemDetail("Framework Version", Environment.Version.ToString()),
};
private string ComputerImageName
{ {
get if (Utilities.IsWindows)
{ return !_darkTheme ? "windows.png" : "windows_d.png";
if (Utilities.IsWindows) else if (Utilities.IsOSX)
return !_darkTheme ? "windows.png" : "windows_d.png"; return !_darkTheme ? "macos.png" : "macos_d.png";
else if (Utilities.IsOSX) else
return !_darkTheme ? "macos.png" : "macos_d.png"; return !_darkTheme ? "linux.png" : "linux_d.png";
else
return !_darkTheme ? "linux.png" : "linux_d.png";
}
}
public AboutViewModel(bool darkTheme) : this()
{
_darkTheme = darkTheme;
_computerImage = Utilities.GetImageFromResources(ComputerImageName);
}
~AboutViewModel()
{
_computerImage.Dispose();
} }
} }
public AboutViewModel(bool darkTheme) : this()
{
_darkTheme = darkTheme;
_computerImage = Utilities.GetImageFromResources(ComputerImageName);
}
~AboutViewModel()
{
_computerImage.Dispose();
}
} }

View File

@ -1,90 +1,87 @@
using System; using Avalonia.Controls;
using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using MvvmGen; using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels;
[ViewModel]
internal abstract partial class ApplicationModelBase
{ {
[ViewModel] private readonly IThemeSwitch _themeSwitch;
internal abstract partial class ApplicationModelBase
[Property]
private bool _aboutEnabled = true;
[Property]
private bool _defaultLightEnabled = false;
[Property]
private bool _defaultDarkEnabled = false;
[Property]
private bool _fluentLightEnabled = false;
[Property]
private bool _fluentDarkEnabled = false;
public ApplicationModelBase(IThemeSwitch themeSwitch) : this()
{ {
private readonly IThemeSwitch _themeSwitch; _themeSwitch = themeSwitch;
IntializeTheme(themeSwitch.Current);
[Property]
private bool _aboutEnabled = true;
[Property]
private bool _defaultLightEnabled = false;
[Property]
private bool _defaultDarkEnabled = false;
[Property]
private bool _fluentLightEnabled = false;
[Property]
private bool _fluentDarkEnabled = false;
public ApplicationModelBase(IThemeSwitch themeSwitch) : this()
{
_themeSwitch = themeSwitch;
IntializeTheme(themeSwitch.Current);
}
[Command]
protected abstract void HelpAbout();
[Command]
protected abstract void DefaultLight();
[Command]
protected abstract void DefaultDark();
[Command]
protected abstract void FluentLight();
[Command]
protected abstract void FluentDark();
protected async void RunHelpAbout(Window currentWindow)
{
if (AboutEnabled)
try
{
AboutEnabled = false;
await new AboutWindow(IsDarkTheme(_themeSwitch.Current)).ShowDialog(currentWindow);
}
finally
{
AboutEnabled = true;
}
}
protected void SetTheme(ApplicationTheme theme)
{
IntializeTheme(theme);
_themeSwitch.ChangeTheme(theme);
}
[Command]
private void FileExit() => Environment.Exit(0);
private void IntializeTheme(ApplicationTheme theme)
{
DefaultLightEnabled = theme != ApplicationTheme.SimpleLight;
DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark;
FluentLightEnabled = theme != ApplicationTheme.FluentLight;
FluentDarkEnabled = theme != ApplicationTheme.FluentDark;
}
private static bool IsDarkTheme(ApplicationTheme? theme) =>
theme switch
{
ApplicationTheme.SimpleDark => true,
ApplicationTheme.FluentDark => true,
_ => false,
};
} }
[Command]
protected abstract void HelpAbout();
[Command]
protected abstract void DefaultLight();
[Command]
protected abstract void DefaultDark();
[Command]
protected abstract void FluentLight();
[Command]
protected abstract void FluentDark();
protected async void RunHelpAbout(Window currentWindow)
{
if (AboutEnabled)
try
{
AboutEnabled = false;
await new AboutWindow(IsDarkTheme(_themeSwitch.Current)).ShowDialog(currentWindow);
}
finally
{
AboutEnabled = true;
}
}
protected void SetTheme(ApplicationTheme theme)
{
IntializeTheme(theme);
_themeSwitch.ChangeTheme(theme);
}
[Command]
private void FileExit() => Environment.Exit(0);
private void IntializeTheme(ApplicationTheme theme)
{
DefaultLightEnabled = theme != ApplicationTheme.SimpleLight;
DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark;
FluentLightEnabled = theme != ApplicationTheme.FluentLight;
FluentDarkEnabled = theme != ApplicationTheme.FluentDark;
}
private static bool IsDarkTheme(ApplicationTheme? theme) =>
theme switch
{
ApplicationTheme.SimpleDark => true,
ApplicationTheme.FluentDark => true,
_ => false,
};
} }

View File

@ -1,27 +1,25 @@
using Avalonia.Controls; using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels;
internal sealed class MainViewModel<TWindow> : ApplicationModelBase where TWindow : Window, IMainWindow
{ {
internal sealed class MainViewModel<TWindow> : ApplicationModelBase where TWindow : Window, IMainWindow private TWindow _window;
public MainViewModel(TWindow window) : base(window.ThemeSwitch)
{ {
private TWindow _window; _window = window;
public MainViewModel(TWindow window) : base(window.ThemeSwitch)
{
_window = window;
}
protected override void HelpAbout() => RunHelpAbout(_window);
protected override void DefaultLight() => SetTheme(ApplicationTheme.SimpleLight);
protected override void DefaultDark() => SetTheme(ApplicationTheme.SimpleDark);
protected override void FluentLight() => SetTheme(ApplicationTheme.FluentLight);
protected override void FluentDark() => SetTheme(ApplicationTheme.FluentDark);
} }
protected override void HelpAbout() => RunHelpAbout(_window);
protected override void DefaultLight() => SetTheme(ApplicationTheme.SimpleLight);
protected override void DefaultDark() => SetTheme(ApplicationTheme.SimpleDark);
protected override void FluentLight() => SetTheme(ApplicationTheme.FluentLight);
protected override void FluentDark() => SetTheme(ApplicationTheme.FluentDark);
} }