//--------------------------------------------------------------------------------------
        /// <summary>
        /// HydrateLayout - Take a layout item and turn it into a VarmintWidget
        /// </summary>
        //--------------------------------------------------------------------------------------
        public static VarmintWidget HydrateLayout(IVarmintWidgetInjector injector, LayoutItem widgetLayout, Dictionary <string, LayoutItem> controlLibrary)
        {
            VarmintWidget output = null;

            Action <LayoutItem> applyLayout = (layout) =>
            {
                foreach (var name in layout.Settings.Keys)
                {
                    switch (name)
                    {
                    case "Style":
                    case "ApplyTo":
                        output.SetValue(name, layout.Settings[name], true);
                        break;

                    default:
                        output.AddSetting(name, layout.Settings[name]);
                        break;
                    }
                }
                foreach (var childItem in layout.Children)
                {
                    if (childItem.VwmlTag.Contains("."))
                    {
                        var parts = childItem.VwmlTag.Split('.');
                        if (parts.Length > 2)
                        {
                            throw new ApplicationException("Property setter specification is too deep.  Only one dot allowed! (" + childItem.VwmlTag + ")");
                        }

                        var propertyType = output.GetType().GetProperty(parts[1]);
                        if (childItem.Children.Count == 1) // Only add items with content
                        {
                            var hydratedLayout = HydrateLayout(injector, childItem.Children[0], controlLibrary);
                            if (!propertyType.PropertyType.IsAssignableFrom(hydratedLayout.GetType()))
                            {
                                throw new ApplicationException("Property " + childItem.VwmlTag + " cannot be assigned Type " + hydratedLayout.GetType().Name);
                            }
                            propertyType.SetValue(output, hydratedLayout);
                        }
                        else if (childItem.Children.Count > 1)
                        {
                            throw new ApplicationException("Too many child nodes on a property setter.  You only get one! (" + childItem.VwmlTag + ")");
                        }
                    }
                    else
                    {
                        output.AddChild(HydrateLayout(injector, childItem, controlLibrary), true);
                    }
                }
            };


            if (controlLibrary.ContainsKey(widgetLayout.VwmlTag))
            {
                var controlLayout = controlLibrary[widgetLayout.VwmlTag];

                if (controlLayout.Settings.ContainsKey("Class"))
                {
                    var controlType = GetWidgetType(controlLayout.Settings["Class"]);
                    if (!controlType.IsSubclassOf(typeof(VarmintWidgetControl)))
                    {
                        throw new ApplicationException("The Class attribute must point to a VarmintWidgetControl");
                    }
                    output = (VarmintWidget)Activator.CreateInstance(controlType);
                    output.EventBindingContext = output;
                }
                else
                {
                    output = new VarmintWidgetControl();
                }

                // Controls will get properties from the control layout, but these can
                // be overridden later by the local instace of the control
                applyLayout(controlLayout);
            }
            else
            {
                var nodeType = GetWidgetType(widgetLayout.VwmlTag);
                output = (VarmintWidget)Activator.CreateInstance(nodeType);
            }
            if (widgetLayout.Name != null)
            {
                output.Name = widgetLayout.Name;
            }

            foreach (var propertyType in output.GetType().GetProperties())
            {
                var injectAttribute = (VarmintWidgetInjectAttribute)propertyType.GetCustomAttribute(typeof(VarmintWidgetInjectAttribute));
                if (injectAttribute != null)
                {
                    propertyType.SetValue(output,
                                          injector.GetInjectedValue(injectAttribute, propertyType));
                }
            }

            applyLayout(widgetLayout);

            return(output);
        }
Example #2
0
        //--------------------------------------------------------------------------------------
        /// <summary>
        /// HydrateLayout - Take a layout item and turn it into a VarmintWidget
        /// </summary>
        //--------------------------------------------------------------------------------------
        private VarmintWidget HydrateLayout(LayoutItem widgetLayout)
        {
            VarmintWidget newWidget = null;

            // Helper method to apply this layout to the widget we created.
            void ApplyLayout(LayoutItem layout)
            {
                // Get the settings explicitly specified in the layout
                foreach (var name in layout.Settings.Keys)
                {
                    switch (name)
                    {
                    case "Style":
                    case "ApplyTo":
                        newWidget.SetValue(name, layout.Settings[name], true);
                        break;

                    default:
                        newWidget.AddSetting(name, layout.Settings[name]);
                        break;
                    }
                }

                foreach (var childItem in layout.Children)
                {
                    if (childItem.VwmlTag.Contains("."))
                    {
                        var parts = childItem.VwmlTag.Split('.');
                        if (parts.Length > 2)
                        {
                            throw new ApplicationException("Property setter specification is too deep.  Only one dot allowed! (" + childItem.VwmlTag + ")");
                        }

                        var propertyType = newWidget.GetType().GetProperty(parts[1]);
                        if (childItem.Children.Count == 1) // Only add items with content
                        {
                            var hydratedLayout = HydrateLayout(childItem.Children[0]);
                            if (propertyType != null && !propertyType.PropertyType.IsInstanceOfType(hydratedLayout))
                            {
                                throw new ApplicationException("Property " + childItem.VwmlTag + " cannot be assigned Type " + hydratedLayout.GetType().Name);
                            }
                            propertyType?.SetValue(newWidget, hydratedLayout);
                        }
                        else if (childItem.Children.Count > 1)
                        {
                            throw new ApplicationException("Too many child nodes on a property setter.  You only get one! (" + childItem.VwmlTag + ")");
                        }
                    }
                    else
                    {
                        newWidget.AddChild(HydrateLayout(childItem));
                    }
                }
            }

            // If the vwmlTag is in the layouts, it must be a control
            if (_controlLibrary.ContainsKey(widgetLayout.VwmlTag))
            {
                var controlLayout = _controlLibrary[widgetLayout.VwmlTag];

                // If there is a class that is bound to this control then we bind events to that class
                if (controlLayout.Settings.ContainsKey("Class"))
                {
                    var controlType = VarmintWidget.GetWidgetType(controlLayout.Settings["Class"]);
                    if (!controlType.IsSubclassOf(typeof(VarmintWidgetControl)))
                    {
                        throw new ApplicationException("The Class attribute must point to a VarmintWidgetControl");
                    }
                    newWidget = (VarmintWidget)Activator.CreateInstance(controlType);
                    newWidget.ControlHandler = newWidget;
                }
                else
                {
                    newWidget = new VarmintWidgetControl();
                }

                // Controls will get properties from the control layout, but these can
                // be overridden later by the local instace of the control
                ApplyLayout(controlLayout);
            }
            else
            {
                var nodeType = VarmintWidget.GetWidgetType(widgetLayout.VwmlTag);
                newWidget = (VarmintWidget)Activator.CreateInstance(nodeType);
            }
            if (widgetLayout.Name != null)
            {
                newWidget.Name = widgetLayout.Name;
            }

            // Automatically inject property values if they are injectable
            foreach (var propertyType in newWidget.GetType().GetProperties())
            {
                var injectAttribute = (VarmintWidgetInjectAttribute)propertyType.GetCustomAttribute(typeof(VarmintWidgetInjectAttribute));
                if (injectAttribute != null)
                {
                    propertyType.SetValue(newWidget, _injector.GetInjectedValue(injectAttribute, propertyType));
                }
            }

            ApplyLayout(widgetLayout);
            return(newWidget);
        }