Add Close... option to Tab context menu (#7728)

<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add a "Close..." option to the tab context menu, with nested entries to close tabs to the right and close other tabs (actions already available)
![immagine](https://user-images.githubusercontent.com/1140981/94178005-c7e03600-fe9a-11ea-9f87-c6f4895d4cf3.png)

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References
#1912 

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #5524
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
First contribution 🙂
Tried to follow some suggestions from https://github.com/microsoft/terminal/issues/1912#issuecomment-667079311

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
This commit is contained in:
mpela81 2020-10-15 04:40:44 -07:00 committed by GitHub
parent f78687453c
commit 004da88bba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 6 deletions

View file

@ -177,8 +177,17 @@
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Do you want to close all tabs?</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Close...</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Close Tabs to the Right</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Close Other Tabs</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Close</value>
<value>Close Tab</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Color...</value>

View file

@ -593,10 +593,61 @@ namespace winrt::TerminalApp::implementation
newTabFlyout.Items().Append(chooseColorMenuItem);
newTabFlyout.Items().Append(renameTabMenuItem);
newTabFlyout.Items().Append(menuSeparator);
newTabFlyout.Items().Append(_CreateCloseSubMenu());
newTabFlyout.Items().Append(closeTabMenuItem);
_tabViewItem.ContextFlyout(newTabFlyout);
}
// Method Description:
// - Creates a sub-menu containing menu items to close multiple tabs
// Arguments:
// - <none>
// Return Value:
// - the created MenuFlyoutSubItem
Controls::MenuFlyoutSubItem Tab::_CreateCloseSubMenu()
{
auto weakThis{ get_weak() };
// Close tabs after
_closeTabsAfterMenuItem.Click([weakThis](auto&&, auto&&) {
if (auto tab{ weakThis.get() })
{
tab->_CloseTabsAfter();
}
});
_closeTabsAfterMenuItem.Text(RS_(L"TabCloseAfter"));
// Close other tabs
_closeOtherTabsMenuItem.Click([weakThis](auto&&, auto&&) {
if (auto tab{ weakThis.get() })
{
tab->_CloseOtherTabs();
}
});
_closeOtherTabsMenuItem.Text(RS_(L"TabCloseOther"));
Controls::MenuFlyoutSubItem closeSubMenu;
closeSubMenu.Text(RS_(L"TabCloseSubMenu"));
closeSubMenu.Items().Append(_closeTabsAfterMenuItem);
closeSubMenu.Items().Append(_closeOtherTabsMenuItem);
return closeSubMenu;
}
// Method Description:
// - Enable the Close menu items based on tab index and total number of tabs
// Arguments:
// - <none>
// Return Value:
// - <none>
void Tab::_EnableCloseMenuItems()
{
// 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);
}
// Method Description:
// - This will update the contents of our TabViewItem for our current state.
// - If we're not in a rename, we'll set the Header of the TabViewItem to
@ -1053,12 +1104,35 @@ namespace winrt::TerminalApp::implementation
SwitchToTabCommand(command);
}
void Tab::UpdateTabViewIndex(const uint32_t idx)
void Tab::_CloseTabsAfter()
{
CloseTabsAfterArgs args{ _TabViewIndex };
ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args };
_dispatch.DoAction(closeTabsAfter);
}
void Tab::_CloseOtherTabs()
{
CloseOtherTabsArgs args{ _TabViewIndex };
ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args };
_dispatch.DoAction(closeOtherTabs);
}
void Tab::UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs)
{
TabViewIndex(idx);
TabViewNumTabs(numTabs);
_EnableCloseMenuItems();
SwitchToTabCommand().Action().Args().as<SwitchToTabArgs>().TabIndex(idx);
}
void Tab::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch)
{
_dispatch = dispatch;
}
DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
DEFINE_EVENT(Tab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
DEFINE_EVENT(Tab, ColorCleared, _colorCleared, winrt::delegate<>);

View file

@ -68,7 +68,9 @@ namespace winrt::TerminalApp::implementation
int GetLeafPaneCount() const noexcept;
void UpdateTabViewIndex(const uint32_t idx);
void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs);
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
@ -83,6 +85,8 @@ namespace winrt::TerminalApp::implementation
// The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector.
// This is needed since Tab is going to be managing its own SwitchToTab command.
OBSERVABLE_GETSET_PROPERTY(uint32_t, TabViewIndex, _PropertyChangedHandlers, 0);
// The TabViewNumTabs is the number of Tab objects in TerminalPage's _tabs vector.
OBSERVABLE_GETSET_PROPERTY(uint32_t, TabViewNumTabs, _PropertyChangedHandlers, 0);
private:
std::shared_ptr<Pane> _rootPane{ nullptr };
@ -92,6 +96,8 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{};
std::optional<winrt::Windows::UI::Color> _themeTabColor{};
std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{};
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{};
bool _focused{ false };
winrt::Microsoft::UI::Xaml::Controls::TabViewItem _tabViewItem{ nullptr };
@ -100,10 +106,15 @@ namespace winrt::TerminalApp::implementation
bool _inRename{ false };
winrt::Windows::UI::Xaml::Controls::TextBox::LayoutUpdated_revoker _tabRenameBoxLayoutUpdatedRevoker;
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
void _MakeTabViewItem();
void _Focus();
void _CreateContextMenu();
winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _CreateCloseSubMenu();
void _EnableCloseMenuItems();
void _RefreshVisualState();
void _BindEventHandlers(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control) noexcept;
@ -123,6 +134,9 @@ namespace winrt::TerminalApp::implementation
void _MakeSwitchToTabCommand();
void _CloseTabsAfter();
void _CloseOtherTabs();
friend class ::TerminalAppLocalTests::TabTests;
};
}

View file

@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ShortcutActionDispatch.idl";
namespace TerminalApp
{
@ -9,5 +10,7 @@ namespace TerminalApp
Windows.UI.Xaml.Controls.IconSource IconSource { get; };
Microsoft.Terminal.Settings.Model.Command SwitchToTabCommand { get; };
UInt32 TabViewIndex { get; };
void SetDispatch(ShortcutActionDispatch dispatch);
}
}

View file

@ -673,8 +673,10 @@ namespace winrt::TerminalApp::implementation
auto newTabImpl = winrt::make_self<Tab>(profileGuid, term);
_tabs.Append(*newTabImpl);
newTabImpl->SetDispatch(*_actionDispatch);
// Give the tab its index in the _tabs vector so it can manage its own SwitchToTab command.
newTabImpl->UpdateTabViewIndex(_tabs.Size() - 1);
_UpdateTabIndices();
// Hookup our event handlers to the new terminal
_RegisterTerminalEvents(term, *newTabImpl);
@ -2542,9 +2544,10 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_UpdateTabIndices()
{
for (uint32_t i = 0; i < _tabs.Size(); ++i)
const uint32_t size = _tabs.Size();
for (uint32_t i = 0; i < size; ++i)
{
_GetStrongTabImpl(i)->UpdateTabViewIndex(i);
_GetStrongTabImpl(i)->UpdateTabViewIndex(i, size);
}
}

View file

@ -20,6 +20,8 @@
#include "SetTabColorArgs.g.cpp"
#include "RenameTabArgs.g.cpp"
#include "ExecuteCommandlineArgs.g.cpp"
#include "CloseOtherTabsArgs.g.cpp"
#include "CloseTabsAfterArgs.g.cpp"
#include <LibraryResources.h>

View file

@ -505,6 +505,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
struct CloseOtherTabsArgs : public CloseOtherTabsArgsT<CloseOtherTabsArgs>
{
CloseOtherTabsArgs() = default;
CloseOtherTabsArgs(uint32_t& tabIndex) :
_Index{ tabIndex } {};
GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, Index, nullptr);
static constexpr std::string_view IndexKey{ "index" };
@ -533,6 +535,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
struct CloseTabsAfterArgs : public CloseTabsAfterArgsT<CloseTabsAfterArgs>
{
CloseTabsAfterArgs() = default;
CloseTabsAfterArgs(uint32_t& tabIndex) :
_Index{ tabIndex } {};
GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, Index, nullptr);
static constexpr std::string_view IndexKey{ "index" };
@ -567,4 +571,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(NewTabArgs);
BASIC_FACTORY(SplitPaneArgs);
BASIC_FACTORY(ExecuteCommandlineArgs);
BASIC_FACTORY(CloseOtherTabsArgs);
BASIC_FACTORY(CloseTabsAfterArgs);
}

View file

@ -141,11 +141,13 @@ namespace Microsoft.Terminal.Settings.Model
[default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs
{
CloseOtherTabsArgs(UInt32 tabIndex);
Windows.Foundation.IReference<UInt32> Index { get; };
};
[default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs
{
CloseTabsAfterArgs(UInt32 tabIndex);
Windows.Foundation.IReference<UInt32> Index { get; };
};
}