Do something

This commit is contained in:
Holger Börchers 2024-08-15 21:39:10 +02:00
parent 4107ca217a
commit 90430ff32f
16 changed files with 88 additions and 96 deletions

View File

@ -5,7 +5,6 @@ using Avalonia.Markup.Xaml;
using Avalonia.Styling;
using Avalonia.Themes.Fluent;
using Avalonia.Themes.Simple;
using AvaloniaCoreRTDemo.Interfaces;
using AvaloniaCoreRTDemo.Windows;
@ -57,7 +56,7 @@ public sealed class App : Application, IThemeSwitch
if (theme == _currentTheme)
return;
bool themeChanged = theme switch
var themeChanged = theme switch
{
ApplicationTheme.SimpleLight
=> _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
@ -95,17 +94,15 @@ public sealed class App : Application, IThemeSwitch
break;
}
if (themeChanged && ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
MainWindow oldWindow = (desktop.MainWindow as MainWindow)!;
MainWindow newWindow = new MainWindow(oldWindow);
if (!themeChanged || ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) return;
var oldWindow = (desktop.MainWindow as MainWindow)!;
var newWindow = new MainWindow(oldWindow);
desktop.MainWindow = newWindow;
DataContext = newWindow.DataContext;
desktop.MainWindow = newWindow;
DataContext = newWindow.DataContext;
oldWindow.Hide();
newWindow.Show();
oldWindow?.Close();
}
oldWindow.Hide();
newWindow.Show();
oldWindow.Close();
}
}

View File

@ -6,4 +6,4 @@ public enum ApplicationTheme : byte
SimpleDark = 1,
FluentLight = 2,
FluentDark = 3,
}
}

View File

@ -4,11 +4,11 @@
<!-- if you want to check exceptions, change this to "Exe" and start your app from the console -->
<OutputType Condition="'$(Configuration.toUpper())' != 'DEBUG'">WinExe</OutputType>
<OutputType Condition="'$(Configuration.toUpper())' == 'DEBUG'">Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ApplicationIcon>Assets/app.ico</ApplicationIcon>
<InvariantGlobalization>true</InvariantGlobalization>
<Nullable>enable</Nullable>
<PublishAot>false</PublishAot>
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<SelfContained>true</SelfContained>
<ImplicitUsings>enable</ImplicitUsings>
@ -48,20 +48,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-*" />
<PackageReference Include="Avalonia" Version="11.1.3" />
<PackageReference Include="Avalonia.Desktop" Version="11.1.3" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.3" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-*" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.3" />
<!--Condition below is needed to generate macOS App only.-->
<PackageReference Include="Dotnet.Bundle" Version="0.9.13" Condition="$(RuntimeIdentifier.StartsWith('osx'))" />
<PackageReference Include="MvvmGen.PureCodeGeneration" Version="1.2.1">
<PackageReference Include="MvvmGen.PureCodeGeneration" Version="1.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="PublishAotCompressed" Version="1.0.0" />
</ItemGroup>
<!-- Information for Dotnet.Bundle to Generate macOS app-->

View File

@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using AvaloniaCoreRTDemo.Controls.ViewModels;
namespace AvaloniaCoreRTDemo.Controls;
@ -22,4 +21,4 @@ public sealed partial class MainControl : UserControl
{
DataContext = new MainControlViewModel(model);
}
}
}

View File

@ -1,18 +1,17 @@
using Avalonia.Media.Imaging;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Controls.ViewModels;
[ViewModel]
internal sealed partial class MainControlViewModel : IMainWindowState
{
private IBitmap _dotNetImage;
private IBitmap _avaloniaImage;
private Bitmap _dotNetImage;
private Bitmap _avaloniaImage;
private bool _unloadable = false;
public IBitmap DotNetImage => _dotNetImage;
public IBitmap AvaloniaImage => _avaloniaImage;
public Bitmap DotNetImage => _dotNetImage;
public Bitmap AvaloniaImage => _avaloniaImage;
public string? Text { get; set; }
partial void OnInitialize()
@ -21,7 +20,8 @@ internal sealed partial class MainControlViewModel : IMainWindowState
_avaloniaImage = Utilities.GetImageFromFile("avalonia.png");
}
public MainControlViewModel(IMainWindowState state) : this()
public MainControlViewModel(IMainWindowState state)
: this()
{
_avaloniaImage = state.AvaloniaImage;
_dotNetImage = state.DotNetImage;
@ -42,4 +42,4 @@ internal sealed partial class MainControlViewModel : IMainWindowState
{
_unloadable = true;
}
}
}

3
src/GlobalUsings.cs Normal file
View File

@ -0,0 +1,3 @@
// Global using directives
global using MvvmGen;

View File

@ -11,4 +11,4 @@ public interface IMainWindow
Size ClientSize { get; }
Size? FrameSize { get; }
WindowState State { get; }
}
}

View File

@ -4,9 +4,9 @@ namespace AvaloniaCoreRTDemo;
public interface IMainWindowState
{
IBitmap DotNetImage { get; }
IBitmap AvaloniaImage { get; }
Bitmap DotNetImage { get; }
Bitmap AvaloniaImage { get; }
string? Text { get; }
void SetUnloadable();
}
}

View File

@ -4,4 +4,4 @@ public interface IThemeSwitch
{
ApplicationTheme Current { get; }
void ChangeTheme(ApplicationTheme theme);
}
}

View File

@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
@ -14,8 +13,9 @@ internal static class Utilities
public static Bitmap GetImageFromResources(string fileName)
{
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}"));
using var assetStream = AssetLoader.Open(
new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}")
);
return new Bitmap(assetStream);
}
@ -23,11 +23,8 @@ internal static class Utilities
{
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);
}
var yOffset = (int)(window.FrameSize.Value.Height - window.ClientSize.Height);
return new(window.Position.X, window.Position.Y + yOffset);
}
public static Bitmap GetImageFromFile(string path)
@ -42,5 +39,6 @@ internal static class Utilities
}
}
private static string GetImageFullPath(string fileName) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}
private static string GetImageFullPath(string fileName) =>
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}

View File

@ -37,7 +37,7 @@
CanUserSortColumns="False"
HeadersVisibility="None"
IsReadOnly="True"
Items="{Binding SystemDetails}">
ItemsSource="{Binding SystemDetails}">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Key, x:DataType=viewModels:SystemDetail}"

View File

@ -1,7 +1,5 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using AvaloniaCoreRTDemo.Windows.ViewModels;
namespace AvaloniaCoreRTDemo.Windows;
@ -10,7 +8,8 @@ public sealed partial class AboutWindow : Window
{
private readonly bool _darkTheme;
public AboutWindow() : this(false) { }
public AboutWindow()
: this(false) { }
public AboutWindow(bool darkTheme)
{
@ -26,4 +25,4 @@ public sealed partial class AboutWindow : Window
AvaloniaXamlLoader.Load(this);
DataContext = new AboutViewModel(_darkTheme);
}
}
}

View File

@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using AvaloniaCoreRTDemo.Controls;
using AvaloniaCoreRTDemo.Interfaces;
using AvaloniaCoreRTDemo.Windows.ViewModels;
@ -14,7 +13,8 @@ public sealed partial class MainWindow : Window, IMainWindow
private MainControl MainController => this.GetControl<MainControl>("MainControl");
public MainWindow() : this(default) { }
public MainWindow()
: this(default) { }
public MainWindow(IMainWindow? window)
{
@ -45,4 +45,4 @@ public sealed partial class MainWindow : Window, IMainWindow
ClientSize = window.ClientSize;
}
}
}
}

View File

@ -1,7 +1,5 @@
using System.Runtime.InteropServices;
using Avalonia.Media.Imaging;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels;
@ -10,28 +8,27 @@ internal record SystemDetail(string Key, string Value);
[ViewModel]
internal sealed partial class AboutViewModel
{
private readonly IBitmap _computerImage;
private readonly Bitmap _computerImage;
private readonly bool _darkTheme;
public IBitmap ComputerImage => _computerImage;
public Bitmap 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()),
};
[
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
{
@ -39,14 +36,14 @@ internal sealed partial class AboutViewModel
{
if (Utilities.IsWindows)
return !_darkTheme ? "windows.png" : "windows_d.png";
else if (Utilities.IsOSX)
if (Utilities.IsOSX)
return !_darkTheme ? "macos.png" : "macos_d.png";
else
return !_darkTheme ? "linux.png" : "linux_d.png";
return !_darkTheme ? "linux.png" : "linux_d.png";
}
}
public AboutViewModel(bool darkTheme) : this()
public AboutViewModel(bool darkTheme)
: this()
{
_darkTheme = darkTheme;
_computerImage = Utilities.GetImageFromResources(ComputerImageName);
@ -56,4 +53,4 @@ internal sealed partial class AboutViewModel
{
_computerImage.Dispose();
}
}
}

View File

@ -1,7 +1,5 @@
using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels;
@ -14,21 +12,22 @@ internal abstract partial class ApplicationModelBase
private bool _aboutEnabled = true;
[Property]
private bool _defaultLightEnabled = false;
private bool _defaultLightEnabled;
[Property]
private bool _defaultDarkEnabled = false;
private bool _defaultDarkEnabled;
[Property]
private bool _fluentLightEnabled = false;
private bool _fluentLightEnabled;
[Property]
private bool _fluentDarkEnabled = false;
private bool _fluentDarkEnabled;
public ApplicationModelBase(IThemeSwitch themeSwitch) : this()
public ApplicationModelBase(IThemeSwitch themeSwitch)
: this()
{
_themeSwitch = themeSwitch;
IntializeTheme(themeSwitch.Current);
InitializeTheme(themeSwitch.Current);
}
[Command]
@ -62,14 +61,14 @@ internal abstract partial class ApplicationModelBase
protected void SetTheme(ApplicationTheme theme)
{
IntializeTheme(theme);
InitializeTheme(theme);
_themeSwitch.ChangeTheme(theme);
}
[Command]
private void FileExit() => Environment.Exit(0);
private void IntializeTheme(ApplicationTheme theme)
private void InitializeTheme(ApplicationTheme theme)
{
DefaultLightEnabled = theme != ApplicationTheme.SimpleLight;
DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark;
@ -84,4 +83,4 @@ internal abstract partial class ApplicationModelBase
ApplicationTheme.FluentDark => true,
_ => false,
};
}
}

View File

@ -1,14 +1,15 @@
using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces;
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;
private readonly TWindow _window;
public MainViewModel(TWindow window) : base(window.ThemeSwitch)
public MainViewModel(TWindow window)
: base(window.ThemeSwitch)
{
_window = window;
}
@ -22,4 +23,4 @@ internal sealed class MainViewModel<TWindow> : ApplicationModelBase where TWindo
protected override void FluentLight() => SetTheme(ApplicationTheme.FluentLight);
protected override void FluentDark() => SetTheme(ApplicationTheme.FluentDark);
}
}