This repository has been archived by the owner on May 1, 2024. It is now read-only.
/
Style.cs
99 lines (89 loc) · 2.87 KB
/
Style.cs
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Runtime.CompilerServices;
using Xamarin.Forms.Xaml;
namespace Xamarin.Forms.StyleSheets
{
sealed class Style
{
Style()
{
}
public IDictionary<string, string> Declarations { get; set; } = new Dictionary<string, string>();
Dictionary<KeyValuePair<string, string>, object> convertedValues = new Dictionary<KeyValuePair<string, string>, object>();
public static Style Parse(CssReader reader, char stopChar = '\0')
{
Style style = new Style();
string propertyName = null, propertyValue = null;
int p;
reader.SkipWhiteSpaces();
bool readingName = true;
while ((p = reader.Peek()) > 0) {
switch (unchecked((char)p)) {
case ':':
reader.Read();
readingName = false;
reader.SkipWhiteSpaces();
break;
case ';':
reader.Read();
if (!string.IsNullOrEmpty(propertyName) && !string.IsNullOrEmpty(propertyValue))
style.Declarations.Add(propertyName, propertyValue);
propertyName = propertyValue = null;
readingName = true;
reader.SkipWhiteSpaces();
break;
default:
if ((char)p == stopChar)
return style;
if (readingName) {
propertyName = reader.ReadIdent();
if (propertyName == null)
throw new Exception();
} else
propertyValue = reader.ReadUntil(stopChar, ';', ':');
break;
}
}
return style;
}
public void Apply(VisualElement styleable)
{
if (styleable == null)
throw new ArgumentNullException(nameof(styleable));
foreach (var decl in Declarations) {
var property = ((IStylable)styleable).GetProperty(decl.Key);
if (property == null)
continue;
if (string.Equals(decl.Value, "none", StringComparison.OrdinalIgnoreCase))
styleable.ClearValue(property, fromStyle: true);
else {
object value;
if (!convertedValues.TryGetValue(decl, out value))
convertedValues[decl] = (value = Convert(styleable, decl.Value, property));
styleable.SetValue(property, value, fromStyle: true);
}
}
foreach (var child in styleable.LogicalChildrenInternal) {
var ve = child as VisualElement;
if (ve == null)
continue;
Apply(ve);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static object Convert(object target, object value, BindableProperty property)
{
Func<MemberInfo> minforetriever = () => property.DeclaringType.GetRuntimeProperty(property.PropertyName) as MemberInfo
?? property.DeclaringType.GetRuntimeMethod("Get" + property.PropertyName, new[] { typeof(BindableObject) }) as MemberInfo;
var serviceProvider = new StyleSheetServiceProvider(target, property);
return value.ConvertTo(property.ReturnType, minforetriever, serviceProvider);
}
public void UnApply(IStylable styleable)
{
throw new NotImplementedException();
}
}
}