diff --git a/mRemoteV1/Properties/Resources.Designer.cs b/mRemoteV1/Properties/Resources.Designer.cs
index a76bf5d6..84b6fe23 100644
--- a/mRemoteV1/Properties/Resources.Designer.cs
+++ b/mRemoteV1/Properties/Resources.Designer.cs
@@ -270,6 +270,16 @@ namespace mRemoteNG {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ConnectedOverlay {
+ get {
+ object obj = ResourceManager.GetObject("ConnectedOverlay", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/mRemoteV1/Properties/Resources.resx b/mRemoteV1/Properties/Resources.resx
index 3dcd32c7..dda31e5f 100644
--- a/mRemoteV1/Properties/Resources.resx
+++ b/mRemoteV1/Properties/Resources.resx
@@ -523,4 +523,7 @@
..\Resources\Images\FamFamFam\exclamation.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Resources\Images\ConnectedOverlay.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
\ No newline at end of file
diff --git a/mRemoteV1/Resources/Images/ConnectedOverlay.png b/mRemoteV1/Resources/Images/ConnectedOverlay.png
new file mode 100644
index 00000000..4baac4bb
Binary files /dev/null and b/mRemoteV1/Resources/Images/ConnectedOverlay.png differ
diff --git a/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs b/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
index 46347eea..b36aff7a 100644
--- a/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
+++ b/mRemoteV1/Tools/ConnectionsTreeToMenuItemsConverter.cs
@@ -6,15 +6,16 @@ using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Tree;
+using mRemoteNG.UI.Controls;
namespace mRemoteNG.Tools
{
public class ConnectionsTreeToMenuItemsConverter
{
+ private readonly StatusImageList _statusImageList = new StatusImageList();
public MouseEventHandler MouseUpEventHandler { get; set; }
-
public IEnumerable CreateToolStripDropDownItems(ConnectionTreeModel connectionTreeModel)
{
var rootNodes = connectionTreeModel.RootNodes;
@@ -49,26 +50,15 @@ namespace mRemoteNG.Tools
var menuItem = new ToolStripMenuItem
{
Text = node.Name,
- Tag = node
+ Tag = node,
+ Image = _statusImageList.GetImage(node)
};
var nodeAsContainer = node as ContainerInfo;
if (nodeAsContainer != null)
{
- menuItem.Image = Resources.Folder;
- menuItem.Tag = nodeAsContainer;
AddSubMenuNodes(nodeAsContainer.Children, menuItem);
}
- else if (node.GetTreeNodeType() == TreeNodeType.PuttySession)
- {
- menuItem.Image = Resources.PuttySessions;
- menuItem.Tag = node;
- }
- else if (node.GetTreeNodeType() == TreeNodeType.Connection)
- {
- menuItem.Image = Resources.Pause;
- menuItem.Tag = node;
- }
menuItem.MouseUp += MouseUpEventHandler;
return menuItem;
diff --git a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs
index 2c3c0b1c..637ff174 100644
--- a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs
+++ b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.Designer.cs
@@ -7,19 +7,6 @@
///
private System.ComponentModel.IContainer components = null;
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
#region Component Designer generated code
///
diff --git a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
index 574d74db..337ff811 100644
--- a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
+++ b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
@@ -20,6 +20,7 @@ namespace mRemoteNG.UI.Controls
private ConnectionTreeModel _connectionTreeModel;
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
+ private readonly StatusImageList _statusImageList = new StatusImageList();
public ConnectionInfo SelectedNode
{
@@ -46,7 +47,6 @@ namespace mRemoteNG.UI.Controls
}
}
-
public ConnectionTree()
{
InitializeComponent();
@@ -54,12 +54,22 @@ namespace mRemoteNG.UI.Controls
UseOverlays = false;
}
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ components?.Dispose();
+ _statusImageList?.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+
#region ConnectionTree Setup
private void SetupConnectionTreeView()
{
- var imageList = new StatusImageList();
- SmallImageList = imageList.GetImageList();
- AddColumns(imageList.ImageGetter);
+ SmallImageList = _statusImageList.ImageList;
+ AddColumns(_statusImageList.ImageGetter);
LinkModelToView();
SetupDropSink();
SetEventHandlers();
@@ -144,7 +154,13 @@ namespace mRemoteNG.UI.Controls
{
//TODO for some reason property changed events are getting triggered twice for each changed property. should be just once. cant find source of duplication
var property = propertyChangedEventArgs.PropertyName;
- if (property != "Name" && property != "OpenConnections") return;
+ if (property != nameof(ConnectionInfo.Name)
+ && property != nameof(ConnectionInfo.OpenConnections)
+ && property != nameof(ConnectionInfo.Icon))
+ {
+ return;
+ }
+
var senderAsConnectionInfo = sender as ConnectionInfo;
if (senderAsConnectionInfo != null)
RefreshObject(senderAsConnectionInfo);
diff --git a/mRemoteV1/UI/Controls/StatusImageList.cs b/mRemoteV1/UI/Controls/StatusImageList.cs
index b5a2413d..aa8f073e 100644
--- a/mRemoteV1/UI/Controls/StatusImageList.cs
+++ b/mRemoteV1/UI/Controls/StatusImageList.cs
@@ -9,49 +9,104 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.UI.Controls
{
- public class StatusImageList
+ public class StatusImageList : IDisposable
{
- public ImageList GetImageList()
+ public ImageList ImageList { get; }
+
+ public StatusImageList()
{
- var imageList = new ImageList
+ ImageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
ImageSize = new Size(16, 16),
TransparentColor = Color.Transparent
};
- FillImageList(imageList);
- return imageList;
+
+ FillImageList(ImageList);
}
public object ImageGetter(object rowObject)
{
- if (rowObject is RootPuttySessionsNodeInfo) return "PuttySessions";
- if (rowObject is RootNodeInfo) return "Root";
- if (rowObject is ContainerInfo) return "Folder";
- var connection = rowObject as ConnectionInfo;
- if (connection == null) return "";
- return connection.OpenConnections.Count > 0 ? "Play" : "Pause";
+ return GetKey(rowObject as ConnectionInfo);
}
- private void FillImageList(ImageList imageList)
+ public Image GetImage(ConnectionInfo connectionInfo)
+ {
+ var key = GetKey(connectionInfo);
+ return ImageList.Images.ContainsKey(key)
+ ? ImageList.Images[key]
+ : null;
+ }
+
+ public string GetKey(ConnectionInfo connectionInfo)
+ {
+ if (connectionInfo == null) return "";
+ if (connectionInfo is RootPuttySessionsNodeInfo) return "PuttySessions";
+ if (connectionInfo is RootNodeInfo) return "Root";
+ if (connectionInfo is ContainerInfo) return "Folder";
+
+ return GetConnectionIcon(connectionInfo);
+ }
+
+ private static string BuildConnectionIconName(string icon, bool connected)
+ {
+ var status = connected ? "Play" : "Default";
+ return $"Connection_{icon}_{status}";
+ }
+
+ private const string DefaultConnectionIcon = "";
+
+ private string GetConnectionIcon(ConnectionInfo connection)
+ {
+ if (string.IsNullOrEmpty(connection.Icon))
+ {
+ return DefaultConnectionIcon;
+ }
+
+ var connected = connection.OpenConnections.Count > 0;
+ var name = BuildConnectionIconName(connection.Icon, connected);
+ if (!ImageList.Images.ContainsKey(name))
+ {
+ var image = ConnectionIcon.FromString(connection.Icon);
+ if (image == null)
+ {
+ return DefaultConnectionIcon;
+ }
+
+ ImageList.Images.Add(BuildConnectionIconName(connection.Icon, false), image);
+ ImageList.Images.Add(BuildConnectionIconName(connection.Icon, true), Overlay(image, Resources.ConnectedOverlay));
+
+ }
+ return name;
+ }
+
+ private static Bitmap Overlay(Icon background, Image foreground)
+ {
+ var result = background.ToBitmap();
+ using (var gr = Graphics.FromImage(result))
+ {
+ gr.DrawImage(foreground, new Rectangle(0, 0, foreground.Width, foreground.Height));
+ }
+ return result;
+ }
+
+ private static void FillImageList(ImageList imageList)
{
try
{
- imageList.Images.Add(Resources.Root);
- imageList.Images.SetKeyName(0, "Root");
- imageList.Images.Add(Resources.Folder);
- imageList.Images.SetKeyName(1, "Folder");
- imageList.Images.Add(Resources.Play);
- imageList.Images.SetKeyName(2, "Play");
- imageList.Images.Add(Resources.Pause);
- imageList.Images.SetKeyName(3, "Pause");
- imageList.Images.Add(Resources.PuttySessions);
- imageList.Images.SetKeyName(4, "PuttySessions");
+ imageList.Images.Add("Root", Resources.Root);
+ imageList.Images.Add("Folder", Resources.Folder);
+ imageList.Images.Add("PuttySessions", Resources.PuttySessions);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionStackTrace($"Unable to fill the image list of type {nameof(StatusImageList)}", ex);
}
}
+
+ public void Dispose()
+ {
+ ImageList?.Dispose();
+ }
}
}
\ No newline at end of file
diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj
index b3474d7f..bde11ba6 100644
--- a/mRemoteV1/mRemoteV1.csproj
+++ b/mRemoteV1/mRemoteV1.csproj
@@ -1194,6 +1194,7 @@
+