Merge branch 'release/v1.76' into develop

# Conflicts:
#	Tools/zip_portable_files.ps1
#	mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs
This commit is contained in:
David Sparer
2018-08-22 10:39:09 -05:00
82 changed files with 1498 additions and 871 deletions

View File

@@ -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):

View File

@@ -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}\""

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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",

View File

@@ -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 {

56
Tools/zip_symbols.ps1 Normal file
View File

@@ -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 ""

View File

@@ -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()
{

View File

@@ -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));
}
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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<string> 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<TestCaseData> ConnectionInfoGeneralTestCases()
{
var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType<ProtocolType>();
var testCases = new List<TestCaseData>();
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<string> BuildExpectedConnectionInfoPropertyList(ProtocolType protocol, bool isContainer)
{
var expectedProperties = new List<string>
{
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;
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<string> 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));
}
}
}

View File

@@ -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),
});
}
}
}

View File

@@ -233,6 +233,10 @@
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
<Compile Include="UI\Forms\PasswordFormTests.cs" />
<Compile Include="UI\WindowListTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowGeneralTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowRdpSpecialTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowSpecialTestsBase.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowVncSpecialTests.cs" />
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
</ItemGroup>
<ItemGroup>

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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
{

View File

@@ -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);
}
/// <summary>
/// When turned on, calls to <see cref="SaveConnections()"/> or
/// <see cref="SaveConnectionsAsync"/> will not immediately execute.
/// Instead, they will be deferred until <see cref="EndBatchingSaves"/>
/// is called.
/// </summary>
public void BeginBatchingSaves()
{
_batchingSaves = true;
}
/// <summary>
/// Immediately executes a single <see cref="SaveConnections()"/> or
/// <see cref="SaveConnectionsAsync"/> if one has been requested
/// since calling <see cref="BeginBatchingSaves"/>.
/// </summary>
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()

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.76.5.*")]
[assembly: AssemblyVersion("1.76.6.*")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -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"]));

View File

@@ -645,7 +645,7 @@
<Value Profile="(Default)" />
</Setting>
<Setting Name="ConDefaultPanel" Type="System.String" Scope="User">
<Value Profile="(Default)" />
<Value Profile="(Default)">General</Value>
</Setting>
<Setting Name="SaveConnectionsAfterEveryEdit" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
@@ -17,6 +17,10 @@
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<PermissionSet Unrestricted="true" ID="Custom" SameSite="site" />
<defaultAssemblyRequest permissionSetReference="Custom" />
</applicationRequestMinimum>
</security>
</trustInfo>
</asmv1:assembly>
</asmv1:assembly>

View File

@@ -1711,6 +1711,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Delete....
/// </summary>
internal static string strDelete {
get {
return ResourceManager.GetString("strDelete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Detect.
/// </summary>
@@ -2777,6 +2786,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Must Be Between 0 and 255.
/// </summary>
internal static string strIPRange {
get {
return ResourceManager.GetString("strIPRange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CTRL-ALT-DEL.
/// </summary>
@@ -4308,6 +4326,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Out Of Range.
/// </summary>
internal static string strOutOfRange {
get {
return ResourceManager.GetString("strOutOfRange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Panel Name.
/// </summary>
@@ -6237,6 +6264,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect All Connections.
/// </summary>
internal static string strReconnectAllConnections {
get {
return ResourceManager.GetString("strReconnectAllConnections", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect to previously opened sessions on startup.
/// </summary>
@@ -7263,6 +7299,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to UltraVNC SingleClick.
/// </summary>
internal static string strUltraVNCSingleClick {
get {
return ResourceManager.GetString("strUltraVNCSingleClick", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uncheck the properties you want not to be saved!.
/// </summary>

View File

@@ -2679,4 +2679,19 @@ This page will walk you through the process of upgrading your connections file o
<data name="strCreateEmptyPanelOnStartUp" xml:space="preserve">
<value>Create an empty panel when mRemoteNG starts</value>
</data>
<data name="strIPRange" xml:space="preserve">
<value>Must Be Between 0 and 255</value>
</data>
<data name="strOutOfRange" xml:space="preserve">
<value>Out Of Range</value>
</data>
<data name="strDelete" xml:space="preserve">
<value>Delete...</value>
</data>
<data name="strReconnectAllConnections" xml:space="preserve">
<value>Reconnect All Connections</value>
</data>
<data name="strUltraVNCSingleClick" xml:space="preserve">
<value>UltraVNC SingleClick</value>
</data>
</root>

View File

@@ -9,35 +9,14 @@ namespace mRemoteNG.Themes
/// </summary>
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<string, Color> _extendedColors;
private Dictionary<string, Color> _default;
#endregion
#region Constructors
public ExtendedColorPalette()
{
_extendedColors = new Dictionary<string, Color>();
_default = new Dictionary<string, Color>(); // If this is the default palette, it will not have a default-default palette
ExtColorPalette = new Dictionary<string, Color>();
DefaultColorPalette = new Dictionary<string, Color>(); // 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
/// <returns></returns>
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
/// <param name="inColor"></param>
public void addColor(string colorKey,Color inColor)
{
_extendedColors.Add(colorKey, inColor);
ExtColorPalette.Add(colorKey, inColor);
}
@@ -111,33 +89,13 @@ namespace mRemoteNG.Themes
/// <param name="inColor"></param>
public void replaceColor(string colorKey, Color inColor)
{
_extendedColors[colorKey]= inColor;
ExtColorPalette[colorKey]= inColor;
}
public Dictionary<string, Color> DefaultColorPalette
{
get
{
return _default;
}
set
{
_default = value;
}
}
public Dictionary<string, Color> DefaultColorPalette { get; set; }
public Dictionary<string, Color> ExtColorPalette
{
get
{
return _extendedColors;
}
set
{
_extendedColors = value;
}
}
public Dictionary<string, Color> ExtColorPalette { get; set; }
}
}

View File

@@ -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);

View File

@@ -7,6 +7,7 @@ using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.Themes
{
/// <inheritdoc />
/// <summary>
/// Container class for all the color and style elements to define a theme
/// </summary>
@@ -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
}
}

View File

@@ -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<ThemeInfo> LoadThemes()
{
if (themes == null)
if (themes != null) return themes.Values.OfType<ThemeInfo>().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<ThemeInfo>().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<ThemeInfo>().ToList();
}
@@ -149,29 +139,24 @@ namespace mRemoteNG.Themes
/// <returns></returns>
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

View File

@@ -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
{
/// <summary>
/// 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
/// </summary>
/// <param name="themeInfo"></param>
public static void SaveToXmlFile(ThemeInfo themeToSave,ThemeInfo baseTheme)
/// <summary>
/// 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
/// </summary>
/// <param name="themeToSave"></param>
/// <param name="baseTheme"></param>
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
/// <param name="themeToUpdate"></param>
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
/// <returns></returns>
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);
}
*/
}
}

View File

@@ -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);

View File

@@ -10,7 +10,7 @@ namespace mRemoteNG.UI.Controls.Base
{
private ThemeManager _themeManager;
public NGGroupBox() : base()
public NGGroupBox()
{
ThemeManager.getInstance().ThemeChanged += OnCreateControl;
}

View File

@@ -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);
}
}

View File

@@ -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
{

View File

@@ -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()
/// <summary>
/// Filters tree items based on the given <see cref="filterText"/>
/// </summary>
/// <param name="filterText">The text to filter by</param>
public void ApplyFilter(string filterText)
{
base.UpdateFiltering();
AutoResizeColumn(Columns[0]);
UseFiltering = true;
_connectionTreeSearchTextFilter.FilterText = filterText;
ModelFilter = _connectionTreeSearchTextFilter;
}
/// <summary>
/// Removes all item filtering from the connection tree
/// </summary>
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)

View File

@@ -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; } = "";
/// <summary>
/// A list of <see cref="ConnectionInfo"/> objects that should
/// always be included in the output, regardless of matching
/// the desired <see cref="FilterText"/>.
/// </summary>
public List<ConnectionInfo> SpecialInclusionList { get; } = new List<ConnectionInfo>();
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) ||

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public partial class FilteredPropertyGrid : PropertyGrid
/// <summary>
/// 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.
/// </summary>
public partial class FilteredPropertyGrid : PropertyGrid
{
/// <summary>Contain a reference to the collection of properties to show in the parent PropertyGrid.</summary>
/// <summary>
/// Contain a reference to the collection of properties to show in the parent PropertyGrid.
/// </summary>
/// <remarks>By default, m_PropertyDescriptors contain all the properties of the object. </remarks>
readonly List<PropertyDescriptor> m_PropertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Contain a reference to the array of properties to display in the PropertyGrid.</summary>
private AttributeCollection m_HiddenAttributes, m_BrowsableAttributes;
/// <summary>Contain references to the arrays of properties or categories to hide.</summary>
private string[] m_BrowsableProperties, m_HiddenProperties;
/// <summary>Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid.</summary>
private ObjectWrapper m_Wrapper;
readonly List<PropertyDescriptor> _propertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Public constructor.</summary>
public FilteredPropertyGrid() {
/// <summary>
/// Contain a reference to the array of properties to display in the PropertyGrid.
/// </summary>
private AttributeCollection _hiddenAttributes;
private AttributeCollection _browsableAttributes;
/// <summary>
/// Contain references to the arrays of properties or categories to hide.
/// </summary>
private string[] _mBrowsableProperties;
private string[] _mHiddenProperties;
/// <summary>
/// Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid.
/// </summary>
private ObjectWrapper _mWrapper;
/// <summary>
/// Public constructor.
/// </summary>
public FilteredPropertyGrid()
{
InitializeComponent();
base.SelectedObject = m_Wrapper;
base.SelectedObject = _mWrapper;
}
public new AttributeCollection BrowsableAttributes {
get { return m_BrowsableAttributes; }
/// <summary>
/// A list of all currently properties being shown by the property grid.
/// </summary>
public IEnumerable<string> 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();
}
}
/// <summary>Get or set the categories to hide.</summary>
/// <summary>
/// Get or set the categories to hide.
/// </summary>
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();
}
}
/// <summary>Get or set the properties to show.</summary>
/// <summary>
/// Get or set the properties to show.
/// </summary>
/// <exception cref="ArgumentException">if one or several properties don't exist.</exception>
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();
}
}
/// <summary>Get or set the properties to hide.</summary>
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();
}
}
/// <summary>Overwrite the PropertyGrid.SelectedObject property.</summary>
/// <summary>
/// Overwrite the PropertyGrid.SelectedObject property.
/// </summary>
/// <remarks>The object passed to the base PropertyGrid is the wrapper.</remarks>
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;
}
}
/*
/// <summary>Called when the browsable properties have changed.</summary>
private void OnBrowsablePropertiesChanged() {
if(m_Wrapper == null) return;
}
*/
/// <summary>
/// Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties.
/// </summary>
private void RefreshProperties()
{
if(_mWrapper == null)
return;
/// <summary>Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties.</summary>
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<PropertyDescriptor>()
.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);
}
}
}
}
/// <summary>Allows to hide a set of properties to the parent PropertyGrid.</summary>
/// <summary>
/// Predicate to determine if a property has a Browsable(false) attribute
/// attatched to it. If so, it should not be shown.
/// </summary>
/// <param name="propertyDescriptor"></param>
/// <returns></returns>
private bool PropertyDoesntHaveBrowsableFalseAttribute(PropertyDescriptor propertyDescriptor)
{
return !propertyDescriptor.Attributes.Contains(new BrowsableAttribute(false));
}
/// <summary>
/// Allows to hide a set of properties to the parent PropertyGrid.
/// </summary>
/// <param name="attribute">A set of attributes that filter the original collection of properties.</param>
/// <remarks>For better performance, include the BrowsableAttribute with true value.</remarks>
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);
}
/// <summary>Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid.</summary>
/// <summary>
/// Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid.
/// </summary>
/// <param name="attribute">The attribute to be added.</param>
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);
}
/// <summary>Add a property to the list of properties to be displayed in the PropertyGrid.</summary>
/// <summary>
/// Add a property to the list of properties to be displayed in the PropertyGrid.
/// </summary>
/// <param name="property">The property to be added.</param>
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);
}
/// <summary>Allows to hide a property to the parent PropertyGrid.</summary>
/// <summary>
/// Allows to hide a property to the parent PropertyGrid.
/// </summary>
/// <param name="property">The name of the property to be hidden.</param>
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);
}
}
}

View File

@@ -4,96 +4,119 @@ using System.ComponentModel;
namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
{
/// <summary>This class is a wrapper. It contains the object the propertyGrid has to display.</summary>
internal class ObjectWrapper : ICustomTypeDescriptor
/// <summary>
/// This class is a wrapper. It contains the object the PropertyGrid has to display.
/// </summary>
internal class ObjectWrapper : ICustomTypeDescriptor
{
/// <summary>Contain a reference to the selected objet that will linked to the parent PropertyGrid.</summary>
private object m_SelectedObject;
/// <summary>Contain a reference to the collection of properties to show in the parent PropertyGrid.</summary>
/// <remarks>By default, m_PropertyDescriptors contain all the properties of the object. </remarks>
List<PropertyDescriptor> m_PropertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Simple constructor.</summary>
/// <summary>
/// Creates a new instance of an <see cref="ObjectWrapper"/> with the given object to be wrapped.
/// </summary>
/// <param name="obj">A reference to the selected object that will linked to the parent PropertyGrid.</param>
internal ObjectWrapper(object obj) {
m_SelectedObject = obj;
internal ObjectWrapper(object obj)
{
SelectedObject = obj;
}
/// <summary>Get or set a reference to the selected objet that will linked to the parent PropertyGrid.</summary>
public object SelectedObject {
get { return m_SelectedObject; }
set { m_SelectedObject = value; }
}
/// <summary>
/// Get or set a reference to the selected objet that will linked to the parent PropertyGrid.
/// </summary>
public object SelectedObject { get; set; }
/// <summary>Get or set a reference to the collection of properties to show in the parent PropertyGrid.</summary>
public List<PropertyDescriptor> PropertyDescriptors {
get { return m_PropertyDescriptors; }
set { m_PropertyDescriptors = value; }
}
/// <summary>
/// Get or set a reference to the collection of properties to show in the parent PropertyGrid
/// </summary>
public List<PropertyDescriptor> PropertyDescriptors { get; set; } = new List<PropertyDescriptor>();
#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);
}
/// <summary>GetAttributes.</summary>
/// <summary>
/// GetAttributes
/// </summary>
/// <returns>AttributeCollection</returns>
public AttributeCollection GetAttributes() {
return TypeDescriptor.GetAttributes(m_SelectedObject,true);
}
/// <summary>Get Class Name.</summary>
/// <returns>String</returns>
public String GetClassName() {
return TypeDescriptor.GetClassName(m_SelectedObject,true);
}
/// <summary>GetComponentName.</summary>
/// <returns>String</returns>
public String GetComponentName() {
return TypeDescriptor.GetComponentName(m_SelectedObject,true);
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(SelectedObject, true);
}
/// <summary>GetConverter.</summary>
/// <summary>
/// Get Class Name
/// </summary>
/// <returns>String</returns>
public string GetClassName()
{
return TypeDescriptor.GetClassName(SelectedObject, true);
}
/// <summary>
/// GetComponentName
/// </summary>
/// <returns>String</returns>
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(SelectedObject, true);
}
/// <summary>
/// GetConverter
/// </summary>
/// <returns>TypeConverter</returns>
public TypeConverter GetConverter() {
return TypeDescriptor.GetConverter(m_SelectedObject,true);
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(SelectedObject, true);
}
/// <summary>GetDefaultEvent.</summary>
/// <summary>
/// GetDefaultEvent
/// </summary>
/// <returns>EventDescriptor</returns>
public EventDescriptor GetDefaultEvent() {
return TypeDescriptor.GetDefaultEvent(m_SelectedObject,true);
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(SelectedObject, true);
}
/// <summary>GetDefaultProperty.</summary>
/// <summary>
/// GetDefaultProperty
/// </summary>
/// <returns>PropertyDescriptor</returns>
public PropertyDescriptor GetDefaultProperty() {
return TypeDescriptor.GetDefaultProperty(m_SelectedObject,true);
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(SelectedObject, true);
}
/// <summary>GetEditor.</summary>
/// <summary>
/// GetEditor
/// </summary>
/// <param name="editorBaseType">editorBaseType</param>
/// <returns>object</returns>
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
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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()]

View File

@@ -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();
}
}

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -1,6 +1,6 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
partial class CredentialsPage
sealed partial class CredentialsPage
{
/// <summary>
/// Required designer variable.

View File

@@ -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 { }
}

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -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();
}
}
}

View File

@@ -1,6 +1,6 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
partial class SecurityPage
sealed partial class SecurityPage
{
/// <summary>
/// Required designer variable.

View File

@@ -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 { }
}

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -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.

View File

@@ -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()

View File

@@ -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<string, Color> 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

View File

@@ -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.

View File

@@ -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 { }
}

View File

@@ -11,15 +11,34 @@ namespace mRemoteNG.UI.Forms
private readonly string _passwordName;
private SecureString _password = new SecureString();
private bool Verify { get; }
/// <summary>
/// Puts the dialog into the New Password mode. An extra
/// password box is shown which must match the first password
/// to continue.
/// </summary>
private bool NewPasswordMode { get; }
public PasswordForm(string passwordName = null, bool verify = true)
/// <summary>
/// Creates a new password form for entering or setting a password.
/// </summary>
/// <param name="passwordName"></param>
/// <param name="newPasswordMode">
/// Puts the dialog into the New Password mode. An extra
/// password box is shown which must match the first password
/// to continue.
/// </param>
public PasswordForm(string passwordName = null, bool newPasswordMode = true)
{
InitializeComponent();
_passwordName = passwordName;
Verify = verify;
NewPasswordMode = newPasswordMode;
}
/// <summary>
/// Dispaly a dialog box requesting that the user
/// enter their password.
/// </summary>
/// <returns></returns>
public Optional<SecureString> 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)
{

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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;
//

View File

@@ -265,6 +265,11 @@ namespace mRemoteNG.UI.Window
_btnShowInheritance.Checked = false;
}
}
/// <summary>
/// A list of properties being shown for the current object.
/// </summary>
public IEnumerable<string> 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");

View File

@@ -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<RootNodeInfo>().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
{

View File

@@ -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

View File

@@ -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;
//

View File

@@ -666,7 +666,7 @@
<value />
</setting>
<setting name="ConDefaultPanel" serializeAs="String">
<value />
<value>General</value>
</setting>
<setting name="SaveConnectionsAfterEveryEdit" serializeAs="String">
<value>True</value>

View File

@@ -23,7 +23,7 @@
<OptionStrict>Off</OptionStrict>
<ManifestCertificateThumbprint>B249710A6BB08171F8E75082CF2355AE2890911A</ManifestCertificateThumbprint>
<ManifestKeyFile>mRemoteV1_TemporaryKey.pfx</ManifestKeyFile>
<GenerateManifests>true</GenerateManifests>
<GenerateManifests>false</GenerateManifests>
<SignManifests>false</SignManifests>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkProfile />
@@ -41,7 +41,7 @@
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.64.0.%2a</ApplicationVersion>
<ApplicationVersion>1.64.0.1</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
@@ -1561,24 +1561,26 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<DebugSymbols>false</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Release\</OutputPath>
<NoWarn>1591,660,661</NoWarn>
<DebugType>none</DebugType>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>1</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<Prefer32Bit>false</Prefer32Bit>
<DefineConstants>
</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release Portable|x86'">
<DebugSymbols>false</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Release Portable\</OutputPath>
<DefineConstants>PORTABLE</DefineConstants>
<NoWarn>1591,660,661</NoWarn>
<DebugType>none</DebugType>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@@ -1597,6 +1599,9 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">