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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + @@ -174,19 +144,62 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + @@ -158,19 +128,62 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + @@ -158,19 +128,62 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + +