From f14aac365bf6bc12b5d7133c22ce0ddd839fc0f2 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 15 Feb 2019 14:48:10 +0300 Subject: [PATCH 001/453] WIP --- .gitmodules | 3 + .../Pages/ButtonSpinnerPage.xaml.cs | 2 +- .../UsableDuringInitializationAttribute.cs | 10 ++ .../Controls/NameScopeExtensions.cs | 3 +- src/Avalonia.Visuals/Visual.cs | 2 + .../Avalonia.Markup.Xaml.csproj | 18 ++ .../AvaloniaTypeConverters.cs | 1 + .../AvaloniaXamlLoader.cs | 15 +- .../AvaloniaPropertyTypeConverter.cs | 4 +- .../Converters/BitmapTypeConverter.cs | 4 +- .../Converters/FontFamilyTypeConverter.cs | 2 +- .../Converters/IconTypeConverter.cs | 2 +- src/Markup/Avalonia.Markup.Xaml/Extensions.cs | 47 +++++ .../MarkupExtensions/BindingExtension.cs | 11 +- .../DynamicResourceExtension.cs | 16 +- .../MarkupExtensions/ResourceInclude.cs | 2 +- .../MarkupExtensions/StyleIncludeExtension.cs | 5 +- .../PortableXaml/TypeDescriptorExtensions.cs | 4 +- .../XamlIl/AvaloniaXamlIlRuntimeCompiler.cs | 160 ++++++++++++++++++ .../AvaloniaPropertyDescriptorEmitter.cs | 21 +++ .../AvaloniaXamlIlCompiler.cs | 61 +++++++ .../AvaloniaXamlIlLanguage.cs | 153 +++++++++++++++++ .../XamlIl/CompilerExtensions/README.md | 4 + .../Transformers/AddNameScopeRegistration.cs | 79 +++++++++ .../IgnoredDirectivesTransformer.cs | 27 +++ .../KnownPseudoMarkupExtensionsTransformer.cs | 26 +++ .../Transformers/XNameTransformer.cs | 33 ++++ .../IAvaloniaXamlIlParentStackProvider.cs | 9 + ...valoniaXamlIlXmlNamespaceInfoProviderV1.cs | 15 ++ .../XamlIl/Runtime/XamlIlRuntimeHelpers.cs | 121 +++++++++++++ .../Avalonia.Markup.Xaml/XamlIl/xamlil.github | 1 + 31 files changed, 827 insertions(+), 34 deletions(-) create mode 100644 src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/Extensions.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaPropertyDescriptorEmitter.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/README.md create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/IgnoredDirectivesTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/KnownPseudoMarkupExtensionsTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/XNameTransformer.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlParentStackProvider.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs create mode 160000 src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github diff --git a/.gitmodules b/.gitmodules index 22c56307b0..22a241f120 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "nukebuild/Numerge"] path = nukebuild/Numerge url = https://github.com/kekekeks/Numerge.git +[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"] + path = src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github + url = https://github.com/kekekeks/XamlIl.git diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs index 1f753ab3ea..c5042baccb 100644 --- a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs @@ -18,7 +18,7 @@ namespace ControlCatalog.Pages AvaloniaXamlLoader.Load(this); } - private void OnSpin(object sender, SpinEventArgs e) + public void OnSpin(object sender, SpinEventArgs e) { var spinner = (ButtonSpinner)sender; var txtBox = (TextBlock)spinner.Content; diff --git a/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs b/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs new file mode 100644 index 0000000000..753a96b9ce --- /dev/null +++ b/src/Avalonia.Base/Metadata/UsableDuringInitializationAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace Avalonia.Metadata +{ + [AttributeUsage(AttributeTargets.Class)] + public class UsableDuringInitializationAttribute : Attribute + { + + } +} diff --git a/src/Avalonia.Styling/Controls/NameScopeExtensions.cs b/src/Avalonia.Styling/Controls/NameScopeExtensions.cs index 491e4d71a7..991a97a614 100644 --- a/src/Avalonia.Styling/Controls/NameScopeExtensions.cs +++ b/src/Avalonia.Styling/Controls/NameScopeExtensions.cs @@ -71,10 +71,11 @@ namespace Avalonia.Controls { Contract.Requires(control != null); - return control.GetSelfAndLogicalAncestors() + var scope = control.GetSelfAndLogicalAncestors() .OfType() .Select(x => (x as INameScope) ?? NameScope.GetNameScope(x)) .FirstOrDefault(x => x != null); + return scope; } } } diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index f26c21d1b6..3360ba84c1 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -9,6 +9,7 @@ using Avalonia.Collections; using Avalonia.Data; using Avalonia.Logging; using Avalonia.Media; +using Avalonia.Metadata; using Avalonia.Rendering; using Avalonia.VisualTree; @@ -23,6 +24,7 @@ namespace Avalonia /// to render the control. To traverse the visual tree, use the /// extension methods defined in . /// + [UsableDuringInitialization] public class Visual : StyledElement, IVisual { /// diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 38d207a31d..4603d31fae 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -15,6 +15,7 @@ + @@ -50,8 +51,21 @@ + + + + + + + + + + + + + @@ -63,6 +77,10 @@ + + + + diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs index c30822aacb..2b6572e1a2 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaTypeConverters.cs @@ -29,6 +29,7 @@ namespace Avalonia.Markup.Xaml /// public static class AvaloniaTypeConverters { + // When adding item to that list make sure to modify AvaloniaXamlIlLanguage private static Dictionary _converters = new Dictionary() { { typeof(AvaloniaList<>), typeof(AvaloniaListConverter<>) }, diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs index a825deeae3..dd413ee10f 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs @@ -13,6 +13,7 @@ using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Text; +using Avalonia.Markup.Xaml.XamlIl; namespace Avalonia.Markup.Xaml { @@ -23,6 +24,8 @@ namespace Avalonia.Markup.Xaml { private readonly AvaloniaXamlSchemaContext _context = GetContext(); + public bool EnforceCompilerForRuntimeXaml { get; set; } = true; + public bool IsDesignMode { get => _context.IsDesignMode; @@ -137,13 +140,13 @@ namespace Avalonia.Markup.Xaml using (var stream = asset.stream) { var absoluteUri = uri.IsAbsoluteUri ? uri : new Uri(baseUri, uri); - try + //try { return Load(stream, asset.assembly, rootInstance, absoluteUri); } - catch (Exception e) + //catch (Exception e) { - throw new XamlLoadException("Error loading xaml at " + absoluteUri + ": " + e.Message, e); + //throw new XamlLoadException("Error loading xaml at " + absoluteUri + ": " + e.Message, e); } } } @@ -179,6 +182,12 @@ namespace Avalonia.Markup.Xaml /// The loaded object. public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null) { + if (EnforceCompilerForRuntimeXaml) + { + return AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri); + } + + var readerSettings = new XamlXmlReaderSettings() { BaseUri = uri, diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs index 8a0ba64582..18a7fe9ab6 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs @@ -28,8 +28,8 @@ namespace Avalonia.Markup.Xaml.Converters var parser = new PropertyParser(); var (ns, owner, propertyName) = parser.Parse(new CharacterReader(((string)value).AsSpan())); var ownerType = TryResolveOwnerByName(context, ns, owner); - var targetType = context.GetFirstAmbientValue()?.TargetType ?? - context.GetFirstAmbientValue + + + + + + + + + + + + + + + + + + + From 9ec7c7ce4bf09825ea0682961b1277b0c6ed5457 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 11 Apr 2019 00:15:30 +0100 Subject: [PATCH 020/453] sensible close delay. --- src/Avalonia.Controls/Notifications/NotificationManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Notifications/NotificationManager.cs b/src/Avalonia.Controls/Notifications/NotificationManager.cs index 8e6ad0a90b..236d67a35f 100644 --- a/src/Avalonia.Controls/Notifications/NotificationManager.cs +++ b/src/Avalonia.Controls/Notifications/NotificationManager.cs @@ -26,7 +26,7 @@ namespace Avalonia.Controls.Notifications } if (expirationTime == null) - expirationTime = TimeSpan.FromSeconds(25); + expirationTime = TimeSpan.FromSeconds(5); if (areaName == string.Empty && _window == null) { From 1bb3156950a3caa3af8395a8ab5a36cba8e7bd47 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Thu, 11 Apr 2019 17:11:09 +0200 Subject: [PATCH 021/453] Introduce StartupEventArgs and ExitEventArgs --- samples/BindingDemo/App.xaml.cs | 3 +- samples/ControlCatalog.NetCore/Program.cs | 13 ++---- samples/ControlCatalog/App.xaml.cs | 10 ++--- samples/PlatformSanityChecks/App.xaml.cs | 3 +- samples/Previewer/App.xaml.cs | 5 ++- samples/RenderDemo/App.xaml.cs | 3 +- samples/VirtualizationDemo/App.xaml.cs | 3 +- .../interop/Direct3DInteropSample/App.paml.cs | 3 +- src/Avalonia.Controls/AppBuilderBase.cs | 1 - src/Avalonia.Controls/Application.cs | 43 +++++++++---------- .../IApplicationLifecycle.cs | 12 ++++-- .../Controls/ExitEventArgs.cs | 12 ++++++ .../Controls/StartupEventArgs.cs | 30 +++++++++++++ .../App.xaml.cs | 8 +--- 14 files changed, 93 insertions(+), 56 deletions(-) create mode 100644 src/Avalonia.Styling/Controls/ExitEventArgs.cs create mode 100644 src/Avalonia.Styling/Controls/StartupEventArgs.cs diff --git a/samples/BindingDemo/App.xaml.cs b/samples/BindingDemo/App.xaml.cs index 01c52a2a49..d95241372f 100644 --- a/samples/BindingDemo/App.xaml.cs +++ b/samples/BindingDemo/App.xaml.cs @@ -3,13 +3,12 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Logging.Serilog; using Avalonia.Markup.Xaml; -using Serilog; namespace BindingDemo { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index ee4c3fe350..42be488569 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -3,13 +3,11 @@ using System.Diagnostics; using System.Linq; using System.Threading; using Avalonia; -using Avalonia.Skia; namespace ControlCatalog.NetCore { static class Program - { - + { static void Main(string[] args) { Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA); @@ -28,15 +26,10 @@ namespace ControlCatalog.NetCore AppBuilder.Configure().InitializeWithLinuxFramebuffer(tl => { tl.Content = new MainView(); - System.Threading.ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer()); + ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer()); }); else - BuildAvaloniaApp().Start(AppMain, args); - } - - static void AppMain(Application app, string[] args) - { - app.Run(); + BuildAvaloniaApp().Start(); } /// diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 6fbcecfd6e..1f466d9f91 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -1,18 +1,16 @@ using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace ControlCatalog { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { - AvaloniaXamlLoader.Load(this); - } + base.OnStartup(e); - protected override void OnStartup() - { - base.OnStartup(); + AvaloniaXamlLoader.Load(this); var mainWindow = new MainWindow(); diff --git a/samples/PlatformSanityChecks/App.xaml.cs b/samples/PlatformSanityChecks/App.xaml.cs index 508fc1e34b..b8f8350156 100644 --- a/samples/PlatformSanityChecks/App.xaml.cs +++ b/samples/PlatformSanityChecks/App.xaml.cs @@ -1,11 +1,12 @@ using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace PlatformSanityChecks { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } diff --git a/samples/Previewer/App.xaml.cs b/samples/Previewer/App.xaml.cs index fffa987a27..0fc42583a5 100644 --- a/samples/Previewer/App.xaml.cs +++ b/samples/Previewer/App.xaml.cs @@ -1,14 +1,15 @@ using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace Previewer { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } } -} \ No newline at end of file +} diff --git a/samples/RenderDemo/App.xaml.cs b/samples/RenderDemo/App.xaml.cs index 0f627961e6..4ac844983b 100644 --- a/samples/RenderDemo/App.xaml.cs +++ b/samples/RenderDemo/App.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia; +using Avalonia.Controls; using Avalonia.Logging.Serilog; using Avalonia.Markup.Xaml; @@ -9,7 +10,7 @@ namespace RenderDemo { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } diff --git a/samples/VirtualizationDemo/App.xaml.cs b/samples/VirtualizationDemo/App.xaml.cs index b220807443..787bbf8d11 100644 --- a/samples/VirtualizationDemo/App.xaml.cs +++ b/samples/VirtualizationDemo/App.xaml.cs @@ -2,13 +2,14 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace VirtualizationDemo { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } diff --git a/samples/interop/Direct3DInteropSample/App.paml.cs b/samples/interop/Direct3DInteropSample/App.paml.cs index 1b6d5fd39c..b08c02509c 100644 --- a/samples/interop/Direct3DInteropSample/App.paml.cs +++ b/samples/interop/Direct3DInteropSample/App.paml.cs @@ -1,11 +1,12 @@ using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace Direct3DInteropSample { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index cda49a12b3..568b04c78c 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -292,7 +292,6 @@ namespace Avalonia.Controls WindowingSubsystemInitializer(); RenderingSubsystemInitializer(); Instance.RegisterServices(); - Instance.Initialize(); AfterSetupCallback(Self); } } diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 383b994e70..2893505655 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -55,10 +55,10 @@ namespace Avalonia } /// - public event EventHandler Startup; + public event EventHandler Startup; /// - public event EventHandler Exit; + public event EventHandler Exit; /// public event EventHandler ResourcesChanged; @@ -199,14 +199,7 @@ namespace Avalonia /// /// true if this instance is shutting down; otherwise, false. /// - internal bool IsShuttingDown { get; set; } - - /// - /// Initializes the application by loading XAML etc. - /// - public virtual void Initialize() - { - } + internal bool IsShuttingDown { get; private set; } public void Run() { @@ -217,7 +210,7 @@ namespace Avalonia _mainLoopCancellationTokenSource = new CancellationTokenSource(); - Dispatcher.UIThread.Post(OnStartup, DispatcherPriority.Send); + Dispatcher.UIThread.Post(() => OnStartup(new StartupEventArgs()), DispatcherPriority.Send); Run(_mainLoopCancellationTokenSource.Token); } @@ -233,7 +226,7 @@ namespace Avalonia // Make sure we call OnExit in case an error happened and OnExit() wasn't called explicitly if (!IsShuttingDown) { - OnExit(); + OnExit(new ExitEventArgs()); } } @@ -248,10 +241,10 @@ namespace Avalonia throw new Exception("Run should only called once"); } - closable.Closed += (s, e) => OnExit(); - _mainLoopCancellationTokenSource = new CancellationTokenSource(); + closable.Closed += (s, e) => _mainLoopCancellationTokenSource?.Cancel(); + Run(_mainLoopCancellationTokenSource.Token); } @@ -284,26 +277,34 @@ namespace Avalonia Run(_mainLoopCancellationTokenSource.Token); } - protected virtual void OnStartup() + protected virtual void OnStartup(StartupEventArgs e) { - Startup?.Invoke(this, EventArgs.Empty); + Startup?.Invoke(this, e); } - protected virtual void OnExit() + protected virtual void OnExit(ExitEventArgs e) { - Exit?.Invoke(this, EventArgs.Empty); + Exit?.Invoke(this, e); + + Environment.ExitCode = e.ApplicationExitCode; } /// public void Shutdown() + { + Shutdown(0); + } + + /// + public void Shutdown(int exitCode) { IsShuttingDown = true; Windows.Clear(); - _mainLoopCancellationTokenSource?.Cancel(); + OnExit(new ExitEventArgs { ApplicationExitCode = exitCode }); - OnExit(); + _mainLoopCancellationTokenSource?.Cancel(); } /// @@ -314,8 +315,6 @@ namespace Avalonia Styles.TryGetResource(key, out value); } - - /// /// Register's the services needed by Avalonia. /// diff --git a/src/Avalonia.Controls/IApplicationLifecycle.cs b/src/Avalonia.Controls/IApplicationLifecycle.cs index c088ceb0eb..958c448d3e 100644 --- a/src/Avalonia.Controls/IApplicationLifecycle.cs +++ b/src/Avalonia.Controls/IApplicationLifecycle.cs @@ -10,16 +10,22 @@ namespace Avalonia.Controls /// /// Sent when the application is starting up. /// - event EventHandler Startup; + event EventHandler Startup; /// /// Sent when the application is exiting. /// - event EventHandler Exit; + event EventHandler Exit; /// - /// Exits the application. + /// Shuts down an application that returns the specified exit code to the operating system. /// void Shutdown(); + + /// + /// Shuts down an application that returns the specified exit code to the operating system. + /// + /// An integer exit code for an application. The default exit code is 0. + void Shutdown(int exitCode); } } diff --git a/src/Avalonia.Styling/Controls/ExitEventArgs.cs b/src/Avalonia.Styling/Controls/ExitEventArgs.cs new file mode 100644 index 0000000000..1a4ee15f17 --- /dev/null +++ b/src/Avalonia.Styling/Controls/ExitEventArgs.cs @@ -0,0 +1,12 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; + +namespace Avalonia.Controls +{ + public class ExitEventArgs : EventArgs + { + public int ApplicationExitCode { get; set; } + } +} diff --git a/src/Avalonia.Styling/Controls/StartupEventArgs.cs b/src/Avalonia.Styling/Controls/StartupEventArgs.cs new file mode 100644 index 0000000000..8b66ce0dc2 --- /dev/null +++ b/src/Avalonia.Styling/Controls/StartupEventArgs.cs @@ -0,0 +1,30 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Avalonia.Controls +{ + public class StartupEventArgs : EventArgs + { + private string[] _args; + + public IReadOnlyList Args => _args ?? (_args = GetArgs()); + + private static string[] GetArgs() + { + try + { + var args = Environment.GetCommandLineArgs(); + + return args.Length > 1 ? args.Skip(1).ToArray() : new string[0]; + } + catch (NotSupportedException) + { + return new string[0]; + } + } + } +} diff --git a/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs b/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs index 653a51232b..e2fc6ab7a2 100644 --- a/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs +++ b/tests/Avalonia.DesignerSupport.TestApp/App.xaml.cs @@ -1,15 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Avalonia.Controls; using Avalonia.Markup.Xaml; namespace Avalonia.DesignerSupport.TestApp { public class App : Application { - public override void Initialize() + protected override void OnStartup(StartupEventArgs e) { AvaloniaXamlLoader.Load(this); } From 8283f3bca7c15a66fcb30bbb255a93c833b23a29 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 12 Apr 2019 00:43:14 +0800 Subject: [PATCH 022/453] Add some bubble notification animations + make IsClosing a direct property. --- .../Notifications/Notification.cs | 17 +++++++++-- .../NotificationArea.xaml | 28 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Notifications/Notification.cs b/src/Avalonia.Controls/Notifications/Notification.cs index c7cd176513..fbf28c07e5 100644 --- a/src/Avalonia.Controls/Notifications/Notification.cs +++ b/src/Avalonia.Controls/Notifications/Notification.cs @@ -2,13 +2,14 @@ using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Controls.Primitives; +using Avalonia.Data; using Avalonia.Interactivity; namespace Avalonia.Controls.Notifications { public class Notification : ContentControl { - private TimeSpan _closingAnimationTime = TimeSpan.Zero; + private TimeSpan _closingAnimationTime = TimeSpan.FromSeconds(0.25); static Notification() { @@ -42,7 +43,19 @@ namespace Avalonia.Controls.Notifications }); } - public bool IsClosing { get; set; } + private bool _isClosing; + + /// + /// Determines if the notification is already closing. + /// + public bool IsClosing + { + get { return _isClosing; } + private set { SetAndRaise(IsClosingProperty, ref _isClosing, value); } + } + + public static readonly DirectProperty IsClosingProperty = + AvaloniaProperty.RegisterDirect(nameof(IsClosing), o => o.IsClosing); /// /// Defines the event. diff --git a/src/Avalonia.Themes.Default/NotificationArea.xaml b/src/Avalonia.Themes.Default/NotificationArea.xaml index 3d3f4b8c20..2b2dd2a797 100644 --- a/src/Avalonia.Themes.Default/NotificationArea.xaml +++ b/src/Avalonia.Themes.Default/NotificationArea.xaml @@ -28,6 +28,34 @@ + + + + + + + + + + + + + + + + From 7e042158977c4111a67e901b21bbfe289897033e Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Fri, 12 Apr 2019 11:41:59 +0200 Subject: [PATCH 024/453] No longer set first window opened as MainWindow --- samples/ControlCatalog/App.xaml.cs | 2 ++ src/Avalonia.Controls/Application.cs | 2 ++ src/Avalonia.Controls/Window.cs | 14 -------------- .../ApplicationTests.cs | 13 ------------- 4 files changed, 4 insertions(+), 27 deletions(-) diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 1f466d9f91..100cfa634e 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -15,6 +15,8 @@ namespace ControlCatalog var mainWindow = new MainWindow(); mainWindow.Show(); + + MainWindow = mainWindow; } } } diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 2893505655..b750e570b3 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -272,6 +272,8 @@ namespace Avalonia { mainWindow.Show(); } + + MainWindow = mainWindow; } Run(_mainLoopCancellationTokenSource.Token); diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 648256e667..411685800e 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -49,8 +49,6 @@ namespace Avalonia.Controls /// public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot, INameScope { - private static bool s_hasAddedFirstWindow; - /// /// Defines the property. /// @@ -262,18 +260,6 @@ namespace Avalonia.Controls } Application.Current.Windows.Add(window); - - if (s_hasAddedFirstWindow) - { - return; - } - - s_hasAddedFirstWindow = true; - - if (Application.Current.MainWindow == null) - { - Application.Current.MainWindow = window; - } } private static void RemoveWindow(Window window) diff --git a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs index 7cedd9b69a..f362e691dc 100644 --- a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs @@ -129,18 +129,5 @@ namespace Avalonia.Controls.UnitTests Assert.True(raised); } } - - [Fact] - public void Should_Have_MainWindow_After_First_Window_Shown() - { - using (UnitTestApplication.Start(TestServices.StyledWindow)) - { - var mainWindow = new Window(); - - mainWindow.Show(); - - Assert.Equal(mainWindow, Application.Current.MainWindow); - } - } } } From 05978b0ba620649e547f4f778ed145d407abfc94 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Fri, 12 Apr 2019 11:50:53 +0200 Subject: [PATCH 025/453] Make sure Shutdown is only called once --- src/Avalonia.Controls/Application.cs | 33 +++++++++---------- .../Controls/ExitEventArgs.cs | 6 +++- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index b750e570b3..99fc2e7367 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -215,21 +215,6 @@ namespace Avalonia Run(_mainLoopCancellationTokenSource.Token); } - /// - /// Runs the application's main loop until the is canceled. - /// - /// The token to track - public void Run(CancellationToken token) - { - Dispatcher.UIThread.MainLoop(token); - - // Make sure we call OnExit in case an error happened and OnExit() wasn't called explicitly - if (!IsShuttingDown) - { - OnExit(new ExitEventArgs()); - } - } - /// /// Runs the application's main loop until the is closed. /// @@ -279,6 +264,17 @@ namespace Avalonia Run(_mainLoopCancellationTokenSource.Token); } + /// + /// Runs the application's main loop until the is canceled. + /// + /// The token to track + public void Run(CancellationToken token) + { + Dispatcher.UIThread.MainLoop(token); + + Shutdown(); + } + protected virtual void OnStartup(StartupEventArgs e) { Startup?.Invoke(this, e); @@ -287,8 +283,6 @@ namespace Avalonia protected virtual void OnExit(ExitEventArgs e) { Exit?.Invoke(this, e); - - Environment.ExitCode = e.ApplicationExitCode; } /// @@ -300,6 +294,11 @@ namespace Avalonia /// public void Shutdown(int exitCode) { + if (IsShuttingDown) + { + return; + } + IsShuttingDown = true; Windows.Clear(); diff --git a/src/Avalonia.Styling/Controls/ExitEventArgs.cs b/src/Avalonia.Styling/Controls/ExitEventArgs.cs index 1a4ee15f17..2e6409e296 100644 --- a/src/Avalonia.Styling/Controls/ExitEventArgs.cs +++ b/src/Avalonia.Styling/Controls/ExitEventArgs.cs @@ -7,6 +7,10 @@ namespace Avalonia.Controls { public class ExitEventArgs : EventArgs { - public int ApplicationExitCode { get; set; } + public int ApplicationExitCode + { + get => Environment.ExitCode; + set => Environment.ExitCode = value; + } } } From 6fbe1c2180ef45a940e193f1b4637e64eaab80ed Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Fri, 12 Apr 2019 19:35:31 +0800 Subject: [PATCH 026/453] More animations shenanigans. --- .../LayoutTransformControl.cs | 1 + .../Notifications/Notification.cs | 32 ++++++++++++++--- .../NotificationArea.xaml | 34 ++++++++++++------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Controls/LayoutTransformControl.cs b/src/Avalonia.Controls/LayoutTransformControl.cs index 950d4f34da..482cfc5320 100644 --- a/src/Avalonia.Controls/LayoutTransformControl.cs +++ b/src/Avalonia.Controls/LayoutTransformControl.cs @@ -51,6 +51,7 @@ namespace Avalonia.Controls { if (TransformRoot == null || LayoutTransform == null) { + LayoutTransform = RenderTransform; return base.ArrangeOverride(finalSize); } diff --git a/src/Avalonia.Controls/Notifications/Notification.cs b/src/Avalonia.Controls/Notifications/Notification.cs index 54de4bcce7..c75e805892 100644 --- a/src/Avalonia.Controls/Notifications/Notification.cs +++ b/src/Avalonia.Controls/Notifications/Notification.cs @@ -9,11 +9,12 @@ namespace Avalonia.Controls.Notifications { public class Notification : ContentControl { - private TimeSpan _closingAnimationTime = TimeSpan.FromSeconds(1); + // private TimeSpan _closingAnimationTime = TimeSpan.FromSeconds(1); static Notification() { //CloseOnClickProperty.Changed.AddClassHandler //TODO Binding + [AssignBinding] public virtual IBinding Binding { get diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs index 8a237f180f..d9345738fc 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleIncludeExtension.cs @@ -18,7 +18,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions { } - public override object ProvideValue(IServiceProvider serviceProvider) + public override object ProvideValue(IServiceProvider serviceProvider) => ProvideTypedValue(serviceProvider); + public IStyle ProvideTypedValue(IServiceProvider serviceProvider) { return new StyleInclude(serviceProvider.GetContextBaseUri()) { Source = Source }; } diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs index 94ebb138eb..0de9e7942b 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs @@ -24,7 +24,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions var bindingType = typeSystem.GetType("Avalonia.Data.IBinding"); var rv = new XamlIlLanguageTypeMappings(typeSystem) { - SupportInitialize = typeSystem.GetType("Avalonia.ISupportInitialize"), + SupportInitialize = typeSystem.GetType("System.ComponentModel.ISupportInitialize"), XmlnsAttributes = { typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"), diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs index 4569accb74..1a646e50c2 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs @@ -35,12 +35,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers throw new XamlIlParseException("Selector property should be a text node", node); var selectorType = pn.Property.GetClrProperty().PropertyType; - + var initialNode = new XamlIlSelectorInitialNode(node, selectorType); XamlIlSelectorNode Create(IEnumerable syntax, Func typeResolver) { - XamlIlSelectorNode result = new XamlIlSelectorInitialNode(node, selectorType); - + XamlIlSelectorNode result = initialNode; + XamlIlOrSelectorNode results = null; foreach (var i in syntax) { switch (i) @@ -93,12 +93,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers case SelectorGrammar.NotSyntax not: result = new XamlIlNotSelector(result, Create(not.Argument, typeResolver)); break; + case SelectorGrammar.CommaSyntax comma: + if (results == null) + results = new XamlIlOrSelectorNode(node, selectorType); + results.Add(result); + result = initialNode; + break; default: throw new XamlIlParseException($"Unsupported selector grammar '{i.GetType()}'.", node); } } - return result; + return results ?? result; } IEnumerable parsed; @@ -126,7 +132,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers abstract class XamlIlSelectorNode : XamlIlAstNode, IXamlIlAstValueNode, IXamlIlAstEmitableNode { - public XamlIlSelectorNode Previous { get; } + protected XamlIlSelectorNode Previous { get; } public abstract IXamlIlType TargetType { get; } public XamlIlSelectorNode(XamlIlSelectorNode previous, @@ -288,4 +294,44 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers && m.Parameters[2].Equals(context.Configuration.WellKnownTypes.Object)); } } + + class XamlIlOrSelectorNode : XamlIlSelectorNode + { + List _selectors = new List(); + public XamlIlOrSelectorNode(IXamlIlLineInfo info, IXamlIlType selectorType) : base(null, info, selectorType) + { + } + + public void Add(XamlIlSelectorNode node) + { + _selectors.Add(node); + } + + //TODO: actually find the type + public override IXamlIlType TargetType => _selectors.FirstOrDefault()?.TargetType; + protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen) + { + if (_selectors.Count == 0) + throw new XamlIlLoadException("Invalid selector count", this); + if (_selectors.Count == 1) + { + _selectors[0].Emit(context, codeGen); + return; + } + var listType = context.Configuration.TypeSystem.FindType("System.Collections.Generic.List`1") + .MakeGenericType(base.Type.GetClrType()); + var add = listType.FindMethod("Add", context.Configuration.WellKnownTypes.Void, false, Type.GetClrType()); + codeGen + .Newobj(listType.FindConstructor()); + foreach (var s in _selectors) + { + codeGen.Dup(); + context.Emit(s, codeGen, Type.GetClrType()); + codeGen.EmitCall(add, true); + } + + EmitCall(context, codeGen, + m => m.Name == "Or" && m.Parameters.Count == 1 && m.Parameters[0].Name.StartsWith("IReadOnlyList")); + } + } } From 29746bbed1f158251f68562687541624ce249390 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Thu, 18 Apr 2019 23:57:24 +0800 Subject: [PATCH 033/453] Add "UseRenderTransform" property for LayoutTransformControl. Wire up the style animation to use that property. --- .../LayoutTransformControl.cs | 49 +++++++++++++++++++ .../NotificationArea.xaml | 38 +++++++------- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/Avalonia.Controls/LayoutTransformControl.cs b/src/Avalonia.Controls/LayoutTransformControl.cs index 482cfc5320..07372eb714 100644 --- a/src/Avalonia.Controls/LayoutTransformControl.cs +++ b/src/Avalonia.Controls/LayoutTransformControl.cs @@ -20,6 +20,9 @@ namespace Avalonia.Controls public static readonly AvaloniaProperty LayoutTransformProperty = AvaloniaProperty.Register(nameof(LayoutTransform)); + public static readonly AvaloniaProperty UseRenderTransformProperty = + AvaloniaProperty.Register(nameof(LayoutTransform)); + static LayoutTransformControl() { ClipToBoundsProperty.OverrideDefaultValue(true); @@ -29,6 +32,7 @@ namespace Avalonia.Controls ChildProperty.Changed .AddClassHandler(x => x.OnChildChanged); + UseRenderTransformProperty.Changed.AddClassHandler(x => x.OnUseRenderTransformPropertyChanged); } /// @@ -40,6 +44,15 @@ namespace Avalonia.Controls set { SetValue(LayoutTransformProperty, value); } } + /// + /// Utilize the for layout transforms. + /// + public bool UseRenderTransform + { + get { return GetValue(UseRenderTransformProperty); } + set { SetValue(UseRenderTransformProperty, value); } + } + public IControl TransformRoot => Child; /// @@ -134,6 +147,42 @@ namespace Avalonia.Controls return transformedDesiredSize; } + IDisposable _renderTransformChangedEvent; + + private void OnUseRenderTransformPropertyChanged(AvaloniaPropertyChangedEventArgs e) + { + // HACK: In theory, this method and the UseRenderTransform shouldn't exist but + // it's hard to animate this particular control with style animations without + // PropertyPaths. + // + // So until we get that implemented, we'll stick on this not-so-good + // workaround. + + var target = e.Sender as LayoutTransformControl; + var shouldUseRenderTransform = (bool)e.NewValue; + if (target != null) + { + if (shouldUseRenderTransform) + { + _renderTransformChangedEvent = RenderTransformProperty.Changed + .Subscribe( + (x) => + { + var target2 = x.Sender as LayoutTransformControl; + if (target2 != null) + { + target2.LayoutTransform = target2.RenderTransform; + } + }); + } + else + { + _renderTransformChangedEvent?.Dispose(); + LayoutTransform = null; + } + } + } + private void OnChildChanged(AvaloniaPropertyChangedEventArgs e) { if (null != TransformRoot) diff --git a/src/Avalonia.Themes.Default/NotificationArea.xaml b/src/Avalonia.Themes.Default/NotificationArea.xaml index a6143e1a30..13adbbc0b6 100644 --- a/src/Avalonia.Themes.Default/NotificationArea.xaml +++ b/src/Avalonia.Themes.Default/NotificationArea.xaml @@ -30,20 +30,18 @@ - - - - + + + + + - + @@ -63,25 +61,27 @@ - + + "; + var xaml = ""; var loader = new AvaloniaXamlLoader(); var style = (Style)loader.Load(xaml); var setter = (Setter)(style.Setters.First()); diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs index d2247e3d02..359d2521e0 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs @@ -162,6 +162,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml [Fact] public void Non_Attached_Property_With_Attached_Property_Syntax_Throws() { + // 1) It has been allowed in AvaloniaObject.SetValue for ages + // 2) There is no way to know if AddOwner was called in compile-time + if (!AvaloniaXamlLoader.UseLegacyXamlLoader) + return; var xaml = @""; From 2b7e3db469115aac3d24ab6f4f9f8e1dc8374e3a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 22 Apr 2019 15:12:44 +0100 Subject: [PATCH 064/453] correctly set notification manager properties. --- src/Avalonia.Controls/TopLevel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index f29da746ab..732363466a 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -103,7 +103,7 @@ namespace Avalonia.Controls PlatformImpl = impl; - _localNotificationManager = new NotificationManager(); + LocalNotificationManager = new NotificationManager(); dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current; var styler = TryGetService(dependencyResolver); @@ -118,7 +118,7 @@ namespace Avalonia.Controls if(_systemNotificationManager == null) { - _systemNotificationManager = _localNotificationManager; + SystemNotificationManager = _localNotificationManager; } Renderer = impl.CreateRenderer(this); From c021bf717dc4d3d055857a3bf0f96d5f3895e1f5 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 22 Apr 2019 17:21:25 +0300 Subject: [PATCH 065/453] Disable Xamarin projects on CI --- dirs.proj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dirs.proj b/dirs.proj index 03fa51b3c4..b78b38d51d 100644 --- a/dirs.proj +++ b/dirs.proj @@ -8,6 +8,7 @@ + From 223e929ca37f64ffc6afee0f7ca0ba6a5e6b54b8 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 22 Apr 2019 18:04:02 +0300 Subject: [PATCH 066/453] Update dirs.proj --- dirs.proj | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dirs.proj b/dirs.proj index b78b38d51d..4939a158bb 100644 --- a/dirs.proj +++ b/dirs.proj @@ -8,16 +8,13 @@ - + - - ---> From 8a877edce01b9cf9d3e5b9419f2fce8023e3a066 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 22 Apr 2019 21:37:33 +0300 Subject: [PATCH 067/453] Why was it here in the first place? --- src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 610d489d34..35d34d83a8 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -92,8 +92,5 @@ - - - From 63b7815fc06b2d87e1951ab898cd6c224c9ca211 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 23 Apr 2019 08:16:30 +0300 Subject: [PATCH 068/453] Don't overwrite dll with pdb --- src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs index 97f7af86b9..61303dbbfe 100644 --- a/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs +++ b/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs @@ -41,7 +41,7 @@ namespace Avalonia.Build.Tasks { File.Copy(input, OutputPath, true); if(File.Exists(inputPdb)) - File.Copy(inputPdb, OutputPath, true); + File.Copy(inputPdb, outputPdb, true); } return true; } From d52afe7a96e732a0f12b22e64d1acf3ac2cd0eba Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 23 Apr 2019 09:48:51 +0300 Subject: [PATCH 069/453] Fixed Avalonia.Diagnostics --- build/EmbedXaml.props | 6 +++--- samples/ControlCatalog/App.xaml | 2 +- .../Avalonia.Controls.DataGrid.csproj | 2 ++ src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj | 1 + src/Avalonia.Diagnostics/DevTools.xaml | 4 +++- src/Avalonia.Diagnostics/DevTools.xaml.cs | 6 ++++++ src/Avalonia.Diagnostics/Views/EventsView.xaml | 3 ++- src/Avalonia.Diagnostics/Views/TreePageView.xaml | 4 +++- src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj | 5 +++-- 9 files changed, 24 insertions(+), 9 deletions(-) diff --git a/build/EmbedXaml.props b/build/EmbedXaml.props index 219ffb2e42..dba14521ab 100644 --- a/build/EmbedXaml.props +++ b/build/EmbedXaml.props @@ -4,8 +4,8 @@ %(Filename) - + Designer - + - \ No newline at end of file + diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index d20e0100a0..2f6d25c089 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -4,7 +4,7 @@ - + \ No newline at end of file + diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/Style2.xaml b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/Style2.xaml index fd93c4a468..04db8fd2dd 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/Style2.xaml +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/Style2.xaml @@ -1,8 +1,9 @@ \ No newline at end of file + diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithPrecompiledXaml.xaml b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithPrecompiledXaml.xaml new file mode 100644 index 0000000000..ac2f75b893 --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithPrecompiledXaml.xaml @@ -0,0 +1,6 @@ + + + diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/XamlIlBugTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs similarity index 66% rename from tests/Avalonia.Markup.Xaml.UnitTests/XamlIlBugTests.cs rename to tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs index 839cd07755..f33054e5ce 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/XamlIlBugTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs @@ -7,7 +7,7 @@ using Xunit; namespace Avalonia.Markup.Xaml.UnitTests { - public class XamlIlBugTests + public class XamlIlTests { [Fact] public void Binding_Button_IsPressed_ShouldWork() @@ -34,7 +34,24 @@ namespace Avalonia.Markup.Xaml.UnitTests Assert.Equal(1, parsed.Transitions.Count); Assert.Equal(Visual.OpacityProperty, parsed.Transitions[0].Property); } - + + [Fact] + public void Parser_Should_Override_Precompiled_Xaml() + { + var precompiled = new XamlIlClassWithPrecompiledXaml(); + Assert.Equal(Brushes.Red, precompiled.Background); + Assert.Equal(1, precompiled.Opacity); + var loaded = (XamlIlClassWithPrecompiledXaml)AvaloniaXamlLoader.Parse(@" + + +"); + Assert.Equal(loaded.Opacity, 0); + Assert.Null(loaded.Background); + + } } @@ -50,4 +67,8 @@ namespace Avalonia.Markup.Xaml.UnitTests } } + public class XamlIlClassWithPrecompiledXaml : UserControl + { + } + } From fa04a50f85675fc214b3913a1de8141f5c962431 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Mon, 29 Apr 2019 15:26:07 +0200 Subject: [PATCH 091/453] Remove non working test --- .../ApplicationTests.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs index b3ce1a3866..b7d752dfe3 100644 --- a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs @@ -143,20 +143,6 @@ namespace Avalonia.Controls.UnitTests } } - [Fact] - public void Throws_InvalidOperationException_On_Run_When_Application_Is_Already_Running() - { - using (UnitTestApplication.Start(TestServices.MockThreadingInterface)) - { - Application.Current.Startup += (s, e) => - { - Assert.Throws(() => { Application.Current.Run(); }); - }; - - Application.Current.Run(); - } - } - [Fact] public void Should_Set_ExitCode_After_Shutdown() { From ddbe82652f673f7b6bc720562d59d2937eaca5bc Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 May 2019 20:32:15 +0100 Subject: [PATCH 092/453] allow binding of notification managers --- src/Avalonia.Controls/TopLevel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 475fc5a927..55b1dbb1f6 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -52,13 +52,13 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly DirectProperty LocalNotificationManagerProperty = - AvaloniaProperty.RegisterDirect(nameof(LocalNotificationManager), o => o.LocalNotificationManager); + AvaloniaProperty.RegisterDirect(nameof(LocalNotificationManager), o => o.LocalNotificationManager, (o, v) => o.LocalNotificationManager = v); /// /// Defines the property. /// public static readonly DirectProperty SystemNotificationManagerProperty = - AvaloniaProperty.RegisterDirect(nameof(SystemNotificationManager), o => o.SystemNotificationManager); + AvaloniaProperty.RegisterDirect(nameof(SystemNotificationManager), o => o.SystemNotificationManager, (o, v) => o.SystemNotificationManager = v); private readonly IInputManager _inputManager; private readonly IAccessKeyHandler _accessKeyHandler; From c7be61a66decdeb5cc44d8b543fcd9d03fd79025 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 May 2019 20:34:04 +0100 Subject: [PATCH 093/453] children of adorner layer that are not adorning controls can arrange with all available size. --- src/Avalonia.Controls/Primitives/AdornerLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 8a724926e8..d198570909 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -64,7 +64,7 @@ namespace Avalonia.Controls.Primitives } else { - child.Arrange(new Rect(child.DesiredSize)); + child.Arrange(new Rect(finalSize)); } } From 147eb272aa156897483d3d74a7ffa9cf4336f8a4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 May 2019 20:34:15 +0100 Subject: [PATCH 094/453] notification area to fill window --- src/Avalonia.Controls/Notifications/NotificationArea.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Notifications/NotificationArea.cs b/src/Avalonia.Controls/Notifications/NotificationArea.cs index c641e09b02..81b3c8fd59 100644 --- a/src/Avalonia.Controls/Notifications/NotificationArea.cs +++ b/src/Avalonia.Controls/Notifications/NotificationArea.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Linq; using System.Threading.Tasks; @@ -39,6 +39,9 @@ namespace Avalonia.Controls.Notifications PseudoClass(PositionProperty, x => x == NotificationPosition.TopRight, ":topright"); PseudoClass(PositionProperty, x => x == NotificationPosition.BottomLeft, ":bottomleft"); PseudoClass(PositionProperty, x => x == NotificationPosition.BottomRight, ":bottomright"); + + HorizontalAlignmentProperty.OverrideDefaultValue(Layout.HorizontalAlignment.Stretch); + VerticalAlignmentProperty.OverrideDefaultValue(Layout.VerticalAlignment.Stretch); } protected override void OnTemplateApplied(TemplateAppliedEventArgs e) From f09228cc483d015bfc747d0efd22b6bb889dc7e6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 May 2019 20:34:36 +0100 Subject: [PATCH 095/453] simplify the usage of notification manager inside main window. --- .../ControlCatalog/ViewModels/MainWindowViewModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs index 7a02f5a45c..f66625ea82 100644 --- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs +++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; @@ -24,19 +24,19 @@ namespace ControlCatalog.ViewModels await Task.Delay(5000); - Application.Current.MainWindow.LocalNotificationManager.Show(new NotificationViewModel { Title = "Warning", Message = "Please save your work before closing." }); + NotificationManager.Show(new NotificationViewModel { Title = "Warning", Message = "Please save your work before closing." }); await Task.Delay(1500); - Application.Current.MainWindow.LocalNotificationManager.Show(new NotificationContent { Message = "Test2", Type = NotificationType.Error }); + NotificationManager.Show(new NotificationContent { Message = "Test2", Type = NotificationType.Error }); await Task.Delay(2000); - Application.Current.MainWindow.LocalNotificationManager.Show(new NotificationContent { Message = "Test3", Type = NotificationType.Warning }); + NotificationManager.Show(new NotificationContent { Message = "Test3", Type = NotificationType.Warning }); await Task.Delay(2500); - Application.Current.MainWindow.LocalNotificationManager.Show(new NotificationContent { Message = "Test4", Type = NotificationType.Success }); + NotificationManager.Show(new NotificationContent { Message = "Test4", Type = NotificationType.Success }); await Task.Delay(500); - Application.Current.MainWindow.LocalNotificationManager.Show("Test5"); + NotificationManager.Show("Test5"); }); } From f8f5610b8cec96c3ede86ffd4baeb9fe0c0d0f62 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 May 2019 21:58:24 +0100 Subject: [PATCH 096/453] polish notifications --- .../ViewModels/MainWindowViewModel.cs | 19 ++----- .../ViewModels/NotificationViewModel.cs | 15 ++++-- .../Views/NotificationView.xaml | 8 +-- .../Notifications/INotificationManager.cs | 2 + .../Notifications/Notification.cs | 10 ++-- .../Notifications/NotificationArea.cs | 9 ++-- .../Notifications/NotificationContent.cs | 6 +++ src/Avalonia.Controls/TopLevel.cs | 8 +-- .../NotificationArea.xaml | 51 ++++++++----------- 9 files changed, 64 insertions(+), 64 deletions(-) diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs index f66625ea82..3c9cb166e8 100644 --- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs +++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs @@ -1,12 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; -using Avalonia; using Avalonia.Controls.Notifications; using Avalonia.Diagnostics.ViewModels; using Avalonia.Threading; -using ReactiveUI; namespace ControlCatalog.ViewModels { @@ -14,26 +9,20 @@ namespace ControlCatalog.ViewModels { public MainWindowViewModel() { - this.WhenAnyValue(x => x.NotificationManager).Subscribe(x => - { - - }); - Dispatcher.UIThread.InvokeAsync(async () => { await Task.Delay(5000); - - NotificationManager.Show(new NotificationViewModel { Title = "Warning", Message = "Please save your work before closing." }); + NotificationManager.Show(new NotificationViewModel (NotificationManager) { Title = "Warning", Message = "Did you know that Avalonia now supports Notifications?" }); await Task.Delay(1500); - NotificationManager.Show(new NotificationContent { Message = "Test2", Type = NotificationType.Error }); + NotificationManager.Show(new NotificationContent { Title= "Title", Message = "Test2", Type = NotificationType.Error }); await Task.Delay(2000); - NotificationManager.Show(new NotificationContent { Message = "Test3", Type = NotificationType.Warning }); + NotificationManager.Show(new NotificationContent { Title = "Title", Message = "Test3", Type = NotificationType.Warning }); await Task.Delay(2500); - NotificationManager.Show(new NotificationContent { Message = "Test4", Type = NotificationType.Success }); + NotificationManager.Show(new NotificationContent { Title = "Title", Message = "Test4", Type = NotificationType.Success }); await Task.Delay(500); NotificationManager.Show("Test5"); diff --git a/samples/ControlCatalog/ViewModels/NotificationViewModel.cs b/samples/ControlCatalog/ViewModels/NotificationViewModel.cs index 8a82a82447..9e60700e71 100644 --- a/samples/ControlCatalog/ViewModels/NotificationViewModel.cs +++ b/samples/ControlCatalog/ViewModels/NotificationViewModel.cs @@ -7,18 +7,25 @@ namespace ControlCatalog.ViewModels { public class NotificationViewModel { - public NotificationViewModel() + public NotificationViewModel(INotificationManager manager) { - OKCommand = ReactiveCommand.Create(() => + YesCommand = ReactiveCommand.Create(() => { - Application.Current.MainWindow.LocalNotificationManager.Show("Notification Accepted"); + manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today." }); + }); + + NoCommand = ReactiveCommand.Create(() => + { + manager.Show(new NotificationContent { Title = "Avalonia Notifications", Message = "Start adding notifications to your app today. To find out more visit..." }); }); } public string Title { get; set; } public string Message { get; set; } - public ReactiveCommand OKCommand { get; } + public ReactiveCommand YesCommand { get; } + + public ReactiveCommand NoCommand { get; } } } diff --git a/samples/ControlCatalog/Views/NotificationView.xaml b/samples/ControlCatalog/Views/NotificationView.xaml index be0a613c57..9ba9badd80 100644 --- a/samples/ControlCatalog/Views/NotificationView.xaml +++ b/samples/ControlCatalog/Views/NotificationView.xaml @@ -8,10 +8,10 @@ - -