diff --git a/mRemoteNG/Config/Settings/Registry/OptRegistryTabsPanelsPage.cs b/mRemoteNG/Config/Settings/Registry/OptRegistryTabsPanelsPage.cs index d42f4a5ec..fe269acf5 100644 --- a/mRemoteNG/Config/Settings/Registry/OptRegistryTabsPanelsPage.cs +++ b/mRemoteNG/Config/Settings/Registry/OptRegistryTabsPanelsPage.cs @@ -48,6 +48,11 @@ namespace mRemoteNG.Config.Settings.Registry /// public WinRegistryEntry StartUpPanelName { get; private set; } + /// + /// Specifies whether Connections and Config panels are bound together when auto-hidden. + /// + public WinRegistryEntry BindConnectionsAndConfigPanels { get; private set; } + public OptRegistryTabsPanelsPage() { RegistryHive hive = WindowsRegistryInfo.Hive; @@ -61,6 +66,7 @@ namespace mRemoteNG.Config.Settings.Registry AlwaysShowPanelSelectionDlg = new WinRegistryEntry(hive, subKey, nameof(AlwaysShowPanelSelectionDlg)).Read(); CreateEmptyPanelOnStartUp = new WinRegistryEntry(hive, subKey, nameof(CreateEmptyPanelOnStartUp)).Read(); StartUpPanelName = new WinRegistryEntry(hive, subKey, nameof(StartUpPanelName)).Read(); + BindConnectionsAndConfigPanels = new WinRegistryEntry(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; + } } } \ No newline at end of file diff --git a/mRemoteNG/Properties/OptionsTabsPanelsPage.Designer.cs b/mRemoteNG/Properties/OptionsTabsPanelsPage.Designer.cs index 81084083c..b14cd22c3 100644 --- a/mRemoteNG/Properties/OptionsTabsPanelsPage.Designer.cs +++ b/mRemoteNG/Properties/OptionsTabsPanelsPage.Designer.cs @@ -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; + } + } } } diff --git a/mRemoteNG/Properties/OptionsTabsPanelsPage.settings b/mRemoteNG/Properties/OptionsTabsPanelsPage.settings index f8f77498d..2f7159637 100644 --- a/mRemoteNG/Properties/OptionsTabsPanelsPage.settings +++ b/mRemoteNG/Properties/OptionsTabsPanelsPage.settings @@ -35,5 +35,8 @@ True + + False + \ No newline at end of file diff --git a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs index f8e5247b2..d20ca2325 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.Designer.cs @@ -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; diff --git a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs index b8d35393c..9c97553ba 100644 --- a/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs +++ b/mRemoteNG/UI/Forms/OptionsPages/TabsPanelsPage.cs @@ -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() diff --git a/mRemoteNG/UI/Forms/frmMain.cs b/mRemoteNG/UI/Forms/frmMain.cs index 2e7ae7c28..0fc35ffe7 100644 --- a/mRemoteNG/UI/Forms/frmMain.cs +++ b/mRemoteNG/UI/Forms/frmMain.cs @@ -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(); diff --git a/mRemoteNG/UI/Panels/PanelBinder.cs b/mRemoteNG/UI/Panels/PanelBinder.cs new file mode 100644 index 000000000..e11aff2df --- /dev/null +++ b/mRemoteNG/UI/Panels/PanelBinder.cs @@ -0,0 +1,127 @@ +using System; +using System.Runtime.Versioning; +using mRemoteNG.App; +using mRemoteNG.Properties; +using WeifenLuo.WinFormsUI.Docking; + +namespace mRemoteNG.UI.Panels +{ + /// + /// Manages the binding between Connections and Config panels so they show/hide together when in auto-hide state + /// + [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() + { + } + + /// + /// Initializes event handlers for the Connections and Config panels + /// + 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 + } + + /// + /// Checks if a panel is in auto-hide state + /// + 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; + } + + /// + /// Shows a panel by activating it (which brings it to front in auto-hide mode) + /// + private void ShowPanel(DockContent panel) + { + if (panel != null && IsPanelAutoHidden(panel)) + { + panel.Activate(); + } + } + } +}