/// <summary> /// Adds an options entry to the category list, creating a new category if necessary. /// </summary> /// <param name="entries">The existing categories.</param> /// <param name="entry">The option entry to add.</param> internal static void AddToCategory(AllOptions entries, IOptionsEntry entry) { string category = entry.Category ?? ""; if (!entries.TryGetValue(category, out OptionsList inCat)) { inCat = new List <IOptionsEntry>(16); entries.Add(category, inCat); } inCat.Add(entry); }
/// <summary> /// Adds an options entry object that operates on Option fields of the encapsulated /// object. /// </summary> /// <param name="info">The property that is wrapped.</param> /// <param name="entry">The entry to add.</param> public void AddField(PropertyInfo info, IOptionsEntry entry) { if (entry == null) { throw new ArgumentNullException(nameof(entry)); } if (info == null) { throw new ArgumentNullException(nameof(info)); } subOptions.Add(info, entry); }
/// <summary> /// Creates a default UI entry. This entry will have the title and tool tip in the /// first column, and the provided UI component in the second column. Only one row is /// added by this method. /// </summary> /// <param name="entry">The options entry to be presented.</param> /// <param name="parent">The parent where the components will be added.</param> /// <param name="row">The row index where the components will be added.</param> /// <param name="presenter">The presenter that can display this option's value.</param> public static void CreateDefaultUIEntry(IOptionsEntry entry, PGridPanel parent, int row, IUIComponent presenter) { parent.AddChild(new PLabel("Label") { Text = LookInStrings(entry.Title), ToolTip = LookInStrings(entry.Tooltip), TextStyle = PUITuning.Fonts.TextLightStyle }, new GridComponentSpec(row, 0) { Margin = LABEL_MARGIN, Alignment = TextAnchor.MiddleLeft }); parent.AddChild(presenter, new GridComponentSpec(row, 1) { Alignment = TextAnchor.MiddleRight, Margin = CONTROL_MARGIN }); }
/// <summary> /// Shared code to create an options entry if an [Option] attribute is found on a /// property. /// </summary> /// <param name="prop">The property to inspect.</param> /// <param name="depth">The current depth of iteration to avoid infinite loops.</param> /// <returns>The OptionsEntry created, or null if none was.</returns> internal static IOptionsEntry TryCreateEntry(PropertyInfo prop, int depth) { IOptionsEntry result = null; // Must have the annotation, cannot be indexed var indexes = prop.GetIndexParameters(); if (indexes == null || indexes.Length < 1) { foreach (var attribute in prop.GetCustomAttributes()) { result = TryCreateEntry(attribute, prop, depth); if (result != null) { break; } } } return(result); }
/// <summary> /// Creates an options entry if an attribute is a valid IOptionSpec or /// DynamicOptionAttribute. /// </summary> /// <param name="attribute">The attribute to parse.</param> /// <param name="prop">The property to inspect.</param> /// <param name="depth">The current depth of iteration to avoid infinite loops.</param> /// <returns>The OptionsEntry created from the attribute, or null if none was.</returns> private static IOptionsEntry TryCreateEntry(Attribute attribute, PropertyInfo prop, int depth) { IOptionsEntry result = null; if (prop == null) { throw new ArgumentNullException(nameof(prop)); } if (attribute is IOptionSpec spec) { if (string.IsNullOrEmpty(spec.Title)) { spec = HandleDefaults(spec, prop); } // Attempt to find a class that will represent it var type = prop.PropertyType; result = FindOptionClass(spec, prop); // See if it has entries that can themselves be added, ignore // value types and avoid infinite recursion if (result == null && !type.IsValueType && depth < 16 && type != prop.DeclaringType) { result = CompositeOptionsEntry.Create(spec, prop, depth); } } else if (attribute is DynamicOptionAttribute doa && typeof(IOptionsEntry).IsAssignableFrom(doa.Handler)) { try { result = Activator.CreateInstance(doa.Handler) as IOptionsEntry; } catch (TargetInvocationException e) { PUtil.LogError("Unable to create option handler for property " + prop.Name + ":"); PUtil.LogException(e.GetBaseException() ?? e); } catch (MissingMethodException) { PUtil.LogWarning("Unable to create option handler for property " + prop.Name + ", it must have a public default constructor"); } } return(result); }