Skip to content

Commit

Permalink
Add Close... option to Tab context menu (#7728)
Browse files Browse the repository at this point in the history
<!-- 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 #1912 (comment)

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
  • Loading branch information
mpela81 authored Oct 15, 2020
1 parent f786874 commit 004da88
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
76 changes: 75 additions & 1 deletion src/cascadia/TerminalApp/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<>);
Expand Down
16 changes: 15 additions & 1 deletion src/cascadia/TerminalApp/Tab.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 };
Expand All @@ -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 };
Expand All @@ -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;
Expand All @@ -123,6 +134,9 @@ namespace winrt::TerminalApp::implementation

void _MakeSwitchToTabCommand();

void _CloseTabsAfter();
void _CloseOtherTabs();

friend class ::TerminalAppLocalTests::TabTests;
};
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/Tab.idl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ShortcutActionDispatch.idl";

namespace TerminalApp
{
Expand All @@ -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);
}
}
9 changes: 6 additions & 3 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" };
Expand Down Expand Up @@ -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" };
Expand Down Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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; };
};
}

0 comments on commit 004da88

Please sign in to comment.