committed by
GitHub
34 changed files with 988 additions and 144 deletions
@ -1,4 +1,5 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"> |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"> |
||||
<application android:label="ControlCatalog.Android" android:icon="@drawable/Icon"></application> |
<application android:label="ControlCatalog.Android" android:icon="@drawable/Icon"></application> |
||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
||||
</manifest> |
</manifest> |
||||
|
|||||
@ -0,0 +1 @@ |
|||||
|
DOTNET_DiagnosticPorts=127.0.0.1:9000,suspend |
||||
@ -0,0 +1 @@ |
|||||
|
DOTNET_DiagnosticPorts=10.0.2.2:9001,suspend |
||||
@ -1,37 +0,0 @@ |
|||||
using System.Collections; |
|
||||
using System.Collections.Generic; |
|
||||
using Avalonia.Animation; |
|
||||
|
|
||||
#nullable enable |
|
||||
|
|
||||
namespace Avalonia.Media |
|
||||
{ |
|
||||
public class GeometryCollection : Animatable, IList<Geometry>, IReadOnlyList<Geometry> |
|
||||
{ |
|
||||
private List<Geometry> _inner; |
|
||||
|
|
||||
public GeometryCollection() => _inner = new List<Geometry>(); |
|
||||
public GeometryCollection(IEnumerable<Geometry> collection) => _inner = new List<Geometry>(collection); |
|
||||
public GeometryCollection(int capacity) => _inner = new List<Geometry>(capacity); |
|
||||
|
|
||||
public Geometry this[int index] |
|
||||
{ |
|
||||
get => _inner[index]; |
|
||||
set => _inner[index] = value; |
|
||||
} |
|
||||
|
|
||||
public int Count => _inner.Count; |
|
||||
public bool IsReadOnly => false; |
|
||||
|
|
||||
public void Add(Geometry item) => _inner.Add(item); |
|
||||
public void Clear() => _inner.Clear(); |
|
||||
public bool Contains(Geometry item) => _inner.Contains(item); |
|
||||
public void CopyTo(Geometry[] array, int arrayIndex) => _inner.CopyTo(array, arrayIndex); |
|
||||
public IEnumerator<Geometry> GetEnumerator() => _inner.GetEnumerator(); |
|
||||
public int IndexOf(Geometry item) => _inner.IndexOf(item); |
|
||||
public void Insert(int index, Geometry item) => _inner.Insert(index, item); |
|
||||
public bool Remove(Geometry item) => _inner.Remove(item); |
|
||||
public void RemoveAt(int index) => _inner.RemoveAt(index); |
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Collections; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
public sealed class DrawingCollection : AvaloniaList<Drawing> |
||||
|
{ |
||||
|
public DrawingCollection() |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
} |
||||
|
|
||||
|
public DrawingCollection(IEnumerable<Drawing> items) : base(items) |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Collections; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
public sealed class GeometryCollection : AvaloniaList<Geometry> |
||||
|
{ |
||||
|
public GeometryCollection() |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
|
||||
|
this.ForEachItem( |
||||
|
x => |
||||
|
{ |
||||
|
Parent?.Invalidate(); |
||||
|
}, |
||||
|
x => |
||||
|
{ |
||||
|
Parent?.Invalidate(); |
||||
|
}, |
||||
|
() => throw new NotSupportedException()); |
||||
|
} |
||||
|
|
||||
|
public GeometryCollection(IEnumerable<Geometry> items) : base(items) |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
|
||||
|
this.ForEachItem( |
||||
|
x => |
||||
|
{ |
||||
|
Parent?.Invalidate(); |
||||
|
}, |
||||
|
x => |
||||
|
{ |
||||
|
Parent?.Invalidate(); |
||||
|
}, |
||||
|
() => throw new NotSupportedException()); |
||||
|
} |
||||
|
|
||||
|
public GeometryGroup? Parent { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Metadata; |
||||
|
|
||||
|
namespace Avalonia.Controls.Templates; |
||||
|
|
||||
|
public interface ITypedDataTemplate : IDataTemplate |
||||
|
{ |
||||
|
[DataType] |
||||
|
Type? DataType { get; } |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using XamlX; |
||||
|
using XamlX.Ast; |
||||
|
using XamlX.Transform; |
||||
|
using XamlX.Transform.Transformers; |
||||
|
using XamlX.TypeSystem; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers |
||||
|
{ |
||||
|
internal class XDataTypeTransformer : IXamlAstTransformer |
||||
|
{ |
||||
|
private const string DataTypePropertyName = "DataType"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts x:DataType directives to regular DataType assignments if property with Avalonia.Metadata.DataTypeAttribute exists.
|
||||
|
/// </summary>
|
||||
|
/// <returns></returns>
|
||||
|
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) |
||||
|
{ |
||||
|
if (node is XamlAstObjectNode on) |
||||
|
{ |
||||
|
for (var c = 0; c < on.Children.Count; c++) |
||||
|
{ |
||||
|
var ch = on.Children[c]; |
||||
|
if (ch is XamlAstXmlDirective { Namespace: XamlNamespaces.Xaml2006, Name: DataTypePropertyName } d) |
||||
|
{ |
||||
|
if (on.Children.OfType<XamlAstXamlPropertyValueNode>() |
||||
|
.Any(p => ((XamlAstNamePropertyReference)p.Property)?.Name == DataTypePropertyName)) |
||||
|
{ |
||||
|
// Break iteration if any DataType property was already set by user code.
|
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
var templateDataTypeAttribute = context.GetAvaloniaTypes().DataTypeAttribute; |
||||
|
|
||||
|
var clrType = (on.Type as XamlAstClrTypeReference)?.Type; |
||||
|
if (clrType is null) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
// Technically it's possible to map "x:DataType" to a property with [DataType] attribute regardless of its name,
|
||||
|
// but we go explicitly strict here and check the name as well.
|
||||
|
var (declaringType, dataTypeProperty) = GetAllProperties(clrType) |
||||
|
.FirstOrDefault(t => t.property.Name == DataTypePropertyName && t.property.CustomAttributes |
||||
|
.Any(a => a.Type == templateDataTypeAttribute)); |
||||
|
|
||||
|
if (dataTypeProperty is not null) |
||||
|
{ |
||||
|
on.Children[c] = new XamlAstXamlPropertyValueNode(d, |
||||
|
new XamlAstNamePropertyReference(d, |
||||
|
new XamlAstClrTypeReference(ch, declaringType, false), dataTypeProperty.Name, |
||||
|
on.Type), |
||||
|
d.Values); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
private static IEnumerable<(IXamlType declaringType, IXamlProperty property)> GetAllProperties(IXamlType t) |
||||
|
{ |
||||
|
foreach (var p in t.Properties) |
||||
|
yield return (t, p); |
||||
|
if(t.BaseType!=null) |
||||
|
foreach (var tuple in GetAllProperties(t.BaseType)) |
||||
|
yield return tuple; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Loading…
Reference in new issue