mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
moved all click-actions for the tree to separate classes to make them easily composable
this has the nice effect of also pushing any calls to the settings class outside the classes that are actualy doing work, making them much easier to test in isolation
This commit is contained in:
28
mRemoteV1/Tree/ExpandNodeClickHandler.cs
Normal file
28
mRemoteV1/Tree/ExpandNodeClickHandler.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.UI.Controls;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class ExpandNodeClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
private readonly ConnectionTree _connectionTree;
|
||||
|
||||
public ExpandNodeClickHandler(ConnectionTree connectionTree)
|
||||
{
|
||||
if (connectionTree == null)
|
||||
throw new ArgumentNullException(nameof(connectionTree));
|
||||
|
||||
_connectionTree = connectionTree;
|
||||
}
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
var clickedNodeAsContainer = clickedNode as ContainerInfo;
|
||||
if (clickedNodeAsContainer == null) return;
|
||||
_connectionTree.ToggleExpansion(clickedNodeAsContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
mRemoteV1/Tree/ITreeNodeClickHandler.cs
Normal file
10
mRemoteV1/Tree/ITreeNodeClickHandler.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public interface ITreeNodeClickHandler
|
||||
{
|
||||
void Execute(ConnectionInfo clickedNode);
|
||||
}
|
||||
}
|
||||
15
mRemoteV1/Tree/OpenConnectionClickHandler.cs
Normal file
15
mRemoteV1/Tree/OpenConnectionClickHandler.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class OpenConnectionClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null) return;
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
ConnectionInitiator.OpenConnection(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
mRemoteV1/Tree/SwitchToConnectionClickHandler.cs
Normal file
15
mRemoteV1/Tree/SwitchToConnectionClickHandler.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class SwitchToConnectionClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null) return;
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
ConnectionInitiator.SwitchToOpenConnection(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
mRemoteV1/Tree/TreeNodeDoubleClickHandler.cs
Normal file
20
mRemoteV1/Tree/TreeNodeDoubleClickHandler.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class TreeNodeDoubleClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
public IEnumerable<ITreeNodeClickHandler> ClickHandlers { get; set; } = new ITreeNodeClickHandler[0];
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null) return;
|
||||
foreach (var handler in ClickHandlers)
|
||||
{
|
||||
handler.Execute(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
mRemoteV1/Tree/TreeNodeSingleClickHandler.cs
Normal file
20
mRemoteV1/Tree/TreeNodeSingleClickHandler.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using mRemoteNG.Connection;
|
||||
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public class TreeNodeSingleClickHandler : ITreeNodeClickHandler
|
||||
{
|
||||
public IEnumerable<ITreeNodeClickHandler> ClickHandlers { get; set; } = new ITreeNodeClickHandler[0];
|
||||
|
||||
public void Execute(ConnectionInfo clickedNode)
|
||||
{
|
||||
if (clickedNode == null) return;
|
||||
foreach (var handler in ClickHandlers)
|
||||
{
|
||||
handler.Execute(clickedNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
public IEnumerable<IConnectionTreeDelegate> PostSetupActions { get; set; } = new IConnectionTreeDelegate[0];
|
||||
|
||||
public TreeNodeDoubleClickHandler DoubleClickHandler { get; set; } = new TreeNodeDoubleClickHandler();
|
||||
|
||||
public TreeNodeSingleClickHandler SingleClickHandler { get; set; } = new TreeNodeSingleClickHandler();
|
||||
|
||||
|
||||
public ConnectionTreeModel ConnectionTreeModel
|
||||
{
|
||||
get { return _connectionTreeModel; }
|
||||
@@ -149,6 +154,66 @@ namespace mRemoteNG.UI.Controls
|
||||
#endregion
|
||||
|
||||
#region ConnectionTree Behavior
|
||||
public RootNodeInfo GetRootConnectionNode()
|
||||
{
|
||||
return (RootNodeInfo)Roots.Cast<ConnectionInfo>().First(item => item is RootNodeInfo);
|
||||
}
|
||||
|
||||
public IEnumerable<RootPuttySessionsNodeInfo> GetRootPuttyNodes()
|
||||
{
|
||||
return Objects.OfType<RootPuttySessionsNodeInfo>();
|
||||
}
|
||||
|
||||
public void AddConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ConnectionInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("UI.Window.Tree.AddConnection() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ContainerInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strErrorAddFolderFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
newNode.SetParent(parent);
|
||||
Expand(parent);
|
||||
SelectObject(newNode);
|
||||
EnsureModelVisible(newNode);
|
||||
}
|
||||
|
||||
public void DuplicateSelectedNode()
|
||||
{
|
||||
var newNode = SelectedNode.Clone();
|
||||
newNode.Parent.SetChildBelow(newNode, SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void RenameSelectedNode()
|
||||
{
|
||||
SelectedItem.BeginEdit();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void DeleteSelectedNode()
|
||||
{
|
||||
if (SelectedNode is RootNodeInfo || SelectedNode is PuttySessionInfo) return;
|
||||
@@ -189,43 +254,6 @@ namespace mRemoteNG.UI.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public void AddConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ConnectionInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("UI.Window.Tree.AddConnection() failed.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
AddNode(new ContainerInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace(Language.strErrorAddFolderFailed, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode == null) return;
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
DefaultConnectionInheritance.Instance.SaveTo(newNode.Inheritance);
|
||||
var selectedContainer = SelectedNode as ContainerInfo;
|
||||
var parent = selectedContainer ?? SelectedNode?.Parent;
|
||||
newNode.SetParent(parent);
|
||||
Expand(parent);
|
||||
SelectObject(newNode);
|
||||
EnsureModelVisible(newNode);
|
||||
}
|
||||
|
||||
private void tvConnections_AfterSelect(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
@@ -240,40 +268,16 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void tvConnections_NodeMouseSingleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ClickCount > 1) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
|
||||
if (clickedNode == null) return;
|
||||
if (clickedNode.GetTreeNodeType() != TreeNodeType.Connection && clickedNode.GetTreeNodeType() != TreeNodeType.PuttySession) return;
|
||||
if (Settings.Default.SingleClickOnConnectionOpensIt)
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
|
||||
if (Settings.Default.SingleClickSwitchesToOpenConnection)
|
||||
ConnectionInitiator.SwitchToOpenConnection(SelectedNode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_NodeMouseClick (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
if (e.ClickCount > 1) return;
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
SingleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
private void tvConnections_NodeMouseDoubleClick(object sender, CellClickEventArgs e)
|
||||
{
|
||||
if (e.ClickCount < 2) return;
|
||||
var clickedNodeAsContainer = e.Model as ContainerInfo;
|
||||
if (clickedNodeAsContainer != null)
|
||||
{
|
||||
ToggleExpansion(clickedNodeAsContainer);
|
||||
}
|
||||
|
||||
var clickedNode = e.Model as ConnectionInfo;
|
||||
if (clickedNode?.GetTreeNodeType() == TreeNodeType.Connection |
|
||||
clickedNode?.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
{
|
||||
ConnectionInitiator.OpenConnection(SelectedNode);
|
||||
}
|
||||
DoubleClickHandler.Execute(clickedNode);
|
||||
}
|
||||
|
||||
private void tvConnections_CellToolTipShowing(object sender, ToolTipShowingEventArgs e)
|
||||
@@ -288,29 +292,6 @@ namespace mRemoteNG.UI.Controls
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_MouseMove (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public RootNodeInfo GetRootConnectionNode()
|
||||
{
|
||||
return (RootNodeInfo)Roots.Cast<ConnectionInfo>().First(item => item is RootNodeInfo);
|
||||
}
|
||||
|
||||
public IEnumerable<RootPuttySessionsNodeInfo> GetRootPuttyNodes()
|
||||
{
|
||||
return Objects.OfType<RootPuttySessionsNodeInfo>();
|
||||
}
|
||||
|
||||
public void DuplicateSelectedNode()
|
||||
{
|
||||
var newNode = SelectedNode.Clone();
|
||||
newNode.Parent.SetChildBelow(newNode, SelectedNode);
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
|
||||
public void RenameSelectedNode()
|
||||
{
|
||||
SelectedItem.BeginEdit();
|
||||
Runtime.SaveConnectionsAsync();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
@@ -33,6 +34,7 @@ namespace mRemoteNG.UI.Window
|
||||
olvConnections.ContextMenuStrip = _contextMenu;
|
||||
SetMenuEventHandlers();
|
||||
SetConnectionTreeEventHandlers();
|
||||
Settings.Default.PropertyChanged += (sender, args) => SetConnectionTreeEventHandlers();
|
||||
}
|
||||
|
||||
#region Form Stuff
|
||||
@@ -90,6 +92,28 @@ namespace mRemoteNG.UI.Window
|
||||
new RootNodeExpander(),
|
||||
new PreviousSessionOpener()
|
||||
};
|
||||
SetConnectionTreeDoubleClickHandlers();
|
||||
SetConnectionTreeSingleClickHandlers();
|
||||
}
|
||||
|
||||
private void SetConnectionTreeDoubleClickHandlers()
|
||||
{
|
||||
olvConnections.DoubleClickHandler.ClickHandlers = new ITreeNodeClickHandler[]
|
||||
{
|
||||
new ExpandNodeClickHandler(olvConnections),
|
||||
new OpenConnectionClickHandler()
|
||||
};
|
||||
}
|
||||
|
||||
private void SetConnectionTreeSingleClickHandlers()
|
||||
{
|
||||
|
||||
var singleClickHandlers = new List<ITreeNodeClickHandler>();
|
||||
if (Settings.Default.SingleClickOnConnectionOpensIt)
|
||||
singleClickHandlers.Add(new OpenConnectionClickHandler());
|
||||
if (Settings.Default.SingleClickSwitchesToOpenConnection)
|
||||
singleClickHandlers.Add(new SwitchToConnectionClickHandler());
|
||||
olvConnections.SingleClickHandler.ClickHandlers = singleClickHandlers;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -214,13 +214,19 @@
|
||||
<Compile Include="Tree\ConnectionDeletionConfirmer.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeDragAndDropHandler.cs" />
|
||||
<Compile Include="Tree\ConnectionTreeModel.cs" />
|
||||
<Compile Include="Tree\ExpandNodeClickHandler.cs" />
|
||||
<Compile Include="Tree\ITreeNodeClickHandler.cs" />
|
||||
<Compile Include="Tree\NodeSearcher.cs" />
|
||||
<Compile Include="Tree\NodeType.cs" />
|
||||
<Compile Include="Tree\ObjectListViewExtensions.cs" />
|
||||
<Compile Include="Tree\OpenConnectionClickHandler.cs" />
|
||||
<Compile Include="Tree\PreviouslyOpenedFolderExpander.cs" />
|
||||
<Compile Include="Tree\PreviousSessionOpener.cs" />
|
||||
<Compile Include="Tree\RootNodeExpander.cs" />
|
||||
<Compile Include="Tree\Root\RootNodeTypeEnum.cs" />
|
||||
<Compile Include="Tree\SwitchToConnectionClickHandler.cs" />
|
||||
<Compile Include="Tree\TreeNodeDoubleClickHandler.cs" />
|
||||
<Compile Include="Tree\TreeNodeSingleClickHandler.cs" />
|
||||
<Compile Include="UI\Controls\ConnectionContextMenu.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
|
||||
Reference in New Issue
Block a user