From e336ec353957adf8ad30e0f4c5324ef1878fcf5c Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Tue, 9 Apr 2024 00:42:14 +0200
Subject: [PATCH] Feature: Enable dockablz to drag & drop tabs inside a window
(#2669)
* Feature: Enable dockablz
* Feature: Enable dockablz
* Fix: Dragablz branch consolidation
* Chore: Update module
* Feature: Handle tab close and show add button
* Chore: Add tab count
* Chore: Cleanup
* Feature: Parition & Close handler
* Feature: Add Parition
* Feature: Add Partition
* Feature: Add close handler
* Feature: Close handler
* Fix: Tab count issues
* Feature: Add dockablz
* Feature: ContextMenu in dragged out / splitted tab
* Fix: Update headers
* Feature: Add interface to close tab
* Chore: Upgrade dragablz
* Feature: Hide embedded window while dragging
* Feature: Focus embedded window based on the visual tree
* Fix: Set IsDraggingWindowChanged for BranchTemplate TabablzControl
* Docs: #2669
---
InnoSetup.iss | 2 +-
Source/3rdparty/Dragablz | 2 +-
Source/GlobalAssemblyInfo.cs | 4 +-
.../ConfigurationInfo.cs | 309 +++-
.../ConfigurationManager.cs | 14 +-
.../ClipboardHelper.cs | 15 +-
.../NETworkManager.Utilities.csproj | 1 +
Source/NETworkManager.sln.DotSettings | 1 +
.../Controls/AWSSessionManagerControl.xaml | 18 +-
.../Controls/AWSSessionManagerControl.xaml.cs | 32 +-
.../Controls/DragablzInterTabClient.cs | 13 +-
.../Controls/DragablzTabHostWindow.xaml | 1423 +++++++++--------
.../Controls/DragablzTabHostWindow.xaml.cs | 305 ++--
.../Controls/DragablzTabItem.cs | 67 +-
.../Controls/IDragablzTabItem.cs | 17 +
.../Controls/IEmbeddedWindow.cs | 17 +
.../Controls/PowerShellControl.xaml | 17 +-
.../Controls/PowerShellControl.xaml.cs | 28 +-
.../NETworkManager/Controls/PuTTYControl.xaml | 17 +-
.../Controls/PuTTYControl.xaml.cs | 25 +-
.../Controls/RemoteDesktopControl.xaml | 7 +-
.../Controls/RemoteDesktopControl.xaml.cs | 33 +-
...htVNCControl.xaml => TigerVNCControl.xaml} | 17 +-
...ontrol.xaml.cs => TigerVNCControl.xaml.cs} | 25 +-
.../Controls/WebConsoleControl.xaml | 5 +-
.../Controls/WebConsoleControl.xaml.cs | 28 +-
.../AWSSessionManagerHostViewModel.cs | 66 +-
.../ViewModels/DNSLookupHostViewModel.cs | 21 +-
.../ViewModels/DNSLookupViewModel.cs | 25 +-
.../ViewModels/IPGeolocationHostViewModel.cs | 27 +-
.../ViewModels/IPGeolocationViewModel.cs | 17 +-
.../ViewModels/IPScannerHostViewModel.cs | 28 +-
.../ViewModels/IPScannerViewModel.cs | 20 +-
.../ViewModels/PortScannerHostViewModel.cs | 23 +-
.../ViewModels/PortScannerViewModel.cs | 22 +-
.../ViewModels/PowerShellHostViewModel.cs | 65 +-
.../ViewModels/PuTTYHostViewModel.cs | 65 +-
.../ViewModels/RemoteDesktopHostViewModel.cs | 33 +-
.../ViewModels/SNMPHostViewModel.cs | 18 +-
.../ViewModels/SNMPViewModel.cs | 18 +-
.../ViewModels/SNTPLookupHostViewModel.cs | 23 +-
.../ViewModels/SNTPLookupViewModel.cs | 19 +-
.../ViewModels/TigerVNCHostViewModel.cs | 31 +-
.../ViewModels/TracerouteHostViewModel.cs | 25 +-
.../ViewModels/TracerouteViewModel.cs | 19 +-
.../ViewModels/WebConsoleHostViewModel.cs | 31 +-
.../ViewModels/WhoisHostViewModel.cs | 23 +-
.../ViewModels/WhoisViewModel.cs | 19 +-
.../Views/AWSSessionManagerHostView.xaml | 299 ++--
.../Views/AWSSessionManagerHostView.xaml.cs | 2 -
.../Views/DNSLookupHostView.xaml | 99 +-
.../Views/DNSLookupHostView.xaml.cs | 2 -
.../Views/DNSLookupView.xaml.cs | 10 +-
.../Views/IPGeolocationHostView.xaml | 45 +-
.../Views/IPGeolocationHostView.xaml.cs | 2 -
.../Views/IPGeolocationView.xaml.cs | 10 +-
.../Views/IPScannerHostView.xaml | 99 +-
.../Views/IPScannerHostView.xaml.cs | 3 -
.../Views/IPScannerView.xaml.cs | 3 +-
.../Views/PortScannerHostView.xaml | 99 +-
.../Views/PortScannerHostView.xaml.cs | 2 -
.../Views/PortScannerView.xaml.cs | 3 +-
.../Views/PowerShellHostView.xaml | 113 +-
.../Views/PowerShellHostView.xaml.cs | 3 +-
.../NETworkManager/Views/PuTTYHostView.xaml | 325 ++--
.../Views/PuTTYHostView.xaml.cs | 2 -
.../Views/RemoteDesktopHostView.xaml | 378 ++---
.../Views/RemoteDesktopHostView.xaml.cs | 3 +-
Source/NETworkManager/Views/SNMPHostView.xaml | 99 +-
.../NETworkManager/Views/SNMPHostView.xaml.cs | 2 -
Source/NETworkManager/Views/SNMPView.xaml.cs | 10 +-
.../Views/SNTPLookupHostView.xaml | 97 +-
.../Views/SNTPLookupHostView.xaml.cs | 2 -
.../Views/SNTPLookupView.xaml.cs | 10 +-
.../Views/TigerVNCHostView.xaml | 113 +-
.../Views/TigerVNCHostView.xaml.cs | 2 -
.../Views/TracerouteHostView.xaml | 99 +-
.../Views/TracerouteHostView.xaml.cs | 2 -
.../Views/TracerouteView.xaml.cs | 3 +-
.../Views/WebConsoleHostView.xaml | 113 +-
.../Views/WebConsoleHostView.xaml.cs | 2 -
.../NETworkManager/Views/WhoisHostView.xaml | 45 +-
.../Views/WhoisHostView.xaml.cs | 2 -
Source/NETworkManager/Views/WhoisView.xaml.cs | 10 +-
Website/docs/changelog/next-release.md | 4 +
Website/docs/img/changelog-2669.gif | Bin 0 -> 3028927 bytes
86 files changed, 3117 insertions(+), 2080 deletions(-)
create mode 100644 Source/NETworkManager/Controls/IDragablzTabItem.cs
create mode 100644 Source/NETworkManager/Controls/IEmbeddedWindow.cs
rename Source/NETworkManager/Controls/{TightVNCControl.xaml => TigerVNCControl.xaml} (81%)
rename Source/NETworkManager/Controls/{TightVNCControl.xaml.cs => TigerVNCControl.xaml.cs} (91%)
create mode 100644 Website/docs/img/changelog-2669.gif
diff --git a/InnoSetup.iss b/InnoSetup.iss
index d4554459df..0a092d4d55 100644
--- a/InnoSetup.iss
+++ b/InnoSetup.iss
@@ -2,7 +2,7 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "NETworkManager"
-#define MyAppVersion "2024.4.1.0"
+#define MyAppVersion "2024.4.9.0"
#define MyAppPublisher "BornToBeRoot"
#define MyAppURL "https://github.com/BornToBeRoot/NETworkManager/"
#define MyAppExeName "NETworkManager.exe"
diff --git a/Source/3rdparty/Dragablz b/Source/3rdparty/Dragablz
index 2b70e0f3a6..2df62f5af3 160000
--- a/Source/3rdparty/Dragablz
+++ b/Source/3rdparty/Dragablz
@@ -1 +1 @@
-Subproject commit 2b70e0f3a686372ea0ddd4d5bf58e5ac317edcaf
+Subproject commit 2df62f5af358d456d725919d44f189675d31d9cc
diff --git a/Source/GlobalAssemblyInfo.cs b/Source/GlobalAssemblyInfo.cs
index 2d4b248a22..3e08f0234c 100644
--- a/Source/GlobalAssemblyInfo.cs
+++ b/Source/GlobalAssemblyInfo.cs
@@ -6,5 +6,5 @@
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("2024.4.1.0")]
-[assembly: AssemblyFileVersion("2024.4.1.0")]
+[assembly: AssemblyVersion("2024.4.9.0")]
+[assembly: AssemblyFileVersion("2024.4.9.0")]
diff --git a/Source/NETworkManager.Settings/ConfigurationInfo.cs b/Source/NETworkManager.Settings/ConfigurationInfo.cs
index f876852cca..4d818175cc 100644
--- a/Source/NETworkManager.Settings/ConfigurationInfo.cs
+++ b/Source/NETworkManager.Settings/ConfigurationInfo.cs
@@ -1,4 +1,5 @@
-using NETworkManager.Models;
+using System.Diagnostics;
+using NETworkManager.Models;
using NETworkManager.Utilities;
namespace NETworkManager.Settings;
@@ -36,22 +37,22 @@ public ConfigurationInfo(bool isAdmin, string executionPath, string applicationF
///
/// Execution path of the application like "C:\Program Files\NETworkManager".
///
- public string ExecutionPath { get; set; }
+ public string ExecutionPath { get; }
///
/// Full path of the application like "C:\Program Files\NETworkManager\NETworkManager.exe"
///
- public string ApplicationFullName { get; set; }
+ public string ApplicationFullName { get; }
///
/// Application name like "NETworkManager".
///
- public string ApplicationName { get; set; }
+ public string ApplicationName { get; }
///
/// Indicates if the application is running in portable mode.
///
- public bool IsPortable { get; set; }
+ public bool IsPortable { get; }
#endregion
@@ -67,35 +68,285 @@ public ConfigurationInfo(bool isAdmin, string executionPath, string applicationF
///
public ApplicationName CurrentApplication { get; set; } = Models.ApplicationName.None;
- ///
- /// Indicates if Remote Desktop has tabs.
- ///
- public bool RemoteDesktopHasTabs { get; set; }
+ private int _ipScannerTabCount;
+ public int IPScannerTabCount
+ {
+ get => _ipScannerTabCount;
+ set
+ {
+ if (value == _ipScannerTabCount)
+ return;
- ///
- /// Indicates if PowerShell has tabs.
- ///
- public bool PowerShellHasTabs { get; set; }
+ _ipScannerTabCount = value;
+ OnPropertyChanged();
+ }
+ }
- ///
- /// Indicates if PuTTY has tabs.
- ///
- public bool PuTTYHasTabs { get; set; }
+ private int _portScannerTabCount;
+ public int PortScannerTabCount
+ {
+ get => _portScannerTabCount;
+ set
+ {
+ if (value == _portScannerTabCount)
+ return;
- ///
- /// Indicates if AWS Session Manager has tabs.
- ///
- public bool AWSSessionManagerHasTabs { get; set; }
+ _portScannerTabCount = value;
+ OnPropertyChanged();
+ }
+ }
- ///
- /// Indicates if TigerVNC has tabs.
- ///
- public bool TigerVNCHasTabs { get; set; }
+ private int _tracerouteTabCount;
+ public int TracerouteTabCount
+ {
+ get => _tracerouteTabCount;
+ set
+ {
+ if (value == _tracerouteTabCount)
+ return;
- ///
- /// Indicates if WebConsole has tabs.
- ///
- public bool WebConsoleHasTabs { get; set; }
+ _tracerouteTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _dnsLookupTabCount;
+ public int DNSLookupTabCount
+ {
+ get => _dnsLookupTabCount;
+ set
+ {
+ if (value == _dnsLookupTabCount)
+ return;
+
+ _dnsLookupTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _remoteDesktopTabCount;
+ public int RemoteDesktopTabCount
+ {
+ get => _remoteDesktopTabCount;
+ set
+ {
+ if (value == _remoteDesktopTabCount)
+ return;
+
+ _remoteDesktopTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isRemoteDesktopWindowDragging;
+ public bool IsRemoteDesktopWindowDragging
+ {
+ get => _isRemoteDesktopWindowDragging;
+ set
+ {
+ if (value == _isRemoteDesktopWindowDragging)
+ return;
+
+ _isRemoteDesktopWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _powerShellTabCount;
+ public int PowerShellTabCount
+ {
+ get => _powerShellTabCount;
+ set
+ {
+ if (value == _powerShellTabCount)
+ return;
+
+ _powerShellTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isPowerShellWindowDragging;
+ public bool IsPowerShellWindowDragging
+ {
+ get => _isPowerShellWindowDragging;
+ set
+ {
+ if (value == _isPowerShellWindowDragging)
+ return;
+
+ _isPowerShellWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _puTTYTabCount;
+ public int PuTTYTabCount
+ {
+ get => _puTTYTabCount;
+ set
+ {
+ if (value == _puTTYTabCount)
+ return;
+
+ _puTTYTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isPuTTYWindowDragging;
+ public bool IsPuTTYWindowDragging
+ {
+ get => _isPuTTYWindowDragging;
+ set
+ {
+ if (value == _isPuTTYWindowDragging)
+ return;
+
+ _isPuTTYWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _awsSessionManagerTabCount;
+ public int AWSSessionManagerTabCount
+ {
+ get => _awsSessionManagerTabCount;
+ set
+ {
+ if (value == _awsSessionManagerTabCount)
+ return;
+
+ _awsSessionManagerTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isAWSSessionManagerWindowDragging;
+ public bool IsAWSSessionManagerWindowDragging
+ {
+ get => _isAWSSessionManagerWindowDragging;
+ set
+ {
+ if (value == _isAWSSessionManagerWindowDragging)
+ return;
+
+ _isAWSSessionManagerWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _tigerVNCTabCount;
+ public int TigerVNCTabCount
+ {
+ get => _tigerVNCTabCount;
+ set
+ {
+ if (value == _tigerVNCTabCount)
+ return;
+
+ _tigerVNCTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isTigerVNCWindowDragging;
+ public bool IsTigerVNCWindowDragging
+ {
+ get => _isTigerVNCWindowDragging;
+ set
+ {
+ if (value == _isTigerVNCWindowDragging)
+ return;
+
+ _isTigerVNCWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _webConsoleTabCount;
+ public int WebConsoleTabCount
+ {
+ get => _webConsoleTabCount;
+ set
+ {
+ if (value == _webConsoleTabCount)
+ return;
+
+ _webConsoleTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isWebConsoleWindowDragging;
+ public bool IsWebConsoleWindowDragging
+ {
+ get => _isWebConsoleWindowDragging;
+ set
+ {
+ if (value == _isWebConsoleWindowDragging)
+ return;
+
+ _isWebConsoleWindowDragging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _snmpTabCount;
+ public int SNMPTabCount
+ {
+ get => _snmpTabCount;
+ set
+ {
+ if (value == _snmpTabCount)
+ return;
+
+ _snmpTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _sntpLookupTabCount;
+ public int SNTPLookupTabCount
+ {
+ get => _sntpLookupTabCount;
+ set
+ {
+ if (value == _sntpLookupTabCount)
+ return;
+
+ _sntpLookupTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _whoisTabCount;
+ public int WhoisTabCount
+ {
+ get => _whoisTabCount;
+ set
+ {
+ if (value == _whoisTabCount)
+ return;
+
+ _whoisTabCount = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private int _ipGeolocationTabCount;
+ public int IPGeolocationTabCount
+ {
+ get => _ipGeolocationTabCount;
+ set
+ {
+ if (value == _ipGeolocationTabCount)
+ return;
+
+ _ipGeolocationTabCount = value;
+ OnPropertyChanged();
+ }
+ }
///
/// Private variable for .
diff --git a/Source/NETworkManager.Settings/ConfigurationManager.cs b/Source/NETworkManager.Settings/ConfigurationManager.cs
index 2fa6ce36dc..f95b48a9fe 100644
--- a/Source/NETworkManager.Settings/ConfigurationManager.cs
+++ b/Source/NETworkManager.Settings/ConfigurationManager.cs
@@ -36,7 +36,7 @@ static ConfigurationManager()
///
/// Current that is used in the application.
///
- public static ConfigurationInfo Current { get; set; }
+ public static ConfigurationInfo Current { get; }
///
/// Method can be called before opening a dialog to fix airspace issues.
@@ -46,12 +46,12 @@ public static void OnDialogOpen()
{
switch (Current.CurrentApplication)
{
- case ApplicationName.RemoteDesktop when Current.RemoteDesktopHasTabs:
- case ApplicationName.PowerShell when Current.PowerShellHasTabs:
- case ApplicationName.PuTTY when Current.PuTTYHasTabs:
- case ApplicationName.AWSSessionManager when Current.AWSSessionManagerHasTabs:
- case ApplicationName.TigerVNC when Current.TigerVNCHasTabs:
- case ApplicationName.WebConsole when Current.WebConsoleHasTabs:
+ case ApplicationName.RemoteDesktop when Current.RemoteDesktopTabCount > 0:
+ case ApplicationName.PowerShell when Current.PowerShellTabCount > 0:
+ case ApplicationName.PuTTY when Current.PuTTYTabCount > 0:
+ case ApplicationName.AWSSessionManager when Current.AWSSessionManagerTabCount > 0:
+ case ApplicationName.TigerVNC when Current.TigerVNCTabCount > 0:
+ case ApplicationName.WebConsole when Current.WebConsoleTabCount > 0:
Current.FixAirspace = true;
break;
}
diff --git a/Source/NETworkManager.Utilities/ClipboardHelper.cs b/Source/NETworkManager.Utilities/ClipboardHelper.cs
index 3d3507a68f..973b4b660c 100644
--- a/Source/NETworkManager.Utilities/ClipboardHelper.cs
+++ b/Source/NETworkManager.Utilities/ClipboardHelper.cs
@@ -1,4 +1,6 @@
-using System.Windows;
+using System;
+using System.Windows;
+using log4net;
namespace NETworkManager.Utilities;
@@ -7,12 +9,19 @@ namespace NETworkManager.Utilities;
///
public static class ClipboardHelper
{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ClipboardHelper));
+
///
/// Methods to set a text to the clipboard.
///
/// Some text...
public static void SetClipboard(string text)
{
- Clipboard.SetDataObject(text, true);
+ try {
+ Clipboard.SetDataObject(text, true);
+ }
+ catch (Exception e) {
+ Log.Error($"Failed to set clipboard: {e.Message}");
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Source/NETworkManager.Utilities/NETworkManager.Utilities.csproj b/Source/NETworkManager.Utilities/NETworkManager.Utilities.csproj
index 88b8712ff5..98feba3747 100644
--- a/Source/NETworkManager.Utilities/NETworkManager.Utilities.csproj
+++ b/Source/NETworkManager.Utilities/NETworkManager.Utilities.csproj
@@ -18,5 +18,6 @@
+
\ No newline at end of file
diff --git a/Source/NETworkManager.sln.DotSettings b/Source/NETworkManager.sln.DotSettings
index 169874be03..8b76d71be8 100644
--- a/Source/NETworkManager.sln.DotSettings
+++ b/Source/NETworkManager.sln.DotSettings
@@ -51,6 +51,7 @@
True
True
True
+ True
True
True
True
diff --git a/Source/NETworkManager/Controls/AWSSessionManagerControl.xaml b/Source/NETworkManager/Controls/AWSSessionManagerControl.xaml
index de05cfa939..bb0f5ef0ff 100644
--- a/Source/NETworkManager/Controls/AWSSessionManagerControl.xaml
+++ b/Source/NETworkManager/Controls/AWSSessionManagerControl.xaml
@@ -8,6 +8,7 @@
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:local="clr-namespace:NETworkManager.Controls"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mah:DialogParticipation.Register="{Binding}"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance local:AWSSessionManagerControl}">
@@ -19,10 +20,19 @@
-
+
+
+
+
OnClose()
-
+ private bool _closed;
+
private readonly IDialogCoordinator _dialogCoordinator;
-
+
+ private readonly Guid _tabId;
private readonly AWSSessionManagerSessionInfo _sessionInfo;
private Process _process;
@@ -71,13 +71,16 @@ public bool IsConnecting
#region Constructor, load
- public AWSSessionManagerControl(AWSSessionManagerSessionInfo sessionInfo)
+ public AWSSessionManagerControl(Guid tabId, AWSSessionManagerSessionInfo sessionInfo)
{
InitializeComponent();
DataContext = this;
_dialogCoordinator = DialogCoordinator.Instance;
+ ConfigurationManager.Current.AWSSessionManagerTabCount++;
+
+ _tabId = tabId;
_sessionInfo = sessionInfo;
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
@@ -108,7 +111,7 @@ private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
public ICommand ReconnectCommand
{
- get { return new RelayCommand(p => ReconnectAction()); }
+ get { return new RelayCommand(_ => ReconnectAction()); }
}
private void ReconnectAction()
@@ -191,7 +194,7 @@ private async Task Connect()
}
catch (Exception ex)
{
- if (!_closing)
+ if (!_closed)
{
var settings = AppearanceManager.MetroDialog;
settings.AffirmativeButtonText = Strings.OK;
@@ -227,7 +230,7 @@ public void ResizeEmbeddedWindow()
WindowHost.ClientSize.Height, NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
}
- public void Disconnect()
+ private void Disconnect()
{
if (IsConnected)
_process.Kill();
@@ -243,10 +246,17 @@ private void Reconnect()
public void CloseTab()
{
- _closing = true;
+ // Prevent multiple calls
+ if (_closed)
+ return;
+
+ _closed = true;
+ // Disconnect the session
Disconnect();
+
+ ConfigurationManager.Current.AWSSessionManagerTabCount--;
}
#endregion
-}
\ No newline at end of file
+}
diff --git a/Source/NETworkManager/Controls/DragablzInterTabClient.cs b/Source/NETworkManager/Controls/DragablzInterTabClient.cs
index 1839758c91..cd3eae37e4 100644
--- a/Source/NETworkManager/Controls/DragablzInterTabClient.cs
+++ b/Source/NETworkManager/Controls/DragablzInterTabClient.cs
@@ -4,23 +4,16 @@
namespace NETworkManager.Controls;
-public class DragablzInterTabClient : IInterTabClient
+public class DragablzInterTabClient(ApplicationName applicationName) : IInterTabClient
{
- private readonly ApplicationName _applicationName;
-
- public DragablzInterTabClient(ApplicationName applicationName)
- {
- _applicationName = applicationName;
- }
-
public INewTabHost GetNewHost(IInterTabClient interTabClient, object partition, TabablzControl source)
{
- var dragablzTabHostWindow = new DragablzTabHostWindow(_applicationName);
+ var dragablzTabHostWindow = new DragablzTabHostWindow(applicationName);
return new NewTabHost(dragablzTabHostWindow, dragablzTabHostWindow.TabsContainer);
}
public TabEmptiedResponse TabEmptiedHandler(TabablzControl tabControl, Window window)
{
- return window is MainWindow ? TabEmptiedResponse.DoNothing : TabEmptiedResponse.CloseWindowOrLayoutBranch;
+ return window is MainWindow ? TabEmptiedResponse.CloseLayoutBranch : TabEmptiedResponse.CloseWindowOrLayoutBranch;
}
}
\ No newline at end of file
diff --git a/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml b/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml
index c1d32d6506..5dabeb4469 100644
--- a/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml
+++ b/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml
@@ -5,6 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
+ xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:controls="clr-namespace:NETworkManager.Controls"
xmlns:application="clr-namespace:NETworkManager.Models;assembly=NETworkManager.Models"
@@ -15,716 +16,740 @@
Style="{DynamicResource DefaultWindow}" MinWidth="800" Width="1024" Height="768" MinHeight="600"
TitleAlignment="Left" Activated="MetroWindow_Activated"
dialogs:DialogParticipation.Register="{Binding}"
+ Closing="DragablzTabHostWindow_OnClosing"
d:DataContext="{d:DesignInstance controls:DragablzTabHostWindow}">
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Gesture="MiddleClick" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs b/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs
index 438f2f715e..c3ba8662f9 100644
--- a/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs
+++ b/Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs
@@ -1,7 +1,10 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
+using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using Dragablz;
@@ -12,74 +15,12 @@
using NETworkManager.Models.RemoteDesktop;
using NETworkManager.Settings;
using NETworkManager.Utilities;
-using NETworkManager.Views;
+using Application = System.Windows.Application;
namespace NETworkManager.Controls;
public sealed partial class DragablzTabHostWindow : INotifyPropertyChanged
{
- #region Constructor
-
- public DragablzTabHostWindow(ApplicationName applicationName)
- {
- InitializeComponent();
- DataContext = this;
-
- ApplicationName = applicationName;
-
- InterTabClient = new DragablzInterTabClient(applicationName);
-
- InterTabController.Partition = applicationName.ToString();
-
- Title =
- $"NETworkManager {AssemblyManager.Current.Version} - {ResourceTranslator.Translate(ResourceIdentifier.ApplicationName, applicationName)}";
- }
-
- #endregion
-
- #region Methods
-
- private async void FocusEmbeddedWindow()
- {
- // Delay the focus to prevent blocking the ui
- // Detect if window is resizing
- do
- {
- await Task.Delay(250);
- } while (Control.MouseButtons == MouseButtons.Left);
-
- /* Don't continue if
- - Header ContextMenu is opened
- */
- if (HeaderContextMenuIsOpen)
- return;
-
- // Switch by name
- switch (ApplicationName)
- {
- case ApplicationName.PowerShell:
- ((PowerShellControl)((DragablzTabItem)TabsContainer?.SelectedItem)?.View)?.FocusEmbeddedWindow();
- break;
- case ApplicationName.PuTTY:
- ((PuTTYControl)((DragablzTabItem)TabsContainer?.SelectedItem)?.View)?.FocusEmbeddedWindow();
- break;
- case ApplicationName.AWSSessionManager:
- ((AWSSessionManagerControl)((DragablzTabItem)TabsContainer?.SelectedItem)?.View)?.FocusEmbeddedWindow();
- break;
- }
- }
-
- #endregion
-
- #region Events
-
- private void MetroWindow_Activated(object sender, EventArgs e)
- {
- FocusEmbeddedWindow();
- }
-
- #endregion
-
#region PropertyChangedEventHandler
public event PropertyChangedEventHandler PropertyChanged;
@@ -94,6 +35,14 @@ private void OnPropertyChanged([CallerMemberName] string propertyName = null)
#region Variables
public IInterTabClient InterTabClient { get; }
+
+ private HashSet _embeddedWindowApplicationNames =
+ [
+ ApplicationName.PowerShell,
+ ApplicationName.PuTTY,
+ ApplicationName.AWSSessionManager
+ ];
+
private ApplicationName _applicationName;
public ApplicationName ApplicationName
@@ -109,6 +58,21 @@ public ApplicationName ApplicationName
}
}
+ private string _interTabPartition;
+
+ public string InterTabPartition
+ {
+ get => _interTabPartition;
+ set
+ {
+ if (value == _interTabPartition)
+ return;
+
+ _interTabPartition = value;
+ OnPropertyChanged();
+ }
+ }
+
private bool _headerContextMenuIsOpen;
public bool HeaderContextMenuIsOpen
@@ -126,59 +90,31 @@ public bool HeaderContextMenuIsOpen
#endregion
+ #region Constructor
+
+ public DragablzTabHostWindow(ApplicationName applicationName)
+ {
+ InitializeComponent();
+ DataContext = this;
+
+ ApplicationName = applicationName;
+
+ InterTabClient = new DragablzInterTabClient(applicationName);
+ InterTabPartition = applicationName.ToString();
+
+ Title =
+ $"NETworkManager {AssemblyManager.Current.Version} - {ResourceTranslator.Translate(ResourceIdentifier.ApplicationName, applicationName)}";
+ }
+
+ #endregion
+
#region ICommand & Actions
public ItemActionCallback CloseItemCommand => CloseItemAction;
private void CloseItemAction(ItemActionCallbackArgs args)
{
- // Switch between application identifiers...
- switch (_applicationName)
- {
- case ApplicationName.IPScanner:
- ((IPScannerView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.PortScanner:
- ((PortScannerView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.Traceroute:
- ((TracerouteView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.DNSLookup:
- ((DNSLookupView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.RemoteDesktop:
- ((RemoteDesktopControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.PowerShell:
- ((PowerShellControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.PuTTY:
- ((PuTTYControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.AWSSessionManager:
- ((AWSSessionManagerControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.TigerVNC:
- ((TigerVNCControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.WebConsole:
- ((WebConsoleControl)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.SNMP:
- ((SNMPView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.SNTPLookup:
- ((SNTPLookupView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.Whois:
- ((WhoisView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
- case ApplicationName.IPGeolocation:
- ((IPGeolocationView)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
- break;
-
- }
+ ((IDragablzTabItem)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
}
#region RemoteDesktop commands
@@ -242,22 +178,23 @@ private void RemoteDesktop_AdjustScreenAction(object view)
private async void RemoteDesktop_SendCtrlAltDelAction(object view)
{
- if (view is RemoteDesktopControl control)
- try
- {
- control.SendKey(Keystroke.CtrlAltDel);
- }
- catch (Exception ex)
- {
- ConfigurationManager.OnDialogOpen();
-
- await this.ShowMessageAsync(Strings.Error,
- string.Format("{0}\n\nMessage:\n{1}",
- Strings.CouldNotSendKeystroke, ex.Message,
- MessageDialogStyle.Affirmative, AppearanceManager.MetroDialog));
-
- ConfigurationManager.OnDialogClose();
- }
+ if (view is not RemoteDesktopControl control)
+ return;
+
+ try
+ {
+ control.SendKey(Keystroke.CtrlAltDel);
+ }
+ catch (Exception ex)
+ {
+ ConfigurationManager.OnDialogOpen();
+
+ await this.ShowMessageAsync(Strings.Error,
+ string.Format("{0}\n\nMessage:\n{1}",
+ Strings.CouldNotSendKeystroke, ex.Message));
+
+ ConfigurationManager.OnDialogClose();
+ }
}
#endregion
@@ -388,4 +325,120 @@ private void WebConsole_RefreshAction(object view)
#endregion
#endregion
+
+ #region Methods
+
+ private async void FocusEmbeddedWindow()
+ {
+ // Delay the focus to prevent blocking the ui
+ // Detect if window is resizing
+ do
+ {
+ await Task.Delay(250);
+ } while (Control.MouseButtons == MouseButtons.Left);
+
+ /* Don't continue if
+ - Header ContextMenu is opened
+ */
+ if (HeaderContextMenuIsOpen)
+ return;
+
+ // Return if the application is not an embedded window
+ if(!_embeddedWindowApplicationNames.Contains(ApplicationName))
+ return;
+
+ var window = Application.Current.Windows.OfType().FirstOrDefault(x => x.IsActive);
+
+ if (window == null)
+ return;
+
+ // Find all TabablzControl in the active window
+ foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren(window))
+ {
+ // Skip if no items
+ if (tabablzControl.Items.Count == 0)
+ continue;
+
+ // Focus embedded window in the selected tab
+ (((DragablzTabItem)tabablzControl.SelectedItem)?.View as IEmbeddedWindow)?.FocusEmbeddedWindow();
+
+ break;
+ }
+ }
+
+ #endregion
+
+ #region Events
+
+ private void MetroWindow_Activated(object sender, EventArgs e)
+ {
+ FocusEmbeddedWindow();
+ }
+
+ private void DragablzTabHostWindow_OnClosing(object sender, CancelEventArgs e)
+ {
+ // Close all tabs properly when the window is closing
+ var window = Application.Current.Windows.OfType().FirstOrDefault(x => x.IsActive);
+
+ if (window == null)
+ return;
+
+ // Find all TabablzControl in the active window
+ foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren(window))
+ {
+ foreach (var tabItem in tabablzControl.Items.OfType())
+ ((IDragablzTabItem)tabItem.View).CloseTab();
+ }
+
+ // Reset the dragging state
+ switch (ApplicationName)
+ {
+ case ApplicationName.RemoteDesktop:
+ ConfigurationManager.Current.IsRemoteDesktopWindowDragging = false;
+ break;
+ case ApplicationName.PowerShell:
+ ConfigurationManager.Current.IsPowerShellWindowDragging = false;
+ break;
+ case ApplicationName.PuTTY:
+ ConfigurationManager.Current.IsPuTTYWindowDragging = false;
+ break;
+ case ApplicationName.AWSSessionManager:
+ ConfigurationManager.Current.IsAWSSessionManagerWindowDragging = false;
+ break;
+ case ApplicationName.TigerVNC:
+ ConfigurationManager.Current.IsTigerVNCWindowDragging = false;
+ break;
+ case ApplicationName.WebConsole:
+ ConfigurationManager.Current.IsWebConsoleWindowDragging = false;
+ break;
+ }
+ }
+
+ private void TabablzControl_OnIsDraggingWindowChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ // Set the dragging state
+ switch (ApplicationName)
+ {
+ case ApplicationName.RemoteDesktop:
+ ConfigurationManager.Current.IsRemoteDesktopWindowDragging = e.NewValue;
+ break;
+ case ApplicationName.PowerShell:
+ ConfigurationManager.Current.IsPowerShellWindowDragging = e.NewValue;
+ break;
+ case ApplicationName.PuTTY:
+ ConfigurationManager.Current.IsPuTTYWindowDragging = e.NewValue;
+ break;
+ case ApplicationName.AWSSessionManager:
+ ConfigurationManager.Current.IsAWSSessionManagerWindowDragging = e.NewValue;
+ break;
+ case ApplicationName.TigerVNC:
+ ConfigurationManager.Current.IsTigerVNCWindowDragging = e.NewValue;
+ break;
+ case ApplicationName.WebConsole:
+ ConfigurationManager.Current.IsWebConsoleWindowDragging = e.NewValue;
+ break;
+ }
+ }
+
+ #endregion
}
\ No newline at end of file
diff --git a/Source/NETworkManager/Controls/DragablzTabItem.cs b/Source/NETworkManager/Controls/DragablzTabItem.cs
index 146f6e2cf1..6d7cedb4ff 100644
--- a/Source/NETworkManager/Controls/DragablzTabItem.cs
+++ b/Source/NETworkManager/Controls/DragablzTabItem.cs
@@ -1,19 +1,21 @@
using System;
+using System.Linq;
+using System.Windows;
using System.Windows.Controls;
+using Dragablz;
+using NETworkManager.Utilities;
using NETworkManager.ViewModels;
namespace NETworkManager.Controls;
public class DragablzTabItem : ViewModelBase
{
- private string _header;
-
- public DragablzTabItem(string header, UserControl view)
- {
- Header = header;
- View = view;
- }
-
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// Header of the tab.
+ /// View of the tab.
+ /// Id of the tab.
public DragablzTabItem(string header, UserControl view, Guid id)
{
Header = header;
@@ -21,10 +23,18 @@ public DragablzTabItem(string header, UserControl view, Guid id)
Id = id;
}
+ ///
+ /// Private field for the property.
+ ///
+ private string _header;
+
+ ///
+ /// Header of the tab.
+ ///
public string Header
{
get => _header;
- set
+ private set
{
if (value == _header)
return;
@@ -34,7 +44,40 @@ public string Header
}
}
- public UserControl View { get; set; }
+ ///
+ /// View of the tab.
+ ///
+ public UserControl View { get; }
+
+ ///
+ /// Id of the tab.
+ ///
+ public Guid Id { get; }
- public Guid Id { get; set; }
-}
\ No newline at end of file
+ ///
+ /// Method to set the of a based on the
+ /// in the current by finding the tab item in all `s
+ /// via the .
+ ///
+ /// Id of the tab to set the header.
+ /// New header to set.
+ public static void SetTabHeader(Guid tabId, string header)
+ {
+ var window = Application.Current.Windows.OfType().FirstOrDefault(x => x.IsActive);
+
+ if (window == null)
+ return;
+
+ // Find all TabablzControl in the active window
+ foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren(window))
+ {
+ var tabItem = tabablzControl.Items.OfType().FirstOrDefault(x => x.Id == tabId);
+
+ if (tabItem == null)
+ continue;
+
+ tabItem.Header = header;
+ break;
+ }
+ }
+}
diff --git a/Source/NETworkManager/Controls/IDragablzTabItem.cs b/Source/NETworkManager/Controls/IDragablzTabItem.cs
new file mode 100644
index 0000000000..262685d2c9
--- /dev/null
+++ b/Source/NETworkManager/Controls/IDragablzTabItem.cs
@@ -0,0 +1,17 @@
+using Dragablz;
+
+namespace NETworkManager.Controls;
+
+///
+/// Interface for a user control that is a in a in a .
+///
+public interface IDragablzTabItem
+{
+ ///
+ /// Method to close the tab.
+ ///
+ public void CloseTab()
+ {
+
+ }
+}
diff --git a/Source/NETworkManager/Controls/IEmbeddedWindow.cs b/Source/NETworkManager/Controls/IEmbeddedWindow.cs
new file mode 100644
index 0000000000..0e0905bf02
--- /dev/null
+++ b/Source/NETworkManager/Controls/IEmbeddedWindow.cs
@@ -0,0 +1,17 @@
+using Dragablz;
+
+namespace NETworkManager.Controls;
+
+///
+/// Interface for a user control that contains an embedded window like a or .
+///
+public interface IEmbeddedWindow
+{
+ ///
+ /// Method to focus the embedded window.
+ ///
+ public void FocusEmbeddedWindow()
+ {
+
+ }
+}
diff --git a/Source/NETworkManager/Controls/PowerShellControl.xaml b/Source/NETworkManager/Controls/PowerShellControl.xaml
index a35afddc9c..4a28e00ac8 100644
--- a/Source/NETworkManager/Controls/PowerShellControl.xaml
+++ b/Source/NETworkManager/Controls/PowerShellControl.xaml
@@ -8,6 +8,7 @@
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:local="clr-namespace:NETworkManager.Controls"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mah:DialogParticipation.Register="{Binding}"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance local:PowerShellControl}">
@@ -19,9 +20,19 @@
-
+
+
+
+
OnClose()
+ private bool _closed;
private readonly IDialogCoordinator _dialogCoordinator;
+ private readonly Guid _tabId;
private readonly PowerShellSessionInfo _sessionInfo;
private Process _process;
@@ -71,15 +71,18 @@ public bool IsConnecting
#region Constructor, load
- public PowerShellControl(PowerShellSessionInfo sessionInfo)
+ public PowerShellControl(Guid tabId, PowerShellSessionInfo sessionInfo)
{
InitializeComponent();
DataContext = this;
_dialogCoordinator = DialogCoordinator.Instance;
+ ConfigurationManager.Current.PowerShellTabCount++;
+
+ _tabId = tabId;
_sessionInfo = sessionInfo;
-
+
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}
@@ -108,7 +111,7 @@ private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
public ICommand ReconnectCommand
{
- get { return new RelayCommand(p => ReconnectAction()); }
+ get { return new RelayCommand(_ => ReconnectAction()); }
}
private void ReconnectAction()
@@ -191,7 +194,7 @@ private async Task Connect()
}
catch (Exception ex)
{
- if (!_closing)
+ if (!_closed)
{
var settings = AppearanceManager.MetroDialog;
settings.AffirmativeButtonText = Strings.OK;
@@ -227,7 +230,7 @@ public void ResizeEmbeddedWindow()
WindowHost.ClientSize.Height, NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
}
- public void Disconnect()
+ private void Disconnect()
{
if (IsConnected)
_process.Kill();
@@ -243,9 +246,16 @@ private void Reconnect()
public void CloseTab()
{
- _closing = true;
+ // Prevent multiple calls
+ if (_closed)
+ return;
+
+ _closed = true;
+ // Disconnect the session
Disconnect();
+
+ ConfigurationManager.Current.PowerShellTabCount--;
}
#endregion
diff --git a/Source/NETworkManager/Controls/PuTTYControl.xaml b/Source/NETworkManager/Controls/PuTTYControl.xaml
index fcc655229b..48fe250712 100644
--- a/Source/NETworkManager/Controls/PuTTYControl.xaml
+++ b/Source/NETworkManager/Controls/PuTTYControl.xaml
@@ -8,6 +8,7 @@
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:local="clr-namespace:NETworkManager.Controls"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mah:DialogParticipation.Register="{Binding}"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance local:PuTTYControl}">
@@ -19,9 +20,19 @@
-
+
+
+
+
OnClose()
+ private bool _closed;
private readonly IDialogCoordinator _dialogCoordinator;
+ private readonly Guid _tabId;
private readonly PuTTYSessionInfo _sessionInfo;
private Process _process;
@@ -72,13 +73,16 @@ public bool IsConnecting
#region Constructor, load
- public PuTTYControl(PuTTYSessionInfo sessionInfo)
+ public PuTTYControl(Guid tabId, PuTTYSessionInfo sessionInfo)
{
InitializeComponent();
DataContext = this;
_dialogCoordinator = DialogCoordinator.Instance;
+
+ ConfigurationManager.Current.PuTTYTabCount++;
+ _tabId = tabId;
_sessionInfo = sessionInfo;
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
@@ -110,7 +114,7 @@ private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
public ICommand ReconnectCommand
{
- get { return new RelayCommand(p => ReconnectAction()); }
+ get { return new RelayCommand(_ => ReconnectAction()); }
}
private void ReconnectAction()
@@ -208,7 +212,7 @@ private async Task Connect()
}
catch (Exception ex)
{
- if (!_closing)
+ if (!_closed)
{
var settings = AppearanceManager.MetroDialog;
settings.AffirmativeButtonText = Strings.OK;
@@ -244,7 +248,7 @@ public void ResizeEmbeddedWindow()
WindowHost.ClientSize.Height, NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
}
- public void Disconnect()
+ private void Disconnect()
{
if (IsConnected)
_process.Kill();
@@ -267,9 +271,16 @@ public void RestartSession()
public void CloseTab()
{
- _closing = true;
+ // Prevent multiple calls
+ if (_closed)
+ return;
+
+ _closed = true;
+ // Disconnect the session
Disconnect();
+
+ ConfigurationManager.Current.PuTTYTabCount--;
}
#endregion
diff --git a/Source/NETworkManager/Controls/RemoteDesktopControl.xaml b/Source/NETworkManager/Controls/RemoteDesktopControl.xaml
index 2f1a224909..7fbeaa0d94 100644
--- a/Source/NETworkManager/Controls/RemoteDesktopControl.xaml
+++ b/Source/NETworkManager/Controls/RemoteDesktopControl.xaml
@@ -8,6 +8,7 @@
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:local="clr-namespace:NETworkManager.Controls"
+ xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance local:RemoteDesktopControl}">
@@ -18,10 +19,14 @@
+ MaxHeight="{Binding RdpClientHeight, Mode=OneWay}"
+ Background="{DynamicResource ResourceKey=MahApps.Brushes.Window.Background}">
+
OnClose()
+ private bool _closed;
private readonly IDialogCoordinator _dialogCoordinator;
+ private readonly Guid _tabId;
private readonly TigerVNCSessionInfo _sessionInfo;
private Process _process;
@@ -71,13 +72,16 @@ public bool IsConnecting
#region Constructor, load
- public TigerVNCControl(TigerVNCSessionInfo sessionInfo)
+ public TigerVNCControl(Guid tabId, TigerVNCSessionInfo sessionInfo)
{
InitializeComponent();
DataContext = this;
_dialogCoordinator = DialogCoordinator.Instance;
+
+ ConfigurationManager.Current.TigerVNCTabCount++;
+ _tabId = tabId;
_sessionInfo = sessionInfo;
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
@@ -109,7 +113,7 @@ private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
public ICommand ReconnectCommand
{
- get { return new RelayCommand(p => ReconnectAction()); }
+ get { return new RelayCommand(_ => ReconnectAction()); }
}
private void ReconnectAction()
@@ -205,7 +209,7 @@ private async Task Connect()
}
catch (Exception ex)
{
- if (!_closing)
+ if (!_closed)
{
var settings = AppearanceManager.MetroDialog;
settings.AffirmativeButtonText = Strings.OK;
@@ -234,7 +238,7 @@ private void ResizeEmbeddedWindow()
WindowHost.ClientSize.Height, NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
}
- public void Disconnect()
+ private void Disconnect()
{
if (IsConnected)
_process.Kill();
@@ -250,9 +254,16 @@ private void Reconnect()
public void CloseTab()
{
- _closing = true;
+ // Prevent multiple calls
+ if (_closed)
+ return;
+
+ _closed = true;
+ // Disconnect the session
Disconnect();
+
+ ConfigurationManager.Current.TigerVNCTabCount--;
}
#endregion
diff --git a/Source/NETworkManager/Controls/WebConsoleControl.xaml b/Source/NETworkManager/Controls/WebConsoleControl.xaml
index aa4ac7cd54..e56f8561e5 100644
--- a/Source/NETworkManager/Controls/WebConsoleControl.xaml
+++ b/Source/NETworkManager/Controls/WebConsoleControl.xaml
@@ -9,7 +9,7 @@
xmlns:converters="clr-namespace:NETworkManager.Converters;assembly=NETworkManager.Converters"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
- xmlns:webview="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
+ xmlns:webview="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
mah:DialogParticipation.Register="{Binding}"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance local:WebConsoleControl}">
@@ -171,6 +171,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+