file-scoped namespaces and other cleanup stuff
This commit is contained in:
parent
c2e7cc1a3c
commit
fc7cdceb05
171
src/App.axaml.cs
171
src/App.axaml.cs
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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-->
|
||||||
|
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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();
|
||||||
}
|
|
||||||
}
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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();
|
||||||
}
|
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
@ -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,
|
||||||
|
};
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user