Merge pull request #29 from josephmoresena/master
Avalonia UI 11 Preview 5
This commit is contained in:
		
							
								
								
									
										16
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							| @@ -25,9 +25,9 @@ jobs: | ||||
|       with: | ||||
|         name: Linux-Artifact | ||||
|         path: | | ||||
|           ./src/bin/x64/Release/net7.0/linux-x64/publish/*.bin | ||||
|           ./src/bin/x64/Release/net7.0/linux-x64/publish/*.so | ||||
|           ./src/bin/x64/Release/net7.0/linux-x64/publish/*.png | ||||
|           ./src/bin/Release/net7.0/linux-x64/publish/*.bin | ||||
|           ./src/bin/Release/net7.0/linux-x64/publish/*.so | ||||
|           ./src/bin/Release/net7.0/linux-x64/publish/*.png | ||||
|   build-on-windows: | ||||
|     runs-on: windows-latest | ||||
|     steps: | ||||
| @@ -42,9 +42,9 @@ jobs: | ||||
|       with: | ||||
|         name: Windows-Artifact | ||||
|         path: | | ||||
|           .\src\bin\x64\Release\net7.0\win-x64\publish\*.exe | ||||
|           .\src\bin\x64\Release\net7.0\win-x64\publish\*.dll | ||||
|           .\src\bin\x64\Release\net7.0\win-x64\publish\*.png | ||||
|           .\src\bin\Release\net7.0\win-x64\publish\*.exe | ||||
|           .\src\bin\Release\net7.0\win-x64\publish\*.dll | ||||
|           .\src\bin\Release\net7.0\win-x64\publish\*.png | ||||
|   build-on-macos: | ||||
|     runs-on: macos-latest | ||||
|     steps: | ||||
| @@ -57,9 +57,9 @@ jobs: | ||||
|       run: | | ||||
|         sudo chmod +x ./test.command | ||||
|         ./test.command | ||||
|         cd ./src/bin/x64/Release/net7.0/osx-x64/publish | ||||
|         cd ./src/bin/Release/net7.0/osx-x64/publish | ||||
|         zip -r -0 macOS-Artifact.zip *.app | ||||
|         mv *.zip ../../../../../../../. | ||||
|         mv *.zip ../../../../../../. | ||||
|     - uses: actions/upload-artifact@v2 | ||||
|       with: | ||||
|         name: macOS-Artifact | ||||
|   | ||||
| @@ -7,14 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaCoreRTDemo", "src\A | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|x64 = Debug|x64 | ||||
| 		Release|x64 = Release|x64 | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| 		Release|Any CPU = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Debug|x64.ActiveCfg = Debug|x64 | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Debug|x64.Build.0 = Debug|x64 | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Release|x64.ActiveCfg = Release|x64 | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Release|x64.Build.0 = Release|x64 | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{41A52A04-F7D8-4981-9546-DB020E54851D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
| @@ -7,7 +7,7 @@ This project is tested only under Windows, and this readme assumes you are using | ||||
| * Any supported 64-bit edition of Windows. NativeAOT requires 64-bit Windows and produces only 64-bit Windows apps. | ||||
| * Visual Studio. VS 2022 Community is free for personal use. Get if from [here](https://visualstudio.microsoft.com). | ||||
| When installing Visual Studio, select *.NET desktop development* and *Desktop development with C++* workloads. To generate native code, NativeAOT requires the native C++ toolchain and Windows SDK. This configuration ensures you have them. | ||||
| * .Net 6.0 SDK. Download it from [here](https://dotnet.microsoft.com/download/dotnet/6.0). Note: Make sure that you download and install the *SDK*. The runtime is not enough for building apps. | ||||
| * .Net 7.0 SDK. Download it from [here](https://dotnet.microsoft.com/download/dotnet/7.0). Note: Make sure that you download and install the *SDK*. The runtime is not enough for building apps. | ||||
| * Git. Install [Git for Windows](https://git-scm.com/download/win). | ||||
|  | ||||
| ## Getting started | ||||
| @@ -34,8 +34,6 @@ We are ready - In your terminal, navigate to `src\bin\Release\net6.0\win-x64\pub | ||||
|  | ||||
| Feel free to use this sample as a base for your projects. | ||||
|  | ||||
| When developing, keep in mind that Avalonia uses Reflection extensively. NativeAOT, being an AOT compiler, needs your help to get reflection right. Refer to `rd.xml` file in the solution. In it, you describe all assemblies and types which your app would potentially reflect over. For more information, see [Reflection in AOT mode](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/reflection-in-aot-mode.md) | ||||
|  | ||||
| This project is configured to help you debug issues with publishing. Before publishing, check the CSPROJ file and modify the various Ilc* properties according to [Optimizing programs targeting Native AOT](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/optimizing.md) document. | ||||
|  | ||||
| ## Artifact test | ||||
|   | ||||
| @@ -1,10 +1,17 @@ | ||||
| <Application xmlns="https://github.com/avaloniaui" | ||||
|              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
|              x:Class="AvaloniaCoreRTDemo.App"> | ||||
|              xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" | ||||
| 			 RequestedThemeVariant="Light" | ||||
|              x:Class="AvaloniaCoreRTDemo.App" | ||||
| 		     x:CompileBindings="True" | ||||
|              x:DataType="viewModels1:ApplicationModelBase"> | ||||
| 	<NativeMenu.Menu> | ||||
| 		<NativeMenu> | ||||
| 			<NativeMenuItem Header="About" Gesture="cmd+b" IsEnabled="{Binding AboutEnabled}" Command="{Binding HelpAboutMethod}"/> | ||||
| 		</NativeMenu> | ||||
| 	</NativeMenu.Menu> | ||||
| 	<Application.Resources> | ||||
| 		<StyleInclude x:Key="fluentDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" /> | ||||
| 		<StyleInclude x:Key="simpleDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml" /> | ||||
| 		<FluentTheme x:Key="fluentTheme" Mode="Light" /> | ||||
| 		<SimpleTheme x:Key="simpleTheme" Mode="Light" /> | ||||
| 	</Application.Resources> | ||||
| </Application> | ||||
| @@ -1,11 +1,13 @@ | ||||
|  | ||||
| using System; | ||||
|  | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
| using Avalonia.Controls.ApplicationLifetimes; | ||||
| using Avalonia.Markup.Xaml; | ||||
| using Avalonia.Styling; | ||||
| using Avalonia.Themes.Fluent; | ||||
| using Avalonia.Themes.Simple; | ||||
|  | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
| using AvaloniaCoreRTDemo.Windows; | ||||
|  | ||||
| @@ -13,10 +15,10 @@ namespace AvaloniaCoreRTDemo | ||||
| { | ||||
|     public sealed class App : Application, IThemeSwitch | ||||
|     { | ||||
|         private FluentTheme _fluentTheme; | ||||
|         private SimpleTheme _simpleTheme; | ||||
|         private IStyle _fluentDataGrid; | ||||
|         private IStyle _simpleDataGrid; | ||||
|         private FluentTheme _fluentTheme = default!; | ||||
|         private SimpleTheme _simpleTheme = default!; | ||||
|         private IStyle _fluentDataGrid = default!; | ||||
|         private IStyle _simpleDataGrid = default!; | ||||
|  | ||||
|         private ApplicationTheme _currentTheme; | ||||
|  | ||||
| @@ -39,13 +41,14 @@ namespace AvaloniaCoreRTDemo | ||||
|  | ||||
|         private void InitializeThemes() | ||||
|         { | ||||
|             this._fluentTheme = (FluentTheme)this.Resources["fluentTheme"]!; | ||||
|             this._simpleTheme = (SimpleTheme)this.Resources["simpleTheme"]!; | ||||
|             this._simpleTheme = new SimpleTheme(); | ||||
|             this._fluentTheme = new FluentTheme(); | ||||
|  | ||||
|             this._fluentDataGrid = (IStyle)this.Resources["fluentDataGrid"]!; | ||||
|             this._simpleDataGrid = (IStyle)this.Resources["simpleDataGrid"]!; | ||||
|  | ||||
|             Styles.Add(_fluentTheme); | ||||
|             Styles.Add(_fluentDataGrid); | ||||
|  | ||||
|             this._currentTheme = ApplicationTheme.FluentLight; | ||||
|         } | ||||
|  | ||||
| @@ -53,48 +56,54 @@ namespace AvaloniaCoreRTDemo | ||||
|  | ||||
|         void IThemeSwitch.ChangeTheme(ApplicationTheme theme) | ||||
|         { | ||||
|             var themeChanged = theme switch | ||||
|             if (theme == this._currentTheme) | ||||
|                 return; | ||||
|  | ||||
|             Boolean 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, | ||||
|                 ApplicationTheme.SimpleLight => this._currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight, | ||||
|                 ApplicationTheme.SimpleDark => this._currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight, | ||||
|                 ApplicationTheme.FluentLight => this._currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark, | ||||
|                 ApplicationTheme.FluentDark => this._currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark, | ||||
|                 _ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null) | ||||
|             }; | ||||
|              | ||||
|  | ||||
|             this._currentTheme = theme; | ||||
|             switch (theme) | ||||
|             { | ||||
|                 case ApplicationTheme.SimpleLight: | ||||
|                     this._simpleTheme.Mode = SimpleThemeMode.Light; | ||||
|                     this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light); | ||||
|                     this.Styles[0] = this._simpleTheme; | ||||
|                     this.Styles[1] = this._simpleDataGrid; | ||||
|                     break; | ||||
|                 case ApplicationTheme.SimpleDark: | ||||
|                     this._simpleTheme.Mode = SimpleThemeMode.Dark; | ||||
|                     this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark); | ||||
|                     this.Styles[0] = this._simpleTheme; | ||||
|                     this.Styles[1] = this._simpleDataGrid; | ||||
|                     break; | ||||
|                 case ApplicationTheme.FluentLight: | ||||
|                     this._fluentTheme.Mode = FluentThemeMode.Light; | ||||
|                     this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light); | ||||
|                     this.Styles[0] = this._fluentTheme; | ||||
|                     this.Styles[1] = this._fluentDataGrid; | ||||
|                     break; | ||||
|                 case ApplicationTheme.FluentDark: | ||||
|                     this._fluentTheme.Mode = FluentThemeMode.Dark; | ||||
|                     this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark); | ||||
|                     this.Styles[0] = this._fluentTheme; | ||||
|                     this.Styles[1] = this._fluentDataGrid; | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             if (themeChanged && ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) | ||||
|             if (themeChanged && this.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) | ||||
|             { | ||||
|                 var oldWindow = desktop.MainWindow; | ||||
|                 var newWindow = new MainWindow(); | ||||
|                 MainWindow oldWindow = (desktop.MainWindow as MainWindow)!; | ||||
|                 MainWindow newWindow = new MainWindow(oldWindow); | ||||
|  | ||||
|                 desktop.MainWindow = newWindow; | ||||
|                 this.DataContext = newWindow.DataContext; | ||||
|  | ||||
|                 oldWindow.Hide(); | ||||
|                 newWindow.Show(); | ||||
|                 oldWindow.Close(); | ||||
|                 this.DataContext = desktop.MainWindow.DataContext; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -2,25 +2,31 @@ | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <!-- if you want to check exceptions, change this to "Exe" and start your app from the console --> | ||||
|     <OutputType>WinExe</OutputType> | ||||
|     <OutputType Condition="'$(Configuration.toUpper())' != 'DEBUG'">WinExe</OutputType> | ||||
|     <OutputType Condition="'$(Configuration.toUpper())' == 'DEBUG'">Exe</OutputType> | ||||
|     <TargetFramework>net7.0</TargetFramework> | ||||
|     <Platforms>x64</Platforms> | ||||
|     <ApplicationIcon>Assets/app.ico</ApplicationIcon> | ||||
|     <InvariantGlobalization>true</InvariantGlobalization> | ||||
|     <Nullable>enable</Nullable> | ||||
|     <PublishAot>true</PublishAot> | ||||
|  | ||||
|     <PublishTrimmed>true</PublishTrimmed> | ||||
|     <SelfContained>true</SelfContained> | ||||
|   </PropertyGroup> | ||||
|    | ||||
|   <PropertyGroup> | ||||
|     <IsWindows Condition="$([MSBuild]::IsOSPlatform('Windows'))">true</IsWindows> | ||||
|     <IsLinux Condition="$([MSBuild]::IsOSPlatform('Linux'))">true</IsLinux> | ||||
|     <IsOSX Condition="$([MSBuild]::IsOSPlatform('OSX'))">true</IsOSX> | ||||
|   </PropertyGroup> | ||||
|    | ||||
|   <PropertyGroup> | ||||
|     <!--Tthese can help when debugging weird exceptions especially when reflection is involved. See https://github.com/dotnet/corert/blob/master/Documentation/using-corert/optimizing-corert.md -->   | ||||
|     <TrimMode>link</TrimMode> | ||||
|     <!--These can help when debugging weird exceptions especially when reflection is involved. See https://github.com/dotnet/corert/blob/master/Documentation/using-corert/optimizing-corert.md -->   | ||||
|     <!--RootAllApplicationAssemblies: False -> TrimMode:link See https://github.com/dotnet/runtimelab/issues/597 and https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/docs/using-nativeaot/optimizing.md --> | ||||
|     <IlcGenerateCompleteTypeMetadata>false</IlcGenerateCompleteTypeMetadata> | ||||
|     <IlcGenerateStackTraceData>false</IlcGenerateStackTraceData> | ||||
|     <IlcGenerateStackTraceData Condition="'$(Configuration.toUpper())' != 'DEBUG'">false</IlcGenerateStackTraceData> | ||||
|     <IlcDisableUnhandledExceptionExperience>true</IlcDisableUnhandledExceptionExperience> | ||||
|     <StripSymbols>true</StripSymbols> | ||||
|     <StripSymbols Condition="'$(Configuration.toUpper())' != 'DEBUG'">true</StripSymbols> | ||||
|   </PropertyGroup> | ||||
|    | ||||
|   <ItemGroup> | ||||
| @@ -37,19 +43,20 @@ | ||||
|       <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> | ||||
|       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||||
|     </None> | ||||
|     <RuntimeHostConfigurationOption Include="Switch.System.Reflection.Assembly.SimulatedCallingAssembly" Value="true" /> | ||||
|   </ItemGroup> | ||||
|      | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Avalonia" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Include="Avalonia.Desktop" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Include="Avalonia.Themes.Simple" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.999-cibuild0026389-beta" /> | ||||
|     <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.ReactiveUI" Version="11.0.0-*" /> | ||||
|     <PackageReference Include="Avalonia.Themes.Simple" Version="11.0.0-*" /> | ||||
|     <PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-*" /> | ||||
|     <!--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.999-cibuild0026389-beta" /> | ||||
|     <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-*" /> | ||||
|     <!--Condition below is needed to generate macOS App only.--> | ||||
|     <PackageReference Include="Dotnet.Bundle" Version="*" Condition="$(RuntimeIdentifier.StartsWith('osx'))" /> | ||||
|     <PackageReference Include="Dotnet.Bundle" Version="0.9.13" Condition="$(RuntimeIdentifier.StartsWith('osx'))" /> | ||||
|   </ItemGroup> | ||||
|   	 | ||||
|   <!-- Information for Dotnet.Bundle to Generate macOS app--> | ||||
|   | ||||
| @@ -2,11 +2,11 @@ | ||||
|              xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels" | ||||
|              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Controls.MainControl" | ||||
| 			 x:CompileBindings="True" | ||||
| 			 x:DataType="viewModels:MainViewModel"> | ||||
| 			 x:DataType="viewModels:MainControlViewModel"> | ||||
| 	<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*" Margin="32"> | ||||
| 		<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" TextAlignment="Center" Margin="0,6">Welcome to Avalonia UI + NativeAOT!</TextBlock> | ||||
| 		<Image Grid.Row="1" Grid.Column="0" Stretch="None" Source="{Binding DotNetImage}"/> | ||||
| 		<Image Grid.Row="1" Grid.Column="1" Stretch="None" Source="{Binding AvaloniaImage}"/> | ||||
| 		<TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Watermark="Type here" AcceptsReturn="True" TextWrapping="Wrap"/> | ||||
| 		<TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Watermark="Type here" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Text}"/> | ||||
| 	</Grid> | ||||
| </UserControl> | ||||
|   | ||||
| @@ -9,13 +9,18 @@ namespace AvaloniaCoreRTDemo.Controls | ||||
|     { | ||||
|         public MainControl() | ||||
|         { | ||||
|             InitializeComponent(); | ||||
|             this.InitializeComponent(); | ||||
|         } | ||||
|  | ||||
|         private void InitializeComponent() | ||||
|         { | ||||
|             AvaloniaXamlLoader.Load(this); | ||||
|             this.DataContext = new MainViewModel(); | ||||
|             this.DataContext = new MainControlViewModel(); | ||||
|         } | ||||
|  | ||||
|         public void Reload(IMainWindowState model) | ||||
|         { | ||||
|             this.DataContext = new MainControlViewModel(model); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										48
									
								
								src/Controls/ViewModels/MainControlViewModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/Controls/ViewModels/MainControlViewModel.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| using System; | ||||
|  | ||||
| using Avalonia.Media.Imaging; | ||||
|  | ||||
| using ReactiveUI; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo.Controls.ViewModels | ||||
| { | ||||
|     internal sealed class MainControlViewModel : ReactiveObject, IMainWindowState | ||||
|     { | ||||
|         private readonly IBitmap _dotNetImage; | ||||
|         private readonly IBitmap _avaloniaImage; | ||||
|  | ||||
|         private Boolean _unloadable = false; | ||||
|  | ||||
|         public IBitmap DotNetImage => this._dotNetImage; | ||||
|         public IBitmap AvaloniaImage => this._avaloniaImage; | ||||
|         public String? Text { get; set; } | ||||
|  | ||||
|         public MainControlViewModel() | ||||
|         { | ||||
|             this._dotNetImage = Utilities.GetImageFromFile("dotnet.png"); | ||||
|             this._avaloniaImage = Utilities.GetImageFromFile("avalonia.png"); | ||||
|         } | ||||
|  | ||||
|         public MainControlViewModel(IMainWindowState state) | ||||
|         { | ||||
|             this._avaloniaImage = state.AvaloniaImage; | ||||
|             this._dotNetImage = state.DotNetImage; | ||||
|             this.Text = state.Text; | ||||
|             state.SetUnloadable(); | ||||
|         } | ||||
|  | ||||
|         ~MainControlViewModel() | ||||
|         { | ||||
|             if (!this._unloadable) | ||||
|             { | ||||
|                 this._dotNetImage.Dispose(); | ||||
|                 this._avaloniaImage.Dispose(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         void IMainWindowState.SetUnloadable() | ||||
|         { | ||||
|             this._unloadable = true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| using Avalonia.Media.Imaging; | ||||
|  | ||||
| using ReactiveUI; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo.Controls.ViewModels | ||||
| { | ||||
|     internal sealed class MainViewModel : ReactiveObject | ||||
|     { | ||||
|         private readonly IBitmap _dotNetImage; | ||||
|         private readonly IBitmap _avaloniaImage; | ||||
|  | ||||
|         public IBitmap DotNetImage => this._dotNetImage; | ||||
|  | ||||
|         public IBitmap AvaloniaImage => this._avaloniaImage; | ||||
|  | ||||
|         public MainViewModel() | ||||
|         { | ||||
|             this._dotNetImage = Utilities.GetImageFromFile("dotnet.png"); | ||||
|             this._avaloniaImage = Utilities.GetImageFromFile("avalonia.png"); | ||||
|         } | ||||
|  | ||||
|         ~MainViewModel() | ||||
|         { | ||||
|             this._dotNetImage.Dispose(); | ||||
|             this._avaloniaImage.Dispose(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,9 +1,15 @@ | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo | ||||
| namespace AvaloniaCoreRTDemo.Interfaces | ||||
| { | ||||
|     public interface IMainWindow | ||||
|     { | ||||
|         IThemeSwitch ThemeSwitch { get; } | ||||
|         IMainWindowState Model { get; } | ||||
|         PixelPoint Position { get; } | ||||
|         Size ClientSize { get; } | ||||
|         Size? FrameSize { get; } | ||||
|         WindowState State { get; } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/Interfaces/IMainWindowState.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Interfaces/IMainWindowState.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| using System; | ||||
|  | ||||
| using Avalonia.Media.Imaging; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo | ||||
| { | ||||
|     public interface IMainWindowState | ||||
|     { | ||||
|         IBitmap DotNetImage { get; } | ||||
|         IBitmap AvaloniaImage { get; } | ||||
|         String? Text { get; } | ||||
|  | ||||
|         void SetUnloadable(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Runtime.InteropServices; | ||||
|  | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
| using Avalonia.Media.Imaging; | ||||
| using Avalonia.Platform; | ||||
|  | ||||
| @@ -19,6 +21,17 @@ namespace AvaloniaCoreRTDemo | ||||
|             return new Bitmap(assetStream); | ||||
|         } | ||||
|  | ||||
|         public static PixelPoint GetWindowPosition(Window window) | ||||
|         { | ||||
|             if (!IsOSX || !window.FrameSize.HasValue) | ||||
|                 return window.Position; | ||||
|             else | ||||
|             { | ||||
|                 Int32 yOffset = (Int32)(window.FrameSize.Value.Height - window.ClientSize.Height); | ||||
|                 return new(window.Position.X, window.Position.Y + yOffset); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static Bitmap GetImageFromFile(String path) | ||||
|         { | ||||
|             try | ||||
| @@ -30,7 +43,7 @@ namespace AvaloniaCoreRTDemo | ||||
|                 return GetImageFromResources("broken-link.png"); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|  | ||||
|         private static String GetImageFullPath(String fileName) | ||||
|             => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); | ||||
|     } | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| 	<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ColumnDefinitions="Auto,*"> | ||||
| 		<Image Margin="0, 60" Grid.Column="0" Stretch="None" Source="{Binding ComputerImage}" VerticalAlignment="Top" HorizontalAlignment="Left"> | ||||
| 		</Image> | ||||
| 		<DataGrid Grid.Column="1" Items="{Binding SystemDetails}" IsReadOnly="True"> | ||||
| 		<DataGrid Grid.Column="1" Items="{Binding SystemDetails}" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" HeadersVisibility="None"> | ||||
| 			<DataGrid.Columns> | ||||
| 				<DataGridTextColumn Header="Key" Binding="{Binding Key, x:DataType=viewModels:SystemDetail}" FontWeight="Bold" /> | ||||
| 				<DataGridTextColumn Header="Value" Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" /> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
|  | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
| using Avalonia.Markup.Xaml; | ||||
|  | ||||
| @@ -9,20 +10,23 @@ namespace AvaloniaCoreRTDemo.Windows | ||||
| { | ||||
|     public sealed partial class AboutWindow : Window | ||||
|     { | ||||
|         public AboutWindow() | ||||
|         { | ||||
|             this.InitializeComponent(); | ||||
|         } | ||||
|         private readonly Boolean _darkTheme; | ||||
|  | ||||
|         public AboutWindow() : this(false) { } | ||||
|  | ||||
|         public AboutWindow(Boolean darkTheme) | ||||
|         { | ||||
|             this.InitializeComponent(darkTheme); | ||||
|             this._darkTheme = darkTheme; | ||||
|             this.InitializeComponent(); | ||||
| #if DEBUG | ||||
|             this.AttachDevTools(); | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         private void InitializeComponent(Boolean darkTheme = default) | ||||
|         private void InitializeComponent() | ||||
|         { | ||||
|             AvaloniaXamlLoader.Load(this); | ||||
|             this.DataContext = new AboutViewModel(darkTheme); | ||||
|             this.DataContext = new AboutViewModel(this._darkTheme); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,10 +4,10 @@ | ||||
|         mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Windows.MainWindow" | ||||
|         Width="640" Height="480" WindowStartupLocation="CenterScreen" Title="AvaloniaCoreRTDemo" Icon="avares://AvaloniaCoreRTDemo/Assets/app.ico" MinWidth="400" MinHeight="350" | ||||
|         x:CompileBindings="True" | ||||
|         x:DataType="viewModels1:MainViewModelBase"> | ||||
|         x:DataType="viewModels1:ApplicationModelBase"> | ||||
|     <DockPanel> | ||||
|         <NativeMenuBar DockPanel.Dock="Top" /> | ||||
|         <controls:MainControl/> | ||||
|         <controls:MainControl Name="MainControl"/> | ||||
|     </DockPanel> | ||||
|     <NativeMenu.Menu> | ||||
|         <NativeMenu> | ||||
|   | ||||
| @@ -1,28 +1,48 @@ | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
| using Avalonia.Markup.Xaml; | ||||
|  | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
| using AvaloniaCoreRTDemo.Windows.ViewModels; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo.Windows | ||||
| { | ||||
|     public sealed partial class MainWindow : Window, IMainWindow | ||||
|     { | ||||
|         public MainWindow() | ||||
|         { | ||||
|             InitializeComponent(); | ||||
| #if DEBUG | ||||
|             this.AttachDevTools(); | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         private void InitializeComponent() | ||||
|         { | ||||
|             AvaloniaXamlLoader.Load(this); | ||||
|             this.DataContext = new MainViewModel<MainWindow>(this); | ||||
|         } | ||||
|  | ||||
|         IThemeSwitch IMainWindow.ThemeSwitch => App.Current as IThemeSwitch; | ||||
|     } | ||||
| } | ||||
| using Avalonia; | ||||
| using Avalonia.Controls; | ||||
| using Avalonia.Markup.Xaml; | ||||
|  | ||||
| using AvaloniaCoreRTDemo.Controls; | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
| using AvaloniaCoreRTDemo.Windows.ViewModels; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo.Windows | ||||
| { | ||||
|     public sealed partial class MainWindow : Window, IMainWindow | ||||
|     { | ||||
|         private readonly Application? _app = App.Current; | ||||
|  | ||||
|         private MainControl MainControl => this.GetControl<MainControl>("MainControl"); | ||||
|  | ||||
|         public MainWindow() : this(default) { } | ||||
|         public MainWindow(IMainWindow? window) | ||||
|         { | ||||
|             this.InitializeComponent(window); | ||||
| #if DEBUG | ||||
|             this.AttachDevTools(); | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)this._app!; | ||||
|         IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainControl.DataContext!; | ||||
|         PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this); | ||||
|         Size IMainWindow.ClientSize => this.ClientSize; | ||||
|         Size? IMainWindow.FrameSize => this.FrameSize; | ||||
|         WindowState IMainWindow.State => this.WindowState; | ||||
|  | ||||
|         private void InitializeComponent(IMainWindow? window) | ||||
|         { | ||||
|             AvaloniaXamlLoader.Load(this); | ||||
|             this.DataContext = new MainViewModel<MainWindow>(this); | ||||
|             if (window is not null) | ||||
|             { | ||||
|                 this.MainControl.Reload(window.Model); | ||||
|                 this.WindowStartupLocation = WindowStartupLocation.Manual; | ||||
|                 this.WindowState = window.State; | ||||
|                 this.Position = window.Position; | ||||
|                 this.FrameSize = window.FrameSize; | ||||
|                 this.ClientSize = window.ClientSize; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,10 +9,10 @@ using ReactiveUI; | ||||
| namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
| { | ||||
|     internal record SystemDetail(string Key, string Value); | ||||
|      | ||||
|  | ||||
|     internal sealed class AboutViewModel : ReactiveObject | ||||
|     { | ||||
|          | ||||
|  | ||||
|         private readonly IBitmap _computerImage; | ||||
|         private readonly Boolean _darkTheme; | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Reactive; | ||||
| 
 | ||||
| using Avalonia.Controls; | ||||
| 
 | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
| @@ -8,14 +9,14 @@ using ReactiveUI; | ||||
| 
 | ||||
| namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
| { | ||||
|     internal abstract class MainViewModelBase : ReactiveObject | ||||
|     internal abstract class ApplicationModelBase : ReactiveObject | ||||
|     { | ||||
|         private readonly IThemeSwitch _themeSwitch; | ||||
|         private Boolean _aboutEnable = true; | ||||
|         private Boolean _defaultLightEnable = true; | ||||
|         private Boolean _defaultDarkEnable = true; | ||||
|         private Boolean _fluentLightEnable = true; | ||||
|         private Boolean _fluentDarkEnable = true; | ||||
|         private Boolean _defaultLightEnable = false; | ||||
|         private Boolean _defaultDarkEnable = false; | ||||
|         private Boolean _fluentLightEnable = false; | ||||
|         private Boolean _fluentDarkEnable = false; | ||||
| 
 | ||||
|         public Boolean AboutEnabled | ||||
|         { | ||||
| @@ -23,12 +24,6 @@ namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
|             set => this.RaiseAndSetIfChanged(ref this._aboutEnable, value); | ||||
|         } | ||||
| 
 | ||||
|         public MainViewModelBase(IThemeSwitch window) | ||||
|         { | ||||
|             this._themeSwitch = window; | ||||
|             this.FileExitCommand = ReactiveCommand.Create(RunFileExit); | ||||
|         } | ||||
| 
 | ||||
|         public Boolean DefaultLightEnabled | ||||
|         { | ||||
|             get => this._defaultLightEnable; | ||||
| @@ -52,19 +47,22 @@ namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
|             get => this._fluentDarkEnable; | ||||
|             set => this.RaiseAndSetIfChanged(ref this._fluentDarkEnable, value); | ||||
|         } | ||||
|          | ||||
|         public ReactiveCommand<Unit, Unit> FileExitCommand { get; } | ||||
|          | ||||
|         public abstract void HelpAboutMethod(); | ||||
| 
 | ||||
|         public ReactiveCommand<Unit, Unit> FileExitCommand { get; } | ||||
| 
 | ||||
|         public ApplicationModelBase(IThemeSwitch themeSwitch) | ||||
|         { | ||||
|             this._themeSwitch = themeSwitch; | ||||
|             this.IntializeTheme(themeSwitch.Current); | ||||
|             this.FileExitCommand = ReactiveCommand.Create(RunFileExit); | ||||
|         } | ||||
| 
 | ||||
|         public abstract void HelpAboutMethod(); | ||||
|         public abstract void DefaultLightMethod(); | ||||
|         public abstract void DefaultDarkMethod(); | ||||
|         public abstract void FluentLightMethod(); | ||||
|         public abstract void FluentDarkMethod(); | ||||
|          | ||||
|         private void RunFileExit() | ||||
|             => Environment.Exit(0); | ||||
|          | ||||
| 
 | ||||
|         protected async void RunHelpAbout(Window currentWindow) | ||||
|         { | ||||
|             if (this.AboutEnabled) | ||||
| @@ -79,6 +77,22 @@ namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         protected void SetTheme(ApplicationTheme theme) | ||||
|         { | ||||
|             this.IntializeTheme(theme); | ||||
|             this._themeSwitch.ChangeTheme(theme); | ||||
|         } | ||||
| 
 | ||||
|         private void RunFileExit() => Environment.Exit(0); | ||||
| 
 | ||||
|         private void IntializeTheme(ApplicationTheme theme) | ||||
|         { | ||||
|             this.DefaultLightEnabled = theme != ApplicationTheme.SimpleLight; | ||||
|             this.DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark; | ||||
|             this.FluentLightEnabled = theme != ApplicationTheme.FluentLight; | ||||
|             this.FluentDarkEnabled = theme != ApplicationTheme.FluentDark; | ||||
|         } | ||||
| 
 | ||||
|         private static Boolean IsDarkTheme(ApplicationTheme? theme) | ||||
|             => theme switch | ||||
|             { | ||||
| @@ -1,39 +1,24 @@ | ||||
| using System; | ||||
| using System.Reactive; | ||||
| using Avalonia.Controls; | ||||
|  | ||||
| using Avalonia.Controls; | ||||
|  | ||||
| using ReactiveUI; | ||||
| using AvaloniaCoreRTDemo.Interfaces; | ||||
|  | ||||
| namespace AvaloniaCoreRTDemo.Windows.ViewModels | ||||
| { | ||||
|     internal sealed class MainViewModel<TWindow> : MainViewModelBase | ||||
|     internal sealed class MainViewModel<TWindow> : ApplicationModelBase | ||||
|         where TWindow : Window, IMainWindow | ||||
|     { | ||||
|         private readonly TWindow _window; | ||||
|         private TWindow _window; | ||||
|  | ||||
|         public MainViewModel(TWindow window) | ||||
|             : base(window.ThemeSwitch) | ||||
|         { | ||||
|             this._window = window; | ||||
|             this.ChangeTheme(window.ThemeSwitch.Current); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public override void HelpAboutMethod() => base.RunHelpAbout(this._window); | ||||
|  | ||||
|         public override void DefaultLightMethod() => this.ChangeTheme(ApplicationTheme.SimpleLight); | ||||
|         public override void DefaultDarkMethod() => this.ChangeTheme(ApplicationTheme.SimpleDark); | ||||
|         public override void FluentLightMethod() => this.ChangeTheme(ApplicationTheme.FluentLight); | ||||
|         public override void FluentDarkMethod() => this.ChangeTheme(ApplicationTheme.FluentDark); | ||||
|          | ||||
|         private void ChangeTheme(ApplicationTheme theme) | ||||
|         { | ||||
|             this.DefaultLightEnabled = theme != ApplicationTheme.SimpleLight; | ||||
|             this.DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark; | ||||
|             this.FluentLightEnabled = theme != ApplicationTheme.FluentLight; | ||||
|             this.FluentDarkEnabled = theme != ApplicationTheme.FluentDark; | ||||
|             this._window.ThemeSwitch?.ChangeTheme(theme); | ||||
|         } | ||||
|         public override void DefaultLightMethod() => base.SetTheme(ApplicationTheme.SimpleLight); | ||||
|         public override void DefaultDarkMethod() => base.SetTheme(ApplicationTheme.SimpleDark); | ||||
|         public override void FluentLightMethod() => base.SetTheme(ApplicationTheme.FluentLight); | ||||
|         public override void FluentDarkMethod() => base.SetTheme(ApplicationTheme.FluentDark); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <configuration> | ||||
|   <packageSources> | ||||
|     <add key="avalonia" value="https://nuget.avaloniaui.net/repository/avalonia-all/index.json" /> | ||||
|     <!--<add key="avalonia" value="https://nuget.avaloniaui.net/repository/avalonia-all/index.json" />--> | ||||
|     <add key="nuget" value="https://api.nuget.org/v3/index.json" /> | ||||
|   </packageSources> | ||||
| </configuration> | ||||
|   | ||||
							
								
								
									
										2
									
								
								test.cmd
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								test.cmd
									
									
									
									
									
								
							| @@ -1,2 +1,2 @@ | ||||
| del src\packages.lock.json | ||||
| dotnet publish -r win-x64 -c release /p:RestoreLockedMode=true /p:TrimLink=true --self-contained | ||||
| dotnet publish -r win-x64 -c Release /p:RestoreLockedMode=true | ||||
| @@ -4,7 +4,7 @@ if [ -d "$dir" ]; then | ||||
|   cd "$dir"  | ||||
| fi  | ||||
| rm -f src/packages.lock.json  | ||||
| dotnet publish -r osx-x64 -c release /p:RestoreLockedMode=true -t:BundleApp /p:TrimLink=true --self-contained  | ||||
| rm -rf src/bin/x64/Release/net7.0/osx-x64/publish/Assets/ | ||||
| rm -rf src/bin/x64/Release/net7.0/osx-x64/publish/AvaloniaCoreRTDemo.app/Contents/MacOS/Assets/ | ||||
| rm src/bin/x64/Release/net7.0/osx-x64/publish/AvaloniaCoreRTDemo.app/Contents/MacOS/AvaloniaCoreRTDemo.dwarf | ||||
| dotnet publish -r osx-x64 -c Release /p:RestoreLockedMode=true -t:BundleApp | ||||
| rm -rf src/bin/Release/net7.0/osx-x64/publish/Assets/ | ||||
| rm -rf src/bin/Release/net7.0/osx-x64/publish/AvaloniaCoreRTDemo.app/Contents/MacOS/Assets/ | ||||
| rm src/bin/Release/net7.0/osx-x64/publish/AvaloniaCoreRTDemo.app/Contents/MacOS/AvaloniaCoreRTDemo.dwarf | ||||
							
								
								
									
										5
									
								
								test.sh
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								test.sh
									
									
									
									
									
								
							| @@ -1,6 +1,5 @@ | ||||
| #!/bin/bash | ||||
| rm -f src/packages.lock.json | ||||
| dotnet publish -r linux-x64 -c release /p:RestoreLockedMode=true /p:TrimLink=true --self-contained  | ||||
| cd src/bin/x64/Release/net7.0/linux-x64/publish  | ||||
| dotnet publish -r linux-x64 -c Release /p:RestoreLockedMode=true | ||||
| cd src/bin/Release/net7.0/linux-x64/publish  | ||||
| cp AvaloniaCoreRTDemo AvaloniaCoreRTDemo.bin  | ||||
| strip AvaloniaCoreRTDemo.bin  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Todor Totev
					Todor Totev