mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-26 03:58:45 +08:00
This commit resolves multiple related issues with the Options dialog that caused freezing, crashes, and slow performance: **Problem 1: Infinite Recursive Loop** - Symptom: Options dialog would freeze when navigating between pages - Cause: LstOptionPages_SelectedIndexChanged event handler triggering itself infinitely - Fix: Added _isHandlingSelectionChange guard flag to prevent recursive calls **Problem 2: Disposed Object Exception** - Symptom: "Cannot access a disposed object" error after SSH connection workflow - Cause: Static FrmOptions instance was disposed but still referenced - Fix: Enhanced OptionsWindow.LoadOptionsForm() to detect disposal before use - Fix: Added FrmMain.RecreateOptionsForm() to recreate disposed forms transparently **Problem 3: Index Out of Range** - Symptom: "index must be less than 0" when accessing empty lstOptionPages - Cause: SetActivatedPage() tried to access Items[0] when collection was empty - Fix: Added bounds checking before accessing lstOptionPages.Items **Problem 4: NullReferenceException in OptionsPages** - Symptom: NullReferenceException in LoadRegistrySettings() across all pages - Cause: pageRegSettingsInstance was null when registry settings didn't exist - Fix: Added null checks and default instance creation in 8 OptionsPages **Problem 5: Slow Page Loading on Recreation** - Symptom: Second Options dialog open showed staggered page loading (~2.2 seconds) - Cause: Application.Idle async pattern loaded pages one-by-one - Fix: Replaced async loading with synchronous batch loading using BeginUpdate/EndUpdate **Files Modified:** - mRemoteNG/UI/Forms/frmOptions.cs - mRemoteNG/UI/Window/OptionsWindow.cs - mRemoteNG/UI/Forms/frmMain.cs - mRemoteNG/UI/Forms/OptionsPages/StartupExitPage.cs - mRemoteNG/UI/Forms/OptionsPages/NotificationsPage.cs - mRemoteNG/UI/Forms/OptionsPages/AppearancePage.cs - mRemoteNG/UI/Forms/OptionsPages/SecurityPage.cs - mRemoteNG/UI/Forms/OptionsPages/ConnectionsPage.cs - mRemoteNG/UI/Forms/OptionsPages/CredentialsPage.cs - mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs - mRemoteNG/UI/Forms/OptionsPages/UpdatesPage.cs **Additional Changes:** - Replaced all Debug.WriteLine with Logger.Instance.Log for consistent logging - Added comprehensive debug logging throughout Options form lifecycle - Improved defensive programming with guard flags and validation checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
168 lines
5.3 KiB
C#
168 lines
5.3 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using mRemoteNG.Tools;
|
|
using NUnit.Framework;
|
|
|
|
namespace mRemoteNGTests.Tools
|
|
{
|
|
public class TabColorConverterTests
|
|
{
|
|
private MiscTools.TabColorConverter _converter;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_converter = new MiscTools.TabColorConverter();
|
|
}
|
|
|
|
[TestCase(typeof(string), true)]
|
|
[TestCase(typeof(Color), true)]
|
|
public void CanConvertFrom(Type typeToConvertFrom, bool expectedOutcome)
|
|
{
|
|
var actualOutcome = _converter.CanConvertFrom(typeToConvertFrom);
|
|
Assert.That(actualOutcome, Is.EqualTo(expectedOutcome));
|
|
}
|
|
|
|
[TestCase(typeof(string), true)]
|
|
[TestCase(typeof(Color), true)]
|
|
public void CanConvertTo(Type typeToConvertTo, bool expectedOutcome)
|
|
{
|
|
var actualOutcome = _converter.CanConvertTo(typeToConvertTo);
|
|
Assert.That(actualOutcome, Is.EqualTo(expectedOutcome));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromColorToStringNamedColor()
|
|
{
|
|
var color = Color.Red;
|
|
var result = _converter.ConvertFrom(color);
|
|
Assert.That(result, Is.EqualTo("Red"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromColorToStringCustomColor()
|
|
{
|
|
var color = Color.FromArgb(255, 128, 64, 32);
|
|
var result = _converter.ConvertFrom(color);
|
|
Assert.That(result, Is.EqualTo("#80401F"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromColorToStringCustomColorWithAlpha()
|
|
{
|
|
var color = Color.FromArgb(128, 255, 0, 0);
|
|
var result = _converter.ConvertFrom(color);
|
|
Assert.That(result, Is.EqualTo("#80FF0000"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromStringReturnsString()
|
|
{
|
|
var colorString = "Blue";
|
|
var result = _converter.ConvertFrom(colorString);
|
|
Assert.That(result, Is.EqualTo("Blue"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromHexStringReturnsString()
|
|
{
|
|
var colorString = "#FF0000";
|
|
var result = _converter.ConvertFrom(colorString);
|
|
Assert.That(result, Is.EqualTo("#FF0000"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromNullReturnsEmptyString()
|
|
{
|
|
var result = _converter.ConvertFrom(null);
|
|
Assert.That(result, Is.EqualTo(string.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromEmptyStringReturnsEmptyString()
|
|
{
|
|
var result = _converter.ConvertFrom("");
|
|
Assert.That(result, Is.EqualTo(string.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertToStringFromString()
|
|
{
|
|
var colorString = "Green";
|
|
var result = _converter.ConvertTo(colorString, typeof(string));
|
|
Assert.That(result, Is.EqualTo("Green"));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertToColorFromNamedString()
|
|
{
|
|
var colorString = "Red";
|
|
var result = _converter.ConvertTo(colorString, typeof(Color));
|
|
Assert.That(result, Is.EqualTo(Color.Red));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertToColorFromHexString()
|
|
{
|
|
var colorString = "#FF0000";
|
|
var result = _converter.ConvertTo(colorString, typeof(Color));
|
|
var expectedColor = Color.FromArgb(255, 255, 0, 0);
|
|
Assert.That(result, Is.EqualTo(expectedColor));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertToColorFromEmptyStringReturnsEmpty()
|
|
{
|
|
var result = _converter.ConvertTo("", typeof(Color));
|
|
Assert.That(result, Is.EqualTo(Color.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertToColorFromNullReturnsEmpty()
|
|
{
|
|
var result = _converter.ConvertTo(null, typeof(Color));
|
|
Assert.That(result, Is.EqualTo(Color.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void GetStandardValuesSupportedReturnsTrue()
|
|
{
|
|
var result = _converter.GetStandardValuesSupported(null);
|
|
Assert.That(result, Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void GetStandardValuesReturnsColorList()
|
|
{
|
|
var result = _converter.GetStandardValues(null);
|
|
Assert.That(result, Is.Not.Null);
|
|
Assert.That(result.Count, Is.GreaterThan(0));
|
|
}
|
|
|
|
[Test]
|
|
public void GetStandardValuesExclusiveReturnsFalse()
|
|
{
|
|
var result = _converter.GetStandardValuesExclusive(null);
|
|
Assert.That(result, Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public void ConvertFromColorObjectDoesNotThrowException()
|
|
{
|
|
// This test verifies the fix for the "Object of type 'System.Drawing.Color' cannot be converted to type 'System.String'" error
|
|
var color = Color.FromArgb(255, 100, 150, 200);
|
|
Assert.DoesNotThrow(() => _converter.ConvertFrom(color));
|
|
}
|
|
|
|
[Test]
|
|
public void ColorPropertyUsesTabColorConverter()
|
|
{
|
|
// This test verifies that the Color property can properly handle Color objects
|
|
// by using TabColorConverter instead of System.Drawing.ColorConverter
|
|
var color = Color.Blue;
|
|
var result = _converter.ConvertFrom(color);
|
|
Assert.That(result, Is.EqualTo("Blue"));
|
|
}
|
|
}
|
|
}
|