Browse Source

Merge branch 'master' into adorner-layer-clipping

pull/6235/head
Jumar Macato 5 years ago
committed by GitHub
parent
commit
998b15b12c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      native/Avalonia.Native/src/OSX/window.mm
  2. 40
      src/Avalonia.Base/Collections/AvaloniaList.cs
  3. 24
      src/Avalonia.Controls.DataGrid/Utils/ReflectionHelper.cs
  4. 20
      src/Avalonia.Controls/Primitives/Thumb.cs
  5. 28
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
  6. 104
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

36
native/Avalonia.Native/src/OSX/window.mm

@ -29,10 +29,12 @@ public:
IAvnMenu* _mainMenu;
bool _shown;
bool _inResize;
WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
{
_shown = false;
_inResize = false;
_mainMenu = nullptr;
BaseEvents = events;
_glContext = gl;
@ -277,6 +279,13 @@ public:
virtual HRESULT Resize(double x, double y) override
{
if(_inResize)
{
return S_OK;
}
_inResize = true;
START_COM_CALL;
@autoreleasepool
@ -304,13 +313,19 @@ public:
y = maxSize.height;
}
if(!_shown)
@try
{
BaseEvents->Resized(AvnSize{x,y});
if(!_shown)
{
BaseEvents->Resized(AvnSize{x,y});
}
[Window setContentSize:NSSize{x, y}];
}
@finally
{
_inResize = false;
}
[StandardContainer setFrameSize:NSSize{x,y}];
[Window setContentSize:NSSize{x, y}];
return S_OK;
}
@ -757,6 +772,7 @@ private:
}
_lastWindowState = state;
_actualWindowState = state;
WindowEvents->WindowStateChanged(state);
}
}
@ -1276,6 +1292,9 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
[_blurBehind setWantsLayer:true];
_blurBehind.hidden = true;
[_blurBehind setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[_content setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[self addSubview:_blurBehind];
[self addSubview:_content];
@ -1311,9 +1330,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_settingSize = true;
[super setFrameSize:newSize];
[_blurBehind setFrameSize:newSize];
[_content setFrameSize:newSize];
auto window = objc_cast<AvnWindow>([self window]);
// TODO get actual titlebar size
@ -1329,6 +1345,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
[_titleBarMaterial setFrame:tbar];
tbar.size.height = height < 1 ? 0 : 1;
[_titleBarUnderline setFrame:tbar];
_settingSize = false;
}
@ -2374,11 +2391,12 @@ protected:
virtual HRESULT Resize(double x, double y) override
{
START_COM_CALL;
@autoreleasepool
{
if (Window != nullptr)
{
[StandardContainer setFrameSize:NSSize{x,y}];
[Window setContentSize:NSSize{x, y}];
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))];

40
src/Avalonia.Base/Collections/AvaloniaList.cs

@ -454,6 +454,28 @@ namespace Avalonia.Collections
}
}
/// <summary>
/// Ensures that the capacity of the list is at least <see cref="capacity"/>.
/// </summary>
/// <param name="capacity">The capacity.</param>
public void EnsureCapacity(int capacity)
{
// Adapted from List<T> implementation.
var currentCapacity = _inner.Capacity;
if (currentCapacity < capacity)
{
var newCapacity = currentCapacity == 0 ? 4 : currentCapacity * 2;
if (newCapacity < capacity)
{
newCapacity = capacity;
}
_inner.Capacity = newCapacity;
}
}
/// <summary>
/// Removes an item from the collection.
/// </summary>
@ -633,24 +655,6 @@ namespace Avalonia.Collections
/// <inheritdoc/>
Delegate[] INotifyCollectionChangedDebug.GetCollectionChangedSubscribers() => _collectionChanged?.GetInvocationList();
private void EnsureCapacity(int capacity)
{
// Adapted from List<T> implementation.
var currentCapacity = _inner.Capacity;
if (currentCapacity < capacity)
{
var newCapacity = currentCapacity == 0 ? 4 : currentCapacity * 2;
if (newCapacity < capacity)
{
newCapacity = capacity;
}
_inner.Capacity = newCapacity;
}
}
/// <summary>
/// Raises the <see cref="CollectionChanged"/> event with an add action.
/// </summary>

24
src/Avalonia.Controls.DataGrid/Utils/ReflectionHelper.cs

@ -340,10 +340,30 @@ namespace Avalonia.Controls.Utils
internal static PropertyInfo GetPropertyOrIndexer(this Type type, string propertyPath, out object[] index)
{
index = null;
// Return the default value of GetProperty if the first character is not an indexer token.
if (string.IsNullOrEmpty(propertyPath) || propertyPath[0] != LeftIndexerToken)
{
// Return the default value of GetProperty if the first character is not an indexer token.
return type.GetProperty(propertyPath);
var property = type.GetProperty(propertyPath);
if (property != null)
{
return property;
}
// GetProperty does not return inherited interface properties,
// so we need to enumerate them manually.
if (type.IsInterface)
{
foreach (var typeInterface in type.GetInterfaces())
{
property = type.GetProperty(propertyPath);
if (property != null)
{
return property;
}
}
}
return null;
}
if (propertyPath.Length < 2 || propertyPath[propertyPath.Length - 1] != RightIndexerToken)

20
src/Avalonia.Controls/Primitives/Thumb.cs

@ -56,6 +56,26 @@ namespace Avalonia.Controls.Primitives
{
}
protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e)
{
if (_lastPoint.HasValue)
{
var ev = new VectorEventArgs
{
RoutedEvent = DragCompletedEvent,
Vector = _lastPoint.Value,
};
_lastPoint = null;
RaiseEvent(ev);
}
PseudoClasses.Remove(":pressed");
base.OnPointerCaptureLost(e);
}
protected override void OnPointerMoved(PointerEventArgs e)
{
if (_lastPoint.HasValue)

28
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs

@ -9,7 +9,6 @@ using XamlX.Ast;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
using XamlParseException = XamlX.XamlParseException;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
@ -21,6 +20,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (node is XamlAstObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension))
{
var convertedNode = ConvertLongFormPropertiesToBindingExpressionNode(context, binding);
var foundPath = false;
if (binding.Arguments.Count > 0 && binding.Arguments[0] is XamlAstTextNode bindingPathText)
{
@ -32,9 +32,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode);
}
binding.Arguments[0] = new ParsedBindingPathNode(bindingPathText, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
if (nodes.Count == 1 && nodes[0] is BindingExpressionGrammar.EmptyExpressionNode)
{
binding.Arguments.RemoveAt(0);
}
else
{
binding.Arguments[0] = new ParsedBindingPathNode(bindingPathText, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
foundPath = true;
}
}
else
if (!foundPath)
{
var bindingPathAssignment = binding.Children.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(v => v.Property.GetClrProperty().Name == "Path");
@ -44,12 +53,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var reader = new CharacterReader(pathValue.Text.AsSpan());
var (nodes, _) = BindingExpressionGrammar.Parse(ref reader);
if (convertedNode != null)
if (nodes.Count == 1 && nodes[0] is BindingExpressionGrammar.EmptyExpressionNode)
{
nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode);
bindingPathAssignment.Values.RemoveAt(0);
}
else
{
if (convertedNode != null)
{
nodes.Insert(nodes.TakeWhile(x => x is BindingExpressionGrammar.ITransformNode).Count(), convertedNode);
}
bindingPathAssignment.Values[0] = new ParsedBindingPathNode(pathValue, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
bindingPathAssignment.Values[0] = new ParsedBindingPathNode(pathValue, context.GetAvaloniaTypes().CompiledBindingPath, nodes);
}
}
}
}

104
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

@ -938,6 +938,110 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
}
}
[Fact]
public void SupportsEmptyPath()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'>
<TextBlock Text='{CompiledBinding}' Name='textBlock' />
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
var dataContext = new TestDataContext
{
StringProperty = "foobar"
};
window.DataContext = dataContext;
Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
}
}
[Fact]
public void SupportsEmptyPathWithStringFormat()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'>
<TextBlock Text='{CompiledBinding StringFormat=bar-\{0\}}' Name='textBlock' />
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
var dataContext = new TestDataContext
{
StringProperty = "foobar"
};
window.DataContext = dataContext;
Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
}
}
[Fact]
public void SupportsDotPath()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'>
<TextBlock Text='{CompiledBinding .}' Name='textBlock' />
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
var dataContext = new TestDataContext
{
StringProperty = "foobar"
};
window.DataContext = dataContext;
Assert.Equal(typeof(TestDataContext).FullName, textBlock.Text);
}
}
[Fact]
public void SupportsExplicitDotPathWithStringFormat()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
x:DataType='local:TestDataContext'>
<TextBlock Text='{CompiledBinding Path=., StringFormat=bar-\{0\}}' Name='textBlock' />
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var textBlock = window.FindControl<TextBlock>("textBlock");
var dataContext = new TestDataContext
{
StringProperty = "foobar"
};
window.DataContext = dataContext;
Assert.Equal("bar-" + typeof(TestDataContext).FullName, textBlock.Text);
}
}
void Throws(string type, Action cb)
{
try

Loading…
Cancel
Save