Add panel binding feature with UI option

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-10-21 17:31:29 +00:00
parent 9c31ee28b6
commit b00185e1dc
7 changed files with 182 additions and 2 deletions

View File

@@ -48,6 +48,11 @@ namespace mRemoteNG.Config.Settings.Registry
/// </summary>
public WinRegistryEntry<string> StartUpPanelName { get; private set; }
/// <summary>
/// Specifies whether Connections and Config panels are bound together when auto-hidden.
/// </summary>
public WinRegistryEntry<bool> BindConnectionsAndConfigPanels { get; private set; }
public OptRegistryTabsPanelsPage()
{
RegistryHive hive = WindowsRegistryInfo.Hive;
@@ -61,6 +66,7 @@ namespace mRemoteNG.Config.Settings.Registry
AlwaysShowPanelSelectionDlg = new WinRegistryEntry<bool>(hive, subKey, nameof(AlwaysShowPanelSelectionDlg)).Read();
CreateEmptyPanelOnStartUp = new WinRegistryEntry<bool>(hive, subKey, nameof(CreateEmptyPanelOnStartUp)).Read();
StartUpPanelName = new WinRegistryEntry<string>(hive, subKey, nameof(StartUpPanelName)).Read();
BindConnectionsAndConfigPanels = new WinRegistryEntry<bool>(hive, subKey, nameof(BindConnectionsAndConfigPanels)).Read();
SetupValidation();
Apply();
@@ -87,6 +93,7 @@ namespace mRemoteNG.Config.Settings.Registry
ApplyAlwaysShowPanelSelectionDlg();
ApplyCreateEmptyPanelOnStartUp();
ApplyStartUpPanelName();
ApplyBindConnectionsAndConfigPanels();
}
private void ApplyAlwaysShowPanelTabs()
@@ -136,5 +143,11 @@ namespace mRemoteNG.Config.Settings.Registry
if (StartUpPanelName.IsSet)
Properties.OptionsTabsPanelsPage.Default.StartUpPanelName = StartUpPanelName.Value;
}
private void ApplyBindConnectionsAndConfigPanels()
{
if (BindConnectionsAndConfigPanels.IsSet)
Properties.OptionsTabsPanelsPage.Default.BindConnectionsAndConfigPanels = BindConnectionsAndConfigPanels.Value;
}
}
}

View File

@@ -154,5 +154,17 @@ namespace mRemoteNG.Properties {
this["cbTabsPanelsPageInOptionMenu"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool BindConnectionsAndConfigPanels {
get {
return ((bool)(this["BindConnectionsAndConfigPanels"]));
}
set {
this["BindConnectionsAndConfigPanels"] = value;
}
}
}
}

View File

@@ -35,5 +35,8 @@
<Setting Name="cbTabsPanelsPageInOptionMenu" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="BindConnectionsAndConfigPanels" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -42,6 +42,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
chkDoubleClickClosesTab = new MrngCheckBox();
chkShowProtocolOnTabs = new MrngCheckBox();
chkCreateEmptyPanelOnStart = new MrngCheckBox();
chkBindConnectionsAndConfigPanels = new MrngCheckBox();
txtBoxPanelName = new MrngTextBox();
lblPanelName = new MrngLabel();
pnlOptions = new System.Windows.Forms.Panel();
@@ -159,6 +160,18 @@ namespace mRemoteNG.UI.Forms.OptionsPages
chkCreateEmptyPanelOnStart.UseVisualStyleBackColor = true;
chkCreateEmptyPanelOnStart.CheckedChanged += chkCreateEmptyPanelOnStart_CheckedChanged;
//
// chkBindConnectionsAndConfigPanels
//
chkBindConnectionsAndConfigPanels._mice = MrngCheckBox.MouseState.OUT;
chkBindConnectionsAndConfigPanels.AutoSize = true;
chkBindConnectionsAndConfigPanels.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
chkBindConnectionsAndConfigPanels.Location = new System.Drawing.Point(3, 210);
chkBindConnectionsAndConfigPanels.Name = "chkBindConnectionsAndConfigPanels";
chkBindConnectionsAndConfigPanels.Size = new System.Drawing.Size(350, 17);
chkBindConnectionsAndConfigPanels.TabIndex = 9;
chkBindConnectionsAndConfigPanels.Text = "Bind Connections and Config panels together when auto-hidden";
chkBindConnectionsAndConfigPanels.UseVisualStyleBackColor = true;
//
// txtBoxPanelName
//
txtBoxPanelName.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
@@ -184,6 +197,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
pnlOptions.Controls.Add(txtBoxPanelName);
pnlOptions.Controls.Add(chkDoubleClickClosesTab);
pnlOptions.Controls.Add(chkCreateEmptyPanelOnStart);
pnlOptions.Controls.Add(chkBindConnectionsAndConfigPanels);
pnlOptions.Controls.Add(chkShowLogonInfoOnTabs);
pnlOptions.Controls.Add(chkAlwaysShowPanelSelectionDlg);
pnlOptions.Controls.Add(chkAlwaysShowConnectionTabs);
@@ -192,7 +206,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
pnlOptions.Dock = System.Windows.Forms.DockStyle.Top;
pnlOptions.Location = new System.Drawing.Point(0, 30);
pnlOptions.Name = "pnlOptions";
pnlOptions.Size = new System.Drawing.Size(610, 216);
pnlOptions.Size = new System.Drawing.Size(610, 240);
pnlOptions.TabIndex = 10;
//
// lblRegistrySettingsUsedInfo
@@ -230,6 +244,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
internal MrngCheckBox chkDoubleClickClosesTab;
internal MrngCheckBox chkShowProtocolOnTabs;
private MrngCheckBox chkCreateEmptyPanelOnStart;
private MrngCheckBox chkBindConnectionsAndConfigPanels;
private Controls.MrngTextBox txtBoxPanelName;
private Controls.MrngLabel lblPanelName;
private System.Windows.Forms.Panel pnlOptions;

View File

@@ -45,6 +45,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
chkDoubleClickClosesTab.Text = Language.DoubleClickTabClosesIt;
chkAlwaysShowPanelSelectionDlg.Text = Language.AlwaysShowPanelSelection;
chkCreateEmptyPanelOnStart.Text = Language.CreateEmptyPanelOnStartUp;
chkBindConnectionsAndConfigPanels.Text = "Bind Connections and Config panels together when auto-hidden";
lblPanelName.Text = $@"{Language.PanelName}:";
lblRegistrySettingsUsedInfo.Text = Language.OptionsCompanyPolicyMessage;
@@ -75,6 +76,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
chkDoubleClickClosesTab.Checked = Properties.OptionsTabsPanelsPage.Default.DoubleClickOnTabClosesIt;
chkAlwaysShowPanelSelectionDlg.Checked = Properties.OptionsTabsPanelsPage.Default.AlwaysShowPanelSelectionDlg;
chkCreateEmptyPanelOnStart.Checked = Properties.OptionsTabsPanelsPage.Default.CreateEmptyPanelOnStartUp;
chkBindConnectionsAndConfigPanels.Checked = Properties.OptionsTabsPanelsPage.Default.BindConnectionsAndConfigPanels;
txtBoxPanelName.Text = Properties.OptionsTabsPanelsPage.Default.StartUpPanelName;
UpdatePanelNameTextBox();
}
@@ -106,6 +108,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
Properties.OptionsTabsPanelsPage.Default.DoubleClickOnTabClosesIt = chkDoubleClickClosesTab.Checked;
Properties.OptionsTabsPanelsPage.Default.AlwaysShowPanelSelectionDlg = chkAlwaysShowPanelSelectionDlg.Checked;
Properties.OptionsTabsPanelsPage.Default.CreateEmptyPanelOnStartUp = chkCreateEmptyPanelOnStart.Checked;
Properties.OptionsTabsPanelsPage.Default.BindConnectionsAndConfigPanels = chkBindConnectionsAndConfigPanels.Checked;
Properties.OptionsTabsPanelsPage.Default.StartUpPanelName = txtBoxPanelName.Text;
}
@@ -144,6 +147,9 @@ namespace mRemoteNG.UI.Forms.OptionsPages
if (pageRegSettingsInstance.StartUpPanelName.IsSet)
DisableControl(txtBoxPanelName);
if (pageRegSettingsInstance.BindConnectionsAndConfigPanels.IsSet)
DisableControl(chkBindConnectionsAndConfigPanels);
// Updates the visibility of the information label indicating whether registry settings are used.
lblRegistrySettingsUsedInfo.Visible = ShowRegistrySettingsUsedInfo();
}
@@ -160,7 +166,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|| pageRegSettingsInstance.DoubleClickOnTabClosesIt.IsSet
|| pageRegSettingsInstance.AlwaysShowPanelSelectionDlg.IsSet
|| pageRegSettingsInstance.CreateEmptyPanelOnStartUp.IsSet
|| pageRegSettingsInstance.StartUpPanelName.IsSet;
|| pageRegSettingsInstance.StartUpPanelName.IsSet
|| pageRegSettingsInstance.BindConnectionsAndConfigPanels.IsSet;
}
private void UpdatePanelNameTextBox()

View File

@@ -227,6 +227,9 @@ namespace mRemoteNG.UI.Forms
CredsAndConsSetup credsAndConsSetup = new();
credsAndConsSetup.LoadCredsAndCons();
// Initialize panel binding for Connections and Config panels
UI.Panels.PanelBinder.Instance.Initialize();
App.Windows.TreeForm.Focus();
PuttySessionsManager.Instance.StartWatcher();

View File

@@ -0,0 +1,127 @@
using System;
using System.Runtime.Versioning;
using mRemoteNG.App;
using mRemoteNG.Properties;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.UI.Panels
{
/// <summary>
/// Manages the binding between Connections and Config panels so they show/hide together when in auto-hide state
/// </summary>
[SupportedOSPlatform("windows")]
public class PanelBinder
{
private static PanelBinder _instance;
private bool _isProcessing; // Prevent recursive calls
public static PanelBinder Instance => _instance ?? (_instance = new PanelBinder());
private PanelBinder()
{
}
/// <summary>
/// Initializes event handlers for the Connections and Config panels
/// </summary>
public void Initialize()
{
if (Windows.TreeForm != null)
{
Windows.TreeForm.VisibleChanged += OnTreeFormVisibleChanged;
Windows.TreeForm.DockStateChanged += OnTreeFormDockStateChanged;
}
if (Windows.ConfigForm != null)
{
Windows.ConfigForm.VisibleChanged += OnConfigFormVisibleChanged;
Windows.ConfigForm.DockStateChanged += OnConfigFormDockStateChanged;
}
}
private void OnTreeFormVisibleChanged(object sender, EventArgs e)
{
if (!OptionsTabsPanelsPage.Default.BindConnectionsAndConfigPanels || _isProcessing)
return;
// Only act when the panel becomes visible
if (!Windows.TreeForm.Visible)
return;
// Only bind when both panels are in auto-hide state
if (!IsPanelAutoHidden(Windows.TreeForm) || !IsPanelAutoHidden(Windows.ConfigForm))
return;
_isProcessing = true;
try
{
ShowPanel(Windows.ConfigForm);
}
finally
{
_isProcessing = false;
}
}
private void OnConfigFormVisibleChanged(object sender, EventArgs e)
{
if (!OptionsTabsPanelsPage.Default.BindConnectionsAndConfigPanels || _isProcessing)
return;
// Only act when the panel becomes visible
if (!Windows.ConfigForm.Visible)
return;
// Only bind when both panels are in auto-hide state
if (!IsPanelAutoHidden(Windows.TreeForm) || !IsPanelAutoHidden(Windows.ConfigForm))
return;
_isProcessing = true;
try
{
ShowPanel(Windows.TreeForm);
}
finally
{
_isProcessing = false;
}
}
private void OnTreeFormDockStateChanged(object sender, EventArgs e)
{
// This event helps us track when panels transition to/from auto-hide
// We don't need to take action here, just be aware of state changes
}
private void OnConfigFormDockStateChanged(object sender, EventArgs e)
{
// This event helps us track when panels transition to/from auto-hide
// We don't need to take action here, just be aware of state changes
}
/// <summary>
/// Checks if a panel is in auto-hide state
/// </summary>
private bool IsPanelAutoHidden(DockContent panel)
{
if (panel == null)
return false;
return panel.DockState == DockState.DockLeftAutoHide ||
panel.DockState == DockState.DockRightAutoHide ||
panel.DockState == DockState.DockTopAutoHide ||
panel.DockState == DockState.DockBottomAutoHide;
}
/// <summary>
/// Shows a panel by activating it (which brings it to front in auto-hide mode)
/// </summary>
private void ShowPanel(DockContent panel)
{
if (panel != null && IsPanelAutoHidden(panel))
{
panel.Activate();
}
}
}
}