Beispiel #1
0
 public Expression GetValue(ComponentBuilderContext context)
 => Expression.MemberInit(
     Expression.New(typeof(MarginPadding)),
     Expression.Bind(_top, Expression.Constant(_value.Top)),
     Expression.Bind(_right, Expression.Constant(_value.Right)),
     Expression.Bind(_bottom, Expression.Constant(_value.Bottom)),
     Expression.Bind(_left, Expression.Constant(_value.Left)));
        public bool Handle(ComponentBuilderContext context, string name, YamlNode node)
        {
            if (name != "import")
            {
                return(false);
            }

            var assemblies = new List <Assembly>();

            foreach (var item in node.ToSequence())
            {
                try
                {
                    assemblies.Add(Assembly.LoadFrom(item.ToScalar().Value));
                }
                catch (Exception e)
                {
                    context.OnException(e);
                }
            }

            // append as element resolver with new assemblies
            var builder = (IYamlComponentBuilder)context.Builder;

            builder.ElementResolver = new CompositeElementResolver(assemblies.Select(a => new AssemblyElementResolver(a)).Append(builder.ElementResolver));

            return(true);
        }
 public Expression GetValue(ComponentBuilderContext context)
 => Expression.MemberInit(
     Expression.New(typeof(ColourInfo)),
     Expression.Bind(_topLeft, new SrgbProvider(_color.TopLeft).GetValue(context)),
     Expression.Bind(_topRight, new SrgbProvider(_color.TopRight).GetValue(context)),
     Expression.Bind(_bottomRight, new SrgbProvider(_color.BottomRight).GetValue(context)),
     Expression.Bind(_bottomLeft, new SrgbProvider(_color.BottomLeft).GetValue(context)));
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (!CollectionPropProvider.IsCollection(prop.Type, out _, out var itemType))
            {
                return(null);
            }

            IEnumerable <YamlNode> items;

            switch (node)
            {
            case YamlSequenceNode n:
                items = n;
                break;

            case YamlScalarNode n when string.IsNullOrEmpty(n.Value):
                items = Enumerable.Empty <YamlNode>();

                break;

            default:
                items = new[] { node };
                break;
            }

            return(new CollectionPropProvider(prop.Type, items.Select(n => ((IYamlComponentBuilder)context.Builder).PropResolver.Resolve(context, element, itemType, n))));
        }
Beispiel #5
0
 public Expression GetValue(ComponentBuilderContext context)
 => Expression.New(_ctor,
                   Expression.Constant(_font.Family, typeof(string)),
                   Expression.Constant(_font.Size, typeof(float)),
                   Expression.Constant(_font.Weight, typeof(string)),
                   Expression.Constant(_font.Italics, typeof(bool)),
                   Expression.Constant(_font.FixedWidth, typeof(bool)));
        protected override ElementBuilder Render(ComponentBuilderContext context)
        {
            var render = null as YamlNode;

            foreach (var(keyNode, valueNode) in _mapping)
            {
                try
                {
                    var key = keyNode.ToScalar().Value;

                    if (key == "render")
                    {
                        render = valueNode;
                        continue;
                    }

                    if (!PartHandler.Handle(context, key, valueNode))
                    {
                        throw new YamlComponentException($"Invalid component part '{key}'.", keyNode);
                    }
                }
                catch (Exception e)
                {
                    context.OnException(e);
                }
            }

            if (render == null)
            {
                return(null);
            }

            return(BuildElement(context, render));
        }
        // resolving a style delegate parameter
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (!IsStyleDelegate(prop.Type))
            {
                return(null);
            }

            var provider = new Provider(prop.Type);

            foreach (var(key, value) in node.ToMapping())
            {
                try
                {
                    // find member by name
                    var memberName = key.ToScalar().Value;
                    var member     = provider.FindMember(memberName);

                    // resolve member using prop provider
                    var memberProvider = member == null ? null : ((IYamlComponentBuilder)context.Builder).PropResolver.Resolve(context, null, member, value);

                    if (memberProvider == null)
                    {
                        throw new YamlComponentException($"Cannot resolve property or field '{memberName}' in element {provider.DrawableType}.", key);
                    }

                    provider.Properties[member] = memberProvider;
                }
                catch (Exception e)
                {
                    context.OnException(e);
                }
            }

            return(provider);
        }
Beispiel #8
0
        static Provider ResolveInternal(ComponentBuilderContext context, ElementBuilder element, YamlNode node)
        {
            if (element == null)
            {
                return(null);
            }

            var value = node.ToScalar().Value;

            // declare a variable for this element
            if (!context.TryDeclareVariable(element.Type, value, null, out var variable))
            {
                throw new YamlComponentException($"Variable '{value}' is already declared.", node);
            }

            // assign to this variable when element is constructed
            if (element.Assignee != null)
            {
                throw new YamlComponentException("Cannot specify multiple keys for an element.", node);
            }

            element.Assignee = variable;

            return(new Provider(value));
        }
Beispiel #9
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (prop.Type != typeof(MarginPadding))
            {
                return(null);
            }

            switch (node)
            {
            case YamlScalarNode scalar:
                return(new Provider(new MarginPadding(scalar.ToSingle())));

            case YamlSequenceNode sequence when sequence.Children.Count == 1:
                return(new Provider(new MarginPadding(sequence[0].ToSingle())));

            case YamlSequenceNode sequence when sequence.Children.Count == 4:
                return(new Provider(new MarginPadding
                {
                    Top = sequence[0].ToSingle(),
                    Right = sequence[1].ToSingle(),
                    Bottom = sequence[2].ToSingle(),
                    Left = sequence[3].ToSingle()
                }));

            case YamlMappingNode mapping:
                var value = new MarginPadding();

                foreach (var(keyNode, valueNode) in mapping)
                {
                    var key = keyNode.ToScalar().Value;

                    switch (key)
                    {
                    case "top":
                        value.Top = valueNode.ToSingle();
                        break;

                    case "right":
                        value.Right = valueNode.ToSingle();
                        break;

                    case "bottom":
                        value.Bottom = valueNode.ToSingle();
                        break;

                    case "left":
                        value.Left = valueNode.ToSingle();
                        break;

                    default:
                        throw new YamlComponentException($"Invalid margin/padding property '{key}'.", keyNode);
                    }
                }

                return(new Provider(value));

            default:
                throw new YamlComponentException("Must be a sequence containing 4 components or a mapping that specifies top-left-bottom-right margin/padding respectively.", node);
            }
        }
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (prop.Type != typeof(LocalisedString))
            {
                return(null);
            }

            return(new Provider(node.ToScalar().Value));
        }
Beispiel #11
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (prop.Type != typeof(ElementKey))
            {
                return(null);
            }

            return(ResolveInternal(context, element, node));
        }
Beispiel #12
0
        public bool Resolve(ComponentBuilderContext context, ElementBuilder element, string prop, YamlNode node)
        {
            if (prop != "key")
            {
                return(false);
            }

            return(ResolveInternal(context, element, node) != null);
        }
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (!typeof(ofElement).IsAssignableFrom(prop.Type))
            {
                return(null);
            }

            return(((IYamlComponentBuilder)context.Builder).BuildElement(context, node));
        }
Beispiel #14
0
        public bool Handle(ComponentBuilderContext context, string name, YamlNode node)
        {
            if (name != "name")
            {
                return(false);
            }

            context.Name = node.ToScalar().Value;
            return(true);
        }
        // resolving some prop that could be a property of drawable
        // the assignment gets appended to the style delegate
        public bool Resolve(ComponentBuilderContext context, ElementBuilder element, string prop, YamlNode node)
        {
            if (element == null)
            {
                return(false);
            }

            // find style delegate parameter
            var styleProps = element.Parameters.Where(p => IsStyleDelegate(p.ParameterType)).ToArray();

            if (styleProps.Length == 0)
            {
                return(false);
            }

            if (styleProps.Length != 1)
            {
                throw new YamlComponentException($"Ambiguous element style prop reference: {string.Join<ParameterInfo>(", ", styleProps)}", node);
            }

            var styleProp = styleProps[0];

            // add or create style delegate prop provider
            Provider provider;

            if (element.Props.TryGetValue(styleProp.Name, out var p) && p is Provider pp)
            {
                provider = pp;
            }

            else
            {
                element.Props[styleProp.Name] = provider = new Provider(styleProp.ParameterType);
            }

            // find member by name
            var member = provider.FindMember(prop);

            if (member == null)
            {
                return(false);
            }

            // resolve member using prop provider
            var memberProvider = ((IYamlComponentBuilder)context.Builder).PropResolver.Resolve(context, element, member, node);

            if (memberProvider == null)
            {
                throw new YamlComponentException($"Cannot resolve property or field '{prop}' in element {provider.DrawableType}.", node);
            }

            provider.Properties[member] = memberProvider;

            return(true);
        }
            public Expression GetValue(ComponentBuilderContext context)
            {
                var drawable = Expression.Parameter(DrawableType, "drawable");

                return(Expression.Lambda(
                           DelegateType,
                           Expression.Block(Properties.Select(x =>
                                                              Expression.Assign(
                                                                  Expression.MakeMemberAccess(drawable, x.Key),
                                                                  x.Value.GetValue(context)))),
                           drawable));
            }
Beispiel #17
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            var underlying = Nullable.GetUnderlyingType(prop.Type);

            if (underlying == null)
            {
                return(null);
            }

            // rerun prop resolution using unwrapped nullable type
            return(new Provider(prop.Type, ((IYamlComponentBuilder)context.Builder).PropResolver.Resolve(context, element, underlying, node)));
        }
Beispiel #18
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (!prop.Type.IsEnum)
            {
                return(null);
            }

            var value = node.ToScalar().Value;

            if (Enum.TryParse(prop.Type, value, IgnoreEnumCase, out var parsed))
            {
                return(new Provider(parsed, prop.Type));
            }

            throw new YamlComponentException($"Cannot convert '{value}' to enum {prop.Type}.", node);
        }
Beispiel #19
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (!prop.Type.IsPrimitive && prop.Type != typeof(string))
            {
                return(null);
            }

            var value = node.ToScalar().Value;

            try
            {
                return(new Provider(Convert.ChangeType(value, prop.Type, CultureInfo.InvariantCulture)));
            }
            catch (Exception e)
            {
                throw new YamlComponentException($"Cannot convert '{value}' to type {prop.Type}.", node, e);
            }
        }
        public ElementBuilder BuildElement(ComponentBuilderContext context, YamlNode node)
        {
            try
            {
                switch (node)
                {
                // element
                case YamlMappingNode mapping:
                    if (mapping.Children.Count == 0)
                    {
                        return(new ElementBuilder.Empty());
                    }

                    if (mapping.Children.Count != 1)
                    {
                        throw new YamlComponentException("Mapping must have one key that indicates element type.", mapping);
                    }

                    var(keyNode, valueNode) = mapping.Children.First();

                    var key = keyNode.ToScalar().Value;

                    // resolve type
                    var type = ElementResolver.Resolve(context, key) ?? throw new YamlComponentException($"Cannot resolve element '{key}'.", keyNode);

                    // build prop dictionary
                    var props = valueNode.ToMapping().ToDictionary(x => x.Key.ToScalar().Value, x => new YamlProp(x.Key, x.Value));

                    return(BuildElementWithProps(context, type, keyNode, props));

                // fragment
                case YamlSequenceNode sequence:
                    var elements = sequence.Select(n => BuildElement(context, n)).Where(e => !(e is ElementBuilder.Empty)).ToArray();

                    return(elements.Length switch
                    {
                        0 => new ElementBuilder.Empty(),
                        1 => elements[0],
                        _ => new FragmentBuilder(elements)
                    });

                case YamlScalarNode scalar when string.IsNullOrEmpty(scalar.Value):
                    return(new ElementBuilder.Empty());
Beispiel #21
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (prop.Type == typeof(Vector2))
            {
                return(new Provider2(ParseVector(node, 2)));
            }

            if (prop.Type == typeof(Vector3))
            {
                return(new Provider3(ParseVector(node, 3)));
            }

            if (prop.Type == typeof(Vector4))
            {
                return(new Provider4(ParseVector(node, 4)));
            }

            return(null);
        }
Beispiel #22
0
 public Expression GetValue(ComponentBuilderContext context) => Expression.Convert(Expression.Constant(_value), typeof(ElementKey));
 public Type Resolve(ComponentBuilderContext context, string name) => _types.GetValueOrDefault(name);
 public Type Resolve(ComponentBuilderContext context, string name) => _resolver?.Resolve(context, AddPrefix(name)) ?? _resolver?.Resolve(context, RemovePrefix(name));
Beispiel #25
0
        public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
        {
            if (prop.Type != typeof(FontUsage))
            {
                return(null);
            }

            switch (node)
            {
            case YamlScalarNode scalar:
                var parts = scalar.Value.Split(',');

                switch (parts.Length)
                {
                case 1:
                    return(new Provider(FontUsage.Default.With(family: parts[0])));

                case 2:
                    return(new Provider(FontUsage.Default.With(family: parts[0], size: node.ToSingle(parts[1]))));

                default: throw new YamlComponentException("Must be a scalar that indicates the font family name and an optional font size.", node);
                }

            case YamlMappingNode mapping:
                var usage = FontUsage.Default;

                foreach (var(keyNode, valueNode) in mapping)
                {
                    var key = keyNode.ToScalar().Value;

                    switch (key)
                    {
                    case "family":
                        usage = usage.With(family: valueNode.ToScalar().Value);
                        break;

                    case "weight":
                        usage = usage.With(weight: valueNode.ToScalar().Value);
                        break;

                    case "italics":
                        usage = usage.With(italics: valueNode.ToBoolean());
                        break;

                    case "size":
                        usage = usage.With(size: valueNode.ToSingle());
                        break;

                    case "fixed":
                        usage = usage.With(fixedWidth: valueNode.ToBoolean());
                        break;

                    default:
                        throw new YamlComponentException($"Invalid font property '{key}'.", keyNode);
                    }
                }

                return(new Provider(usage));

            default:
                throw new YamlComponentException("Must be a scalar or sequence.", node);
            }
        }
Beispiel #26
0
 public bool Handle(ComponentBuilderContext context, string name, YamlNode node)
 => _handlers.Any(h => h.Handle(context, name, node));
Beispiel #27
0
 public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
 => prop.GetAttributes()
 .OfType <IPropResolver>()
 .Select(r => r.Resolve(context, element, prop, node))
 .FirstOrDefault(p => p != null);
Beispiel #28
0
 public bool Resolve(ComponentBuilderContext context, ElementBuilder element, string prop, YamlNode node)
 => _resolvers.Any(r => r.Resolve(context, element, prop, node));
Beispiel #29
0
 public Expression GetValue(ComponentBuilderContext context)
 => Expression.New(_ctor,
                   Expression.Constant(_v[0]),
                   Expression.Constant(_v[1]));
Beispiel #30
0
 public IPropProvider Resolve(ComponentBuilderContext context, ElementBuilder element, PropTypeInfo prop, YamlNode node)
 => _resolvers.Select(r => r.Resolve(context, element, prop, node)).FirstOrDefault(p => p != null);