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

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

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

@ -4,11 +4,11 @@
<!-- if you want to check exceptions, change this to "Exe" and start your app from the console --> <!-- 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'">WinExe</OutputType>
<OutputType Condition="'$(Configuration.toUpper())' == 'DEBUG'">Exe</OutputType> <OutputType Condition="'$(Configuration.toUpper())' == 'DEBUG'">Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ApplicationIcon>Assets/app.ico</ApplicationIcon> <ApplicationIcon>Assets/app.ico</ApplicationIcon>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>false</PublishAot> <PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed> <PublishTrimmed>true</PublishTrimmed>
<SelfContained>true</SelfContained> <SelfContained>true</SelfContained>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -48,20 +48,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-*" /> <PackageReference Include="Avalonia" Version="11.1.3" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Desktop" Version="11.1.3" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Themes.Simple" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.3" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--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.--> <!--Condition below is needed to generate macOS App only.-->
<PackageReference Include="Dotnet.Bundle" Version="0.9.13" Condition="$(RuntimeIdentifier.StartsWith('osx'))" /> <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> <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-->

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

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

3
src/GlobalUsings.cs Normal file

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

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

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

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

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

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

@ -1,7 +1,5 @@
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;
@ -10,7 +8,8 @@ public sealed partial class AboutWindow : Window
{ {
private readonly bool _darkTheme; private readonly bool _darkTheme;
public AboutWindow() : this(false) { } public AboutWindow()
: this(false) { }
public AboutWindow(bool darkTheme) public AboutWindow(bool darkTheme)
{ {
@ -26,4 +25,4 @@ public sealed partial class AboutWindow : Window
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
DataContext = new AboutViewModel(_darkTheme); DataContext = new AboutViewModel(_darkTheme);
} }
} }

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

@ -1,7 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels; namespace AvaloniaCoreRTDemo.Windows.ViewModels;
@ -10,28 +8,27 @@ internal record SystemDetail(string Key, string Value);
[ViewModel] [ViewModel]
internal sealed partial class AboutViewModel internal sealed partial class AboutViewModel
{ {
private readonly IBitmap _computerImage; private readonly Bitmap _computerImage;
private readonly bool _darkTheme; private readonly bool _darkTheme;
public IBitmap ComputerImage => _computerImage; public Bitmap ComputerImage => _computerImage;
public IReadOnlyList<SystemDetail> SystemDetails { get; } = public IReadOnlyList<SystemDetail> SystemDetails { get; } =
new[] [
{ new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()),
new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()), new SystemDetail("OS", RuntimeInformation.OSDescription),
new SystemDetail("OS", RuntimeInformation.OSDescription), new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()),
new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()), new SystemDetail("OS Version", Environment.OSVersion.ToString()),
new SystemDetail("OS Version", Environment.OSVersion.ToString()), new SystemDetail("Computer", Environment.MachineName),
new SystemDetail("Computer", Environment.MachineName), new SystemDetail("User", Environment.UserName),
new SystemDetail("User", Environment.UserName), new SystemDetail("System Path", Environment.SystemDirectory),
new SystemDetail("System Path", Environment.SystemDirectory), new SystemDetail("Current Path", Environment.CurrentDirectory),
new SystemDetail("Current Path", Environment.CurrentDirectory), new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()),
new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()), new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription),
new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription), new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()),
new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()), new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()),
new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()), new SystemDetail("Framework Version", Environment.Version.ToString())
new SystemDetail("Framework Version", Environment.Version.ToString()), ];
};
private string ComputerImageName private string ComputerImageName
{ {
@ -39,14 +36,14 @@ internal sealed partial class AboutViewModel
{ {
if (Utilities.IsWindows) if (Utilities.IsWindows)
return !_darkTheme ? "windows.png" : "windows_d.png"; return !_darkTheme ? "windows.png" : "windows_d.png";
else if (Utilities.IsOSX) if (Utilities.IsOSX)
return !_darkTheme ? "macos.png" : "macos_d.png"; 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; _darkTheme = darkTheme;
_computerImage = Utilities.GetImageFromResources(ComputerImageName); _computerImage = Utilities.GetImageFromResources(ComputerImageName);
@ -56,4 +53,4 @@ internal sealed partial class AboutViewModel
{ {
_computerImage.Dispose(); _computerImage.Dispose();
} }
} }

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

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