using System; using System.Reflection; using System.Windows.Forms; using Inspectron.Settings.Attributes; using Microsoft.WindowsAPICodePack.Dialogs; namespace Inspectron.Settings.Windows.Configuration; public class DefaultControlFactory : IControlFactory { public virtual Control CreateControl(string name, string description, PropertyInfo propertyInfo, object initialValue, Action valueChangedCallback, OptionsWindow optionsWindow) { var type = propertyInfo.PropertyType; // Check for SettingDescriptionAttribute var settingDescriptionAttribute = propertyInfo.GetCustomAttribute(); string settingDescription = settingDescriptionAttribute?.Description; // Check for SettingPreviewAttribute var previewAttribute = propertyInfo.GetCustomAttribute(); Label previewLabel = null; Func getPreview = null; if (previewAttribute != null) { var method = previewAttribute.PreviewClass.GetMethod(previewAttribute.PreviewFunction, BindingFlags.Public | BindingFlags.Static); getPreview = value => (string)method.Invoke(null, new[] { value }); previewLabel = new Label { AutoSize = false, Size = new System.Drawing.Size(600, 30), Padding = new Padding(15, 0, 0, 0), Font = new System.Drawing.Font("Segoe UI", 10, System.Drawing.FontStyle.Italic), Text = getPreview(initialValue) }; } if (type == typeof(string) && name.EndsWith("Path", StringComparison.OrdinalIgnoreCase)) { return CreatePathControl(name, description, initialValue, valueChangedCallback, optionsWindow, settingDescription, previewLabel, getPreview); } else if (type == typeof(string)) { return CreateStringControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview); } else if (type == typeof(int)) { return CreateIntControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview); } else if (type == typeof(bool)) { return CreateBoolControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview); } else if (type.IsEnum) { return CreateEnumControl(description, type, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview); } else { return new Label { Text = $"Unsupported type: {type.Name}", AutoSize = true }; } } private Control CreatePathControl(string name, string description, object initialValue, Action valueChangedCallback, OptionsWindow optionsWindow, string settingDescription, Label previewLabel, Func getPreview) { var textBox = new TextBox { Text = initialValue as string, Width = 400 }; var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) }; var browseButton = new Button { Text = "Browse", AutoSize = true }; browseButton.Click += (s, e) => { using (var dialog = new CommonOpenFileDialog { IsFolderPicker = true }) { if (dialog.ShowDialog(optionsWindow.Handle) == CommonFileDialogResult.Ok) { textBox.Text = dialog.FileName; valueChangedCallback(dialog.FileName); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(dialog.FileName); } } }; textBox.TextChanged += (s, e) => { valueChangedCallback(textBox.Text); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(textBox.Text); }; return CreateOuterPanel(settingDescription, previewLabel, label, textBox, browseButton); } private Control CreateStringControl(string description, object initialValue, Action valueChangedCallback, string settingDescription, Label previewLabel, Func getPreview) { var textBox = new TextBox { Text = initialValue as string, Width = 600 }; var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) }; textBox.TextChanged += (s, e) => { valueChangedCallback(textBox.Text); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(textBox.Text); }; return CreateOuterPanel(settingDescription, previewLabel, label, textBox); } private Control CreateIntControl(string description, object initialValue, Action valueChangedCallback, string settingDescription, Label previewLabel, Func getPreview) { var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) }; var numericUpDown = new NumericUpDown { Minimum = 0, Maximum = 99999999999, Value = Convert.ToDecimal(initialValue), Width = 200 }; numericUpDown.ValueChanged += (s, e) => { valueChangedCallback(Convert.ToInt32(numericUpDown.Value)); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(Convert.ToInt32(numericUpDown.Value)); }; return CreateOuterPanel(settingDescription, previewLabel, label, numericUpDown); } private Control CreateBoolControl(string description, object initialValue, Action valueChangedCallback, string settingDescription, Label previewLabel, Func getPreview) { var checkBox = new CheckBox { Text = description, Checked = (bool)initialValue, AutoSize = true }; checkBox.CheckedChanged += (s, e) => { valueChangedCallback(checkBox.Checked); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(checkBox.Checked); }; return CreateOuterPanel(settingDescription, previewLabel, checkBox); } private Control CreateEnumControl(string description, Type enumType, object initialValue, Action valueChangedCallback, string settingDescription, Label previewLabel, Func getPreview) { var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) }; var comboBox = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 200 }; // Populate ComboBox with enum values foreach (var value in Enum.GetValues(enumType)) { comboBox.Items.Add(value); } // Set initial value comboBox.SelectedItem = initialValue; comboBox.SelectedIndexChanged += (s, e) => { valueChangedCallback(comboBox.SelectedItem); if (previewLabel != null && getPreview != null) previewLabel.Text = getPreview(comboBox.SelectedItem); }; return CreateOuterPanel(settingDescription, previewLabel, label, comboBox); } private Control CreateOuterPanel(string settingDescription, Label previewLabel, params Control[] controls) { var outerPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.TopDown, AutoSize = true, Margin = new Padding(0, 25, 0, 0) }; if (!string.IsNullOrEmpty(settingDescription)) { var descriptionLabel = new Label { Text = settingDescription, AutoSize = true, Padding = new Padding(0, 5, 0, 0) }; outerPanel.Controls.Add(descriptionLabel); } foreach (var control in controls) { outerPanel.Controls.Add(control); } if (previewLabel != null) outerPanel.Controls.Add(previewLabel); return outerPanel; } }