From ed482d910afa3598b39d85689c0dd52316571f90 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 24 Oct 2024 11:02:21 -0700 Subject: [PATCH] Add 'Move Tab' submenu to tab context menu --- .../Resources/en-US/Resources.resw | 11 +- src/cascadia/TerminalApp/TabBase.cpp | 103 ++++++++++++++---- src/cascadia/TerminalApp/TabBase.h | 8 +- src/cascadia/TerminalApp/TerminalTab.cpp | 32 +----- src/cascadia/TerminalApp/TerminalTab.h | 1 - 5 files changed, 101 insertions(+), 54 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 26823366401..217f4e88879 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -193,6 +193,9 @@ Close + + Move tab + Close tabs to the right @@ -941,4 +944,10 @@ Close pane - + + Move left + + + Move right + + \ No newline at end of file diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp index 2d5e8da4433..0cedab37d0a 100644 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ b/src/cascadia/TerminalApp/TabBase.cpp @@ -7,6 +7,7 @@ #include "TabBase.g.cpp" #include "Utils.h" #include "ColorHelper.h" +#include "../inc/WindowingBehavior.h" using namespace winrt; using namespace winrt::Windows::UI::Xaml; @@ -56,10 +57,72 @@ namespace winrt::TerminalApp::implementation tab->RequestFocusActiveControl.raise(); } }); + _AppendMoveMenuItems(contextMenuFlyout); _AppendCloseMenuItems(contextMenuFlyout); TabViewItem().ContextFlyout(contextMenuFlyout); } + void TabBase::_AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout) + { + auto weakThis{ get_weak() }; + + // Move to new window + { + Controls::FontIcon moveTabToNewWindowTabSymbol; + moveTabToNewWindowTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); + moveTabToNewWindowTabSymbol.Glyph(L"\xE8A7"); + + _moveToNewWindowMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ winrt::to_hstring(NewWindow), MoveTabDirection::Forward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveToNewWindowMenuItem.Text(RS_(L"MoveTabToNewWindowText")); + _moveToNewWindowMenuItem.Icon(moveTabToNewWindowTabSymbol); + + const auto moveTabToNewWindowToolTip = RS_(L"MoveTabToNewWindowToolTip"); + WUX::Controls::ToolTipService::SetToolTip(_moveToNewWindowMenuItem, box_value(moveTabToNewWindowToolTip)); + Automation::AutomationProperties::SetHelpText(_moveToNewWindowMenuItem, moveTabToNewWindowToolTip); + } + + // Move left + { + _moveLeftMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ hstring{}, MoveTabDirection::Backward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveLeftMenuItem.Text(RS_(L"TabMoveLeft")); + } + + // Move right + { + _moveRightMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ hstring{}, MoveTabDirection::Forward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveRightMenuItem.Text(RS_(L"TabMoveRight")); + } + + // Create a sub-menu for our extended move tab items. + Controls::MenuFlyoutSubItem moveSubMenu; + moveSubMenu.Text(RS_(L"TabMoveSubMenu")); + moveSubMenu.Items().Append(_moveToNewWindowMenuItem); + moveSubMenu.Items().Append(_moveRightMenuItem); + moveSubMenu.Items().Append(_moveLeftMenuItem); + flyout.Items().Append(moveSubMenu); + } + // Method Description: // - Append the close menu items to the context menu flyout // Arguments: @@ -75,7 +138,9 @@ namespace winrt::TerminalApp::implementation _closeTabsAfterMenuItem.Click([weakThis](auto&&, auto&&) { if (auto tab{ weakThis.get() }) { - tab->_CloseTabsAfter(); + CloseTabsAfterArgs args{ tab->_TabViewIndex }; + ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args }; + tab->_dispatch.DoAction(*tab, closeTabsAfter); } }); _closeTabsAfterMenuItem.Text(RS_(L"TabCloseAfter")); @@ -88,7 +153,9 @@ namespace winrt::TerminalApp::implementation _closeOtherTabsMenuItem.Click([weakThis](auto&&, auto&&) { if (auto tab{ weakThis.get() }) { - tab->_CloseOtherTabs(); + CloseOtherTabsArgs args{ tab->_TabViewIndex }; + ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args }; + tab->_dispatch.DoAction(*tab, closeOtherTabs); } }); _closeOtherTabsMenuItem.Text(RS_(L"TabCloseOther")); @@ -129,33 +196,27 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Enable the Close menu items based on tab index and total number of tabs + // - Enable menu items based on tab index and total number of tabs // Arguments: // - // Return Value: // - - void TabBase::_EnableCloseMenuItems() + void TabBase::_EnableMenuItems() { - // close other tabs is enabled only if there are other tabs - _closeOtherTabsMenuItem.IsEnabled(TabViewNumTabs() > 1); - // close tabs after is enabled only if there are other tabs on the right - _closeTabsAfterMenuItem.IsEnabled(TabViewIndex() < TabViewNumTabs() - 1); - } + const auto tabIndex = TabViewIndex(); + const auto numOfTabs = TabViewNumTabs(); - void TabBase::_CloseTabsAfter() - { - CloseTabsAfterArgs args{ _TabViewIndex }; - ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args }; + // enabled if there are other tabs + _closeOtherTabsMenuItem.IsEnabled(numOfTabs > 1); - _dispatch.DoAction(closeTabsAfter); - } + // enabled if there are other tabs on the right + _closeTabsAfterMenuItem.IsEnabled(tabIndex < numOfTabs - 1); - void TabBase::_CloseOtherTabs() - { - CloseOtherTabsArgs args{ _TabViewIndex }; - ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args }; + // enabled if not left-most tab + _moveLeftMenuItem.IsEnabled(tabIndex > 0); - _dispatch.DoAction(closeOtherTabs); + // enabled if not last tab + _moveRightMenuItem.IsEnabled(tabIndex < numOfTabs - 1); } void TabBase::UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs) @@ -164,7 +225,7 @@ namespace winrt::TerminalApp::implementation TabViewIndex(idx); TabViewNumTabs(numTabs); - _EnableCloseMenuItems(); + _EnableMenuItems(); _UpdateSwitchToTabKeyChord(); } diff --git a/src/cascadia/TerminalApp/TabBase.h b/src/cascadia/TerminalApp/TabBase.h index 9a538550b8d..aa4928c669b 100644 --- a/src/cascadia/TerminalApp/TabBase.h +++ b/src/cascadia/TerminalApp/TabBase.h @@ -54,6 +54,9 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::FocusState _focusState{ winrt::Windows::UI::Xaml::FocusState::Unfocused }; winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{}; winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveToNewWindowMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveRightMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveLeftMenuItem{}; winrt::TerminalApp::ShortcutActionDispatch _dispatch; Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr }; winrt::hstring _keyChord{}; @@ -69,10 +72,9 @@ namespace winrt::TerminalApp::implementation virtual void _MakeTabViewItem(); + void _AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); - void _EnableCloseMenuItems(); - void _CloseTabsAfter(); - void _CloseOtherTabs(); + void _EnableMenuItems(); void _UpdateSwitchToTabKeyChord(); void _UpdateToolTip(); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 0a01e83d13e..e81e452708e 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -10,7 +10,6 @@ #include "Utils.h" #include "ColorHelper.h" #include "AppLogic.h" -#include "../inc/WindowingBehavior.h" using namespace winrt; using namespace winrt::Windows::UI::Xaml; @@ -1443,23 +1442,6 @@ namespace winrt::TerminalApp::implementation Automation::AutomationProperties::SetHelpText(splitTabMenuItem, splitTabToolTip); } - Controls::MenuFlyoutItem moveTabToNewWindowMenuItem; - { - // "Move tab to new window" - Controls::FontIcon moveTabToNewWindowTabSymbol; - moveTabToNewWindowTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); - moveTabToNewWindowTabSymbol.Glyph(L"\xE8A7"); - - moveTabToNewWindowMenuItem.Click({ get_weak(), &TerminalTab::_moveTabToNewWindowClicked }); - moveTabToNewWindowMenuItem.Text(RS_(L"MoveTabToNewWindowText")); - moveTabToNewWindowMenuItem.Icon(moveTabToNewWindowTabSymbol); - - const auto moveTabToNewWindowToolTip = RS_(L"MoveTabToNewWindowToolTip"); - - WUX::Controls::ToolTipService::SetToolTip(moveTabToNewWindowMenuItem, box_value(moveTabToNewWindowToolTip)); - Automation::AutomationProperties::SetHelpText(moveTabToNewWindowMenuItem, moveTabToNewWindowToolTip); - } - Controls::MenuFlyoutItem closePaneMenuItem = _closePaneMenuItem; { // "Close pane" @@ -1535,12 +1517,15 @@ namespace winrt::TerminalApp::implementation contextMenuFlyout.Items().Append(renameTabMenuItem); contextMenuFlyout.Items().Append(duplicateTabMenuItem); contextMenuFlyout.Items().Append(splitTabMenuItem); - contextMenuFlyout.Items().Append(moveTabToNewWindowMenuItem); + _AppendMoveMenuItems(contextMenuFlyout); contextMenuFlyout.Items().Append(exportTabMenuItem); contextMenuFlyout.Items().Append(findMenuItem); contextMenuFlyout.Items().Append(restartConnectionMenuItem); contextMenuFlyout.Items().Append(menuSeparator); + auto closeSubMenu = _AppendCloseMenuItems(contextMenuFlyout); + closeSubMenu.Items().Append(closePaneMenuItem); + // GH#5750 - When the context menu is dismissed with ESC, toss the focus // back to our control. contextMenuFlyout.Closed([weakThis](auto&&, auto&&) { @@ -1560,8 +1545,6 @@ namespace winrt::TerminalApp::implementation } } }); - auto closeSubMenu = _AppendCloseMenuItems(contextMenuFlyout); - closeSubMenu.Items().Append(closePaneMenuItem); TabViewItem().ContextFlyout(contextMenuFlyout); } @@ -2001,13 +1984,6 @@ namespace winrt::TerminalApp::implementation actionAndArgs.Action(ShortcutAction::ExportBuffer); _dispatch.DoAction(*this, actionAndArgs); } - void TerminalTab::_moveTabToNewWindowClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) - { - MoveTabArgs args{ winrt::to_hstring(NewWindow), MoveTabDirection::Forward }; - ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; - _dispatch.DoAction(*this, actionAndArgs); - } void TerminalTab::_findClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index f38895a3da6..5a2f67b295d 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -196,7 +196,6 @@ namespace winrt::TerminalApp::implementation void _splitTabClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); void _closePaneClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); void _exportTextClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); - void _moveTabToNewWindowClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); void _findClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); void _bubbleRestartTerminalRequested(TerminalApp::TerminalPaneContent sender, const winrt::Windows::Foundation::IInspectable& args);