/// <summary> /// Applying UI element to the GUI. /// </summary> /// <param name="element">Shared UI element.</param> public void ApplyControl(FrameworkElement element) { // Drop invalid. if (element == null) { return; } // Adding herader to layout. if (orientation == Orientation.Horizontal) { LayoutHandler.HorizontalLayoutAddChild(root, element); } else { LayoutHandler.VerticalLayoutAddChild(root, element); } }
/// <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); }
/// <summary> /// Unbinding descriptor from panel. /// Will affect only memeber defied into descriptor and leave and other GUI elements childed to the panel. /// </summary> /// <param name="root">Root panle that was binding target for descriptor.</param> public void UnbindFrom(Panel root) { // Get all memebers. var members = GetType().GetMembers(); // Checking every child into the root. for (int i = 0; i < root.Children.Count; i++) { // Getting current child. var child = root.Children[i]; // If child is layout control and has a binded memeber. if (child is IGUIField control && control.BindedMember != null) { #region Validation // Checking is the binded memeber is a part of the descriptor. bool thisDesc = false; foreach (var member in members) { // Check if binded member is the one from the descriptor. if (member.Equals(control.BindedMember)) { thisDesc = true; break; } } // Skip if not possesed to that descriptor. if (!thisDesc) { continue; } #endregion #region Unbind control from UI // Unsubscribe element from hadler's events. LayoutHandler.UnregistrateField(control); // Remove from UI. root.Children.RemoveAt(i); i--; #endregion #region Sub descriptor processing // If member is UI descriptor. if (control is Panel subPanel && MembersHandler.GetSpecifiedMemberType(control.BindedMember).IsSubclassOf(typeof(UIDescriptor))) { try { // Requiest descriptor unbinding. ((UIDescriptor)control.Value).UnbindFrom(subPanel); } catch (Exception ex) { // Log error. MessageBox.Show("Subpanel UIDescriptor unbind operation failed." + "\n\nDetails:\n" + ex.Message); } } #endregion } } }
/// <summary> /// Binding UIDescriptor content to the layer's root. /// </summary> /// <param name="layer">Target layer.</param> public async Task BindToAsync(LayoutLayer layer) { // Storing layer. RootLayer = layer; activeLayer = layer; #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(); // Perform all descriptor map. foreach (MemberInfo member in members) { var memberMeta = new MembersHandler.MemberMeta(member); #region Validation // Skip if the member is not field or property. if (!memberMeta.IsValue) { continue; } // Skip if member excluded from instpector. if (member.GetCustomAttribute <HideInInspectorAttribute>() != null) { continue; } #endregion #region Virtualization // Suspending virtualization if (IsVirtualized && virtualizedPackCounter == VirtualizedItemsPack) { // Droping the counter. virtualizedPackCounter = 0; // Waiting till loading. while (!lastVirtualizedElement.IsLoaded) { await Task.Delay(5); } Panel rootPanel = (Panel)RootLayer.root; // Checking if the last element still in the visible bounds. bool isVisible = LayoutHandler.IsUserVisible(lastVirtualizedElement, Window.GetWindow(lastVirtualizedElement)); // Suspending if the last not visible till view update. if (!isVisible) { // Marker that using for blocking the thread. bool unlocked = false; var window = Window.GetWindow(lastVirtualizedElement); // Waiting till the root will change a size/ window.Activated += Activated; rootPanel.SizeChanged += SizeChanged; void Activated(object sender, EventArgs e) { VirtValHandler(); }; void SizeChanged(object sender, SizeChangedEventArgs e) { VirtValHandler(); }; void VirtValHandler() { // Checking if the last element is already visible. isVisible = LayoutHandler.IsUserVisible(lastVirtualizedElement, window); if (isVisible) { // Unsubscribing from event. window.Activated -= Activated; rootPanel.SizeChanged -= SizeChanged; // Unblocking the thread. unlocked = true; } } // Unblocking instantiation of next group of elements. while (!unlocked) { await Task.Delay(5); } } } #endregion if (!(RegistredFields[member] is IGUIField virtualizedElement)) { // Instantiating a member. var field = InstantiateMember(ref activeLayer, memberMeta, globalOptions); // Skip in case if not instantiated. if (field == null) { continue; } // Storing in virtualization meta. var meta = new VirtualizedItemMeta( field, ref activeLayer, member); // Settup into virtualization system. lastVirtualizedElement = meta.Element ?? lastVirtualizedElement; //VirtualizedElements.Add(meta); // Applying to the layout. activeLayer?.ApplyControl(field as FrameworkElement); }