//-------------------------------------------------------------------------------------- /// <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); }
//-------------------------------------------------------------------------------------- /// <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); }