committed by
GitHub
158 changed files with 3554 additions and 2792 deletions
@ -0,0 +1,15 @@ |
|||||
|
// 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.Metadata |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the ambient class/property
|
||||
|
/// </summary>
|
||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, Inherited = true)] |
||||
|
public class AmbientAttribute : Attribute |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// 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.Metadata |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the property that contains the object's content in markup.
|
||||
|
/// </summary>
|
||||
|
[AttributeUsage(AttributeTargets.Property)] |
||||
|
public class TemplateContentAttribute : Attribute |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
using System; |
||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Avalonia.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Holds resources for a <see cref="Style"/>.
|
||||
|
/// </summary>
|
||||
|
public class StyleResources : IDictionary<string, object>, IDictionary |
||||
|
{ |
||||
|
private Dictionary<string, object> _inner = new Dictionary<string, object>(); |
||||
|
|
||||
|
public object this[string key] |
||||
|
{ |
||||
|
get { return _inner[key]; } |
||||
|
set { _inner[key] = value; } |
||||
|
} |
||||
|
|
||||
|
public int Count => _inner.Count; |
||||
|
|
||||
|
ICollection<string> IDictionary<string, object>.Keys => _inner.Keys; |
||||
|
|
||||
|
ICollection<object> IDictionary<string, object>.Values => _inner.Values; |
||||
|
|
||||
|
bool ICollection<KeyValuePair<string, object>>.IsReadOnly => false; |
||||
|
|
||||
|
object IDictionary.this[object key] |
||||
|
{ |
||||
|
get { return ((IDictionary)_inner)[key]; } |
||||
|
set { ((IDictionary)_inner)[key] = value; } |
||||
|
} |
||||
|
|
||||
|
ICollection IDictionary.Keys => _inner.Keys; |
||||
|
|
||||
|
ICollection IDictionary.Values => _inner.Values; |
||||
|
|
||||
|
bool ICollection.IsSynchronized => false; |
||||
|
|
||||
|
object ICollection.SyncRoot => ((IDictionary)_inner).SyncRoot; |
||||
|
|
||||
|
bool IDictionary.IsFixedSize => false; |
||||
|
|
||||
|
bool IDictionary.IsReadOnly => false; |
||||
|
|
||||
|
public void Add(string key, object value) => _inner.Add(key, value); |
||||
|
|
||||
|
public void Clear() => _inner.Clear(); |
||||
|
|
||||
|
public bool ContainsKey(string key) => _inner.ContainsKey(key); |
||||
|
|
||||
|
public bool Remove(string key) => _inner.Remove(key); |
||||
|
|
||||
|
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _inner.GetEnumerator(); |
||||
|
|
||||
|
public bool TryGetValue(string key, out object value) => _inner.TryGetValue(key, out value); |
||||
|
|
||||
|
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) |
||||
|
{ |
||||
|
return ((IDictionary<string, object>)_inner).Contains(item); |
||||
|
} |
||||
|
|
||||
|
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) |
||||
|
{ |
||||
|
((IDictionary<string, object>)_inner).Add(item); |
||||
|
} |
||||
|
|
||||
|
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) |
||||
|
{ |
||||
|
((IDictionary<string, object>)_inner).CopyTo(array, arrayIndex); |
||||
|
} |
||||
|
|
||||
|
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) |
||||
|
{ |
||||
|
return ((IDictionary<string, object>)_inner).Remove(item); |
||||
|
} |
||||
|
|
||||
|
void ICollection.CopyTo(Array array, int index) => ((IDictionary)_inner).CopyTo(array, index); |
||||
|
|
||||
|
IEnumerator IEnumerable.GetEnumerator() => _inner.GetEnumerator(); |
||||
|
|
||||
|
IDictionaryEnumerator IDictionary.GetEnumerator() => ((IDictionary)_inner).GetEnumerator(); |
||||
|
|
||||
|
void IDictionary.Add(object key, object value) => ((IDictionary)_inner).Add(key, value); |
||||
|
|
||||
|
bool IDictionary.Contains(object key) => ((IDictionary)_inner).Contains(key); |
||||
|
|
||||
|
void IDictionary.Remove(object key) => ((IDictionary)_inner).Remove(key); |
||||
|
} |
||||
|
} |
||||
@ -1,225 +1,11 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
namespace Avalonia.Markup.Xaml |
||||
// 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.IO; |
|
||||
using System.Reflection; |
|
||||
using System.Text; |
|
||||
using OmniXaml; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Markup.Xaml.Context; |
|
||||
using Avalonia.Markup.Xaml.Styling; |
|
||||
using OmniXaml.ObjectAssembler; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Markup.Xaml.Data; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml |
|
||||
{ |
{ |
||||
/// <summary>
|
public class AvaloniaXamlLoader : AvaloniaXamlLoaderPortableXaml |
||||
/// Loads XAML for a avalonia application.
|
|
||||
/// </summary>
|
|
||||
public class AvaloniaXamlLoader : XmlLoader |
|
||||
{ |
{ |
||||
private static AvaloniaParserFactory s_parserFactory; |
public static object Parse(string xaml) |
||||
private static IInstanceLifeCycleListener s_lifeCycleListener = new AvaloniaLifeCycleListener(); |
=> new AvaloniaXamlLoader().Load(xaml); |
||||
private static Stack<Uri> s_uriStack = new Stack<Uri>(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
|
||||
/// </summary>
|
|
||||
public AvaloniaXamlLoader() |
|
||||
: this(GetParserFactory()) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="xamlParserFactory">The parser factory to use.</param>
|
|
||||
public AvaloniaXamlLoader(IParserFactory xamlParserFactory) |
|
||||
: base(xamlParserFactory) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the URI of the XAML file currently being loaded.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// TODO: Making this internal for now as I'm not sure that this is the correct
|
|
||||
/// thing to do, but its needed by <see cref="StyleInclude"/> to get the URL of
|
|
||||
/// the currently loading XAML file, as we can't use the OmniXAML parsing context
|
|
||||
/// there. Maybe we need a way to inject OmniXAML context into the objects its
|
|
||||
/// constructing?
|
|
||||
/// </remarks>
|
|
||||
internal static Uri UriContext => s_uriStack.Count > 0 ? s_uriStack.Peek() : null; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads the XAML into a Avalonia component.
|
|
||||
/// </summary>
|
|
||||
/// <param name="obj">The object to load the XAML into.</param>
|
|
||||
public static void Load(object obj) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(obj != null); |
|
||||
|
|
||||
var loader = new AvaloniaXamlLoader(); |
|
||||
loader.Load(obj.GetType(), obj); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads the XAML for a type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="type">The type.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Type type, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(type != null); |
|
||||
|
|
||||
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
|
|
||||
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
|
|
||||
// Ideally we'd be able to use .xaml everywhere
|
|
||||
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
|
||||
|
|
||||
if (assetLocator == null) |
|
||||
{ |
|
||||
throw new InvalidOperationException( |
|
||||
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
|
||||
} |
|
||||
|
|
||||
foreach (var uri in GetUrisFor(type)) |
|
||||
{ |
|
||||
if (assetLocator.Exists(uri)) |
|
||||
{ |
|
||||
using (var stream = assetLocator.Open(uri)) |
|
||||
{ |
|
||||
var initialize = rootInstance as ISupportInitialize; |
|
||||
initialize?.BeginInit(); |
|
||||
return Load(stream, rootInstance, uri); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw new FileNotFoundException("Unable to find view for " + type.FullName); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a URI.
|
|
||||
/// </summary>
|
|
||||
/// <param name="uri">The URI of the XAML file.</param>
|
|
||||
/// <param name="baseUri">
|
|
||||
/// A base URI to use if <paramref name="uri"/> is relative.
|
|
||||
/// </param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(uri != null); |
|
||||
|
|
||||
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
|
||||
|
|
||||
if (assetLocator == null) |
|
||||
{ |
|
||||
throw new InvalidOperationException( |
|
||||
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
|
||||
} |
|
||||
|
|
||||
using (var stream = assetLocator.Open(uri, baseUri)) |
|
||||
{ |
|
||||
return Load(stream, rootInstance, uri); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a string.
|
|
||||
/// </summary>
|
|
||||
/// <param name="xaml">The string containing the XAML.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(string xaml, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(xaml != null); |
|
||||
|
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml))) |
|
||||
{ |
|
||||
return Load(stream, rootInstance); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a stream.
|
|
||||
/// </summary>
|
|
||||
/// <param name="stream">The stream containing the XAML.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <param name="uri">The URI of the XAML</param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Stream stream, object rootInstance = null, Uri uri = null) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
if (uri != null) |
|
||||
{ |
|
||||
s_uriStack.Push(uri); |
|
||||
} |
|
||||
|
|
||||
var result = base.Load(stream, new Settings |
|
||||
{ |
|
||||
RootInstance = rootInstance, |
|
||||
InstanceLifeCycleListener = s_lifeCycleListener, |
|
||||
ParsingContext = new Dictionary<string, object> |
|
||||
{ |
|
||||
{ "Uri", uri } |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
var topLevel = result as TopLevel; |
|
||||
|
|
||||
if (topLevel != null) |
|
||||
{ |
|
||||
DelayedBinding.ApplyBindings(topLevel); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
if (uri != null) |
|
||||
{ |
|
||||
s_uriStack.Pop(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static AvaloniaParserFactory GetParserFactory() |
|
||||
{ |
|
||||
if (s_parserFactory == null) |
|
||||
{ |
|
||||
s_parserFactory = new AvaloniaParserFactory(); |
|
||||
} |
|
||||
|
|
||||
return s_parserFactory; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the URI for a type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="type">The type.</param>
|
|
||||
/// <returns>The URI.</returns>
|
|
||||
private static IEnumerable<Uri> GetUrisFor(Type type) |
|
||||
{ |
|
||||
var asm = type.GetTypeInfo().Assembly.GetName().Name; |
|
||||
var typeName = type.FullName; |
|
||||
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm); |
|
||||
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm); |
|
||||
|
|
||||
} |
public static T Parse<T>(string xaml) |
||||
|
=> (T)Parse(xaml); |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,215 @@ |
|||||
|
// 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 Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml.Data; |
||||
|
using Avalonia.Markup.Xaml.PortableXaml; |
||||
|
using Avalonia.Platform; |
||||
|
using Portable.Xaml; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Reflection; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Loads XAML for a avalonia application.
|
||||
|
/// </summary>
|
||||
|
public class AvaloniaXamlLoaderPortableXaml |
||||
|
{ |
||||
|
private readonly AvaloniaXamlSchemaContext _context = GetContext(); |
||||
|
|
||||
|
private static AvaloniaXamlSchemaContext GetContext() |
||||
|
{ |
||||
|
var result = AvaloniaLocator.Current.GetService<AvaloniaXamlSchemaContext>(); |
||||
|
|
||||
|
if (result == null) |
||||
|
{ |
||||
|
result = AvaloniaXamlSchemaContext.Create(); |
||||
|
|
||||
|
AvaloniaLocator.CurrentMutable |
||||
|
.Bind<AvaloniaXamlSchemaContext>() |
||||
|
.ToConstant(result); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
||||
|
/// </summary>
|
||||
|
public AvaloniaXamlLoaderPortableXaml() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads the XAML into a Avalonia component.
|
||||
|
/// </summary>
|
||||
|
/// <param name="obj">The object to load the XAML into.</param>
|
||||
|
public static void Load(object obj) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(obj != null); |
||||
|
|
||||
|
var loader = new AvaloniaXamlLoader(); |
||||
|
loader.Load(obj.GetType(), obj); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads the XAML for a type.
|
||||
|
/// </summary>
|
||||
|
/// <param name="type">The type.</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Type type, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(type != null); |
||||
|
|
||||
|
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
|
||||
|
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
|
||||
|
// Ideally we'd be able to use .xaml everywhere
|
||||
|
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
||||
|
|
||||
|
if (assetLocator == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException( |
||||
|
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
||||
|
} |
||||
|
|
||||
|
foreach (var uri in GetUrisFor(type)) |
||||
|
{ |
||||
|
if (assetLocator.Exists(uri)) |
||||
|
{ |
||||
|
using (var stream = assetLocator.Open(uri)) |
||||
|
{ |
||||
|
var initialize = rootInstance as ISupportInitialize; |
||||
|
initialize?.BeginInit(); |
||||
|
try |
||||
|
{ |
||||
|
return Load(stream, rootInstance, uri); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
initialize?.EndInit(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
throw new FileNotFoundException("Unable to find view for " + type.FullName); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a URI.
|
||||
|
/// </summary>
|
||||
|
/// <param name="uri">The URI of the XAML file.</param>
|
||||
|
/// <param name="baseUri">
|
||||
|
/// A base URI to use if <paramref name="uri"/> is relative.
|
||||
|
/// </param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(uri != null); |
||||
|
|
||||
|
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
||||
|
|
||||
|
if (assetLocator == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException( |
||||
|
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
||||
|
} |
||||
|
|
||||
|
using (var stream = assetLocator.Open(uri, baseUri)) |
||||
|
{ |
||||
|
return Load(stream, rootInstance, uri); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a string.
|
||||
|
/// </summary>
|
||||
|
/// <param name="xaml">The string containing the XAML.</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(string xaml, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(xaml != null); |
||||
|
|
||||
|
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml))) |
||||
|
{ |
||||
|
return Load(stream, rootInstance); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a stream.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The stream containing the XAML.</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <param name="uri">The URI of the XAML</param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Stream stream, object rootInstance = null, Uri uri = null) |
||||
|
{ |
||||
|
var readerSettings = new XamlXmlReaderSettings() |
||||
|
{ |
||||
|
BaseUri = uri, |
||||
|
LocalAssembly = rootInstance?.GetType().GetTypeInfo().Assembly |
||||
|
}; |
||||
|
|
||||
|
var reader = new XamlXmlReader(stream, _context, readerSettings); |
||||
|
|
||||
|
object result = LoadFromReader( |
||||
|
reader, |
||||
|
AvaloniaXamlContext.For(readerSettings, rootInstance)); |
||||
|
|
||||
|
var topLevel = result as TopLevel; |
||||
|
|
||||
|
if (topLevel != null) |
||||
|
{ |
||||
|
DelayedBinding.ApplyBindings(topLevel); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null) |
||||
|
{ |
||||
|
var writer = AvaloniaXamlObjectWriter.Create( |
||||
|
reader.SchemaContext, |
||||
|
context); |
||||
|
|
||||
|
XamlServices.Transform(reader, writer); |
||||
|
writer.ApplyAllDelayedProperties(); |
||||
|
return writer.Result; |
||||
|
} |
||||
|
|
||||
|
internal static object LoadFromReader(XamlReader reader) |
||||
|
{ |
||||
|
//return XamlServices.Load(reader);
|
||||
|
return LoadFromReader(reader, null); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the URI for a type.
|
||||
|
/// </summary>
|
||||
|
/// <param name="type">The type.</param>
|
||||
|
/// <returns>The URI.</returns>
|
||||
|
private static IEnumerable<Uri> GetUrisFor(Type type) |
||||
|
{ |
||||
|
var asm = type.GetTypeInfo().Assembly.GetName().Name; |
||||
|
var typeName = type.FullName; |
||||
|
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm); |
||||
|
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,33 +0,0 @@ |
|||||
// 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 Avalonia.Markup.Xaml.Data; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Typing; |
|
||||
using System.Reflection; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaAttachableXamlMember : AttachableMember |
|
||||
{ |
|
||||
public AvaloniaAttachableXamlMember(string name, |
|
||||
XamlType owner, |
|
||||
MethodInfo getter, |
|
||||
MethodInfo setter, |
|
||||
ITypeRepository xamlTypeRepository, |
|
||||
ITypeFeatureProvider featureProvider) |
|
||||
: base(name, getter, setter, xamlTypeRepository, featureProvider) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return "Avalonia Attachable XAML Member " + base.ToString(); |
|
||||
} |
|
||||
|
|
||||
protected override IMemberValuePlugin LookupXamlMemberValueConnector() |
|
||||
{ |
|
||||
return new AvaloniaMemberValuePlugin(this); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,58 +0,0 @@ |
|||||
// 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; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Reflection; |
|
||||
using Glass; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Builder; |
|
||||
using Avalonia.Metadata; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaContentPropertyProvider : IContentPropertyProvider |
|
||||
{ |
|
||||
private readonly Dictionary<Type, string> _values = new Dictionary<Type, string>(); |
|
||||
|
|
||||
public string GetContentPropertyName(Type type) |
|
||||
{ |
|
||||
string result; |
|
||||
|
|
||||
if (!_values.TryGetValue(type, out result)) |
|
||||
{ |
|
||||
result = LookupContentProperty(type); |
|
||||
_values[type] = result; |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
private string LookupContentProperty(Type type) |
|
||||
{ |
|
||||
var result = (from member in type.GetRuntimeProperties() |
|
||||
let att = member.GetCustomAttribute<ContentAttribute>() |
|
||||
where att != null |
|
||||
select member).FirstOrDefault(); |
|
||||
|
|
||||
return result?.Name; |
|
||||
} |
|
||||
|
|
||||
void IAdd<ContentPropertyDefinition>.Add(ContentPropertyDefinition item) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
IEnumerator IEnumerable.GetEnumerator() |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
IEnumerator<ContentPropertyDefinition> IEnumerable<ContentPropertyDefinition>.GetEnumerator() |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
// 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 OmniXaml; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaLifeCycleListener : IInstanceLifeCycleListener |
|
||||
{ |
|
||||
public void OnAfterProperties(object instance) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void OnAssociatedToParent(object instance) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void OnBegin(object instance) |
|
||||
{ |
|
||||
var isi = instance as ISupportInitialize; |
|
||||
isi?.BeginInit(); |
|
||||
} |
|
||||
|
|
||||
public void OnEnd(object instance) |
|
||||
{ |
|
||||
var isi = instance as ISupportInitialize; |
|
||||
isi?.EndInit(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,25 +0,0 @@ |
|||||
// 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 OmniXaml.TypeConversion; |
|
||||
using OmniXaml.Typing; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaMemberValuePlugin : MemberValuePlugin |
|
||||
{ |
|
||||
private readonly MutableMember _xamlMember; |
|
||||
|
|
||||
public AvaloniaMemberValuePlugin(MutableMember xamlMember) |
|
||||
: base(xamlMember) |
|
||||
{ |
|
||||
_xamlMember = xamlMember; |
|
||||
} |
|
||||
|
|
||||
public override void SetValue(object instance, object value, IValueContext valueContext) |
|
||||
{ |
|
||||
PropertyAccessor.SetValue(instance, _xamlMember, value, valueContext); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,181 +0,0 @@ |
|||||
// 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; |
|
||||
using System.Reflection; |
|
||||
using OmniXaml.Builder; |
|
||||
using OmniXaml.Typing; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Markup.Xaml.Templates; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Metadata; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Styling; |
|
||||
using Glass.Core; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaNamespaceRegistry : INamespaceRegistry |
|
||||
{ |
|
||||
private const string ClrNamespace = "clr-namespace:"; |
|
||||
private const string AvaloniaNs = "https://github.com/avaloniaui"; |
|
||||
|
|
||||
private static readonly IEnumerable<Assembly> ForcedAssemblies = new[] |
|
||||
{ |
|
||||
typeof(AvaloniaObject).GetTypeInfo().Assembly, |
|
||||
typeof(Control).GetTypeInfo().Assembly, |
|
||||
typeof(Style).GetTypeInfo().Assembly, |
|
||||
typeof(DataTemplate).GetTypeInfo().Assembly, |
|
||||
typeof(SolidColorBrush).GetTypeInfo().Assembly, |
|
||||
typeof(IValueConverter).GetTypeInfo().Assembly, |
|
||||
}; |
|
||||
|
|
||||
private List<ClrNamespace> _clrNamespaces = new List<ClrNamespace>(); |
|
||||
private List<XamlNamespace> _namespaces = new List<XamlNamespace>(); |
|
||||
private Dictionary<string, string> _prefixes = new Dictionary<string, string>(); |
|
||||
private List<Assembly> _scanned = new List<Assembly>(); |
|
||||
|
|
||||
public AvaloniaNamespaceRegistry() |
|
||||
{ |
|
||||
ScanAssemblies(ForcedAssemblies); |
|
||||
ScanNewAssemblies(); |
|
||||
RegisterPrefix(new PrefixRegistration(string.Empty, AvaloniaNs)); |
|
||||
} |
|
||||
|
|
||||
public IEnumerable<PrefixRegistration> RegisteredPrefixes => |
|
||||
_prefixes.Select(x => new PrefixRegistration(x.Key, x.Value)); |
|
||||
|
|
||||
public void AddNamespace(XamlNamespace xamlNamespace) |
|
||||
{ |
|
||||
_namespaces.Add(xamlNamespace); |
|
||||
} |
|
||||
|
|
||||
public Namespace GetNamespace(string name) |
|
||||
{ |
|
||||
Namespace result; |
|
||||
|
|
||||
if (!IsClrNamespace(name)) |
|
||||
{ |
|
||||
ScanNewAssemblies(); |
|
||||
result = _namespaces.FirstOrDefault(x => x.Name == name); |
|
||||
|
|
||||
if (result == null) |
|
||||
{ |
|
||||
result = _namespaces.FirstOrDefault(x => x.Name == name); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
var nsAndAssembly = ParseClrNameSpace(name); |
|
||||
|
|
||||
result = _clrNamespaces.FirstOrDefault(x => |
|
||||
x.Name == nsAndAssembly.Item1 && |
|
||||
x.Assembly.GetName().Name == nsAndAssembly.Item2); |
|
||||
|
|
||||
if (result == null) |
|
||||
{ |
|
||||
var clr = CreateClrNamespace(name); |
|
||||
_clrNamespaces.Add(clr); |
|
||||
result = clr; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
public Namespace GetNamespaceByPrefix(string prefix) |
|
||||
{ |
|
||||
string uri; |
|
||||
|
|
||||
if (_prefixes.TryGetValue(prefix, out uri)) |
|
||||
{ |
|
||||
return GetNamespace(uri); |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public void RegisterPrefix(PrefixRegistration prefixRegistration) |
|
||||
{ |
|
||||
_prefixes[prefixRegistration.Prefix] = prefixRegistration.Ns; |
|
||||
} |
|
||||
|
|
||||
private static bool IsClrNamespace(string ns) |
|
||||
{ |
|
||||
return ns.StartsWith(ClrNamespace); |
|
||||
} |
|
||||
|
|
||||
private static ClrNamespace CreateClrNamespace(string formattedClrString) |
|
||||
{ |
|
||||
var nsAndAssembly = ParseClrNameSpace(formattedClrString); |
|
||||
var assembly = GetAssembly(nsAndAssembly.Item2); |
|
||||
|
|
||||
return new ClrNamespace(assembly, nsAndAssembly.Item1); |
|
||||
} |
|
||||
|
|
||||
private static Tuple<string, string> ParseClrNameSpace(string clrNamespace) |
|
||||
{ |
|
||||
var startOfNamespace = clrNamespace.IndexOf(":", StringComparison.Ordinal) + 1; |
|
||||
var endOfNamespace = clrNamespace.IndexOf(";", startOfNamespace, StringComparison.Ordinal); |
|
||||
|
|
||||
if (endOfNamespace < 0) |
|
||||
{ |
|
||||
endOfNamespace = clrNamespace.Length - startOfNamespace; |
|
||||
} |
|
||||
|
|
||||
var ns = clrNamespace.Substring(startOfNamespace, endOfNamespace - startOfNamespace); |
|
||||
|
|
||||
var remainingPartStart = startOfNamespace + ns.Length + 1; |
|
||||
var remainingPartLenght = clrNamespace.Length - remainingPartStart; |
|
||||
var assemblyPart = clrNamespace.Substring(remainingPartStart, remainingPartLenght); |
|
||||
|
|
||||
return Tuple.Create(ns, assemblyPart.Dicotomize('=').Item2); |
|
||||
} |
|
||||
|
|
||||
private static Assembly GetAssembly(string assemblyName) |
|
||||
{ |
|
||||
return Assembly.Load(new AssemblyName(assemblyName)); |
|
||||
} |
|
||||
|
|
||||
private void ScanAssemblies(IEnumerable<Assembly> assemblies) |
|
||||
{ |
|
||||
foreach (var assembly in assemblies) |
|
||||
{ |
|
||||
var namespaces = assembly.GetCustomAttributes<XmlnsDefinitionAttribute>() |
|
||||
.Select(x => new { x.XmlNamespace, x.ClrNamespace }) |
|
||||
.GroupBy(x => x.XmlNamespace); |
|
||||
|
|
||||
foreach (var nsa in namespaces) |
|
||||
{ |
|
||||
var xamlNamespace = _namespaces.FirstOrDefault(x => x.Name == nsa.Key); |
|
||||
|
|
||||
if (xamlNamespace == null) |
|
||||
{ |
|
||||
xamlNamespace = new XamlNamespace(nsa.Key); |
|
||||
_namespaces.Add(xamlNamespace); |
|
||||
} |
|
||||
|
|
||||
var clrNamespaces = nsa.Select(x => x.ClrNamespace); |
|
||||
xamlNamespace.Addresses.Add(new ConfiguredAssemblyWithNamespaces(assembly, clrNamespaces)); |
|
||||
} |
|
||||
|
|
||||
_scanned.Add(assembly); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void ScanNewAssemblies() |
|
||||
{ |
|
||||
IEnumerable<Assembly> assemblies = AvaloniaLocator.Current |
|
||||
.GetService<IRuntimePlatform>() |
|
||||
?.GetLoadedAssemblies(); |
|
||||
|
|
||||
if (assemblies != null) |
|
||||
{ |
|
||||
assemblies = assemblies.Except(_scanned); |
|
||||
ScanAssemblies(assemblies); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,79 +0,0 @@ |
|||||
// 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 OmniXaml; |
|
||||
using OmniXaml.ObjectAssembler; |
|
||||
using OmniXaml.ObjectAssembler.Commands; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using Avalonia.Markup.Xaml.Templates; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Collections.ObjectModel; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaObjectAssembler : IObjectAssembler |
|
||||
{ |
|
||||
private readonly TemplateHostingObjectAssembler objectAssembler; |
|
||||
private readonly ObjectAssembler assembler; |
|
||||
|
|
||||
public AvaloniaObjectAssembler( |
|
||||
IRuntimeTypeSource typeSource, |
|
||||
ITopDownValueContext topDownValueContext, |
|
||||
Settings settings = null) |
|
||||
{ |
|
||||
var mapping = new DeferredLoaderMapping(); |
|
||||
mapping.Map<Template>(x => x.Content, new TemplateLoader()); |
|
||||
mapping.Map<ControlTemplate>(x => x.Content, new TemplateLoader()); |
|
||||
mapping.Map<DataTemplate>(x => x.Content, new TemplateLoader()); |
|
||||
mapping.Map<FocusAdornerTemplate>(x => x.Content, new TemplateLoader()); |
|
||||
mapping.Map<TreeDataTemplate>(x => x.Content, new TemplateLoader()); |
|
||||
mapping.Map<ItemsPanelTemplate>(x => x.Content, new TemplateLoader()); |
|
||||
|
|
||||
var parsingDictionary = GetDictionary(settings); |
|
||||
var valueContext = new ValueContext(typeSource, topDownValueContext, parsingDictionary); |
|
||||
assembler = new ObjectAssembler(typeSource, valueContext, settings); |
|
||||
objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public object Result => objectAssembler.Result; |
|
||||
|
|
||||
public EventHandler<XamlSetValueEventArgs> XamlSetValueHandler { get; set; } |
|
||||
|
|
||||
public IRuntimeTypeSource TypeSource => assembler.TypeSource; |
|
||||
|
|
||||
public ITopDownValueContext TopDownValueContext => assembler.TopDownValueContext; |
|
||||
|
|
||||
public IInstanceLifeCycleListener LifecycleListener |
|
||||
{ |
|
||||
get { throw new NotImplementedException(); } |
|
||||
} |
|
||||
|
|
||||
public void Process(Instruction node) |
|
||||
{ |
|
||||
objectAssembler.Process(node); |
|
||||
} |
|
||||
|
|
||||
public void OverrideInstance(object instance) |
|
||||
{ |
|
||||
objectAssembler.OverrideInstance(instance); |
|
||||
} |
|
||||
|
|
||||
private static IReadOnlyDictionary<string, object> GetDictionary(Settings settings) |
|
||||
{ |
|
||||
IReadOnlyDictionary<string, object> dict; |
|
||||
|
|
||||
if (settings != null) |
|
||||
{ |
|
||||
dict = settings.ParsingContext; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
dict = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>()); |
|
||||
} |
|
||||
|
|
||||
return dict; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,41 +0,0 @@ |
|||||
// 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 OmniXaml; |
|
||||
using OmniXaml.ObjectAssembler; |
|
||||
using OmniXaml.Parsers.Parser; |
|
||||
using OmniXaml.Parsers.ProtoParser; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaParserFactory : IParserFactory |
|
||||
{ |
|
||||
private readonly IRuntimeTypeSource runtimeTypeSource; |
|
||||
|
|
||||
public AvaloniaParserFactory() |
|
||||
: this(new TypeFactory()) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public AvaloniaParserFactory(ITypeFactory typeFactory) |
|
||||
{ |
|
||||
runtimeTypeSource = new AvaloniaRuntimeTypeSource(typeFactory); |
|
||||
} |
|
||||
|
|
||||
public IParser Create(Settings settings) |
|
||||
{ |
|
||||
var xamlInstructionParser = new OrderAwareInstructionParser(new InstructionParser(runtimeTypeSource)); |
|
||||
|
|
||||
IObjectAssembler objectAssembler = new AvaloniaObjectAssembler( |
|
||||
runtimeTypeSource, |
|
||||
new TopDownValueContext(), |
|
||||
settings); |
|
||||
var phaseParserKit = new PhaseParserKit( |
|
||||
new ProtoInstructionParser(runtimeTypeSource), |
|
||||
xamlInstructionParser, |
|
||||
objectAssembler); |
|
||||
|
|
||||
return new XmlParser(phaseParserKit); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,91 +0,0 @@ |
|||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Reflection; |
|
||||
using Collections; |
|
||||
using Controls; |
|
||||
using Controls.Primitives; |
|
||||
using Controls.Templates; |
|
||||
using Converters; |
|
||||
using Data; |
|
||||
using Glass; |
|
||||
using Input; |
|
||||
using Media; |
|
||||
using Media.Imaging; |
|
||||
using Metadata; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Builder; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using OmniXaml.Typing; |
|
||||
using Avalonia.Styling; |
|
||||
using Platform; |
|
||||
using Templates; |
|
||||
|
|
||||
public class AvaloniaRuntimeTypeSource : IRuntimeTypeSource |
|
||||
{ |
|
||||
private readonly RuntimeTypeSource inner; |
|
||||
|
|
||||
public AvaloniaRuntimeTypeSource(ITypeFactory typeFactory) |
|
||||
{ |
|
||||
var namespaceRegistry = new AvaloniaNamespaceRegistry(); |
|
||||
var featureProvider = new AvaloniaTypeFeatureProvider(); |
|
||||
var typeRepository = new AvaloniaTypeRepository(namespaceRegistry, typeFactory, featureProvider); |
|
||||
|
|
||||
inner = new RuntimeTypeSource(typeRepository, namespaceRegistry); |
|
||||
} |
|
||||
|
|
||||
public Namespace GetNamespace(string name) |
|
||||
{ |
|
||||
return inner.GetNamespace(name); |
|
||||
} |
|
||||
|
|
||||
public Namespace GetNamespaceByPrefix(string prefix) |
|
||||
{ |
|
||||
return inner.GetNamespaceByPrefix(prefix); |
|
||||
} |
|
||||
|
|
||||
public void RegisterPrefix(PrefixRegistration prefixRegistration) |
|
||||
{ |
|
||||
inner.RegisterPrefix(prefixRegistration); |
|
||||
} |
|
||||
|
|
||||
public void AddNamespace(XamlNamespace xamlNamespace) |
|
||||
{ |
|
||||
inner.AddNamespace(xamlNamespace); |
|
||||
} |
|
||||
|
|
||||
public IEnumerable<PrefixRegistration> RegisteredPrefixes => inner.RegisteredPrefixes; |
|
||||
|
|
||||
public XamlType GetByType(Type type) |
|
||||
{ |
|
||||
return inner.GetByType(type); |
|
||||
} |
|
||||
|
|
||||
public XamlType GetByQualifiedName(string qualifiedName) |
|
||||
{ |
|
||||
return inner.GetByQualifiedName(qualifiedName); |
|
||||
} |
|
||||
|
|
||||
public XamlType GetByPrefix(string prefix, string typeName) |
|
||||
{ |
|
||||
return inner.GetByPrefix(prefix, typeName); |
|
||||
} |
|
||||
|
|
||||
public XamlType GetByFullAddress(XamlTypeName xamlTypeName) |
|
||||
{ |
|
||||
return inner.GetByFullAddress(xamlTypeName); |
|
||||
} |
|
||||
|
|
||||
public Member GetMember(PropertyInfo propertyInfo) |
|
||||
{ |
|
||||
return inner.GetMember(propertyInfo); |
|
||||
} |
|
||||
|
|
||||
public AttachableMember GetAttachableMember(string name, MethodInfo getter, MethodInfo setter) |
|
||||
{ |
|
||||
return inner.GetAttachableMember(name, getter, setter); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,180 +0,0 @@ |
|||||
// 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; |
|
||||
using System.Reflection; |
|
||||
using Avalonia.Collections; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Controls.Templates; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Markup.Xaml.Converters; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
using Avalonia.Metadata; |
|
||||
using Avalonia.Styling; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Builder; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using OmniXaml.TypeConversion.BuiltInConverters; |
|
||||
using OmniXaml.Typing; |
|
||||
using OmniMetadata = OmniXaml.Typing.Metadata; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaTypeFeatureProvider : ITypeFeatureProvider |
|
||||
{ |
|
||||
private Dictionary<Type, OmniMetadata> _metadata = |
|
||||
new Dictionary<Type, OmniMetadata>(); |
|
||||
|
|
||||
private Dictionary<Type, TypeConverterRegistration> _typeConverters = |
|
||||
new Dictionary<Type, TypeConverterRegistration>(); |
|
||||
|
|
||||
public IEnumerable<TypeConverterRegistration> TypeConverters => _typeConverters.Values; |
|
||||
|
|
||||
public AvaloniaTypeFeatureProvider() |
|
||||
{ |
|
||||
RegisterTypeConverters(); |
|
||||
} |
|
||||
|
|
||||
public string GetContentPropertyName(Type type) |
|
||||
{ |
|
||||
return GetMetadata(type)?.ContentProperty; |
|
||||
} |
|
||||
|
|
||||
public OmniMetadata GetMetadata(Type type) |
|
||||
{ |
|
||||
OmniMetadata result; |
|
||||
|
|
||||
if (!_metadata.TryGetValue(type, out result)) |
|
||||
{ |
|
||||
result = LoadMetadata(type); |
|
||||
_metadata.Add(type, result); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
public ITypeConverter GetTypeConverter(Type type) |
|
||||
{ |
|
||||
TypeConverterRegistration result; |
|
||||
_typeConverters.TryGetValue(type, out result); |
|
||||
return result?.TypeConverter; |
|
||||
} |
|
||||
|
|
||||
public void RegisterMetadata(Type type, OmniMetadata metadata) |
|
||||
{ |
|
||||
_metadata.Add(type, metadata); |
|
||||
} |
|
||||
|
|
||||
public void RegisterTypeConverter(Type type, ITypeConverter converter) |
|
||||
{ |
|
||||
_typeConverters.Add(type, new TypeConverterRegistration(type, converter)); |
|
||||
} |
|
||||
|
|
||||
private static OmniMetadata LoadMetadata(Type type) |
|
||||
{ |
|
||||
return new OmniMetadata |
|
||||
{ |
|
||||
ContentProperty = GetContentProperty(type), |
|
||||
PropertyDependencies = GetPropertyDependencies(type), |
|
||||
RuntimePropertyName = type.GetRuntimeProperty("Name")?.Name, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
private static string GetContentProperty(Type type) |
|
||||
{ |
|
||||
while (type != null) |
|
||||
{ |
|
||||
var properties = type.GetTypeInfo().DeclaredProperties |
|
||||
.Where(x => x.GetCustomAttribute<ContentAttribute>() != null); |
|
||||
string result = null; |
|
||||
|
|
||||
foreach (var property in properties) |
|
||||
{ |
|
||||
if (result != null) |
|
||||
{ |
|
||||
throw new Exception($"Content property defined more than once on {type}."); |
|
||||
} |
|
||||
|
|
||||
result = property.Name; |
|
||||
} |
|
||||
|
|
||||
if (result != null) |
|
||||
{ |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
type = type.GetTypeInfo().BaseType; |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
private static DependencyRegistrations GetPropertyDependencies(Type type) |
|
||||
{ |
|
||||
var result = new List<DependencyRegistration>(); |
|
||||
|
|
||||
while (type != null) |
|
||||
{ |
|
||||
var registrations = type.GetTypeInfo().DeclaredProperties |
|
||||
.Select(x => new |
|
||||
{ |
|
||||
Property = x.Name, |
|
||||
Attributes = x.GetCustomAttributes<DependsOnAttribute>(), |
|
||||
}) |
|
||||
.Where(x => x.Attributes.Any()) |
|
||||
.SelectMany(x => x.Attributes.Select(y => new DependencyRegistration(x.Property, y.Name))); |
|
||||
|
|
||||
result.AddRange(registrations); |
|
||||
type = type.GetTypeInfo().BaseType; |
|
||||
} |
|
||||
|
|
||||
return result.Count > 0 ? new DependencyRegistrations(result) : null; |
|
||||
} |
|
||||
|
|
||||
private void RegisterTypeConverters() |
|
||||
{ |
|
||||
// HACK: For now these are hard-coded. Hopefully when the .NET Standard Platform
|
|
||||
// is available we can use the System.ComponentModel.TypeConverters so don't want to
|
|
||||
// spend time for now inventing a mechanism to register type converters if it's all
|
|
||||
// going to change.
|
|
||||
RegisterTypeConverter(typeof(string), new StringTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(int), new IntTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(long), new IntTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(short), new IntTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(double), new DoubleTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(float), new IntTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(bool), new BooleanConverter()); |
|
||||
RegisterTypeConverter(typeof(Type), new TypeTypeConverter()); |
|
||||
|
|
||||
RegisterTypeConverter(typeof(IBitmap), new BitmapTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(IBrush), new BrushTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Color), new ColorTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Classes), new ClassesTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(ColumnDefinitions), new ColumnDefinitionsTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(DateTime), new DateTimeTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Geometry), new GeometryTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(GridLength), new GridLengthTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(KeyGesture), new KeyGestureConverter()); |
|
||||
RegisterTypeConverter(typeof(AvaloniaList<double>), new AvaloniaListTypeConverter<double>()); |
|
||||
RegisterTypeConverter(typeof(IMemberSelector), new MemberSelectorTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Point), new PointTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(IList<Point>), new PointsListTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(AvaloniaProperty), new AvaloniaPropertyTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(RelativePoint), new RelativePointTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(RelativeRect), new RelativeRectTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(RowDefinitions), new RowDefinitionsTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Size), new SizeTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Selector), new SelectorTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(SolidColorBrush), new BrushTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Thickness), new ThicknessTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(TimeSpan), new TimeSpanTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Uri), new UriTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(Cursor), new CursorTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(WindowIcon), new IconTypeConverter()); |
|
||||
RegisterTypeConverter(typeof(FontWeight), new FontWeightConverter()); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,28 +0,0 @@ |
|||||
// 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 OmniXaml; |
|
||||
using OmniXaml.Typing; |
|
||||
using Glass.Core; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaTypeRepository : TypeRepository |
|
||||
{ |
|
||||
private readonly ITypeFactory _typeFactory; |
|
||||
|
|
||||
public AvaloniaTypeRepository(INamespaceRegistry xamlNamespaceRegistry, |
|
||||
ITypeFactory typeFactory, |
|
||||
ITypeFeatureProvider featureProvider) : base(xamlNamespaceRegistry, typeFactory, featureProvider) |
|
||||
{ |
|
||||
_typeFactory = typeFactory; |
|
||||
} |
|
||||
|
|
||||
public override XamlType GetByType(Type type) |
|
||||
{ |
|
||||
Guard.ThrowIfNull(type, nameof(type)); |
|
||||
return new AvaloniaXamlType(type, this, _typeFactory, FeatureProvider); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,126 +0,0 @@ |
|||||
// 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.Linq; |
|
||||
using System.Reflection; |
|
||||
using Glass; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Builder; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using OmniXaml.Typing; |
|
||||
using Avalonia.Collections; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Controls.Primitives; |
|
||||
using Avalonia.Controls.Templates; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Markup.Xaml.Converters; |
|
||||
using Avalonia.Markup.Xaml.Data; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
using Avalonia.Metadata; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Styling; |
|
||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaWiringContext : WiringContext |
|
||||
{ |
|
||||
private const string AvaloniaNs = "https://github.com/avaloniaui"; |
|
||||
|
|
||||
public AvaloniaWiringContext(ITypeFactory typeFactory) |
|
||||
: this(typeFactory, new TypeFeatureProvider(GetContentPropertyProvider(), GetConverterProvider())) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public AvaloniaWiringContext(ITypeFactory typeFactory, TypeFeatureProvider featureProvider) |
|
||||
: base(CreateTypeContext(typeFactory, featureProvider), featureProvider) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
private static ITypeContext CreateTypeContext(ITypeFactory typeFactory, TypeFeatureProvider featureProvider) |
|
||||
{ |
|
||||
var xamlNamespaceRegistry = CreateXamlNamespaceRegistry(); |
|
||||
var typeRepository = new AvaloniaTypeRepository(xamlNamespaceRegistry, typeFactory, featureProvider); |
|
||||
|
|
||||
typeRepository.RegisterMetadata(new GenericMetadata<Visual>().WithRuntimeNameProperty(d => d.Name)); |
|
||||
typeRepository.RegisterMetadata(new GenericMetadata<Setter>().WithMemberDependency(x => x.Value, x => x.Property)); |
|
||||
typeRepository.RegisterMetadata( |
|
||||
new GenericMetadata<SelectingItemsControl>() |
|
||||
.WithMemberDependency(x => x.SelectedIndex, x => x.Items) |
|
||||
.WithMemberDependency(x => x.SelectedItem, x => x.Items)); |
|
||||
|
|
||||
return new TypeContext(typeRepository, xamlNamespaceRegistry, typeFactory); |
|
||||
} |
|
||||
|
|
||||
private static XamlNamespaceRegistry CreateXamlNamespaceRegistry() |
|
||||
{ |
|
||||
var xamlNamespaceRegistry = new XamlNamespaceRegistry(); |
|
||||
|
|
||||
var forcedAssemblies = new[] |
|
||||
{ |
|
||||
typeof(Binding), |
|
||||
typeof(Control), |
|
||||
typeof(IValueConverter), |
|
||||
typeof(Style), |
|
||||
}.Select(t => t.GetTypeInfo().Assembly); |
|
||||
|
|
||||
foreach (var nsa in |
|
||||
forcedAssemblies |
|
||||
.Concat(AvaloniaLocator.Current.GetService<IPclPlatformWrapper>().GetLoadedAssemblies()) |
|
||||
.Distinct() |
|
||||
.SelectMany(asm |
|
||||
=> asm.GetCustomAttributes<XmlnsDefinitionAttribute>().Select(attr => new {asm, attr})) |
|
||||
.GroupBy(entry => entry.attr.XmlNamespace)) |
|
||||
{ |
|
||||
var def = XamlNamespace.Map(nsa.Key) |
|
||||
.With(nsa.GroupBy(x => x.asm).Select( |
|
||||
a => Route.Assembly(a.Key) |
|
||||
.WithNamespaces(a.Select(entry => entry.attr.ClrNamespace).ToList()) |
|
||||
)); |
|
||||
xamlNamespaceRegistry.AddNamespace(def); |
|
||||
} |
|
||||
xamlNamespaceRegistry.RegisterPrefix(new PrefixRegistration(string.Empty, AvaloniaNs)); |
|
||||
|
|
||||
return xamlNamespaceRegistry; |
|
||||
} |
|
||||
|
|
||||
private static ITypeConverterProvider GetConverterProvider() |
|
||||
{ |
|
||||
var typeConverterProvider = new TypeConverterProvider(); |
|
||||
var converters = new[] |
|
||||
{ |
|
||||
new TypeConverterRegistration(typeof(IBitmap), new BitmapTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Brush), new BrushTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Color), new ColorTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Classes), new ClassesTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(ColumnDefinitions), new ColumnDefinitionsTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Geometry), new GeometryTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(GridLength), new GridLengthTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(KeyGesture), new KeyGestureConverter()), |
|
||||
new TypeConverterRegistration(typeof(AvaloniaList<double>), new AvaloniaListTypeConverter<double>()), |
|
||||
new TypeConverterRegistration(typeof(IMemberSelector), new MemberSelectorTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Point), new PointTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(IList<Point>), new PointsListTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(AvaloniaProperty), new AvaloniaPropertyTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(RelativePoint), new RelativePointTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(RelativeRect), new RelativeRectTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(RowDefinitions), new RowDefinitionsTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Selector), new SelectorTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Thickness), new ThicknessTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(TimeSpan), new TimeSpanTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Uri), new UriTypeConverter()), |
|
||||
new TypeConverterRegistration(typeof(Cursor), new CursorTypeConverter()) |
|
||||
}; |
|
||||
|
|
||||
typeConverterProvider.AddAll(converters); |
|
||||
return typeConverterProvider; |
|
||||
} |
|
||||
|
|
||||
private static IContentPropertyProvider GetContentPropertyProvider() |
|
||||
{ |
|
||||
return new AvaloniaContentPropertyProvider(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
// 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 Avalonia.Markup.Xaml.Data; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Typing; |
|
||||
using System; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaXamlMember : Member |
|
||||
{ |
|
||||
public AvaloniaXamlMember(string name, |
|
||||
XamlType owner, |
|
||||
ITypeRepository xamlTypeRepository, |
|
||||
ITypeFeatureProvider featureProvider) |
|
||||
: base(name, owner, xamlTypeRepository, featureProvider) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
protected override IMemberValuePlugin LookupXamlMemberValueConnector() |
|
||||
{ |
|
||||
return new AvaloniaMemberValuePlugin(this); |
|
||||
} |
|
||||
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return "Avalonia XAML Member " + base.ToString(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,61 +0,0 @@ |
|||||
// 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.Reflection; |
|
||||
using OmniXaml; |
|
||||
using OmniXaml.Typing; |
|
||||
using Avalonia.Controls; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
public class AvaloniaXamlType : XamlType |
|
||||
{ |
|
||||
public AvaloniaXamlType(Type type, |
|
||||
ITypeRepository typeRepository, |
|
||||
ITypeFactory typeFactory, |
|
||||
ITypeFeatureProvider featureProvider) : base(type, typeRepository, typeFactory, featureProvider) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public override OmniXaml.INameScope GetNamescope(object instance) |
|
||||
{ |
|
||||
var result = instance as OmniXaml.INameScope; |
|
||||
|
|
||||
if (result == null) |
|
||||
{ |
|
||||
var control = instance as Control; |
|
||||
|
|
||||
if (control != null) |
|
||||
{ |
|
||||
var avaloniaNs = (instance as Avalonia.Controls.INameScope) ?? NameScope.GetNameScope(control); |
|
||||
|
|
||||
if (avaloniaNs != null) |
|
||||
{ |
|
||||
result = new NameScopeWrapper(avaloniaNs); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
protected override Member LookupMember(string name) |
|
||||
{ |
|
||||
return new AvaloniaXamlMember(name, this, TypeRepository, FeatureProvider); |
|
||||
} |
|
||||
|
|
||||
protected override AttachableMember LookupAttachableMember(string name) |
|
||||
{ |
|
||||
// OmniXAML seems to require a getter and setter even though we don't use them.
|
|
||||
var getter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Get" + name); |
|
||||
var setter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Set" + name); |
|
||||
return new AvaloniaAttachableXamlMember(name, this, getter, setter, TypeRepository, FeatureProvider); |
|
||||
} |
|
||||
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
return "Avalonia XAML Type " + base.ToString(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,30 +0,0 @@ |
|||||
// 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.
|
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
internal class NameScopeWrapper : OmniXaml.INameScope |
|
||||
{ |
|
||||
private readonly Avalonia.Controls.INameScope _inner; |
|
||||
|
|
||||
public NameScopeWrapper(Avalonia.Controls.INameScope inner) |
|
||||
{ |
|
||||
_inner = inner; |
|
||||
} |
|
||||
|
|
||||
public object Find(string name) |
|
||||
{ |
|
||||
return _inner.Find(name); |
|
||||
} |
|
||||
|
|
||||
public void Register(string name, object scopedElement) |
|
||||
{ |
|
||||
_inner.Register(name, scopedElement); |
|
||||
} |
|
||||
|
|
||||
public void Unregister(string name) |
|
||||
{ |
|
||||
_inner.Unregister(name); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,174 +0,0 @@ |
|||||
// 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.Linq; |
|
||||
using System.Reflection; |
|
||||
using System.Runtime.CompilerServices; |
|
||||
using OmniXaml.ObjectAssembler; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using OmniXaml.Typing; |
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Data; |
|
||||
using Avalonia.Markup.Xaml.Data; |
|
||||
using Avalonia.Styling; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Context |
|
||||
{ |
|
||||
internal static class PropertyAccessor |
|
||||
{ |
|
||||
public static void SetValue( |
|
||||
object instance, |
|
||||
MutableMember member, |
|
||||
object value, |
|
||||
IValueContext context) |
|
||||
{ |
|
||||
var avaloniaProperty = FindAvaloniaProperty(instance, member); |
|
||||
|
|
||||
if (value is IBinding) |
|
||||
{ |
|
||||
SetBinding(instance, member, avaloniaProperty, context, (IBinding)value); |
|
||||
} |
|
||||
else if (avaloniaProperty != null) |
|
||||
{ |
|
||||
((AvaloniaObject)instance).SetValue(avaloniaProperty, value); |
|
||||
} |
|
||||
else if (instance is Setter && member.Name == "Value") |
|
||||
{ |
|
||||
// TODO: Make this more generic somehow.
|
|
||||
var setter = (Setter)instance; |
|
||||
var targetType = setter.Property.PropertyType; |
|
||||
var xamlType = member.TypeRepository.GetByType(targetType); |
|
||||
var convertedValue = default(object); |
|
||||
|
|
||||
if (CommonValueConversion.TryConvert(value, xamlType, context, out convertedValue)) |
|
||||
{ |
|
||||
SetClrProperty(instance, member, convertedValue); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
SetClrProperty(instance, member, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static AvaloniaProperty FindAvaloniaProperty(object instance, MutableMember member) |
|
||||
{ |
|
||||
var registry = AvaloniaPropertyRegistry.Instance; |
|
||||
var attached = member as AvaloniaAttachableXamlMember; |
|
||||
var target = instance as AvaloniaObject; |
|
||||
|
|
||||
if (target == null) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
if (attached == null) |
|
||||
{ |
|
||||
return registry.FindRegistered(target, member.Name); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
var ownerType = attached.DeclaringType.UnderlyingType; |
|
||||
|
|
||||
RuntimeHelpers.RunClassConstructor(ownerType.TypeHandle); |
|
||||
|
|
||||
return registry.GetRegistered(target) |
|
||||
.Where(x => x.OwnerType == ownerType && x.Name == attached.Name) |
|
||||
.FirstOrDefault(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static void SetBinding( |
|
||||
object instance, |
|
||||
MutableMember member, |
|
||||
AvaloniaProperty property, |
|
||||
IValueContext context, |
|
||||
IBinding binding) |
|
||||
{ |
|
||||
if (!(AssignBinding(instance, member, binding) || |
|
||||
ApplyBinding(instance, property, context, binding))) |
|
||||
{ |
|
||||
throw new InvalidOperationException( |
|
||||
$"Cannot assign to '{member.Name}' on '{instance.GetType()}"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static void SetClrProperty(object instance, MutableMember member, object value) |
|
||||
{ |
|
||||
if (member.IsAttachable) |
|
||||
{ |
|
||||
member.Setter.Invoke(null, new[] { instance, value }); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
member.Setter.Invoke(instance, new[] { value }); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static bool AssignBinding(object instance, MutableMember member, IBinding binding) |
|
||||
{ |
|
||||
var property = instance.GetType() |
|
||||
.GetRuntimeProperties() |
|
||||
.FirstOrDefault(x => x.Name == member.Name); |
|
||||
|
|
||||
if (property?.GetCustomAttribute<AssignBindingAttribute>() != null) |
|
||||
{ |
|
||||
property.SetValue(instance, binding); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
private static bool ApplyBinding( |
|
||||
object instance, |
|
||||
AvaloniaProperty property, |
|
||||
IValueContext context, |
|
||||
IBinding binding) |
|
||||
{ |
|
||||
if (property == null) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
var control = instance as IControl; |
|
||||
|
|
||||
if (control != null) |
|
||||
{ |
|
||||
if (property != Control.DataContextProperty) |
|
||||
{ |
|
||||
DelayedBinding.Add(control, property, binding); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
control.Bind(property, binding); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
// The target is not a control, so we need to find an anchor that will let us look
|
|
||||
// up named controls and style resources. First look for the closest IControl in
|
|
||||
// the TopDownValueContext.
|
|
||||
object anchor = context.TopDownValueContext.StoredInstances |
|
||||
.Select(x => x.Instance) |
|
||||
.OfType<IControl>() |
|
||||
.LastOrDefault(); |
|
||||
|
|
||||
// If a control was not found, then try to find the highest-level style as the XAML
|
|
||||
// file could be a XAML file containing only styles.
|
|
||||
if (anchor == null) |
|
||||
{ |
|
||||
anchor = context.TopDownValueContext.StoredInstances |
|
||||
.Select(x => x.Instance) |
|
||||
.OfType<IStyle>() |
|
||||
.FirstOrDefault(); |
|
||||
} |
|
||||
|
|
||||
((IAvaloniaObject)instance).Bind(property, binding, anchor); |
|
||||
} |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,58 +0,0 @@ |
|||||
using OmniXaml.TypeConversion; |
|
||||
using System; |
|
||||
using System.Globalization; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Converters |
|
||||
{ |
|
||||
public class DateTimeTypeConverter : ITypeConverter |
|
||||
{ |
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
|
||||
{ |
|
||||
if (culture == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("culture"); |
|
||||
} |
|
||||
|
|
||||
if (value == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("value"); |
|
||||
} |
|
||||
|
|
||||
DateTimeFormatInfo dateTimeFormatInfo = (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo)); |
|
||||
DateTime d = DateTime.ParseExact(value.ToString(), dateTimeFormatInfo.ShortDatePattern, culture); |
|
||||
return d; |
|
||||
} |
|
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
if (destinationType == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("destinationType"); |
|
||||
} |
|
||||
|
|
||||
if (culture == null) |
|
||||
{ |
|
||||
throw new ArgumentNullException("culture"); |
|
||||
} |
|
||||
|
|
||||
DateTime? d = value as DateTime?; |
|
||||
|
|
||||
if (!d.HasValue || destinationType != typeof(string)) |
|
||||
{ |
|
||||
throw new NotSupportedException(); |
|
||||
} |
|
||||
DateTimeFormatInfo dateTimeFormatInfo = (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo)); |
|
||||
return d.Value.ToString(dateTimeFormatInfo.ShortDatePattern, culture); |
|
||||
} |
|
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
|
||||
{ |
|
||||
return destinationType == typeof(string); |
|
||||
} |
|
||||
|
|
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
|
||||
{ |
|
||||
return sourceType == typeof(string); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,39 +0,0 @@ |
|||||
namespace Avalonia.Markup.Xaml.Converters |
|
||||
{ |
|
||||
using Avalonia.Media; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
using System; |
|
||||
using System.Globalization; |
|
||||
|
|
||||
public class FontWeightConverter : ITypeConverter |
|
||||
{ |
|
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
|
||||
{ |
|
||||
return sourceType == typeof(string); |
|
||||
} |
|
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
|
||||
{ |
|
||||
FontWeight result; |
|
||||
|
|
||||
if (Enum.TryParse(value as string, out result)) |
|
||||
{ |
|
||||
return result; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
throw new ArgumentException("unable to convert parameter to FontWeight"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,30 +1,24 @@ |
|||||
|
// 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.Globalization; |
||||
|
using Avalonia.Media; |
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Converters |
namespace Avalonia.Markup.Xaml.Converters |
||||
{ |
{ |
||||
using System; |
using System.ComponentModel; |
||||
using System.Globalization; |
|
||||
using Media; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
|
|
||||
public class GeometryTypeConverter : ITypeConverter |
public class GeometryTypeConverter : TypeConverter |
||||
{ |
{ |
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
{ |
{ |
||||
return sourceType == typeof(string); |
return sourceType == typeof(string); |
||||
} |
} |
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
|
||||
{ |
{ |
||||
return StreamGeometry.Parse((string)value); |
return StreamGeometry.Parse((string)value); |
||||
} |
} |
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
@ -1,70 +1,55 @@ |
|||||
using System; |
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
using System.Collections.Generic; |
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
using System.Globalization; |
|
||||
using System.Linq; |
|
||||
using System.Reflection; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia.Controls; |
using Avalonia.Controls; |
||||
using Avalonia.Media.Imaging; |
using Avalonia.Media.Imaging; |
||||
using Avalonia.Platform; |
using Avalonia.Platform; |
||||
using OmniXaml.TypeConversion; |
using System; |
||||
|
using System.Globalization; |
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Converters |
namespace Avalonia.Markup.Xaml.Converters |
||||
{ |
{ |
||||
class IconTypeConverter : ITypeConverter |
using Portable.Xaml.ComponentModel; |
||||
{ |
using System.ComponentModel; |
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
|
||||
{ |
|
||||
return sourceType == typeof(string) || typeof(IBitmap).GetTypeInfo().IsAssignableFrom(sourceType.GetTypeInfo()); |
|
||||
} |
|
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
public class IconTypeConverter : TypeConverter |
||||
|
{ |
||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
{ |
{ |
||||
return false; |
return sourceType == typeof(string); |
||||
} |
} |
||||
|
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
{ |
{ |
||||
var path = value as string; |
var path = value as string; |
||||
if (path != null) |
if (path != null) |
||||
{ |
{ |
||||
return CreateIconFromPath(context, path); |
return CreateIconFromPath(context, path); |
||||
} |
} |
||||
|
|
||||
var bitmap = value as IBitmap; |
var bitmap = value as IBitmap; |
||||
if (bitmap != null) |
if (bitmap != null) |
||||
{ |
{ |
||||
return new WindowIcon(bitmap); |
return new WindowIcon(bitmap); |
||||
} |
} |
||||
|
|
||||
throw new NotSupportedException(); |
throw new NotSupportedException(); |
||||
} |
} |
||||
|
|
||||
private WindowIcon CreateIconFromPath(IValueContext context, string path) |
private WindowIcon CreateIconFromPath(ITypeDescriptorContext context, string path) |
||||
{ |
{ |
||||
var uri = new Uri(path, UriKind.RelativeOrAbsolute); |
var uri = new Uri(path, UriKind.RelativeOrAbsolute); |
||||
var baseUri = GetBaseUri(context); |
|
||||
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file"; |
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file"; |
||||
|
|
||||
switch (scheme) |
switch (scheme) |
||||
{ |
{ |
||||
case "file": |
case "file": |
||||
return new WindowIcon(path); |
return new WindowIcon(path); |
||||
|
|
||||
default: |
default: |
||||
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
||||
return new WindowIcon(assets.Open(uri, baseUri)); |
return new WindowIcon(assets.Open(uri, context.GetBaseUri())); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
private Uri GetBaseUri(IValueContext context) |
|
||||
{ |
|
||||
object result; |
|
||||
context.ParsingDictionary.TryGetValue("Uri", out result); |
|
||||
return result as Uri; |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,30 +1,24 @@ |
|||||
|
// 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; |
||||
using System.Globalization; |
using System.Globalization; |
||||
using OmniXaml.TypeConversion; |
|
||||
using Avalonia.Input; |
using Avalonia.Input; |
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Converters |
namespace Avalonia.Markup.Xaml.Converters |
||||
{ |
{ |
||||
class KeyGestureConverter : ITypeConverter |
using System.ComponentModel; |
||||
|
|
||||
|
public class KeyGestureConverter : TypeConverter |
||||
{ |
{ |
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
{ |
{ |
||||
return sourceType == typeof(string); |
return sourceType == typeof(string); |
||||
} |
} |
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
|
||||
{ |
{ |
||||
return KeyGesture.Parse((string)value); |
return KeyGesture.Parse((string)value); |
||||
} |
} |
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,49 @@ |
|||||
|
// 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 Avalonia.Styling; |
||||
|
using Portable.Xaml; |
||||
|
using Portable.Xaml.ComponentModel; |
||||
|
using System.ComponentModel; |
||||
|
using Portable.Xaml.Markup; |
||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.Converters |
||||
|
{ |
||||
|
public class SetterValueTypeConverter : TypeConverter |
||||
|
{ |
||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) |
||||
|
{ |
||||
|
return sourceType == typeof(string); |
||||
|
} |
||||
|
|
||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) |
||||
|
{ |
||||
|
object setter = context.GetService<IProvideValueTarget>().TargetObject; |
||||
|
var schemaContext = context.GetService<IXamlSchemaContextProvider>().SchemaContext; |
||||
|
|
||||
|
return ConvertSetterValue(context, schemaContext, culture, (setter as Setter), value); |
||||
|
} |
||||
|
|
||||
|
[Obsolete("TODO: try assosiate Setter.Value property with SetterValueTypeConverter, so far coouldn't make it :(")] |
||||
|
internal static object ConvertSetterValue(ITypeDescriptorContext dcontext, XamlSchemaContext context, CultureInfo info, Setter setter, object value) |
||||
|
{ |
||||
|
Type targetType = setter?.Property?.PropertyType; |
||||
|
|
||||
|
if (targetType == null) |
||||
|
{ |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
var ttConv = context.GetXamlType(targetType)?.TypeConverter?.ConverterInstance; |
||||
|
|
||||
|
if (ttConv != null) |
||||
|
{ |
||||
|
value = ttConv.ConvertFromString(dcontext, info, value as string); |
||||
|
} |
||||
|
|
||||
|
return value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,32 +0,0 @@ |
|||||
// 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.Globalization; |
|
||||
using OmniXaml.TypeConversion; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Converters |
|
||||
{ |
|
||||
public class UriTypeConverter : ITypeConverter |
|
||||
{ |
|
||||
public bool CanConvertFrom(IValueContext context, Type sourceType) |
|
||||
{ |
|
||||
return sourceType == typeof(string); |
|
||||
} |
|
||||
|
|
||||
public bool CanConvertTo(IValueContext context, Type destinationType) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public object ConvertFrom(IValueContext context, CultureInfo culture, object value) |
|
||||
{ |
|
||||
return new Uri((string)value); |
|
||||
} |
|
||||
|
|
||||
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
// 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.ComponentModel; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Data |
|
||||
{ |
|
||||
public class SourceBindingEndpoint |
|
||||
{ |
|
||||
public Type PropertyType { get; } |
|
||||
|
|
||||
public INotifyPropertyChanged Source { get; } |
|
||||
|
|
||||
public dynamic PropertyGetter { get; } |
|
||||
|
|
||||
public Delegate PropertySetter { get; } |
|
||||
|
|
||||
public SourceBindingEndpoint(INotifyPropertyChanged source, Type propertyType, dynamic propertyGetter, Delegate propertySetter) |
|
||||
{ |
|
||||
Source = source; |
|
||||
PropertyType = propertyType; |
|
||||
PropertyGetter = propertyGetter; |
|
||||
PropertySetter = propertySetter; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
// 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.
|
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.Data |
|
||||
{ |
|
||||
public class TargetBindingEndpoint |
|
||||
{ |
|
||||
public AvaloniaObject Object { get; } |
|
||||
|
|
||||
public AvaloniaProperty Property { get; } |
|
||||
|
|
||||
public TargetBindingEndpoint(AvaloniaObject obj, AvaloniaProperty property) |
|
||||
{ |
|
||||
Object = obj; |
|
||||
Property = property; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,86 +0,0 @@ |
|||||
// 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.Linq; |
|
||||
using System.Reflection; |
|
||||
using OmniXaml; |
|
||||
using Glass.Core; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard |
|
||||
{ |
|
||||
public class StaticExtension : MarkupExtension |
|
||||
{ |
|
||||
public StaticExtension() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public StaticExtension(string identifier) |
|
||||
{ |
|
||||
Identifier = identifier; |
|
||||
} |
|
||||
|
|
||||
public string Identifier { get; set; } |
|
||||
|
|
||||
public override object ProvideValue(MarkupExtensionContext markupExtensionContext) |
|
||||
{ |
|
||||
var typeRepository = markupExtensionContext.ValueContext.TypeRepository; |
|
||||
var typeAndMember = GetTypeAndMember(Identifier); |
|
||||
var prefixAndType = GetPrefixAndType(typeAndMember.Item1); |
|
||||
var xamlType = typeRepository.GetByPrefix(prefixAndType.Item1, prefixAndType.Item2); |
|
||||
return GetValue(xamlType.UnderlyingType, typeAndMember.Item2); |
|
||||
} |
|
||||
|
|
||||
private static Tuple<string, string> GetTypeAndMember(string s) |
|
||||
{ |
|
||||
var parts = s.Split('.'); |
|
||||
|
|
||||
if (parts.Length != 2) |
|
||||
{ |
|
||||
throw new ArgumentException("Static member must be in the form Type.Member."); |
|
||||
} |
|
||||
|
|
||||
return Tuple.Create(parts[0], parts[1]); |
|
||||
} |
|
||||
|
|
||||
private static Tuple<string, string> GetPrefixAndType(string s) |
|
||||
{ |
|
||||
if (s.Contains(":")) |
|
||||
{ |
|
||||
return s.Dicotomize(':'); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
return new Tuple<string, string>(string.Empty, s); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private object GetValue(Type type, string name) |
|
||||
{ |
|
||||
var t = type; |
|
||||
|
|
||||
while (t != null) |
|
||||
{ |
|
||||
var result = t.GetTypeInfo().DeclaredMembers.FirstOrDefault(x => x.Name == name); |
|
||||
|
|
||||
if (result is PropertyInfo) |
|
||||
{ |
|
||||
var property = ((PropertyInfo)result); |
|
||||
|
|
||||
if (property.GetMethod.IsStatic) |
|
||||
{ |
|
||||
return ((PropertyInfo)result).GetValue(null); |
|
||||
} |
|
||||
} |
|
||||
else if (result is FieldInfo) |
|
||||
{ |
|
||||
return ((FieldInfo)result).GetValue(null); |
|
||||
} |
|
||||
|
|
||||
t = t.GetTypeInfo().BaseType; |
|
||||
} |
|
||||
|
|
||||
throw new ArgumentException($"Static member '{type}.{name}' not found."); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
// 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 OmniXaml; |
|
||||
using OmniXaml.Attributes; |
|
||||
using OmniXaml.Typing; |
|
||||
using Glass.Core; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard |
|
||||
{ |
|
||||
[ContentProperty("TargetType")] |
|
||||
public class TypeExtension : MarkupExtension |
|
||||
{ |
|
||||
public Type Type { get; set; } |
|
||||
|
|
||||
public TypeExtension() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public TypeExtension(Type type) |
|
||||
{ |
|
||||
Type = type; |
|
||||
} |
|
||||
|
|
||||
public string TypeName { get; set; } |
|
||||
|
|
||||
private Type ResolveFromString(string type, ITypeRepository typeRepository) |
|
||||
{ |
|
||||
Guard.ThrowIfNull(type, nameof(type)); |
|
||||
|
|
||||
var split = type.Split(':'); |
|
||||
var prefix = split.Length == 1 ? split[0] : null; |
|
||||
var typeName = split.Length == 1 ? split[1] : split[0]; |
|
||||
var xamlType = typeRepository.GetByPrefix(prefix, typeName); |
|
||||
return xamlType.UnderlyingType; |
|
||||
} |
|
||||
|
|
||||
public override object ProvideValue(MarkupExtensionContext markupExtensionContext) |
|
||||
{ |
|
||||
if (Type != null) |
|
||||
{ |
|
||||
return Type; |
|
||||
} |
|
||||
|
|
||||
return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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 Avalonia.Markup.Xaml.Styling; |
||||
|
using Avalonia.Styling; |
||||
|
using Portable.Xaml; |
||||
|
using Portable.Xaml.ComponentModel; |
||||
|
using System.ComponentModel; |
||||
|
using Portable.Xaml.Markup; |
||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.MarkupExtensions |
||||
|
{ |
||||
|
[MarkupExtensionReturnType(typeof(IStyle))] |
||||
|
public class StyleIncludeExtension : MarkupExtension |
||||
|
{ |
||||
|
public StyleIncludeExtension() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override object ProvideValue(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
var tdc = (ITypeDescriptorContext)serviceProvider; |
||||
|
return new StyleInclude(tdc.GetBaseUri()) { Source = Source }; |
||||
|
} |
||||
|
|
||||
|
public Uri Source { get; set; } |
||||
|
|
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue