/// <summary> /// Instantiating member of descriptor. /// </summary> /// <param name="layer">Layer that will be shared to the elemen OnLayout handler.</param> /// <param name="memberMeta">Target member.</param> /// <param name="globalOptions">Options of the descriptor.</param> /// <returns></returns> private object InstantiateMember(ref LayoutLayer layer, MembersHandler.MemberMeta memberMeta, IEnumerable <Attribute> globalOptions) { #region Definig handler // The handler that will apply options to the element. void ApplyOptionsHandler( FrameworkElement element, IEnumerable <Attribute> localAttributes) { if (element == null) { return; } // Applying global options foreach (IGUILayoutOption option in globalOptions) { option.ApplyLayoutOption(element); } // Perform options attributes. foreach (Attribute attr in localAttributes) { // Skip if not an option. if (!(attr is IGUILayoutOption option)) { continue; } // Applying option to the element. option.ApplyLayoutOption(element); } // Applying the shared options. foreach (ISharableGUILayoutOption option in SharedLayoutOptions) { // Applying option to the element. option.ApplyLayoutOption(element); } } #endregion // Getting all attributes. IEnumerable <Attribute> attributes = memberMeta.Member.GetCustomAttributes <Attribute>(true); #region Perform general layout attributes // Perform general attributes. foreach (Attribute attr in attributes) { // Skip if an option. if (attr is IGUILayoutOption) { continue; } // Apply layout control to GUI. if (attr is IGUIElement attrControl) { attrControl.OnLayout(ref layer, this, memberMeta); } } #endregion #region Defining UI field type // Check if default control was overrided by custom one. var customControlDesc = memberMeta.Member.GetCustomAttribute <CustomControlAttribute>(); Type controlType; if (customControlDesc != null && // Is overriding requested? customControlDesc.ControlType != null) // Is target type is not null { // Set redefined control like target to instinitation. controlType = customControlDesc.ControlType; } else { //// Looking for the certain control only for derect defined descriptors. //if (memberMeta.SourceType.IsSubclassOf(typeof(UIDescriptor))) //{ // // Set binded type like target to instiniation. // controlType = LayoutHandler.GetBindedControl(memberMeta.SourceType, false); //} //else { // Set binded type like target to instiniation. controlType = LayoutHandler.GetBindedControl(memberMeta.SourceType, true); } } #endregion // Is control defined to that member? if (controlType != null) { // Instiniating target control by the type. var control = (IGUIField)Activator.CreateInstance(controlType); #region Set prefix label // Is spawned elelment has a label. if (control is UI.Controls.ILabel label) { // Instiniating handle that will provide managmend of the control. ContentAttribute localizationHandler; // Try to get described one. if (UniformDataOperator.AssembliesManagement.MembersHandler. TryToGetAttribute(memberMeta.Member, out ContentAttribute attribute)) { // Buferize if found. localizationHandler = attribute; } else { // Initialize new one. localizationHandler = ContentAttribute.Empty; } // Binding spawned element to the conent. localizationHandler.BindToLabel(label, memberMeta.Member); } #endregion #region Perform Layout options // Check if spawned control is framework element. if (control is FrameworkElement fEl) { // Applying options to the element. ApplyOptionsHandler(fEl, attributes); } #endregion #region Binding to a layout // Sign up this control on desctiptor events. TryToBindControl(control, this, memberMeta.Member); // Adding instiniated element to the layout. //activeLayer?.ApplyControl(control as FrameworkElement); // Initialize control. control.OnLayout(ref layer, this, memberMeta.Member, globalOptions, attributes); // Adding field to the registration table. RegistredFields.Add(memberMeta.Member, control); #endregion return(control); } else { // Check if that just other descriptor. if (memberMeta.SourceType.IsSubclassOf(typeof(UIDescriptor))) { //#region Configurating layout //// Add horizontal shift for sub descriptor. //new BeginHorizontalGroupAttribute().OnLayout(ref activeLayer); //new Controls.SpaceAttribute().OnLayout(ref activeLayer); // Add vertical group. var vertGroup = new BeginVerticalGroupAttribute(); vertGroup.OnLayout(ref layer, this, memberMeta); //#endregion #region Applying options to the new root // Applying options to the element. ApplyOptionsHandler(vertGroup.Layer.root as FrameworkElement, attributes); #endregion #region Looking for descriptor object. // Bufer that will contain value of the descriptor. // Trying to get value via reflection. UIDescriptor subDesc = memberMeta.Property != null? memberMeta.Property.GetValue(this) as UIDescriptor:// Operate like property. memberMeta.Field.GetValue(this) as UIDescriptor; // Instiniate default in case if value is null. if (subDesc == null) { try { // Insiniate empty constructor. subDesc = Activator.CreateInstance(memberMeta.SourceType) as UIDescriptor; } catch (Exception ex) { // Log error. MessageBox.Show("UIDescriptor must contain empty constructor, " + "or be instiniated before calling into UI." + "\n\nDetails:\n" + ex.Message); // Skip to the next member. return(null); } // Updating stored value for current member. if (memberMeta.Property != null) { memberMeta.Property.SetValue(this, subDesc); } else { memberMeta.Field.SetValue(this, subDesc); } } // Defining the sharable options. var sharableOption = InsertSharableOptions(SharedLayoutOptions, attributes, true); sharableOption = InsertSharableOptions(sharableOption, globalOptions, false); subDesc.SharedLayoutOptions = sharableOption.ToArray(); #endregion // Binding descriptor to the UI. Panel subPanel = (Panel)layer.root; if (subDesc.IsVirtualized) { _ = subDesc.BindToAsync(subPanel); } else { subDesc.BindTo(subPanel); } // End descriptor layer. new EndGroupAttribute().OnLayout(ref layer); // Subscribing on the sub descriptor changed update. subDesc.ValueChanged += OnValueChangedCallback; return(subPanel); } } return(null); }
/// <summary> /// Insiniate UI by descriptor's attributes map and add it as child to parent element. /// </summary> /// <param name="root">UI element that would contain instiniated UI elemets.</param> public void BindTo(Panel root) { #region Getting descripting data // Getting relevant type. var selfType = this.GetType(); // Getting options applied to every memeber. var globalOptions = Attribute.GetCustomAttributes(selfType, typeof(Attribute)).Where (f => f.GetType().GetInterface(typeof(IGUILayoutOption).FullName) != null); // Get all memebers. var members = selfType.GetMembers(); // Sorting by order. var orderedMembers = members.Where(f => f.GetCustomAttribute <OrderAttribute>() != null). OrderBy(f => f.GetCustomAttribute <OrderAttribute>().Order); // Sorting disordered members by metadata. var disorderedMembers = members.Where(f => f.GetCustomAttribute <OrderAttribute>() == null). OrderBy(f => f.MetadataToken); #endregion // Sort in declaretion order. members = orderedMembers.Concat(disorderedMembers).ToArray(); // Instiniate first UILayer. activeLayer = new LayoutLayer() { root = root // Thet binding target as root for cuurent layer. }; // Perform all descriptor map. foreach (MemberInfo member in members) { #region Validation // Skip if the member is not field or property. if (!MembersHandler.GetSpecifiedMemberInfo( member, out PropertyInfo prop, out FieldInfo field)) { continue; } // Skip if member excluded from instpector. if (member.GetCustomAttribute <HideInInspectorAttribute>() != null) { continue; } #endregion // Getting all attributes. var attributes = member.GetCustomAttributes <Attribute>(true); // Allocating and defining types. var memberType = MembersHandler.GetSpecifiedMemberType(member); Type controlType = null; #region Perform general layout attributes // Perform general attributes. foreach (Attribute attr in attributes) { // Skip if an option. if (attr is IGUILayoutOption) { continue; } // Apply layout control to GUI. if (attr is IGUIElement attrControl) { attrControl.OnLayout(ref activeLayer, this, member); } } #endregion #region Defining UI field type // Check if default control was overrided by custom one. var customControlDesc = member.GetCustomAttribute <CustomControlAttribute>(); if (customControlDesc != null && // Is overriding requested? customControlDesc.ControlType != null && // Is target type is not null? customControlDesc.ControlType.IsSubclassOf(typeof(IGUIField))) // Is target type has correct inherience { // Set redefined control like target to instinitation. controlType = customControlDesc.ControlType; } else { // Set binded type like target to instiniation. controlType = LayoutHandler.GetBindedControl(memberType, true); } #endregion // Is control defined to that member? if (controlType != null) { #region Insiniation UI field // Instiniating target type. var control = (IGUIField)Activator.CreateInstance(controlType); // Sing up this control on desctiptor events. TryToBindControl(control, this, member); // Initialize control. control.OnLayout(ref activeLayer, this, member); // Adding field to the registration table. RegistredFields.Add(member, control); #endregion #region Set prefix label // Is spawned elelment has a label. if (control is UI.Controls.ILabel label) { // Instiniating handle that will provide managmend of the control. ContentAttribute localizationHandler = null; // Try to get described one. if (UniformDataOperator.AttributesHandler. TryToGetAttribute(member, out ContentAttribute attribute)) { // Buferize if found. localizationHandler = attribute; } else { // Initialize new one. localizationHandler = ContentAttribute.Empty; } // Binding spawned element to the conent. localizationHandler.BindToLable(label, member); } #endregion #region Perform Layout options // Check if spawned control is framework element. if (control is FrameworkElement fEl) { // Applying global options foreach (IGUILayoutOption option in globalOptions) { option.ApplyLayoutOption(fEl); } // Perform options attributes. foreach (Attribute attr in attributes) { // Skip if not an option. if (!(attr is IGUILayoutOption option)) { continue; } // Applying option to the element. option.ApplyLayoutOption(fEl); } } #endregion } else { // Check if that just other descriptor. if (memberType.IsSubclassOf(typeof(UIDescriptor))) { #region Configurating layout // Add horizontal shift for sub descriptor. new BeginHorizontalGroupAttribute().OnLayout(ref activeLayer); new Controls.SpaceAttribute(10).OnLayout(ref activeLayer); // Add vertical group. var vertGroup = new BeginVerticalGroupAttribute(); vertGroup.OnLayout(ref activeLayer); #endregion #region Looking for descriptor object. // Bufer that will contain value of the descriptor. UIDescriptor subDesc = null; // Trying to get value via reflection. subDesc = prop != null? prop.GetValue(this) as UIDescriptor: // Operate like property. field.GetValue(this) as UIDescriptor; // Operate like fields. // Instiniate default in case if value is null. if (subDesc == null) { try { // Insiniate empty constructor. subDesc = Activator.CreateInstance(memberType) as UIDescriptor; } catch (Exception ex) { // Log error. MessageBox.Show("UIDescriptor must contain empty constructor, " + "or be instiniated before calling into UI." + "\n\nDetails:\n" + ex.Message); // Skip to the next member. continue; } // Updating stored value for current member. if (prop != null) { prop.SetValue(this, subDesc); } else { field.SetValue(this, subDesc); } } #endregion // Binding descriptor to the UI. subDesc.BindTo((Panel)activeLayer.root); } } } // Marking as loaded. IsLoaded = true; // Inform subscribers. Loaded?.Invoke(this); }