committed by
GitHub
434 changed files with 4401 additions and 9226 deletions
@ -0,0 +1,40 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|||
<Suppression> |
|||
<DiagnosticId>CP0002</DiagnosticId> |
|||
<Target>M:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost.PreFilterMessage(System.Windows.Forms.Message@)</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net461/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net461/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
<Suppression> |
|||
<DiagnosticId>CP0002</DiagnosticId> |
|||
<Target>M:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost.PreFilterMessage(System.Windows.Forms.Message@)</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net6.0-windows7.0/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net6.0-windows7.0/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
<Suppression> |
|||
<DiagnosticId>CP0002</DiagnosticId> |
|||
<Target>M:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost.PreFilterMessage(System.Windows.Forms.Message@)</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net8.0-windows7.0/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net8.0-windows7.0/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
<Suppression> |
|||
<DiagnosticId>CP0008</DiagnosticId> |
|||
<Target>T:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net461/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net461/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
<Suppression> |
|||
<DiagnosticId>CP0008</DiagnosticId> |
|||
<Target>T:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net6.0-windows7.0/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net6.0-windows7.0/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
<Suppression> |
|||
<DiagnosticId>CP0008</DiagnosticId> |
|||
<Target>T:Avalonia.Win32.Interoperability.WinFormsAvaloniaControlHost</Target> |
|||
<Left>baseline/Avalonia.Win32.Interoperability/lib/net8.0-windows7.0/Avalonia.Win32.Interoperability.dll</Left> |
|||
<Right>current/Avalonia.Win32.Interoperability/lib/net8.0-windows7.0/Avalonia.Win32.Interoperability.dll</Right> |
|||
</Suppression> |
|||
</Suppressions> |
|||
@ -1,12 +1,8 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<!-- '!NET6_0_OR_GREATER' equivalent --> |
|||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))"> |
|||
<PackageReference Include="System.Memory" Version="4.5.5" /> |
|||
</ItemGroup> |
|||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))"> |
|||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" /> |
|||
</ItemGroup> |
|||
<!-- '!NET8_0_OR_GREATER' equivalent --> |
|||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))"> |
|||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" /> |
|||
<PackageReference Include="System.Memory" Version="4.5.5" /> |
|||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" /> |
|||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.10" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="Moq" Version="4.18.4" /> |
|||
<PackageReference Include="Moq" Version="4.20.72" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -1,5 +0,0 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="ReactiveUI" Version="20.1.1" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -1 +1 @@ |
|||
Subproject commit 83567b8a50bbf612a0b1420a3dc6d8e8ebee2399 |
|||
Subproject commit c32d3040e536ae9768233ea5a445697632578bd0 |
|||
@ -1,10 +0,0 @@ |
|||
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> |
|||
<Found Context="routeData"> |
|||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> |
|||
</Found> |
|||
<NotFound> |
|||
<LayoutView Layout="@typeof(MainLayout)"> |
|||
<p>Sorry, there's nothing at this address.</p> |
|||
</LayoutView> |
|||
</NotFound> |
|||
</Router> |
|||
@ -1,10 +0,0 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Avalonia; |
|||
using Avalonia.Browser.Blazor; |
|||
|
|||
namespace ControlCatalog.Browser.Blazor; |
|||
|
|||
public partial class App |
|||
{ |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
|||
<PropertyGroup> |
|||
<TargetFramework>$(AvsCurrentBrowserTargetFramework)</TargetFramework> |
|||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> |
|||
<Nullable>enable</Nullable> |
|||
<EmccTotalMemory>16777216</EmccTotalMemory> |
|||
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport> |
|||
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" PrivateAssets="all" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" /> |
|||
<ProjectReference Include="..\..\src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj" /> |
|||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|||
<Import Project="..\..\build\BuildTargets.targets" /> |
|||
|
|||
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.props" /> |
|||
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.targets" /> |
|||
|
|||
</Project> |
|||
|
|||
@ -1,5 +0,0 @@ |
|||
@page "/" |
|||
|
|||
@using Avalonia.Browser.Blazor |
|||
|
|||
<AvaloniaView /> |
|||
@ -1,39 +0,0 @@ |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading.Tasks; |
|||
using Avalonia; |
|||
using Avalonia.Browser.Blazor; |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using ControlCatalog.Browser.Blazor; |
|||
|
|||
public class Program |
|||
{ |
|||
public static async Task Main(string[] args) |
|||
{ |
|||
var host = CreateHostBuilder(args).Build(); |
|||
await StartAvaloniaApp(); |
|||
await host.RunAsync(); |
|||
} |
|||
|
|||
public static async Task StartAvaloniaApp() |
|||
{ |
|||
await AppBuilder.Configure<ControlCatalog.App>() |
|||
.StartBlazorAppAsync(); |
|||
} |
|||
|
|||
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args) |
|||
{ |
|||
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
|||
|
|||
builder.RootComponents.Add<App>("#app"); |
|||
|
|||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); |
|||
|
|||
return builder; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
@ -1,22 +0,0 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "http://localhost:13961", |
|||
"sslPort": 44319 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"ControlCatalog.Web": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": "true", |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"applicationUrl": "https://localhost:5001;http://localhost:5000", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
@inherits LayoutComponentBase |
|||
|
|||
<div class="page"> |
|||
<div class="main"> |
|||
@Body |
|||
</div> |
|||
</div> |
|||
@ -1,10 +0,0 @@ |
|||
@using System.Net.Http |
|||
@using System.Net.Http.Json |
|||
@using Microsoft.AspNetCore.Components.Forms |
|||
@using Microsoft.AspNetCore.Components.Routing |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using Microsoft.AspNetCore.Components.Web.Virtualization |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
|||
@using Microsoft.JSInterop |
|||
@using ControlCatalog.Browser.Blazor.Shared |
|||
@using SkiaSharp |
|||
@ -1,56 +0,0 @@ |
|||
html, body { |
|||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; |
|||
margin: 0; |
|||
height: 100vh; |
|||
overflow: hidden; |
|||
touch-action: none; |
|||
} |
|||
|
|||
a, .btn-link { |
|||
color: #0366d6; |
|||
} |
|||
|
|||
.btn-primary { |
|||
color: #fff; |
|||
background-color: #1b6ec2; |
|||
border-color: #1861ac; |
|||
} |
|||
|
|||
.content { |
|||
padding-top: 1.1rem; |
|||
} |
|||
|
|||
.valid.modified:not([type=checkbox]) { |
|||
outline: 1px solid #26b050; |
|||
} |
|||
|
|||
.invalid { |
|||
outline: 1px solid red; |
|||
} |
|||
|
|||
.validation-message { |
|||
color: red; |
|||
} |
|||
|
|||
#blazor-error-ui { |
|||
background: lightyellow; |
|||
bottom: 0; |
|||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); |
|||
display: none; |
|||
left: 0; |
|||
padding: 0.6rem 1.25rem 0.7rem 1.25rem; |
|||
position: fixed; |
|||
width: 100%; |
|||
z-index: 1000; |
|||
} |
|||
|
|||
#blazor-error-ui .dismiss { |
|||
cursor: pointer; |
|||
position: absolute; |
|||
right: 0.75rem; |
|||
top: 0.5rem; |
|||
} |
|||
|
|||
#app, .page { |
|||
height: 100%; |
|||
} |
|||
|
Before Width: | Height: | Size: 172 KiB |
@ -1,22 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
|
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title>Avalonia Sample</title> |
|||
<base href="/" /> |
|||
<link href="css/app.css" rel="stylesheet" /> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app">Powered by Avalonia</div> |
|||
|
|||
<div id="blazor-error-ui"> |
|||
An unhandled error has occurred. |
|||
<a href="" class="reload">Reload</a> |
|||
<a class="dismiss">🗙</a> |
|||
</div> |
|||
<script src="_framework/blazor.webassembly.js"></script> |
|||
</body> |
|||
</html> |
|||
@ -1,22 +1,41 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>net461</TargetFramework> |
|||
<PlatformTarget>x64</PlatformTarget> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework> |
|||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> |
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
|||
<ApplicationManifest>../ControlCatalog.NetCore/app.manifest</ApplicationManifest> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" /> |
|||
<Compile Include="..\..\src\Avalonia.X11\Interop\Glib.cs" Link="NativeControls\Gtk\Glib.cs" /> |
|||
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Include="NativeControls\Gtk\nodes.mp4"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</Content> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\ControlCatalog.NetCore\NativeControls\Win\*.cs" Link="NativeControls\*" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> |
|||
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> |
|||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> |
|||
<!-- For native controls test --> |
|||
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> |
|||
</ItemGroup> |
|||
|
|||
<PropertyGroup> |
|||
<!-- For Microsoft.CodeAnalysis --> |
|||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> |
|||
<ApplicationManifest>app.manifest</ApplicationManifest> |
|||
</PropertyGroup> |
|||
|
|||
<Import Project="..\..\build\SampleApp.props" /> |
|||
<Import Project="..\..\build\NetFX.props" /> |
|||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|||
</Project> |
|||
|
|||
@ -1,7 +1,7 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace ControlCatalog.NetCore; |
|||
namespace ControlCatalog.Desktop; |
|||
|
|||
internal unsafe class WinApi |
|||
{ |
|||
@ -1,38 +1,180 @@ |
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Avalonia; |
|||
using Avalonia.Platform; |
|||
using ControlCatalog.NetCore; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Fonts.Inter; |
|||
using Avalonia.Headless; |
|||
using Avalonia.LinuxFramebuffer.Output; |
|||
using Avalonia.LogicalTree; |
|||
using Avalonia.Rendering.Composition; |
|||
using Avalonia.Threading; |
|||
using Avalonia.Vulkan; |
|||
using ControlCatalog.Pages; |
|||
|
|||
namespace ControlCatalog |
|||
namespace ControlCatalog.Desktop |
|||
{ |
|||
internal class Program |
|||
static class Program |
|||
{ |
|||
private static bool s_useFramebuffer; |
|||
|
|||
[STAThread] |
|||
public static int Main(string[] args) |
|||
=> BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); |
|||
static int Main(string[] args) |
|||
{ |
|||
if (args.Contains("--fbdev")) |
|||
{ |
|||
s_useFramebuffer = true; |
|||
} |
|||
|
|||
if (args.Contains("--wait-for-attach")) |
|||
{ |
|||
Console.WriteLine("Attach debugger and use 'Set next statement'"); |
|||
while (true) |
|||
{ |
|||
Thread.Sleep(100); |
|||
if (Debugger.IsAttached) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
var builder = BuildAvaloniaApp(); |
|||
|
|||
double GetScaling() |
|||
{ |
|||
var idx = Array.IndexOf(args, "--scaling"); |
|||
if (idx != 0 && args.Length > idx + 1 && |
|||
double.TryParse(args[idx + 1], NumberStyles.Any, CultureInfo.InvariantCulture, out var scaling)) |
|||
return scaling; |
|||
return 1; |
|||
} |
|||
if (s_useFramebuffer) |
|||
{ |
|||
SilenceConsole(); |
|||
return builder.StartLinuxFbDev(args, new FbDevOutputOptions() |
|||
{ |
|||
Scaling = GetScaling() |
|||
}); |
|||
} |
|||
else if (args.Contains("--vnc")) |
|||
{ |
|||
return builder.StartWithHeadlessVncPlatform(null, 5901, args, ShutdownMode.OnMainWindowClose); |
|||
} |
|||
else if (args.Contains("--full-headless")) |
|||
{ |
|||
return builder |
|||
.UseHeadless(new AvaloniaHeadlessPlatformOptions |
|||
{ |
|||
UseHeadlessDrawing = true |
|||
}) |
|||
.AfterSetup(_ => |
|||
{ |
|||
DispatcherTimer.RunOnce(async () => |
|||
{ |
|||
var window = ((IClassicDesktopStyleApplicationLifetime)Application.Current.ApplicationLifetime) |
|||
.MainWindow; |
|||
var tc = window.GetLogicalDescendants().OfType<TabControl>().First(); |
|||
foreach (var page in tc.Items.Cast<TabItem>().ToList()) |
|||
{ |
|||
if (page.Header.ToString() == "DatePicker" || page.Header.ToString() == "TreeView") |
|||
continue; |
|||
Console.WriteLine("Selecting " + page.Header); |
|||
tc.SelectedItem = page; |
|||
await Task.Delay(50); |
|||
} |
|||
Console.WriteLine("Selecting the first page"); |
|||
tc.SelectedItem = tc.Items.OfType<object>().First(); |
|||
await Task.Delay(500); |
|||
Console.WriteLine("Clicked through all pages, triggering GC"); |
|||
for (var c = 0; c < 3; c++) |
|||
{ |
|||
GC.Collect(2, GCCollectionMode.Forced); |
|||
await Task.Delay(50); |
|||
} |
|||
|
|||
void FormatMem(string metric, long bytes) |
|||
{ |
|||
Console.WriteLine(metric + ": " + bytes / 1024 / 1024 + "MB"); |
|||
} |
|||
|
|||
FormatMem("GC allocated bytes", GC.GetTotalMemory(true)); |
|||
FormatMem("WorkingSet64", Process.GetCurrentProcess().WorkingSet64); |
|||
}, TimeSpan.FromSeconds(1)); |
|||
}) |
|||
.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
else if (args.Contains("--drm")) |
|||
{ |
|||
SilenceConsole(); |
|||
return builder.StartLinuxDrm(args, scaling: GetScaling()); |
|||
} |
|||
else if (args.Contains("--dxgi")) |
|||
{ |
|||
builder.With(new Win32PlatformOptions() |
|||
{ |
|||
CompositionMode = new [] { Win32CompositionMode.LowLatencyDxgiSwapChain } |
|||
}); |
|||
return builder.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
else |
|||
return builder.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// This method is needed for IDE previewer infrastructure
|
|||
/// </summary>
|
|||
public static AppBuilder BuildAvaloniaApp() |
|||
=> AppBuilder.Configure<App>() |
|||
.LogToTrace() |
|||
.UsePlatformDetect() |
|||
.With(new X11PlatformOptions |
|||
{ |
|||
EnableMultiTouch = true, |
|||
UseDBusMenu = true, |
|||
EnableIme = true, |
|||
}) |
|||
|
|||
.With(new VulkanOptions |
|||
{ |
|||
VulkanInstanceCreationOptions = new () |
|||
{ |
|||
UseDebug = true |
|||
} |
|||
}) |
|||
.With(new CompositionOptions() |
|||
{ |
|||
UseRegionDirtyRectClipping = true |
|||
}) |
|||
.UseSkia() |
|||
.WithInterFont() |
|||
.AfterSetup(builder => |
|||
{ |
|||
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() |
|||
if (!s_useFramebuffer) |
|||
{ |
|||
StartupScreenIndex = 1, |
|||
}); |
|||
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() |
|||
{ |
|||
StartupScreenIndex = 1, |
|||
}); |
|||
} |
|||
|
|||
EmbedSample.Implementation = new EmbedSampleWin(); |
|||
EmbedSample.Implementation = OperatingSystem.IsWindows() ? (INativeDemoControl)new EmbedSampleWin() |
|||
: OperatingSystem.IsMacOS() ? new EmbedSampleMac() |
|||
: OperatingSystem.IsLinux() ? new EmbedSampleGtk() |
|||
: null; |
|||
}) |
|||
.UseWin32() |
|||
.UseSkia(); |
|||
.LogToTrace(); |
|||
|
|||
private static void ConfigureAssetAssembly(AppBuilder builder) |
|||
static void SilenceConsole() |
|||
{ |
|||
AssetLoader.SetDefaultAssembly(typeof(App).Assembly); |
|||
new Thread(() => |
|||
{ |
|||
Console.CursorVisible = false; |
|||
while (true) |
|||
Console.ReadKey(true); |
|||
}) |
|||
{ IsBackground = true }.Start(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,6 +1,6 @@ |
|||
{ |
|||
"profiles": { |
|||
"ControlCatalog.NetCore": { |
|||
"ControlCatalog.Desktop": { |
|||
"commandName": "Project" |
|||
}, |
|||
"Dxgi": { |
|||
@ -1,41 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework> |
|||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> |
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" /> |
|||
<Compile Include="..\..\src\Avalonia.X11\Interop\Glib.cs" Link="NativeControls\Gtk\Glib.cs" /> |
|||
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Include="NativeControls\Gtk\nodes.mp4"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</Content> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> |
|||
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> |
|||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> |
|||
<!-- For native controls test --> |
|||
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> |
|||
</ItemGroup> |
|||
|
|||
<PropertyGroup> |
|||
<!-- For Microsoft.CodeAnalysis --> |
|||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> |
|||
<ApplicationManifest>app.manifest</ApplicationManifest> |
|||
</PropertyGroup> |
|||
|
|||
<Import Project="..\..\build\SampleApp.props" /> |
|||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|||
</Project> |
|||
@ -1,180 +0,0 @@ |
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Fonts.Inter; |
|||
using Avalonia.Headless; |
|||
using Avalonia.LinuxFramebuffer.Output; |
|||
using Avalonia.LogicalTree; |
|||
using Avalonia.Rendering.Composition; |
|||
using Avalonia.Threading; |
|||
using Avalonia.Vulkan; |
|||
using ControlCatalog.Pages; |
|||
|
|||
namespace ControlCatalog.NetCore |
|||
{ |
|||
static class Program |
|||
{ |
|||
private static bool s_useFramebuffer; |
|||
|
|||
[STAThread] |
|||
static int Main(string[] args) |
|||
{ |
|||
if (args.Contains("--fbdev")) |
|||
{ |
|||
s_useFramebuffer = true; |
|||
} |
|||
|
|||
if (args.Contains("--wait-for-attach")) |
|||
{ |
|||
Console.WriteLine("Attach debugger and use 'Set next statement'"); |
|||
while (true) |
|||
{ |
|||
Thread.Sleep(100); |
|||
if (Debugger.IsAttached) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
var builder = BuildAvaloniaApp(); |
|||
|
|||
double GetScaling() |
|||
{ |
|||
var idx = Array.IndexOf(args, "--scaling"); |
|||
if (idx != 0 && args.Length > idx + 1 && |
|||
double.TryParse(args[idx + 1], NumberStyles.Any, CultureInfo.InvariantCulture, out var scaling)) |
|||
return scaling; |
|||
return 1; |
|||
} |
|||
if (s_useFramebuffer) |
|||
{ |
|||
SilenceConsole(); |
|||
return builder.StartLinuxFbDev(args, new FbDevOutputOptions() |
|||
{ |
|||
Scaling = GetScaling() |
|||
}); |
|||
} |
|||
else if (args.Contains("--vnc")) |
|||
{ |
|||
return builder.StartWithHeadlessVncPlatform(null, 5901, args, ShutdownMode.OnMainWindowClose); |
|||
} |
|||
else if (args.Contains("--full-headless")) |
|||
{ |
|||
return builder |
|||
.UseHeadless(new AvaloniaHeadlessPlatformOptions |
|||
{ |
|||
UseHeadlessDrawing = true |
|||
}) |
|||
.AfterSetup(_ => |
|||
{ |
|||
DispatcherTimer.RunOnce(async () => |
|||
{ |
|||
var window = ((IClassicDesktopStyleApplicationLifetime)Application.Current.ApplicationLifetime) |
|||
.MainWindow; |
|||
var tc = window.GetLogicalDescendants().OfType<TabControl>().First(); |
|||
foreach (var page in tc.Items.Cast<TabItem>().ToList()) |
|||
{ |
|||
if (page.Header.ToString() == "DatePicker" || page.Header.ToString() == "TreeView") |
|||
continue; |
|||
Console.WriteLine("Selecting " + page.Header); |
|||
tc.SelectedItem = page; |
|||
await Task.Delay(50); |
|||
} |
|||
Console.WriteLine("Selecting the first page"); |
|||
tc.SelectedItem = tc.Items.OfType<object>().First(); |
|||
await Task.Delay(500); |
|||
Console.WriteLine("Clicked through all pages, triggering GC"); |
|||
for (var c = 0; c < 3; c++) |
|||
{ |
|||
GC.Collect(2, GCCollectionMode.Forced); |
|||
await Task.Delay(50); |
|||
} |
|||
|
|||
void FormatMem(string metric, long bytes) |
|||
{ |
|||
Console.WriteLine(metric + ": " + bytes / 1024 / 1024 + "MB"); |
|||
} |
|||
|
|||
FormatMem("GC allocated bytes", GC.GetTotalMemory(true)); |
|||
FormatMem("WorkingSet64", Process.GetCurrentProcess().WorkingSet64); |
|||
}, TimeSpan.FromSeconds(1)); |
|||
}) |
|||
.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
else if (args.Contains("--drm")) |
|||
{ |
|||
SilenceConsole(); |
|||
return builder.StartLinuxDrm(args, scaling: GetScaling()); |
|||
} |
|||
else if (args.Contains("--dxgi")) |
|||
{ |
|||
builder.With(new Win32PlatformOptions() |
|||
{ |
|||
CompositionMode = new [] { Win32CompositionMode.LowLatencyDxgiSwapChain } |
|||
}); |
|||
return builder.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
else |
|||
return builder.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// This method is needed for IDE previewer infrastructure
|
|||
/// </summary>
|
|||
public static AppBuilder BuildAvaloniaApp() |
|||
=> AppBuilder.Configure<App>() |
|||
.UsePlatformDetect() |
|||
.With(new X11PlatformOptions |
|||
{ |
|||
EnableMultiTouch = true, |
|||
UseDBusMenu = true, |
|||
EnableIme = true, |
|||
}) |
|||
|
|||
.With(new VulkanOptions |
|||
{ |
|||
VulkanInstanceCreationOptions = new () |
|||
{ |
|||
UseDebug = true |
|||
} |
|||
}) |
|||
.With(new CompositionOptions() |
|||
{ |
|||
UseRegionDirtyRectClipping = true |
|||
}) |
|||
.UseSkia() |
|||
.WithInterFont() |
|||
.AfterSetup(builder => |
|||
{ |
|||
if (!s_useFramebuffer) |
|||
{ |
|||
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() |
|||
{ |
|||
StartupScreenIndex = 1, |
|||
}); |
|||
} |
|||
|
|||
EmbedSample.Implementation = OperatingSystem.IsWindows() ? (INativeDemoControl)new EmbedSampleWin() |
|||
: OperatingSystem.IsMacOS() ? new EmbedSampleMac() |
|||
: OperatingSystem.IsLinux() ? new EmbedSampleGtk() |
|||
: null; |
|||
}) |
|||
.LogToTrace(); |
|||
|
|||
static void SilenceConsole() |
|||
{ |
|||
new Thread(() => |
|||
{ |
|||
Console.CursorVisible = false; |
|||
while (true) |
|||
Console.ReadKey(true); |
|||
}) |
|||
{ IsBackground = true }.Start(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,45 +1,58 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:controls="using:Generators.Sandbox.Controls" |
|||
x:Class="Generators.Sandbox.Controls.SignUpView"> |
|||
<StackPanel> |
|||
xmlns:vm="clr-namespace:Generators.Sandbox.ViewModels" |
|||
x:Class="Generators.Sandbox.Controls.SignUpView" |
|||
x:DataType="vm:SignUpViewModel"> |
|||
<UserControl.Styles> |
|||
<Style Selector="DataValidationErrors"> |
|||
<Setter Property="ErrorTemplate"> |
|||
<Setter.Value> |
|||
<DataTemplate /> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
</UserControl.Styles> |
|||
<StackPanel> |
|||
<controls:CustomTextBox Margin="0 10 0 0" |
|||
x:Name="UserNameTextBox" |
|||
Text="{Binding UserName}" |
|||
Watermark="Please, enter user name..." |
|||
UseFloatingWatermark="True" /> |
|||
<TextBlock x:Name="UserNameValidation" |
|||
<TextBlock x:Name="UserNameValidation" |
|||
Text="{Binding UserNameValidation}" |
|||
Foreground="Green" |
|||
FontSize="12" /> |
|||
<TextBox Margin="0 10 0 0" |
|||
x:Name="PasswordTextBox" |
|||
Text="{Binding Password}" |
|||
Watermark="Please, enter your password..." |
|||
UseFloatingWatermark="True" |
|||
PasswordChar="*" /> |
|||
<TextBlock x:Name="PasswordValidation" |
|||
<TextBlock x:Name="PasswordValidation" |
|||
Text="{Binding PasswordValidation}" |
|||
Foreground="Red" |
|||
FontSize="12" /> |
|||
<TextBox Margin="0 10 0 0" |
|||
x:Name="ConfirmPasswordTextBox" |
|||
Text="{Binding ConfirmPassword}" |
|||
Watermark="Please, confirm the password..." |
|||
UseFloatingWatermark="True" |
|||
PasswordChar="*" /> |
|||
<TextBlock x:Name="ConfirmPasswordValidation" |
|||
Text="{Binding ConfirmPasswordValidation}" |
|||
TextWrapping="Wrap" |
|||
Foreground="Red" |
|||
FontSize="12" /> |
|||
<TextBlock> |
|||
<TextBlock.Inlines> |
|||
<InlineCollection> |
|||
<Run x:Name="SignUpButtonDescription" /> |
|||
</InlineCollection> |
|||
</TextBlock.Inlines> |
|||
</TextBlock> |
|||
<TextBlock Text="Press the button below to sign up." /> |
|||
<Button Margin="0 10 0 5" |
|||
Content="Sign up" |
|||
Command="{Binding SignUp}" |
|||
x:Name="SignUpButton" /> |
|||
<TextBlock x:Name="CompoundValidation" |
|||
TextWrapping="Wrap" |
|||
Foreground="Red" |
|||
FontSize="12" /> |
|||
FontSize="12" |
|||
Text="{Binding CompoundValidation}" /> |
|||
</StackPanel> |
|||
</UserControl> |
|||
|
|||
@ -1,70 +1,76 @@ |
|||
using System.Reactive; |
|||
using ReactiveUI; |
|||
using ReactiveUI.Validation.Extensions; |
|||
using ReactiveUI.Validation.Helpers; |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Linq; |
|||
using CommunityToolkit.Mvvm.ComponentModel; |
|||
using CommunityToolkit.Mvvm.Input; |
|||
|
|||
namespace Generators.Sandbox.ViewModels; |
|||
|
|||
public class SignUpViewModel : ReactiveValidationObject |
|||
public class SignUpViewModel : ObservableValidator |
|||
{ |
|||
private string _userName = string.Empty; |
|||
private string _password = string.Empty; |
|||
private string _confirmPassword = string.Empty; |
|||
|
|||
public SignUpViewModel() |
|||
{ |
|||
this.ValidationRule( |
|||
vm => vm.UserName, |
|||
name => !string.IsNullOrWhiteSpace(name), |
|||
"UserName is required."); |
|||
|
|||
this.ValidationRule( |
|||
vm => vm.Password, |
|||
password => !string.IsNullOrWhiteSpace(password), |
|||
"Password is required."); |
|||
UserName = "Joseph!"; |
|||
Password = "1234"; |
|||
ConfirmPassword = "1234"; |
|||
SignUp = new RelayCommand(() => { }, () => !HasErrors); |
|||
|
|||
this.ValidationRule( |
|||
vm => vm.Password, |
|||
password => password?.Length > 2, |
|||
password => $"Password should be longer, current length: {password.Length}"); |
|||
ErrorsChanged += OnErrorsChanged; |
|||
} |
|||
|
|||
this.ValidationRule( |
|||
vm => vm.ConfirmPassword, |
|||
confirmation => !string.IsNullOrWhiteSpace(confirmation), |
|||
"Confirm password field is required."); |
|||
public RelayCommand SignUp { get; } |
|||
|
|||
var passwordsObservable = |
|||
this.WhenAnyValue( |
|||
x => x.Password, |
|||
x => x.ConfirmPassword, |
|||
(password, confirmation) => |
|||
password == confirmation); |
|||
[Required] |
|||
public string? UserName { |
|||
get; |
|||
set => SetProperty(ref field, value, validate: true); |
|||
} |
|||
|
|||
this.ValidationRule( |
|||
vm => vm.ConfirmPassword, |
|||
passwordsObservable, |
|||
"Passwords must match."); |
|||
public string? UserNameValidation |
|||
=> GetValidationMessage(nameof(UserName)); |
|||
|
|||
SignUp = ReactiveCommand.Create(() => {}, this.IsValid()); |
|||
[Required] |
|||
[MinLength(2)] |
|||
public string? Password |
|||
{ |
|||
get; |
|||
set |
|||
{ |
|||
if (SetProperty(ref field, value, validate: true)) |
|||
ValidateProperty(ConfirmPassword, nameof(ConfirmPassword)); |
|||
} |
|||
} |
|||
|
|||
public ReactiveCommand<Unit, Unit> SignUp { get; } |
|||
public string? PasswordValidation |
|||
=> GetValidationMessage(nameof(Password)); |
|||
|
|||
public string UserName |
|||
[Required] |
|||
[Compare(nameof(Password))] |
|||
public string? ConfirmPassword |
|||
{ |
|||
get => _userName; |
|||
set => this.RaiseAndSetIfChanged(ref _userName, value); |
|||
get; |
|||
set => SetProperty(ref field, value, validate: true); |
|||
} |
|||
|
|||
public string Password |
|||
public string? ConfirmPasswordValidation |
|||
=> GetValidationMessage(nameof(ConfirmPassword)); |
|||
|
|||
public string? CompoundValidation |
|||
=> GetValidationMessage(null); |
|||
|
|||
private void OnErrorsChanged(object? sender, DataErrorsChangedEventArgs e) |
|||
{ |
|||
get => _password; |
|||
set => this.RaiseAndSetIfChanged(ref _password, value); |
|||
if (e.PropertyName is not null) |
|||
OnPropertyChanged(e.PropertyName + "Validation"); |
|||
|
|||
OnPropertyChanged(CompoundValidation); |
|||
SignUp.NotifyCanExecuteChanged(); |
|||
} |
|||
|
|||
public string ConfirmPassword |
|||
private string? GetValidationMessage(string? propertyName) |
|||
{ |
|||
get => _confirmPassword; |
|||
set => this.RaiseAndSetIfChanged(ref _confirmPassword, value); |
|||
var message = string.Join(Environment.NewLine, GetErrors(propertyName).Select(v => v.ErrorMessage)); |
|||
return string.IsNullOrEmpty(message) ? null : message; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,110 +1,158 @@ |
|||
using SharpDX; |
|||
using SharpDX.D3DCompiler; |
|||
using SharpDX.Direct3D; |
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using SharpDX.Direct2D1; |
|||
using SharpDX.Direct3D11; |
|||
using SharpDX.DXGI; |
|||
using SharpDX.Mathematics.Interop; |
|||
using Buffer = SharpDX.Direct3D11.Buffer; |
|||
using DeviceContext = SharpDX.Direct2D1.DeviceContext; |
|||
using DxgiFactory1 = SharpDX.DXGI.Factory1; |
|||
using Matrix = SharpDX.Matrix; |
|||
using D3DDevice = SharpDX.Direct3D11.Device; |
|||
using DxgiResource = SharpDX.DXGI.Resource; |
|||
using FeatureLevel = SharpDX.Direct3D.FeatureLevel; |
|||
using InputElement = SharpDX.Direct3D11.InputElement; |
|||
|
|||
using System.Numerics; |
|||
using Silk.NET.Core.Native; |
|||
using Silk.NET.Direct3D.Compilers; |
|||
using Silk.NET.Direct3D11; |
|||
using Silk.NET.DXGI; |
|||
using static Silk.NET.Core.Native.SilkMarshal; |
|||
|
|||
namespace GpuInterop.D3DDemo; |
|||
|
|||
public class D3DContent |
|||
public static class D3DContent |
|||
{ |
|||
private static D3DCompiler s_compiler = D3DCompiler.GetApi(); |
|||
|
|||
public static Buffer CreateMesh(D3DDevice device) |
|||
public static unsafe ComPtr<ID3D11Buffer> CreateMesh(ComPtr<ID3D11Device> device) |
|||
{ |
|||
// Compile Vertex and Pixel shaders
|
|||
var vertexShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "VS", "vs_4_0"); |
|||
var vertexShader = new VertexShader(device, vertexShaderByteCode); |
|||
using var vertexShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "VS", "vs_4_0"); |
|||
using ComPtr<ID3D11VertexShader> vertexShader = default; |
|||
ThrowHResult(device.CreateVertexShader( |
|||
vertexShaderByteCode.GetBufferPointer(), |
|||
vertexShaderByteCode.GetBufferSize(), |
|||
(ID3D11ClassLinkage*)null, |
|||
vertexShader.GetAddressOf())); |
|||
|
|||
var pixelShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "PS", "ps_4_0"); |
|||
var pixelShader = new PixelShader(device, pixelShaderByteCode); |
|||
using var pixelShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "PS", "ps_4_0"); |
|||
using ComPtr<ID3D11PixelShader> pixelShader = default; |
|||
ThrowHResult(device.CreatePixelShader( |
|||
pixelShaderByteCode.GetBufferPointer(), |
|||
pixelShaderByteCode.GetBufferSize(), |
|||
(ID3D11ClassLinkage*)null, |
|||
pixelShader.GetAddressOf())); |
|||
|
|||
var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode); |
|||
using ComPtr<ID3D10Blob> vertexShaderSignature = default; |
|||
ThrowHResult(s_compiler.GetInputSignatureBlob( |
|||
vertexShaderByteCode.GetBufferPointer(), |
|||
vertexShaderByteCode.GetBufferSize(), |
|||
vertexShaderSignature.GetAddressOf())); |
|||
|
|||
var inputElements = new[] |
|||
// Layout from VertexShader input signature
|
|||
using ComPtr<ID3D11InputLayout> inputLayout = default; |
|||
var positionNamePtr = StringToPtr("POSITION", NativeStringEncoding.LPStr); |
|||
var colorNamePtr = StringToPtr("COLOR", NativeStringEncoding.LPStr); |
|||
try |
|||
{ |
|||
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), |
|||
new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) |
|||
}; |
|||
const int inputCount = 2; |
|||
var inputs = stackalloc InputElementDesc[inputCount] |
|||
{ |
|||
new InputElementDesc((byte*)positionNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 0), |
|||
new InputElementDesc((byte*)colorNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 16) |
|||
}; |
|||
|
|||
// Layout from VertexShader input signature
|
|||
var layout = new InputLayout( |
|||
device, |
|||
signature, |
|||
inputElements); |
|||
ThrowHResult(device.CreateInputLayout( |
|||
inputs, |
|||
inputCount, |
|||
vertexShaderSignature.GetBufferPointer(), |
|||
vertexShaderSignature.GetBufferSize(), |
|||
inputLayout.GetAddressOf())); |
|||
} |
|||
finally |
|||
{ |
|||
FreeString(positionNamePtr, NativeStringEncoding.LPStr); |
|||
FreeString(colorNamePtr, NativeStringEncoding.LPStr); |
|||
} |
|||
|
|||
// Instantiate Vertex buffer from vertex data
|
|||
using var vertices = Buffer.Create( |
|||
device, |
|||
BindFlags.VertexBuffer, |
|||
new[] |
|||
var vertices = new[] |
|||
{ |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
|
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
|
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
|
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
|
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
|
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
|
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
}; |
|||
|
|||
using ComPtr<ID3D11Buffer> vertexBuffer = default; |
|||
|
|||
fixed (Vector4* verticesPtr = vertices) |
|||
{ |
|||
var vertexBufferDesc = new BufferDesc |
|||
{ |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
|
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
|
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
|
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
|
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
|
|||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
|
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), |
|||
}); |
|||
ByteWidth = (uint)(sizeof(Vector4) * vertices.Length), |
|||
Usage = Usage.Default, |
|||
BindFlags = (uint)BindFlag.VertexBuffer, |
|||
CPUAccessFlags = (uint)CpuAccessFlag.None, |
|||
MiscFlags = (uint)ResourceMiscFlag.None, |
|||
StructureByteStride = 0 |
|||
}; |
|||
var subresourceData = new SubresourceData(verticesPtr); |
|||
ThrowHResult(device.CreateBuffer(&vertexBufferDesc, &subresourceData, vertexBuffer.GetAddressOf())); |
|||
} |
|||
|
|||
// Create Constant Buffer
|
|||
var constantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, |
|||
BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); |
|||
|
|||
var context = device.ImmediateContext; |
|||
ComPtr<ID3D11Buffer> constantBuffer = default; |
|||
var constantBufferDesc = new BufferDesc |
|||
{ |
|||
ByteWidth = (uint)sizeof(Matrix4x4), |
|||
Usage = Usage.Default, |
|||
BindFlags = (uint)BindFlag.ConstantBuffer, |
|||
CPUAccessFlags = (uint)CpuAccessFlag.None, |
|||
MiscFlags = (uint)ResourceMiscFlag.None, |
|||
StructureByteStride = 0 |
|||
}; |
|||
ThrowHResult(device.CreateBuffer(&constantBufferDesc, (SubresourceData*)null, constantBuffer.GetAddressOf())); |
|||
|
|||
// Prepare All the stages
|
|||
context.InputAssembler.InputLayout = layout; |
|||
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; |
|||
context.InputAssembler.SetVertexBuffers(0, |
|||
new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0)); |
|||
context.VertexShader.SetConstantBuffer(0, constantBuffer); |
|||
context.VertexShader.Set(vertexShader); |
|||
context.PixelShader.Set(pixelShader); |
|||
using ComPtr<ID3D11DeviceContext> context = default; |
|||
device.GetImmediateContext(context.GetAddressOf()); |
|||
|
|||
context.IASetInputLayout(inputLayout); |
|||
context.IASetPrimitiveTopology(D3DPrimitiveTopology.D3D10PrimitiveTopologyTrianglelist); |
|||
var stride = (uint)(sizeof(Vector4) * 2); |
|||
var offset = 0u; |
|||
context.IASetVertexBuffers(0, 1, &vertexBuffer.Handle, &stride, &offset); |
|||
context.VSSetConstantBuffers(0, 1, &constantBuffer.Handle); |
|||
context.VSSetShader(vertexShader, (ID3D11ClassInstance**)null, 0); |
|||
context.PSSetShader(pixelShader, (ID3D11ClassInstance**)null, 0); |
|||
|
|||
return constantBuffer; |
|||
} |
|||
|
|||
private static unsafe ComPtr<ID3D10Blob> CompileShader(string fileName, string entryPoint, string profile) |
|||
{ |
|||
ComPtr<ID3D10Blob> blob = default; |
|||
ThrowHResult(s_compiler.CompileFromFile(fileName, null, null, entryPoint, profile, 0u, 0u, blob.GetAddressOf(), null)); |
|||
return blob; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,7 @@ |
|||
namespace GpuInterop; |
|||
|
|||
public enum DemoType |
|||
{ |
|||
Vulkan, |
|||
D3D11 |
|||
} |
|||
@ -1,13 +1,5 @@ |
|||
<Window xmlns="https://github.com/avaloniaui" |
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
|||
xmlns:gpuInterop="clr-namespace:GpuInterop" |
|||
xmlns:d3DDemo="clr-namespace:GpuInterop.D3DDemo" |
|||
xmlns:vulkanDemo="clr-namespace:GpuInterop.VulkanDemo" |
|||
x:Class="GpuInterop.MainWindow"> |
|||
<gpuInterop:GpuDemo> |
|||
<gpuInterop:GpuDemo.Demo> |
|||
<!--<d3DDemo:D3D11DemoControl/>--> |
|||
<vulkanDemo:VulkanDemoControl/> |
|||
</gpuInterop:GpuDemo.Demo> |
|||
</gpuInterop:GpuDemo> |
|||
|
|||
</Window> |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
{ |
|||
"$schema": "http://json.schemastore.org/launchsettings.json", |
|||
"profiles": { |
|||
"GpuInterop (Vulkan)": { |
|||
"commandName": "Project", |
|||
}, |
|||
"GpuInterop (Direct3D)": { |
|||
"commandName": "Project", |
|||
"commandLineArgs": "--d3d" |
|||
} |
|||
} |
|||
} |
|||
@ -1,54 +1,97 @@ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using Avalonia; |
|||
using SharpDX.Direct3D; |
|||
using SharpDX.Direct3D11; |
|||
using SharpDX.DXGI; |
|||
using D3DDevice = SharpDX.Direct3D11.Device; |
|||
using DxgiFactory1 = SharpDX.DXGI.Factory1; |
|||
using Silk.NET.Core.Native; |
|||
using Silk.NET.Direct3D11; |
|||
using Silk.NET.DXGI; |
|||
using VulkanFormat = Silk.NET.Vulkan.Format; |
|||
using static Silk.NET.Core.Native.SilkMarshal; |
|||
|
|||
namespace GpuInterop.VulkanDemo; |
|||
|
|||
public class D3DMemoryHelper |
|||
{ |
|||
public static D3DDevice CreateDeviceByLuid(Span<byte> luid) |
|||
private const int DxgiErrorNotFound = unchecked((int)0x887A0002); |
|||
|
|||
public static unsafe ComPtr<ID3D11Device> CreateDeviceByLuid(Luid luid) |
|||
{ |
|||
var factory = new DxgiFactory1(); |
|||
var longLuid = MemoryMarshal.Cast<byte, long>(luid)[0]; |
|||
for (var c = 0; c < factory.GetAdapterCount1(); c++) |
|||
using var dxgi = new DXGI(DXGI.CreateDefaultContext(["DXGI.dll"])); |
|||
using var d3d11 = new D3D11(D3D11.CreateDefaultContext(["d3d11.dll"])); |
|||
using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>(); |
|||
using var adapter = GetAdapterByLuid(factory, luid); |
|||
|
|||
const int featureLevelCount = 8; |
|||
var featureLevels = stackalloc D3DFeatureLevel[featureLevelCount] |
|||
{ |
|||
using var adapter = factory.GetAdapter1(c); |
|||
if (adapter.Description1.Luid != longLuid) |
|||
continue; |
|||
|
|||
return new D3DDevice(adapter, DeviceCreationFlags.None, |
|||
new[] |
|||
{ |
|||
FeatureLevel.Level_12_1, FeatureLevel.Level_12_0, FeatureLevel.Level_11_1, |
|||
FeatureLevel.Level_11_0, FeatureLevel.Level_10_0, FeatureLevel.Level_9_3, |
|||
FeatureLevel.Level_9_2, FeatureLevel.Level_9_1, |
|||
}); |
|||
D3DFeatureLevel.Level121, |
|||
D3DFeatureLevel.Level120, |
|||
D3DFeatureLevel.Level111, |
|||
D3DFeatureLevel.Level110, |
|||
D3DFeatureLevel.Level100, |
|||
D3DFeatureLevel.Level93, |
|||
D3DFeatureLevel.Level92, |
|||
D3DFeatureLevel.Level91 |
|||
}; |
|||
|
|||
ComPtr<ID3D11Device> device = default; |
|||
ComPtr<ID3D11DeviceContext> context = default; |
|||
D3DFeatureLevel actualFeatureLevel; |
|||
ThrowHResult(d3d11.CreateDevice( |
|||
adapter, |
|||
D3DDriverType.Unknown, |
|||
IntPtr.Zero, |
|||
0u, |
|||
featureLevels, |
|||
featureLevelCount, |
|||
D3D11.SdkVersion, |
|||
device.GetAddressOf(), |
|||
&actualFeatureLevel, |
|||
context.GetAddressOf())); |
|||
|
|||
return device; |
|||
} |
|||
|
|||
private static unsafe ComPtr<IDXGIAdapter> GetAdapterByLuid(ComPtr<IDXGIFactory1> factory, Luid luid) |
|||
{ |
|||
var index = 0u; |
|||
ComPtr<IDXGIAdapter> adapter = default; |
|||
|
|||
while (factory.EnumAdapters(index, adapter.GetAddressOf()) != DxgiErrorNotFound) |
|||
{ |
|||
AdapterDesc adapterDesc; |
|||
if (adapter.GetDesc(&adapterDesc) == 0 & AreLuidsEqual(adapterDesc.AdapterLuid, luid)) |
|||
return adapter; |
|||
|
|||
adapter.Dispose(); |
|||
++index; |
|||
} |
|||
|
|||
throw new ArgumentException("Device with the corresponding LUID not found"); |
|||
} |
|||
|
|||
public static Texture2D CreateMemoryHandle(D3DDevice device, PixelSize size, Silk.NET.Vulkan.Format format) |
|||
public static unsafe ComPtr<ID3D11Texture2D> CreateMemoryHandle(ComPtr<ID3D11Device> device, PixelSize size, VulkanFormat format) |
|||
{ |
|||
if (format != Silk.NET.Vulkan.Format.R8G8B8A8Unorm) |
|||
if (format != VulkanFormat.R8G8B8A8Unorm) |
|||
throw new ArgumentException("Not supported format"); |
|||
return new Texture2D(device, |
|||
new Texture2DDescription |
|||
{ |
|||
Format = Format.R8G8B8A8_UNorm, |
|||
Width = size.Width, |
|||
Height = size.Height, |
|||
ArraySize = 1, |
|||
MipLevels = 1, |
|||
SampleDescription = new SampleDescription { Count = 1, Quality = 0 }, |
|||
CpuAccessFlags = default, |
|||
OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle, |
|||
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource |
|||
}); |
|||
|
|||
ComPtr<ID3D11Texture2D> texture = default; |
|||
var textureDesc = new Texture2DDesc |
|||
{ |
|||
Format = Format.FormatR8G8B8A8Unorm, |
|||
Width = (uint)size.Width, |
|||
Height = (uint)size.Height, |
|||
ArraySize = 1, |
|||
MipLevels = 1, |
|||
SampleDesc = new SampleDesc(1, 0), |
|||
Usage = Usage.Default, |
|||
BindFlags = (uint)(BindFlag.RenderTarget | BindFlag.ShaderResource), |
|||
CPUAccessFlags = 0, |
|||
MiscFlags = (uint)(ResourceMiscFlag.SharedKeyedmutex | ResourceMiscFlag.SharedNthandle) |
|||
}; |
|||
ThrowHResult(device.CreateTexture2D(&textureDesc, (SubresourceData*)null, texture.GetAddressOf())); |
|||
|
|||
return texture; |
|||
} |
|||
|
|||
private static bool AreLuidsEqual(Luid x, Luid y) |
|||
=> x.Low == y.Low && x.High == y.High; |
|||
} |
|||
|
|||
@ -1,8 +0,0 @@ |
|||
<Application |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ReactiveUIDemo.App"> |
|||
<Application.Styles> |
|||
<FluentTheme /> |
|||
</Application.Styles> |
|||
</Application> |
|||
@ -1,37 +0,0 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Markup.Xaml; |
|||
using Avalonia.ReactiveUI; |
|||
using ReactiveUI; |
|||
using ReactiveUIDemo.ViewModels; |
|||
using ReactiveUIDemo.Views; |
|||
using Splat; |
|||
|
|||
namespace ReactiveUIDemo |
|||
{ |
|||
public class App : Application |
|||
{ |
|||
public override void Initialize() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
Locator.CurrentMutable.Register(() => new FooView(), typeof(IViewFor<FooViewModel>)); |
|||
Locator.CurrentMutable.Register(() => new BarView(), typeof(IViewFor<BarViewModel>)); |
|||
} |
|||
|
|||
public override void OnFrameworkInitializationCompleted() |
|||
{ |
|||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) |
|||
desktop.MainWindow = new MainWindow(); |
|||
base.OnFrameworkInitializationCompleted(); |
|||
} |
|||
|
|||
public static int Main(string[] args) |
|||
=> BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); |
|||
|
|||
public static AppBuilder BuildAvaloniaApp() |
|||
=> AppBuilder.Configure<App>() |
|||
.UsePlatformDetect() |
|||
.UseReactiveUI() |
|||
.LogToTrace(); |
|||
} |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
<Window xmlns="https://github.com/avaloniaui" |
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
|||
x:Class="ReactiveUIDemo.MainWindow" |
|||
xmlns:vm="using:ReactiveUIDemo.ViewModels" |
|||
xmlns:rxui="using:Avalonia.ReactiveUI" |
|||
Title="AvaloniaUI ReactiveUI Demo" |
|||
x:DataType="vm:MainWindowViewModel"> |
|||
<TabControl TabStripPlacement="Left"> |
|||
<TabItem Header="RoutedViewHost"> |
|||
<DockPanel DataContext="{Binding RoutedViewHost}"> |
|||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Spacing="8"> |
|||
<Button Command="{Binding ShowFoo}">Foo</Button> |
|||
<Button Command="{Binding ShowBar}">Bar</Button> |
|||
</StackPanel> |
|||
<rxui:RoutedViewHost Router="{Binding Router}"/> |
|||
</DockPanel> |
|||
</TabItem> |
|||
</TabControl> |
|||
</Window> |
|||
@ -1,22 +0,0 @@ |
|||
using ReactiveUIDemo.ViewModels; |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace ReactiveUIDemo |
|||
{ |
|||
public class MainWindow : Window |
|||
{ |
|||
public MainWindow() |
|||
{ |
|||
this.InitializeComponent(); |
|||
this.DataContext = new MainWindowViewModel(); |
|||
this.AttachDevTools(); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
} |
|||
} |
|||
@ -1,28 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Update="Views\BarView.axaml.cs"> |
|||
<DependentUpon>BarView.axaml</DependentUpon> |
|||
</Compile> |
|||
<Compile Update="Views\FooView.axaml.cs"> |
|||
<DependentUpon>FooView.axaml</DependentUpon> |
|||
</Compile> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="..\..\build\SampleApp.props" /> |
|||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|||
<Import Project="..\..\build\BuildTargets.targets" /> |
|||
<Import Project="..\..\build\ReactiveUI.props" /> |
|||
</Project> |
|||
@ -1,11 +0,0 @@ |
|||
using ReactiveUI; |
|||
|
|||
namespace ReactiveUIDemo.ViewModels |
|||
{ |
|||
internal class BarViewModel : ReactiveObject, IRoutableViewModel |
|||
{ |
|||
public BarViewModel(IScreen screen) => HostScreen = screen; |
|||
public string UrlPathSegment => "Bar"; |
|||
public IScreen HostScreen { get; } |
|||
} |
|||
} |
|||
@ -1,11 +0,0 @@ |
|||
using ReactiveUI; |
|||
|
|||
namespace ReactiveUIDemo.ViewModels |
|||
{ |
|||
internal class FooViewModel : ReactiveObject, IRoutableViewModel |
|||
{ |
|||
public FooViewModel(IScreen screen) => HostScreen = screen; |
|||
public string UrlPathSegment => "Foo"; |
|||
public IScreen HostScreen { get; } |
|||
} |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
using ReactiveUI; |
|||
|
|||
namespace ReactiveUIDemo.ViewModels |
|||
{ |
|||
internal class MainWindowViewModel : ReactiveObject |
|||
{ |
|||
public RoutedViewHostPageViewModel RoutedViewHost { get; } = new(); |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
using ReactiveUI; |
|||
|
|||
namespace ReactiveUIDemo.ViewModels |
|||
{ |
|||
internal class RoutedViewHostPageViewModel : ReactiveObject, IScreen |
|||
{ |
|||
public RoutedViewHostPageViewModel() |
|||
{ |
|||
Foo = new(this); |
|||
Bar = new(this); |
|||
Router.Navigate.Execute(Foo); |
|||
} |
|||
|
|||
public RoutingState Router { get; } = new(); |
|||
public FooViewModel Foo { get; } |
|||
public BarViewModel Bar { get; } |
|||
|
|||
public void ShowFoo() => Router.Navigate.Execute(Foo); |
|||
public void ShowBar() => Router.Navigate.Execute(Bar); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue