Merge branch 'v1.78.2-dev' into copilot/add-color-support-for-connection-folders

This commit is contained in:
Dimitrij
2025-10-07 21:24:50 +01:00
committed by GitHub
18 changed files with 398 additions and 13 deletions

View File

@@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- #2734: fix native build for Windows-x64
### Added
- Add configurable connection tab colors to distinguish between different environments (e.g., Dev, Test, Live)
- #2728 Add support for building mRemoteNG on Windows ARM64
- #2723: Read keyboardhook, gatewayaccesstoken and gatewaycredentialssource from RDP File
- #2690: தமிழ் (ta) Translation update

View File

@@ -42,6 +42,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("Descr", connectionInfo.Description));
element.Add(new XAttribute("Icon", connectionInfo.Icon));
element.Add(new XAttribute("Panel", connectionInfo.Panel));
element.Add(new XAttribute("TabColor", connectionInfo.TabColor));
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
if (!Runtime.UseCredentialManager)
@@ -187,6 +188,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
element.Add(new XAttribute("InheritIcon", inheritance.Icon.ToString().ToLowerInvariant()));
if (inheritance.Panel)
element.Add(new XAttribute("InheritPanel", inheritance.Panel.ToString().ToLowerInvariant()));
if (inheritance.TabColor)
element.Add(new XAttribute("InheritTabColor", inheritance.TabColor.ToString().ToLowerInvariant()));
if (inheritance.Password)
element.Add(new XAttribute("InheritPassword", inheritance.Password.ToString().ToLowerInvariant()));
if (inheritance.Port)

View File

@@ -328,6 +328,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.Inheritance.DisplayWallpaper = xmlnode.GetAttributeAsBool("InheritDisplayWallpaper");
connectionInfo.Inheritance.Icon = xmlnode.GetAttributeAsBool("InheritIcon");
connectionInfo.Inheritance.Panel = xmlnode.GetAttributeAsBool("InheritPanel");
connectionInfo.Inheritance.TabColor = xmlnode.GetAttributeAsBool("InheritTabColor");
connectionInfo.Inheritance.Port = xmlnode.GetAttributeAsBool("InheritPort");
connectionInfo.Inheritance.Protocol = xmlnode.GetAttributeAsBool("InheritProtocol");
connectionInfo.Inheritance.PuttySession = xmlnode.GetAttributeAsBool("InheritPuttySession");
@@ -350,6 +351,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml
connectionInfo.Icon = xmlnode.GetAttributeAsString("Icon");
connectionInfo.Panel = xmlnode.GetAttributeAsString("Panel");
connectionInfo.TabColor = xmlnode.GetAttributeAsString("TabColor");
}
else
{

View File

@@ -61,6 +61,10 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
if (host.Vnc)
finalProtocol = ProtocolType.VNC;
break;
case ProtocolType.ARD:
if (host.Vnc)
finalProtocol = ProtocolType.ARD;
break;
default:
protocolValid = false;
break;

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.RDP;
@@ -23,6 +24,7 @@ namespace mRemoteNG.Connection
private string _icon;
private string _panel;
private string _color;
private string _tabColor;
private string _hostname;
private ExternalAddressProvider _externalAddressProvider;
@@ -163,6 +165,13 @@ namespace mRemoteNG.Connection
{
get => GetPropertyValue("Color", _color);
set => SetField(ref _color, value, "Color");
LocalizedAttributes.LocalizedDisplayName(nameof(Language.TabColor)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionTabColor)),
TypeConverter(typeof(MiscTools.TabColorConverter))]
public virtual string TabColor
{
get => GetPropertyValue("TabColor", _tabColor);
set => SetField(ref _tabColor, value, "TabColor");
}
#endregion
@@ -920,7 +929,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.Compression)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionCompression)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public ProtocolVNC.Compression VNCCompression
{
@@ -932,7 +941,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.Encoding)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionEncoding)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public ProtocolVNC.Encoding VNCEncoding
{
@@ -944,7 +953,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.AuthenticationMode)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionAuthenticationMode)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public ProtocolVNC.AuthMode VNCAuthMode
{
@@ -956,7 +965,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ProxyType)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionVNCProxyType)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public ProtocolVNC.ProxyType VNCProxyType
{
@@ -967,7 +976,7 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory(nameof(Language.Proxy), 7),
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ProxyAddress)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionVNCProxyAddress)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public string VNCProxyIP
{
@@ -978,7 +987,7 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory(nameof(Language.Proxy), 7),
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ProxyPort)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionVNCProxyPort)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public int VNCProxyPort
{
@@ -989,7 +998,7 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory(nameof(Language.Proxy), 7),
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ProxyUsername)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionVNCProxyUsername)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public string VNCProxyUsername
{
@@ -1001,7 +1010,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ProxyPassword)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionVNCProxyPassword)),
PasswordPropertyText(true),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public string VNCProxyPassword
{
@@ -1013,7 +1022,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.Colors)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionColors)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC),
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD),
Browsable(false)]
public ProtocolVNC.Colors VNCColors
{
@@ -1025,7 +1034,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.SmartSizeMode)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionSmartSizeMode)),
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC)]
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD)]
public ProtocolVNC.SmartSizeMode VNCSmartSizeMode
{
get => GetPropertyValue("VNCSmartSizeMode", _vncSmartSizeMode);
@@ -1036,7 +1045,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName(nameof(Language.ViewOnly)),
LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionViewOnly)),
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
AttributeUsedInProtocol(ProtocolType.VNC)]
AttributeUsedInProtocol(ProtocolType.VNC, ProtocolType.ARD)]
public bool VNCViewOnly
{
get => GetPropertyValue("VNCViewOnly", _vncViewOnly);

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Reflection;
using mRemoteNG.App;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.ARD;
using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.PowerShell;
using mRemoteNG.Connection.Protocol.RAW;
@@ -254,6 +255,8 @@ namespace mRemoteNG.Connection
return (int)RdpProtocol.Defaults.Port;
case ProtocolType.VNC:
return (int)ProtocolVNC.Defaults.Port;
case ProtocolType.ARD:
return (int)ProtocolARD.Defaults.Port;
case ProtocolType.SSH1:
return (int)ProtocolSSH1.Defaults.Port;
case ProtocolType.SSH2:
@@ -290,6 +293,7 @@ namespace mRemoteNG.Connection
Icon = Settings.Default.ConDefaultIcon;
Panel = Language.General;
Color = string.Empty;
TabColor = string.Empty;
}
private void SetConnectionDefaults()

View File

@@ -55,6 +55,10 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDescriptionInherit(nameof(Language.PropertyDescriptionColor)),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
public bool Color { get; set; }
LocalizedAttributes.LocalizedDisplayNameInherit(nameof(Language.TabColor)),
LocalizedAttributes.LocalizedDescriptionInherit(nameof(Language.PropertyDescriptionTabColor)),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
public bool TabColor { get; set; }
#endregion

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Versioning;
using mRemoteNG.Connection.Protocol.VNC;
namespace mRemoteNG.Connection.Protocol.ARD
{
[SupportedOSPlatform("windows")]
public class ProtocolARD : ProtocolVNC
{
public ProtocolARD()
{
}
public new enum Defaults
{
Port = 5900
}
}
}

View File

@@ -5,6 +5,7 @@ using mRemoteNG.Connection.Protocol.Rlogin;
using mRemoteNG.Connection.Protocol.SSH;
using mRemoteNG.Connection.Protocol.Telnet;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Connection.Protocol.ARD;
using System;
using mRemoteNG.Connection.Protocol.PowerShell;
using mRemoteNG.Resources.Language;
@@ -28,6 +29,8 @@ namespace mRemoteNG.Connection.Protocol
return rdp;
case ProtocolType.VNC:
return new ProtocolVNC();
case ProtocolType.ARD:
return new ProtocolARD();
case ProtocolType.SSH1:
return new ProtocolSSH1();
case ProtocolType.SSH2:

View File

@@ -35,6 +35,9 @@ namespace mRemoteNG.Connection.Protocol
[LocalizedAttributes.LocalizedDescription(nameof(Language.PowerShell))]
PowerShell = 10,
[LocalizedAttributes.LocalizedDescription(nameof(Language.Ard))]
ARD = 11,
[LocalizedAttributes.LocalizedDescription(nameof(Language.ExternalTool))]
IntApp = 20
}

View File

@@ -159,6 +159,9 @@
<data name="AskUpdatesMainInstruction" xml:space="preserve">
<value>Automatic update settings</value>
</data>
<data name="Ard" xml:space="preserve">
<value>ARD (Apple Remote Desktop)</value>
</data>
<data name="Aspect" xml:space="preserve">
<value>Aspect</value>
</data>
@@ -1022,6 +1025,8 @@ If you run into such an error, please create a new connection file!</value>
</data>
<data name="PropertyDescriptionColor" xml:space="preserve">
<value>Sets the color for the connection or folder in the connections tree. Connections inherit this color from their parent folder.</value>
<data name="PropertyDescriptionTabColor" xml:space="preserve">
<value>Sets the color of the connection tab. Leave empty for default theme color.</value>
</data>
<data name="PropertyDescriptionPassword" xml:space="preserve">
<value>Enter your password.</value>
@@ -1188,6 +1193,9 @@ If you run into such an error, please create a new connection file!</value>
<data name="Panel" xml:space="preserve">
<value>Panel</value>
</data>
<data name="TabColor" xml:space="preserve">
<value>Tab Color</value>
</data>
<data name="Password" xml:space="preserve">
<value>Password</value>
</data>

View File

@@ -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;
}
}
}
}

View File

@@ -168,6 +168,7 @@ namespace mRemoteNG.UI.Controls.ConnectionInfoPropertyGrid
strHide.AddRange(SpecialRdpExclusions());
break;
case ProtocolType.VNC:
case ProtocolType.ARD:
strHide.AddRange(SpecialVncExclusions());
break;
}

View File

@@ -991,8 +991,11 @@ namespace mRemoteNG.UI.Tabs
rectText = DrawHelper.RtlTransform(this, rectText);
rectIcon = DrawHelper.RtlTransform(this, rectIcon);
Color activeColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedActive.Background;
Color lostFocusColor = DockPane.DockPanel.Theme.ColorPalette.TabSelectedInactive.Background;
// Get custom tab color if available
Color? customTabColor = GetCustomTabColor(tab.Content);
Color activeColor = customTabColor ?? DockPane.DockPanel.Theme.ColorPalette.TabSelectedActive.Background;
Color lostFocusColor = customTabColor ?? DockPane.DockPanel.Theme.ColorPalette.TabSelectedInactive.Background;
Color inactiveColor = DockPane.DockPanel.Theme.ColorPalette.MainWindowActive.Background;
Color mouseHoverColor = DockPane.DockPanel.Theme.ColorPalette.TabUnselectedHovered.Background;
@@ -1056,6 +1059,31 @@ namespace mRemoteNG.UI.Tabs
g.DrawIcon(tab.Content.DockHandler.Icon, rectIcon);
}
private Color? GetCustomTabColor(IDockContent content)
{
try
{
if (content is ConnectionTab connectionTab)
{
InterfaceControl interfaceControl = InterfaceControl.FindInterfaceControl(connectionTab);
if (interfaceControl?.Info != null)
{
string tabColorStr = interfaceControl.Info.TabColor;
if (!string.IsNullOrEmpty(tabColorStr))
{
ColorConverter converter = new ColorConverter();
return (Color)converter.ConvertFromString(tabColorStr);
}
}
}
}
catch
{
// If there's any error parsing the color, just return null to use default
}
return null;
}
private bool m_isMouseDown;
protected bool IsMouseDown

View File

@@ -776,6 +776,7 @@ namespace mRemoteNG.UI.Window
ProtocolBase protocolBase = sender as ProtocolBase;
if (!(protocolBase?.InterfaceControl.Parent is ConnectionTab tabPage)) return;
if (tabPage.Disposing || tabPage.IsDisposed) return;
if (IsDisposed || Disposing) return;
tabPage.protocolClose = true;
Invoke(new Action(() => tabPage.Close()));
}

View File

@@ -87,6 +87,26 @@ Icon
The icon indicates the visual identifier for the connection.
Clicking the icon will let you set a different icon for the connection.
Tab Color
---------
.. note::
The Tab Color property is available in the Display category of the connection properties.
You can set a custom color for connection tabs to help distinguish between different environments (e.g., Development, Testing, Production).
This can be especially useful when working with critical systems like Live servers, where you want a clear visual reminder.
To set a tab color:
1. Select your connection in the Connections panel
2. In the Config panel, expand the **Display** category
3. Find the **Tab Color** property
4. Enter a color name (e.g., "Red", "Green", "Blue") or a hex color code (e.g., "#FF0000", "#00FF00")
5. Leave empty to use the default theme color
The tab color will be applied when you open the connection. You can use inheritance to set the same color for multiple connections in a folder.
Status
------

View File

@@ -115,6 +115,7 @@ namespace mRemoteNGTests.Connection
[TestCase(ProtocolType.SSH2, ExpectedResult = 22)]
[TestCase(ProtocolType.Telnet, ExpectedResult = 23)]
[TestCase(ProtocolType.VNC, ExpectedResult = 5900)]
[TestCase(ProtocolType.ARD, ExpectedResult = 5900)]
public int GetDefaultPortReturnsCorrectPortForProtocol(ProtocolType protocolType)
{
_connectionInfo.Protocol = protocolType;

View 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);
}
}
}