Browse Source

Merge branch 'master' into fix-textbox-exception-on-click

pull/2553/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
87d8b9f215
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .github/FUNDING.yml
  2. 1
      packages/Avalonia/Avalonia.csproj
  3. 3
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  4. 1
      src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
  5. 15
      src/Avalonia.Controls/Application.cs
  6. 1
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  7. 2
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  8. 1
      src/Avalonia.Desktop/Avalonia.Desktop.csproj
  9. 1
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  10. 17
      src/Avalonia.Styling/StyledElement.cs
  11. 5
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  12. 2
      src/Avalonia.X11/Avalonia.X11.csproj
  13. 1
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  14. 1
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  15. 24
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  16. 18
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  17. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
  18. 1
      src/Skia/Avalonia.Skia/Avalonia.Skia.csproj
  19. 1
      src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
  20. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  21. 27
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  22. 3
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  23. 31
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/DataTemplateTests.cs
  24. 6
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml
  25. 79
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
  26. 7
      tests/Avalonia.Styling.UnitTests/StyledElementTests.cs
  27. 23
      tests/Avalonia.Styling.UnitTests/StyledElementTests_NameScope.cs
  28. 46
      tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

1
.github/FUNDING.yml

@ -0,0 +1 @@
open_collective: avalonia

1
packages/Avalonia/Avalonia.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461;netcoreapp2.0</TargetFrameworks>
<PackageId>Avalonia</PackageId>
</PropertyGroup>
<ItemGroup>

3
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -150,7 +150,8 @@ namespace Avalonia.Build.Tasks
classType = typeSystem.TargetAssembly.FindType(tn.Text);
if (classType == null)
throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false);
compiler.OverrideRootType(parsed,
new XamlIlAstClrTypeReference(classDirective, classType, false));
initialRoot.Children.Remove(classDirective);
}

1
src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Avalonia.Controls.DataGrid</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />

15
src/Avalonia.Controls/Application.cs

@ -255,16 +255,13 @@ namespace Avalonia
if (MainWindow == null)
{
Dispatcher.UIThread.Post(() =>
if (!mainWindow.IsVisible)
{
if (!mainWindow.IsVisible)
{
mainWindow.Show();
}
MainWindow = mainWindow;
});
}
mainWindow.Show();
}
MainWindow = mainWindow;
}
return Run(new CancellationTokenSource());
}

1
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -380,6 +380,7 @@ namespace Avalonia.Controls.Primitives
}
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Reset:
SelectedIndex = IndexOf(Items, SelectedItem);
break;

2
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -357,7 +357,7 @@ namespace Avalonia.Controls.Primitives
if (control.TemplatedParent == this)
{
foreach (IControl child in control.GetVisualChildren())
foreach (IControl child in control.GetLogicalChildren())
{
RegisterNames(child, nameScope);
}

1
src/Avalonia.Desktop/Avalonia.Desktop.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Avalonia.Desktop</PackageId>
</PropertyGroup>
<ItemGroup>

1
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Avalonia.ReactiveUI</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />

17
src/Avalonia.Styling/StyledElement.cs

@ -677,23 +677,6 @@ namespace Avalonia
if (Name != null)
{
_nameScope?.Register(Name, this);
var visualParent = Parent as StyledElement;
if (this is INameScope && visualParent != null)
{
// If we have e.g. a named UserControl in a window then we want that control
// to be findable by name from the Window, so register with both name scopes.
// This differs from WPF's behavior in that XAML manually registers controls
// with name scopes based on the XAML file in which the name attribute appears,
// but we're trying to avoid XAML magic in Avalonia in order to made code-
// created UIs easy. This will cause problems if a UserControl declares a name
// in its XAML and that control is included multiple times in a parent control
// (as the name will be duplicated), however at the moment I'm fine with saying
// "don't do that".
var parentNameScope = NameScope.FindNameScope(visualParent);
parentNameScope?.Register(Name, this);
}
}
}

5
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -528,6 +528,8 @@ namespace Avalonia.Rendering
oldScene?.Dispose();
}
_dirty.Clear();
if (SceneInvalidated != null)
{
var rect = new Rect();
@ -540,10 +542,9 @@ namespace Avalonia.Rendering
}
}
System.Diagnostics.Debug.WriteLine("Invalidated " + rect);
SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
}
_dirty.Clear();
}
else
{

2
src/Avalonia.X11/Avalonia.X11.csproj

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.X11</PackageId>
</PropertyGroup>
<ItemGroup>

1
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -3,6 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>$(DefineConstants);GTK3_PINVOKE</DefineConstants>
<PackageId>Avalonia.Gtk3</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />

1
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.LinuxFramebuffer</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />

24
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -112,13 +112,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
}
rootObject.Type = rootType;
OverrideRootType(parsed, rootType);
Transform(parsed);
Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource);
}
public void OverrideRootType(XamlIlDocument doc, IXamlIlAstTypeReference newType)
{
var root = (XamlIlAstObjectNode)doc.Root;
var oldType = root.Type;
if (oldType.Equals(newType))
return;
root.Type = newType;
foreach (var child in root.Children.OfType<XamlIlAstXamlPropertyValueNode>())
{
if (child.Property is XamlIlAstNamePropertyReference prop)
{
if (prop.DeclaringType.Equals(oldType))
prop.DeclaringType = newType;
if (prop.TargetType.Equals(oldType))
prop.TargetType = newType;
}
}
}
}
}

18
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Data;
using Portable.Xaml;
using Portable.Xaml.Markup;
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedParameter.Global
@ -17,19 +18,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
var resourceNodes = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents
.OfType<IResourceNode>().ToList();
return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes));
var rootObject = provider.GetService<IRootObjectProvider>().RootObject;
return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject));
}
class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider
class DeferredParentServiceProvider :
IAvaloniaXamlIlParentStackProvider,
IServiceProvider,
IRootObjectProvider
{
private readonly IServiceProvider _parentProvider;
private readonly List<IResourceNode> _parentResourceNodes;
public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes)
public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes,
object rootObject)
{
_parentProvider = parentProvider;
_parentResourceNodes = parentResourceNodes;
RootObject = rootObject;
}
public IEnumerable<object> Parents => GetParents();
@ -46,8 +52,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider))
return this;
if (serviceType == typeof(IRootObjectProvider))
return this;
return _parentProvider?.GetService(serviceType);
}
public object RootObject { get; }
}

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

@ -1 +1 @@
Subproject commit 3b3c1f93a566080d417b9782f9cc4ea67cd62344
Subproject commit 1e3ffc315401f0b2eb96a0e79b25c2fc19a80d78

1
src/Skia/Avalonia.Skia/Avalonia.Skia.csproj

@ -3,6 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Avalonia.Skia</RootNamespace>
<AssemblyName>Avalonia.Skia</AssemblyName>
<PackageId>Avalonia.Skia</PackageId>
<IncludeLinuxSkia>true</IncludeLinuxSkia>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

1
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Avalonia.Direct2D1</PackageId>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Win32\Interop\UnmanagedMethods.cs">

1
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.Win32</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />

27
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@ -341,6 +341,33 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(-1, target.SelectedIndex);
}
[Fact]
public void Moving_Selected_Item_Should_Update_Selection()
{
var items = new AvaloniaList<Item>
{
new Item(),
new Item(),
};
var target = new SelectingItemsControl
{
Items = items,
Template = Template(),
};
target.ApplyTemplate();
target.SelectedIndex = 0;
Assert.Equal(items[0], target.SelectedItem);
Assert.Equal(0, target.SelectedIndex);
items.Move(0, 1);
Assert.Equal(items[1], target.SelectedItem);
Assert.Equal(1, target.SelectedIndex);
}
[Fact]
public void Resetting_Items_Collection_Should_Clear_Selection()
{

3
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@ -32,7 +32,8 @@
<EmbeddedResource Include="Xaml\Style2.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
<AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml"/>
<AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml" />
<AvaloniaResource Include="Xaml\XamlIlClassWithCustomProperty.xaml" />
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
</Project>

31
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/DataTemplateTests.cs

@ -38,6 +38,37 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
}
[Fact]
public void DataTemplate_Can_Contain_Named_UserControl()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:sys='clr-namespace:System;assembly=mscorlib'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ItemsControl Name='itemsControl' Items='{Binding}'>
<ItemsControl.ItemTemplate>
<DataTemplate>
<UserControl Name='foo'/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var itemsControl = window.FindControl<ItemsControl>("itemsControl");
window.DataContext = new[] { "item1", "item2" };
window.ApplyTemplate();
itemsControl.ApplyTemplate();
itemsControl.Presenter.ApplyTemplate();
Assert.Equal(2, itemsControl.Presenter.Panel.Children.Count);
}
}
[Fact]
public void Can_Set_DataContext_In_DataTemplate()
{

6
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml

@ -0,0 +1,6 @@
<UserControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
Test="123">
</UserControl>

79
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@ -5,8 +5,12 @@ using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using JetBrains.Annotations;
@ -117,6 +121,81 @@ namespace Avalonia.Markup.Xaml.UnitTests
Assert.Equal(Brushes.Red.Color, ((ISolidColorBrush)canvas.Background).Color);
}
}
[Fact]
public void Event_Handlers_Should_Work_For_Templates()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var w =new XamlIlBugTestsEventHandlerCodeBehind();
w.ApplyTemplate();
w.Show();
Dispatcher.UIThread.RunJobs();
var itemsPresenter = ((ItemsControl)w.Content).GetVisualChildren().FirstOrDefault();
var item = itemsPresenter
.GetVisualChildren().First()
.GetVisualChildren().First()
.GetVisualChildren().First();
((Control)item).RaiseEvent(new PointerPressedEventArgs {ClickCount = 20});
Assert.Equal(20, w.Args.ClickCount);
}
}
[Fact]
public void Custom_Properties_Should_Work_With_XClass()
{
var precompiled = new XamlIlClassWithCustomProperty();
Assert.Equal("123", precompiled.Test);
var loaded = (XamlIlClassWithCustomProperty)AvaloniaXamlLoader.Parse(@"
<UserControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
Test='321'>
</UserControl>");
Assert.Equal("321", loaded.Test);
}
}
public class XamlIlBugTestsEventHandlerCodeBehind : Window
{
public PointerPressedEventArgs Args;
public void HandlePointerPressed(object sender, PointerPressedEventArgs args)
{
Args = args;
}
public XamlIlBugTestsEventHandlerCodeBehind()
{
new AvaloniaXamlLoader().Load(@"
<Window x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlBugTestsEventHandlerCodeBehind'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns='https://github.com/avaloniaui'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests;assembly=Avalonia.Markup.Xaml.UnitTests'
>
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button PointerPressed='HandlePointerPressed' Content='{Binding .}' />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
", typeof(XamlIlBugTestsEventHandlerCodeBehind).Assembly, this);
((ItemsControl)Content).Items = new[] {"123"};
}
}
public class XamlIlClassWithCustomProperty : UserControl
{
public string Test { get; set; }
public XamlIlClassWithCustomProperty()
{
AvaloniaXamlLoader.Load(this);
}
}
public class XamlIlBugTestsBrushToColorConverter : IMultiValueConverter

7
tests/Avalonia.Styling.UnitTests/StyledElementTests.cs

@ -273,13 +273,10 @@ namespace Avalonia.Styling.UnitTests
var root = new TestRoot();
var child = new Border();
((ISupportInitialize)child).BeginInit();
child.BeginInit();
root.Child = child;
child.Name = "foo";
Assert.Null(root.FindControl<Border>("foo"));
((ISupportInitialize)child).EndInit();
Assert.Same(root.FindControl<Border>("foo"), child);
child.EndInit();
}
}

23
tests/Avalonia.Styling.UnitTests/StyledElementTests_NameScope.cs

@ -1,11 +1,6 @@
// 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 Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Xunit;
@ -70,23 +65,5 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(NameScope.GetNameScope((StyledElement)root.Presenter).Find("foo"));
}
[Fact]
public void Control_That_Is_NameScope_Should_Register_With_Parent_NameScope()
{
UserControl userControl;
var root = new TestTemplatedRoot
{
Content = userControl = new UserControl
{
Name = "foo",
}
};
root.ApplyTemplate();
Assert.Same(userControl, root.FindControl<UserControl>("foo"));
Assert.Same(userControl, userControl.FindControl<UserControl>("foo"));
}
}
}

46
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

@ -325,6 +325,52 @@ namespace Avalonia.Visuals.UnitTests.Rendering
context.Verify(x => x.DrawImage(borderLayer, 0.5, It.IsAny<Rect>(), It.IsAny<Rect>(), BitmapInterpolationMode.Default));
}
[Fact]
public void Can_Dirty_Control_In_SceneInvalidated()
{
Border border1;
Border border2;
var root = new TestRoot
{
Width = 100,
Height = 100,
Child = new StackPanel
{
Children =
{
(border1 = new Border
{
Background = Brushes.Red,
Child = new Canvas(),
}),
(border2 = new Border
{
Background = Brushes.Red,
Child = new Canvas(),
}),
}
}
};
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
var target = CreateTargetAndRunFrame(root);
var invalidated = false;
target.SceneInvalidated += (s, e) =>
{
invalidated = true;
target.AddDirty(border2);
};
target.AddDirty(border1);
target.Paint(new Rect(root.DesiredSize));
Assert.True(invalidated);
Assert.True(((IRenderLoopTask)target).NeedsUpdate);
}
private DeferredRenderer CreateTargetAndRunFrame(
TestRoot root,
Mock<IRenderTimer> timer = null,

Loading…
Cancel
Save