241 lines
9.4 KiB
C#
Raw Permalink Normal View History

2025-03-04 20:20:08 -08:00
using System;
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;
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
{
this.MinimumSize = new Size(210, 120);
this.AutoScaleMode = AutoScaleMode.None;
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-10 18:34:45 -07:00
// Measure text widths for layout.
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
{
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-10 18:34:45 -07:00
comboItemsWidth += 20; // extra padding for dropdown arrow and margin.
2025-03-05 10:07:49 -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-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;
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-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-10 18:34:45 -07:00
combo.Items.Add(item);
}
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-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-10 18:34:45 -07:00
if (!string.IsNullOrEmpty(selectedKey) && combo.Items.Contains(selectedKey))
{
2025-03-10 18:34:45 -07:00
combo.SelectedItem = selectedKey;
}
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.
if (valueType == typeof(bool))
2025-03-04 20:20:08 -08:00
{
2025-03-10 18:34:45 -07:00
ComboBox combo = new ComboBox
{
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;
}
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
{
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",
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);
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-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)
{
// 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;
}
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
{
// Default to string if parsing fails.
2025-03-04 20:20:08 -08:00
NewValue = txt.Text;
}
2025-03-04 20:20:08 -08:00
}
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}