mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
Add TabColorConverter to fix Color to String conversion issue
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
This commit is contained in:
@@ -158,7 +158,7 @@ namespace mRemoteNG.Connection
|
||||
[LocalizedAttributes.LocalizedCategory(nameof(Language.Display)),
|
||||
LocalizedAttributes.LocalizedDisplayName(nameof(Language.TabColor)),
|
||||
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionTabColor)),
|
||||
TypeConverter(typeof(ColorConverter))]
|
||||
TypeConverter(typeof(MiscTools.TabColorConverter))]
|
||||
public virtual string TabColor
|
||||
{
|
||||
get => GetPropertyValue("TabColor", _tabColor);
|
||||
|
||||
@@ -268,5 +268,131 @@ namespace mRemoteNG.Tools
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
|
||||
public class TabColorConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
|
||||
{
|
||||
return sourceType == typeof(string) || sourceType == typeof(Color) || base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
|
||||
{
|
||||
return destinationType == typeof(string) || destinationType == typeof(Color) || base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object? value)
|
||||
{
|
||||
if (value == null || (value is string str && string.IsNullOrWhiteSpace(str)))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (value is string stringValue)
|
||||
{
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
if (value is Color colorValue)
|
||||
{
|
||||
// Convert Color to string representation
|
||||
// Use named color if it's a known color, otherwise use hex format
|
||||
if (colorValue.IsNamedColor)
|
||||
{
|
||||
return colorValue.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return hex format without alpha if fully opaque, otherwise include alpha
|
||||
if (colorValue.A == 255)
|
||||
{
|
||||
return $"#{colorValue.R:X2}{colorValue.G:X2}{colorValue.B:X2}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"#{colorValue.A:X2}{colorValue.R:X2}{colorValue.G:X2}{colorValue.B:X2}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
if (value == null || (value is string str && string.IsNullOrWhiteSpace(str)))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
return value.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
if (destinationType == typeof(Color))
|
||||
{
|
||||
if (value == null || (value is string str && string.IsNullOrWhiteSpace(str)))
|
||||
{
|
||||
return Color.Empty;
|
||||
}
|
||||
|
||||
if (value is string stringValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
ColorConverter converter = new ColorConverter();
|
||||
return converter.ConvertFromString(stringValue) ?? Color.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Color.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType) ?? throw new InvalidOperationException("Base conversion returned null.");
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext? context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext? context)
|
||||
{
|
||||
// Provide a list of common colors for the dropdown
|
||||
Color[] colors =
|
||||
[
|
||||
Color.Red,
|
||||
Color.Orange,
|
||||
Color.Yellow,
|
||||
Color.Green,
|
||||
Color.Blue,
|
||||
Color.Purple,
|
||||
Color.Pink,
|
||||
Color.Brown,
|
||||
Color.Black,
|
||||
Color.White,
|
||||
Color.Gray,
|
||||
Color.LightGray,
|
||||
Color.DarkGray,
|
||||
Color.Cyan,
|
||||
Color.Magenta,
|
||||
Color.Lime,
|
||||
Color.Navy,
|
||||
Color.Teal,
|
||||
Color.Maroon,
|
||||
Color.Olive
|
||||
];
|
||||
|
||||
return new StandardValuesCollection(colors);
|
||||
}
|
||||
|
||||
public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context)
|
||||
{
|
||||
// Return false to allow custom values (hex codes or other color names)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
148
mRemoteNGTests/Tools/TabColorConverterTests.cs
Normal file
148
mRemoteNGTests/Tools/TabColorConverterTests.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user