diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de0838a0..e63bba606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs index 06bb61246..a12d8ed78 100644 --- a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs +++ b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs @@ -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) diff --git a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs index ab6c15a05..7f053ea1d 100644 --- a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs +++ b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs @@ -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 { diff --git a/mRemoteNG/Connection/AbstractConnectionRecord.cs b/mRemoteNG/Connection/AbstractConnectionRecord.cs index 74ff6e15a..c16b0ec60 100644 --- a/mRemoteNG/Connection/AbstractConnectionRecord.cs +++ b/mRemoteNG/Connection/AbstractConnectionRecord.cs @@ -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; @@ -22,6 +23,7 @@ namespace mRemoteNG.Connection private string _description; private string _icon; private string _panel; + private string _tabColor; private string _hostname; private ExternalAddressProvider _externalAddressProvider; @@ -153,6 +155,16 @@ namespace mRemoteNG.Connection set => SetField(ref _panel, value, "Panel"); } + [LocalizedAttributes.LocalizedCategory(nameof(Language.Display)), + LocalizedAttributes.LocalizedDisplayName(nameof(Language.TabColor)), + LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionTabColor)), + TypeConverter(typeof(ColorConverter))] + public virtual string TabColor + { + get => GetPropertyValue("TabColor", _tabColor); + set => SetField(ref _tabColor, value, "TabColor"); + } + #endregion #region Connection diff --git a/mRemoteNG/Connection/ConnectionInfo.cs b/mRemoteNG/Connection/ConnectionInfo.cs index f65384368..0e02383a8 100644 --- a/mRemoteNG/Connection/ConnectionInfo.cs +++ b/mRemoteNG/Connection/ConnectionInfo.cs @@ -289,6 +289,7 @@ namespace mRemoteNG.Connection Description = Settings.Default.ConDefaultDescription; Icon = Settings.Default.ConDefaultIcon; Panel = Language.General; + TabColor = ""; } private void SetConnectionDefaults() diff --git a/mRemoteNG/Connection/ConnectionInfoInheritance.cs b/mRemoteNG/Connection/ConnectionInfoInheritance.cs index 1c0e2281f..ec2ca3ea2 100644 --- a/mRemoteNG/Connection/ConnectionInfoInheritance.cs +++ b/mRemoteNG/Connection/ConnectionInfoInheritance.cs @@ -50,6 +50,12 @@ namespace mRemoteNG.Connection TypeConverter(typeof(MiscTools.YesNoTypeConverter))] public bool Panel { get; set; } + [LocalizedAttributes.LocalizedCategory(nameof(Language.Display), 2), + LocalizedAttributes.LocalizedDisplayNameInherit(nameof(Language.TabColor)), + LocalizedAttributes.LocalizedDescriptionInherit(nameof(Language.PropertyDescriptionTabColor)), + TypeConverter(typeof(MiscTools.YesNoTypeConverter))] + public bool TabColor { get; set; } + #endregion #region Connection diff --git a/mRemoteNG/Language/Language.resx b/mRemoteNG/Language/Language.resx index 311c87c40..f4297a933 100644 --- a/mRemoteNG/Language/Language.resx +++ b/mRemoteNG/Language/Language.resx @@ -1020,6 +1020,9 @@ If you run into such an error, please create a new connection file! Sets the panel in which the connection will open. + + Sets the color of the connection tab. Leave empty for default theme color. + Enter your password. @@ -1182,6 +1185,9 @@ If you run into such an error, please create a new connection file! Panel + + Tab Color + Password diff --git a/mRemoteNG/UI/Tabs/DockPaneStripNG.cs b/mRemoteNG/UI/Tabs/DockPaneStripNG.cs index a149ebbfc..0360d64e6 100644 --- a/mRemoteNG/UI/Tabs/DockPaneStripNG.cs +++ b/mRemoteNG/UI/Tabs/DockPaneStripNG.cs @@ -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 diff --git a/mRemoteNGDocumentation/user_interface/connections.rst b/mRemoteNGDocumentation/user_interface/connections.rst index 84aa31e41..763730ea2 100644 --- a/mRemoteNGDocumentation/user_interface/connections.rst +++ b/mRemoteNGDocumentation/user_interface/connections.rst @@ -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 ------