2025-03-04 20:20:08 -08:00
|
|
|
|
using System;
|
2025-03-05 16:04:27 -08:00
|
|
|
|
using System.Collections.Generic;
|
2025-03-04 20:20:08 -08:00
|
|
|
|
using System.Drawing;
|
2025-03-10 18:34:45 -07:00
|
|
|
|
using System.Linq;
|
2025-03-04 20:20:08 -08:00
|
|
|
|
using System.Windows.Forms;
|
2025-03-11 19:43:44 -07:00
|
|
|
|
using System.Globalization;
|
2025-03-04 20:20:08 -08:00
|
|
|
|
|
|
|
|
|
namespace Better_NCP_Editor
|
|
|
|
|
{
|
|
|
|
|
public partial class EditValueForm : Form
|
|
|
|
|
{
|
|
|
|
|
public object NewValue { get; private set; }
|
|
|
|
|
private Control inputControl;
|
2025-03-10 18:34:45 -07:00
|
|
|
|
private readonly Type valueType;
|
2025-03-04 20:20:08 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
public EditValueForm(string propertyName, string currentValue, Type valueType, List<string>? comboItems, Dictionary<string, string> allItems, Dictionary<string, UInt64> skinIDs)
|
|
|
|
|
{
|
|
|
|
|
// Validate required parameters.
|
|
|
|
|
if (string.IsNullOrWhiteSpace(propertyName))
|
|
|
|
|
throw new ArgumentException("Property name cannot be null or empty.", nameof(propertyName));
|
|
|
|
|
if (currentValue == null)
|
|
|
|
|
throw new ArgumentNullException(nameof(currentValue));
|
|
|
|
|
if (valueType == null)
|
|
|
|
|
throw new ArgumentNullException(nameof(valueType));
|
|
|
|
|
|
|
|
|
|
this.valueType = valueType;
|
|
|
|
|
|
|
|
|
|
// Set up the form's basic properties and size.
|
|
|
|
|
InitializeForm(propertyName, currentValue, comboItems);
|
|
|
|
|
// Create and add the input control.
|
|
|
|
|
CreateInputControl(propertyName, currentValue, comboItems, allItems, skinIDs);
|
|
|
|
|
// Create and add OK/Cancel buttons.
|
|
|
|
|
CreateButtons();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeForm(string propertyName, string currentValue, List<string>? comboItems)
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
2025-03-05 16:04:27 -08:00
|
|
|
|
this.MinimumSize = new Size(210, 120);
|
2025-03-07 15:35:41 -08:00
|
|
|
|
this.AutoScaleMode = AutoScaleMode.None;
|
2025-03-05 16:04:27 -08:00
|
|
|
|
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
|
|
|
this.MaximizeBox = false;
|
2025-03-10 18:34:45 -07:00
|
|
|
|
this.StartPosition = FormStartPosition.CenterParent;
|
|
|
|
|
this.Text = $"Edit {propertyName}";
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Measure text widths for layout.
|
2025-03-07 15:35:41 -08:00
|
|
|
|
int propertyNameWidth = TextRenderer.MeasureText(propertyName, this.Font).Width;
|
|
|
|
|
int currentValueWidth = valueType == typeof(bool)
|
|
|
|
|
? TextRenderer.MeasureText("false", this.Font).Width + 30
|
|
|
|
|
: TextRenderer.MeasureText(currentValue, this.Font).Width + 40;
|
|
|
|
|
|
|
|
|
|
int comboItemsWidth = 0;
|
|
|
|
|
if (comboItems != null)
|
2025-03-05 10:07:49 -08:00
|
|
|
|
{
|
2025-03-07 15:35:41 -08:00
|
|
|
|
foreach (var item in comboItems)
|
|
|
|
|
{
|
|
|
|
|
int itemWidth = TextRenderer.MeasureText(item, this.Font).Width;
|
2025-03-10 18:34:45 -07:00
|
|
|
|
comboItemsWidth = Math.Max(comboItemsWidth, itemWidth);
|
2025-03-07 15:35:41 -08:00
|
|
|
|
}
|
2025-03-10 18:34:45 -07:00
|
|
|
|
comboItemsWidth += 20; // extra padding for dropdown arrow and margin.
|
2025-03-05 10:07:49 -08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-07 15:35:41 -08:00
|
|
|
|
int desiredWidth = Math.Max(propertyNameWidth, Math.Max(currentValueWidth, comboItemsWidth)) + 40;
|
2025-03-05 10:07:49 -08:00
|
|
|
|
this.ClientSize = new Size(desiredWidth, 120);
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Create and add the property label.
|
2025-03-04 20:20:08 -08:00
|
|
|
|
Label lblProperty = new Label()
|
|
|
|
|
{
|
|
|
|
|
Text = propertyName,
|
|
|
|
|
Location = new Point(10, 10),
|
|
|
|
|
AutoSize = true
|
|
|
|
|
};
|
|
|
|
|
this.Controls.Add(lblProperty);
|
2025-03-10 18:34:45 -07:00
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
private void CreateInputControl(string propertyName, string currentValue, List<string>? comboItems, Dictionary<string, string> allItems, Dictionary<string, UInt64> skinIDs)
|
|
|
|
|
{
|
|
|
|
|
int controlWidth = this.ClientSize.Width - 20;
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
|
|
|
|
if (comboItems != null)
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Create a ComboBox when comboItems are provided.
|
|
|
|
|
ComboBox combo = new ComboBox
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
|
|
|
|
Location = new Point(10, 40),
|
2025-03-10 18:34:45 -07:00
|
|
|
|
Width = controlWidth,
|
2025-03-04 20:20:08 -08:00
|
|
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
|
|
|
};
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Add items and adjust the dropdown width to fit the widest item.
|
|
|
|
|
int maxItemWidth = comboItems.Select(item => TextRenderer.MeasureText(item, combo.Font).Width).Max();
|
|
|
|
|
int paddedWidth = maxItemWidth + 20;
|
|
|
|
|
combo.DropDownWidth = paddedWidth;
|
|
|
|
|
if (combo.Width < paddedWidth)
|
|
|
|
|
combo.Width = paddedWidth;
|
|
|
|
|
|
|
|
|
|
foreach (var item in comboItems)
|
2025-03-05 16:04:27 -08:00
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
combo.Items.Add(item);
|
2025-03-05 16:04:27 -08:00
|
|
|
|
}
|
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Attempt to set the selected item using the provided dictionaries.
|
|
|
|
|
string? selectedKey = allItems.FirstOrDefault(x => x.Value == currentValue).Key;
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// If not found, try using skinIDs (with safe parsing).
|
|
|
|
|
if (string.IsNullOrEmpty(selectedKey) && skinIDs != null && UInt64.TryParse(currentValue, out UInt64 parsedValue))
|
|
|
|
|
{
|
|
|
|
|
selectedKey = skinIDs.FirstOrDefault(x => x.Value == parsedValue).Key;
|
|
|
|
|
}
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
if (!string.IsNullOrEmpty(selectedKey) && combo.Items.Contains(selectedKey))
|
2025-03-05 16:04:27 -08:00
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
combo.SelectedItem = selectedKey;
|
2025-03-05 16:04:27 -08:00
|
|
|
|
}
|
|
|
|
|
else if (combo.Items.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
combo.SelectedIndex = 0;
|
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
inputControl = combo;
|
|
|
|
|
this.Controls.Add(combo);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// For bool types, use a ComboBox to choose true/false.
|
2025-03-05 16:04:27 -08:00
|
|
|
|
if (valueType == typeof(bool))
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
ComboBox combo = new ComboBox
|
2025-03-05 16:04:27 -08:00
|
|
|
|
{
|
|
|
|
|
Location = new Point(10, 40),
|
|
|
|
|
Width = controlWidth,
|
|
|
|
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|
|
|
|
};
|
|
|
|
|
combo.Items.Add("true");
|
|
|
|
|
combo.Items.Add("false");
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Parse the current value safely.
|
|
|
|
|
if (bool.TryParse(currentValue, out bool boolVal))
|
|
|
|
|
{
|
|
|
|
|
combo.SelectedItem = boolVal.ToString().ToLower();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
combo.SelectedIndex = 0;
|
|
|
|
|
}
|
2025-03-05 16:04:27 -08:00
|
|
|
|
inputControl = combo;
|
|
|
|
|
this.Controls.Add(combo);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
// Default to a TextBox for other types.
|
|
|
|
|
TextBox txtBox = new TextBox
|
2025-03-05 16:04:27 -08:00
|
|
|
|
{
|
|
|
|
|
Location = new Point(10, 40),
|
|
|
|
|
Width = controlWidth,
|
|
|
|
|
Text = currentValue
|
|
|
|
|
};
|
|
|
|
|
inputControl = txtBox;
|
|
|
|
|
this.Controls.Add(txtBox);
|
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
}
|
2025-03-10 18:34:45 -07:00
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
|
2025-03-10 18:34:45 -07:00
|
|
|
|
private void CreateButtons()
|
|
|
|
|
{
|
2025-03-04 20:20:08 -08:00
|
|
|
|
// OK button.
|
2025-03-10 18:34:45 -07:00
|
|
|
|
Button btnOk = new Button
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
|
|
|
|
Text = "OK",
|
|
|
|
|
Location = new Point(10, 80),
|
2025-03-05 10:07:49 -08:00
|
|
|
|
Size = new Size(80, 25),
|
|
|
|
|
DialogResult = DialogResult.OK,
|
|
|
|
|
Anchor = AnchorStyles.Left | AnchorStyles.Bottom
|
2025-03-04 20:20:08 -08:00
|
|
|
|
};
|
|
|
|
|
btnOk.Click += BtnOk_Click;
|
|
|
|
|
this.Controls.Add(btnOk);
|
|
|
|
|
|
|
|
|
|
// Cancel button.
|
2025-03-10 18:34:45 -07:00
|
|
|
|
Button btnCancel = new Button
|
2025-03-04 20:20:08 -08:00
|
|
|
|
{
|
|
|
|
|
Text = "Cancel",
|
2025-03-05 16:04:27 -08:00
|
|
|
|
Location = new Point(100, 80),
|
2025-03-05 10:07:49 -08:00
|
|
|
|
Size = new Size(80, 25),
|
|
|
|
|
DialogResult = DialogResult.Cancel,
|
|
|
|
|
Anchor = AnchorStyles.Left | AnchorStyles.Bottom
|
2025-03-04 20:20:08 -08:00
|
|
|
|
};
|
|
|
|
|
this.Controls.Add(btnCancel);
|
2025-03-05 16:04:27 -08:00
|
|
|
|
|
|
|
|
|
this.AcceptButton = btnOk;
|
|
|
|
|
this.CancelButton = btnCancel;
|
2025-03-04 20:20:08 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BtnOk_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
if (inputControl is ComboBox combo)
|
2025-03-05 16:04:27 -08:00
|
|
|
|
{
|
2025-03-10 18:34:45 -07:00
|
|
|
|
if (valueType == typeof(bool))
|
|
|
|
|
{
|
|
|
|
|
if (bool.TryParse(combo.SelectedItem?.ToString(), out bool boolVal))
|
|
|
|
|
NewValue = boolVal;
|
|
|
|
|
else
|
|
|
|
|
NewValue = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// For non-boolean values, return the selected string.
|
|
|
|
|
NewValue = combo.SelectedItem?.ToString() ?? string.Empty;
|
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
}
|
|
|
|
|
else if (inputControl is TextBox txt)
|
|
|
|
|
{
|
2025-03-11 19:43:44 -07:00
|
|
|
|
// Parse the value based on the expected type using invariant culture.
|
|
|
|
|
if (valueType == typeof(int) &&
|
|
|
|
|
int.TryParse(txt.Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out int intValue))
|
|
|
|
|
{
|
2025-03-04 20:20:08 -08:00
|
|
|
|
NewValue = intValue;
|
2025-03-11 19:43:44 -07:00
|
|
|
|
}
|
|
|
|
|
else if (valueType == typeof(double) &&
|
|
|
|
|
double.TryParse(txt.Text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double doubleValue))
|
|
|
|
|
{
|
|
|
|
|
NewValue = doubleValue;
|
|
|
|
|
}
|
|
|
|
|
else if (valueType == typeof(float) &&
|
|
|
|
|
float.TryParse(txt.Text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out float floatValue))
|
|
|
|
|
{
|
|
|
|
|
NewValue = floatValue;
|
|
|
|
|
}
|
|
|
|
|
else if (valueType == typeof(bool) &&
|
|
|
|
|
bool.TryParse(txt.Text, out bool boolValue))
|
|
|
|
|
{
|
|
|
|
|
NewValue = boolValue;
|
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
else
|
2025-03-11 19:43:44 -07:00
|
|
|
|
{
|
|
|
|
|
// Default to string if parsing fails.
|
2025-03-04 20:20:08 -08:00
|
|
|
|
NewValue = txt.Text;
|
2025-03-11 19:43:44 -07:00
|
|
|
|
}
|
2025-03-04 20:20:08 -08:00
|
|
|
|
}
|
|
|
|
|
this.DialogResult = DialogResult.OK;
|
|
|
|
|
this.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|