committed by
GitHub
46 changed files with 718 additions and 280 deletions
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,43 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net7.0</TargetFramework> |
||||
|
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> |
||||
|
<WasmMainJSPath>main.js</WasmMainJSPath> |
||||
|
<OutputType>Exe</OutputType> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver> |
||||
|
<WasmBuildNative>true</WasmBuildNative> |
||||
|
<EmccFlags>-sVERBOSE -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'"> |
||||
|
<RunAOTCompilation>true</RunAOTCompilation> |
||||
|
<PublishTrimmed>true</PublishTrimmed> |
||||
|
<TrimMode>full</TrimMode> |
||||
|
<WasmBuildNative>true</WasmBuildNative> |
||||
|
<InvariantGlobalization>true</InvariantGlobalization> |
||||
|
<EmccCompileOptimizationFlag>-O2</EmccCompileOptimizationFlag> |
||||
|
<EmccLinkOptimizationFlag>-O2</EmccLinkOptimizationFlag> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<TrimmerRootDescriptor Include="Roots.xml" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.csproj" /> |
||||
|
<ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<WasmExtraFilesToDeploy Include="index.html" /> |
||||
|
<WasmExtraFilesToDeploy Include="main.js" /> |
||||
|
<WasmExtraFilesToDeploy Include="favicon.ico" /> |
||||
|
<WasmExtraFilesToDeploy Include="Logo.svg" /> |
||||
|
<WasmExtraFilesToDeploy Include="app.css" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.props" /> |
||||
|
<Import Project="..\..\src\Browser\Avalonia.Browser\Avalonia.Browser.targets" /> |
||||
|
</Project> |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.Runtime.Versioning; |
||||
|
using System.Threading.Tasks; |
||||
|
using Avalonia; |
||||
|
using Avalonia.Browser; |
||||
|
using MobileSandbox; |
||||
|
|
||||
|
[assembly:SupportedOSPlatform("browser")] |
||||
|
|
||||
|
internal partial class Program |
||||
|
{ |
||||
|
public static async Task Main(string[] args) |
||||
|
{ |
||||
|
await BuildAvaloniaApp() |
||||
|
.StartBrowserAppAsync("out"); |
||||
|
} |
||||
|
|
||||
|
public static AppBuilder BuildAvaloniaApp() |
||||
|
=> AppBuilder.Configure<App>(); |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"profiles": { |
||||
|
"MobileSandbox.Browser": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
}, |
||||
|
"applicationUrl": "https://localhost:65312;http://localhost:65313;" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
<linker> |
||||
|
<assembly fullname="MobileSandbox" preserve="All" /> |
||||
|
<assembly fullname="MobileSandbox.Browser" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Themes.Fluent" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Themes.Simple" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Controls.ColorPicker" preserve="All" /> |
||||
|
</linker> |
||||
@ -0,0 +1,56 @@ |
|||||
|
:root { |
||||
|
--sat: env(safe-area-inset-top); |
||||
|
--sar: env(safe-area-inset-right); |
||||
|
--sab: env(safe-area-inset-bottom); |
||||
|
--sal: env(safe-area-inset-left); |
||||
|
} |
||||
|
|
||||
|
#out { |
||||
|
height: 100vh; |
||||
|
width: 100vw |
||||
|
} |
||||
|
|
||||
|
#avalonia-splash { |
||||
|
position: relative; |
||||
|
height: 100%; |
||||
|
width: 100%; |
||||
|
color: whitesmoke; |
||||
|
background: #171C2C; |
||||
|
font-family: 'Nunito', sans-serif; |
||||
|
background-position: center; |
||||
|
background-size: cover; |
||||
|
background-repeat: no-repeat; |
||||
|
} |
||||
|
|
||||
|
#avalonia-splash a{ |
||||
|
color: whitesmoke; |
||||
|
text-decoration: none; |
||||
|
} |
||||
|
|
||||
|
.center { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
height: 250px; |
||||
|
} |
||||
|
|
||||
|
.splash-close { |
||||
|
animation: slide 0.5s linear 1s forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slide { |
||||
|
0% { |
||||
|
top: 0%; |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
opacity: 80%; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
top: 100%; |
||||
|
overflow: hidden; |
||||
|
opacity: 0; |
||||
|
display: none; |
||||
|
visibility: collapse; |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 172 KiB |
@ -0,0 +1,31 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<!-- Licensed to the .NET Foundation under one or more agreements. --> |
||||
|
<!-- The .NET Foundation licenses this file to you under the MIT license. --> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<title>Mobile Sandbox</title> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<link rel="modulepreload" href="./main.js" /> |
||||
|
<link rel="modulepreload" href="./dotnet.js" /> |
||||
|
<link rel="modulepreload" href="./avalonia.js" /> |
||||
|
<link rel="stylesheet" href="./app.css" /> |
||||
|
</head> |
||||
|
|
||||
|
<body style="margin: 0px"> |
||||
|
<div id="out"> |
||||
|
<div id="avalonia-splash"> |
||||
|
<div class="center"> |
||||
|
<h2>Powered by</h2> |
||||
|
<a class="navbar-brand" href="https://www.avaloniaui.net/" target="_blank"> |
||||
|
<img src="Logo.svg" alt="Avalonia Logo" width="30" height="24" /> |
||||
|
Avalonia |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<script type='module' src="./main.js"></script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,16 @@ |
|||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
|
||||
|
import { dotnet } from './dotnet.js' |
||||
|
|
||||
|
const is_browser = typeof window != "undefined"; |
||||
|
if (!is_browser) throw new Error(`Expected to be running in a browser`); |
||||
|
|
||||
|
const dotnetRuntime = await dotnet |
||||
|
.withDiagnosticTracing(false) |
||||
|
.withApplicationArgumentsFromQuery() |
||||
|
.create(); |
||||
|
|
||||
|
const config = dotnetRuntime.getConfig(); |
||||
|
|
||||
|
await dotnetRuntime.runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]); |
||||
@ -0,0 +1,11 @@ |
|||||
|
{ |
||||
|
"wasmHostProperties": { |
||||
|
"perHostConfig": [ |
||||
|
{ |
||||
|
"name": "browser", |
||||
|
"html-path": "index.html", |
||||
|
"Host": "browser" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
<Styles xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
xmlns:controls="using:Avalonia.Diagnostics.Controls" |
||||
|
x:ClassModifier="internal"> |
||||
|
<Design.PreviewWith> |
||||
|
<controls:BrushEditor /> |
||||
|
</Design.PreviewWith> |
||||
|
|
||||
|
<Style Selector=":is(controls|BrushEditor)"> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<Grid> |
||||
|
<Button Theme="{StaticResource SimpleTextBoxClearButtonTheme}" |
||||
|
x:Name="PART_ClearButton" |
||||
|
HorizontalAlignment="Right" |
||||
|
VerticalContentAlignment="Center"/> |
||||
|
</Grid> |
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
</Styles> |
||||
@ -0,0 +1,121 @@ |
|||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.Metadata; |
||||
|
using Avalonia.Controls.Primitives; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Interactivity; |
||||
|
using Avalonia.Media; |
||||
|
using Avalonia.Media.Immutable; |
||||
|
|
||||
|
namespace Avalonia.Diagnostics.Controls |
||||
|
{ |
||||
|
[TemplatePart("PART_ClearButton", typeof(Button))] |
||||
|
partial class BrushEditor : TemplatedControl |
||||
|
{ |
||||
|
private readonly EventHandler<RoutedEventArgs> clearHandler; |
||||
|
private Button? _clearButton = default; |
||||
|
private readonly ColorView _colorView = new() |
||||
|
{ |
||||
|
HexInputAlphaPosition = AlphaComponentPosition.Leading, // Always match XAML
|
||||
|
}; |
||||
|
|
||||
|
public BrushEditor() |
||||
|
{ |
||||
|
FlyoutBase.SetAttachedFlyout(this, new Flyout { Content = _colorView }); |
||||
|
_colorView.ColorChanged += (_, e) => Brush = new ImmutableSolidColorBrush(e.NewColor); |
||||
|
clearHandler = (s, e) => Brush = default; |
||||
|
} |
||||
|
|
||||
|
protected override Type StyleKeyOverride => typeof(BrushEditor); |
||||
|
|
||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
||||
|
{ |
||||
|
base.OnApplyTemplate(e); |
||||
|
if (_clearButton is not null) |
||||
|
{ |
||||
|
_clearButton.Click -= clearHandler; |
||||
|
} |
||||
|
_clearButton = e.NameScope.Find<Button>("PART_ClearButton"); |
||||
|
if (_clearButton is Button button) |
||||
|
{ |
||||
|
button.Click += clearHandler; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Brush" /> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly DirectProperty<BrushEditor, IBrush?> BrushProperty = |
||||
|
AvaloniaProperty.RegisterDirect<BrushEditor, IBrush?>( |
||||
|
nameof(Brush), o => o.Brush, (o, v) => o.Brush = v); |
||||
|
|
||||
|
private IBrush? _brush; |
||||
|
|
||||
|
public IBrush? Brush |
||||
|
{ |
||||
|
get => _brush; |
||||
|
set => SetAndRaise(BrushProperty, ref _brush, value); |
||||
|
} |
||||
|
|
||||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) |
||||
|
{ |
||||
|
base.OnPropertyChanged(change); |
||||
|
|
||||
|
if (change.Property == BrushProperty) |
||||
|
{ |
||||
|
if (Brush is ISolidColorBrush scb) |
||||
|
{ |
||||
|
_colorView.Color = scb.Color; |
||||
|
} |
||||
|
ToolTip.SetTip(this, Brush?.GetType().Name ?? "(null)"); |
||||
|
InvalidateVisual(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override void OnPointerPressed(PointerPressedEventArgs e) |
||||
|
{ |
||||
|
base.OnPointerPressed(e); |
||||
|
|
||||
|
FlyoutBase.ShowAttachedFlyout(this); |
||||
|
} |
||||
|
|
||||
|
public override void Render(DrawingContext context) |
||||
|
{ |
||||
|
base.Render(context); |
||||
|
|
||||
|
var brush = Brush ?? Brushes.Black; |
||||
|
|
||||
|
context.FillRectangle(brush, Bounds); |
||||
|
|
||||
|
var text = (Brush as ISolidColorBrush)?.Color.ToString() ?? "(null)"; |
||||
|
|
||||
|
var ft = new FormattedText(text, |
||||
|
CultureInfo.CurrentCulture, |
||||
|
FlowDirection.LeftToRight, |
||||
|
Typeface.Default, |
||||
|
10, |
||||
|
GetTextBrush(brush)); |
||||
|
|
||||
|
context.DrawText(ft, |
||||
|
new Point(Bounds.Width / 2 - ft.Width / 2, Bounds.Height / 2 - ft.Height / 2)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Get Contrasted Text Color
|
||||
|
/// </summary>
|
||||
|
/// <param name="brush"></param>
|
||||
|
/// <returns></returns>
|
||||
|
private static IBrush GetTextBrush(IBrush brush) |
||||
|
{ |
||||
|
if (brush is ISolidColorBrush solid) |
||||
|
{ |
||||
|
var color = solid.Color; |
||||
|
var l = ColorHelper.GetRelativeLuminance(color); |
||||
|
|
||||
|
return l < 0.5 ? Brushes.White : Brushes.Black; |
||||
|
} |
||||
|
return Brushes.White; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,94 +0,0 @@ |
|||||
using System.Globalization; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Controls.Primitives; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Media.Immutable; |
|
||||
|
|
||||
namespace Avalonia.Diagnostics.Controls |
|
||||
{ |
|
||||
internal sealed class BrushEditor : Control |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Defines the <see cref="Brush" /> property.
|
|
||||
/// </summary>
|
|
||||
public static readonly DirectProperty<BrushEditor, IBrush?> BrushProperty = |
|
||||
AvaloniaProperty.RegisterDirect<BrushEditor, IBrush?>( |
|
||||
nameof(Brush), o => o.Brush, (o, v) => o.Brush = v); |
|
||||
|
|
||||
private IBrush? _brush; |
|
||||
|
|
||||
public IBrush? Brush |
|
||||
{ |
|
||||
get => _brush; |
|
||||
set => SetAndRaise(BrushProperty, ref _brush, value); |
|
||||
} |
|
||||
|
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) |
|
||||
{ |
|
||||
base.OnPropertyChanged(change); |
|
||||
|
|
||||
if (change.Property == BrushProperty) |
|
||||
{ |
|
||||
switch (Brush) |
|
||||
{ |
|
||||
case ISolidColorBrush scb: |
|
||||
{ |
|
||||
var colorView = new ColorView |
|
||||
{ |
|
||||
HexInputAlphaPosition = AlphaComponentPosition.Leading, // Always match XAML
|
|
||||
Color = scb.Color, |
|
||||
}; |
|
||||
|
|
||||
colorView.ColorChanged += (_, e) => Brush = new ImmutableSolidColorBrush(e.NewColor); |
|
||||
|
|
||||
FlyoutBase.SetAttachedFlyout(this, new Flyout { Content = colorView }); |
|
||||
ToolTip.SetTip(this, $"{scb.Color} ({Brush.GetType().Name})"); |
|
||||
|
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
default: |
|
||||
|
|
||||
FlyoutBase.SetAttachedFlyout(this, null); |
|
||||
ToolTip.SetTip(this, Brush?.GetType().Name ?? "(null)"); |
|
||||
|
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
InvalidateVisual(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e) |
|
||||
{ |
|
||||
base.OnPointerPressed(e); |
|
||||
|
|
||||
FlyoutBase.ShowAttachedFlyout(this); |
|
||||
} |
|
||||
|
|
||||
public override void Render(DrawingContext context) |
|
||||
{ |
|
||||
base.Render(context); |
|
||||
|
|
||||
if (Brush != null) |
|
||||
{ |
|
||||
context.FillRectangle(Brush, Bounds); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
context.FillRectangle(Brushes.Black, Bounds); |
|
||||
|
|
||||
var ft = new FormattedText("(null)", |
|
||||
CultureInfo.CurrentCulture, |
|
||||
FlowDirection.LeftToRight, |
|
||||
Typeface.Default, |
|
||||
10, |
|
||||
Brushes.White); |
|
||||
|
|
||||
context.DrawText(ft, |
|
||||
new Point(Bounds.Width / 2 - ft.Width / 2, Bounds.Height / 2 - ft.Height / 2)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue