Merge pull request #1389 from mRemoteNG/refactor_config_window

Refactored config window to make property management easier
This commit is contained in:
David Sparer
2019-04-24 12:08:12 -05:00
committed by GitHub
22 changed files with 1226 additions and 1417 deletions

View File

@@ -53,7 +53,8 @@ namespace mRemoteNGTests.Connection
[Test]
public void CloneCorrectlySetsParentOfInheritanceObject()
{
var clonedConnection = _connectionInfo.Clone();
var originalConnection = new ConnectionInfo();
var clonedConnection = originalConnection.Clone();
Assert.That(clonedConnection.Inheritance.Parent, Is.EqualTo(clonedConnection));
}
@@ -135,7 +136,7 @@ namespace mRemoteNGTests.Connection
{
public static IEnumerable<PropertyInfo> GetProperties()
{
return new ConnectionInfoInheritance(new object()).GetProperties();
return new ConnectionInfoInheritance(new ConnectionInfo()).GetProperties();
}
}
}

View File

@@ -11,7 +11,7 @@ namespace mRemoteNGTests.Connection
[TestCaseSource(nameof(GetInheritanceProperties))]
public void LoadingDefaultInheritanceUpdatesAllProperties(PropertyInfo property)
{
var inheritanceSource = new ConnectionInfoInheritance(new object(), true);
var inheritanceSource = new ConnectionInfoInheritance(new ConnectionInfo(), true);
inheritanceSource.TurnOnInheritanceCompletely();
DefaultConnectionInheritance.Instance.TurnOffInheritanceCompletely();
@@ -25,7 +25,7 @@ namespace mRemoteNGTests.Connection
[TestCaseSource(nameof(GetInheritanceProperties))]
public void SavingDefaultInheritanceExportsAllProperties(PropertyInfo property)
{
var saveTarget = new ConnectionInfoInheritance(new object(), true);
var saveTarget = new ConnectionInfoInheritance(new ConnectionInfo(), true);
saveTarget.TurnOffInheritanceCompletely();
DefaultConnectionInheritance.Instance.TurnOnInheritanceCompletely();
@@ -40,7 +40,7 @@ namespace mRemoteNGTests.Connection
public void NewInheritanceInstancesCreatedWithDefaultInheritanceValues()
{
DefaultConnectionInheritance.Instance.Domain = true;
var inheritanceInstance = new ConnectionInfoInheritance(new object());
var inheritanceInstance = new ConnectionInfoInheritance(new ConnectionInfo());
Assert.That(inheritanceInstance.Domain, Is.True);
}
@@ -48,7 +48,7 @@ namespace mRemoteNGTests.Connection
public void NewInheritanceInstancesCreatedWithAllDefaultInheritanceValues(PropertyInfo property)
{
DefaultConnectionInheritance.Instance.TurnOnInheritanceCompletely();
var inheritanceInstance = new ConnectionInfoInheritance(new object());
var inheritanceInstance = new ConnectionInfoInheritance(new ConnectionInfo());
var valueInDestination = property.GetValue(inheritanceInstance);
var valueInSource = property.GetValue(DefaultConnectionInheritance.Instance);
@@ -57,7 +57,7 @@ namespace mRemoteNGTests.Connection
private static IEnumerable<PropertyInfo> GetInheritanceProperties()
{
return new ConnectionInfoInheritance(new object(), true).GetProperties();
return new ConnectionInfoInheritance(new ConnectionInfo(), true).GetProperties();
}
}
}

View File

@@ -1,94 +1,17 @@
using System;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
using mRemoteNG.Connection.Protocol.ICA;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Connection;
using mRemoteNG.Container;
namespace mRemoteNGTests.TestHelpers
{
internal static class ConnectionInfoHelpers
internal static class ConnectionInfoHelpers
{
private static readonly Random _random = new Random();
/// <summary>
/// Returns a <see cref="ConnectionInfo"/> object with randomized
/// values in all fields.
/// </summary>
internal static ConnectionInfo GetRandomizedConnectionInfo(bool randomizeInheritance = false)
{
var connectionInfo = new ConnectionInfo
{
// string types
Name = RandomString(),
Hostname = RandomString(),
Description = RandomString(),
Domain = RandomString(),
ExtApp = RandomString(),
Icon = RandomString(),
LoadBalanceInfo = RandomString(),
MacAddress = RandomString(),
Panel = RandomString(),
Password = RandomString(),
PostExtApp = RandomString(),
PreExtApp = RandomString(),
PuttySession = RandomString(),
RDGatewayHostname = RandomString(),
RDGatewayUsername = RandomString(),
RDGatewayDomain = RandomString(),
RDGatewayPassword = RandomString(),
UserField = RandomString(),
Username = RandomString(),
VNCProxyIP = RandomString(),
VNCProxyPassword = RandomString(),
VNCProxyUsername = RandomString(),
// bool types
AutomaticResize = RandomBool(),
CacheBitmaps = RandomBool(),
DisplayThemes = RandomBool(),
DisplayWallpaper = RandomBool(),
EnableDesktopComposition = RandomBool(),
EnableFontSmoothing = RandomBool(),
IsContainer = RandomBool(),
IsDefault = RandomBool(),
IsQuickConnect = RandomBool(),
PleaseConnect = RandomBool(),
RDPAlertIdleTimeout = RandomBool(),
RedirectDiskDrives = RandomBool(),
RedirectKeys = RandomBool(),
RedirectPorts = RandomBool(),
RedirectPrinters = RandomBool(),
RedirectSmartCards = RandomBool(),
UseConsoleSession = RandomBool(),
UseCredSsp = RandomBool(),
VNCViewOnly = RandomBool(),
Favorite = RandomBool(),
// ints
Port = RandomInt(),
RDPMinutesToIdleTimeout = RandomInt(),
VNCProxyPort = RandomInt(),
// enums
Colors = RandomEnum<RdpProtocol.RDPColors>(),
ICAEncryptionStrength = RandomEnum<IcaProtocol.EncryptionStrength> (),
Protocol = RandomEnum<ProtocolType>(),
RDGatewayUsageMethod = RandomEnum<RdpProtocol.RDGatewayUsageMethod>(),
RDGatewayUseConnectionCredentials = RandomEnum<RdpProtocol.RDGatewayUseConnectionCredentials>(),
RDPAuthenticationLevel = RandomEnum<RdpProtocol.AuthenticationLevel>(),
RedirectSound = RandomEnum<RdpProtocol.RDPSounds>(),
RenderingEngine = RandomEnum<HTTPBase.RenderingEngine>(),
Resolution = RandomEnum<RdpProtocol.RDPResolutions>(),
SoundQuality = RandomEnum<RdpProtocol.RDPSoundQuality>(),
VNCAuthMode = RandomEnum<ProtocolVNC.AuthMode>(),
VNCColors = RandomEnum<ProtocolVNC.Colors>(),
VNCCompression = RandomEnum<ProtocolVNC.Compression>(),
VNCEncoding = RandomEnum<ProtocolVNC.Encoding>(),
VNCProxyType = RandomEnum<ProtocolVNC.ProxyType>(),
VNCSmartSizeMode = RandomEnum<ProtocolVNC.SmartSizeMode>(),
};
var connectionInfo = new ConnectionInfo().RandomizeValues();
if (randomizeInheritance)
connectionInfo.Inheritance = GetRandomizedInheritance(connectionInfo);
@@ -96,38 +19,24 @@ namespace mRemoteNGTests.TestHelpers
return connectionInfo;
}
internal static ContainerInfo GetRandomizedContainerInfo(bool randomizeInheritance = false)
{
var containerInfo = new ContainerInfo().RandomizeValues();
if (randomizeInheritance)
containerInfo.Inheritance = GetRandomizedInheritance(containerInfo);
return containerInfo;
}
internal static ConnectionInfoInheritance GetRandomizedInheritance(ConnectionInfo parent)
{
var inheritance = new ConnectionInfoInheritance(parent, true);
foreach (var property in inheritance.GetProperties())
{
property.SetValue(inheritance, RandomBool());
property.SetValue(inheritance, Randomizer.RandomBool());
}
return inheritance;
}
internal static string RandomString()
{
return Guid.NewGuid().ToString("N");
}
internal static bool RandomBool()
{
return _random.Next() % 2 == 0;
}
internal static int RandomInt()
{
return _random.Next();
}
internal static T RandomEnum<T>() where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enum");
var values = Enum.GetValues(typeof(T));
return (T)values.GetValue(_random.Next(values.Length));
}
}
}

View File

@@ -6,7 +6,7 @@ using Enum = System.Enum;
namespace mRemoteNGTests.TestHelpers
{
internal static class Randomizer
internal static class Randomizer
{
private static readonly Random Random = new Random();
@@ -98,7 +98,8 @@ namespace mRemoteNGTests.TestHelpers
if (opByType.TryGetValue(property.PropertyType, out var mutator))
mutator(property, con);
else if (opByType.TryGetValue(property.PropertyType.BaseType, out var mutator2))
else if (property.PropertyType.BaseType != null &&
opByType.TryGetValue(property.PropertyType.BaseType, out var mutator2))
mutator2(property, con);
}

View File

@@ -0,0 +1,133 @@
using System;
using System.Linq;
using mRemoteNG.UI.Controls.FilteredPropertyGrid;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Controls
{
public class FilteredPropertyGridTests
{
[Test]
public void AllPropertiesVisibleByDefault()
{
var grid = new FilteredPropertyGrid();
var obj = new {Prop1 = "hello"};
grid.SelectedObject = obj;
Assert.That(grid.VisibleProperties, Is.EquivalentTo(new []{ nameof(obj.Prop1) }));
}
[Test]
public void PropertiesOnTheHiddenPropertiesListAreNotShown()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world" };
grid.HiddenProperties = new[] { nameof(obj.Prop1) };
grid.SelectedObject = obj;
Assert.That(grid.VisibleProperties, Is.EquivalentTo(new[] { nameof(obj.Prop2) }));
}
[Test]
public void OnlyPropertiesOnTheBrowsablePropertiesListAreShown()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world" };
grid.BrowsableProperties = new[] { nameof(obj.Prop1) };
grid.SelectedObject = obj;
Assert.That(grid.VisibleProperties, Is.EquivalentTo(new[] { nameof(obj.Prop1) }));
}
[Test]
public void APropertyOnBothTheBrowsableAndHiddenListWillNotBeShown()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world", Prop3 = "!" };
grid.BrowsableProperties = new[] { nameof(obj.Prop1), nameof(obj.Prop2) };
grid.HiddenProperties = new[] { nameof(obj.Prop1) };
grid.SelectedObject = obj;
Assert.That(grid.VisibleProperties, Is.EquivalentTo(new[] { nameof(obj.Prop2) }));
}
[Test]
public void ExceptionThrownWhenNonExistantPropertyFoundInBrowsablePropertiesList()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello" };
grid.SelectedObject = obj;
Assert.Throws<InvalidOperationException>(() =>
grid.BrowsableProperties = new[] {"NonExistantProperty"});
}
[Test]
public void HiddenPropertiesListCanHandleNonExistentProperties()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello" };
grid.SelectedObject = obj;
Assert.DoesNotThrow(() => grid.HiddenProperties = new[] { "NonExistantProperty" });
}
[Test]
public void GetVisibleGridItemsReturnsAllExpandedItems()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = new{Prop3 = "world"} };
grid.SelectedObject = obj;
var visibleGridItems = grid.GetVisibleGridItems();
Assert.That(visibleGridItems.Select(i => i.Label),
Is.EquivalentTo(new[]
{
nameof(obj.Prop1),
nameof(obj.Prop2)
}));
}
[Test]
public void CanSelectGridItem()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world" };
grid.SelectedObject = obj;
grid.SelectGridItem(nameof(obj.Prop2));
Assert.That(grid.SelectedGridItem.PropertyDescriptor?.Name,
Is.EqualTo(nameof(obj.Prop2)));
}
[Test]
public void FindNextGridItemPropertyReturnsTheCorrectItem()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world" };
grid.SelectedObject = obj;
grid.SelectGridItem(nameof(obj.Prop1));
var nextGridItem = grid.FindNextGridItemProperty(grid.SelectedGridItem);
Assert.That(nextGridItem?.PropertyDescriptor?.Name,
Is.EqualTo(nameof(obj.Prop2)));
}
[Test]
public void FindPreviousGridItemPropertyReturnsTheCorrectItem()
{
var grid = new FilteredPropertyGrid();
var obj = new { Prop1 = "hello", Prop2 = "world", Prop3 = "!" };
grid.SelectedObject = obj;
grid.SelectGridItem(nameof(obj.Prop3));
var nextGridItem = grid.FindPreviousGridItemProperty(grid.SelectedGridItem);
Assert.That(nextGridItem?.PropertyDescriptor?.Name,
Is.EqualTo(nameof(obj.Prop2)));
}
}
}

View File

@@ -12,17 +12,14 @@ using NUnit.Framework;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public class ConfigWindowGeneralTests
public class ConfigWindowGeneralTests
{
private ConfigWindow _configWindow;
[SetUp]
public void Setup()
{
_configWindow = new ConfigWindow
{
PropertiesVisible = true
};
_configWindow = new ConfigWindow();
}
[TestCaseSource(nameof(ConnectionInfoGeneralTestCases))]
@@ -57,7 +54,92 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
}
private static IEnumerable<TestCaseData> ConnectionInfoGeneralTestCases()
[Test]
public void SwitchFromInheritanceToConnectionPropertiesWhenClickingRootNode()
{
// connection with a normal parent container
var connection = new ConnectionInfo();
connection.SetParent(new ContainerInfo());
_configWindow.SelectedTreeNode = connection;
_configWindow.ShowInheritanceProperties();
_configWindow.SelectedTreeNode = new RootNodeInfo(RootNodeType.Connection);
Assert.That(_configWindow.PropertiesVisible, Is.True,
() => "The property mode should switch from inheritance to connection properties when clicking on the root node.");
}
[Test]
public void SwitchFromInheritanceToConnectionPropertiesWhenClickingRootPuttyNode()
{
// connection with a normal parent container
var connection = new ConnectionInfo();
connection.SetParent(new ContainerInfo());
_configWindow.SelectedTreeNode = connection;
_configWindow.ShowInheritanceProperties();
_configWindow.SelectedTreeNode = new RootPuttySessionsNodeInfo();
Assert.That(_configWindow.PropertiesVisible, Is.True,
() => "The property mode should switch from inheritance to connection properties when clicking on the root node.");
}
[Test]
public void SwitchFromInheritanceToConnectionPropertiesWhenClickingChildOfRootNode()
{
// connection with a normal parent container
var root = new RootNodeInfo(RootNodeType.Connection);
var containerWhoseParentIsRoot = new ContainerInfo();
var connection = new ConnectionInfo();
root.AddChild(containerWhoseParentIsRoot);
containerWhoseParentIsRoot.AddChild(connection);
_configWindow.SelectedTreeNode = connection;
_configWindow.ShowInheritanceProperties();
_configWindow.SelectedTreeNode = containerWhoseParentIsRoot;
Assert.That(_configWindow.PropertiesVisible, Is.True,
() => "The property mode should switch from inheritance to connection properties " +
"when clicking on a container whose parent is the root node.");
}
[TestCaseSource(nameof(EveryNodeType))]
public void DefaultConnectionPropertiesCanBeShownRegardlessOfWhichNodeIsSelected(ConnectionInfo selectedObject)
{
_configWindow.SelectedTreeNode = selectedObject;
Assert.That(_configWindow.CanShowDefaultProperties, Is.True);
}
[TestCaseSource(nameof(EveryNodeType))]
public void DefaultInheritancePropertiesCanBeShownRegardlessOfWhichNodeIsSelected(ConnectionInfo selectedObject)
{
_configWindow.SelectedTreeNode = selectedObject;
Assert.That(_configWindow.CanShowDefaultInheritance, Is.True);
}
[TestCaseSource(nameof(EveryNodeType))]
public void ConnectionPropertiesCanAlwaysBeShownUnlessNothingIsSelected(ConnectionInfo selectedObject)
{
_configWindow.SelectedTreeNode = selectedObject;
var selectedObjectNotNull = selectedObject != null;
Assert.That(_configWindow.CanShowProperties, Is.EqualTo(selectedObjectNotNull));
}
[TestCaseSource(nameof(EveryNodeType))]
public void InheritancePropertiesAreVisibleInCertainCases(ConnectionInfo selectedObject)
{
_configWindow.SelectedTreeNode = selectedObject;
var shouldBeAvailable = selectedObject != null &&
!(selectedObject is RootNodeInfo) &&
!(selectedObject is PuttySessionInfo) &&
!(selectedObject.Parent is RootNodeInfo);
Assert.That(_configWindow.CanShowInheritance, Is.EqualTo(shouldBeAvailable));
}
private static IEnumerable<TestCaseData> ConnectionInfoGeneralTestCases()
{
var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType<ProtocolType>();
var testCases = new List<TestCaseData>();
@@ -80,6 +162,56 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
return testCases;
}
private static IEnumerable<TestCaseData> EveryNodeType()
{
var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType<ProtocolType>().ToList();
var root = new RootNodeInfo(RootNodeType.Connection);
var container = new ContainerInfo();
var connectionsWithNormalParent = protocolTypes
.Select(protocolType =>
{
var c = new ConnectionInfo {Protocol = protocolType};
c.SetParent(container);
return new TestCaseData(c).SetName(protocolType + ", Connection, NormalParent");
});
var connectionsWithRootParent = protocolTypes
.Select(protocolType =>
{
var c = new ConnectionInfo { Protocol = protocolType };
c.SetParent(root);
return new TestCaseData(c).SetName(protocolType + ", Connection, RootParent");
});
var contianersWithNormalParent = protocolTypes
.Select(protocolType =>
{
var c = new ContainerInfo { Protocol = protocolType };
c.SetParent(container);
return new TestCaseData(c).SetName(protocolType + ", Connection, NormalParent");
});
var containersWithRootParent = protocolTypes
.Select(protocolType =>
{
var c = new ContainerInfo { Protocol = protocolType };
c.SetParent(root);
return new TestCaseData(c).SetName(protocolType + ", Connection, RootParent");
});
return connectionsWithNormalParent
.Concat(connectionsWithRootParent)
.Concat(contianersWithNormalParent)
.Concat(containersWithRootParent)
.Concat(new[]
{
new TestCaseData(root).SetName("RootNode"),
new TestCaseData(new RootPuttySessionsNodeInfo()).SetName("RootPuttyNode"),
new TestCaseData(new PuttySessionInfo()).SetName("PuttyNode"),
new TestCaseData(null).SetName("Null"),
});
}
internal static ConnectionInfo ConstructConnectionInfo(ProtocolType protocol, bool isContainer)
{
// build connection info. set certain connection properties so

View File

@@ -6,7 +6,7 @@ using NUnit.Framework;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public abstract class ConfigWindowSpecialTestsBase
public abstract class ConfigWindowSpecialTestsBase
{
protected abstract ProtocolType Protocol { get; }
protected bool TestAgainstContainerInfo { get; set; } = false;
@@ -20,10 +20,7 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
ConnectionInfo = ConfigWindowGeneralTests.ConstructConnectionInfo(Protocol, TestAgainstContainerInfo);
ExpectedPropertyList = ConfigWindowGeneralTests.BuildExpectedConnectionInfoPropertyList(Protocol, TestAgainstContainerInfo);
ConfigWindow = new ConfigWindow
{
PropertiesVisible = true,
};
ConfigWindow = new ConfigWindow();
}
public void RunVerification()

View File

@@ -218,6 +218,7 @@
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
<Compile Include="UI\Controls\ConnectionTreeTests.cs" />
<Compile Include="UI\Controls\FilteredPropertyGridTests.cs" />
<Compile Include="UI\Controls\PageSequenceTests.cs" />
<Compile Include="UI\Controls\SecureTextBoxTestForm.cs">
<SubType>Form</SubType>

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
@@ -7,11 +6,11 @@ using mRemoteNG.Connection.Protocol.ICA;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Tools;
using mRemoteNG.Tools.Attributes;
namespace mRemoteNG.Connection
{
[Obsolete("Valid for mRemoteNG v1.75 (confCons v2.6) or earlier")]
public abstract class AbstractConnectionRecord : INotifyPropertyChanged
{
#region Fields
@@ -132,7 +131,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameAddress"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAddress")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAddress"),
UsedInAllProtocolsExcept()]
public virtual string Hostname
{
get => _hostname.Trim();
@@ -141,7 +141,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameUsername"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUsername")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUsername"),
UsedInAllProtocolsExcept(ProtocolType.VNC, ProtocolType.Telnet, ProtocolType.Rlogin, ProtocolType.RAW)]
public virtual string Username
{
get => GetPropertyValue("Username", _username);
@@ -151,7 +152,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNamePassword"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPassword"),
PasswordPropertyText(true)]
PasswordPropertyText(true),
UsedInAllProtocolsExcept(ProtocolType.Telnet, ProtocolType.Rlogin, ProtocolType.RAW)]
public virtual string Password
{
get => GetPropertyValue("Password", _password);
@@ -160,7 +162,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameDomain"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDomain")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDomain"),
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA, ProtocolType.IntApp)]
public string Domain
{
get => GetPropertyValue("Domain", _domain).Trim();
@@ -184,7 +187,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameExternalTool"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionExternalTool"),
TypeConverter(typeof(ExternalToolsTypeConverter))]
TypeConverter(typeof(ExternalToolsTypeConverter)),
UsedInProtocol(ProtocolType.IntApp)]
public string ExtApp
{
get => GetPropertyValue("ExtApp", _extApp);
@@ -193,7 +197,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNamePort"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPort")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPort"),
UsedInAllProtocolsExcept(ProtocolType.ICA)]
public virtual int Port
{
get => GetPropertyValue("Port", _port);
@@ -203,7 +208,9 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNamePuttySession"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPuttySession"),
TypeConverter(typeof(Config.Putty.PuttySessionsManager.SessionList))]
TypeConverter(typeof(Config.Putty.PuttySessionsManager.SessionList)),
UsedInProtocol(ProtocolType.SSH1, ProtocolType.SSH2, ProtocolType.Telnet,
ProtocolType.RAW, ProtocolType.Rlogin)]
public virtual string PuttySession
{
get => GetPropertyValue("PuttySession", _puttySession);
@@ -213,7 +220,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameEncryptionStrength"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionEncryptionStrength"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.ICA)]
public IcaProtocol.EncryptionStrength ICAEncryptionStrength
{
get => GetPropertyValue("ICAEncryptionStrength", _icaEncryption);
@@ -223,7 +231,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameUseConsoleSession"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUseConsoleSession"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool UseConsoleSession
{
get => GetPropertyValue("UseConsoleSession", _useConsoleSession);
@@ -233,7 +242,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameAuthenticationLevel"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAuthenticationLevel"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public RdpProtocol.AuthenticationLevel RDPAuthenticationLevel
{
get => GetPropertyValue("RDPAuthenticationLevel", _rdpAuthenticationLevel);
@@ -242,7 +252,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPMinutesToIdleTimeout"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout"),
UsedInProtocol(ProtocolType.RDP)]
public virtual int RDPMinutesToIdleTimeout
{
get => GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout);
@@ -258,7 +269,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDPAlertIdleTimeout"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout"),
UsedInProtocol(ProtocolType.RDP)]
public bool RDPAlertIdleTimeout
{
get => GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout);
@@ -267,7 +279,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameLoadBalanceInfo"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo"),
UsedInProtocol(ProtocolType.RDP)]
public string LoadBalanceInfo
{
get => GetPropertyValue("LoadBalanceInfo", _loadBalanceInfo).Trim();
@@ -277,7 +290,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRenderingEngine"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRenderingEngine"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.HTTP, ProtocolType.HTTPS)]
public HTTPBase.RenderingEngine RenderingEngine
{
get => GetPropertyValue("RenderingEngine", _renderingEngine);
@@ -287,7 +301,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameUseCredSsp"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUseCredSsp"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool UseCredSsp
{
get => GetPropertyValue("UseCredSsp", _useCredSsp);
@@ -301,7 +316,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayUsageMethod"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayUsageMethod"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public RdpProtocol.RDGatewayUsageMethod RDGatewayUsageMethod
{
get => GetPropertyValue("RDGatewayUsageMethod", _rdGatewayUsageMethod);
@@ -310,7 +326,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayHostname"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayHostname")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayHostname"),
UsedInProtocol(ProtocolType.RDP)]
public string RDGatewayHostname
{
get => GetPropertyValue("RDGatewayHostname", _rdGatewayHostname).Trim();
@@ -320,7 +337,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayUseConnectionCredentials"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayUseConnectionCredentials"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public RdpProtocol.RDGatewayUseConnectionCredentials RDGatewayUseConnectionCredentials
{
get => GetPropertyValue("RDGatewayUseConnectionCredentials", _rdGatewayUseConnectionCredentials);
@@ -329,7 +347,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayUsername"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayUsername")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayUsername"),
UsedInProtocol(ProtocolType.RDP)]
public string RDGatewayUsername
{
get => GetPropertyValue("RDGatewayUsername", _rdGatewayUsername).Trim();
@@ -339,7 +358,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayPassword"),
LocalizedAttributes.LocalizedDescription("strPropertyNameRDGatewayPassword"),
PasswordPropertyText(true)]
PasswordPropertyText(true),
UsedInProtocol(ProtocolType.RDP)]
public string RDGatewayPassword
{
get => GetPropertyValue("RDGatewayPassword", _rdGatewayPassword);
@@ -348,7 +368,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRDGatewayDomain"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayDomain")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayDomain"),
UsedInProtocol(ProtocolType.RDP)]
public string RDGatewayDomain
{
get => GetPropertyValue("RDGatewayDomain", _rdGatewayDomain).Trim();
@@ -362,7 +383,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameResolution"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionResolution"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA)]
public RdpProtocol.RDPResolutions Resolution
{
get => GetPropertyValue("Resolution", _resolution);
@@ -372,7 +394,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameAutomaticResize"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAutomaticResize"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool AutomaticResize
{
get => GetPropertyValue("AutomaticResize", _automaticResize);
@@ -382,7 +405,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameColors"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionColors"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA)]
public RdpProtocol.RDPColors Colors
{
get => GetPropertyValue("Colors", _colors);
@@ -392,7 +416,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameCacheBitmaps"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionCacheBitmaps"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP, ProtocolType.ICA)]
public bool CacheBitmaps
{
get => GetPropertyValue("CacheBitmaps", _cacheBitmaps);
@@ -402,7 +427,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameDisplayWallpaper"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDisplayWallpaper"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool DisplayWallpaper
{
get => GetPropertyValue("DisplayWallpaper", _displayWallpaper);
@@ -412,7 +438,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameDisplayThemes"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDisplayThemes"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool DisplayThemes
{
get => GetPropertyValue("DisplayThemes", _displayThemes);
@@ -422,7 +449,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameEnableFontSmoothing"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionEnableFontSmoothing"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool EnableFontSmoothing
{
get => GetPropertyValue("EnableFontSmoothing", _enableFontSmoothing);
@@ -432,7 +460,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameEnableDesktopComposition"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionEnableDesktopComposition"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool EnableDesktopComposition
{
get => GetPropertyValue("EnableDesktopComposition", _enableDesktopComposition);
@@ -446,7 +475,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectKeys"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectKeys"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectKeys
{
get => GetPropertyValue("RedirectKeys", _redirectKeys);
@@ -456,7 +486,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectDrives"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectDrives"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectDiskDrives
{
get => GetPropertyValue("RedirectDiskDrives", _redirectDiskDrives);
@@ -466,7 +497,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectPrinters"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectPrinters"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectPrinters
{
get => GetPropertyValue("RedirectPrinters", _redirectPrinters);
@@ -476,7 +508,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectClipboard"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectClipboard"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectClipboard
{
get { return GetPropertyValue("RedirectClipboard", _redirectClipboard); }
@@ -487,7 +520,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectPorts"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectPorts"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectPorts
{
get => GetPropertyValue("RedirectPorts", _redirectPorts);
@@ -497,7 +531,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectSmartCards"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectSmartCards"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectSmartCards
{
get => GetPropertyValue("RedirectSmartCards", _redirectSmartCards);
@@ -507,7 +542,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectSounds"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectSounds"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public RdpProtocol.RDPSounds RedirectSound
{
get => GetPropertyValue("RedirectSound", _redirectSound);
@@ -517,7 +553,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameSoundQuality"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionSoundQuality"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public RdpProtocol.RDPSoundQuality SoundQuality
{
get => GetPropertyValue("SoundQuality", _soundQuality);
@@ -527,18 +564,19 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectAudioCapture"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectAudioCapture"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.RDP)]
public bool RedirectAudioCapture
{
get { return GetPropertyValue("RedirectAudioCapture", _redirectAudioCapture); }
set { SetField(ref _redirectAudioCapture, value, "RedirectAudioCapture"); }
get => GetPropertyValue(nameof(RedirectAudioCapture), _redirectAudioCapture);
set => SetField(ref _redirectAudioCapture, value, nameof(RedirectAudioCapture));
}
#endregion
#region Misc
[Browsable(false)] public string ConstantID { get; /*set;*/ }
[Browsable(false)] public string ConstantID { get; }
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameExternalToolBefore"),
@@ -590,12 +628,14 @@ namespace mRemoteNG.Connection
#endregion
#region VNC
// TODO: it seems all these VNC properties were added and serialized but
// never hooked up to the VNC protocol or shown to the user
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameCompression"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionCompression"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public ProtocolVNC.Compression VNCCompression
{
get => GetPropertyValue("VNCCompression", _vncCompression);
@@ -603,10 +643,11 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameEncoding"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionEncoding"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public ProtocolVNC.Encoding VNCEncoding
{
get => GetPropertyValue("VNCEncoding", _vncEncoding);
@@ -614,10 +655,11 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameAuthenticationMode"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAuthenticationMode"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public ProtocolVNC.AuthMode VNCAuthMode
{
get => GetPropertyValue("VNCAuthMode", _vncAuthMode);
@@ -625,10 +667,11 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryProxy", 7),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameVNCProxyType"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyType"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public ProtocolVNC.ProxyType VNCProxyType
{
get => GetPropertyValue("VNCProxyType", _vncProxyType);
@@ -636,9 +679,10 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryProxy", 7),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameVNCProxyAddress"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyAddress")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyAddress"),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public string VNCProxyIP
{
get => GetPropertyValue("VNCProxyIP", _vncProxyIp);
@@ -646,9 +690,10 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryProxy", 7),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameVNCProxyPort"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyPort")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyPort"),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public int VNCProxyPort
{
get => GetPropertyValue("VNCProxyPort", _vncProxyPort);
@@ -656,9 +701,10 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryProxy", 7),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameVNCProxyUsername"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyUsername")]
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyUsername"),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public string VNCProxyUsername
{
get => GetPropertyValue("VNCProxyUsername", _vncProxyUsername);
@@ -666,10 +712,11 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryProxy", 7),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameVNCProxyPassword"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyPassword"),
PasswordPropertyText(true)]
PasswordPropertyText(true),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public string VNCProxyPassword
{
get => GetPropertyValue("VNCProxyPassword", _vncProxyPassword);
@@ -677,10 +724,11 @@ namespace mRemoteNG.Connection
}
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
Browsable(false),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameColors"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionColors"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC),
Browsable(false)]
public ProtocolVNC.Colors VNCColors
{
get => GetPropertyValue("VNCColors", _vncColors);
@@ -690,7 +738,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameSmartSizeMode"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionSmartSizeMode"),
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
TypeConverter(typeof(MiscTools.EnumTypeConverter)),
UsedInProtocol(ProtocolType.VNC)]
public ProtocolVNC.SmartSizeMode VNCSmartSizeMode
{
get => GetPropertyValue("VNCSmartSizeMode", _vncSmartSizeMode);
@@ -700,7 +749,8 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameViewOnly"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionViewOnly"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
TypeConverter(typeof(MiscTools.YesNoTypeConverter)),
UsedInProtocol(ProtocolType.VNC)]
public bool VNCViewOnly
{
get => GetPropertyValue("VNCViewOnly", _vncViewOnly);

View File

@@ -22,9 +22,18 @@ namespace mRemoteNG.Connection
[DefaultProperty("Name")]
public class ConnectionInfo : AbstractConnectionRecord, IHasParent, IInheritable
{
private ConnectionInfoInheritance _inheritance;
#region Public Properties
[Browsable(false)] public ConnectionInfoInheritance Inheritance { get; set; }
[Browsable(false)]
public ConnectionInfoInheritance Inheritance
{
get => _inheritance;
set => _inheritance = _inheritance.Parent != this
? _inheritance.Clone(this)
: value;
}
[Browsable(false)] public ProtocolList OpenConnections { get; protected set; }
@@ -72,11 +81,14 @@ namespace mRemoteNG.Connection
{
var newConnectionInfo = new ConnectionInfo();
newConnectionInfo.CopyFrom(this);
newConnectionInfo.Inheritance = Inheritance.Clone();
newConnectionInfo.Inheritance.Parent = newConnectionInfo;
return newConnectionInfo;
}
/// <summary>
/// Copies all connection and inheritance values
/// from the given <see cref="sourceConnectionInfo"/>.
/// </summary>
/// <param name="sourceConnectionInfo"></param>
public void CopyFrom(ConnectionInfo sourceConnectionInfo)
{
var properties = GetType().BaseType?.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
@@ -88,8 +100,7 @@ namespace mRemoteNG.Connection
property.SetValue(this, remotePropertyValue, null);
}
var clonedInheritance = sourceConnectionInfo.Inheritance.Clone();
clonedInheritance.Parent = this;
var clonedInheritance = sourceConnectionInfo.Inheritance.Clone(this);
Inheritance = clonedInheritance;
}
@@ -388,7 +399,7 @@ namespace mRemoteNG.Connection
private void SetNonBrowsablePropertiesDefaults()
{
Inheritance = new ConnectionInfoInheritance(this);
_inheritance = new ConnectionInfoInheritance(this);
SetNewOpenConnectionList();
//PositionID = 0;
}

View File

@@ -391,12 +391,12 @@ namespace mRemoteNG.Connection
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool VNCViewOnly {get; set;}
#endregion
[Browsable(false)] public object Parent { get; set; }
[Browsable(false)] public ConnectionInfo Parent { get; private set; }
#endregion
public ConnectionInfoInheritance(object parent, bool ignoreDefaultInheritance = false)
public ConnectionInfoInheritance(ConnectionInfo parent, bool ignoreDefaultInheritance = false)
{
Parent = parent;
if (!ignoreDefaultInheritance)
@@ -404,9 +404,10 @@ namespace mRemoteNG.Connection
}
public ConnectionInfoInheritance Clone()
public ConnectionInfoInheritance Clone(ConnectionInfo parent)
{
var newInheritance = (ConnectionInfoInheritance)MemberwiseClone();
newInheritance.Parent = parent;
newInheritance._tempInheritanceStorage = null;
return newInheritance;
}
@@ -431,7 +432,7 @@ namespace mRemoteNG.Connection
private void StashInheritanceData()
{
_tempInheritanceStorage = Clone();
_tempInheritanceStorage = Clone(Parent);
}
public void TurnOnInheritanceCompletely()
@@ -458,6 +459,19 @@ namespace mRemoteNG.Connection
return filteredProperties;
}
/// <summary>
/// Gets the name of all properties where inheritance is turned on
/// (set to True).
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetEnabledInheritanceProperties()
{
return GetProperties()
.Where(property => (bool)property.GetValue(this))
.Select(property => property.Name)
.ToList();
}
private bool FilterProperty(PropertyInfo propertyInfo)
{
var exclusions = new[] {"EverythingInherited", "Parent"};

View File

@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Configuration;
using mRemoteNG.App;
@@ -7,6 +8,7 @@ namespace mRemoteNG.Connection
{
public class DefaultConnectionInfo : ConnectionInfo
{
[Browsable(false)]
public static DefaultConnectionInfo Instance { get; } = new DefaultConnectionInfo();
private DefaultConnectionInfo()

View File

@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using mRemoteNG.App;
@@ -6,6 +7,7 @@ namespace mRemoteNG.Connection
{
public class DefaultConnectionInheritance : ConnectionInfoInheritance
{
[Browsable(false)]
public static DefaultConnectionInheritance Instance { get; } = new DefaultConnectionInheritance();
private DefaultConnectionInheritance() : base(null, true)

View File

@@ -204,7 +204,7 @@ namespace mRemoteNG.Container
var newContainer = new ContainerInfo();
newContainer.CopyFrom(this);
newContainer.OpenConnections = new ProtocolList();
newContainer.Inheritance = Inheritance.Clone();
newContainer.Inheritance = Inheritance.Clone(newContainer);
foreach (var child in Children.ToArray())
{
var newChild = child.Clone();

View File

@@ -0,0 +1,18 @@
using System;
using System.Linq;
using mRemoteNG.Connection.Protocol;
namespace mRemoteNG.Tools.Attributes
{
public class UsedInAllProtocolsExceptAttribute : UsedInProtocolAttribute
{
public UsedInAllProtocolsExceptAttribute(params ProtocolType[] exceptions)
: base(Enum
.GetValues(typeof(ProtocolType))
.Cast<ProtocolType>()
.Except(exceptions)
.ToArray())
{
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using mRemoteNG.Connection.Protocol;
namespace mRemoteNG.Tools.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
public class UsedInProtocolAttribute : Attribute
{
public ProtocolType[] SupportedProtocolTypes { get; }
public UsedInProtocolAttribute(params ProtocolType[] supportedProtocolTypes)
{
SupportedProtocolTypes = supportedProtocolTypes;
}
}
}

View File

@@ -0,0 +1,37 @@
namespace mRemoteNG.UI.Controls.ConnectionInfoPropertyGrid
{
partial class ConnectionInfoPropertyGrid
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
}
#endregion
}
}

View File

@@ -0,0 +1,350 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Messages;
using mRemoteNG.Security;
using mRemoteNG.Tools;
using mRemoteNG.Tools.Attributes;
using mRemoteNG.Tree.Root;
namespace mRemoteNG.UI.Controls.ConnectionInfoPropertyGrid
{
public partial class ConnectionInfoPropertyGrid : FilteredPropertyGrid.FilteredPropertyGrid
{
private readonly Dictionary<Type, IEnumerable<PropertyInfo>> _propertyCache = new Dictionary<Type, IEnumerable<PropertyInfo>>();
private ConnectionInfo _selectedConnectionInfo;
private PropertyMode _propertyMode;
/// <summary>
/// The <see cref="ConnectionInfo"/> currently being shown by this
/// property grid.
/// </summary>
public ConnectionInfo SelectedConnectionInfo
{
get => _selectedConnectionInfo;
set
{
if (_selectedConnectionInfo == value)
return;
_selectedConnectionInfo = value;
RootNodeSelected = SelectedConnectionInfo is RootNodeInfo;
SetGridObject();
}
}
/// <summary>
/// Determines which set of properties this grid will display.
/// </summary>
public PropertyMode PropertyMode
{
get => _propertyMode;
set
{
if (_propertyMode == value)
return;
_propertyMode = value;
SetGridObject();
}
}
/// <summary>
/// Is the property grid showing the selected connection's
/// inheritance info? If false, the connection's normal
/// properties are shown instead.
/// </summary>
public bool IsShowingInheritance => PropertyMode == PropertyMode.Inheritance ||
PropertyMode == PropertyMode.DefaultInheritance;
/// <summary>
/// This indicates whether the current <see cref="SelectedConnectionInfo"/>
/// is a <see cref="DefaultConnectionInfo"/>.
/// </summary>
public bool IsShowingDefaultProperties => PropertyMode == PropertyMode.DefaultConnection ||
PropertyMode == PropertyMode.DefaultInheritance;
/// <summary>
/// True when the <see cref="SelectedConnectionInfo"/> is
/// of type <see cref="RootNodeInfo"/>.
/// </summary>
public bool RootNodeSelected { get; private set; }
public ConnectionInfoPropertyGrid()
{
InitializeComponent();
PropertyValueChanged += pGrid_PropertyValueChanged;
}
private void SetGridObject()
{
ClearFilters();
switch (PropertyMode)
{
case PropertyMode.Connection:
default:
SelectedObject = SelectedConnectionInfo;
break;
case PropertyMode.Inheritance:
SelectedObject = SelectedConnectionInfo?.Inheritance;
break;
case PropertyMode.DefaultConnection:
SelectedObject = DefaultConnectionInfo.Instance;
break;
case PropertyMode.DefaultInheritance:
SelectedObject = DefaultConnectionInheritance.Instance;
break;
}
if (SelectedObject != null)
ShowHideGridItems();
}
private void ShowHideGridItems()
{
try
{
if (SelectedConnectionInfo == null)
return;
if (RootNodeSelected && PropertyMode == PropertyMode.Connection)
{
if (SelectedConnectionInfo is RootPuttySessionsNodeInfo)
{
BrowsableProperties = new[]
{
nameof(RootPuttySessionsNodeInfo.Name)
};
}
else if (SelectedConnectionInfo is RootNodeInfo)
{
BrowsableProperties = new[]
{
nameof(RootNodeInfo.Name),
nameof(RootNodeInfo.Password)
};
}
Refresh();
return;
}
// set all browsable properties valid for this connection's protocol
BrowsableProperties =
GetPropertiesForGridObject(SelectedObject)
.Where(property =>
IsValidForProtocol(property, SelectedConnectionInfo.Protocol, IsShowingInheritance))
.Select(property => property.Name)
.ToArray();
var strHide = new List<string>();
if (PropertyMode == PropertyMode.Connection)
{
// hide any inherited properties
strHide.AddRange(SelectedConnectionInfo.Inheritance.GetEnabledInheritanceProperties());
// ReSharper disable once SwitchStatementMissingSomeCases
switch (SelectedConnectionInfo.Protocol)
{
case ProtocolType.RDP:
strHide.AddRange(SpecialRdpExclusions());
break;
case ProtocolType.VNC:
strHide.AddRange(SpecialVncExclusions());
break;
}
if (SelectedConnectionInfo.IsContainer)
strHide.Add(nameof(AbstractConnectionRecord.Hostname));
if (SelectedConnectionInfo is PuttySessionInfo)
strHide.Add(nameof(AbstractConnectionRecord.Favorite));
}
else if (PropertyMode == PropertyMode.DefaultConnection)
{
strHide.Add(nameof(AbstractConnectionRecord.Hostname));
strHide.Add(nameof(AbstractConnectionRecord.Name));
}
HiddenProperties = strHide.ToArray();
Refresh();
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(
MessageClass.ErrorMsg,
Language.strConfigPropertyGridHideItemsFailed +
Environment.NewLine + ex.Message, true);
}
}
private IEnumerable<PropertyInfo> GetPropertiesForGridObject(object currentGridObject)
{
if (_propertyCache.TryGetValue(currentGridObject.GetType(), out var properties))
return properties;
var type = currentGridObject.GetType();
var props = type.GetProperties();
_propertyCache.Add(type, props);
return props;
}
private bool IsValidForProtocol(PropertyInfo property, ProtocolType protocol, bool skipProtocolCheck)
{
return
property.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false &&
(skipProtocolCheck || property.GetCustomAttribute<UsedInProtocolAttribute>()?
.SupportedProtocolTypes
.Contains(protocol) != false);
}
/// <summary>
///
/// </summary>
private List<string> SpecialRdpExclusions()
{
var strHide = new List<string>();
if (SelectedConnectionInfo.RDPMinutesToIdleTimeout <= 0)
{
strHide.Add(nameof(AbstractConnectionRecord.RDPAlertIdleTimeout));
}
if (SelectedConnectionInfo.RDGatewayUsageMethod == RdpProtocol.RDGatewayUsageMethod.Never)
{
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayDomain));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayHostname));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayPassword));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayUseConnectionCredentials));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayUsername));
}
else if (SelectedConnectionInfo.RDGatewayUseConnectionCredentials ==
RdpProtocol.RDGatewayUseConnectionCredentials.Yes)
{
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayDomain));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayPassword));
strHide.Add(nameof(AbstractConnectionRecord.RDGatewayUsername));
}
if (!(SelectedConnectionInfo.Resolution == RdpProtocol.RDPResolutions.FitToWindow ||
SelectedConnectionInfo.Resolution == RdpProtocol.RDPResolutions.Fullscreen))
{
strHide.Add(nameof(AbstractConnectionRecord.AutomaticResize));
}
if (SelectedConnectionInfo.RedirectSound != RdpProtocol.RDPSounds.BringToThisComputer)
{
strHide.Add(nameof(AbstractConnectionRecord.SoundQuality));
}
return strHide;
}
private List<string> SpecialVncExclusions()
{
var strHide = new List<string>();
if (SelectedConnectionInfo.VNCAuthMode == ProtocolVNC.AuthMode.AuthVNC)
{
strHide.Add(nameof(AbstractConnectionRecord.Username));
strHide.Add(nameof(AbstractConnectionRecord.Domain));
}
if (SelectedConnectionInfo.VNCProxyType == ProtocolVNC.ProxyType.ProxyNone)
{
strHide.Add(nameof(AbstractConnectionRecord.VNCProxyIP));
strHide.Add(nameof(AbstractConnectionRecord.VNCProxyPassword));
strHide.Add(nameof(AbstractConnectionRecord.VNCProxyPort));
strHide.Add(nameof(AbstractConnectionRecord.VNCProxyUsername));
}
return strHide;
}
private void UpdateConnectionInfoNode(PropertyValueChangedEventArgs e)
{
if (IsShowingInheritance)
return;
if (e.ChangedItem.Label == Language.strPropertyNameProtocol)
{
SelectedConnectionInfo.SetDefaultPort();
}
else if (e.ChangedItem.Label == Language.strPropertyNameName)
{
if (Settings.Default.SetHostnameLikeDisplayName)
{
if (!string.IsNullOrEmpty(SelectedConnectionInfo.Name))
SelectedConnectionInfo.Hostname = SelectedConnectionInfo.Name;
}
}
if (IsShowingDefaultProperties)
DefaultConnectionInfo.Instance.SaveTo(Settings.Default, a => "ConDefault" + a);
}
private void UpdateRootInfoNode(PropertyValueChangedEventArgs e)
{
if (!(SelectedObject is RootNodeInfo rootInfo))
return;
if (e.ChangedItem.PropertyDescriptor?.Name != "Password")
return;
if (rootInfo.Password)
{
var passwordName = Settings.Default.UseSQLServer
? Language.strSQLServer.TrimEnd(':')
: Path.GetFileName(Runtime.ConnectionsService.GetStartupConnectionFileName());
var password = MiscTools.PasswordDialog(passwordName);
// operation cancelled, dont set a password
if (!password.Any() || password.First().Length == 0)
{
rootInfo.Password = false;
return;
}
rootInfo.PasswordString = password.First().ConvertToUnsecureString();
}
else
{
rootInfo.PasswordString = "";
}
}
private void UpdateInheritanceNode()
{
if (IsShowingDefaultProperties && IsShowingInheritance)
DefaultConnectionInheritance.Instance.SaveTo(Settings.Default, a => "InhDefault" + a);
}
private void pGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
try
{
UpdateConnectionInfoNode(e);
UpdateRootInfoNode(e);
UpdateInheritanceNode();
ShowHideGridItems();
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg,
Language.strConfigPropertyGridValueFailed + Environment.NewLine +
ex.Message, true);
}
}
}
}

View File

@@ -0,0 +1,10 @@
namespace mRemoteNG.UI.Controls.ConnectionInfoPropertyGrid
{
public enum PropertyMode
{
Connection,
Inheritance,
DefaultConnection,
DefaultInheritance,
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
{
@@ -126,8 +125,8 @@ namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
}
else if (_mWrapper.SelectedObject != value)
{
var needrefresh = value.GetType() != _mWrapper.SelectedObject.GetType();
_mWrapper.SelectedObject = value;
var needrefresh = value?.GetType() != _mWrapper.SelectedObject?.GetType();
_mWrapper.SelectedObject = value ?? new object();
if (needrefresh)
RefreshProperties();
}
@@ -139,6 +138,159 @@ namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
}
}
public List<GridItem> GetVisibleGridItems()
{
var gridRoot = SelectedGridItem;
while (gridRoot.GridItemType != GridItemType.Root)
{
gridRoot = gridRoot.Parent;
}
return GetVisibleGridItemsRecursive(gridRoot, new List<GridItem>());
}
private List<GridItem> GetVisibleGridItemsRecursive(GridItem item, List<GridItem> gridItems)
{
if (item.GridItemType == GridItemType.Property && !gridItems.Contains(item))
gridItems.Add(item);
if (item.Expandable && !item.Expanded)
return gridItems;
foreach (GridItem child in item.GridItems)
{
GetVisibleGridItemsRecursive(child, gridItems);
}
return gridItems;
}
public GridItem FindPreviousGridItemProperty(GridItem startItem)
{
var gridItems = GetVisibleGridItems();
if (gridItems.Count == 0 || startItem == null)
return null;
var startIndex = gridItems.IndexOf(startItem);
if (startItem.GridItemType == GridItemType.Property)
{
startIndex--;
if (startIndex < 0)
{
startIndex = gridItems.Count - 1;
}
}
var previousIndex = 0;
var previousIndexValid = false;
for (var index = startIndex; index >= 0; index--)
{
if (gridItems[index].GridItemType != GridItemType.Property) continue;
previousIndex = index;
previousIndexValid = true;
break;
}
if (previousIndexValid)
return gridItems[previousIndex];
for (var index = gridItems.Count - 1; index >= startIndex + 1; index--)
{
if (gridItems[index].GridItemType != GridItemType.Property) continue;
previousIndex = index;
previousIndexValid = true;
break;
}
return !previousIndexValid ? null : gridItems[previousIndex];
}
public GridItem FindNextGridItemProperty(GridItem startItem)
{
var gridItems = GetVisibleGridItems();
if (gridItems.Count == 0 || startItem == null)
return null;
var startIndex = gridItems.IndexOf(startItem);
if (startItem.GridItemType == GridItemType.Property)
{
startIndex++;
if (startIndex >= gridItems.Count)
{
startIndex = 0;
}
}
var nextIndex = 0;
var nextIndexValid = false;
for (var index = startIndex; index <= gridItems.Count - 1; index++)
{
if (gridItems[index].GridItemType != GridItemType.Property) continue;
nextIndex = index;
nextIndexValid = true;
break;
}
if (nextIndexValid)
return gridItems[nextIndex];
for (var index = 0; index <= startIndex - 1; index++)
{
if (gridItems[index].GridItemType != GridItemType.Property) continue;
nextIndex = index;
nextIndexValid = true;
break;
}
return !nextIndexValid ? null : gridItems[nextIndex];
}
/// <summary>
/// Selects the next grid item in the property grid
/// using the currently selected grid item as a reference.
/// Does nothing if there is no next item.
/// </summary>
public void SelectNextGridItem()
{
var nextGridItem = FindNextGridItemProperty(SelectedGridItem);
if (nextGridItem != null)
SelectedGridItem = nextGridItem;
}
/// <summary>
/// Selects the previous grid item in the property grid
/// using the currently selected grid item as a reference.
/// Does nothing if there is no previous item.
/// </summary>
public void SelectPreviousGridItem()
{
var previousGridItem = FindPreviousGridItemProperty(SelectedGridItem);
if (previousGridItem != null)
SelectedGridItem = previousGridItem;
}
/// <summary>
/// Select the grid item whose backing property name
/// matches the given <see cref="propertyName"/>.
/// </summary>
/// <param name="propertyName"></param>
public void SelectGridItem(string propertyName)
{
var item = GetVisibleGridItems()
.FirstOrDefault(gridItem => gridItem.PropertyDescriptor?.Name == propertyName);
if (item != null)
SelectedGridItem = item;
}
public void ClearFilters()
{
_mBrowsableProperties = null;
_mHiddenProperties = null;
RefreshProperties();
}
/// <summary>
/// Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties.
/// </summary>
@@ -156,7 +308,24 @@ namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
foreach (Attribute attribute in _browsableAttributes)
ShowAttribute(attribute);
}
else
// Display if necessary, some properties
if (_mBrowsableProperties != null && _mBrowsableProperties.Length > 0)
{
var allproperties = TypeDescriptor.GetProperties(_mWrapper.SelectedObject);
foreach (var propertyname in _mBrowsableProperties)
{
var property = allproperties[propertyname];
if (property == null)
throw new InvalidOperationException($"Property '{propertyname}' not found on object '{_mWrapper.GetClassName()}'");
ShowProperty(property);
}
}
if ((_browsableAttributes == null || _browsableAttributes.Count == 0) &&
(_mBrowsableProperties == null || _mBrowsableProperties.Length == 0))
{
// Fill the collection with all the properties.
var originalPropertyDescriptors = TypeDescriptor
@@ -166,15 +335,12 @@ namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
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(_mWrapper.SelectedObject);
// Remove from the list the attributes that mustn't be displayed.
if (_hiddenAttributes != null)
foreach (Attribute attribute in _hiddenAttributes)
HideAttribute(attribute);
// Hide if necessary, some properties
if (_mHiddenProperties != null && _mHiddenProperties.Length > 0)
@@ -182,33 +348,10 @@ namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
// Remove from the list the properties that mustn't be displayed.
foreach (var propertyname in _mHiddenProperties)
{
try
{
var property = allproperties[propertyname];
// Remove from the list the property
HideProperty(property);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Could not hide Property.",
ex);
}
}
}
var property = _propertyDescriptors.FirstOrDefault(p => p.Name == propertyname);
// Display if necessary, some properties
if (_mBrowsableProperties != null && _mBrowsableProperties.Length > 0)
{
foreach (var propertyname in _mBrowsableProperties)
{
try
{
ShowProperty(allproperties[propertyname]);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Property not found", ex);
}
// Remove from the list the property
HideProperty(property);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -284,6 +284,7 @@
<Compile Include="Themes\MremoteNGThemeBase.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Tools\Attributes\UsedInAllProtocolsExceptAttribute.cs" />
<Compile Include="Tools\Clipboard\WindowsClipboard.cs" />
<Compile Include="Tools\CustomCollections\IFullyNotifiableList.cs" />
<Compile Include="Tools\CustomCollections\FullyObservableCollection.cs" />
@@ -350,6 +351,7 @@
<Compile Include="Tools\MultiSSHController.cs" />
<Compile Include="Tools\MouseClickSimulator.cs" />
<Compile Include="Tools\NotificationAreaIcon.cs" />
<Compile Include="Tools\Attributes\UsedInProtocolAttribute.cs" />
<Compile Include="Tools\WindowsRegistry\IRegistry.cs" />
<Compile Include="Tools\WindowsRegistry\RegistryHive.cs" />
<Compile Include="Tools\WindowsRegistry\WindowsRegistry.cs" />
@@ -415,6 +417,13 @@
<Compile Include="UI\Controls\ConnectionContextMenu.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="UI\Controls\ConnectionInfoPropertyGrid\ConnectionInfoPropertyGrid.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="UI\Controls\ConnectionInfoPropertyGrid\ConnectionInfoPropertyGrid.Designer.cs">
<DependentUpon>ConnectionInfoPropertyGrid.cs</DependentUpon>
</Compile>
<Compile Include="UI\Controls\ConnectionInfoPropertyGrid\PropertyMode.cs" />
<Compile Include="UI\Controls\ConnectionTree\ConnectionTree.cs">
<SubType>Component</SubType>
</Compile>
@@ -1104,16 +1113,16 @@
<None Include="Resources\Templates\Installer_Header.psd" />
<None Include="Resources\Templates\Installer_Side.psd" />
<None Include="Resources\Themes\darcula.vstheme">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Themes\vs2015blue.vstheme">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Themes\vs2015dark.vstheme">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Themes\vs2015light.vstheme">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Templates\VisualElements_150_dark.psd" />
<None Include="Resources\Templates\VisualElements_150_light.psd" />
@@ -1247,13 +1256,13 @@
</Content>
<None Include="Resources\Images\Header_dark.png" />
<None Include="Resources\Tiles\mRemoteNG.VisualElementsManifest.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Tiles\VisualElements_70.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Tiles\VisualElements_150.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources\Icons\Appearance_Icon.ico" />
<None Include="Resources\Icons\mRemoteNG_Icon.ico" />