diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index 12bde3a7..3a3f075f 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -1,7 +1,31 @@ -1.76.5 (2018-xx-xx): +1.76.7 (2018-xx-xx): Fixes: ------ +#1076: Wrong object selected when duplicating connection then switching between properties and inheritance in config window +#1068: Fixed some toolbar positioning bugs + + +1.76.6 (2018-08-03): + +Fixes: +------ +#1062: Entering correct password when starting app does not load connections file + +1.76.5 (2018-08-02): + +Fixes: +------ +#1057: Hitting F2 with no connection node selected caused unhandled exception +#1052: 'Switch to notification panel' feature does not always switch +#1051: Tooltips always displayed regardless of 'Show description tooltips in connection tree' setting +#1050: Config window retains access to previously selected node after loading new connections file +#1045: Config window shows several incorrect properties for HTTPS connections +#1040: Canceling "select panel" form does not cancel +#1039: Set default theme when themes disabled +#1038: Unable to add connection with active filter +#1036: Exception when themes are active and options page closed on Connections then reopened +#1034: Connection context menu not being translated #1030: Exception thrown if importing from port scan and no tree node is selected #1020: BackupFileKeepCount setting not limiting backup file count #1004: Duplicating root or PuTTy node through hotkey causes unhandled exception @@ -12,6 +36,9 @@ Fixes: #991: Error when deleting host in filtered view #971: Portable Settings now apply to any machine they are used on #961: Connections file overwritten if correct decryption password not provided +#893: Removed unneeded files from build/package +#868: if statement returned the same value +#762: Increased button size to fit locaized text 1.76.4 Alpha 6 (2018-06-03): diff --git a/Jenkinsfile_publish.groovy b/Jenkinsfile_publish.groovy index 2c30f879..d304d0f6 100644 --- a/Jenkinsfile_publish.groovy +++ b/Jenkinsfile_publish.groovy @@ -1,9 +1,13 @@ node('windows') { def jobDir = pwd() def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\"" - def vsToolsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools" - def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow" - def nunitTestAdapterPath = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\VisualStudio\\14.0\\Extensions" + def msBuild = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\msbuild.exe" + def nunitConsolePath = "${jobDir}\\packages\\NUnit.ConsoleRunner.3.7.0\\tools\\nunit3-console.exe" + def openCoverPath = "${jobDir}\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe" + def testResultFilePrefix = "TestResult" + def testResultFileNormal = "${testResultFilePrefix}_UnitTests_normal.xml" + def testResultFilePortable = "${testResultFilePrefix}_UnitTests_portable.xml" + def coverageReport = "code_coverage_report.xml" stage ('Clean output dir') { @@ -32,24 +36,24 @@ node('windows') { withCredentials([file(credentialsId: '9b674d57-6792-48e3-984a-4d1bab2abb64', variable: 'CODE_SIGNING_CERT')]) { withCredentials([usernamePassword(credentialsId: '05b7449b-05c0-490f-8661-236242526e62', passwordVariable: 'MRNG_CERT_PASSWORD', usernameVariable: 'NO_USERNAME')]) { stage ('Build mRemoteNG (Normal - MSI)') { - bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\"" + bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\"" archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true } stage ('Build mRemoteNG (Portable)') { - bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\"" + bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\"" archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true } } } - stage ('Run Unit Tests (Normal - MSI)') { - bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release\\mRemoteNGTests.dll\"" - } - - stage ('Run Unit Tests (Portable)') { - bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release Portable\\mRemoteNGTests.dll\"" - } + stage ('Run Unit Tests (Normal - MSI)') { + bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release\\mRemoteNGTests.dll\" --result=${testResultFileNormal} --x86" + } + + stage ('Run Unit Tests (Portable)') { + bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release portable\\mRemoteNGTests.dll\" --result=${testResultFilePortable} --x86" + } stage ('Generate UpdateCheck Files') { bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\create_upg_chk_files.ps1\" -TagName \"${env.TagName}\" -UpdateChannel \"${env.UpdateChannel}\"" diff --git a/Tools/github_functions.ps1 b/Tools/github_functions.ps1 index 6c3700b5..db17cb0a 100644 --- a/Tools/github_functions.ps1 +++ b/Tools/github_functions.ps1 @@ -175,9 +175,14 @@ function Upload-GitHubReleaseAsset { ) $UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$" - $file = Get-Item -Path $FilePath + $files = Get-Item -Path $FilePath - $req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop + # Get-Item could produce an array of files if a wildcard is provided. (C:\*.txt) + # Upload each matching item individually + foreach ($file in $files) { + Write-Output "Uploading asset to GitHub release: '$($file.FullName)'" + $req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop + } } diff --git a/Tools/postbuild_mremotev1.ps1 b/Tools/postbuild_mremotev1.ps1 index a2aa5f14..7129950d 100644 --- a/Tools/postbuild_mremotev1.ps1 +++ b/Tools/postbuild_mremotev1.ps1 @@ -46,4 +46,5 @@ Format-Table -AutoSize -Wrap -InputObject @{ & "$PSScriptRoot\tidy_files_for_release.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName & "$PSScriptRoot\sign_binaries.ps1" -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning & "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName -CertificatePath $CertificatePath +& "$PSScriptRoot\zip_symbols.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName & "$PSScriptRoot\zip_portable_files.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName \ No newline at end of file diff --git a/Tools/tidy_files_for_release.ps1 b/Tools/tidy_files_for_release.ps1 index c02e7e48..b56218fb 100644 --- a/Tools/tidy_files_for_release.ps1 +++ b/Tools/tidy_files_for_release.ps1 @@ -15,7 +15,6 @@ if ($ConfigurationName -match "Release") { Write-Output "Removing unnecessary files from Release versions" Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "app.publish") -Recurse -Force $filesToDelete = Get-ChildItem -Path $TargetDir -Recurse -Include @( - "*.pdb", "*.publish", "*.xml", "*.backup", diff --git a/Tools/zip_portable_files.ps1 b/Tools/zip_portable_files.ps1 index 66f0c68b..6af31e7c 100644 --- a/Tools/zip_portable_files.ps1 +++ b/Tools/zip_portable_files.ps1 @@ -39,19 +39,22 @@ if ($ConfigurationName -eq "Release Portable") { $PortableZip="$($SolutionDir)Release\mRemoteNG-Portable-$($version).zip" - Remove-Item -Recurse "$($SolutionDir)mRemoteV1\bin\package" -ErrorAction SilentlyContinue | Out-Null - New-Item "$($SolutionDir)mRemoteV1\bin\package" -ItemType "directory" | Out-Null + $tempFolderPath = Join-Path -Path $SolutionDir -ChildPath "mRemoteV1\bin\package" + Remove-Item -Recurse $tempFolderPath -ErrorAction SilentlyContinue | Out-Null + New-Item $tempFolderPath -ItemType "directory" | Out-Null - Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination "$($SolutionDir)mRemoteV1\bin\package" + Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination $tempFolderPath #Write-Output "$($SolutionDir)mRemoteV1\bin\$ConfigurationName" #Write-Output "$($SolutionDir)mRemoteV1\bin\package" - Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination "$($SolutionDir)mRemoteV1\bin\package" -Recurse -Force - Copy-Item "$($SolutionDir)*.txt" -Destination "$($SolutionDir)mRemoteV1\bin\package" + Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination $tempFolderPath -Recurse -Force + # Delete any PDB files that accidentally get copied into the temp folder + Get-ChildItem -Path $tempFolderPath -Filter "*.pdb" | Remove-Item + Copy-Item "$($SolutionDir)*.txt" -Destination $tempFolderPath Write-Output "Creating portable ZIP file $($PortableZip)" Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue - & $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip "$($SolutionDir)mRemoteV1\bin\package\*.*" + & $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip (Join-Path -Path $tempFolderPath -ChildPath "*.*") #& $SEVENZIP a -bt -mx=9 -tzip -y $PortableZip "$($SolutionDir)*.TXT" } else { diff --git a/Tools/zip_symbols.ps1 b/Tools/zip_symbols.ps1 new file mode 100644 index 00000000..bf2d2878 --- /dev/null +++ b/Tools/zip_symbols.ps1 @@ -0,0 +1,56 @@ +param ( + [string] + [Parameter(Mandatory=$true)] + $SolutionDir, + + [string] + [Parameter(Mandatory=$true)] + $TargetDir, + + [string] + [Parameter(Mandatory=$true)] + $ConfigurationName +) + +Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) =====" + +if(-not [string]::IsNullOrEmpty($Env:APPVEYOR_BUILD_FOLDER)) { + Write-Output "Too early to run via Appveyor - artifacts don't get generated properly. Exiting" + Exit +} + +Write-Output "Solution Dir: '$($SolutionDir)'" +Write-Output "Target Dir: '$($TargetDir)'" +$ConfigurationName = $ConfigurationName.Trim() +Write-Output "Config Name (trimmed): '$($ConfigurationName)'" + + +# Windows Sysinternals Sigcheck from http://technet.microsoft.com/en-us/sysinternals/bb897441 +$SIGCHECK="$($SolutionDir)Tools\exes\sigcheck.exe" +$SEVENZIP="$($SolutionDir)Tools\7zip\7za.exe" + +# Package Zip +if ($ConfigurationName -match "Release") { + Write-Output "Packaging debug symbols" + + $version = & $SIGCHECK /accepteula -q -n "$($SolutionDir)mRemoteV1\bin\$($ConfigurationName)\mRemoteNG.exe" + + Write-Output "Version is $($version)" + + if ($ConfigurationName -match "Portable") { + $zipFilePrefix = "mRemoteNG-Portable-symbols" + } else { + $zipFilePrefix = "mRemoteNG-symbols" + } + + $outputZipPath="$($SolutionDir)Release\$zipFilePrefix-$($version).zip" + + Write-Output "Creating debug symbols ZIP file $($outputZipPath)" + Remove-Item -Force $outputZipPath -ErrorAction SilentlyContinue + & $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $outputZipPath (Join-Path -Path $TargetDir -ChildPath "*.pdb") +} +else { + Write-Output "We will not package debug symbols - this isnt a release build." +} + +Write-Output "" \ No newline at end of file diff --git a/mRemoteNGTests/Connection/ConnectionInfoTests.cs b/mRemoteNGTests/Connection/ConnectionInfoTests.cs index fb809f38..9e127a0b 100644 --- a/mRemoteNGTests/Connection/ConnectionInfoTests.cs +++ b/mRemoteNGTests/Connection/ConnectionInfoTests.cs @@ -43,6 +43,20 @@ namespace mRemoteNGTests.Connection Assert.That(clonedConnection.Parent, Is.Null); } + [Test] + public void CloneAlsoCopiesInheritanceObject() + { + var clonedConnection = _connectionInfo.Clone(); + Assert.That(clonedConnection.Inheritance, Is.Not.EqualTo(_connectionInfo.Inheritance)); + } + + [Test] + public void CloneCorrectlySetsParentOfInheritanceObject() + { + var clonedConnection = _connectionInfo.Clone(); + Assert.That(clonedConnection.Inheritance.Parent, Is.EqualTo(clonedConnection)); + } + [Test] public void CopyFromCopiesProperties() { diff --git a/mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs b/mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs index 9743ea0a..81e8eb51 100644 --- a/mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs +++ b/mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs @@ -8,7 +8,7 @@ using mRemoteNG.Connection.Protocol.VNC; namespace mRemoteNGTests.TestHelpers { - internal class ConnectionInfoHelpers + internal static class ConnectionInfoHelpers { private static readonly Random _random = new Random(); @@ -128,5 +128,5 @@ namespace mRemoteNGTests.TestHelpers var values = Enum.GetValues(typeof(T)); return (T)values.GetValue(_random.Next(values.Length)); } - } + } } diff --git a/mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs b/mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs index b6227d98..142caed7 100644 --- a/mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs +++ b/mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs @@ -184,5 +184,19 @@ namespace mRemoteNGTests.UI.Controls Assert.That(widthAfter, Is.GreaterThan(widthBefore)); } + + [Test] + [Apartment(ApartmentState.STA)] + public void RenamingNodeWithNothingSelectedDoesNothing() + { + var connectionTreeModel = new ConnectionTreeModel(); + var root = new RootNodeInfo(RootNodeType.Connection); + connectionTreeModel.AddRootNode(root); + + _connectionTree.ConnectionTreeModel = connectionTreeModel; + _connectionTree.SelectedObject = null; + + Assert.DoesNotThrow(() => _connectionTree.RenameSelectedNode()); + } } } diff --git a/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowGeneralTests.cs b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowGeneralTests.cs new file mode 100644 index 00000000..265fec25 --- /dev/null +++ b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowGeneralTests.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using mRemoteNG.Connection; +using mRemoteNG.Connection.Protocol; +using mRemoteNG.Connection.Protocol.RDP; +using mRemoteNG.Connection.Protocol.VNC; +using mRemoteNG.Container; +using mRemoteNG.Tree.Root; +using mRemoteNG.UI.Window; +using NUnit.Framework; + +namespace mRemoteNGTests.UI.Window.ConfigWindowTests +{ + public class ConfigWindowGeneralTests + { + private ConfigWindow _configWindow; + + [SetUp] + public void Setup() + { + _configWindow = new ConfigWindow + { + PropertiesVisible = true + }; + } + + [TestCaseSource(nameof(ConnectionInfoGeneralTestCases))] + public void PropertyGridShowCorrectPropertiesForConnectionInfo(ConnectionInfo connectionInfo, IEnumerable expectedVisibleProperties) + { + _configWindow.SelectedTreeNode = connectionInfo; + Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties)); + } + + [Test] + public void PropertyGridShowCorrectPropertiesForRootConnectionInfo() + { + var expectedVisibleProperties = new[] + { + nameof(RootNodeInfo.Name), + nameof(RootNodeInfo.Password), + }; + + _configWindow.SelectedTreeNode = new RootNodeInfo(RootNodeType.Connection); + Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties)); + } + + [Test] + public void PropertyGridShowCorrectPropertiesForRootPuttyInfo() + { + var expectedVisibleProperties = new[] + { + nameof(RootNodeInfo.Name), + }; + + _configWindow.SelectedTreeNode = new RootPuttySessionsNodeInfo(); + Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties)); + } + + private static IEnumerable ConnectionInfoGeneralTestCases() + { + var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType(); + var testCases = new List(); + + foreach (var protocol in protocolTypes) + { + var expectedPropertyListConnection = BuildExpectedConnectionInfoPropertyList(protocol, false); + var connectionInfo = ConstructConnectionInfo(protocol, false); + var testCaseConnection = new TestCaseData(connectionInfo, expectedPropertyListConnection) + .SetName(protocol + ", ConnectionInfo"); + testCases.Add(testCaseConnection); + + var expectedPropertyListContainer = BuildExpectedConnectionInfoPropertyList(protocol, true); + var containerInfo = ConstructConnectionInfo(protocol, true); + var testCaseContainer = new TestCaseData(containerInfo, expectedPropertyListContainer) + .SetName(protocol + ", ContainerInfo"); + testCases.Add(testCaseContainer); + } + + return testCases; + } + + internal static ConnectionInfo ConstructConnectionInfo(ProtocolType protocol, bool isContainer) + { + // build connection info. set certain connection properties so + // that toggled properties are hidden in the property grid. We + // will test those separately in the special protocol tests. + var node = isContainer + ? new ContainerInfo() + : new ConnectionInfo(); + + node.Protocol = protocol; + node.Resolution = RdpProtocol.RDPResolutions.Res800x600; + node.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Never; + node.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes; + node.RedirectSound = RdpProtocol.RDPSounds.DoNotPlay; + node.VNCAuthMode = ProtocolVNC.AuthMode.AuthVNC; + node.VNCProxyType = ProtocolVNC.ProxyType.ProxyNone; + node.Inheritance.TurnOffInheritanceCompletely(); + + return node; + } + + internal static List BuildExpectedConnectionInfoPropertyList(ProtocolType protocol, bool isContainer) + { + var expectedProperties = new List + { + nameof(ConnectionInfo.Name), + nameof(ConnectionInfo.Description), + nameof(ConnectionInfo.Icon), + nameof(ConnectionInfo.Panel), + nameof(ConnectionInfo.Protocol), + nameof(ConnectionInfo.PreExtApp), + nameof(ConnectionInfo.PostExtApp), + nameof(ConnectionInfo.MacAddress), + nameof(ConnectionInfo.UserField), + }; + + if (!isContainer) + { + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Hostname), + }); + } + + switch (protocol) + { + case ProtocolType.RDP: + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Domain), + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.UseConsoleSession), + nameof(ConnectionInfo.RDPAuthenticationLevel), + nameof(ConnectionInfo.RDPMinutesToIdleTimeout), + nameof(ConnectionInfo.LoadBalanceInfo), + nameof(ConnectionInfo.UseCredSsp), + nameof(ConnectionInfo.RDGatewayUsageMethod), + nameof(ConnectionInfo.Resolution), + nameof(ConnectionInfo.Colors), + nameof(ConnectionInfo.CacheBitmaps), + nameof(ConnectionInfo.DisplayWallpaper), + nameof(ConnectionInfo.DisplayThemes), + nameof(ConnectionInfo.EnableFontSmoothing), + nameof(ConnectionInfo.EnableDesktopComposition), + nameof(ConnectionInfo.RedirectKeys), + nameof(ConnectionInfo.RedirectDiskDrives), + nameof(ConnectionInfo.RedirectPrinters), + nameof(ConnectionInfo.RedirectPorts), + nameof(ConnectionInfo.RedirectSmartCards), + nameof(ConnectionInfo.RedirectSound), + }); + break; + case ProtocolType.VNC: + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.VNCSmartSizeMode), + nameof(ConnectionInfo.VNCViewOnly), + }); + break; + case ProtocolType.SSH1: + case ProtocolType.SSH2: + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.PuttySession) + }); + break; + case ProtocolType.Telnet: + case ProtocolType.Rlogin: + case ProtocolType.RAW: + expectedProperties.AddRange(new[] + { + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.PuttySession), + }); + break; + case ProtocolType.HTTP: + case ProtocolType.HTTPS: + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.RenderingEngine), + }); + break; + case ProtocolType.ICA: + expectedProperties.AddRange(new [] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Domain), + nameof(ConnectionInfo.ICAEncryptionStrength), + nameof(ConnectionInfo.Resolution), + nameof(ConnectionInfo.Colors), + nameof(ConnectionInfo.CacheBitmaps), + }); + break; + case ProtocolType.IntApp: + expectedProperties.AddRange(new[] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Password), + nameof(ConnectionInfo.Domain), + nameof(ConnectionInfo.Port), + nameof(ConnectionInfo.ExtApp), + }); + break; + default: + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + } + + return expectedProperties; + } + } +} diff --git a/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowRdpSpecialTests.cs b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowRdpSpecialTests.cs new file mode 100644 index 00000000..0804652e --- /dev/null +++ b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowRdpSpecialTests.cs @@ -0,0 +1,73 @@ +using mRemoteNG.Connection; +using mRemoteNG.Connection.Protocol; +using mRemoteNG.Connection.Protocol.RDP; +using NUnit.Framework; + +namespace mRemoteNGTests.UI.Window.ConfigWindowTests +{ + public class ConfigWindowRdpSpecialTests : ConfigWindowSpecialTestsBase + { + protected override ProtocolType Protocol => ProtocolType.RDP; + + [Test] + public void PropertyShownWhenActive_RdpMinutesToIdleTimeout() + { + ConnectionInfo.RDPMinutesToIdleTimeout = 1; + ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.RDPAlertIdleTimeout)); + + RunVerification(); + } + + [TestCase(RdpProtocol.RDGatewayUsageMethod.Always)] + [TestCase(RdpProtocol.RDGatewayUsageMethod.Detect)] + public void RdGatewayPropertiesShown_WhenRdGatewayUsageMethodIsNotNever(RdpProtocol.RDGatewayUsageMethod gatewayUsageMethod) + { + ConnectionInfo.RDGatewayUsageMethod = gatewayUsageMethod; + ConnectionInfo.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes; + ExpectedPropertyList.AddRange(new [] + { + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname), + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials) + }); + + RunVerification(); + } + + [TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.No)] + [TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.SmartCard)] + public void RdGatewayPropertiesShown_WhenRDGatewayUseConnectionCredentialsIsNotYes(RdpProtocol.RDGatewayUseConnectionCredentials useConnectionCredentials) + { + ConnectionInfo.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always; + ConnectionInfo.RDGatewayUseConnectionCredentials = useConnectionCredentials; + ExpectedPropertyList.AddRange(new [] + { + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname), + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUsername), + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayPassword), + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayDomain), + nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials) + }); + + RunVerification(); + } + + [Test] + public void SoundQualityPropertyShown_WhenRdpSoundsSetToBringToThisComputer() + { + ConnectionInfo.RedirectSound = RdpProtocol.RDPSounds.BringToThisComputer; + ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.SoundQuality)); + + RunVerification(); + } + + [TestCase(RdpProtocol.RDPResolutions.FitToWindow)] + [TestCase(RdpProtocol.RDPResolutions.Fullscreen)] + public void AutomaticResizePropertyShown_WhenResolutionIsDynamic(RdpProtocol.RDPResolutions resolution) + { + ConnectionInfo.Resolution = resolution; + ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.AutomaticResize)); + + RunVerification(); + } + } +} diff --git a/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowSpecialTestsBase.cs b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowSpecialTestsBase.cs new file mode 100644 index 00000000..e5f9169c --- /dev/null +++ b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowSpecialTestsBase.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using mRemoteNG.Connection; +using mRemoteNG.Connection.Protocol; +using mRemoteNG.UI.Window; +using NUnit.Framework; + +namespace mRemoteNGTests.UI.Window.ConfigWindowTests +{ + public abstract class ConfigWindowSpecialTestsBase + { + protected abstract ProtocolType Protocol { get; } + protected bool TestAgainstContainerInfo { get; set; } = false; + protected ConfigWindow ConfigWindow; + protected ConnectionInfo ConnectionInfo; + protected List ExpectedPropertyList; + + [SetUp] + public virtual void Setup() + { + ConnectionInfo = ConfigWindowGeneralTests.ConstructConnectionInfo(Protocol, TestAgainstContainerInfo); + ExpectedPropertyList = ConfigWindowGeneralTests.BuildExpectedConnectionInfoPropertyList(Protocol, TestAgainstContainerInfo); + + ConfigWindow = new ConfigWindow + { + PropertiesVisible = true, + }; + } + + public void RunVerification() + { + ConfigWindow.SelectedTreeNode = ConnectionInfo; + Assert.That( + ConfigWindow.VisibleObjectProperties, + Is.EquivalentTo(ExpectedPropertyList)); + } + } +} diff --git a/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowVncSpecialTests.cs b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowVncSpecialTests.cs new file mode 100644 index 00000000..50cc49b0 --- /dev/null +++ b/mRemoteNGTests/UI/Window/ConfigWindowTests/ConfigWindowVncSpecialTests.cs @@ -0,0 +1,37 @@ +using mRemoteNG.Connection.Protocol; +using mRemoteNG.Connection.Protocol.VNC; +using NUnit.Framework; + +namespace mRemoteNGTests.UI.Window.ConfigWindowTests +{ + public class ConfigWindowVncSpecialTests : ConfigWindowSpecialTestsBase + { + protected override ProtocolType Protocol => ProtocolType.VNC; + + [Test] + public void UserDomainPropertiesShown_WhenAuthModeIsWindows() + { + ConnectionInfo.VNCAuthMode = ProtocolVNC.AuthMode.AuthWin; + ExpectedPropertyList.AddRange(new [] + { + nameof(ConnectionInfo.Username), + nameof(ConnectionInfo.Domain), + }); + } + + [TestCase(ProtocolVNC.ProxyType.ProxyHTTP)] + [TestCase(ProtocolVNC.ProxyType.ProxySocks5)] + [TestCase(ProtocolVNC.ProxyType.ProxyUltra)] + public void ProxyPropertiesShown_WhenProxyModeIsNotNone(ProtocolVNC.ProxyType proxyType) + { + ConnectionInfo.VNCProxyType = proxyType; + ExpectedPropertyList.AddRange(new[] + { + nameof(ConnectionInfo.VNCProxyIP), + nameof(ConnectionInfo.VNCProxyPort), + nameof(ConnectionInfo.VNCProxyUsername), + nameof(ConnectionInfo.VNCProxyPassword), + }); + } + } +} diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj index ab063b29..bf825006 100644 --- a/mRemoteNGTests/mRemoteNGTests.csproj +++ b/mRemoteNGTests/mRemoteNGTests.csproj @@ -233,6 +233,10 @@ + + + + diff --git a/mRemoteV1/App/Windows.cs b/mRemoteV1/App/Windows.cs index 73fc901a..3ffc26a4 100644 --- a/mRemoteV1/App/Windows.cs +++ b/mRemoteV1/App/Windows.cs @@ -1,8 +1,8 @@ -using mRemoteNG.UI.Forms; -using mRemoteNG.UI.Window; -using System; +using System; using mRemoteNG.Messages; using mRemoteNG.UI; +using mRemoteNG.UI.Forms; +using mRemoteNG.UI.Window; namespace mRemoteNG.App { @@ -15,8 +15,14 @@ namespace mRemoteNG.App private static PortScanWindow _portscanForm; private static UltraVNCWindow _ultravncscForm; private static ComponentsCheckWindow _componentscheckForm; + private static ConnectionTreeWindow _treeForm; + + internal static ConnectionTreeWindow TreeForm + { + get => _treeForm ?? (_treeForm = new ConnectionTreeWindow()); + set => _treeForm = value; + } - internal static ConnectionTreeWindow TreeForm { get; set; } = new ConnectionTreeWindow(); internal static ConfigWindow ConfigForm { get; set; } = new ConfigWindow(); internal static ErrorAndInfoWindow ErrorsForm { get; set; } = new ErrorAndInfoWindow(); internal static ScreenshotManagerWindow ScreenshotForm { get; set; } = new ScreenshotManagerWindow(); diff --git a/mRemoteV1/Config/Putty/PuttySessionsManager.cs b/mRemoteV1/Config/Putty/PuttySessionsManager.cs index 42eab567..72e9a1ce 100644 --- a/mRemoteV1/Config/Putty/PuttySessionsManager.cs +++ b/mRemoteV1/Config/Putty/PuttySessionsManager.cs @@ -1,13 +1,13 @@ -using mRemoteNG.Tools; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using mRemoteNG.Tools; using mRemoteNG.Tree.Root; // ReSharper disable ArrangeAccessorOwnerBody namespace mRemoteNG.Config.Putty { - public class PuttySessionsManager + public class PuttySessionsManager { public static PuttySessionsManager Instance { get; } = new PuttySessionsManager(); @@ -35,10 +35,12 @@ namespace mRemoteNG.Config.Putty } } - private void AddSessionsFromProvider(AbstractPuttySessionsProvider provider) + private void AddSessionsFromProvider(AbstractPuttySessionsProvider puttySessionProvider) { - var rootTreeNode = provider.RootInfo; - provider.GetSessions(); + puttySessionProvider.ThrowIfNull(nameof(puttySessionProvider)); + + var rootTreeNode = puttySessionProvider.RootInfo; + puttySessionProvider.GetSessions(); if (!RootPuttySessionsNodes.Contains(rootTreeNode) && rootTreeNode.HasChildren()) RootPuttySessionsNodes.Add(rootTreeNode); diff --git a/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs b/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs index c66b9709..929b66be 100644 --- a/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs +++ b/mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs @@ -1,19 +1,19 @@ -using Microsoft.Win32; -using mRemoteNG.App; -using mRemoteNG.Connection; -using mRemoteNG.Connection.Protocol; -using mRemoteNG.Messages; using System; using System.Collections.Generic; using System.Management; using System.Security.Principal; using System.Text; using System.Web; +using Microsoft.Win32; +using mRemoteNG.App; +using mRemoteNG.Connection; +using mRemoteNG.Connection.Protocol; +using mRemoteNG.Messages; namespace mRemoteNG.Config.Putty { - public class PuttySessionsRegistryProvider : AbstractPuttySessionsProvider + public class PuttySessionsRegistryProvider : AbstractPuttySessionsProvider { private const string PuttySessionsKey = "Software\\SimonTatham\\PuTTY\\Sessions"; private static ManagementEventWatcher _eventWatcher; @@ -39,7 +39,10 @@ namespace mRemoteNG.Config.Putty } public override PuttySessionInfo GetSession(string sessionName) - { + { + if (string.IsNullOrEmpty(sessionName)) + return null; + var sessionsKey = Registry.CurrentUser.OpenSubKey(PuttySessionsKey); var sessionKey = sessionsKey?.OpenSubKey(sessionName); if (sessionKey == null) return null; @@ -50,10 +53,15 @@ namespace mRemoteNG.Config.Putty { PuttySession = sessionName, Name = sessionName, - Hostname = sessionKey.GetValue("HostName").ToString(), - Username = sessionKey.GetValue("UserName").ToString() + Hostname = sessionKey.GetValue("HostName")?.ToString() ?? "", + Username = sessionKey.GetValue("UserName")?.ToString() ?? "" }; - var protocol = string.IsNullOrEmpty(sessionKey.GetValue("Protocol").ToString()) ? sessionKey.GetValue("Protocol").ToString() : "ssh"; + + + var protocol = string.IsNullOrEmpty(sessionKey.GetValue("Protocol")?.ToString()) + ? "ssh" + : sessionKey.GetValue("Protocol").ToString(); + switch (protocol.ToLowerInvariant()) { case "raw": @@ -65,7 +73,7 @@ namespace mRemoteNG.Config.Putty case "serial": return null; case "ssh": - int.TryParse(sessionKey.GetValue("SshProt").ToString(), out var sshVersion); + int.TryParse(sessionKey.GetValue("SshProt")?.ToString(), out var sshVersion); /* Per PUTTY.H in PuTTYNG & PuTTYNG Upstream (PuTTY proper currently) * expect 0 for SSH1, 3 for SSH2 ONLY * 1 for SSH1 with a 2 fallback @@ -81,7 +89,12 @@ namespace mRemoteNG.Config.Putty default: return null; } - sessionInfo.Port = Convert.ToInt32(sessionKey.GetValue("PortNumber")); + + int.TryParse(sessionKey.GetValue("PortNumber")?.ToString(), out var portNumber); + if (portNumber == default(int)) + sessionInfo.SetDefaultPort(); + else + sessionInfo.Port = portNumber; return sessionInfo; } diff --git a/mRemoteV1/Config/Putty/PuttySessionsXmingProvider.cs b/mRemoteV1/Config/Putty/PuttySessionsXmingProvider.cs index e418c0bf..4b99a02a 100644 --- a/mRemoteV1/Config/Putty/PuttySessionsXmingProvider.cs +++ b/mRemoteV1/Config/Putty/PuttySessionsXmingProvider.cs @@ -33,6 +33,7 @@ namespace mRemoteNG.Config.Putty foreach (var sessionName in Directory.GetFiles(sessionsFolderPath)) { var sessionFileName = Path.GetFileName(sessionName); + // ReSharper disable once ConstantConditionalAccessQualifier sessionNames.Add(raw ? sessionFileName : System.Web.HttpUtility.UrlDecode(sessionFileName?.Replace("+", "%2B"))); } @@ -174,7 +175,8 @@ namespace mRemoteNG.Config.Putty private static string GetPuttyConfPath() { var puttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? mRemoteNG.Settings.Default.CustomPuttyPath : App.Info.GeneralAppInfo.PuttyPath; - return Path.Combine(Path.GetDirectoryName(puttyPath), "putty.conf"); + puttyPath = Path.GetDirectoryName(puttyPath); + return string.IsNullOrEmpty(puttyPath) ? null : Path.Combine(puttyPath, "putty.conf"); } private static string GetSessionsFolderPath() @@ -201,6 +203,9 @@ namespace mRemoteNG.Config.Putty private static PuttySessionInfo ModifyRegistrySessionInfo(PuttySessionInfo sessionInfo) { + if (sessionInfo == null) + return null; + sessionInfo.Name = string.Format(RegistrySessionNameFormat, sessionInfo.Name); sessionInfo.PuttySession = string.Format(RegistrySessionNameFormat, sessionInfo.PuttySession); return sessionInfo; diff --git a/mRemoteV1/Config/Settings/SettingsLoader.cs b/mRemoteV1/Config/Settings/SettingsLoader.cs index a228e9d7..a730dac6 100644 --- a/mRemoteV1/Config/Settings/SettingsLoader.cs +++ b/mRemoteV1/Config/Settings/SettingsLoader.cs @@ -19,6 +19,7 @@ namespace mRemoteNG.Config.Settings { private readonly ExternalAppsLoader _externalAppsLoader; private readonly MessageCollector _messageCollector; + private readonly MenuStrip _mainMenu; private readonly QuickConnectToolStrip _quickConnectToolStrip; private readonly ExternalToolsToolStrip _externalToolsToolStrip; private readonly MultiSshToolStrip _multiSshToolStrip; @@ -31,7 +32,8 @@ namespace mRemoteNG.Config.Settings MessageCollector messageCollector, QuickConnectToolStrip quickConnectToolStrip, ExternalToolsToolStrip externalToolsToolStrip, - MultiSshToolStrip multiSshToolStrip) + MultiSshToolStrip multiSshToolStrip, + MenuStrip mainMenu) { if (mainForm == null) throw new ArgumentNullException(nameof(mainForm)); @@ -43,13 +45,16 @@ namespace mRemoteNG.Config.Settings throw new ArgumentNullException(nameof(externalToolsToolStrip)); if (multiSshToolStrip == null) throw new ArgumentNullException(nameof(multiSshToolStrip)); + if (mainMenu == null) + throw new ArgumentNullException(nameof(mainMenu)); MainForm = mainForm; _messageCollector = messageCollector; _quickConnectToolStrip = quickConnectToolStrip; _externalToolsToolStrip = externalToolsToolStrip; _multiSshToolStrip = multiSshToolStrip; - _externalAppsLoader = new ExternalAppsLoader(MainForm, messageCollector, _externalToolsToolStrip); + _mainMenu = mainMenu; + _externalAppsLoader = new ExternalAppsLoader(MainForm, messageCollector, _externalToolsToolStrip); } #region Public Methods @@ -197,6 +202,7 @@ namespace mRemoteNG.Config.Settings private void LoadToolbarsFromSettings() { ResetAllToolbarLocations(); + AddMainMenuPanel(); AddExternalAppsPanel(); AddQuickConnectPanel(); AddMultiSshPanel(); @@ -210,31 +216,49 @@ namespace mRemoteNG.Config.Settings private void ResetAllToolbarLocations() { var tempToolStrip = new ToolStripPanel(); + tempToolStrip.Join(_mainMenu); tempToolStrip.Join(_quickConnectToolStrip); tempToolStrip.Join(_externalToolsToolStrip); tempToolStrip.Join(_multiSshToolStrip); } + private void AddMainMenuPanel() + { + SetToolstripGripStyle(_mainMenu); + var toolStripPanel = ToolStripPanelFromString("top"); + toolStripPanel.Join(_mainMenu, new Point(3, 0)); + } + private void AddQuickConnectPanel() { + SetToolstripGripStyle(_quickConnectToolStrip); + _quickConnectToolStrip.Visible = mRemoteNG.Settings.Default.QuickyTBVisible; var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.QuickyTBParentDock); toolStripPanel.Join(_quickConnectToolStrip, mRemoteNG.Settings.Default.QuickyTBLocation); - _quickConnectToolStrip.Visible = mRemoteNG.Settings.Default.QuickyTBVisible; } private void AddExternalAppsPanel() { - var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock); - toolStripPanel.Join(_externalToolsToolStrip, mRemoteNG.Settings.Default.ExtAppsTBLocation); + SetToolstripGripStyle(_externalToolsToolStrip); _externalToolsToolStrip.Visible = mRemoteNG.Settings.Default.ExtAppsTBVisible; + var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock); + toolStripPanel.Join(_externalToolsToolStrip, mRemoteNG.Settings.Default.ExtAppsTBLocation); } private void AddMultiSshPanel() { - var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock); - toolStripPanel.Join(_multiSshToolStrip, mRemoteNG.Settings.Default.MultiSshToolbarLocation); + SetToolstripGripStyle(_multiSshToolStrip); _multiSshToolStrip.Visible = mRemoteNG.Settings.Default.MultiSshToolbarVisible; + var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.MultiSshToolbarParentDock); + toolStripPanel.Join(_multiSshToolStrip, mRemoteNG.Settings.Default.MultiSshToolbarLocation); } + + private void SetToolstripGripStyle(ToolStrip toolbar) + { + toolbar.GripStyle = mRemoteNG.Settings.Default.LockToolbars + ? ToolStripGripStyle.Hidden + : ToolStripGripStyle.Visible; + } private ToolStripPanel ToolStripPanelFromString(string panel) { diff --git a/mRemoteV1/Connection/ConnectionInfo.cs b/mRemoteV1/Connection/ConnectionInfo.cs index 646ddda7..64a0702d 100644 --- a/mRemoteV1/Connection/ConnectionInfo.cs +++ b/mRemoteV1/Connection/ConnectionInfo.cs @@ -78,7 +78,8 @@ namespace mRemoteNG.Connection var newConnectionInfo = new ConnectionInfo(); newConnectionInfo.CopyFrom(this); newConnectionInfo.Inheritance = Inheritance.Clone(); - return newConnectionInfo; + newConnectionInfo.Inheritance.Parent = newConnectionInfo; + return newConnectionInfo; } public void CopyFrom(ConnectionInfo sourceConnectionInfo) diff --git a/mRemoteV1/Connection/ConnectionInitiator.cs b/mRemoteV1/Connection/ConnectionInitiator.cs index 4502df26..19a8813b 100644 --- a/mRemoteV1/Connection/ConnectionInitiator.cs +++ b/mRemoteV1/Connection/ConnectionInitiator.cs @@ -96,6 +96,7 @@ namespace mRemoteNG.Connection var newProtocol = protocolFactory.CreateProtocol(connectionInfo); var connectionPanel = SetConnectionPanel(connectionInfo, force); + if (string.IsNullOrEmpty(connectionPanel)) return; var connectionForm = SetConnectionForm(conForm, connectionPanel); var connectionContainer = SetConnectionContainer(connectionInfo, connectionForm); SetConnectionFormEventHandlers(newProtocol, connectionForm); @@ -163,6 +164,10 @@ namespace mRemoteNG.Connection { connectionPanel = frmPnl.Panel; } + else + { + return null; + } } else { diff --git a/mRemoteV1/Connection/ConnectionsService.cs b/mRemoteV1/Connection/ConnectionsService.cs index f799f155..c6240ec9 100644 --- a/mRemoteV1/Connection/ConnectionsService.cs +++ b/mRemoteV1/Connection/ConnectionsService.cs @@ -32,11 +32,6 @@ namespace mRemoteNG.Connection public DateTime LastSqlUpdate { get; set; } public ConnectionTreeModel ConnectionTreeModel { get; private set; } - //public ConnectionTreeModel ConnectionTreeModel - //{ - // get { return Windows.TreeForm.ConnectionTree.ConnectionTreeModel; } - // set { Windows.TreeForm.ConnectionTree.ConnectionTreeModel = value; } - //} public ConnectionsService(PuttySessionsManager puttySessionsManager) { @@ -50,6 +45,7 @@ namespace mRemoteNG.Connection { try { + filename.ThrowIfNullOrEmpty(nameof(filename)); var newConnectionsModel = new ConnectionTreeModel(); newConnectionsModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection)); SaveConnections(newConnectionsModel, false, new SaveFilter(), filename, true); @@ -83,6 +79,10 @@ namespace mRemoteNG.Connection { newConnectionInfo.Port = uri.Port; } + + if (string.IsNullOrEmpty(newConnectionInfo.Panel)) + newConnectionInfo.Panel = Language.strGeneral; + newConnectionInfo.IsQuickConnect = true; return newConnectionInfo; @@ -131,11 +131,22 @@ namespace mRemoteNG.Connection RaiseConnectionsLoadedEvent(oldConnectionTreeModel, newConnectionTreeModel, oldIsUsingDatabaseValue, useDatabase, connectionFileName); } + /// + /// When turned on, calls to or + /// will not immediately execute. + /// Instead, they will be deferred until + /// is called. + /// public void BeginBatchingSaves() { _batchingSaves = true; } + /// + /// Immediately executes a single or + /// if one has been requested + /// since calling . + /// public void EndBatchingSaves() { _batchingSaves = false; @@ -222,9 +233,10 @@ namespace mRemoteNG.Connection private void SaveConnectionsBGd() { - Monitor.Enter(SaveLock); - SaveConnections(); - Monitor.Exit(SaveLock); + lock (SaveLock) + { + SaveConnections(); + } } public string GetStartupConnectionFileName() diff --git a/mRemoteV1/Connection/WebHelper.cs b/mRemoteV1/Connection/WebHelper.cs index 75e51a24..27673805 100644 --- a/mRemoteV1/Connection/WebHelper.cs +++ b/mRemoteV1/Connection/WebHelper.cs @@ -13,6 +13,8 @@ namespace mRemoteNG.Connection connectionInfo.Hostname = url; connectionInfo.Protocol = url.StartsWith("https:") ? ProtocolType.HTTPS : ProtocolType.HTTP; connectionInfo.SetDefaultPort(); + if (string.IsNullOrEmpty(connectionInfo.Panel)) + connectionInfo.Panel = Language.strGeneral; connectionInfo.IsQuickConnect = true; var connectionInitiator = new ConnectionInitiator(); connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump); diff --git a/mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs b/mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs index 1f26c713..c9d7d9dc 100644 --- a/mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs +++ b/mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using System.Windows.Forms; using mRemoteNG.Messages.MessageWriters; using mRemoteNG.UI.Forms; @@ -12,29 +13,21 @@ namespace mRemoteNG.Messages.WriterDecorators private readonly IMessageTypeFilteringOptions _filter; private readonly IMessageWriter _decoratedWriter; private readonly ErrorAndInfoWindow _messageWindow; - private Timer _ecTimer; private readonly FrmMain _frmMain = FrmMain.Default; public MessageFocusDecorator(ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter) { - if (filter == null) - throw new ArgumentNullException(nameof(filter)); - if (messageWindow == null) - throw new ArgumentNullException(nameof(messageWindow)); - if (decoratedWriter == null) - throw new ArgumentNullException(nameof(decoratedWriter)); - - _filter = filter; - _messageWindow = messageWindow; - _decoratedWriter = decoratedWriter; - CreateTimer(); + _filter = filter ?? throw new ArgumentNullException(nameof(filter)); + _messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow)); + _decoratedWriter = decoratedWriter ?? throw new ArgumentNullException(nameof(decoratedWriter)); } - public void Write(IMessage message) + public async void Write(IMessage message) { - if (WeShouldFocusNotificationPanel(message)) - BeginSwitchToPanel(); _decoratedWriter.Write(message); + + if (WeShouldFocusNotificationPanel(message)) + await SwitchToMessageAsync(); } private bool WeShouldFocusNotificationPanel(IMessage message) @@ -43,7 +36,8 @@ namespace mRemoteNG.Messages.WriterDecorators switch (message.Class) { case MessageClass.InformationMsg: - if (_filter.AllowInfoMessages) return true; + if (_filter.AllowInfoMessages) + return true; break; case MessageClass.WarningMsg: if (_filter.AllowWarningMessages) return true; @@ -55,43 +49,46 @@ namespace mRemoteNG.Messages.WriterDecorators return false; } - private void CreateTimer() + private async Task SwitchToMessageAsync() { - _ecTimer = new Timer - { - Enabled = false, - Interval = 300 - }; - _ecTimer.Tick += SwitchTimerTick; - } - - private void BeginSwitchToPanel() - { - _ecTimer.Enabled = true; - } - - private void SwitchTimerTick(object sender, EventArgs e) - { - SwitchToMessage(); - _ecTimer.Enabled = false; + await Task + .Delay(TimeSpan.FromMilliseconds(300)) + .ContinueWith(task => SwitchToMessage()); } private void SwitchToMessage() { + if (_messageWindow.InvokeRequired) + { + _frmMain.Invoke((MethodInvoker)SwitchToMessage); + return; + } + + // do not attempt to focus the notification panel if it is in an inconsistent state + if (_messageWindow.DockState == DockState.Unknown) + return; + _messageWindow.PreviousActiveForm = (DockContent)_frmMain.pnlDock.ActiveContent; - ShowMcForm(); + + // Show the notifications panel solution: + // https://stackoverflow.com/questions/13843604/calling-up-dockpanel-suites-autohidden-dockcontent-programmatically + if (AutoHideEnabled(_messageWindow)) + _frmMain.pnlDock.ActiveAutoHideContent = _messageWindow; + else + _messageWindow.Show(_frmMain.pnlDock); + _messageWindow.lvErrorCollector.Focus(); _messageWindow.lvErrorCollector.SelectedItems.Clear(); _messageWindow.lvErrorCollector.Items[0].Selected = true; _messageWindow.lvErrorCollector.FocusedItem = _messageWindow.lvErrorCollector.Items[0]; } - private void ShowMcForm() + private bool AutoHideEnabled(DockContent content) { - if (_frmMain.pnlDock.InvokeRequired) - _frmMain.pnlDock.Invoke((MethodInvoker)ShowMcForm); - else - _messageWindow.Show(_frmMain.pnlDock); + return content.DockState == DockState.DockBottomAutoHide || + content.DockState == DockState.DockTopAutoHide || + content.DockState == DockState.DockLeftAutoHide || + content.DockState == DockState.DockRightAutoHide; } } } \ No newline at end of file diff --git a/mRemoteV1/Properties/AssemblyInfo.cs b/mRemoteV1/Properties/AssemblyInfo.cs index 47f3885d..2d2f304f 100644 --- a/mRemoteV1/Properties/AssemblyInfo.cs +++ b/mRemoteV1/Properties/AssemblyInfo.cs @@ -33,5 +33,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // -[assembly: AssemblyVersion("1.76.5.*")] +[assembly: AssemblyVersion("1.76.6.*")] [assembly: NeutralResourcesLanguage("en")] \ No newline at end of file diff --git a/mRemoteV1/Properties/Settings.Designer.cs b/mRemoteV1/Properties/Settings.Designer.cs index 8baba315..885f33ec 100644 --- a/mRemoteV1/Properties/Settings.Designer.cs +++ b/mRemoteV1/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace mRemoteNG { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -2593,7 +2593,7 @@ namespace mRemoteNG { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] + [global::System.Configuration.DefaultSettingValueAttribute("General")] public string ConDefaultPanel { get { return ((string)(this["ConDefaultPanel"])); diff --git a/mRemoteV1/Properties/Settings.settings b/mRemoteV1/Properties/Settings.settings index 313e4d63..4f2f8cc6 100644 --- a/mRemoteV1/Properties/Settings.settings +++ b/mRemoteV1/Properties/Settings.settings @@ -645,7 +645,7 @@ - + General True diff --git a/mRemoteV1/Properties/app.manifest b/mRemoteV1/Properties/app.manifest index 4c249cd2..3b4845c3 100644 --- a/mRemoteV1/Properties/app.manifest +++ b/mRemoteV1/Properties/app.manifest @@ -1,6 +1,6 @@  - + @@ -17,6 +17,10 @@ --> + + + + - + \ No newline at end of file diff --git a/mRemoteV1/Resources/Language/Language.Designer.cs b/mRemoteV1/Resources/Language/Language.Designer.cs index e93828e7..d2c32ce5 100644 --- a/mRemoteV1/Resources/Language/Language.Designer.cs +++ b/mRemoteV1/Resources/Language/Language.Designer.cs @@ -1711,6 +1711,15 @@ namespace mRemoteNG { } } + /// + /// Looks up a localized string similar to Delete.... + /// + internal static string strDelete { + get { + return ResourceManager.GetString("strDelete", resourceCulture); + } + } + /// /// Looks up a localized string similar to Detect. /// @@ -2777,6 +2786,15 @@ namespace mRemoteNG { } } + /// + /// Looks up a localized string similar to Must Be Between 0 and 255. + /// + internal static string strIPRange { + get { + return ResourceManager.GetString("strIPRange", resourceCulture); + } + } + /// /// Looks up a localized string similar to CTRL-ALT-DEL. /// @@ -4308,6 +4326,15 @@ namespace mRemoteNG { } } + /// + /// Looks up a localized string similar to Out Of Range. + /// + internal static string strOutOfRange { + get { + return ResourceManager.GetString("strOutOfRange", resourceCulture); + } + } + /// /// Looks up a localized string similar to Panel Name. /// @@ -6237,6 +6264,15 @@ namespace mRemoteNG { } } + /// + /// Looks up a localized string similar to Reconnect All Connections. + /// + internal static string strReconnectAllConnections { + get { + return ResourceManager.GetString("strReconnectAllConnections", resourceCulture); + } + } + /// /// Looks up a localized string similar to Reconnect to previously opened sessions on startup. /// @@ -7263,6 +7299,15 @@ namespace mRemoteNG { } } + /// + /// Looks up a localized string similar to UltraVNC SingleClick. + /// + internal static string strUltraVNCSingleClick { + get { + return ResourceManager.GetString("strUltraVNCSingleClick", resourceCulture); + } + } + /// /// Looks up a localized string similar to Uncheck the properties you want not to be saved!. /// diff --git a/mRemoteV1/Resources/Language/Language.resx b/mRemoteV1/Resources/Language/Language.resx index 60bc8bb8..1c99d700 100644 --- a/mRemoteV1/Resources/Language/Language.resx +++ b/mRemoteV1/Resources/Language/Language.resx @@ -2679,4 +2679,19 @@ This page will walk you through the process of upgrading your connections file o Create an empty panel when mRemoteNG starts + + Must Be Between 0 and 255 + + + Out Of Range + + + Delete... + + + Reconnect All Connections + + + UltraVNC SingleClick + \ No newline at end of file diff --git a/mRemoteV1/Themes/ExtendedColorPalette.cs b/mRemoteV1/Themes/ExtendedColorPalette.cs index dfaa7e0c..4ecc1c52 100644 --- a/mRemoteV1/Themes/ExtendedColorPalette.cs +++ b/mRemoteV1/Themes/ExtendedColorPalette.cs @@ -9,35 +9,14 @@ namespace mRemoteNG.Themes /// public class PseudoKeyColor { - private string key; - private Color value; public PseudoKeyColor(string _key, Color _value) { - key = _key; - value = _value; - } - public string Key - { - get - { - return key; - } - set - { - key = value; - } - } - public Color Value - { - get - { - return value; - } - set - { - this.value = value; - } + Key = _key; + Value = _value; } + public string Key { get; set; } + + public Color Value { get; set; } } @@ -48,15 +27,14 @@ namespace mRemoteNG.Themes { #region Private Variables //Collection for color values that are not loaded by dock panels (list, buttons,panel content, etc) - private Dictionary _extendedColors; - private Dictionary _default; + #endregion #region Constructors public ExtendedColorPalette() { - _extendedColors = new Dictionary(); - _default = new Dictionary(); // If this is the default palette, it will not have a default-default palette + ExtColorPalette = new Dictionary(); + DefaultColorPalette = new Dictionary(); // If this is the default palette, it will not have a default-default palette } #endregion @@ -65,7 +43,7 @@ namespace mRemoteNG.Themes // Set the default theme, that theme should contain all color values used by the application public void setDefault(ExtendedColorPalette inPalettte) { - _default = inPalettte._extendedColors; + DefaultColorPalette = inPalettte.ExtColorPalette; } #endregion @@ -76,12 +54,12 @@ namespace mRemoteNG.Themes /// public Color getColor(string colorKey) { - var retColor = _extendedColors.ContainsKey(colorKey) ? _extendedColors[colorKey]:Color.Empty; + var retColor = ExtColorPalette.ContainsKey(colorKey) ? ExtColorPalette[colorKey]:Color.Empty; //Invisible colors are not good, might indicate missing color from the palette as is represented by 00000000 if (retColor != Color.Empty && retColor.A != 0) return retColor; - if(_default != null) + if(DefaultColorPalette != null) { - retColor = _default.ContainsKey(colorKey) ? _default[colorKey] : Color.Empty; + retColor = DefaultColorPalette.ContainsKey(colorKey) ? DefaultColorPalette[colorKey] : Color.Empty; } //why are we here?, just avoid a crash if(retColor == Color.Empty) @@ -100,7 +78,7 @@ namespace mRemoteNG.Themes /// public void addColor(string colorKey,Color inColor) { - _extendedColors.Add(colorKey, inColor); + ExtColorPalette.Add(colorKey, inColor); } @@ -111,33 +89,13 @@ namespace mRemoteNG.Themes /// public void replaceColor(string colorKey, Color inColor) { - _extendedColors[colorKey]= inColor; + ExtColorPalette[colorKey]= inColor; } - public Dictionary DefaultColorPalette - { - get - { - return _default; - } - set - { - _default = value; - } - } + public Dictionary DefaultColorPalette { get; set; } - public Dictionary ExtColorPalette - { - get - { - return _extendedColors; - } - set - { - _extendedColors = value; - } - } + public Dictionary ExtColorPalette { get; set; } } } diff --git a/mRemoteV1/Themes/MremoteNGPaletteManipulator.cs b/mRemoteV1/Themes/MremoteNGPaletteManipulator.cs index adca1727..2ee357cb 100644 --- a/mRemoteV1/Themes/MremoteNGPaletteManipulator.cs +++ b/mRemoteV1/Themes/MremoteNGPaletteManipulator.cs @@ -34,7 +34,7 @@ namespace mRemoteNG.Themes foreach (DictionaryEntry entry in resourceSet) { var colorName = entry.Key.ToString(); - var xmlQueryPath = (string)entry.Value; + var xmlQueryPath = entry.Value.ToString(); if (_xml.DocumentElement == null) continue; var colorNodeList = _xml.DocumentElement.FirstChild.SelectNodes(xmlQueryPath); var color = colorNodeList != null && colorNodeList.Count > 0 ? colorNodeList[0].Value : null; @@ -60,7 +60,7 @@ namespace mRemoteNG.Themes foreach (DictionaryEntry entry in resourceSet) { var colorName = entry.Key.ToString(); - var xmlQueryPath = (string)entry.Value; + var xmlQueryPath = entry.Value.ToString(); var colorNodeList = _xml.DocumentElement?.FirstChild.SelectNodes(xmlQueryPath); if (colorNodeList == null || colorNodeList.Count <= 0) continue; var paletteColor = colorPalette.getColor(colorName); diff --git a/mRemoteV1/Themes/ThemeInfo.cs b/mRemoteV1/Themes/ThemeInfo.cs index 1fa03269..86db8d84 100644 --- a/mRemoteV1/Themes/ThemeInfo.cs +++ b/mRemoteV1/Themes/ThemeInfo.cs @@ -7,6 +7,7 @@ using WeifenLuo.WinFormsUI.Docking; namespace mRemoteNG.Themes { + /// /// /// Container class for all the color and style elements to define a theme /// @@ -15,34 +16,32 @@ namespace mRemoteNG.Themes #region Private Variables private string _name; private ThemeBase _theme; - private String _URI; + private string _URI; private VisualStudioToolStripExtender.VsVersion _version; private ExtendedColorPalette _extendedPalette; - private bool _isThemeBase; - private bool _isExtendable; #endregion #region Constructors - public ThemeInfo(string themeName, ThemeBase inTheme, String inURI, VisualStudioToolStripExtender.VsVersion inVersion, ExtendedColorPalette inExtendedPalette) + public ThemeInfo(string themeName, ThemeBase inTheme, string inURI, VisualStudioToolStripExtender.VsVersion inVersion, ExtendedColorPalette inExtendedPalette) { _name = themeName; _theme = inTheme; _URI = inURI; _version = inVersion; _extendedPalette = inExtendedPalette; - _isThemeBase = false; - _isExtendable = false; + IsThemeBase = false; + IsExtendable = false; } - public ThemeInfo(string themeName, ThemeBase inTheme, String inURI, VisualStudioToolStripExtender.VsVersion inVersion) + public ThemeInfo(string themeName, ThemeBase inTheme, string inURI, VisualStudioToolStripExtender.VsVersion inVersion) { _name = themeName; _theme = inTheme; _URI = inURI; _version = inVersion; - _isThemeBase = false; - _isExtendable = false; + IsThemeBase = false; + IsExtendable = false; } #endregion @@ -57,8 +56,8 @@ namespace mRemoteNG.Themes }; var clonedObj = new ThemeInfo(_name, _theme, _URI, _version, extPalette) { - IsExtendable = _isExtendable, - IsThemeBase = _isThemeBase + IsExtendable = IsExtendable, + IsThemeBase = IsThemeBase }; return clonedObj; @@ -71,8 +70,8 @@ namespace mRemoteNG.Themes [Browsable(false)] public string Name { - get { return _name; } - set + get => _name; + set { if (string.Equals(_name, value, StringComparison.InvariantCulture)) { @@ -84,7 +83,7 @@ namespace mRemoteNG.Themes public ThemeBase Theme { - get { return _theme; } + get => _theme; set { if (value != null && _theme == value) @@ -97,7 +96,7 @@ namespace mRemoteNG.Themes public string URI { - get { return _URI; } + get => _URI; set { if (value != null && _URI == value) @@ -110,7 +109,7 @@ namespace mRemoteNG.Themes public VisualStudioToolStripExtender.VsVersion Version { - get { return _version; } + get => _version; set { if (Equals(_version, value)) @@ -123,7 +122,7 @@ namespace mRemoteNG.Themes public ExtendedColorPalette ExtendedPalette { - get { return _extendedPalette; } + get => _extendedPalette; set { if (_extendedPalette != null && _extendedPalette == value) @@ -134,23 +133,10 @@ namespace mRemoteNG.Themes } } - public bool IsThemeBase - { - get { return _isThemeBase; } - set - { - _isThemeBase = value; - } - } + public bool IsThemeBase { get; set; } + + public bool IsExtendable { get; set; } - public bool IsExtendable - { - get { return _isExtendable; } - set - { - _isExtendable = value; - } - } #endregion } } \ No newline at end of file diff --git a/mRemoteV1/Themes/ThemeManager.cs b/mRemoteV1/Themes/ThemeManager.cs index 6941446e..a3b9a2e2 100644 --- a/mRemoteV1/Themes/ThemeManager.cs +++ b/mRemoteV1/Themes/ThemeManager.cs @@ -46,11 +46,7 @@ namespace mRemoteNG.Themes #region Public Methods public static ThemeManager getInstance() { - if(themeInstance == null) - { - themeInstance = new ThemeManager(); - } - return themeInstance; + return themeInstance ?? (themeInstance = new ThemeManager()); } @@ -64,80 +60,74 @@ namespace mRemoteNG.Themes //THe manager precharges all the themes at once public List LoadThemes() { - if (themes == null) + if (themes != null) return themes.Values.OfType().ToList(); + themes = new Hashtable(); + + //Load the files in theme folder first, to incluide vstheme light as default + var themePath = App.Info.SettingsFileInfo.ThemeFolder; + if (themePath == null) return themes.Values.OfType().ToList(); + try { - themes = new Hashtable(); - - //Load the files in theme folder first, to incluide vstheme light as default - string themePath = App.Info.SettingsFileInfo.ThemeFolder; - if (themePath != null) + //In install mode first time is necesary to copy the themes folder + if (!Directory.Exists(themePath)) { - try - { - //In install mode first time is necesary to copy the themes folder - if (!Directory.Exists(themePath)) - { - Directory.CreateDirectory(themePath); + Directory.CreateDirectory(themePath); - } - DirectoryInfo orig = new DirectoryInfo(App.Info.SettingsFileInfo.InstalledThemeFolder); - FileInfo[] files = orig.GetFiles(); - foreach (FileInfo file in files) - { + } + var orig = new DirectoryInfo(App.Info.SettingsFileInfo.InstalledThemeFolder); + var files = orig.GetFiles(); + foreach (var file in files) + { - if (!File.Exists(Path.Combine(themePath, file.Name))) - file.CopyTo(Path.Combine(themePath, file.Name), true); - } - - - - //Check that theme folder exist before trying to load themes - if (Directory.Exists(themePath)) - { - string[] themeFiles = Directory.GetFiles(themePath, "*.vstheme"); - string defaultThemeURL = Directory.GetFiles(themePath, "vs2015light" + ".vstheme")[0]; - //First we load the default theme, its vs2015light - ThemeInfo defaultTheme = ThemeSerializer.LoadFromXmlFile(defaultThemeURL); - themes.Add(defaultTheme.Name, defaultTheme); - //Then the rest - foreach (string themeFile in themeFiles) - { - //filter default one - ThemeInfo extTheme = ThemeSerializer.LoadFromXmlFile(themeFile, defaultTheme); - if (extTheme.Theme != null && !themes.ContainsKey(extTheme.Name)) - { - themes.Add(extTheme.Name, extTheme); - } - } - - - //Load the embedded themes, extended palettes are taken from the vs2015 themes, trying to match the color theme - ThemeInfo vs2003 = new ThemeInfo("Vs2003", new VS2003Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2003, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); - themes.Add(vs2003.Name, vs2003); - ThemeInfo vs2005 = new ThemeInfo("Vs2005", new VS2005Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2005, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); - themes.Add(vs2005.Name, vs2005); - ThemeInfo vs2012Light = new ThemeInfo("vs2012Light", new VS2012LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); - themes.Add(vs2012Light.Name, vs2012Light); - ThemeInfo vs2012Dark = new ThemeInfo("vs2012Dark", new VS2012DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette); - themes.Add(vs2012Dark.Name, vs2012Dark); - ThemeInfo vs2012Blue = new ThemeInfo("vs2012Blue", new VS2012BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette); - themes.Add(vs2012Blue.Name, vs2012Blue); - ThemeInfo vs2013Light = new ThemeInfo("vs2013Light", new VS2013LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); - themes.Add(vs2013Light.Name, vs2013Light); - ThemeInfo vs2013Dark = new ThemeInfo("vs2013Dark", new VS2013DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette); - themes.Add(vs2013Dark.Name, vs2013Dark); - ThemeInfo vs2013Blue = new ThemeInfo("vs2013Blue", new VS2013BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette); - themes.Add(vs2013Blue.Name, vs2013Blue); - } - } - catch(Exception ex ) - { - Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Error loading themes" + Environment.NewLine + ex.Message, true); - } - + if (!File.Exists(Path.Combine(themePath, file.Name))) + file.CopyTo(Path.Combine(themePath, file.Name), true); } - } + + + //Check that theme folder exist before trying to load themes + if (Directory.Exists(themePath)) + { + var themeFiles = Directory.GetFiles(themePath, "*.vstheme"); + var defaultThemeURL = Directory.GetFiles(themePath, "vs2015light" + ".vstheme")[0]; + //First we load the default theme, its vs2015light + var defaultTheme = ThemeSerializer.LoadFromXmlFile(defaultThemeURL); + themes.Add(defaultTheme.Name, defaultTheme); + //Then the rest + foreach (var themeFile in themeFiles) + { + //filter default one + var extTheme = ThemeSerializer.LoadFromXmlFile(themeFile, defaultTheme); + if (extTheme.Theme != null && !themes.ContainsKey(extTheme.Name)) + { + themes.Add(extTheme.Name, extTheme); + } + } + + + //Load the embedded themes, extended palettes are taken from the vs2015 themes, trying to match the color theme + var vs2003 = new ThemeInfo("Vs2003", new VS2003Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2003, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); + themes.Add(vs2003.Name, vs2003); + var vs2005 = new ThemeInfo("Vs2005", new VS2005Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2005, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); + themes.Add(vs2005.Name, vs2005); + var vs2012Light = new ThemeInfo("vs2012Light", new VS2012LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); + themes.Add(vs2012Light.Name, vs2012Light); + var vs2012Dark = new ThemeInfo("vs2012Dark", new VS2012DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette); + themes.Add(vs2012Dark.Name, vs2012Dark); + var vs2012Blue = new ThemeInfo("vs2012Blue", new VS2012BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette); + themes.Add(vs2012Blue.Name, vs2012Blue); + var vs2013Light = new ThemeInfo("vs2013Light", new VS2013LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette); + themes.Add(vs2013Light.Name, vs2013Light); + var vs2013Dark = new ThemeInfo("vs2013Dark", new VS2013DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette); + themes.Add(vs2013Dark.Name, vs2013Dark); + var vs2013Blue = new ThemeInfo("vs2013Blue", new VS2013BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette); + themes.Add(vs2013Blue.Name, vs2013Blue); + } + } + catch(Exception ex) + { + Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, "Error loading themes" + Environment.NewLine + ex.Message, true); + } return themes.Values.OfType().ToList(); } @@ -149,29 +139,24 @@ namespace mRemoteNG.Themes /// public ThemeInfo addTheme(ThemeInfo baseTheme, string newThemeName) { - if (!themes.Contains(newThemeName)) - { - ThemeInfo modifiedTheme = (ThemeInfo)baseTheme.Clone(); - modifiedTheme.Name = newThemeName; - modifiedTheme.IsExtendable = true; - modifiedTheme.IsThemeBase = false; - ThemeSerializer.SaveToXmlFile(modifiedTheme,baseTheme); - themes.Add(newThemeName,modifiedTheme); - return modifiedTheme; - } - return null; + if (themes.Contains(newThemeName)) return null; + var modifiedTheme = (ThemeInfo)baseTheme.Clone(); + modifiedTheme.Name = newThemeName; + modifiedTheme.IsExtendable = true; + modifiedTheme.IsThemeBase = false; + ThemeSerializer.SaveToXmlFile(modifiedTheme,baseTheme); + themes.Add(newThemeName,modifiedTheme); + return modifiedTheme; } //Delete a theme from memory and disk public void deleteTheme(ThemeInfo themeToDelete) { - if (themes.Contains(themeToDelete.Name)) - { - if(ActiveTheme == themeToDelete) - ActiveTheme = DefaultTheme; - themes.Remove(themeToDelete.Name); - ThemeSerializer.DeleteFile(themeToDelete); - } + if (!themes.Contains(themeToDelete.Name)) return; + if(ActiveTheme == themeToDelete) + ActiveTheme = DefaultTheme; + themes.Remove(themeToDelete.Name); + ThemeSerializer.DeleteFile(themeToDelete); } //Sincronize the theme XML values from memory to disk @@ -191,10 +176,8 @@ namespace mRemoteNG.Themes { if (themes.Contains(name)) return false; - char[] badChars = Path.GetInvalidFileNameChars(); - if (name.IndexOfAny(badChars) != -1) - return false; - return true; + var badChars = Path.GetInvalidFileNameChars(); + return name.IndexOfAny(badChars) == -1; } @@ -206,10 +189,11 @@ namespace mRemoteNG.Themes public event ThemeChangedEventHandler ThemeChanged { - add { ThemeChangedEvent = (ThemeChangedEventHandler)System.Delegate.Combine(ThemeChangedEvent, value); } - remove { ThemeChangedEvent = (ThemeChangedEventHandler)System.Delegate.Remove(ThemeChangedEvent, value); } + add => ThemeChangedEvent = (ThemeChangedEventHandler)Delegate.Combine(ThemeChangedEvent, value); + remove => ThemeChangedEvent = (ThemeChangedEventHandler)Delegate.Remove(ThemeChangedEvent, value); } + // ReSharper disable once UnusedParameter.Local private void NotifyThemeChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Name") @@ -223,44 +207,29 @@ namespace mRemoteNG.Themes #region Properties public bool ThemingActive { - get - { - return _themeActive; - } + get => _themeActive; set { - if(themes.Count != 0) - { - _themeActive = value; - Settings.Default.ThemingActive = value; - NotifyThemeChanged(this, new PropertyChangedEventArgs("")); - } + if (themes.Count == 0) return; + _themeActive = value; + Settings.Default.ThemingActive = value; + NotifyThemeChanged(this, new PropertyChangedEventArgs("")); } } - private ThemeInfo DefaultTheme - { - get - { - return (ThemeInfo) themes["vs2015light"]; - } - } - + public ThemeInfo DefaultTheme => (ThemeInfo) themes["vs2015light"]; + public ThemeInfo ActiveTheme { - get - { - return _activeTheme; - } - set + // default if themes are not enabled + get => ThemingActive == false ? DefaultTheme : _activeTheme; + set { //You can only enable theming if there are themes laoded - if(value != null) - { - _activeTheme = value; - Settings.Default.ThemeName = value.Name; - NotifyThemeChanged(this, new PropertyChangedEventArgs("theme")); - } + if (value == null) return; + _activeTheme = value; + Settings.Default.ThemeName = value.Name; + NotifyThemeChanged(this, new PropertyChangedEventArgs("theme")); } } #endregion diff --git a/mRemoteV1/Themes/ThemeSerializer.cs b/mRemoteV1/Themes/ThemeSerializer.cs index d23c97e5..25eacc97 100644 --- a/mRemoteV1/Themes/ThemeSerializer.cs +++ b/mRemoteV1/Themes/ThemeSerializer.cs @@ -1,25 +1,22 @@ -using System.Collections.Generic; -using System; -using System.Drawing; using System.IO; -using System.Xml; using WeifenLuo.WinFormsUI.Docking; using System.Linq; namespace mRemoteNG.Themes { - public class ThemeSerializer + public static class ThemeSerializer { - /// - /// Save the theme to file, name property is used as filename - /// The baseTheme is used as a template, by copy that file and rewrite the extpalette values - /// - /// - public static void SaveToXmlFile(ThemeInfo themeToSave,ThemeInfo baseTheme) + /// + /// Save the theme to file, name property is used as filename + /// The baseTheme is used as a template, by copy that file and rewrite the extpalette values + /// + /// + /// + public static void SaveToXmlFile(ThemeInfo themeToSave,ThemeInfo baseTheme) { - string oldURI = baseTheme.URI; - String directoryName = Path.GetDirectoryName(oldURI); - string toSaveURI = directoryName + Path.DirectorySeparatorChar + themeToSave.Name + ".vstheme"; + var oldURI = baseTheme.URI; + var directoryName = Path.GetDirectoryName(oldURI); + var toSaveURI = directoryName + Path.DirectorySeparatorChar + themeToSave.Name + ".vstheme"; File.Copy(baseTheme.URI, toSaveURI); themeToSave.URI = toSaveURI; } @@ -35,10 +32,9 @@ namespace mRemoteNG.Themes /// public static void UpdateThemeXMLValues(ThemeInfo themeToUpdate) { - byte[] bytesIn = File.ReadAllBytes(themeToUpdate.URI); - MremoteNGPaletteManipulator manipulator; - manipulator = new MremoteNGPaletteManipulator(bytesIn, themeToUpdate.ExtendedPalette); - byte[] bytesOut = manipulator.mergePalette(themeToUpdate.ExtendedPalette); + var bytesIn = File.ReadAllBytes(themeToUpdate.URI); + var manipulator = new MremoteNGPaletteManipulator(bytesIn, themeToUpdate.ExtendedPalette); + var bytesOut = manipulator.mergePalette(themeToUpdate.ExtendedPalette); File.WriteAllBytes(themeToUpdate.URI, bytesOut); } @@ -50,22 +46,22 @@ namespace mRemoteNG.Themes /// public static ThemeInfo LoadFromXmlFile(string filename, ThemeInfo defaultTheme=null) { - byte[] bytes = File.ReadAllBytes(filename); + var bytes = File.ReadAllBytes(filename); //Load the dockpanel part - MremoteNGThemeBase themeBaseLoad= new MremoteNGThemeBase(bytes); + var themeBaseLoad= new MremoteNGThemeBase(bytes); //Load the mremote part - MremoteNGPaletteManipulator extColorLoader; - //Cause we cannot default the theme for the default theme - extColorLoader = new MremoteNGPaletteManipulator(bytes, defaultTheme ==null ? null:defaultTheme.ExtendedPalette); - ThemeInfo loadedTheme = new ThemeInfo(Path.GetFileNameWithoutExtension(filename), themeBaseLoad, filename, VisualStudioToolStripExtender.VsVersion.Vs2015, extColorLoader.getColors()); - if((new string[] { "darcula", "vs2015blue", "vs2015dark" , "vs2015light" }).Contains(Path.GetFileNameWithoutExtension(filename))) + //Cause we cannot default the theme for the default theme + var extColorLoader = new MremoteNGPaletteManipulator(bytes, defaultTheme?.ExtendedPalette); + var loadedTheme = new ThemeInfo(Path.GetFileNameWithoutExtension(filename), themeBaseLoad, filename, VisualStudioToolStripExtender.VsVersion.Vs2015, extColorLoader.getColors()); + if(new[] { "darcula", "vs2015blue", "vs2015dark" , "vs2015light" }.Contains(Path.GetFileNameWithoutExtension(filename))) { loadedTheme.IsThemeBase = true; } loadedTheme.IsExtendable = true; return loadedTheme; } - + + /* private static string EncodeColorName(Color color) { // best/simplest answer to converting to hex: http://stackoverflow.com/questions/12078942/how-to-convert-from-argb-to-hex-aarrggbb @@ -77,7 +73,7 @@ namespace mRemoteNG.Themes var regex = new System.Text.RegularExpressions.Regex("^[0-9a-fA-F]{8}$"); return regex.Match(name).Success ? Color.FromArgb(Convert.ToInt32(name, 16)) : Color.FromName(name); } - + */ } } diff --git a/mRemoteV1/UI/Controls/Base/NGComboBox.cs b/mRemoteV1/UI/Controls/Base/NGComboBox.cs index a3ca197b..4163aade 100644 --- a/mRemoteV1/UI/Controls/Base/NGComboBox.cs +++ b/mRemoteV1/UI/Controls/Base/NGComboBox.cs @@ -73,7 +73,7 @@ namespace mRemoteNG.UI.Controls.Base else e.Graphics.FillRectangle(new SolidBrush(_themeManager.ActiveTheme.ExtendedPalette.getColor("ComboBox_Background")), e.Bounds); - if(DisplayMember == null || DisplayMember == "") + if(string.IsNullOrEmpty(DisplayMember)) e.Graphics.DrawString(Items[index].ToString(), e.Font, itemBrush, e.Bounds, StringFormat.GenericDefault); else { @@ -129,7 +129,7 @@ namespace mRemoteNG.UI.Controls.Base } //Arrow - e.Graphics.DrawString("\u25BC", this.Font, new SolidBrush(ButtFore), Width-17, Height/2 -5); + e.Graphics.DrawString("\u25BC", Font, new SolidBrush(ButtFore), Width-17, Height/2 -5); //Text var textRect = new Rectangle(2, 2, Width - 20, Height - 4); diff --git a/mRemoteV1/UI/Controls/Base/NGGroupBox.cs b/mRemoteV1/UI/Controls/Base/NGGroupBox.cs index 4fbaf951..3d369529 100644 --- a/mRemoteV1/UI/Controls/Base/NGGroupBox.cs +++ b/mRemoteV1/UI/Controls/Base/NGGroupBox.cs @@ -10,7 +10,7 @@ namespace mRemoteNG.UI.Controls.Base { private ThemeManager _themeManager; - public NGGroupBox() : base() + public NGGroupBox() { ThemeManager.getInstance().ThemeChanged += OnCreateControl; } diff --git a/mRemoteV1/UI/Controls/Base/NGLabel.cs b/mRemoteV1/UI/Controls/Base/NGLabel.cs index b2775bf5..0613f445 100644 --- a/mRemoteV1/UI/Controls/Base/NGLabel.cs +++ b/mRemoteV1/UI/Controls/Base/NGLabel.cs @@ -42,12 +42,12 @@ namespace mRemoteNG.UI.Controls.Base e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias; if (Enabled) { - TextRenderer.DrawText(e.Graphics, this.Text, Font, ClientRectangle, ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); + TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); } else { var disabledtextLabel = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Disabled_Foreground"); - TextRenderer.DrawText(e.Graphics, this.Text, Font, ClientRectangle, disabledtextLabel, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); + TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, disabledtextLabel, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); } } diff --git a/mRemoteV1/UI/Controls/Base/NGNumericUpDown.cs b/mRemoteV1/UI/Controls/Base/NGNumericUpDown.cs index 9afc7d92..4b6cec61 100644 --- a/mRemoteV1/UI/Controls/Base/NGNumericUpDown.cs +++ b/mRemoteV1/UI/Controls/Base/NGNumericUpDown.cs @@ -1,7 +1,8 @@ -using mRemoteNG.Themes; -using System; +using System; using System.Drawing; using System.Windows.Forms; +using mRemoteNG.Themes; +// ReSharper disable LocalizableElement namespace mRemoteNG.UI.Controls.Base { @@ -14,7 +15,7 @@ namespace mRemoteNG.UI.Controls.Base private NGButton Up; private NGButton Down; - public NGNumericUpDown() : base() + public NGNumericUpDown() { _themeManager = ThemeManager.getInstance(); ThemeManager.getInstance().ThemeChanged += OnCreateControl; @@ -28,7 +29,8 @@ namespace mRemoteNG.UI.Controls.Base BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background"); SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true); //Hide those nonthemable butons - Controls[0].Hide(); + if (Controls.Count > 0) + Controls[0].Hide(); //Add new themable buttons Up = new NGButton { diff --git a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs index 4efb7809..ae4137d8 100644 --- a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs +++ b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs @@ -20,7 +20,8 @@ namespace mRemoteNG.UI.Controls private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler(); private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance; private readonly StatusImageList _statusImageList = new StatusImageList(); - private bool _nodeInEditMode; + private readonly ConnectionTreeSearchTextFilter _connectionTreeSearchTextFilter = new ConnectionTreeSearchTextFilter(); + private bool _nodeInEditMode; private bool _allowEdit; private ConnectionContextMenu _contextMenu; private ConnectionTreeModel _connectionTreeModel; @@ -54,8 +55,6 @@ namespace mRemoteNG.UI.Controls UseOverlays = false; } - - protected override void Dispose(bool disposing) { if (disposing) @@ -265,6 +264,9 @@ namespace mRemoteNG.UI.Controls if (SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttyRoot || SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttySession) return; + // the new node will survive filtering if filtering is active + _connectionTreeSearchTextFilter.SpecialInclusionList.Add(newNode); + // use root node if no node is selected ConnectionInfo parentNode = SelectedNode ?? GetRootConnectionNode(); DefaultConnectionInfo.Instance.SaveTo(newNode); @@ -335,10 +337,24 @@ namespace mRemoteNG.UI.Controls AutoResizeColumn(Columns[0]); } - protected override void UpdateFiltering() + /// + /// Filters tree items based on the given + /// + /// The text to filter by + public void ApplyFilter(string filterText) { - base.UpdateFiltering(); - AutoResizeColumn(Columns[0]); + UseFiltering = true; + _connectionTreeSearchTextFilter.FilterText = filterText; + ModelFilter = _connectionTreeSearchTextFilter; + } + + /// + /// Removes all item filtering from the connection tree + /// + public void RemoveFilter() + { + UseFiltering = false; + ResetColumnFiltering(); } private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) @@ -363,6 +379,12 @@ namespace mRemoteNG.UI.Controls } } + protected override void UpdateFiltering() + { + base.UpdateFiltering(); + AutoResizeColumn(Columns[0]); + } + private void tvConnections_AfterSelect(object sender, EventArgs e) { try @@ -399,6 +421,13 @@ namespace mRemoteNG.UI.Controls { try { + if (!Settings.Default.ShowDescriptionTooltipsInTree) + { + // setting text to null prevents the tooltip from being shown + e.Text = null; + return; + } + var nodeProducingTooltip = (ConnectionInfo)e.Model; e.Text = nodeProducingTooltip.Description; } @@ -434,6 +463,9 @@ namespace mRemoteNG.UI.Controls ConnectionTreeModel.RenameNode(SelectedNode, e.Label); _nodeInEditMode = false; _allowEdit = false; + // ensures that if we are filtering and a new item is added that doesn't match the filter, it will be filtered out + _connectionTreeSearchTextFilter.SpecialInclusionList.Clear(); + UpdateFiltering(); Windows.ConfigForm.SelectedTreeNode = SelectedNode; } catch (Exception ex) diff --git a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTreeSearchTextFilter.cs b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTreeSearchTextFilter.cs index e31c0a5a..82e38858 100644 --- a/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTreeSearchTextFilter.cs +++ b/mRemoteV1/UI/Controls/ConnectionTree/ConnectionTreeSearchTextFilter.cs @@ -1,4 +1,5 @@ -using BrightIdeasSoftware; +using System.Collections.Generic; +using BrightIdeasSoftware; using mRemoteNG.Connection; namespace mRemoteNG.UI.Controls @@ -7,12 +8,22 @@ namespace mRemoteNG.UI.Controls { public string FilterText { get; set; } = ""; + /// + /// A list of objects that should + /// always be included in the output, regardless of matching + /// the desired . + /// + public List SpecialInclusionList { get; } = new List(); + public bool Filter(object modelObject) { var objectAsConnectionInfo = modelObject as ConnectionInfo; if (objectAsConnectionInfo == null) return false; + if (SpecialInclusionList.Contains(objectAsConnectionInfo)) + return true; + var filterTextLower = FilterText.ToLowerInvariant(); if (objectAsConnectionInfo.Name.ToLowerInvariant().Contains(filterTextLower) || diff --git a/mRemoteV1/UI/Controls/FilteredPropertyGrid/FilteredPropertyGrid.cs b/mRemoteV1/UI/Controls/FilteredPropertyGrid/FilteredPropertyGrid.cs index 37c1829b..127654ba 100644 --- a/mRemoteV1/UI/Controls/FilteredPropertyGrid/FilteredPropertyGrid.cs +++ b/mRemoteV1/UI/Controls/FilteredPropertyGrid/FilteredPropertyGrid.cs @@ -1,171 +1,263 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Linq; using System.Windows.Forms; using mRemoteNG.App; namespace mRemoteNG.UI.Controls.FilteredPropertyGrid { - /// - /// This class overrides the standard PropertyGrid provided by Microsoft. - /// It also allows to hide (or filter) the properties of the SelectedObject displayed by the PropertyGrid. - /// - public partial class FilteredPropertyGrid : PropertyGrid + /// + /// This class overrides the standard PropertyGrid provided by Microsoft. + /// It also allows to hide (or filter) the properties of the SelectedObject displayed by the PropertyGrid. + /// + public partial class FilteredPropertyGrid : PropertyGrid { - /// Contain a reference to the collection of properties to show in the parent PropertyGrid. + /// + /// Contain a reference to the collection of properties to show in the parent PropertyGrid. + /// /// By default, m_PropertyDescriptors contain all the properties of the object. - readonly List m_PropertyDescriptors = new List(); - /// Contain a reference to the array of properties to display in the PropertyGrid. - private AttributeCollection m_HiddenAttributes, m_BrowsableAttributes; - /// Contain references to the arrays of properties or categories to hide. - private string[] m_BrowsableProperties, m_HiddenProperties; - /// Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid. - private ObjectWrapper m_Wrapper; + readonly List _propertyDescriptors = new List(); - /// Public constructor. - public FilteredPropertyGrid() { + /// + /// Contain a reference to the array of properties to display in the PropertyGrid. + /// + private AttributeCollection _hiddenAttributes; + private AttributeCollection _browsableAttributes; + + /// + /// Contain references to the arrays of properties or categories to hide. + /// + private string[] _mBrowsableProperties; + private string[] _mHiddenProperties; + /// + /// Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid. + /// + private ObjectWrapper _mWrapper; + + /// + /// Public constructor. + /// + public FilteredPropertyGrid() + { InitializeComponent(); - base.SelectedObject = m_Wrapper; + base.SelectedObject = _mWrapper; } - public new AttributeCollection BrowsableAttributes { - get { return m_BrowsableAttributes; } + /// + /// A list of all currently properties being shown by the property grid. + /// + public IEnumerable VisibleProperties => _propertyDescriptors.Select(p => p.Name); + + public new AttributeCollection BrowsableAttributes { + get { return _browsableAttributes; } set { - if (m_BrowsableAttributes == value) return; - m_HiddenAttributes = null; - m_BrowsableAttributes = value; + if (_browsableAttributes == value) return; + _hiddenAttributes = null; + _browsableAttributes = value; RefreshProperties(); } } - /// Get or set the categories to hide. + /// + /// Get or set the categories to hide. + /// public AttributeCollection HiddenAttributes { - get { return m_HiddenAttributes; } + get { return _hiddenAttributes; } set { - if (value == m_HiddenAttributes) return; - m_HiddenAttributes = value; - m_BrowsableAttributes = null; + if (value == _hiddenAttributes) return; + _hiddenAttributes = value; + _browsableAttributes = null; RefreshProperties(); } } - /// Get or set the properties to show. + + /// + /// Get or set the properties to show. + /// /// if one or several properties don't exist. public string[] BrowsableProperties { - get { return m_BrowsableProperties; } + get { return _mBrowsableProperties; } set { - if (value == m_BrowsableProperties) return; - m_BrowsableProperties = value; - //m_HiddenProperties = null; + if (value == _mBrowsableProperties) return; + _mBrowsableProperties = value; RefreshProperties(); } } /// Get or set the properties to hide. public string[] HiddenProperties { - get { return m_HiddenProperties; } + get { return _mHiddenProperties; } set { - if (value == m_HiddenProperties) return; - //m_BrowsableProperties = null; - m_HiddenProperties = value; + if (value == _mHiddenProperties) return; + _mHiddenProperties = value; RefreshProperties(); } } - /// Overwrite the PropertyGrid.SelectedObject property. + /// + /// Overwrite the PropertyGrid.SelectedObject property. + /// /// The object passed to the base PropertyGrid is the wrapper. public new object SelectedObject { - get { return m_Wrapper != null ? ((ObjectWrapper)base.SelectedObject).SelectedObject : null; } + get + { + return _mWrapper != null + ? ((ObjectWrapper)base.SelectedObject).SelectedObject + : null; + } set { // Set the new object to the wrapper and create one if necessary. - if(m_Wrapper == null) { - m_Wrapper = new ObjectWrapper(value); + if(_mWrapper == null) + { + _mWrapper = new ObjectWrapper(value); RefreshProperties(); } - else if(m_Wrapper.SelectedObject != value) { - var needrefresh = value.GetType() != m_Wrapper.SelectedObject.GetType(); - m_Wrapper.SelectedObject = value; - if(needrefresh) RefreshProperties(); + else if(_mWrapper.SelectedObject != value) + { + var needrefresh = value.GetType() != _mWrapper.SelectedObject.GetType(); + _mWrapper.SelectedObject = value; + if(needrefresh) + RefreshProperties(); } // Set the list of properties to the wrapper. - m_Wrapper.PropertyDescriptors = m_PropertyDescriptors; + _mWrapper.PropertyDescriptors = _propertyDescriptors; // Link the wrapper to the parent PropertyGrid. - base.SelectedObject = m_Wrapper; + base.SelectedObject = _mWrapper; } } - /* - /// Called when the browsable properties have changed. - private void OnBrowsablePropertiesChanged() { - if(m_Wrapper == null) return; - } - */ + /// + /// Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties. + /// + private void RefreshProperties() + { + if(_mWrapper == null) + return; - /// Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties. - private void RefreshProperties() { - if(m_Wrapper == null) return; // Clear the list of properties to be displayed. - m_PropertyDescriptors.Clear(); + _propertyDescriptors.Clear(); // Check whether the list is filtered - if(m_BrowsableAttributes != null && m_BrowsableAttributes.Count > 0) { + if(_browsableAttributes != null && _browsableAttributes.Count > 0) + { // Add to the list the attributes that need to be displayed. - foreach(Attribute attribute in m_BrowsableAttributes) ShowAttribute(attribute); - } else { - // Fill the collection with all the properties. - var originalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject); - foreach(PropertyDescriptor propertydescriptor in originalpropertydescriptors) m_PropertyDescriptors.Add(propertydescriptor); - // Remove from the list the attributes that mustn't be displayed. - if(m_HiddenAttributes != null) foreach(Attribute attribute in m_HiddenAttributes) HideAttribute(attribute); + foreach(Attribute attribute in _browsableAttributes) + ShowAttribute(attribute); } + else + { + // Fill the collection with all the properties. + var originalPropertyDescriptors = TypeDescriptor + .GetProperties(_mWrapper.SelectedObject) + .OfType() + .Where(PropertyDoesntHaveBrowsableFalseAttribute); + + foreach(PropertyDescriptor propertyDescriptor in originalPropertyDescriptors) + _propertyDescriptors.Add(propertyDescriptor); + + // Remove from the list the attributes that mustn't be displayed. + if(_hiddenAttributes != null) + foreach (Attribute attribute in _hiddenAttributes) + HideAttribute(attribute); + } + // Get all the properties of the SelectedObject - var allproperties = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject); - // Hide if necessary, some properties - if(m_HiddenProperties != null && m_HiddenProperties.Length > 0) { + var allproperties = TypeDescriptor.GetProperties(_mWrapper.SelectedObject); + + // Hide if necessary, some properties + if(_mHiddenProperties != null && _mHiddenProperties.Length > 0) + { // Remove from the list the properties that mustn't be displayed. - foreach(var propertyname in m_HiddenProperties) { - try { + foreach(var propertyname in _mHiddenProperties) + { + try + { var property = allproperties[propertyname]; // Remove from the list the property HideProperty(property); - } catch(Exception ex) { + } + catch (Exception ex) + { Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Could not hide Property.", ex); } } } + // Display if necessary, some properties - if(m_BrowsableProperties != null && m_BrowsableProperties.Length > 0) { - foreach(var propertyname in m_BrowsableProperties) { - try { + if(_mBrowsableProperties != null && _mBrowsableProperties.Length > 0) + { + foreach(var propertyname in _mBrowsableProperties) + { + try + { ShowProperty(allproperties[propertyname]); - } catch(Exception knfe) { - Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Property not found", knfe); + } + catch (Exception ex) + { + Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Property not found", ex); } } } } - /// Allows to hide a set of properties to the parent PropertyGrid. + + /// + /// Predicate to determine if a property has a Browsable(false) attribute + /// attatched to it. If so, it should not be shown. + /// + /// + /// + private bool PropertyDoesntHaveBrowsableFalseAttribute(PropertyDescriptor propertyDescriptor) + { + return !propertyDescriptor.Attributes.Contains(new BrowsableAttribute(false)); + } + + /// + /// Allows to hide a set of properties to the parent PropertyGrid. + /// /// A set of attributes that filter the original collection of properties. /// For better performance, include the BrowsableAttribute with true value. - private void HideAttribute(Attribute attribute) { - var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject,new[] { attribute }); - if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) throw new ArgumentException("Attribute not found",attribute.ToString()); - foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) HideProperty(propertydescriptor); + private void HideAttribute(Attribute attribute) + { + var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(_mWrapper.SelectedObject,new[] { attribute }); + if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) + throw new ArgumentException("Attribute not found", attribute.ToString()); + + foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) + HideProperty(propertydescriptor); } - /// Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid. + + /// + /// Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid. + /// /// The attribute to be added. - private void ShowAttribute(Attribute attribute) { - var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject,new[] { attribute }); - if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) throw new ArgumentException("Attribute not found",attribute.ToString()); - foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) ShowProperty(propertydescriptor); + private void ShowAttribute(Attribute attribute) + { + var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(_mWrapper.SelectedObject,new[] { attribute }); + if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) + throw new ArgumentException("Attribute not found", attribute.ToString()); + + foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) + ShowProperty(propertydescriptor); } - /// Add a property to the list of properties to be displayed in the PropertyGrid. + + /// + /// Add a property to the list of properties to be displayed in the PropertyGrid. + /// /// The property to be added. - private void ShowProperty(PropertyDescriptor property) { - if(!m_PropertyDescriptors.Contains(property)) m_PropertyDescriptors.Add(property); + private void ShowProperty(PropertyDescriptor property) + { + if(!_propertyDescriptors.Contains(property)) + _propertyDescriptors.Add(property); } - /// Allows to hide a property to the parent PropertyGrid. + + /// + /// Allows to hide a property to the parent PropertyGrid. + /// /// The name of the property to be hidden. - private void HideProperty(PropertyDescriptor property) { - if(m_PropertyDescriptors.Contains(property)) m_PropertyDescriptors.Remove(property); + private void HideProperty(PropertyDescriptor property) + { + if(_propertyDescriptors.Contains(property)) + _propertyDescriptors.Remove(property); } } } \ No newline at end of file diff --git a/mRemoteV1/UI/Controls/FilteredPropertyGrid/ObjectWrapper.cs b/mRemoteV1/UI/Controls/FilteredPropertyGrid/ObjectWrapper.cs index b9398552..a67abef4 100644 --- a/mRemoteV1/UI/Controls/FilteredPropertyGrid/ObjectWrapper.cs +++ b/mRemoteV1/UI/Controls/FilteredPropertyGrid/ObjectWrapper.cs @@ -4,96 +4,119 @@ using System.ComponentModel; namespace mRemoteNG.UI.Controls.FilteredPropertyGrid { - /// This class is a wrapper. It contains the object the propertyGrid has to display. - internal class ObjectWrapper : ICustomTypeDescriptor + /// + /// This class is a wrapper. It contains the object the PropertyGrid has to display. + /// + internal class ObjectWrapper : ICustomTypeDescriptor { - /// Contain a reference to the selected objet that will linked to the parent PropertyGrid. - private object m_SelectedObject; - /// Contain a reference to the collection of properties to show in the parent PropertyGrid. - /// By default, m_PropertyDescriptors contain all the properties of the object. - List m_PropertyDescriptors = new List(); - - /// Simple constructor. + /// + /// Creates a new instance of an with the given object to be wrapped. + /// /// A reference to the selected object that will linked to the parent PropertyGrid. - internal ObjectWrapper(object obj) { - m_SelectedObject = obj; + internal ObjectWrapper(object obj) + { + SelectedObject = obj; } - /// Get or set a reference to the selected objet that will linked to the parent PropertyGrid. - public object SelectedObject { - get { return m_SelectedObject; } - set { m_SelectedObject = value; } - } + /// + /// Get or set a reference to the selected objet that will linked to the parent PropertyGrid. + /// + public object SelectedObject { get; set; } - /// Get or set a reference to the collection of properties to show in the parent PropertyGrid. - public List PropertyDescriptors { - get { return m_PropertyDescriptors; } - set { m_PropertyDescriptors = value; } - } + /// + /// Get or set a reference to the collection of properties to show in the parent PropertyGrid + /// + public List PropertyDescriptors { get; set; } = new List(); - #region ICustomTypeDescriptor Members - public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { + #region ICustomTypeDescriptor Members + public PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { return GetProperties(); } - public PropertyDescriptorCollection GetProperties() { - return new PropertyDescriptorCollection(m_PropertyDescriptors.ToArray(),true); + public PropertyDescriptorCollection GetProperties() + { + return new PropertyDescriptorCollection(PropertyDescriptors.ToArray(), true); } - /// GetAttributes. + /// + /// GetAttributes + /// /// AttributeCollection - public AttributeCollection GetAttributes() { - return TypeDescriptor.GetAttributes(m_SelectedObject,true); - } - /// Get Class Name. - /// String - public String GetClassName() { - return TypeDescriptor.GetClassName(m_SelectedObject,true); - } - /// GetComponentName. - /// String - public String GetComponentName() { - return TypeDescriptor.GetComponentName(m_SelectedObject,true); + public AttributeCollection GetAttributes() + { + return TypeDescriptor.GetAttributes(SelectedObject, true); } - /// GetConverter. + /// + /// Get Class Name + /// + /// String + public string GetClassName() + { + return TypeDescriptor.GetClassName(SelectedObject, true); + } + + /// + /// GetComponentName + /// + /// String + public string GetComponentName() + { + return TypeDescriptor.GetComponentName(SelectedObject, true); + } + + /// + /// GetConverter + /// /// TypeConverter - public TypeConverter GetConverter() { - return TypeDescriptor.GetConverter(m_SelectedObject,true); + public TypeConverter GetConverter() + { + return TypeDescriptor.GetConverter(SelectedObject, true); } - /// GetDefaultEvent. + /// + /// GetDefaultEvent + /// /// EventDescriptor - public EventDescriptor GetDefaultEvent() { - return TypeDescriptor.GetDefaultEvent(m_SelectedObject,true); + public EventDescriptor GetDefaultEvent() + { + return TypeDescriptor.GetDefaultEvent(SelectedObject, true); } - /// GetDefaultProperty. + /// + /// GetDefaultProperty + /// /// PropertyDescriptor - public PropertyDescriptor GetDefaultProperty() { - return TypeDescriptor.GetDefaultProperty(m_SelectedObject,true); + public PropertyDescriptor GetDefaultProperty() + { + return TypeDescriptor.GetDefaultProperty(SelectedObject, true); } - /// GetEditor. + /// + /// GetEditor + /// /// editorBaseType /// object - public object GetEditor(Type editorBaseType) { - return TypeDescriptor.GetEditor(this,editorBaseType,true); + public object GetEditor(Type editorBaseType) + { + return TypeDescriptor.GetEditor(this,editorBaseType, true); } - public EventDescriptorCollection GetEvents(Attribute[] attributes) { - return TypeDescriptor.GetEvents(m_SelectedObject,attributes,true); + public EventDescriptorCollection GetEvents(Attribute[] attributes) + { + return TypeDescriptor.GetEvents(SelectedObject, attributes, true); } - public EventDescriptorCollection GetEvents() { - return TypeDescriptor.GetEvents(m_SelectedObject,true); + public EventDescriptorCollection GetEvents() + { + return TypeDescriptor.GetEvents(SelectedObject, true); } - public object GetPropertyOwner(PropertyDescriptor pd) { - return m_SelectedObject; + public object GetPropertyOwner(PropertyDescriptor pd) + { + return SelectedObject; } - #endregion - } } diff --git a/mRemoteV1/UI/Controls/IPTextBox.cs b/mRemoteV1/UI/Controls/IPTextBox.cs index 0634c76b..7dad5a66 100644 --- a/mRemoteV1/UI/Controls/IPTextBox.cs +++ b/mRemoteV1/UI/Controls/IPTextBox.cs @@ -29,9 +29,8 @@ namespace mRemoteNG.UI.Controls /** Sets and Gets the tooltiptext on toolTip1 */ public string ToolTipText { - get - { return toolTip1.GetToolTip(Octet1); } - set + get => toolTip1.GetToolTip(Octet1); + set { toolTip1.SetToolTip(Octet1,value); toolTip1.SetToolTip(Octet2,value); @@ -46,12 +45,8 @@ namespace mRemoteNG.UI.Controls /** Set or Get the string that represents the value in the box */ public override string Text { - get - { - return Octet1.Text + @"." + Octet2.Text + @"." + Octet3.Text + @"." + Octet4.Text; - - } - set + get => Octet1.Text + @"." + Octet2.Text + @"." + Octet3.Text + @"." + Octet4.Text; + set { if (!string.IsNullOrEmpty(value)) { @@ -245,7 +240,7 @@ namespace mRemoteNG.UI.Controls if(theValue >=0 && theValue <= 255) return true; - MessageBox.Show("Must Be Between 0 and 255","Out Of Range"); + MessageBox.Show(Language.strIPRange,Language.strOutOfRange); return false; } catch diff --git a/mRemoteV1/UI/Forms/Input/input.cs b/mRemoteV1/UI/Forms/Input/input.cs index 67c842fd..6df973c9 100644 --- a/mRemoteV1/UI/Forms/Input/input.cs +++ b/mRemoteV1/UI/Forms/Input/input.cs @@ -28,13 +28,13 @@ namespace mRemoteNG.UI.Forms.Input textBox.Anchor = textBox.Anchor | AnchorStyles.Right; textBox.SetBounds(12, 36, 372, 20); - buttonOk.Text = "OK"; + buttonOk.Text = Language.strButtonOK; buttonOk.DialogResult = DialogResult.OK; buttonOk.FlatStyle = FlatStyle.Flat; buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; buttonOk.SetBounds(228, 72, 75, 23); - buttonCancel.Text = "Cancel"; + buttonCancel.Text = Language.strButtonCancel; buttonCancel.DialogResult = DialogResult.Cancel; buttonCancel.FlatStyle = FlatStyle.Flat; buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; diff --git a/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.Designer.cs index 6696dcc2..4a6a5018 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.Designer.cs @@ -2,7 +2,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class AdvancedPage : OptionsPage + public sealed partial class AdvancedPage : OptionsPage { //UserControl overrides dispose to clean up the component list. [System.Diagnostics.DebuggerNonUserCode()] diff --git a/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.cs b/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.cs index 8b058bec..23937f1f 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/AdvancedPage.cs @@ -9,19 +9,19 @@ using mRemoteNG.Tools; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class AdvancedPage + public sealed partial class AdvancedPage { public AdvancedPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } #region Public Methods public override string PageName { - get { return Language.strTabAdvanced; } + get => Language.strTabAdvanced; set { } } @@ -108,16 +108,14 @@ namespace mRemoteNG.UI.Forms.OptionsPages { using (var openFileDialog = new OpenFileDialog()) { - openFileDialog.Filter = $"{Language.strFilterApplication}|*.exe|{Language.strFilterAll}|*.*"; + openFileDialog.Filter = $@"{Language.strFilterApplication}|*.exe|{Language.strFilterAll}|*.*"; openFileDialog.FileName = Path.GetFileName(GeneralAppInfo.PuttyPath); openFileDialog.CheckFileExists = true; openFileDialog.Multiselect = false; - if (openFileDialog.ShowDialog() == DialogResult.OK) - { - txtCustomPuttyPath.Text = openFileDialog.FileName; - SetPuttyLaunchButtonEnabled(); - } + if (openFileDialog.ShowDialog() != DialogResult.OK) return; + txtCustomPuttyPath.Text = openFileDialog.FileName; + SetPuttyLaunchButtonEnabled(); } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.Designer.cs index edd7ce7c..6e550f44 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class AppearancePage : OptionsPage + public sealed partial class AppearancePage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.cs b/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.cs index e16e516f..5dae889c 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/AppearancePage.cs @@ -5,17 +5,17 @@ using mRemoteNG.Tools; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class AppearancePage + public sealed partial class AppearancePage { public AppearancePage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.strTabAppearance; } + get => Language.strTabAppearance; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs index 462bf768..7f38b188 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class ConnectionsPage : OptionsPage + public sealed partial class ConnectionsPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs b/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs index 302c2b43..a4ac76d2 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs @@ -3,19 +3,19 @@ using mRemoteNG.Config; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class ConnectionsPage + public sealed partial class ConnectionsPage { - private FrmMain _frmMain = FrmMain.Default; + private readonly FrmMain _frmMain = FrmMain.Default; public ConnectionsPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.strConnections; } + get => Language.strConnections; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.Designer.cs index 416050ab..0d06f197 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.Designer.cs @@ -1,6 +1,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - partial class CredentialsPage + sealed partial class CredentialsPage { /// /// Required designer variable. diff --git a/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs b/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs index 64c91c46..27b5e608 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs @@ -4,16 +4,16 @@ using mRemoteNG.Security.SymmetricEncryption; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class CredentialsPage : OptionsPage + public sealed partial class CredentialsPage : OptionsPage { public CredentialsPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.Credentials; } + get => Language.Credentials; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.Designer.cs index d183d8ff..1d13b356 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class NotificationsPage : OptionsPage + public sealed partial class NotificationsPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.cs b/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.cs index 477abbae..34e7d46f 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/NotificationsPage.cs @@ -5,17 +5,17 @@ using mRemoteNG.App; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class NotificationsPage + public sealed partial class NotificationsPage { public NotificationsPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.strMenuNotifications; } + get => Language.strMenuNotifications; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/OptionsPage.cs b/mRemoteV1/UI/Forms/OptionsPages/OptionsPage.cs index 36ef5cc2..63357fd1 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/OptionsPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/OptionsPage.cs @@ -9,24 +9,17 @@ namespace mRemoteNG.UI.Forms.OptionsPages protected OptionsPage() { //InitializeComponent(); - Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme; - + Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme; } #region Public Properties - [Browsable(false)]public virtual string PageName {get; set;} + // ReSharper disable once UnusedAutoPropertyAccessor.Global + [Browsable(false)]public virtual string PageName {get; set;} - public virtual Icon PageIcon {get; set;} - public virtual Image IconImage{ - get - { - if (PageIcon != null) - return PageIcon.ToBitmap(); - return null; - } - } + public virtual Icon PageIcon {get; protected set;} + public virtual Image IconImage => PageIcon?.ToBitmap(); - #endregion + #endregion #region Public Methods public virtual void ApplyLanguage() @@ -50,26 +43,26 @@ namespace mRemoteNG.UI.Forms.OptionsPages } #endregion + /* private void InitializeComponent() { - this.SuspendLayout(); + SuspendLayout(); // // OptionsPage // - this.Name = "OptionsPage"; - this.Size = new System.Drawing.Size(610, 489); - this.ResumeLayout(false); + Name = "OptionsPage"; + Size = new Size(610, 489); + ResumeLayout(false); } + */ - public virtual void ApplyTheme() + protected virtual void ApplyTheme() { - if (Themes.ThemeManager.getInstance().ThemingActive) - { - BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); - ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); - Invalidate(); - } + if (!Themes.ThemeManager.getInstance().ThemingActive) return; + BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); + ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); + Invalidate(); } } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.Designer.cs index f2e16032..796e82e7 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.Designer.cs @@ -1,6 +1,6 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - partial class SecurityPage + sealed partial class SecurityPage { /// /// Required designer variable. diff --git a/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.cs b/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.cs index d8901d11..b5e2c57e 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/SecurityPage.cs @@ -4,20 +4,20 @@ using mRemoteNG.Security; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class SecurityPage : OptionsPage + public sealed partial class SecurityPage : OptionsPage { public SecurityPage() { InitializeComponent(); PopulateEncryptionEngineDropDown(); PopulateBlockCipherDropDown(); - base.ApplyTheme(); + ApplyTheme(); } [Browsable(false)] public override string PageName { - get { return Language.strTabSecurity; } + get => Language.strTabSecurity; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.Designer.cs index f1a1654f..bfc4c758 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class SqlServerPage : OptionsPage + public sealed partial class SqlServerPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.cs b/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.cs index 4be316f2..ad59e290 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/SqlServerPage.cs @@ -7,20 +7,20 @@ using mRemoteNG.Security.SymmetricEncryption; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class SqlServerPage + public sealed partial class SqlServerPage { private readonly SqlDatabaseConnectionTester _databaseConnectionTester; public SqlServerPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); _databaseConnectionTester = new SqlDatabaseConnectionTester(); } public override string PageName { - get { return Language.strSQLServer.TrimEnd(':'); } + get => Language.strSQLServer.TrimEnd(':'); set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.Designer.cs index d12491cc..7cbe6aeb 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class StartupExitPage : OptionsPage + public sealed partial class StartupExitPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.cs b/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.cs index 88c1bee3..b3389990 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/StartupExitPage.cs @@ -2,17 +2,17 @@ using System; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class StartupExitPage + public sealed partial class StartupExitPage { public StartupExitPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.strStartupExit; } + get => Language.strStartupExit; set { } } diff --git a/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs index 238d391c..1969b466 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs @@ -3,7 +3,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class TabsPanelsPage : OptionsPage + public sealed partial class TabsPanelsPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs b/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs index 7b82b222..24a5e22b 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs @@ -1,16 +1,16 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class TabsPanelsPage + public sealed partial class TabsPanelsPage { public TabsPanelsPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } public override string PageName { - get { return Language.strTabsAndPanels.Replace("&&", "&"); } + get => Language.strTabsAndPanels.Replace("&&", "&"); set { } } @@ -26,7 +26,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages chkDoubleClickClosesTab.Text = Language.strDoubleClickTabClosesIt; chkAlwaysShowPanelSelectionDlg.Text = Language.strAlwaysShowPanelSelection; chkCreateEmptyPanelOnStart.Text = Language.strCreateEmptyPanelOnStartUp; - lblPanelName.Text = $"{Language.strPanelName}:"; + lblPanelName.Text = $@"{Language.strPanelName}:"; } public override void LoadSettings() diff --git a/mRemoteV1/UI/Forms/OptionsPages/ThemePage.cs b/mRemoteV1/UI/Forms/OptionsPages/ThemePage.cs index 5f911cf3..0dd4f532 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/ThemePage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/ThemePage.cs @@ -1,9 +1,7 @@ using System; -using System.ComponentModel; using System.Windows.Forms; using mRemoteNG.Themes; using System.Linq; -using System.Drawing; using System.Collections.Generic; using BrightIdeasSoftware; @@ -25,18 +23,16 @@ namespace mRemoteNG.UI.Forms.OptionsPages InitializeComponent(); _themeManager = ThemeManager.getInstance(); - if (_themeManager.ThemingActive) - { - _themeManager = ThemeManager.getInstance(); - _themeManager.ThemeChanged += ApplyTheme; - _oriTheme = _themeManager.ActiveTheme; - _oriActiveTheming = _themeManager.ThemingActive; - } + if (!_themeManager.ThemingActive) return; + _themeManager = ThemeManager.getInstance(); + _themeManager.ThemeChanged += ApplyTheme; + _oriTheme = _themeManager.ActiveTheme; + _oriActiveTheming = _themeManager.ThemingActive; } public override string PageName { - get { return Language.strOptionsTabTheme; } + get => Language.strOptionsTabTheme; set { } } @@ -65,6 +61,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages btnThemeDelete.Enabled = false; //Load the list of themes cboTheme.Items.Clear(); + // ReSharper disable once CoVariantArrayConversion cboTheme.Items.AddRange(_themeManager.LoadThemes().OrderBy(x => x.Name).ToArray()); cboTheme.SelectedItem = _themeManager.ActiveTheme; cboTheme_SelectionChangeCommitted(this, new EventArgs()); @@ -80,23 +77,23 @@ namespace mRemoteNG.UI.Forms.OptionsPages { themeEnableCombo.Checked = false; cboTheme.Enabled = false; + // reset to the default theme when disabling theme support + _themeManager.ActiveTheme = _themeManager.DefaultTheme; } } private void ListPalette_FormatCell(object sender, FormatCellEventArgs e) { - if (e.ColumnIndex == this.ColorCol.Index) - { - PseudoKeyColor colorElem = (PseudoKeyColor)e.Model; - e.SubItem.BackColor = colorElem.Value; - } + if (e.ColumnIndex != ColorCol.Index) return; + var colorElem = (PseudoKeyColor)e.Model; + e.SubItem.BackColor = colorElem.Value; } public override void SaveSettings() { base.SaveSettings(); - foreach(ThemeInfo updatedTheme in modifiedThemes) + foreach(var updatedTheme in modifiedThemes) { _themeManager.updateTheme(updatedTheme); } @@ -120,26 +117,18 @@ namespace mRemoteNG.UI.Forms.OptionsPages { btnThemeNew.Enabled = false; btnThemeDelete.Enabled = false; - if (_themeManager.ThemingActive) - { - _themeManager.ActiveTheme = (ThemeInfo)cboTheme.SelectedItem; - listPalette.ClearObjects(); - if (_themeManager.ActiveTheme.IsExtendable && _themeManager.ThemingActive) - { - btnThemeNew.Enabled = true; - listPalette.ClearObjects(); - listPalette.Enabled = false; - ColorMeList(); - if (!_themeManager.ActiveTheme.IsThemeBase) - { - listPalette.Enabled = true; - btnThemeDelete.Enabled = true; - listPalette.CellClick += ListPalette_CellClick; - - } - } - } - + if (!_themeManager.ThemingActive) return; + _themeManager.ActiveTheme = (ThemeInfo)cboTheme.SelectedItem; + listPalette.ClearObjects(); + if (!_themeManager.ActiveTheme.IsExtendable || !_themeManager.ThemingActive) return; + btnThemeNew.Enabled = true; + listPalette.ClearObjects(); + listPalette.Enabled = false; + ColorMeList(); + if (_themeManager.ActiveTheme.IsThemeBase) return; + listPalette.Enabled = true; + btnThemeDelete.Enabled = true; + listPalette.CellClick += ListPalette_CellClick; } @@ -153,63 +142,59 @@ namespace mRemoteNG.UI.Forms.OptionsPages private void ListPalette_CellClick(object sender, CellClickEventArgs e) { - PseudoKeyColor colorElem = (PseudoKeyColor)e.Model; + var colorElem = (PseudoKeyColor)e.Model; - ColorDialog colorDlg = new ColorDialog(); - colorDlg.AllowFullOpen = true; - colorDlg.FullOpen = true; - colorDlg.AnyColor = true; - colorDlg.SolidColorOnly = false; - colorDlg.Color = colorElem.Value; - - if (colorDlg.ShowDialog() == DialogResult.OK) + var colorDlg = new ColorDialog { - modifiedThemes.Add(_themeManager.ActiveTheme); - _themeManager.ActiveTheme.ExtendedPalette.replaceColor(colorElem.Key, colorDlg.Color); - colorElem.Value = colorDlg.Color; - listPalette.RefreshObject(e.Model); - _themeManager.refreshUI(); - } + AllowFullOpen = true, + FullOpen = true, + AnyColor = true, + SolidColorOnly = false, + Color = colorElem.Value + }; + + if (colorDlg.ShowDialog() != DialogResult.OK) return; + modifiedThemes.Add(_themeManager.ActiveTheme); + _themeManager.ActiveTheme.ExtendedPalette.replaceColor(colorElem.Key, colorDlg.Color); + colorElem.Value = colorDlg.Color; + listPalette.RefreshObject(e.Model); + _themeManager.refreshUI(); } private void ColorMeList() { - foreach (KeyValuePair colorElem in _themeManager.ActiveTheme.ExtendedPalette.ExtColorPalette) + foreach (var colorElem in _themeManager.ActiveTheme.ExtendedPalette.ExtColorPalette) listPalette.AddObject(new PseudoKeyColor(colorElem.Key, colorElem.Value)); } private void btnThemeNew_Click(object sender, EventArgs e) { - String name = _themeManager.ActiveTheme.Name; - DialogResult res = Input.input.InputBox(Language.strOptionsThemeNewThemeCaption, Language.strOptionsThemeNewThemeText, ref name); - if (res == DialogResult.OK) + var name = _themeManager.ActiveTheme.Name; + var res = Input.input.InputBox(Language.strOptionsThemeNewThemeCaption, Language.strOptionsThemeNewThemeText, ref name); + if (res != DialogResult.OK) return; + if (_themeManager.isThemeNameOk(name)) { - if (_themeManager.isThemeNameOk(name)) - { - ThemeInfo addedTheme = _themeManager.addTheme(_themeManager.ActiveTheme, name); - _themeManager.ActiveTheme = addedTheme; - LoadSettings(); - } - else - { - TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strErrors, Language.strOptionsThemeNewThemeError, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.Ok, TaskDialog.ESysIcons.Error, TaskDialog.ESysIcons.Information, 0); - } + var addedTheme = _themeManager.addTheme(_themeManager.ActiveTheme, name); + _themeManager.ActiveTheme = addedTheme; + LoadSettings(); + } + else + { + TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strErrors, Language.strOptionsThemeNewThemeError, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.Ok, TaskDialog.ESysIcons.Error, TaskDialog.ESysIcons.Information, 0); } } private void btnThemeDelete_Click(object sender, EventArgs e) { - DialogResult res = TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strWarnings , Language.strOptionsThemeDeleteConfirmation, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.YesNo, TaskDialog.ESysIcons.Question, TaskDialog.ESysIcons.Information, 0); + var res = TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strWarnings , Language.strOptionsThemeDeleteConfirmation, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.YesNo, TaskDialog.ESysIcons.Question, TaskDialog.ESysIcons.Information, 0); - if (res == DialogResult.Yes) - { - if (modifiedThemes.Contains(_themeManager.ActiveTheme)) - modifiedThemes.Remove(_themeManager.ActiveTheme); - _themeManager.deleteTheme(_themeManager.ActiveTheme); - LoadSettings(); - } + if (res != DialogResult.Yes) return; + if (modifiedThemes.Contains(_themeManager.ActiveTheme)) + modifiedThemes.Remove(_themeManager.ActiveTheme); + _themeManager.deleteTheme(_themeManager.ActiveTheme); + LoadSettings(); } #endregion diff --git a/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.Designer.cs b/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.Designer.cs index af0207c9..8cec079e 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.Designer.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.Designer.cs @@ -2,7 +2,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class UpdatesPage : OptionsPage + public sealed partial class UpdatesPage : OptionsPage { //UserControl overrides dispose to clean up the component list. diff --git a/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs b/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs index 63bc94ca..4a4de03c 100644 --- a/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs +++ b/mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs @@ -10,7 +10,7 @@ using mRemoteNG.UI.TaskDialog; namespace mRemoteNG.UI.Forms.OptionsPages { - public partial class UpdatesPage + public sealed partial class UpdatesPage { #region Private Fields @@ -21,14 +21,14 @@ namespace mRemoteNG.UI.Forms.OptionsPages public UpdatesPage() { InitializeComponent(); - base.ApplyTheme(); + ApplyTheme(); } #region Public Methods public override string PageName { - get { return Language.strTabUpdates; } + get => Language.strTabUpdates; set { } } diff --git a/mRemoteV1/UI/Forms/PasswordForm.cs b/mRemoteV1/UI/Forms/PasswordForm.cs index eee2902e..9aafa1db 100644 --- a/mRemoteV1/UI/Forms/PasswordForm.cs +++ b/mRemoteV1/UI/Forms/PasswordForm.cs @@ -11,15 +11,34 @@ namespace mRemoteNG.UI.Forms private readonly string _passwordName; private SecureString _password = new SecureString(); - private bool Verify { get; } + /// + /// Puts the dialog into the New Password mode. An extra + /// password box is shown which must match the first password + /// to continue. + /// + private bool NewPasswordMode { get; } - public PasswordForm(string passwordName = null, bool verify = true) + /// + /// Creates a new password form for entering or setting a password. + /// + /// + /// + /// Puts the dialog into the New Password mode. An extra + /// password box is shown which must match the first password + /// to continue. + /// + public PasswordForm(string passwordName = null, bool newPasswordMode = true) { InitializeComponent(); _passwordName = passwordName; - Verify = verify; + NewPasswordMode = newPasswordMode; } + /// + /// Dispaly a dialog box requesting that the user + /// enter their password. + /// + /// public Optional GetKey() { var dialog = ShowDialog(); @@ -33,7 +52,7 @@ namespace mRemoteNG.UI.Forms { ApplyLanguage(); - if (Verify) return; + if (NewPasswordMode) return; Height = Height - (txtVerify.Top - txtPassword.Top); lblVerify.Visible = false; txtVerify.Visible = false; @@ -44,7 +63,7 @@ namespace mRemoteNG.UI.Forms _password = txtPassword.Text.ConvertToSecureString(); txtPassword.Text = ""; txtVerify.Text = ""; - if (Verify) return; + if (NewPasswordMode) return; Height = Height + (txtVerify.Top - txtPassword.Top); } @@ -55,12 +74,12 @@ namespace mRemoteNG.UI.Forms } private void btnOK_Click(object sender, EventArgs e) - { - if (Verify && VerifyPassword()) - DialogResult = DialogResult.OK; - else - DialogResult = DialogResult.OK; - } + { + if (NewPasswordMode) + VerifyNewPassword(); + + DialogResult = DialogResult.OK; + } private void txtPassword_TextChanged(object sender, EventArgs e) { @@ -79,7 +98,7 @@ namespace mRemoteNG.UI.Forms btnOK.Text = Language.strButtonOK; } - private bool VerifyPassword() + private bool VerifyNewPassword() { if (txtPassword.Text.Length >= 3) { diff --git a/mRemoteV1/UI/Forms/frmChoosePanel.Designer.cs b/mRemoteV1/UI/Forms/frmChoosePanel.Designer.cs index 083ad1ba..66d789ea 100644 --- a/mRemoteV1/UI/Forms/frmChoosePanel.Designer.cs +++ b/mRemoteV1/UI/Forms/frmChoosePanel.Designer.cs @@ -29,25 +29,26 @@ namespace mRemoteNG.UI.Forms //Do not modify it using the code editor. [System.Diagnostics.DebuggerStepThrough()]private void InitializeComponent() { - this.cbPanels = new Controls.Base.NGComboBox(); - this.btnOK = new Controls.Base.NGButton(); - this.lblDescription = new Controls.Base.NGLabel(); - this.btnNew = new Controls.Base.NGButton(); - this.btnCancel = new Controls.Base.NGButton(); + this.cbPanels = new mRemoteNG.UI.Controls.Base.NGComboBox(); + this.btnOK = new mRemoteNG.UI.Controls.Base.NGButton(); + this.lblDescription = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.btnNew = new mRemoteNG.UI.Controls.Base.NGButton(); this.SuspendLayout(); // // cbPanels // + this.cbPanels._mice = mRemoteNG.UI.Controls.Base.NGComboBox.MouseState.HOVER; this.cbPanels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cbPanels.FormattingEnabled = true; - this.cbPanels.Location = new System.Drawing.Point(79, 42); + this.cbPanels.Location = new System.Drawing.Point(12, 42); this.cbPanels.Name = "cbPanels"; - this.cbPanels.Size = new System.Drawing.Size(157, 21); + this.cbPanels.Size = new System.Drawing.Size(224, 21); this.cbPanels.TabIndex = 10; // // btnOK // - this.btnOK.Location = new System.Drawing.Point(92, 73); + this.btnOK._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; + this.btnOK.Location = new System.Drawing.Point(167, 72); this.btnOK.Name = "btnOK"; this.btnOK.Size = new System.Drawing.Size(69, 23); this.btnOK.TabIndex = 20; @@ -66,9 +67,10 @@ namespace mRemoteNG.UI.Forms // // btnNew // + this.btnNew._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; this.btnNew.Image = global::mRemoteNG.Resources.Panel_Add; this.btnNew.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.btnNew.Location = new System.Drawing.Point(10, 38); + this.btnNew.Location = new System.Drawing.Point(101, 70); this.btnNew.Name = "btnNew"; this.btnNew.Size = new System.Drawing.Size(60, 27); this.btnNew.TabIndex = 40; @@ -77,27 +79,14 @@ namespace mRemoteNG.UI.Forms this.btnNew.UseVisualStyleBackColor = true; this.btnNew.Click += new System.EventHandler(this.btnNew_Click); // - // btnCancel - // - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnCancel.Location = new System.Drawing.Point(167, 73); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(69, 23); - this.btnCancel.TabIndex = 30; - this.btnCancel.Text = global::mRemoteNG.Language.strButtonCancel; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // // frmChoosePanel // this.AcceptButton = this.btnOK; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.btnCancel; this.ClientSize = new System.Drawing.Size(245, 107); this.Controls.Add(this.lblDescription); this.Controls.Add(this.btnNew); - this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnOK); this.Controls.Add(this.cbPanels); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; @@ -116,6 +105,5 @@ namespace mRemoteNG.UI.Forms internal Controls.Base.NGButton btnOK; internal Controls.Base.NGLabel lblDescription; internal Controls.Base.NGButton btnNew; - internal Controls.Base.NGButton btnCancel; } } diff --git a/mRemoteV1/UI/Forms/frmChoosePanel.cs b/mRemoteV1/UI/Forms/frmChoosePanel.cs index 4b5cd36e..cb545a8d 100644 --- a/mRemoteV1/UI/Forms/frmChoosePanel.cs +++ b/mRemoteV1/UI/Forms/frmChoosePanel.cs @@ -16,21 +16,15 @@ namespace mRemoteNG.UI.Forms } public string Panel { - get - { - return cbPanels.SelectedItem.ToString(); - } - set - { - cbPanels.SelectedItem = value; - } - } + get => cbPanels.SelectedItem.ToString(); + set => cbPanels.SelectedItem = value; + } private void frmChoosePanel_Load(object sender, System.EventArgs e) { ApplyLanguage(); - - AddAvailablePanels(); + ApplyTheme(); + AddAvailablePanels(); } private void ApplyLanguage() @@ -38,15 +32,23 @@ namespace mRemoteNG.UI.Forms btnOK.Text = Language.strButtonOK; lblDescription.Text = Language.strLabelSelectPanel; btnNew.Text = Language.strButtonNew; - btnCancel.Text = Language.strButtonCancel; Text = Language.strTitleSelectPanel; } - - private void AddAvailablePanels() + + private void ApplyTheme() + { + if (!Themes.ThemeManager.getInstance().ThemingActive) return; + BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); + ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); + lblDescription.BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); + lblDescription.ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); + } + + private void AddAvailablePanels() { cbPanels.Items.Clear(); - for (int i = 0; i <= Runtime.WindowList.Count - 1; i++) + for (var i = 0; i <= Runtime.WindowList.Count - 1; i++) { cbPanels.Items.Add(Runtime.WindowList[i].Text.Replace("&&", "&")); } @@ -67,24 +69,17 @@ namespace mRemoteNG.UI.Forms private void btnNew_Click(object sender, System.EventArgs e) { var pnlName = Language.strNewPanel; - - if (input.InputBox(Language.strNewPanel, Language.strPanelName + ":", ref pnlName) == DialogResult.OK && !string.IsNullOrEmpty(pnlName)) - { - _panelAdder.AddPanel(pnlName); - AddAvailablePanels(); - cbPanels.SelectedItem = pnlName; - cbPanels.Focus(); - } + + if (input.InputBox(Language.strNewPanel, Language.strPanelName + ":", ref pnlName) != DialogResult.OK || string.IsNullOrEmpty(pnlName)) return; + _panelAdder.AddPanel(pnlName); + AddAvailablePanels(); + cbPanels.SelectedItem = pnlName; + cbPanels.Focus(); } private void btnOK_Click(object sender, System.EventArgs e) { DialogResult = DialogResult.OK; } - - private void btnCancel_Click(object sender, System.EventArgs e) - { - DialogResult = DialogResult.Cancel; - } } } diff --git a/mRemoteV1/UI/Forms/frmMain.Designer.cs b/mRemoteV1/UI/Forms/frmMain.Designer.cs index e2b16cb4..deba6344 100644 --- a/mRemoteV1/UI/Forms/frmMain.Designer.cs +++ b/mRemoteV1/UI/Forms/frmMain.Designer.cs @@ -84,7 +84,7 @@ namespace mRemoteNG.UI.Forms this.fileMenu.ConnectionInitiator = null; this.fileMenu.Name = "mMenFile"; this.fileMenu.Size = new System.Drawing.Size(37, 20); - this.fileMenu.Text = "&File"; + this.fileMenu.Text = Language.strMenuFile; this.fileMenu.TreeWindow = null; this.fileMenu.DropDownOpening += new System.EventHandler(this.mainFileMenu1_DropDownOpening); // @@ -94,7 +94,7 @@ namespace mRemoteNG.UI.Forms this.viewMenu.MainForm = null; this.viewMenu.Name = "mMenView"; this.viewMenu.Size = new System.Drawing.Size(44, 20); - this.viewMenu.Text = "&View"; + this.viewMenu.Text = Language.strMenuView; this.viewMenu.TsExternalTools = null; this.viewMenu.TsMultiSsh = null; this.viewMenu.TsQuickConnect = null; @@ -106,13 +106,13 @@ namespace mRemoteNG.UI.Forms this.toolsMenu.MainForm = null; this.toolsMenu.Name = "mMenTools"; this.toolsMenu.Size = new System.Drawing.Size(47, 20); - this.toolsMenu.Text = "&Tools"; + this.toolsMenu.Text = Language.strMenuTools; // // helpMenu // this.helpMenu.Name = "mMenInfo"; this.helpMenu.Size = new System.Drawing.Size(44, 20); - this.helpMenu.Text = "&Help"; + this.helpMenu.Text = Language.strMenuHelp; this.helpMenu.TextDirection = System.Windows.Forms.ToolStripTextDirection.Horizontal; // // mMenSep3 diff --git a/mRemoteV1/UI/Forms/frmMain.cs b/mRemoteV1/UI/Forms/frmMain.cs index e378ff66..6d8f0313 100644 --- a/mRemoteV1/UI/Forms/frmMain.cs +++ b/mRemoteV1/UI/Forms/frmMain.cs @@ -75,8 +75,8 @@ namespace mRemoteNG.UI.Forms public bool AreWeUsingSqlServerForSavingConnections { - get { return _usingSqlServer; } - set + get => _usingSqlServer; + set { if (_usingSqlServer == value) { @@ -89,8 +89,8 @@ namespace mRemoteNG.UI.Forms public string ConnectionsFileName { - get { return _connectionsFileName; } - set + get => _connectionsFileName; + set { if (_connectionsFileName == value) { @@ -103,8 +103,8 @@ namespace mRemoteNG.UI.Forms public bool ShowFullPathInTitle { - get { return _showFullPathInTitle; } - set + get => _showFullPathInTitle; + set { if (_showFullPathInTitle == value) { @@ -117,8 +117,8 @@ namespace mRemoteNG.UI.Forms public ConnectionInfo SelectedConnection { - get { return _selectedConnection; } - set + get => _selectedConnection; + set { if (_selectedConnection == value) { @@ -139,12 +139,12 @@ namespace mRemoteNG.UI.Forms Startup.Instance.InitializeProgram(messageCollector); - SetMenuDependencies(); - msMain.Location = Point.Empty; - var settingsLoader = new SettingsLoader(this, messageCollector, _quickConnectToolStrip, _externalToolsToolStrip, _multiSshToolStrip); + var settingsLoader = new SettingsLoader(this, messageCollector, _quickConnectToolStrip, _externalToolsToolStrip, _multiSshToolStrip, msMain); settingsLoader.LoadSettings(); + SetMenuDependencies(); + var uiLoader = new DockPanelLayoutLoader(this, messageCollector); uiLoader.LoadPanelsFromXml(); @@ -249,24 +249,20 @@ namespace mRemoteNG.UI.Forms //Theming support private void SetSchema() { - if (_themeManager.ThemingActive) - { - // Persist settings when rebuilding UI - this.pnlDock.Theme = _themeManager.ActiveTheme.Theme; - ApplyTheme(); - } + if (!_themeManager.ThemingActive) return; + // Persist settings when rebuilding UI + pnlDock.Theme = _themeManager.ActiveTheme.Theme; + ApplyTheme(); } private void ApplyTheme() { - if(_themeManager.ThemingActive) - { - vsToolStripExtender.SetStyle(msMain, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); - vsToolStripExtender.SetStyle(_quickConnectToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); - vsToolStripExtender.SetStyle(_externalToolsToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); - vsToolStripExtender.SetStyle(_multiSshToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); - tsContainer.TopToolStripPanel.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("CommandBarMenuDefault_Background"); - } - } + if (!_themeManager.ThemingActive) return; + vsToolStripExtender.SetStyle(msMain, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); + vsToolStripExtender.SetStyle(_quickConnectToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); + vsToolStripExtender.SetStyle(_externalToolsToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); + vsToolStripExtender.SetStyle(_multiSshToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme); + tsContainer.TopToolStripPanel.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("CommandBarMenuDefault_Background"); + } private void frmMain_Shown(object sender, EventArgs e) { @@ -625,14 +621,8 @@ namespace mRemoteNG.UI.Forms public delegate void ClipboardchangeEventHandler(); public static event ClipboardchangeEventHandler ClipboardChanged { - add - { - _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Combine(_clipboardChangedEvent, value); - } - remove - { - _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Remove(_clipboardChangedEvent, value); - } + add => _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Combine(_clipboardChangedEvent, value); + remove => _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Remove(_clipboardChangedEvent, value); } #endregion diff --git a/mRemoteV1/UI/Forms/frmOptions.cs b/mRemoteV1/UI/Forms/frmOptions.cs index d39cc7c8..a613469f 100644 --- a/mRemoteV1/UI/Forms/frmOptions.cs +++ b/mRemoteV1/UI/Forms/frmOptions.cs @@ -40,16 +40,14 @@ namespace mRemoteNG.UI.Forms } private void ApplyTheme() { - if(Themes.ThemeManager.getInstance().ThemingActive) - { - BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); - ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); - } + if (!Themes.ThemeManager.getInstance().ThemingActive) return; + BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background"); + ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground"); } private void ApplyLanguage() { - this.Text = Language.strOptionsPageTitle; + Text = Language.strOptionsPageTitle; foreach (var optionPage in _pages.Values) { optionPage.ApplyLanguage(); @@ -93,8 +91,8 @@ namespace mRemoteNG.UI.Forms private void SetInitiallyActivatedPage() { - bool isSet = false; - for (int i = 0; i < lstOptionPages.Items.Count; i++) + var isSet = false; + for (var i = 0; i < lstOptionPages.Items.Count; i++) { if (!lstOptionPages.Items[i].Text.Equals(_pageName)) continue; lstOptionPages.Items[i].Selected = true; @@ -118,7 +116,7 @@ namespace mRemoteNG.UI.Forms } - private void LstOptionPages_SelectedIndexChanged(object sender, System.EventArgs e) + private void LstOptionPages_SelectedIndexChanged(object sender, EventArgs e) { pnlMain.Controls.Clear(); diff --git a/mRemoteV1/UI/Menu/MainFileMenu.cs b/mRemoteV1/UI/Menu/MainFileMenu.cs index 78c4f09e..85e08c88 100644 --- a/mRemoteV1/UI/Menu/MainFileMenu.cs +++ b/mRemoteV1/UI/Menu/MainFileMenu.cs @@ -167,7 +167,7 @@ namespace mRemoteNG.UI.Menu _mMenFileDelete.Image = Resources.Delete; _mMenFileDelete.Name = "mMenFileDelete"; _mMenFileDelete.Size = new System.Drawing.Size(281, 22); - _mMenFileDelete.Text = "Delete..."; + _mMenFileDelete.Text = Language.strDelete; _mMenFileDelete.Click += mMenFileDelete_Click; // // mMenFileRename @@ -175,7 +175,7 @@ namespace mRemoteNG.UI.Menu _mMenFileRename.Image = Resources.Rename; _mMenFileRename.Name = "mMenFileRename"; _mMenFileRename.Size = new System.Drawing.Size(281, 22); - _mMenFileRename.Text = "Rename"; + _mMenFileRename.Text = Language.strRename; _mMenFileRename.Click += mMenFileRename_Click; // // mMenFileDuplicate @@ -183,7 +183,7 @@ namespace mRemoteNG.UI.Menu _mMenFileDuplicate.Image = Resources.page_copy; _mMenFileDuplicate.Name = "mMenFileDuplicate"; _mMenFileDuplicate.Size = new System.Drawing.Size(281, 22); - _mMenFileDuplicate.Text = "Duplicate"; + _mMenFileDuplicate.Text = Language.strDuplicate; _mMenFileDuplicate.Click += mMenFileDuplicate_Click; // // mMenFileSep4 @@ -196,7 +196,7 @@ namespace mRemoteNG.UI.Menu _mMenReconnectAll.Image = Resources.Refresh; _mMenReconnectAll.Name = "mMenReconnectAll"; _mMenReconnectAll.Size = new System.Drawing.Size(281, 22); - _mMenReconnectAll.Text = "Reconnect All Connections"; + _mMenReconnectAll.Text = Language.strReconnectAllConnections; _mMenReconnectAll.Click += mMenReconnectAll_Click; // // mMenFileSep3 diff --git a/mRemoteV1/UI/Menu/ToolsMenu.cs b/mRemoteV1/UI/Menu/ToolsMenu.cs index 178461f3..69627ddd 100644 --- a/mRemoteV1/UI/Menu/ToolsMenu.cs +++ b/mRemoteV1/UI/Menu/ToolsMenu.cs @@ -61,7 +61,7 @@ namespace mRemoteNG.UI.Menu _mMenToolsUvncsc.Image = Resources.UVNC_SC; _mMenToolsUvncsc.Name = "mMenToolsUVNCSC"; _mMenToolsUvncsc.Size = new System.Drawing.Size(184, 22); - _mMenToolsUvncsc.Text = "UltraVNC SingleClick"; + _mMenToolsUvncsc.Text = Language.strUltraVNCSingleClick; _mMenToolsUvncsc.Visible = false; _mMenToolsUvncsc.Click += mMenToolsUVNCSC_Click; // diff --git a/mRemoteV1/UI/Window/ConfigWindow.cs b/mRemoteV1/UI/Window/ConfigWindow.cs index 880536c9..fd1c8244 100644 --- a/mRemoteV1/UI/Window/ConfigWindow.cs +++ b/mRemoteV1/UI/Window/ConfigWindow.cs @@ -265,6 +265,11 @@ namespace mRemoteNG.UI.Window _btnShowInheritance.Checked = false; } } + + /// + /// A list of properties being shown for the current object. + /// + public IEnumerable VisibleObjectProperties => _pGrid.VisibleProperties; #endregion #region Constructors @@ -1176,7 +1181,8 @@ namespace mRemoteNG.UI.Window strHide.Add("SoundQuality"); break; case ProtocolType.HTTP: - strHide.Add("CacheBitmaps"); + case ProtocolType.HTTPS: + strHide.Add("CacheBitmaps"); strHide.Add("Colors"); strHide.Add("DisplayThemes"); strHide.Add("DisplayWallpaper"); @@ -1218,49 +1224,6 @@ namespace mRemoteNG.UI.Window strHide.Add("VNCSmartSizeMode"); strHide.Add("VNCViewOnly"); strHide.Add("SoundQuality"); - break; - case ProtocolType.HTTPS: - strHide.Add("CacheBitmaps"); - strHide.Add("Colors"); - strHide.Add("DisplayThemes"); - strHide.Add("DisplayWallpaper"); - strHide.Add("EnableFontSmoothing"); - strHide.Add("EnableDesktopComposition"); - strHide.Add("Domain"); - strHide.Add("ExtApp"); - strHide.Add("ICAEncryptionStrength"); - strHide.Add("PuttySession"); - strHide.Add("RDGatewayDomain"); - strHide.Add("RDGatewayHostname"); - strHide.Add("RDGatewayPassword"); - strHide.Add("RDGatewayUsageMethod"); - strHide.Add("RDGatewayUseConnectionCredentials"); - strHide.Add("RDGatewayUsername"); - strHide.Add("RDPAuthenticationLevel"); - strHide.Add("RDPMinutesToIdleTimeout"); - strHide.Add("RDPAlertIdleTimeout"); - strHide.Add("LoadBalanceInfo"); - strHide.Add("RedirectDiskDrives"); - strHide.Add("RedirectKeys"); - strHide.Add("RedirectPorts"); - strHide.Add("RedirectPrinters"); - strHide.Add("RedirectSmartCards"); - strHide.Add("RedirectSound;Resolution"); - strHide.Add("AutomaticResize"); - strHide.Add("UseConsoleSession"); - strHide.Add("UseCredSsp"); - strHide.Add("VNCAuthMode"); - strHide.Add("VNCColors"); - strHide.Add("VNCCompression"); - strHide.Add("VNCEncoding"); - strHide.Add("VNCProxyIP"); - strHide.Add("VNCProxyPassword"); - strHide.Add("VNCProxyPort"); - strHide.Add("VNCProxyType"); - strHide.Add("VNCProxyUsername"); - strHide.Add("VNCSmartSizeMode"); - strHide.Add("VNCViewOnly"); - strHide.Add("SoundQuality"); break; case ProtocolType.ICA: strHide.Add("DisplayThemes"); diff --git a/mRemoteV1/UI/Window/ConnectionTreeWindow.cs b/mRemoteV1/UI/Window/ConnectionTreeWindow.cs index 99f0c520..6e3c1d45 100644 --- a/mRemoteV1/UI/Window/ConnectionTreeWindow.cs +++ b/mRemoteV1/UI/Window/ConnectionTreeWindow.cs @@ -2,12 +2,14 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.Linq; using System.Windows.Forms; using mRemoteNG.App; using mRemoteNG.Config.Connections; using mRemoteNG.Connection; using mRemoteNG.Themes; using mRemoteNG.Tree; +using mRemoteNG.Tree.Root; using mRemoteNG.UI.Controls; using WeifenLuo.WinFormsUI.Docking; // ReSharper disable ArrangeAccessorOwnerBody @@ -19,7 +21,6 @@ namespace mRemoteNG.UI.Window private readonly ConnectionContextMenu _contextMenu; private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator(); private ThemeManager _themeManager; - private readonly ConnectionTreeSearchTextFilter _connectionTreeSearchTextFilter = new ConnectionTreeSearchTextFilter(); public ConnectionInfo SelectedNode => olvConnections.SelectedNode; @@ -43,7 +44,6 @@ namespace mRemoteNG.UI.Window SetMenuEventHandlers(); SetConnectionTreeEventHandlers(); Settings.Default.PropertyChanged += OnAppSettingsChanged; - olvConnections.ModelFilter = _connectionTreeSearchTextFilter; } private void OnAppSettingsChanged(object o, PropertyChangedEventArgs propertyChangedEventArgs) @@ -159,6 +159,8 @@ namespace mRemoteNG.UI.Window private void ConnectionsServiceOnConnectionsLoaded(object o, ConnectionsLoadedEventArgs connectionsLoadedEventArgs) { olvConnections.ConnectionTreeModel = connectionsLoadedEventArgs.NewConnectionTreeModel; + olvConnections.SelectedObject = connectionsLoadedEventArgs.NewConnectionTreeModel.RootNodes + .OfType().FirstOrDefault(); } #endregion @@ -243,13 +245,10 @@ namespace mRemoteNG.UI.Window { if (txtSearch.Text == "" || txtSearch.Text == Language.strSearchPrompt) { - olvConnections.UseFiltering = false; - olvConnections.ResetColumnFiltering(); + olvConnections.RemoveFilter(); return; } - olvConnections.UseFiltering = true; - _connectionTreeSearchTextFilter.FilterText = txtSearch.Text; - olvConnections.ModelFilter = _connectionTreeSearchTextFilter; + olvConnections.ApplyFilter(txtSearch.Text); } else { diff --git a/mRemoteV1/UI/Window/ErrorAndInfoWindow.cs b/mRemoteV1/UI/Window/ErrorAndInfoWindow.cs index 463e840f..a379657d 100644 --- a/mRemoteV1/UI/Window/ErrorAndInfoWindow.cs +++ b/mRemoteV1/UI/Window/ErrorAndInfoWindow.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Collections; +using System.Globalization; using System.Windows.Forms; using System.Text; using WeifenLuo.WinFormsUI.Docking; @@ -14,7 +15,7 @@ namespace mRemoteNG.UI.Window public partial class ErrorAndInfoWindow : BaseWindow { private ControlLayout _layout = ControlLayout.Vertical; - private ThemeManager _themeManager; + private readonly ThemeManager _themeManager; public DockContent PreviousActiveForm { get; set; } @@ -53,11 +54,9 @@ namespace mRemoteNG.UI.Window #region Private Methods private new void ApplyTheme() { - if(_themeManager.ThemingActive) - { - lvErrorCollector.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background"); - lvErrorCollector.ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Foreground"); - } + if (!_themeManager.ThemingActive) return; + lvErrorCollector.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background"); + lvErrorCollector.ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Foreground"); } @@ -224,7 +223,7 @@ namespace mRemoteNG.UI.Window break; } - lblMsgDate.Text = eMsg.Date.ToString(); + lblMsgDate.Text = eMsg.Date.ToString(CultureInfo.InvariantCulture); txtMsgText.Text = eMsg.Text; } catch (Exception ex) @@ -291,7 +290,7 @@ namespace mRemoteNG.UI.Window } stringBuilder.AppendLine(message.Class.ToString()); - stringBuilder.AppendLine(message.Date.ToString()); + stringBuilder.AppendLine(message.Date.ToString(CultureInfo.InvariantCulture)); stringBuilder.AppendLine(message.Text); stringBuilder.AppendLine("----------"); } @@ -339,8 +338,8 @@ namespace mRemoteNG.UI.Window } } #endregion - - public enum ControlLayout + + private enum ControlLayout { Vertical = 0, Horizontal = 1 diff --git a/mRemoteV1/UI/Window/UpdateWindow.Designer.cs b/mRemoteV1/UI/Window/UpdateWindow.Designer.cs index 8a9f34a1..6a8d2f24 100644 --- a/mRemoteV1/UI/Window/UpdateWindow.Designer.cs +++ b/mRemoteV1/UI/Window/UpdateWindow.Designer.cs @@ -20,17 +20,17 @@ namespace mRemoteNG.UI.Window private void InitializeComponent() { - this.btnCheckForUpdate = new Controls.Base.NGButton(); + this.btnCheckForUpdate = new mRemoteNG.UI.Controls.Base.NGButton(); this.pnlUpdate = new System.Windows.Forms.Panel(); - this.lblChangeLogLabel = new Controls.Base.NGLabel(); - this.btnDownload = new Controls.Base.NGButton(); - this.prgbDownload = new Controls.Base.NGProgressBar(); - this.txtChangeLog = new Controls.Base.NGTextBox(); - this.lblStatus = new Controls.Base.NGLabel(); - this.lblLatestVersionLabel = new Controls.Base.NGLabel(); - this.lblInstalledVersionLabel = new Controls.Base.NGLabel(); - this.lblLatestVersion = new Controls.Base.NGLabel(); - this.lblInstalledVersion = new Controls.Base.NGLabel(); + this.lblChangeLogLabel = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.btnDownload = new mRemoteNG.UI.Controls.Base.NGButton(); + this.prgbDownload = new mRemoteNG.UI.Controls.Base.NGProgressBar(); + this.txtChangeLog = new mRemoteNG.UI.Controls.Base.NGTextBox(); + this.lblStatus = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.lblLatestVersionLabel = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.lblInstalledVersionLabel = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.lblLatestVersion = new mRemoteNG.UI.Controls.Base.NGLabel(); + this.lblInstalledVersion = new mRemoteNG.UI.Controls.Base.NGLabel(); this.pbUpdateImage = new System.Windows.Forms.PictureBox(); this.pnlUpdate.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pbUpdateImage)).BeginInit(); @@ -38,6 +38,7 @@ namespace mRemoteNG.UI.Window // // btnCheckForUpdate // + this.btnCheckForUpdate._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; this.btnCheckForUpdate.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btnCheckForUpdate.Location = new System.Drawing.Point(16, 104); this.btnCheckForUpdate.Name = "btnCheckForUpdate"; @@ -74,11 +75,12 @@ namespace mRemoteNG.UI.Window // // btnDownload // + this.btnDownload._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER; this.btnDownload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnDownload.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btnDownload.Location = new System.Drawing.Point(0, 216); this.btnDownload.Name = "btnDownload"; - this.btnDownload.Size = new System.Drawing.Size(144, 32); + this.btnDownload.Size = new System.Drawing.Size(224, 32); this.btnDownload.TabIndex = 2; this.btnDownload.Text = "Download and Install"; this.btnDownload.UseVisualStyleBackColor = true; @@ -88,9 +90,9 @@ namespace mRemoteNG.UI.Window // this.prgbDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.prgbDownload.Location = new System.Drawing.Point(160, 224); + this.prgbDownload.Location = new System.Drawing.Point(230, 224); this.prgbDownload.Name = "prgbDownload"; - this.prgbDownload.Size = new System.Drawing.Size(542, 23); + this.prgbDownload.Size = new System.Drawing.Size(472, 23); this.prgbDownload.TabIndex = 3; this.prgbDownload.Visible = false; // diff --git a/mRemoteV1/app.config b/mRemoteV1/app.config index 2e5fd3f6..8b26045a 100644 --- a/mRemoteV1/app.config +++ b/mRemoteV1/app.config @@ -666,7 +666,7 @@ - + General True diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj index 8251869c..d8b3f1e1 100644 --- a/mRemoteV1/mRemoteV1.csproj +++ b/mRemoteV1/mRemoteV1.csproj @@ -23,7 +23,7 @@ Off B249710A6BB08171F8E75082CF2355AE2890911A mRemoteV1_TemporaryKey.pfx - true + false false v4.6 @@ -41,7 +41,7 @@ false true 1 - 1.64.0.%2a + 1.64.0.1 false true true @@ -1561,24 +1561,26 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo false - false + true true bin\Release\ 1591,660,661 - none + full x86 AllRules.ruleset 1 false false + + - false + true true bin\Release Portable\ PORTABLE 1591,660,661 - none + full x86 false MinimumRecommendedRules.ruleset @@ -1597,6 +1599,9 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo MinimumRecommendedRules.ruleset false + + LocalIntranet +