summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core.Design/AttributeTableBuilder.cs
blob: 508c6387c1686f45cf1c991161492078641f431b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
´╗┐using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Markup;
using Microsoft.Windows.Design;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Core.Design
{
	internal class AttributeTableBuilder : Microsoft.Windows.Design.Metadata.AttributeTableBuilder
	{
		public AttributeTableBuilder ()
		{
			// Turn off validation of values, which doesn't work for OnPlatform/OnIdiom
			AddCustomAttributes (typeof (AbsoluteLayout).Assembly,
				new XmlnsSupportsValidationAttribute ("http://xamarin.com/schemas/2014/forms", false));

			// Style isn't a view, make it visible
			AddCallback (typeof(Style), builder => builder.AddCustomAttributes(
				new EditorBrowsableAttribute (EditorBrowsableState.Always), 
				new System.Windows.Markup.ContentPropertyAttribute("Setters"),
				// Since the class doesn't have a public parameterless ctor, we need to provide a converter
				new System.ComponentModel.TypeConverterAttribute(typeof(StringConverter))));

			// The Setter.Value can actually come from an <OnPlatform />, so enable it as Content.
			AddCallback (typeof (Setter), builder => builder.AddCustomAttributes (
				new EditorBrowsableAttribute (EditorBrowsableState.Always), 
				new System.Windows.Markup.ContentPropertyAttribute("Value")));

			// Special case for FontSize which isn't an enum.
			var fontElements = typeof(View).Assembly.ExportedTypes.Where(t => typeof(IFontElement).IsAssignableFrom(t));
			foreach (var fontElement in fontElements) {
				AddCallback (fontElement, builder => builder.AddCustomAttributes (
					"FontSize",
					new System.ComponentModel.TypeConverterAttribute (typeof (EnumConverter<NamedSize>))));
			}

			// TODO: OnPlatform/OnIdiom
			// These two should be proper markup extensions, to follow WPF syntax for those.
			// That would allow us to turn on XAML validation, which otherwise fails.
			// NOTE: the two also need to provide a non-generic, object-based T so that 
			// the language service can find the type by its name. That class can be internal 
			// though, since its visibility in the markup is controlled by the EditorBrowsableAttribute.
			// Make OnPlatform/OnIdiom visible for intellisense, and set as markup extension. 
			AddCallback (typeof (OnPlatform<>), builder => builder.AddCustomAttributes (new Attribute[] {
				new EditorBrowsableAttribute (EditorBrowsableState.Always),
				//new System.ComponentModel.TypeConverterAttribute(typeof(AnythingConverter)),
				//new System.Windows.Markup.MarkupExtensionReturnTypeAttribute (),
			}));
			AddCallback (typeof (OnIdiom<>), builder => builder.AddCustomAttributes (new Attribute[] {
				new EditorBrowsableAttribute (EditorBrowsableState.Always), 
				//new System.ComponentModel.TypeConverterAttribute(typeof(AnythingConverter)),
				//new System.Windows.Markup.MarkupExtensionReturnTypeAttribute (),
			}));
		}
	}

	internal class AnythingConverter : System.ComponentModel.TypeConverter
	{
		public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
		{
			return true;
		}

		public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
		{
			return true;
		}

		public override bool IsValid (ITypeDescriptorContext context, object value)
		{
			return true;
		}
	}
}