diff --git a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs index 0e8743f3..afa6c06e 100644 --- a/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs +++ b/mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionNodeSerializer28.cs @@ -43,6 +43,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml 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("ConnectionFrameColor", connectionInfo.ConnectionFrameColor)); element.Add(new XAttribute("Id", connectionInfo.ConstantID)); if (!Runtime.UseCredentialManager) @@ -195,6 +196,8 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml element.Add(new XAttribute("InheritPanel", inheritance.Panel.ToString().ToLowerInvariant())); if (inheritance.TabColor) element.Add(new XAttribute("InheritTabColor", inheritance.TabColor.ToString().ToLowerInvariant())); + if (inheritance.ConnectionFrameColor) + element.Add(new XAttribute("InheritConnectionFrameColor", inheritance.ConnectionFrameColor.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 8b4b523f..66e28834 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.Icon = xmlnode.GetAttributeAsBool("InheritIcon"); connectionInfo.Inheritance.Panel = xmlnode.GetAttributeAsBool("InheritPanel"); connectionInfo.Inheritance.TabColor = xmlnode.GetAttributeAsBool("InheritTabColor"); + connectionInfo.Inheritance.ConnectionFrameColor = xmlnode.GetAttributeAsBool("InheritConnectionFrameColor"); connectionInfo.Inheritance.Port = xmlnode.GetAttributeAsBool("InheritPort"); connectionInfo.Inheritance.Protocol = xmlnode.GetAttributeAsBool("InheritProtocol"); connectionInfo.Inheritance.PuttySession = xmlnode.GetAttributeAsBool("InheritPuttySession"); @@ -351,6 +352,7 @@ namespace mRemoteNG.Config.Serializers.ConnectionSerializers.Xml connectionInfo.Icon = xmlnode.GetAttributeAsString("Icon"); connectionInfo.Panel = xmlnode.GetAttributeAsString("Panel"); connectionInfo.TabColor = xmlnode.GetAttributeAsString("TabColor"); + connectionInfo.ConnectionFrameColor = xmlnode.GetAttributeAsEnum("ConnectionFrameColor"); } else { diff --git a/mRemoteNG/Connection/AbstractConnectionRecord.cs b/mRemoteNG/Connection/AbstractConnectionRecord.cs index d0ddbc4b..37c756d7 100644 --- a/mRemoteNG/Connection/AbstractConnectionRecord.cs +++ b/mRemoteNG/Connection/AbstractConnectionRecord.cs @@ -25,6 +25,7 @@ namespace mRemoteNG.Connection private string _panel; private string _color; private string _tabColor; + private ConnectionFrameColor _connectionFrameColor; private string _hostname; private ExternalAddressProvider _externalAddressProvider; @@ -181,6 +182,16 @@ namespace mRemoteNG.Connection set => SetField(ref _tabColor, value, "TabColor"); } + [LocalizedAttributes.LocalizedCategory(nameof(Language.Display)), + LocalizedAttributes.LocalizedDisplayName(nameof(Language.ConnectionFrameColor)), + LocalizedAttributes.LocalizedDescription(nameof(Language.PropertyDescriptionConnectionFrameColor)), + TypeConverter(typeof(MiscTools.EnumTypeConverter))] + public virtual ConnectionFrameColor ConnectionFrameColor + { + get => GetPropertyValue("ConnectionFrameColor", _connectionFrameColor); + set => SetField(ref _connectionFrameColor, value, "ConnectionFrameColor"); + } + #endregion #region Connection diff --git a/mRemoteNG/Connection/ConnectionFrameColor.cs b/mRemoteNG/Connection/ConnectionFrameColor.cs new file mode 100644 index 00000000..fc156490 --- /dev/null +++ b/mRemoteNG/Connection/ConnectionFrameColor.cs @@ -0,0 +1,26 @@ +using mRemoteNG.Tools; +using mRemoteNG.Resources.Language; + +namespace mRemoteNG.Connection +{ + public enum ConnectionFrameColor + { + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorNone))] + None = 0, + + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorRed))] + Red = 1, + + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorYellow))] + Yellow = 2, + + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorGreen))] + Green = 3, + + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorBlue))] + Blue = 4, + + [LocalizedAttributes.LocalizedDescription(nameof(Language.FrameColorPurple))] + Purple = 5 + } +} diff --git a/mRemoteNG/Connection/ConnectionInfo.cs b/mRemoteNG/Connection/ConnectionInfo.cs index 5e35c122..daf2d2af 100644 --- a/mRemoteNG/Connection/ConnectionInfo.cs +++ b/mRemoteNG/Connection/ConnectionInfo.cs @@ -294,6 +294,7 @@ namespace mRemoteNG.Connection Panel = Language.General; Color = string.Empty; TabColor = string.Empty; + ConnectionFrameColor = ConnectionFrameColor.None; } private void SetConnectionDefaults() diff --git a/mRemoteNG/Connection/ConnectionInfoInheritance.cs b/mRemoteNG/Connection/ConnectionInfoInheritance.cs index 27853152..a21d6294 100644 --- a/mRemoteNG/Connection/ConnectionInfoInheritance.cs +++ b/mRemoteNG/Connection/ConnectionInfoInheritance.cs @@ -62,6 +62,12 @@ namespace mRemoteNG.Connection TypeConverter(typeof(MiscTools.YesNoTypeConverter))] public bool TabColor { get; set; } + [LocalizedAttributes.LocalizedCategory(nameof(Language.Display), 2), + LocalizedAttributes.LocalizedDisplayNameInherit(nameof(Language.ConnectionFrameColor)), + LocalizedAttributes.LocalizedDescriptionInherit(nameof(Language.PropertyDescriptionConnectionFrameColor)), + TypeConverter(typeof(MiscTools.YesNoTypeConverter))] + public bool ConnectionFrameColor { get; set; } + #endregion #region Connection diff --git a/mRemoteNG/Connection/InterfaceControl.cs b/mRemoteNG/Connection/InterfaceControl.cs index cc10f2a6..4ff3780e 100644 --- a/mRemoteNG/Connection/InterfaceControl.cs +++ b/mRemoteNG/Connection/InterfaceControl.cs @@ -32,6 +32,9 @@ namespace mRemoteNG.Connection Size = Parent.Size; Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; InitializeComponent(); + + // Enable custom painting for border + this.Paint += InterfaceControl_Paint; } catch (Exception ex) { @@ -41,6 +44,41 @@ namespace mRemoteNG.Connection } } + private void InterfaceControl_Paint(object sender, PaintEventArgs e) + { + // Draw colored border based on ConnectionFrameColor property + if (Info?.ConnectionFrameColor != null && Info.ConnectionFrameColor != ConnectionFrameColor.None) + { + Color frameColor = GetFrameColor(Info.ConnectionFrameColor); + int borderWidth = 4; // 4 pixel border for visibility + + using (Pen pen = new Pen(frameColor, borderWidth)) + { + // Draw border inside the control bounds + Rectangle rect = new Rectangle( + borderWidth / 2, + borderWidth / 2, + this.Width - borderWidth, + this.Height - borderWidth + ); + e.Graphics.DrawRectangle(pen, rect); + } + } + } + + private Color GetFrameColor(ConnectionFrameColor frameColor) + { + return frameColor switch + { + ConnectionFrameColor.Red => Color.FromArgb(220, 53, 69), // Bootstrap danger red + ConnectionFrameColor.Yellow => Color.FromArgb(255, 193, 7), // Warning yellow + ConnectionFrameColor.Green => Color.FromArgb(40, 167, 69), // Success green + ConnectionFrameColor.Blue => Color.FromArgb(0, 123, 255), // Primary blue + ConnectionFrameColor.Purple => Color.FromArgb(111, 66, 193), // Purple + _ => Color.Transparent + }; + } + public static InterfaceControl FindInterfaceControl(DockPanel DockPnl) { // instead of repeating the code, call the routine using ConnectionTab if called by DockPanel diff --git a/mRemoteNG/Language/Language.resx b/mRemoteNG/Language/Language.resx index aafda966..c014728c 100644 --- a/mRemoteNG/Language/Language.resx +++ b/mRemoteNG/Language/Language.resx @@ -2517,4 +2517,28 @@ Nightly Channel includes Alphas, Betas & Release Candidates. Community Reddit + + Connection Frame Color + + + Sets a colored border around the connection panel to visually distinguish between different environments (e.g., production, test, development). + + + None + + + Red (Production) + + + Yellow (Staging/UAT) + + + Green (Test) + + + Blue (Development) + + + Purple (Custom) + \ No newline at end of file