mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
Add Sessions menu with keyboard shortcuts for tab navigation
Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
This commit is contained in:
@@ -2559,4 +2559,16 @@ Nightly Channel includes Alphas, Betas & Release Candidates.</value>
|
||||
<data name="VaultOpenbaoSecretEngineSSHOTP" xml:space="preserve">
|
||||
<value>SSH engine OTP mode</value>
|
||||
</data>
|
||||
<data name="_Sessions" xml:space="preserve">
|
||||
<value>&Sessions</value>
|
||||
</data>
|
||||
<data name="NextSession" xml:space="preserve">
|
||||
<value>Next Session</value>
|
||||
</data>
|
||||
<data name="PreviousSession" xml:space="preserve">
|
||||
<value>Previous Session</value>
|
||||
</data>
|
||||
<data name="JumpToSession" xml:space="preserve">
|
||||
<value>Jump to Session {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
12
mRemoteNG/UI/Forms/frmMain.Designer.cs
generated
12
mRemoteNG/UI/Forms/frmMain.Designer.cs
generated
@@ -38,6 +38,7 @@ namespace mRemoteNG.UI.Forms
|
||||
this.pnlDock = new WeifenLuo.WinFormsUI.Docking.DockPanel();
|
||||
this.msMain = new System.Windows.Forms.MenuStrip();
|
||||
this.fileMenu = new mRemoteNG.UI.Menu.FileMenu();
|
||||
this.sessionsMenu = new mRemoteNG.UI.Menu.SessionsMenu();
|
||||
this.viewMenu = new mRemoteNG.UI.Menu.ViewMenu();
|
||||
this.toolsMenu = new mRemoteNG.UI.Menu.ToolsMenu();
|
||||
this.helpMenu = new mRemoteNG.UI.Menu.HelpMenu();
|
||||
@@ -75,13 +76,14 @@ namespace mRemoteNG.UI.Forms
|
||||
this.msMain.GripStyle = System.Windows.Forms.ToolStripGripStyle.Visible;
|
||||
this.msMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.fileMenu,
|
||||
this.sessionsMenu,
|
||||
this.viewMenu,
|
||||
this.toolsMenu,
|
||||
this.helpMenu});
|
||||
this.msMain.Location = new System.Drawing.Point(3, 0);
|
||||
this.msMain.Name = "msMain";
|
||||
this.msMain.Padding = new System.Windows.Forms.Padding(0, 0, 1, 0);
|
||||
this.msMain.Size = new System.Drawing.Size(151, 25);
|
||||
this.msMain.Size = new System.Drawing.Size(212, 25);
|
||||
this.msMain.Stretch = false;
|
||||
this.msMain.TabIndex = 0;
|
||||
this.msMain.Text = "Main Toolbar";
|
||||
@@ -94,6 +96,13 @@ namespace mRemoteNG.UI.Forms
|
||||
this.fileMenu.Text = "&File";
|
||||
this.fileMenu.TreeWindow = null;
|
||||
//
|
||||
// sessionsMenu
|
||||
//
|
||||
this.sessionsMenu.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
|
||||
this.sessionsMenu.Name = "mMenSessions";
|
||||
this.sessionsMenu.Size = new System.Drawing.Size(61, 19);
|
||||
this.sessionsMenu.Text = "&Sessions";
|
||||
//
|
||||
// viewMenu
|
||||
//
|
||||
this.viewMenu.FullscreenHandler = null;
|
||||
@@ -253,6 +262,7 @@ namespace mRemoteNG.UI.Forms
|
||||
internal System.Windows.Forms.ToolStripSeparator mMenSep3;
|
||||
private System.ComponentModel.IContainer components;
|
||||
private Menu.FileMenu fileMenu;
|
||||
private Menu.SessionsMenu sessionsMenu;
|
||||
private Menu.ViewMenu viewMenu;
|
||||
private Menu.ToolsMenu toolsMenu;
|
||||
private Menu.HelpMenu helpMenu;
|
||||
|
||||
@@ -292,6 +292,7 @@ namespace mRemoteNG.UI.Forms
|
||||
private void ApplyLanguage()
|
||||
{
|
||||
fileMenu.ApplyLanguage();
|
||||
sessionsMenu.ApplyLanguage();
|
||||
viewMenu.ApplyLanguage();
|
||||
toolsMenu.ApplyLanguage();
|
||||
helpMenu.ApplyLanguage();
|
||||
|
||||
150
mRemoteNG/UI/Menu/msMain/SessionsMenu.cs
Normal file
150
mRemoteNG/UI/Menu/msMain/SessionsMenu.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.UI.Window;
|
||||
using mRemoteNG.Resources.Language;
|
||||
using System.Runtime.Versioning;
|
||||
using mRemoteNG.UI.Forms;
|
||||
|
||||
namespace mRemoteNG.UI.Menu
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class SessionsMenu : ToolStripMenuItem
|
||||
{
|
||||
private ToolStripMenuItem _mMenSessionsNextSession;
|
||||
private ToolStripMenuItem _mMenSessionsPreviousSession;
|
||||
private ToolStripSeparator _mMenSessionsSep1;
|
||||
private readonly ToolStripMenuItem[] _sessionNumberItems = new ToolStripMenuItem[9];
|
||||
|
||||
public SessionsMenu()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_mMenSessionsNextSession = new ToolStripMenuItem();
|
||||
_mMenSessionsPreviousSession = new ToolStripMenuItem();
|
||||
_mMenSessionsSep1 = new ToolStripSeparator();
|
||||
|
||||
// Initialize session number menu items (Ctrl+1 through Ctrl+9)
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
_sessionNumberItems[i] = new ToolStripMenuItem();
|
||||
}
|
||||
|
||||
//
|
||||
// mMenSessions
|
||||
//
|
||||
DropDownItems.Add(_mMenSessionsNextSession);
|
||||
DropDownItems.Add(_mMenSessionsPreviousSession);
|
||||
DropDownItems.Add(_mMenSessionsSep1);
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
DropDownItems.Add(_sessionNumberItems[i]);
|
||||
}
|
||||
|
||||
Name = "mMenSessions";
|
||||
Size = new System.Drawing.Size(61, 20);
|
||||
Text = Language._Sessions;
|
||||
|
||||
//
|
||||
// mMenSessionsNextSession
|
||||
//
|
||||
_mMenSessionsNextSession.Name = "mMenSessionsNextSession";
|
||||
_mMenSessionsNextSession.ShortcutKeys = Keys.Control | Keys.Right;
|
||||
_mMenSessionsNextSession.Size = new System.Drawing.Size(230, 22);
|
||||
_mMenSessionsNextSession.Text = Language.NextSession;
|
||||
_mMenSessionsNextSession.Click += mMenSessionsNextSession_Click;
|
||||
|
||||
//
|
||||
// mMenSessionsPreviousSession
|
||||
//
|
||||
_mMenSessionsPreviousSession.Name = "mMenSessionsPreviousSession";
|
||||
_mMenSessionsPreviousSession.ShortcutKeys = Keys.Control | Keys.Left;
|
||||
_mMenSessionsPreviousSession.Size = new System.Drawing.Size(230, 22);
|
||||
_mMenSessionsPreviousSession.Text = Language.PreviousSession;
|
||||
_mMenSessionsPreviousSession.Click += mMenSessionsPreviousSession_Click;
|
||||
|
||||
//
|
||||
// mMenSessionsSep1
|
||||
//
|
||||
_mMenSessionsSep1.Name = "mMenSessionsSep1";
|
||||
_mMenSessionsSep1.Size = new System.Drawing.Size(227, 6);
|
||||
|
||||
// Initialize session number items (Ctrl+1 through Ctrl+9)
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
int sessionNumber = i + 1;
|
||||
_sessionNumberItems[i].Name = $"mMenSessionsSession{sessionNumber}";
|
||||
_sessionNumberItems[i].ShortcutKeys = Keys.Control | (Keys.D1 + i);
|
||||
_sessionNumberItems[i].Size = new System.Drawing.Size(230, 22);
|
||||
_sessionNumberItems[i].Text = string.Format(Language.JumpToSession, sessionNumber);
|
||||
int capturedIndex = i; // Capture the index for the lambda
|
||||
_sessionNumberItems[i].Click += (s, e) => JumpToSessionNumber(capturedIndex);
|
||||
}
|
||||
|
||||
// Hook up the dropdown opening event to update enabled state
|
||||
DropDownOpening += SessionsMenu_DropDownOpening;
|
||||
}
|
||||
|
||||
public void ApplyLanguage()
|
||||
{
|
||||
Text = Language._Sessions;
|
||||
_mMenSessionsNextSession.Text = Language.NextSession;
|
||||
_mMenSessionsPreviousSession.Text = Language.PreviousSession;
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
_sessionNumberItems[i].Text = string.Format(Language.JumpToSession, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void SessionsMenu_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
// Update enabled state of menu items based on active sessions
|
||||
var connectionWindow = GetActiveConnectionWindow();
|
||||
bool hasMultipleSessions = false;
|
||||
int sessionCount = 0;
|
||||
|
||||
if (connectionWindow != null)
|
||||
{
|
||||
var documents = connectionWindow.GetDocuments();
|
||||
sessionCount = documents.Length;
|
||||
hasMultipleSessions = sessionCount > 1;
|
||||
}
|
||||
|
||||
_mMenSessionsNextSession.Enabled = hasMultipleSessions;
|
||||
_mMenSessionsPreviousSession.Enabled = hasMultipleSessions;
|
||||
|
||||
// Enable/disable session number items based on session count
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
_sessionNumberItems[i].Enabled = (i < sessionCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void mMenSessionsNextSession_Click(object sender, EventArgs e)
|
||||
{
|
||||
var connectionWindow = GetActiveConnectionWindow();
|
||||
connectionWindow?.NavigateToNextTab();
|
||||
}
|
||||
|
||||
private void mMenSessionsPreviousSession_Click(object sender, EventArgs e)
|
||||
{
|
||||
var connectionWindow = GetActiveConnectionWindow();
|
||||
connectionWindow?.NavigateToPreviousTab();
|
||||
}
|
||||
|
||||
private void JumpToSessionNumber(int index)
|
||||
{
|
||||
var connectionWindow = GetActiveConnectionWindow();
|
||||
connectionWindow?.NavigateToTab(index);
|
||||
}
|
||||
|
||||
private ConnectionWindow GetActiveConnectionWindow()
|
||||
{
|
||||
return FrmMain.Default.pnlDock?.ActiveDocument as ConnectionWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,6 +387,34 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
}
|
||||
|
||||
internal void NavigateToTab(int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
var documents = connDock.DocumentsToArray();
|
||||
if (index < 0 || index >= documents.Length) return;
|
||||
|
||||
documents[index].DockHandler.Activate();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("NavigateToTab (UI.Window.ConnectionWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal IDockContent[] GetDocuments()
|
||||
{
|
||||
try
|
||||
{
|
||||
return connDock.DocumentsToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage("GetDocuments (UI.Window.ConnectionWindow) failed", ex);
|
||||
return Array.Empty<IDockContent>();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
Reference in New Issue
Block a user